aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorjacob gw <jacoblevgw@gmail.com>2021-03-01 15:16:18 -0500
committerVeikka Tuominen <git@vexu.eu>2021-03-08 00:33:59 +0200
commit30ffa052f2b53d9a01aedbe672bec3c5e28d5118 (patch)
tree252ec19b85f0e80e3e7c872d570ef3d4540bec73 /src/codegen/c.zig
parent6467ef6d3b5648d47c13b877d3d4fe6a5b5efb7d (diff)
downloadzig-30ffa052f2b53d9a01aedbe672bec3c5e28d5118.tar.gz
zig-30ffa052f2b53d9a01aedbe672bec3c5e28d5118.zip
stage2 cbe: add error union and error union operations
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig85
1 files changed, 83 insertions, 2 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 084c653d1c..ceafe01d35 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -251,6 +251,31 @@ pub const DeclGen = struct {
// error values will be #defined at the top of the file
return writer.print("zig_error_{s}", .{payload.data.name});
},
+ .ErrorUnion => {
+ const error_type = t.errorUnionSet();
+ const payload_type = t.errorUnionChild();
+ const data = val.castTag(.error_union).?.data;
+ try writer.writeByte('(');
+ try dg.renderType(writer, t);
+ try writer.writeAll("){");
+ if (val.getError()) |_| {
+ try writer.writeAll(" .error = ");
+ try dg.renderValue(
+ writer,
+ error_type,
+ data,
+ );
+ try writer.writeAll(" }");
+ } else {
+ try writer.writeAll(" .payload = ");
+ try dg.renderValue(
+ writer,
+ payload_type,
+ data,
+ );
+ try writer.writeAll(", .error = 0 }");
+ }
+ },
else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{
@tagName(e),
}),
@@ -385,16 +410,17 @@ pub const DeclGen = struct {
return w.writeAll(some.name);
}
const child_type = t.errorUnionChild();
+ const set_type = t.errorUnionSet();
var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
defer buffer.deinit();
const bw = buffer.writer();
try bw.writeAll("typedef struct { ");
- try dg.renderType(bw, t.errorUnionChild());
+ try dg.renderType(bw, child_type);
try bw.writeAll(" payload; uint16_t error; } ");
const name_index = buffer.items.len;
- try bw.print("zig_err_union_{s}_t;\n", .{typeToCIdentifier(child_type)});
+ try bw.print("zig_err_union_{s}_{s}_t;\n", .{ typeToCIdentifier(set_type), typeToCIdentifier(child_type) });
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);
@@ -543,6 +569,12 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
.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).?),
+ .unwrap_errunion_payload => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload).?),
+ .unwrap_errunion_err => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err).?),
+ .unwrap_errunion_payload_ptr => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload_ptr).?),
+ .unwrap_errunion_err_ptr => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err_ptr).?),
+ .wrap_errunion_payload => try genWrapErrUnionPay(o, inst.castTag(.wrap_errunion_payload).?),
+ .wrap_errunion_err => try genWrapErrUnionErr(o, inst.castTag(.wrap_errunion_err).?),
else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}),
};
switch (result_value) {
@@ -962,6 +994,35 @@ fn genOptionalPayload(o: *Object, inst: *Inst.UnOp) !CValue {
return local;
}
+// *(E!T) -> E NOT *E
+fn genUnwrapErrUnionErr(o: *Object, inst: *Inst.UnOp) !CValue {
+ const writer = o.writer();
+ const operand = try o.resolveInst(inst.operand);
+
+ const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else ".";
+
+ const local = try o.allocLocal(inst.base.ty, .Const);
+ try writer.writeAll(" = (");
+ try o.writeCValue(writer, operand);
+
+ try writer.print("){s}error;\n", .{maybe_deref});
+ return local;
+}
+fn genUnwrapErrUnionPay(o: *Object, inst: *Inst.UnOp) !CValue {
+ const writer = o.writer();
+ const operand = try o.resolveInst(inst.operand);
+
+ const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else ".";
+ const maybe_addrof = if (inst.base.ty.zigTypeTag() == .Pointer) "&" else "";
+
+ const local = try o.allocLocal(inst.base.ty, .Const);
+ try writer.print(" = {s}(", .{maybe_addrof});
+ try o.writeCValue(writer, operand);
+
+ try writer.print("){s}payload;\n", .{maybe_deref});
+ return local;
+}
+
fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue {
const writer = o.writer();
const operand = try o.resolveInst(inst.operand);
@@ -978,6 +1039,26 @@ fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue {
try writer.writeAll("};\n");
return local;
}
+fn genWrapErrUnionErr(o: *Object, inst: *Inst.UnOp) !CValue {
+ const writer = o.writer();
+ const operand = try o.resolveInst(inst.operand);
+
+ const local = try o.allocLocal(inst.base.ty, .Const);
+ try writer.writeAll(" = { .error = ");
+ try o.writeCValue(writer, operand);
+ try writer.writeAll(" };\n");
+ return local;
+}
+fn genWrapErrUnionPay(o: *Object, inst: *Inst.UnOp) !CValue {
+ const writer = o.writer();
+ const operand = try o.resolveInst(inst.operand);
+
+ const local = try o.allocLocal(inst.base.ty, .Const);
+ try writer.writeAll(" = { .error = 0, .payload = ");
+ try o.writeCValue(writer, operand);
+ try writer.writeAll(" };\n");
+ return local;
+}
fn genIsErr(o: *Object, inst: *Inst.UnOp) !CValue {
const writer = o.writer();