diff options
| author | Veikka Tuominen <git@vexu.eu> | 2021-01-29 18:20:35 +0200 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2021-03-08 00:33:07 +0200 |
| commit | cfc19eace71c92ecd7e138db6d961271a1b6c126 (patch) | |
| tree | a95c89dbf3b86a83747203c406b4fbb34a1eaad2 /src | |
| parent | c22f010fdd2c5ead80cbdc902738a9d023322436 (diff) | |
| download | zig-cfc19eace71c92ecd7e138db6d961271a1b6c126.tar.gz zig-cfc19eace71c92ecd7e138db6d961271a1b6c126.zip | |
stage2 cbe: errors
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen/c.zig | 29 | ||||
| -rw-r--r-- | src/link/C.zig | 13 | ||||
| -rw-r--r-- | src/type.zig | 12 |
3 files changed, 54 insertions, 0 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 642166092e..fe87a5994a 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -217,6 +217,11 @@ pub const DeclGen = struct { try writer.writeAll(" }"); } }, + .ErrorSet => { + const payload = val.castTag(.@"error").?; + // error values will be #defined at the top of the file + return writer.print("zig_error_{s}", .{payload.data.name}); + }, else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{ @tagName(e), }), @@ -327,6 +332,16 @@ pub const DeclGen = struct { try dg.renderType(w, child_type); try w.writeAll(" payload; bool is_null; }"); }, + .ErrorSet => { + comptime std.debug.assert(Type.initTag(.anyerror).abiSize(std.Target.current) == 2); + try w.writeAll("uint16_t"); + }, + .ErrorUnion => { + // TODO this needs to be typedeffed since different structs are different types. + try w.writeAll("struct { "); + try dg.renderType(w, t.errorUnionChild()); + try w.writeAll(" payload; uint16_t error; }"); + }, .Null, .Undefined => unreachable, // must be const or comptime else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement type {s}", .{ @tagName(e), @@ -464,6 +479,8 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi .wrap_optional => try genWrapOptional(o, inst.castTag(.wrap_optional).?), .optional_payload => try genOptionalPayload(o, inst.castTag(.optional_payload).?), .optional_payload_ptr => try genOptionalPayload(o, inst.castTag(.optional_payload).?), + .is_err => try genIsErr(o, inst.castTag(.is_err).?), + .is_err_ptr => try genIsErr(o, inst.castTag(.is_err_ptr).?), else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}), }; switch (result_value) { @@ -900,6 +917,18 @@ fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue { return local; } +fn genIsErr(o: *Object, inst: *Inst.UnOp) !CValue { + const writer = o.writer(); + const maybe_deref = if (inst.base.tag == .is_err_ptr) "[0]" else ""; + 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 != 0;\n", .{maybe_deref}); + return local; +} + fn IndentWriter(comptime UnderlyingWriter: type) type { return struct { const Self = @This(); diff --git a/src/link/C.zig b/src/link/C.zig index 8fb3637cbe..1860fdb051 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -150,6 +150,19 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { .iov_len = zig_h.len, }); + var error_defs_buf = std.ArrayList(u8).init(comp.gpa); + defer error_defs_buf.deinit(); + + var it = module.global_error_set.iterator(); + while (it.next()) |entry| { + try error_defs_buf.writer().print("#define zig_error_{s} {d}\n", .{ entry.key, entry.value }); + } + try error_defs_buf.writer().writeByte('\n'); + all_buffers.appendAssumeCapacity(.{ + .iov_base = error_defs_buf.items.ptr, + .iov_len = error_defs_buf.items.len, + }); + var fn_count: usize = 0; // Forward decls and non-functions first. diff --git a/src/type.zig b/src/type.zig index bb8dcea390..50d55a0c54 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1813,6 +1813,18 @@ pub const Type = extern union { } } + /// Asserts that the type is an error union. + pub fn errorUnionChild(self: Type) Type { + return switch (self.tag()) { + .anyerror_void_error_union => Type.initTag(.anyerror), + .error_union => { + const payload = self.castTag(.error_union).?; + return payload.data.payload; + }, + else => unreachable, + }; + } + /// Asserts the type is an array or vector. pub fn arrayLen(self: Type) u64 { return switch (self.tag()) { |
