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...@@ -2612,8 +2612,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2612 .switch_block,2612 .switch_block,
2613 .switch_cond,2613 .switch_cond,
2614 .switch_cond_ref,2614 .switch_cond_ref,
2615 .switch_capture,
2616 .switch_capture_ref,
2617 .switch_capture_tag,2615 .switch_capture_tag,
2618 .struct_init_empty,2616 .struct_init_empty,
2619 .struct_init,2617 .struct_init,
...@@ -6876,17 +6874,22 @@ fn switchExpr(...@@ -6876,17 +6874,22 @@ fn switchExpr(
6876 var dbg_var_inst: Zir.Inst.Ref = undefined;6874 var dbg_var_inst: Zir.Inst.Ref = undefined;
6877 var dbg_var_tag_name: ?u32 = null;6875 var dbg_var_tag_name: ?u32 = null;
6878 var dbg_var_tag_inst: Zir.Inst.Ref = undefined;6876 var dbg_var_tag_inst: Zir.Inst.Ref = undefined;
6879 var capture_inst: Zir.Inst.Index = 0;
6880 var tag_inst: Zir.Inst.Index = 0;6877 var tag_inst: Zir.Inst.Index = 0;
6881 var capture_val_scope: Scope.LocalVal = undefined;6878 var capture_val_scope: Scope.LocalVal = undefined;
6882 var tag_scope: Scope.LocalVal = undefined;6879 var tag_scope: Scope.LocalVal = undefined;
6880
6881 var capture: Zir.Inst.SwitchBlock.ProngInfo.Capture = .none;
6882
6883 const sub_scope = blk: {6883 const sub_scope = blk: {
6884 const payload_token = case.payload_token orelse break :blk &case_scope.base;6884 const payload_token = case.payload_token orelse break :blk &case_scope.base;
6885 const ident = if (token_tags[payload_token] == .asterisk)6885 const ident = if (token_tags[payload_token] == .asterisk)
6886 payload_token + 16886 payload_token + 1
6887 else6887 else
6888 payload_token;6888 payload_token;
6889
6889 const is_ptr = ident != payload_token;6890 const is_ptr = ident != payload_token;
6891 capture = if (is_ptr) .by_ref else .by_val;
6892
6890 const ident_slice = tree.tokenSlice(ident);6893 const ident_slice = tree.tokenSlice(ident);
6891 var payload_sub_scope: *Scope = undefined;6894 var payload_sub_scope: *Scope = undefined;
6892 if (mem.eql(u8, ident_slice, "_")) {6895 if (mem.eql(u8, ident_slice, "_")) {
...@@ -6895,46 +6898,18 @@ fn switchExpr(...@@ -6895,46 +6898,18 @@ fn switchExpr(
6895 }6898 }
6896 payload_sub_scope = &case_scope.base;6899 payload_sub_scope = &case_scope.base;
6897 } else {6900 } 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 }
6926 const capture_name = try astgen.identAsString(ident);6901 const capture_name = try astgen.identAsString(ident);
6927 try astgen.detectLocalShadowing(&case_scope.base, capture_name, ident, ident_slice, .capture);6902 try astgen.detectLocalShadowing(&case_scope.base, capture_name, ident, ident_slice, .capture);
6928 capture_val_scope = .{6903 capture_val_scope = .{
6929 .parent = &case_scope.base,6904 .parent = &case_scope.base,
6930 .gen_zir = &case_scope,6905 .gen_zir = &case_scope,
6931 .name = capture_name,6906 .name = capture_name,
6932 .inst = indexToRef(capture_inst),6907 .inst = indexToRef(switch_block),
6933 .token_src = payload_token,6908 .token_src = payload_token,
6934 .id_cat = .capture,6909 .id_cat = .capture,
6935 };6910 };
6936 dbg_var_name = capture_name;6911 dbg_var_name = capture_name;
6937 dbg_var_inst = indexToRef(capture_inst);6912 dbg_var_inst = indexToRef(switch_block);
6938 payload_sub_scope = &capture_val_scope.base;6913 payload_sub_scope = &capture_val_scope.base;
6939 }6914 }
69406915
...@@ -7023,7 +6998,6 @@ fn switchExpr(...@@ -7023,7 +6998,6 @@ fn switchExpr(
7023 case_scope.instructions_top = parent_gz.instructions.items.len;6998 case_scope.instructions_top = parent_gz.instructions.items.len;
7024 defer case_scope.unstack();6999 defer case_scope.unstack();
70257000
7026 if (capture_inst != 0) try case_scope.instructions.append(gpa, capture_inst);
7027 if (tag_inst != 0) try case_scope.instructions.append(gpa, tag_inst);7001 if (tag_inst != 0) try case_scope.instructions.append(gpa, tag_inst);
7028 try case_scope.addDbgBlockBegin();7002 try case_scope.addDbgBlockBegin();
7029 if (dbg_var_name) |some| {7003 if (dbg_var_name) |some| {
...@@ -7042,10 +7016,28 @@ fn switchExpr(...@@ -7042,10 +7016,28 @@ fn switchExpr(
7042 }7016 }
70437017
7044 const case_slice = case_scope.instructionsSlice();7018 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);
7046 try payloads.ensureUnusedCapacity(gpa, body_len);7032 try payloads.ensureUnusedCapacity(gpa, body_len);
7047 const inline_bit = @as(u32, @boolToInt(case.inline_token != null)) << 31;7033 payloads.items[body_len_index] = @bitCast(u32, Zir.Inst.SwitchBlock.ProngInfo{
7048 payloads.items[body_len_index] = body_len | inline_bit;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 }
7049 appendBodyWithFixupsArrayList(astgen, payloads, case_slice);7041 appendBodyWithFixupsArrayList(astgen, payloads, case_slice);
7050 }7042 }
7051 }7043 }
...@@ -7092,7 +7084,7 @@ fn switchExpr(...@@ -7092,7 +7084,7 @@ fn switchExpr(
7092 end_index += 3 + items_len + 2 * ranges_len;7084 end_index += 3 + items_len + 2 * ranges_len;
7093 }7085 }
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;
7096 end_index += body_len;7088 end_index += body_len;
70977089
7098 switch (strat.tag) {7090 switch (strat.tag) {
src/Module.zig+17-7
...@@ -5871,6 +5871,7 @@ pub const SwitchProngSrc = union(enum) {...@@ -5871,6 +5871,7 @@ pub const SwitchProngSrc = union(enum) {
5871 multi: Multi,5871 multi: Multi,
5872 range: Multi,5872 range: Multi,
5873 multi_capture: u32,5873 multi_capture: u32,
5874 special,
58745875
5875 pub const Multi = struct {5876 pub const Multi = struct {
5876 prong: u32,5877 prong: u32,
...@@ -5908,14 +5909,22 @@ pub const SwitchProngSrc = union(enum) {...@@ -5908,14 +5909,22 @@ pub const SwitchProngSrc = union(enum) {
5908 var scalar_i: u32 = 0;5909 var scalar_i: u32 = 0;
5909 for (case_nodes) |case_node| {5910 for (case_nodes) |case_node| {
5910 const case = tree.fullSwitchCase(case_node).?;5911 const case = tree.fullSwitchCase(case_node).?;
5911 if (case.ast.values.len == 0)5912
5912 continue;5913 const is_special = special: {
5913 if (case.ast.values.len == 1 and5914 if (case.ast.values.len == 0) break :special true;
5914 node_tags[case.ast.values[0]] == .identifier and5915 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .identifier) {
5915 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))5916 break :special mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_");
5916 {5917 }
5917 continue;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 );
5918 }5926 }
5927
5919 const is_multi = case.ast.values.len != 1 or5928 const is_multi = case.ast.values.len != 1 or
5920 node_tags[case.ast.values[0]] == .switch_range;5929 node_tags[case.ast.values[0]] == .switch_range;
59215930
...@@ -5956,6 +5965,7 @@ pub const SwitchProngSrc = union(enum) {...@@ -5956,6 +5965,7 @@ pub const SwitchProngSrc = union(enum) {
5956 range_i += 1;5965 range_i += 1;
5957 } else unreachable;5966 } else unreachable;
5958 },5967 },
5968 .special => {},
5959 }5969 }
5960 if (is_multi) {5970 if (is_multi) {
5961 multi_i += 1;5971 multi_i += 1;
src/Sema.zig+468-181
...@@ -277,9 +277,6 @@ pub const Block = struct {...@@ -277,9 +277,6 @@ pub const Block = struct {
277277
278 c_import_buf: ?*std.ArrayList(u8) = null,278 c_import_buf: ?*std.ArrayList(u8) = null,
279279
280 /// type of `err` in `else => |err|`
281 switch_else_err_ty: ?Type = null,
282
283 /// Value for switch_capture in an inline case280 /// Value for switch_capture in an inline case
284 inline_case_capture: Air.Inst.Ref = .none,281 inline_case_capture: Air.Inst.Ref = .none,
285282
...@@ -397,7 +394,6 @@ pub const Block = struct {...@@ -397,7 +394,6 @@ pub const Block = struct {
397 .want_safety = parent.want_safety,394 .want_safety = parent.want_safety,
398 .float_mode = parent.float_mode,395 .float_mode = parent.float_mode,
399 .c_import_buf = parent.c_import_buf,396 .c_import_buf = parent.c_import_buf,
400 .switch_else_err_ty = parent.switch_else_err_ty,
401 .error_return_trace_index = parent.error_return_trace_index,397 .error_return_trace_index = parent.error_return_trace_index,
402 };398 };
403 }399 }
...@@ -1017,8 +1013,6 @@ fn analyzeBodyInner(...@@ -1017,8 +1013,6 @@ fn analyzeBodyInner(
1017 .switch_block => try sema.zirSwitchBlock(block, inst),1013 .switch_block => try sema.zirSwitchBlock(block, inst),
1018 .switch_cond => try sema.zirSwitchCond(block, inst, false),1014 .switch_cond => try sema.zirSwitchCond(block, inst, false),
1019 .switch_cond_ref => try sema.zirSwitchCond(block, inst, true),1015 .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),
1022 .switch_capture_tag => try sema.zirSwitchCaptureTag(block, inst),1016 .switch_capture_tag => try sema.zirSwitchCaptureTag(block, inst),
1023 .type_info => try sema.zirTypeInfo(block, inst),1017 .type_info => try sema.zirTypeInfo(block, inst),
1024 .size_of => try sema.zirSizeOf(block, inst),1018 .size_of => try sema.zirSizeOf(block, inst),
...@@ -10083,61 +10077,160 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10083,61 +10077,160 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10083 return sema.analyzeSlice(block, src, array_ptr, start, len, sentinel, sentinel_src, ptr_src, start_src, end_src, true);10077 return sema.analyzeSlice(block, src, array_ptr, start, len, sentinel, sentinel_src, ptr_src, start_src, end_src, true);
10084}10078}
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(
10087 sema: *Sema,10083 sema: *Sema,
10088 block: *Block,10084 parent_block: *Block,
10089 inst: Zir.Inst.Index,10085 child_block: *Block,
10090 is_ref: bool,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,
10091) CompileError!Air.Inst.Ref {10097) CompileError!Air.Inst.Ref {
10092 const tracy = trace(@src());10098 switch (capture) {
10093 defer tracy.end();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 {
10095 const mod = sema.mod;10203 const mod = sema.mod;
10096 const gpa = sema.gpa;10204 const gpa = sema.gpa;
10097 const zir_datas = sema.code.instructions.items(.data);10205 const operand_ty = sema.typeOf(operand);
10098 const capture_info = zir_datas[inst].switch_capture;10206 const operand_ptr_ty = if (capture_byref) sema.typeOf(operand_ptr) else undefined;
10099 const switch_info = zir_datas[capture_info.switch_inst].pl_node;10207 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_node_offset };
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;
1011110208
10112 if (block.inline_case_capture != .none) {10209 if (block.inline_case_capture != .none) {
10113 const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, undefined) catch unreachable;10210 const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, "") catch unreachable;
10114 const resolved_item_val = try sema.resolveLazyValue(item_val);
10115 if (operand_ty.zigTypeTag(mod) == .Union) {10211 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).?);
10117 const union_obj = mod.typeToUnion(operand_ty).?;10213 const union_obj = mod.typeToUnion(operand_ty).?;
10118 const field_ty = union_obj.fields.values()[field_index].ty;10214 const field_ty = union_obj.fields.values()[field_index].ty;
10119 if (try sema.resolveDefinedValue(block, sema.src, operand_ptr)) |union_val| {10215 if (capture_byref) {
10120 if (is_ref) {10216 if (try sema.resolveDefinedValue(block, sema.src, operand_ptr)) |union_ptr| {
10121 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{10217 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
10122 .pointee_type = field_ty,10218 .pointee_type = field_ty,
10123 .mutable = operand_ptr_ty.ptrIsMutable(mod),10219 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10124 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),10220 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
10125 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),10221 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
10126 });10222 });
10127 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{10223 return sema.addConstant(
10128 .ty = ptr_field_ty.toIntern(),10224 ptr_field_ty,
10129 .addr = .{ .field = .{10225 (try mod.intern(.{ .ptr = .{
10130 .base = union_val.toIntern(),10226 .ty = ptr_field_ty.toIntern(),
10131 .index = field_index,10227 .addr = .{ .field = .{
10132 } },10228 .base = union_ptr.toIntern(),
10133 } })).toValue());10229 .index = field_index,
10230 } },
10231 } })).toValue(),
10232 );
10134 }10233 }
10135 return sema.addConstant(
10136 field_ty,
10137 mod.intern_pool.indexToKey(union_val.toIntern()).un.val.toValue(),
10138 );
10139 }
10140 if (is_ref) {
10141 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{10234 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
10142 .pointee_type = field_ty,10235 .pointee_type = field_ty,
10143 .mutable = operand_ptr_ty.ptrIsMutable(mod),10236 .mutable = operand_ptr_ty.ptrIsMutable(mod),
...@@ -10146,29 +10239,27 @@ fn zirSwitchCapture(...@@ -10146,29 +10239,27 @@ fn zirSwitchCapture(
10146 });10239 });
10147 return block.addStructFieldPtr(operand_ptr, field_index, ptr_field_ty);10240 return block.addStructFieldPtr(operand_ptr, field_index, ptr_field_ty);
10148 } else {10241 } 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);
10150 }10247 }
10151 } else if (is_ref) {10248 } else if (capture_byref) {
10152 return sema.addConstantMaybeRef(block, operand_ty, resolved_item_val, true);10249 return sema.addConstantMaybeRef(block, operand_ty, item_val, true);
10153 } else {10250 } else {
10154 return block.inline_case_capture;10251 return block.inline_case_capture;
10155 }10252 }
10156 }10253 }
1015710254
10158 const operand = if (operand_is_ref)10255 if (is_special_prong) {
10159 try sema.analyzeLoad(block, operand_src, operand_ptr, operand_src)10256 if (capture_byref) {
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) {
10166 return operand_ptr;10257 return operand_ptr;
10167 }10258 }
1016810259
10169 switch (operand_ty.zigTypeTag(mod)) {10260 switch (operand_ty.zigTypeTag(mod)) {
10170 .ErrorSet => if (block.switch_else_err_ty) |some| {10261 .ErrorSet => if (else_error_ty) |ty| {
10171 return sema.bitCast(block, some, operand, operand_src, null);10262 return sema.bitCast(block, ty, operand, operand_src, null);
10172 } else {10263 } else {
10173 try block.addUnreachable(false);10264 try block.addUnreachable(false);
10174 return Air.Inst.Ref.unreachable_value;10265 return Air.Inst.Ref.unreachable_value;
...@@ -10177,41 +10268,33 @@ fn zirSwitchCapture(...@@ -10177,41 +10268,33 @@ fn zirSwitchCapture(
10177 }10268 }
10178 }10269 }
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
10184 switch (operand_ty.zigTypeTag(mod)) {10271 switch (operand_ty.zigTypeTag(mod)) {
10185 .Union => {10272 .Union => {
10186 const union_obj = mod.typeToUnion(operand_ty).?;10273 const union_obj = mod.typeToUnion(operand_ty).?;
10187 const first_item = try sema.resolveInst(items[0]);10274 const first_item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
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;
1019110275
10192 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, mod).?);10276 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, mod).?);
10193 const first_field = union_obj.fields.values()[first_field_index];10277 const first_field = union_obj.fields.values()[first_field_index];
1019410278
10195 for (items[1..], 0..) |item, i| {10279 for (case_vals[1..], 0..) |item, i| {
10196 const item_ref = try sema.resolveInst(item);10280 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
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;
1020010281
10201 const field_index = operand_ty.unionTagFieldIndex(item_val, mod).?;10282 const field_index = operand_ty.unionTagFieldIndex(item_val, mod).?;
10202 const field = union_obj.fields.values()[field_index];10283 const field = union_obj.fields.values()[field_index];
10203 if (!field.ty.eql(first_field.ty, mod)) {10284 if (!field.ty.eql(first_field.ty, mod)) {
10204 const msg = msg: {10285 const msg = msg: {
10205 const raw_capture_src = Module.SwitchProngSrc{ .multi_capture = capture_info.prong_index };10286 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
10206 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_info.src_node, .first);
1020710287
10208 const msg = try sema.errMsg(block, capture_src, "capture group with incompatible types", .{});10288 const msg = try sema.errMsg(block, capture_src, "capture group with incompatible types", .{});
10209 errdefer msg.destroy(gpa);10289 errdefer msg.destroy(gpa);
1021010290
10211 const raw_first_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = capture_info.prong_index, .item = 0 } };10291 // This must be a multi-prong so this must be a `multi_capture` src
10212 const first_item_src = raw_first_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_info.src_node, .first);10292 const multi_idx = raw_capture_src.multi_capture;
10213 const raw_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = capture_info.prong_index, .item = 1 + @intCast(u32, i) } };10293
10214 const item_src = raw_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_info.src_node, .first);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);
10215 try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(mod)});10298 try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(mod)});
10216 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(mod)});10299 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(mod)});
10217 break :msg msg;10300 break :msg msg;
...@@ -10220,7 +10303,7 @@ fn zirSwitchCapture(...@@ -10220,7 +10303,7 @@ fn zirSwitchCapture(
10220 }10303 }
10221 }10304 }
1022210305
10223 if (is_ref) {10306 if (capture_byref) {
10224 const field_ty_ptr = try Type.ptr(sema.arena, mod, .{10307 const field_ty_ptr = try Type.ptr(sema.arena, mod, .{
10225 .pointee_type = first_field.ty,10308 .pointee_type = first_field.ty,
10226 .@"addrspace" = .generic,10309 .@"addrspace" = .generic,
...@@ -10250,31 +10333,35 @@ fn zirSwitchCapture(...@@ -10250,31 +10333,35 @@ fn zirSwitchCapture(
10250 return block.addStructFieldVal(operand, first_field_index, first_field.ty);10333 return block.addStructFieldVal(operand, first_field_index, first_field.ty);
10251 },10334 },
10252 .ErrorSet => {10335 .ErrorSet => {
10253 if (items.len > 1) {10336 if (capture_byref) {
10254 var names: Module.Fn.InferredErrorSet.NameMap = .{};10337 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
10255 try names.ensureUnusedCapacity(sema.arena, items.len);10338 return sema.fail(
10256 for (items) |item| {10339 block,
10257 const item_ref = try sema.resolveInst(item);10340 capture_src,
10258 // Previous switch validation ensured this will succeed10341 "error set cannot be captured by reference",
10259 const item_val = sema.resolveConstLazyValue(block, .unneeded, item_ref, "") catch unreachable;10342 .{},
10260 names.putAssumeCapacityNoClobber(item_val.getErrorName(mod).unwrap().?, {});10343 );
10261 }10344 }
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;
1026910345
10346 if (case_vals.len == 1) {
10347 const item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
10270 const item_ty = try mod.singleErrorSetType(item_val.getErrorName(mod).unwrap().?);10348 const item_ty = try mod.singleErrorSetType(item_val.getErrorName(mod).unwrap().?);
10271 return sema.bitCast(block, item_ty, operand, operand_src, null);10349 return sema.bitCast(block, item_ty, operand, operand_src, null);
10272 }10350 }
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);
10273 },10360 },
10274 else => {10361 else => {
10275 // In this case the capture value is just the passed-through value of the10362 // In this case the capture value is just the passed-through value
10276 // switch condition.10363 // of the switch condition.
10277 if (is_ref) {10364 if (capture_byref) {
10278 return operand_ptr;10365 return operand_ptr;
10279 } else {10366 } else {
10280 return operand;10367 return operand;
...@@ -10415,28 +10502,42 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10415,28 +10502,42 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10415 var case_vals = try std.ArrayListUnmanaged(Air.Inst.Ref).initCapacity(gpa, scalar_cases_len + 2 * multi_cases_len);10502 var case_vals = try std.ArrayListUnmanaged(Air.Inst.Ref).initCapacity(gpa, scalar_cases_len + 2 * multi_cases_len);
10416 defer case_vals.deinit(gpa);10503 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
10418 const special_prong = extra.data.bits.specialProng();10512 const special_prong = extra.data.bits.specialProng();
10419 const special: struct { body: []const Zir.Inst.Index, end: usize, is_inline: bool } = switch (special_prong) {10513 const special: Special = switch (special_prong) {
10420 .none => .{ .body = &.{}, .end = header_extra_index, .is_inline = false },10514 .none => .{ .body = &.{}, .end = header_extra_index, .capture = .none, .is_inline = false },
10421 .under, .@"else" => blk: {10515 .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]);
10423 const extra_body_start = header_extra_index + 1;10517 const extra_body_start = header_extra_index + 1;
10424 break :blk .{10518 break :blk .{
10425 .body = sema.code.extra[extra_body_start..][0..body_len],10519 .body = sema.code.extra[extra_body_start..][0..info.body_len],
10426 .end = extra_body_start + body_len,10520 .end = extra_body_start + info.body_len,
10427 .is_inline = sema.code.extra[header_extra_index] >> 31 != 0,10521 .capture = info.capture,
10522 .is_inline = info.is_inline,
10428 };10523 };
10429 },10524 },
10430 };10525 };
1043110526
10432 const maybe_union_ty = blk: {10527 const raw_operand: struct { val: Air.Inst.Ref, ptr: Air.Inst.Ref } = blk: {
10433 const zir_tags = sema.code.instructions.items(.tag);10528 const zir_tags = sema.code.instructions.items(.tag);
10434 const zir_data = sema.code.instructions.items(.data);10529 const zir_data = sema.code.instructions.items(.data);
10435 const cond_index = Zir.refToIndex(extra.data.operand).?;10530 const cond_index = Zir.refToIndex(extra.data.operand).?;
10436 const raw_operand = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable;10531 const raw = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable;
10437 const target_ty = sema.typeOf(raw_operand);10532 if (zir_tags[cond_index] == .switch_cond_ref) {
10438 break :blk if (zir_tags[cond_index] == .switch_cond_ref) target_ty.childType(mod) else target_ty;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 }
10439 };10538 };
10539
10540 const maybe_union_ty = sema.typeOf(raw_operand.val);
10440 const union_originally = maybe_union_ty.zigTypeTag(mod) == .Union;10541 const union_originally = maybe_union_ty.zigTypeTag(mod) == .Union;
1044110542
10442 // Duplicate checking variables later also used for `inline else`.10543 // Duplicate checking variables later also used for `inline else`.
...@@ -10496,9 +10597,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10496,9 +10597,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10496 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {10597 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
10497 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);10598 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
10498 extra_index += 1;10599 extra_index += 1;
10499 const body_len = @truncate(u31, sema.code.extra[extra_index]);10600 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
10500 extra_index += 1;10601 extra_index += 1 + info.body_len;
10501 extra_index += body_len;
1050210602
10503 case_vals.appendAssumeCapacity(try sema.validateSwitchItemEnum(10603 case_vals.appendAssumeCapacity(try sema.validateSwitchItemEnum(
10504 block,10604 block,
...@@ -10518,10 +10618,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10518,10 +10618,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10518 extra_index += 1;10618 extra_index += 1;
10519 const ranges_len = sema.code.extra[extra_index];10619 const ranges_len = sema.code.extra[extra_index];
10520 extra_index += 1;10620 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]);
10522 extra_index += 1;10622 extra_index += 1;
10523 const items = sema.code.refSlice(extra_index, items_len);10623 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
10526 try case_vals.ensureUnusedCapacity(gpa, items.len);10626 try case_vals.ensureUnusedCapacity(gpa, items.len);
10527 for (items, 0..) |item_ref, item_i| {10627 for (items, 0..) |item_ref, item_i| {
...@@ -10596,9 +10696,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10596,9 +10696,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10596 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {10696 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
10597 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);10697 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
10598 extra_index += 1;10698 extra_index += 1;
10599 const body_len = @truncate(u31, sema.code.extra[extra_index]);10699 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
10600 extra_index += 1;10700 extra_index += 1 + info.body_len;
10601 extra_index += body_len;
1060210701
10603 case_vals.appendAssumeCapacity(try sema.validateSwitchItemError(10702 case_vals.appendAssumeCapacity(try sema.validateSwitchItemError(
10604 block,10703 block,
...@@ -10617,10 +10716,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10617,10 +10716,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10617 extra_index += 1;10716 extra_index += 1;
10618 const ranges_len = sema.code.extra[extra_index];10717 const ranges_len = sema.code.extra[extra_index];
10619 extra_index += 1;10718 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]);
10621 extra_index += 1;10720 extra_index += 1;
10622 const items = sema.code.refSlice(extra_index, items_len);10721 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
10625 try case_vals.ensureUnusedCapacity(gpa, items.len);10724 try case_vals.ensureUnusedCapacity(gpa, items.len);
10626 for (items, 0..) |item_ref, item_i| {10725 for (items, 0..) |item_ref, item_i| {
...@@ -10694,7 +10793,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10694,7 +10793,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10694 .dbg_block_end,10793 .dbg_block_end,
10695 .dbg_stmt,10794 .dbg_stmt,
10696 .dbg_var_val,10795 .dbg_var_val,
10697 .switch_capture,
10698 .ret_type,10796 .ret_type,
10699 .as_node,10797 .as_node,
10700 .ret_node,10798 .ret_node,
...@@ -10739,9 +10837,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10739,9 +10837,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10739 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {10837 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
10740 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);10838 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
10741 extra_index += 1;10839 extra_index += 1;
10742 const body_len = @truncate(u31, sema.code.extra[extra_index]);10840 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
10743 extra_index += 1;10841 extra_index += 1 + info.body_len;
10744 extra_index += body_len;
1074510842
10746 case_vals.appendAssumeCapacity(try sema.validateSwitchItemInt(10843 case_vals.appendAssumeCapacity(try sema.validateSwitchItemInt(
10747 block,10844 block,
...@@ -10760,7 +10857,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10760,7 +10857,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10760 extra_index += 1;10857 extra_index += 1;
10761 const ranges_len = sema.code.extra[extra_index];10858 const ranges_len = sema.code.extra[extra_index];
10762 extra_index += 1;10859 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]);
10764 extra_index += 1;10861 extra_index += 1;
10765 const items = sema.code.refSlice(extra_index, items_len);10862 const items = sema.code.refSlice(extra_index, items_len);
10766 extra_index += items_len;10863 extra_index += items_len;
...@@ -10798,7 +10895,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10798,7 +10895,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10798 case_vals.appendAssumeCapacity(vals[1]);10895 case_vals.appendAssumeCapacity(vals[1]);
10799 }10896 }
1080010897
10801 extra_index += body_len;10898 extra_index += info.body_len;
10802 }10899 }
10803 }10900 }
1080410901
...@@ -10835,9 +10932,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10835,9 +10932,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10835 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {10932 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
10836 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);10933 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
10837 extra_index += 1;10934 extra_index += 1;
10838 const body_len = @truncate(u31, sema.code.extra[extra_index]);10935 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
10839 extra_index += 1;10936 extra_index += 1 + info.body_len;
10840 extra_index += body_len;
1084110937
10842 case_vals.appendAssumeCapacity(try sema.validateSwitchItemBool(10938 case_vals.appendAssumeCapacity(try sema.validateSwitchItemBool(
10843 block,10939 block,
...@@ -10856,10 +10952,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10856,10 +10952,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10856 extra_index += 1;10952 extra_index += 1;
10857 const ranges_len = sema.code.extra[extra_index];10953 const ranges_len = sema.code.extra[extra_index];
10858 extra_index += 1;10954 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]);
10860 extra_index += 1;10956 extra_index += 1;
10861 const items = sema.code.refSlice(extra_index, items_len);10957 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
10864 try case_vals.ensureUnusedCapacity(gpa, items.len);10960 try case_vals.ensureUnusedCapacity(gpa, items.len);
10865 for (items, 0..) |item_ref, item_i| {10961 for (items, 0..) |item_ref, item_i| {
...@@ -10918,9 +11014,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10918,9 +11014,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10918 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {11014 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
10919 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);11015 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
10920 extra_index += 1;11016 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]);
10922 extra_index += 1;11018 extra_index += 1;
10923 extra_index += body_len;11019 extra_index += info.body_len;
1092411020
10925 case_vals.appendAssumeCapacity(try sema.validateSwitchItemSparse(11021 case_vals.appendAssumeCapacity(try sema.validateSwitchItemSparse(
10926 block,11022 block,
...@@ -10939,10 +11035,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10939,10 +11035,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10939 extra_index += 1;11035 extra_index += 1;
10940 const ranges_len = sema.code.extra[extra_index];11036 const ranges_len = sema.code.extra[extra_index];
10941 extra_index += 1;11037 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]);
10943 extra_index += 1;11039 extra_index += 1;
10944 const items = sema.code.refSlice(extra_index, items_len);11040 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
10947 try case_vals.ensureUnusedCapacity(gpa, items.len);11043 try case_vals.ensureUnusedCapacity(gpa, items.len);
10948 for (items, 0..) |item_ref, item_i| {11044 for (items, 0..) |item_ref, item_i| {
...@@ -11006,7 +11102,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11006,7 +11102,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11006 .is_comptime = block.is_comptime,11102 .is_comptime = block.is_comptime,
11007 .comptime_reason = block.comptime_reason,11103 .comptime_reason = block.comptime_reason,
11008 .is_typeof = block.is_typeof,11104 .is_typeof = block.is_typeof,
11009 .switch_else_err_ty = else_error_ty,
11010 .c_import_buf = block.c_import_buf,11105 .c_import_buf = block.c_import_buf,
11011 .runtime_cond = block.runtime_cond,11106 .runtime_cond = block.runtime_cond,
11012 .runtime_loop = block.runtime_loop,11107 .runtime_loop = block.runtime_loop,
...@@ -11024,19 +11119,31 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11024,19 +11119,31 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11024 var scalar_i: usize = 0;11119 var scalar_i: usize = 0;
11025 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {11120 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
11026 extra_index += 1;11121 extra_index += 1;
11027 const body_len = @truncate(u31, sema.code.extra[extra_index]);11122 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
11028 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
11029 extra_index += 1;11123 extra_index += 1;
11030 const body = sema.code.extra[extra_index..][0..body_len];11124 const body = sema.code.extra[extra_index..][0..info.body_len];
11031 extra_index += body_len;11125 extra_index += info.body_len;
1103211126
11033 const item = case_vals.items[scalar_i];11127 const item = case_vals.items[scalar_i];
11034 const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable;11128 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
11035 if (resolved_operand_val.eql(item_val, operand_ty, mod)) {11129 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
11036 if (is_inline) child_block.inline_case_capture = operand;11130 if (info.is_inline) child_block.inline_case_capture = operand;
11037
11038 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);11131 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 );
11040 }11147 }
11041 }11148 }
11042 }11149 }
...@@ -11048,22 +11155,34 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11048,22 +11155,34 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11048 extra_index += 1;11155 extra_index += 1;
11049 const ranges_len = sema.code.extra[extra_index];11156 const ranges_len = sema.code.extra[extra_index];
11050 extra_index += 1;11157 extra_index += 1;
11051 const body_len = @truncate(u31, sema.code.extra[extra_index]);11158 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
11052 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
11053 extra_index += 1 + items_len;11159 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
11056 const items = case_vals.items[case_val_idx..][0..items_len];11162 const items = case_vals.items[case_val_idx..][0..items_len];
11057 case_val_idx += items_len;11163 case_val_idx += items_len;
1105811164
11059 for (items) |item| {11165 for (items) |item| {
11060 // Validation above ensured these will succeed.11166 // Validation above ensured these will succeed.
11061 const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable;11167 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
11062 if (resolved_operand_val.eql(item_val, operand_ty, mod)) {11168 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
11063 if (is_inline) child_block.inline_case_capture = operand;11169 if (info.is_inline) child_block.inline_case_capture = operand;
11064
11065 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);11170 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 );
11067 }11186 }
11068 }11187 }
1106911188
...@@ -11079,13 +11198,27 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11079,13 +11198,27 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11079 if ((try sema.compareAll(resolved_operand_val, .gte, first_val, operand_ty)) and11198 if ((try sema.compareAll(resolved_operand_val, .gte, first_val, operand_ty)) and
11080 (try sema.compareAll(resolved_operand_val, .lte, last_val, operand_ty)))11199 (try sema.compareAll(resolved_operand_val, .lte, last_val, operand_ty)))
11081 {11200 {
11082 if (is_inline) child_block.inline_case_capture = operand;11201 if (info.is_inline) child_block.inline_case_capture = operand;
11083 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);11202 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 );
11085 }11218 }
11086 }11219 }
1108711220
11088 extra_index += body_len;11221 extra_index += info.body_len;
11089 }11222 }
11090 }11223 }
11091 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand);11224 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...@@ -11093,7 +11226,22 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11093 if (empty_enum) {11226 if (empty_enum) {
11094 return Air.Inst.Ref.void_value;11227 return Air.Inst.Ref.void_value;
11095 }11228 }
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 );
11097 }11245 }
1109811246
11099 if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline) {11247 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...@@ -11113,7 +11261,22 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11113 const ok = try block.addUnOp(.is_named_enum_value, operand);11261 const ok = try block.addUnOp(.is_named_enum_value, operand);
11114 try sema.addSafetyCheck(block, ok, .corrupt_switch);11262 try sema.addSafetyCheck(block, ok, .corrupt_switch);
11115 }11263 }
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 );
11117 }11280 }
1111811281
11119 if (child_block.is_comptime) {11282 if (child_block.is_comptime) {
...@@ -11140,11 +11303,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11140,11 +11303,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11140 var scalar_i: usize = 0;11303 var scalar_i: usize = 0;
11141 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {11304 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
11142 extra_index += 1;11305 extra_index += 1;
11143 const body_len = @truncate(u31, sema.code.extra[extra_index]);11306 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
11144 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
11145 extra_index += 1;11307 extra_index += 1;
11146 const body = sema.code.extra[extra_index..][0..body_len];11308 const body = sema.code.extra[extra_index..][0..info.body_len];
11147 extra_index += body_len;11309 extra_index += info.body_len;
1114811310
11149 var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope);11311 var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope);
11150 defer wip_captures.deinit();11312 defer wip_captures.deinit();
...@@ -11154,7 +11316,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11154,7 +11316,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11154 case_block.inline_case_capture = .none;11316 case_block.inline_case_capture = .none;
1115511317
11156 const item = case_vals.items[scalar_i];11318 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;
11158 // `item` is already guaranteed to be constant known.11320 // `item` is already guaranteed to be constant known.
1115911321
11160 const analyze_body = if (union_originally) blk: {11322 const analyze_body = if (union_originally) blk: {
...@@ -11166,7 +11328,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11166,7 +11328,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11166 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {11328 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
11167 // nothing to do here11329 // nothing to do here
11168 } else if (analyze_body) {11330 } 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 );
11170 } else {11343 } else {
11171 _ = try case_block.addNoOp(.unreach);11344 _ = try case_block.addNoOp(.unreach);
11172 }11345 }
...@@ -11195,8 +11368,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11195,8 +11368,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11195 extra_index += 1;11368 extra_index += 1;
11196 const ranges_len = sema.code.extra[extra_index];11369 const ranges_len = sema.code.extra[extra_index];
11197 extra_index += 1;11370 extra_index += 1;
11198 const body_len = @truncate(u31, sema.code.extra[extra_index]);11371 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, sema.code.extra[extra_index]);
11199 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
11200 extra_index += 1 + items_len;11372 extra_index += 1 + items_len;
1120111373
11202 const items = case_vals.items[case_val_idx..][0..items_len];11374 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...@@ -11207,9 +11379,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11207 case_block.inline_case_capture = .none;11379 case_block.inline_case_capture = .none;
1120811380
11209 // Generate all possible cases as scalar prongs.11381 // Generate all possible cases as scalar prongs.
11210 if (is_inline) {11382 if (info.is_inline) {
11211 const body_start = extra_index + 2 * ranges_len;11383 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];
11213 var emit_bb = false;11385 var emit_bb = false;
1121411386
11215 var range_i: u32 = 0;11387 var range_i: u32 = 0;
...@@ -11250,7 +11422,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11250,7 +11422,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11250 };11422 };
11251 emit_bb = true;11423 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
11255 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);11438 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
11256 cases_extra.appendAssumeCapacity(1); // items_len11439 cases_extra.appendAssumeCapacity(1); // items_len
...@@ -11286,7 +11469,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11286,7 +11469,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11286 emit_bb = true;11469 emit_bb = true;
1128711470
11288 if (analyze_body) {11471 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 );
11290 } else {11484 } else {
11291 _ = try case_block.addNoOp(.unreach);11485 _ = try case_block.addNoOp(.unreach);
11292 }11486 }
...@@ -11298,7 +11492,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11298,7 +11492,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11298 cases_extra.appendSliceAssumeCapacity(case_block.instructions.items);11492 cases_extra.appendSliceAssumeCapacity(case_block.instructions.items);
11299 }11493 }
1130011494
11301 extra_index += body_len;11495 extra_index += info.body_len;
11302 continue;11496 continue;
11303 }11497 }
1130411498
...@@ -11319,12 +11513,23 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11319,12 +11513,23 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11319 else11513 else
11320 true;11514 true;
1132111515
11322 const body = sema.code.extra[extra_index..][0..body_len];11516 const body = sema.code.extra[extra_index..][0..info.body_len];
11323 extra_index += body_len;11517 extra_index += info.body_len;
11324 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {11518 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
11325 // nothing to do here11519 // nothing to do here
11326 } else if (analyze_body) {11520 } 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 );
11328 } else {11533 } else {
11329 _ = try case_block.addNoOp(.unreach);11534 _ = try case_block.addNoOp(.unreach);
11330 }11535 }
...@@ -11397,12 +11602,23 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11397,12 +11602,23 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11397 case_block.instructions.shrinkRetainingCapacity(0);11602 case_block.instructions.shrinkRetainingCapacity(0);
11398 case_block.wip_capture_scope = wip_captures.scope;11603 case_block.wip_capture_scope = wip_captures.scope;
1139911604
11400 const body = sema.code.extra[extra_index..][0..body_len];11605 const body = sema.code.extra[extra_index..][0..info.body_len];
11401 extra_index += body_len;11606 extra_index += info.body_len;
11402 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {11607 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
11403 // nothing to do here11608 // nothing to do here
11404 } else {11609 } 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 );
11406 }11622 }
1140711623
11408 try wip_captures.finalize();11624 try wip_captures.finalize();
...@@ -11461,7 +11677,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11461,7 +11677,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11461 emit_bb = true;11677 emit_bb = true;
1146211678
11463 if (analyze_body) {11679 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 );
11465 } else {11692 } else {
11466 _ = try case_block.addNoOp(.unreach);11693 _ = try case_block.addNoOp(.unreach);
11467 }11694 }
...@@ -11497,7 +11724,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11497,7 +11724,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11497 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);11724 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
11498 emit_bb = true;11725 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
11502 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);11740 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
11503 cases_extra.appendAssumeCapacity(1); // items_len11741 cases_extra.appendAssumeCapacity(1); // items_len
...@@ -11520,7 +11758,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11520,7 +11758,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11520 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);11758 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
11521 emit_bb = true;11759 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
11525 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);11774 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
11526 cases_extra.appendAssumeCapacity(1); // items_len11775 cases_extra.appendAssumeCapacity(1); // items_len
...@@ -11540,7 +11789,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11540,7 +11789,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11540 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);11789 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
11541 emit_bb = true;11790 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
11545 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);11805 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
11546 cases_extra.appendAssumeCapacity(1); // items_len11806 cases_extra.appendAssumeCapacity(1); // items_len
...@@ -11558,7 +11818,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11558,7 +11818,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11558 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);11818 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
11559 emit_bb = true;11819 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
11563 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);11834 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
11564 cases_extra.appendAssumeCapacity(1); // items_len11835 cases_extra.appendAssumeCapacity(1); // items_len
...@@ -11601,7 +11872,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11601,7 +11872,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11601 {11872 {
11602 // nothing to do here11873 // nothing to do here
11603 } else if (special.body.len != 0 and analyze_body and !special.is_inline) {11874 } 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 );
11605 } else {11887 } else {
11606 // We still need a terminator in this block, but we have proven11888 // We still need a terminator in this block, but we have proven
11607 // that it is unreachable.11889 // that it is unreachable.
...@@ -11746,7 +12028,7 @@ fn resolveSwitchItemVal(...@@ -11746,7 +12028,7 @@ fn resolveSwitchItemVal(
11746 else => |e| return e,12028 else => |e| return e,
11747 };12029 };
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) {
11750 error.NeededSourceLocation => {12032 error.NeededSourceLocation => {
11751 const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand);12033 const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand);
11752 _ = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known");12034 _ = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known");
...@@ -11755,7 +12037,12 @@ fn resolveSwitchItemVal(...@@ -11755,7 +12037,12 @@ fn resolveSwitchItemVal(
11755 else => |e| return e,12037 else => |e| return e,
11756 };12038 };
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() };
11759}12046}
1176012047
11761fn validateSwitchRange(12048fn validateSwitchRange(
src/Zir.zig+23-86
...@@ -676,17 +676,6 @@ pub const Inst = struct {...@@ -676,17 +676,6 @@ pub const Inst = struct {
676 /// what will be switched on.676 /// what will be switched on.
677 /// Uses the `un_node` union field.677 /// Uses the `un_node` union field.
678 switch_cond_ref,678 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,
690 /// Produces the capture value for an inline switch prong tag capture.679 /// Produces the capture value for an inline switch prong tag capture.
691 /// Uses the `un_tok` field.680 /// Uses the `un_tok` field.
692 switch_capture_tag,681 switch_capture_tag,
...@@ -1135,8 +1124,6 @@ pub const Inst = struct {...@@ -1135,8 +1124,6 @@ pub const Inst = struct {
1135 .typeof_log2_int_type,1124 .typeof_log2_int_type,
1136 .resolve_inferred_alloc,1125 .resolve_inferred_alloc,
1137 .set_eval_branch_quota,1126 .set_eval_branch_quota,
1138 .switch_capture,
1139 .switch_capture_ref,
1140 .switch_capture_tag,1127 .switch_capture_tag,
1141 .switch_block,1128 .switch_block,
1142 .switch_cond,1129 .switch_cond,
...@@ -1427,8 +1414,6 @@ pub const Inst = struct {...@@ -1427,8 +1414,6 @@ pub const Inst = struct {
1427 .slice_length,1414 .slice_length,
1428 .import,1415 .import,
1429 .typeof_log2_int_type,1416 .typeof_log2_int_type,
1430 .switch_capture,
1431 .switch_capture_ref,
1432 .switch_capture_tag,1417 .switch_capture_tag,
1433 .switch_block,1418 .switch_block,
1434 .switch_cond,1419 .switch_cond,
...@@ -1685,8 +1670,6 @@ pub const Inst = struct {...@@ -1685,8 +1670,6 @@ pub const Inst = struct {
1685 .switch_block = .pl_node,1670 .switch_block = .pl_node,
1686 .switch_cond = .un_node,1671 .switch_cond = .un_node,
1687 .switch_cond_ref = .un_node,1672 .switch_cond_ref = .un_node,
1688 .switch_capture = .switch_capture,
1689 .switch_capture_ref = .switch_capture,
1690 .switch_capture_tag = .un_tok,1673 .switch_capture_tag = .un_tok,
1691 .array_base_ptr = .un_node,1674 .array_base_ptr = .un_node,
1692 .field_base_ptr = .un_node,1675 .field_base_ptr = .un_node,
...@@ -2254,10 +2237,6 @@ pub const Inst = struct {...@@ -2254,10 +2237,6 @@ pub const Inst = struct {
2254 operand: Ref,2237 operand: Ref,
2255 payload_index: u32,2238 payload_index: u32,
2256 },2239 },
2257 switch_capture: struct {
2258 switch_inst: Index,
2259 prong_index: u32,
2260 },
2261 dbg_stmt: LineColumn,2240 dbg_stmt: LineColumn,
2262 /// Used for unary operators which reference an inst,2241 /// Used for unary operators which reference an inst,
2263 /// with an AST node source location.2242 /// with an AST node source location.
...@@ -2327,7 +2306,6 @@ pub const Inst = struct {...@@ -2327,7 +2306,6 @@ pub const Inst = struct {
2327 bool_br,2306 bool_br,
2328 @"unreachable",2307 @"unreachable",
2329 @"break",2308 @"break",
2330 switch_capture,
2331 dbg_stmt,2309 dbg_stmt,
2332 inst_node,2310 inst_node,
2333 str_op,2311 str_op,
...@@ -2667,25 +2645,29 @@ pub const Inst = struct {...@@ -2667,25 +2645,29 @@ pub const Inst = struct {
26672645
2668 /// 0. multi_cases_len: u32 // If has_multi_cases is set.2646 /// 0. multi_cases_len: u32 // If has_multi_cases is set.
2669 /// 1. else_body { // If has_else or has_under is set.2647 /// 1. else_body { // If has_else or has_under is set.
2670 /// body_len: u32,2648 /// info: ProngInfo,
2671 /// body member Index for every body_len2649 /// body member Index for every info.body_len
2672 /// }2650 /// }
2673 /// 2. scalar_cases: { // for every scalar_cases_len2651 /// 2. scalar_cases: { // for every scalar_cases_len
2674 /// item: Ref,2652 /// item: Ref,
2675 /// body_len: u32,2653 /// info: ProngInfo,
2676 /// body member Index for every body_len2654 /// body member Index for every info.body_len
2677 /// }2655 /// }
2678 /// 3. multi_cases: { // for every multi_cases_len2656 /// 3. multi_cases: { // for every multi_cases_len
2679 /// items_len: u32,2657 /// items_len: u32,
2680 /// ranges_len: u32,2658 /// ranges_len: u32,
2681 /// body_len: u32,2659 /// info: ProngInfo,
2682 /// item: Ref // for every items_len2660 /// item: Ref // for every items_len
2683 /// ranges: { // for every ranges_len2661 /// ranges: { // for every ranges_len
2684 /// item_first: Ref,2662 /// item_first: Ref,
2685 /// item_last: Ref,2663 /// item_last: Ref,
2686 /// }2664 /// }
2687 /// body member Index for every body_len2665 /// body member Index for every info.body_len
2688 /// }2666 /// }
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.
2689 pub const SwitchBlock = struct {2671 pub const SwitchBlock = struct {
2690 /// This is always a `switch_cond` or `switch_cond_ref` instruction.2672 /// This is always a `switch_cond` or `switch_cond_ref` instruction.
2691 /// If it is a `switch_cond_ref` instruction, bits.is_ref is always true.2673 /// If it is a `switch_cond_ref` instruction, bits.is_ref is always true.
...@@ -2697,6 +2679,19 @@ pub const Inst = struct {...@@ -2697,6 +2679,19 @@ pub const Inst = struct {
2697 operand: Ref,2679 operand: Ref,
2698 bits: Bits,2680 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
2700 pub const Bits = packed struct {2695 pub const Bits = packed struct {
2701 /// If true, one or more prongs have multiple items.2696 /// If true, one or more prongs have multiple items.
2702 has_multi_cases: bool,2697 has_multi_cases: bool,
...@@ -2724,64 +2719,6 @@ pub const Inst = struct {...@@ -2724,64 +2719,6 @@ pub const Inst = struct {
2724 items: []const Ref,2719 items: []const Ref,
2725 body: []const Index,2720 body: []const Index,
2726 };2721 };
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 }
2785 };2722 };
27862723
2787 pub const Field = struct {2724 pub const Field = struct {
src/print_zir.zig+27-24
...@@ -436,10 +436,6 @@ const Writer = struct {...@@ -436,10 +436,6 @@ const Writer = struct {
436436
437 .@"unreachable" => try self.writeUnreachable(stream, inst),437 .@"unreachable" => try self.writeUnreachable(stream, inst),
438438
439 .switch_capture,
440 .switch_capture_ref,
441 => try self.writeSwitchCapture(stream, inst),
442
443 .dbg_stmt => try self.writeDbgStmt(stream, inst),439 .dbg_stmt => try self.writeDbgStmt(stream, inst),
444440
445 .dbg_block_begin,441 .dbg_block_begin,
...@@ -1913,15 +1909,20 @@ const Writer = struct {...@@ -1913,15 +1909,20 @@ const Writer = struct {
1913 else => break :else_prong,1909 else => break :else_prong,
1914 };1910 };
19151911
1916 const body_len = @truncate(u31, self.code.extra[extra_index]);1912 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, self.code.extra[extra_index]);
1917 const inline_text = if (self.code.extra[extra_index] >> 31 != 0) "inline " else "";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 "";
1918 extra_index += 1;1919 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];
1920 extra_index += body.len;1921 extra_index += body.len;
19211922
1922 try stream.writeAll(",\n");1923 try stream.writeAll(",\n");
1923 try stream.writeByteNTimes(' ', self.indent);1924 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 });
1925 try self.writeBracedBody(stream, body);1926 try self.writeBracedBody(stream, body);
1926 }1927 }
19271928
...@@ -1931,15 +1932,19 @@ const Writer = struct {...@@ -1931,15 +1932,19 @@ const Writer = struct {
1931 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {1932 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
1932 const item_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);1933 const item_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
1933 extra_index += 1;1934 extra_index += 1;
1934 const body_len = @truncate(u31, self.code.extra[extra_index]);1935 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, self.code.extra[extra_index]);
1935 const is_inline = self.code.extra[extra_index] >> 31 != 0;
1936 extra_index += 1;1936 extra_index += 1;
1937 const body = self.code.extra[extra_index..][0..body_len];1937 const body = self.code.extra[extra_index..][0..info.body_len];
1938 extra_index += body_len;1938 extra_index += info.body_len;
19391939
1940 try stream.writeAll(",\n");1940 try stream.writeAll(",\n");
1941 try stream.writeByteNTimes(' ', self.indent);1941 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 ");
1943 try self.writeInstRef(stream, item_ref);1948 try self.writeInstRef(stream, item_ref);
1944 try stream.writeAll(" => ");1949 try stream.writeAll(" => ");
1945 try self.writeBracedBody(stream, body);1950 try self.writeBracedBody(stream, body);
...@@ -1952,15 +1957,19 @@ const Writer = struct {...@@ -1952,15 +1957,19 @@ const Writer = struct {
1952 extra_index += 1;1957 extra_index += 1;
1953 const ranges_len = self.code.extra[extra_index];1958 const ranges_len = self.code.extra[extra_index];
1954 extra_index += 1;1959 extra_index += 1;
1955 const body_len = @truncate(u31, self.code.extra[extra_index]);1960 const info = @bitCast(Zir.Inst.SwitchBlock.ProngInfo, self.code.extra[extra_index]);
1956 const is_inline = self.code.extra[extra_index] >> 31 != 0;
1957 extra_index += 1;1961 extra_index += 1;
1958 const items = self.code.refSlice(extra_index, items_len);1962 const items = self.code.refSlice(extra_index, items_len);
1959 extra_index += items_len;1963 extra_index += items_len;
19601964
1961 try stream.writeAll(",\n");1965 try stream.writeAll(",\n");
1962 try stream.writeByteNTimes(' ', self.indent);1966 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
1965 for (items, 0..) |item_ref, item_i| {1974 for (items, 0..) |item_ref, item_i| {
1966 if (item_i != 0) try stream.writeAll(", ");1975 if (item_i != 0) try stream.writeAll(", ");
...@@ -1982,8 +1991,8 @@ const Writer = struct {...@@ -1982,8 +1991,8 @@ const Writer = struct {
1982 try self.writeInstRef(stream, item_last);1991 try self.writeInstRef(stream, item_last);
1983 }1992 }
19841993
1985 const body = self.code.extra[extra_index..][0..body_len];1994 const body = self.code.extra[extra_index..][0..info.body_len];
1986 extra_index += body_len;1995 extra_index += info.body_len;
1987 try stream.writeAll(" => ");1996 try stream.writeAll(" => ");
1988 try self.writeBracedBody(stream, body);1997 try self.writeBracedBody(stream, body);
1989 }1998 }
...@@ -2435,12 +2444,6 @@ const Writer = struct {...@@ -2435,12 +2444,6 @@ const Writer = struct {
2435 try self.writeSrc(stream, src);2444 try self.writeSrc(stream, src);
2436 }2445 }
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
2444 fn writeDbgStmt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2447 fn writeDbgStmt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
2445 const inst_data = self.code.instructions.items(.data)[inst].dbg_stmt;2448 const inst_data = self.code.instructions.items(.data)[inst].dbg_stmt;
2446 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });2449 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });