diff --git a/src/AstGen.zig b/src/AstGen.zig index 87891046b64d..3909e95f771c 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -2610,8 +2610,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As .slice_length, .import, .switch_block, - .switch_cond, - .switch_cond_ref, + .switch_block_ref, .struct_init_empty, .struct_init, .struct_init_ref, @@ -6819,10 +6818,6 @@ fn switchExpr( const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column }; const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node); - const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond; - const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node); - // Sema expects a dbg_stmt immediately after switch_cond(_ref) - try emitDbgStmt(parent_gz, operand_lc); const item_ri: ResultInfo = .{ .rl = .none }; // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti, @@ -6842,8 +6837,11 @@ fn switchExpr( block_scope.instructions_top = GenZir.unstacked_top; block_scope.setBreakResultInfo(ri); + // Sema expects a dbg_stmt immediately before switch_block(_ref) + try emitDbgStmt(parent_gz, operand_lc); // This gets added to the parent block later, after the item expressions. - const switch_block = try parent_gz.makeBlockInst(.switch_block, switch_node); + const switch_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_block_ref else .switch_block; + const switch_block = try parent_gz.makeBlockInst(switch_tag, switch_node); // We re-use this same scope for all cases, including the special prong, if any. var case_scope = parent_gz.makeSubBlock(&block_scope.base); @@ -7060,7 +7058,7 @@ fn switchExpr( payloads.items.len - case_table_end); const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.SwitchBlock{ - .operand = cond, + .operand = raw_operand, .bits = Zir.Inst.SwitchBlock.Bits{ .has_multi_cases = multi_cases_len != 0, .has_else = special_prong == .@"else", diff --git a/src/Autodoc.zig b/src/Autodoc.zig index afb5bc6704be..b739a63fec2a 100644 --- a/src/Autodoc.zig +++ b/src/Autodoc.zig @@ -1992,31 +1992,6 @@ fn walkInstruction( .expr = .{ .switchIndex = switch_index }, }; }, - .switch_cond => { - const un_node = data[inst_index].un_node; - const operand = try self.walkRef( - file, - parent_scope, - parent_src, - un_node.operand, - need_type, - ); - const operand_index = self.exprs.items.len; - try self.exprs.append(self.arena, operand.expr); - - // const ast_index = self.ast_nodes.items.len; - // const sep = "=" ** 200; - // log.debug("{s}", .{sep}); - // log.debug("SWITCH COND", .{}); - // log.debug("ast index = {}", .{ast_index}); - // log.debug("ast previous = {}", .{self.ast_nodes.items[ast_index - 1]}); - // log.debug("{s}", .{sep}); - - return DocData.WalkResult{ - .typeRef = operand.typeRef, - .expr = .{ .typeOf = operand_index }, - }; - }, .typeof => { const un_node = data[inst_index].un_node; diff --git a/src/Sema.zig b/src/Sema.zig index bc77e7ee3752..c34e11a7eede 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -979,9 +979,8 @@ fn analyzeBodyInner( .slice_start => try sema.zirSliceStart(block, inst), .slice_length => try sema.zirSliceLength(block, inst), .str => try sema.zirStr(block, inst), - .switch_block => try sema.zirSwitchBlock(block, inst), - .switch_cond => try sema.zirSwitchCond(block, inst, false), - .switch_cond_ref => try sema.zirSwitchCond(block, inst, true), + .switch_block => try sema.zirSwitchBlock(block, inst, false), + .switch_block_ref => try sema.zirSwitchBlock(block, inst, true), .type_info => try sema.zirTypeInfo(block, inst), .size_of => try sema.zirSizeOf(block, inst), .bit_size_of => try sema.zirBitSizeOf(block, inst), @@ -10384,22 +10383,13 @@ const SwitchProngAnalysis = struct { } }; -fn zirSwitchCond( +fn switchCond( sema: *Sema, block: *Block, - inst: Zir.Inst.Index, - is_ref: bool, + src: LazySrcLoc, + operand: Air.Inst.Ref, ) CompileError!Air.Inst.Ref { - const inst_data = sema.code.instructions.items(.data)[inst].un_node; - const src = inst_data.src(); - const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = inst_data.src_node }; - const operand_ptr = try sema.resolveInst(inst_data.operand); - const operand = if (is_ref) - try sema.analyzeLoad(block, src, operand_ptr, operand_src) - else - operand_ptr; const operand_ty = sema.typeOf(operand); - switch (operand_ty.zigTypeTag()) { .Type, .Void, @@ -10456,7 +10446,7 @@ fn zirSwitchCond( const SwitchErrorSet = std.StringHashMap(Module.SwitchProngSrc); -fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_ref: bool) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -10468,10 +10458,21 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const special_prong_src: LazySrcLoc = .{ .node_offset_switch_special_prong = src_node_offset }; const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index); - const operand = try sema.resolveInst(extra.data.operand); - // AstGen guarantees that the instruction immediately following - // switch_cond(_ref) is a dbg_stmt - const cond_dbg_node_index = Zir.refToIndex(extra.data.operand).? + 1; + const raw_operand: struct { val: Air.Inst.Ref, ptr: Air.Inst.Ref } = blk: { + const maybe_ptr = try sema.resolveInst(extra.data.operand); + if (operand_is_ref) { + const val = try sema.analyzeLoad(block, src, maybe_ptr, operand_src); + break :blk .{ .val = val, .ptr = maybe_ptr }; + } else { + break :blk .{ .val = maybe_ptr, .ptr = undefined }; + } + }; + + const operand = try sema.switchCond(block, src, raw_operand.val); + + // AstGen guarantees that the instruction immediately preceding + // switch_block(_ref) is a dbg_stmt + const cond_dbg_node_index = inst - 1; var header_extra_index: usize = extra.end; @@ -10525,19 +10526,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError }, }; - const raw_operand: struct { val: Air.Inst.Ref, ptr: Air.Inst.Ref } = blk: { - const zir_tags = sema.code.instructions.items(.tag); - const zir_data = sema.code.instructions.items(.data); - const cond_index = Zir.refToIndex(extra.data.operand).?; - const raw = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable; - if (zir_tags[cond_index] == .switch_cond_ref) { - const val = try sema.analyzeLoad(block, src, raw, operand_src); - break :blk .{ .val = val, .ptr = raw }; - } else { - break :blk .{ .val = raw, .ptr = undefined }; - } - }; - const maybe_union_ty = sema.typeOf(raw_operand.val); const union_originally = maybe_union_ty.zigTypeTag() == .Union; diff --git a/src/Zir.zig b/src/Zir.zig index 556e0f8f2535..e965cfe257e3 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -666,15 +666,9 @@ pub const Inst = struct { /// A switch expression. Uses the `pl_node` union field. /// AST node is the switch, payload is `SwitchBlock`. switch_block, - /// Produces the value that will be switched on. For example, for - /// integers, it returns the integer with no modifications. For tagged unions, it - /// returns the active enum tag. - /// Uses the `un_node` union field. - switch_cond, - /// Same as `switch_cond`, except the input operand is a pointer to - /// what will be switched on. - /// Uses the `un_node` union field. - switch_cond_ref, + /// A switch expression. Uses the `pl_node` union field. + /// AST node is the switch, payload is `SwitchBlock`. Operand is a pointer. + switch_block_ref, /// Given a /// *A returns *A /// *E!A returns *A @@ -1121,8 +1115,7 @@ pub const Inst = struct { .resolve_inferred_alloc, .set_eval_branch_quota, .switch_block, - .switch_cond, - .switch_cond_ref, + .switch_block_ref, .array_base_ptr, .field_base_ptr, .validate_array_init_ty, @@ -1410,8 +1403,7 @@ pub const Inst = struct { .import, .typeof_log2_int_type, .switch_block, - .switch_cond, - .switch_cond_ref, + .switch_block_ref, .array_base_ptr, .field_base_ptr, .struct_init_empty, @@ -1662,8 +1654,7 @@ pub const Inst = struct { .err_union_code_ptr = .un_node, .enum_literal = .str_tok, .switch_block = .pl_node, - .switch_cond = .un_node, - .switch_cond_ref = .un_node, + .switch_block_ref = .pl_node, .array_base_ptr = .un_node, .field_base_ptr = .un_node, .validate_array_init_ty = .pl_node, @@ -3009,13 +3000,10 @@ pub const Inst = struct { /// captured payload. Whether this is captured by reference or by value /// depends on whether the `byref` bit is set for the corresponding body. pub const SwitchBlock = struct { - /// This is always a `switch_cond` or `switch_cond_ref` instruction. - /// If it is a `switch_cond_ref` instruction, bits.is_ref is always true. - /// If it is a `switch_cond` instruction, bits.is_ref is always false. - /// Both `switch_cond` and `switch_cond_ref` return a value, not a pointer, - /// that is useful for the case items, but cannot be used for capture values. - /// For the capture values, Sema is expected to find the operand of this operand - /// and use that. + /// The operand passed to the `switch` expression. If this is a + /// `switch_block`, this is the operand value; if `switch_block_ref` it + /// is a pointer to the operand. `switch_block_ref` is always used if + /// any prong has a byref capture. operand: Ref, bits: Bits, diff --git a/src/print_zir.zig b/src/print_zir.zig index 221dbed662c4..d488d6235fdc 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -221,8 +221,6 @@ const Writer = struct { .bit_reverse, .@"resume", .@"await", - .switch_cond, - .switch_cond_ref, .array_base_ptr, .field_base_ptr, .validate_struct_init_ty, @@ -387,7 +385,9 @@ const Writer = struct { .error_set_decl_anon => try self.writeErrorSetDecl(stream, inst, .anon), .error_set_decl_func => try self.writeErrorSetDecl(stream, inst, .func), - .switch_block => try self.writeSwitchBlock(stream, inst), + .switch_block, + .switch_block_ref, + => try self.writeSwitchBlock(stream, inst), .field_ptr, .field_ptr_init,