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 {...@@ -869,8 +869,10 @@ pub noinline fn returnError(st: *StackTrace) void {
869}869}
870870
871pub inline fn addErrRetTraceAddr(st: *StackTrace, addr: usize) void {871pub inline fn addErrRetTraceAddr(st: *StackTrace, addr: usize) void {
872 st.instruction_addresses[st.index & (st.instruction_addresses.len - 1)] = addr;872 if (st.index < st.instruction_addresses.len)
873 st.index +%= 1;873 st.instruction_addresses[st.index] = addr;
874
875 st.index += 1;
874}876}
875877
876const std = @import("std.zig");878const std = @import("std.zig");
lib/std/debug.zig+8
...@@ -411,6 +411,14 @@ pub fn writeStackTrace(...@@ -411,6 +411,14 @@ pub fn writeStackTrace(
411 const return_address = stack_trace.instruction_addresses[frame_index];411 const return_address = stack_trace.instruction_addresses[frame_index];
412 try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);412 try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);
413 }413 }
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 }
414}422}
415423
416pub const StackIterator = struct {424pub const StackIterator = struct {
src/Air.zig+5
...@@ -733,6 +733,10 @@ pub const Inst = struct {...@@ -733,6 +733,10 @@ pub const Inst = struct {
733 /// Uses the `ty_op` field.733 /// Uses the `ty_op` field.
734 addrspace_cast,734 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
736 pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag {740 pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag {
737 switch (op) {741 switch (op) {
738 .lt => return if (optimized) .cmp_lt_optimized else .cmp_lt,742 .lt => return if (optimized) .cmp_lt_optimized else .cmp_lt,
...@@ -1179,6 +1183,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1179,6 +1183,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1179 .slice_len,1183 .slice_len,
1180 .ret_addr,1184 .ret_addr,
1181 .frame_addr,1185 .frame_addr,
1186 .save_err_return_trace_index,
1182 => return Type.usize,1187 => return Type.usize,
11831188
1184 .wasm_memory_grow => return Type.i32,1189 .wasm_memory_grow => return Type.i32,
src/AstGen.zig+1059-815
...@@ -213,123 +213,149 @@ pub fn deinit(astgen: *AstGen, gpa: Allocator) void {...@@ -213,123 +213,149 @@ pub fn deinit(astgen: *AstGen, gpa: Allocator) void {
213 astgen.ref_table.deinit(gpa);213 astgen.ref_table.deinit(gpa);
214}214}
215215
216pub const ResultLoc = union(enum) {216pub const ResultInfo = struct {
217 /// The expression is the right-hand side of assignment to `_`. Only the side-effects of the217 /// The semantics requested for the result location
218 /// expression should be generated. The result instruction from the expression must218 rl: Loc,
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 };
249219
250 pub const Strategy = struct {220 /// The "operator" consuming the result location
251 elide_store_to_block_ptr_instructions: bool,221 ctx: Context = .none,
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 };
264222
265 fn strategy(rl: ResultLoc, block_scope: *GenZir) Strategy {223 /// Turns a `coerced_ty` back into a `ty`. Should be called at branch points
266 switch (rl) {224 /// such as if and switch expressions.
267 // In this branch there will not be any store_to_block_ptr instructions.225 fn br(ri: ResultInfo) ResultInfo {
268 .none, .ty, .ty_shift_operand, .coerced_ty, .ref => return .{226 return switch (ri.rl) {
269 .tag = .break_operand,227 .coerced_ty => |ty| .{
270 .elide_store_to_block_ptr_instructions = false,228 .rl = .{ .ty = ty },
271 },229 .ctx = ri.ctx,
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,
282 },230 },
283 .inferred_ptr, .block_ptr => {231 else => ri,
284 if (block_scope.rvalue_rl_count == block_scope.break_count) {232 };
285 // Neither prong of the if consumed the result location, so we can233 }
286 // use break instructions to create an rvalue.234
287 return .{235 fn zirTag(ri: ResultInfo) Zir.Inst.Tag {
288 .tag = .break_operand,236 switch (ri.rl) {
289 .elide_store_to_block_ptr_instructions = true,237 .ty => return switch (ri.ctx) {
290 };238 .shift_op => .as_shift_operand,
291 } else {239 else => .as_node,
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 }
299 },240 },
241 else => unreachable,
300 }242 }
301 }243 }
302244
303 /// Turns a `coerced_ty` back into a `ty`. Should be called at branch points245 pub const Loc = union(enum) {
304 /// such as if and switch expressions.246 /// The expression is the right-hand side of assignment to `_`. Only the side-effects of the
305 fn br(rl: ResultLoc) ResultLoc {247 /// expression should be generated. The result instruction from the expression must
306 return switch (rl) {248 /// be ignored.
307 .coerced_ty => |ty| .{ .ty = ty },249 discard,
308 else => rl,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,
309 };275 };
310 }
311276
312 fn zirTag(rl: ResultLoc) Zir.Inst.Tag {277 pub const Strategy = struct {
313 return switch (rl) {278 elide_store_to_block_ptr_instructions: bool,
314 .ty => .as_node,279 tag: Tag,
315 .ty_shift_operand => .as_shift_operand,280
316 else => unreachable,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 };
317 };290 };
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 };
319};345};
320346
321pub const align_rl: ResultLoc = .{ .ty = .u29_type };347pub const align_ri: ResultInfo = .{ .rl = .{ .ty = .u29_type } };
322pub const coerced_align_rl: ResultLoc = .{ .coerced_ty = .u29_type };348pub const coerced_align_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .u29_type } };
323pub const bool_rl: ResultLoc = .{ .ty = .bool_type };349pub const bool_ri: ResultInfo = .{ .rl = .{ .ty = .bool_type } };
324pub const type_rl: ResultLoc = .{ .ty = .type_type };350pub const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } };
325pub const coerced_type_rl: ResultLoc = .{ .coerced_ty = .type_type };351pub const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } };
326352
327fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zir.Inst.Ref {353fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
328 const prev_force_comptime = gz.force_comptime;354 const prev_force_comptime = gz.force_comptime;
329 gz.force_comptime = true;355 gz.force_comptime = true;
330 defer gz.force_comptime = prev_force_comptime;356 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);
333}359}
334360
335fn reachableTypeExpr(361fn reachableTypeExpr(
...@@ -342,24 +368,24 @@ fn reachableTypeExpr(...@@ -342,24 +368,24 @@ fn reachableTypeExpr(
342 gz.force_comptime = true;368 gz.force_comptime = true;
343 defer gz.force_comptime = prev_force_comptime;369 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);
346}372}
347373
348/// Same as `expr` but fails with a compile error if the result type is `noreturn`.374/// Same as `expr` but fails with a compile error if the result type is `noreturn`.
349fn reachableExpr(375fn reachableExpr(
350 gz: *GenZir,376 gz: *GenZir,
351 scope: *Scope,377 scope: *Scope,
352 rl: ResultLoc,378 ri: ResultInfo,
353 node: Ast.Node.Index,379 node: Ast.Node.Index,
354 reachable_node: Ast.Node.Index,380 reachable_node: Ast.Node.Index,
355) InnerError!Zir.Inst.Ref {381) InnerError!Zir.Inst.Ref {
356 return reachableExprComptime(gz, scope, rl, node, reachable_node, false);382 return reachableExprComptime(gz, scope, ri, node, reachable_node, false);
357}383}
358384
359fn reachableExprComptime(385fn reachableExprComptime(
360 gz: *GenZir,386 gz: *GenZir,
361 scope: *Scope,387 scope: *Scope,
362 rl: ResultLoc,388 ri: ResultInfo,
363 node: Ast.Node.Index,389 node: Ast.Node.Index,
364 reachable_node: Ast.Node.Index,390 reachable_node: Ast.Node.Index,
365 force_comptime: bool,391 force_comptime: bool,
...@@ -368,7 +394,7 @@ fn reachableExprComptime(...@@ -368,7 +394,7 @@ fn reachableExprComptime(
368 gz.force_comptime = prev_force_comptime or force_comptime;394 gz.force_comptime = prev_force_comptime or force_comptime;
369 defer gz.force_comptime = prev_force_comptime;395 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);
372 if (gz.refIsNoReturn(result_inst)) {398 if (gz.refIsNoReturn(result_inst)) {
373 try gz.astgen.appendErrorNodeNotes(reachable_node, "unreachable code", .{}, &[_]u32{399 try gz.astgen.appendErrorNodeNotes(reachable_node, "unreachable code", .{}, &[_]u32{
374 try gz.astgen.errNoteNode(node, "control flow is diverted here", .{}),400 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...@@ -569,14 +595,14 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
569 .@"orelse",595 .@"orelse",
570 => {},596 => {},
571 }597 }
572 return expr(gz, scope, .ref, node);598 return expr(gz, scope, .{ .rl = .ref }, node);
573}599}
574600
575/// Turn Zig AST into untyped ZIR instructions.601/// Turn Zig AST into untyped ZIR instructions.
576/// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the602/// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the
577/// result instruction can be used to inspect whether it is isNoReturn() but that is it,603/// result instruction can be used to inspect whether it is isNoReturn() but that is it,
578/// it must otherwise not be used.604/// 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 {
580 const astgen = gz.astgen;606 const astgen = gz.astgen;
581 const tree = astgen.tree;607 const tree = astgen.tree;
582 const main_tokens = tree.nodes.items(.main_token);608 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...@@ -617,161 +643,161 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
617643
618 .assign => {644 .assign => {
619 try assign(gz, scope, node);645 try assign(gz, scope, node);
620 return rvalue(gz, rl, .void_value, node);646 return rvalue(gz, ri, .void_value, node);
621 },647 },
622648
623 .assign_shl => {649 .assign_shl => {
624 try assignShift(gz, scope, node, .shl);650 try assignShift(gz, scope, node, .shl);
625 return rvalue(gz, rl, .void_value, node);651 return rvalue(gz, ri, .void_value, node);
626 },652 },
627 .assign_shl_sat => {653 .assign_shl_sat => {
628 try assignShiftSat(gz, scope, node);654 try assignShiftSat(gz, scope, node);
629 return rvalue(gz, rl, .void_value, node);655 return rvalue(gz, ri, .void_value, node);
630 },656 },
631 .assign_shr => {657 .assign_shr => {
632 try assignShift(gz, scope, node, .shr);658 try assignShift(gz, scope, node, .shr);
633 return rvalue(gz, rl, .void_value, node);659 return rvalue(gz, ri, .void_value, node);
634 },660 },
635661
636 .assign_bit_and => {662 .assign_bit_and => {
637 try assignOp(gz, scope, node, .bit_and);663 try assignOp(gz, scope, node, .bit_and);
638 return rvalue(gz, rl, .void_value, node);664 return rvalue(gz, ri, .void_value, node);
639 },665 },
640 .assign_bit_or => {666 .assign_bit_or => {
641 try assignOp(gz, scope, node, .bit_or);667 try assignOp(gz, scope, node, .bit_or);
642 return rvalue(gz, rl, .void_value, node);668 return rvalue(gz, ri, .void_value, node);
643 },669 },
644 .assign_bit_xor => {670 .assign_bit_xor => {
645 try assignOp(gz, scope, node, .xor);671 try assignOp(gz, scope, node, .xor);
646 return rvalue(gz, rl, .void_value, node);672 return rvalue(gz, ri, .void_value, node);
647 },673 },
648 .assign_div => {674 .assign_div => {
649 try assignOp(gz, scope, node, .div);675 try assignOp(gz, scope, node, .div);
650 return rvalue(gz, rl, .void_value, node);676 return rvalue(gz, ri, .void_value, node);
651 },677 },
652 .assign_sub => {678 .assign_sub => {
653 try assignOp(gz, scope, node, .sub);679 try assignOp(gz, scope, node, .sub);
654 return rvalue(gz, rl, .void_value, node);680 return rvalue(gz, ri, .void_value, node);
655 },681 },
656 .assign_sub_wrap => {682 .assign_sub_wrap => {
657 try assignOp(gz, scope, node, .subwrap);683 try assignOp(gz, scope, node, .subwrap);
658 return rvalue(gz, rl, .void_value, node);684 return rvalue(gz, ri, .void_value, node);
659 },685 },
660 .assign_sub_sat => {686 .assign_sub_sat => {
661 try assignOp(gz, scope, node, .sub_sat);687 try assignOp(gz, scope, node, .sub_sat);
662 return rvalue(gz, rl, .void_value, node);688 return rvalue(gz, ri, .void_value, node);
663 },689 },
664 .assign_mod => {690 .assign_mod => {
665 try assignOp(gz, scope, node, .mod_rem);691 try assignOp(gz, scope, node, .mod_rem);
666 return rvalue(gz, rl, .void_value, node);692 return rvalue(gz, ri, .void_value, node);
667 },693 },
668 .assign_add => {694 .assign_add => {
669 try assignOp(gz, scope, node, .add);695 try assignOp(gz, scope, node, .add);
670 return rvalue(gz, rl, .void_value, node);696 return rvalue(gz, ri, .void_value, node);
671 },697 },
672 .assign_add_wrap => {698 .assign_add_wrap => {
673 try assignOp(gz, scope, node, .addwrap);699 try assignOp(gz, scope, node, .addwrap);
674 return rvalue(gz, rl, .void_value, node);700 return rvalue(gz, ri, .void_value, node);
675 },701 },
676 .assign_add_sat => {702 .assign_add_sat => {
677 try assignOp(gz, scope, node, .add_sat);703 try assignOp(gz, scope, node, .add_sat);
678 return rvalue(gz, rl, .void_value, node);704 return rvalue(gz, ri, .void_value, node);
679 },705 },
680 .assign_mul => {706 .assign_mul => {
681 try assignOp(gz, scope, node, .mul);707 try assignOp(gz, scope, node, .mul);
682 return rvalue(gz, rl, .void_value, node);708 return rvalue(gz, ri, .void_value, node);
683 },709 },
684 .assign_mul_wrap => {710 .assign_mul_wrap => {
685 try assignOp(gz, scope, node, .mulwrap);711 try assignOp(gz, scope, node, .mulwrap);
686 return rvalue(gz, rl, .void_value, node);712 return rvalue(gz, ri, .void_value, node);
687 },713 },
688 .assign_mul_sat => {714 .assign_mul_sat => {
689 try assignOp(gz, scope, node, .mul_sat);715 try assignOp(gz, scope, node, .mul_sat);
690 return rvalue(gz, rl, .void_value, node);716 return rvalue(gz, ri, .void_value, node);
691 },717 },
692718
693 // zig fmt: off719 // zig fmt: off
694 .shl => return shiftOp(gz, scope, rl, node, node_datas[node].lhs, node_datas[node].rhs, .shl),720 .shl => return shiftOp(gz, scope, ri, 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),721 .shr => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shr),
696722
697 .add => return simpleBinOp(gz, scope, rl, node, .add),723 .add => return simpleBinOp(gz, scope, ri, node, .add),
698 .add_wrap => return simpleBinOp(gz, scope, rl, node, .addwrap),724 .add_wrap => return simpleBinOp(gz, scope, ri, node, .addwrap),
699 .add_sat => return simpleBinOp(gz, scope, rl, node, .add_sat),725 .add_sat => return simpleBinOp(gz, scope, ri, node, .add_sat),
700 .sub => return simpleBinOp(gz, scope, rl, node, .sub),726 .sub => return simpleBinOp(gz, scope, ri, node, .sub),
701 .sub_wrap => return simpleBinOp(gz, scope, rl, node, .subwrap),727 .sub_wrap => return simpleBinOp(gz, scope, ri, node, .subwrap),
702 .sub_sat => return simpleBinOp(gz, scope, rl, node, .sub_sat),728 .sub_sat => return simpleBinOp(gz, scope, ri, node, .sub_sat),
703 .mul => return simpleBinOp(gz, scope, rl, node, .mul),729 .mul => return simpleBinOp(gz, scope, ri, node, .mul),
704 .mul_wrap => return simpleBinOp(gz, scope, rl, node, .mulwrap),730 .mul_wrap => return simpleBinOp(gz, scope, ri, node, .mulwrap),
705 .mul_sat => return simpleBinOp(gz, scope, rl, node, .mul_sat),731 .mul_sat => return simpleBinOp(gz, scope, ri, node, .mul_sat),
706 .div => return simpleBinOp(gz, scope, rl, node, .div),732 .div => return simpleBinOp(gz, scope, ri, node, .div),
707 .mod => return simpleBinOp(gz, scope, rl, node, .mod_rem),733 .mod => return simpleBinOp(gz, scope, ri, node, .mod_rem),
708 .shl_sat => return simpleBinOp(gz, scope, rl, node, .shl_sat),734 .shl_sat => return simpleBinOp(gz, scope, ri, node, .shl_sat),
709735
710 .bit_and => return simpleBinOp(gz, scope, rl, node, .bit_and),736 .bit_and => return simpleBinOp(gz, scope, ri, node, .bit_and),
711 .bit_or => return simpleBinOp(gz, scope, rl, node, .bit_or),737 .bit_or => return simpleBinOp(gz, scope, ri, node, .bit_or),
712 .bit_xor => return simpleBinOp(gz, scope, rl, node, .xor),738 .bit_xor => return simpleBinOp(gz, scope, ri, node, .xor),
713 .bang_equal => return simpleBinOp(gz, scope, rl, node, .cmp_neq),739 .bang_equal => return simpleBinOp(gz, scope, ri, node, .cmp_neq),
714 .equal_equal => return simpleBinOp(gz, scope, rl, node, .cmp_eq),740 .equal_equal => return simpleBinOp(gz, scope, ri, node, .cmp_eq),
715 .greater_than => return simpleBinOp(gz, scope, rl, node, .cmp_gt),741 .greater_than => return simpleBinOp(gz, scope, ri, node, .cmp_gt),
716 .greater_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_gte),742 .greater_or_equal => return simpleBinOp(gz, scope, ri, node, .cmp_gte),
717 .less_than => return simpleBinOp(gz, scope, rl, node, .cmp_lt),743 .less_than => return simpleBinOp(gz, scope, ri, node, .cmp_lt),
718 .less_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_lte),744 .less_or_equal => return simpleBinOp(gz, scope, ri, node, .cmp_lte),
719 .array_cat => return simpleBinOp(gz, scope, rl, node, .array_cat),745 .array_cat => return simpleBinOp(gz, scope, ri, node, .array_cat),
720746
721 .array_mult => {747 .array_mult => {
722 const result = try gz.addPlNode(.array_mul, node, Zir.Inst.Bin{748 const result = try gz.addPlNode(.array_mul, node, Zir.Inst.Bin{
723 .lhs = try expr(gz, scope, .none, node_datas[node].lhs),749 .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
724 .rhs = try comptimeExpr(gz, scope, .{ .coerced_ty = .usize_type }, node_datas[node].rhs),750 .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs),
725 });751 });
726 return rvalue(gz, rl, result, node);752 return rvalue(gz, ri, result, node);
727 },753 },
728754
729 .error_union => return simpleBinOp(gz, scope, rl, node, .error_union_type),755 .error_union => return simpleBinOp(gz, scope, ri, node, .error_union_type),
730 .merge_error_sets => return simpleBinOp(gz, scope, rl, node, .merge_error_sets),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),758 .bool_and => return boolBinOp(gz, scope, ri, node, .bool_br_and),
733 .bool_or => return boolBinOp(gz, scope, rl, node, .bool_br_or),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),761 .bool_not => return simpleUnOp(gz, scope, ri, node, bool_ri, node_datas[node].lhs, .bool_not),
736 .bit_not => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .bit_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),764 .negation => return negation(gz, scope, ri, node),
739 .negation_wrap => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .negate_wrap),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)),769 .asm_simple => return asmExpr(gz, scope, ri, node, tree.asmSimple(node)),
744 .@"asm" => return asmExpr(gz, scope, rl, node, tree.asmFull(node)),770 .@"asm" => return asmExpr(gz, scope, ri, node, tree.asmFull(node)),
745771
746 .string_literal => return stringLiteral(gz, rl, node),772 .string_literal => return stringLiteral(gz, ri, node),
747 .multiline_string_literal => return multilineStringLiteral(gz, rl, 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),
750 // zig fmt: on776 // zig fmt: on
751777
752 .builtin_call_two, .builtin_call_two_comma => {778 .builtin_call_two, .builtin_call_two_comma => {
753 if (node_datas[node].lhs == 0) {779 if (node_datas[node].lhs == 0) {
754 const params = [_]Ast.Node.Index{};780 const params = [_]Ast.Node.Index{};
755 return builtinCall(gz, scope, rl, node, &params);781 return builtinCall(gz, scope, ri, node, &params);
756 } else if (node_datas[node].rhs == 0) {782 } else if (node_datas[node].rhs == 0) {
757 const params = [_]Ast.Node.Index{node_datas[node].lhs};783 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);
759 } else {785 } else {
760 const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };786 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);
762 }788 }
763 },789 },
764 .builtin_call, .builtin_call_comma => {790 .builtin_call, .builtin_call_comma => {
765 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];791 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);
767 },793 },
768794
769 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => {795 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => {
770 var params: [1]Ast.Node.Index = undefined;796 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));
772 },798 },
773 .call, .call_comma, .async_call, .async_call_comma => {799 .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));
775 },801 },
776802
777 .unreachable_literal => {803 .unreachable_literal => {
...@@ -786,112 +812,112 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr...@@ -786,112 +812,112 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
786 return Zir.Inst.Ref.unreachable_value;812 return Zir.Inst.Ref.unreachable_value;
787 },813 },
788 .@"return" => return ret(gz, scope, node),814 .@"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)),817 .if_simple => return ifExpr(gz, scope, ri.br(), node, tree.ifSimple(node)),
792 .@"if" => return ifExpr(gz, scope, rl.br(), node, tree.ifFull(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),820 .while_simple => return whileExpr(gz, scope, ri.br(), node, tree.whileSimple(node), false),
795 .while_cont => return whileExpr(gz, scope, rl.br(), node, tree.whileCont(node), false),821 .while_cont => return whileExpr(gz, scope, ri.br(), node, tree.whileCont(node), false),
796 .@"while" => return whileExpr(gz, scope, rl.br(), node, tree.whileFull(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),824 .for_simple => return forExpr(gz, scope, ri.br(), node, tree.forSimple(node), false),
799 .@"for" => return forExpr(gz, scope, rl.br(), node, tree.forFull(node), false),825 .@"for" => return forExpr(gz, scope, ri.br(), node, tree.forFull(node), false),
800826
801 .slice_open => {827 .slice_open => {
802 const lhs = try expr(gz, scope, .ref, node_datas[node].lhs);828 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
803 const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, node_datas[node].rhs);829 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
804 const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{830 const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{
805 .lhs = lhs,831 .lhs = lhs,
806 .start = start,832 .start = start,
807 });833 });
808 return rvalue(gz, rl, result, node);834 return rvalue(gz, ri, result, node);
809 },835 },
810 .slice => {836 .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);
812 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);838 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);
813 const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.start);839 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
814 const end = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.end);840 const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end);
815 const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{841 const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{
816 .lhs = lhs,842 .lhs = lhs,
817 .start = start,843 .start = start,
818 .end = end,844 .end = end,
819 });845 });
820 return rvalue(gz, rl, result, node);846 return rvalue(gz, ri, result, node);
821 },847 },
822 .slice_sentinel => {848 .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);
824 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);850 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);
825 const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.start);851 const start = try expr(gz, scope, .{ .rl = .{ .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;852 const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none;
827 const sentinel = try expr(gz, scope, .none, extra.sentinel);853 const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel);
828 const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{854 const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{
829 .lhs = lhs,855 .lhs = lhs,
830 .start = start,856 .start = start,
831 .end = end,857 .end = end,
832 .sentinel = sentinel,858 .sentinel = sentinel,
833 });859 });
834 return rvalue(gz, rl, result, node);860 return rvalue(gz, ri, result, node);
835 },861 },
836862
837 .deref => {863 .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);
839 _ = try gz.addUnNode(.validate_deref, lhs, node);865 _ = try gz.addUnNode(.validate_deref, lhs, node);
840 switch (rl) {866 switch (ri.rl) {
841 .ref => return lhs,867 .ref => return lhs,
842 else => {868 else => {
843 const result = try gz.addUnNode(.load, lhs, node);869 const result = try gz.addUnNode(.load, lhs, node);
844 return rvalue(gz, rl, result, node);870 return rvalue(gz, ri, result, node);
845 },871 },
846 }872 }
847 },873 },
848 .address_of => {874 .address_of => {
849 const result = try expr(gz, scope, .ref, node_datas[node].lhs);875 const result = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
850 return rvalue(gz, rl, result, node);876 return rvalue(gz, ri, result, node);
851 },877 },
852 .optional_type => {878 .optional_type => {
853 const operand = try typeExpr(gz, scope, node_datas[node].lhs);879 const operand = try typeExpr(gz, scope, node_datas[node].lhs);
854 const result = try gz.addUnNode(.optional_type, operand, node);880 const result = try gz.addUnNode(.optional_type, operand, node);
855 return rvalue(gz, rl, result, node);881 return rvalue(gz, ri, result, node);
856 },882 },
857 .unwrap_optional => switch (rl) {883 .unwrap_optional => switch (ri.rl) {
858 .ref => return gz.addUnNode(884 .ref => return gz.addUnNode(
859 .optional_payload_safe_ptr,885 .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),
861 node,887 node,
862 ),888 ),
863 else => return rvalue(gz, rl, try gz.addUnNode(889 else => return rvalue(gz, ri, try gz.addUnNode(
864 .optional_payload_safe,890 .optional_payload_safe,
865 try expr(gz, scope, .none, node_datas[node].lhs),891 try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
866 node,892 node,
867 ), node),893 ), node),
868 },894 },
869 .block_two, .block_two_semicolon => {895 .block_two, .block_two_semicolon => {
870 const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };896 const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
871 if (node_datas[node].lhs == 0) {897 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]);
873 } else if (node_datas[node].rhs == 0) {899 } 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]);
875 } else {901 } else {
876 return blockExpr(gz, scope, rl, node, statements[0..2]);902 return blockExpr(gz, scope, ri, node, statements[0..2]);
877 }903 }
878 },904 },
879 .block, .block_semicolon => {905 .block, .block_semicolon => {
880 const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];906 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);
882 },908 },
883 .enum_literal => return simpleStrTok(gz, rl, main_tokens[node], node, .enum_literal),909 .enum_literal => return simpleStrTok(gz, ri, main_tokens[node], node, .enum_literal),
884 .error_value => return simpleStrTok(gz, rl, node_datas[node].rhs, node, .error_value),910 .error_value => return simpleStrTok(gz, ri, node_datas[node].rhs, node, .error_value),
885 // TODO restore this when implementing https://github.com/ziglang/zig/issues/6025911 // 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),
887 .anyframe_literal => {913 .anyframe_literal => {
888 const result = try gz.addUnNode(.anyframe_type, .void_type, node);914 const result = try gz.addUnNode(.anyframe_type, .void_type, node);
889 return rvalue(gz, rl, result, node);915 return rvalue(gz, ri, result, node);
890 },916 },
891 .anyframe_type => {917 .anyframe_type => {
892 const return_type = try typeExpr(gz, scope, node_datas[node].rhs);918 const return_type = try typeExpr(gz, scope, node_datas[node].rhs);
893 const result = try gz.addUnNode(.anyframe_type, return_type, node);919 const result = try gz.addUnNode(.anyframe_type, return_type, node);
894 return rvalue(gz, rl, result, node);920 return rvalue(gz, ri, result, node);
895 },921 },
896 .@"catch" => {922 .@"catch" => {
897 const catch_token = main_tokens[node];923 const catch_token = main_tokens[node];
...@@ -899,11 +925,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr...@@ -899,11 +925,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
899 catch_token + 2925 catch_token + 2
900 else926 else
901 null;927 null;
902 switch (rl) {928 switch (ri.rl) {
903 .ref => return orelseCatchExpr(929 .ref => return orelseCatchExpr(
904 gz,930 gz,
905 scope,931 scope,
906 rl,932 ri,
907 node,933 node,
908 node_datas[node].lhs,934 node_datas[node].lhs,
909 .is_non_err_ptr,935 .is_non_err_ptr,
...@@ -915,7 +941,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr...@@ -915,7 +941,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
915 else => return orelseCatchExpr(941 else => return orelseCatchExpr(
916 gz,942 gz,
917 scope,943 scope,
918 rl,944 ri,
919 node,945 node,
920 node_datas[node].lhs,946 node_datas[node].lhs,
921 .is_non_err,947 .is_non_err,
...@@ -926,11 +952,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr...@@ -926,11 +952,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
926 ),952 ),
927 }953 }
928 },954 },
929 .@"orelse" => switch (rl) {955 .@"orelse" => switch (ri.rl) {
930 .ref => return orelseCatchExpr(956 .ref => return orelseCatchExpr(
931 gz,957 gz,
932 scope,958 scope,
933 rl,959 ri,
934 node,960 node,
935 node_datas[node].lhs,961 node_datas[node].lhs,
936 .is_non_null_ptr,962 .is_non_null_ptr,
...@@ -942,7 +968,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr...@@ -942,7 +968,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
942 else => return orelseCatchExpr(968 else => return orelseCatchExpr(
943 gz,969 gz,
944 scope,970 scope,
945 rl,971 ri,
946 node,972 node,
947 node_datas[node].lhs,973 node_datas[node].lhs,
948 .is_non_null,974 .is_non_null,
...@@ -953,94 +979,94 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr...@@ -953,94 +979,94 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
953 ),979 ),
954 },980 },
955981
956 .ptr_type_aligned => return ptrType(gz, scope, rl, node, tree.ptrTypeAligned(node)),982 .ptr_type_aligned => return ptrType(gz, scope, ri, node, tree.ptrTypeAligned(node)),
957 .ptr_type_sentinel => return ptrType(gz, scope, rl, node, tree.ptrTypeSentinel(node)),983 .ptr_type_sentinel => return ptrType(gz, scope, ri, node, tree.ptrTypeSentinel(node)),
958 .ptr_type => return ptrType(gz, scope, rl, node, tree.ptrType(node)),984 .ptr_type => return ptrType(gz, scope, ri, node, tree.ptrType(node)),
959 .ptr_type_bit_range => return ptrType(gz, scope, rl, node, tree.ptrTypeBitRange(node)),985 .ptr_type_bit_range => return ptrType(gz, scope, ri, node, tree.ptrTypeBitRange(node)),
960986
961 .container_decl,987 .container_decl,
962 .container_decl_trailing,988 .container_decl_trailing,
963 => return containerDecl(gz, scope, rl, node, tree.containerDecl(node)),989 => return containerDecl(gz, scope, ri, node, tree.containerDecl(node)),
964 .container_decl_two, .container_decl_two_trailing => {990 .container_decl_two, .container_decl_two_trailing => {
965 var buffer: [2]Ast.Node.Index = undefined;991 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));
967 },993 },
968 .container_decl_arg,994 .container_decl_arg,
969 .container_decl_arg_trailing,995 .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
972 .tagged_union,998 .tagged_union,
973 .tagged_union_trailing,999 .tagged_union_trailing,
974 => return containerDecl(gz, scope, rl, node, tree.taggedUnion(node)),1000 => return containerDecl(gz, scope, ri, node, tree.taggedUnion(node)),
975 .tagged_union_two, .tagged_union_two_trailing => {1001 .tagged_union_two, .tagged_union_two_trailing => {
976 var buffer: [2]Ast.Node.Index = undefined;1002 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));
978 },1004 },
979 .tagged_union_enum_tag,1005 .tagged_union_enum_tag,
980 .tagged_union_enum_tag_trailing,1006 .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
983 .@"break" => return breakExpr(gz, scope, node),1009 .@"break" => return breakExpr(gz, scope, node),
984 .@"continue" => return continueExpr(gz, scope, node),1010 .@"continue" => return continueExpr(gz, scope, node),
985 .grouped_expression => return expr(gz, scope, rl, node_datas[node].lhs),1011 .grouped_expression => return expr(gz, scope, ri, node_datas[node].lhs),
986 .array_type => return arrayType(gz, scope, rl, node),1012 .array_type => return arrayType(gz, scope, ri, node),
987 .array_type_sentinel => return arrayTypeSentinel(gz, scope, rl, node),1013 .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node),
988 .char_literal => return charLiteral(gz, rl, node),1014 .char_literal => return charLiteral(gz, ri, node),
989 .error_set_decl => return errorSetDecl(gz, rl, node),1015 .error_set_decl => return errorSetDecl(gz, ri, node),
990 .array_access => return arrayAccess(gz, scope, rl, node),1016 .array_access => return arrayAccess(gz, scope, ri, node),
991 .@"comptime" => return comptimeExprAst(gz, scope, rl, node),1017 .@"comptime" => return comptimeExprAst(gz, scope, ri, node),
992 .@"switch", .switch_comma => return switchExpr(gz, scope, rl.br(), node),1018 .@"switch", .switch_comma => return switchExpr(gz, scope, ri.br(), node),
9931019
994 .@"nosuspend" => return nosuspendExpr(gz, scope, rl, node),1020 .@"nosuspend" => return nosuspendExpr(gz, scope, ri, node),
995 .@"suspend" => return suspendExpr(gz, scope, node),1021 .@"suspend" => return suspendExpr(gz, scope, node),
996 .@"await" => return awaitExpr(gz, scope, rl, node),1022 .@"await" => return awaitExpr(gz, scope, ri, node),
997 .@"resume" => return resumeExpr(gz, scope, rl, 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
1001 .array_init_one, .array_init_one_comma => {1027 .array_init_one, .array_init_one_comma => {
1002 var elements: [1]Ast.Node.Index = undefined;1028 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));
1004 },1030 },
1005 .array_init_dot_two, .array_init_dot_two_comma => {1031 .array_init_dot_two, .array_init_dot_two_comma => {
1006 var elements: [2]Ast.Node.Index = undefined;1032 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));
1008 },1034 },
1009 .array_init_dot,1035 .array_init_dot,
1010 .array_init_dot_comma,1036 .array_init_dot_comma,
1011 => return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDot(node)),1037 => return arrayInitExpr(gz, scope, ri, node, tree.arrayInitDot(node)),
1012 .array_init,1038 .array_init,
1013 .array_init_comma,1039 .array_init_comma,
1014 => return arrayInitExpr(gz, scope, rl, node, tree.arrayInit(node)),1040 => return arrayInitExpr(gz, scope, ri, node, tree.arrayInit(node)),
10151041
1016 .struct_init_one, .struct_init_one_comma => {1042 .struct_init_one, .struct_init_one_comma => {
1017 var fields: [1]Ast.Node.Index = undefined;1043 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));
1019 },1045 },
1020 .struct_init_dot_two, .struct_init_dot_two_comma => {1046 .struct_init_dot_two, .struct_init_dot_two_comma => {
1021 var fields: [2]Ast.Node.Index = undefined;1047 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));
1023 },1049 },
1024 .struct_init_dot,1050 .struct_init_dot,
1025 .struct_init_dot_comma,1051 .struct_init_dot_comma,
1026 => return structInitExpr(gz, scope, rl, node, tree.structInitDot(node)),1052 => return structInitExpr(gz, scope, ri, node, tree.structInitDot(node)),
1027 .struct_init,1053 .struct_init,
1028 .struct_init_comma,1054 .struct_init_comma,
1029 => return structInitExpr(gz, scope, rl, node, tree.structInit(node)),1055 => return structInitExpr(gz, scope, ri, node, tree.structInit(node)),
10301056
1031 .fn_proto_simple => {1057 .fn_proto_simple => {
1032 var params: [1]Ast.Node.Index = undefined;1058 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));
1034 },1060 },
1035 .fn_proto_multi => {1061 .fn_proto_multi => {
1036 return fnProtoExpr(gz, scope, rl, node, tree.fnProtoMulti(node));1062 return fnProtoExpr(gz, scope, ri, node, tree.fnProtoMulti(node));
1037 },1063 },
1038 .fn_proto_one => {1064 .fn_proto_one => {
1039 var params: [1]Ast.Node.Index = undefined;1065 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));
1041 },1067 },
1042 .fn_proto => {1068 .fn_proto => {
1043 return fnProtoExpr(gz, scope, rl, node, tree.fnProto(node));1069 return fnProtoExpr(gz, scope, ri, node, tree.fnProto(node));
1044 },1070 },
1045 }1071 }
1046}1072}
...@@ -1048,7 +1074,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr...@@ -1048,7 +1074,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
1048fn nosuspendExpr(1074fn nosuspendExpr(
1049 gz: *GenZir,1075 gz: *GenZir,
1050 scope: *Scope,1076 scope: *Scope,
1051 rl: ResultLoc,1077 ri: ResultInfo,
1052 node: Ast.Node.Index,1078 node: Ast.Node.Index,
1053) InnerError!Zir.Inst.Ref {1079) InnerError!Zir.Inst.Ref {
1054 const astgen = gz.astgen;1080 const astgen = gz.astgen;
...@@ -1063,7 +1089,7 @@ fn nosuspendExpr(...@@ -1063,7 +1089,7 @@ fn nosuspendExpr(
1063 }1089 }
1064 gz.nosuspend_node = node;1090 gz.nosuspend_node = node;
1065 defer gz.nosuspend_node = 0;1091 defer gz.nosuspend_node = 0;
1066 return expr(gz, scope, rl, body_node);1092 return expr(gz, scope, ri, body_node);
1067}1093}
10681094
1069fn suspendExpr(1095fn suspendExpr(
...@@ -1096,7 +1122,7 @@ fn suspendExpr(...@@ -1096,7 +1122,7 @@ fn suspendExpr(
1096 suspend_scope.suspend_node = node;1122 suspend_scope.suspend_node = node;
1097 defer suspend_scope.unstack();1123 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);
1100 if (!gz.refIsNoReturn(body_result)) {1126 if (!gz.refIsNoReturn(body_result)) {
1101 _ = try suspend_scope.addBreak(.break_inline, suspend_inst, .void_value);1127 _ = try suspend_scope.addBreak(.break_inline, suspend_inst, .void_value);
1102 }1128 }
...@@ -1108,7 +1134,7 @@ fn suspendExpr(...@@ -1108,7 +1134,7 @@ fn suspendExpr(
1108fn awaitExpr(1134fn awaitExpr(
1109 gz: *GenZir,1135 gz: *GenZir,
1110 scope: *Scope,1136 scope: *Scope,
1111 rl: ResultLoc,1137 ri: ResultInfo,
1112 node: Ast.Node.Index,1138 node: Ast.Node.Index,
1113) InnerError!Zir.Inst.Ref {1139) InnerError!Zir.Inst.Ref {
1114 const astgen = gz.astgen;1140 const astgen = gz.astgen;
...@@ -1121,7 +1147,7 @@ fn awaitExpr(...@@ -1121,7 +1147,7 @@ fn awaitExpr(
1121 try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}),1147 try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}),
1122 });1148 });
1123 }1149 }
1124 const operand = try expr(gz, scope, .none, rhs_node);1150 const operand = try expr(gz, scope, .{ .rl = .none }, rhs_node);
1125 const result = if (gz.nosuspend_node != 0)1151 const result = if (gz.nosuspend_node != 0)
1126 try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{1152 try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{
1127 .node = gz.nodeIndexToRelative(node),1153 .node = gz.nodeIndexToRelative(node),
...@@ -1130,28 +1156,28 @@ fn awaitExpr(...@@ -1130,28 +1156,28 @@ fn awaitExpr(
1130 else1156 else
1131 try gz.addUnNode(.@"await", operand, node);1157 try gz.addUnNode(.@"await", operand, node);
11321158
1133 return rvalue(gz, rl, result, node);1159 return rvalue(gz, ri, result, node);
1134}1160}
11351161
1136fn resumeExpr(1162fn resumeExpr(
1137 gz: *GenZir,1163 gz: *GenZir,
1138 scope: *Scope,1164 scope: *Scope,
1139 rl: ResultLoc,1165 ri: ResultInfo,
1140 node: Ast.Node.Index,1166 node: Ast.Node.Index,
1141) InnerError!Zir.Inst.Ref {1167) InnerError!Zir.Inst.Ref {
1142 const astgen = gz.astgen;1168 const astgen = gz.astgen;
1143 const tree = astgen.tree;1169 const tree = astgen.tree;
1144 const node_datas = tree.nodes.items(.data);1170 const node_datas = tree.nodes.items(.data);
1145 const rhs_node = node_datas[node].lhs;1171 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);
1147 const result = try gz.addUnNode(.@"resume", operand, node);1173 const result = try gz.addUnNode(.@"resume", operand, node);
1148 return rvalue(gz, rl, result, node);1174 return rvalue(gz, ri, result, node);
1149}1175}
11501176
1151fn fnProtoExpr(1177fn fnProtoExpr(
1152 gz: *GenZir,1178 gz: *GenZir,
1153 scope: *Scope,1179 scope: *Scope,
1154 rl: ResultLoc,1180 ri: ResultInfo,
1155 node: Ast.Node.Index,1181 node: Ast.Node.Index,
1156 fn_proto: Ast.full.FnProto,1182 fn_proto: Ast.full.FnProto,
1157) InnerError!Zir.Inst.Ref {1183) InnerError!Zir.Inst.Ref {
...@@ -1217,7 +1243,7 @@ fn fnProtoExpr(...@@ -1217,7 +1243,7 @@ fn fnProtoExpr(
1217 assert(param_type_node != 0);1243 assert(param_type_node != 0);
1218 var param_gz = block_scope.makeSubBlock(scope);1244 var param_gz = block_scope.makeSubBlock(scope);
1219 defer param_gz.unstack();1245 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);
1221 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);1247 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
1222 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);1248 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);
1223 const main_tokens = tree.nodes.items(.main_token);1249 const main_tokens = tree.nodes.items(.main_token);
...@@ -1231,7 +1257,7 @@ fn fnProtoExpr(...@@ -1231,7 +1257,7 @@ fn fnProtoExpr(
1231 };1257 };
12321258
1233 const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {1259 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);
1235 };1261 };
12361262
1237 if (fn_proto.ast.addrspace_expr != 0) {1263 if (fn_proto.ast.addrspace_expr != 0) {
...@@ -1246,7 +1272,7 @@ fn fnProtoExpr(...@@ -1246,7 +1272,7 @@ fn fnProtoExpr(
1246 try expr(1272 try expr(
1247 &block_scope,1273 &block_scope,
1248 scope,1274 scope,
1249 .{ .ty = .calling_convention_type },1275 .{ .rl = .{ .ty = .calling_convention_type } },
1250 fn_proto.ast.callconv_expr,1276 fn_proto.ast.callconv_expr,
1251 )1277 )
1252 else1278 else
...@@ -1257,7 +1283,7 @@ fn fnProtoExpr(...@@ -1257,7 +1283,7 @@ fn fnProtoExpr(
1257 if (is_inferred_error) {1283 if (is_inferred_error) {
1258 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});1284 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
1259 }1285 }
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
1262 const result = try block_scope.addFunc(.{1288 const result = try block_scope.addFunc(.{
1263 .src_node = fn_proto.ast.proto_node,1289 .src_node = fn_proto.ast.proto_node,
...@@ -1288,13 +1314,13 @@ fn fnProtoExpr(...@@ -1288,13 +1314,13 @@ fn fnProtoExpr(
1288 try block_scope.setBlockBody(block_inst);1314 try block_scope.setBlockBody(block_inst);
1289 try gz.instructions.append(astgen.gpa, block_inst);1315 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);
1292}1318}
12931319
1294fn arrayInitExpr(1320fn arrayInitExpr(
1295 gz: *GenZir,1321 gz: *GenZir,
1296 scope: *Scope,1322 scope: *Scope,
1297 rl: ResultLoc,1323 ri: ResultInfo,
1298 node: Ast.Node.Index,1324 node: Ast.Node.Index,
1299 array_init: Ast.full.ArrayInit,1325 array_init: Ast.full.ArrayInit,
1300) InnerError!Zir.Inst.Ref {1326) InnerError!Zir.Inst.Ref {
...@@ -1336,7 +1362,7 @@ fn arrayInitExpr(...@@ -1336,7 +1362,7 @@ fn arrayInitExpr(
1336 .elem = elem_type,1362 .elem = elem_type,
1337 };1363 };
1338 } else {1364 } 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);
1340 const array_type_inst = try gz.addPlNode(1366 const array_type_inst = try gz.addPlNode(
1341 .array_type_sentinel,1367 .array_type_sentinel,
1342 array_init.ast.type_expr,1368 array_init.ast.type_expr,
...@@ -1364,11 +1390,11 @@ fn arrayInitExpr(...@@ -1364,11 +1390,11 @@ fn arrayInitExpr(
1364 };1390 };
1365 };1391 };
13661392
1367 switch (rl) {1393 switch (ri.rl) {
1368 .discard => {1394 .discard => {
1369 // TODO elements should still be coerced if type is provided1395 // TODO elements should still be coerced if type is provided
1370 for (array_init.ast.elements) |elem_init| {1396 for (array_init.ast.elements) |elem_init| {
1371 _ = try expr(gz, scope, .discard, elem_init);1397 _ = try expr(gz, scope, .{ .rl = .discard }, elem_init);
1372 }1398 }
1373 return Zir.Inst.Ref.void_value;1399 return Zir.Inst.Ref.void_value;
1374 },1400 },
...@@ -1380,13 +1406,13 @@ fn arrayInitExpr(...@@ -1380,13 +1406,13 @@ fn arrayInitExpr(
1380 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;1406 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
1381 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);1407 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
1382 },1408 },
1383 .ty, .ty_shift_operand, .coerced_ty => {1409 .ty, .coerced_ty => {
1384 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;1410 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
1385 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);1411 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);
1387 },1413 },
1388 .ptr => |ptr_res| {1414 .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);
1390 },1416 },
1391 .inferred_ptr => |ptr_inst| {1417 .inferred_ptr => |ptr_inst| {
1392 if (types.array == .none) {1418 if (types.array == .none) {
...@@ -1394,9 +1420,9 @@ fn arrayInitExpr(...@@ -1394,9 +1420,9 @@ fn arrayInitExpr(
1394 // analyzing array_base_ptr against an alloc_inferred_mut.1420 // analyzing array_base_ptr against an alloc_inferred_mut.
1395 // See corresponding logic in structInitExpr.1421 // See corresponding logic in structInitExpr.
1396 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);1422 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);
1398 } else {1424 } 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);
1400 }1426 }
1401 },1427 },
1402 .block_ptr => |block_gz| {1428 .block_ptr => |block_gz| {
...@@ -1404,9 +1430,9 @@ fn arrayInitExpr(...@@ -1404,9 +1430,9 @@ fn arrayInitExpr(
1404 // See corresponding logic in structInitExpr.1430 // See corresponding logic in structInitExpr.
1405 if (types.array == .none and astgen.isInferred(block_gz.rl_ptr)) {1431 if (types.array == .none and astgen.isInferred(block_gz.rl_ptr)) {
1406 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);1432 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);
1408 }1434 }
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);
1410 },1436 },
1411 }1437 }
1412}1438}
...@@ -1426,7 +1452,7 @@ fn arrayInitExprRlNone(...@@ -1426,7 +1452,7 @@ fn arrayInitExprRlNone(
1426 var extra_index = try reserveExtra(astgen, elements.len);1452 var extra_index = try reserveExtra(astgen, elements.len);
14271453
1428 for (elements) |elem_init| {1454 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);
1430 astgen.extra.items[extra_index] = @enumToInt(elem_ref);1456 astgen.extra.items[extra_index] = @enumToInt(elem_ref);
1431 extra_index += 1;1457 extra_index += 1;
1432 }1458 }
...@@ -1455,9 +1481,9 @@ fn arrayInitExprInner(...@@ -1455,9 +1481,9 @@ fn arrayInitExprInner(
1455 }1481 }
14561482
1457 for (elements) |elem_init, i| {1483 for (elements) |elem_init, i| {
1458 const rl = if (elem_ty != .none)1484 const ri = if (elem_ty != .none)
1459 ResultLoc{ .coerced_ty = elem_ty }1485 ResultInfo{ .rl = .{ .coerced_ty = elem_ty } }
1460 else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) rl: {1486 else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) ri: {
1461 const ty_expr = try gz.add(.{1487 const ty_expr = try gz.add(.{
1462 .tag = .elem_type_index,1488 .tag = .elem_type_index,
1463 .data = .{ .bin = .{1489 .data = .{ .bin = .{
...@@ -1465,10 +1491,10 @@ fn arrayInitExprInner(...@@ -1465,10 +1491,10 @@ fn arrayInitExprInner(
1465 .rhs = @intToEnum(Zir.Inst.Ref, i),1491 .rhs = @intToEnum(Zir.Inst.Ref, i),
1466 } },1492 } },
1467 });1493 });
1468 break :rl ResultLoc{ .coerced_ty = ty_expr };1494 break :ri ResultInfo{ .rl = .{ .coerced_ty = ty_expr } };
1469 } else ResultLoc{ .none = {} };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);
1472 astgen.extra.items[extra_index] = @enumToInt(elem_ref);1498 astgen.extra.items[extra_index] = @enumToInt(elem_ref);
1473 extra_index += 1;1499 extra_index += 1;
1474 }1500 }
...@@ -1479,7 +1505,7 @@ fn arrayInitExprInner(...@@ -1479,7 +1505,7 @@ fn arrayInitExprInner(
1479fn arrayInitExprRlPtr(1505fn arrayInitExprRlPtr(
1480 gz: *GenZir,1506 gz: *GenZir,
1481 scope: *Scope,1507 scope: *Scope,
1482 rl: ResultLoc,1508 ri: ResultInfo,
1483 node: Ast.Node.Index,1509 node: Ast.Node.Index,
1484 result_ptr: Zir.Inst.Ref,1510 result_ptr: Zir.Inst.Ref,
1485 elements: []const Ast.Node.Index,1511 elements: []const Ast.Node.Index,
...@@ -1494,7 +1520,7 @@ fn arrayInitExprRlPtr(...@@ -1494,7 +1520,7 @@ fn arrayInitExprRlPtr(
1494 defer as_scope.unstack();1520 defer as_scope.unstack();
14951521
1496 const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements);1522 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);
1498}1524}
14991525
1500fn arrayInitExprRlPtrInner(1526fn arrayInitExprRlPtrInner(
...@@ -1518,7 +1544,7 @@ fn arrayInitExprRlPtrInner(...@@ -1518,7 +1544,7 @@ fn arrayInitExprRlPtrInner(
1518 });1544 });
1519 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;1545 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;
1520 extra_index += 1;1546 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);
1522 }1548 }
15231549
1524 const tag: Zir.Inst.Tag = if (gz.force_comptime)1550 const tag: Zir.Inst.Tag = if (gz.force_comptime)
...@@ -1533,7 +1559,7 @@ fn arrayInitExprRlPtrInner(...@@ -1533,7 +1559,7 @@ fn arrayInitExprRlPtrInner(
1533fn structInitExpr(1559fn structInitExpr(
1534 gz: *GenZir,1560 gz: *GenZir,
1535 scope: *Scope,1561 scope: *Scope,
1536 rl: ResultLoc,1562 ri: ResultInfo,
1537 node: Ast.Node.Index,1563 node: Ast.Node.Index,
1538 struct_init: Ast.full.StructInit,1564 struct_init: Ast.full.StructInit,
1539) InnerError!Zir.Inst.Ref {1565) InnerError!Zir.Inst.Ref {
...@@ -1542,7 +1568,7 @@ fn structInitExpr(...@@ -1542,7 +1568,7 @@ fn structInitExpr(
15421568
1543 if (struct_init.ast.type_expr == 0) {1569 if (struct_init.ast.type_expr == 0) {
1544 if (struct_init.ast.fields.len == 0) {1570 if (struct_init.ast.fields.len == 0) {
1545 return rvalue(gz, rl, .empty_struct, node);1571 return rvalue(gz, ri, .empty_struct, node);
1546 }1572 }
1547 } else array: {1573 } else array: {
1548 const node_tags = tree.nodes.items(.tag);1574 const node_tags = tree.nodes.items(.tag);
...@@ -1554,7 +1580,7 @@ fn structInitExpr(...@@ -1554,7 +1580,7 @@ fn structInitExpr(
1554 if (struct_init.ast.fields.len == 0) {1580 if (struct_init.ast.fields.len == 0) {
1555 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1581 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1556 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);1582 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);
1558 }1584 }
1559 break :array;1585 break :array;
1560 },1586 },
...@@ -1571,7 +1597,7 @@ fn structInitExpr(...@@ -1571,7 +1597,7 @@ fn structInitExpr(
1571 .rhs = elem_type,1597 .rhs = elem_type,
1572 });1598 });
1573 } else blk: {1599 } 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);
1575 break :blk try gz.addPlNode(1601 break :blk try gz.addPlNode(
1576 .array_type_sentinel,1602 .array_type_sentinel,
1577 struct_init.ast.type_expr,1603 struct_init.ast.type_expr,
...@@ -1583,11 +1609,11 @@ fn structInitExpr(...@@ -1583,11 +1609,11 @@ fn structInitExpr(
1583 );1609 );
1584 };1610 };
1585 const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node);1611 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);
1587 }1613 }
1588 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1614 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1589 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);1615 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);
1591 } else {1617 } else {
1592 return astgen.failNode(1618 return astgen.failNode(
1593 struct_init.ast.type_expr,1619 struct_init.ast.type_expr,
...@@ -1597,7 +1623,7 @@ fn structInitExpr(...@@ -1597,7 +1623,7 @@ fn structInitExpr(
1597 }1623 }
1598 }1624 }
15991625
1600 switch (rl) {1626 switch (ri.rl) {
1601 .discard => {1627 .discard => {
1602 if (struct_init.ast.type_expr != 0) {1628 if (struct_init.ast.type_expr != 0) {
1603 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1629 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
...@@ -1626,26 +1652,26 @@ fn structInitExpr(...@@ -1626,26 +1652,26 @@ fn structInitExpr(
1626 return structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);1652 return structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);
1627 }1653 }
1628 },1654 },
1629 .ty, .ty_shift_operand, .coerced_ty => |ty_inst| {1655 .ty, .coerced_ty => |ty_inst| {
1630 if (struct_init.ast.type_expr == 0) {1656 if (struct_init.ast.type_expr == 0) {
1631 const result = try structInitExprRlNone(gz, scope, node, struct_init, ty_inst, .struct_init_anon);1657 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);
1633 }1659 }
1634 const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1660 const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1635 _ = try gz.addUnNode(.validate_struct_init_ty, inner_ty_inst, node);1661 _ = try gz.addUnNode(.validate_struct_init_ty, inner_ty_inst, node);
1636 const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init);1662 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);
1638 },1664 },
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),
1640 .inferred_ptr => |ptr_inst| {1666 .inferred_ptr => |ptr_inst| {
1641 if (struct_init.ast.type_expr == 0) {1667 if (struct_init.ast.type_expr == 0) {
1642 // We treat this case differently so that we don't get a crash when1668 // We treat this case differently so that we don't get a crash when
1643 // analyzing field_base_ptr against an alloc_inferred_mut.1669 // analyzing field_base_ptr against an alloc_inferred_mut.
1644 // See corresponding logic in arrayInitExpr.1670 // See corresponding logic in arrayInitExpr.
1645 const result = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);1671 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);
1647 } else {1673 } else {
1648 return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst);1674 return structInitExprRlPtr(gz, scope, ri, node, struct_init, ptr_inst);
1649 }1675 }
1650 },1676 },
1651 .block_ptr => |block_gz| {1677 .block_ptr => |block_gz| {
...@@ -1653,10 +1679,10 @@ fn structInitExpr(...@@ -1653,10 +1679,10 @@ fn structInitExpr(
1653 // See corresponding logic in arrayInitExpr.1679 // See corresponding logic in arrayInitExpr.
1654 if (struct_init.ast.type_expr == 0 and astgen.isInferred(block_gz.rl_ptr)) {1680 if (struct_init.ast.type_expr == 0 and astgen.isInferred(block_gz.rl_ptr)) {
1655 const result = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);1681 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);
1657 }1683 }
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);
1660 },1686 },
1661 }1687 }
1662}1688}
...@@ -1681,16 +1707,15 @@ fn structInitExprRlNone(...@@ -1681,16 +1707,15 @@ fn structInitExprRlNone(
1681 for (struct_init.ast.fields) |field_init| {1707 for (struct_init.ast.fields) |field_init| {
1682 const name_token = tree.firstToken(field_init) - 2;1708 const name_token = tree.firstToken(field_init) - 2;
1683 const str_index = try astgen.identAsString(name_token);1709 const str_index = try astgen.identAsString(name_token);
1684 const sub_rl: ResultLoc = if (ty_inst != .none)1710 const sub_ri: ResultInfo = if (ty_inst != .none)
1685 ResultLoc{ .ty = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{1711 ResultInfo{ .rl = .{ .ty = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{
1686 .container_type = ty_inst,1712 .container_type = ty_inst,
1687 .name_start = str_index,1713 .name_start = str_index,
1688 }) }1714 }) } }
1689 else1715 else .{ .rl = .none };
1690 .none;
1691 setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{1716 setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{
1692 .field_name = str_index,1717 .field_name = str_index,
1693 .init = try expr(gz, scope, sub_rl, field_init),1718 .init = try expr(gz, scope, sub_ri, field_init),
1694 });1719 });
1695 extra_index += field_size;1720 extra_index += field_size;
1696 }1721 }
...@@ -1701,7 +1726,7 @@ fn structInitExprRlNone(...@@ -1701,7 +1726,7 @@ fn structInitExprRlNone(
1701fn structInitExprRlPtr(1726fn structInitExprRlPtr(
1702 gz: *GenZir,1727 gz: *GenZir,
1703 scope: *Scope,1728 scope: *Scope,
1704 rl: ResultLoc,1729 ri: ResultInfo,
1705 node: Ast.Node.Index,1730 node: Ast.Node.Index,
1706 struct_init: Ast.full.StructInit,1731 struct_init: Ast.full.StructInit,
1707 result_ptr: Zir.Inst.Ref,1732 result_ptr: Zir.Inst.Ref,
...@@ -1717,7 +1742,7 @@ fn structInitExprRlPtr(...@@ -1717,7 +1742,7 @@ fn structInitExprRlPtr(
1717 defer as_scope.unstack();1742 defer as_scope.unstack();
17181743
1719 const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr);1744 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);
1721}1746}
17221747
1723fn structInitExprRlPtrInner(1748fn structInitExprRlPtrInner(
...@@ -1744,7 +1769,7 @@ fn structInitExprRlPtrInner(...@@ -1744,7 +1769,7 @@ fn structInitExprRlPtrInner(
1744 });1769 });
1745 astgen.extra.items[extra_index] = refToIndex(field_ptr).?;1770 astgen.extra.items[extra_index] = refToIndex(field_ptr).?;
1746 extra_index += 1;1771 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);
1748 }1773 }
17491774
1750 const tag: Zir.Inst.Tag = if (gz.force_comptime)1775 const tag: Zir.Inst.Tag = if (gz.force_comptime)
...@@ -1782,7 +1807,7 @@ fn structInitExprRlTy(...@@ -1782,7 +1807,7 @@ fn structInitExprRlTy(
1782 });1807 });
1783 setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{1808 setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{
1784 .field_type = refToIndex(field_ty_inst).?,1809 .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),
1786 });1811 });
1787 extra_index += field_size;1812 extra_index += field_size;
1788 }1813 }
...@@ -1795,14 +1820,14 @@ fn structInitExprRlTy(...@@ -1795,14 +1820,14 @@ fn structInitExprRlTy(
1795fn comptimeExpr(1820fn comptimeExpr(
1796 gz: *GenZir,1821 gz: *GenZir,
1797 scope: *Scope,1822 scope: *Scope,
1798 rl: ResultLoc,1823 ri: ResultInfo,
1799 node: Ast.Node.Index,1824 node: Ast.Node.Index,
1800) InnerError!Zir.Inst.Ref {1825) InnerError!Zir.Inst.Ref {
1801 const prev_force_comptime = gz.force_comptime;1826 const prev_force_comptime = gz.force_comptime;
1802 gz.force_comptime = true;1827 gz.force_comptime = true;
1803 defer gz.force_comptime = prev_force_comptime;1828 defer gz.force_comptime = prev_force_comptime;
18041829
1805 return expr(gz, scope, rl, node);1830 return expr(gz, scope, ri, node);
1806}1831}
18071832
1808/// This one is for an actual `comptime` syntax, and will emit a compile error if1833/// This one is for an actual `comptime` syntax, and will emit a compile error if
...@@ -1811,7 +1836,7 @@ fn comptimeExpr(...@@ -1811,7 +1836,7 @@ fn comptimeExpr(
1811fn comptimeExprAst(1836fn comptimeExprAst(
1812 gz: *GenZir,1837 gz: *GenZir,
1813 scope: *Scope,1838 scope: *Scope,
1814 rl: ResultLoc,1839 ri: ResultInfo,
1815 node: Ast.Node.Index,1840 node: Ast.Node.Index,
1816) InnerError!Zir.Inst.Ref {1841) InnerError!Zir.Inst.Ref {
1817 const astgen = gz.astgen;1842 const astgen = gz.astgen;
...@@ -1822,11 +1847,50 @@ fn comptimeExprAst(...@@ -1822,11 +1847,50 @@ fn comptimeExprAst(
1822 const node_datas = tree.nodes.items(.data);1847 const node_datas = tree.nodes.items(.data);
1823 const body_node = node_datas[node].lhs;1848 const body_node = node_datas[node].lhs;
1824 gz.force_comptime = true;1849 gz.force_comptime = true;
1825 const result = try expr(gz, scope, rl, body_node);1850 const result = try expr(gz, scope, ri, body_node);
1826 gz.force_comptime = false;1851 gz.force_comptime = false;
1827 return result;1852 return result;
1828}1853}
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
1830fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {1894fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
1831 const astgen = parent_gz.astgen;1895 const astgen = parent_gz.astgen;
1832 const tree = astgen.tree;1896 const tree = astgen.tree;
...@@ -1842,6 +1906,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -1842,6 +1906,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
1842 const block_gz = scope.cast(GenZir).?;1906 const block_gz = scope.cast(GenZir).?;
18431907
1844 if (block_gz.cur_defer_node != 0) {1908 if (block_gz.cur_defer_node != 0) {
1909 // We are breaking out of a `defer` block.
1845 return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{1910 return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{
1846 try astgen.errNoteNode(1911 try astgen.errNoteNode(
1847 block_gz.cur_defer_node,1912 block_gz.cur_defer_node,
...@@ -1862,9 +1927,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -1862,9 +1927,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
1862 } else if (block_gz.break_block != 0) {1927 } else if (block_gz.break_block != 0) {
1863 break :blk block_gz.break_block;1928 break :blk block_gz.break_block;
1864 }1929 }
1930 // If not the target, start over with the parent
1865 scope = block_gz.parent;1931 scope = block_gz.parent;
1866 continue;1932 continue;
1867 };1933 };
1934 // If we made it here, this block is the target of the break expr
18681935
1869 const break_tag: Zir.Inst.Tag = if (block_gz.is_inline or block_gz.force_comptime)1936 const break_tag: Zir.Inst.Tag = if (block_gz.is_inline or block_gz.force_comptime)
1870 .break_inline1937 .break_inline
...@@ -1874,17 +1941,25 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -1874,17 +1941,25 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
1874 if (rhs == 0) {1941 if (rhs == 0) {
1875 try genDefers(parent_gz, scope, parent_scope, .normal_only);1942 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
1877 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);1948 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
1878 return Zir.Inst.Ref.unreachable_value;1949 return Zir.Inst.Ref.unreachable_value;
1879 }1950 }
1880 block_gz.break_count += 1;1951 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);
1883 const search_index = @intCast(Zir.Inst.Index, astgen.instructions.len);1954 const search_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
18841955
1885 try genDefers(parent_gz, scope, parent_scope, .normal_only);1956 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) {
1888 .block_ptr => {1963 .block_ptr => {
1889 const br = try parent_gz.addBreak(break_tag, block_inst, operand);1964 const br = try parent_gz.addBreak(break_tag, block_inst, operand);
1890 try block_gz.labeled_breaks.append(astgen.gpa, .{ .br = br, .search = search_index });1965 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)...@@ -1990,7 +2065,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
1990fn blockExpr(2065fn blockExpr(
1991 gz: *GenZir,2066 gz: *GenZir,
1992 scope: *Scope,2067 scope: *Scope,
1993 rl: ResultLoc,2068 ri: ResultInfo,
1994 block_node: Ast.Node.Index,2069 block_node: Ast.Node.Index,
1995 statements: []const Ast.Node.Index,2070 statements: []const Ast.Node.Index,
1996) InnerError!Zir.Inst.Ref {2071) InnerError!Zir.Inst.Ref {
...@@ -2006,12 +2081,38 @@ fn blockExpr(...@@ -2006,12 +2081,38 @@ fn blockExpr(
2006 if (token_tags[lbrace - 1] == .colon and2081 if (token_tags[lbrace - 1] == .colon and
2007 token_tags[lbrace - 2] == .identifier)2082 token_tags[lbrace - 2] == .identifier)
2008 {2083 {
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);
2010 }2113 }
20112114
2012 var sub_gz = gz.makeSubBlock(scope);2115 return rvalue(gz, ri, .void_value, block_node);
2013 try blockExprStmts(&sub_gz, &sub_gz.base, statements);
2014 return rvalue(gz, rl, .void_value, block_node);
2015}2116}
20162117
2017fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.TokenIndex) !void {2118fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.TokenIndex) !void {
...@@ -2049,7 +2150,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke...@@ -2049,7 +2150,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke
2049fn labeledBlockExpr(2150fn labeledBlockExpr(
2050 gz: *GenZir,2151 gz: *GenZir,
2051 parent_scope: *Scope,2152 parent_scope: *Scope,
2052 rl: ResultLoc,2153 ri: ResultInfo,
2053 block_node: Ast.Node.Index,2154 block_node: Ast.Node.Index,
2054 statements: []const Ast.Node.Index,2155 statements: []const Ast.Node.Index,
2055) InnerError!Zir.Inst.Ref {2156) InnerError!Zir.Inst.Ref {
...@@ -2078,12 +2179,15 @@ fn labeledBlockExpr(...@@ -2078,12 +2179,15 @@ fn labeledBlockExpr(
2078 .token = label_token,2179 .token = label_token,
2079 .block_inst = block_inst,2180 .block_inst = block_inst,
2080 };2181 };
2081 block_scope.setBreakResultLoc(rl);2182 block_scope.setBreakResultInfo(ri);
2082 defer block_scope.unstack();2183 defer block_scope.unstack();
2083 defer block_scope.labeled_breaks.deinit(astgen.gpa);2184 defer block_scope.labeled_breaks.deinit(astgen.gpa);
20842185
2085 try blockExprStmts(&block_scope, &block_scope.base, statements);2186 try blockExprStmts(&block_scope, &block_scope.base, statements);
2086 if (!block_scope.endsWithNoReturn()) {2187 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
2087 const break_tag: Zir.Inst.Tag = if (block_scope.force_comptime) .break_inline else .@"break";2191 const break_tag: Zir.Inst.Tag = if (block_scope.force_comptime) .break_inline else .@"break";
2088 _ = try block_scope.addBreak(break_tag, block_inst, .void_value);2192 _ = try block_scope.addBreak(break_tag, block_inst, .void_value);
2089 }2193 }
...@@ -2094,7 +2198,7 @@ fn labeledBlockExpr(...@@ -2094,7 +2198,7 @@ fn labeledBlockExpr(
20942198
2095 const zir_datas = gz.astgen.instructions.items(.data);2199 const zir_datas = gz.astgen.instructions.items(.data);
2096 const zir_tags = gz.astgen.instructions.items(.tag);2200 const zir_tags = gz.astgen.instructions.items(.tag);
2097 const strat = rl.strategy(&block_scope);2201 const strat = ri.rl.strategy(&block_scope);
2098 switch (strat.tag) {2202 switch (strat.tag) {
2099 .break_void => {2203 .break_void => {
2100 // The code took advantage of the result location as a pointer.2204 // The code took advantage of the result location as a pointer.
...@@ -2107,7 +2211,8 @@ fn labeledBlockExpr(...@@ -2107,7 +2211,8 @@ fn labeledBlockExpr(
2107 return indexToRef(block_inst);2211 return indexToRef(block_inst);
2108 },2212 },
2109 .break_operand => {2213 .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).
2111 // The break instructions need to have their operands coerced if the2216 // The break instructions need to have their operands coerced if the
2112 // block's result location is a `ty`. In this case we overwrite the2217 // block's result location is a `ty`. In this case we overwrite the
2113 // `store_to_block_ptr` instruction with an `as` instruction and repurpose2218 // `store_to_block_ptr` instruction with an `as` instruction and repurpose
...@@ -2135,9 +2240,9 @@ fn labeledBlockExpr(...@@ -2135,9 +2240,9 @@ fn labeledBlockExpr(
2135 }2240 }
2136 try block_scope.setBlockBody(block_inst);2241 try block_scope.setBlockBody(block_inst);
2137 const block_ref = indexToRef(block_inst);2242 const block_ref = indexToRef(block_inst);
2138 switch (rl) {2243 switch (ri.rl) {
2139 .ref => return block_ref,2244 .ref => return block_ref,
2140 else => return rvalue(gz, rl, block_ref, block_node),2245 else => return rvalue(gz, ri, block_ref, block_node),
2141 }2246 }
2142 },2247 },
2143 }2248 }
...@@ -2208,12 +2313,12 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2208,12 +2313,12 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2208 continue;2313 continue;
2209 },2314 },
22102315
2211 .while_simple => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileSimple(inner_node), true),2316 .while_simple => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileSimple(inner_node), true),
2212 .while_cont => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileCont(inner_node), true),2317 .while_cont => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileCont(inner_node), true),
2213 .@"while" => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileFull(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),2320 .for_simple => _ = try forExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.forSimple(inner_node), true),
2216 .@"for" => _ = try forExpr(gz, scope, .discard, inner_node, tree.forFull(inner_node), true),2321 .@"for" => _ = try forExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.forFull(inner_node), true),
22172322
2218 else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node),2323 else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node),
2219 // zig fmt: on2324 // zig fmt: on
...@@ -2234,7 +2339,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner...@@ -2234,7 +2339,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
2234 try emitDbgNode(gz, statement);2339 try emitDbgNode(gz, statement);
2235 // We need to emit an error if the result is not `noreturn` or `void`, but2340 // We need to emit an error if the result is not `noreturn` or `void`, but
2236 // we want to avoid adding the ZIR instruction if possible for performance.2341 // 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);
2238 return addEnsureResult(gz, maybe_unused_result, statement);2343 return addEnsureResult(gz, maybe_unused_result, statement);
2239}2344}
22402345
...@@ -2533,6 +2638,8 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2533,6 +2638,8 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2533 .validate_array_init_ty,2638 .validate_array_init_ty,
2534 .validate_struct_init_ty,2639 .validate_struct_init_ty,
2535 .validate_deref,2640 .validate_deref,
2641 .save_err_ret_index,
2642 .restore_err_ret_index,
2536 => break :b true,2643 => break :b true,
25372644
2538 .@"defer" => unreachable,2645 .@"defer" => unreachable,
...@@ -2799,7 +2906,7 @@ fn varDecl(...@@ -2799,7 +2906,7 @@ fn varDecl(
2799 }2906 }
28002907
2801 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0)2908 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)
2803 else2910 else
2804 .none;2911 .none;
28052912
...@@ -2816,16 +2923,22 @@ fn varDecl(...@@ -2816,16 +2923,22 @@ fn varDecl(
2816 if (align_inst == .none and2923 if (align_inst == .none and
2817 !nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node, type_node != 0))2924 !nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node, type_node != 0))
2818 {2925 {
2819 const result_loc: ResultLoc = if (type_node != 0) .{2926 const result_info: ResultInfo = if (type_node != 0) .{
2820 .ty = try typeExpr(gz, scope, type_node),2927 .rl = .{ .ty = try typeExpr(gz, scope, type_node) },
2821 } else .none;2928 .ctx = .const_init,
2929 } else .{ .rl = .none, .ctx = .const_init };
2822 const prev_anon_name_strategy = gz.anon_name_strategy;2930 const prev_anon_name_strategy = gz.anon_name_strategy;
2823 gz.anon_name_strategy = .dbg_var;2931 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);
2825 gz.anon_name_strategy = prev_anon_name_strategy;2933 gz.anon_name_strategy = prev_anon_name_strategy;
28262934
2827 try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);2935 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
2829 const sub_scope = try block_arena.create(Scope.LocalVal);2942 const sub_scope = try block_arena.create(Scope.LocalVal);
2830 sub_scope.* = .{2943 sub_scope.* = .{
2831 .parent = scope,2944 .parent = scope,
...@@ -2891,8 +3004,13 @@ fn varDecl(...@@ -2891,8 +3004,13 @@ fn varDecl(
2891 init_scope.rl_ptr = alloc;3004 init_scope.rl_ptr = alloc;
2892 init_scope.rl_ty_inst = .none;3005 init_scope.rl_ty_inst = .none;
2893 }3006 }
2894 const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope };3007 const init_result_info: ResultInfo = .{ .rl = .{ .block_ptr = &init_scope }, .ctx = .const_init };
2895 const init_inst = try reachableExpr(&init_scope, &init_scope.base, init_result_loc, var_decl.ast.init_node, node);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
2897 const zir_tags = astgen.instructions.items(.tag);3015 const zir_tags = astgen.instructions.items(.tag);
2898 const zir_datas = astgen.instructions.items(.data);3016 const zir_datas = astgen.instructions.items(.data);
...@@ -2981,7 +3099,7 @@ fn varDecl(...@@ -2981,7 +3099,7 @@ fn varDecl(
2981 const is_comptime = var_decl.comptime_token != null or gz.force_comptime;3099 const is_comptime = var_decl.comptime_token != null or gz.force_comptime;
2982 var resolve_inferred_alloc: Zir.Inst.Ref = .none;3100 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
2983 const var_data: struct {3101 const var_data: struct {
2984 result_loc: ResultLoc,3102 result_info: ResultInfo,
2985 alloc: Zir.Inst.Ref,3103 alloc: Zir.Inst.Ref,
2986 } = if (var_decl.ast.type_node != 0) a: {3104 } = if (var_decl.ast.type_node != 0) a: {
2987 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);3105 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
...@@ -3003,7 +3121,7 @@ fn varDecl(...@@ -3003,7 +3121,7 @@ fn varDecl(
3003 }3121 }
3004 };3122 };
3005 gz.rl_ty_inst = type_inst;3123 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 } } } };
3007 } else a: {3125 } else a: {
3008 const alloc = alloc: {3126 const alloc = alloc: {
3009 if (align_inst == .none) {3127 if (align_inst == .none) {
...@@ -3024,11 +3142,11 @@ fn varDecl(...@@ -3024,11 +3142,11 @@ fn varDecl(
3024 };3142 };
3025 gz.rl_ty_inst = .none;3143 gz.rl_ty_inst = .none;
3026 resolve_inferred_alloc = alloc;3144 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 } } };
3028 };3146 };
3029 const prev_anon_name_strategy = gz.anon_name_strategy;3147 const prev_anon_name_strategy = gz.anon_name_strategy;
3030 gz.anon_name_strategy = .dbg_var;3148 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);
3032 gz.anon_name_strategy = prev_anon_name_strategy;3150 gz.anon_name_strategy = prev_anon_name_strategy;
3033 if (resolve_inferred_alloc != .none) {3151 if (resolve_inferred_alloc != .none) {
3034 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);3152 _ = 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...@@ -3098,15 +3216,15 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi
3098 // This intentionally does not support `@"_"` syntax.3216 // This intentionally does not support `@"_"` syntax.
3099 const ident_name = tree.tokenSlice(main_tokens[lhs]);3217 const ident_name = tree.tokenSlice(main_tokens[lhs]);
3100 if (mem.eql(u8, ident_name, "_")) {3218 if (mem.eql(u8, ident_name, "_")) {
3101 _ = try expr(gz, scope, .discard, rhs);3219 _ = try expr(gz, scope, .{ .rl = .discard }, rhs);
3102 return;3220 return;
3103 }3221 }
3104 }3222 }
3105 const lvalue = try lvalExpr(gz, scope, lhs);3223 const lvalue = try lvalExpr(gz, scope, lhs);
3106 _ = try expr(gz, scope, .{ .ptr = .{3224 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{
3107 .inst = lvalue,3225 .inst = lvalue,
3108 .src_node = infix_node,3226 .src_node = infix_node,
3109 } }, rhs);3227 } } }, rhs);
3110}3228}
31113229
3112fn assignOp(3230fn assignOp(
...@@ -3123,7 +3241,7 @@ fn assignOp(...@@ -3123,7 +3241,7 @@ fn assignOp(
3123 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3241 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
3124 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);3242 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
3125 const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node);3243 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
3128 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{3246 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
3129 .lhs = lhs,3247 .lhs = lhs,
...@@ -3146,7 +3264,7 @@ fn assignShift(...@@ -3146,7 +3264,7 @@ fn assignShift(
3146 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3264 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
3147 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);3265 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
3148 const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node);3266 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
3151 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{3269 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
3152 .lhs = lhs,3270 .lhs = lhs,
...@@ -3164,7 +3282,7 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE...@@ -3164,7 +3282,7 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE
3164 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3282 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
3165 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);3283 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
3166 // Saturating shift-left allows any integer type for both the LHS and RHS.3284 // 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
3169 const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{3287 const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{
3170 .lhs = lhs,3288 .lhs = lhs,
...@@ -3176,7 +3294,7 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE...@@ -3176,7 +3294,7 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE
3176fn ptrType(3294fn ptrType(
3177 gz: *GenZir,3295 gz: *GenZir,
3178 scope: *Scope,3296 scope: *Scope,
3179 rl: ResultLoc,3297 ri: ResultInfo,
3180 node: Ast.Node.Index,3298 node: Ast.Node.Index,
3181 ptr_info: Ast.full.PtrType,3299 ptr_info: Ast.full.PtrType,
3182) InnerError!Zir.Inst.Ref {3300) InnerError!Zir.Inst.Ref {
...@@ -3194,21 +3312,21 @@ fn ptrType(...@@ -3194,21 +3312,21 @@ fn ptrType(
3194 var trailing_count: u32 = 0;3312 var trailing_count: u32 = 0;
31953313
3196 if (ptr_info.ast.sentinel != 0) {3314 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);
3198 trailing_count += 1;3316 trailing_count += 1;
3199 }3317 }
3200 if (ptr_info.ast.align_node != 0) {3318 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);
3202 trailing_count += 1;3320 trailing_count += 1;
3203 }3321 }
3204 if (ptr_info.ast.addrspace_node != 0) {3322 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);
3206 trailing_count += 1;3324 trailing_count += 1;
3207 }3325 }
3208 if (ptr_info.ast.bit_range_start != 0) {3326 if (ptr_info.ast.bit_range_start != 0) {
3209 assert(ptr_info.ast.bit_range_end != 0);3327 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);3328 bit_start_ref = try expr(gz, scope, .{ .rl = .{ .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);3329 bit_end_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_end);
3212 trailing_count += 2;3330 trailing_count += 2;
3213 }3331 }
32143332
...@@ -3255,10 +3373,10 @@ fn ptrType(...@@ -3255,10 +3373,10 @@ fn ptrType(
3255 } });3373 } });
3256 gz.instructions.appendAssumeCapacity(new_index);3374 gz.instructions.appendAssumeCapacity(new_index);
32573375
3258 return rvalue(gz, rl, result, node);3376 return rvalue(gz, ri, result, node);
3259}3377}
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 {
3262 const astgen = gz.astgen;3380 const astgen = gz.astgen;
3263 const tree = astgen.tree;3381 const tree = astgen.tree;
3264 const node_datas = tree.nodes.items(.data);3382 const node_datas = tree.nodes.items(.data);
...@@ -3271,17 +3389,17 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Z...@@ -3271,17 +3389,17 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Z
3271 {3389 {
3272 return astgen.failNode(len_node, "unable to infer array size", .{});3390 return astgen.failNode(len_node, "unable to infer array size", .{});
3273 }3391 }
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);
3275 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);3393 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);
32763394
3277 const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{3395 const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{
3278 .lhs = len,3396 .lhs = len,
3279 .rhs = elem_type,3397 .rhs = elem_type,
3280 });3398 });
3281 return rvalue(gz, rl, result, node);3399 return rvalue(gz, ri, result, node);
3282}3400}
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 {
3285 const astgen = gz.astgen;3403 const astgen = gz.astgen;
3286 const tree = astgen.tree;3404 const tree = astgen.tree;
3287 const node_datas = tree.nodes.items(.data);3405 const node_datas = tree.nodes.items(.data);
...@@ -3295,16 +3413,16 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I...@@ -3295,16 +3413,16 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I
3295 {3413 {
3296 return astgen.failNode(len_node, "unable to infer array size", .{});3414 return astgen.failNode(len_node, "unable to infer array size", .{});
3297 }3415 }
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);
3299 const elem_type = try typeExpr(gz, scope, extra.elem_type);3417 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
3302 const result = try gz.addPlNode(.array_type_sentinel, node, Zir.Inst.ArrayTypeSentinel{3420 const result = try gz.addPlNode(.array_type_sentinel, node, Zir.Inst.ArrayTypeSentinel{
3303 .len = len,3421 .len = len,
3304 .elem_type = elem_type,3422 .elem_type = elem_type,
3305 .sentinel = sentinel,3423 .sentinel = sentinel,
3306 });3424 });
3307 return rvalue(gz, rl, result, node);3425 return rvalue(gz, ri, result, node);
3308}3426}
33093427
3310const WipMembers = struct {3428const WipMembers = struct {
...@@ -3540,7 +3658,7 @@ fn fnDecl(...@@ -3540,7 +3658,7 @@ fn fnDecl(
3540 assert(param_type_node != 0);3658 assert(param_type_node != 0);
3541 var param_gz = decl_gz.makeSubBlock(scope);3659 var param_gz = decl_gz.makeSubBlock(scope);
3542 defer param_gz.unstack();3660 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);
3544 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);3662 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
3545 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);3663 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);
35463664
...@@ -3589,7 +3707,7 @@ fn fnDecl(...@@ -3589,7 +3707,7 @@ fn fnDecl(
3589 var align_gz = decl_gz.makeSubBlock(params_scope);3707 var align_gz = decl_gz.makeSubBlock(params_scope);
3590 defer align_gz.unstack();3708 defer align_gz.unstack();
3591 const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {3709 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);
3593 if (align_gz.instructionsSlice().len == 0) {3711 if (align_gz.instructionsSlice().len == 0) {
3594 // In this case we will send a len=0 body which can be encoded more efficiently.3712 // In this case we will send a len=0 body which can be encoded more efficiently.
3595 break :inst inst;3713 break :inst inst;
...@@ -3601,7 +3719,7 @@ fn fnDecl(...@@ -3601,7 +3719,7 @@ fn fnDecl(
3601 var addrspace_gz = decl_gz.makeSubBlock(params_scope);3719 var addrspace_gz = decl_gz.makeSubBlock(params_scope);
3602 defer addrspace_gz.unstack();3720 defer addrspace_gz.unstack();
3603 const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: {3721 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);
3605 if (addrspace_gz.instructionsSlice().len == 0) {3723 if (addrspace_gz.instructionsSlice().len == 0) {
3606 // In this case we will send a len=0 body which can be encoded more efficiently.3724 // In this case we will send a len=0 body which can be encoded more efficiently.
3607 break :inst inst;3725 break :inst inst;
...@@ -3613,7 +3731,7 @@ fn fnDecl(...@@ -3613,7 +3731,7 @@ fn fnDecl(
3613 var section_gz = decl_gz.makeSubBlock(params_scope);3731 var section_gz = decl_gz.makeSubBlock(params_scope);
3614 defer section_gz.unstack();3732 defer section_gz.unstack();
3615 const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {3733 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);
3617 if (section_gz.instructionsSlice().len == 0) {3735 if (section_gz.instructionsSlice().len == 0) {
3618 // In this case we will send a len=0 body which can be encoded more efficiently.3736 // In this case we will send a len=0 body which can be encoded more efficiently.
3619 break :inst inst;3737 break :inst inst;
...@@ -3636,7 +3754,7 @@ fn fnDecl(...@@ -3636,7 +3754,7 @@ fn fnDecl(
3636 const inst = try expr(3754 const inst = try expr(
3637 &decl_gz,3755 &decl_gz,
3638 params_scope,3756 params_scope,
3639 .{ .coerced_ty = .calling_convention_type },3757 .{ .rl = .{ .coerced_ty = .calling_convention_type } },
3640 fn_proto.ast.callconv_expr,3758 fn_proto.ast.callconv_expr,
3641 );3759 );
3642 if (cc_gz.instructionsSlice().len == 0) {3760 if (cc_gz.instructionsSlice().len == 0) {
...@@ -3658,7 +3776,7 @@ fn fnDecl(...@@ -3658,7 +3776,7 @@ fn fnDecl(
3658 var ret_gz = decl_gz.makeSubBlock(params_scope);3776 var ret_gz = decl_gz.makeSubBlock(params_scope);
3659 defer ret_gz.unstack();3777 defer ret_gz.unstack();
3660 const ret_ref: Zir.Inst.Ref = inst: {3778 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);
3662 if (ret_gz.instructionsSlice().len == 0) {3780 if (ret_gz.instructionsSlice().len == 0) {
3663 // In this case we will send a len=0 body which can be encoded more efficiently.3781 // In this case we will send a len=0 body which can be encoded more efficiently.
3664 break :inst inst;3782 break :inst inst;
...@@ -3712,10 +3830,13 @@ fn fnDecl(...@@ -3712,10 +3830,13 @@ fn fnDecl(
3712 const lbrace_line = astgen.source_line - decl_gz.decl_line;3830 const lbrace_line = astgen.source_line - decl_gz.decl_line;
3713 const lbrace_column = astgen.source_column;3831 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);
3716 try checkUsed(gz, &fn_gz.base, params_scope);3834 try checkUsed(gz, &fn_gz.base, params_scope);
37173835
3718 if (!fn_gz.endsWithNoReturn()) {3836 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
3719 // Since we are adding the return instruction here, we must handle the coercion.3840 // Since we are adding the return instruction here, we must handle the coercion.
3720 // We do this by using the `ret_tok` instruction.3841 // We do this by using the `ret_tok` instruction.
3721 _ = try fn_gz.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node));3842 _ = try fn_gz.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node));
...@@ -3808,13 +3929,13 @@ fn globalVarDecl(...@@ -3808,13 +3929,13 @@ fn globalVarDecl(
3808 break :blk token_tags[maybe_extern_token] == .keyword_extern;3929 break :blk token_tags[maybe_extern_token] == .keyword_extern;
3809 };3930 };
3810 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: {3931 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);
3812 };3933 };
3813 const addrspace_inst: Zir.Inst.Ref = if (var_decl.ast.addrspace_node == 0) .none else inst: {3934 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);
3815 };3936 };
3816 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {3937 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);
3818 };3939 };
3819 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;3940 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;
3820 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);3941 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);
...@@ -3854,7 +3975,7 @@ fn globalVarDecl(...@@ -3854,7 +3975,7 @@ fn globalVarDecl(
3854 try expr(3975 try expr(
3855 &block_scope,3976 &block_scope,
3856 &block_scope.base,3977 &block_scope.base,
3857 .{ .ty = .type_type },3978 .{ .rl = .{ .ty = .type_type } },
3858 var_decl.ast.type_node,3979 var_decl.ast.type_node,
3859 )3980 )
3860 else3981 else
...@@ -3863,7 +3984,7 @@ fn globalVarDecl(...@@ -3863,7 +3984,7 @@ fn globalVarDecl(
3863 const init_inst = try expr(3984 const init_inst = try expr(
3864 &block_scope,3985 &block_scope,
3865 &block_scope.base,3986 &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 },
3867 var_decl.ast.init_node,3988 var_decl.ast.init_node,
3868 );3989 );
38693990
...@@ -3952,7 +4073,7 @@ fn comptimeDecl(...@@ -3952,7 +4073,7 @@ fn comptimeDecl(
3952 };4073 };
3953 defer decl_block.unstack();4074 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);
3956 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {4077 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {
3957 _ = try decl_block.addBreak(.break_inline, block_inst, .void_value);4078 _ = try decl_block.addBreak(.break_inline, block_inst, .void_value);
3958 }4079 }
...@@ -4156,8 +4277,12 @@ fn testDecl(...@@ -4156,8 +4277,12 @@ fn testDecl(
4156 const lbrace_line = astgen.source_line - decl_block.decl_line;4277 const lbrace_line = astgen.source_line - decl_block.decl_line;
4157 const lbrace_column = astgen.source_column;4278 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);
4160 if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) {4281 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
4161 // Since we are adding the return instruction here, we must handle the coercion.4286 // Since we are adding the return instruction here, we must handle the coercion.
4162 // We do this by using the `ret_tok` instruction.4287 // We do this by using the `ret_tok` instruction.
4163 _ = try fn_block.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node));4288 _ = try fn_block.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node));
...@@ -4370,7 +4495,7 @@ fn structDeclInner(...@@ -4370,7 +4495,7 @@ fn structDeclInner(
4370 if (layout == .Packed) {4495 if (layout == .Packed) {
4371 try astgen.appendErrorNode(member.ast.align_expr, "unable to override alignment of packed struct fields", .{});4496 try astgen.appendErrorNode(member.ast.align_expr, "unable to override alignment of packed struct fields", .{});
4372 }4497 }
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);
4374 if (!block_scope.endsWithNoReturn()) {4499 if (!block_scope.endsWithNoReturn()) {
4375 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);4500 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);
4376 }4501 }
...@@ -4383,9 +4508,9 @@ fn structDeclInner(...@@ -4383,9 +4508,9 @@ fn structDeclInner(
4383 }4508 }
43844509
4385 if (have_value) {4510 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);
4389 if (!block_scope.endsWithNoReturn()) {4514 if (!block_scope.endsWithNoReturn()) {
4390 _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst);4515 _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst);
4391 }4516 }
...@@ -4514,7 +4639,7 @@ fn unionDeclInner(...@@ -4514,7 +4639,7 @@ fn unionDeclInner(
4514 return astgen.failNode(member_node, "union field missing type", .{});4639 return astgen.failNode(member_node, "union field missing type", .{});
4515 }4640 }
4516 if (have_align) {4641 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);
4518 wip_members.appendToField(@enumToInt(align_inst));4643 wip_members.appendToField(@enumToInt(align_inst));
4519 }4644 }
4520 if (have_value) {4645 if (have_value) {
...@@ -4546,7 +4671,7 @@ fn unionDeclInner(...@@ -4546,7 +4671,7 @@ fn unionDeclInner(
4546 },4671 },
4547 );4672 );
4548 }4673 }
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);
4550 wip_members.appendToField(@enumToInt(tag_value));4675 wip_members.appendToField(@enumToInt(tag_value));
4551 }4676 }
4552 }4677 }
...@@ -4584,7 +4709,7 @@ fn unionDeclInner(...@@ -4584,7 +4709,7 @@ fn unionDeclInner(
4584fn containerDecl(4709fn containerDecl(
4585 gz: *GenZir,4710 gz: *GenZir,
4586 scope: *Scope,4711 scope: *Scope,
4587 rl: ResultLoc,4712 ri: ResultInfo,
4588 node: Ast.Node.Index,4713 node: Ast.Node.Index,
4589 container_decl: Ast.full.ContainerDecl,4714 container_decl: Ast.full.ContainerDecl,
4590) InnerError!Zir.Inst.Ref {4715) InnerError!Zir.Inst.Ref {
...@@ -4610,7 +4735,7 @@ fn containerDecl(...@@ -4610,7 +4735,7 @@ fn containerDecl(
4610 } else std.builtin.Type.ContainerLayout.Auto;4735 } else std.builtin.Type.ContainerLayout.Auto;
46114736
4612 const result = try structDeclInner(gz, scope, node, container_decl, layout, container_decl.ast.arg);4737 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);
4614 },4739 },
4615 .keyword_union => {4740 .keyword_union => {
4616 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {4741 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
...@@ -4620,7 +4745,7 @@ fn containerDecl(...@@ -4620,7 +4745,7 @@ fn containerDecl(
4620 } else std.builtin.Type.ContainerLayout.Auto;4745 } else std.builtin.Type.ContainerLayout.Auto;
46214746
4622 const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, container_decl.ast.arg, container_decl.ast.enum_token);4747 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);
4624 },4749 },
4625 .keyword_enum => {4750 .keyword_enum => {
4626 if (container_decl.layout_token) |t| {4751 if (container_decl.layout_token) |t| {
...@@ -4750,7 +4875,7 @@ fn containerDecl(...@@ -4750,7 +4875,7 @@ fn containerDecl(
4750 _ = try astgen.scanDecls(&namespace, container_decl.ast.members);4875 _ = try astgen.scanDecls(&namespace, container_decl.ast.members);
47514876
4752 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)4877 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)
4754 else4879 else
4755 .none;4880 .none;
47564881
...@@ -4794,7 +4919,7 @@ fn containerDecl(...@@ -4794,7 +4919,7 @@ fn containerDecl(
4794 },4919 },
4795 );4920 );
4796 }4921 }
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);
4798 wip_members.appendToField(@enumToInt(tag_value_inst));4923 wip_members.appendToField(@enumToInt(tag_value_inst));
4799 }4924 }
4800 }4925 }
...@@ -4825,7 +4950,7 @@ fn containerDecl(...@@ -4825,7 +4950,7 @@ fn containerDecl(
48254950
4826 block_scope.unstack();4951 block_scope.unstack();
4827 try gz.addNamespaceCaptures(&namespace);4952 try gz.addNamespaceCaptures(&namespace);
4828 return rvalue(gz, rl, indexToRef(decl_inst), node);4953 return rvalue(gz, ri, indexToRef(decl_inst), node);
4829 },4954 },
4830 .keyword_opaque => {4955 .keyword_opaque => {
4831 assert(container_decl.ast.arg == 0);4956 assert(container_decl.ast.arg == 0);
...@@ -4875,7 +5000,7 @@ fn containerDecl(...@@ -4875,7 +5000,7 @@ fn containerDecl(
4875 astgen.extra.appendSliceAssumeCapacity(decls_slice);5000 astgen.extra.appendSliceAssumeCapacity(decls_slice);
48765001
4877 try gz.addNamespaceCaptures(&namespace);5002 try gz.addNamespaceCaptures(&namespace);
4878 return rvalue(gz, rl, indexToRef(decl_inst), node);5003 return rvalue(gz, ri, indexToRef(decl_inst), node);
4879 },5004 },
4880 else => unreachable,5005 else => unreachable,
4881 }5006 }
...@@ -5006,7 +5131,7 @@ fn containerMember(...@@ -5006,7 +5131,7 @@ fn containerMember(
5006 return .decl;5131 return .decl;
5007}5132}
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 {
5010 const astgen = gz.astgen;5135 const astgen = gz.astgen;
5011 const gpa = astgen.gpa;5136 const gpa = astgen.gpa;
5012 const tree = astgen.tree;5137 const tree = astgen.tree;
...@@ -5061,13 +5186,13 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir...@@ -5061,13 +5186,13 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir
5061 .fields_len = @intCast(u32, fields_len),5186 .fields_len = @intCast(u32, fields_len),
5062 });5187 });
5063 const result = try gz.addPlNodePayloadIndex(.error_set_decl, node, payload_index);5188 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);
5065}5190}
50665191
5067fn tryExpr(5192fn tryExpr(
5068 parent_gz: *GenZir,5193 parent_gz: *GenZir,
5069 scope: *Scope,5194 scope: *Scope,
5070 rl: ResultLoc,5195 ri: ResultInfo,
5071 node: Ast.Node.Index,5196 node: Ast.Node.Index,
5072 operand_node: Ast.Node.Index,5197 operand_node: Ast.Node.Index,
5073) InnerError!Zir.Inst.Ref {5198) InnerError!Zir.Inst.Ref {
...@@ -5097,15 +5222,15 @@ fn tryExpr(...@@ -5097,15 +5222,15 @@ fn tryExpr(
5097 const try_line = astgen.source_line - parent_gz.decl_line;5222 const try_line = astgen.source_line - parent_gz.decl_line;
5098 const try_column = astgen.source_column;5223 const try_column = astgen.source_column;
50995224
5100 const operand_rl: ResultLoc = switch (rl) {5225 const operand_ri: ResultInfo = switch (ri.rl) {
5101 .ref => .ref,5226 .ref => .{ .rl = .ref, .ctx = .error_handling_expr },
5102 else => .none,5227 else => .{ .rl = .none, .ctx = .error_handling_expr },
5103 };5228 };
5104 // This could be a pointer or value depending on the `rl` parameter.5229 // This could be a pointer or value depending on the `ri` parameter.
5105 const operand = try reachableExpr(parent_gz, scope, operand_rl, operand_node, node);5230 const operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, node);
5106 const is_inline = parent_gz.force_comptime;5231 const is_inline = parent_gz.force_comptime;
5107 const is_inline_bit = @as(u2, @boolToInt(is_inline));5232 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;
5109 const block_tag: Zir.Inst.Tag = switch (is_inline_bit | is_ptr_bit) {5234 const block_tag: Zir.Inst.Tag = switch (is_inline_bit | is_ptr_bit) {
5110 0b00 => .@"try",5235 0b00 => .@"try",
5111 0b01 => .@"try",5236 0b01 => .@"try",
...@@ -5120,7 +5245,7 @@ fn tryExpr(...@@ -5120,7 +5245,7 @@ fn tryExpr(
5120 var else_scope = parent_gz.makeSubBlock(scope);5245 var else_scope = parent_gz.makeSubBlock(scope);
5121 defer else_scope.unstack();5246 defer else_scope.unstack();
51225247
5123 const err_tag = switch (rl) {5248 const err_tag = switch (ri.rl) {
5124 .ref => Zir.Inst.Tag.err_union_code_ptr,5249 .ref => Zir.Inst.Tag.err_union_code_ptr,
5125 else => Zir.Inst.Tag.err_union_code,5250 else => Zir.Inst.Tag.err_union_code,
5126 };5251 };
...@@ -5131,16 +5256,16 @@ fn tryExpr(...@@ -5131,16 +5256,16 @@ fn tryExpr(
51315256
5132 try else_scope.setTryBody(try_inst, operand);5257 try else_scope.setTryBody(try_inst, operand);
5133 const result = indexToRef(try_inst);5258 const result = indexToRef(try_inst);
5134 switch (rl) {5259 switch (ri.rl) {
5135 .ref => return result,5260 .ref => return result,
5136 else => return rvalue(parent_gz, rl, result, node),5261 else => return rvalue(parent_gz, ri, result, node),
5137 }5262 }
5138}5263}
51395264
5140fn orelseCatchExpr(5265fn orelseCatchExpr(
5141 parent_gz: *GenZir,5266 parent_gz: *GenZir,
5142 scope: *Scope,5267 scope: *Scope,
5143 rl: ResultLoc,5268 ri: ResultInfo,
5144 node: Ast.Node.Index,5269 node: Ast.Node.Index,
5145 lhs: Ast.Node.Index,5270 lhs: Ast.Node.Index,
5146 cond_op: Zir.Inst.Tag,5271 cond_op: Zir.Inst.Tag,
...@@ -5152,20 +5277,22 @@ fn orelseCatchExpr(...@@ -5152,20 +5277,22 @@ fn orelseCatchExpr(
5152 const astgen = parent_gz.astgen;5277 const astgen = parent_gz.astgen;
5153 const tree = astgen.tree;5278 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
5155 var block_scope = parent_gz.makeSubBlock(scope);5282 var block_scope = parent_gz.makeSubBlock(scope);
5156 block_scope.setBreakResultLoc(rl);5283 block_scope.setBreakResultInfo(ri);
5157 defer block_scope.unstack();5284 defer block_scope.unstack();
51585285
5159 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {5286 const operand_ri: ResultInfo = switch (block_scope.break_result_info.rl) {
5160 .ref => .ref,5287 .ref => .{ .rl = .ref, .ctx = if (do_err_trace) .error_handling_expr else .none },
5161 else => .none,5288 else => .{ .rl = .none, .ctx = if (do_err_trace) .error_handling_expr else .none },
5162 };5289 };
5163 block_scope.break_count += 1;5290 block_scope.break_count += 1;
5164 // This could be a pointer or value depending on the `operand_rl` parameter.5291 // This could be a pointer or value depending on the `operand_ri` parameter.
5165 // We cannot use `block_scope.break_result_loc` because that has the bare5292 // We cannot use `block_scope.break_result_info` because that has the bare
5166 // type, whereas this expression has the optional type. Later we make5293 // type, whereas this expression has the optional type. Later we make
5167 // up for this fact by calling rvalue on the else branch.5294 // 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);
5169 const cond = try block_scope.addUnNode(cond_op, operand, node);5296 const cond = try block_scope.addUnNode(cond_op, operand, node);
5170 const condbr = try block_scope.addCondBr(.condbr, node);5297 const condbr = try block_scope.addCondBr(.condbr, node);
51715298
...@@ -5179,14 +5306,19 @@ fn orelseCatchExpr(...@@ -5179,14 +5306,19 @@ fn orelseCatchExpr(
51795306
5180 // This could be a pointer or value depending on `unwrap_op`.5307 // This could be a pointer or value depending on `unwrap_op`.
5181 const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);5308 const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);
5182 const then_result = switch (rl) {5309 const then_result = switch (ri.rl) {
5183 .ref => unwrapped_payload,5310 .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),
5185 };5312 };
51865313
5187 var else_scope = block_scope.makeSubBlock(scope);5314 var else_scope = block_scope.makeSubBlock(scope);
5188 defer else_scope.unstack();5315 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
5190 var err_val_scope: Scope.LocalVal = undefined;5322 var err_val_scope: Scope.LocalVal = undefined;
5191 const else_sub_scope = blk: {5323 const else_sub_scope = blk: {
5192 const payload = payload_token orelse break :blk &else_scope.base;5324 const payload = payload_token orelse break :blk &else_scope.base;
...@@ -5209,9 +5341,13 @@ fn orelseCatchExpr(...@@ -5209,9 +5341,13 @@ fn orelseCatchExpr(
5209 break :blk &err_val_scope.base;5341 break :blk &err_val_scope.base;
5210 };5342 };
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);
5213 if (!else_scope.endsWithNoReturn()) {5345 if (!else_scope.endsWithNoReturn()) {
5214 block_scope.break_count += 1;5346 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);
5215 }5351 }
5216 try checkUsed(parent_gz, &else_scope.base, else_sub_scope);5352 try checkUsed(parent_gz, &else_scope.base, else_sub_scope);
52175353
...@@ -5220,9 +5356,9 @@ fn orelseCatchExpr(...@@ -5220,9 +5356,9 @@ fn orelseCatchExpr(
5220 // instructions or not.5356 // instructions or not.
52215357
5222 const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break";5358 const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break";
5223 return finishThenElseBlock(5359 const result = try finishThenElseBlock(
5224 parent_gz,5360 parent_gz,
5225 rl,5361 ri,
5226 node,5362 node,
5227 &block_scope,5363 &block_scope,
5228 &then_scope,5364 &then_scope,
...@@ -5235,12 +5371,13 @@ fn orelseCatchExpr(...@@ -5235,12 +5371,13 @@ fn orelseCatchExpr(
5235 block,5371 block,
5236 break_tag,5372 break_tag,
5237 );5373 );
5374 return result;
5238}5375}
52395376
5240/// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`.5377/// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`.
5241fn finishThenElseBlock(5378fn finishThenElseBlock(
5242 parent_gz: *GenZir,5379 parent_gz: *GenZir,
5243 rl: ResultLoc,5380 ri: ResultInfo,
5244 node: Ast.Node.Index,5381 node: Ast.Node.Index,
5245 block_scope: *GenZir,5382 block_scope: *GenZir,
5246 then_scope: *GenZir,5383 then_scope: *GenZir,
...@@ -5255,7 +5392,7 @@ fn finishThenElseBlock(...@@ -5255,7 +5392,7 @@ fn finishThenElseBlock(
5255) InnerError!Zir.Inst.Ref {5392) InnerError!Zir.Inst.Ref {
5256 // We now have enough information to decide whether the result instruction should5393 // We now have enough information to decide whether the result instruction should
5257 // be communicated via result location pointer or break instructions.5394 // be communicated via result location pointer or break instructions.
5258 const strat = rl.strategy(block_scope);5395 const strat = ri.rl.strategy(block_scope);
5259 // else_scope may be stacked on then_scope, so check for no-return on then_scope manually5396 // else_scope may be stacked on then_scope, so check for no-return on then_scope manually
5260 const tags = parent_gz.astgen.instructions.items(.tag);5397 const tags = parent_gz.astgen.instructions.items(.tag);
5261 const then_slice = then_scope.instructionsSliceUpto(else_scope);5398 const then_slice = then_scope.instructionsSliceUpto(else_scope);
...@@ -5285,9 +5422,9 @@ fn finishThenElseBlock(...@@ -5285,9 +5422,9 @@ fn finishThenElseBlock(
5285 try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break);5422 try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break);
5286 }5423 }
5287 const block_ref = indexToRef(main_block);5424 const block_ref = indexToRef(main_block);
5288 switch (rl) {5425 switch (ri.rl) {
5289 .ref => return block_ref,5426 .ref => return block_ref,
5290 else => return rvalue(parent_gz, rl, block_ref, node),5427 else => return rvalue(parent_gz, ri, block_ref, node),
5291 }5428 }
5292 },5429 },
5293 }5430 }
...@@ -5306,14 +5443,14 @@ fn tokenIdentEql(astgen: *AstGen, token1: Ast.TokenIndex, token2: Ast.TokenIndex...@@ -5306,14 +5443,14 @@ fn tokenIdentEql(astgen: *AstGen, token1: Ast.TokenIndex, token2: Ast.TokenIndex
5306fn fieldAccess(5443fn fieldAccess(
5307 gz: *GenZir,5444 gz: *GenZir,
5308 scope: *Scope,5445 scope: *Scope,
5309 rl: ResultLoc,5446 ri: ResultInfo,
5310 node: Ast.Node.Index,5447 node: Ast.Node.Index,
5311) InnerError!Zir.Inst.Ref {5448) InnerError!Zir.Inst.Ref {
5312 switch (rl) {5449 switch (ri.rl) {
5313 .ref => return addFieldAccess(.field_ptr, gz, scope, .ref, node),5450 .ref => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node),
5314 else => {5451 else => {
5315 const access = try addFieldAccess(.field_val, gz, scope, .none, node);5452 const access = try addFieldAccess(.field_val, gz, scope, .{ .rl = .none }, node);
5316 return rvalue(gz, rl, access, node);5453 return rvalue(gz, ri, access, node);
5317 },5454 },
5318 }5455 }
5319}5456}
...@@ -5322,7 +5459,7 @@ fn addFieldAccess(...@@ -5322,7 +5459,7 @@ fn addFieldAccess(
5322 tag: Zir.Inst.Tag,5459 tag: Zir.Inst.Tag,
5323 gz: *GenZir,5460 gz: *GenZir,
5324 scope: *Scope,5461 scope: *Scope,
5325 lhs_rl: ResultLoc,5462 lhs_ri: ResultInfo,
5326 node: Ast.Node.Index,5463 node: Ast.Node.Index,
5327) InnerError!Zir.Inst.Ref {5464) InnerError!Zir.Inst.Ref {
5328 const astgen = gz.astgen;5465 const astgen = gz.astgen;
...@@ -5336,7 +5473,7 @@ fn addFieldAccess(...@@ -5336,7 +5473,7 @@ fn addFieldAccess(
5336 const str_index = try astgen.identAsString(field_ident);5473 const str_index = try astgen.identAsString(field_ident);
53375474
5338 return gz.addPlNode(tag, node, Zir.Inst.Field{5475 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),
5340 .field_name_start = str_index,5477 .field_name_start = str_index,
5341 });5478 });
5342}5479}
...@@ -5344,20 +5481,20 @@ fn addFieldAccess(...@@ -5344,20 +5481,20 @@ fn addFieldAccess(
5344fn arrayAccess(5481fn arrayAccess(
5345 gz: *GenZir,5482 gz: *GenZir,
5346 scope: *Scope,5483 scope: *Scope,
5347 rl: ResultLoc,5484 ri: ResultInfo,
5348 node: Ast.Node.Index,5485 node: Ast.Node.Index,
5349) InnerError!Zir.Inst.Ref {5486) InnerError!Zir.Inst.Ref {
5350 const astgen = gz.astgen;5487 const astgen = gz.astgen;
5351 const tree = astgen.tree;5488 const tree = astgen.tree;
5352 const node_datas = tree.nodes.items(.data);5489 const node_datas = tree.nodes.items(.data);
5353 switch (rl) {5490 switch (ri.rl) {
5354 .ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{5491 .ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{
5355 .lhs = try expr(gz, scope, .ref, node_datas[node].lhs),5492 .lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs),
5356 .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),5493 .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs),
5357 }),5494 }),
5358 else => return rvalue(gz, rl, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{5495 else => return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{
5359 .lhs = try expr(gz, scope, .none, node_datas[node].lhs),5496 .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
5360 .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),5497 .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs),
5361 }), node),5498 }), node),
5362 }5499 }
5363}5500}
...@@ -5365,7 +5502,7 @@ fn arrayAccess(...@@ -5365,7 +5502,7 @@ fn arrayAccess(
5365fn simpleBinOp(5502fn simpleBinOp(
5366 gz: *GenZir,5503 gz: *GenZir,
5367 scope: *Scope,5504 scope: *Scope,
5368 rl: ResultLoc,5505 ri: ResultInfo,
5369 node: Ast.Node.Index,5506 node: Ast.Node.Index,
5370 op_inst_tag: Zir.Inst.Tag,5507 op_inst_tag: Zir.Inst.Tag,
5371) InnerError!Zir.Inst.Ref {5508) InnerError!Zir.Inst.Ref {
...@@ -5374,15 +5511,15 @@ fn simpleBinOp(...@@ -5374,15 +5511,15 @@ fn simpleBinOp(
5374 const node_datas = tree.nodes.items(.data);5511 const node_datas = tree.nodes.items(.data);
53755512
5376 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{5513 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{
5377 .lhs = try reachableExpr(gz, scope, .none, node_datas[node].lhs, node),5514 .lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node),
5378 .rhs = try reachableExpr(gz, scope, .none, node_datas[node].rhs, node),5515 .rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node),
5379 });5516 });
5380 return rvalue(gz, rl, result, node);5517 return rvalue(gz, ri, result, node);
5381}5518}
53825519
5383fn simpleStrTok(5520fn simpleStrTok(
5384 gz: *GenZir,5521 gz: *GenZir,
5385 rl: ResultLoc,5522 ri: ResultInfo,
5386 ident_token: Ast.TokenIndex,5523 ident_token: Ast.TokenIndex,
5387 node: Ast.Node.Index,5524 node: Ast.Node.Index,
5388 op_inst_tag: Zir.Inst.Tag,5525 op_inst_tag: Zir.Inst.Tag,
...@@ -5390,13 +5527,13 @@ fn simpleStrTok(...@@ -5390,13 +5527,13 @@ fn simpleStrTok(
5390 const astgen = gz.astgen;5527 const astgen = gz.astgen;
5391 const str_index = try astgen.identAsString(ident_token);5528 const str_index = try astgen.identAsString(ident_token);
5392 const result = try gz.addStrTok(op_inst_tag, str_index, ident_token);5529 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);
5394}5531}
53955532
5396fn boolBinOp(5533fn boolBinOp(
5397 gz: *GenZir,5534 gz: *GenZir,
5398 scope: *Scope,5535 scope: *Scope,
5399 rl: ResultLoc,5536 ri: ResultInfo,
5400 node: Ast.Node.Index,5537 node: Ast.Node.Index,
5401 zir_tag: Zir.Inst.Tag,5538 zir_tag: Zir.Inst.Tag,
5402) InnerError!Zir.Inst.Ref {5539) InnerError!Zir.Inst.Ref {
...@@ -5404,25 +5541,25 @@ fn boolBinOp(...@@ -5404,25 +5541,25 @@ fn boolBinOp(
5404 const tree = astgen.tree;5541 const tree = astgen.tree;
5405 const node_datas = tree.nodes.items(.data);5542 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);
5408 const bool_br = try gz.addBoolBr(zir_tag, lhs);5545 const bool_br = try gz.addBoolBr(zir_tag, lhs);
54095546
5410 var rhs_scope = gz.makeSubBlock(scope);5547 var rhs_scope = gz.makeSubBlock(scope);
5411 defer rhs_scope.unstack();5548 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);
5413 if (!gz.refIsNoReturn(rhs)) {5550 if (!gz.refIsNoReturn(rhs)) {
5414 _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);5551 _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);
5415 }5552 }
5416 try rhs_scope.setBoolBrBody(bool_br);5553 try rhs_scope.setBoolBrBody(bool_br);
54175554
5418 const block_ref = indexToRef(bool_br);5555 const block_ref = indexToRef(bool_br);
5419 return rvalue(gz, rl, block_ref, node);5556 return rvalue(gz, ri, block_ref, node);
5420}5557}
54215558
5422fn ifExpr(5559fn ifExpr(
5423 parent_gz: *GenZir,5560 parent_gz: *GenZir,
5424 scope: *Scope,5561 scope: *Scope,
5425 rl: ResultLoc,5562 ri: ResultInfo,
5426 node: Ast.Node.Index,5563 node: Ast.Node.Index,
5427 if_full: Ast.full.If,5564 if_full: Ast.full.If,
5428) InnerError!Zir.Inst.Ref {5565) InnerError!Zir.Inst.Ref {
...@@ -5430,8 +5567,10 @@ fn ifExpr(...@@ -5430,8 +5567,10 @@ fn ifExpr(
5430 const tree = astgen.tree;5567 const tree = astgen.tree;
5431 const token_tags = tree.tokens.items(.tag);5568 const token_tags = tree.tokens.items(.tag);
54325569
5570 const do_err_trace = astgen.fn_block != null and if_full.error_token != null;
5571
5433 var block_scope = parent_gz.makeSubBlock(scope);5572 var block_scope = parent_gz.makeSubBlock(scope);
5434 block_scope.setBreakResultLoc(rl);5573 block_scope.setBreakResultInfo(ri);
5435 defer block_scope.unstack();5574 defer block_scope.unstack();
54365575
5437 const payload_is_ref = if (if_full.payload_token) |payload_token|5576 const payload_is_ref = if (if_full.payload_token) |payload_token|
...@@ -5445,23 +5584,23 @@ fn ifExpr(...@@ -5445,23 +5584,23 @@ fn ifExpr(
5445 bool_bit: Zir.Inst.Ref,5584 bool_bit: Zir.Inst.Ref,
5446 } = c: {5585 } = c: {
5447 if (if_full.error_token) |_| {5586 if (if_full.error_token) |_| {
5448 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;5587 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none, .ctx = .error_handling_expr };
5449 const err_union = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr);5588 const err_union = try expr(&block_scope, &block_scope.base, cond_ri, if_full.ast.cond_expr);
5450 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;5589 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;
5451 break :c .{5590 break :c .{
5452 .inst = err_union,5591 .inst = err_union,
5453 .bool_bit = try block_scope.addUnNode(tag, err_union, if_full.ast.cond_expr),5592 .bool_bit = try block_scope.addUnNode(tag, err_union, if_full.ast.cond_expr),
5454 };5593 };
5455 } else if (if_full.payload_token) |_| {5594 } else if (if_full.payload_token) |_| {
5456 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;5595 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
5457 const optional = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr);5596 const optional = try expr(&block_scope, &block_scope.base, cond_ri, if_full.ast.cond_expr);
5458 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;5597 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;
5459 break :c .{5598 break :c .{
5460 .inst = optional,5599 .inst = optional,
5461 .bool_bit = try block_scope.addUnNode(tag, optional, if_full.ast.cond_expr),5600 .bool_bit = try block_scope.addUnNode(tag, optional, if_full.ast.cond_expr),
5462 };5601 };
5463 } else {5602 } 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);
5465 break :c .{5604 break :c .{
5466 .inst = cond,5605 .inst = cond,
5467 .bool_bit = cond,5606 .bool_bit = cond,
...@@ -5537,7 +5676,7 @@ fn ifExpr(...@@ -5537,7 +5676,7 @@ fn ifExpr(
5537 }5676 }
5538 };5677 };
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);
5541 if (!then_scope.endsWithNoReturn()) {5680 if (!then_scope.endsWithNoReturn()) {
5542 block_scope.break_count += 1;5681 block_scope.break_count += 1;
5543 }5682 }
...@@ -5550,6 +5689,11 @@ fn ifExpr(...@@ -5550,6 +5689,11 @@ fn ifExpr(
5550 var else_scope = parent_gz.makeSubBlock(scope);5689 var else_scope = parent_gz.makeSubBlock(scope);
5551 defer else_scope.unstack();5690 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
5553 const else_node = if_full.ast.else_expr;5697 const else_node = if_full.ast.else_expr;
5554 const else_info: struct {5698 const else_info: struct {
5555 src: Ast.Node.Index,5699 src: Ast.Node.Index,
...@@ -5582,9 +5726,13 @@ fn ifExpr(...@@ -5582,9 +5726,13 @@ fn ifExpr(
5582 break :s &else_scope.base;5726 break :s &else_scope.base;
5583 }5727 }
5584 };5728 };
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);
5586 if (!else_scope.endsWithNoReturn()) {5730 if (!else_scope.endsWithNoReturn()) {
5587 block_scope.break_count += 1;5731 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);
5588 }5736 }
5589 try checkUsed(parent_gz, &else_scope.base, sub_scope);5737 try checkUsed(parent_gz, &else_scope.base, sub_scope);
5590 try else_scope.addDbgBlockEnd();5738 try else_scope.addDbgBlockEnd();
...@@ -5594,17 +5742,17 @@ fn ifExpr(...@@ -5594,17 +5742,17 @@ fn ifExpr(
5594 };5742 };
5595 } else .{5743 } else .{
5596 .src = if_full.ast.then_expr,5744 .src = if_full.ast.then_expr,
5597 .result = switch (rl) {5745 .result = switch (ri.rl) {
5598 // Explicitly store void to ptr result loc if there is no else branch5746 // 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),
5600 else => .none,5748 else => .none,
5601 },5749 },
5602 };5750 };
56035751
5604 const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break";5752 const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break";
5605 return finishThenElseBlock(5753 const result = try finishThenElseBlock(
5606 parent_gz,5754 parent_gz,
5607 rl,5755 ri,
5608 node,5756 node,
5609 &block_scope,5757 &block_scope,
5610 &then_scope,5758 &then_scope,
...@@ -5617,6 +5765,7 @@ fn ifExpr(...@@ -5617,6 +5765,7 @@ fn ifExpr(
5617 block,5765 block,
5618 break_tag,5766 break_tag,
5619 );5767 );
5768 return result;
5620}5769}
56215770
5622/// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`.5771/// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`.
...@@ -5737,7 +5886,7 @@ fn setCondBrPayloadElideBlockStorePtr(...@@ -5737,7 +5886,7 @@ fn setCondBrPayloadElideBlockStorePtr(
5737fn whileExpr(5886fn whileExpr(
5738 parent_gz: *GenZir,5887 parent_gz: *GenZir,
5739 scope: *Scope,5888 scope: *Scope,
5740 rl: ResultLoc,5889 ri: ResultInfo,
5741 node: Ast.Node.Index,5890 node: Ast.Node.Index,
5742 while_full: Ast.full.While,5891 while_full: Ast.full.While,
5743 is_statement: bool,5892 is_statement: bool,
...@@ -5757,7 +5906,7 @@ fn whileExpr(...@@ -5757,7 +5906,7 @@ fn whileExpr(
57575906
5758 var loop_scope = parent_gz.makeSubBlock(scope);5907 var loop_scope = parent_gz.makeSubBlock(scope);
5759 loop_scope.is_inline = is_inline;5908 loop_scope.is_inline = is_inline;
5760 loop_scope.setBreakResultLoc(rl);5909 loop_scope.setBreakResultInfo(ri);
5761 defer loop_scope.unstack();5910 defer loop_scope.unstack();
5762 defer loop_scope.labeled_breaks.deinit(astgen.gpa);5911 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
57635912
...@@ -5775,23 +5924,23 @@ fn whileExpr(...@@ -5775,23 +5924,23 @@ fn whileExpr(
5775 bool_bit: Zir.Inst.Ref,5924 bool_bit: Zir.Inst.Ref,
5776 } = c: {5925 } = c: {
5777 if (while_full.error_token) |_| {5926 if (while_full.error_token) |_| {
5778 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;5927 const cond_ri: ResultInfo = .{ .rl = 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);5928 const err_union = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr);
5780 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;5929 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;
5781 break :c .{5930 break :c .{
5782 .inst = err_union,5931 .inst = err_union,
5783 .bool_bit = try continue_scope.addUnNode(tag, err_union, while_full.ast.then_expr),5932 .bool_bit = try continue_scope.addUnNode(tag, err_union, while_full.ast.then_expr),
5784 };5933 };
5785 } else if (while_full.payload_token) |_| {5934 } else if (while_full.payload_token) |_| {
5786 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;5935 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
5787 const optional = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr);5936 const optional = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr);
5788 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;5937 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;
5789 break :c .{5938 break :c .{
5790 .inst = optional,5939 .inst = optional,
5791 .bool_bit = try continue_scope.addUnNode(tag, optional, while_full.ast.then_expr),5940 .bool_bit = try continue_scope.addUnNode(tag, optional, while_full.ast.then_expr),
5792 };5941 };
5793 } else {5942 } 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);
5795 break :c .{5944 break :c .{
5796 .inst = cond,5945 .inst = cond,
5797 .bool_bit = cond,5946 .bool_bit = cond,
...@@ -5910,7 +6059,7 @@ fn whileExpr(...@@ -5910,7 +6059,7 @@ fn whileExpr(
5910 if (dbg_var_name) |some| {6059 if (dbg_var_name) |some| {
5911 try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst);6060 try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst);
5912 }6061 }
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);
5914 _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr);6063 _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr);
59156064
5916 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);6065 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
...@@ -5955,7 +6104,7 @@ fn whileExpr(...@@ -5955,7 +6104,7 @@ fn whileExpr(
5955 // control flow apply to outer loops; not this one.6104 // control flow apply to outer loops; not this one.
5956 loop_scope.continue_block = 0;6105 loop_scope.continue_block = 0;
5957 loop_scope.break_block = 0;6106 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);
5959 if (is_statement) {6108 if (is_statement) {
5960 _ = try addEnsureResult(&else_scope, else_result, else_node);6109 _ = try addEnsureResult(&else_scope, else_result, else_node);
5961 }6110 }
...@@ -5982,7 +6131,7 @@ fn whileExpr(...@@ -5982,7 +6131,7 @@ fn whileExpr(
5982 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";6131 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
5983 const result = try finishThenElseBlock(6132 const result = try finishThenElseBlock(
5984 parent_gz,6133 parent_gz,
5985 rl,6134 ri,
5986 node,6135 node,
5987 &loop_scope,6136 &loop_scope,
5988 &then_scope,6137 &then_scope,
...@@ -6004,7 +6153,7 @@ fn whileExpr(...@@ -6004,7 +6153,7 @@ fn whileExpr(
6004fn forExpr(6153fn forExpr(
6005 parent_gz: *GenZir,6154 parent_gz: *GenZir,
6006 scope: *Scope,6155 scope: *Scope,
6007 rl: ResultLoc,6156 ri: ResultInfo,
6008 node: Ast.Node.Index,6157 node: Ast.Node.Index,
6009 for_full: Ast.full.While,6158 for_full: Ast.full.While,
6010 is_statement: bool,6159 is_statement: bool,
...@@ -6027,8 +6176,8 @@ fn forExpr(...@@ -6027,8 +6176,8 @@ fn forExpr(
60276176
6028 try emitDbgNode(parent_gz, for_full.ast.cond_expr);6177 try emitDbgNode(parent_gz, for_full.ast.cond_expr);
60296178
6030 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;6179 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
6031 const array_ptr = try expr(parent_gz, scope, cond_rl, for_full.ast.cond_expr);6180 const array_ptr = try expr(parent_gz, scope, cond_ri, for_full.ast.cond_expr);
6032 const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr);6181 const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr);
60336182
6034 const index_ptr = blk: {6183 const index_ptr = blk: {
...@@ -6045,7 +6194,7 @@ fn forExpr(...@@ -6045,7 +6194,7 @@ fn forExpr(
60456194
6046 var loop_scope = parent_gz.makeSubBlock(scope);6195 var loop_scope = parent_gz.makeSubBlock(scope);
6047 loop_scope.is_inline = is_inline;6196 loop_scope.is_inline = is_inline;
6048 loop_scope.setBreakResultLoc(rl);6197 loop_scope.setBreakResultInfo(ri);
6049 defer loop_scope.unstack();6198 defer loop_scope.unstack();
6050 defer loop_scope.labeled_breaks.deinit(astgen.gpa);6199 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
60516200
...@@ -6149,7 +6298,7 @@ fn forExpr(...@@ -6149,7 +6298,7 @@ fn forExpr(
6149 break :blk &index_scope.base;6298 break :blk &index_scope.base;
6150 };6299 };
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);
6153 _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr);6302 _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr);
61546303
6155 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);6304 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
...@@ -6168,7 +6317,7 @@ fn forExpr(...@@ -6168,7 +6317,7 @@ fn forExpr(
6168 // control flow apply to outer loops; not this one.6317 // control flow apply to outer loops; not this one.
6169 loop_scope.continue_block = 0;6318 loop_scope.continue_block = 0;
6170 loop_scope.break_block = 0;6319 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);
6172 if (is_statement) {6321 if (is_statement) {
6173 _ = try addEnsureResult(&else_scope, else_result, else_node);6322 _ = try addEnsureResult(&else_scope, else_result, else_node);
6174 }6323 }
...@@ -6193,7 +6342,7 @@ fn forExpr(...@@ -6193,7 +6342,7 @@ fn forExpr(
6193 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";6342 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
6194 const result = try finishThenElseBlock(6343 const result = try finishThenElseBlock(
6195 parent_gz,6344 parent_gz,
6196 rl,6345 ri,
6197 node,6346 node,
6198 &loop_scope,6347 &loop_scope,
6199 &then_scope,6348 &then_scope,
...@@ -6215,7 +6364,7 @@ fn forExpr(...@@ -6215,7 +6364,7 @@ fn forExpr(
6215fn switchExpr(6364fn switchExpr(
6216 parent_gz: *GenZir,6365 parent_gz: *GenZir,
6217 scope: *Scope,6366 scope: *Scope,
6218 rl: ResultLoc,6367 ri: ResultInfo,
6219 switch_node: Ast.Node.Index,6368 switch_node: Ast.Node.Index,
6220) InnerError!Zir.Inst.Ref {6369) InnerError!Zir.Inst.Ref {
6221 const astgen = parent_gz.astgen;6370 const astgen = parent_gz.astgen;
...@@ -6346,13 +6495,13 @@ fn switchExpr(...@@ -6346,13 +6495,13 @@ fn switchExpr(
6346 }6495 }
6347 }6496 }
63486497
6349 const operand_rl: ResultLoc = if (any_payload_is_ref) .ref else .none;6498 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };
6350 const raw_operand = try expr(parent_gz, scope, operand_rl, operand_node);6499 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);
6351 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;6500 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;
6352 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);6501 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);
6353 // We need the type of the operand to use as the result location for all the prong items.6502 // We need the type of the operand to use as the result location for all the prong items.
6354 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);6503 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
6357 // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti,6506 // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti,
6358 // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with6507 // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with
...@@ -6369,7 +6518,7 @@ fn switchExpr(...@@ -6369,7 +6518,7 @@ fn switchExpr(
6369 var block_scope = parent_gz.makeSubBlock(scope);6518 var block_scope = parent_gz.makeSubBlock(scope);
6370 // block_scope not used for collecting instructions6519 // block_scope not used for collecting instructions
6371 block_scope.instructions_top = GenZir.unstacked_top;6520 block_scope.instructions_top = GenZir.unstacked_top;
6372 block_scope.setBreakResultLoc(rl);6521 block_scope.setBreakResultInfo(ri);
63736522
6374 // This gets added to the parent block later, after the item expressions.6523 // This gets added to the parent block later, after the item expressions.
6375 const switch_block = try parent_gz.makeBlockInst(.switch_block, switch_node);6524 const switch_block = try parent_gz.makeBlockInst(.switch_block, switch_node);
...@@ -6510,7 +6659,7 @@ fn switchExpr(...@@ -6510,7 +6659,7 @@ fn switchExpr(
6510 if (node_tags[item_node] == .switch_range) continue;6659 if (node_tags[item_node] == .switch_range) continue;
6511 items_len += 1;6660 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);
6514 try payloads.append(gpa, @enumToInt(item_inst));6663 try payloads.append(gpa, @enumToInt(item_inst));
6515 }6664 }
65166665
...@@ -6520,8 +6669,8 @@ fn switchExpr(...@@ -6520,8 +6669,8 @@ fn switchExpr(
6520 if (node_tags[range] != .switch_range) continue;6669 if (node_tags[range] != .switch_range) continue;
6521 ranges_len += 1;6670 ranges_len += 1;
65226671
6523 const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs);6672 const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs);
6524 const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs);6673 const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs);
6525 try payloads.appendSlice(gpa, &[_]u32{6674 try payloads.appendSlice(gpa, &[_]u32{
6526 @enumToInt(first), @enumToInt(last),6675 @enumToInt(first), @enumToInt(last),
6527 });6676 });
...@@ -6539,7 +6688,7 @@ fn switchExpr(...@@ -6539,7 +6688,7 @@ fn switchExpr(
6539 scalar_case_index += 1;6688 scalar_case_index += 1;
6540 try payloads.resize(gpa, header_index + 2); // item, body_len6689 try payloads.resize(gpa, header_index + 2); // item, body_len
6541 const item_node = case.ast.values[0];6690 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);
6543 payloads.items[header_index] = @enumToInt(item_inst);6692 payloads.items[header_index] = @enumToInt(item_inst);
6544 break :blk header_index + 1;6693 break :blk header_index + 1;
6545 };6694 };
...@@ -6558,7 +6707,7 @@ fn switchExpr(...@@ -6558,7 +6707,7 @@ fn switchExpr(
6558 if (dbg_var_tag_name) |some| {6707 if (dbg_var_tag_name) |some| {
6559 try case_scope.addDbgVar(.dbg_var_val, some, dbg_var_tag_inst);6708 try case_scope.addDbgVar(.dbg_var_val, some, dbg_var_tag_inst);
6560 }6709 }
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);
6562 try checkUsed(parent_gz, &case_scope.base, sub_scope);6711 try checkUsed(parent_gz, &case_scope.base, sub_scope);
6563 try case_scope.addDbgBlockEnd();6712 try case_scope.addDbgBlockEnd();
6564 if (!parent_gz.refIsNoReturn(case_result)) {6713 if (!parent_gz.refIsNoReturn(case_result)) {
...@@ -6600,7 +6749,7 @@ fn switchExpr(...@@ -6600,7 +6749,7 @@ fn switchExpr(
66006749
6601 zir_datas[switch_block].pl_node.payload_index = payload_index;6750 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);
6604 for (payloads.items[case_table_start..case_table_end]) |start_index, i| {6753 for (payloads.items[case_table_start..case_table_end]) |start_index, i| {
6605 var body_len_index = start_index;6754 var body_len_index = start_index;
6606 var end_index = start_index;6755 var end_index = start_index;
...@@ -6672,8 +6821,8 @@ fn switchExpr(...@@ -6672,8 +6821,8 @@ fn switchExpr(
6672 }6821 }
66736822
6674 const block_ref = indexToRef(switch_block);6823 const block_ref = indexToRef(switch_block);
6675 if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and rl != .ref)6824 if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and ri.rl != .ref)
6676 return rvalue(parent_gz, rl, block_ref, switch_node);6825 return rvalue(parent_gz, ri, block_ref, switch_node);
6677 return block_ref;6826 return block_ref;
6678}6827}
66796828
...@@ -6713,6 +6862,10 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6713,6 +6862,10 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6713 if (operand_node == 0) {6862 if (operand_node == 0) {
6714 // Returning a void value; skip error defers.6863 // Returning a void value; skip error defers.
6715 try genDefers(gz, defer_outer, scope, .normal_only);6864 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
6716 _ = try gz.addUnNode(.ret_node, .void_value, node);6869 _ = try gz.addUnNode(.ret_node, .void_value, node);
6717 return Zir.Inst.Ref.unreachable_value;6870 return Zir.Inst.Ref.unreachable_value;
6718 }6871 }
...@@ -6736,30 +6889,36 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6736,30 +6889,36 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6736 return Zir.Inst.Ref.unreachable_value;6889 return Zir.Inst.Ref.unreachable_value;
6737 }6890 }
67386891
6739 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{6892 const ri: ResultInfo = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{
6740 .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) },6893 .rl = .{ .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) } },
6894 .ctx = .@"return",
6741 } else .{6895 } else .{
6742 .ty = try gz.addNode(.ret_type, node),6896 .rl = .{ .ty = try gz.addNode(.ret_type, node) },
6897 .ctx = .@"return",
6743 };6898 };
6744 const prev_anon_name_strategy = gz.anon_name_strategy;6899 const prev_anon_name_strategy = gz.anon_name_strategy;
6745 gz.anon_name_strategy = .func;6900 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);
6747 gz.anon_name_strategy = prev_anon_name_strategy;6902 gz.anon_name_strategy = prev_anon_name_strategy;
67486903
6749 switch (nodeMayEvalToError(tree, operand_node)) {6904 switch (nodeMayEvalToError(tree, operand_node)) {
6750 .never => {6905 .never => {
6751 // Returning a value that cannot be an error; skip error defers.6906 // Returning a value that cannot be an error; skip error defers.
6752 try genDefers(gz, defer_outer, scope, .normal_only);6907 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
6753 try emitDbgStmt(gz, ret_line, ret_column);6912 try emitDbgStmt(gz, ret_line, ret_column);
6754 try gz.addRet(rl, operand, node);6913 try gz.addRet(ri, operand, node);
6755 return Zir.Inst.Ref.unreachable_value;6914 return Zir.Inst.Ref.unreachable_value;
6756 },6915 },
6757 .always => {6916 .always => {
6758 // Value is always an error. Emit both error defers and regular defers.6917 // 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;
6760 try genDefers(gz, defer_outer, scope, .{ .both = err_code });6919 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
6761 try emitDbgStmt(gz, ret_line, ret_column);6920 try emitDbgStmt(gz, ret_line, ret_column);
6762 try gz.addRet(rl, operand, node);6921 try gz.addRet(ri, operand, node);
6763 return Zir.Inst.Ref.unreachable_value;6922 return Zir.Inst.Ref.unreachable_value;
6764 },6923 },
6765 .maybe => {6924 .maybe => {
...@@ -6768,12 +6927,17 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6768,12 +6927,17 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6768 // Only regular defers; no branch needed.6927 // Only regular defers; no branch needed.
6769 try genDefers(gz, defer_outer, scope, .normal_only);6928 try genDefers(gz, defer_outer, scope, .normal_only);
6770 try emitDbgStmt(gz, ret_line, ret_column);6929 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);
6772 return Zir.Inst.Ref.unreachable_value;6936 return Zir.Inst.Ref.unreachable_value;
6773 }6937 }
67746938
6775 // Emit conditional branch for generating errdefers.6939 // 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;
6777 const is_non_err = try gz.addUnNode(.is_non_err, result, node);6941 const is_non_err = try gz.addUnNode(.is_non_err, result, node);
6778 const condbr = try gz.addCondBr(.condbr, node);6942 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...@@ -6781,8 +6945,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6781 defer then_scope.unstack();6945 defer then_scope.unstack();
67826946
6783 try genDefers(&then_scope, defer_outer, scope, .normal_only);6947 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
6784 try emitDbgStmt(&then_scope, ret_line, ret_column);6952 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
6787 var else_scope = gz.makeSubBlock(scope);6955 var else_scope = gz.makeSubBlock(scope);
6788 defer else_scope.unstack();6956 defer else_scope.unstack();
...@@ -6792,7 +6960,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6792,7 +6960,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6792 };6960 };
6793 try genDefers(&else_scope, defer_outer, scope, which_ones);6961 try genDefers(&else_scope, defer_outer, scope, which_ones);
6794 try emitDbgStmt(&else_scope, ret_line, ret_column);6962 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
6797 try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0);6965 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 {...@@ -6825,7 +6993,7 @@ fn parseBitCount(buf: []const u8) std.fmt.ParseIntError!u16 {
6825fn identifier(6993fn identifier(
6826 gz: *GenZir,6994 gz: *GenZir,
6827 scope: *Scope,6995 scope: *Scope,
6828 rl: ResultLoc,6996 ri: ResultInfo,
6829 ident: Ast.Node.Index,6997 ident: Ast.Node.Index,
6830) InnerError!Zir.Inst.Ref {6998) InnerError!Zir.Inst.Ref {
6831 const tracy = trace(@src());6999 const tracy = trace(@src());
...@@ -6844,7 +7012,7 @@ fn identifier(...@@ -6844,7 +7012,7 @@ fn identifier(
6844 // if not @"" syntax, just use raw token slice7012 // if not @"" syntax, just use raw token slice
6845 if (ident_name_raw[0] != '@') {7013 if (ident_name_raw[0] != '@') {
6846 if (primitives.get(ident_name_raw)) |zir_const_ref| {7014 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);
6848 }7016 }
68497017
6850 if (ident_name_raw.len >= 2) integer: {7018 if (ident_name_raw.len >= 2) integer: {
...@@ -6877,19 +7045,19 @@ fn identifier(...@@ -6877,19 +7045,19 @@ fn identifier(
6877 .bit_count = bit_count,7045 .bit_count = bit_count,
6878 } },7046 } },
6879 });7047 });
6880 return rvalue(gz, rl, result, ident);7048 return rvalue(gz, ri, result, ident);
6881 }7049 }
6882 }7050 }
6883 }7051 }
68847052
6885 // Local variables, including function parameters.7053 // Local variables, including function parameters.
6886 return localVarRef(gz, scope, rl, ident, ident_token);7054 return localVarRef(gz, scope, ri, ident, ident_token);
6887}7055}
68887056
6889fn localVarRef(7057fn localVarRef(
6890 gz: *GenZir,7058 gz: *GenZir,
6891 scope: *Scope,7059 scope: *Scope,
6892 rl: ResultLoc,7060 ri: ResultInfo,
6893 ident: Ast.Node.Index,7061 ident: Ast.Node.Index,
6894 ident_token: Ast.TokenIndex,7062 ident_token: Ast.TokenIndex,
6895) InnerError!Zir.Inst.Ref {7063) InnerError!Zir.Inst.Ref {
...@@ -6907,7 +7075,7 @@ fn localVarRef(...@@ -6907,7 +7075,7 @@ fn localVarRef(
6907 if (local_val.name == name_str_index) {7075 if (local_val.name == name_str_index) {
6908 // Locals cannot shadow anything, so we do not need to look for ambiguous7076 // Locals cannot shadow anything, so we do not need to look for ambiguous
6909 // references in this case.7077 // references in this case.
6910 if (rl == .discard) {7078 if (ri.rl == .discard) {
6911 local_val.discarded = ident_token;7079 local_val.discarded = ident_token;
6912 } else {7080 } else {
6913 local_val.used = ident_token;7081 local_val.used = ident_token;
...@@ -6923,14 +7091,14 @@ fn localVarRef(...@@ -6923,14 +7091,14 @@ fn localVarRef(
6923 gpa,7091 gpa,
6924 );7092 );
69257093
6926 return rvalue(gz, rl, value_inst, ident);7094 return rvalue(gz, ri, value_inst, ident);
6927 }7095 }
6928 s = local_val.parent;7096 s = local_val.parent;
6929 },7097 },
6930 .local_ptr => {7098 .local_ptr => {
6931 const local_ptr = s.cast(Scope.LocalPtr).?;7099 const local_ptr = s.cast(Scope.LocalPtr).?;
6932 if (local_ptr.name == name_str_index) {7100 if (local_ptr.name == name_str_index) {
6933 if (rl == .discard) {7101 if (ri.rl == .discard) {
6934 local_ptr.discarded = ident_token;7102 local_ptr.discarded = ident_token;
6935 } else {7103 } else {
6936 local_ptr.used = ident_token;7104 local_ptr.used = ident_token;
...@@ -6955,11 +7123,11 @@ fn localVarRef(...@@ -6955,11 +7123,11 @@ fn localVarRef(
6955 gpa,7123 gpa,
6956 );7124 );
69577125
6958 switch (rl) {7126 switch (ri.rl) {
6959 .ref => return ptr_inst,7127 .ref => return ptr_inst,
6960 else => {7128 else => {
6961 const loaded = try gz.addUnNode(.load, ptr_inst, ident);7129 const loaded = try gz.addUnNode(.load, ptr_inst, ident);
6962 return rvalue(gz, rl, loaded, ident);7130 return rvalue(gz, ri, loaded, ident);
6963 },7131 },
6964 }7132 }
6965 }7133 }
...@@ -6992,11 +7160,11 @@ fn localVarRef(...@@ -6992,11 +7160,11 @@ fn localVarRef(
69927160
6993 // Decl references happen by name rather than ZIR index so that when unrelated7161 // Decl references happen by name rather than ZIR index so that when unrelated
6994 // decls are modified, ZIR code containing references to them can be unmodified.7162 // decls are modified, ZIR code containing references to them can be unmodified.
6995 switch (rl) {7163 switch (ri.rl) {
6996 .ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token),7164 .ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token),
6997 else => {7165 else => {
6998 const result = try gz.addStrTok(.decl_val, name_str_index, ident_token);7166 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);
7000 },7168 },
7001 }7169 }
7002}7170}
...@@ -7040,7 +7208,7 @@ fn tunnelThroughClosure(...@@ -7040,7 +7208,7 @@ fn tunnelThroughClosure(
70407208
7041fn stringLiteral(7209fn stringLiteral(
7042 gz: *GenZir,7210 gz: *GenZir,
7043 rl: ResultLoc,7211 ri: ResultInfo,
7044 node: Ast.Node.Index,7212 node: Ast.Node.Index,
7045) InnerError!Zir.Inst.Ref {7213) InnerError!Zir.Inst.Ref {
7046 const astgen = gz.astgen;7214 const astgen = gz.astgen;
...@@ -7055,12 +7223,12 @@ fn stringLiteral(...@@ -7055,12 +7223,12 @@ fn stringLiteral(
7055 .len = str.len,7223 .len = str.len,
7056 } },7224 } },
7057 });7225 });
7058 return rvalue(gz, rl, result, node);7226 return rvalue(gz, ri, result, node);
7059}7227}
70607228
7061fn multilineStringLiteral(7229fn multilineStringLiteral(
7062 gz: *GenZir,7230 gz: *GenZir,
7063 rl: ResultLoc,7231 ri: ResultInfo,
7064 node: Ast.Node.Index,7232 node: Ast.Node.Index,
7065) InnerError!Zir.Inst.Ref {7233) InnerError!Zir.Inst.Ref {
7066 const astgen = gz.astgen;7234 const astgen = gz.astgen;
...@@ -7072,10 +7240,10 @@ fn multilineStringLiteral(...@@ -7072,10 +7240,10 @@ fn multilineStringLiteral(
7072 .len = str.len,7240 .len = str.len,
7073 } },7241 } },
7074 });7242 });
7075 return rvalue(gz, rl, result, node);7243 return rvalue(gz, ri, result, node);
7076}7244}
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 {
7079 const astgen = gz.astgen;7247 const astgen = gz.astgen;
7080 const tree = astgen.tree;7248 const tree = astgen.tree;
7081 const main_tokens = tree.nodes.items(.main_token);7249 const main_tokens = tree.nodes.items(.main_token);
...@@ -7085,7 +7253,7 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir....@@ -7085,7 +7253,7 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.
7085 switch (std.zig.parseCharLiteral(slice)) {7253 switch (std.zig.parseCharLiteral(slice)) {
7086 .success => |codepoint| {7254 .success => |codepoint| {
7087 const result = try gz.addInt(codepoint);7255 const result = try gz.addInt(codepoint);
7088 return rvalue(gz, rl, result, node);7256 return rvalue(gz, ri, result, node);
7089 },7257 },
7090 .failure => |err| return astgen.failWithStrLitError(err, main_token, slice, 0),7258 .failure => |err| return astgen.failWithStrLitError(err, main_token, slice, 0),
7091 }7259 }
...@@ -7093,7 +7261,7 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir....@@ -7093,7 +7261,7 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.
70937261
7094const Sign = enum { negative, positive };7262const 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 {
7097 const astgen = gz.astgen;7265 const astgen = gz.astgen;
7098 const tree = astgen.tree;7266 const tree = astgen.tree;
7099 const main_tokens = tree.nodes.items(.main_token);7267 const main_tokens = tree.nodes.items(.main_token);
...@@ -7135,7 +7303,7 @@ fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node:...@@ -7135,7 +7303,7 @@ fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node:
7135 const bigger_again: f128 = smaller_float;7303 const bigger_again: f128 = smaller_float;
7136 if (bigger_again == float_number) {7304 if (bigger_again == float_number) {
7137 const result = try gz.addFloat(smaller_float);7305 const result = try gz.addFloat(smaller_float);
7138 return rvalue(gz, rl, result, source_node);7306 return rvalue(gz, ri, result, source_node);
7139 }7307 }
7140 // We need to use 128 bits. Break the float into 4 u32 values so we can7308 // We need to use 128 bits. Break the float into 4 u32 values so we can
7141 // put it into the `extra` array.7309 // put it into the `extra` array.
...@@ -7146,16 +7314,16 @@ fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node:...@@ -7146,16 +7314,16 @@ fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node:
7146 .piece2 = @truncate(u32, int_bits >> 64),7314 .piece2 = @truncate(u32, int_bits >> 64),
7147 .piece3 = @truncate(u32, int_bits >> 96),7315 .piece3 = @truncate(u32, int_bits >> 96),
7148 });7316 });
7149 return rvalue(gz, rl, result, source_node);7317 return rvalue(gz, ri, result, source_node);
7150 },7318 },
7151 .failure => |err| return astgen.failWithNumberError(err, num_token, bytes),7319 .failure => |err| return astgen.failWithNumberError(err, num_token, bytes),
7152 };7320 };
71537321
7154 if (sign == .positive) {7322 if (sign == .positive) {
7155 return rvalue(gz, rl, result, source_node);7323 return rvalue(gz, ri, result, source_node);
7156 } else {7324 } else {
7157 const negated = try gz.addUnNode(.negate, result, source_node);7325 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);
7159 }7327 }
7160}7328}
71617329
...@@ -7191,7 +7359,7 @@ fn failWithNumberError(astgen: *AstGen, err: std.zig.number_literal.Error, token...@@ -7191,7 +7359,7 @@ fn failWithNumberError(astgen: *AstGen, err: std.zig.number_literal.Error, token
7191fn asmExpr(7359fn asmExpr(
7192 gz: *GenZir,7360 gz: *GenZir,
7193 scope: *Scope,7361 scope: *Scope,
7194 rl: ResultLoc,7362 ri: ResultInfo,
7195 node: Ast.Node.Index,7363 node: Ast.Node.Index,
7196 full: Ast.full.Asm,7364 full: Ast.full.Asm,
7197) InnerError!Zir.Inst.Ref {7365) InnerError!Zir.Inst.Ref {
...@@ -7214,7 +7382,7 @@ fn asmExpr(...@@ -7214,7 +7382,7 @@ fn asmExpr(
7214 },7382 },
7215 else => .{7383 else => .{
7216 .tag = .asm_expr,7384 .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)),
7218 },7386 },
7219 };7387 };
72207388
...@@ -7266,7 +7434,7 @@ fn asmExpr(...@@ -7266,7 +7434,7 @@ fn asmExpr(
7266 outputs[i] = .{7434 outputs[i] = .{
7267 .name = name,7435 .name = name,
7268 .constraint = constraint,7436 .constraint = constraint,
7269 .operand = try localVarRef(gz, scope, .ref, node, ident_token),7437 .operand = try localVarRef(gz, scope, .{ .rl = .ref }, node, ident_token),
7270 };7438 };
7271 }7439 }
7272 }7440 }
...@@ -7282,7 +7450,7 @@ fn asmExpr(...@@ -7282,7 +7450,7 @@ fn asmExpr(
7282 const name = try astgen.identAsString(symbolic_name);7450 const name = try astgen.identAsString(symbolic_name);
7283 const constraint_token = symbolic_name + 2;7451 const constraint_token = symbolic_name + 2;
7284 const constraint = (try astgen.strLitAsString(constraint_token)).index;7452 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);
7286 inputs[i] = .{7454 inputs[i] = .{
7287 .name = name,7455 .name = name,
7288 .constraint = constraint,7456 .constraint = constraint,
...@@ -7327,31 +7495,31 @@ fn asmExpr(...@@ -7327,31 +7495,31 @@ fn asmExpr(
7327 .inputs = inputs,7495 .inputs = inputs,
7328 .clobbers = clobbers_buffer[0..clobber_i],7496 .clobbers = clobbers_buffer[0..clobber_i],
7329 });7497 });
7330 return rvalue(gz, rl, result, node);7498 return rvalue(gz, ri, result, node);
7331}7499}
73327500
7333fn as(7501fn as(
7334 gz: *GenZir,7502 gz: *GenZir,
7335 scope: *Scope,7503 scope: *Scope,
7336 rl: ResultLoc,7504 ri: ResultInfo,
7337 node: Ast.Node.Index,7505 node: Ast.Node.Index,
7338 lhs: Ast.Node.Index,7506 lhs: Ast.Node.Index,
7339 rhs: Ast.Node.Index,7507 rhs: Ast.Node.Index,
7340) InnerError!Zir.Inst.Ref {7508) InnerError!Zir.Inst.Ref {
7341 const dest_type = try typeExpr(gz, scope, lhs);7509 const dest_type = try typeExpr(gz, scope, lhs);
7342 switch (rl) {7510 switch (ri.rl) {
7343 .none, .discard, .ref, .ty, .ty_shift_operand, .coerced_ty => {7511 .none, .discard, .ref, .ty, .coerced_ty => {
7344 const result = try reachableExpr(gz, scope, .{ .ty = dest_type }, rhs, node);7512 const result = try reachableExpr(gz, scope, .{ .rl = .{ .ty = dest_type } }, rhs, node);
7345 return rvalue(gz, rl, result, node);7513 return rvalue(gz, ri, result, node);
7346 },7514 },
7347 .ptr => |result_ptr| {7515 .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);
7349 },7517 },
7350 .inferred_ptr => |result_ptr| {7518 .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);
7352 },7520 },
7353 .block_ptr => |block_scope| {7521 .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);
7355 },7523 },
7356 }7524 }
7357}7525}
...@@ -7359,29 +7527,29 @@ fn as(...@@ -7359,29 +7527,29 @@ fn as(
7359fn unionInit(7527fn unionInit(
7360 gz: *GenZir,7528 gz: *GenZir,
7361 scope: *Scope,7529 scope: *Scope,
7362 rl: ResultLoc,7530 ri: ResultInfo,
7363 node: Ast.Node.Index,7531 node: Ast.Node.Index,
7364 params: []const Ast.Node.Index,7532 params: []const Ast.Node.Index,
7365) InnerError!Zir.Inst.Ref {7533) InnerError!Zir.Inst.Ref {
7366 const union_type = try typeExpr(gz, scope, params[0]);7534 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]);
7368 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{7536 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{
7369 .container_type = union_type,7537 .container_type = union_type,
7370 .field_name = field_name,7538 .field_name = field_name,
7371 });7539 });
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);
7373 const result = try gz.addPlNode(.union_init, node, Zir.Inst.UnionInit{7541 const result = try gz.addPlNode(.union_init, node, Zir.Inst.UnionInit{
7374 .union_type = union_type,7542 .union_type = union_type,
7375 .init = init,7543 .init = init,
7376 .field_name = field_name,7544 .field_name = field_name,
7377 });7545 });
7378 return rvalue(gz, rl, result, node);7546 return rvalue(gz, ri, result, node);
7379}7547}
73807548
7381fn asRlPtr(7549fn asRlPtr(
7382 parent_gz: *GenZir,7550 parent_gz: *GenZir,
7383 scope: *Scope,7551 scope: *Scope,
7384 rl: ResultLoc,7552 ri: ResultInfo,
7385 src_node: Ast.Node.Index,7553 src_node: Ast.Node.Index,
7386 result_ptr: Zir.Inst.Ref,7554 result_ptr: Zir.Inst.Ref,
7387 operand_node: Ast.Node.Index,7555 operand_node: Ast.Node.Index,
...@@ -7390,31 +7558,31 @@ fn asRlPtr(...@@ -7390,31 +7558,31 @@ fn asRlPtr(
7390 var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr, src_node);7558 var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr, src_node);
7391 defer as_scope.unstack();7559 defer as_scope.unstack();
73927560
7393 const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node);7561 const result = try reachableExpr(&as_scope, &as_scope.base, .{ .rl = .{ .block_ptr = &as_scope } }, operand_node, src_node);
7394 return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type);7562 return as_scope.finishCoercion(parent_gz, ri, operand_node, result, dest_type);
7395}7563}
73967564
7397fn bitCast(7565fn bitCast(
7398 gz: *GenZir,7566 gz: *GenZir,
7399 scope: *Scope,7567 scope: *Scope,
7400 rl: ResultLoc,7568 ri: ResultInfo,
7401 node: Ast.Node.Index,7569 node: Ast.Node.Index,
7402 lhs: Ast.Node.Index,7570 lhs: Ast.Node.Index,
7403 rhs: Ast.Node.Index,7571 rhs: Ast.Node.Index,
7404) InnerError!Zir.Inst.Ref {7572) InnerError!Zir.Inst.Ref {
7405 const dest_type = try reachableTypeExpr(gz, scope, lhs, node);7573 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);
7407 const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{7575 const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{
7408 .lhs = dest_type,7576 .lhs = dest_type,
7409 .rhs = operand,7577 .rhs = operand,
7410 });7578 });
7411 return rvalue(gz, rl, result, node);7579 return rvalue(gz, ri, result, node);
7412}7580}
74137581
7414fn typeOf(7582fn typeOf(
7415 gz: *GenZir,7583 gz: *GenZir,
7416 scope: *Scope,7584 scope: *Scope,
7417 rl: ResultLoc,7585 ri: ResultInfo,
7418 node: Ast.Node.Index,7586 node: Ast.Node.Index,
7419 args: []const Ast.Node.Index,7587 args: []const Ast.Node.Index,
7420) InnerError!Zir.Inst.Ref {7588) InnerError!Zir.Inst.Ref {
...@@ -7430,7 +7598,7 @@ fn typeOf(...@@ -7430,7 +7598,7 @@ fn typeOf(
7430 typeof_scope.force_comptime = false;7598 typeof_scope.force_comptime = false;
7431 defer typeof_scope.unstack();7599 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);
7434 if (!gz.refIsNoReturn(ty_expr)) {7602 if (!gz.refIsNoReturn(ty_expr)) {
7435 _ = try typeof_scope.addBreak(.break_inline, typeof_inst, ty_expr);7603 _ = try typeof_scope.addBreak(.break_inline, typeof_inst, ty_expr);
7436 }7604 }
...@@ -7438,7 +7606,7 @@ fn typeOf(...@@ -7438,7 +7606,7 @@ fn typeOf(
74387606
7439 // typeof_scope unstacked now, can add new instructions to gz7607 // typeof_scope unstacked now, can add new instructions to gz
7440 try gz.instructions.append(gpa, typeof_inst);7608 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);
7442 }7610 }
7443 const payload_size: u32 = std.meta.fields(Zir.Inst.TypeOfPeer).len;7611 const payload_size: u32 = std.meta.fields(Zir.Inst.TypeOfPeer).len;
7444 const payload_index = try reserveExtra(astgen, payload_size + args.len);7612 const payload_index = try reserveExtra(astgen, payload_size + args.len);
...@@ -7450,7 +7618,7 @@ fn typeOf(...@@ -7450,7 +7618,7 @@ fn typeOf(
7450 typeof_scope.force_comptime = false;7618 typeof_scope.force_comptime = false;
74517619
7452 for (args) |arg, i| {7620 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);
7454 astgen.extra.items[args_index + i] = @enumToInt(param_ref);7622 astgen.extra.items[args_index + i] = @enumToInt(param_ref);
7455 }7623 }
7456 _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value);7624 _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value);
...@@ -7466,13 +7634,13 @@ fn typeOf(...@@ -7466,13 +7634,13 @@ fn typeOf(
7466 astgen.appendBodyWithFixups(body);7634 astgen.appendBodyWithFixups(body);
7467 typeof_scope.unstack();7635 typeof_scope.unstack();
74687636
7469 return rvalue(gz, rl, typeof_inst, node);7637 return rvalue(gz, ri, typeof_inst, node);
7470}7638}
74717639
7472fn builtinCall(7640fn builtinCall(
7473 gz: *GenZir,7641 gz: *GenZir,
7474 scope: *Scope,7642 scope: *Scope,
7475 rl: ResultLoc,7643 ri: ResultInfo,
7476 node: Ast.Node.Index,7644 node: Ast.Node.Index,
7477 params: []const Ast.Node.Index,7645 params: []const Ast.Node.Index,
7478) InnerError!Zir.Inst.Ref {7646) InnerError!Zir.Inst.Ref {
...@@ -7524,7 +7692,7 @@ fn builtinCall(...@@ -7524,7 +7692,7 @@ fn builtinCall(
7524 if (!gop.found_existing) {7692 if (!gop.found_existing) {
7525 gop.value_ptr.* = str_lit_token;7693 gop.value_ptr.* = str_lit_token;
7526 }7694 }
7527 return rvalue(gz, rl, result, node);7695 return rvalue(gz, ri, result, node);
7528 },7696 },
7529 .compile_log => {7697 .compile_log => {
7530 const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{7698 const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{
...@@ -7532,32 +7700,32 @@ fn builtinCall(...@@ -7532,32 +7700,32 @@ fn builtinCall(
7532 });7700 });
7533 var extra_index = try reserveExtra(gz.astgen, params.len);7701 var extra_index = try reserveExtra(gz.astgen, params.len);
7534 for (params) |param| {7702 for (params) |param| {
7535 const param_ref = try expr(gz, scope, .none, param);7703 const param_ref = try expr(gz, scope, .{ .rl = .none }, param);
7536 astgen.extra.items[extra_index] = @enumToInt(param_ref);7704 astgen.extra.items[extra_index] = @enumToInt(param_ref);
7537 extra_index += 1;7705 extra_index += 1;
7538 }7706 }
7539 const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log, payload_index, params.len);7707 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);
7541 },7709 },
7542 .field => {7710 .field => {
7543 if (rl == .ref) {7711 if (ri.rl == .ref) {
7544 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{7712 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
7545 .lhs = try expr(gz, scope, .ref, params[0]),7713 .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),
7546 .field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]),7714 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]),
7547 });7715 });
7548 }7716 }
7549 const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{7717 const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
7550 .lhs = try expr(gz, scope, .none, params[0]),7718 .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
7551 .field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]),7719 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]),
7552 });7720 });
7553 return rvalue(gz, rl, result, node);7721 return rvalue(gz, ri, result, node);
7554 },7722 },
75557723
7556 // zig fmt: off7724 // zig fmt: off
7557 .as => return as( gz, scope, rl, node, params[0], params[1]),7725 .as => return as( gz, scope, ri, node, params[0], params[1]),
7558 .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]),7726 .bit_cast => return bitCast( gz, scope, ri, node, params[0], params[1]),
7559 .TypeOf => return typeOf( gz, scope, rl, node, params),7727 .TypeOf => return typeOf( gz, scope, ri, node, params),
7560 .union_init => return unionInit(gz, scope, rl, node, params),7728 .union_init => return unionInit(gz, scope, ri, node, params),
7561 .c_import => return cImport( gz, scope, node, params[0]),7729 .c_import => return cImport( gz, scope, node, params[0]),
7562 // zig fmt: on7730 // zig fmt: on
75637731
...@@ -7582,9 +7750,9 @@ fn builtinCall(...@@ -7582,9 +7750,9 @@ fn builtinCall(
7582 local_val.used = ident_token;7750 local_val.used = ident_token;
7583 _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{7751 _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{
7584 .operand = local_val.inst,7752 .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]),
7586 });7754 });
7587 return rvalue(gz, rl, .void_value, node);7755 return rvalue(gz, ri, .void_value, node);
7588 }7756 }
7589 s = local_val.parent;7757 s = local_val.parent;
7590 },7758 },
...@@ -7597,9 +7765,9 @@ fn builtinCall(...@@ -7597,9 +7765,9 @@ fn builtinCall(
7597 const loaded = try gz.addUnNode(.load, local_ptr.ptr, node);7765 const loaded = try gz.addUnNode(.load, local_ptr.ptr, node);
7598 _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{7766 _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{
7599 .operand = loaded,7767 .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]),
7601 });7769 });
7602 return rvalue(gz, rl, .void_value, node);7770 return rvalue(gz, ri, .void_value, node);
7603 }7771 }
7604 s = local_ptr.parent;7772 s = local_ptr.parent;
7605 },7773 },
...@@ -7631,47 +7799,47 @@ fn builtinCall(...@@ -7631,47 +7799,47 @@ fn builtinCall(
7631 },7799 },
7632 else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}),7800 else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}),
7633 }7801 }
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]);
7635 _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{7803 _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{
7636 .namespace = namespace,7804 .namespace = namespace,
7637 .decl_name = decl_name,7805 .decl_name = decl_name,
7638 .options = options,7806 .options = options,
7639 });7807 });
7640 return rvalue(gz, rl, .void_value, node);7808 return rvalue(gz, ri, .void_value, node);
7641 },7809 },
7642 .@"extern" => {7810 .@"extern" => {
7643 const type_inst = try typeExpr(gz, scope, params[0]);7811 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]);
7645 const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{7813 const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{
7646 .node = gz.nodeIndexToRelative(node),7814 .node = gz.nodeIndexToRelative(node),
7647 .lhs = type_inst,7815 .lhs = type_inst,
7648 .rhs = options,7816 .rhs = options,
7649 });7817 });
7650 return rvalue(gz, rl, result, node);7818 return rvalue(gz, ri, result, node);
7651 },7819 },
7652 .fence => {7820 .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]);
7654 const result = try gz.addExtendedPayload(.fence, Zir.Inst.UnNode{7822 const result = try gz.addExtendedPayload(.fence, Zir.Inst.UnNode{
7655 .node = gz.nodeIndexToRelative(node),7823 .node = gz.nodeIndexToRelative(node),
7656 .operand = order,7824 .operand = order,
7657 });7825 });
7658 return rvalue(gz, rl, result, node);7826 return rvalue(gz, ri, result, node);
7659 },7827 },
7660 .set_float_mode => {7828 .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]);
7662 const result = try gz.addExtendedPayload(.set_float_mode, Zir.Inst.UnNode{7830 const result = try gz.addExtendedPayload(.set_float_mode, Zir.Inst.UnNode{
7663 .node = gz.nodeIndexToRelative(node),7831 .node = gz.nodeIndexToRelative(node),
7664 .operand = order,7832 .operand = order,
7665 });7833 });
7666 return rvalue(gz, rl, result, node);7834 return rvalue(gz, ri, result, node);
7667 },7835 },
7668 .set_align_stack => {7836 .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]);
7670 const result = try gz.addExtendedPayload(.set_align_stack, Zir.Inst.UnNode{7838 const result = try gz.addExtendedPayload(.set_align_stack, Zir.Inst.UnNode{
7671 .node = gz.nodeIndexToRelative(node),7839 .node = gz.nodeIndexToRelative(node),
7672 .operand = order,7840 .operand = order,
7673 });7841 });
7674 return rvalue(gz, rl, result, node);7842 return rvalue(gz, ri, result, node);
7675 },7843 },
76767844
7677 .src => {7845 .src => {
...@@ -7683,62 +7851,62 @@ fn builtinCall(...@@ -7683,62 +7851,62 @@ fn builtinCall(
7683 .line = astgen.source_line,7851 .line = astgen.source_line,
7684 .column = astgen.source_column,7852 .column = astgen.source_column,
7685 });7853 });
7686 return rvalue(gz, rl, result, node);7854 return rvalue(gz, ri, result, node);
7687 },7855 },
76887856
7689 // zig fmt: off7857 // zig fmt: off
7690 .This => return rvalue(gz, rl, try gz.addNodeExtended(.this, node), node),7858 .This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node),
7691 .return_address => return rvalue(gz, rl, try gz.addNodeExtended(.ret_addr, node), node),7859 .return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node),
7692 .error_return_trace => return rvalue(gz, rl, try gz.addNodeExtended(.error_return_trace, node), node),7860 .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node),
7693 .frame => return rvalue(gz, rl, try gz.addNodeExtended(.frame, node), node),7861 .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node),
7694 .frame_address => return rvalue(gz, rl, try gz.addNodeExtended(.frame_address, node), node),7862 .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node),
7695 .breakpoint => return rvalue(gz, rl, try gz.addNodeExtended(.breakpoint, node), node),7863 .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node),
76967864
7697 .type_info => return simpleUnOpType(gz, scope, rl, node, params[0], .type_info),7865 .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info),
7698 .size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .size_of),7866 .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of),
7699 .bit_size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .bit_size_of),7867 .bit_size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .bit_size_of),
7700 .align_of => return simpleUnOpType(gz, scope, rl, node, params[0], .align_of),7868 .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of),
77017869
7702 .ptr_to_int => return simpleUnOp(gz, scope, rl, node, .none, params[0], .ptr_to_int),7870 .ptr_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ptr_to_int),
7703 .compile_error => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .compile_error),7871 .compile_error => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .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),7872 .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .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),7873 .enum_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .enum_to_int),
7706 .bool_to_int => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .bool_to_int),7874 .bool_to_int => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .bool_to_int),
7707 .embed_file => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .embed_file),7875 .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .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),7876 .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name),
7709 .set_cold => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_cold),7877 .set_cold => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_cold),
7710 .set_runtime_safety => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_runtime_safety),7878 .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety),
7711 .sqrt => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sqrt),7879 .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt),
7712 .sin => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sin),7880 .sin => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sin),
7713 .cos => return simpleUnOp(gz, scope, rl, node, .none, params[0], .cos),7881 .cos => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .cos),
7714 .tan => return simpleUnOp(gz, scope, rl, node, .none, params[0], .tan),7882 .tan => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tan),
7715 .exp => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp),7883 .exp => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp),
7716 .exp2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp2),7884 .exp2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp2),
7717 .log => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log),7885 .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log),
7718 .log2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log2),7886 .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2),
7719 .log10 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log10),7887 .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10),
7720 .fabs => return simpleUnOp(gz, scope, rl, node, .none, params[0], .fabs),7888 .fabs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .fabs),
7721 .floor => return simpleUnOp(gz, scope, rl, node, .none, params[0], .floor),7889 .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor),
7722 .ceil => return simpleUnOp(gz, scope, rl, node, .none, params[0], .ceil),7890 .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil),
7723 .trunc => return simpleUnOp(gz, scope, rl, node, .none, params[0], .trunc),7891 .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc),
7724 .round => return simpleUnOp(gz, scope, rl, node, .none, params[0], .round),7892 .round => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .round),
7725 .tag_name => return simpleUnOp(gz, scope, rl, node, .none, params[0], .tag_name),7893 .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name),
7726 .type_name => return simpleUnOp(gz, scope, rl, node, .none, params[0], .type_name),7894 .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name),
7727 .Frame => return simpleUnOp(gz, scope, rl, node, .none, params[0], .frame_type),7895 .Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type),
7728 .frame_size => return simpleUnOp(gz, scope, rl, node, .none, params[0], .frame_size),7896 .frame_size => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_size),
77297897
7730 .float_to_int => return typeCast(gz, scope, rl, node, params[0], params[1], .float_to_int),7898 .float_to_int => return typeCast(gz, scope, ri, 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),7899 .int_to_float => return typeCast(gz, scope, ri, 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),7900 .int_to_ptr => return typeCast(gz, scope, ri, 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),7901 .int_to_enum => return typeCast(gz, scope, ri, node, params[0], params[1], .int_to_enum),
7734 .float_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .float_cast),7902 .float_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .float_cast),
7735 .int_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .int_cast),7903 .int_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .int_cast),
7736 .ptr_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .ptr_cast),7904 .ptr_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .ptr_cast),
7737 .truncate => return typeCast(gz, scope, rl, node, params[0], params[1], .truncate),7905 .truncate => return typeCast(gz, scope, ri, node, params[0], params[1], .truncate),
7738 // zig fmt: on7906 // zig fmt: on
77397907
7740 .Type => {7908 .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
7743 const gpa = gz.astgen.gpa;7911 const gpa = gz.astgen.gpa;
77447912
...@@ -7760,219 +7928,219 @@ fn builtinCall(...@@ -7760,219 +7928,219 @@ fn builtinCall(
7760 });7928 });
7761 gz.instructions.appendAssumeCapacity(new_index);7929 gz.instructions.appendAssumeCapacity(new_index);
7762 const result = indexToRef(new_index);7930 const result = indexToRef(new_index);
7763 return rvalue(gz, rl, result, node);7931 return rvalue(gz, ri, result, node);
7764 },7932 },
7765 .panic => {7933 .panic => {
7766 try emitDbgNode(gz, node);7934 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);
7768 },7936 },
7769 .error_to_int => {7937 .error_to_int => {
7770 const operand = try expr(gz, scope, .none, params[0]);7938 const operand = try expr(gz, scope, .{ .rl = .none }, params[0]);
7771 const result = try gz.addExtendedPayload(.error_to_int, Zir.Inst.UnNode{7939 const result = try gz.addExtendedPayload(.error_to_int, Zir.Inst.UnNode{
7772 .node = gz.nodeIndexToRelative(node),7940 .node = gz.nodeIndexToRelative(node),
7773 .operand = operand,7941 .operand = operand,
7774 });7942 });
7775 return rvalue(gz, rl, result, node);7943 return rvalue(gz, ri, result, node);
7776 },7944 },
7777 .int_to_error => {7945 .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]);
7779 const result = try gz.addExtendedPayload(.int_to_error, Zir.Inst.UnNode{7947 const result = try gz.addExtendedPayload(.int_to_error, Zir.Inst.UnNode{
7780 .node = gz.nodeIndexToRelative(node),7948 .node = gz.nodeIndexToRelative(node),
7781 .operand = operand,7949 .operand = operand,
7782 });7950 });
7783 return rvalue(gz, rl, result, node);7951 return rvalue(gz, ri, result, node);
7784 },7952 },
7785 .align_cast => {7953 .align_cast => {
7786 const dest_align = try comptimeExpr(gz, scope, align_rl, params[0]);7954 const dest_align = try comptimeExpr(gz, scope, align_ri, params[0]);
7787 const rhs = try expr(gz, scope, .none, params[1]);7955 const rhs = try expr(gz, scope, .{ .rl = .none }, params[1]);
7788 const result = try gz.addPlNode(.align_cast, node, Zir.Inst.Bin{7956 const result = try gz.addPlNode(.align_cast, node, Zir.Inst.Bin{
7789 .lhs = dest_align,7957 .lhs = dest_align,
7790 .rhs = rhs,7958 .rhs = rhs,
7791 });7959 });
7792 return rvalue(gz, rl, result, node);7960 return rvalue(gz, ri, result, node);
7793 },7961 },
7794 .err_set_cast => {7962 .err_set_cast => {
7795 const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{7963 const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{
7796 .lhs = try typeExpr(gz, scope, params[0]),7964 .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]),
7798 .node = gz.nodeIndexToRelative(node),7966 .node = gz.nodeIndexToRelative(node),
7799 });7967 });
7800 return rvalue(gz, rl, result, node);7968 return rvalue(gz, ri, result, node);
7801 },7969 },
7802 .addrspace_cast => {7970 .addrspace_cast => {
7803 const result = try gz.addExtendedPayload(.addrspace_cast, Zir.Inst.BinNode{7971 const result = try gz.addExtendedPayload(.addrspace_cast, Zir.Inst.BinNode{
7804 .lhs = try comptimeExpr(gz, scope, .{ .ty = .address_space_type }, params[0]),7972 .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .address_space_type } }, params[0]),
7805 .rhs = try expr(gz, scope, .none, params[1]),7973 .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]),
7806 .node = gz.nodeIndexToRelative(node),7974 .node = gz.nodeIndexToRelative(node),
7807 });7975 });
7808 return rvalue(gz, rl, result, node);7976 return rvalue(gz, ri, result, node);
7809 },7977 },
78107978
7811 // zig fmt: off7979 // zig fmt: off
7812 .has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl),7980 .has_decl => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_decl),
7813 .has_field => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_field),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),7983 .clz => return bitBuiltin(gz, scope, ri, node, params[0], .clz),
7816 .ctz => return bitBuiltin(gz, scope, rl, node, params[0], .ctz),7984 .ctz => return bitBuiltin(gz, scope, ri, node, params[0], .ctz),
7817 .pop_count => return bitBuiltin(gz, scope, rl, node, params[0], .pop_count),7985 .pop_count => return bitBuiltin(gz, scope, ri, node, params[0], .pop_count),
7818 .byte_swap => return bitBuiltin(gz, scope, rl, node, params[0], .byte_swap),7986 .byte_swap => return bitBuiltin(gz, scope, ri, node, params[0], .byte_swap),
7819 .bit_reverse => return bitBuiltin(gz, scope, rl, node, params[0], .bit_reverse),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),7989 .div_exact => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_exact),
7822 .div_floor => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_floor),7990 .div_floor => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_floor),
7823 .div_trunc => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_trunc),7991 .div_trunc => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_trunc),
7824 .mod => return divBuiltin(gz, scope, rl, node, params[0], params[1], .mod),7992 .mod => return divBuiltin(gz, scope, ri, node, params[0], params[1], .mod),
7825 .rem => return divBuiltin(gz, scope, rl, node, params[0], params[1], .rem),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),7995 .shl_exact => return shiftOp(gz, scope, ri, node, params[0], params[1], .shl_exact),
7828 .shr_exact => return shiftOp(gz, scope, rl, node, params[0], params[1], .shr_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),7998 .bit_offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .bit_offset_of),
7831 .offset_of => return offsetOf(gz, scope, rl, node, params[0], params[1], .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),8001 .c_undef => return simpleCBuiltin(gz, scope, ri, node, params[0], .c_undef),
7834 .c_include => return simpleCBuiltin(gz, scope, rl, node, params[0], .c_include),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),8004 .cmpxchg_strong => return cmpxchg(gz, scope, ri, node, params, 1),
7837 .cmpxchg_weak => return cmpxchg(gz, scope, rl, node, params, 0),8005 .cmpxchg_weak => return cmpxchg(gz, scope, ri, node, params, 0),
7838 // zig fmt: on8006 // zig fmt: on
78398007
7840 .wasm_memory_size => {8008 .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]);
7842 const result = try gz.addExtendedPayload(.wasm_memory_size, Zir.Inst.UnNode{8010 const result = try gz.addExtendedPayload(.wasm_memory_size, Zir.Inst.UnNode{
7843 .node = gz.nodeIndexToRelative(node),8011 .node = gz.nodeIndexToRelative(node),
7844 .operand = operand,8012 .operand = operand,
7845 });8013 });
7846 return rvalue(gz, rl, result, node);8014 return rvalue(gz, ri, result, node);
7847 },8015 },
7848 .wasm_memory_grow => {8016 .wasm_memory_grow => {
7849 const index_arg = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]);8017 const index_arg = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
7850 const delta_arg = try expr(gz, scope, .{ .coerced_ty = .u32_type }, params[1]);8018 const delta_arg = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[1]);
7851 const result = try gz.addExtendedPayload(.wasm_memory_grow, Zir.Inst.BinNode{8019 const result = try gz.addExtendedPayload(.wasm_memory_grow, Zir.Inst.BinNode{
7852 .node = gz.nodeIndexToRelative(node),8020 .node = gz.nodeIndexToRelative(node),
7853 .lhs = index_arg,8021 .lhs = index_arg,
7854 .rhs = delta_arg,8022 .rhs = delta_arg,
7855 });8023 });
7856 return rvalue(gz, rl, result, node);8024 return rvalue(gz, ri, result, node);
7857 },8025 },
7858 .c_define => {8026 .c_define => {
7859 if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});8027 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]);8028 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0]);
7861 const value = try comptimeExpr(gz, scope, .none, params[1]);8029 const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
7862 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{8030 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
7863 .node = gz.nodeIndexToRelative(node),8031 .node = gz.nodeIndexToRelative(node),
7864 .lhs = name,8032 .lhs = name,
7865 .rhs = value,8033 .rhs = value,
7866 });8034 });
7867 return rvalue(gz, rl, result, node);8035 return rvalue(gz, ri, result, node);
7868 },8036 },
78698037
7870 .splat => {8038 .splat => {
7871 const len = try expr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]);8039 const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
7872 const scalar = try expr(gz, scope, .none, params[1]);8040 const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]);
7873 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{8041 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
7874 .lhs = len,8042 .lhs = len,
7875 .rhs = scalar,8043 .rhs = scalar,
7876 });8044 });
7877 return rvalue(gz, rl, result, node);8045 return rvalue(gz, ri, result, node);
7878 },8046 },
7879 .reduce => {8047 .reduce => {
7880 const op = try expr(gz, scope, .{ .ty = .reduce_op_type }, params[0]);8048 const op = try expr(gz, scope, .{ .rl = .{ .ty = .reduce_op_type } }, params[0]);
7881 const scalar = try expr(gz, scope, .none, params[1]);8049 const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]);
7882 const result = try gz.addPlNode(.reduce, node, Zir.Inst.Bin{8050 const result = try gz.addPlNode(.reduce, node, Zir.Inst.Bin{
7883 .lhs = op,8051 .lhs = op,
7884 .rhs = scalar,8052 .rhs = scalar,
7885 });8053 });
7886 return rvalue(gz, rl, result, node);8054 return rvalue(gz, ri, result, node);
7887 },8055 },
78888056
7889 .max => {8057 .max => {
7890 const a = try expr(gz, scope, .none, params[0]);8058 const a = try expr(gz, scope, .{ .rl = .none }, params[0]);
7891 const b = try expr(gz, scope, .none, params[1]);8059 const b = try expr(gz, scope, .{ .rl = .none }, params[1]);
7892 const result = try gz.addPlNode(.max, node, Zir.Inst.Bin{8060 const result = try gz.addPlNode(.max, node, Zir.Inst.Bin{
7893 .lhs = a,8061 .lhs = a,
7894 .rhs = b,8062 .rhs = b,
7895 });8063 });
7896 return rvalue(gz, rl, result, node);8064 return rvalue(gz, ri, result, node);
7897 },8065 },
7898 .min => {8066 .min => {
7899 const a = try expr(gz, scope, .none, params[0]);8067 const a = try expr(gz, scope, .{ .rl = .none }, params[0]);
7900 const b = try expr(gz, scope, .none, params[1]);8068 const b = try expr(gz, scope, .{ .rl = .none }, params[1]);
7901 const result = try gz.addPlNode(.min, node, Zir.Inst.Bin{8069 const result = try gz.addPlNode(.min, node, Zir.Inst.Bin{
7902 .lhs = a,8070 .lhs = a,
7903 .rhs = b,8071 .rhs = b,
7904 });8072 });
7905 return rvalue(gz, rl, result, node);8073 return rvalue(gz, ri, result, node);
7906 },8074 },
79078075
7908 .add_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .add_with_overflow),8076 .add_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .add_with_overflow),
7909 .sub_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .sub_with_overflow),8077 .sub_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .sub_with_overflow),
7910 .mul_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .mul_with_overflow),8078 .mul_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .mul_with_overflow),
7911 .shl_with_overflow => {8079 .shl_with_overflow => {
7912 const int_type = try typeExpr(gz, scope, params[0]);8080 const int_type = try typeExpr(gz, scope, params[0]);
7913 const log2_int_type = try gz.addUnNode(.log2_int_type, int_type, params[0]);8081 const log2_int_type = try gz.addUnNode(.log2_int_type, int_type, params[0]);
7914 const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);8082 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]);8083 const lhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[1]);
7916 const rhs = try expr(gz, scope, .{ .ty = log2_int_type }, params[2]);8084 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type } }, params[2]);
7917 const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);8085 const ptr = try expr(gz, scope, .{ .rl = .{ .ty = ptr_type } }, params[3]);
7918 const result = try gz.addExtendedPayload(.shl_with_overflow, Zir.Inst.OverflowArithmetic{8086 const result = try gz.addExtendedPayload(.shl_with_overflow, Zir.Inst.OverflowArithmetic{
7919 .node = gz.nodeIndexToRelative(node),8087 .node = gz.nodeIndexToRelative(node),
7920 .lhs = lhs,8088 .lhs = lhs,
7921 .rhs = rhs,8089 .rhs = rhs,
7922 .ptr = ptr,8090 .ptr = ptr,
7923 });8091 });
7924 return rvalue(gz, rl, result, node);8092 return rvalue(gz, ri, result, node);
7925 },8093 },
79268094
7927 .atomic_load => {8095 .atomic_load => {
7928 const result = try gz.addPlNode(.atomic_load, node, Zir.Inst.AtomicLoad{8096 const result = try gz.addPlNode(.atomic_load, node, Zir.Inst.AtomicLoad{
7929 // zig fmt: off8097 // zig fmt: off
7930 .elem_type = try typeExpr(gz, scope, params[0]),8098 .elem_type = try typeExpr(gz, scope, params[0]),
7931 .ptr = try expr (gz, scope, .none, params[1]),8099 .ptr = try expr (gz, scope, .{ .rl = .none }, params[1]),
7932 .ordering = try expr (gz, scope, .{ .coerced_ty = .atomic_order_type }, params[2]),8100 .ordering = try expr (gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[2]),
7933 // zig fmt: on8101 // zig fmt: on
7934 });8102 });
7935 return rvalue(gz, rl, result, node);8103 return rvalue(gz, ri, result, node);
7936 },8104 },
7937 .atomic_rmw => {8105 .atomic_rmw => {
7938 const int_type = try typeExpr(gz, scope, params[0]);8106 const int_type = try typeExpr(gz, scope, params[0]);
7939 const result = try gz.addPlNode(.atomic_rmw, node, Zir.Inst.AtomicRmw{8107 const result = try gz.addPlNode(.atomic_rmw, node, Zir.Inst.AtomicRmw{
7940 // zig fmt: off8108 // zig fmt: off
7941 .ptr = try expr(gz, scope, .none, params[1]),8109 .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
7942 .operation = try expr(gz, scope, .{ .coerced_ty = .atomic_rmw_op_type }, params[2]),8110 .operation = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_rmw_op_type } }, params[2]),
7943 .operand = try expr(gz, scope, .{ .ty = int_type }, params[3]),8111 .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[3]),
7944 .ordering = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[4]),8112 .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[4]),
7945 // zig fmt: on8113 // zig fmt: on
7946 });8114 });
7947 return rvalue(gz, rl, result, node);8115 return rvalue(gz, ri, result, node);
7948 },8116 },
7949 .atomic_store => {8117 .atomic_store => {
7950 const int_type = try typeExpr(gz, scope, params[0]);8118 const int_type = try typeExpr(gz, scope, params[0]);
7951 const result = try gz.addPlNode(.atomic_store, node, Zir.Inst.AtomicStore{8119 const result = try gz.addPlNode(.atomic_store, node, Zir.Inst.AtomicStore{
7952 // zig fmt: off8120 // zig fmt: off
7953 .ptr = try expr(gz, scope, .none, params[1]),8121 .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
7954 .operand = try expr(gz, scope, .{ .ty = int_type }, params[2]),8122 .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]),
7955 .ordering = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[3]),8123 .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[3]),
7956 // zig fmt: on8124 // zig fmt: on
7957 });8125 });
7958 return rvalue(gz, rl, result, node);8126 return rvalue(gz, ri, result, node);
7959 },8127 },
7960 .mul_add => {8128 .mul_add => {
7961 const float_type = try typeExpr(gz, scope, params[0]);8129 const float_type = try typeExpr(gz, scope, params[0]);
7962 const mulend1 = try expr(gz, scope, .{ .coerced_ty = float_type }, params[1]);8130 const mulend1 = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_type } }, params[1]);
7963 const mulend2 = try expr(gz, scope, .{ .coerced_ty = float_type }, params[2]);8131 const mulend2 = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_type } }, params[2]);
7964 const addend = try expr(gz, scope, .{ .ty = float_type }, params[3]);8132 const addend = try expr(gz, scope, .{ .rl = .{ .ty = float_type } }, params[3]);
7965 const result = try gz.addPlNode(.mul_add, node, Zir.Inst.MulAdd{8133 const result = try gz.addPlNode(.mul_add, node, Zir.Inst.MulAdd{
7966 .mulend1 = mulend1,8134 .mulend1 = mulend1,
7967 .mulend2 = mulend2,8135 .mulend2 = mulend2,
7968 .addend = addend,8136 .addend = addend,
7969 });8137 });
7970 return rvalue(gz, rl, result, node);8138 return rvalue(gz, ri, result, node);
7971 },8139 },
7972 .call => {8140 .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]);
7974 const callee = try calleeExpr(gz, scope, params[1]);8142 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]);
7976 const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{8144 const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{
7977 .options = options,8145 .options = options,
7978 .callee = callee,8146 .callee = callee,
...@@ -7983,115 +8151,115 @@ fn builtinCall(...@@ -7983,115 +8151,115 @@ fn builtinCall(
7983 .ensure_result_used = false,8151 .ensure_result_used = false,
7984 },8152 },
7985 });8153 });
7986 return rvalue(gz, rl, result, node);8154 return rvalue(gz, ri, result, node);
7987 },8155 },
7988 .field_parent_ptr => {8156 .field_parent_ptr => {
7989 const parent_type = try typeExpr(gz, scope, params[0]);8157 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]);
7991 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{8159 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{
7992 .parent_type = parent_type,8160 .parent_type = parent_type,
7993 .field_name = field_name,8161 .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]),
7995 });8163 });
7996 return rvalue(gz, rl, result, node);8164 return rvalue(gz, ri, result, node);
7997 },8165 },
7998 .memcpy => {8166 .memcpy => {
7999 const result = try gz.addPlNode(.memcpy, node, Zir.Inst.Memcpy{8167 const result = try gz.addPlNode(.memcpy, node, Zir.Inst.Memcpy{
8000 .dest = try expr(gz, scope, .{ .coerced_ty = .manyptr_u8_type }, params[0]),8168 .dest = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_u8_type } }, params[0]),
8001 .source = try expr(gz, scope, .{ .coerced_ty = .manyptr_const_u8_type }, params[1]),8169 .source = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_const_u8_type } }, params[1]),
8002 .byte_count = try expr(gz, scope, .{ .coerced_ty = .usize_type }, params[2]),8170 .byte_count = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, params[2]),
8003 });8171 });
8004 return rvalue(gz, rl, result, node);8172 return rvalue(gz, ri, result, node);
8005 },8173 },
8006 .memset => {8174 .memset => {
8007 const result = try gz.addPlNode(.memset, node, Zir.Inst.Memset{8175 const result = try gz.addPlNode(.memset, node, Zir.Inst.Memset{
8008 .dest = try expr(gz, scope, .{ .coerced_ty = .manyptr_u8_type }, params[0]),8176 .dest = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_u8_type } }, params[0]),
8009 .byte = try expr(gz, scope, .{ .coerced_ty = .u8_type }, params[1]),8177 .byte = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u8_type } }, params[1]),
8010 .byte_count = try expr(gz, scope, .{ .coerced_ty = .usize_type }, params[2]),8178 .byte_count = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, params[2]),
8011 });8179 });
8012 return rvalue(gz, rl, result, node);8180 return rvalue(gz, ri, result, node);
8013 },8181 },
8014 .shuffle => {8182 .shuffle => {
8015 const result = try gz.addPlNode(.shuffle, node, Zir.Inst.Shuffle{8183 const result = try gz.addPlNode(.shuffle, node, Zir.Inst.Shuffle{
8016 .elem_type = try typeExpr(gz, scope, params[0]),8184 .elem_type = try typeExpr(gz, scope, params[0]),
8017 .a = try expr(gz, scope, .none, params[1]),8185 .a = try expr(gz, scope, .{ .rl = .none }, params[1]),
8018 .b = try expr(gz, scope, .none, params[2]),8186 .b = try expr(gz, scope, .{ .rl = .none }, params[2]),
8019 .mask = try comptimeExpr(gz, scope, .none, params[3]),8187 .mask = try comptimeExpr(gz, scope, .{ .rl = .none }, params[3]),
8020 });8188 });
8021 return rvalue(gz, rl, result, node);8189 return rvalue(gz, ri, result, node);
8022 },8190 },
8023 .select => {8191 .select => {
8024 const result = try gz.addExtendedPayload(.select, Zir.Inst.Select{8192 const result = try gz.addExtendedPayload(.select, Zir.Inst.Select{
8025 .node = gz.nodeIndexToRelative(node),8193 .node = gz.nodeIndexToRelative(node),
8026 .elem_type = try typeExpr(gz, scope, params[0]),8194 .elem_type = try typeExpr(gz, scope, params[0]),
8027 .pred = try expr(gz, scope, .none, params[1]),8195 .pred = try expr(gz, scope, .{ .rl = .none }, params[1]),
8028 .a = try expr(gz, scope, .none, params[2]),8196 .a = try expr(gz, scope, .{ .rl = .none }, params[2]),
8029 .b = try expr(gz, scope, .none, params[3]),8197 .b = try expr(gz, scope, .{ .rl = .none }, params[3]),
8030 });8198 });
8031 return rvalue(gz, rl, result, node);8199 return rvalue(gz, ri, result, node);
8032 },8200 },
8033 .async_call => {8201 .async_call => {
8034 const result = try gz.addExtendedPayload(.builtin_async_call, Zir.Inst.AsyncCall{8202 const result = try gz.addExtendedPayload(.builtin_async_call, Zir.Inst.AsyncCall{
8035 .node = gz.nodeIndexToRelative(node),8203 .node = gz.nodeIndexToRelative(node),
8036 .frame_buffer = try expr(gz, scope, .none, params[0]),8204 .frame_buffer = try expr(gz, scope, .{ .rl = .none }, params[0]),
8037 .result_ptr = try expr(gz, scope, .none, params[1]),8205 .result_ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
8038 .fn_ptr = try expr(gz, scope, .none, params[2]),8206 .fn_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]),
8039 .args = try expr(gz, scope, .none, params[3]),8207 .args = try expr(gz, scope, .{ .rl = .none }, params[3]),
8040 });8208 });
8041 return rvalue(gz, rl, result, node);8209 return rvalue(gz, ri, result, node);
8042 },8210 },
8043 .Vector => {8211 .Vector => {
8044 const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{8212 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]),
8046 .rhs = try typeExpr(gz, scope, params[1]),8214 .rhs = try typeExpr(gz, scope, params[1]),
8047 });8215 });
8048 return rvalue(gz, rl, result, node);8216 return rvalue(gz, ri, result, node);
8049 },8217 },
8050 .prefetch => {8218 .prefetch => {
8051 const ptr = try expr(gz, scope, .none, params[0]);8219 const ptr = try expr(gz, scope, .{ .rl = .none }, params[0]);
8052 const options = try comptimeExpr(gz, scope, .{ .ty = .prefetch_options_type }, params[1]);8220 const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .prefetch_options_type } }, params[1]);
8053 const result = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{8221 const result = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{
8054 .node = gz.nodeIndexToRelative(node),8222 .node = gz.nodeIndexToRelative(node),
8055 .lhs = ptr,8223 .lhs = ptr,
8056 .rhs = options,8224 .rhs = options,
8057 });8225 });
8058 return rvalue(gz, rl, result, node);8226 return rvalue(gz, ri, result, node);
8059 },8227 },
8060 }8228 }
8061}8229}
80628230
8063fn simpleNoOpVoid(8231fn simpleNoOpVoid(
8064 gz: *GenZir,8232 gz: *GenZir,
8065 rl: ResultLoc,8233 ri: ResultInfo,
8066 node: Ast.Node.Index,8234 node: Ast.Node.Index,
8067 tag: Zir.Inst.Tag,8235 tag: Zir.Inst.Tag,
8068) InnerError!Zir.Inst.Ref {8236) InnerError!Zir.Inst.Ref {
8069 _ = try gz.addNode(tag, node);8237 _ = try gz.addNode(tag, node);
8070 return rvalue(gz, rl, .void_value, node);8238 return rvalue(gz, ri, .void_value, node);
8071}8239}
80728240
8073fn hasDeclOrField(8241fn hasDeclOrField(
8074 gz: *GenZir,8242 gz: *GenZir,
8075 scope: *Scope,8243 scope: *Scope,
8076 rl: ResultLoc,8244 ri: ResultInfo,
8077 node: Ast.Node.Index,8245 node: Ast.Node.Index,
8078 lhs_node: Ast.Node.Index,8246 lhs_node: Ast.Node.Index,
8079 rhs_node: Ast.Node.Index,8247 rhs_node: Ast.Node.Index,
8080 tag: Zir.Inst.Tag,8248 tag: Zir.Inst.Tag,
8081) InnerError!Zir.Inst.Ref {8249) InnerError!Zir.Inst.Ref {
8082 const container_type = try typeExpr(gz, scope, lhs_node);8250 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);
8084 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8252 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8085 .lhs = container_type,8253 .lhs = container_type,
8086 .rhs = name,8254 .rhs = name,
8087 });8255 });
8088 return rvalue(gz, rl, result, node);8256 return rvalue(gz, ri, result, node);
8089}8257}
80908258
8091fn typeCast(8259fn typeCast(
8092 gz: *GenZir,8260 gz: *GenZir,
8093 scope: *Scope,8261 scope: *Scope,
8094 rl: ResultLoc,8262 ri: ResultInfo,
8095 node: Ast.Node.Index,8263 node: Ast.Node.Index,
8096 lhs_node: Ast.Node.Index,8264 lhs_node: Ast.Node.Index,
8097 rhs_node: Ast.Node.Index,8265 rhs_node: Ast.Node.Index,
...@@ -8099,42 +8267,42 @@ fn typeCast(...@@ -8099,42 +8267,42 @@ fn typeCast(
8099) InnerError!Zir.Inst.Ref {8267) InnerError!Zir.Inst.Ref {
8100 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8268 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8101 .lhs = try typeExpr(gz, scope, lhs_node),8269 .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),
8103 });8271 });
8104 return rvalue(gz, rl, result, node);8272 return rvalue(gz, ri, result, node);
8105}8273}
81068274
8107fn simpleUnOpType(8275fn simpleUnOpType(
8108 gz: *GenZir,8276 gz: *GenZir,
8109 scope: *Scope,8277 scope: *Scope,
8110 rl: ResultLoc,8278 ri: ResultInfo,
8111 node: Ast.Node.Index,8279 node: Ast.Node.Index,
8112 operand_node: Ast.Node.Index,8280 operand_node: Ast.Node.Index,
8113 tag: Zir.Inst.Tag,8281 tag: Zir.Inst.Tag,
8114) InnerError!Zir.Inst.Ref {8282) InnerError!Zir.Inst.Ref {
8115 const operand = try typeExpr(gz, scope, operand_node);8283 const operand = try typeExpr(gz, scope, operand_node);
8116 const result = try gz.addUnNode(tag, operand, node);8284 const result = try gz.addUnNode(tag, operand, node);
8117 return rvalue(gz, rl, result, node);8285 return rvalue(gz, ri, result, node);
8118}8286}
81198287
8120fn simpleUnOp(8288fn simpleUnOp(
8121 gz: *GenZir,8289 gz: *GenZir,
8122 scope: *Scope,8290 scope: *Scope,
8123 rl: ResultLoc,8291 ri: ResultInfo,
8124 node: Ast.Node.Index,8292 node: Ast.Node.Index,
8125 operand_rl: ResultLoc,8293 operand_ri: ResultInfo,
8126 operand_node: Ast.Node.Index,8294 operand_node: Ast.Node.Index,
8127 tag: Zir.Inst.Tag,8295 tag: Zir.Inst.Tag,
8128) InnerError!Zir.Inst.Ref {8296) 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);
8130 const result = try gz.addUnNode(tag, operand, node);8298 const result = try gz.addUnNode(tag, operand, node);
8131 return rvalue(gz, rl, result, node);8299 return rvalue(gz, ri, result, node);
8132}8300}
81338301
8134fn negation(8302fn negation(
8135 gz: *GenZir,8303 gz: *GenZir,
8136 scope: *Scope,8304 scope: *Scope,
8137 rl: ResultLoc,8305 ri: ResultInfo,
8138 node: Ast.Node.Index,8306 node: Ast.Node.Index,
8139) InnerError!Zir.Inst.Ref {8307) InnerError!Zir.Inst.Ref {
8140 const astgen = gz.astgen;8308 const astgen = gz.astgen;
...@@ -8146,18 +8314,18 @@ fn negation(...@@ -8146,18 +8314,18 @@ fn negation(
8146 // its negativity rather than having it go through comptime subtraction.8314 // its negativity rather than having it go through comptime subtraction.
8147 const operand_node = node_datas[node].lhs;8315 const operand_node = node_datas[node].lhs;
8148 if (node_tags[operand_node] == .number_literal) {8316 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);
8150 }8318 }
81518319
8152 const operand = try expr(gz, scope, .none, operand_node);8320 const operand = try expr(gz, scope, .{ .rl = .none }, operand_node);
8153 const result = try gz.addUnNode(.negate, operand, node);8321 const result = try gz.addUnNode(.negate, operand, node);
8154 return rvalue(gz, rl, result, node);8322 return rvalue(gz, ri, result, node);
8155}8323}
81568324
8157fn cmpxchg(8325fn cmpxchg(
8158 gz: *GenZir,8326 gz: *GenZir,
8159 scope: *Scope,8327 scope: *Scope,
8160 rl: ResultLoc,8328 ri: ResultInfo,
8161 node: Ast.Node.Index,8329 node: Ast.Node.Index,
8162 params: []const Ast.Node.Index,8330 params: []const Ast.Node.Index,
8163 small: u16,8331 small: u16,
...@@ -8166,98 +8334,98 @@ fn cmpxchg(...@@ -8166,98 +8334,98 @@ fn cmpxchg(
8166 const result = try gz.addExtendedPayloadSmall(.cmpxchg, small, Zir.Inst.Cmpxchg{8334 const result = try gz.addExtendedPayloadSmall(.cmpxchg, small, Zir.Inst.Cmpxchg{
8167 // zig fmt: off8335 // zig fmt: off
8168 .node = gz.nodeIndexToRelative(node),8336 .node = gz.nodeIndexToRelative(node),
8169 .ptr = try expr(gz, scope, .none, params[1]),8337 .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
8170 .expected_value = try expr(gz, scope, .{ .ty = int_type }, params[2]),8338 .expected_value = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]),
8171 .new_value = try expr(gz, scope, .{ .coerced_ty = int_type }, params[3]),8339 .new_value = try expr(gz, scope, .{ .rl = .{ .coerced_ty = int_type } }, params[3]),
8172 .success_order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[4]),8340 .success_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[4]),
8173 .failure_order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[5]),8341 .failure_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[5]),
8174 // zig fmt: on8342 // zig fmt: on
8175 });8343 });
8176 return rvalue(gz, rl, result, node);8344 return rvalue(gz, ri, result, node);
8177}8345}
81788346
8179fn bitBuiltin(8347fn bitBuiltin(
8180 gz: *GenZir,8348 gz: *GenZir,
8181 scope: *Scope,8349 scope: *Scope,
8182 rl: ResultLoc,8350 ri: ResultInfo,
8183 node: Ast.Node.Index,8351 node: Ast.Node.Index,
8184 operand_node: Ast.Node.Index,8352 operand_node: Ast.Node.Index,
8185 tag: Zir.Inst.Tag,8353 tag: Zir.Inst.Tag,
8186) InnerError!Zir.Inst.Ref {8354) 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);
8188 const result = try gz.addUnNode(tag, operand, node);8356 const result = try gz.addUnNode(tag, operand, node);
8189 return rvalue(gz, rl, result, node);8357 return rvalue(gz, ri, result, node);
8190}8358}
81918359
8192fn divBuiltin(8360fn divBuiltin(
8193 gz: *GenZir,8361 gz: *GenZir,
8194 scope: *Scope,8362 scope: *Scope,
8195 rl: ResultLoc,8363 ri: ResultInfo,
8196 node: Ast.Node.Index,8364 node: Ast.Node.Index,
8197 lhs_node: Ast.Node.Index,8365 lhs_node: Ast.Node.Index,
8198 rhs_node: Ast.Node.Index,8366 rhs_node: Ast.Node.Index,
8199 tag: Zir.Inst.Tag,8367 tag: Zir.Inst.Tag,
8200) InnerError!Zir.Inst.Ref {8368) InnerError!Zir.Inst.Ref {
8201 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8369 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8202 .lhs = try expr(gz, scope, .none, lhs_node),8370 .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node),
8203 .rhs = try expr(gz, scope, .none, rhs_node),8371 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),
8204 });8372 });
8205 return rvalue(gz, rl, result, node);8373 return rvalue(gz, ri, result, node);
8206}8374}
82078375
8208fn simpleCBuiltin(8376fn simpleCBuiltin(
8209 gz: *GenZir,8377 gz: *GenZir,
8210 scope: *Scope,8378 scope: *Scope,
8211 rl: ResultLoc,8379 ri: ResultInfo,
8212 node: Ast.Node.Index,8380 node: Ast.Node.Index,
8213 operand_node: Ast.Node.Index,8381 operand_node: Ast.Node.Index,
8214 tag: Zir.Inst.Extended,8382 tag: Zir.Inst.Extended,
8215) InnerError!Zir.Inst.Ref {8383) InnerError!Zir.Inst.Ref {
8216 const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";8384 const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
8217 if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});8385 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);
8219 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{8387 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
8220 .node = gz.nodeIndexToRelative(node),8388 .node = gz.nodeIndexToRelative(node),
8221 .operand = operand,8389 .operand = operand,
8222 });8390 });
8223 return rvalue(gz, rl, .void_value, node);8391 return rvalue(gz, ri, .void_value, node);
8224}8392}
82258393
8226fn offsetOf(8394fn offsetOf(
8227 gz: *GenZir,8395 gz: *GenZir,
8228 scope: *Scope,8396 scope: *Scope,
8229 rl: ResultLoc,8397 ri: ResultInfo,
8230 node: Ast.Node.Index,8398 node: Ast.Node.Index,
8231 lhs_node: Ast.Node.Index,8399 lhs_node: Ast.Node.Index,
8232 rhs_node: Ast.Node.Index,8400 rhs_node: Ast.Node.Index,
8233 tag: Zir.Inst.Tag,8401 tag: Zir.Inst.Tag,
8234) InnerError!Zir.Inst.Ref {8402) InnerError!Zir.Inst.Ref {
8235 const type_inst = try typeExpr(gz, scope, lhs_node);8403 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);
8237 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8405 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8238 .lhs = type_inst,8406 .lhs = type_inst,
8239 .rhs = field_name,8407 .rhs = field_name,
8240 });8408 });
8241 return rvalue(gz, rl, result, node);8409 return rvalue(gz, ri, result, node);
8242}8410}
82438411
8244fn shiftOp(8412fn shiftOp(
8245 gz: *GenZir,8413 gz: *GenZir,
8246 scope: *Scope,8414 scope: *Scope,
8247 rl: ResultLoc,8415 ri: ResultInfo,
8248 node: Ast.Node.Index,8416 node: Ast.Node.Index,
8249 lhs_node: Ast.Node.Index,8417 lhs_node: Ast.Node.Index,
8250 rhs_node: Ast.Node.Index,8418 rhs_node: Ast.Node.Index,
8251 tag: Zir.Inst.Tag,8419 tag: Zir.Inst.Tag,
8252) InnerError!Zir.Inst.Ref {8420) 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);
8254 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);8422 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);
8256 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8424 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8257 .lhs = lhs,8425 .lhs = lhs,
8258 .rhs = rhs,8426 .rhs = rhs,
8259 });8427 });
8260 return rvalue(gz, rl, result, node);8428 return rvalue(gz, ri, result, node);
8261}8429}
82628430
8263fn cImport(8431fn cImport(
...@@ -8275,7 +8443,7 @@ fn cImport(...@@ -8275,7 +8443,7 @@ fn cImport(
8275 defer block_scope.unstack();8443 defer block_scope.unstack();
82768444
8277 const block_inst = try gz.makeBlockInst(.c_import, node);8445 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);
8279 _ = try gz.addUnNode(.ensure_result_used, block_result, node);8447 _ = try gz.addUnNode(.ensure_result_used, block_result, node);
8280 if (!gz.refIsNoReturn(block_result)) {8448 if (!gz.refIsNoReturn(block_result)) {
8281 _ = try block_scope.addBreak(.break_inline, block_inst, .void_value);8449 _ = try block_scope.addBreak(.break_inline, block_inst, .void_value);
...@@ -8290,29 +8458,29 @@ fn cImport(...@@ -8290,29 +8458,29 @@ fn cImport(
8290fn overflowArithmetic(8458fn overflowArithmetic(
8291 gz: *GenZir,8459 gz: *GenZir,
8292 scope: *Scope,8460 scope: *Scope,
8293 rl: ResultLoc,8461 ri: ResultInfo,
8294 node: Ast.Node.Index,8462 node: Ast.Node.Index,
8295 params: []const Ast.Node.Index,8463 params: []const Ast.Node.Index,
8296 tag: Zir.Inst.Extended,8464 tag: Zir.Inst.Extended,
8297) InnerError!Zir.Inst.Ref {8465) InnerError!Zir.Inst.Ref {
8298 const int_type = try typeExpr(gz, scope, params[0]);8466 const int_type = try typeExpr(gz, scope, params[0]);
8299 const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);8467 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]);8468 const lhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[1]);
8301 const rhs = try expr(gz, scope, .{ .ty = int_type }, params[2]);8469 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]);
8302 const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);8470 const ptr = try expr(gz, scope, .{ .rl = .{ .ty = ptr_type } }, params[3]);
8303 const result = try gz.addExtendedPayload(tag, Zir.Inst.OverflowArithmetic{8471 const result = try gz.addExtendedPayload(tag, Zir.Inst.OverflowArithmetic{
8304 .node = gz.nodeIndexToRelative(node),8472 .node = gz.nodeIndexToRelative(node),
8305 .lhs = lhs,8473 .lhs = lhs,
8306 .rhs = rhs,8474 .rhs = rhs,
8307 .ptr = ptr,8475 .ptr = ptr,
8308 });8476 });
8309 return rvalue(gz, rl, result, node);8477 return rvalue(gz, ri, result, node);
8310}8478}
83118479
8312fn callExpr(8480fn callExpr(
8313 gz: *GenZir,8481 gz: *GenZir,
8314 scope: *Scope,8482 scope: *Scope,
8315 rl: ResultLoc,8483 ri: ResultInfo,
8316 node: Ast.Node.Index,8484 node: Ast.Node.Index,
8317 call: Ast.full.Call,8485 call: Ast.full.Call,
8318) InnerError!Zir.Inst.Ref {8486) InnerError!Zir.Inst.Ref {
...@@ -8364,7 +8532,7 @@ fn callExpr(...@@ -8364,7 +8532,7 @@ fn callExpr(
8364 defer arg_block.unstack();8532 defer arg_block.unstack();
83658533
8366 // `call_inst` is reused to provide the param type.8534 // `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);
8368 _ = try arg_block.addBreak(.break_inline, call_index, arg_ref);8536 _ = try arg_block.addBreak(.break_inline, call_index, arg_ref);
83698537
8370 const body = arg_block.instructionsSlice();8538 const body = arg_block.instructionsSlice();
...@@ -8375,9 +8543,18 @@ fn callExpr(...@@ -8375,9 +8543,18 @@ fn callExpr(
8375 scratch_index += 1;8543 scratch_index += 1;
8376 }8544 }
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
8378 const payload_index = try addExtra(astgen, Zir.Inst.Call{8554 const payload_index = try addExtra(astgen, Zir.Inst.Call{
8379 .callee = callee,8555 .callee = callee,
8380 .flags = .{8556 .flags = .{
8557 .pop_error_return_trace = !propagate_error_trace,
8381 .packed_modifier = @intCast(Zir.Inst.Call.Flags.PackedModifier, @enumToInt(modifier)),8558 .packed_modifier = @intCast(Zir.Inst.Call.Flags.PackedModifier, @enumToInt(modifier)),
8382 .args_len = @intCast(Zir.Inst.Call.Flags.PackedArgsLen, call.ast.params.len),8559 .args_len = @intCast(Zir.Inst.Call.Flags.PackedArgsLen, call.ast.params.len),
8383 },8560 },
...@@ -8392,7 +8569,7 @@ fn callExpr(...@@ -8392,7 +8569,7 @@ fn callExpr(
8392 .payload_index = payload_index,8569 .payload_index = payload_index,
8393 } },8570 } },
8394 });8571 });
8395 return rvalue(gz, rl, call_inst, node); // TODO function call with result location8572 return rvalue(gz, ri, call_inst, node); // TODO function call with result location
8396}8573}
83978574
8398/// calleeExpr generates the function part of a call expression (f in f(x)), or the8575/// calleeExpr generates the function part of a call expression (f in f(x)), or the
...@@ -8413,7 +8590,7 @@ fn calleeExpr(...@@ -8413,7 +8590,7 @@ fn calleeExpr(
84138590
8414 const tag = tree.nodes.items(.tag)[node];8591 const tag = tree.nodes.items(.tag)[node];
8415 switch (tag) {8592 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
8418 .builtin_call_two,8595 .builtin_call_two,
8419 .builtin_call_two_comma,8596 .builtin_call_two_comma,
...@@ -8445,8 +8622,8 @@ fn calleeExpr(...@@ -8445,8 +8622,8 @@ fn calleeExpr(
8445 // If anything is wrong, fall back to builtinCall.8622 // If anything is wrong, fall back to builtinCall.
8446 // It will emit any necessary compile errors and notes.8623 // It will emit any necessary compile errors and notes.
8447 if (std.mem.eql(u8, builtin_name, "@field") and params.len == 2) {8624 if (std.mem.eql(u8, builtin_name, "@field") and params.len == 2) {
8448 const lhs = try expr(gz, scope, .ref, params[0]);8625 const lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]);
8449 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);8626 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]);
8450 return gz.addExtendedPayload(.field_call_bind_named, Zir.Inst.FieldNamedNode{8627 return gz.addExtendedPayload(.field_call_bind_named, Zir.Inst.FieldNamedNode{
8451 .node = gz.nodeIndexToRelative(node),8628 .node = gz.nodeIndexToRelative(node),
8452 .lhs = lhs,8629 .lhs = lhs,
...@@ -8454,9 +8631,9 @@ fn calleeExpr(...@@ -8454,9 +8631,9 @@ fn calleeExpr(
8454 });8631 });
8455 }8632 }
84568633
8457 return builtinCall(gz, scope, .none, node, params);8634 return builtinCall(gz, scope, .{ .rl = .none }, node, params);
8458 },8635 },
8459 else => return expr(gz, scope, .none, node),8636 else => return expr(gz, scope, .{ .rl = .none }, node),
8460 }8637 }
8461}8638}
84628639
...@@ -8738,6 +8915,33 @@ fn nodeMayNeedMemoryLocation(tree: *const Ast, start_node: Ast.Node.Index, have_...@@ -8738,6 +8915,33 @@ fn nodeMayNeedMemoryLocation(tree: *const Ast, start_node: Ast.Node.Index, have_
8738 }8915 }
8739}8916}
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
8741fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError {8945fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError {
8742 const node_tags = tree.nodes.items(.tag);8946 const node_tags = tree.nodes.items(.tag);
8743 const node_datas = tree.nodes.items(.data);8947 const node_datas = tree.nodes.items(.data);
...@@ -9472,7 +9676,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {...@@ -9472,7 +9676,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
9472/// Assumes nothing stacked on `gz`.9676/// Assumes nothing stacked on `gz`.
9473fn rvalue(9677fn rvalue(
9474 gz: *GenZir,9678 gz: *GenZir,
9475 rl: ResultLoc,9679 ri: ResultInfo,
9476 raw_result: Zir.Inst.Ref,9680 raw_result: Zir.Inst.Ref,
9477 src_node: Ast.Node.Index,9681 src_node: Ast.Node.Index,
9478) InnerError!Zir.Inst.Ref {9682) InnerError!Zir.Inst.Ref {
...@@ -9487,7 +9691,7 @@ fn rvalue(...@@ -9487,7 +9691,7 @@ fn rvalue(
9487 break :r raw_result;9691 break :r raw_result;
9488 };9692 };
9489 if (gz.endsWithNoReturn()) return result;9693 if (gz.endsWithNoReturn()) return result;
9490 switch (rl) {9694 switch (ri.rl) {
9491 .none, .coerced_ty => return result,9695 .none, .coerced_ty => return result,
9492 .discard => {9696 .discard => {
9493 // Emit a compile error for discarding error values.9697 // Emit a compile error for discarding error values.
...@@ -9513,7 +9717,7 @@ fn rvalue(...@@ -9513,7 +9717,7 @@ fn rvalue(
9513 }9717 }
9514 return indexToRef(gop.value_ptr.*);9718 return indexToRef(gop.value_ptr.*);
9515 },9719 },
9516 .ty, .ty_shift_operand => |ty_inst| {9720 .ty => |ty_inst| {
9517 // Quickly eliminate some common, unnecessary type coercion.9721 // Quickly eliminate some common, unnecessary type coercion.
9518 const as_ty = @as(u64, @enumToInt(Zir.Inst.Ref.type_type)) << 32;9722 const as_ty = @as(u64, @enumToInt(Zir.Inst.Ref.type_type)) << 32;
9519 const as_comptime_int = @as(u64, @enumToInt(Zir.Inst.Ref.comptime_int_type)) << 32;9723 const as_comptime_int = @as(u64, @enumToInt(Zir.Inst.Ref.comptime_int_type)) << 32;
...@@ -9574,7 +9778,7 @@ fn rvalue(...@@ -9574,7 +9778,7 @@ fn rvalue(
9574 => return result, // type of result is already correct9778 => return result, // type of result is already correct
95759779
9576 // Need an explicit type coercion instruction.9780 // 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{
9578 .dest_type = ty_inst,9782 .dest_type = ty_inst,
9579 .operand = result,9783 .operand = result,
9580 }),9784 }),
...@@ -10268,8 +10472,8 @@ const GenZir = struct {...@@ -10268,8 +10472,8 @@ const GenZir = struct {
10268 label: ?Label = null,10472 label: ?Label = null,
10269 break_block: Zir.Inst.Index = 0,10473 break_block: Zir.Inst.Index = 0,
10270 continue_block: Zir.Inst.Index = 0,10474 continue_block: Zir.Inst.Index = 0,
10271 /// Only valid when setBreakResultLoc is called.10475 /// Only valid when setBreakResultInfo is called.
10272 break_result_loc: AstGen.ResultLoc = undefined,10476 break_result_info: AstGen.ResultInfo = undefined,
10273 /// When a block has a pointer result location, here it is.10477 /// When a block has a pointer result location, here it is.
10274 rl_ptr: Zir.Inst.Ref = .none,10478 rl_ptr: Zir.Inst.Ref = .none,
10275 /// When a block has a type result location, here it is.10479 /// When a block has a type result location, here it is.
...@@ -10371,7 +10575,7 @@ const GenZir = struct {...@@ -10371,7 +10575,7 @@ const GenZir = struct {
10371 fn finishCoercion(10575 fn finishCoercion(
10372 as_scope: *GenZir,10576 as_scope: *GenZir,
10373 parent_gz: *GenZir,10577 parent_gz: *GenZir,
10374 rl: ResultLoc,10578 ri: ResultInfo,
10375 src_node: Ast.Node.Index,10579 src_node: Ast.Node.Index,
10376 result: Zir.Inst.Ref,10580 result: Zir.Inst.Ref,
10377 dest_type: Zir.Inst.Ref,10581 dest_type: Zir.Inst.Ref,
...@@ -10397,7 +10601,7 @@ const GenZir = struct {...@@ -10397,7 +10601,7 @@ const GenZir = struct {
10397 as_scope.instructions_top = GenZir.unstacked_top;10601 as_scope.instructions_top = GenZir.unstacked_top;
10398 // as_scope now unstacked, can add new instructions to parent_gz10602 // as_scope now unstacked, can add new instructions to parent_gz
10399 const casted_result = try parent_gz.addBin(.as, dest_type, result);10603 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);
10401 } else {10605 } else {
10402 // implicitly move all as_scope instructions to parent_gz10606 // implicitly move all as_scope instructions to parent_gz
10403 as_scope.instructions_top = GenZir.unstacked_top;10607 as_scope.instructions_top = GenZir.unstacked_top;
...@@ -10440,7 +10644,7 @@ const GenZir = struct {...@@ -10440,7 +10644,7 @@ const GenZir = struct {
10440 return gz.astgen.tree.firstToken(gz.decl_node_index);10644 return gz.astgen.tree.firstToken(gz.decl_node_index);
10441 }10645 }
1044210646
10443 fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void {10647 fn setBreakResultInfo(gz: *GenZir, parent_ri: AstGen.ResultInfo) void {
10444 // Depending on whether the result location is a pointer or value, different10648 // Depending on whether the result location is a pointer or value, different
10445 // ZIR needs to be generated. In the former case we rely on storing to the10649 // ZIR needs to be generated. In the former case we rely on storing to the
10446 // pointer to communicate the result, and use breakvoid; in the latter case10650 // pointer to communicate the result, and use breakvoid; in the latter case
...@@ -10449,32 +10653,32 @@ const GenZir = struct {...@@ -10449,32 +10653,32 @@ const GenZir = struct {
10449 // the scenario where the result location is not consumed. In this case10653 // the scenario where the result location is not consumed. In this case
10450 // we emit ZIR for the block break instructions to have the result values,10654 // we emit ZIR for the block break instructions to have the result values,
10451 // and then rvalue() on that to pass the value to the result location.10655 // and then rvalue() on that to pass the value to the result location.
10452 switch (parent_rl) {10656 switch (parent_ri.rl) {
10453 .ty, .ty_shift_operand, .coerced_ty => |ty_inst| {10657 .ty, .coerced_ty => |ty_inst| {
10454 gz.rl_ty_inst = ty_inst;10658 gz.rl_ty_inst = ty_inst;
10455 gz.break_result_loc = parent_rl;10659 gz.break_result_info = parent_ri;
10456 },10660 },
1045710661
10458 .discard, .none, .ref => {10662 .discard, .none, .ref => {
10459 gz.rl_ty_inst = .none;10663 gz.rl_ty_inst = .none;
10460 gz.break_result_loc = parent_rl;10664 gz.break_result_info = parent_ri;
10461 },10665 },
1046210666
10463 .ptr => |ptr_res| {10667 .ptr => |ptr_res| {
10464 gz.rl_ty_inst = .none;10668 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 } } };
10466 },10670 },
1046710671
10468 .inferred_ptr => |ptr| {10672 .inferred_ptr => |ptr| {
10469 gz.rl_ty_inst = .none;10673 gz.rl_ty_inst = .none;
10470 gz.rl_ptr = ptr;10674 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 };
10472 },10676 },
1047310677
10474 .block_ptr => |parent_block_scope| {10678 .block_ptr => |parent_block_scope| {
10475 gz.rl_ty_inst = parent_block_scope.rl_ty_inst;10679 gz.rl_ty_inst = parent_block_scope.rl_ty_inst;
10476 gz.rl_ptr = parent_block_scope.rl_ptr;10680 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 };
10478 },10682 },
10479 }10683 }
10480 }10684 }
...@@ -11157,6 +11361,46 @@ const GenZir = struct {...@@ -11157,6 +11361,46 @@ const GenZir = struct {
11157 });11361 });
11158 }11362 }
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
11160 fn addBreak(11404 fn addBreak(
11161 gz: *GenZir,11405 gz: *GenZir,
11162 tag: Zir.Inst.Tag,11406 tag: Zir.Inst.Tag,
...@@ -11624,10 +11868,10 @@ const GenZir = struct {...@@ -11624,10 +11868,10 @@ const GenZir = struct {
11624 return new_index;11868 return new_index;
11625 }11869 }
1162611870
11627 fn addRet(gz: *GenZir, rl: ResultLoc, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void {11871 fn addRet(gz: *GenZir, ri: ResultInfo, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void {
11628 switch (rl) {11872 switch (ri.rl) {
11629 .ptr => |ptr_res| _ = try gz.addUnNode(.ret_load, ptr_res.inst, node),11873 .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),
11631 else => unreachable,11875 else => unreachable,
11632 }11876 }
11633 }11877 }
src/Liveness.zig+2
...@@ -228,6 +228,7 @@ pub fn categorizeOperand(...@@ -228,6 +228,7 @@ pub fn categorizeOperand(
228 .frame_addr,228 .frame_addr,
229 .wasm_memory_size,229 .wasm_memory_size,
230 .err_return_trace,230 .err_return_trace,
231 .save_err_return_trace_index,
231 => return .none,232 => return .none,
232233
233 .fence => return .write,234 .fence => return .write,
...@@ -805,6 +806,7 @@ fn analyzeInst(...@@ -805,6 +806,7 @@ fn analyzeInst(
805 .frame_addr,806 .frame_addr,
806 .wasm_memory_size,807 .wasm_memory_size,
807 .err_return_trace,808 .err_return_trace,
809 .save_err_return_trace_index,
808 => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),810 => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),
809811
810 .not,812 .not,
src/Module.zig+6
...@@ -5633,6 +5633,12 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5633,6 +5633,12 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
56335633
5634 const last_arg_index = inner_block.instructions.items.len;5634 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
5636 sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {5642 sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
5637 // TODO make these unreachable instead of @panic5643 // TODO make these unreachable instead of @panic
5638 error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),5644 error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),
src/Sema.zig+317-33
...@@ -32,6 +32,8 @@ owner_func: ?*Module.Fn,...@@ -32,6 +32,8 @@ owner_func: ?*Module.Fn,
32/// This starts out the same as `owner_func` and then diverges in the case of32/// This starts out the same as `owner_func` and then diverges in the case of
33/// an inline or comptime function call.33/// an inline or comptime function call.
34func: ?*Module.Fn,34func: ?*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,
35/// When semantic analysis needs to know the return type of the function whose body37/// When semantic analysis needs to know the return type of the function whose body
36/// is being analyzed, this `Type` should be used instead of going through `func`.38/// is being analyzed, this `Type` should be used instead of going through `func`.
37/// This will correctly handle the case of a comptime/inline function call of a39/// This will correctly handle the case of a comptime/inline function call of a
...@@ -153,6 +155,10 @@ pub const Block = struct {...@@ -153,6 +155,10 @@ pub const Block = struct {
153 is_typeof: bool = false,155 is_typeof: bool = false,
154 is_coerce_result_ptr: bool = false,156 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
156 /// when null, it is determined by build mode, changed by @setRuntimeSafety162 /// when null, it is determined by build mode, changed by @setRuntimeSafety
157 want_safety: ?bool = null,163 want_safety: ?bool = null,
158164
...@@ -226,6 +232,7 @@ pub const Block = struct {...@@ -226,6 +232,7 @@ pub const Block = struct {
226 .float_mode = parent.float_mode,232 .float_mode = parent.float_mode,
227 .c_import_buf = parent.c_import_buf,233 .c_import_buf = parent.c_import_buf,
228 .switch_else_err_ty = parent.switch_else_err_ty,234 .switch_else_err_ty = parent.switch_else_err_ty,
235 .error_return_trace_index = parent.error_return_trace_index,
229 };236 };
230 }237 }
231238
...@@ -499,6 +506,25 @@ pub const Block = struct {...@@ -499,6 +506,25 @@ pub const Block = struct {
499 return result_index;506 return result_index;
500 }507 }
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
502 fn addUnreachable(block: *Block, src: LazySrcLoc, safety_check: bool) !void {528 fn addUnreachable(block: *Block, src: LazySrcLoc, safety_check: bool) !void {
503 if (safety_check and block.wantSafety()) {529 if (safety_check and block.wantSafety()) {
504 _ = try block.sema.safetyPanic(block, src, .unreach);530 _ = try block.sema.safetyPanic(block, src, .unreach);
...@@ -1208,6 +1234,16 @@ fn analyzeBodyInner(...@@ -1208,6 +1234,16 @@ fn analyzeBodyInner(
1208 i += 1;1234 i += 1;
1209 continue;1235 continue;
1210 },1236 },
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
1212 // Special case instructions to handle comptime control flow.1248 // Special case instructions to handle comptime control flow.
1213 .@"break" => {1249 .@"break" => {
...@@ -1300,31 +1336,32 @@ fn analyzeBodyInner(...@@ -1300,31 +1336,32 @@ fn analyzeBodyInner(
1300 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);1336 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
1301 const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];1337 const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
1302 const gpa = sema.gpa;1338 const gpa = sema.gpa;
1303 // If this block contains a function prototype, we need to reset the1339
1304 // current list of parameters and restore it later.1340 const opt_break_data = b: {
1305 // Note: this probably needs to be resolved in a more general manner.1341 // Create a temporary child block so that this inline block is properly
1306 const prev_params = block.params;1342 // labeled for any .restore_err_ret_index instructions
1307 const need_sub_block = tags[inline_body[inline_body.len - 1]] == .repeat_inline;1343 var child_block = block.makeSubBlock();
1308 var sub_block = block;1344
1309 var block_space: Block = undefined;1345 // If this block contains a function prototype, we need to reset the
1310 // NOTE: this has to be done like this because branching in1346 // current list of parameters and restore it later.
1311 // defers here breaks stage1.1347 // Note: this probably needs to be resolved in a more general manner.
1312 block_space.instructions = .{};1348 if (tags[inline_body[inline_body.len - 1]] == .repeat_inline) {
1313 if (need_sub_block) {1349 child_block.inline_block = inline_body[0];
1314 block_space = block.makeSubBlock();1350 } else child_block.inline_block = block.inline_block;
1315 block_space.inline_block = inline_body[0];1351
1316 sub_block = &block_space;1352 var label: Block.Label = .{
1317 }1353 .zir_block = inst,
1318 block.params = .{};1354 .merges = undefined,
1319 defer {1355 };
1320 block.params.deinit(gpa);1356 child_block.label = &label;
1321 block.params = prev_params;1357 defer child_block.params.deinit(gpa);
1322 block_space.instructions.deinit(gpa);1358
1323 }1359 // Write these instructions directly into the parent block
1324 const opt_break_data = try sema.analyzeBodyBreak(sub_block, inline_body);1360 child_block.instructions = block.instructions;
1325 if (need_sub_block) {1361 defer block.instructions = child_block.instructions;
1326 try block.instructions.appendSlice(gpa, block_space.instructions.items);1362
1327 }1363 break :b try sema.analyzeBodyBreak(&child_block, inline_body);
1364 };
13281365
1329 // A runtime conditional branch that needs a post-hoc block to be1366 // A runtime conditional branch that needs a post-hoc block to be
1330 // emitted communicates this by mapping the block index into the inst map.1367 // 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...@@ -4968,7 +5005,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
49685005
4969 // Reserve space for a Block instruction so that generated Break instructions can5006 // Reserve space for a Block instruction so that generated Break instructions can
4970 // point to it, even if it doesn't end up getting used because the code ends up being5007 // 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.
4972 const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);5009 const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
4973 try sema.air_instructions.append(gpa, .{5010 try sema.air_instructions.append(gpa, .{
4974 .tag = .block,5011 .tag = .block,
...@@ -4999,6 +5036,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -4999,6 +5036,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
4999 .runtime_cond = parent_block.runtime_cond,5036 .runtime_cond = parent_block.runtime_cond,
5000 .runtime_loop = parent_block.runtime_loop,5037 .runtime_loop = parent_block.runtime_loop,
5001 .runtime_index = parent_block.runtime_index,5038 .runtime_index = parent_block.runtime_index,
5039 .error_return_trace_index = parent_block.error_return_trace_index,
5002 };5040 };
50035041
5004 defer child_block.instructions.deinit(gpa);5042 defer child_block.instructions.deinit(gpa);
...@@ -5641,6 +5679,117 @@ fn funcDeclSrc(sema: *Sema, block: *Block, src: LazySrcLoc, func_inst: Air.Inst....@@ -5641,6 +5679,117 @@ fn funcDeclSrc(sema: *Sema, block: *Block, src: LazySrcLoc, func_inst: Air.Inst.
5641 return owner_decl.srcLoc();5679 return owner_decl.srcLoc();
5642}5680}
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
5644fn zirCall(5793fn zirCall(
5645 sema: *Sema,5794 sema: *Sema,
5646 block: *Block,5795 block: *Block,
...@@ -5657,6 +5806,7 @@ fn zirCall(...@@ -5657,6 +5806,7 @@ fn zirCall(
56575806
5658 const modifier = @intToEnum(std.builtin.CallOptions.Modifier, extra.data.flags.packed_modifier);5807 const modifier = @intToEnum(std.builtin.CallOptions.Modifier, extra.data.flags.packed_modifier);
5659 const ensure_result_used = extra.data.flags.ensure_result_used;5808 const ensure_result_used = extra.data.flags.ensure_result_used;
5809 const pop_error_return_trace = extra.data.flags.pop_error_return_trace;
56605810
5661 var func = try sema.resolveInst(extra.data.callee);5811 var func = try sema.resolveInst(extra.data.callee);
5662 var resolved_args: []Air.Inst.Ref = undefined;5812 var resolved_args: []Air.Inst.Ref = undefined;
...@@ -5729,6 +5879,9 @@ fn zirCall(...@@ -5729,6 +5879,9 @@ fn zirCall(
57295879
5730 const args_body = sema.code.extra[extra.end..];5880 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
5732 const parent_comptime = block.is_comptime;5885 const parent_comptime = block.is_comptime;
5733 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.5886 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
5734 var extra_index: usize = 0;5887 var extra_index: usize = 0;
...@@ -5746,10 +5899,8 @@ fn zirCall(...@@ -5746,10 +5899,8 @@ fn zirCall(
5746 else5899 else
5747 func_ty_info.param_types[arg_index];5900 func_ty_info.param_types[arg_index];
57485901
5749 const old_comptime = block.is_comptime;
5750 defer block.is_comptime = old_comptime;
5751 // Generate args to comptime params in comptime block.5902 // Generate args to comptime params in comptime block.
5752 block.is_comptime = parent_comptime;5903 defer block.is_comptime = parent_comptime;
5753 if (arg_index < fn_params_len and func_ty_info.comptime_params[arg_index]) {5904 if (arg_index < fn_params_len and func_ty_info.comptime_params[arg_index]) {
5754 block.is_comptime = true;5905 block.is_comptime = true;
5755 }5906 }
...@@ -5758,13 +5909,58 @@ fn zirCall(...@@ -5758,13 +5909,58 @@ fn zirCall(
5758 try sema.inst_map.put(sema.gpa, inst, param_ty_inst);5909 try sema.inst_map.put(sema.gpa, inst, param_ty_inst);
57595910
5760 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);5911 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) {
5762 return resolved;5914 return resolved;
5763 }5915 }
5916 if (resolved_ty.isError()) {
5917 input_is_error = true;
5918 }
5764 resolved_args[arg_index] = resolved;5919 resolved_args[arg_index] = resolved;
5765 }5920 }
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 }
5768}5964}
57695965
5770const GenericCallAdapter = struct {5966const GenericCallAdapter = struct {
...@@ -6056,6 +6252,10 @@ fn analyzeCall(...@@ -6056,6 +6252,10 @@ fn analyzeCall(
6056 sema.func = module_fn;6252 sema.func = module_fn;
6057 defer sema.func = parent_func;6253 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
6059 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, fn_owner_decl.src_scope);6259 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, fn_owner_decl.src_scope);
6060 defer wip_captures.deinit();6260 defer wip_captures.deinit();
60616261
...@@ -6069,6 +6269,7 @@ fn analyzeCall(...@@ -6069,6 +6269,7 @@ fn analyzeCall(
6069 .label = null,6269 .label = null,
6070 .inlining = &inlining,6270 .inlining = &inlining,
6071 .is_comptime = is_comptime_call,6271 .is_comptime = is_comptime_call,
6272 .error_return_trace_index = block.error_return_trace_index,
6072 };6273 };
60736274
6074 const merges = &child_block.inlining.?.merges;6275 const merges = &child_block.inlining.?.merges;
...@@ -6814,6 +7015,13 @@ fn instantiateGenericCall(...@@ -6814,6 +7015,13 @@ fn instantiateGenericCall(
6814 }7015 }
6815 arg_i += 1;7016 arg_i += 1;
6816 }7017 }
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
6817 const new_func_inst = child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst) catch |err| {7025 const new_func_inst = child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst) catch |err| {
6818 // TODO look up the compile error that happened here and attach a note to it7026 // TODO look up the compile error that happened here and attach a note to it
6819 // pointing here, at the generic instantiation callsite.7027 // pointing here, at the generic instantiation callsite.
...@@ -9703,6 +9911,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9703,6 +9911,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9703 .defer_err_code,9911 .defer_err_code,
9704 .err_union_code,9912 .err_union_code,
9705 .ret_err_value_code,9913 .ret_err_value_code,
9914 .restore_err_ret_index,
9706 .is_non_err,9915 .is_non_err,
9707 .condbr,9916 .condbr,
9708 => {},9917 => {},
...@@ -10005,6 +10214,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10005,6 +10214,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10005 .runtime_cond = block.runtime_cond,10214 .runtime_cond = block.runtime_cond,
10006 .runtime_loop = block.runtime_loop,10215 .runtime_loop = block.runtime_loop,
10007 .runtime_index = block.runtime_index,10216 .runtime_index = block.runtime_index,
10217 .error_return_trace_index = block.error_return_trace_index,
10008 };10218 };
10009 const merges = &child_block.label.?.merges;10219 const merges = &child_block.label.?.merges;
10010 defer child_block.instructions.deinit(gpa);10220 defer child_block.instructions.deinit(gpa);
...@@ -10888,6 +11098,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op...@@ -10888,6 +11098,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
10888 const tags = sema.code.instructions.items(.tag);11098 const tags = sema.code.instructions.items(.tag);
10889 for (body) |inst| {11099 for (body) |inst| {
10890 switch (tags[inst]) {11100 switch (tags[inst]) {
11101 .save_err_ret_index,
10891 .dbg_block_begin,11102 .dbg_block_begin,
10892 .dbg_block_end,11103 .dbg_block_end,
10893 .dbg_stmt,11104 .dbg_stmt,
...@@ -10910,6 +11121,10 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op...@@ -10910,6 +11121,10 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
10910 try sema.zirDbgStmt(block, inst);11121 try sema.zirDbgStmt(block, inst);
10911 continue;11122 continue;
10912 },11123 },
11124 .save_err_ret_index => {
11125 try sema.zirSaveErrRetIndex(block, inst);
11126 continue;
11127 },
10913 .str => try sema.zirStr(block, inst),11128 .str => try sema.zirStr(block, inst),
10914 .as_node => try sema.zirAsNode(block, inst),11129 .as_node => try sema.zirAsNode(block, inst),
10915 .field_val => try sema.zirFieldVal(block, inst),11130 .field_val => try sema.zirFieldVal(block, inst),
...@@ -10955,6 +11170,7 @@ fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Ind...@@ -10955,6 +11170,7 @@ fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Ind
10955 return;11170 return;
10956 }11171 }
10957 if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| {11172 if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| {
11173 if (!operand_ty.isError()) return;
10958 if (val.getError() == null) return;11174 if (val.getError() == null) return;
10959 try sema.maybeErrorUnwrapComptime(block, body, err_operand);11175 try sema.maybeErrorUnwrapComptime(block, body, err_operand);
10960 }11176 }
...@@ -15519,6 +15735,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -15519,6 +15735,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
15519 .is_comptime = false,15735 .is_comptime = false,
15520 .is_typeof = true,15736 .is_typeof = true,
15521 .want_safety = false,15737 .want_safety = false,
15738 .error_return_trace_index = block.error_return_trace_index,
15522 };15739 };
15523 defer child_block.instructions.deinit(sema.gpa);15740 defer child_block.instructions.deinit(sema.gpa);
1552415741
...@@ -16176,6 +16393,75 @@ fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {...@@ -16176,6 +16393,75 @@ fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {
16176 backend_supports_error_return_tracing;16393 backend_supports_error_return_tracing;
16177}16394}
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
16179fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {16465fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {
16180 assert(sema.fn_ret_ty.zigTypeTag() == .ErrorUnion);16466 assert(sema.fn_ret_ty.zigTypeTag() == .ErrorUnion);
1618116467
...@@ -17181,8 +17467,6 @@ fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -17181,8 +17467,6 @@ fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1718117467
17182fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {17468fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
17183 const inst_data = sema.code.instructions.items(.data)[inst].un_node;17469 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
17184 const src = inst_data.src();
17185 _ = src;
17186 const operand = try sema.resolveInst(inst_data.operand);17470 const operand = try sema.resolveInst(inst_data.operand);
17187 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };17471 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 {...@@ -988,6 +988,15 @@ pub const Inst = struct {
988 /// Uses the `err_defer_code` union field.988 /// Uses the `err_defer_code` union field.
989 defer_err_code,989 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
991 /// The ZIR instruction tag is one of the `Extended` ones.1000 /// The ZIR instruction tag is one of the `Extended` ones.
992 /// Uses the `extended` union field.1001 /// Uses the `extended` union field.
993 extended,1002 extended,
...@@ -1236,6 +1245,8 @@ pub const Inst = struct {...@@ -1236,6 +1245,8 @@ pub const Inst = struct {
1236 //.try_ptr_inline,1245 //.try_ptr_inline,
1237 .@"defer",1246 .@"defer",
1238 .defer_err_code,1247 .defer_err_code,
1248 .save_err_ret_index,
1249 .restore_err_ret_index,
1239 => false,1250 => false,
12401251
1241 .@"break",1252 .@"break",
...@@ -1305,6 +1316,8 @@ pub const Inst = struct {...@@ -1305,6 +1316,8 @@ pub const Inst = struct {
1305 .check_comptime_control_flow,1316 .check_comptime_control_flow,
1306 .@"defer",1317 .@"defer",
1307 .defer_err_code,1318 .defer_err_code,
1319 .restore_err_ret_index,
1320 .save_err_ret_index,
1308 => true,1321 => true,
13091322
1310 .param,1323 .param,
...@@ -1810,6 +1823,9 @@ pub const Inst = struct {...@@ -1810,6 +1823,9 @@ pub const Inst = struct {
1810 .@"defer" = .@"defer",1823 .@"defer" = .@"defer",
1811 .defer_err_code = .defer_err_code,1824 .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
1813 .extended = .extended,1829 .extended = .extended,
1814 });1830 });
1815 };1831 };
...@@ -2586,6 +2602,13 @@ pub const Inst = struct {...@@ -2586,6 +2602,13 @@ pub const Inst = struct {
2586 err_code: Ref,2602 err_code: Ref,
2587 payload_index: u32,2603 payload_index: u32,
2588 },2604 },
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
2590 // Make sure we don't accidentally add a field to make this union2613 // Make sure we don't accidentally add a field to make this union
2591 // bigger than expected. Note that in Debug builds, Zig is allowed2614 // bigger than expected. Note that in Debug builds, Zig is allowed
...@@ -2624,6 +2647,8 @@ pub const Inst = struct {...@@ -2624,6 +2647,8 @@ pub const Inst = struct {
2624 str_op,2647 str_op,
2625 @"defer",2648 @"defer",
2626 defer_err_code,2649 defer_err_code,
2650 save_err_ret_index,
2651 restore_err_ret_index,
2627 };2652 };
2628 };2653 };
26292654
...@@ -2809,10 +2834,11 @@ pub const Inst = struct {...@@ -2809,10 +2834,11 @@ pub const Inst = struct {
2809 pub const Flags = packed struct {2834 pub const Flags = packed struct {
2810 /// std.builtin.CallOptions.Modifier in packed form2835 /// std.builtin.CallOptions.Modifier in packed form
2811 pub const PackedModifier = u3;2836 pub const PackedModifier = u3;
2812 pub const PackedArgsLen = u28;2837 pub const PackedArgsLen = u27;
28132838
2814 packed_modifier: PackedModifier,2839 packed_modifier: PackedModifier,
2815 ensure_result_used: bool = false,2840 ensure_result_used: bool = false,
2841 pop_error_return_trace: bool,
2816 args_len: PackedArgsLen,2842 args_len: PackedArgsLen,
28172843
2818 comptime {2844 comptime {
src/arch/aarch64/CodeGen.zig+6
...@@ -702,6 +702,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -702,6 +702,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
702 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),702 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
703 .err_return_trace => try self.airErrReturnTrace(inst),703 .err_return_trace => try self.airErrReturnTrace(inst),
704 .set_err_return_trace => try self.airSetErrReturnTrace(inst),704 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
705 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),
705706
706 .wrap_optional => try self.airWrapOptional(inst),707 .wrap_optional => try self.airWrapOptional(inst),
707 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),708 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
...@@ -2867,6 +2868,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {...@@ -2867,6 +2868,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
2867 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});2868 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});
2868}2869}
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
2870fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {2876fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
2871 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2877 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2872 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2878 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 {...@@ -751,6 +751,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
751 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),751 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
752 .err_return_trace => try self.airErrReturnTrace(inst),752 .err_return_trace => try self.airErrReturnTrace(inst),
753 .set_err_return_trace => try self.airSetErrReturnTrace(inst),753 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
754 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),
754755
755 .wrap_optional => try self.airWrapOptional(inst),756 .wrap_optional => try self.airWrapOptional(inst),
756 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),757 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
...@@ -2116,6 +2117,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {...@@ -2116,6 +2117,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
2116 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});2117 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});
2117}2118}
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
2119/// T to E!T2125/// T to E!T
2120fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {2126fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
2121 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2127 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 {...@@ -665,6 +665,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
665 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),665 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
666 .err_return_trace => try self.airErrReturnTrace(inst),666 .err_return_trace => try self.airErrReturnTrace(inst),
667 .set_err_return_trace => try self.airSetErrReturnTrace(inst),667 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
668 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),
668669
669 .wrap_optional => try self.airWrapOptional(inst),670 .wrap_optional => try self.airWrapOptional(inst),
670 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),671 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
...@@ -1329,6 +1330,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {...@@ -1329,6 +1330,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
1329 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});1330 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});
1330}1331}
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
1332fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {1338fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
1333 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1339 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1334 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1340 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 {...@@ -679,6 +679,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
679 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),679 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
680 .err_return_trace => @panic("TODO try self.airErrReturnTrace(inst)"),680 .err_return_trace => @panic("TODO try self.airErrReturnTrace(inst)"),
681 .set_err_return_trace => @panic("TODO try self.airSetErrReturnTrace(inst)"),681 .set_err_return_trace => @panic("TODO try self.airSetErrReturnTrace(inst)"),
682 .save_err_return_trace_index=> @panic("TODO try self.airSaveErrReturnTraceIndex(inst)"),
682683
683 .wrap_optional => try self.airWrapOptional(inst),684 .wrap_optional => try self.airWrapOptional(inst),
684 .wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"),685 .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 {...@@ -1857,6 +1857,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1857 .tag_name,1857 .tag_name,
1858 .err_return_trace,1858 .err_return_trace,
1859 .set_err_return_trace,1859 .set_err_return_trace,
1860 .save_err_return_trace_index,
1860 .is_named_enum_value,1861 .is_named_enum_value,
1861 .error_set_has_value,1862 .error_set_has_value,
1862 .addrspace_cast,1863 .addrspace_cast,
src/arch/x86_64/CodeGen.zig+6
...@@ -756,6 +756,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -756,6 +756,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
756 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),756 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
757 .err_return_trace => try self.airErrReturnTrace(inst),757 .err_return_trace => try self.airErrReturnTrace(inst),
758 .set_err_return_trace => try self.airSetErrReturnTrace(inst),758 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
759 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),
759760
760 .wrap_optional => try self.airWrapOptional(inst),761 .wrap_optional => try self.airWrapOptional(inst),
761 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),762 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
...@@ -1973,6 +1974,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {...@@ -1973,6 +1974,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
1973 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});1974 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});
1974}1975}
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
1976fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {1982fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
1977 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1983 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1978 if (self.liveness.isUnused(inst)) {1984 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...@@ -1935,6 +1935,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
1935 .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),1935 .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),
1936 .err_return_trace => try airErrReturnTrace(f, inst),1936 .err_return_trace => try airErrReturnTrace(f, inst),
1937 .set_err_return_trace => try airSetErrReturnTrace(f, inst),1937 .set_err_return_trace => try airSetErrReturnTrace(f, inst),
1938 .save_err_return_trace_index => try airSaveErrReturnTraceIndex(f, inst),
19381939
1939 .wasm_memory_size => try airWasmMemorySize(f, inst),1940 .wasm_memory_size => try airWasmMemorySize(f, inst),
1940 .wasm_memory_grow => try airWasmMemoryGrow(f, inst),1941 .wasm_memory_grow => try airWasmMemoryGrow(f, inst),
...@@ -3625,6 +3626,11 @@ fn airSetErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3625,6 +3626,11 @@ fn airSetErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue {
3625 return f.fail("TODO: C backend: implement airSetErrReturnTrace", .{});3626 return f.fail("TODO: C backend: implement airSetErrReturnTrace", .{});
3626}3627}
36273628
3629fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {
3630 _ = inst;
3631 return f.fail("TODO: C backend: implement airSaveErrReturnTraceIndex", .{});
3632}
3633
3628fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {3634fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
3629 if (f.liveness.isUnused(inst))3635 if (f.liveness.isUnused(inst))
3630 return CValue.none;3636 return CValue.none;
src/codegen/llvm.zig+19
...@@ -4592,6 +4592,7 @@ pub const FuncGen = struct {...@@ -4592,6 +4592,7 @@ pub const FuncGen = struct {
4592 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),4592 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
4593 .err_return_trace => try self.airErrReturnTrace(inst),4593 .err_return_trace => try self.airErrReturnTrace(inst),
4594 .set_err_return_trace => try self.airSetErrReturnTrace(inst),4594 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
4595 .save_err_return_trace_index => try self.airSaveErrReturnTraceIndex(inst),
45954596
4596 .wrap_optional => try self.airWrapOptional(inst),4597 .wrap_optional => try self.airWrapOptional(inst),
4597 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),4598 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
...@@ -6543,6 +6544,24 @@ pub const FuncGen = struct {...@@ -6543,6 +6544,24 @@ pub const FuncGen = struct {
6543 return null;6544 return null;
6544 }6545 }
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
6546 fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6565 fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6547 if (self.liveness.isUnused(inst)) return null;6566 if (self.liveness.isUnused(inst)) return null;
65486567
src/print_air.zig+1
...@@ -197,6 +197,7 @@ const Writer = struct {...@@ -197,6 +197,7 @@ const Writer = struct {
197 .unreach,197 .unreach,
198 .ret_addr,198 .ret_addr,
199 .frame_addr,199 .frame_addr,
200 .save_err_return_trace_index,
200 => try w.writeNoOp(s, inst),201 => try w.writeNoOp(s, inst),
201202
202 .const_ty,203 .const_ty,
src/print_zir.zig+20-1
...@@ -254,6 +254,9 @@ const Writer = struct {...@@ -254,6 +254,9 @@ const Writer = struct {
254 .str => try self.writeStr(stream, inst),254 .str => try self.writeStr(stream, inst),
255 .int_type => try self.writeIntType(stream, inst),255 .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
257 .@"break",260 .@"break",
258 .break_inline,261 .break_inline,
259 => try self.writeBreak(stream, inst),262 => try self.writeBreak(stream, inst),
...@@ -440,7 +443,7 @@ const Writer = struct {...@@ -440,7 +443,7 @@ const Writer = struct {
440443
441 .dbg_block_begin,444 .dbg_block_begin,
442 .dbg_block_end,445 .dbg_block_end,
443 => try stream.writeAll("))"),446 => try stream.writeAll(")"),
444447
445 .closure_get => try self.writeInstNode(stream, inst),448 .closure_get => try self.writeInstNode(stream, inst),
446449
...@@ -2272,6 +2275,22 @@ const Writer = struct {...@@ -2272,6 +2275,22 @@ const Writer = struct {
2272 try self.writeSrc(stream, int_type.src());2275 try self.writeSrc(stream, int_type.src());
2273 }2276 }
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
2275 fn writeBreak(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2294 fn writeBreak(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
2276 const inst_data = self.code.instructions.items(.data)[inst].@"break";2295 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 {...@@ -2971,9 +2971,10 @@ pub const Value = extern union {
2971 };2971 };
2972 }2972 }
29732973
2974 /// Valid for all types. Asserts the value is not undefined and not unreachable.2974 /// Valid only for error (union) types. Asserts the value is not undefined and not
2975 /// Prefer `errorUnionIsPayload` to find out whether something is an error or not2975 /// unreachable. For error unions, prefer `errorUnionIsPayload` to find out whether
2976 /// because it works without having to figure out the string.2976 /// something is an error or not because it works without having to figure out the
2977 /// string.
2977 pub fn getError(self: Value) ?[]const u8 {2978 pub fn getError(self: Value) ?[]const u8 {
2978 return switch (self.tag()) {2979 return switch (self.tag()) {
2979 .@"error" => self.castTag(.@"error").?.data.name,2980 .@"error" => self.castTag(.@"error").?.data.name,
test/behavior/bugs/12891.zig+1
...@@ -7,6 +7,7 @@ test "issue12891" {...@@ -7,6 +7,7 @@ test "issue12891" {
7 try std.testing.expect(i < f);7 try std.testing.expect(i < f);
8}8}
9test "nan" {9test "nan" {
10 if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1112
12 const f = comptime std.math.nan(f64);13 const f = comptime std.math.nan(f64);
test/behavior/error.zig+13
...@@ -830,3 +830,16 @@ test "compare error union and error set" {...@@ -830,3 +830,16 @@ test "compare error union and error set" {
830 try expect(a != b);830 try expect(a != b);
831 try expect(b != a);831 try expect(b != a);
832}832}
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" {...@@ -1401,7 +1401,21 @@ test "continue in inline for inside a comptime switch" {
1401 try expect(count == 4);1401 try expect(count == 4);
1402}1402}
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
1404test "continue nested inline for loop" {1415test "continue nested inline for loop" {
1416 // TODO: https://github.com/ziglang/zig/issues/13175
1417 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
1418
1405 var a: u8 = 0;1419 var a: u8 = 0;
1406 loop: inline for ([_]u8{ 1, 2 }) |x| {1420 loop: inline for ([_]u8{ 1, 2 }) |x| {
1407 inline for ([_]u8{1}) |y| {1421 inline for ([_]u8{1}) |y| {
...@@ -1415,13 +1429,21 @@ test "continue nested inline for loop" {...@@ -1415,13 +1429,21 @@ test "continue nested inline for loop" {
1415 try expect(a == 2);1429 try expect(a == 2);
1416}1430}
14171431
1418test "length of global array is determinable at comptime" {1432test "continue nested inline for loop in named block expr" {
1419 const S = struct {1433 // TODO: https://github.com/ziglang/zig/issues/13175
1420 var bytes: [1024]u8 = undefined;1434 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
14211435
1422 fn foo() !void {1436 var a: u8 = 0;
1423 try std.testing.expect(bytes.len == 1024);1437 loop: inline for ([_]u8{ 1, 2 }) |x| {
1424 }1438 a = b: {
1425 };1439 inline for ([_]u8{1}) |y| {
1426 comptime try S.foo();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);
1427}1449}
test/stack_traces.zig+541
...@@ -97,6 +97,547 @@ pub fn addCases(cases: *tests.StackTracesContext) void {...@@ -97,6 +97,547 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
97 ,97 ,
98 },98 },
99 });99 });
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
101 cases.addCase(.{642 cases.addCase(.{
102 .name = "try try return return",643 .name = "try try return return",