diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-06-02 19:49:34 -0700 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-06-05 10:37:08 +0200 |
| commit | f4ac37f55da7258c25194e66e1cfe3270ca9d419 (patch) | |
| tree | 950151f6d2db1620463fe2a3a44faa02b1dfe685 /src/Sema.zig | |
| parent | 6d3586e0edf3278862a3a969debaa842014f8110 (diff) | |
| download | zig-f4ac37f55da7258c25194e66e1cfe3270ca9d419.tar.gz zig-f4ac37f55da7258c25194e66e1cfe3270ca9d419.zip | |
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.
Diffstat (limited to 'src/Sema.zig')
| -rw-r--r-- | src/Sema.zig | 109 |
1 files changed, 63 insertions, 46 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 12ff5c5dbc..6d618fee2c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1323,7 +1323,7 @@ fn analyzeBodyInner( } }, .@"try" => blk: { - if (!block.is_comptime) break :blk try sema.zirTry(block, inst, false); + if (!block.is_comptime) break :blk try sema.zirTry(block, inst); const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; @@ -1376,7 +1376,7 @@ fn analyzeBodyInner( // } //}, .try_ptr => blk: { - if (!block.is_comptime) break :blk try sema.zirTry(block, inst, true); + if (!block.is_comptime) break :blk try sema.zirTryPtr(block, inst); const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; @@ -13065,22 +13065,13 @@ fn zirCondbr( return always_noreturn; } -fn zirTry( - sema: *Sema, - parent_block: *Block, - inst: Zir.Inst.Index, - is_ptr: bool, -) CompileError!Zir.Inst.Ref { +fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); const body = sema.code.extra[extra.end..][0..extra.data.body_len]; - const operand = try sema.resolveInst(extra.data.operand); - const err_union = if (is_ptr) - try sema.analyzeLoad(parent_block, src, operand, operand_src) - else - operand; + const err_union = try sema.resolveInst(extra.data.operand); const err_union_ty = sema.typeOf(err_union); if (err_union_ty.zigTypeTag() != .ErrorUnion) { return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{ @@ -13091,11 +13082,7 @@ fn zirTry( if (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)) |is_non_err_val| { if (is_non_err_val.toBool()) { - if (is_ptr) { - return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false); - } else { - return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, operand, operand_src, false); - } + return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, err_union, operand_src, false); } // We can analyze the body directly in the parent block because we know there are // no breaks from the body possible, and that the body is noreturn. @@ -13108,39 +13095,12 @@ fn zirTry( // This body is guaranteed to end with noreturn and has no breaks. _ = try sema.analyzeBodyInner(&sub_block, body); - if (is_ptr) { - const operand_ty = sema.typeOf(operand); - const ptr_info = operand_ty.ptrInfo().data; - const res_ty = try Type.ptr(sema.arena, sema.mod, .{ - .pointee_type = err_union_ty.errorUnionPayload(), - .@"addrspace" = ptr_info.@"addrspace", - .mutable = ptr_info.mutable, - .@"allowzero" = ptr_info.@"allowzero", - .@"volatile" = ptr_info.@"volatile", - }); - const res_ty_ref = try sema.addType(res_ty); - try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len + - sub_block.instructions.items.len); - const try_inst = try parent_block.addInst(.{ - .tag = .try_ptr, - .data = .{ .ty_pl = .{ - .ty = res_ty_ref, - .payload = sema.addExtraAssumeCapacity(Air.TryPtr{ - .ptr = operand, - .body_len = @intCast(u32, sub_block.instructions.items.len), - }), - } }, - }); - sema.air_extra.appendSliceAssumeCapacity(sub_block.instructions.items); - return try_inst; - } - try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len + sub_block.instructions.items.len); const try_inst = try parent_block.addInst(.{ .tag = .@"try", .data = .{ .pl_op = .{ - .operand = operand, + .operand = err_union, .payload = sema.addExtraAssumeCapacity(Air.Try{ .body_len = @intCast(u32, sub_block.instructions.items.len), }), @@ -13150,6 +13110,63 @@ fn zirTry( return try_inst; } +fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref { + const inst_data = sema.code.instructions.items(.data)[inst].pl_node; + const src = inst_data.src(); + const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; + const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); + const body = sema.code.extra[extra.end..][0..extra.data.body_len]; + const operand = try sema.resolveInst(extra.data.operand); + const err_union = try sema.analyzeLoad(parent_block, src, operand, operand_src); + const err_union_ty = sema.typeOf(err_union); + if (err_union_ty.zigTypeTag() != .ErrorUnion) { + return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{ + err_union_ty.fmt(sema.mod), + }); + } + const is_non_err = try sema.analyzeIsNonErr(parent_block, operand_src, err_union); + + if (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)) |is_non_err_val| { + if (is_non_err_val.toBool()) { + return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false); + } + // We can analyze the body directly in the parent block because we know there are + // no breaks from the body possible, and that the body is noreturn. + return sema.resolveBody(parent_block, body, inst); + } + + var sub_block = parent_block.makeSubBlock(); + defer sub_block.instructions.deinit(sema.gpa); + + // This body is guaranteed to end with noreturn and has no breaks. + _ = try sema.analyzeBodyInner(&sub_block, body); + + const operand_ty = sema.typeOf(operand); + const ptr_info = operand_ty.ptrInfo().data; + const res_ty = try Type.ptr(sema.arena, sema.mod, .{ + .pointee_type = err_union_ty.errorUnionPayload(), + .@"addrspace" = ptr_info.@"addrspace", + .mutable = ptr_info.mutable, + .@"allowzero" = ptr_info.@"allowzero", + .@"volatile" = ptr_info.@"volatile", + }); + const res_ty_ref = try sema.addType(res_ty); + try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.TryPtr).Struct.fields.len + + sub_block.instructions.items.len); + const try_inst = try parent_block.addInst(.{ + .tag = .try_ptr, + .data = .{ .ty_pl = .{ + .ty = res_ty_ref, + .payload = sema.addExtraAssumeCapacity(Air.TryPtr{ + .ptr = operand, + .body_len = @intCast(u32, sub_block.instructions.items.len), + }), + } }, + }); + sema.air_extra.appendSliceAssumeCapacity(sub_block.instructions.items); + return try_inst; +} + // A `break` statement is inside a runtime condition, but trying to // break from an inline loop. In such case we must convert it to // a runtime break. |
