authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-05-26 04:10:51+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-06-13 12:53:18+01:00
log00609e7edbbc949b12e29a8d9911d988b78d7e03
treef5f76c6dc16054d3480398fd566e35099a74feb7
parentcebd80032a2dcc9f516f8183d1bfade5d1f12e45
signaturelock-open Commit is signed but in an unrecognized format.

Eliminate switch_capture and switch_capture_ref ZIR tags

These tags are unnecessary, as this information can be more efficiently encoded within the switch_block instruction itself. We also use a neat little trick to avoid needing a dummy instruction (like is used for errdefer captures): since the switch_block itself cannot otherwise be referenced within a prong, we can repurpose its index within prongs to refer to the captured value.

5 files changed, 565 insertions(+), 336 deletions(-)

src/AstGen.zig+30-38
......@@ -2612,8 +2612,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
26122612 .switch_block,
26132613 .switch_cond,
26142614 .switch_cond_ref,
2615 .switch_capture,
2616 .switch_capture_ref,
26172615 .switch_capture_tag,
26182616 .struct_init_empty,
26192617 .struct_init,
......@@ -6876,17 +6874,22 @@ fn switchExpr(
68766874 var dbg_var_inst: Zir.Inst.Ref = undefined;
68776875 var dbg_var_tag_name: ?u32 = null;
68786876 var dbg_var_tag_inst: Zir.Inst.Ref = undefined;
6879 var capture_inst: Zir.Inst.Index = 0;
68806877 var tag_inst: Zir.Inst.Index = 0;
68816878 var capture_val_scope: Scope.LocalVal = undefined;
68826879 var tag_scope: Scope.LocalVal = undefined;
6880
6881 var capture: Zir.Inst.SwitchBlock.ProngInfo.Capture = .none;
6882
68836883 const sub_scope = blk: {
68846884 const payload_token = case.payload_token orelse break :blk &case_scope.base;
68856885 const ident = if (token_tags[payload_token] == .asterisk)
68866886 payload_token + 1
68876887 else
68886888 payload_token;
6889
68896890 const is_ptr = ident != payload_token;
6891 capture = if (is_ptr) .by_ref else .by_val;
6892
68906893 const ident_slice = tree.tokenSlice(ident);
68916894 var payload_sub_scope: *Scope = undefined;
68926895 if (mem.eql(u8, ident_slice, "_")) {
......@@ -6895,46 +6898,18 @@ fn switchExpr(
68956898 }
68966899 payload_sub_scope = &case_scope.base;
68976900 } else {
6898 if (case_node == special_node) {
6899 const capture_tag: Zir.Inst.Tag = if (is_ptr)
6900 .switch_capture_ref
6901 else
6902 .switch_capture;
6903 capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len);
6904 try astgen.instructions.append(gpa, .{
6905 .tag = capture_tag,
6906 .data = .{
6907 .switch_capture = .{
6908 .switch_inst = switch_block,
6909 // Max int communicates that this is the else/underscore prong.
6910 .prong_index = std.math.maxInt(u32),
6911 },
6912 },
6913 });
6914 } else {
6915 const capture_tag: Zir.Inst.Tag = if (is_ptr) .switch_capture_ref else .switch_capture;
6916 const capture_index = if (is_multi_case) scalar_cases_len + multi_case_index else scalar_case_index;
6917 capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len);
6918 try astgen.instructions.append(gpa, .{
6919 .tag = capture_tag,
6920 .data = .{ .switch_capture = .{
6921 .switch_inst = switch_block,
6922 .prong_index = capture_index,
6923 } },
6924 });
6925 }
69266901 const capture_name = try astgen.identAsString(ident);
69276902 try astgen.detectLocalShadowing(&case_scope.base, capture_name, ident, ident_slice, .capture);
69286903 capture_val_scope = .{
69296904 .parent = &case_scope.base,
69306905 .gen_zir = &case_scope,
69316906 .name = capture_name,
6932 .inst = indexToRef(capture_inst),
6907 .inst = indexToRef(switch_block),
69336908 .token_src = payload_token,
69346909 .id_cat = .capture,
69356910 };
69366911 dbg_var_name = capture_name;
6937 dbg_var_inst = indexToRef(capture_inst);
6912 dbg_var_inst = indexToRef(switch_block);
69386913 payload_sub_scope = &capture_val_scope.base;
69396914 }
69406915
......@@ -7023,7 +6998,6 @@ fn switchExpr(
70236998 case_scope.instructions_top = parent_gz.instructions.items.len;
70246999 defer case_scope.unstack();
70257000
7026 if (capture_inst != 0) try case_scope.instructions.append(gpa, capture_inst);
70277001 if (tag_inst != 0) try case_scope.instructions.append(gpa, tag_inst);
70287002 try case_scope.addDbgBlockBegin();
70297003 if (dbg_var_name) |some| {
......@@ -7042,10 +7016,28 @@ fn switchExpr(
70427016 }
70437017
70447018 const case_slice = case_scope.instructionsSlice();
7045 const body_len = astgen.countBodyLenAfterFixups(case_slice);
7019 // Since we use the switch_block instruction itself to refer to the
7020 // capture, which will not be added to the child block, we need to
7021 // handle ref_table manually.
7022 const refs_len = refs: {
7023 var n: usize = 0;
7024 var check_inst = switch_block;
7025 while (astgen.ref_table.get(check_inst)) |ref_inst| {
7026 n += 1;
7027 check_inst = ref_inst;
7028 }
7029 break :refs n;
7030 };
7031 const body_len = refs_len + astgen.countBodyLenAfterFixups(case_slice);
70467032 try payloads.ensureUnusedCapacity(gpa, body_len);
7047 const inline_bit = @as(u32, @boolToInt(case.inline_token != null)) << 31;
7048 payloads.items[body_len_index] = body_len | inline_bit;
7033 payloads.items[body_len_index] = @bitCast(u32, Zir.Inst.SwitchBlock.ProngInfo{
7034 .body_len = @intCast(u29, body_len),
7035 .capture = capture,
7036 .is_inline = case.inline_token != null,
7037 });
7038 if (astgen.ref_table.fetchRemove(switch_block)) |kv| {
7039 appendPossiblyRefdBodyInst(astgen, payloads, kv.value);
7040 }
70497041 appendBodyWithFixupsArrayList(astgen, payloads, case_slice);
70507042 }
70517043 }
......@@ -7092,7 +7084,7 @@ fn switchExpr(
70927084 end_index += 3 + items_len + 2 * ranges_len;
70937085 }
70947086
7095 const body_len = @truncate(u31, payloads.items[body_len_index]);
7087 const body_len = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, payloads.items[body_len_index]).body_len;
70967088 end_index += body_len;
70977089
70987090 switch (strat.tag) {
src/Module.zig+17-7
......@@ -5871,6 +5871,7 @@ pub const SwitchProngSrc = union(enum) {
58715871 multi: Multi,
58725872 range: Multi,
58735873 multi_capture: u32,
5874 special,
58745875
58755876 pub const Multi = struct {
58765877 prong: u32,
......@@ -5908,14 +5909,22 @@ pub const SwitchProngSrc = union(enum) {
59085909 var scalar_i: u32 = 0;
59095910 for (case_nodes) |case_node| {
59105911 const case = tree.fullSwitchCase(case_node).?;
5911 if (case.ast.values.len == 0)
5912 continue;
5913 if (case.ast.values.len == 1 and
5914 node_tags[case.ast.values[0]] == .identifier and
5915 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
5916 {
5917 continue;
5912
5913 const is_special = special: {
5914 if (case.ast.values.len == 0) break :special true;
5915 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .identifier) {
5916 break :special mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_");
5917 }
5918 break :special false;
5919 };
5920
5921 if (is_special) {
5922 if (prong_src != .special) continue;
5923 return LazySrcLoc.nodeOffset(
5924 decl.nodeIndexToRelative(case.ast.values[0]),
5925 );
59185926 }
5927
59195928 const is_multi = case.ast.values.len != 1 or
59205929 node_tags[case.ast.values[0]] == .switch_range;
59215930
......@@ -5956,6 +5965,7 @@ pub const SwitchProngSrc = union(enum) {
59565965 range_i += 1;
59575966 } else unreachable;
59585967 },
5968 .special => {},
59595969 }
59605970 if (is_multi) {
59615971 multi_i += 1;
src/Sema.zig+468-181
......@@ -277,9 +277,6 @@ pub const Block = struct {
277277
278278 c_import_buf: ?*std.ArrayList(u8) = null,
279279
280 /// type of `err` in `else => |err|`
281 switch_else_err_ty: ?Type = null,
282
283280 /// Value for switch_capture in an inline case
284281 inline_case_capture: Air.Inst.Ref = .none,
285282
......@@ -397,7 +394,6 @@ pub const Block = struct {
397394 .want_safety = parent.want_safety,
398395 .float_mode = parent.float_mode,
399396 .c_import_buf = parent.c_import_buf,
400 .switch_else_err_ty = parent.switch_else_err_ty,
401397 .error_return_trace_index = parent.error_return_trace_index,
402398 };
403399 }
......@@ -1017,8 +1013,6 @@ fn analyzeBodyInner(
10171013 .switch_block => try sema.zirSwitchBlock(block, inst),
10181014 .switch_cond => try sema.zirSwitchCond(block, inst, false),
10191015 .switch_cond_ref => try sema.zirSwitchCond(block, inst, true),
1020 .switch_capture => try sema.zirSwitchCapture(block, inst, false),
1021 .switch_capture_ref => try sema.zirSwitchCapture(block, inst, true),
10221016 .switch_capture_tag => try sema.zirSwitchCaptureTag(block, inst),
10231017 .type_info => try sema.zirTypeInfo(block, inst),
10241018 .size_of => try sema.zirSizeOf(block, inst),
......@@ -10083,61 +10077,160 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1008310077 return sema.analyzeSlice(block, src, array_ptr, start, len, sentinel, sentinel_src, ptr_src, start_src, end_src, true);
1008410078}
1008510079
10086fn zirSwitchCapture(
10080/// Resolve a switch prong which is determined at comptime to have no peers. Uses
10081/// `resolveBlockBody`. Sets up captures as needed.
10082fn resolveSwitchProngComptime(
1008710083 sema: *Sema,
10088 block: *Block,
10089 inst: Zir.Inst.Index,
10090 is_ref: bool,
10084 parent_block: *Block,
10085 child_block: *Block,
10086 src: LazySrcLoc,
10087 operand: Air.Inst.Ref,
10088 operand_ptr: Air.Inst.Ref,
10089 prong_type: enum { normal, special },
10090 prong_body: []const Zir.Inst.Index,
10091 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
10092 raw_capture_src: Module.SwitchProngSrc,
10093 else_error_ty: ?Type,
10094 case_vals: []const Air.Inst.Ref,
10095 switch_block_inst: Zir.Inst.Index,
10096 merges: *Block.Merges,
1009110097) CompileError!Air.Inst.Ref {
10092 const tracy = trace(@src());
10093 defer tracy.end();
10098 switch (capture) {
10099 .none => {
10100 return sema.resolveBlockBody(parent_block, src, child_block, prong_body, switch_block_inst, merges);
10101 },
10102
10103 .by_val, .by_ref => {
10104 const zir_datas = sema.code.instructions.items(.data);
10105 const switch_info = zir_datas[switch_block_inst].pl_node;
10106
10107 const capture_ref = try sema.analyzeSwitchCapture(
10108 child_block,
10109 capture == .by_ref,
10110 operand,
10111 operand_ptr,
10112 switch_info.src_node,
10113 prong_type == .special,
10114 raw_capture_src,
10115 else_error_ty,
10116 case_vals,
10117 );
10118
10119 if (sema.typeOf(capture_ref).isNoReturn(sema.mod)) {
10120 // This prong should be unreachable!
10121 return Air.Inst.Ref.unreachable_value;
10122 }
10123
10124 sema.inst_map.putAssumeCapacity(switch_block_inst, capture_ref);
10125 defer assert(sema.inst_map.remove(switch_block_inst));
10126
10127 return sema.resolveBlockBody(parent_block, src, child_block, prong_body, switch_block_inst, merges);
10128 },
10129 }
10130}
10131
10132/// Analyze a switch prong which may have peers at runtime. Uses
10133/// `analyzeBodyRuntimeBreak`. Sets up captures as needed.
10134fn analyzeSwitchProngRuntime(
10135 sema: *Sema,
10136 case_block: *Block,
10137 operand: Air.Inst.Ref,
10138 operand_ptr: Air.Inst.Ref,
10139 prong_type: enum { normal, special },
10140 prong_body: []const Zir.Inst.Index,
10141 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
10142 raw_capture_src: Module.SwitchProngSrc,
10143 else_error_ty: ?Type,
10144 case_vals: []const Air.Inst.Ref,
10145 switch_block_inst: Zir.Inst.Index,
10146) CompileError!void {
10147 switch (capture) {
10148 .none => {
10149 return sema.analyzeBodyRuntimeBreak(case_block, prong_body);
10150 },
10151
10152 .by_val, .by_ref => {
10153 const zir_datas = sema.code.instructions.items(.data);
10154 const switch_info = zir_datas[switch_block_inst].pl_node;
10155
10156 const capture_ref = try sema.analyzeSwitchCapture(
10157 case_block,
10158 capture == .by_ref,
10159 operand,
10160 operand_ptr,
10161 switch_info.src_node,
10162 prong_type == .special,
10163 raw_capture_src,
10164 else_error_ty,
10165 case_vals,
10166 );
1009410167
10168 if (sema.typeOf(capture_ref).isNoReturn(sema.mod)) {
10169 // No need to analyze any further, the prong is unreachable
10170 return;
10171 }
10172
10173 sema.inst_map.putAssumeCapacity(switch_block_inst, capture_ref);
10174 defer assert(sema.inst_map.remove(switch_block_inst));
10175
10176 return sema.analyzeBodyRuntimeBreak(case_block, prong_body);
10177 },
10178 }
10179}
10180
10181fn analyzeSwitchCapture(
10182 sema: *Sema,
10183 /// Must be the child block so that `inline_case_capture` is set for inline prongs.
10184 block: *Block,
10185 capture_byref: bool,
10186 /// The raw switch operand value.
10187 operand: Air.Inst.Ref,
10188 /// Pointer to the raw switch operand. May be undefined if `capture_byref` is false.
10189 operand_ptr: Air.Inst.Ref,
10190 switch_node_offset: i32,
10191 /// `true` if this is the `else` or `_` prong of a switch.
10192 is_special_prong: bool,
10193 /// Must use the `scalar`, `special`, or `multi_capture` union field.
10194 raw_capture_src: Module.SwitchProngSrc,
10195 /// If this is the `else` prong of a switch on an error set, this is the
10196 /// type that should be assigned to the capture. If `null`, the prong should
10197 /// be unreachable.
10198 else_error_ty: ?Type,
10199 /// The set of all values which can reach this prong. May be undefined if
10200 /// the prong has `is_special_prong` or contains ranges.
10201 case_vals: []const Air.Inst.Ref,
10202) CompileError!Air.Inst.Ref {
1009510203 const mod = sema.mod;
1009610204 const gpa = sema.gpa;
10097 const zir_datas = sema.code.instructions.items(.data);
10098 const capture_info = zir_datas[inst].switch_capture;
10099 const switch_info = zir_datas[capture_info.switch_inst].pl_node;
10100 const switch_extra = sema.code.extraData(Zir.Inst.SwitchBlock, switch_info.payload_index);
10101 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_info.src_node };
10102 const cond = try sema.resolveInst(switch_extra.data.operand);
10103 const cond_ty = sema.typeOf(cond);
10104 const cond_inst = Zir.refToIndex(switch_extra.data.operand).?;
10105 const cond_info = zir_datas[cond_inst].un_node;
10106 const cond_tag = sema.code.instructions.items(.tag)[cond_inst];
10107 const operand_is_ref = cond_tag == .switch_cond_ref;
10108 const operand_ptr = try sema.resolveInst(cond_info.operand);
10109 const operand_ptr_ty = sema.typeOf(operand_ptr);
10110 const operand_ty = if (operand_is_ref) operand_ptr_ty.childType(mod) else operand_ptr_ty;
10205 const operand_ty = sema.typeOf(operand);
10206 const operand_ptr_ty = if (capture_byref) sema.typeOf(operand_ptr) else undefined;
10207 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_node_offset };
1011110208
1011210209 if (block.inline_case_capture != .none) {
10113 const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, undefined) catch unreachable;
10114 const resolved_item_val = try sema.resolveLazyValue(item_val);
10210 const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, "") catch unreachable;
1011510211 if (operand_ty.zigTypeTag(mod) == .Union) {
10116 const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(resolved_item_val, mod).?);
10212 const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(item_val, mod).?);
1011710213 const union_obj = mod.typeToUnion(operand_ty).?;
1011810214 const field_ty = union_obj.fields.values()[field_index].ty;
10119 if (try sema.resolveDefinedValue(block, sema.src, operand_ptr)) |union_val| {
10120 if (is_ref) {
10215 if (capture_byref) {
10216 if (try sema.resolveDefinedValue(block, sema.src, operand_ptr)) |union_ptr| {
1012110217 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
1012210218 .pointee_type = field_ty,
1012310219 .mutable = operand_ptr_ty.ptrIsMutable(mod),
1012410220 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
1012510221 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
1012610222 });
10127 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
10128 .ty = ptr_field_ty.toIntern(),
10129 .addr = .{ .field = .{
10130 .base = union_val.toIntern(),
10131 .index = field_index,
10132 } },
10133 } })).toValue());
10223 return sema.addConstant(
10224 ptr_field_ty,
10225 (try mod.intern(.{ .ptr = .{
10226 .ty = ptr_field_ty.toIntern(),
10227 .addr = .{ .field = .{
10228 .base = union_ptr.toIntern(),
10229 .index = field_index,
10230 } },
10231 } })).toValue(),
10232 );
1013410233 }
10135 return sema.addConstant(
10136 field_ty,
10137 mod.intern_pool.indexToKey(union_val.toIntern()).un.val.toValue(),
10138 );
10139 }
10140 if (is_ref) {
1014110234 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
1014210235 .pointee_type = field_ty,
1014310236 .mutable = operand_ptr_ty.ptrIsMutable(mod),
......@@ -10146,29 +10239,27 @@ fn zirSwitchCapture(
1014610239 });
1014710240 return block.addStructFieldPtr(operand_ptr, field_index, ptr_field_ty);
1014810241 } else {
10149 return block.addStructFieldVal(operand_ptr, field_index, field_ty);
10242 if (try sema.resolveDefinedValue(block, sema.src, operand)) |union_val| {
10243 const tag_and_val = mod.intern_pool.indexToKey(union_val.toIntern()).un;
10244 return sema.addConstant(field_ty, tag_and_val.val.toValue());
10245 }
10246 return block.addStructFieldVal(operand, field_index, field_ty);
1015010247 }
10151 } else if (is_ref) {
10152 return sema.addConstantMaybeRef(block, operand_ty, resolved_item_val, true);
10248 } else if (capture_byref) {
10249 return sema.addConstantMaybeRef(block, operand_ty, item_val, true);
1015310250 } else {
1015410251 return block.inline_case_capture;
1015510252 }
1015610253 }
1015710254
10158 const operand = if (operand_is_ref)
10159 try sema.analyzeLoad(block, operand_src, operand_ptr, operand_src)
10160 else
10161 operand_ptr;
10162
10163 if (capture_info.prong_index == std.math.maxInt(@TypeOf(capture_info.prong_index))) {
10164 // It is the else/`_` prong.
10165 if (is_ref) {
10255 if (is_special_prong) {
10256 if (capture_byref) {
1016610257 return operand_ptr;
1016710258 }
1016810259
1016910260 switch (operand_ty.zigTypeTag(mod)) {
10170 .ErrorSet => if (block.switch_else_err_ty) |some| {
10171 return sema.bitCast(block, some, operand, operand_src, null);
10261 .ErrorSet => if (else_error_ty) |ty| {
10262 return sema.bitCast(block, ty, operand, operand_src, null);
1017210263 } else {
1017310264 try block.addUnreachable(false);
1017410265 return Air.Inst.Ref.unreachable_value;
......@@ -10177,41 +10268,33 @@ fn zirSwitchCapture(
1017710268 }
1017810269 }
1017910270
10180 // Note that these are the *uncasted* prong items.
10181 // Also note that items from ranges are not included so this only works for non-ranged types.
10182 const items = switch_extra.data.getProng(sema.code, switch_extra.end, capture_info.prong_index).items;
10183
1018410271 switch (operand_ty.zigTypeTag(mod)) {
1018510272 .Union => {
1018610273 const union_obj = mod.typeToUnion(operand_ty).?;
10187 const first_item = try sema.resolveInst(items[0]);
10188 // Previous switch validation ensured this will succeed
10189 const first_item_coerced = try sema.coerce(block, cond_ty, first_item, .unneeded);
10190 const first_item_val = sema.resolveConstValue(block, .unneeded, first_item_coerced, "") catch unreachable;
10274 const first_item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
1019110275
1019210276 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, mod).?);
1019310277 const first_field = union_obj.fields.values()[first_field_index];
1019410278
10195 for (items[1..], 0..) |item, i| {
10196 const item_ref = try sema.resolveInst(item);
10197 // Previous switch validation ensured this will succeed
10198 const item_coerced = try sema.coerce(block, cond_ty, item_ref, .unneeded);
10199 const item_val = sema.resolveConstValue(block, .unneeded, item_coerced, "") catch unreachable;
10279 for (case_vals[1..], 0..) |item, i| {
10280 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
1020010281
1020110282 const field_index = operand_ty.unionTagFieldIndex(item_val, mod).?;
1020210283 const field = union_obj.fields.values()[field_index];
1020310284 if (!field.ty.eql(first_field.ty, mod)) {
1020410285 const msg = msg: {
10205 const raw_capture_src = Module.SwitchProngSrc{ .multi_capture = capture_info.prong_index };
10206 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_info.src_node, .first);
10286 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
1020710287
1020810288 const msg = try sema.errMsg(block, capture_src, "capture group with incompatible types", .{});
1020910289 errdefer msg.destroy(gpa);
1021010290
10211 const raw_first_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = capture_info.prong_index, .item = 0 } };
10212 const first_item_src = raw_first_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_info.src_node, .first);
10213 const raw_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = capture_info.prong_index, .item = 1 + @intCast(u32, i) } };
10214 const item_src = raw_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_info.src_node, .first);
10291 // This must be a multi-prong so this must be a `multi_capture` src
10292 const multi_idx = raw_capture_src.multi_capture;
10293
10294 const raw_first_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_idx, .item = 0 } };
10295 const first_item_src = raw_first_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .first);
10296 const raw_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_idx, .item = 1 + @intCast(u32, i) } };
10297 const item_src = raw_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .first);
1021510298 try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(mod)});
1021610299 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(mod)});
1021710300 break :msg msg;
......@@ -10220,7 +10303,7 @@ fn zirSwitchCapture(
1022010303 }
1022110304 }
1022210305
10223 if (is_ref) {
10306 if (capture_byref) {
1022410307 const field_ty_ptr = try Type.ptr(sema.arena, mod, .{
1022510308 .pointee_type = first_field.ty,
1022610309 .@"addrspace" = .generic,
......@@ -10250,31 +10333,35 @@ fn zirSwitchCapture(
1025010333 return block.addStructFieldVal(operand, first_field_index, first_field.ty);
1025110334 },
1025210335 .ErrorSet => {
10253 if (items.len > 1) {
10254 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10255 try names.ensureUnusedCapacity(sema.arena, items.len);
10256 for (items) |item| {
10257 const item_ref = try sema.resolveInst(item);
10258 // Previous switch validation ensured this will succeed
10259 const item_val = sema.resolveConstLazyValue(block, .unneeded, item_ref, "") catch unreachable;
10260 names.putAssumeCapacityNoClobber(item_val.getErrorName(mod).unwrap().?, {});
10261 }
10262 const else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
10263
10264 return sema.bitCast(block, else_error_ty, operand, operand_src, null);
10265 } else {
10266 const item_ref = try sema.resolveInst(items[0]);
10267 // Previous switch validation ensured this will succeed
10268 const item_val = sema.resolveConstLazyValue(block, .unneeded, item_ref, "") catch unreachable;
10336 if (capture_byref) {
10337 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
10338 return sema.fail(
10339 block,
10340 capture_src,
10341 "error set cannot be captured by reference",
10342 .{},
10343 );
10344 }
1026910345
10346 if (case_vals.len == 1) {
10347 const item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
1027010348 const item_ty = try mod.singleErrorSetType(item_val.getErrorName(mod).unwrap().?);
1027110349 return sema.bitCast(block, item_ty, operand, operand_src, null);
1027210350 }
10351
10352 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10353 try names.ensureUnusedCapacity(sema.arena, case_vals.len);
10354 for (case_vals) |err| {
10355 const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable;
10356 names.putAssumeCapacityNoClobber(err_val.getErrorName(mod).unwrap().?, {});
10357 }
10358 const error_ty = try mod.errorSetFromUnsortedNames(names.keys());
10359 return sema.bitCast(block, error_ty, operand, operand_src, null);
1027310360 },
1027410361 else => {
10275 // In this case the capture value is just the passed-through value of the
10276 // switch condition.
10277 if (is_ref) {
10362 // In this case the capture value is just the passed-through value
10363 // of the switch condition.
10364 if (capture_byref) {
1027810365 return operand_ptr;
1027910366 } else {
1028010367 return operand;
......@@ -10415,28 +10502,42 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1041510502 var case_vals = try std.ArrayListUnmanaged(Air.Inst.Ref).initCapacity(gpa, scalar_cases_len + 2 * multi_cases_len);
1041610503 defer case_vals.deinit(gpa);
1041710504
10505 const Special = struct {
10506 body: []const Zir.Inst.Index,
10507 end: usize,
10508 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
10509 is_inline: bool,
10510 };
10511
1041810512 const special_prong = extra.data.bits.specialProng();
10419 const special: struct { body: []const Zir.Inst.Index, end: usize, is_inline: bool } = switch (special_prong) {
10420 .none => .{ .body = &.{}, .end = header_extra_index, .is_inline = false },
10513 const special: Special = switch (special_prong) {
10514 .none => .{ .body = &.{}, .end = header_extra_index, .capture = .none, .is_inline = false },
1042110515 .under, .@"else" => blk: {
10422 const body_len = @truncate(u31, sema.code.extra[header_extra_index]);
10516 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[header_extra_index]);
1042310517 const extra_body_start = header_extra_index + 1;
1042410518 break :blk .{
10425 .body = sema.code.extra[extra_body_start..][0..body_len],
10426 .end = extra_body_start + body_len,
10427 .is_inline = sema.code.extra[header_extra_index] >> 31 != 0,
10519 .body = sema.code.extra[extra_body_start..][0..info.body_len],
10520 .end = extra_body_start + info.body_len,
10521 .capture = info.capture,
10522 .is_inline = info.is_inline,
1042810523 };
1042910524 },
1043010525 };
1043110526
10432 const maybe_union_ty = blk: {
10527 const raw_operand: struct { val: Air.Inst.Ref, ptr: Air.Inst.Ref } = blk: {
1043310528 const zir_tags = sema.code.instructions.items(.tag);
1043410529 const zir_data = sema.code.instructions.items(.data);
1043510530 const cond_index = Zir.refToIndex(extra.data.operand).?;
10436 const raw_operand = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable;
10437 const target_ty = sema.typeOf(raw_operand);
10438 break :blk if (zir_tags[cond_index] == .switch_cond_ref) target_ty.childType(mod) else target_ty;
10531 const raw = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable;
10532 if (zir_tags[cond_index] == .switch_cond_ref) {
10533 const val = try sema.analyzeLoad(block, src, raw, operand_src);
10534 break :blk .{ .val = val, .ptr = raw };
10535 } else {
10536 break :blk .{ .val = raw, .ptr = undefined };
10537 }
1043910538 };
10539
10540 const maybe_union_ty = sema.typeOf(raw_operand.val);
1044010541 const union_originally = maybe_union_ty.zigTypeTag(mod) == .Union;
1044110542
1044210543 // Duplicate checking variables later also used for `inline else`.
......@@ -10496,9 +10597,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1049610597 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
1049710598 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
1049810599 extra_index += 1;
10499 const body_len = @truncate(u31, sema.code.extra[extra_index]);
10500 extra_index += 1;
10501 extra_index += body_len;
10600 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
10601 extra_index += 1 + info.body_len;
1050210602
1050310603 case_vals.appendAssumeCapacity(try sema.validateSwitchItemEnum(
1050410604 block,
......@@ -10518,10 +10618,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1051810618 extra_index += 1;
1051910619 const ranges_len = sema.code.extra[extra_index];
1052010620 extra_index += 1;
10521 const body_len = @truncate(u31, sema.code.extra[extra_index]);
10621 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
1052210622 extra_index += 1;
1052310623 const items = sema.code.refSlice(extra_index, items_len);
10524 extra_index += items_len + body_len;
10624 extra_index += items_len + info.body_len;
1052510625
1052610626 try case_vals.ensureUnusedCapacity(gpa, items.len);
1052710627 for (items, 0..) |item_ref, item_i| {
......@@ -10596,9 +10696,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1059610696 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
1059710697 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
1059810698 extra_index += 1;
10599 const body_len = @truncate(u31, sema.code.extra[extra_index]);
10600 extra_index += 1;
10601 extra_index += body_len;
10699 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
10700 extra_index += 1 + info.body_len;
1060210701
1060310702 case_vals.appendAssumeCapacity(try sema.validateSwitchItemError(
1060410703 block,
......@@ -10617,10 +10716,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1061710716 extra_index += 1;
1061810717 const ranges_len = sema.code.extra[extra_index];
1061910718 extra_index += 1;
10620 const body_len = @truncate(u31, sema.code.extra[extra_index]);
10719 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
1062110720 extra_index += 1;
1062210721 const items = sema.code.refSlice(extra_index, items_len);
10623 extra_index += items_len + body_len;
10722 extra_index += items_len + info.body_len;
1062410723
1062510724 try case_vals.ensureUnusedCapacity(gpa, items.len);
1062610725 for (items, 0..) |item_ref, item_i| {
......@@ -10694,7 +10793,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1069410793 .dbg_block_end,
1069510794 .dbg_stmt,
1069610795 .dbg_var_val,
10697 .switch_capture,
1069810796 .ret_type,
1069910797 .as_node,
1070010798 .ret_node,
......@@ -10739,9 +10837,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1073910837 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
1074010838 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
1074110839 extra_index += 1;
10742 const body_len = @truncate(u31, sema.code.extra[extra_index]);
10743 extra_index += 1;
10744 extra_index += body_len;
10840 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
10841 extra_index += 1 + info.body_len;
1074510842
1074610843 case_vals.appendAssumeCapacity(try sema.validateSwitchItemInt(
1074710844 block,
......@@ -10760,7 +10857,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1076010857 extra_index += 1;
1076110858 const ranges_len = sema.code.extra[extra_index];
1076210859 extra_index += 1;
10763 const body_len = @truncate(u31, sema.code.extra[extra_index]);
10860 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
1076410861 extra_index += 1;
1076510862 const items = sema.code.refSlice(extra_index, items_len);
1076610863 extra_index += items_len;
......@@ -10798,7 +10895,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1079810895 case_vals.appendAssumeCapacity(vals[1]);
1079910896 }
1080010897
10801 extra_index += body_len;
10898 extra_index += info.body_len;
1080210899 }
1080310900 }
1080410901
......@@ -10835,9 +10932,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1083510932 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
1083610933 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
1083710934 extra_index += 1;
10838 const body_len = @truncate(u31, sema.code.extra[extra_index]);
10839 extra_index += 1;
10840 extra_index += body_len;
10935 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
10936 extra_index += 1 + info.body_len;
1084110937
1084210938 case_vals.appendAssumeCapacity(try sema.validateSwitchItemBool(
1084310939 block,
......@@ -10856,10 +10952,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1085610952 extra_index += 1;
1085710953 const ranges_len = sema.code.extra[extra_index];
1085810954 extra_index += 1;
10859 const body_len = @truncate(u31, sema.code.extra[extra_index]);
10955 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
1086010956 extra_index += 1;
1086110957 const items = sema.code.refSlice(extra_index, items_len);
10862 extra_index += items_len + body_len;
10958 extra_index += items_len + info.body_len;
1086310959
1086410960 try case_vals.ensureUnusedCapacity(gpa, items.len);
1086510961 for (items, 0..) |item_ref, item_i| {
......@@ -10918,9 +11014,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1091811014 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
1091911015 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
1092011016 extra_index += 1;
10921 const body_len = @truncate(u31, sema.code.extra[extra_index]);
11017 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
1092211018 extra_index += 1;
10923 extra_index += body_len;
11019 extra_index += info.body_len;
1092411020
1092511021 case_vals.appendAssumeCapacity(try sema.validateSwitchItemSparse(
1092611022 block,
......@@ -10939,10 +11035,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1093911035 extra_index += 1;
1094011036 const ranges_len = sema.code.extra[extra_index];
1094111037 extra_index += 1;
10942 const body_len = @truncate(u31, sema.code.extra[extra_index]);
11038 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
1094311039 extra_index += 1;
1094411040 const items = sema.code.refSlice(extra_index, items_len);
10945 extra_index += items_len + body_len;
11041 extra_index += items_len + info.body_len;
1094611042
1094711043 try case_vals.ensureUnusedCapacity(gpa, items.len);
1094811044 for (items, 0..) |item_ref, item_i| {
......@@ -11006,7 +11102,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1100611102 .is_comptime = block.is_comptime,
1100711103 .comptime_reason = block.comptime_reason,
1100811104 .is_typeof = block.is_typeof,
11009 .switch_else_err_ty = else_error_ty,
1101011105 .c_import_buf = block.c_import_buf,
1101111106 .runtime_cond = block.runtime_cond,
1101211107 .runtime_loop = block.runtime_loop,
......@@ -11024,19 +11119,31 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1102411119 var scalar_i: usize = 0;
1102511120 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
1102611121 extra_index += 1;
11027 const body_len = @truncate(u31, sema.code.extra[extra_index]);
11028 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
11122 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
1102911123 extra_index += 1;
11030 const body = sema.code.extra[extra_index..][0..body_len];
11031 extra_index += body_len;
11124 const body = sema.code.extra[extra_index..][0..info.body_len];
11125 extra_index += info.body_len;
1103211126
1103311127 const item = case_vals.items[scalar_i];
11034 const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable;
11035 if (resolved_operand_val.eql(item_val, operand_ty, mod)) {
11036 if (is_inline) child_block.inline_case_capture = operand;
11037
11128 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
11129 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
11130 if (info.is_inline) child_block.inline_case_capture = operand;
1103811131 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
11039 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
11132 return sema.resolveSwitchProngComptime(
11133 block,
11134 &child_block,
11135 src,
11136 raw_operand.val,
11137 raw_operand.ptr,
11138 .normal,
11139 body,
11140 info.capture,
11141 .{ .scalar = @intCast(u32, scalar_i) },
11142 else_error_ty,
11143 &.{item},
11144 inst,
11145 merges,
11146 );
1104011147 }
1104111148 }
1104211149 }
......@@ -11048,22 +11155,34 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1104811155 extra_index += 1;
1104911156 const ranges_len = sema.code.extra[extra_index];
1105011157 extra_index += 1;
11051 const body_len = @truncate(u31, sema.code.extra[extra_index]);
11052 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
11158 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
1105311159 extra_index += 1 + items_len;
11054 const body = sema.code.extra[extra_index + 2 * ranges_len ..][0..body_len];
11160 const body = sema.code.extra[extra_index + 2 * ranges_len ..][0..info.body_len];
1105511161
1105611162 const items = case_vals.items[case_val_idx..][0..items_len];
1105711163 case_val_idx += items_len;
1105811164
1105911165 for (items) |item| {
1106011166 // Validation above ensured these will succeed.
11061 const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable;
11062 if (resolved_operand_val.eql(item_val, operand_ty, mod)) {
11063 if (is_inline) child_block.inline_case_capture = operand;
11064
11167 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
11168 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
11169 if (info.is_inline) child_block.inline_case_capture = operand;
1106511170 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
11066 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
11171 return sema.resolveSwitchProngComptime(
11172 block,
11173 &child_block,
11174 src,
11175 raw_operand.val,
11176 raw_operand.ptr,
11177 .normal,
11178 body,
11179 info.capture,
11180 .{ .multi_capture = @intCast(u32, multi_i) },
11181 else_error_ty,
11182 items,
11183 inst,
11184 merges,
11185 );
1106711186 }
1106811187 }
1106911188
......@@ -11079,13 +11198,27 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1107911198 if ((try sema.compareAll(resolved_operand_val, .gte, first_val, operand_ty)) and
1108011199 (try sema.compareAll(resolved_operand_val, .lte, last_val, operand_ty)))
1108111200 {
11082 if (is_inline) child_block.inline_case_capture = operand;
11201 if (info.is_inline) child_block.inline_case_capture = operand;
1108311202 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
11084 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
11203 return sema.resolveSwitchProngComptime(
11204 block,
11205 &child_block,
11206 src,
11207 raw_operand.val,
11208 raw_operand.ptr,
11209 .normal,
11210 body,
11211 info.capture,
11212 .{ .multi_capture = @intCast(u32, multi_i) },
11213 else_error_ty,
11214 undefined,
11215 inst,
11216 merges,
11217 );
1108511218 }
1108611219 }
1108711220
11088 extra_index += body_len;
11221 extra_index += info.body_len;
1108911222 }
1109011223 }
1109111224 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand);
......@@ -11093,7 +11226,22 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1109311226 if (empty_enum) {
1109411227 return Air.Inst.Ref.void_value;
1109511228 }
11096 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
11229
11230 return sema.resolveSwitchProngComptime(
11231 block,
11232 &child_block,
11233 src,
11234 raw_operand.val,
11235 raw_operand.ptr,
11236 .special,
11237 special.body,
11238 special.capture,
11239 .special,
11240 else_error_ty,
11241 undefined,
11242 inst,
11243 merges,
11244 );
1109711245 }
1109811246
1109911247 if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline) {
......@@ -11113,7 +11261,22 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1111311261 const ok = try block.addUnOp(.is_named_enum_value, operand);
1111411262 try sema.addSafetyCheck(block, ok, .corrupt_switch);
1111511263 }
11116 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
11264
11265 return sema.resolveSwitchProngComptime(
11266 block,
11267 &child_block,
11268 src,
11269 raw_operand.val,
11270 raw_operand.ptr,
11271 .special,
11272 special.body,
11273 special.capture,
11274 .special,
11275 else_error_ty,
11276 undefined,
11277 inst,
11278 merges,
11279 );
1111711280 }
1111811281
1111911282 if (child_block.is_comptime) {
......@@ -11140,11 +11303,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1114011303 var scalar_i: usize = 0;
1114111304 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
1114211305 extra_index += 1;
11143 const body_len = @truncate(u31, sema.code.extra[extra_index]);
11144 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
11306 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
1114511307 extra_index += 1;
11146 const body = sema.code.extra[extra_index..][0..body_len];
11147 extra_index += body_len;
11308 const body = sema.code.extra[extra_index..][0..info.body_len];
11309 extra_index += info.body_len;
1114811310
1114911311 var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope);
1115011312 defer wip_captures.deinit();
......@@ -11154,7 +11316,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1115411316 case_block.inline_case_capture = .none;
1115511317
1115611318 const item = case_vals.items[scalar_i];
11157 if (is_inline) case_block.inline_case_capture = item;
11319 if (info.is_inline) case_block.inline_case_capture = item;
1115811320 // `item` is already guaranteed to be constant known.
1115911321
1116011322 const analyze_body = if (union_originally) blk: {
......@@ -11166,7 +11328,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1116611328 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
1116711329 // nothing to do here
1116811330 } else if (analyze_body) {
11169 try sema.analyzeBodyRuntimeBreak(&case_block, body);
11331 try sema.analyzeSwitchProngRuntime(
11332 &case_block,
11333 raw_operand.val,
11334 raw_operand.ptr,
11335 .normal,
11336 body,
11337 info.capture,
11338 .{ .scalar = @intCast(u32, scalar_i) },
11339 else_error_ty,
11340 &.{item},
11341 inst,
11342 );
1117011343 } else {
1117111344 _ = try case_block.addNoOp(.unreach);
1117211345 }
......@@ -11195,8 +11368,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1119511368 extra_index += 1;
1119611369 const ranges_len = sema.code.extra[extra_index];
1119711370 extra_index += 1;
11198 const body_len = @truncate(u31, sema.code.extra[extra_index]);
11199 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
11371 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
1120011372 extra_index += 1 + items_len;
1120111373
1120211374 const items = case_vals.items[case_val_idx..][0..items_len];
......@@ -11207,9 +11379,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1120711379 case_block.inline_case_capture = .none;
1120811380
1120911381 // Generate all possible cases as scalar prongs.
11210 if (is_inline) {
11382 if (info.is_inline) {
1121111383 const body_start = extra_index + 2 * ranges_len;
11212 const body = sema.code.extra[body_start..][0..body_len];
11384 const body = sema.code.extra[body_start..][0..info.body_len];
1121311385 var emit_bb = false;
1121411386
1121511387 var range_i: u32 = 0;
......@@ -11250,7 +11422,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1125011422 };
1125111423 emit_bb = true;
1125211424
11253 try sema.analyzeBodyRuntimeBreak(&case_block, body);
11425 try sema.analyzeSwitchProngRuntime(
11426 &case_block,
11427 raw_operand.val,
11428 raw_operand.ptr,
11429 .normal,
11430 body,
11431 info.capture,
11432 .{ .multi_capture = multi_i },
11433 else_error_ty,
11434 undefined,
11435 inst,
11436 );
1125411437
1125511438 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
1125611439 cases_extra.appendAssumeCapacity(1); // items_len
......@@ -11286,7 +11469,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1128611469 emit_bb = true;
1128711470
1128811471 if (analyze_body) {
11289 try sema.analyzeBodyRuntimeBreak(&case_block, body);
11472 try sema.analyzeSwitchProngRuntime(
11473 &case_block,
11474 raw_operand.val,
11475 raw_operand.ptr,
11476 .normal,
11477 body,
11478 info.capture,
11479 .{ .multi_capture = multi_i },
11480 else_error_ty,
11481 &.{item},
11482 inst,
11483 );
1129011484 } else {
1129111485 _ = try case_block.addNoOp(.unreach);
1129211486 }
......@@ -11298,7 +11492,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1129811492 cases_extra.appendSliceAssumeCapacity(case_block.instructions.items);
1129911493 }
1130011494
11301 extra_index += body_len;
11495 extra_index += info.body_len;
1130211496 continue;
1130311497 }
1130411498
......@@ -11319,12 +11513,23 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1131911513 else
1132011514 true;
1132111515
11322 const body = sema.code.extra[extra_index..][0..body_len];
11323 extra_index += body_len;
11516 const body = sema.code.extra[extra_index..][0..info.body_len];
11517 extra_index += info.body_len;
1132411518 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
1132511519 // nothing to do here
1132611520 } else if (analyze_body) {
11327 try sema.analyzeBodyRuntimeBreak(&case_block, body);
11521 try sema.analyzeSwitchProngRuntime(
11522 &case_block,
11523 raw_operand.val,
11524 raw_operand.ptr,
11525 .normal,
11526 body,
11527 info.capture,
11528 .{ .multi_capture = multi_i },
11529 else_error_ty,
11530 items,
11531 inst,
11532 );
1132811533 } else {
1132911534 _ = try case_block.addNoOp(.unreach);
1133011535 }
......@@ -11397,12 +11602,23 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1139711602 case_block.instructions.shrinkRetainingCapacity(0);
1139811603 case_block.wip_capture_scope = wip_captures.scope;
1139911604
11400 const body = sema.code.extra[extra_index..][0..body_len];
11401 extra_index += body_len;
11605 const body = sema.code.extra[extra_index..][0..info.body_len];
11606 extra_index += info.body_len;
1140211607 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
1140311608 // nothing to do here
1140411609 } else {
11405 try sema.analyzeBodyRuntimeBreak(&case_block, body);
11610 try sema.analyzeSwitchProngRuntime(
11611 &case_block,
11612 raw_operand.val,
11613 raw_operand.ptr,
11614 .normal,
11615 body,
11616 info.capture,
11617 .{ .multi_capture = multi_i },
11618 else_error_ty,
11619 items,
11620 inst,
11621 );
1140611622 }
1140711623
1140811624 try wip_captures.finalize();
......@@ -11461,7 +11677,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1146111677 emit_bb = true;
1146211678
1146311679 if (analyze_body) {
11464 try sema.analyzeBodyRuntimeBreak(&case_block, special.body);
11680 try sema.analyzeSwitchProngRuntime(
11681 &case_block,
11682 raw_operand.val,
11683 raw_operand.ptr,
11684 .special,
11685 special.body,
11686 special.capture,
11687 .special,
11688 else_error_ty,
11689 &.{item_ref},
11690 inst,
11691 );
1146511692 } else {
1146611693 _ = try case_block.addNoOp(.unreach);
1146711694 }
......@@ -11497,7 +11724,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1149711724 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
1149811725 emit_bb = true;
1149911726
11500 try sema.analyzeBodyRuntimeBreak(&case_block, special.body);
11727 try sema.analyzeSwitchProngRuntime(
11728 &case_block,
11729 raw_operand.val,
11730 raw_operand.ptr,
11731 .special,
11732 special.body,
11733 special.capture,
11734 .special,
11735 else_error_ty,
11736 &.{item_ref},
11737 inst,
11738 );
1150111739
1150211740 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
1150311741 cases_extra.appendAssumeCapacity(1); // items_len
......@@ -11520,7 +11758,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1152011758 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
1152111759 emit_bb = true;
1152211760
11523 try sema.analyzeBodyRuntimeBreak(&case_block, special.body);
11761 try sema.analyzeSwitchProngRuntime(
11762 &case_block,
11763 raw_operand.val,
11764 raw_operand.ptr,
11765 .special,
11766 special.body,
11767 special.capture,
11768 .special,
11769 else_error_ty,
11770 &.{item_ref},
11771 inst,
11772 );
1152411773
1152511774 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
1152611775 cases_extra.appendAssumeCapacity(1); // items_len
......@@ -11540,7 +11789,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1154011789 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
1154111790 emit_bb = true;
1154211791
11543 try sema.analyzeBodyRuntimeBreak(&case_block, special.body);
11792 try sema.analyzeSwitchProngRuntime(
11793 &case_block,
11794 raw_operand.val,
11795 raw_operand.ptr,
11796 .special,
11797 special.body,
11798 special.capture,
11799 .special,
11800 else_error_ty,
11801 &.{Air.Inst.Ref.bool_true},
11802 inst,
11803 );
1154411804
1154511805 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
1154611806 cases_extra.appendAssumeCapacity(1); // items_len
......@@ -11558,7 +11818,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1155811818 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
1155911819 emit_bb = true;
1156011820
11561 try sema.analyzeBodyRuntimeBreak(&case_block, special.body);
11821 try sema.analyzeSwitchProngRuntime(
11822 &case_block,
11823 raw_operand.val,
11824 raw_operand.ptr,
11825 .special,
11826 special.body,
11827 special.capture,
11828 .special,
11829 else_error_ty,
11830 &.{Air.Inst.Ref.bool_false},
11831 inst,
11832 );
1156211833
1156311834 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
1156411835 cases_extra.appendAssumeCapacity(1); // items_len
......@@ -11601,7 +11872,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1160111872 {
1160211873 // nothing to do here
1160311874 } else if (special.body.len != 0 and analyze_body and !special.is_inline) {
11604 try sema.analyzeBodyRuntimeBreak(&case_block, special.body);
11875 try sema.analyzeSwitchProngRuntime(
11876 &case_block,
11877 raw_operand.val,
11878 raw_operand.ptr,
11879 .special,
11880 special.body,
11881 special.capture,
11882 .special,
11883 else_error_ty,
11884 undefined,
11885 inst,
11886 );
1160511887 } else {
1160611888 // We still need a terminator in this block, but we have proven
1160711889 // that it is unreachable.
......@@ -11746,7 +12028,7 @@ fn resolveSwitchItemVal(
1174612028 else => |e| return e,
1174712029 };
1174812030
11749 const val = sema.resolveConstLazyValue(block, .unneeded, item, "") catch |err| switch (err) {
12031 const maybe_lazy = sema.resolveConstValue(block, .unneeded, item, "") catch |err| switch (err) {
1175012032 error.NeededSourceLocation => {
1175112033 const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand);
1175212034 _ = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known");
......@@ -11755,7 +12037,12 @@ fn resolveSwitchItemVal(
1175512037 else => |e| return e,
1175612038 };
1175712039
11758 return .{ .ref = item, .val = val.toIntern() };
12040 const val = try sema.resolveLazyValue(maybe_lazy);
12041 const new_item = if (val.toIntern() != maybe_lazy.toIntern()) blk: {
12042 break :blk try sema.addConstant(coerce_ty, val);
12043 } else item;
12044
12045 return .{ .ref = new_item, .val = val.toIntern() };
1175912046}
1176012047
1176112048fn validateSwitchRange(
src/Zir.zig+23-86
......@@ -676,17 +676,6 @@ pub const Inst = struct {
676676 /// what will be switched on.
677677 /// Uses the `un_node` union field.
678678 switch_cond_ref,
679 /// Produces the capture value for a switch prong.
680 /// Uses the `switch_capture` field.
681 /// If the `prong_index` field is max int, it means this is the capture
682 /// for the else/`_` prong.
683 switch_capture,
684 /// Produces the capture value for a switch prong.
685 /// Result is a pointer to the value.
686 /// Uses the `switch_capture` field.
687 /// If the `prong_index` field is max int, it means this is the capture
688 /// for the else/`_` prong.
689 switch_capture_ref,
690679 /// Produces the capture value for an inline switch prong tag capture.
691680 /// Uses the `un_tok` field.
692681 switch_capture_tag,
......@@ -1135,8 +1124,6 @@ pub const Inst = struct {
11351124 .typeof_log2_int_type,
11361125 .resolve_inferred_alloc,
11371126 .set_eval_branch_quota,
1138 .switch_capture,
1139 .switch_capture_ref,
11401127 .switch_capture_tag,
11411128 .switch_block,
11421129 .switch_cond,
......@@ -1427,8 +1414,6 @@ pub const Inst = struct {
14271414 .slice_length,
14281415 .import,
14291416 .typeof_log2_int_type,
1430 .switch_capture,
1431 .switch_capture_ref,
14321417 .switch_capture_tag,
14331418 .switch_block,
14341419 .switch_cond,
......@@ -1685,8 +1670,6 @@ pub const Inst = struct {
16851670 .switch_block = .pl_node,
16861671 .switch_cond = .un_node,
16871672 .switch_cond_ref = .un_node,
1688 .switch_capture = .switch_capture,
1689 .switch_capture_ref = .switch_capture,
16901673 .switch_capture_tag = .un_tok,
16911674 .array_base_ptr = .un_node,
16921675 .field_base_ptr = .un_node,
......@@ -2254,10 +2237,6 @@ pub const Inst = struct {
22542237 operand: Ref,
22552238 payload_index: u32,
22562239 },
2257 switch_capture: struct {
2258 switch_inst: Index,
2259 prong_index: u32,
2260 },
22612240 dbg_stmt: LineColumn,
22622241 /// Used for unary operators which reference an inst,
22632242 /// with an AST node source location.
......@@ -2327,7 +2306,6 @@ pub const Inst = struct {
23272306 bool_br,
23282307 @"unreachable",
23292308 @"break",
2330 switch_capture,
23312309 dbg_stmt,
23322310 inst_node,
23332311 str_op,
......@@ -2667,25 +2645,29 @@ pub const Inst = struct {
26672645
26682646 /// 0. multi_cases_len: u32 // If has_multi_cases is set.
26692647 /// 1. else_body { // If has_else or has_under is set.
2670 /// body_len: u32,
2671 /// body member Index for every body_len
2648 /// info: ProngInfo,
2649 /// body member Index for every info.body_len
26722650 /// }
26732651 /// 2. scalar_cases: { // for every scalar_cases_len
26742652 /// item: Ref,
2675 /// body_len: u32,
2676 /// body member Index for every body_len
2653 /// info: ProngInfo,
2654 /// body member Index for every info.body_len
26772655 /// }
26782656 /// 3. multi_cases: { // for every multi_cases_len
26792657 /// items_len: u32,
26802658 /// ranges_len: u32,
2681 /// body_len: u32,
2659 /// info: ProngInfo,
26822660 /// item: Ref // for every items_len
26832661 /// ranges: { // for every ranges_len
26842662 /// item_first: Ref,
26852663 /// item_last: Ref,
26862664 /// }
2687 /// body member Index for every body_len
2665 /// body member Index for every info.body_len
26882666 /// }
2667 ///
2668 /// When analyzing a case body, the switch instruction itself refers to the
2669 /// captured payload. Whether this is captured by reference or by value
2670 /// depends on whether the `byref` bit is set for the corresponding body.
26892671 pub const SwitchBlock = struct {
26902672 /// This is always a `switch_cond` or `switch_cond_ref` instruction.
26912673 /// If it is a `switch_cond_ref` instruction, bits.is_ref is always true.
......@@ -2697,6 +2679,19 @@ pub const Inst = struct {
26972679 operand: Ref,
26982680 bits: Bits,
26992681
2682 /// These are stored in trailing data in `extra` for each prong.
2683 pub const ProngInfo = packed struct(u32) {
2684 body_len: u29,
2685 capture: Capture,
2686 is_inline: bool,
2687
2688 pub const Capture = enum(u2) {
2689 none,
2690 by_val,
2691 by_ref,
2692 };
2693 };
2694
27002695 pub const Bits = packed struct {
27012696 /// If true, one or more prongs have multiple items.
27022697 has_multi_cases: bool,
......@@ -2724,64 +2719,6 @@ pub const Inst = struct {
27242719 items: []const Ref,
27252720 body: []const Index,
27262721 };
2727
2728 /// TODO performance optimization: instead of having this helper method
2729 /// change the definition of switch_capture instruction to store extra_index
2730 /// instead of prong_index. This way, Sema won't be doing O(N^2) iterations
2731 /// over the switch prongs.
2732 pub fn getProng(
2733 self: SwitchBlock,
2734 zir: Zir,
2735 extra_end: usize,
2736 prong_index: usize,
2737 ) MultiProng {
2738 var extra_index: usize = extra_end + @boolToInt(self.bits.has_multi_cases);
2739
2740 if (self.bits.specialProng() != .none) {
2741 const body_len = @truncate(u31, zir.extra[extra_index]);
2742 extra_index += 1;
2743 const body = zir.extra[extra_index..][0..body_len];
2744 extra_index += body.len;
2745 }
2746
2747 var cur_idx: usize = 0;
2748 while (cur_idx < self.bits.scalar_cases_len) : (cur_idx += 1) {
2749 const items = zir.refSlice(extra_index, 1);
2750 extra_index += 1;
2751 const body_len = @truncate(u31, zir.extra[extra_index]);
2752 extra_index += 1;
2753 const body = zir.extra[extra_index..][0..body_len];
2754 extra_index += body_len;
2755 if (cur_idx == prong_index) {
2756 return .{
2757 .items = items,
2758 .body = body,
2759 };
2760 }
2761 }
2762 while (true) : (cur_idx += 1) {
2763 const items_len = zir.extra[extra_index];
2764 extra_index += 1;
2765 const ranges_len = zir.extra[extra_index];
2766 extra_index += 1;
2767 const body_len = @truncate(u31, zir.extra[extra_index]);
2768 extra_index += 1;
2769 const items = zir.refSlice(extra_index, items_len);
2770 extra_index += items_len;
2771 // Each range has a start and an end.
2772 extra_index += 2 * ranges_len;
2773
2774 const body = zir.extra[extra_index..][0..body_len];
2775 extra_index += body_len;
2776
2777 if (cur_idx == prong_index) {
2778 return .{
2779 .items = items,
2780 .body = body,
2781 };
2782 }
2783 }
2784 }
27852722 };
27862723
27872724 pub const Field = struct {
src/print_zir.zig+27-24
......@@ -436,10 +436,6 @@ const Writer = struct {
436436
437437 .@"unreachable" => try self.writeUnreachable(stream, inst),
438438
439 .switch_capture,
440 .switch_capture_ref,
441 => try self.writeSwitchCapture(stream, inst),
442
443439 .dbg_stmt => try self.writeDbgStmt(stream, inst),
444440
445441 .dbg_block_begin,
......@@ -1913,15 +1909,20 @@ const Writer = struct {
19131909 else => break :else_prong,
19141910 };
19151911
1916 const body_len = @truncate(u31, self.code.extra[extra_index]);
1917 const inline_text = if (self.code.extra[extra_index] >> 31 != 0) "inline " else "";
1912 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, self.code.extra[extra_index]);
1913 const capture_text = switch (info.capture) {
1914 .none => "",
1915 .by_val => "by_val ",
1916 .by_ref => "by_ref ",
1917 };
1918 const inline_text = if (info.is_inline) "inline " else "";
19181919 extra_index += 1;
1919 const body = self.code.extra[extra_index..][0..body_len];
1920 const body = self.code.extra[extra_index..][0..info.body_len];
19201921 extra_index += body.len;
19211922
19221923 try stream.writeAll(",\n");
19231924 try stream.writeByteNTimes(' ', self.indent);
1924 try stream.print("{s}{s} => ", .{ inline_text, prong_name });
1925 try stream.print("{s}{s}{s} => ", .{ capture_text, inline_text, prong_name });
19251926 try self.writeBracedBody(stream, body);
19261927 }
19271928
......@@ -1931,15 +1932,19 @@ const Writer = struct {
19311932 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
19321933 const item_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
19331934 extra_index += 1;
1934 const body_len = @truncate(u31, self.code.extra[extra_index]);
1935 const is_inline = self.code.extra[extra_index] >> 31 != 0;
1935 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, self.code.extra[extra_index]);
19361936 extra_index += 1;
1937 const body = self.code.extra[extra_index..][0..body_len];
1938 extra_index += body_len;
1937 const body = self.code.extra[extra_index..][0..info.body_len];
1938 extra_index += info.body_len;
19391939
19401940 try stream.writeAll(",\n");
19411941 try stream.writeByteNTimes(' ', self.indent);
1942 if (is_inline) try stream.writeAll("inline ");
1942 switch (info.capture) {
1943 .none => {},
1944 .by_val => try stream.writeAll("by_val "),
1945 .by_ref => try stream.writeAll("by_ref "),
1946 }
1947 if (info.is_inline) try stream.writeAll("inline ");
19431948 try self.writeInstRef(stream, item_ref);
19441949 try stream.writeAll(" => ");
19451950 try self.writeBracedBody(stream, body);
......@@ -1952,15 +1957,19 @@ const Writer = struct {
19521957 extra_index += 1;
19531958 const ranges_len = self.code.extra[extra_index];
19541959 extra_index += 1;
1955 const body_len = @truncate(u31, self.code.extra[extra_index]);
1956 const is_inline = self.code.extra[extra_index] >> 31 != 0;
1960 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, self.code.extra[extra_index]);
19571961 extra_index += 1;
19581962 const items = self.code.refSlice(extra_index, items_len);
19591963 extra_index += items_len;
19601964
19611965 try stream.writeAll(",\n");
19621966 try stream.writeByteNTimes(' ', self.indent);
1963 if (is_inline) try stream.writeAll("inline ");
1967 switch (info.capture) {
1968 .none => {},
1969 .by_val => try stream.writeAll("by_val "),
1970 .by_ref => try stream.writeAll("by_ref "),
1971 }
1972 if (info.is_inline) try stream.writeAll("inline ");
19641973
19651974 for (items, 0..) |item_ref, item_i| {
19661975 if (item_i != 0) try stream.writeAll(", ");
......@@ -1982,8 +1991,8 @@ const Writer = struct {
19821991 try self.writeInstRef(stream, item_last);
19831992 }
19841993
1985 const body = self.code.extra[extra_index..][0..body_len];
1986 extra_index += body_len;
1994 const body = self.code.extra[extra_index..][0..info.body_len];
1995 extra_index += info.body_len;
19871996 try stream.writeAll(" => ");
19881997 try self.writeBracedBody(stream, body);
19891998 }
......@@ -2435,12 +2444,6 @@ const Writer = struct {
24352444 try self.writeSrc(stream, src);
24362445 }
24372446
2438 fn writeSwitchCapture(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
2439 const inst_data = self.code.instructions.items(.data)[inst].switch_capture;
2440 try self.writeInstIndex(stream, inst_data.switch_inst);
2441 try stream.print(", {d})", .{inst_data.prong_index});
2442 }
2443
24442447 fn writeDbgStmt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
24452448 const inst_data = self.code.instructions.items(.data)[inst].dbg_stmt;
24462449 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });