authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-21 20:24:37-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-10-21 20:24:37-07:00
log09236d29b7722d71533478aa7080706acde28d0d
treed1c5776cf14fc9f579e7fb5ce99de9a015e80eac
parentb9103bd514e46a43ab0f3dce397af2ea8a789fda
parentc36a2c27a51039d486f4149018154687a300d1eb
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12837 from topolarity/err-ret-trace-improvements-1923

stage2: Pop error trace frames for handled errors (#1923)

23 files changed, 2089 insertions(+), 863 deletions(-)

lib/std/builtin.zig+4-2
......@@ -869,8 +869,10 @@ pub noinline fn returnError(st: *StackTrace) void {
869869}
870870
871871pub inline fn addErrRetTraceAddr(st: *StackTrace, addr: usize) void {
872 st.instruction_addresses[st.index & (st.instruction_addresses.len - 1)] = addr;
873 st.index +%= 1;
872 if (st.index < st.instruction_addresses.len)
873 st.instruction_addresses[st.index] = addr;
874
875 st.index += 1;
874876}
875877
876878const std = @import("std.zig");
lib/std/debug.zig+8
......@@ -411,6 +411,14 @@ pub fn writeStackTrace(
411411 const return_address = stack_trace.instruction_addresses[frame_index];
412412 try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);
413413 }
414
415 if (stack_trace.index > stack_trace.instruction_addresses.len) {
416 const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;
417
418 tty_config.setColor(out_stream, .Bold);
419 try out_stream.print("({d} additional stack frames skipped...)\n", .{dropped_frames});
420 tty_config.setColor(out_stream, .Reset);
421 }
414422}
415423
416424pub const StackIterator = struct {
src/Air.zig+5
......@@ -733,6 +733,10 @@ pub const Inst = struct {
733733 /// Uses the `ty_op` field.
734734 addrspace_cast,
735735
736 /// Saves the error return trace index, if any. Otherwise, returns 0.
737 /// Uses the `ty_pl` field.
738 save_err_return_trace_index,
739
736740 pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag {
737741 switch (op) {
738742 .lt => return if (optimized) .cmp_lt_optimized else .cmp_lt,
......@@ -1179,6 +1183,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
11791183 .slice_len,
11801184 .ret_addr,
11811185 .frame_addr,
1186 .save_err_return_trace_index,
11821187 => return Type.usize,
11831188
11841189 .wasm_memory_grow => return Type.i32,
src/AstGen.zig+1059-815
......@@ -213,123 +213,149 @@ pub fn deinit(astgen: *AstGen, gpa: Allocator) void {
213213 astgen.ref_table.deinit(gpa);
214214}
215215
216pub const ResultLoc = union(enum) {
217 /// The expression is the right-hand side of assignment to `_`. Only the side-effects of the
218 /// expression should be generated. The result instruction from the expression must
219 /// be ignored.
220 discard,
221 /// The expression has an inferred type, and it will be evaluated as an rvalue.
222 none,
223 /// The expression must generate a pointer rather than a value. For example, the left hand side
224 /// of an assignment uses this kind of result location.
225 ref,
226 /// The expression will be coerced into this type, but it will be evaluated as an rvalue.
227 ty: Zir.Inst.Ref,
228 /// Same as `ty` but for shift operands.
229 ty_shift_operand: Zir.Inst.Ref,
230 /// Same as `ty` but it is guaranteed that Sema will additionally perform the coercion,
231 /// so no `as` instruction needs to be emitted.
232 coerced_ty: Zir.Inst.Ref,
233 /// The expression must store its result into this typed pointer. The result instruction
234 /// from the expression must be ignored.
235 ptr: PtrResultLoc,
236 /// The expression must store its result into this allocation, which has an inferred type.
237 /// The result instruction from the expression must be ignored.
238 /// Always an instruction with tag `alloc_inferred`.
239 inferred_ptr: Zir.Inst.Ref,
240 /// There is a pointer for the expression to store its result into, however, its type
241 /// is inferred based on peer type resolution for a `Zir.Inst.Block`.
242 /// The result instruction from the expression must be ignored.
243 block_ptr: *GenZir,
244
245 const PtrResultLoc = struct {
246 inst: Zir.Inst.Ref,
247 src_node: ?Ast.Node.Index = null,
248 };
216pub const ResultInfo = struct {
217 /// The semantics requested for the result location
218 rl: Loc,
249219
250 pub const Strategy = struct {
251 elide_store_to_block_ptr_instructions: bool,
252 tag: Tag,
253
254 pub const Tag = enum {
255 /// Both branches will use break_void; result location is used to communicate the
256 /// result instruction.
257 break_void,
258 /// Use break statements to pass the block result value, and call rvalue() at
259 /// the end depending on rl. Also elide the store_to_block_ptr instructions
260 /// depending on rl.
261 break_operand,
262 };
263 };
220 /// The "operator" consuming the result location
221 ctx: Context = .none,
264222
265 fn strategy(rl: ResultLoc, block_scope: *GenZir) Strategy {
266 switch (rl) {
267 // In this branch there will not be any store_to_block_ptr instructions.
268 .none, .ty, .ty_shift_operand, .coerced_ty, .ref => return .{
269 .tag = .break_operand,
270 .elide_store_to_block_ptr_instructions = false,
271 },
272 .discard => return .{
273 .tag = .break_void,
274 .elide_store_to_block_ptr_instructions = false,
275 },
276 // The pointer got passed through to the sub-expressions, so we will use
277 // break_void here.
278 // In this branch there will not be any store_to_block_ptr instructions.
279 .ptr => return .{
280 .tag = .break_void,
281 .elide_store_to_block_ptr_instructions = false,
223 /// Turns a `coerced_ty` back into a `ty`. Should be called at branch points
224 /// such as if and switch expressions.
225 fn br(ri: ResultInfo) ResultInfo {
226 return switch (ri.rl) {
227 .coerced_ty => |ty| .{
228 .rl = .{ .ty = ty },
229 .ctx = ri.ctx,
282230 },
283 .inferred_ptr, .block_ptr => {
284 if (block_scope.rvalue_rl_count == block_scope.break_count) {
285 // Neither prong of the if consumed the result location, so we can
286 // use break instructions to create an rvalue.
287 return .{
288 .tag = .break_operand,
289 .elide_store_to_block_ptr_instructions = true,
290 };
291 } else {
292 // Allow the store_to_block_ptr instructions to remain so that
293 // semantic analysis can turn them into bitcasts.
294 return .{
295 .tag = .break_void,
296 .elide_store_to_block_ptr_instructions = false,
297 };
298 }
231 else => ri,
232 };
233 }
234
235 fn zirTag(ri: ResultInfo) Zir.Inst.Tag {
236 switch (ri.rl) {
237 .ty => return switch (ri.ctx) {
238 .shift_op => .as_shift_operand,
239 else => .as_node,
299240 },
241 else => unreachable,
300242 }
301243 }
302244
303 /// Turns a `coerced_ty` back into a `ty`. Should be called at branch points
304 /// such as if and switch expressions.
305 fn br(rl: ResultLoc) ResultLoc {
306 return switch (rl) {
307 .coerced_ty => |ty| .{ .ty = ty },
308 else => rl,
245 pub const Loc = union(enum) {
246 /// The expression is the right-hand side of assignment to `_`. Only the side-effects of the
247 /// expression should be generated. The result instruction from the expression must
248 /// be ignored.
249 discard,
250 /// The expression has an inferred type, and it will be evaluated as an rvalue.
251 none,
252 /// The expression must generate a pointer rather than a value. For example, the left hand side
253 /// of an assignment uses this kind of result location.
254 ref,
255 /// The expression will be coerced into this type, but it will be evaluated as an rvalue.
256 ty: Zir.Inst.Ref,
257 /// Same as `ty` but it is guaranteed that Sema will additionally perform the coercion,
258 /// so no `as` instruction needs to be emitted.
259 coerced_ty: Zir.Inst.Ref,
260 /// The expression must store its result into this typed pointer. The result instruction
261 /// from the expression must be ignored.
262 ptr: PtrResultLoc,
263 /// The expression must store its result into this allocation, which has an inferred type.
264 /// The result instruction from the expression must be ignored.
265 /// Always an instruction with tag `alloc_inferred`.
266 inferred_ptr: Zir.Inst.Ref,
267 /// There is a pointer for the expression to store its result into, however, its type
268 /// is inferred based on peer type resolution for a `Zir.Inst.Block`.
269 /// The result instruction from the expression must be ignored.
270 block_ptr: *GenZir,
271
272 const PtrResultLoc = struct {
273 inst: Zir.Inst.Ref,
274 src_node: ?Ast.Node.Index = null,
309275 };
310 }
311276
312 fn zirTag(rl: ResultLoc) Zir.Inst.Tag {
313 return switch (rl) {
314 .ty => .as_node,
315 .ty_shift_operand => .as_shift_operand,
316 else => unreachable,
277 pub const Strategy = struct {
278 elide_store_to_block_ptr_instructions: bool,
279 tag: Tag,
280
281 pub const Tag = enum {
282 /// Both branches will use break_void; result location is used to communicate the
283 /// result instruction.
284 break_void,
285 /// Use break statements to pass the block result value, and call rvalue() at
286 /// the end depending on rl. Also elide the store_to_block_ptr instructions
287 /// depending on rl.
288 break_operand,
289 };
317290 };
318 }
291
292 fn strategy(rl: Loc, block_scope: *GenZir) Strategy {
293 switch (rl) {
294 // In this branch there will not be any store_to_block_ptr instructions.
295 .none, .ty, .coerced_ty, .ref => return .{
296 .tag = .break_operand,
297 .elide_store_to_block_ptr_instructions = false,
298 },
299 .discard => return .{
300 .tag = .break_void,
301 .elide_store_to_block_ptr_instructions = false,
302 },
303 // The pointer got passed through to the sub-expressions, so we will use
304 // break_void here.
305 // In this branch there will not be any store_to_block_ptr instructions.
306 .ptr => return .{
307 .tag = .break_void,
308 .elide_store_to_block_ptr_instructions = false,
309 },
310 .inferred_ptr, .block_ptr => {
311 if (block_scope.rvalue_rl_count == block_scope.break_count) {
312 // Neither prong of the if consumed the result location, so we can
313 // use break instructions to create an rvalue.
314 return .{
315 .tag = .break_operand,
316 .elide_store_to_block_ptr_instructions = true,
317 };
318 } else {
319 // Allow the store_to_block_ptr instructions to remain so that
320 // semantic analysis can turn them into bitcasts.
321 return .{
322 .tag = .break_void,
323 .elide_store_to_block_ptr_instructions = false,
324 };
325 }
326 },
327 }
328 }
329 };
330
331 pub const Context = enum {
332 /// The expression is the operand to a return expression.
333 @"return",
334 /// The expression is the input to an error-handling operator (if-else, try, or catch).
335 error_handling_expr,
336 /// The expression is the right-hand side of a shift operation.
337 shift_op,
338 /// The expression is an argument in a function call.
339 fn_arg,
340 /// The expression is the right-hand side of an initializer for a `const` variable
341 const_init,
342 /// No specific operator in particular.
343 none,
344 };
319345};
320346
321pub const align_rl: ResultLoc = .{ .ty = .u29_type };
322pub const coerced_align_rl: ResultLoc = .{ .coerced_ty = .u29_type };
323pub const bool_rl: ResultLoc = .{ .ty = .bool_type };
324pub const type_rl: ResultLoc = .{ .ty = .type_type };
325pub const coerced_type_rl: ResultLoc = .{ .coerced_ty = .type_type };
347pub const align_ri: ResultInfo = .{ .rl = .{ .ty = .u29_type } };
348pub const coerced_align_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .u29_type } };
349pub const bool_ri: ResultInfo = .{ .rl = .{ .ty = .bool_type } };
350pub const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } };
351pub const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } };
326352
327353fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
328354 const prev_force_comptime = gz.force_comptime;
329355 gz.force_comptime = true;
330356 defer gz.force_comptime = prev_force_comptime;
331357
332 return expr(gz, scope, coerced_type_rl, type_node);
358 return expr(gz, scope, coerced_type_ri, type_node);
333359}
334360
335361fn reachableTypeExpr(
......@@ -342,24 +368,24 @@ fn reachableTypeExpr(
342368 gz.force_comptime = true;
343369 defer gz.force_comptime = prev_force_comptime;
344370
345 return reachableExpr(gz, scope, coerced_type_rl, type_node, reachable_node);
371 return reachableExpr(gz, scope, coerced_type_ri, type_node, reachable_node);
346372}
347373
348374/// Same as `expr` but fails with a compile error if the result type is `noreturn`.
349375fn reachableExpr(
350376 gz: *GenZir,
351377 scope: *Scope,
352 rl: ResultLoc,
378 ri: ResultInfo,
353379 node: Ast.Node.Index,
354380 reachable_node: Ast.Node.Index,
355381) InnerError!Zir.Inst.Ref {
356 return reachableExprComptime(gz, scope, rl, node, reachable_node, false);
382 return reachableExprComptime(gz, scope, ri, node, reachable_node, false);
357383}
358384
359385fn reachableExprComptime(
360386 gz: *GenZir,
361387 scope: *Scope,
362 rl: ResultLoc,
388 ri: ResultInfo,
363389 node: Ast.Node.Index,
364390 reachable_node: Ast.Node.Index,
365391 force_comptime: bool,
......@@ -368,7 +394,7 @@ fn reachableExprComptime(
368394 gz.force_comptime = prev_force_comptime or force_comptime;
369395 defer gz.force_comptime = prev_force_comptime;
370396
371 const result_inst = try expr(gz, scope, rl, node);
397 const result_inst = try expr(gz, scope, ri, node);
372398 if (gz.refIsNoReturn(result_inst)) {
373399 try gz.astgen.appendErrorNodeNotes(reachable_node, "unreachable code", .{}, &[_]u32{
374400 try gz.astgen.errNoteNode(node, "control flow is diverted here", .{}),
......@@ -569,14 +595,14 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
569595 .@"orelse",
570596 => {},
571597 }
572 return expr(gz, scope, .ref, node);
598 return expr(gz, scope, .{ .rl = .ref }, node);
573599}
574600
575601/// Turn Zig AST into untyped ZIR instructions.
576602/// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the
577603/// result instruction can be used to inspect whether it is isNoReturn() but that is it,
578604/// it must otherwise not be used.
579fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
605fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
580606 const astgen = gz.astgen;
581607 const tree = astgen.tree;
582608 const main_tokens = tree.nodes.items(.main_token);
......@@ -617,161 +643,161 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
617643
618644 .assign => {
619645 try assign(gz, scope, node);
620 return rvalue(gz, rl, .void_value, node);
646 return rvalue(gz, ri, .void_value, node);
621647 },
622648
623649 .assign_shl => {
624650 try assignShift(gz, scope, node, .shl);
625 return rvalue(gz, rl, .void_value, node);
651 return rvalue(gz, ri, .void_value, node);
626652 },
627653 .assign_shl_sat => {
628654 try assignShiftSat(gz, scope, node);
629 return rvalue(gz, rl, .void_value, node);
655 return rvalue(gz, ri, .void_value, node);
630656 },
631657 .assign_shr => {
632658 try assignShift(gz, scope, node, .shr);
633 return rvalue(gz, rl, .void_value, node);
659 return rvalue(gz, ri, .void_value, node);
634660 },
635661
636662 .assign_bit_and => {
637663 try assignOp(gz, scope, node, .bit_and);
638 return rvalue(gz, rl, .void_value, node);
664 return rvalue(gz, ri, .void_value, node);
639665 },
640666 .assign_bit_or => {
641667 try assignOp(gz, scope, node, .bit_or);
642 return rvalue(gz, rl, .void_value, node);
668 return rvalue(gz, ri, .void_value, node);
643669 },
644670 .assign_bit_xor => {
645671 try assignOp(gz, scope, node, .xor);
646 return rvalue(gz, rl, .void_value, node);
672 return rvalue(gz, ri, .void_value, node);
647673 },
648674 .assign_div => {
649675 try assignOp(gz, scope, node, .div);
650 return rvalue(gz, rl, .void_value, node);
676 return rvalue(gz, ri, .void_value, node);
651677 },
652678 .assign_sub => {
653679 try assignOp(gz, scope, node, .sub);
654 return rvalue(gz, rl, .void_value, node);
680 return rvalue(gz, ri, .void_value, node);
655681 },
656682 .assign_sub_wrap => {
657683 try assignOp(gz, scope, node, .subwrap);
658 return rvalue(gz, rl, .void_value, node);
684 return rvalue(gz, ri, .void_value, node);
659685 },
660686 .assign_sub_sat => {
661687 try assignOp(gz, scope, node, .sub_sat);
662 return rvalue(gz, rl, .void_value, node);
688 return rvalue(gz, ri, .void_value, node);
663689 },
664690 .assign_mod => {
665691 try assignOp(gz, scope, node, .mod_rem);
666 return rvalue(gz, rl, .void_value, node);
692 return rvalue(gz, ri, .void_value, node);
667693 },
668694 .assign_add => {
669695 try assignOp(gz, scope, node, .add);
670 return rvalue(gz, rl, .void_value, node);
696 return rvalue(gz, ri, .void_value, node);
671697 },
672698 .assign_add_wrap => {
673699 try assignOp(gz, scope, node, .addwrap);
674 return rvalue(gz, rl, .void_value, node);
700 return rvalue(gz, ri, .void_value, node);
675701 },
676702 .assign_add_sat => {
677703 try assignOp(gz, scope, node, .add_sat);
678 return rvalue(gz, rl, .void_value, node);
704 return rvalue(gz, ri, .void_value, node);
679705 },
680706 .assign_mul => {
681707 try assignOp(gz, scope, node, .mul);
682 return rvalue(gz, rl, .void_value, node);
708 return rvalue(gz, ri, .void_value, node);
683709 },
684710 .assign_mul_wrap => {
685711 try assignOp(gz, scope, node, .mulwrap);
686 return rvalue(gz, rl, .void_value, node);
712 return rvalue(gz, ri, .void_value, node);
687713 },
688714 .assign_mul_sat => {
689715 try assignOp(gz, scope, node, .mul_sat);
690 return rvalue(gz, rl, .void_value, node);
716 return rvalue(gz, ri, .void_value, node);
691717 },
692718
693719 // zig fmt: off
694 .shl => return shiftOp(gz, scope, rl, node, node_datas[node].lhs, node_datas[node].rhs, .shl),
695 .shr => return shiftOp(gz, scope, rl, node, node_datas[node].lhs, node_datas[node].rhs, .shr),
696
697 .add => return simpleBinOp(gz, scope, rl, node, .add),
698 .add_wrap => return simpleBinOp(gz, scope, rl, node, .addwrap),
699 .add_sat => return simpleBinOp(gz, scope, rl, node, .add_sat),
700 .sub => return simpleBinOp(gz, scope, rl, node, .sub),
701 .sub_wrap => return simpleBinOp(gz, scope, rl, node, .subwrap),
702 .sub_sat => return simpleBinOp(gz, scope, rl, node, .sub_sat),
703 .mul => return simpleBinOp(gz, scope, rl, node, .mul),
704 .mul_wrap => return simpleBinOp(gz, scope, rl, node, .mulwrap),
705 .mul_sat => return simpleBinOp(gz, scope, rl, node, .mul_sat),
706 .div => return simpleBinOp(gz, scope, rl, node, .div),
707 .mod => return simpleBinOp(gz, scope, rl, node, .mod_rem),
708 .shl_sat => return simpleBinOp(gz, scope, rl, node, .shl_sat),
709
710 .bit_and => return simpleBinOp(gz, scope, rl, node, .bit_and),
711 .bit_or => return simpleBinOp(gz, scope, rl, node, .bit_or),
712 .bit_xor => return simpleBinOp(gz, scope, rl, node, .xor),
713 .bang_equal => return simpleBinOp(gz, scope, rl, node, .cmp_neq),
714 .equal_equal => return simpleBinOp(gz, scope, rl, node, .cmp_eq),
715 .greater_than => return simpleBinOp(gz, scope, rl, node, .cmp_gt),
716 .greater_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_gte),
717 .less_than => return simpleBinOp(gz, scope, rl, node, .cmp_lt),
718 .less_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_lte),
719 .array_cat => return simpleBinOp(gz, scope, rl, node, .array_cat),
720 .shl => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shl),
721 .shr => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shr),
722
723 .add => return simpleBinOp(gz, scope, ri, node, .add),
724 .add_wrap => return simpleBinOp(gz, scope, ri, node, .addwrap),
725 .add_sat => return simpleBinOp(gz, scope, ri, node, .add_sat),
726 .sub => return simpleBinOp(gz, scope, ri, node, .sub),
727 .sub_wrap => return simpleBinOp(gz, scope, ri, node, .subwrap),
728 .sub_sat => return simpleBinOp(gz, scope, ri, node, .sub_sat),
729 .mul => return simpleBinOp(gz, scope, ri, node, .mul),
730 .mul_wrap => return simpleBinOp(gz, scope, ri, node, .mulwrap),
731 .mul_sat => return simpleBinOp(gz, scope, ri, node, .mul_sat),
732 .div => return simpleBinOp(gz, scope, ri, node, .div),
733 .mod => return simpleBinOp(gz, scope, ri, node, .mod_rem),
734 .shl_sat => return simpleBinOp(gz, scope, ri, node, .shl_sat),
735
736 .bit_and => return simpleBinOp(gz, scope, ri, node, .bit_and),
737 .bit_or => return simpleBinOp(gz, scope, ri, node, .bit_or),
738 .bit_xor => return simpleBinOp(gz, scope, ri, node, .xor),
739 .bang_equal => return simpleBinOp(gz, scope, ri, node, .cmp_neq),
740 .equal_equal => return simpleBinOp(gz, scope, ri, node, .cmp_eq),
741 .greater_than => return simpleBinOp(gz, scope, ri, node, .cmp_gt),
742 .greater_or_equal => return simpleBinOp(gz, scope, ri, node, .cmp_gte),
743 .less_than => return simpleBinOp(gz, scope, ri, node, .cmp_lt),
744 .less_or_equal => return simpleBinOp(gz, scope, ri, node, .cmp_lte),
745 .array_cat => return simpleBinOp(gz, scope, ri, node, .array_cat),
720746
721747 .array_mult => {
722748 const result = try gz.addPlNode(.array_mul, node, Zir.Inst.Bin{
723 .lhs = try expr(gz, scope, .none, node_datas[node].lhs),
724 .rhs = try comptimeExpr(gz, scope, .{ .coerced_ty = .usize_type }, node_datas[node].rhs),
749 .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
750 .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs),
725751 });
726 return rvalue(gz, rl, result, node);
752 return rvalue(gz, ri, result, node);
727753 },
728754
729 .error_union => return simpleBinOp(gz, scope, rl, node, .error_union_type),
730 .merge_error_sets => return simpleBinOp(gz, scope, rl, node, .merge_error_sets),
755 .error_union => return simpleBinOp(gz, scope, ri, node, .error_union_type),
756 .merge_error_sets => return simpleBinOp(gz, scope, ri, node, .merge_error_sets),
731757
732 .bool_and => return boolBinOp(gz, scope, rl, node, .bool_br_and),
733 .bool_or => return boolBinOp(gz, scope, rl, node, .bool_br_or),
758 .bool_and => return boolBinOp(gz, scope, ri, node, .bool_br_and),
759 .bool_or => return boolBinOp(gz, scope, ri, node, .bool_br_or),
734760
735 .bool_not => return simpleUnOp(gz, scope, rl, node, bool_rl, node_datas[node].lhs, .bool_not),
736 .bit_not => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .bit_not),
761 .bool_not => return simpleUnOp(gz, scope, ri, node, bool_ri, node_datas[node].lhs, .bool_not),
762 .bit_not => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .bit_not),
737763
738 .negation => return negation(gz, scope, rl, node),
739 .negation_wrap => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .negate_wrap),
764 .negation => return negation(gz, scope, ri, node),
765 .negation_wrap => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .negate_wrap),
740766
741 .identifier => return identifier(gz, scope, rl, node),
767 .identifier => return identifier(gz, scope, ri, node),
742768
743 .asm_simple => return asmExpr(gz, scope, rl, node, tree.asmSimple(node)),
744 .@"asm" => return asmExpr(gz, scope, rl, node, tree.asmFull(node)),
769 .asm_simple => return asmExpr(gz, scope, ri, node, tree.asmSimple(node)),
770 .@"asm" => return asmExpr(gz, scope, ri, node, tree.asmFull(node)),
745771
746 .string_literal => return stringLiteral(gz, rl, node),
747 .multiline_string_literal => return multilineStringLiteral(gz, rl, node),
772 .string_literal => return stringLiteral(gz, ri, node),
773 .multiline_string_literal => return multilineStringLiteral(gz, ri, node),
748774
749 .number_literal => return numberLiteral(gz, rl, node, node, .positive),
775 .number_literal => return numberLiteral(gz, ri, node, node, .positive),
750776 // zig fmt: on
751777
752778 .builtin_call_two, .builtin_call_two_comma => {
753779 if (node_datas[node].lhs == 0) {
754780 const params = [_]Ast.Node.Index{};
755 return builtinCall(gz, scope, rl, node, &params);
781 return builtinCall(gz, scope, ri, node, &params);
756782 } else if (node_datas[node].rhs == 0) {
757783 const params = [_]Ast.Node.Index{node_datas[node].lhs};
758 return builtinCall(gz, scope, rl, node, &params);
784 return builtinCall(gz, scope, ri, node, &params);
759785 } else {
760786 const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
761 return builtinCall(gz, scope, rl, node, &params);
787 return builtinCall(gz, scope, ri, node, &params);
762788 }
763789 },
764790 .builtin_call, .builtin_call_comma => {
765791 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
766 return builtinCall(gz, scope, rl, node, params);
792 return builtinCall(gz, scope, ri, node, params);
767793 },
768794
769795 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => {
770796 var params: [1]Ast.Node.Index = undefined;
771 return callExpr(gz, scope, rl, node, tree.callOne(&params, node));
797 return callExpr(gz, scope, ri, node, tree.callOne(&params, node));
772798 },
773799 .call, .call_comma, .async_call, .async_call_comma => {
774 return callExpr(gz, scope, rl, node, tree.callFull(node));
800 return callExpr(gz, scope, ri, node, tree.callFull(node));
775801 },
776802
777803 .unreachable_literal => {
......@@ -786,112 +812,112 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
786812 return Zir.Inst.Ref.unreachable_value;
787813 },
788814 .@"return" => return ret(gz, scope, node),
789 .field_access => return fieldAccess(gz, scope, rl, node),
815 .field_access => return fieldAccess(gz, scope, ri, node),
790816
791 .if_simple => return ifExpr(gz, scope, rl.br(), node, tree.ifSimple(node)),
792 .@"if" => return ifExpr(gz, scope, rl.br(), node, tree.ifFull(node)),
817 .if_simple => return ifExpr(gz, scope, ri.br(), node, tree.ifSimple(node)),
818 .@"if" => return ifExpr(gz, scope, ri.br(), node, tree.ifFull(node)),
793819
794 .while_simple => return whileExpr(gz, scope, rl.br(), node, tree.whileSimple(node), false),
795 .while_cont => return whileExpr(gz, scope, rl.br(), node, tree.whileCont(node), false),
796 .@"while" => return whileExpr(gz, scope, rl.br(), node, tree.whileFull(node), false),
820 .while_simple => return whileExpr(gz, scope, ri.br(), node, tree.whileSimple(node), false),
821 .while_cont => return whileExpr(gz, scope, ri.br(), node, tree.whileCont(node), false),
822 .@"while" => return whileExpr(gz, scope, ri.br(), node, tree.whileFull(node), false),
797823
798 .for_simple => return forExpr(gz, scope, rl.br(), node, tree.forSimple(node), false),
799 .@"for" => return forExpr(gz, scope, rl.br(), node, tree.forFull(node), false),
824 .for_simple => return forExpr(gz, scope, ri.br(), node, tree.forSimple(node), false),
825 .@"for" => return forExpr(gz, scope, ri.br(), node, tree.forFull(node), false),
800826
801827 .slice_open => {
802 const lhs = try expr(gz, scope, .ref, node_datas[node].lhs);
803 const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, node_datas[node].rhs);
828 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
829 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
804830 const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{
805831 .lhs = lhs,
806832 .start = start,
807833 });
808 return rvalue(gz, rl, result, node);
834 return rvalue(gz, ri, result, node);
809835 },
810836 .slice => {
811 const lhs = try expr(gz, scope, .ref, node_datas[node].lhs);
837 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
812838 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);
813 const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.start);
814 const end = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.end);
839 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
840 const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end);
815841 const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{
816842 .lhs = lhs,
817843 .start = start,
818844 .end = end,
819845 });
820 return rvalue(gz, rl, result, node);
846 return rvalue(gz, ri, result, node);
821847 },
822848 .slice_sentinel => {
823 const lhs = try expr(gz, scope, .ref, node_datas[node].lhs);
849 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
824850 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);
825 const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.start);
826 const end = if (extra.end != 0) try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.end) else .none;
827 const sentinel = try expr(gz, scope, .none, extra.sentinel);
851 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
852 const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none;
853 const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel);
828854 const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{
829855 .lhs = lhs,
830856 .start = start,
831857 .end = end,
832858 .sentinel = sentinel,
833859 });
834 return rvalue(gz, rl, result, node);
860 return rvalue(gz, ri, result, node);
835861 },
836862
837863 .deref => {
838 const lhs = try expr(gz, scope, .none, node_datas[node].lhs);
864 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
839865 _ = try gz.addUnNode(.validate_deref, lhs, node);
840 switch (rl) {
866 switch (ri.rl) {
841867 .ref => return lhs,
842868 else => {
843869 const result = try gz.addUnNode(.load, lhs, node);
844 return rvalue(gz, rl, result, node);
870 return rvalue(gz, ri, result, node);
845871 },
846872 }
847873 },
848874 .address_of => {
849 const result = try expr(gz, scope, .ref, node_datas[node].lhs);
850 return rvalue(gz, rl, result, node);
875 const result = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
876 return rvalue(gz, ri, result, node);
851877 },
852878 .optional_type => {
853879 const operand = try typeExpr(gz, scope, node_datas[node].lhs);
854880 const result = try gz.addUnNode(.optional_type, operand, node);
855 return rvalue(gz, rl, result, node);
881 return rvalue(gz, ri, result, node);
856882 },
857 .unwrap_optional => switch (rl) {
883 .unwrap_optional => switch (ri.rl) {
858884 .ref => return gz.addUnNode(
859885 .optional_payload_safe_ptr,
860 try expr(gz, scope, .ref, node_datas[node].lhs),
886 try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs),
861887 node,
862888 ),
863 else => return rvalue(gz, rl, try gz.addUnNode(
889 else => return rvalue(gz, ri, try gz.addUnNode(
864890 .optional_payload_safe,
865 try expr(gz, scope, .none, node_datas[node].lhs),
891 try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
866892 node,
867893 ), node),
868894 },
869895 .block_two, .block_two_semicolon => {
870896 const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
871897 if (node_datas[node].lhs == 0) {
872 return blockExpr(gz, scope, rl, node, statements[0..0]);
898 return blockExpr(gz, scope, ri, node, statements[0..0]);
873899 } else if (node_datas[node].rhs == 0) {
874 return blockExpr(gz, scope, rl, node, statements[0..1]);
900 return blockExpr(gz, scope, ri, node, statements[0..1]);
875901 } else {
876 return blockExpr(gz, scope, rl, node, statements[0..2]);
902 return blockExpr(gz, scope, ri, node, statements[0..2]);
877903 }
878904 },
879905 .block, .block_semicolon => {
880906 const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
881 return blockExpr(gz, scope, rl, node, statements);
907 return blockExpr(gz, scope, ri, node, statements);
882908 },
883 .enum_literal => return simpleStrTok(gz, rl, main_tokens[node], node, .enum_literal),
884 .error_value => return simpleStrTok(gz, rl, node_datas[node].rhs, node, .error_value),
909 .enum_literal => return simpleStrTok(gz, ri, main_tokens[node], node, .enum_literal),
910 .error_value => return simpleStrTok(gz, ri, node_datas[node].rhs, node, .error_value),
885911 // TODO restore this when implementing https://github.com/ziglang/zig/issues/6025
886 // .anyframe_literal => return rvalue(gz, rl, .anyframe_type, node),
912 // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node),
887913 .anyframe_literal => {
888914 const result = try gz.addUnNode(.anyframe_type, .void_type, node);
889 return rvalue(gz, rl, result, node);
915 return rvalue(gz, ri, result, node);
890916 },
891917 .anyframe_type => {
892918 const return_type = try typeExpr(gz, scope, node_datas[node].rhs);
893919 const result = try gz.addUnNode(.anyframe_type, return_type, node);
894 return rvalue(gz, rl, result, node);
920 return rvalue(gz, ri, result, node);
895921 },
896922 .@"catch" => {
897923 const catch_token = main_tokens[node];
......@@ -899,11 +925,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
899925 catch_token + 2
900926 else
901927 null;
902 switch (rl) {
928 switch (ri.rl) {
903929 .ref => return orelseCatchExpr(
904930 gz,
905931 scope,
906 rl,
932 ri,
907933 node,
908934 node_datas[node].lhs,
909935 .is_non_err_ptr,
......@@ -915,7 +941,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
915941 else => return orelseCatchExpr(
916942 gz,
917943 scope,
918 rl,
944 ri,
919945 node,
920946 node_datas[node].lhs,
921947 .is_non_err,
......@@ -926,11 +952,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
926952 ),
927953 }
928954 },
929 .@"orelse" => switch (rl) {
955 .@"orelse" => switch (ri.rl) {
930956 .ref => return orelseCatchExpr(
931957 gz,
932958 scope,
933 rl,
959 ri,
934960 node,
935961 node_datas[node].lhs,
936962 .is_non_null_ptr,
......@@ -942,7 +968,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
942968 else => return orelseCatchExpr(
943969 gz,
944970 scope,
945 rl,
971 ri,
946972 node,
947973 node_datas[node].lhs,
948974 .is_non_null,
......@@ -953,94 +979,94 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
953979 ),
954980 },
955981
956 .ptr_type_aligned => return ptrType(gz, scope, rl, node, tree.ptrTypeAligned(node)),
957 .ptr_type_sentinel => return ptrType(gz, scope, rl, node, tree.ptrTypeSentinel(node)),
958 .ptr_type => return ptrType(gz, scope, rl, node, tree.ptrType(node)),
959 .ptr_type_bit_range => return ptrType(gz, scope, rl, node, tree.ptrTypeBitRange(node)),
982 .ptr_type_aligned => return ptrType(gz, scope, ri, node, tree.ptrTypeAligned(node)),
983 .ptr_type_sentinel => return ptrType(gz, scope, ri, node, tree.ptrTypeSentinel(node)),
984 .ptr_type => return ptrType(gz, scope, ri, node, tree.ptrType(node)),
985 .ptr_type_bit_range => return ptrType(gz, scope, ri, node, tree.ptrTypeBitRange(node)),
960986
961987 .container_decl,
962988 .container_decl_trailing,
963 => return containerDecl(gz, scope, rl, node, tree.containerDecl(node)),
989 => return containerDecl(gz, scope, ri, node, tree.containerDecl(node)),
964990 .container_decl_two, .container_decl_two_trailing => {
965991 var buffer: [2]Ast.Node.Index = undefined;
966 return containerDecl(gz, scope, rl, node, tree.containerDeclTwo(&buffer, node));
992 return containerDecl(gz, scope, ri, node, tree.containerDeclTwo(&buffer, node));
967993 },
968994 .container_decl_arg,
969995 .container_decl_arg_trailing,
970 => return containerDecl(gz, scope, rl, node, tree.containerDeclArg(node)),
996 => return containerDecl(gz, scope, ri, node, tree.containerDeclArg(node)),
971997
972998 .tagged_union,
973999 .tagged_union_trailing,
974 => return containerDecl(gz, scope, rl, node, tree.taggedUnion(node)),
1000 => return containerDecl(gz, scope, ri, node, tree.taggedUnion(node)),
9751001 .tagged_union_two, .tagged_union_two_trailing => {
9761002 var buffer: [2]Ast.Node.Index = undefined;
977 return containerDecl(gz, scope, rl, node, tree.taggedUnionTwo(&buffer, node));
1003 return containerDecl(gz, scope, ri, node, tree.taggedUnionTwo(&buffer, node));
9781004 },
9791005 .tagged_union_enum_tag,
9801006 .tagged_union_enum_tag_trailing,
981 => return containerDecl(gz, scope, rl, node, tree.taggedUnionEnumTag(node)),
1007 => return containerDecl(gz, scope, ri, node, tree.taggedUnionEnumTag(node)),
9821008
9831009 .@"break" => return breakExpr(gz, scope, node),
9841010 .@"continue" => return continueExpr(gz, scope, node),
985 .grouped_expression => return expr(gz, scope, rl, node_datas[node].lhs),
986 .array_type => return arrayType(gz, scope, rl, node),
987 .array_type_sentinel => return arrayTypeSentinel(gz, scope, rl, node),
988 .char_literal => return charLiteral(gz, rl, node),
989 .error_set_decl => return errorSetDecl(gz, rl, node),
990 .array_access => return arrayAccess(gz, scope, rl, node),
991 .@"comptime" => return comptimeExprAst(gz, scope, rl, node),
992 .@"switch", .switch_comma => return switchExpr(gz, scope, rl.br(), node),
993
994 .@"nosuspend" => return nosuspendExpr(gz, scope, rl, node),
1011 .grouped_expression => return expr(gz, scope, ri, node_datas[node].lhs),
1012 .array_type => return arrayType(gz, scope, ri, node),
1013 .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node),
1014 .char_literal => return charLiteral(gz, ri, node),
1015 .error_set_decl => return errorSetDecl(gz, ri, node),
1016 .array_access => return arrayAccess(gz, scope, ri, node),
1017 .@"comptime" => return comptimeExprAst(gz, scope, ri, node),
1018 .@"switch", .switch_comma => return switchExpr(gz, scope, ri.br(), node),
1019
1020 .@"nosuspend" => return nosuspendExpr(gz, scope, ri, node),
9951021 .@"suspend" => return suspendExpr(gz, scope, node),
996 .@"await" => return awaitExpr(gz, scope, rl, node),
997 .@"resume" => return resumeExpr(gz, scope, rl, node),
1022 .@"await" => return awaitExpr(gz, scope, ri, node),
1023 .@"resume" => return resumeExpr(gz, scope, ri, node),
9981024
999 .@"try" => return tryExpr(gz, scope, rl, node, node_datas[node].lhs),
1025 .@"try" => return tryExpr(gz, scope, ri, node, node_datas[node].lhs),
10001026
10011027 .array_init_one, .array_init_one_comma => {
10021028 var elements: [1]Ast.Node.Index = undefined;
1003 return arrayInitExpr(gz, scope, rl, node, tree.arrayInitOne(&elements, node));
1029 return arrayInitExpr(gz, scope, ri, node, tree.arrayInitOne(&elements, node));
10041030 },
10051031 .array_init_dot_two, .array_init_dot_two_comma => {
10061032 var elements: [2]Ast.Node.Index = undefined;
1007 return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDotTwo(&elements, node));
1033 return arrayInitExpr(gz, scope, ri, node, tree.arrayInitDotTwo(&elements, node));
10081034 },
10091035 .array_init_dot,
10101036 .array_init_dot_comma,
1011 => return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDot(node)),
1037 => return arrayInitExpr(gz, scope, ri, node, tree.arrayInitDot(node)),
10121038 .array_init,
10131039 .array_init_comma,
1014 => return arrayInitExpr(gz, scope, rl, node, tree.arrayInit(node)),
1040 => return arrayInitExpr(gz, scope, ri, node, tree.arrayInit(node)),
10151041
10161042 .struct_init_one, .struct_init_one_comma => {
10171043 var fields: [1]Ast.Node.Index = undefined;
1018 return structInitExpr(gz, scope, rl, node, tree.structInitOne(&fields, node));
1044 return structInitExpr(gz, scope, ri, node, tree.structInitOne(&fields, node));
10191045 },
10201046 .struct_init_dot_two, .struct_init_dot_two_comma => {
10211047 var fields: [2]Ast.Node.Index = undefined;
1022 return structInitExpr(gz, scope, rl, node, tree.structInitDotTwo(&fields, node));
1048 return structInitExpr(gz, scope, ri, node, tree.structInitDotTwo(&fields, node));
10231049 },
10241050 .struct_init_dot,
10251051 .struct_init_dot_comma,
1026 => return structInitExpr(gz, scope, rl, node, tree.structInitDot(node)),
1052 => return structInitExpr(gz, scope, ri, node, tree.structInitDot(node)),
10271053 .struct_init,
10281054 .struct_init_comma,
1029 => return structInitExpr(gz, scope, rl, node, tree.structInit(node)),
1055 => return structInitExpr(gz, scope, ri, node, tree.structInit(node)),
10301056
10311057 .fn_proto_simple => {
10321058 var params: [1]Ast.Node.Index = undefined;
1033 return fnProtoExpr(gz, scope, rl, node, tree.fnProtoSimple(&params, node));
1059 return fnProtoExpr(gz, scope, ri, node, tree.fnProtoSimple(&params, node));
10341060 },
10351061 .fn_proto_multi => {
1036 return fnProtoExpr(gz, scope, rl, node, tree.fnProtoMulti(node));
1062 return fnProtoExpr(gz, scope, ri, node, tree.fnProtoMulti(node));
10371063 },
10381064 .fn_proto_one => {
10391065 var params: [1]Ast.Node.Index = undefined;
1040 return fnProtoExpr(gz, scope, rl, node, tree.fnProtoOne(&params, node));
1066 return fnProtoExpr(gz, scope, ri, node, tree.fnProtoOne(&params, node));
10411067 },
10421068 .fn_proto => {
1043 return fnProtoExpr(gz, scope, rl, node, tree.fnProto(node));
1069 return fnProtoExpr(gz, scope, ri, node, tree.fnProto(node));
10441070 },
10451071 }
10461072}
......@@ -1048,7 +1074,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
10481074fn nosuspendExpr(
10491075 gz: *GenZir,
10501076 scope: *Scope,
1051 rl: ResultLoc,
1077 ri: ResultInfo,
10521078 node: Ast.Node.Index,
10531079) InnerError!Zir.Inst.Ref {
10541080 const astgen = gz.astgen;
......@@ -1063,7 +1089,7 @@ fn nosuspendExpr(
10631089 }
10641090 gz.nosuspend_node = node;
10651091 defer gz.nosuspend_node = 0;
1066 return expr(gz, scope, rl, body_node);
1092 return expr(gz, scope, ri, body_node);
10671093}
10681094
10691095fn suspendExpr(
......@@ -1096,7 +1122,7 @@ fn suspendExpr(
10961122 suspend_scope.suspend_node = node;
10971123 defer suspend_scope.unstack();
10981124
1099 const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node);
1125 const body_result = try expr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node);
11001126 if (!gz.refIsNoReturn(body_result)) {
11011127 _ = try suspend_scope.addBreak(.break_inline, suspend_inst, .void_value);
11021128 }
......@@ -1108,7 +1134,7 @@ fn suspendExpr(
11081134fn awaitExpr(
11091135 gz: *GenZir,
11101136 scope: *Scope,
1111 rl: ResultLoc,
1137 ri: ResultInfo,
11121138 node: Ast.Node.Index,
11131139) InnerError!Zir.Inst.Ref {
11141140 const astgen = gz.astgen;
......@@ -1121,7 +1147,7 @@ fn awaitExpr(
11211147 try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}),
11221148 });
11231149 }
1124 const operand = try expr(gz, scope, .none, rhs_node);
1150 const operand = try expr(gz, scope, .{ .rl = .none }, rhs_node);
11251151 const result = if (gz.nosuspend_node != 0)
11261152 try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{
11271153 .node = gz.nodeIndexToRelative(node),
......@@ -1130,28 +1156,28 @@ fn awaitExpr(
11301156 else
11311157 try gz.addUnNode(.@"await", operand, node);
11321158
1133 return rvalue(gz, rl, result, node);
1159 return rvalue(gz, ri, result, node);
11341160}
11351161
11361162fn resumeExpr(
11371163 gz: *GenZir,
11381164 scope: *Scope,
1139 rl: ResultLoc,
1165 ri: ResultInfo,
11401166 node: Ast.Node.Index,
11411167) InnerError!Zir.Inst.Ref {
11421168 const astgen = gz.astgen;
11431169 const tree = astgen.tree;
11441170 const node_datas = tree.nodes.items(.data);
11451171 const rhs_node = node_datas[node].lhs;
1146 const operand = try expr(gz, scope, .none, rhs_node);
1172 const operand = try expr(gz, scope, .{ .rl = .none }, rhs_node);
11471173 const result = try gz.addUnNode(.@"resume", operand, node);
1148 return rvalue(gz, rl, result, node);
1174 return rvalue(gz, ri, result, node);
11491175}
11501176
11511177fn fnProtoExpr(
11521178 gz: *GenZir,
11531179 scope: *Scope,
1154 rl: ResultLoc,
1180 ri: ResultInfo,
11551181 node: Ast.Node.Index,
11561182 fn_proto: Ast.full.FnProto,
11571183) InnerError!Zir.Inst.Ref {
......@@ -1217,7 +1243,7 @@ fn fnProtoExpr(
12171243 assert(param_type_node != 0);
12181244 var param_gz = block_scope.makeSubBlock(scope);
12191245 defer param_gz.unstack();
1220 const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node);
1246 const param_type = try expr(&param_gz, scope, coerced_type_ri, param_type_node);
12211247 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
12221248 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);
12231249 const main_tokens = tree.nodes.items(.main_token);
......@@ -1231,7 +1257,7 @@ fn fnProtoExpr(
12311257 };
12321258
12331259 const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
1234 break :inst try expr(&block_scope, scope, align_rl, fn_proto.ast.align_expr);
1260 break :inst try expr(&block_scope, scope, align_ri, fn_proto.ast.align_expr);
12351261 };
12361262
12371263 if (fn_proto.ast.addrspace_expr != 0) {
......@@ -1246,7 +1272,7 @@ fn fnProtoExpr(
12461272 try expr(
12471273 &block_scope,
12481274 scope,
1249 .{ .ty = .calling_convention_type },
1275 .{ .rl = .{ .ty = .calling_convention_type } },
12501276 fn_proto.ast.callconv_expr,
12511277 )
12521278 else
......@@ -1257,7 +1283,7 @@ fn fnProtoExpr(
12571283 if (is_inferred_error) {
12581284 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
12591285 }
1260 const ret_ty = try expr(&block_scope, scope, coerced_type_rl, fn_proto.ast.return_type);
1286 const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type);
12611287
12621288 const result = try block_scope.addFunc(.{
12631289 .src_node = fn_proto.ast.proto_node,
......@@ -1288,13 +1314,13 @@ fn fnProtoExpr(
12881314 try block_scope.setBlockBody(block_inst);
12891315 try gz.instructions.append(astgen.gpa, block_inst);
12901316
1291 return rvalue(gz, rl, indexToRef(block_inst), fn_proto.ast.proto_node);
1317 return rvalue(gz, ri, indexToRef(block_inst), fn_proto.ast.proto_node);
12921318}
12931319
12941320fn arrayInitExpr(
12951321 gz: *GenZir,
12961322 scope: *Scope,
1297 rl: ResultLoc,
1323 ri: ResultInfo,
12981324 node: Ast.Node.Index,
12991325 array_init: Ast.full.ArrayInit,
13001326) InnerError!Zir.Inst.Ref {
......@@ -1336,7 +1362,7 @@ fn arrayInitExpr(
13361362 .elem = elem_type,
13371363 };
13381364 } else {
1339 const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);
1365 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel);
13401366 const array_type_inst = try gz.addPlNode(
13411367 .array_type_sentinel,
13421368 array_init.ast.type_expr,
......@@ -1364,11 +1390,11 @@ fn arrayInitExpr(
13641390 };
13651391 };
13661392
1367 switch (rl) {
1393 switch (ri.rl) {
13681394 .discard => {
13691395 // TODO elements should still be coerced if type is provided
13701396 for (array_init.ast.elements) |elem_init| {
1371 _ = try expr(gz, scope, .discard, elem_init);
1397 _ = try expr(gz, scope, .{ .rl = .discard }, elem_init);
13721398 }
13731399 return Zir.Inst.Ref.void_value;
13741400 },
......@@ -1380,13 +1406,13 @@ fn arrayInitExpr(
13801406 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
13811407 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
13821408 },
1383 .ty, .ty_shift_operand, .coerced_ty => {
1409 .ty, .coerced_ty => {
13841410 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
13851411 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
1386 return rvalue(gz, rl, result, node);
1412 return rvalue(gz, ri, result, node);
13871413 },
13881414 .ptr => |ptr_res| {
1389 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_res.inst, array_init.ast.elements, types.array);
1415 return arrayInitExprRlPtr(gz, scope, ri, node, ptr_res.inst, array_init.ast.elements, types.array);
13901416 },
13911417 .inferred_ptr => |ptr_inst| {
13921418 if (types.array == .none) {
......@@ -1394,9 +1420,9 @@ fn arrayInitExpr(
13941420 // analyzing array_base_ptr against an alloc_inferred_mut.
13951421 // See corresponding logic in structInitExpr.
13961422 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
1397 return rvalue(gz, rl, result, node);
1423 return rvalue(gz, ri, result, node);
13981424 } else {
1399 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array);
1425 return arrayInitExprRlPtr(gz, scope, ri, node, ptr_inst, array_init.ast.elements, types.array);
14001426 }
14011427 },
14021428 .block_ptr => |block_gz| {
......@@ -1404,9 +1430,9 @@ fn arrayInitExpr(
14041430 // See corresponding logic in structInitExpr.
14051431 if (types.array == .none and astgen.isInferred(block_gz.rl_ptr)) {
14061432 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
1407 return rvalue(gz, rl, result, node);
1433 return rvalue(gz, ri, result, node);
14081434 }
1409 return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, types.array);
1435 return arrayInitExprRlPtr(gz, scope, ri, node, block_gz.rl_ptr, array_init.ast.elements, types.array);
14101436 },
14111437 }
14121438}
......@@ -1426,7 +1452,7 @@ fn arrayInitExprRlNone(
14261452 var extra_index = try reserveExtra(astgen, elements.len);
14271453
14281454 for (elements) |elem_init| {
1429 const elem_ref = try expr(gz, scope, .none, elem_init);
1455 const elem_ref = try expr(gz, scope, .{ .rl = .none }, elem_init);
14301456 astgen.extra.items[extra_index] = @enumToInt(elem_ref);
14311457 extra_index += 1;
14321458 }
......@@ -1455,9 +1481,9 @@ fn arrayInitExprInner(
14551481 }
14561482
14571483 for (elements) |elem_init, i| {
1458 const rl = if (elem_ty != .none)
1459 ResultLoc{ .coerced_ty = elem_ty }
1460 else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) rl: {
1484 const ri = if (elem_ty != .none)
1485 ResultInfo{ .rl = .{ .coerced_ty = elem_ty } }
1486 else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) ri: {
14611487 const ty_expr = try gz.add(.{
14621488 .tag = .elem_type_index,
14631489 .data = .{ .bin = .{
......@@ -1465,10 +1491,10 @@ fn arrayInitExprInner(
14651491 .rhs = @intToEnum(Zir.Inst.Ref, i),
14661492 } },
14671493 });
1468 break :rl ResultLoc{ .coerced_ty = ty_expr };
1469 } else ResultLoc{ .none = {} };
1494 break :ri ResultInfo{ .rl = .{ .coerced_ty = ty_expr } };
1495 } else ResultInfo{ .rl = .{ .none = {} } };
14701496
1471 const elem_ref = try expr(gz, scope, rl, elem_init);
1497 const elem_ref = try expr(gz, scope, ri, elem_init);
14721498 astgen.extra.items[extra_index] = @enumToInt(elem_ref);
14731499 extra_index += 1;
14741500 }
......@@ -1479,7 +1505,7 @@ fn arrayInitExprInner(
14791505fn arrayInitExprRlPtr(
14801506 gz: *GenZir,
14811507 scope: *Scope,
1482 rl: ResultLoc,
1508 ri: ResultInfo,
14831509 node: Ast.Node.Index,
14841510 result_ptr: Zir.Inst.Ref,
14851511 elements: []const Ast.Node.Index,
......@@ -1494,7 +1520,7 @@ fn arrayInitExprRlPtr(
14941520 defer as_scope.unstack();
14951521
14961522 const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements);
1497 return as_scope.finishCoercion(gz, rl, node, result, array_ty);
1523 return as_scope.finishCoercion(gz, ri, node, result, array_ty);
14981524}
14991525
15001526fn arrayInitExprRlPtrInner(
......@@ -1518,7 +1544,7 @@ fn arrayInitExprRlPtrInner(
15181544 });
15191545 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;
15201546 extra_index += 1;
1521 _ = try expr(gz, scope, .{ .ptr = .{ .inst = elem_ptr } }, elem_init);
1547 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = elem_ptr } } }, elem_init);
15221548 }
15231549
15241550 const tag: Zir.Inst.Tag = if (gz.force_comptime)
......@@ -1533,7 +1559,7 @@ fn arrayInitExprRlPtrInner(
15331559fn structInitExpr(
15341560 gz: *GenZir,
15351561 scope: *Scope,
1536 rl: ResultLoc,
1562 ri: ResultInfo,
15371563 node: Ast.Node.Index,
15381564 struct_init: Ast.full.StructInit,
15391565) InnerError!Zir.Inst.Ref {
......@@ -1542,7 +1568,7 @@ fn structInitExpr(
15421568
15431569 if (struct_init.ast.type_expr == 0) {
15441570 if (struct_init.ast.fields.len == 0) {
1545 return rvalue(gz, rl, .empty_struct, node);
1571 return rvalue(gz, ri, .empty_struct, node);
15461572 }
15471573 } else array: {
15481574 const node_tags = tree.nodes.items(.tag);
......@@ -1554,7 +1580,7 @@ fn structInitExpr(
15541580 if (struct_init.ast.fields.len == 0) {
15551581 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
15561582 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
1557 return rvalue(gz, rl, result, node);
1583 return rvalue(gz, ri, result, node);
15581584 }
15591585 break :array;
15601586 },
......@@ -1571,7 +1597,7 @@ fn structInitExpr(
15711597 .rhs = elem_type,
15721598 });
15731599 } else blk: {
1574 const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);
1600 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel);
15751601 break :blk try gz.addPlNode(
15761602 .array_type_sentinel,
15771603 struct_init.ast.type_expr,
......@@ -1583,11 +1609,11 @@ fn structInitExpr(
15831609 );
15841610 };
15851611 const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node);
1586 return rvalue(gz, rl, result, node);
1612 return rvalue(gz, ri, result, node);
15871613 }
15881614 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
15891615 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
1590 return rvalue(gz, rl, result, node);
1616 return rvalue(gz, ri, result, node);
15911617 } else {
15921618 return astgen.failNode(
15931619 struct_init.ast.type_expr,
......@@ -1597,7 +1623,7 @@ fn structInitExpr(
15971623 }
15981624 }
15991625
1600 switch (rl) {
1626 switch (ri.rl) {
16011627 .discard => {
16021628 if (struct_init.ast.type_expr != 0) {
16031629 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
......@@ -1626,26 +1652,26 @@ fn structInitExpr(
16261652 return structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);
16271653 }
16281654 },
1629 .ty, .ty_shift_operand, .coerced_ty => |ty_inst| {
1655 .ty, .coerced_ty => |ty_inst| {
16301656 if (struct_init.ast.type_expr == 0) {
16311657 const result = try structInitExprRlNone(gz, scope, node, struct_init, ty_inst, .struct_init_anon);
1632 return rvalue(gz, rl, result, node);
1658 return rvalue(gz, ri, result, node);
16331659 }
16341660 const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
16351661 _ = try gz.addUnNode(.validate_struct_init_ty, inner_ty_inst, node);
16361662 const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init);
1637 return rvalue(gz, rl, result, node);
1663 return rvalue(gz, ri, result, node);
16381664 },
1639 .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_res.inst),
1665 .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, ri, node, struct_init, ptr_res.inst),
16401666 .inferred_ptr => |ptr_inst| {
16411667 if (struct_init.ast.type_expr == 0) {
16421668 // We treat this case differently so that we don't get a crash when
16431669 // analyzing field_base_ptr against an alloc_inferred_mut.
16441670 // See corresponding logic in arrayInitExpr.
16451671 const result = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);
1646 return rvalue(gz, rl, result, node);
1672 return rvalue(gz, ri, result, node);
16471673 } else {
1648 return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst);
1674 return structInitExprRlPtr(gz, scope, ri, node, struct_init, ptr_inst);
16491675 }
16501676 },
16511677 .block_ptr => |block_gz| {
......@@ -1653,10 +1679,10 @@ fn structInitExpr(
16531679 // See corresponding logic in arrayInitExpr.
16541680 if (struct_init.ast.type_expr == 0 and astgen.isInferred(block_gz.rl_ptr)) {
16551681 const result = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);
1656 return rvalue(gz, rl, result, node);
1682 return rvalue(gz, ri, result, node);
16571683 }
16581684
1659 return structInitExprRlPtr(gz, scope, rl, node, struct_init, block_gz.rl_ptr);
1685 return structInitExprRlPtr(gz, scope, ri, node, struct_init, block_gz.rl_ptr);
16601686 },
16611687 }
16621688}
......@@ -1681,16 +1707,15 @@ fn structInitExprRlNone(
16811707 for (struct_init.ast.fields) |field_init| {
16821708 const name_token = tree.firstToken(field_init) - 2;
16831709 const str_index = try astgen.identAsString(name_token);
1684 const sub_rl: ResultLoc = if (ty_inst != .none)
1685 ResultLoc{ .ty = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{
1710 const sub_ri: ResultInfo = if (ty_inst != .none)
1711 ResultInfo{ .rl = .{ .ty = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{
16861712 .container_type = ty_inst,
16871713 .name_start = str_index,
1688 }) }
1689 else
1690 .none;
1714 }) } }
1715 else .{ .rl = .none };
16911716 setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{
16921717 .field_name = str_index,
1693 .init = try expr(gz, scope, sub_rl, field_init),
1718 .init = try expr(gz, scope, sub_ri, field_init),
16941719 });
16951720 extra_index += field_size;
16961721 }
......@@ -1701,7 +1726,7 @@ fn structInitExprRlNone(
17011726fn structInitExprRlPtr(
17021727 gz: *GenZir,
17031728 scope: *Scope,
1704 rl: ResultLoc,
1729 ri: ResultInfo,
17051730 node: Ast.Node.Index,
17061731 struct_init: Ast.full.StructInit,
17071732 result_ptr: Zir.Inst.Ref,
......@@ -1717,7 +1742,7 @@ fn structInitExprRlPtr(
17171742 defer as_scope.unstack();
17181743
17191744 const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr);
1720 return as_scope.finishCoercion(gz, rl, node, result, ty_inst);
1745 return as_scope.finishCoercion(gz, ri, node, result, ty_inst);
17211746}
17221747
17231748fn structInitExprRlPtrInner(
......@@ -1744,7 +1769,7 @@ fn structInitExprRlPtrInner(
17441769 });
17451770 astgen.extra.items[extra_index] = refToIndex(field_ptr).?;
17461771 extra_index += 1;
1747 _ = try expr(gz, scope, .{ .ptr = .{ .inst = field_ptr } }, field_init);
1772 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = field_ptr } } }, field_init);
17481773 }
17491774
17501775 const tag: Zir.Inst.Tag = if (gz.force_comptime)
......@@ -1782,7 +1807,7 @@ fn structInitExprRlTy(
17821807 });
17831808 setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{
17841809 .field_type = refToIndex(field_ty_inst).?,
1785 .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init),
1810 .init = try expr(gz, scope, .{ .rl = .{ .ty = field_ty_inst } }, field_init),
17861811 });
17871812 extra_index += field_size;
17881813 }
......@@ -1795,14 +1820,14 @@ fn structInitExprRlTy(
17951820fn comptimeExpr(
17961821 gz: *GenZir,
17971822 scope: *Scope,
1798 rl: ResultLoc,
1823 ri: ResultInfo,
17991824 node: Ast.Node.Index,
18001825) InnerError!Zir.Inst.Ref {
18011826 const prev_force_comptime = gz.force_comptime;
18021827 gz.force_comptime = true;
18031828 defer gz.force_comptime = prev_force_comptime;
18041829
1805 return expr(gz, scope, rl, node);
1830 return expr(gz, scope, ri, node);
18061831}
18071832
18081833/// This one is for an actual `comptime` syntax, and will emit a compile error if
......@@ -1811,7 +1836,7 @@ fn comptimeExpr(
18111836fn comptimeExprAst(
18121837 gz: *GenZir,
18131838 scope: *Scope,
1814 rl: ResultLoc,
1839 ri: ResultInfo,
18151840 node: Ast.Node.Index,
18161841) InnerError!Zir.Inst.Ref {
18171842 const astgen = gz.astgen;
......@@ -1822,11 +1847,50 @@ fn comptimeExprAst(
18221847 const node_datas = tree.nodes.items(.data);
18231848 const body_node = node_datas[node].lhs;
18241849 gz.force_comptime = true;
1825 const result = try expr(gz, scope, rl, body_node);
1850 const result = try expr(gz, scope, ri, body_node);
18261851 gz.force_comptime = false;
18271852 return result;
18281853}
18291854
1855/// Restore the error return trace index. Performs the restore only if the result is a non-error or
1856/// if the result location is a non-error-handling expression.
1857fn restoreErrRetIndex(
1858 gz: *GenZir,
1859 bt: GenZir.BranchTarget,
1860 ri: ResultInfo,
1861 node: Ast.Node.Index,
1862 result: Zir.Inst.Ref,
1863) !void {
1864 const op = switch (nodeMayEvalToError(gz.astgen.tree, node)) {
1865 .always => return, // never restore/pop
1866 .never => .none, // always restore/pop
1867 .maybe => switch (ri.ctx) {
1868 .error_handling_expr, .@"return", .fn_arg, .const_init => switch (ri.rl) {
1869 .ptr => |ptr_res| try gz.addUnNode(.load, ptr_res.inst, node),
1870 .inferred_ptr => |ptr| try gz.addUnNode(.load, ptr, node),
1871 .block_ptr => |block_scope| if (block_scope.rvalue_rl_count != block_scope.break_count) b: {
1872 // The result location may have been used by this expression, in which case
1873 // the operand is not the result and we need to load the rl ptr.
1874 switch (gz.astgen.instructions.items(.tag)[Zir.refToIndex(block_scope.rl_ptr).?]) {
1875 .alloc_inferred, .alloc_inferred_mut => {
1876 // This is a terrible workaround for Sema's inability to load from a .alloc_inferred ptr
1877 // before its type has been resolved. The operand we use here instead is not guaranteed
1878 // to be valid, and when it's not, we will pop error traces prematurely.
1879 //
1880 // TODO: Update this to do a proper load from the rl_ptr, once Sema can support it.
1881 break :b result;
1882 },
1883 else => break :b try gz.addUnNode(.load, block_scope.rl_ptr, node),
1884 }
1885 } else result,
1886 else => result,
1887 },
1888 else => .none, // always restore/pop
1889 },
1890 };
1891 _ = try gz.addRestoreErrRetIndex(bt, .{ .if_non_error = op });
1892}
1893
18301894fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
18311895 const astgen = parent_gz.astgen;
18321896 const tree = astgen.tree;
......@@ -1842,6 +1906,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
18421906 const block_gz = scope.cast(GenZir).?;
18431907
18441908 if (block_gz.cur_defer_node != 0) {
1909 // We are breaking out of a `defer` block.
18451910 return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{
18461911 try astgen.errNoteNode(
18471912 block_gz.cur_defer_node,
......@@ -1862,9 +1927,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
18621927 } else if (block_gz.break_block != 0) {
18631928 break :blk block_gz.break_block;
18641929 }
1930 // If not the target, start over with the parent
18651931 scope = block_gz.parent;
18661932 continue;
18671933 };
1934 // If we made it here, this block is the target of the break expr
18681935
18691936 const break_tag: Zir.Inst.Tag = if (block_gz.is_inline or block_gz.force_comptime)
18701937 .break_inline
......@@ -1874,17 +1941,25 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
18741941 if (rhs == 0) {
18751942 try genDefers(parent_gz, scope, parent_scope, .normal_only);
18761943
1944 // As our last action before the break, "pop" the error trace if needed
1945 if (!block_gz.force_comptime)
1946 _ = try parent_gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always);
1947
18771948 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
18781949 return Zir.Inst.Ref.unreachable_value;
18791950 }
18801951 block_gz.break_count += 1;
18811952
1882 const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_loc, rhs, node);
1953 const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_info, rhs, node);
18831954 const search_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
18841955
18851956 try genDefers(parent_gz, scope, parent_scope, .normal_only);
18861957
1887 switch (block_gz.break_result_loc) {
1958 // As our last action before the break, "pop" the error trace if needed
1959 if (!block_gz.force_comptime)
1960 try restoreErrRetIndex(parent_gz, .{ .block = block_inst }, block_gz.break_result_info, rhs, operand);
1961
1962 switch (block_gz.break_result_info.rl) {
18881963 .block_ptr => {
18891964 const br = try parent_gz.addBreak(break_tag, block_inst, operand);
18901965 try block_gz.labeled_breaks.append(astgen.gpa, .{ .br = br, .search = search_index });
......@@ -1990,7 +2065,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
19902065fn blockExpr(
19912066 gz: *GenZir,
19922067 scope: *Scope,
1993 rl: ResultLoc,
2068 ri: ResultInfo,
19942069 block_node: Ast.Node.Index,
19952070 statements: []const Ast.Node.Index,
19962071) InnerError!Zir.Inst.Ref {
......@@ -2006,12 +2081,38 @@ fn blockExpr(
20062081 if (token_tags[lbrace - 1] == .colon and
20072082 token_tags[lbrace - 2] == .identifier)
20082083 {
2009 return labeledBlockExpr(gz, scope, rl, block_node, statements);
2084 return labeledBlockExpr(gz, scope, ri, block_node, statements);
2085 }
2086
2087 if (!gz.force_comptime) {
2088 // Since this block is unlabeled, its control flow is effectively linear and we
2089 // can *almost* get away with inlining the block here. However, we actually need
2090 // to preserve the .block for Sema, to properly pop the error return trace.
2091
2092 const block_tag: Zir.Inst.Tag = .block;
2093 const block_inst = try gz.makeBlockInst(block_tag, block_node);
2094 try gz.instructions.append(astgen.gpa, block_inst);
2095
2096 var block_scope = gz.makeSubBlock(scope);
2097 defer block_scope.unstack();
2098
2099 try blockExprStmts(&block_scope, &block_scope.base, statements);
2100
2101 if (!block_scope.endsWithNoReturn()) {
2102 // As our last action before the break, "pop" the error trace if needed
2103 _ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always);
2104
2105 const break_tag: Zir.Inst.Tag = if (block_scope.force_comptime) .break_inline else .@"break";
2106 _ = try block_scope.addBreak(break_tag, block_inst, .void_value);
2107 }
2108
2109 try block_scope.setBlockBody(block_inst);
2110 } else {
2111 var sub_gz = gz.makeSubBlock(scope);
2112 try blockExprStmts(&sub_gz, &sub_gz.base, statements);
20102113 }
20112114
2012 var sub_gz = gz.makeSubBlock(scope);
2013 try blockExprStmts(&sub_gz, &sub_gz.base, statements);
2014 return rvalue(gz, rl, .void_value, block_node);
2115 return rvalue(gz, ri, .void_value, block_node);
20152116}
20162117
20172118fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.TokenIndex) !void {
......@@ -2049,7 +2150,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke
20492150fn labeledBlockExpr(
20502151 gz: *GenZir,
20512152 parent_scope: *Scope,
2052 rl: ResultLoc,
2153 ri: ResultInfo,
20532154 block_node: Ast.Node.Index,
20542155 statements: []const Ast.Node.Index,
20552156) InnerError!Zir.Inst.Ref {
......@@ -2078,12 +2179,15 @@ fn labeledBlockExpr(
20782179 .token = label_token,
20792180 .block_inst = block_inst,
20802181 };
2081 block_scope.setBreakResultLoc(rl);
2182 block_scope.setBreakResultInfo(ri);
20822183 defer block_scope.unstack();
20832184 defer block_scope.labeled_breaks.deinit(astgen.gpa);
20842185
20852186 try blockExprStmts(&block_scope, &block_scope.base, statements);
20862187 if (!block_scope.endsWithNoReturn()) {
2188 // As our last action before the return, "pop" the error trace if needed
2189 _ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always);
2190
20872191 const break_tag: Zir.Inst.Tag = if (block_scope.force_comptime) .break_inline else .@"break";
20882192 _ = try block_scope.addBreak(break_tag, block_inst, .void_value);
20892193 }
......@@ -2094,7 +2198,7 @@ fn labeledBlockExpr(
20942198
20952199 const zir_datas = gz.astgen.instructions.items(.data);
20962200 const zir_tags = gz.astgen.instructions.items(.tag);
2097 const strat = rl.strategy(&block_scope);
2201 const strat = ri.rl.strategy(&block_scope);
20982202 switch (strat.tag) {
20992203 .break_void => {
21002204 // The code took advantage of the result location as a pointer.
......@@ -2107,7 +2211,8 @@ fn labeledBlockExpr(
21072211 return indexToRef(block_inst);
21082212 },
21092213 .break_operand => {
2110 // All break operands are values that did not use the result location pointer.
2214 // All break operands are values that did not use the result location pointer
2215 // (except for a single .store_to_block_ptr inst which we re-write here).
21112216 // The break instructions need to have their operands coerced if the
21122217 // block's result location is a `ty`. In this case we overwrite the
21132218 // `store_to_block_ptr` instruction with an `as` instruction and repurpose
......@@ -2135,9 +2240,9 @@ fn labeledBlockExpr(
21352240 }
21362241 try block_scope.setBlockBody(block_inst);
21372242 const block_ref = indexToRef(block_inst);
2138 switch (rl) {
2243 switch (ri.rl) {
21392244 .ref => return block_ref,
2140 else => return rvalue(gz, rl, block_ref, block_node),
2245 else => return rvalue(gz, ri, block_ref, block_node),
21412246 }
21422247 },
21432248 }
......@@ -2208,12 +2313,12 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
22082313 continue;
22092314 },
22102315
2211 .while_simple => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileSimple(inner_node), true),
2212 .while_cont => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileCont(inner_node), true),
2213 .@"while" => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileFull(inner_node), true),
2316 .while_simple => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileSimple(inner_node), true),
2317 .while_cont => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileCont(inner_node), true),
2318 .@"while" => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileFull(inner_node), true),
22142319
2215 .for_simple => _ = try forExpr(gz, scope, .discard, inner_node, tree.forSimple(inner_node), true),
2216 .@"for" => _ = try forExpr(gz, scope, .discard, inner_node, tree.forFull(inner_node), true),
2320 .for_simple => _ = try forExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.forSimple(inner_node), true),
2321 .@"for" => _ = try forExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.forFull(inner_node), true),
22172322
22182323 else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node),
22192324 // zig fmt: on
......@@ -2234,7 +2339,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
22342339 try emitDbgNode(gz, statement);
22352340 // We need to emit an error if the result is not `noreturn` or `void`, but
22362341 // we want to avoid adding the ZIR instruction if possible for performance.
2237 const maybe_unused_result = try expr(gz, scope, .none, statement);
2342 const maybe_unused_result = try expr(gz, scope, .{ .rl = .none }, statement);
22382343 return addEnsureResult(gz, maybe_unused_result, statement);
22392344}
22402345
......@@ -2533,6 +2638,8 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
25332638 .validate_array_init_ty,
25342639 .validate_struct_init_ty,
25352640 .validate_deref,
2641 .save_err_ret_index,
2642 .restore_err_ret_index,
25362643 => break :b true,
25372644
25382645 .@"defer" => unreachable,
......@@ -2799,7 +2906,7 @@ fn varDecl(
27992906 }
28002907
28012908 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0)
2802 try expr(gz, scope, align_rl, var_decl.ast.align_node)
2909 try expr(gz, scope, align_ri, var_decl.ast.align_node)
28032910 else
28042911 .none;
28052912
......@@ -2816,16 +2923,22 @@ fn varDecl(
28162923 if (align_inst == .none and
28172924 !nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node, type_node != 0))
28182925 {
2819 const result_loc: ResultLoc = if (type_node != 0) .{
2820 .ty = try typeExpr(gz, scope, type_node),
2821 } else .none;
2926 const result_info: ResultInfo = if (type_node != 0) .{
2927 .rl = .{ .ty = try typeExpr(gz, scope, type_node) },
2928 .ctx = .const_init,
2929 } else .{ .rl = .none, .ctx = .const_init };
28222930 const prev_anon_name_strategy = gz.anon_name_strategy;
28232931 gz.anon_name_strategy = .dbg_var;
2824 const init_inst = try reachableExpr(gz, scope, result_loc, var_decl.ast.init_node, node);
2932 const init_inst = try reachableExpr(gz, scope, result_info, var_decl.ast.init_node, node);
28252933 gz.anon_name_strategy = prev_anon_name_strategy;
28262934
28272935 try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);
28282936
2937 // The const init expression may have modified the error return trace, so signal
2938 // to Sema that it should save the new index for restoring later.
2939 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))
2940 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
2941
28292942 const sub_scope = try block_arena.create(Scope.LocalVal);
28302943 sub_scope.* = .{
28312944 .parent = scope,
......@@ -2891,8 +3004,13 @@ fn varDecl(
28913004 init_scope.rl_ptr = alloc;
28923005 init_scope.rl_ty_inst = .none;
28933006 }
2894 const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope };
2895 const init_inst = try reachableExpr(&init_scope, &init_scope.base, init_result_loc, var_decl.ast.init_node, node);
3007 const init_result_info: ResultInfo = .{ .rl = .{ .block_ptr = &init_scope }, .ctx = .const_init };
3008 const init_inst = try reachableExpr(&init_scope, &init_scope.base, init_result_info, var_decl.ast.init_node, node);
3009
3010 // The const init expression may have modified the error return trace, so signal
3011 // to Sema that it should save the new index for restoring later.
3012 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))
3013 _ = try init_scope.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
28963014
28973015 const zir_tags = astgen.instructions.items(.tag);
28983016 const zir_datas = astgen.instructions.items(.data);
......@@ -2981,7 +3099,7 @@ fn varDecl(
29813099 const is_comptime = var_decl.comptime_token != null or gz.force_comptime;
29823100 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
29833101 const var_data: struct {
2984 result_loc: ResultLoc,
3102 result_info: ResultInfo,
29853103 alloc: Zir.Inst.Ref,
29863104 } = if (var_decl.ast.type_node != 0) a: {
29873105 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
......@@ -3003,7 +3121,7 @@ fn varDecl(
30033121 }
30043122 };
30053123 gz.rl_ty_inst = type_inst;
3006 break :a .{ .alloc = alloc, .result_loc = .{ .ptr = .{ .inst = alloc } } };
3124 break :a .{ .alloc = alloc, .result_info = .{ .rl = .{ .ptr = .{ .inst = alloc } } } };
30073125 } else a: {
30083126 const alloc = alloc: {
30093127 if (align_inst == .none) {
......@@ -3024,11 +3142,11 @@ fn varDecl(
30243142 };
30253143 gz.rl_ty_inst = .none;
30263144 resolve_inferred_alloc = alloc;
3027 break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } };
3145 break :a .{ .alloc = alloc, .result_info = .{ .rl = .{ .inferred_ptr = alloc } } };
30283146 };
30293147 const prev_anon_name_strategy = gz.anon_name_strategy;
30303148 gz.anon_name_strategy = .dbg_var;
3031 _ = try reachableExprComptime(gz, scope, var_data.result_loc, var_decl.ast.init_node, node, is_comptime);
3149 _ = try reachableExprComptime(gz, scope, var_data.result_info, var_decl.ast.init_node, node, is_comptime);
30323150 gz.anon_name_strategy = prev_anon_name_strategy;
30333151 if (resolve_inferred_alloc != .none) {
30343152 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
......@@ -3098,15 +3216,15 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi
30983216 // This intentionally does not support `@"_"` syntax.
30993217 const ident_name = tree.tokenSlice(main_tokens[lhs]);
31003218 if (mem.eql(u8, ident_name, "_")) {
3101 _ = try expr(gz, scope, .discard, rhs);
3219 _ = try expr(gz, scope, .{ .rl = .discard }, rhs);
31023220 return;
31033221 }
31043222 }
31053223 const lvalue = try lvalExpr(gz, scope, lhs);
3106 _ = try expr(gz, scope, .{ .ptr = .{
3224 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{
31073225 .inst = lvalue,
31083226 .src_node = infix_node,
3109 } }, rhs);
3227 } } }, rhs);
31103228}
31113229
31123230fn assignOp(
......@@ -3123,7 +3241,7 @@ fn assignOp(
31233241 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
31243242 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
31253243 const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node);
3126 const rhs = try expr(gz, scope, .{ .coerced_ty = lhs_type }, node_datas[infix_node].rhs);
3244 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs);
31273245
31283246 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
31293247 .lhs = lhs,
......@@ -3146,7 +3264,7 @@ fn assignShift(
31463264 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
31473265 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
31483266 const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node);
3149 const rhs = try expr(gz, scope, .{ .ty = rhs_type }, node_datas[infix_node].rhs);
3267 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, node_datas[infix_node].rhs);
31503268
31513269 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
31523270 .lhs = lhs,
......@@ -3164,7 +3282,7 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE
31643282 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
31653283 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
31663284 // Saturating shift-left allows any integer type for both the LHS and RHS.
3167 const rhs = try expr(gz, scope, .none, node_datas[infix_node].rhs);
3285 const rhs = try expr(gz, scope, .{ .rl = .none }, node_datas[infix_node].rhs);
31683286
31693287 const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{
31703288 .lhs = lhs,
......@@ -3176,7 +3294,7 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE
31763294fn ptrType(
31773295 gz: *GenZir,
31783296 scope: *Scope,
3179 rl: ResultLoc,
3297 ri: ResultInfo,
31803298 node: Ast.Node.Index,
31813299 ptr_info: Ast.full.PtrType,
31823300) InnerError!Zir.Inst.Ref {
......@@ -3194,21 +3312,21 @@ fn ptrType(
31943312 var trailing_count: u32 = 0;
31953313
31963314 if (ptr_info.ast.sentinel != 0) {
3197 sentinel_ref = try expr(gz, scope, .{ .ty = elem_type }, ptr_info.ast.sentinel);
3315 sentinel_ref = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, ptr_info.ast.sentinel);
31983316 trailing_count += 1;
31993317 }
32003318 if (ptr_info.ast.align_node != 0) {
3201 align_ref = try expr(gz, scope, coerced_align_rl, ptr_info.ast.align_node);
3319 align_ref = try expr(gz, scope, coerced_align_ri, ptr_info.ast.align_node);
32023320 trailing_count += 1;
32033321 }
32043322 if (ptr_info.ast.addrspace_node != 0) {
3205 addrspace_ref = try expr(gz, scope, .{ .ty = .address_space_type }, ptr_info.ast.addrspace_node);
3323 addrspace_ref = try expr(gz, scope, .{ .rl = .{ .ty = .address_space_type } }, ptr_info.ast.addrspace_node);
32063324 trailing_count += 1;
32073325 }
32083326 if (ptr_info.ast.bit_range_start != 0) {
32093327 assert(ptr_info.ast.bit_range_end != 0);
3210 bit_start_ref = try expr(gz, scope, .{ .coerced_ty = .u16_type }, ptr_info.ast.bit_range_start);
3211 bit_end_ref = try expr(gz, scope, .{ .coerced_ty = .u16_type }, ptr_info.ast.bit_range_end);
3328 bit_start_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start);
3329 bit_end_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_end);
32123330 trailing_count += 2;
32133331 }
32143332
......@@ -3255,10 +3373,10 @@ fn ptrType(
32553373 } });
32563374 gz.instructions.appendAssumeCapacity(new_index);
32573375
3258 return rvalue(gz, rl, result, node);
3376 return rvalue(gz, ri, result, node);
32593377}
32603378
3261fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Zir.Inst.Ref {
3379fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref {
32623380 const astgen = gz.astgen;
32633381 const tree = astgen.tree;
32643382 const node_datas = tree.nodes.items(.data);
......@@ -3271,17 +3389,17 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Z
32713389 {
32723390 return astgen.failNode(len_node, "unable to infer array size", .{});
32733391 }
3274 const len = try expr(gz, scope, .{ .coerced_ty = .usize_type }, len_node);
3392 const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node);
32753393 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);
32763394
32773395 const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{
32783396 .lhs = len,
32793397 .rhs = elem_type,
32803398 });
3281 return rvalue(gz, rl, result, node);
3399 return rvalue(gz, ri, result, node);
32823400}
32833401
3284fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Zir.Inst.Ref {
3402fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref {
32853403 const astgen = gz.astgen;
32863404 const tree = astgen.tree;
32873405 const node_datas = tree.nodes.items(.data);
......@@ -3295,16 +3413,16 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I
32953413 {
32963414 return astgen.failNode(len_node, "unable to infer array size", .{});
32973415 }
3298 const len = try reachableExpr(gz, scope, .{ .coerced_ty = .usize_type }, len_node, node);
3416 const len = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node);
32993417 const elem_type = try typeExpr(gz, scope, extra.elem_type);
3300 const sentinel = try reachableExpr(gz, scope, .{ .coerced_ty = elem_type }, extra.sentinel, node);
3418 const sentinel = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = elem_type } }, extra.sentinel, node);
33013419
33023420 const result = try gz.addPlNode(.array_type_sentinel, node, Zir.Inst.ArrayTypeSentinel{
33033421 .len = len,
33043422 .elem_type = elem_type,
33053423 .sentinel = sentinel,
33063424 });
3307 return rvalue(gz, rl, result, node);
3425 return rvalue(gz, ri, result, node);
33083426}
33093427
33103428const WipMembers = struct {
......@@ -3540,7 +3658,7 @@ fn fnDecl(
35403658 assert(param_type_node != 0);
35413659 var param_gz = decl_gz.makeSubBlock(scope);
35423660 defer param_gz.unstack();
3543 const param_type = try expr(&param_gz, params_scope, coerced_type_rl, param_type_node);
3661 const param_type = try expr(&param_gz, params_scope, coerced_type_ri, param_type_node);
35443662 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
35453663 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);
35463664
......@@ -3589,7 +3707,7 @@ fn fnDecl(
35893707 var align_gz = decl_gz.makeSubBlock(params_scope);
35903708 defer align_gz.unstack();
35913709 const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
3592 const inst = try expr(&decl_gz, params_scope, coerced_align_rl, fn_proto.ast.align_expr);
3710 const inst = try expr(&decl_gz, params_scope, coerced_align_ri, fn_proto.ast.align_expr);
35933711 if (align_gz.instructionsSlice().len == 0) {
35943712 // In this case we will send a len=0 body which can be encoded more efficiently.
35953713 break :inst inst;
......@@ -3601,7 +3719,7 @@ fn fnDecl(
36013719 var addrspace_gz = decl_gz.makeSubBlock(params_scope);
36023720 defer addrspace_gz.unstack();
36033721 const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: {
3604 const inst = try expr(&decl_gz, params_scope, .{ .coerced_ty = .address_space_type }, fn_proto.ast.addrspace_expr);
3722 const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .address_space_type } }, fn_proto.ast.addrspace_expr);
36053723 if (addrspace_gz.instructionsSlice().len == 0) {
36063724 // In this case we will send a len=0 body which can be encoded more efficiently.
36073725 break :inst inst;
......@@ -3613,7 +3731,7 @@ fn fnDecl(
36133731 var section_gz = decl_gz.makeSubBlock(params_scope);
36143732 defer section_gz.unstack();
36153733 const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
3616 const inst = try expr(&decl_gz, params_scope, .{ .coerced_ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
3734 const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .const_slice_u8_type } }, fn_proto.ast.section_expr);
36173735 if (section_gz.instructionsSlice().len == 0) {
36183736 // In this case we will send a len=0 body which can be encoded more efficiently.
36193737 break :inst inst;
......@@ -3636,7 +3754,7 @@ fn fnDecl(
36363754 const inst = try expr(
36373755 &decl_gz,
36383756 params_scope,
3639 .{ .coerced_ty = .calling_convention_type },
3757 .{ .rl = .{ .coerced_ty = .calling_convention_type } },
36403758 fn_proto.ast.callconv_expr,
36413759 );
36423760 if (cc_gz.instructionsSlice().len == 0) {
......@@ -3658,7 +3776,7 @@ fn fnDecl(
36583776 var ret_gz = decl_gz.makeSubBlock(params_scope);
36593777 defer ret_gz.unstack();
36603778 const ret_ref: Zir.Inst.Ref = inst: {
3661 const inst = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);
3779 const inst = try expr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type);
36623780 if (ret_gz.instructionsSlice().len == 0) {
36633781 // In this case we will send a len=0 body which can be encoded more efficiently.
36643782 break :inst inst;
......@@ -3712,10 +3830,13 @@ fn fnDecl(
37123830 const lbrace_line = astgen.source_line - decl_gz.decl_line;
37133831 const lbrace_column = astgen.source_column;
37143832
3715 _ = try expr(&fn_gz, params_scope, .none, body_node);
3833 _ = try expr(&fn_gz, params_scope, .{ .rl = .none }, body_node);
37163834 try checkUsed(gz, &fn_gz.base, params_scope);
37173835
37183836 if (!fn_gz.endsWithNoReturn()) {
3837 // As our last action before the return, "pop" the error trace if needed
3838 _ = try gz.addRestoreErrRetIndex(.ret, .always);
3839
37193840 // Since we are adding the return instruction here, we must handle the coercion.
37203841 // We do this by using the `ret_tok` instruction.
37213842 _ = try fn_gz.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node));
......@@ -3808,13 +3929,13 @@ fn globalVarDecl(
38083929 break :blk token_tags[maybe_extern_token] == .keyword_extern;
38093930 };
38103931 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: {
3811 break :inst try expr(&block_scope, &block_scope.base, align_rl, var_decl.ast.align_node);
3932 break :inst try expr(&block_scope, &block_scope.base, align_ri, var_decl.ast.align_node);
38123933 };
38133934 const addrspace_inst: Zir.Inst.Ref = if (var_decl.ast.addrspace_node == 0) .none else inst: {
3814 break :inst try expr(&block_scope, &block_scope.base, .{ .ty = .address_space_type }, var_decl.ast.addrspace_node);
3935 break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node);
38153936 };
38163937 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {
3817 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);
3938 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .const_slice_u8_type } }, var_decl.ast.section_node);
38183939 };
38193940 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;
38203941 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);
......@@ -3854,7 +3975,7 @@ fn globalVarDecl(
38543975 try expr(
38553976 &block_scope,
38563977 &block_scope.base,
3857 .{ .ty = .type_type },
3978 .{ .rl = .{ .ty = .type_type } },
38583979 var_decl.ast.type_node,
38593980 )
38603981 else
......@@ -3863,7 +3984,7 @@ fn globalVarDecl(
38633984 const init_inst = try expr(
38643985 &block_scope,
38653986 &block_scope.base,
3866 if (type_inst != .none) .{ .ty = type_inst } else .none,
3987 if (type_inst != .none) .{ .rl = .{ .ty = type_inst } } else .{ .rl = .none },
38673988 var_decl.ast.init_node,
38683989 );
38693990
......@@ -3952,7 +4073,7 @@ fn comptimeDecl(
39524073 };
39534074 defer decl_block.unstack();
39544075
3955 const block_result = try expr(&decl_block, &decl_block.base, .none, body_node);
4076 const block_result = try expr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node);
39564077 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {
39574078 _ = try decl_block.addBreak(.break_inline, block_inst, .void_value);
39584079 }
......@@ -4156,8 +4277,12 @@ fn testDecl(
41564277 const lbrace_line = astgen.source_line - decl_block.decl_line;
41574278 const lbrace_column = astgen.source_column;
41584279
4159 const block_result = try expr(&fn_block, &fn_block.base, .none, body_node);
4280 const block_result = try expr(&fn_block, &fn_block.base, .{ .rl = .none }, body_node);
41604281 if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) {
4282
4283 // As our last action before the return, "pop" the error trace if needed
4284 _ = try gz.addRestoreErrRetIndex(.ret, .always);
4285
41614286 // Since we are adding the return instruction here, we must handle the coercion.
41624287 // We do this by using the `ret_tok` instruction.
41634288 _ = try fn_block.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node));
......@@ -4370,7 +4495,7 @@ fn structDeclInner(
43704495 if (layout == .Packed) {
43714496 try astgen.appendErrorNode(member.ast.align_expr, "unable to override alignment of packed struct fields", .{});
43724497 }
4373 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_rl, member.ast.align_expr);
4498 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, member.ast.align_expr);
43744499 if (!block_scope.endsWithNoReturn()) {
43754500 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);
43764501 }
......@@ -4383,9 +4508,9 @@ fn structDeclInner(
43834508 }
43844509
43854510 if (have_value) {
4386 const rl: ResultLoc = if (field_type == .none) .none else .{ .coerced_ty = field_type };
4511 const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = field_type } };
43874512
4388 const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr);
4513 const default_inst = try expr(&block_scope, &namespace.base, ri, member.ast.value_expr);
43894514 if (!block_scope.endsWithNoReturn()) {
43904515 _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst);
43914516 }
......@@ -4514,7 +4639,7 @@ fn unionDeclInner(
45144639 return astgen.failNode(member_node, "union field missing type", .{});
45154640 }
45164641 if (have_align) {
4517 const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr);
4642 const align_inst = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .u32_type } }, member.ast.align_expr);
45184643 wip_members.appendToField(@enumToInt(align_inst));
45194644 }
45204645 if (have_value) {
......@@ -4546,7 +4671,7 @@ fn unionDeclInner(
45464671 },
45474672 );
45484673 }
4549 const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);
4674 const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);
45504675 wip_members.appendToField(@enumToInt(tag_value));
45514676 }
45524677 }
......@@ -4584,7 +4709,7 @@ fn unionDeclInner(
45844709fn containerDecl(
45854710 gz: *GenZir,
45864711 scope: *Scope,
4587 rl: ResultLoc,
4712 ri: ResultInfo,
45884713 node: Ast.Node.Index,
45894714 container_decl: Ast.full.ContainerDecl,
45904715) InnerError!Zir.Inst.Ref {
......@@ -4610,7 +4735,7 @@ fn containerDecl(
46104735 } else std.builtin.Type.ContainerLayout.Auto;
46114736
46124737 const result = try structDeclInner(gz, scope, node, container_decl, layout, container_decl.ast.arg);
4613 return rvalue(gz, rl, result, node);
4738 return rvalue(gz, ri, result, node);
46144739 },
46154740 .keyword_union => {
46164741 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
......@@ -4620,7 +4745,7 @@ fn containerDecl(
46204745 } else std.builtin.Type.ContainerLayout.Auto;
46214746
46224747 const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, container_decl.ast.arg, container_decl.ast.enum_token);
4623 return rvalue(gz, rl, result, node);
4748 return rvalue(gz, ri, result, node);
46244749 },
46254750 .keyword_enum => {
46264751 if (container_decl.layout_token) |t| {
......@@ -4750,7 +4875,7 @@ fn containerDecl(
47504875 _ = try astgen.scanDecls(&namespace, container_decl.ast.members);
47514876
47524877 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
4753 try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg)
4878 try comptimeExpr(&block_scope, &namespace.base, .{ .rl = .{ .ty = .type_type } }, container_decl.ast.arg)
47544879 else
47554880 .none;
47564881
......@@ -4794,7 +4919,7 @@ fn containerDecl(
47944919 },
47954920 );
47964921 }
4797 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr);
4922 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);
47984923 wip_members.appendToField(@enumToInt(tag_value_inst));
47994924 }
48004925 }
......@@ -4825,7 +4950,7 @@ fn containerDecl(
48254950
48264951 block_scope.unstack();
48274952 try gz.addNamespaceCaptures(&namespace);
4828 return rvalue(gz, rl, indexToRef(decl_inst), node);
4953 return rvalue(gz, ri, indexToRef(decl_inst), node);
48294954 },
48304955 .keyword_opaque => {
48314956 assert(container_decl.ast.arg == 0);
......@@ -4875,7 +5000,7 @@ fn containerDecl(
48755000 astgen.extra.appendSliceAssumeCapacity(decls_slice);
48765001
48775002 try gz.addNamespaceCaptures(&namespace);
4878 return rvalue(gz, rl, indexToRef(decl_inst), node);
5003 return rvalue(gz, ri, indexToRef(decl_inst), node);
48795004 },
48805005 else => unreachable,
48815006 }
......@@ -5006,7 +5131,7 @@ fn containerMember(
50065131 return .decl;
50075132}
50085133
5009fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
5134fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
50105135 const astgen = gz.astgen;
50115136 const gpa = astgen.gpa;
50125137 const tree = astgen.tree;
......@@ -5061,13 +5186,13 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir
50615186 .fields_len = @intCast(u32, fields_len),
50625187 });
50635188 const result = try gz.addPlNodePayloadIndex(.error_set_decl, node, payload_index);
5064 return rvalue(gz, rl, result, node);
5189 return rvalue(gz, ri, result, node);
50655190}
50665191
50675192fn tryExpr(
50685193 parent_gz: *GenZir,
50695194 scope: *Scope,
5070 rl: ResultLoc,
5195 ri: ResultInfo,
50715196 node: Ast.Node.Index,
50725197 operand_node: Ast.Node.Index,
50735198) InnerError!Zir.Inst.Ref {
......@@ -5097,15 +5222,15 @@ fn tryExpr(
50975222 const try_line = astgen.source_line - parent_gz.decl_line;
50985223 const try_column = astgen.source_column;
50995224
5100 const operand_rl: ResultLoc = switch (rl) {
5101 .ref => .ref,
5102 else => .none,
5225 const operand_ri: ResultInfo = switch (ri.rl) {
5226 .ref => .{ .rl = .ref, .ctx = .error_handling_expr },
5227 else => .{ .rl = .none, .ctx = .error_handling_expr },
51035228 };
5104 // This could be a pointer or value depending on the `rl` parameter.
5105 const operand = try reachableExpr(parent_gz, scope, operand_rl, operand_node, node);
5229 // This could be a pointer or value depending on the `ri` parameter.
5230 const operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, node);
51065231 const is_inline = parent_gz.force_comptime;
51075232 const is_inline_bit = @as(u2, @boolToInt(is_inline));
5108 const is_ptr_bit = @as(u2, @boolToInt(operand_rl == .ref)) << 1;
5233 const is_ptr_bit = @as(u2, @boolToInt(operand_ri.rl == .ref)) << 1;
51095234 const block_tag: Zir.Inst.Tag = switch (is_inline_bit | is_ptr_bit) {
51105235 0b00 => .@"try",
51115236 0b01 => .@"try",
......@@ -5120,7 +5245,7 @@ fn tryExpr(
51205245 var else_scope = parent_gz.makeSubBlock(scope);
51215246 defer else_scope.unstack();
51225247
5123 const err_tag = switch (rl) {
5248 const err_tag = switch (ri.rl) {
51245249 .ref => Zir.Inst.Tag.err_union_code_ptr,
51255250 else => Zir.Inst.Tag.err_union_code,
51265251 };
......@@ -5131,16 +5256,16 @@ fn tryExpr(
51315256
51325257 try else_scope.setTryBody(try_inst, operand);
51335258 const result = indexToRef(try_inst);
5134 switch (rl) {
5259 switch (ri.rl) {
51355260 .ref => return result,
5136 else => return rvalue(parent_gz, rl, result, node),
5261 else => return rvalue(parent_gz, ri, result, node),
51375262 }
51385263}
51395264
51405265fn orelseCatchExpr(
51415266 parent_gz: *GenZir,
51425267 scope: *Scope,
5143 rl: ResultLoc,
5268 ri: ResultInfo,
51445269 node: Ast.Node.Index,
51455270 lhs: Ast.Node.Index,
51465271 cond_op: Zir.Inst.Tag,
......@@ -5152,20 +5277,22 @@ fn orelseCatchExpr(
51525277 const astgen = parent_gz.astgen;
51535278 const tree = astgen.tree;
51545279
5280 const do_err_trace = astgen.fn_block != null and (cond_op == .is_non_err or cond_op == .is_non_err_ptr);
5281
51555282 var block_scope = parent_gz.makeSubBlock(scope);
5156 block_scope.setBreakResultLoc(rl);
5283 block_scope.setBreakResultInfo(ri);
51575284 defer block_scope.unstack();
51585285
5159 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
5160 .ref => .ref,
5161 else => .none,
5286 const operand_ri: ResultInfo = switch (block_scope.break_result_info.rl) {
5287 .ref => .{ .rl = .ref, .ctx = if (do_err_trace) .error_handling_expr else .none },
5288 else => .{ .rl = .none, .ctx = if (do_err_trace) .error_handling_expr else .none },
51625289 };
51635290 block_scope.break_count += 1;
5164 // This could be a pointer or value depending on the `operand_rl` parameter.
5165 // We cannot use `block_scope.break_result_loc` because that has the bare
5291 // This could be a pointer or value depending on the `operand_ri` parameter.
5292 // We cannot use `block_scope.break_result_info` because that has the bare
51665293 // type, whereas this expression has the optional type. Later we make
51675294 // up for this fact by calling rvalue on the else branch.
5168 const operand = try reachableExpr(&block_scope, &block_scope.base, operand_rl, lhs, rhs);
5295 const operand = try reachableExpr(&block_scope, &block_scope.base, operand_ri, lhs, rhs);
51695296 const cond = try block_scope.addUnNode(cond_op, operand, node);
51705297 const condbr = try block_scope.addCondBr(.condbr, node);
51715298
......@@ -5179,14 +5306,19 @@ fn orelseCatchExpr(
51795306
51805307 // This could be a pointer or value depending on `unwrap_op`.
51815308 const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);
5182 const then_result = switch (rl) {
5309 const then_result = switch (ri.rl) {
51835310 .ref => unwrapped_payload,
5184 else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node),
5311 else => try rvalue(&then_scope, block_scope.break_result_info, unwrapped_payload, node),
51855312 };
51865313
51875314 var else_scope = block_scope.makeSubBlock(scope);
51885315 defer else_scope.unstack();
51895316
5317 // We know that the operand (almost certainly) modified the error return trace,
5318 // so signal to Sema that it should save the new index for restoring later.
5319 if (do_err_trace and nodeMayAppendToErrorTrace(tree, lhs))
5320 _ = try else_scope.addSaveErrRetIndex(.always);
5321
51905322 var err_val_scope: Scope.LocalVal = undefined;
51915323 const else_sub_scope = blk: {
51925324 const payload = payload_token orelse break :blk &else_scope.base;
......@@ -5209,9 +5341,13 @@ fn orelseCatchExpr(
52095341 break :blk &err_val_scope.base;
52105342 };
52115343
5212 const else_result = try expr(&else_scope, else_sub_scope, block_scope.break_result_loc, rhs);
5344 const else_result = try expr(&else_scope, else_sub_scope, block_scope.break_result_info, rhs);
52135345 if (!else_scope.endsWithNoReturn()) {
52145346 block_scope.break_count += 1;
5347
5348 // As our last action before the break, "pop" the error trace if needed
5349 if (do_err_trace)
5350 try restoreErrRetIndex(&else_scope, .{ .block = block }, block_scope.break_result_info, rhs, else_result);
52155351 }
52165352 try checkUsed(parent_gz, &else_scope.base, else_sub_scope);
52175353
......@@ -5220,9 +5356,9 @@ fn orelseCatchExpr(
52205356 // instructions or not.
52215357
52225358 const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break";
5223 return finishThenElseBlock(
5359 const result = try finishThenElseBlock(
52245360 parent_gz,
5225 rl,
5361 ri,
52265362 node,
52275363 &block_scope,
52285364 &then_scope,
......@@ -5235,12 +5371,13 @@ fn orelseCatchExpr(
52355371 block,
52365372 break_tag,
52375373 );
5374 return result;
52385375}
52395376
52405377/// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`.
52415378fn finishThenElseBlock(
52425379 parent_gz: *GenZir,
5243 rl: ResultLoc,
5380 ri: ResultInfo,
52445381 node: Ast.Node.Index,
52455382 block_scope: *GenZir,
52465383 then_scope: *GenZir,
......@@ -5255,7 +5392,7 @@ fn finishThenElseBlock(
52555392) InnerError!Zir.Inst.Ref {
52565393 // We now have enough information to decide whether the result instruction should
52575394 // be communicated via result location pointer or break instructions.
5258 const strat = rl.strategy(block_scope);
5395 const strat = ri.rl.strategy(block_scope);
52595396 // else_scope may be stacked on then_scope, so check for no-return on then_scope manually
52605397 const tags = parent_gz.astgen.instructions.items(.tag);
52615398 const then_slice = then_scope.instructionsSliceUpto(else_scope);
......@@ -5285,9 +5422,9 @@ fn finishThenElseBlock(
52855422 try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break);
52865423 }
52875424 const block_ref = indexToRef(main_block);
5288 switch (rl) {
5425 switch (ri.rl) {
52895426 .ref => return block_ref,
5290 else => return rvalue(parent_gz, rl, block_ref, node),
5427 else => return rvalue(parent_gz, ri, block_ref, node),
52915428 }
52925429 },
52935430 }
......@@ -5306,14 +5443,14 @@ fn tokenIdentEql(astgen: *AstGen, token1: Ast.TokenIndex, token2: Ast.TokenIndex
53065443fn fieldAccess(
53075444 gz: *GenZir,
53085445 scope: *Scope,
5309 rl: ResultLoc,
5446 ri: ResultInfo,
53105447 node: Ast.Node.Index,
53115448) InnerError!Zir.Inst.Ref {
5312 switch (rl) {
5313 .ref => return addFieldAccess(.field_ptr, gz, scope, .ref, node),
5449 switch (ri.rl) {
5450 .ref => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node),
53145451 else => {
5315 const access = try addFieldAccess(.field_val, gz, scope, .none, node);
5316 return rvalue(gz, rl, access, node);
5452 const access = try addFieldAccess(.field_val, gz, scope, .{ .rl = .none }, node);
5453 return rvalue(gz, ri, access, node);
53175454 },
53185455 }
53195456}
......@@ -5322,7 +5459,7 @@ fn addFieldAccess(
53225459 tag: Zir.Inst.Tag,
53235460 gz: *GenZir,
53245461 scope: *Scope,
5325 lhs_rl: ResultLoc,
5462 lhs_ri: ResultInfo,
53265463 node: Ast.Node.Index,
53275464) InnerError!Zir.Inst.Ref {
53285465 const astgen = gz.astgen;
......@@ -5336,7 +5473,7 @@ fn addFieldAccess(
53365473 const str_index = try astgen.identAsString(field_ident);
53375474
53385475 return gz.addPlNode(tag, node, Zir.Inst.Field{
5339 .lhs = try expr(gz, scope, lhs_rl, object_node),
5476 .lhs = try expr(gz, scope, lhs_ri, object_node),
53405477 .field_name_start = str_index,
53415478 });
53425479}
......@@ -5344,20 +5481,20 @@ fn addFieldAccess(
53445481fn arrayAccess(
53455482 gz: *GenZir,
53465483 scope: *Scope,
5347 rl: ResultLoc,
5484 ri: ResultInfo,
53485485 node: Ast.Node.Index,
53495486) InnerError!Zir.Inst.Ref {
53505487 const astgen = gz.astgen;
53515488 const tree = astgen.tree;
53525489 const node_datas = tree.nodes.items(.data);
5353 switch (rl) {
5490 switch (ri.rl) {
53545491 .ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{
5355 .lhs = try expr(gz, scope, .ref, node_datas[node].lhs),
5356 .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),
5492 .lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs),
5493 .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs),
53575494 }),
5358 else => return rvalue(gz, rl, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{
5359 .lhs = try expr(gz, scope, .none, node_datas[node].lhs),
5360 .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),
5495 else => return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{
5496 .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
5497 .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs),
53615498 }), node),
53625499 }
53635500}
......@@ -5365,7 +5502,7 @@ fn arrayAccess(
53655502fn simpleBinOp(
53665503 gz: *GenZir,
53675504 scope: *Scope,
5368 rl: ResultLoc,
5505 ri: ResultInfo,
53695506 node: Ast.Node.Index,
53705507 op_inst_tag: Zir.Inst.Tag,
53715508) InnerError!Zir.Inst.Ref {
......@@ -5374,15 +5511,15 @@ fn simpleBinOp(
53745511 const node_datas = tree.nodes.items(.data);
53755512
53765513 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{
5377 .lhs = try reachableExpr(gz, scope, .none, node_datas[node].lhs, node),
5378 .rhs = try reachableExpr(gz, scope, .none, node_datas[node].rhs, node),
5514 .lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node),
5515 .rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node),
53795516 });
5380 return rvalue(gz, rl, result, node);
5517 return rvalue(gz, ri, result, node);
53815518}
53825519
53835520fn simpleStrTok(
53845521 gz: *GenZir,
5385 rl: ResultLoc,
5522 ri: ResultInfo,
53865523 ident_token: Ast.TokenIndex,
53875524 node: Ast.Node.Index,
53885525 op_inst_tag: Zir.Inst.Tag,
......@@ -5390,13 +5527,13 @@ fn simpleStrTok(
53905527 const astgen = gz.astgen;
53915528 const str_index = try astgen.identAsString(ident_token);
53925529 const result = try gz.addStrTok(op_inst_tag, str_index, ident_token);
5393 return rvalue(gz, rl, result, node);
5530 return rvalue(gz, ri, result, node);
53945531}
53955532
53965533fn boolBinOp(
53975534 gz: *GenZir,
53985535 scope: *Scope,
5399 rl: ResultLoc,
5536 ri: ResultInfo,
54005537 node: Ast.Node.Index,
54015538 zir_tag: Zir.Inst.Tag,
54025539) InnerError!Zir.Inst.Ref {
......@@ -5404,25 +5541,25 @@ fn boolBinOp(
54045541 const tree = astgen.tree;
54055542 const node_datas = tree.nodes.items(.data);
54065543
5407 const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs);
5544 const lhs = try expr(gz, scope, bool_ri, node_datas[node].lhs);
54085545 const bool_br = try gz.addBoolBr(zir_tag, lhs);
54095546
54105547 var rhs_scope = gz.makeSubBlock(scope);
54115548 defer rhs_scope.unstack();
5412 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs);
5549 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_ri, node_datas[node].rhs);
54135550 if (!gz.refIsNoReturn(rhs)) {
54145551 _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);
54155552 }
54165553 try rhs_scope.setBoolBrBody(bool_br);
54175554
54185555 const block_ref = indexToRef(bool_br);
5419 return rvalue(gz, rl, block_ref, node);
5556 return rvalue(gz, ri, block_ref, node);
54205557}
54215558
54225559fn ifExpr(
54235560 parent_gz: *GenZir,
54245561 scope: *Scope,
5425 rl: ResultLoc,
5562 ri: ResultInfo,
54265563 node: Ast.Node.Index,
54275564 if_full: Ast.full.If,
54285565) InnerError!Zir.Inst.Ref {
......@@ -5430,8 +5567,10 @@ fn ifExpr(
54305567 const tree = astgen.tree;
54315568 const token_tags = tree.tokens.items(.tag);
54325569
5570 const do_err_trace = astgen.fn_block != null and if_full.error_token != null;
5571
54335572 var block_scope = parent_gz.makeSubBlock(scope);
5434 block_scope.setBreakResultLoc(rl);
5573 block_scope.setBreakResultInfo(ri);
54355574 defer block_scope.unstack();
54365575
54375576 const payload_is_ref = if (if_full.payload_token) |payload_token|
......@@ -5445,23 +5584,23 @@ fn ifExpr(
54455584 bool_bit: Zir.Inst.Ref,
54465585 } = c: {
54475586 if (if_full.error_token) |_| {
5448 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
5449 const err_union = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr);
5587 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none, .ctx = .error_handling_expr };
5588 const err_union = try expr(&block_scope, &block_scope.base, cond_ri, if_full.ast.cond_expr);
54505589 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;
54515590 break :c .{
54525591 .inst = err_union,
54535592 .bool_bit = try block_scope.addUnNode(tag, err_union, if_full.ast.cond_expr),
54545593 };
54555594 } else if (if_full.payload_token) |_| {
5456 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
5457 const optional = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr);
5595 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
5596 const optional = try expr(&block_scope, &block_scope.base, cond_ri, if_full.ast.cond_expr);
54585597 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;
54595598 break :c .{
54605599 .inst = optional,
54615600 .bool_bit = try block_scope.addUnNode(tag, optional, if_full.ast.cond_expr),
54625601 };
54635602 } else {
5464 const cond = try expr(&block_scope, &block_scope.base, bool_rl, if_full.ast.cond_expr);
5603 const cond = try expr(&block_scope, &block_scope.base, bool_ri, if_full.ast.cond_expr);
54655604 break :c .{
54665605 .inst = cond,
54675606 .bool_bit = cond,
......@@ -5537,7 +5676,7 @@ fn ifExpr(
55375676 }
55385677 };
55395678
5540 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, if_full.ast.then_expr);
5679 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, if_full.ast.then_expr);
55415680 if (!then_scope.endsWithNoReturn()) {
55425681 block_scope.break_count += 1;
55435682 }
......@@ -5550,6 +5689,11 @@ fn ifExpr(
55505689 var else_scope = parent_gz.makeSubBlock(scope);
55515690 defer else_scope.unstack();
55525691
5692 // We know that the operand (almost certainly) modified the error return trace,
5693 // so signal to Sema that it should save the new index for restoring later.
5694 if (do_err_trace and nodeMayAppendToErrorTrace(tree, if_full.ast.cond_expr))
5695 _ = try else_scope.addSaveErrRetIndex(.always);
5696
55535697 const else_node = if_full.ast.else_expr;
55545698 const else_info: struct {
55555699 src: Ast.Node.Index,
......@@ -5582,9 +5726,13 @@ fn ifExpr(
55825726 break :s &else_scope.base;
55835727 }
55845728 };
5585 const e = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node);
5729 const e = try expr(&else_scope, sub_scope, block_scope.break_result_info, else_node);
55865730 if (!else_scope.endsWithNoReturn()) {
55875731 block_scope.break_count += 1;
5732
5733 // As our last action before the break, "pop" the error trace if needed
5734 if (do_err_trace)
5735 try restoreErrRetIndex(&else_scope, .{ .block = block }, block_scope.break_result_info, else_node, e);
55885736 }
55895737 try checkUsed(parent_gz, &else_scope.base, sub_scope);
55905738 try else_scope.addDbgBlockEnd();
......@@ -5594,17 +5742,17 @@ fn ifExpr(
55945742 };
55955743 } else .{
55965744 .src = if_full.ast.then_expr,
5597 .result = switch (rl) {
5745 .result = switch (ri.rl) {
55985746 // Explicitly store void to ptr result loc if there is no else branch
5599 .ptr, .block_ptr => try rvalue(&else_scope, rl, .void_value, node),
5747 .ptr, .block_ptr => try rvalue(&else_scope, ri, .void_value, node),
56005748 else => .none,
56015749 },
56025750 };
56035751
56045752 const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break";
5605 return finishThenElseBlock(
5753 const result = try finishThenElseBlock(
56065754 parent_gz,
5607 rl,
5755 ri,
56085756 node,
56095757 &block_scope,
56105758 &then_scope,
......@@ -5617,6 +5765,7 @@ fn ifExpr(
56175765 block,
56185766 break_tag,
56195767 );
5768 return result;
56205769}
56215770
56225771/// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`.
......@@ -5737,7 +5886,7 @@ fn setCondBrPayloadElideBlockStorePtr(
57375886fn whileExpr(
57385887 parent_gz: *GenZir,
57395888 scope: *Scope,
5740 rl: ResultLoc,
5889 ri: ResultInfo,
57415890 node: Ast.Node.Index,
57425891 while_full: Ast.full.While,
57435892 is_statement: bool,
......@@ -5757,7 +5906,7 @@ fn whileExpr(
57575906
57585907 var loop_scope = parent_gz.makeSubBlock(scope);
57595908 loop_scope.is_inline = is_inline;
5760 loop_scope.setBreakResultLoc(rl);
5909 loop_scope.setBreakResultInfo(ri);
57615910 defer loop_scope.unstack();
57625911 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
57635912
......@@ -5775,23 +5924,23 @@ fn whileExpr(
57755924 bool_bit: Zir.Inst.Ref,
57765925 } = c: {
57775926 if (while_full.error_token) |_| {
5778 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
5779 const err_union = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr);
5927 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
5928 const err_union = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr);
57805929 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;
57815930 break :c .{
57825931 .inst = err_union,
57835932 .bool_bit = try continue_scope.addUnNode(tag, err_union, while_full.ast.then_expr),
57845933 };
57855934 } else if (while_full.payload_token) |_| {
5786 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
5787 const optional = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr);
5935 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
5936 const optional = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr);
57885937 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;
57895938 break :c .{
57905939 .inst = optional,
57915940 .bool_bit = try continue_scope.addUnNode(tag, optional, while_full.ast.then_expr),
57925941 };
57935942 } else {
5794 const cond = try expr(&continue_scope, &continue_scope.base, bool_rl, while_full.ast.cond_expr);
5943 const cond = try expr(&continue_scope, &continue_scope.base, bool_ri, while_full.ast.cond_expr);
57955944 break :c .{
57965945 .inst = cond,
57975946 .bool_bit = cond,
......@@ -5910,7 +6059,7 @@ fn whileExpr(
59106059 if (dbg_var_name) |some| {
59116060 try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst);
59126061 }
5913 const then_result = try expr(&then_scope, then_sub_scope, .none, while_full.ast.then_expr);
6062 const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, while_full.ast.then_expr);
59146063 _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr);
59156064
59166065 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
......@@ -5955,7 +6104,7 @@ fn whileExpr(
59556104 // control flow apply to outer loops; not this one.
59566105 loop_scope.continue_block = 0;
59576106 loop_scope.break_block = 0;
5958 const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node);
6107 const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_info, else_node);
59596108 if (is_statement) {
59606109 _ = try addEnsureResult(&else_scope, else_result, else_node);
59616110 }
......@@ -5982,7 +6131,7 @@ fn whileExpr(
59826131 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
59836132 const result = try finishThenElseBlock(
59846133 parent_gz,
5985 rl,
6134 ri,
59866135 node,
59876136 &loop_scope,
59886137 &then_scope,
......@@ -6004,7 +6153,7 @@ fn whileExpr(
60046153fn forExpr(
60056154 parent_gz: *GenZir,
60066155 scope: *Scope,
6007 rl: ResultLoc,
6156 ri: ResultInfo,
60086157 node: Ast.Node.Index,
60096158 for_full: Ast.full.While,
60106159 is_statement: bool,
......@@ -6027,8 +6176,8 @@ fn forExpr(
60276176
60286177 try emitDbgNode(parent_gz, for_full.ast.cond_expr);
60296178
6030 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
6031 const array_ptr = try expr(parent_gz, scope, cond_rl, for_full.ast.cond_expr);
6179 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
6180 const array_ptr = try expr(parent_gz, scope, cond_ri, for_full.ast.cond_expr);
60326181 const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr);
60336182
60346183 const index_ptr = blk: {
......@@ -6045,7 +6194,7 @@ fn forExpr(
60456194
60466195 var loop_scope = parent_gz.makeSubBlock(scope);
60476196 loop_scope.is_inline = is_inline;
6048 loop_scope.setBreakResultLoc(rl);
6197 loop_scope.setBreakResultInfo(ri);
60496198 defer loop_scope.unstack();
60506199 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
60516200
......@@ -6149,7 +6298,7 @@ fn forExpr(
61496298 break :blk &index_scope.base;
61506299 };
61516300
6152 const then_result = try expr(&then_scope, then_sub_scope, .none, for_full.ast.then_expr);
6301 const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, for_full.ast.then_expr);
61536302 _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr);
61546303
61556304 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
......@@ -6168,7 +6317,7 @@ fn forExpr(
61686317 // control flow apply to outer loops; not this one.
61696318 loop_scope.continue_block = 0;
61706319 loop_scope.break_block = 0;
6171 const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node);
6320 const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_info, else_node);
61726321 if (is_statement) {
61736322 _ = try addEnsureResult(&else_scope, else_result, else_node);
61746323 }
......@@ -6193,7 +6342,7 @@ fn forExpr(
61936342 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
61946343 const result = try finishThenElseBlock(
61956344 parent_gz,
6196 rl,
6345 ri,
61976346 node,
61986347 &loop_scope,
61996348 &then_scope,
......@@ -6215,7 +6364,7 @@ fn forExpr(
62156364fn switchExpr(
62166365 parent_gz: *GenZir,
62176366 scope: *Scope,
6218 rl: ResultLoc,
6367 ri: ResultInfo,
62196368 switch_node: Ast.Node.Index,
62206369) InnerError!Zir.Inst.Ref {
62216370 const astgen = parent_gz.astgen;
......@@ -6346,13 +6495,13 @@ fn switchExpr(
63466495 }
63476496 }
63486497
6349 const operand_rl: ResultLoc = if (any_payload_is_ref) .ref else .none;
6350 const raw_operand = try expr(parent_gz, scope, operand_rl, operand_node);
6498 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };
6499 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);
63516500 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;
63526501 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);
63536502 // We need the type of the operand to use as the result location for all the prong items.
63546503 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);
6355 const item_rl: ResultLoc = .{ .ty = cond_ty_inst };
6504 const item_ri: ResultInfo = .{ .rl = .{ .ty = cond_ty_inst } };
63566505
63576506 // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti,
63586507 // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with
......@@ -6369,7 +6518,7 @@ fn switchExpr(
63696518 var block_scope = parent_gz.makeSubBlock(scope);
63706519 // block_scope not used for collecting instructions
63716520 block_scope.instructions_top = GenZir.unstacked_top;
6372 block_scope.setBreakResultLoc(rl);
6521 block_scope.setBreakResultInfo(ri);
63736522
63746523 // This gets added to the parent block later, after the item expressions.
63756524 const switch_block = try parent_gz.makeBlockInst(.switch_block, switch_node);
......@@ -6510,7 +6659,7 @@ fn switchExpr(
65106659 if (node_tags[item_node] == .switch_range) continue;
65116660 items_len += 1;
65126661
6513 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);
6662 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node);
65146663 try payloads.append(gpa, @enumToInt(item_inst));
65156664 }
65166665
......@@ -6520,8 +6669,8 @@ fn switchExpr(
65206669 if (node_tags[range] != .switch_range) continue;
65216670 ranges_len += 1;
65226671
6523 const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs);
6524 const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs);
6672 const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs);
6673 const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs);
65256674 try payloads.appendSlice(gpa, &[_]u32{
65266675 @enumToInt(first), @enumToInt(last),
65276676 });
......@@ -6539,7 +6688,7 @@ fn switchExpr(
65396688 scalar_case_index += 1;
65406689 try payloads.resize(gpa, header_index + 2); // item, body_len
65416690 const item_node = case.ast.values[0];
6542 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);
6691 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node);
65436692 payloads.items[header_index] = @enumToInt(item_inst);
65446693 break :blk header_index + 1;
65456694 };
......@@ -6558,7 +6707,7 @@ fn switchExpr(
65586707 if (dbg_var_tag_name) |some| {
65596708 try case_scope.addDbgVar(.dbg_var_val, some, dbg_var_tag_inst);
65606709 }
6561 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);
6710 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, case.ast.target_expr);
65626711 try checkUsed(parent_gz, &case_scope.base, sub_scope);
65636712 try case_scope.addDbgBlockEnd();
65646713 if (!parent_gz.refIsNoReturn(case_result)) {
......@@ -6600,7 +6749,7 @@ fn switchExpr(
66006749
66016750 zir_datas[switch_block].pl_node.payload_index = payload_index;
66026751
6603 const strat = rl.strategy(&block_scope);
6752 const strat = ri.rl.strategy(&block_scope);
66046753 for (payloads.items[case_table_start..case_table_end]) |start_index, i| {
66056754 var body_len_index = start_index;
66066755 var end_index = start_index;
......@@ -6672,8 +6821,8 @@ fn switchExpr(
66726821 }
66736822
66746823 const block_ref = indexToRef(switch_block);
6675 if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and rl != .ref)
6676 return rvalue(parent_gz, rl, block_ref, switch_node);
6824 if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and ri.rl != .ref)
6825 return rvalue(parent_gz, ri, block_ref, switch_node);
66776826 return block_ref;
66786827}
66796828
......@@ -6713,6 +6862,10 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
67136862 if (operand_node == 0) {
67146863 // Returning a void value; skip error defers.
67156864 try genDefers(gz, defer_outer, scope, .normal_only);
6865
6866 // As our last action before the return, "pop" the error trace if needed
6867 _ = try gz.addRestoreErrRetIndex(.ret, .always);
6868
67166869 _ = try gz.addUnNode(.ret_node, .void_value, node);
67176870 return Zir.Inst.Ref.unreachable_value;
67186871 }
......@@ -6736,30 +6889,36 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
67366889 return Zir.Inst.Ref.unreachable_value;
67376890 }
67386891
6739 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{
6740 .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) },
6892 const ri: ResultInfo = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{
6893 .rl = .{ .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) } },
6894 .ctx = .@"return",
67416895 } else .{
6742 .ty = try gz.addNode(.ret_type, node),
6896 .rl = .{ .ty = try gz.addNode(.ret_type, node) },
6897 .ctx = .@"return",
67436898 };
67446899 const prev_anon_name_strategy = gz.anon_name_strategy;
67456900 gz.anon_name_strategy = .func;
6746 const operand = try reachableExpr(gz, scope, rl, operand_node, node);
6901 const operand = try reachableExpr(gz, scope, ri, operand_node, node);
67476902 gz.anon_name_strategy = prev_anon_name_strategy;
67486903
67496904 switch (nodeMayEvalToError(tree, operand_node)) {
67506905 .never => {
67516906 // Returning a value that cannot be an error; skip error defers.
67526907 try genDefers(gz, defer_outer, scope, .normal_only);
6908
6909 // As our last action before the return, "pop" the error trace if needed
6910 _ = try gz.addRestoreErrRetIndex(.ret, .always);
6911
67536912 try emitDbgStmt(gz, ret_line, ret_column);
6754 try gz.addRet(rl, operand, node);
6913 try gz.addRet(ri, operand, node);
67556914 return Zir.Inst.Ref.unreachable_value;
67566915 },
67576916 .always => {
67586917 // Value is always an error. Emit both error defers and regular defers.
6759 const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand;
6918 const err_code = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
67606919 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
67616920 try emitDbgStmt(gz, ret_line, ret_column);
6762 try gz.addRet(rl, operand, node);
6921 try gz.addRet(ri, operand, node);
67636922 return Zir.Inst.Ref.unreachable_value;
67646923 },
67656924 .maybe => {
......@@ -6768,12 +6927,17 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
67686927 // Only regular defers; no branch needed.
67696928 try genDefers(gz, defer_outer, scope, .normal_only);
67706929 try emitDbgStmt(gz, ret_line, ret_column);
6771 try gz.addRet(rl, operand, node);
6930
6931 // As our last action before the return, "pop" the error trace if needed
6932 const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
6933 _ = try gz.addRestoreErrRetIndex(.ret, .{ .if_non_error = result });
6934
6935 try gz.addRet(ri, operand, node);
67726936 return Zir.Inst.Ref.unreachable_value;
67736937 }
67746938
67756939 // Emit conditional branch for generating errdefers.
6776 const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand;
6940 const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
67776941 const is_non_err = try gz.addUnNode(.is_non_err, result, node);
67786942 const condbr = try gz.addCondBr(.condbr, node);
67796943
......@@ -6781,8 +6945,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
67816945 defer then_scope.unstack();
67826946
67836947 try genDefers(&then_scope, defer_outer, scope, .normal_only);
6948
6949 // As our last action before the return, "pop" the error trace if needed
6950 _ = try then_scope.addRestoreErrRetIndex(.ret, .always);
6951
67846952 try emitDbgStmt(&then_scope, ret_line, ret_column);
6785 try then_scope.addRet(rl, operand, node);
6953 try then_scope.addRet(ri, operand, node);
67866954
67876955 var else_scope = gz.makeSubBlock(scope);
67886956 defer else_scope.unstack();
......@@ -6792,7 +6960,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
67926960 };
67936961 try genDefers(&else_scope, defer_outer, scope, which_ones);
67946962 try emitDbgStmt(&else_scope, ret_line, ret_column);
6795 try else_scope.addRet(rl, operand, node);
6963 try else_scope.addRet(ri, operand, node);
67966964
67976965 try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0);
67986966
......@@ -6825,7 +6993,7 @@ fn parseBitCount(buf: []const u8) std.fmt.ParseIntError!u16 {
68256993fn identifier(
68266994 gz: *GenZir,
68276995 scope: *Scope,
6828 rl: ResultLoc,
6996 ri: ResultInfo,
68296997 ident: Ast.Node.Index,
68306998) InnerError!Zir.Inst.Ref {
68316999 const tracy = trace(@src());
......@@ -6844,7 +7012,7 @@ fn identifier(
68447012 // if not @"" syntax, just use raw token slice
68457013 if (ident_name_raw[0] != '@') {
68467014 if (primitives.get(ident_name_raw)) |zir_const_ref| {
6847 return rvalue(gz, rl, zir_const_ref, ident);
7015 return rvalue(gz, ri, zir_const_ref, ident);
68487016 }
68497017
68507018 if (ident_name_raw.len >= 2) integer: {
......@@ -6877,19 +7045,19 @@ fn identifier(
68777045 .bit_count = bit_count,
68787046 } },
68797047 });
6880 return rvalue(gz, rl, result, ident);
7048 return rvalue(gz, ri, result, ident);
68817049 }
68827050 }
68837051 }
68847052
68857053 // Local variables, including function parameters.
6886 return localVarRef(gz, scope, rl, ident, ident_token);
7054 return localVarRef(gz, scope, ri, ident, ident_token);
68877055}
68887056
68897057fn localVarRef(
68907058 gz: *GenZir,
68917059 scope: *Scope,
6892 rl: ResultLoc,
7060 ri: ResultInfo,
68937061 ident: Ast.Node.Index,
68947062 ident_token: Ast.TokenIndex,
68957063) InnerError!Zir.Inst.Ref {
......@@ -6907,7 +7075,7 @@ fn localVarRef(
69077075 if (local_val.name == name_str_index) {
69087076 // Locals cannot shadow anything, so we do not need to look for ambiguous
69097077 // references in this case.
6910 if (rl == .discard) {
7078 if (ri.rl == .discard) {
69117079 local_val.discarded = ident_token;
69127080 } else {
69137081 local_val.used = ident_token;
......@@ -6923,14 +7091,14 @@ fn localVarRef(
69237091 gpa,
69247092 );
69257093
6926 return rvalue(gz, rl, value_inst, ident);
7094 return rvalue(gz, ri, value_inst, ident);
69277095 }
69287096 s = local_val.parent;
69297097 },
69307098 .local_ptr => {
69317099 const local_ptr = s.cast(Scope.LocalPtr).?;
69327100 if (local_ptr.name == name_str_index) {
6933 if (rl == .discard) {
7101 if (ri.rl == .discard) {
69347102 local_ptr.discarded = ident_token;
69357103 } else {
69367104 local_ptr.used = ident_token;
......@@ -6955,11 +7123,11 @@ fn localVarRef(
69557123 gpa,
69567124 );
69577125
6958 switch (rl) {
7126 switch (ri.rl) {
69597127 .ref => return ptr_inst,
69607128 else => {
69617129 const loaded = try gz.addUnNode(.load, ptr_inst, ident);
6962 return rvalue(gz, rl, loaded, ident);
7130 return rvalue(gz, ri, loaded, ident);
69637131 },
69647132 }
69657133 }
......@@ -6992,11 +7160,11 @@ fn localVarRef(
69927160
69937161 // Decl references happen by name rather than ZIR index so that when unrelated
69947162 // decls are modified, ZIR code containing references to them can be unmodified.
6995 switch (rl) {
7163 switch (ri.rl) {
69967164 .ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token),
69977165 else => {
69987166 const result = try gz.addStrTok(.decl_val, name_str_index, ident_token);
6999 return rvalue(gz, rl, result, ident);
7167 return rvalue(gz, ri, result, ident);
70007168 },
70017169 }
70027170}
......@@ -7040,7 +7208,7 @@ fn tunnelThroughClosure(
70407208
70417209fn stringLiteral(
70427210 gz: *GenZir,
7043 rl: ResultLoc,
7211 ri: ResultInfo,
70447212 node: Ast.Node.Index,
70457213) InnerError!Zir.Inst.Ref {
70467214 const astgen = gz.astgen;
......@@ -7055,12 +7223,12 @@ fn stringLiteral(
70557223 .len = str.len,
70567224 } },
70577225 });
7058 return rvalue(gz, rl, result, node);
7226 return rvalue(gz, ri, result, node);
70597227}
70607228
70617229fn multilineStringLiteral(
70627230 gz: *GenZir,
7063 rl: ResultLoc,
7231 ri: ResultInfo,
70647232 node: Ast.Node.Index,
70657233) InnerError!Zir.Inst.Ref {
70667234 const astgen = gz.astgen;
......@@ -7072,10 +7240,10 @@ fn multilineStringLiteral(
70727240 .len = str.len,
70737241 } },
70747242 });
7075 return rvalue(gz, rl, result, node);
7243 return rvalue(gz, ri, result, node);
70767244}
70777245
7078fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
7246fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
70797247 const astgen = gz.astgen;
70807248 const tree = astgen.tree;
70817249 const main_tokens = tree.nodes.items(.main_token);
......@@ -7085,7 +7253,7 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.
70857253 switch (std.zig.parseCharLiteral(slice)) {
70867254 .success => |codepoint| {
70877255 const result = try gz.addInt(codepoint);
7088 return rvalue(gz, rl, result, node);
7256 return rvalue(gz, ri, result, node);
70897257 },
70907258 .failure => |err| return astgen.failWithStrLitError(err, main_token, slice, 0),
70917259 }
......@@ -7093,7 +7261,7 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.
70937261
70947262const Sign = enum { negative, positive };
70957263
7096fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref {
7264fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref {
70977265 const astgen = gz.astgen;
70987266 const tree = astgen.tree;
70997267 const main_tokens = tree.nodes.items(.main_token);
......@@ -7135,7 +7303,7 @@ fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node:
71357303 const bigger_again: f128 = smaller_float;
71367304 if (bigger_again == float_number) {
71377305 const result = try gz.addFloat(smaller_float);
7138 return rvalue(gz, rl, result, source_node);
7306 return rvalue(gz, ri, result, source_node);
71397307 }
71407308 // We need to use 128 bits. Break the float into 4 u32 values so we can
71417309 // put it into the `extra` array.
......@@ -7146,16 +7314,16 @@ fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node:
71467314 .piece2 = @truncate(u32, int_bits >> 64),
71477315 .piece3 = @truncate(u32, int_bits >> 96),
71487316 });
7149 return rvalue(gz, rl, result, source_node);
7317 return rvalue(gz, ri, result, source_node);
71507318 },
71517319 .failure => |err| return astgen.failWithNumberError(err, num_token, bytes),
71527320 };
71537321
71547322 if (sign == .positive) {
7155 return rvalue(gz, rl, result, source_node);
7323 return rvalue(gz, ri, result, source_node);
71567324 } else {
71577325 const negated = try gz.addUnNode(.negate, result, source_node);
7158 return rvalue(gz, rl, negated, source_node);
7326 return rvalue(gz, ri, negated, source_node);
71597327 }
71607328}
71617329
......@@ -7191,7 +7359,7 @@ fn failWithNumberError(astgen: *AstGen, err: std.zig.number_literal.Error, token
71917359fn asmExpr(
71927360 gz: *GenZir,
71937361 scope: *Scope,
7194 rl: ResultLoc,
7362 ri: ResultInfo,
71957363 node: Ast.Node.Index,
71967364 full: Ast.full.Asm,
71977365) InnerError!Zir.Inst.Ref {
......@@ -7214,7 +7382,7 @@ fn asmExpr(
72147382 },
72157383 else => .{
72167384 .tag = .asm_expr,
7217 .tmpl = @enumToInt(try comptimeExpr(gz, scope, .none, full.ast.template)),
7385 .tmpl = @enumToInt(try comptimeExpr(gz, scope, .{ .rl = .none }, full.ast.template)),
72187386 },
72197387 };
72207388
......@@ -7266,7 +7434,7 @@ fn asmExpr(
72667434 outputs[i] = .{
72677435 .name = name,
72687436 .constraint = constraint,
7269 .operand = try localVarRef(gz, scope, .ref, node, ident_token),
7437 .operand = try localVarRef(gz, scope, .{ .rl = .ref }, node, ident_token),
72707438 };
72717439 }
72727440 }
......@@ -7282,7 +7450,7 @@ fn asmExpr(
72827450 const name = try astgen.identAsString(symbolic_name);
72837451 const constraint_token = symbolic_name + 2;
72847452 const constraint = (try astgen.strLitAsString(constraint_token)).index;
7285 const operand = try expr(gz, scope, .none, node_datas[input_node].lhs);
7453 const operand = try expr(gz, scope, .{ .rl = .none }, node_datas[input_node].lhs);
72867454 inputs[i] = .{
72877455 .name = name,
72887456 .constraint = constraint,
......@@ -7327,31 +7495,31 @@ fn asmExpr(
73277495 .inputs = inputs,
73287496 .clobbers = clobbers_buffer[0..clobber_i],
73297497 });
7330 return rvalue(gz, rl, result, node);
7498 return rvalue(gz, ri, result, node);
73317499}
73327500
73337501fn as(
73347502 gz: *GenZir,
73357503 scope: *Scope,
7336 rl: ResultLoc,
7504 ri: ResultInfo,
73377505 node: Ast.Node.Index,
73387506 lhs: Ast.Node.Index,
73397507 rhs: Ast.Node.Index,
73407508) InnerError!Zir.Inst.Ref {
73417509 const dest_type = try typeExpr(gz, scope, lhs);
7342 switch (rl) {
7343 .none, .discard, .ref, .ty, .ty_shift_operand, .coerced_ty => {
7344 const result = try reachableExpr(gz, scope, .{ .ty = dest_type }, rhs, node);
7345 return rvalue(gz, rl, result, node);
7510 switch (ri.rl) {
7511 .none, .discard, .ref, .ty, .coerced_ty => {
7512 const result = try reachableExpr(gz, scope, .{ .rl = .{ .ty = dest_type } }, rhs, node);
7513 return rvalue(gz, ri, result, node);
73467514 },
73477515 .ptr => |result_ptr| {
7348 return asRlPtr(gz, scope, rl, node, result_ptr.inst, rhs, dest_type);
7516 return asRlPtr(gz, scope, ri, node, result_ptr.inst, rhs, dest_type);
73497517 },
73507518 .inferred_ptr => |result_ptr| {
7351 return asRlPtr(gz, scope, rl, node, result_ptr, rhs, dest_type);
7519 return asRlPtr(gz, scope, ri, node, result_ptr, rhs, dest_type);
73527520 },
73537521 .block_ptr => |block_scope| {
7354 return asRlPtr(gz, scope, rl, node, block_scope.rl_ptr, rhs, dest_type);
7522 return asRlPtr(gz, scope, ri, node, block_scope.rl_ptr, rhs, dest_type);
73557523 },
73567524 }
73577525}
......@@ -7359,29 +7527,29 @@ fn as(
73597527fn unionInit(
73607528 gz: *GenZir,
73617529 scope: *Scope,
7362 rl: ResultLoc,
7530 ri: ResultInfo,
73637531 node: Ast.Node.Index,
73647532 params: []const Ast.Node.Index,
73657533) InnerError!Zir.Inst.Ref {
73667534 const union_type = try typeExpr(gz, scope, params[0]);
7367 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
7535 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]);
73687536 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{
73697537 .container_type = union_type,
73707538 .field_name = field_name,
73717539 });
7372 const init = try reachableExpr(gz, scope, .{ .ty = field_type }, params[2], node);
7540 const init = try reachableExpr(gz, scope, .{ .rl = .{ .ty = field_type } }, params[2], node);
73737541 const result = try gz.addPlNode(.union_init, node, Zir.Inst.UnionInit{
73747542 .union_type = union_type,
73757543 .init = init,
73767544 .field_name = field_name,
73777545 });
7378 return rvalue(gz, rl, result, node);
7546 return rvalue(gz, ri, result, node);
73797547}
73807548
73817549fn asRlPtr(
73827550 parent_gz: *GenZir,
73837551 scope: *Scope,
7384 rl: ResultLoc,
7552 ri: ResultInfo,
73857553 src_node: Ast.Node.Index,
73867554 result_ptr: Zir.Inst.Ref,
73877555 operand_node: Ast.Node.Index,
......@@ -7390,31 +7558,31 @@ fn asRlPtr(
73907558 var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr, src_node);
73917559 defer as_scope.unstack();
73927560
7393 const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node);
7394 return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type);
7561 const result = try reachableExpr(&as_scope, &as_scope.base, .{ .rl = .{ .block_ptr = &as_scope } }, operand_node, src_node);
7562 return as_scope.finishCoercion(parent_gz, ri, operand_node, result, dest_type);
73957563}
73967564
73977565fn bitCast(
73987566 gz: *GenZir,
73997567 scope: *Scope,
7400 rl: ResultLoc,
7568 ri: ResultInfo,
74017569 node: Ast.Node.Index,
74027570 lhs: Ast.Node.Index,
74037571 rhs: Ast.Node.Index,
74047572) InnerError!Zir.Inst.Ref {
74057573 const dest_type = try reachableTypeExpr(gz, scope, lhs, node);
7406 const operand = try reachableExpr(gz, scope, .none, rhs, node);
7574 const operand = try reachableExpr(gz, scope, .{ .rl = .none }, rhs, node);
74077575 const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{
74087576 .lhs = dest_type,
74097577 .rhs = operand,
74107578 });
7411 return rvalue(gz, rl, result, node);
7579 return rvalue(gz, ri, result, node);
74127580}
74137581
74147582fn typeOf(
74157583 gz: *GenZir,
74167584 scope: *Scope,
7417 rl: ResultLoc,
7585 ri: ResultInfo,
74187586 node: Ast.Node.Index,
74197587 args: []const Ast.Node.Index,
74207588) InnerError!Zir.Inst.Ref {
......@@ -7430,7 +7598,7 @@ fn typeOf(
74307598 typeof_scope.force_comptime = false;
74317599 defer typeof_scope.unstack();
74327600
7433 const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, args[0], node);
7601 const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .{ .rl = .none }, args[0], node);
74347602 if (!gz.refIsNoReturn(ty_expr)) {
74357603 _ = try typeof_scope.addBreak(.break_inline, typeof_inst, ty_expr);
74367604 }
......@@ -7438,7 +7606,7 @@ fn typeOf(
74387606
74397607 // typeof_scope unstacked now, can add new instructions to gz
74407608 try gz.instructions.append(gpa, typeof_inst);
7441 return rvalue(gz, rl, indexToRef(typeof_inst), node);
7609 return rvalue(gz, ri, indexToRef(typeof_inst), node);
74427610 }
74437611 const payload_size: u32 = std.meta.fields(Zir.Inst.TypeOfPeer).len;
74447612 const payload_index = try reserveExtra(astgen, payload_size + args.len);
......@@ -7450,7 +7618,7 @@ fn typeOf(
74507618 typeof_scope.force_comptime = false;
74517619
74527620 for (args) |arg, i| {
7453 const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, arg, node);
7621 const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .{ .rl = .none }, arg, node);
74547622 astgen.extra.items[args_index + i] = @enumToInt(param_ref);
74557623 }
74567624 _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value);
......@@ -7466,13 +7634,13 @@ fn typeOf(
74667634 astgen.appendBodyWithFixups(body);
74677635 typeof_scope.unstack();
74687636
7469 return rvalue(gz, rl, typeof_inst, node);
7637 return rvalue(gz, ri, typeof_inst, node);
74707638}
74717639
74727640fn builtinCall(
74737641 gz: *GenZir,
74747642 scope: *Scope,
7475 rl: ResultLoc,
7643 ri: ResultInfo,
74767644 node: Ast.Node.Index,
74777645 params: []const Ast.Node.Index,
74787646) InnerError!Zir.Inst.Ref {
......@@ -7524,7 +7692,7 @@ fn builtinCall(
75247692 if (!gop.found_existing) {
75257693 gop.value_ptr.* = str_lit_token;
75267694 }
7527 return rvalue(gz, rl, result, node);
7695 return rvalue(gz, ri, result, node);
75287696 },
75297697 .compile_log => {
75307698 const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{
......@@ -7532,32 +7700,32 @@ fn builtinCall(
75327700 });
75337701 var extra_index = try reserveExtra(gz.astgen, params.len);
75347702 for (params) |param| {
7535 const param_ref = try expr(gz, scope, .none, param);
7703 const param_ref = try expr(gz, scope, .{ .rl = .none }, param);
75367704 astgen.extra.items[extra_index] = @enumToInt(param_ref);
75377705 extra_index += 1;
75387706 }
75397707 const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log, payload_index, params.len);
7540 return rvalue(gz, rl, result, node);
7708 return rvalue(gz, ri, result, node);
75417709 },
75427710 .field => {
7543 if (rl == .ref) {
7711 if (ri.rl == .ref) {
75447712 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
7545 .lhs = try expr(gz, scope, .ref, params[0]),
7546 .field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]),
7713 .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),
7714 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]),
75477715 });
75487716 }
75497717 const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
7550 .lhs = try expr(gz, scope, .none, params[0]),
7551 .field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]),
7718 .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
7719 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]),
75527720 });
7553 return rvalue(gz, rl, result, node);
7721 return rvalue(gz, ri, result, node);
75547722 },
75557723
75567724 // zig fmt: off
7557 .as => return as( gz, scope, rl, node, params[0], params[1]),
7558 .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]),
7559 .TypeOf => return typeOf( gz, scope, rl, node, params),
7560 .union_init => return unionInit(gz, scope, rl, node, params),
7725 .as => return as( gz, scope, ri, node, params[0], params[1]),
7726 .bit_cast => return bitCast( gz, scope, ri, node, params[0], params[1]),
7727 .TypeOf => return typeOf( gz, scope, ri, node, params),
7728 .union_init => return unionInit(gz, scope, ri, node, params),
75617729 .c_import => return cImport( gz, scope, node, params[0]),
75627730 // zig fmt: on
75637731
......@@ -7582,9 +7750,9 @@ fn builtinCall(
75827750 local_val.used = ident_token;
75837751 _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{
75847752 .operand = local_val.inst,
7585 .options = try comptimeExpr(gz, scope, .{ .coerced_ty = .export_options_type }, params[1]),
7753 .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]),
75867754 });
7587 return rvalue(gz, rl, .void_value, node);
7755 return rvalue(gz, ri, .void_value, node);
75887756 }
75897757 s = local_val.parent;
75907758 },
......@@ -7597,9 +7765,9 @@ fn builtinCall(
75977765 const loaded = try gz.addUnNode(.load, local_ptr.ptr, node);
75987766 _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{
75997767 .operand = loaded,
7600 .options = try comptimeExpr(gz, scope, .{ .coerced_ty = .export_options_type }, params[1]),
7768 .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]),
76017769 });
7602 return rvalue(gz, rl, .void_value, node);
7770 return rvalue(gz, ri, .void_value, node);
76037771 }
76047772 s = local_ptr.parent;
76057773 },
......@@ -7631,47 +7799,47 @@ fn builtinCall(
76317799 },
76327800 else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}),
76337801 }
7634 const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]);
7802 const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .export_options_type } }, params[1]);
76357803 _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{
76367804 .namespace = namespace,
76377805 .decl_name = decl_name,
76387806 .options = options,
76397807 });
7640 return rvalue(gz, rl, .void_value, node);
7808 return rvalue(gz, ri, .void_value, node);
76417809 },
76427810 .@"extern" => {
76437811 const type_inst = try typeExpr(gz, scope, params[0]);
7644 const options = try comptimeExpr(gz, scope, .{ .ty = .extern_options_type }, params[1]);
7812 const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .extern_options_type } }, params[1]);
76457813 const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{
76467814 .node = gz.nodeIndexToRelative(node),
76477815 .lhs = type_inst,
76487816 .rhs = options,
76497817 });
7650 return rvalue(gz, rl, result, node);
7818 return rvalue(gz, ri, result, node);
76517819 },
76527820 .fence => {
7653 const order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[0]);
7821 const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[0]);
76547822 const result = try gz.addExtendedPayload(.fence, Zir.Inst.UnNode{
76557823 .node = gz.nodeIndexToRelative(node),
76567824 .operand = order,
76577825 });
7658 return rvalue(gz, rl, result, node);
7826 return rvalue(gz, ri, result, node);
76597827 },
76607828 .set_float_mode => {
7661 const order = try expr(gz, scope, .{ .coerced_ty = .float_mode_type }, params[0]);
7829 const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .float_mode_type } }, params[0]);
76627830 const result = try gz.addExtendedPayload(.set_float_mode, Zir.Inst.UnNode{
76637831 .node = gz.nodeIndexToRelative(node),
76647832 .operand = order,
76657833 });
7666 return rvalue(gz, rl, result, node);
7834 return rvalue(gz, ri, result, node);
76677835 },
76687836 .set_align_stack => {
7669 const order = try expr(gz, scope, align_rl, params[0]);
7837 const order = try expr(gz, scope, align_ri, params[0]);
76707838 const result = try gz.addExtendedPayload(.set_align_stack, Zir.Inst.UnNode{
76717839 .node = gz.nodeIndexToRelative(node),
76727840 .operand = order,
76737841 });
7674 return rvalue(gz, rl, result, node);
7842 return rvalue(gz, ri, result, node);
76757843 },
76767844
76777845 .src => {
......@@ -7683,62 +7851,62 @@ fn builtinCall(
76837851 .line = astgen.source_line,
76847852 .column = astgen.source_column,
76857853 });
7686 return rvalue(gz, rl, result, node);
7854 return rvalue(gz, ri, result, node);
76877855 },
76887856
76897857 // zig fmt: off
7690 .This => return rvalue(gz, rl, try gz.addNodeExtended(.this, node), node),
7691 .return_address => return rvalue(gz, rl, try gz.addNodeExtended(.ret_addr, node), node),
7692 .error_return_trace => return rvalue(gz, rl, try gz.addNodeExtended(.error_return_trace, node), node),
7693 .frame => return rvalue(gz, rl, try gz.addNodeExtended(.frame, node), node),
7694 .frame_address => return rvalue(gz, rl, try gz.addNodeExtended(.frame_address, node), node),
7695 .breakpoint => return rvalue(gz, rl, try gz.addNodeExtended(.breakpoint, node), node),
7696
7697 .type_info => return simpleUnOpType(gz, scope, rl, node, params[0], .type_info),
7698 .size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .size_of),
7699 .bit_size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .bit_size_of),
7700 .align_of => return simpleUnOpType(gz, scope, rl, node, params[0], .align_of),
7701
7702 .ptr_to_int => return simpleUnOp(gz, scope, rl, node, .none, params[0], .ptr_to_int),
7703 .compile_error => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .compile_error),
7704 .set_eval_branch_quota => return simpleUnOp(gz, scope, rl, node, .{ .coerced_ty = .u32_type }, params[0], .set_eval_branch_quota),
7705 .enum_to_int => return simpleUnOp(gz, scope, rl, node, .none, params[0], .enum_to_int),
7706 .bool_to_int => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .bool_to_int),
7707 .embed_file => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .embed_file),
7708 .error_name => return simpleUnOp(gz, scope, rl, node, .{ .ty = .anyerror_type }, params[0], .error_name),
7709 .set_cold => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_cold),
7710 .set_runtime_safety => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_runtime_safety),
7711 .sqrt => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sqrt),
7712 .sin => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sin),
7713 .cos => return simpleUnOp(gz, scope, rl, node, .none, params[0], .cos),
7714 .tan => return simpleUnOp(gz, scope, rl, node, .none, params[0], .tan),
7715 .exp => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp),
7716 .exp2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp2),
7717 .log => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log),
7718 .log2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log2),
7719 .log10 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log10),
7720 .fabs => return simpleUnOp(gz, scope, rl, node, .none, params[0], .fabs),
7721 .floor => return simpleUnOp(gz, scope, rl, node, .none, params[0], .floor),
7722 .ceil => return simpleUnOp(gz, scope, rl, node, .none, params[0], .ceil),
7723 .trunc => return simpleUnOp(gz, scope, rl, node, .none, params[0], .trunc),
7724 .round => return simpleUnOp(gz, scope, rl, node, .none, params[0], .round),
7725 .tag_name => return simpleUnOp(gz, scope, rl, node, .none, params[0], .tag_name),
7726 .type_name => return simpleUnOp(gz, scope, rl, node, .none, params[0], .type_name),
7727 .Frame => return simpleUnOp(gz, scope, rl, node, .none, params[0], .frame_type),
7728 .frame_size => return simpleUnOp(gz, scope, rl, node, .none, params[0], .frame_size),
7729
7730 .float_to_int => return typeCast(gz, scope, rl, node, params[0], params[1], .float_to_int),
7731 .int_to_float => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_float),
7732 .int_to_ptr => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_ptr),
7733 .int_to_enum => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_enum),
7734 .float_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .float_cast),
7735 .int_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .int_cast),
7736 .ptr_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .ptr_cast),
7737 .truncate => return typeCast(gz, scope, rl, node, params[0], params[1], .truncate),
7858 .This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node),
7859 .return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node),
7860 .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node),
7861 .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node),
7862 .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node),
7863 .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node),
7864
7865 .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info),
7866 .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of),
7867 .bit_size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .bit_size_of),
7868 .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of),
7869
7870 .ptr_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ptr_to_int),
7871 .compile_error => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .compile_error),
7872 .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota),
7873 .enum_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .enum_to_int),
7874 .bool_to_int => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .bool_to_int),
7875 .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .embed_file),
7876 .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name),
7877 .set_cold => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_cold),
7878 .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety),
7879 .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt),
7880 .sin => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sin),
7881 .cos => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .cos),
7882 .tan => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tan),
7883 .exp => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp),
7884 .exp2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp2),
7885 .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log),
7886 .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2),
7887 .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10),
7888 .fabs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .fabs),
7889 .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor),
7890 .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil),
7891 .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc),
7892 .round => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .round),
7893 .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name),
7894 .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name),
7895 .Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type),
7896 .frame_size => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_size),
7897
7898 .float_to_int => return typeCast(gz, scope, ri, node, params[0], params[1], .float_to_int),
7899 .int_to_float => return typeCast(gz, scope, ri, node, params[0], params[1], .int_to_float),
7900 .int_to_ptr => return typeCast(gz, scope, ri, node, params[0], params[1], .int_to_ptr),
7901 .int_to_enum => return typeCast(gz, scope, ri, node, params[0], params[1], .int_to_enum),
7902 .float_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .float_cast),
7903 .int_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .int_cast),
7904 .ptr_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .ptr_cast),
7905 .truncate => return typeCast(gz, scope, ri, node, params[0], params[1], .truncate),
77387906 // zig fmt: on
77397907
77407908 .Type => {
7741 const operand = try expr(gz, scope, .{ .coerced_ty = .type_info_type }, params[0]);
7909 const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .type_info_type } }, params[0]);
77427910
77437911 const gpa = gz.astgen.gpa;
77447912
......@@ -7760,219 +7928,219 @@ fn builtinCall(
77607928 });
77617929 gz.instructions.appendAssumeCapacity(new_index);
77627930 const result = indexToRef(new_index);
7763 return rvalue(gz, rl, result, node);
7931 return rvalue(gz, ri, result, node);
77647932 },
77657933 .panic => {
77667934 try emitDbgNode(gz, node);
7767 return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], if (gz.force_comptime) .panic_comptime else .panic);
7935 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], if (gz.force_comptime) .panic_comptime else .panic);
77687936 },
77697937 .error_to_int => {
7770 const operand = try expr(gz, scope, .none, params[0]);
7938 const operand = try expr(gz, scope, .{ .rl = .none }, params[0]);
77717939 const result = try gz.addExtendedPayload(.error_to_int, Zir.Inst.UnNode{
77727940 .node = gz.nodeIndexToRelative(node),
77737941 .operand = operand,
77747942 });
7775 return rvalue(gz, rl, result, node);
7943 return rvalue(gz, ri, result, node);
77767944 },
77777945 .int_to_error => {
7778 const operand = try expr(gz, scope, .{ .coerced_ty = .u16_type }, params[0]);
7946 const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, params[0]);
77797947 const result = try gz.addExtendedPayload(.int_to_error, Zir.Inst.UnNode{
77807948 .node = gz.nodeIndexToRelative(node),
77817949 .operand = operand,
77827950 });
7783 return rvalue(gz, rl, result, node);
7951 return rvalue(gz, ri, result, node);
77847952 },
77857953 .align_cast => {
7786 const dest_align = try comptimeExpr(gz, scope, align_rl, params[0]);
7787 const rhs = try expr(gz, scope, .none, params[1]);
7954 const dest_align = try comptimeExpr(gz, scope, align_ri, params[0]);
7955 const rhs = try expr(gz, scope, .{ .rl = .none }, params[1]);
77887956 const result = try gz.addPlNode(.align_cast, node, Zir.Inst.Bin{
77897957 .lhs = dest_align,
77907958 .rhs = rhs,
77917959 });
7792 return rvalue(gz, rl, result, node);
7960 return rvalue(gz, ri, result, node);
77937961 },
77947962 .err_set_cast => {
77957963 const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{
77967964 .lhs = try typeExpr(gz, scope, params[0]),
7797 .rhs = try expr(gz, scope, .none, params[1]),
7965 .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]),
77987966 .node = gz.nodeIndexToRelative(node),
77997967 });
7800 return rvalue(gz, rl, result, node);
7968 return rvalue(gz, ri, result, node);
78017969 },
78027970 .addrspace_cast => {
78037971 const result = try gz.addExtendedPayload(.addrspace_cast, Zir.Inst.BinNode{
7804 .lhs = try comptimeExpr(gz, scope, .{ .ty = .address_space_type }, params[0]),
7805 .rhs = try expr(gz, scope, .none, params[1]),
7972 .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .address_space_type } }, params[0]),
7973 .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]),
78067974 .node = gz.nodeIndexToRelative(node),
78077975 });
7808 return rvalue(gz, rl, result, node);
7976 return rvalue(gz, ri, result, node);
78097977 },
78107978
78117979 // zig fmt: off
7812 .has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl),
7813 .has_field => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_field),
7980 .has_decl => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_decl),
7981 .has_field => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_field),
78147982
7815 .clz => return bitBuiltin(gz, scope, rl, node, params[0], .clz),
7816 .ctz => return bitBuiltin(gz, scope, rl, node, params[0], .ctz),
7817 .pop_count => return bitBuiltin(gz, scope, rl, node, params[0], .pop_count),
7818 .byte_swap => return bitBuiltin(gz, scope, rl, node, params[0], .byte_swap),
7819 .bit_reverse => return bitBuiltin(gz, scope, rl, node, params[0], .bit_reverse),
7983 .clz => return bitBuiltin(gz, scope, ri, node, params[0], .clz),
7984 .ctz => return bitBuiltin(gz, scope, ri, node, params[0], .ctz),
7985 .pop_count => return bitBuiltin(gz, scope, ri, node, params[0], .pop_count),
7986 .byte_swap => return bitBuiltin(gz, scope, ri, node, params[0], .byte_swap),
7987 .bit_reverse => return bitBuiltin(gz, scope, ri, node, params[0], .bit_reverse),
78207988
7821 .div_exact => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_exact),
7822 .div_floor => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_floor),
7823 .div_trunc => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_trunc),
7824 .mod => return divBuiltin(gz, scope, rl, node, params[0], params[1], .mod),
7825 .rem => return divBuiltin(gz, scope, rl, node, params[0], params[1], .rem),
7989 .div_exact => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_exact),
7990 .div_floor => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_floor),
7991 .div_trunc => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_trunc),
7992 .mod => return divBuiltin(gz, scope, ri, node, params[0], params[1], .mod),
7993 .rem => return divBuiltin(gz, scope, ri, node, params[0], params[1], .rem),
78267994
7827 .shl_exact => return shiftOp(gz, scope, rl, node, params[0], params[1], .shl_exact),
7828 .shr_exact => return shiftOp(gz, scope, rl, node, params[0], params[1], .shr_exact),
7995 .shl_exact => return shiftOp(gz, scope, ri, node, params[0], params[1], .shl_exact),
7996 .shr_exact => return shiftOp(gz, scope, ri, node, params[0], params[1], .shr_exact),
78297997
7830 .bit_offset_of => return offsetOf(gz, scope, rl, node, params[0], params[1], .bit_offset_of),
7831 .offset_of => return offsetOf(gz, scope, rl, node, params[0], params[1], .offset_of),
7998 .bit_offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .bit_offset_of),
7999 .offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .offset_of),
78328000
7833 .c_undef => return simpleCBuiltin(gz, scope, rl, node, params[0], .c_undef),
7834 .c_include => return simpleCBuiltin(gz, scope, rl, node, params[0], .c_include),
8001 .c_undef => return simpleCBuiltin(gz, scope, ri, node, params[0], .c_undef),
8002 .c_include => return simpleCBuiltin(gz, scope, ri, node, params[0], .c_include),
78358003
7836 .cmpxchg_strong => return cmpxchg(gz, scope, rl, node, params, 1),
7837 .cmpxchg_weak => return cmpxchg(gz, scope, rl, node, params, 0),
8004 .cmpxchg_strong => return cmpxchg(gz, scope, ri, node, params, 1),
8005 .cmpxchg_weak => return cmpxchg(gz, scope, ri, node, params, 0),
78388006 // zig fmt: on
78398007
78408008 .wasm_memory_size => {
7841 const operand = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]);
8009 const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
78428010 const result = try gz.addExtendedPayload(.wasm_memory_size, Zir.Inst.UnNode{
78438011 .node = gz.nodeIndexToRelative(node),
78448012 .operand = operand,
78458013 });
7846 return rvalue(gz, rl, result, node);
8014 return rvalue(gz, ri, result, node);
78478015 },
78488016 .wasm_memory_grow => {
7849 const index_arg = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]);
7850 const delta_arg = try expr(gz, scope, .{ .coerced_ty = .u32_type }, params[1]);
8017 const index_arg = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
8018 const delta_arg = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[1]);
78518019 const result = try gz.addExtendedPayload(.wasm_memory_grow, Zir.Inst.BinNode{
78528020 .node = gz.nodeIndexToRelative(node),
78538021 .lhs = index_arg,
78548022 .rhs = delta_arg,
78558023 });
7856 return rvalue(gz, rl, result, node);
8024 return rvalue(gz, ri, result, node);
78578025 },
78588026 .c_define => {
78598027 if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});
7860 const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[0]);
7861 const value = try comptimeExpr(gz, scope, .none, params[1]);
8028 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0]);
8029 const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
78628030 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
78638031 .node = gz.nodeIndexToRelative(node),
78648032 .lhs = name,
78658033 .rhs = value,
78668034 });
7867 return rvalue(gz, rl, result, node);
8035 return rvalue(gz, ri, result, node);
78688036 },
78698037
78708038 .splat => {
7871 const len = try expr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]);
7872 const scalar = try expr(gz, scope, .none, params[1]);
8039 const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
8040 const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]);
78738041 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
78748042 .lhs = len,
78758043 .rhs = scalar,
78768044 });
7877 return rvalue(gz, rl, result, node);
8045 return rvalue(gz, ri, result, node);
78788046 },
78798047 .reduce => {
7880 const op = try expr(gz, scope, .{ .ty = .reduce_op_type }, params[0]);
7881 const scalar = try expr(gz, scope, .none, params[1]);
8048 const op = try expr(gz, scope, .{ .rl = .{ .ty = .reduce_op_type } }, params[0]);
8049 const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]);
78828050 const result = try gz.addPlNode(.reduce, node, Zir.Inst.Bin{
78838051 .lhs = op,
78848052 .rhs = scalar,
78858053 });
7886 return rvalue(gz, rl, result, node);
8054 return rvalue(gz, ri, result, node);
78878055 },
78888056
78898057 .max => {
7890 const a = try expr(gz, scope, .none, params[0]);
7891 const b = try expr(gz, scope, .none, params[1]);
8058 const a = try expr(gz, scope, .{ .rl = .none }, params[0]);
8059 const b = try expr(gz, scope, .{ .rl = .none }, params[1]);
78928060 const result = try gz.addPlNode(.max, node, Zir.Inst.Bin{
78938061 .lhs = a,
78948062 .rhs = b,
78958063 });
7896 return rvalue(gz, rl, result, node);
8064 return rvalue(gz, ri, result, node);
78978065 },
78988066 .min => {
7899 const a = try expr(gz, scope, .none, params[0]);
7900 const b = try expr(gz, scope, .none, params[1]);
8067 const a = try expr(gz, scope, .{ .rl = .none }, params[0]);
8068 const b = try expr(gz, scope, .{ .rl = .none }, params[1]);
79018069 const result = try gz.addPlNode(.min, node, Zir.Inst.Bin{
79028070 .lhs = a,
79038071 .rhs = b,
79048072 });
7905 return rvalue(gz, rl, result, node);
8073 return rvalue(gz, ri, result, node);
79068074 },
79078075
7908 .add_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .add_with_overflow),
7909 .sub_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .sub_with_overflow),
7910 .mul_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .mul_with_overflow),
8076 .add_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .add_with_overflow),
8077 .sub_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .sub_with_overflow),
8078 .mul_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .mul_with_overflow),
79118079 .shl_with_overflow => {
79128080 const int_type = try typeExpr(gz, scope, params[0]);
79138081 const log2_int_type = try gz.addUnNode(.log2_int_type, int_type, params[0]);
79148082 const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);
7915 const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]);
7916 const rhs = try expr(gz, scope, .{ .ty = log2_int_type }, params[2]);
7917 const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);
8083 const lhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[1]);
8084 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type } }, params[2]);
8085 const ptr = try expr(gz, scope, .{ .rl = .{ .ty = ptr_type } }, params[3]);
79188086 const result = try gz.addExtendedPayload(.shl_with_overflow, Zir.Inst.OverflowArithmetic{
79198087 .node = gz.nodeIndexToRelative(node),
79208088 .lhs = lhs,
79218089 .rhs = rhs,
79228090 .ptr = ptr,
79238091 });
7924 return rvalue(gz, rl, result, node);
8092 return rvalue(gz, ri, result, node);
79258093 },
79268094
79278095 .atomic_load => {
79288096 const result = try gz.addPlNode(.atomic_load, node, Zir.Inst.AtomicLoad{
79298097 // zig fmt: off
7930 .elem_type = try typeExpr(gz, scope, params[0]),
7931 .ptr = try expr (gz, scope, .none, params[1]),
7932 .ordering = try expr (gz, scope, .{ .coerced_ty = .atomic_order_type }, params[2]),
8098 .elem_type = try typeExpr(gz, scope, params[0]),
8099 .ptr = try expr (gz, scope, .{ .rl = .none }, params[1]),
8100 .ordering = try expr (gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[2]),
79338101 // zig fmt: on
79348102 });
7935 return rvalue(gz, rl, result, node);
8103 return rvalue(gz, ri, result, node);
79368104 },
79378105 .atomic_rmw => {
79388106 const int_type = try typeExpr(gz, scope, params[0]);
79398107 const result = try gz.addPlNode(.atomic_rmw, node, Zir.Inst.AtomicRmw{
79408108 // zig fmt: off
7941 .ptr = try expr(gz, scope, .none, params[1]),
7942 .operation = try expr(gz, scope, .{ .coerced_ty = .atomic_rmw_op_type }, params[2]),
7943 .operand = try expr(gz, scope, .{ .ty = int_type }, params[3]),
7944 .ordering = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[4]),
8109 .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
8110 .operation = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_rmw_op_type } }, params[2]),
8111 .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[3]),
8112 .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[4]),
79458113 // zig fmt: on
79468114 });
7947 return rvalue(gz, rl, result, node);
8115 return rvalue(gz, ri, result, node);
79488116 },
79498117 .atomic_store => {
79508118 const int_type = try typeExpr(gz, scope, params[0]);
79518119 const result = try gz.addPlNode(.atomic_store, node, Zir.Inst.AtomicStore{
79528120 // zig fmt: off
7953 .ptr = try expr(gz, scope, .none, params[1]),
7954 .operand = try expr(gz, scope, .{ .ty = int_type }, params[2]),
7955 .ordering = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[3]),
8121 .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
8122 .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]),
8123 .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[3]),
79568124 // zig fmt: on
79578125 });
7958 return rvalue(gz, rl, result, node);
8126 return rvalue(gz, ri, result, node);
79598127 },
79608128 .mul_add => {
79618129 const float_type = try typeExpr(gz, scope, params[0]);
7962 const mulend1 = try expr(gz, scope, .{ .coerced_ty = float_type }, params[1]);
7963 const mulend2 = try expr(gz, scope, .{ .coerced_ty = float_type }, params[2]);
7964 const addend = try expr(gz, scope, .{ .ty = float_type }, params[3]);
8130 const mulend1 = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_type } }, params[1]);
8131 const mulend2 = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_type } }, params[2]);
8132 const addend = try expr(gz, scope, .{ .rl = .{ .ty = float_type } }, params[3]);
79658133 const result = try gz.addPlNode(.mul_add, node, Zir.Inst.MulAdd{
79668134 .mulend1 = mulend1,
79678135 .mulend2 = mulend2,
79688136 .addend = addend,
79698137 });
7970 return rvalue(gz, rl, result, node);
8138 return rvalue(gz, ri, result, node);
79718139 },
79728140 .call => {
7973 const options = try comptimeExpr(gz, scope, .{ .ty = .call_options_type }, params[0]);
8141 const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .call_options_type } }, params[0]);
79748142 const callee = try calleeExpr(gz, scope, params[1]);
7975 const args = try expr(gz, scope, .none, params[2]);
8143 const args = try expr(gz, scope, .{ .rl = .none }, params[2]);
79768144 const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{
79778145 .options = options,
79788146 .callee = callee,
......@@ -7983,115 +8151,115 @@ fn builtinCall(
79838151 .ensure_result_used = false,
79848152 },
79858153 });
7986 return rvalue(gz, rl, result, node);
8154 return rvalue(gz, ri, result, node);
79878155 },
79888156 .field_parent_ptr => {
79898157 const parent_type = try typeExpr(gz, scope, params[0]);
7990 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
8158 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]);
79918159 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{
79928160 .parent_type = parent_type,
79938161 .field_name = field_name,
7994 .field_ptr = try expr(gz, scope, .none, params[2]),
8162 .field_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]),
79958163 });
7996 return rvalue(gz, rl, result, node);
8164 return rvalue(gz, ri, result, node);
79978165 },
79988166 .memcpy => {
79998167 const result = try gz.addPlNode(.memcpy, node, Zir.Inst.Memcpy{
8000 .dest = try expr(gz, scope, .{ .coerced_ty = .manyptr_u8_type }, params[0]),
8001 .source = try expr(gz, scope, .{ .coerced_ty = .manyptr_const_u8_type }, params[1]),
8002 .byte_count = try expr(gz, scope, .{ .coerced_ty = .usize_type }, params[2]),
8168 .dest = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_u8_type } }, params[0]),
8169 .source = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_const_u8_type } }, params[1]),
8170 .byte_count = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, params[2]),
80038171 });
8004 return rvalue(gz, rl, result, node);
8172 return rvalue(gz, ri, result, node);
80058173 },
80068174 .memset => {
80078175 const result = try gz.addPlNode(.memset, node, Zir.Inst.Memset{
8008 .dest = try expr(gz, scope, .{ .coerced_ty = .manyptr_u8_type }, params[0]),
8009 .byte = try expr(gz, scope, .{ .coerced_ty = .u8_type }, params[1]),
8010 .byte_count = try expr(gz, scope, .{ .coerced_ty = .usize_type }, params[2]),
8176 .dest = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_u8_type } }, params[0]),
8177 .byte = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u8_type } }, params[1]),
8178 .byte_count = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, params[2]),
80118179 });
8012 return rvalue(gz, rl, result, node);
8180 return rvalue(gz, ri, result, node);
80138181 },
80148182 .shuffle => {
80158183 const result = try gz.addPlNode(.shuffle, node, Zir.Inst.Shuffle{
80168184 .elem_type = try typeExpr(gz, scope, params[0]),
8017 .a = try expr(gz, scope, .none, params[1]),
8018 .b = try expr(gz, scope, .none, params[2]),
8019 .mask = try comptimeExpr(gz, scope, .none, params[3]),
8185 .a = try expr(gz, scope, .{ .rl = .none }, params[1]),
8186 .b = try expr(gz, scope, .{ .rl = .none }, params[2]),
8187 .mask = try comptimeExpr(gz, scope, .{ .rl = .none }, params[3]),
80208188 });
8021 return rvalue(gz, rl, result, node);
8189 return rvalue(gz, ri, result, node);
80228190 },
80238191 .select => {
80248192 const result = try gz.addExtendedPayload(.select, Zir.Inst.Select{
80258193 .node = gz.nodeIndexToRelative(node),
80268194 .elem_type = try typeExpr(gz, scope, params[0]),
8027 .pred = try expr(gz, scope, .none, params[1]),
8028 .a = try expr(gz, scope, .none, params[2]),
8029 .b = try expr(gz, scope, .none, params[3]),
8195 .pred = try expr(gz, scope, .{ .rl = .none }, params[1]),
8196 .a = try expr(gz, scope, .{ .rl = .none }, params[2]),
8197 .b = try expr(gz, scope, .{ .rl = .none }, params[3]),
80308198 });
8031 return rvalue(gz, rl, result, node);
8199 return rvalue(gz, ri, result, node);
80328200 },
80338201 .async_call => {
80348202 const result = try gz.addExtendedPayload(.builtin_async_call, Zir.Inst.AsyncCall{
80358203 .node = gz.nodeIndexToRelative(node),
8036 .frame_buffer = try expr(gz, scope, .none, params[0]),
8037 .result_ptr = try expr(gz, scope, .none, params[1]),
8038 .fn_ptr = try expr(gz, scope, .none, params[2]),
8039 .args = try expr(gz, scope, .none, params[3]),
8204 .frame_buffer = try expr(gz, scope, .{ .rl = .none }, params[0]),
8205 .result_ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
8206 .fn_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]),
8207 .args = try expr(gz, scope, .{ .rl = .none }, params[3]),
80408208 });
8041 return rvalue(gz, rl, result, node);
8209 return rvalue(gz, ri, result, node);
80428210 },
80438211 .Vector => {
80448212 const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{
8045 .lhs = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]),
8213 .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]),
80468214 .rhs = try typeExpr(gz, scope, params[1]),
80478215 });
8048 return rvalue(gz, rl, result, node);
8216 return rvalue(gz, ri, result, node);
80498217 },
80508218 .prefetch => {
8051 const ptr = try expr(gz, scope, .none, params[0]);
8052 const options = try comptimeExpr(gz, scope, .{ .ty = .prefetch_options_type }, params[1]);
8219 const ptr = try expr(gz, scope, .{ .rl = .none }, params[0]);
8220 const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .prefetch_options_type } }, params[1]);
80538221 const result = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{
80548222 .node = gz.nodeIndexToRelative(node),
80558223 .lhs = ptr,
80568224 .rhs = options,
80578225 });
8058 return rvalue(gz, rl, result, node);
8226 return rvalue(gz, ri, result, node);
80598227 },
80608228 }
80618229}
80628230
80638231fn simpleNoOpVoid(
80648232 gz: *GenZir,
8065 rl: ResultLoc,
8233 ri: ResultInfo,
80668234 node: Ast.Node.Index,
80678235 tag: Zir.Inst.Tag,
80688236) InnerError!Zir.Inst.Ref {
80698237 _ = try gz.addNode(tag, node);
8070 return rvalue(gz, rl, .void_value, node);
8238 return rvalue(gz, ri, .void_value, node);
80718239}
80728240
80738241fn hasDeclOrField(
80748242 gz: *GenZir,
80758243 scope: *Scope,
8076 rl: ResultLoc,
8244 ri: ResultInfo,
80778245 node: Ast.Node.Index,
80788246 lhs_node: Ast.Node.Index,
80798247 rhs_node: Ast.Node.Index,
80808248 tag: Zir.Inst.Tag,
80818249) InnerError!Zir.Inst.Ref {
80828250 const container_type = try typeExpr(gz, scope, lhs_node);
8083 const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, rhs_node);
8251 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, rhs_node);
80848252 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
80858253 .lhs = container_type,
80868254 .rhs = name,
80878255 });
8088 return rvalue(gz, rl, result, node);
8256 return rvalue(gz, ri, result, node);
80898257}
80908258
80918259fn typeCast(
80928260 gz: *GenZir,
80938261 scope: *Scope,
8094 rl: ResultLoc,
8262 ri: ResultInfo,
80958263 node: Ast.Node.Index,
80968264 lhs_node: Ast.Node.Index,
80978265 rhs_node: Ast.Node.Index,
......@@ -8099,42 +8267,42 @@ fn typeCast(
80998267) InnerError!Zir.Inst.Ref {
81008268 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
81018269 .lhs = try typeExpr(gz, scope, lhs_node),
8102 .rhs = try expr(gz, scope, .none, rhs_node),
8270 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),
81038271 });
8104 return rvalue(gz, rl, result, node);
8272 return rvalue(gz, ri, result, node);
81058273}
81068274
81078275fn simpleUnOpType(
81088276 gz: *GenZir,
81098277 scope: *Scope,
8110 rl: ResultLoc,
8278 ri: ResultInfo,
81118279 node: Ast.Node.Index,
81128280 operand_node: Ast.Node.Index,
81138281 tag: Zir.Inst.Tag,
81148282) InnerError!Zir.Inst.Ref {
81158283 const operand = try typeExpr(gz, scope, operand_node);
81168284 const result = try gz.addUnNode(tag, operand, node);
8117 return rvalue(gz, rl, result, node);
8285 return rvalue(gz, ri, result, node);
81188286}
81198287
81208288fn simpleUnOp(
81218289 gz: *GenZir,
81228290 scope: *Scope,
8123 rl: ResultLoc,
8291 ri: ResultInfo,
81248292 node: Ast.Node.Index,
8125 operand_rl: ResultLoc,
8293 operand_ri: ResultInfo,
81268294 operand_node: Ast.Node.Index,
81278295 tag: Zir.Inst.Tag,
81288296) InnerError!Zir.Inst.Ref {
8129 const operand = try expr(gz, scope, operand_rl, operand_node);
8297 const operand = try expr(gz, scope, operand_ri, operand_node);
81308298 const result = try gz.addUnNode(tag, operand, node);
8131 return rvalue(gz, rl, result, node);
8299 return rvalue(gz, ri, result, node);
81328300}
81338301
81348302fn negation(
81358303 gz: *GenZir,
81368304 scope: *Scope,
8137 rl: ResultLoc,
8305 ri: ResultInfo,
81388306 node: Ast.Node.Index,
81398307) InnerError!Zir.Inst.Ref {
81408308 const astgen = gz.astgen;
......@@ -8146,18 +8314,18 @@ fn negation(
81468314 // its negativity rather than having it go through comptime subtraction.
81478315 const operand_node = node_datas[node].lhs;
81488316 if (node_tags[operand_node] == .number_literal) {
8149 return numberLiteral(gz, rl, operand_node, node, .negative);
8317 return numberLiteral(gz, ri, operand_node, node, .negative);
81508318 }
81518319
8152 const operand = try expr(gz, scope, .none, operand_node);
8320 const operand = try expr(gz, scope, .{ .rl = .none }, operand_node);
81538321 const result = try gz.addUnNode(.negate, operand, node);
8154 return rvalue(gz, rl, result, node);
8322 return rvalue(gz, ri, result, node);
81558323}
81568324
81578325fn cmpxchg(
81588326 gz: *GenZir,
81598327 scope: *Scope,
8160 rl: ResultLoc,
8328 ri: ResultInfo,
81618329 node: Ast.Node.Index,
81628330 params: []const Ast.Node.Index,
81638331 small: u16,
......@@ -8166,98 +8334,98 @@ fn cmpxchg(
81668334 const result = try gz.addExtendedPayloadSmall(.cmpxchg, small, Zir.Inst.Cmpxchg{
81678335 // zig fmt: off
81688336 .node = gz.nodeIndexToRelative(node),
8169 .ptr = try expr(gz, scope, .none, params[1]),
8170 .expected_value = try expr(gz, scope, .{ .ty = int_type }, params[2]),
8171 .new_value = try expr(gz, scope, .{ .coerced_ty = int_type }, params[3]),
8172 .success_order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[4]),
8173 .failure_order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[5]),
8337 .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
8338 .expected_value = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]),
8339 .new_value = try expr(gz, scope, .{ .rl = .{ .coerced_ty = int_type } }, params[3]),
8340 .success_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[4]),
8341 .failure_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[5]),
81748342 // zig fmt: on
81758343 });
8176 return rvalue(gz, rl, result, node);
8344 return rvalue(gz, ri, result, node);
81778345}
81788346
81798347fn bitBuiltin(
81808348 gz: *GenZir,
81818349 scope: *Scope,
8182 rl: ResultLoc,
8350 ri: ResultInfo,
81838351 node: Ast.Node.Index,
81848352 operand_node: Ast.Node.Index,
81858353 tag: Zir.Inst.Tag,
81868354) InnerError!Zir.Inst.Ref {
8187 const operand = try expr(gz, scope, .none, operand_node);
8355 const operand = try expr(gz, scope, .{ .rl = .none }, operand_node);
81888356 const result = try gz.addUnNode(tag, operand, node);
8189 return rvalue(gz, rl, result, node);
8357 return rvalue(gz, ri, result, node);
81908358}
81918359
81928360fn divBuiltin(
81938361 gz: *GenZir,
81948362 scope: *Scope,
8195 rl: ResultLoc,
8363 ri: ResultInfo,
81968364 node: Ast.Node.Index,
81978365 lhs_node: Ast.Node.Index,
81988366 rhs_node: Ast.Node.Index,
81998367 tag: Zir.Inst.Tag,
82008368) InnerError!Zir.Inst.Ref {
82018369 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8202 .lhs = try expr(gz, scope, .none, lhs_node),
8203 .rhs = try expr(gz, scope, .none, rhs_node),
8370 .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node),
8371 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),
82048372 });
8205 return rvalue(gz, rl, result, node);
8373 return rvalue(gz, ri, result, node);
82068374}
82078375
82088376fn simpleCBuiltin(
82098377 gz: *GenZir,
82108378 scope: *Scope,
8211 rl: ResultLoc,
8379 ri: ResultInfo,
82128380 node: Ast.Node.Index,
82138381 operand_node: Ast.Node.Index,
82148382 tag: Zir.Inst.Extended,
82158383) InnerError!Zir.Inst.Ref {
82168384 const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
82178385 if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});
8218 const operand = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, operand_node);
8386 const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, operand_node);
82198387 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
82208388 .node = gz.nodeIndexToRelative(node),
82218389 .operand = operand,
82228390 });
8223 return rvalue(gz, rl, .void_value, node);
8391 return rvalue(gz, ri, .void_value, node);
82248392}
82258393
82268394fn offsetOf(
82278395 gz: *GenZir,
82288396 scope: *Scope,
8229 rl: ResultLoc,
8397 ri: ResultInfo,
82308398 node: Ast.Node.Index,
82318399 lhs_node: Ast.Node.Index,
82328400 rhs_node: Ast.Node.Index,
82338401 tag: Zir.Inst.Tag,
82348402) InnerError!Zir.Inst.Ref {
82358403 const type_inst = try typeExpr(gz, scope, lhs_node);
8236 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, rhs_node);
8404 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, rhs_node);
82378405 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
82388406 .lhs = type_inst,
82398407 .rhs = field_name,
82408408 });
8241 return rvalue(gz, rl, result, node);
8409 return rvalue(gz, ri, result, node);
82428410}
82438411
82448412fn shiftOp(
82458413 gz: *GenZir,
82468414 scope: *Scope,
8247 rl: ResultLoc,
8415 ri: ResultInfo,
82488416 node: Ast.Node.Index,
82498417 lhs_node: Ast.Node.Index,
82508418 rhs_node: Ast.Node.Index,
82518419 tag: Zir.Inst.Tag,
82528420) InnerError!Zir.Inst.Ref {
8253 const lhs = try expr(gz, scope, .none, lhs_node);
8421 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
82548422 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
8255 const rhs = try expr(gz, scope, .{ .ty_shift_operand = log2_int_type }, rhs_node);
8423 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);
82568424 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
82578425 .lhs = lhs,
82588426 .rhs = rhs,
82598427 });
8260 return rvalue(gz, rl, result, node);
8428 return rvalue(gz, ri, result, node);
82618429}
82628430
82638431fn cImport(
......@@ -8275,7 +8443,7 @@ fn cImport(
82758443 defer block_scope.unstack();
82768444
82778445 const block_inst = try gz.makeBlockInst(.c_import, node);
8278 const block_result = try expr(&block_scope, &block_scope.base, .none, body_node);
8446 const block_result = try expr(&block_scope, &block_scope.base, .{ .rl = .none }, body_node);
82798447 _ = try gz.addUnNode(.ensure_result_used, block_result, node);
82808448 if (!gz.refIsNoReturn(block_result)) {
82818449 _ = try block_scope.addBreak(.break_inline, block_inst, .void_value);
......@@ -8290,29 +8458,29 @@ fn cImport(
82908458fn overflowArithmetic(
82918459 gz: *GenZir,
82928460 scope: *Scope,
8293 rl: ResultLoc,
8461 ri: ResultInfo,
82948462 node: Ast.Node.Index,
82958463 params: []const Ast.Node.Index,
82968464 tag: Zir.Inst.Extended,
82978465) InnerError!Zir.Inst.Ref {
82988466 const int_type = try typeExpr(gz, scope, params[0]);
82998467 const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);
8300 const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]);
8301 const rhs = try expr(gz, scope, .{ .ty = int_type }, params[2]);
8302 const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);
8468 const lhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[1]);
8469 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]);
8470 const ptr = try expr(gz, scope, .{ .rl = .{ .ty = ptr_type } }, params[3]);
83038471 const result = try gz.addExtendedPayload(tag, Zir.Inst.OverflowArithmetic{
83048472 .node = gz.nodeIndexToRelative(node),
83058473 .lhs = lhs,
83068474 .rhs = rhs,
83078475 .ptr = ptr,
83088476 });
8309 return rvalue(gz, rl, result, node);
8477 return rvalue(gz, ri, result, node);
83108478}
83118479
83128480fn callExpr(
83138481 gz: *GenZir,
83148482 scope: *Scope,
8315 rl: ResultLoc,
8483 ri: ResultInfo,
83168484 node: Ast.Node.Index,
83178485 call: Ast.full.Call,
83188486) InnerError!Zir.Inst.Ref {
......@@ -8364,7 +8532,7 @@ fn callExpr(
83648532 defer arg_block.unstack();
83658533
83668534 // `call_inst` is reused to provide the param type.
8367 const arg_ref = try expr(&arg_block, &arg_block.base, .{ .coerced_ty = call_inst }, param_node);
8535 const arg_ref = try expr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst }, .ctx = .fn_arg }, param_node);
83688536 _ = try arg_block.addBreak(.break_inline, call_index, arg_ref);
83698537
83708538 const body = arg_block.instructionsSlice();
......@@ -8375,9 +8543,18 @@ fn callExpr(
83758543 scratch_index += 1;
83768544 }
83778545
8546 // If our result location is a try/catch/error-union-if/return, a function argument,
8547 // or an initializer for a `const` variable, the error trace propagates.
8548 // Otherwise, it should always be popped (handled in Sema).
8549 const propagate_error_trace = switch (ri.ctx) {
8550 .error_handling_expr, .@"return", .fn_arg, .const_init => true,
8551 else => false,
8552 };
8553
83788554 const payload_index = try addExtra(astgen, Zir.Inst.Call{
83798555 .callee = callee,
83808556 .flags = .{
8557 .pop_error_return_trace = !propagate_error_trace,
83818558 .packed_modifier = @intCast(Zir.Inst.Call.Flags.PackedModifier, @enumToInt(modifier)),
83828559 .args_len = @intCast(Zir.Inst.Call.Flags.PackedArgsLen, call.ast.params.len),
83838560 },
......@@ -8392,7 +8569,7 @@ fn callExpr(
83928569 .payload_index = payload_index,
83938570 } },
83948571 });
8395 return rvalue(gz, rl, call_inst, node); // TODO function call with result location
8572 return rvalue(gz, ri, call_inst, node); // TODO function call with result location
83968573}
83978574
83988575/// calleeExpr generates the function part of a call expression (f in f(x)), or the
......@@ -8413,7 +8590,7 @@ fn calleeExpr(
84138590
84148591 const tag = tree.nodes.items(.tag)[node];
84158592 switch (tag) {
8416 .field_access => return addFieldAccess(.field_call_bind, gz, scope, .ref, node),
8593 .field_access => return addFieldAccess(.field_call_bind, gz, scope, .{ .rl = .ref }, node),
84178594
84188595 .builtin_call_two,
84198596 .builtin_call_two_comma,
......@@ -8445,8 +8622,8 @@ fn calleeExpr(
84458622 // If anything is wrong, fall back to builtinCall.
84468623 // It will emit any necessary compile errors and notes.
84478624 if (std.mem.eql(u8, builtin_name, "@field") and params.len == 2) {
8448 const lhs = try expr(gz, scope, .ref, params[0]);
8449 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
8625 const lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]);
8626 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]);
84508627 return gz.addExtendedPayload(.field_call_bind_named, Zir.Inst.FieldNamedNode{
84518628 .node = gz.nodeIndexToRelative(node),
84528629 .lhs = lhs,
......@@ -8454,9 +8631,9 @@ fn calleeExpr(
84548631 });
84558632 }
84568633
8457 return builtinCall(gz, scope, .none, node, params);
8634 return builtinCall(gz, scope, .{ .rl = .none }, node, params);
84588635 },
8459 else => return expr(gz, scope, .none, node),
8636 else => return expr(gz, scope, .{ .rl = .none }, node),
84608637 }
84618638}
84628639
......@@ -8738,6 +8915,33 @@ fn nodeMayNeedMemoryLocation(tree: *const Ast, start_node: Ast.Node.Index, have_
87388915 }
87398916}
87408917
8918fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool {
8919 const node_tags = tree.nodes.items(.tag);
8920 const node_datas = tree.nodes.items(.data);
8921
8922 var node = start_node;
8923 while (true) {
8924 switch (node_tags[node]) {
8925 // These don't have the opportunity to call any runtime functions.
8926 .error_value,
8927 .identifier,
8928 .@"comptime",
8929 => return false,
8930
8931 // Forward the question to the LHS sub-expression.
8932 .grouped_expression,
8933 .@"try",
8934 .@"nosuspend",
8935 .unwrap_optional,
8936 => node = node_datas[node].lhs,
8937
8938 // Anything that does not eval to an error is guaranteed to pop any
8939 // additions to the error trace, so it effectively does not append.
8940 else => return nodeMayEvalToError(tree, start_node) != .never,
8941 }
8942 }
8943}
8944
87418945fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError {
87428946 const node_tags = tree.nodes.items(.tag);
87438947 const node_datas = tree.nodes.items(.data);
......@@ -9472,7 +9676,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
94729676/// Assumes nothing stacked on `gz`.
94739677fn rvalue(
94749678 gz: *GenZir,
9475 rl: ResultLoc,
9679 ri: ResultInfo,
94769680 raw_result: Zir.Inst.Ref,
94779681 src_node: Ast.Node.Index,
94789682) InnerError!Zir.Inst.Ref {
......@@ -9487,7 +9691,7 @@ fn rvalue(
94879691 break :r raw_result;
94889692 };
94899693 if (gz.endsWithNoReturn()) return result;
9490 switch (rl) {
9694 switch (ri.rl) {
94919695 .none, .coerced_ty => return result,
94929696 .discard => {
94939697 // Emit a compile error for discarding error values.
......@@ -9513,7 +9717,7 @@ fn rvalue(
95139717 }
95149718 return indexToRef(gop.value_ptr.*);
95159719 },
9516 .ty, .ty_shift_operand => |ty_inst| {
9720 .ty => |ty_inst| {
95179721 // Quickly eliminate some common, unnecessary type coercion.
95189722 const as_ty = @as(u64, @enumToInt(Zir.Inst.Ref.type_type)) << 32;
95199723 const as_comptime_int = @as(u64, @enumToInt(Zir.Inst.Ref.comptime_int_type)) << 32;
......@@ -9574,7 +9778,7 @@ fn rvalue(
95749778 => return result, // type of result is already correct
95759779
95769780 // Need an explicit type coercion instruction.
9577 else => return gz.addPlNode(rl.zirTag(), src_node, Zir.Inst.As{
9781 else => return gz.addPlNode(ri.zirTag(), src_node, Zir.Inst.As{
95789782 .dest_type = ty_inst,
95799783 .operand = result,
95809784 }),
......@@ -10268,8 +10472,8 @@ const GenZir = struct {
1026810472 label: ?Label = null,
1026910473 break_block: Zir.Inst.Index = 0,
1027010474 continue_block: Zir.Inst.Index = 0,
10271 /// Only valid when setBreakResultLoc is called.
10272 break_result_loc: AstGen.ResultLoc = undefined,
10475 /// Only valid when setBreakResultInfo is called.
10476 break_result_info: AstGen.ResultInfo = undefined,
1027310477 /// When a block has a pointer result location, here it is.
1027410478 rl_ptr: Zir.Inst.Ref = .none,
1027510479 /// When a block has a type result location, here it is.
......@@ -10371,7 +10575,7 @@ const GenZir = struct {
1037110575 fn finishCoercion(
1037210576 as_scope: *GenZir,
1037310577 parent_gz: *GenZir,
10374 rl: ResultLoc,
10578 ri: ResultInfo,
1037510579 src_node: Ast.Node.Index,
1037610580 result: Zir.Inst.Ref,
1037710581 dest_type: Zir.Inst.Ref,
......@@ -10397,7 +10601,7 @@ const GenZir = struct {
1039710601 as_scope.instructions_top = GenZir.unstacked_top;
1039810602 // as_scope now unstacked, can add new instructions to parent_gz
1039910603 const casted_result = try parent_gz.addBin(.as, dest_type, result);
10400 return rvalue(parent_gz, rl, casted_result, src_node);
10604 return rvalue(parent_gz, ri, casted_result, src_node);
1040110605 } else {
1040210606 // implicitly move all as_scope instructions to parent_gz
1040310607 as_scope.instructions_top = GenZir.unstacked_top;
......@@ -10440,7 +10644,7 @@ const GenZir = struct {
1044010644 return gz.astgen.tree.firstToken(gz.decl_node_index);
1044110645 }
1044210646
10443 fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void {
10647 fn setBreakResultInfo(gz: *GenZir, parent_ri: AstGen.ResultInfo) void {
1044410648 // Depending on whether the result location is a pointer or value, different
1044510649 // ZIR needs to be generated. In the former case we rely on storing to the
1044610650 // pointer to communicate the result, and use breakvoid; in the latter case
......@@ -10449,32 +10653,32 @@ const GenZir = struct {
1044910653 // the scenario where the result location is not consumed. In this case
1045010654 // we emit ZIR for the block break instructions to have the result values,
1045110655 // and then rvalue() on that to pass the value to the result location.
10452 switch (parent_rl) {
10453 .ty, .ty_shift_operand, .coerced_ty => |ty_inst| {
10656 switch (parent_ri.rl) {
10657 .ty, .coerced_ty => |ty_inst| {
1045410658 gz.rl_ty_inst = ty_inst;
10455 gz.break_result_loc = parent_rl;
10659 gz.break_result_info = parent_ri;
1045610660 },
1045710661
1045810662 .discard, .none, .ref => {
1045910663 gz.rl_ty_inst = .none;
10460 gz.break_result_loc = parent_rl;
10664 gz.break_result_info = parent_ri;
1046110665 },
1046210666
1046310667 .ptr => |ptr_res| {
1046410668 gz.rl_ty_inst = .none;
10465 gz.break_result_loc = .{ .ptr = .{ .inst = ptr_res.inst } };
10669 gz.break_result_info = .{ .rl = .{ .ptr = .{ .inst = ptr_res.inst } } };
1046610670 },
1046710671
1046810672 .inferred_ptr => |ptr| {
1046910673 gz.rl_ty_inst = .none;
1047010674 gz.rl_ptr = ptr;
10471 gz.break_result_loc = .{ .block_ptr = gz };
10675 gz.break_result_info = .{ .rl = .{ .block_ptr = gz }, .ctx = parent_ri.ctx };
1047210676 },
1047310677
1047410678 .block_ptr => |parent_block_scope| {
1047510679 gz.rl_ty_inst = parent_block_scope.rl_ty_inst;
1047610680 gz.rl_ptr = parent_block_scope.rl_ptr;
10477 gz.break_result_loc = .{ .block_ptr = gz };
10681 gz.break_result_info = .{ .rl = .{ .block_ptr = gz }, .ctx = parent_ri.ctx };
1047810682 },
1047910683 }
1048010684 }
......@@ -11157,6 +11361,46 @@ const GenZir = struct {
1115711361 });
1115811362 }
1115911363
11364 fn addSaveErrRetIndex(
11365 gz: *GenZir,
11366 cond: union(enum) {
11367 always: void,
11368 if_of_error_type: Zir.Inst.Ref,
11369 },
11370 ) !Zir.Inst.Index {
11371 return gz.addAsIndex(.{
11372 .tag = .save_err_ret_index,
11373 .data = .{ .save_err_ret_index = .{
11374 .operand = if (cond == .if_of_error_type) cond.if_of_error_type else .none,
11375 } },
11376 });
11377 }
11378
11379 const BranchTarget = union(enum) {
11380 ret,
11381 block: Zir.Inst.Index,
11382 };
11383
11384 fn addRestoreErrRetIndex(
11385 gz: *GenZir,
11386 bt: BranchTarget,
11387 cond: union(enum) {
11388 always: void,
11389 if_non_error: Zir.Inst.Ref,
11390 },
11391 ) !Zir.Inst.Index {
11392 return gz.addAsIndex(.{
11393 .tag = .restore_err_ret_index,
11394 .data = .{ .restore_err_ret_index = .{
11395 .block = switch (bt) {
11396 .ret => .none,
11397 .block => |b| Zir.indexToRef(b),
11398 },
11399 .operand = if (cond == .if_non_error) cond.if_non_error else .none,
11400 } },
11401 });
11402 }
11403
1116011404 fn addBreak(
1116111405 gz: *GenZir,
1116211406 tag: Zir.Inst.Tag,
......@@ -11624,10 +11868,10 @@ const GenZir = struct {
1162411868 return new_index;
1162511869 }
1162611870
11627 fn addRet(gz: *GenZir, rl: ResultLoc, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void {
11628 switch (rl) {
11871 fn addRet(gz: *GenZir, ri: ResultInfo, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void {
11872 switch (ri.rl) {
1162911873 .ptr => |ptr_res| _ = try gz.addUnNode(.ret_load, ptr_res.inst, node),
11630 .ty, .ty_shift_operand => _ = try gz.addUnNode(.ret_node, operand, node),
11874 .ty => _ = try gz.addUnNode(.ret_node, operand, node),
1163111875 else => unreachable,
1163211876 }
1163311877 }
src/Liveness.zig+2
......@@ -228,6 +228,7 @@ pub fn categorizeOperand(
228228 .frame_addr,
229229 .wasm_memory_size,
230230 .err_return_trace,
231 .save_err_return_trace_index,
231232 => return .none,
232233
233234 .fence => return .write,
......@@ -805,6 +806,7 @@ fn analyzeInst(
805806 .frame_addr,
806807 .wasm_memory_size,
807808 .err_return_trace,
809 .save_err_return_trace_index,
808810 => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),
809811
810812 .not,
src/Module.zig+6
......@@ -5633,6 +5633,12 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
56335633
56345634 const last_arg_index = inner_block.instructions.items.len;
56355635
5636 // Save the error trace as our first action in the function.
5637 // If this is unnecessary after all, Liveness will clean it up for us.
5638 const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&inner_block);
5639 sema.error_return_trace_index_on_fn_entry = error_return_trace_index;
5640 inner_block.error_return_trace_index = error_return_trace_index;
5641
56365642 sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
56375643 // TODO make these unreachable instead of @panic
56385644 error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),
src/Sema.zig+317-33
......@@ -32,6 +32,8 @@ owner_func: ?*Module.Fn,
3232/// This starts out the same as `owner_func` and then diverges in the case of
3333/// an inline or comptime function call.
3434func: ?*Module.Fn,
35/// Used to restore the error return trace when returning a non-error from a function.
36error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
3537/// When semantic analysis needs to know the return type of the function whose body
3638/// is being analyzed, this `Type` should be used instead of going through `func`.
3739/// This will correctly handle the case of a comptime/inline function call of a
......@@ -153,6 +155,10 @@ pub const Block = struct {
153155 is_typeof: bool = false,
154156 is_coerce_result_ptr: bool = false,
155157
158 /// Keep track of the active error return trace index around blocks so that we can correctly
159 /// pop the error trace upon block exit.
160 error_return_trace_index: Air.Inst.Ref = .none,
161
156162 /// when null, it is determined by build mode, changed by @setRuntimeSafety
157163 want_safety: ?bool = null,
158164
......@@ -226,6 +232,7 @@ pub const Block = struct {
226232 .float_mode = parent.float_mode,
227233 .c_import_buf = parent.c_import_buf,
228234 .switch_else_err_ty = parent.switch_else_err_ty,
235 .error_return_trace_index = parent.error_return_trace_index,
229236 };
230237 }
231238
......@@ -499,6 +506,25 @@ pub const Block = struct {
499506 return result_index;
500507 }
501508
509 /// Insert an instruction into the block at `index`. Moves all following
510 /// instructions forward in the block to make room. Operation is O(N).
511 pub fn insertInst(block: *Block, index: Air.Inst.Index, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref {
512 return Air.indexToRef(try block.insertInstAsIndex(index, inst));
513 }
514
515 pub fn insertInstAsIndex(block: *Block, index: Air.Inst.Index, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Index {
516 const sema = block.sema;
517 const gpa = sema.gpa;
518
519 try sema.air_instructions.ensureUnusedCapacity(gpa, 1);
520
521 const result_index = @intCast(Air.Inst.Index, sema.air_instructions.len);
522 sema.air_instructions.appendAssumeCapacity(inst);
523
524 try block.instructions.insert(gpa, index, result_index);
525 return result_index;
526 }
527
502528 fn addUnreachable(block: *Block, src: LazySrcLoc, safety_check: bool) !void {
503529 if (safety_check and block.wantSafety()) {
504530 _ = try block.sema.safetyPanic(block, src, .unreach);
......@@ -1208,6 +1234,16 @@ fn analyzeBodyInner(
12081234 i += 1;
12091235 continue;
12101236 },
1237 .save_err_ret_index => {
1238 try sema.zirSaveErrRetIndex(block, inst);
1239 i += 1;
1240 continue;
1241 },
1242 .restore_err_ret_index => {
1243 try sema.zirRestoreErrRetIndex(block, inst);
1244 i += 1;
1245 continue;
1246 },
12111247
12121248 // Special case instructions to handle comptime control flow.
12131249 .@"break" => {
......@@ -1300,31 +1336,32 @@ fn analyzeBodyInner(
13001336 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
13011337 const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
13021338 const gpa = sema.gpa;
1303 // If this block contains a function prototype, we need to reset the
1304 // current list of parameters and restore it later.
1305 // Note: this probably needs to be resolved in a more general manner.
1306 const prev_params = block.params;
1307 const need_sub_block = tags[inline_body[inline_body.len - 1]] == .repeat_inline;
1308 var sub_block = block;
1309 var block_space: Block = undefined;
1310 // NOTE: this has to be done like this because branching in
1311 // defers here breaks stage1.
1312 block_space.instructions = .{};
1313 if (need_sub_block) {
1314 block_space = block.makeSubBlock();
1315 block_space.inline_block = inline_body[0];
1316 sub_block = &block_space;
1317 }
1318 block.params = .{};
1319 defer {
1320 block.params.deinit(gpa);
1321 block.params = prev_params;
1322 block_space.instructions.deinit(gpa);
1323 }
1324 const opt_break_data = try sema.analyzeBodyBreak(sub_block, inline_body);
1325 if (need_sub_block) {
1326 try block.instructions.appendSlice(gpa, block_space.instructions.items);
1327 }
1339
1340 const opt_break_data = b: {
1341 // Create a temporary child block so that this inline block is properly
1342 // labeled for any .restore_err_ret_index instructions
1343 var child_block = block.makeSubBlock();
1344
1345 // If this block contains a function prototype, we need to reset the
1346 // current list of parameters and restore it later.
1347 // Note: this probably needs to be resolved in a more general manner.
1348 if (tags[inline_body[inline_body.len - 1]] == .repeat_inline) {
1349 child_block.inline_block = inline_body[0];
1350 } else child_block.inline_block = block.inline_block;
1351
1352 var label: Block.Label = .{
1353 .zir_block = inst,
1354 .merges = undefined,
1355 };
1356 child_block.label = &label;
1357 defer child_block.params.deinit(gpa);
1358
1359 // Write these instructions directly into the parent block
1360 child_block.instructions = block.instructions;
1361 defer block.instructions = child_block.instructions;
1362
1363 break :b try sema.analyzeBodyBreak(&child_block, inline_body);
1364 };
13281365
13291366 // A runtime conditional branch that needs a post-hoc block to be
13301367 // emitted communicates this by mapping the block index into the inst map.
......@@ -4968,7 +5005,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
49685005
49695006 // Reserve space for a Block instruction so that generated Break instructions can
49705007 // point to it, even if it doesn't end up getting used because the code ends up being
4971 // comptime evaluated.
5008 // comptime evaluated or is an unlabeled block.
49725009 const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
49735010 try sema.air_instructions.append(gpa, .{
49745011 .tag = .block,
......@@ -4999,6 +5036,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
49995036 .runtime_cond = parent_block.runtime_cond,
50005037 .runtime_loop = parent_block.runtime_loop,
50015038 .runtime_index = parent_block.runtime_index,
5039 .error_return_trace_index = parent_block.error_return_trace_index,
50025040 };
50035041
50045042 defer child_block.instructions.deinit(gpa);
......@@ -5641,6 +5679,117 @@ fn funcDeclSrc(sema: *Sema, block: *Block, src: LazySrcLoc, func_inst: Air.Inst.
56415679 return owner_decl.srcLoc();
56425680}
56435681
5682pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {
5683 const src = sema.src;
5684
5685 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
5686 if (!backend_supports_error_return_tracing or !sema.mod.comp.bin_file.options.error_return_tracing)
5687 return .none;
5688
5689 if (block.is_comptime)
5690 return .none;
5691
5692 const unresolved_stack_trace_ty = sema.getBuiltinType(block, src, "StackTrace") catch |err| switch (err) {
5693 error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
5694 else => |e| return e,
5695 };
5696 const stack_trace_ty = sema.resolveTypeFields(block, src, unresolved_stack_trace_ty) catch |err| switch (err) {
5697 error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
5698 else => |e| return e,
5699 };
5700 const field_index = sema.structFieldIndex(block, stack_trace_ty, "index", src) catch |err| switch (err) {
5701 error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
5702 else => |e| return e,
5703 };
5704
5705 return try block.addInst(.{
5706 .tag = .save_err_return_trace_index,
5707 .data = .{ .ty_pl = .{
5708 .ty = try sema.addType(stack_trace_ty),
5709 .payload = @intCast(u32, field_index),
5710 } },
5711 });
5712}
5713
5714/// Add instructions to block to "pop" the error return trace.
5715/// If `operand` is provided, only pops if operand is non-error.
5716fn popErrorReturnTrace(
5717 sema: *Sema,
5718 block: *Block,
5719 src: LazySrcLoc,
5720 operand: Air.Inst.Ref,
5721 saved_error_trace_index: Air.Inst.Ref,
5722) CompileError!void {
5723 var is_non_error: ?bool = null;
5724 var is_non_error_inst: Air.Inst.Ref = undefined;
5725 if (operand != .none) {
5726 is_non_error_inst = try sema.analyzeIsNonErr(block, src, operand);
5727 if (try sema.resolveDefinedValue(block, src, is_non_error_inst)) |cond_val|
5728 is_non_error = cond_val.toBool();
5729 } else is_non_error = true; // no operand means pop unconditionally
5730
5731 if (is_non_error == true) {
5732 // AstGen determined this result does not go to an error-handling expr (try/catch/return etc.), or
5733 // the result is comptime-known to be a non-error. Either way, pop unconditionally.
5734
5735 const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
5736 const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
5737 const ptr_stack_trace_ty = try Type.Tag.single_mut_pointer.create(sema.arena, stack_trace_ty);
5738 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
5739 const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, "index", src, stack_trace_ty, true);
5740 try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store);
5741 } else if (is_non_error == null) {
5742 // The result might be an error. If it is, we leave the error trace alone. If it isn't, we need
5743 // to pop any error trace that may have been propagated from our arguments.
5744
5745 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Block).Struct.fields.len);
5746 const cond_block_inst = try block.addInstAsIndex(.{
5747 .tag = .block,
5748 .data = .{
5749 .ty_pl = .{
5750 .ty = Air.Inst.Ref.void_type,
5751 .payload = undefined, // updated below
5752 },
5753 },
5754 });
5755
5756 var then_block = block.makeSubBlock();
5757 defer then_block.instructions.deinit(sema.gpa);
5758
5759 // If non-error, then pop the error return trace by restoring the index.
5760 const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
5761 const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
5762 const ptr_stack_trace_ty = try Type.Tag.single_mut_pointer.create(sema.arena, stack_trace_ty);
5763 const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);
5764 const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, "index", src, stack_trace_ty, true);
5765 try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store);
5766 _ = try then_block.addBr(cond_block_inst, Air.Inst.Ref.void_value);
5767
5768 // Otherwise, do nothing
5769 var else_block = block.makeSubBlock();
5770 defer else_block.instructions.deinit(sema.gpa);
5771 _ = try else_block.addBr(cond_block_inst, Air.Inst.Ref.void_value);
5772
5773 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.CondBr).Struct.fields.len +
5774 then_block.instructions.items.len + else_block.instructions.items.len +
5775 @typeInfo(Air.Block).Struct.fields.len + 1); // +1 for the sole .cond_br instruction in the .block
5776
5777 const cond_br_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
5778 try sema.air_instructions.append(sema.gpa, .{ .tag = .cond_br, .data = .{ .pl_op = .{
5779 .operand = is_non_error_inst,
5780 .payload = sema.addExtraAssumeCapacity(Air.CondBr{
5781 .then_body_len = @intCast(u32, then_block.instructions.items.len),
5782 .else_body_len = @intCast(u32, else_block.instructions.items.len),
5783 }),
5784 } } });
5785 sema.air_extra.appendSliceAssumeCapacity(then_block.instructions.items);
5786 sema.air_extra.appendSliceAssumeCapacity(else_block.instructions.items);
5787
5788 sema.air_instructions.items(.data)[cond_block_inst].ty_pl.payload = sema.addExtraAssumeCapacity(Air.Block{ .body_len = 1 });
5789 sema.air_extra.appendAssumeCapacity(cond_br_inst);
5790 }
5791}
5792
56445793fn zirCall(
56455794 sema: *Sema,
56465795 block: *Block,
......@@ -5657,6 +5806,7 @@ fn zirCall(
56575806
56585807 const modifier = @intToEnum(std.builtin.CallOptions.Modifier, extra.data.flags.packed_modifier);
56595808 const ensure_result_used = extra.data.flags.ensure_result_used;
5809 const pop_error_return_trace = extra.data.flags.pop_error_return_trace;
56605810
56615811 var func = try sema.resolveInst(extra.data.callee);
56625812 var resolved_args: []Air.Inst.Ref = undefined;
......@@ -5729,6 +5879,9 @@ fn zirCall(
57295879
57305880 const args_body = sema.code.extra[extra.end..];
57315881
5882 var input_is_error = false;
5883 const block_index = @intCast(Air.Inst.Index, block.instructions.items.len);
5884
57325885 const parent_comptime = block.is_comptime;
57335886 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
57345887 var extra_index: usize = 0;
......@@ -5746,10 +5899,8 @@ fn zirCall(
57465899 else
57475900 func_ty_info.param_types[arg_index];
57485901
5749 const old_comptime = block.is_comptime;
5750 defer block.is_comptime = old_comptime;
57515902 // Generate args to comptime params in comptime block.
5752 block.is_comptime = parent_comptime;
5903 defer block.is_comptime = parent_comptime;
57535904 if (arg_index < fn_params_len and func_ty_info.comptime_params[arg_index]) {
57545905 block.is_comptime = true;
57555906 }
......@@ -5758,13 +5909,58 @@ fn zirCall(
57585909 try sema.inst_map.put(sema.gpa, inst, param_ty_inst);
57595910
57605911 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
5761 if (sema.typeOf(resolved).zigTypeTag() == .NoReturn) {
5912 const resolved_ty = sema.typeOf(resolved);
5913 if (resolved_ty.zigTypeTag() == .NoReturn) {
57625914 return resolved;
57635915 }
5916 if (resolved_ty.isError()) {
5917 input_is_error = true;
5918 }
57645919 resolved_args[arg_index] = resolved;
57655920 }
5921 if (sema.owner_func == null or !sema.owner_func.?.calls_or_awaits_errorable_fn)
5922 input_is_error = false; // input was an error type, but no errorable fn's were actually called
57665923
5767 return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src);
5924 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
5925 if (backend_supports_error_return_tracing and sema.mod.comp.bin_file.options.error_return_tracing and
5926 !block.is_comptime and (input_is_error or pop_error_return_trace))
5927 {
5928 const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: {
5929 break :b try sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src);
5930 };
5931
5932 const return_ty = sema.typeOf(call_inst);
5933 if (modifier != .always_tail and return_ty.isNoReturn())
5934 return call_inst; // call to "fn(...) noreturn", don't pop
5935
5936 // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only
5937 // need to clean-up our own trace if we were passed to a non-error-handling expression.
5938 if (input_is_error or (pop_error_return_trace and modifier != .always_tail and return_ty.isError())) {
5939 const unresolved_stack_trace_ty = try sema.getBuiltinType(block, call_src, "StackTrace");
5940 const stack_trace_ty = try sema.resolveTypeFields(block, call_src, unresolved_stack_trace_ty);
5941 const field_index = try sema.structFieldIndex(block, stack_trace_ty, "index", call_src);
5942
5943 // Insert a save instruction before the arg resolution + call instructions we just generated
5944 const save_inst = try block.insertInst(block_index, .{
5945 .tag = .save_err_return_trace_index,
5946 .data = .{ .ty_pl = .{
5947 .ty = try sema.addType(stack_trace_ty),
5948 .payload = @intCast(u32, field_index),
5949 } },
5950 });
5951
5952 // Pop the error return trace, testing the result for non-error if necessary
5953 const operand = if (pop_error_return_trace or modifier == .always_tail) .none else call_inst;
5954 try sema.popErrorReturnTrace(block, call_src, operand, save_inst);
5955 }
5956
5957 if (modifier == .always_tail) // Perform the call *after* the restore, so that a tail call is possible.
5958 return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src);
5959
5960 return call_inst;
5961 } else {
5962 return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src);
5963 }
57685964}
57695965
57705966const GenericCallAdapter = struct {
......@@ -6056,6 +6252,10 @@ fn analyzeCall(
60566252 sema.func = module_fn;
60576253 defer sema.func = parent_func;
60586254
6255 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;
6256 sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index;
6257 defer sema.error_return_trace_index_on_fn_entry = parent_err_ret_index;
6258
60596259 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, fn_owner_decl.src_scope);
60606260 defer wip_captures.deinit();
60616261
......@@ -6069,6 +6269,7 @@ fn analyzeCall(
60696269 .label = null,
60706270 .inlining = &inlining,
60716271 .is_comptime = is_comptime_call,
6272 .error_return_trace_index = block.error_return_trace_index,
60726273 };
60736274
60746275 const merges = &child_block.inlining.?.merges;
......@@ -6814,6 +7015,13 @@ fn instantiateGenericCall(
68147015 }
68157016 arg_i += 1;
68167017 }
7018
7019 // Save the error trace as our first action in the function.
7020 // If this is unnecessary after all, Liveness will clean it up for us.
7021 const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block);
7022 child_sema.error_return_trace_index_on_fn_entry = error_return_trace_index;
7023 child_block.error_return_trace_index = error_return_trace_index;
7024
68177025 const new_func_inst = child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst) catch |err| {
68187026 // TODO look up the compile error that happened here and attach a note to it
68197027 // pointing here, at the generic instantiation callsite.
......@@ -9703,6 +9911,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
97039911 .defer_err_code,
97049912 .err_union_code,
97059913 .ret_err_value_code,
9914 .restore_err_ret_index,
97069915 .is_non_err,
97079916 .condbr,
97089917 => {},
......@@ -10005,6 +10214,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1000510214 .runtime_cond = block.runtime_cond,
1000610215 .runtime_loop = block.runtime_loop,
1000710216 .runtime_index = block.runtime_index,
10217 .error_return_trace_index = block.error_return_trace_index,
1000810218 };
1000910219 const merges = &child_block.label.?.merges;
1001010220 defer child_block.instructions.deinit(gpa);
......@@ -10888,6 +11098,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
1088811098 const tags = sema.code.instructions.items(.tag);
1088911099 for (body) |inst| {
1089011100 switch (tags[inst]) {
11101 .save_err_ret_index,
1089111102 .dbg_block_begin,
1089211103 .dbg_block_end,
1089311104 .dbg_stmt,
......@@ -10910,6 +11121,10 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
1091011121 try sema.zirDbgStmt(block, inst);
1091111122 continue;
1091211123 },
11124 .save_err_ret_index => {
11125 try sema.zirSaveErrRetIndex(block, inst);
11126 continue;
11127 },
1091311128 .str => try sema.zirStr(block, inst),
1091411129 .as_node => try sema.zirAsNode(block, inst),
1091511130 .field_val => try sema.zirFieldVal(block, inst),
......@@ -10955,6 +11170,7 @@ fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Ind
1095511170 return;
1095611171 }
1095711172 if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| {
11173 if (!operand_ty.isError()) return;
1095811174 if (val.getError() == null) return;
1095911175 try sema.maybeErrorUnwrapComptime(block, body, err_operand);
1096011176 }
......@@ -15519,6 +15735,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
1551915735 .is_comptime = false,
1552015736 .is_typeof = true,
1552115737 .want_safety = false,
15738 .error_return_trace_index = block.error_return_trace_index,
1552215739 };
1552315740 defer child_block.instructions.deinit(sema.gpa);
1552415741
......@@ -16176,6 +16393,75 @@ fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {
1617616393 backend_supports_error_return_tracing;
1617716394}
1617816395
16396fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
16397 const inst_data = sema.code.instructions.items(.data)[inst].save_err_ret_index;
16398
16399 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
16400 const ok = backend_supports_error_return_tracing and sema.mod.comp.bin_file.options.error_return_tracing;
16401 if (!ok) return;
16402
16403 // This is only relevant at runtime.
16404 if (block.is_comptime) return;
16405
16406 // This is only relevant within functions.
16407 if (sema.func == null) return;
16408
16409 const save_index = inst_data.operand == .none or b: {
16410 const operand = try sema.resolveInst(inst_data.operand);
16411 const operand_ty = sema.typeOf(operand);
16412 break :b operand_ty.isError();
16413 };
16414
16415 if (save_index)
16416 block.error_return_trace_index = try sema.analyzeSaveErrRetIndex(block);
16417}
16418
16419fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!void {
16420 const inst_data = sema.code.instructions.items(.data)[inst].restore_err_ret_index;
16421 const src = sema.src; // TODO
16422
16423 // This is only relevant at runtime.
16424 if (start_block.is_comptime) return;
16425
16426 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
16427 const ok = sema.owner_func.?.calls_or_awaits_errorable_fn and
16428 sema.mod.comp.bin_file.options.error_return_tracing and
16429 backend_supports_error_return_tracing;
16430 if (!ok) return;
16431
16432 const tracy = trace(@src());
16433 defer tracy.end();
16434
16435 const saved_index = if (Zir.refToIndex(inst_data.block)) |zir_block| b: {
16436 var block = start_block;
16437 while (true) {
16438 if (block.label) |label| {
16439 if (label.zir_block == zir_block) {
16440 const target_trace_index = if (block.parent) |parent_block| tgt: {
16441 break :tgt parent_block.error_return_trace_index;
16442 } else sema.error_return_trace_index_on_fn_entry;
16443
16444 if (start_block.error_return_trace_index != target_trace_index)
16445 break :b target_trace_index;
16446
16447 return; // No need to restore
16448 }
16449 }
16450 block = block.parent.?;
16451 }
16452 } else b: {
16453 if (start_block.error_return_trace_index != sema.error_return_trace_index_on_fn_entry)
16454 break :b sema.error_return_trace_index_on_fn_entry;
16455
16456 return; // No need to restore
16457 };
16458
16459 assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere
16460
16461 const operand = try sema.resolveInst(inst_data.operand);
16462 return sema.popErrorReturnTrace(start_block, src, operand, saved_index);
16463}
16464
1617916465fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {
1618016466 assert(sema.fn_ret_ty.zigTypeTag() == .ErrorUnion);
1618116467
......@@ -17181,8 +17467,6 @@ fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1718117467
1718217468fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1718317469 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
17184 const src = inst_data.src();
17185 _ = src;
1718617470 const operand = try sema.resolveInst(inst_data.operand);
1718717471 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1718817472
src/Zir.zig+27-1
......@@ -988,6 +988,15 @@ pub const Inst = struct {
988988 /// Uses the `err_defer_code` union field.
989989 defer_err_code,
990990
991 /// Requests that Sema update the saved error return trace index for the enclosing
992 /// block, if the operand is .none or of an error/error-union type.
993 /// Uses the `save_err_ret_index` field.
994 save_err_ret_index,
995 /// Sets error return trace to zero if no operand is given,
996 /// otherwise sets the value to the given amount.
997 /// Uses the `restore_err_ret_index` union field.
998 restore_err_ret_index,
999
9911000 /// The ZIR instruction tag is one of the `Extended` ones.
9921001 /// Uses the `extended` union field.
9931002 extended,
......@@ -1236,6 +1245,8 @@ pub const Inst = struct {
12361245 //.try_ptr_inline,
12371246 .@"defer",
12381247 .defer_err_code,
1248 .save_err_ret_index,
1249 .restore_err_ret_index,
12391250 => false,
12401251
12411252 .@"break",
......@@ -1305,6 +1316,8 @@ pub const Inst = struct {
13051316 .check_comptime_control_flow,
13061317 .@"defer",
13071318 .defer_err_code,
1319 .restore_err_ret_index,
1320 .save_err_ret_index,
13081321 => true,
13091322
13101323 .param,
......@@ -1810,6 +1823,9 @@ pub const Inst = struct {
18101823 .@"defer" = .@"defer",
18111824 .defer_err_code = .defer_err_code,
18121825
1826 .save_err_ret_index = .save_err_ret_index,
1827 .restore_err_ret_index = .restore_err_ret_index,
1828
18131829 .extended = .extended,
18141830 });
18151831 };
......@@ -2586,6 +2602,13 @@ pub const Inst = struct {
25862602 err_code: Ref,
25872603 payload_index: u32,
25882604 },
2605 save_err_ret_index: struct {
2606 operand: Ref, // If error type (or .none), save new trace index
2607 },
2608 restore_err_ret_index: struct {
2609 block: Ref, // If restored, the index is from this block's entrypoint
2610 operand: Ref, // If non-error (or .none), then restore the index
2611 },
25892612
25902613 // Make sure we don't accidentally add a field to make this union
25912614 // bigger than expected. Note that in Debug builds, Zig is allowed
......@@ -2624,6 +2647,8 @@ pub const Inst = struct {
26242647 str_op,
26252648 @"defer",
26262649 defer_err_code,
2650 save_err_ret_index,
2651 restore_err_ret_index,
26272652 };
26282653 };
26292654
......@@ -2809,10 +2834,11 @@ pub const Inst = struct {
28092834 pub const Flags = packed struct {
28102835 /// std.builtin.CallOptions.Modifier in packed form
28112836 pub const PackedModifier = u3;
2812 pub const PackedArgsLen = u28;
2837 pub const PackedArgsLen = u27;
28132838
28142839 packed_modifier: PackedModifier,
28152840 ensure_result_used: bool = false,
2841 pop_error_return_trace: bool,
28162842 args_len: PackedArgsLen,
28172843
28182844 comptime {
src/arch/aarch64/CodeGen.zig+6
......@@ -702,6 +702,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
702702 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
703703 .err_return_trace => try self.airErrReturnTrace(inst),
704704 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
705 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),
705706
706707 .wrap_optional => try self.airWrapOptional(inst),
707708 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
......@@ -2867,6 +2868,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
28672868 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});
28682869}
28692870
2871fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
2872 _ = inst;
2873 return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch});
2874}
2875
28702876fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
28712877 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
28722878 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
src/arch/arm/CodeGen.zig+6
......@@ -751,6 +751,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
751751 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
752752 .err_return_trace => try self.airErrReturnTrace(inst),
753753 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
754 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),
754755
755756 .wrap_optional => try self.airWrapOptional(inst),
756757 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
......@@ -2116,6 +2117,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
21162117 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});
21172118}
21182119
2120fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
2121 _ = inst;
2122 return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch});
2123}
2124
21192125/// T to E!T
21202126fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
21212127 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
src/arch/riscv64/CodeGen.zig+6
......@@ -665,6 +665,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
665665 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
666666 .err_return_trace => try self.airErrReturnTrace(inst),
667667 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
668 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),
668669
669670 .wrap_optional => try self.airWrapOptional(inst),
670671 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
......@@ -1329,6 +1330,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
13291330 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});
13301331}
13311332
1333fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
1334 _ = inst;
1335 return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch});
1336}
1337
13321338fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
13331339 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
13341340 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
src/arch/sparc64/CodeGen.zig+1
......@@ -679,6 +679,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
679679 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
680680 .err_return_trace => @panic("TODO try self.airErrReturnTrace(inst)"),
681681 .set_err_return_trace => @panic("TODO try self.airSetErrReturnTrace(inst)"),
682 .save_err_return_trace_index=> @panic("TODO try self.airSaveErrReturnTraceIndex(inst)"),
682683
683684 .wrap_optional => try self.airWrapOptional(inst),
684685 .wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"),
src/arch/wasm/CodeGen.zig+1
......@@ -1857,6 +1857,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
18571857 .tag_name,
18581858 .err_return_trace,
18591859 .set_err_return_trace,
1860 .save_err_return_trace_index,
18601861 .is_named_enum_value,
18611862 .error_set_has_value,
18621863 .addrspace_cast,
src/arch/x86_64/CodeGen.zig+6
......@@ -756,6 +756,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
756756 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
757757 .err_return_trace => try self.airErrReturnTrace(inst),
758758 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
759 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),
759760
760761 .wrap_optional => try self.airWrapOptional(inst),
761762 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
......@@ -1973,6 +1974,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
19731974 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});
19741975}
19751976
1977fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
1978 _ = inst;
1979 return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch});
1980}
1981
19761982fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
19771983 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
19781984 if (self.liveness.isUnused(inst)) {
src/codegen/c.zig+6
......@@ -1935,6 +1935,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
19351935 .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),
19361936 .err_return_trace => try airErrReturnTrace(f, inst),
19371937 .set_err_return_trace => try airSetErrReturnTrace(f, inst),
1938 .save_err_return_trace_index => try airSaveErrReturnTraceIndex(f, inst),
19381939
19391940 .wasm_memory_size => try airWasmMemorySize(f, inst),
19401941 .wasm_memory_grow => try airWasmMemoryGrow(f, inst),
......@@ -3625,6 +3626,11 @@ fn airSetErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue {
36253626 return f.fail("TODO: C backend: implement airSetErrReturnTrace", .{});
36263627}
36273628
3629fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {
3630 _ = inst;
3631 return f.fail("TODO: C backend: implement airSaveErrReturnTraceIndex", .{});
3632}
3633
36283634fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
36293635 if (f.liveness.isUnused(inst))
36303636 return CValue.none;
src/codegen/llvm.zig+19
......@@ -4592,6 +4592,7 @@ pub const FuncGen = struct {
45924592 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
45934593 .err_return_trace => try self.airErrReturnTrace(inst),
45944594 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
4595 .save_err_return_trace_index => try self.airSaveErrReturnTraceIndex(inst),
45954596
45964597 .wrap_optional => try self.airWrapOptional(inst),
45974598 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
......@@ -6543,6 +6544,24 @@ pub const FuncGen = struct {
65436544 return null;
65446545 }
65456546
6547 fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6548 if (self.liveness.isUnused(inst)) return null;
6549
6550 const target = self.dg.module.getTarget();
6551
6552 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
6553 //const struct_ty = try self.resolveInst(ty_pl.ty);
6554 const struct_ty = self.air.getRefType(ty_pl.ty);
6555 const field_index = ty_pl.payload;
6556
6557 var ptr_ty_buf: Type.Payload.Pointer = undefined;
6558 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?;
6559 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
6560 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field_index, "");
6561 const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base);
6562 return self.load(field_ptr, field_ptr_ty);
6563 }
6564
65466565 fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
65476566 if (self.liveness.isUnused(inst)) return null;
65486567
src/print_air.zig+1
......@@ -197,6 +197,7 @@ const Writer = struct {
197197 .unreach,
198198 .ret_addr,
199199 .frame_addr,
200 .save_err_return_trace_index,
200201 => try w.writeNoOp(s, inst),
201202
202203 .const_ty,
src/print_zir.zig+20-1
......@@ -254,6 +254,9 @@ const Writer = struct {
254254 .str => try self.writeStr(stream, inst),
255255 .int_type => try self.writeIntType(stream, inst),
256256
257 .save_err_ret_index => try self.writeSaveErrRetIndex(stream, inst),
258 .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, inst),
259
257260 .@"break",
258261 .break_inline,
259262 => try self.writeBreak(stream, inst),
......@@ -440,7 +443,7 @@ const Writer = struct {
440443
441444 .dbg_block_begin,
442445 .dbg_block_end,
443 => try stream.writeAll("))"),
446 => try stream.writeAll(")"),
444447
445448 .closure_get => try self.writeInstNode(stream, inst),
446449
......@@ -2272,6 +2275,22 @@ const Writer = struct {
22722275 try self.writeSrc(stream, int_type.src());
22732276 }
22742277
2278 fn writeSaveErrRetIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
2279 const inst_data = self.code.instructions.items(.data)[inst].save_err_ret_index;
2280
2281 try self.writeInstRef(stream, inst_data.operand);
2282 try stream.writeAll(")");
2283 }
2284
2285 fn writeRestoreErrRetIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
2286 const inst_data = self.code.instructions.items(.data)[inst].restore_err_ret_index;
2287
2288 try self.writeInstRef(stream, inst_data.block);
2289 try stream.writeAll(", ");
2290 try self.writeInstRef(stream, inst_data.operand);
2291 try stream.writeAll(")");
2292 }
2293
22752294 fn writeBreak(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
22762295 const inst_data = self.code.instructions.items(.data)[inst].@"break";
22772296
src/value.zig+4-3
......@@ -2971,9 +2971,10 @@ pub const Value = extern union {
29712971 };
29722972 }
29732973
2974 /// Valid for all types. Asserts the value is not undefined and not unreachable.
2975 /// Prefer `errorUnionIsPayload` to find out whether something is an error or not
2976 /// because it works without having to figure out the string.
2974 /// Valid only for error (union) types. Asserts the value is not undefined and not
2975 /// unreachable. For error unions, prefer `errorUnionIsPayload` to find out whether
2976 /// something is an error or not because it works without having to figure out the
2977 /// string.
29772978 pub fn getError(self: Value) ?[]const u8 {
29782979 return switch (self.tag()) {
29792980 .@"error" => self.castTag(.@"error").?.data.name,
test/behavior/bugs/12891.zig+1
......@@ -7,6 +7,7 @@ test "issue12891" {
77 try std.testing.expect(i < f);
88}
99test "nan" {
10 if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
1011 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1112
1213 const f = comptime std.math.nan(f64);
test/behavior/error.zig+13
......@@ -830,3 +830,16 @@ test "compare error union and error set" {
830830 try expect(a != b);
831831 try expect(b != a);
832832}
833
834fn non_errorable() void {
835 // Make sure catch works even in a function that does not call any errorable functions.
836 //
837 // This test is needed because stage 2's fix for #1923 means that catch blocks interact
838 // with the error return trace index.
839 var x: error{Foo}!void = {};
840 return x catch {};
841}
842
843test "catch within a function that calls no errorable functions" {
844 non_errorable();
845}
test/behavior/eval.zig+30-8
......@@ -1401,7 +1401,21 @@ test "continue in inline for inside a comptime switch" {
14011401 try expect(count == 4);
14021402}
14031403
1404test "length of global array is determinable at comptime" {
1405 const S = struct {
1406 var bytes: [1024]u8 = undefined;
1407
1408 fn foo() !void {
1409 try std.testing.expect(bytes.len == 1024);
1410 }
1411 };
1412 comptime try S.foo();
1413}
1414
14041415test "continue nested inline for loop" {
1416 // TODO: https://github.com/ziglang/zig/issues/13175
1417 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
1418
14051419 var a: u8 = 0;
14061420 loop: inline for ([_]u8{ 1, 2 }) |x| {
14071421 inline for ([_]u8{1}) |y| {
......@@ -1415,13 +1429,21 @@ test "continue nested inline for loop" {
14151429 try expect(a == 2);
14161430}
14171431
1418test "length of global array is determinable at comptime" {
1419 const S = struct {
1420 var bytes: [1024]u8 = undefined;
1432test "continue nested inline for loop in named block expr" {
1433 // TODO: https://github.com/ziglang/zig/issues/13175
1434 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
14211435
1422 fn foo() !void {
1423 try std.testing.expect(bytes.len == 1024);
1424 }
1425 };
1426 comptime try S.foo();
1436 var a: u8 = 0;
1437 loop: inline for ([_]u8{ 1, 2 }) |x| {
1438 a = b: {
1439 inline for ([_]u8{1}) |y| {
1440 if (x == y) {
1441 continue :loop;
1442 }
1443 }
1444 break :b x;
1445 };
1446 try expect(x == 2);
1447 }
1448 try expect(a == 2);
14271449}
test/stack_traces.zig+541
......@@ -97,6 +97,547 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
9797 ,
9898 },
9999 });
100 cases.addCase(.{
101 .name = "non-error return pops error trace",
102 .source =
103 \\fn bar() !void {
104 \\ return error.UhOh;
105 \\}
106 \\
107 \\fn foo() !void {
108 \\ bar() catch {
109 \\ return; // non-error result: success
110 \\ };
111 \\}
112 \\
113 \\pub fn main() !void {
114 \\ try foo();
115 \\ return error.UnrelatedError;
116 \\}
117 ,
118 .Debug = .{
119 .expect =
120 \\error: UnrelatedError
121 \\source.zig:13:5: [address] in main (test)
122 \\ return error.UnrelatedError;
123 \\ ^
124 \\
125 ,
126 },
127 .ReleaseSafe = .{
128 .exclude_os = .{
129 .windows, // TODO
130 .linux, // defeated by aggressive inlining
131 },
132 .expect =
133 \\error: UnrelatedError
134 \\source.zig:13:5: [address] in [function]
135 \\ return error.UnrelatedError;
136 \\ ^
137 \\
138 ,
139 },
140 .ReleaseFast = .{
141 .expect =
142 \\error: UnrelatedError
143 \\
144 ,
145 },
146 .ReleaseSmall = .{
147 .expect =
148 \\error: UnrelatedError
149 \\
150 ,
151 },
152 });
153
154 cases.addCase(.{
155 .name = "try return + handled catch/if-else",
156 .source =
157 \\fn foo() !void {
158 \\ return error.TheSkyIsFalling;
159 \\}
160 \\
161 \\pub fn main() !void {
162 \\ foo() catch {}; // should not affect error trace
163 \\ if (foo()) |_| {} else |_| {
164 \\ // should also not affect error trace
165 \\ }
166 \\ try foo();
167 \\}
168 ,
169 .Debug = .{
170 .expect =
171 \\error: TheSkyIsFalling
172 \\source.zig:2:5: [address] in foo (test)
173 \\ return error.TheSkyIsFalling;
174 \\ ^
175 \\source.zig:10:5: [address] in main (test)
176 \\ try foo();
177 \\ ^
178 \\
179 ,
180 },
181 .ReleaseSafe = .{
182 .exclude_os = .{
183 .windows, // TODO
184 .linux, // defeated by aggressive inlining
185 },
186 .expect =
187 \\error: TheSkyIsFalling
188 \\source.zig:2:5: [address] in [function]
189 \\ return error.TheSkyIsFalling;
190 \\ ^
191 \\source.zig:10:5: [address] in [function]
192 \\ try foo();
193 \\ ^
194 \\
195 ,
196 },
197 .ReleaseFast = .{
198 .expect =
199 \\error: TheSkyIsFalling
200 \\
201 ,
202 },
203 .ReleaseSmall = .{
204 .expect =
205 \\error: TheSkyIsFalling
206 \\
207 ,
208 },
209 });
210
211 cases.addCase(.{
212 .name = "break from inline loop pops error return trace",
213 .source =
214 \\fn foo() !void { return error.FooBar; }
215 \\
216 \\pub fn main() !void {
217 \\ comptime var i: usize = 0;
218 \\ b: inline while (i < 5) : (i += 1) {
219 \\ foo() catch {
220 \\ break :b; // non-error break, success
221 \\ };
222 \\ }
223 \\ // foo() was successfully handled, should not appear in trace
224 \\
225 \\ return error.BadTime;
226 \\}
227 ,
228 .Debug = .{
229 .expect =
230 \\error: BadTime
231 \\source.zig:12:5: [address] in main (test)
232 \\ return error.BadTime;
233 \\ ^
234 \\
235 ,
236 },
237 .ReleaseSafe = .{
238 .exclude_os = .{
239 .windows, // TODO
240 .linux, // defeated by aggressive inlining
241 },
242 .expect =
243 \\error: BadTime
244 \\source.zig:12:5: [address] in [function]
245 \\ return error.BadTime;
246 \\ ^
247 \\
248 ,
249 },
250 .ReleaseFast = .{
251 .expect =
252 \\error: BadTime
253 \\
254 ,
255 },
256 .ReleaseSmall = .{
257 .expect =
258 \\error: BadTime
259 \\
260 ,
261 },
262 });
263
264 cases.addCase(.{
265 .name = "catch and re-throw error",
266 .source =
267 \\fn foo() !void {
268 \\ return error.TheSkyIsFalling;
269 \\}
270 \\
271 \\pub fn main() !void {
272 \\ return foo() catch error.AndMyCarIsOutOfGas;
273 \\}
274 ,
275 .Debug = .{
276 .expect =
277 \\error: AndMyCarIsOutOfGas
278 \\source.zig:2:5: [address] in foo (test)
279 \\ return error.TheSkyIsFalling;
280 \\ ^
281 \\source.zig:6:5: [address] in main (test)
282 \\ return foo() catch error.AndMyCarIsOutOfGas;
283 \\ ^
284 \\
285 ,
286 },
287 .ReleaseSafe = .{
288 .exclude_os = .{
289 .windows, // TODO
290 .linux, // defeated by aggressive inlining
291 },
292 .expect =
293 \\error: AndMyCarIsOutOfGas
294 \\source.zig:2:5: [address] in [function]
295 \\ return error.TheSkyIsFalling;
296 \\ ^
297 \\source.zig:6:5: [address] in [function]
298 \\ return foo() catch error.AndMyCarIsOutOfGas;
299 \\ ^
300 \\
301 ,
302 },
303 .ReleaseFast = .{
304 .expect =
305 \\error: AndMyCarIsOutOfGas
306 \\
307 ,
308 },
309 .ReleaseSmall = .{
310 .expect =
311 \\error: AndMyCarIsOutOfGas
312 \\
313 ,
314 },
315 });
316
317 cases.addCase(.{
318 .name = "errors stored in var do not contribute to error trace",
319 .source =
320 \\fn foo() !void {
321 \\ return error.TheSkyIsFalling;
322 \\}
323 \\
324 \\pub fn main() !void {
325 \\ // Once an error is stored in a variable, it is popped from the trace
326 \\ var x = foo();
327 \\ x = {};
328 \\
329 \\ // As a result, this error trace will still be clean
330 \\ return error.SomethingUnrelatedWentWrong;
331 \\}
332 ,
333 .Debug = .{
334 .expect =
335 \\error: SomethingUnrelatedWentWrong
336 \\source.zig:11:5: [address] in main (test)
337 \\ return error.SomethingUnrelatedWentWrong;
338 \\ ^
339 \\
340 ,
341 },
342 .ReleaseSafe = .{
343 .exclude_os = .{
344 .windows, // TODO
345 .linux, // defeated by aggressive inlining
346 },
347 .expect =
348 \\error: SomethingUnrelatedWentWrong
349 \\source.zig:11:5: [address] in [function]
350 \\ return error.SomethingUnrelatedWentWrong;
351 \\ ^
352 \\
353 ,
354 },
355 .ReleaseFast = .{
356 .expect =
357 \\error: SomethingUnrelatedWentWrong
358 \\
359 ,
360 },
361 .ReleaseSmall = .{
362 .expect =
363 \\error: SomethingUnrelatedWentWrong
364 \\
365 ,
366 },
367 });
368
369 cases.addCase(.{
370 .name = "error stored in const has trace preserved for duration of block",
371 .source =
372 \\fn foo() !void { return error.TheSkyIsFalling; }
373 \\fn bar() !void { return error.InternalError; }
374 \\fn baz() !void { return error.UnexpectedReality; }
375 \\
376 \\pub fn main() !void {
377 \\ const x = foo();
378 \\ const y = b: {
379 \\ if (true)
380 \\ break :b bar();
381 \\
382 \\ break :b {};
383 \\ };
384 \\ x catch {};
385 \\ y catch {};
386 \\ // foo()/bar() error traces not popped until end of block
387 \\
388 \\ {
389 \\ const z = baz();
390 \\ z catch {};
391 \\ // baz() error trace still alive here
392 \\ }
393 \\ // baz() error trace popped, foo(), bar() still alive
394 \\ return error.StillUnresolved;
395 \\}
396 ,
397 .Debug = .{
398 .expect =
399 \\error: StillUnresolved
400 \\source.zig:1:18: [address] in foo (test)
401 \\fn foo() !void { return error.TheSkyIsFalling; }
402 \\ ^
403 \\source.zig:2:18: [address] in bar (test)
404 \\fn bar() !void { return error.InternalError; }
405 \\ ^
406 \\source.zig:23:5: [address] in main (test)
407 \\ return error.StillUnresolved;
408 \\ ^
409 \\
410 ,
411 },
412 .ReleaseSafe = .{
413 .exclude_os = .{
414 .windows, // TODO
415 .linux, // defeated by aggressive inlining
416 },
417 .expect =
418 \\error: StillUnresolved
419 \\source.zig:1:18: [address] in [function]
420 \\fn foo() !void { return error.TheSkyIsFalling; }
421 \\ ^
422 \\source.zig:2:18: [address] in [function]
423 \\fn bar() !void { return error.InternalError; }
424 \\ ^
425 \\source.zig:23:5: [address] in [function]
426 \\ return error.StillUnresolved;
427 \\ ^
428 \\
429 ,
430 },
431 .ReleaseFast = .{
432 .expect =
433 \\error: StillUnresolved
434 \\
435 ,
436 },
437 .ReleaseSmall = .{
438 .expect =
439 \\error: StillUnresolved
440 \\
441 ,
442 },
443 });
444
445 cases.addCase(.{
446 .name = "error passed to function has its trace preserved for duration of the call",
447 .source =
448 \\pub fn expectError(expected_error: anyerror, actual_error: anyerror!void) !void {
449 \\ actual_error catch |err| {
450 \\ if (err == expected_error) return {};
451 \\ };
452 \\ return error.TestExpectedError;
453 \\}
454 \\
455 \\fn alwaysErrors() !void { return error.ThisErrorShouldNotAppearInAnyTrace; }
456 \\fn foo() !void { return error.Foo; }
457 \\
458 \\pub fn main() !void {
459 \\ try expectError(error.ThisErrorShouldNotAppearInAnyTrace, alwaysErrors());
460 \\ try expectError(error.ThisErrorShouldNotAppearInAnyTrace, alwaysErrors());
461 \\ try expectError(error.Foo, foo());
462 \\
463 \\ // Only the error trace for this failing check should appear:
464 \\ try expectError(error.Bar, foo());
465 \\}
466 ,
467 .Debug = .{
468 .expect =
469 \\error: TestExpectedError
470 \\source.zig:9:18: [address] in foo (test)
471 \\fn foo() !void { return error.Foo; }
472 \\ ^
473 \\source.zig:5:5: [address] in expectError (test)
474 \\ return error.TestExpectedError;
475 \\ ^
476 \\source.zig:17:5: [address] in main (test)
477 \\ try expectError(error.Bar, foo());
478 \\ ^
479 \\
480 ,
481 },
482 .ReleaseSafe = .{
483 .exclude_os = .{
484 .windows, // TODO
485 },
486 .expect =
487 \\error: TestExpectedError
488 \\source.zig:9:18: [address] in [function]
489 \\fn foo() !void { return error.Foo; }
490 \\ ^
491 \\source.zig:5:5: [address] in [function]
492 \\ return error.TestExpectedError;
493 \\ ^
494 \\source.zig:17:5: [address] in [function]
495 \\ try expectError(error.Bar, foo());
496 \\ ^
497 \\
498 ,
499 },
500 .ReleaseFast = .{
501 .expect =
502 \\error: TestExpectedError
503 \\
504 ,
505 },
506 .ReleaseSmall = .{
507 .expect =
508 \\error: TestExpectedError
509 \\
510 ,
511 },
512 });
513
514 cases.addCase(.{
515 .name = "try return from within catch",
516 .source =
517 \\fn foo() !void {
518 \\ return error.TheSkyIsFalling;
519 \\}
520 \\
521 \\fn bar() !void {
522 \\ return error.AndMyCarIsOutOfGas;
523 \\}
524 \\
525 \\pub fn main() !void {
526 \\ foo() catch { // error trace should include foo()
527 \\ try bar();
528 \\ };
529 \\}
530 ,
531 .Debug = .{
532 .expect =
533 \\error: AndMyCarIsOutOfGas
534 \\source.zig:2:5: [address] in foo (test)
535 \\ return error.TheSkyIsFalling;
536 \\ ^
537 \\source.zig:6:5: [address] in bar (test)
538 \\ return error.AndMyCarIsOutOfGas;
539 \\ ^
540 \\source.zig:11:9: [address] in main (test)
541 \\ try bar();
542 \\ ^
543 \\
544 ,
545 },
546 .ReleaseSafe = .{
547 .exclude_os = .{
548 .windows, // TODO
549 },
550 .expect =
551 \\error: AndMyCarIsOutOfGas
552 \\source.zig:2:5: [address] in [function]
553 \\ return error.TheSkyIsFalling;
554 \\ ^
555 \\source.zig:6:5: [address] in [function]
556 \\ return error.AndMyCarIsOutOfGas;
557 \\ ^
558 \\source.zig:11:9: [address] in [function]
559 \\ try bar();
560 \\ ^
561 \\
562 ,
563 },
564 .ReleaseFast = .{
565 .expect =
566 \\error: AndMyCarIsOutOfGas
567 \\
568 ,
569 },
570 .ReleaseSmall = .{
571 .expect =
572 \\error: AndMyCarIsOutOfGas
573 \\
574 ,
575 },
576 });
577
578 cases.addCase(.{
579 .name = "try return from within if-else",
580 .source =
581 \\fn foo() !void {
582 \\ return error.TheSkyIsFalling;
583 \\}
584 \\
585 \\fn bar() !void {
586 \\ return error.AndMyCarIsOutOfGas;
587 \\}
588 \\
589 \\pub fn main() !void {
590 \\ if (foo()) |_| {} else |_| { // error trace should include foo()
591 \\ try bar();
592 \\ }
593 \\}
594 ,
595 .Debug = .{
596 .expect =
597 \\error: AndMyCarIsOutOfGas
598 \\source.zig:2:5: [address] in foo (test)
599 \\ return error.TheSkyIsFalling;
600 \\ ^
601 \\source.zig:6:5: [address] in bar (test)
602 \\ return error.AndMyCarIsOutOfGas;
603 \\ ^
604 \\source.zig:11:9: [address] in main (test)
605 \\ try bar();
606 \\ ^
607 \\
608 ,
609 },
610 .ReleaseSafe = .{
611 .exclude_os = .{
612 .windows, // TODO
613 },
614 .expect =
615 \\error: AndMyCarIsOutOfGas
616 \\source.zig:2:5: [address] in [function]
617 \\ return error.TheSkyIsFalling;
618 \\ ^
619 \\source.zig:6:5: [address] in [function]
620 \\ return error.AndMyCarIsOutOfGas;
621 \\ ^
622 \\source.zig:11:9: [address] in [function]
623 \\ try bar();
624 \\ ^
625 \\
626 ,
627 },
628 .ReleaseFast = .{
629 .expect =
630 \\error: AndMyCarIsOutOfGas
631 \\
632 ,
633 },
634 .ReleaseSmall = .{
635 .expect =
636 \\error: AndMyCarIsOutOfGas
637 \\
638 ,
639 },
640 });
100641
101642 cases.addCase(.{
102643 .name = "try try return return",