authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-03 16:10:41-07:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-05 10:37:08+02:00
logd2f31d315e47c3918cd711d1008862df49df38f2
tree837e3a388702515cd6037b0b7a3b648a710b86bb
parent779770cff58923e5113b5419accf910059fddea7

C backend: implement `try` instruction


1 files changed, 92 insertions(+), 2 deletions(-)

src/codegen/c.zig+92-2
......@@ -1875,8 +1875,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
18751875 .union_init => try airUnionInit(f, inst),
18761876 .prefetch => try airPrefetch(f, inst),
18771877
1878 .@"try" => @panic("TODO"),
1879 .try_ptr => @panic("TODO"),
1878 .@"try" => try airTry(f, inst),
1879 .try_ptr => try airTryPtr(f, inst),
18801880
18811881 .dbg_var_ptr,
18821882 .dbg_var_val,
......@@ -2864,6 +2864,91 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
28642864 return result;
28652865}
28662866
2867fn airTry(f: *Function, inst: Air.Inst.Index) !CValue {
2868 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
2869 const err_union = try f.resolveInst(pl_op.operand);
2870 const extra = f.air.extraData(Air.Try, pl_op.payload);
2871 const body = f.air.extra[extra.end..][0..extra.data.body_len];
2872 const err_union_ty = f.air.typeOf(pl_op.operand);
2873 const result_ty = f.air.typeOfIndex(inst);
2874 return lowerTry(f, err_union, body, err_union_ty, false, result_ty);
2875}
2876
2877fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue {
2878 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
2879 const extra = f.air.extraData(Air.TryPtr, ty_pl.payload);
2880 const err_union_ptr = try f.resolveInst(extra.data.ptr);
2881 const body = f.air.extra[extra.end..][0..extra.data.body_len];
2882 const err_union_ty = f.air.typeOf(extra.data.ptr).childType();
2883 const result_ty = f.air.typeOfIndex(inst);
2884 return lowerTry(f, err_union_ptr, body, err_union_ty, true, result_ty);
2885}
2886
2887fn lowerTry(
2888 f: *Function,
2889 err_union: CValue,
2890 body: []const Air.Inst.Index,
2891 err_union_ty: Type,
2892 operand_is_ptr: bool,
2893 result_ty: Type,
2894) !CValue {
2895 if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
2896 // If the error set has no fields, then the payload and the error
2897 // union are the same value.
2898 return err_union;
2899 }
2900
2901 const payload_ty = err_union_ty.errorUnionPayload();
2902 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
2903
2904 const writer = f.object.writer();
2905
2906 err: {
2907 if (!payload_has_bits) {
2908 if (operand_is_ptr) {
2909 try writer.writeAll("if(*");
2910 } else {
2911 try writer.writeAll("if(");
2912 }
2913 try f.writeCValue(writer, err_union);
2914 try writer.writeAll(")");
2915 break :err;
2916 }
2917 if (operand_is_ptr or isByRef(err_union_ty)) {
2918 try writer.writeAll("if(");
2919 try f.writeCValue(writer, err_union);
2920 try writer.writeAll("->error)");
2921 break :err;
2922 }
2923 try writer.writeAll("if(");
2924 try f.writeCValue(writer, err_union);
2925 try writer.writeAll(".error)");
2926 }
2927
2928 try genBody(f, body);
2929 try f.object.indent_writer.insertNewline();
2930
2931 if (!payload_has_bits) {
2932 if (!operand_is_ptr) {
2933 return CValue.none;
2934 } else {
2935 return err_union;
2936 }
2937 }
2938
2939 const local = try f.allocLocal(result_ty, .Const);
2940 if (operand_is_ptr or isByRef(payload_ty)) {
2941 try writer.writeAll(" = &");
2942 try f.writeCValue(writer, err_union);
2943 try writer.writeAll("->payload;\n");
2944 } else {
2945 try writer.writeAll(" = ");
2946 try f.writeCValue(writer, err_union);
2947 try writer.writeAll(".payload;\n");
2948 }
2949 return local;
2950}
2951
28672952fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
28682953 const branch = f.air.instructions.items(.data)[inst].br;
28692954 const block = f.blocks.get(branch.block_inst).?;
......@@ -4224,3 +4309,8 @@ fn loweredFnRetTyHasBits(fn_ty: Type) bool {
42244309 }
42254310 return false;
42264311}
4312
4313fn isByRef(ty: Type) bool {
4314 _ = ty;
4315 return false;
4316}