diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-07-07 20:47:21 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-07-07 20:47:21 -0700 |
| commit | c2e66d9bab396a69514ec7c3c41fb0404e542f21 (patch) | |
| tree | fbc8b06cd459cd5e4ad2b39384c9d5d73e25c8ee /src/codegen | |
| parent | 5c8bd443d92c6306f60857720103ae46ca7b8b3e (diff) | |
| download | zig-c2e66d9bab396a69514ec7c3c41fb0404e542f21.tar.gz zig-c2e66d9bab396a69514ec7c3c41fb0404e542f21.zip | |
stage2: basic inferred error set support
* Inferred error sets are stored in the return Type of the function,
owned by the Module.Fn. So it cleans up that memory in deinit().
* Sema: update the inferred error set in zirRetErrValue
- Update relevant code in wrapErrorUnion
* C backend: improve some some instructions to take advantage of
liveness analysis to avoid being emitted when unused.
* C backend: when an error union has a payload type with no runtime
bits, emit the error union as the same type as the error set.
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index db0e910643..3aaf559802 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -360,6 +360,12 @@ pub const DeclGen = struct { const error_type = t.errorUnionSet(); const payload_type = t.errorUnionChild(); const data = val.castTag(.error_union).?.data; + + if (!payload_type.hasCodeGenBits()) { + // We use the error type directly as the type. + return dg.renderValue(writer, error_type, data); + } + try writer.writeByte('('); try dg.renderType(writer, t); try writer.writeAll("){"); @@ -604,6 +610,10 @@ pub const DeclGen = struct { const child_type = t.errorUnionChild(); const err_set_type = t.errorUnionSet(); + if (!child_type.hasCodeGenBits()) { + return dg.renderType(w, err_set_type); + } + var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); defer buffer.deinit(); const bw = buffer.writer(); @@ -613,7 +623,7 @@ pub const DeclGen = struct { try bw.writeAll(" payload; uint16_t error; } "); const name_index = buffer.items.len; if (err_set_type.castTag(.error_set_inferred)) |inf_err_set_payload| { - const func = inf_err_set_payload.data; + const func = inf_err_set_payload.data.func; try bw.print("zig_E_{s};\n", .{func.owner_decl.name}); } else { try bw.print("zig_E_{s}_{s};\n", .{ @@ -895,10 +905,10 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi .ref => try genRef(o, inst.castTag(.ref).?), .struct_field_ptr => try genStructFieldPtr(o, inst.castTag(.struct_field_ptr).?), - .is_err => try genIsErr(o, inst.castTag(.is_err).?, "", "!="), - .is_non_err => try genIsErr(o, inst.castTag(.is_non_err).?, "", "=="), - .is_err_ptr => try genIsErr(o, inst.castTag(.is_err_ptr).?, "[0]", "!="), - .is_non_err_ptr => try genIsErr(o, inst.castTag(.is_non_err_ptr).?, "[0]", "=="), + .is_err => try genIsErr(o, inst.castTag(.is_err).?, "", ".", "!="), + .is_non_err => try genIsErr(o, inst.castTag(.is_non_err).?, "", ".", "=="), + .is_err_ptr => try genIsErr(o, inst.castTag(.is_err_ptr).?, "*", "->", "!="), + .is_non_err_ptr => try genIsErr(o, inst.castTag(.is_non_err_ptr).?, "*", "->", "=="), .unwrap_errunion_payload => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload).?), .unwrap_errunion_err => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err).?), @@ -1384,9 +1394,25 @@ fn genStructFieldPtr(o: *Object, inst: *Inst.StructFieldPtr) !CValue { // *(E!T) -> E NOT *E fn genUnwrapErrUnionErr(o: *Object, inst: *Inst.UnOp) !CValue { + if (inst.base.isUnused()) + return CValue.none; + const writer = o.writer(); const operand = try o.resolveInst(inst.operand); + const payload_ty = inst.operand.ty.errorUnionChild(); + if (!payload_ty.hasCodeGenBits()) { + if (inst.operand.ty.zigTypeTag() == .Pointer) { + const local = try o.allocLocal(inst.base.ty, .Const); + try writer.writeAll(" = *"); + try o.writeCValue(writer, operand); + try writer.writeAll(";\n"); + return local; + } else { + return operand; + } + } + const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else "."; const local = try o.allocLocal(inst.base.ty, .Const); @@ -1396,10 +1422,19 @@ fn genUnwrapErrUnionErr(o: *Object, inst: *Inst.UnOp) !CValue { try writer.print("){s}error;\n", .{maybe_deref}); return local; } + fn genUnwrapErrUnionPay(o: *Object, inst: *Inst.UnOp) !CValue { + if (inst.base.isUnused()) + return CValue.none; + const writer = o.writer(); const operand = try o.resolveInst(inst.operand); + const payload_ty = inst.operand.ty.errorUnionChild(); + if (!payload_ty.hasCodeGenBits()) { + return CValue.none; + } + const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else "."; const maybe_addrof = if (inst.base.ty.zigTypeTag() == .Pointer) "&" else ""; @@ -1448,14 +1483,26 @@ fn genWrapErrUnionPay(o: *Object, inst: *Inst.UnOp) !CValue { return local; } -fn genIsErr(o: *Object, inst: *Inst.UnOp, deref_suffix: []const u8, op_str: []const u8) !CValue { +fn genIsErr( + o: *Object, + inst: *Inst.UnOp, + deref_prefix: [*:0]const u8, + deref_suffix: [*:0]const u8, + op_str: [*:0]const u8, +) !CValue { const writer = o.writer(); const operand = try o.resolveInst(inst.operand); - const local = try o.allocLocal(Type.initTag(.bool), .Const); - try writer.writeAll(" = ("); - try o.writeCValue(writer, operand); - try writer.print("){s}.error {s} 0;\n", .{ deref_suffix, op_str }); + const payload_ty = inst.operand.ty.errorUnionChild(); + if (!payload_ty.hasCodeGenBits()) { + try writer.print(" = {s}", .{deref_prefix}); + try o.writeCValue(writer, operand); + try writer.print(" {s} 0;\n", .{op_str}); + } else { + try writer.writeAll(" = "); + try o.writeCValue(writer, operand); + try writer.print("{s}error {s} 0;\n", .{ deref_suffix, op_str }); + } return local; } |
