Commit 434537213e

mlugg <mlugg@mlugg.co.uk>
2024-02-13 02:54:57
Sema: eliminate `src` field
`sema.src` is a failed experiment. It introduces complexity, and makes often unwarranted assumptions about the existence of instructions providing source locations, requiring an unreasonable amount of caution in AstGen for correctness. Eliminating it simplifies the whole frontend. This required adding source locations to a few instructions, but the cost in ZIR bytes should be counteracted by the other work on this branch.
1 parent aba29f9
src/AstGen.zig
@@ -2122,7 +2122,7 @@ fn restoreErrRetIndex(
             else => .none, // always restore/pop
         },
     };
-    _ = try gz.addRestoreErrRetIndex(bt, .{ .if_non_error = op });
+    _ = try gz.addRestoreErrRetIndex(bt, .{ .if_non_error = op }, node);
 }
 
 fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
@@ -2179,7 +2179,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
 
                     // As our last action before the break, "pop" the error trace if needed
                     if (!block_gz.is_comptime)
-                        _ = try parent_gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always);
+                        _ = try parent_gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always, node);
 
                     _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
                     return Zir.Inst.Ref.unreachable_value;
@@ -2271,7 +2271,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
 
                 // As our last action before the continue, "pop" the error trace if needed
                 if (!gen_zir.is_comptime)
-                    _ = try parent_gz.addRestoreErrRetIndex(.{ .block = continue_block }, .always);
+                    _ = try parent_gz.addRestoreErrRetIndex(.{ .block = continue_block }, .always, node);
 
                 _ = try parent_gz.addBreak(break_tag, continue_block, .void_value);
                 return Zir.Inst.Ref.unreachable_value;
@@ -2331,7 +2331,7 @@ fn blockExpr(
 
         if (!block_scope.endsWithNoReturn()) {
             // As our last action before the break, "pop" the error trace if needed
-            _ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always);
+            _ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always, block_node);
             _ = try block_scope.addBreak(.@"break", block_inst, .void_value);
         }
 
@@ -2426,7 +2426,7 @@ fn labeledBlockExpr(
     try blockExprStmts(&block_scope, &block_scope.base, statements);
     if (!block_scope.endsWithNoReturn()) {
         // As our last action before the return, "pop" the error trace if needed
-        _ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always);
+        _ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always, block_node);
         _ = try block_scope.addBreak(.@"break", block_inst, .void_value);
     }
 
@@ -2818,7 +2818,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
             .export_value,
             .set_eval_branch_quota,
             .atomic_store,
-            .store,
             .store_node,
             .store_to_inferred_ptr,
             .resolve_inferred_alloc,
@@ -2829,7 +2828,8 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
             .validate_deref,
             .validate_destructure,
             .save_err_ret_index,
-            .restore_err_ret_index,
+            .restore_err_ret_index_unconditional,
+            .restore_err_ret_index_fn_entry,
             .validate_struct_init_ty,
             .validate_struct_init_result_ty,
             .validate_ptr_struct_init,
@@ -3692,7 +3692,10 @@ fn assignOp(
         .lhs = lhs,
         .rhs = rhs,
     });
-    _ = try gz.addBin(.store, lhs_ptr, result);
+    _ = try gz.addPlNode(.store_node, infix_node, Zir.Inst.Bin{
+        .lhs = lhs_ptr,
+        .rhs = result,
+    });
 }
 
 fn assignShift(
@@ -3715,7 +3718,10 @@ fn assignShift(
         .lhs = lhs,
         .rhs = rhs,
     });
-    _ = try gz.addBin(.store, lhs_ptr, result);
+    _ = try gz.addPlNode(.store_node, infix_node, Zir.Inst.Bin{
+        .lhs = lhs_ptr,
+        .rhs = result,
+    });
 }
 
 fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!void {
@@ -3733,7 +3739,10 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE
         .lhs = lhs,
         .rhs = rhs,
     });
-    _ = try gz.addBin(.store, lhs_ptr, result);
+    _ = try gz.addPlNode(.store_node, infix_node, Zir.Inst.Bin{
+        .lhs = lhs_ptr,
+        .rhs = result,
+    });
 }
 
 fn ptrType(
@@ -4294,7 +4303,7 @@ fn fnDecl(
 
         if (!fn_gz.endsWithNoReturn()) {
             // As our last action before the return, "pop" the error trace if needed
-            _ = try gz.addRestoreErrRetIndex(.ret, .always);
+            _ = try gz.addRestoreErrRetIndex(.ret, .always, decl_node);
 
             // Add implicit return at end of function.
             _ = try fn_gz.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node));
@@ -4742,7 +4751,7 @@ fn testDecl(
     if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) {
 
         // As our last action before the return, "pop" the error trace if needed
-        _ = try gz.addRestoreErrRetIndex(.ret, .always);
+        _ = try gz.addRestoreErrRetIndex(.ret, .always, node);
 
         // Add implicit return at end of function.
         _ = try fn_block.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node));
@@ -6149,7 +6158,7 @@ fn boolBinOp(
     const node_datas = tree.nodes.items(.data);
 
     const lhs = try expr(gz, scope, bool_ri, node_datas[node].lhs);
-    const bool_br = try gz.addBoolBr(zir_tag, lhs);
+    const bool_br = (try gz.addPlNodePayloadIndex(zir_tag, node, undefined)).toIndex().?;
 
     var rhs_scope = gz.makeSubBlock(scope);
     defer rhs_scope.unstack();
@@ -6157,7 +6166,7 @@ fn boolBinOp(
     if (!gz.refIsNoReturn(rhs)) {
         _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs);
     }
-    try rhs_scope.setBoolBrBody(bool_br);
+    try rhs_scope.setBoolBrBody(bool_br, lhs);
 
     const block_ref = bool_br.toRef();
     return rvalue(gz, ri, block_ref, node);
@@ -6725,7 +6734,10 @@ fn forExpr(
         const alloc_tag: Zir.Inst.Tag = if (is_inline) .alloc_comptime_mut else .alloc;
         const index_ptr = try parent_gz.addUnNode(alloc_tag, .usize_type, node);
         // initialize to zero
-        _ = try parent_gz.addBin(.store, index_ptr, .zero_usize);
+        _ = try parent_gz.addPlNode(.store_node, node, Zir.Inst.Bin{
+            .lhs = index_ptr,
+            .rhs = .zero_usize,
+        });
         break :blk index_ptr;
     };
 
@@ -6955,7 +6967,10 @@ fn forExpr(
             .lhs = index,
             .rhs = .one_usize,
         });
-        _ = try loop_scope.addBin(.store, index_ptr, index_plus_one);
+        _ = try loop_scope.addPlNode(.store_node, node, Zir.Inst.Bin{
+            .lhs = index_ptr,
+            .rhs = index_plus_one,
+        });
         const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
         _ = try loop_scope.addNode(repeat_tag, node);
 
@@ -8008,7 +8023,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
         try genDefers(gz, defer_outer, scope, .normal_only);
 
         // As our last action before the return, "pop" the error trace if needed
-        _ = try gz.addRestoreErrRetIndex(.ret, .always);
+        _ = try gz.addRestoreErrRetIndex(.ret, .always, node);
 
         _ = try gz.addUnNode(.ret_node, .void_value, node);
         return Zir.Inst.Ref.unreachable_value;
@@ -8051,7 +8066,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
             try genDefers(gz, defer_outer, scope, .normal_only);
 
             // As our last action before the return, "pop" the error trace if needed
-            _ = try gz.addRestoreErrRetIndex(.ret, .always);
+            _ = try gz.addRestoreErrRetIndex(.ret, .always, node);
 
             try emitDbgStmt(gz, ret_lc);
             try gz.addRet(ri, operand, node);
@@ -8074,7 +8089,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
 
                 // As our last action before the return, "pop" the error trace if needed
                 const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
-                _ = try gz.addRestoreErrRetIndex(.ret, .{ .if_non_error = result });
+                _ = try gz.addRestoreErrRetIndex(.ret, .{ .if_non_error = result }, node);
 
                 try gz.addRet(ri, operand, node);
                 return Zir.Inst.Ref.unreachable_value;
@@ -8091,7 +8106,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
             try genDefers(&then_scope, defer_outer, scope, .normal_only);
 
             // As our last action before the return, "pop" the error trace if needed
-            _ = try then_scope.addRestoreErrRetIndex(.ret, .always);
+            _ = try then_scope.addRestoreErrRetIndex(.ret, .always, node);
 
             try emitDbgStmt(&then_scope, ret_lc);
             try then_scope.addRet(ri, operand, node);
@@ -10979,7 +10994,10 @@ fn rvalueInner(
             return .void_value;
         },
         .inferred_ptr => |alloc| {
-            _ = try gz.addBin(.store_to_inferred_ptr, alloc, result);
+            _ = try gz.addPlNode(.store_to_inferred_ptr, src_node, Zir.Inst.Bin{
+                .lhs = alloc,
+                .rhs = result,
+            });
             return .void_value;
         },
         .destructure => |destructure| {
@@ -11006,7 +11024,10 @@ fn rvalueInner(
                         });
                     },
                     .inferred_ptr => |ptr_inst| {
-                        _ = try gz.addBin(.store_to_inferred_ptr, ptr_inst, elem_val);
+                        _ = try gz.addPlNode(.store_to_inferred_ptr, src_node, Zir.Inst.Bin{
+                            .lhs = ptr_inst,
+                            .rhs = elem_val,
+                        });
                     },
                     .discard => unreachable,
                 }
@@ -11828,19 +11849,20 @@ const GenZir = struct {
     }
 
     /// Assumes nothing stacked on `gz`. Unstacks `gz`.
-    fn setBoolBrBody(gz: *GenZir, inst: Zir.Inst.Index) !void {
+    fn setBoolBrBody(gz: *GenZir, bool_br: Zir.Inst.Index, bool_br_lhs: Zir.Inst.Ref) !void {
         const astgen = gz.astgen;
         const gpa = astgen.gpa;
         const body = gz.instructionsSlice();
         const body_len = astgen.countBodyLenAfterFixups(body);
         try astgen.extra.ensureUnusedCapacity(
             gpa,
-            @typeInfo(Zir.Inst.Block).Struct.fields.len + body_len,
+            @typeInfo(Zir.Inst.BoolBr).Struct.fields.len + body_len,
         );
         const zir_datas = astgen.instructions.items(.data);
-        zir_datas[@intFromEnum(inst)].bool_br.payload_index = astgen.addExtraAssumeCapacity(
-            Zir.Inst.Block{ .body_len = body_len },
-        );
+        zir_datas[@intFromEnum(bool_br)].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.BoolBr{
+            .lhs = bool_br_lhs,
+            .body_len = body_len,
+        });
         astgen.appendBodyWithFixups(body);
         gz.unstack();
     }
@@ -12225,30 +12247,6 @@ const GenZir = struct {
         return new_index.toRef();
     }
 
-    /// Note that this returns a `Zir.Inst.Index` not a ref.
-    /// Leaves the `payload_index` field undefined.
-    fn addBoolBr(
-        gz: *GenZir,
-        tag: Zir.Inst.Tag,
-        lhs: Zir.Inst.Ref,
-    ) !Zir.Inst.Index {
-        assert(lhs != .none);
-        const gpa = gz.astgen.gpa;
-        try gz.instructions.ensureUnusedCapacity(gpa, 1);
-        try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
-
-        const new_index: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len);
-        gz.astgen.instructions.appendAssumeCapacity(.{
-            .tag = tag,
-            .data = .{ .bool_br = .{
-                .lhs = lhs,
-                .payload_index = undefined,
-            } },
-        });
-        gz.instructions.appendAssumeCapacity(new_index);
-        return new_index;
-    }
-
     fn addInt(gz: *GenZir, integer: u64) !Zir.Inst.Ref {
         return gz.add(.{
             .tag = .int,
@@ -12569,17 +12567,37 @@ const GenZir = struct {
             always: void,
             if_non_error: Zir.Inst.Ref,
         },
+        src_node: Ast.Node.Index,
     ) !Zir.Inst.Index {
-        return gz.addAsIndex(.{
-            .tag = .restore_err_ret_index,
-            .data = .{ .restore_err_ret_index = .{
-                .block = switch (bt) {
-                    .ret => .none,
-                    .block => |b| b.toRef(),
-                },
-                .operand = if (cond == .if_non_error) cond.if_non_error else .none,
-            } },
-        });
+        switch (cond) {
+            .always => return gz.addAsIndex(.{
+                .tag = .restore_err_ret_index_unconditional,
+                .data = .{ .un_node = .{
+                    .operand = switch (bt) {
+                        .ret => .none,
+                        .block => |b| b.toRef(),
+                    },
+                    .src_node = gz.nodeIndexToRelative(src_node),
+                } },
+            }),
+            .if_non_error => |operand| switch (bt) {
+                .ret => return gz.addAsIndex(.{
+                    .tag = .restore_err_ret_index_fn_entry,
+                    .data = .{ .un_node = .{
+                        .operand = operand,
+                        .src_node = gz.nodeIndexToRelative(src_node),
+                    } },
+                }),
+                .block => |block| return (try gz.addExtendedPayload(
+                    .restore_err_ret_index,
+                    Zir.Inst.RestoreErrRetIndex{
+                        .src_node = gz.nodeIndexToRelative(src_node),
+                        .block = block.toRef(),
+                        .operand = operand,
+                    },
+                )).toIndex().?,
+            },
+        }
     }
 
     fn addBreak(
src/Autodoc.zig
@@ -1799,7 +1799,8 @@ fn walkInstruction(
             };
         },
         .bool_br_and, .bool_br_or => {
-            const bool_br = data[@intFromEnum(inst)].bool_br;
+            const pl_node = data[@intFromEnum(inst)].pl_node;
+            const extra = file.zir.extraData(Zir.Inst.BoolBr, pl_node.payload_index);
 
             const bin_index = self.exprs.items.len;
             try self.exprs.append(self.arena, .{ .binOp = .{ .lhs = 0, .rhs = 0 } });
@@ -1808,14 +1809,13 @@ fn walkInstruction(
                 file,
                 parent_scope,
                 parent_src,
-                bool_br.lhs,
+                extra.data.lhs,
                 false,
                 call_ctx,
             );
             const lhs_index = self.exprs.items.len;
             try self.exprs.append(self.arena, lhs.expr);
 
-            const extra = file.zir.extraData(Zir.Inst.Block, bool_br.payload_index);
             const rhs = try self.walkInstruction(
                 file,
                 parent_scope,
src/print_zir.zig
@@ -199,10 +199,6 @@ const Writer = struct {
         const tag = tags[@intFromEnum(inst)];
         try stream.print("= {s}(", .{@tagName(tags[@intFromEnum(inst)])});
         switch (tag) {
-            .store,
-            .store_to_inferred_ptr,
-            => try self.writeBin(stream, inst),
-
             .alloc,
             .alloc_mut,
             .alloc_comptime_mut,
@@ -280,6 +276,8 @@ const Writer = struct {
             .validate_deref,
             .check_comptime_control_flow,
             .opt_eu_base_ptr_init,
+            .restore_err_ret_index_unconditional,
+            .restore_err_ret_index_fn_entry,
             => try self.writeUnNode(stream, inst),
 
             .ref,
@@ -303,7 +301,6 @@ const Writer = struct {
             .int_type => try self.writeIntType(stream, inst),
 
             .save_err_ret_index => try self.writeSaveErrRetIndex(stream, inst),
-            .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, inst),
 
             .@"break",
             .break_inline,
@@ -392,6 +389,7 @@ const Writer = struct {
             .shr_exact,
             .xor,
             .store_node,
+            .store_to_inferred_ptr,
             .error_union_type,
             .merge_error_sets,
             .bit_and,
@@ -615,6 +613,8 @@ const Writer = struct {
             .cmpxchg => try self.writeCmpxchg(stream, extended),
             .ptr_cast_full => try self.writePtrCastFull(stream, extended),
             .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),
+
+            .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended),
         }
     }
 
@@ -624,14 +624,6 @@ const Writer = struct {
         try self.writeSrc(stream, src);
     }
 
-    fn writeBin(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
-        const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].bin;
-        try self.writeInstRef(stream, inst_data.lhs);
-        try stream.writeAll(", ");
-        try self.writeInstRef(stream, inst_data.rhs);
-        try stream.writeByte(')');
-    }
-
     fn writeArrayInitElemType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
         const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].bin;
         try self.writeInstRef(stream, inst_data.lhs);
@@ -2505,12 +2497,14 @@ const Writer = struct {
     }
 
     fn writeBoolBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
-        const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].bool_br;
-        const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);
+        const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
+        const extra = self.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index);
         const body = self.code.bodySlice(extra.end, extra.data.body_len);
-        try self.writeInstRef(stream, inst_data.lhs);
+        try self.writeInstRef(stream, extra.data.lhs);
         try stream.writeAll(", ");
         try self.writeBracedBody(stream, body);
+        try stream.writeAll(") ");
+        try self.writeSrc(stream, inst_data.src());
     }
 
     fn writeIntType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
@@ -2531,13 +2525,14 @@ const Writer = struct {
         try stream.writeAll(")");
     }
 
-    fn writeRestoreErrRetIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
-        const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].restore_err_ret_index;
+    fn writeRestoreErrRetIndex(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
+        const extra = self.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data;
 
-        try self.writeInstRef(stream, inst_data.block);
-        try self.writeInstRef(stream, inst_data.operand);
+        try self.writeInstRef(stream, extra.block);
+        try self.writeInstRef(stream, extra.operand);
 
-        try stream.writeAll(")");
+        try stream.writeAll(") ");
+        try self.writeSrc(stream, extra.src());
     }
 
     fn writeBreak(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
src/Sema.zig
@@ -50,11 +50,6 @@ branch_count: u32 = 0,
 /// Populated when returning `error.ComptimeBreak`. Used to communicate the
 /// break instruction up the stack to find the corresponding Block.
 comptime_break_inst: Zir.Inst.Index = undefined,
-/// This field is updated when a new source location becomes active, so that
-/// instructions which do not have explicitly mapped source locations still have
-/// access to the source location set by the previous instruction which did
-/// contain a mapped source location.
-src: LazySrcLoc = .{ .token_offset = 0 },
 decl_val_table: std.AutoHashMapUnmanaged(InternPool.DeclIndex, Air.Inst.Ref) = .{},
 /// When doing a generic function instantiation, this array collects a value
 /// for each parameter of the generic owner. `none` for non-comptime parameters.
@@ -1006,10 +1001,10 @@ fn analyzeBodyInner(
         const air_inst: Air.Inst.Ref = switch (tags[@intFromEnum(inst)]) {
             // zig fmt: off
             .alloc                        => try sema.zirAlloc(block, inst),
-            .alloc_inferred               => try sema.zirAllocInferred(block, inst, true),
-            .alloc_inferred_mut           => try sema.zirAllocInferred(block, inst, false),
-            .alloc_inferred_comptime      => try sema.zirAllocInferredComptime(inst, true),
-            .alloc_inferred_comptime_mut  => try sema.zirAllocInferredComptime(inst, false),
+            .alloc_inferred               => try sema.zirAllocInferred(block, true),
+            .alloc_inferred_mut           => try sema.zirAllocInferred(block, false),
+            .alloc_inferred_comptime      => try sema.zirAllocInferredComptime(true),
+            .alloc_inferred_comptime_mut  => try sema.zirAllocInferredComptime(false),
             .alloc_mut                    => try sema.zirAllocMut(block, inst),
             .alloc_comptime_mut           => try sema.zirAllocComptime(block, inst),
             .make_ptr_const               => try sema.zirMakePtrConst(block, inst),
@@ -1308,6 +1303,11 @@ fn analyzeBodyInner(
                         i += 1;
                         continue;
                     },
+                    .restore_err_ret_index => {
+                        try sema.zirRestoreErrRetIndex(block, extended);
+                        i += 1;
+                        continue;
+                    },
                     .value_placeholder => unreachable, // never appears in a body
                 };
             },
@@ -1369,11 +1369,6 @@ fn analyzeBodyInner(
                 i += 1;
                 continue;
             },
-            .store => {
-                try sema.zirStore(block, inst);
-                i += 1;
-                continue;
-            },
             .store_node => {
                 try sema.zirStoreNode(block, inst);
                 i += 1;
@@ -1518,8 +1513,15 @@ fn analyzeBodyInner(
                 i += 1;
                 continue;
             },
-            .restore_err_ret_index => {
-                try sema.zirRestoreErrRetIndex(block, inst);
+            .restore_err_ret_index_unconditional => {
+                const un_node = datas[@intFromEnum(inst)].un_node;
+                try sema.restoreErrRetIndex(block, un_node.src(), un_node.operand, .none);
+                i += 1;
+                continue;
+            },
+            .restore_err_ret_index_fn_entry => {
+                const un_node = datas[@intFromEnum(inst)].un_node;
+                try sema.restoreErrRetIndex(block, un_node.src(), .none, un_node.operand);
                 i += 1;
                 continue;
             },
@@ -2779,7 +2781,7 @@ fn zirStructDecl(
     const src: LazySrcLoc = if (small.has_src_node) blk: {
         const node_offset: i32 = @bitCast(sema.code.extra[extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len]);
         break :blk LazySrcLoc.nodeOffset(node_offset);
-    } else sema.src;
+    } else unreachable; // MLUGG TODO
 
     // Because these three things each reference each other, `undefined`
     // placeholders are used before being set after the struct type gains an
@@ -2945,7 +2947,7 @@ fn zirEnumDecl(
         const node_offset: i32 = @bitCast(sema.code.extra[extra_index]);
         extra_index += 1;
         break :blk LazySrcLoc.nodeOffset(node_offset);
-    } else sema.src;
+    } else unreachable; // MLUGG TODO
     const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x };
 
     const tag_type_ref = if (small.has_tag_type) blk: {
@@ -3218,7 +3220,7 @@ fn zirUnionDecl(
         const node_offset: i32 = @bitCast(sema.code.extra[extra_index]);
         extra_index += 1;
         break :blk LazySrcLoc.nodeOffset(node_offset);
-    } else sema.src;
+    } else unreachable; // MLUGG TODO
 
     extra_index += @intFromBool(small.has_tag_type);
     extra_index += @intFromBool(small.has_body_len);
@@ -3327,7 +3329,7 @@ fn zirOpaqueDecl(
         const node_offset: i32 = @bitCast(sema.code.extra[extra_index]);
         extra_index += 1;
         break :blk LazySrcLoc.nodeOffset(node_offset);
-    } else sema.src;
+    } else unreachable; // MLUGG TODO
 
     const decls_len = if (small.has_decls_len) blk: {
         const decls_len = sema.code.extra[extra_index];
@@ -3977,13 +3979,9 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai
 
 fn zirAllocInferredComptime(
     sema: *Sema,
-    inst: Zir.Inst.Index,
     is_const: bool,
 ) CompileError!Air.Inst.Ref {
     const gpa = sema.gpa;
-    const src_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].node;
-    const src = LazySrcLoc.nodeOffset(src_node);
-    sema.src = src;
 
     try sema.air_instructions.append(gpa, .{
         .tag = .inferred_alloc_comptime,
@@ -4042,16 +4040,12 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
 fn zirAllocInferred(
     sema: *Sema,
     block: *Block,
-    inst: Zir.Inst.Index,
     is_const: bool,
 ) CompileError!Air.Inst.Ref {
     const tracy = trace(@src());
     defer tracy.end();
 
     const gpa = sema.gpa;
-    const src_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].node;
-    const src = LazySrcLoc.nodeOffset(src_node);
-    sema.src = src;
 
     if (block.is_comptime) {
         try sema.air_instructions.append(gpa, .{
@@ -5428,10 +5422,11 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
     const tracy = trace(@src());
     defer tracy.end();
 
-    const src: LazySrcLoc = sema.src;
-    const bin_inst = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin;
-    const ptr = try sema.resolveInst(bin_inst.lhs);
-    const operand = try sema.resolveInst(bin_inst.rhs);
+    const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
+    const src = pl_node.src();
+    const bin = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data;
+    const ptr = try sema.resolveInst(bin.lhs);
+    const operand = try sema.resolveInst(bin.rhs);
     const ptr_inst = ptr.toIndex().?;
     const air_datas = sema.air_instructions.items(.data);
 
@@ -5496,16 +5491,6 @@ fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
     sema.branch_quota = @max(sema.branch_quota, quota);
 }
 
-fn zirStore(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
-    const tracy = trace(@src());
-    defer tracy.end();
-
-    const bin_inst = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin;
-    const ptr = try sema.resolveInst(bin_inst.lhs);
-    const value = try sema.resolveInst(bin_inst.rhs);
-    return sema.storePtr(block, sema.src, ptr, value);
-}
-
 fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
     const tracy = trace(@src());
     defer tracy.end();
@@ -5709,7 +5694,6 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.I
 fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
     const src_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].node;
     const src = LazySrcLoc.nodeOffset(src_node);
-    sema.src = src;
     if (block.is_comptime)
         return sema.fail(block, src, "encountered @trap at comptime", .{});
     _ = try block.addNoOp(.trap);
@@ -6384,10 +6368,6 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError
 }
 
 fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
-    // We do not set sema.src here because dbg_stmt instructions are only emitted for
-    // ZIR code that possibly will need to generate runtime code. So error messages
-    // and other source locations must not rely on sema.src being set from dbg_stmt
-    // instructions.
     if (block.is_comptime or block.ownerModule().strip) return;
 
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
@@ -6632,7 +6612,6 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
 pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {
     const mod = sema.mod;
     const gpa = sema.gpa;
-    const src = sema.src;
 
     if (block.is_comptime or block.is_typeof) {
         const index_val = try mod.intValue_u64(Type.usize, sema.comptime_err_ret_trace.items.len);
@@ -6650,9 +6629,10 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
         else => |e| return e,
     };
     const field_name = try mod.intern_pool.getOrPutString(gpa, "index");
-    const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, src) catch |err| switch (err) {
-        error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
-        else => |e| return e,
+    const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, .unneeded) catch |err| switch (err) {
+        error.AnalysisFail, error.NeededSourceLocation => @panic("std.builtin.StackTrace is corrupt"),
+        error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
+        error.OutOfMemory => |e| return e,
     };
 
     return try block.addInst(.{
@@ -9900,7 +9880,6 @@ fn zirAsNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src = inst_data.src();
     const extra = sema.code.extraData(Zir.Inst.As, inst_data.payload_index).data;
-    sema.src = src;
     return sema.analyzeAs(block, src, extra.dest_type, extra.operand, false);
 }
 
@@ -10855,7 +10834,7 @@ const SwitchProngAnalysis = struct {
                             .address_space = operand_ptr_ty.ptrAddressSpace(mod),
                         },
                     });
-                    if (try sema.resolveDefinedValue(block, sema.src, spa.operand_ptr)) |union_ptr| {
+                    if (try sema.resolveDefinedValue(block, operand_src, spa.operand_ptr)) |union_ptr| {
                         return Air.internedToRef((try mod.intern(.{ .ptr = .{
                             .ty = ptr_field_ty.toIntern(),
                             .addr = .{ .field = .{
@@ -10866,7 +10845,7 @@ const SwitchProngAnalysis = struct {
                     }
                     return block.addStructFieldPtr(spa.operand_ptr, field_index, ptr_field_ty);
                 } else {
-                    if (try sema.resolveDefinedValue(block, sema.src, spa.operand)) |union_val| {
+                    if (try sema.resolveDefinedValue(block, operand_src, spa.operand)) |union_val| {
                         const tag_and_val = ip.indexToKey(union_val.toIntern()).un;
                         return Air.internedToRef(tag_and_val.val);
                     }
@@ -13191,6 +13170,7 @@ fn validateErrSetSwitch(
                 // else => |e| return e,
                 // even if all the possible errors were already handled.
                 const tags = sema.code.instructions.items(.tag);
+                const datas = sema.code.instructions.items(.data);
                 for (else_case.body) |else_inst| switch (tags[@intFromEnum(else_inst)]) {
                     .dbg_block_begin,
                     .dbg_block_end,
@@ -13205,11 +13185,16 @@ fn validateErrSetSwitch(
                     .err_union_code,
                     .ret_err_value_code,
                     .save_err_ret_index,
-                    .restore_err_ret_index,
+                    .restore_err_ret_index_unconditional,
+                    .restore_err_ret_index_fn_entry,
                     .is_non_err,
                     .ret_is_non_err,
                     .condbr,
                     => {},
+                    .extended => switch (datas[@intFromEnum(else_inst)].extended.opcode) {
+                        .restore_err_ret_index => {},
+                        else => break,
+                    },
                     else => break,
                 } else break :else_validation;
 
@@ -13707,7 +13692,6 @@ fn zirShl(
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src = inst_data.src();
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -13878,7 +13862,6 @@ fn zirShr(
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src = inst_data.src();
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -14014,7 +13997,6 @@ fn zirBitwise(
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -14795,21 +14777,20 @@ fn zirArithmetic(
     defer tracy.end();
 
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
-    sema.src = .{ .node_offset_bin_op = inst_data.src_node };
+    const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
     const lhs = try sema.resolveInst(extra.lhs);
     const rhs = try sema.resolveInst(extra.rhs);
 
-    return sema.analyzeArithmetic(block, zir_tag, lhs, rhs, sema.src, lhs_src, rhs_src, safety);
+    return sema.analyzeArithmetic(block, zir_tag, lhs, rhs, src, lhs_src, rhs_src, safety);
 }
 
 fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -14975,7 +14956,6 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -15141,7 +15121,6 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -15252,7 +15231,6 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -15494,7 +15472,6 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -15679,7 +15656,6 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -15775,7 +15751,6 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -18741,13 +18716,16 @@ fn zirBoolBr(
     defer tracy.end();
 
     const mod = sema.mod;
+    const gpa = sema.gpa;
+
     const datas = sema.code.instructions.items(.data);
-    const inst_data = datas[@intFromEnum(inst)].bool_br;
-    const lhs = try sema.resolveInst(inst_data.lhs);
-    const lhs_src = sema.src;
-    const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
+    const inst_data = datas[@intFromEnum(inst)].pl_node;
+    const extra = sema.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index);
+
+    const lhs = try sema.resolveInst(extra.data.lhs);
     const body = sema.code.bodySlice(extra.end, extra.data.body_len);
-    const gpa = sema.gpa;
+    const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
+    const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
 
     if (try sema.resolveDefinedValue(parent_block, lhs_src, lhs)) |lhs_val| {
         if (is_bool_or and lhs_val.toBool()) {
@@ -18795,7 +18773,7 @@ fn zirBoolBr(
 
     const result = sema.finishCondBr(parent_block, &child_block, &then_block, &else_block, lhs, block_inst);
     if (!sema.typeOf(rhs_result).isNoReturn(mod)) {
-        if (try sema.resolveDefinedValue(rhs_block, sema.src, rhs_result)) |rhs_val| {
+        if (try sema.resolveDefinedValue(rhs_block, rhs_src, rhs_result)) |rhs_val| {
             if (is_bool_or and rhs_val.toBool()) {
                 return .bool_true;
             } else if (!is_bool_or and !rhs_val.toBool()) {
@@ -19375,17 +19353,21 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
         block.error_return_trace_index = try sema.analyzeSaveErrRetIndex(block);
 }
 
-fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!void {
-    const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].restore_err_ret_index;
-    const src = sema.src; // TODO
-
-    const mod = sema.mod;
-    const ip = &mod.intern_pool;
+fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
+    const extra = sema.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data;
+    return sema.restoreErrRetIndex(start_block, extra.src(), extra.block, extra.operand);
+}
 
+/// If `operand` is non-error (or is `none`), restores the error return trace to
+/// its state at the point `block` was reached (or, if `block` is `none`, the
+/// point this function began execution).
+fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_block: Zir.Inst.Ref, operand_zir: Zir.Inst.Ref) CompileError!void {
     const tracy = trace(@src());
     defer tracy.end();
 
-    const saved_index = if (inst_data.block.toIndexAllowNone()) |zir_block| b: {
+    const mod = sema.mod;
+
+    const saved_index = if (target_block.toIndexAllowNone()) |zir_block| b: {
         var block = start_block;
         while (true) {
             if (block.label) |label| {
@@ -19409,7 +19391,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
         return; // No need to restore
     };
 
-    const operand = try sema.resolveInstAllowNone(inst_data.operand);
+    const operand = try sema.resolveInstAllowNone(operand_zir);
 
     if (start_block.is_comptime or start_block.is_typeof) {
         const is_non_error = if (operand != .none) blk: {
@@ -19427,7 +19409,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
         return;
     }
 
-    if (!ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) return;
+    if (!mod.intern_pool.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) return;
     if (!start_block.ownerModule().error_tracing) return;
 
     assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere
@@ -23161,7 +23143,6 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
 fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 {
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
-    sema.src = src;
     const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
     const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -26416,12 +26397,16 @@ fn preparePanicId(sema: *Sema, block: *Block, panic_id: Module.PanicId) !InternP
     try sema.prepareSimplePanic(block);
 
     const panic_messages_ty = try sema.getBuiltinType("panic_messages");
-    const msg_decl_index = (try sema.namespaceLookup(
+    const msg_decl_index = (sema.namespaceLookup(
         block,
-        sema.src,
+        .unneeded,
         panic_messages_ty.getNamespaceIndex(mod).unwrap().?,
         try mod.intern_pool.getOrPutString(gpa, @tagName(panic_id)),
-    )).?;
+    ) catch |err| switch (err) {
+        error.AnalysisFail, error.NeededSourceLocation => @panic("std.builtin.panic_messages is corrupt"),
+        error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
+        error.OutOfMemory => |e| return e,
+    }).?;
     try sema.ensureDeclAnalyzed(msg_decl_index);
     mod.panic_messages[@intFromEnum(panic_id)] = msg_decl_index.toOptional();
     return msg_decl_index;
src/Zir.zig
@@ -303,11 +303,11 @@ pub const Inst = struct {
         bool_not,
         /// Short-circuiting boolean `and`. `lhs` is a boolean `Ref` and the other operand
         /// is a block, which is evaluated if `lhs` is `true`.
-        /// Uses the `bool_br` union field.
+        /// Uses the `pl_node` union field. Payload is `BoolBr`.
         bool_br_and,
         /// Short-circuiting boolean `or`. `lhs` is a boolean `Ref` and the other operand
         /// is a block, which is evaluated if `lhs` is `false`.
-        /// Uses the `bool_br` union field.
+        /// Uses the `pl_node` union field. Payload is `BoolBr`.
         bool_br_or,
         /// Return a value from a block.
         /// Uses the `break` union field.
@@ -592,16 +592,12 @@ pub const Inst = struct {
         /// Returns a pointer to the subslice.
         /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceLength`.
         slice_length,
-        /// Write a value to a pointer. For loading, see `load`.
-        /// Source location is assumed to be same as previous instruction.
-        /// Uses the `bin` union field.
-        store,
         /// Same as `store` except provides a source location.
         /// Uses the `pl_node` union field. Payload is `Bin`.
         store_node,
-        /// Same as `store` but the type of the value being stored will be used to infer
-        /// the pointer type.
-        /// Uses the `bin` union field.
+        /// Same as `store_node` but the type of the value being stored will be
+        /// used to infer the pointer type of an `alloc_inferred`.
+        /// Uses the `pl_node` union field. Payload is `Bin`.
         store_to_inferred_ptr,
         /// String Literal. Makes an anonymous Decl and then takes a pointer to it.
         /// Uses the `str` union field.
@@ -1036,10 +1032,18 @@ pub const Inst = struct {
         /// block, if the operand is .none or of an error/error-union type.
         /// Uses the `save_err_ret_index` field.
         save_err_ret_index,
-        /// Sets error return trace to zero if no operand is given,
-        /// otherwise sets the value to the given amount.
-        /// Uses the `restore_err_ret_index` union field.
-        restore_err_ret_index,
+        /// Specialized form of `Extended.restore_err_ret_index`.
+        /// Unconditionally restores the error return index to its last saved state
+        /// in the block referred to by `operand`. If `operand` is `none`, restores
+        /// to the point of function entry.
+        /// Uses the `un_node` field.
+        restore_err_ret_index_unconditional,
+        /// Specialized form of `Extended.restore_err_ret_index`.
+        /// Restores the error return index to its state at the entry of
+        /// the current function conditional on `operand` being a non-error.
+        /// If `operand` is `none`, restores unconditionally.
+        /// Uses the `un_node` field.
+        restore_err_ret_index_fn_entry,
 
         /// The ZIR instruction tag is one of the `Extended` ones.
         /// Uses the `extended` union field.
@@ -1145,7 +1149,6 @@ pub const Inst = struct {
                 .shl,
                 .shl_sat,
                 .shr,
-                .store,
                 .store_node,
                 .store_to_inferred_ptr,
                 .str,
@@ -1265,7 +1268,6 @@ pub const Inst = struct {
                 .@"defer",
                 .defer_err_code,
                 .save_err_ret_index,
-                .restore_err_ret_index,
                 .for_len,
                 .opt_eu_base_ptr_init,
                 .coerce_ptr_elem_ty,
@@ -1290,6 +1292,8 @@ pub const Inst = struct {
                 .array_init_elem_type,
                 .array_init_elem_ptr,
                 .validate_ref_ty,
+                .restore_err_ret_index_unconditional,
+                .restore_err_ret_index_fn_entry,
                 => false,
 
                 .@"break",
@@ -1338,7 +1342,6 @@ pub const Inst = struct {
                 .ensure_err_union_payload_void,
                 .set_eval_branch_quota,
                 .atomic_store,
-                .store,
                 .store_node,
                 .store_to_inferred_ptr,
                 .resolve_inferred_alloc,
@@ -1352,8 +1355,9 @@ pub const Inst = struct {
                 .check_comptime_control_flow,
                 .@"defer",
                 .defer_err_code,
-                .restore_err_ret_index,
                 .save_err_ret_index,
+                .restore_err_ret_index_unconditional,
+                .restore_err_ret_index_fn_entry,
                 .validate_struct_init_ty,
                 .validate_struct_init_result_ty,
                 .validate_ptr_struct_init,
@@ -1635,8 +1639,8 @@ pub const Inst = struct {
                 .declaration = .pl_node,
                 .suspend_block = .pl_node,
                 .bool_not = .un_node,
-                .bool_br_and = .bool_br,
-                .bool_br_or = .bool_br,
+                .bool_br_and = .pl_node,
+                .bool_br_or = .pl_node,
                 .@"break" = .@"break",
                 .break_inline = .@"break",
                 .check_comptime_control_flow = .un_node,
@@ -1713,9 +1717,8 @@ pub const Inst = struct {
                 .slice_end = .pl_node,
                 .slice_sentinel = .pl_node,
                 .slice_length = .pl_node,
-                .store = .bin,
                 .store_node = .pl_node,
-                .store_to_inferred_ptr = .bin,
+                .store_to_inferred_ptr = .pl_node,
                 .str = .str,
                 .negate = .un_node,
                 .negate_wrap = .un_node,
@@ -1845,7 +1848,8 @@ pub const Inst = struct {
                 .defer_err_code = .defer_err_code,
 
                 .save_err_ret_index = .save_err_ret_index,
-                .restore_err_ret_index = .restore_err_ret_index,
+                .restore_err_ret_index_unconditional = .un_node,
+                .restore_err_ret_index_fn_entry = .un_node,
 
                 .struct_init_empty = .un_node,
                 .struct_init_empty_result = .un_node,
@@ -2075,6 +2079,13 @@ pub const Inst = struct {
         /// Implements the `@inComptime` builtin.
         /// `operand` is `src_node: i32`.
         in_comptime,
+        /// Restores the error return index to its last saved state in a given
+        /// block. If the block is `.none`, restores to the state from the point
+        /// of function entry. If the operand is not `.none`, the restore is
+        /// conditional on the operand value not being an error.
+        /// `operand` is payload index to `RestoreErrRetIndex`.
+        /// `small` is undefined.
+        restore_err_ret_index,
         /// Used as a placeholder instruction which is just a dummy index for Sema to replace
         /// with a specific value. For instance, this is used for the capture of an `errdefer`.
         /// This should never appear in a body.
@@ -2345,11 +2356,6 @@ pub const Inst = struct {
                 return LazySrcLoc.nodeOffset(self.src_node);
             }
         },
-        bool_br: struct {
-            lhs: Ref,
-            /// Points to a `Block`.
-            payload_index: u32,
-        },
         @"unreachable": struct {
             /// Offset from Decl AST node index.
             /// `Tag` determines which kind of AST node this points to.
@@ -2396,10 +2402,6 @@ pub const Inst = struct {
         save_err_ret_index: struct {
             operand: Ref, // If error type (or .none), save new trace index
         },
-        restore_err_ret_index: struct {
-            block: Ref, // If restored, the index is from this block's entrypoint
-            operand: Ref, // If non-error (or .none), then restore the index
-        },
         elem_val_imm: struct {
             /// The indexable value being accessed.
             operand: Ref,
@@ -2435,7 +2437,6 @@ pub const Inst = struct {
             float,
             ptr_type,
             int_type,
-            bool_br,
             @"unreachable",
             @"break",
             dbg_stmt,
@@ -2444,7 +2445,6 @@ pub const Inst = struct {
             @"defer",
             defer_err_code,
             save_err_ret_index,
-            restore_err_ret_index,
             elem_val_imm,
         };
     };
@@ -2630,6 +2630,13 @@ pub const Inst = struct {
         body_len: u32,
     };
 
+    /// Trailing:
+    /// * inst: Index // for each `body_len`
+    pub const BoolBr = struct {
+        lhs: Ref,
+        body_len: u32,
+    };
+
     /// Trailing:
     /// 0. doc_comment: u32          // if `has_doc_comment`; null-terminated string index
     /// 1. align_body_len: u32       // if `has_align_linksection_addrspace`; 0 means no `align`
@@ -3439,6 +3446,18 @@ pub const Inst = struct {
         /// The RHS of the array multiplication.
         rhs: Ref,
     };
+
+    pub const RestoreErrRetIndex = struct {
+        src_node: i32,
+        /// If `.none`, restore the trace to its state upon function entry.
+        block: Ref,
+        /// If `.none`, restore unconditionally.
+        operand: Ref,
+
+        pub fn src(self: RestoreErrRetIndex) LazySrcLoc {
+            return LazySrcLoc.nodeOffset(self.src_node);
+        }
+    };
 };
 
 pub const SpecialProng = enum { none, @"else", under };