authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-02 19:49:34-07:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-05 10:37:08+02:00
logf4ac37f55da7258c25194e66e1cfe3270ca9d419
tree950151f6d2db1620463fe2a3a44faa02b1dfe685
parent6d3586e0edf3278862a3a969debaa842014f8110

Sema: extract out zirTryPtr from zirTry

This function took is_ptr: bool and then branched on it three times. Now, instead, each implementation does no branching and the logic is easier to follow, both for maintainers and compilers. I also fixed a bug with TryPtr not ensuring enough capacity in the extra array.

1 files changed, 63 insertions(+), 46 deletions(-)

src/Sema.zig+63-46
......@@ -1323,7 +1323,7 @@ fn analyzeBodyInner(
13231323 }
13241324 },
13251325 .@"try" => blk: {
1326 if (!block.is_comptime) break :blk try sema.zirTry(block, inst, false);
1326 if (!block.is_comptime) break :blk try sema.zirTry(block, inst);
13271327 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13281328 const src = inst_data.src();
13291329 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
......@@ -1376,7 +1376,7 @@ fn analyzeBodyInner(
13761376 // }
13771377 //},
13781378 .try_ptr => blk: {
1379 if (!block.is_comptime) break :blk try sema.zirTry(block, inst, true);
1379 if (!block.is_comptime) break :blk try sema.zirTryPtr(block, inst);
13801380 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13811381 const src = inst_data.src();
13821382 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
......@@ -13065,22 +13065,13 @@ fn zirCondbr(
1306513065 return always_noreturn;
1306613066}
1306713067
13068fn zirTry(
13069 sema: *Sema,
13070 parent_block: *Block,
13071 inst: Zir.Inst.Index,
13072 is_ptr: bool,
13073) CompileError!Zir.Inst.Ref {
13068fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref {
1307413069 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1307513070 const src = inst_data.src();
1307613071 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
1307713072 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1307813073 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
13079 const operand = try sema.resolveInst(extra.data.operand);
13080 const err_union = if (is_ptr)
13081 try sema.analyzeLoad(parent_block, src, operand, operand_src)
13082 else
13083 operand;
13074 const err_union = try sema.resolveInst(extra.data.operand);
1308413075 const err_union_ty = sema.typeOf(err_union);
1308513076 if (err_union_ty.zigTypeTag() != .ErrorUnion) {
1308613077 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{
......@@ -13091,11 +13082,7 @@ fn zirTry(
1309113082
1309213083 if (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)) |is_non_err_val| {
1309313084 if (is_non_err_val.toBool()) {
13094 if (is_ptr) {
13095 return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false);
13096 } else {
13097 return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, operand, operand_src, false);
13098 }
13085 return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, err_union, operand_src, false);
1309913086 }
1310013087 // We can analyze the body directly in the parent block because we know there are
1310113088 // no breaks from the body possible, and that the body is noreturn.
......@@ -13108,39 +13095,12 @@ fn zirTry(
1310813095 // This body is guaranteed to end with noreturn and has no breaks.
1310913096 _ = try sema.analyzeBodyInner(&sub_block, body);
1311013097
13111 if (is_ptr) {
13112 const operand_ty = sema.typeOf(operand);
13113 const ptr_info = operand_ty.ptrInfo().data;
13114 const res_ty = try Type.ptr(sema.arena, sema.mod, .{
13115 .pointee_type = err_union_ty.errorUnionPayload(),
13116 .@"addrspace" = ptr_info.@"addrspace",
13117 .mutable = ptr_info.mutable,
13118 .@"allowzero" = ptr_info.@"allowzero",
13119 .@"volatile" = ptr_info.@"volatile",
13120 });
13121 const res_ty_ref = try sema.addType(res_ty);
13122 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len +
13123 sub_block.instructions.items.len);
13124 const try_inst = try parent_block.addInst(.{
13125 .tag = .try_ptr,
13126 .data = .{ .ty_pl = .{
13127 .ty = res_ty_ref,
13128 .payload = sema.addExtraAssumeCapacity(Air.TryPtr{
13129 .ptr = operand,
13130 .body_len = @intCast(u32, sub_block.instructions.items.len),
13131 }),
13132 } },
13133 });
13134 sema.air_extra.appendSliceAssumeCapacity(sub_block.instructions.items);
13135 return try_inst;
13136 }
13137
1313813098 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len +
1313913099 sub_block.instructions.items.len);
1314013100 const try_inst = try parent_block.addInst(.{
1314113101 .tag = .@"try",
1314213102 .data = .{ .pl_op = .{
13143 .operand = operand,
13103 .operand = err_union,
1314413104 .payload = sema.addExtraAssumeCapacity(Air.Try{
1314513105 .body_len = @intCast(u32, sub_block.instructions.items.len),
1314613106 }),
......@@ -13150,6 +13110,63 @@ fn zirTry(
1315013110 return try_inst;
1315113111}
1315213112
13113fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref {
13114 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13115 const src = inst_data.src();
13116 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
13117 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
13118 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
13119 const operand = try sema.resolveInst(extra.data.operand);
13120 const err_union = try sema.analyzeLoad(parent_block, src, operand, operand_src);
13121 const err_union_ty = sema.typeOf(err_union);
13122 if (err_union_ty.zigTypeTag() != .ErrorUnion) {
13123 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{
13124 err_union_ty.fmt(sema.mod),
13125 });
13126 }
13127 const is_non_err = try sema.analyzeIsNonErr(parent_block, operand_src, err_union);
13128
13129 if (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)) |is_non_err_val| {
13130 if (is_non_err_val.toBool()) {
13131 return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false);
13132 }
13133 // We can analyze the body directly in the parent block because we know there are
13134 // no breaks from the body possible, and that the body is noreturn.
13135 return sema.resolveBody(parent_block, body, inst);
13136 }
13137
13138 var sub_block = parent_block.makeSubBlock();
13139 defer sub_block.instructions.deinit(sema.gpa);
13140
13141 // This body is guaranteed to end with noreturn and has no breaks.
13142 _ = try sema.analyzeBodyInner(&sub_block, body);
13143
13144 const operand_ty = sema.typeOf(operand);
13145 const ptr_info = operand_ty.ptrInfo().data;
13146 const res_ty = try Type.ptr(sema.arena, sema.mod, .{
13147 .pointee_type = err_union_ty.errorUnionPayload(),
13148 .@"addrspace" = ptr_info.@"addrspace",
13149 .mutable = ptr_info.mutable,
13150 .@"allowzero" = ptr_info.@"allowzero",
13151 .@"volatile" = ptr_info.@"volatile",
13152 });
13153 const res_ty_ref = try sema.addType(res_ty);
13154 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.TryPtr).Struct.fields.len +
13155 sub_block.instructions.items.len);
13156 const try_inst = try parent_block.addInst(.{
13157 .tag = .try_ptr,
13158 .data = .{ .ty_pl = .{
13159 .ty = res_ty_ref,
13160 .payload = sema.addExtraAssumeCapacity(Air.TryPtr{
13161 .ptr = operand,
13162 .body_len = @intCast(u32, sub_block.instructions.items.len),
13163 }),
13164 } },
13165 });
13166 sema.air_extra.appendSliceAssumeCapacity(sub_block.instructions.items);
13167 return try_inst;
13168}
13169
1315313170// A `break` statement is inside a runtime condition, but trying to
1315413171// break from an inline loop. In such case we must convert it to
1315513172// a runtime break.