aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-06-03 16:10:41 -0700
committerJakub Konka <kubkon@jakubkonka.com>2022-06-05 10:37:08 +0200
commitd2f31d315e47c3918cd711d1008862df49df38f2 (patch)
tree837e3a388702515cd6037b0b7a3b648a710b86bb /src
parent779770cff58923e5113b5419accf910059fddea7 (diff)
downloadzig-d2f31d315e47c3918cd711d1008862df49df38f2.tar.gz
zig-d2f31d315e47c3918cd711d1008862df49df38f2.zip
C backend: implement `try` instruction
Diffstat (limited to 'src')
-rw-r--r--src/codegen/c.zig94
1 files changed, 92 insertions, 2 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 597b3b0f6b..4c2239b306 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1875,8 +1875,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.union_init => try airUnionInit(f, inst),
.prefetch => try airPrefetch(f, inst),
- .@"try" => @panic("TODO"),
- .try_ptr => @panic("TODO"),
+ .@"try" => try airTry(f, inst),
+ .try_ptr => try airTryPtr(f, inst),
.dbg_var_ptr,
.dbg_var_val,
@@ -2864,6 +2864,91 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
return result;
}
+fn airTry(f: *Function, inst: Air.Inst.Index) !CValue {
+ const pl_op = f.air.instructions.items(.data)[inst].pl_op;
+ const err_union = try f.resolveInst(pl_op.operand);
+ const extra = f.air.extraData(Air.Try, pl_op.payload);
+ const body = f.air.extra[extra.end..][0..extra.data.body_len];
+ const err_union_ty = f.air.typeOf(pl_op.operand);
+ const result_ty = f.air.typeOfIndex(inst);
+ return lowerTry(f, err_union, body, err_union_ty, false, result_ty);
+}
+
+fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue {
+ const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
+ const extra = f.air.extraData(Air.TryPtr, ty_pl.payload);
+ const err_union_ptr = try f.resolveInst(extra.data.ptr);
+ const body = f.air.extra[extra.end..][0..extra.data.body_len];
+ const err_union_ty = f.air.typeOf(extra.data.ptr).childType();
+ const result_ty = f.air.typeOfIndex(inst);
+ return lowerTry(f, err_union_ptr, body, err_union_ty, true, result_ty);
+}
+
+fn lowerTry(
+ f: *Function,
+ err_union: CValue,
+ body: []const Air.Inst.Index,
+ err_union_ty: Type,
+ operand_is_ptr: bool,
+ result_ty: Type,
+) !CValue {
+ if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
+ // If the error set has no fields, then the payload and the error
+ // union are the same value.
+ return err_union;
+ }
+
+ const payload_ty = err_union_ty.errorUnionPayload();
+ const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
+
+ const writer = f.object.writer();
+
+ err: {
+ if (!payload_has_bits) {
+ if (operand_is_ptr) {
+ try writer.writeAll("if(*");
+ } else {
+ try writer.writeAll("if(");
+ }
+ try f.writeCValue(writer, err_union);
+ try writer.writeAll(")");
+ break :err;
+ }
+ if (operand_is_ptr or isByRef(err_union_ty)) {
+ try writer.writeAll("if(");
+ try f.writeCValue(writer, err_union);
+ try writer.writeAll("->error)");
+ break :err;
+ }
+ try writer.writeAll("if(");
+ try f.writeCValue(writer, err_union);
+ try writer.writeAll(".error)");
+ }
+
+ try genBody(f, body);
+ try f.object.indent_writer.insertNewline();
+
+ if (!payload_has_bits) {
+ if (!operand_is_ptr) {
+ return CValue.none;
+ } else {
+ return err_union;
+ }
+ }
+
+ const local = try f.allocLocal(result_ty, .Const);
+ if (operand_is_ptr or isByRef(payload_ty)) {
+ try writer.writeAll(" = &");
+ try f.writeCValue(writer, err_union);
+ try writer.writeAll("->payload;\n");
+ } else {
+ try writer.writeAll(" = ");
+ try f.writeCValue(writer, err_union);
+ try writer.writeAll(".payload;\n");
+ }
+ return local;
+}
+
fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
const branch = f.air.instructions.items(.data)[inst].br;
const block = f.blocks.get(branch.block_inst).?;
@@ -4224,3 +4309,8 @@ fn loweredFnRetTyHasBits(fn_ty: Type) bool {
}
return false;
}
+
+fn isByRef(ty: Type) bool {
+ _ = ty;
+ return false;
+}