aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2021-01-29 18:20:35 +0200
committerVeikka Tuominen <git@vexu.eu>2021-03-08 00:33:07 +0200
commitcfc19eace71c92ecd7e138db6d961271a1b6c126 (patch)
treea95c89dbf3b86a83747203c406b4fbb34a1eaad2 /src
parentc22f010fdd2c5ead80cbdc902738a9d023322436 (diff)
downloadzig-cfc19eace71c92ecd7e138db6d961271a1b6c126.tar.gz
zig-cfc19eace71c92ecd7e138db6d961271a1b6c126.zip
stage2 cbe: errors
Diffstat (limited to 'src')
-rw-r--r--src/codegen/c.zig29
-rw-r--r--src/link/C.zig13
-rw-r--r--src/type.zig12
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()) {