diff options
| author | Cody Tapscott <topolarity@tapscott.me> | 2022-09-14 17:38:08 -0700 |
|---|---|---|
| committer | Cody Tapscott <topolarity@tapscott.me> | 2022-10-21 11:22:46 -0700 |
| commit | 77720e30aaead1c814f2714bd5a7ad7ad0fbc23e (patch) | |
| tree | 70ab61b6e3a86770290565d4efe132d6ec31b67f /src | |
| parent | 724d75363855176aa5e6b3d9bcd1656e2cc1f6a6 (diff) | |
| download | zig-77720e30aaead1c814f2714bd5a7ad7ad0fbc23e.tar.gz zig-77720e30aaead1c814f2714bd5a7ad7ad0fbc23e.zip | |
Re-factor: Change AstGen.ResultLoc to be a struct
This re-factor is intended to make it easier to track what kind of
operator/expression consumes a result location, without overloading the
ResultLoc union for this purpose.
This is used in the following commit to keep track of initializer
expressions of `const` variables to avoid popping error traces
pre-maturely. Hopefully this will also be useful for implementing
RLS temporaries in the future.
Diffstat (limited to 'src')
| -rw-r--r-- | src/AstGen.zig | 1721 |
1 files changed, 865 insertions, 856 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig index ec67a89810..65818d98df 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -213,127 +213,145 @@ pub fn deinit(astgen: *AstGen, gpa: Allocator) void { astgen.ref_table.deinit(gpa); } -pub const ResultLoc = union(enum) { - /// The expression is the right-hand side of assignment to `_`. Only the side-effects of the - /// expression should be generated. The result instruction from the expression must - /// be ignored. - discard, - /// The expression has an inferred type, and it will be evaluated as an rvalue. - none, - /// The expression must generate a pointer rather than a value. For example, the left hand side - /// of an assignment uses this kind of result location. - ref, - /// Exactly like `none`, except also indicates this is an error-handling expr (try/catch/return etc.) - catch_none, - /// Exactly like `ref`, except also indicates this is an error-handling expr (try/catch/return etc.) - catch_ref, - /// The expression will be coerced into this type, but it will be evaluated as an rvalue. - ty: Zir.Inst.Ref, - /// Same as `ty` but for shift operands. - ty_shift_operand: Zir.Inst.Ref, - /// Same as `ty` but it is guaranteed that Sema will additionally perform the coercion, - /// so no `as` instruction needs to be emitted. - coerced_ty: Zir.Inst.Ref, - /// The expression must store its result into this typed pointer. The result instruction - /// from the expression must be ignored. - ptr: PtrResultLoc, - /// The expression must store its result into this allocation, which has an inferred type. - /// The result instruction from the expression must be ignored. - /// Always an instruction with tag `alloc_inferred`. - inferred_ptr: Zir.Inst.Ref, - /// There is a pointer for the expression to store its result into, however, its type - /// is inferred based on peer type resolution for a `Zir.Inst.Block`. - /// The result instruction from the expression must be ignored. - block_ptr: *GenZir, - - const PtrResultLoc = struct { - inst: Zir.Inst.Ref, - src_node: ?Ast.Node.Index = null, - }; +pub const ResultInfo = struct { + /// The semantics requested for the result location + rl: Loc, - pub const Strategy = struct { - elide_store_to_block_ptr_instructions: bool, - tag: Tag, - - pub const Tag = enum { - /// Both branches will use break_void; result location is used to communicate the - /// result instruction. - break_void, - /// Use break statements to pass the block result value, and call rvalue() at - /// the end depending on rl. Also elide the store_to_block_ptr instructions - /// depending on rl. - break_operand, - }; - }; + /// The "operator" consuming the result location + ctx: Context = .none, - fn strategy(rl: ResultLoc, block_scope: *GenZir) Strategy { - switch (rl) { - // In this branch there will not be any store_to_block_ptr instructions. - .none, .catch_none, .ty, .ty_shift_operand, .coerced_ty, .ref, .catch_ref => return .{ - .tag = .break_operand, - .elide_store_to_block_ptr_instructions = false, - }, - .discard => return .{ - .tag = .break_void, - .elide_store_to_block_ptr_instructions = false, - }, - // The pointer got passed through to the sub-expressions, so we will use - // break_void here. - // In this branch there will not be any store_to_block_ptr instructions. - .ptr => return .{ - .tag = .break_void, - .elide_store_to_block_ptr_instructions = false, + /// Turns a `coerced_ty` back into a `ty`. Should be called at branch points + /// such as if and switch expressions. + fn br(ri: ResultInfo) ResultInfo { + return switch (ri.rl) { + .coerced_ty => |ty| .{ + .rl = .{ .ty = ty }, + .ctx = ri.ctx, }, - .inferred_ptr, .block_ptr => { - if (block_scope.rvalue_rl_count == block_scope.break_count) { - // Neither prong of the if consumed the result location, so we can - // use break instructions to create an rvalue. - return .{ - .tag = .break_operand, - .elide_store_to_block_ptr_instructions = true, - }; - } else { - // Allow the store_to_block_ptr instructions to remain so that - // semantic analysis can turn them into bitcasts. - return .{ - .tag = .break_void, - .elide_store_to_block_ptr_instructions = false, - }; - } + else => ri, + }; + } + + fn zirTag(ri: ResultInfo) Zir.Inst.Tag { + switch (ri.rl) { + .ty => return switch (ri.ctx) { + .shift_op => .as_shift_operand, + else => .as_node, }, + else => unreachable, } } - /// Turns a `coerced_ty` back into a `ty`. Should be called at branch points - /// such as if and switch expressions. - fn br(rl: ResultLoc) ResultLoc { - return switch (rl) { - .coerced_ty => |ty| .{ .ty = ty }, - else => rl, + pub const Loc = union(enum) { + /// The expression is the right-hand side of assignment to `_`. Only the side-effects of the + /// expression should be generated. The result instruction from the expression must + /// be ignored. + discard, + /// The expression has an inferred type, and it will be evaluated as an rvalue. + none, + /// The expression must generate a pointer rather than a value. For example, the left hand side + /// of an assignment uses this kind of result location. + ref, + /// The expression will be coerced into this type, but it will be evaluated as an rvalue. + ty: Zir.Inst.Ref, + /// Same as `ty` but it is guaranteed that Sema will additionally perform the coercion, + /// so no `as` instruction needs to be emitted. + coerced_ty: Zir.Inst.Ref, + /// The expression must store its result into this typed pointer. The result instruction + /// from the expression must be ignored. + ptr: PtrResultLoc, + /// The expression must store its result into this allocation, which has an inferred type. + /// The result instruction from the expression must be ignored. + /// Always an instruction with tag `alloc_inferred`. + inferred_ptr: Zir.Inst.Ref, + /// There is a pointer for the expression to store its result into, however, its type + /// is inferred based on peer type resolution for a `Zir.Inst.Block`. + /// The result instruction from the expression must be ignored. + block_ptr: *GenZir, + + const PtrResultLoc = struct { + inst: Zir.Inst.Ref, + src_node: ?Ast.Node.Index = null, }; - } - fn zirTag(rl: ResultLoc) Zir.Inst.Tag { - return switch (rl) { - .ty => .as_node, - .ty_shift_operand => .as_shift_operand, - else => unreachable, + pub const Strategy = struct { + elide_store_to_block_ptr_instructions: bool, + tag: Tag, + + pub const Tag = enum { + /// Both branches will use break_void; result location is used to communicate the + /// result instruction. + break_void, + /// Use break statements to pass the block result value, and call rvalue() at + /// the end depending on rl. Also elide the store_to_block_ptr instructions + /// depending on rl. + break_operand, + }; }; - } + + fn strategy(rl: Loc, block_scope: *GenZir) Strategy { + switch (rl) { + // In this branch there will not be any store_to_block_ptr instructions. + .none, .ty, .coerced_ty, .ref => return .{ + .tag = .break_operand, + .elide_store_to_block_ptr_instructions = false, + }, + .discard => return .{ + .tag = .break_void, + .elide_store_to_block_ptr_instructions = false, + }, + // The pointer got passed through to the sub-expressions, so we will use + // break_void here. + // In this branch there will not be any store_to_block_ptr instructions. + .ptr => return .{ + .tag = .break_void, + .elide_store_to_block_ptr_instructions = false, + }, + .inferred_ptr, .block_ptr => { + if (block_scope.rvalue_rl_count == block_scope.break_count) { + // Neither prong of the if consumed the result location, so we can + // use break instructions to create an rvalue. + return .{ + .tag = .break_operand, + .elide_store_to_block_ptr_instructions = true, + }; + } else { + // Allow the store_to_block_ptr instructions to remain so that + // semantic analysis can turn them into bitcasts. + return .{ + .tag = .break_void, + .elide_store_to_block_ptr_instructions = false, + }; + } + }, + } + } + }; + + pub const Context = enum { + /// The expression is the operand to a return expression. + @"return", + /// The expression is the input to an error-handling operator (if-else, try, or catch). + error_handling_expr, + /// The expression is the right-hand side of a shift operation. + shift_op, + /// No specific operator in particular. + none, + }; }; -pub const align_rl: ResultLoc = .{ .ty = .u29_type }; -pub const coerced_align_rl: ResultLoc = .{ .coerced_ty = .u29_type }; -pub const bool_rl: ResultLoc = .{ .ty = .bool_type }; -pub const type_rl: ResultLoc = .{ .ty = .type_type }; -pub const coerced_type_rl: ResultLoc = .{ .coerced_ty = .type_type }; +pub const align_ri: ResultInfo = .{ .rl = .{ .ty = .u29_type } }; +pub const coerced_align_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .u29_type } }; +pub const bool_ri: ResultInfo = .{ .rl = .{ .ty = .bool_type } }; +pub const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } }; +pub const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } }; fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zir.Inst.Ref { const prev_force_comptime = gz.force_comptime; gz.force_comptime = true; defer gz.force_comptime = prev_force_comptime; - return expr(gz, scope, coerced_type_rl, type_node); + return expr(gz, scope, coerced_type_ri, type_node); } fn reachableTypeExpr( @@ -346,24 +364,24 @@ fn reachableTypeExpr( gz.force_comptime = true; defer gz.force_comptime = prev_force_comptime; - return reachableExpr(gz, scope, coerced_type_rl, type_node, reachable_node); + return reachableExpr(gz, scope, coerced_type_ri, type_node, reachable_node); } /// Same as `expr` but fails with a compile error if the result type is `noreturn`. fn reachableExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, reachable_node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { - return reachableExprComptime(gz, scope, rl, node, reachable_node, false); + return reachableExprComptime(gz, scope, ri, node, reachable_node, false); } fn reachableExprComptime( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, reachable_node: Ast.Node.Index, force_comptime: bool, @@ -372,7 +390,7 @@ fn reachableExprComptime( gz.force_comptime = prev_force_comptime or force_comptime; defer gz.force_comptime = prev_force_comptime; - const result_inst = try expr(gz, scope, rl, node); + const result_inst = try expr(gz, scope, ri, node); if (gz.refIsNoReturn(result_inst)) { try gz.astgen.appendErrorNodeNotes(reachable_node, "unreachable code", .{}, &[_]u32{ try gz.astgen.errNoteNode(node, "control flow is diverted here", .{}), @@ -573,14 +591,14 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins .@"orelse", => {}, } - return expr(gz, scope, .ref, node); + return expr(gz, scope, .{ .rl = .ref }, node); } /// Turn Zig AST into untyped ZIR instructions. /// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the /// result instruction can be used to inspect whether it is isNoReturn() but that is it, /// it must otherwise not be used. -fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { +fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; const tree = astgen.tree; const main_tokens = tree.nodes.items(.main_token); @@ -621,161 +639,161 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr .assign => { try assign(gz, scope, node); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_shl => { try assignShift(gz, scope, node, .shl); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_shl_sat => { try assignShiftSat(gz, scope, node); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_shr => { try assignShift(gz, scope, node, .shr); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_bit_and => { try assignOp(gz, scope, node, .bit_and); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_bit_or => { try assignOp(gz, scope, node, .bit_or); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_bit_xor => { try assignOp(gz, scope, node, .xor); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_div => { try assignOp(gz, scope, node, .div); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_sub => { try assignOp(gz, scope, node, .sub); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_sub_wrap => { try assignOp(gz, scope, node, .subwrap); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_sub_sat => { try assignOp(gz, scope, node, .sub_sat); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_mod => { try assignOp(gz, scope, node, .mod_rem); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_add => { try assignOp(gz, scope, node, .add); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_add_wrap => { try assignOp(gz, scope, node, .addwrap); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_add_sat => { try assignOp(gz, scope, node, .add_sat); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_mul => { try assignOp(gz, scope, node, .mul); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_mul_wrap => { try assignOp(gz, scope, node, .mulwrap); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .assign_mul_sat => { try assignOp(gz, scope, node, .mul_sat); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, // zig fmt: off - .shl => return shiftOp(gz, scope, rl, node, node_datas[node].lhs, node_datas[node].rhs, .shl), - .shr => return shiftOp(gz, scope, rl, node, node_datas[node].lhs, node_datas[node].rhs, .shr), - - .add => return simpleBinOp(gz, scope, rl, node, .add), - .add_wrap => return simpleBinOp(gz, scope, rl, node, .addwrap), - .add_sat => return simpleBinOp(gz, scope, rl, node, .add_sat), - .sub => return simpleBinOp(gz, scope, rl, node, .sub), - .sub_wrap => return simpleBinOp(gz, scope, rl, node, .subwrap), - .sub_sat => return simpleBinOp(gz, scope, rl, node, .sub_sat), - .mul => return simpleBinOp(gz, scope, rl, node, .mul), - .mul_wrap => return simpleBinOp(gz, scope, rl, node, .mulwrap), - .mul_sat => return simpleBinOp(gz, scope, rl, node, .mul_sat), - .div => return simpleBinOp(gz, scope, rl, node, .div), - .mod => return simpleBinOp(gz, scope, rl, node, .mod_rem), - .shl_sat => return simpleBinOp(gz, scope, rl, node, .shl_sat), - - .bit_and => return simpleBinOp(gz, scope, rl, node, .bit_and), - .bit_or => return simpleBinOp(gz, scope, rl, node, .bit_or), - .bit_xor => return simpleBinOp(gz, scope, rl, node, .xor), - .bang_equal => return simpleBinOp(gz, scope, rl, node, .cmp_neq), - .equal_equal => return simpleBinOp(gz, scope, rl, node, .cmp_eq), - .greater_than => return simpleBinOp(gz, scope, rl, node, .cmp_gt), - .greater_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_gte), - .less_than => return simpleBinOp(gz, scope, rl, node, .cmp_lt), - .less_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_lte), - .array_cat => return simpleBinOp(gz, scope, rl, node, .array_cat), + .shl => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shl), + .shr => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shr), + + .add => return simpleBinOp(gz, scope, ri, node, .add), + .add_wrap => return simpleBinOp(gz, scope, ri, node, .addwrap), + .add_sat => return simpleBinOp(gz, scope, ri, node, .add_sat), + .sub => return simpleBinOp(gz, scope, ri, node, .sub), + .sub_wrap => return simpleBinOp(gz, scope, ri, node, .subwrap), + .sub_sat => return simpleBinOp(gz, scope, ri, node, .sub_sat), + .mul => return simpleBinOp(gz, scope, ri, node, .mul), + .mul_wrap => return simpleBinOp(gz, scope, ri, node, .mulwrap), + .mul_sat => return simpleBinOp(gz, scope, ri, node, .mul_sat), + .div => return simpleBinOp(gz, scope, ri, node, .div), + .mod => return simpleBinOp(gz, scope, ri, node, .mod_rem), + .shl_sat => return simpleBinOp(gz, scope, ri, node, .shl_sat), + + .bit_and => return simpleBinOp(gz, scope, ri, node, .bit_and), + .bit_or => return simpleBinOp(gz, scope, ri, node, .bit_or), + .bit_xor => return simpleBinOp(gz, scope, ri, node, .xor), + .bang_equal => return simpleBinOp(gz, scope, ri, node, .cmp_neq), + .equal_equal => return simpleBinOp(gz, scope, ri, node, .cmp_eq), + .greater_than => return simpleBinOp(gz, scope, ri, node, .cmp_gt), + .greater_or_equal => return simpleBinOp(gz, scope, ri, node, .cmp_gte), + .less_than => return simpleBinOp(gz, scope, ri, node, .cmp_lt), + .less_or_equal => return simpleBinOp(gz, scope, ri, node, .cmp_lte), + .array_cat => return simpleBinOp(gz, scope, ri, node, .array_cat), .array_mult => { const result = try gz.addPlNode(.array_mul, node, Zir.Inst.Bin{ - .lhs = try expr(gz, scope, .none, node_datas[node].lhs), - .rhs = try comptimeExpr(gz, scope, .{ .coerced_ty = .usize_type }, node_datas[node].rhs), + .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs), + .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, - .error_union => return simpleBinOp(gz, scope, rl, node, .error_union_type), - .merge_error_sets => return simpleBinOp(gz, scope, rl, node, .merge_error_sets), + .error_union => return simpleBinOp(gz, scope, ri, node, .error_union_type), + .merge_error_sets => return simpleBinOp(gz, scope, ri, node, .merge_error_sets), - .bool_and => return boolBinOp(gz, scope, rl, node, .bool_br_and), - .bool_or => return boolBinOp(gz, scope, rl, node, .bool_br_or), + .bool_and => return boolBinOp(gz, scope, ri, node, .bool_br_and), + .bool_or => return boolBinOp(gz, scope, ri, node, .bool_br_or), - .bool_not => return simpleUnOp(gz, scope, rl, node, bool_rl, node_datas[node].lhs, .bool_not), - .bit_not => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .bit_not), + .bool_not => return simpleUnOp(gz, scope, ri, node, bool_ri, node_datas[node].lhs, .bool_not), + .bit_not => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .bit_not), - .negation => return negation(gz, scope, rl, node), - .negation_wrap => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .negate_wrap), + .negation => return negation(gz, scope, ri, node), + .negation_wrap => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .negate_wrap), - .identifier => return identifier(gz, scope, rl, node), + .identifier => return identifier(gz, scope, ri, node), - .asm_simple => return asmExpr(gz, scope, rl, node, tree.asmSimple(node)), - .@"asm" => return asmExpr(gz, scope, rl, node, tree.asmFull(node)), + .asm_simple => return asmExpr(gz, scope, ri, node, tree.asmSimple(node)), + .@"asm" => return asmExpr(gz, scope, ri, node, tree.asmFull(node)), - .string_literal => return stringLiteral(gz, rl, node), - .multiline_string_literal => return multilineStringLiteral(gz, rl, node), + .string_literal => return stringLiteral(gz, ri, node), + .multiline_string_literal => return multilineStringLiteral(gz, ri, node), - .number_literal => return numberLiteral(gz, rl, node, node, .positive), + .number_literal => return numberLiteral(gz, ri, node, node, .positive), // zig fmt: on .builtin_call_two, .builtin_call_two_comma => { if (node_datas[node].lhs == 0) { const params = [_]Ast.Node.Index{}; - return builtinCall(gz, scope, rl, node, ¶ms); + return builtinCall(gz, scope, ri, node, ¶ms); } else if (node_datas[node].rhs == 0) { const params = [_]Ast.Node.Index{node_datas[node].lhs}; - return builtinCall(gz, scope, rl, node, ¶ms); + return builtinCall(gz, scope, ri, node, ¶ms); } else { const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; - return builtinCall(gz, scope, rl, node, ¶ms); + return builtinCall(gz, scope, ri, node, ¶ms); } }, .builtin_call, .builtin_call_comma => { const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; - return builtinCall(gz, scope, rl, node, params); + return builtinCall(gz, scope, ri, node, params); }, .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => { var params: [1]Ast.Node.Index = undefined; - return callExpr(gz, scope, rl, node, tree.callOne(¶ms, node)); + return callExpr(gz, scope, ri, node, tree.callOne(¶ms, node)); }, .call, .call_comma, .async_call, .async_call_comma => { - return callExpr(gz, scope, rl, node, tree.callFull(node)); + return callExpr(gz, scope, ri, node, tree.callFull(node)); }, .unreachable_literal => { @@ -790,112 +808,112 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr return Zir.Inst.Ref.unreachable_value; }, .@"return" => return ret(gz, scope, node), - .field_access => return fieldAccess(gz, scope, rl, node), + .field_access => return fieldAccess(gz, scope, ri, node), - .if_simple => return ifExpr(gz, scope, rl.br(), node, tree.ifSimple(node)), - .@"if" => return ifExpr(gz, scope, rl.br(), node, tree.ifFull(node)), + .if_simple => return ifExpr(gz, scope, ri.br(), node, tree.ifSimple(node)), + .@"if" => return ifExpr(gz, scope, ri.br(), node, tree.ifFull(node)), - .while_simple => return whileExpr(gz, scope, rl.br(), node, tree.whileSimple(node), false), - .while_cont => return whileExpr(gz, scope, rl.br(), node, tree.whileCont(node), false), - .@"while" => return whileExpr(gz, scope, rl.br(), node, tree.whileFull(node), false), + .while_simple => return whileExpr(gz, scope, ri.br(), node, tree.whileSimple(node), false), + .while_cont => return whileExpr(gz, scope, ri.br(), node, tree.whileCont(node), false), + .@"while" => return whileExpr(gz, scope, ri.br(), node, tree.whileFull(node), false), - .for_simple => return forExpr(gz, scope, rl.br(), node, tree.forSimple(node), false), - .@"for" => return forExpr(gz, scope, rl.br(), node, tree.forFull(node), false), + .for_simple => return forExpr(gz, scope, ri.br(), node, tree.forSimple(node), false), + .@"for" => return forExpr(gz, scope, ri.br(), node, tree.forFull(node), false), .slice_open => { - const lhs = try expr(gz, scope, .ref, node_datas[node].lhs); - const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, node_datas[node].rhs); + const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); + const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{ .lhs = lhs, .start = start, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .slice => { - const lhs = try expr(gz, scope, .ref, node_datas[node].lhs); + const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice); - const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.start); - const end = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.end); + const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start); + const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end); const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{ .lhs = lhs, .start = start, .end = end, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .slice_sentinel => { - const lhs = try expr(gz, scope, .ref, node_datas[node].lhs); + const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel); - const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.start); - const end = if (extra.end != 0) try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.end) else .none; - const sentinel = try expr(gz, scope, .none, extra.sentinel); + const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start); + const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none; + const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel); const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{ .lhs = lhs, .start = start, .end = end, .sentinel = sentinel, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .deref => { - const lhs = try expr(gz, scope, .none, node_datas[node].lhs); + const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs); _ = try gz.addUnNode(.validate_deref, lhs, node); - switch (rl) { - .ref, .catch_ref => return lhs, + switch (ri.rl) { + .ref => return lhs, else => { const result = try gz.addUnNode(.load, lhs, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, } }, .address_of => { - const result = try expr(gz, scope, .ref, node_datas[node].lhs); - return rvalue(gz, rl, result, node); + const result = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); + return rvalue(gz, ri, result, node); }, .optional_type => { const operand = try typeExpr(gz, scope, node_datas[node].lhs); const result = try gz.addUnNode(.optional_type, operand, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, - .unwrap_optional => switch (rl) { - .ref, .catch_ref => return gz.addUnNode( + .unwrap_optional => switch (ri.rl) { + .ref => return gz.addUnNode( .optional_payload_safe_ptr, - try expr(gz, scope, .ref, node_datas[node].lhs), + try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs), node, ), - else => return rvalue(gz, rl, try gz.addUnNode( + else => return rvalue(gz, ri, try gz.addUnNode( .optional_payload_safe, - try expr(gz, scope, .none, node_datas[node].lhs), + try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs), node, ), node), }, .block_two, .block_two_semicolon => { const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; if (node_datas[node].lhs == 0) { - return blockExpr(gz, scope, rl, node, statements[0..0]); + return blockExpr(gz, scope, ri, node, statements[0..0]); } else if (node_datas[node].rhs == 0) { - return blockExpr(gz, scope, rl, node, statements[0..1]); + return blockExpr(gz, scope, ri, node, statements[0..1]); } else { - return blockExpr(gz, scope, rl, node, statements[0..2]); + return blockExpr(gz, scope, ri, node, statements[0..2]); } }, .block, .block_semicolon => { const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; - return blockExpr(gz, scope, rl, node, statements); + return blockExpr(gz, scope, ri, node, statements); }, - .enum_literal => return simpleStrTok(gz, rl, main_tokens[node], node, .enum_literal), - .error_value => return simpleStrTok(gz, rl, node_datas[node].rhs, node, .error_value), + .enum_literal => return simpleStrTok(gz, ri, main_tokens[node], node, .enum_literal), + .error_value => return simpleStrTok(gz, ri, node_datas[node].rhs, node, .error_value), // TODO restore this when implementing https://github.com/ziglang/zig/issues/6025 - // .anyframe_literal => return rvalue(gz, rl, .anyframe_type, node), + // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node), .anyframe_literal => { const result = try gz.addUnNode(.anyframe_type, .void_type, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .anyframe_type => { const return_type = try typeExpr(gz, scope, node_datas[node].rhs); const result = try gz.addUnNode(.anyframe_type, return_type, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .@"catch" => { const catch_token = main_tokens[node]; @@ -903,11 +921,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr catch_token + 2 else null; - switch (rl) { - .ref, .catch_ref => return orelseCatchExpr( + switch (ri.rl) { + .ref => return orelseCatchExpr( gz, scope, - rl, + ri, node, node_datas[node].lhs, .is_non_err_ptr, @@ -919,7 +937,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr else => return orelseCatchExpr( gz, scope, - rl, + ri, node, node_datas[node].lhs, .is_non_err, @@ -930,11 +948,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr ), } }, - .@"orelse" => switch (rl) { - .ref, .catch_ref => return orelseCatchExpr( + .@"orelse" => switch (ri.rl) { + .ref => return orelseCatchExpr( gz, scope, - rl, + ri, node, node_datas[node].lhs, .is_non_null_ptr, @@ -946,7 +964,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr else => return orelseCatchExpr( gz, scope, - rl, + ri, node, node_datas[node].lhs, .is_non_null, @@ -957,94 +975,94 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr ), }, - .ptr_type_aligned => return ptrType(gz, scope, rl, node, tree.ptrTypeAligned(node)), - .ptr_type_sentinel => return ptrType(gz, scope, rl, node, tree.ptrTypeSentinel(node)), - .ptr_type => return ptrType(gz, scope, rl, node, tree.ptrType(node)), - .ptr_type_bit_range => return ptrType(gz, scope, rl, node, tree.ptrTypeBitRange(node)), + .ptr_type_aligned => return ptrType(gz, scope, ri, node, tree.ptrTypeAligned(node)), + .ptr_type_sentinel => return ptrType(gz, scope, ri, node, tree.ptrTypeSentinel(node)), + .ptr_type => return ptrType(gz, scope, ri, node, tree.ptrType(node)), + .ptr_type_bit_range => return ptrType(gz, scope, ri, node, tree.ptrTypeBitRange(node)), .container_decl, .container_decl_trailing, - => return containerDecl(gz, scope, rl, node, tree.containerDecl(node)), + => return containerDecl(gz, scope, ri, node, tree.containerDecl(node)), .container_decl_two, .container_decl_two_trailing => { var buffer: [2]Ast.Node.Index = undefined; - return containerDecl(gz, scope, rl, node, tree.containerDeclTwo(&buffer, node)); + return containerDecl(gz, scope, ri, node, tree.containerDeclTwo(&buffer, node)); }, .container_decl_arg, .container_decl_arg_trailing, - => return containerDecl(gz, scope, rl, node, tree.containerDeclArg(node)), + => return containerDecl(gz, scope, ri, node, tree.containerDeclArg(node)), .tagged_union, .tagged_union_trailing, - => return containerDecl(gz, scope, rl, node, tree.taggedUnion(node)), + => return containerDecl(gz, scope, ri, node, tree.taggedUnion(node)), .tagged_union_two, .tagged_union_two_trailing => { var buffer: [2]Ast.Node.Index = undefined; - return containerDecl(gz, scope, rl, node, tree.taggedUnionTwo(&buffer, node)); + return containerDecl(gz, scope, ri, node, tree.taggedUnionTwo(&buffer, node)); }, .tagged_union_enum_tag, .tagged_union_enum_tag_trailing, - => return containerDecl(gz, scope, rl, node, tree.taggedUnionEnumTag(node)), + => return containerDecl(gz, scope, ri, node, tree.taggedUnionEnumTag(node)), .@"break" => return breakExpr(gz, scope, node), .@"continue" => return continueExpr(gz, scope, node), - .grouped_expression => return expr(gz, scope, rl, node_datas[node].lhs), - .array_type => return arrayType(gz, scope, rl, node), - .array_type_sentinel => return arrayTypeSentinel(gz, scope, rl, node), - .char_literal => return charLiteral(gz, rl, node), - .error_set_decl => return errorSetDecl(gz, rl, node), - .array_access => return arrayAccess(gz, scope, rl, node), - .@"comptime" => return comptimeExprAst(gz, scope, rl, node), - .@"switch", .switch_comma => return switchExpr(gz, scope, rl.br(), node), - - .@"nosuspend" => return nosuspendExpr(gz, scope, rl, node), + .grouped_expression => return expr(gz, scope, ri, node_datas[node].lhs), + .array_type => return arrayType(gz, scope, ri, node), + .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node), + .char_literal => return charLiteral(gz, ri, node), + .error_set_decl => return errorSetDecl(gz, ri, node), + .array_access => return arrayAccess(gz, scope, ri, node), + .@"comptime" => return comptimeExprAst(gz, scope, ri, node), + .@"switch", .switch_comma => return switchExpr(gz, scope, ri.br(), node), + + .@"nosuspend" => return nosuspendExpr(gz, scope, ri, node), .@"suspend" => return suspendExpr(gz, scope, node), - .@"await" => return awaitExpr(gz, scope, rl, node), - .@"resume" => return resumeExpr(gz, scope, rl, node), + .@"await" => return awaitExpr(gz, scope, ri, node), + .@"resume" => return resumeExpr(gz, scope, ri, node), - .@"try" => return tryExpr(gz, scope, rl, node, node_datas[node].lhs), + .@"try" => return tryExpr(gz, scope, ri, node, node_datas[node].lhs), .array_init_one, .array_init_one_comma => { var elements: [1]Ast.Node.Index = undefined; - return arrayInitExpr(gz, scope, rl, node, tree.arrayInitOne(&elements, node)); + return arrayInitExpr(gz, scope, ri, node, tree.arrayInitOne(&elements, node)); }, .array_init_dot_two, .array_init_dot_two_comma => { var elements: [2]Ast.Node.Index = undefined; - return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDotTwo(&elements, node)); + return arrayInitExpr(gz, scope, ri, node, tree.arrayInitDotTwo(&elements, node)); }, .array_init_dot, .array_init_dot_comma, - => return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDot(node)), + => return arrayInitExpr(gz, scope, ri, node, tree.arrayInitDot(node)), .array_init, .array_init_comma, - => return arrayInitExpr(gz, scope, rl, node, tree.arrayInit(node)), + => return arrayInitExpr(gz, scope, ri, node, tree.arrayInit(node)), .struct_init_one, .struct_init_one_comma => { var fields: [1]Ast.Node.Index = undefined; - return structInitExpr(gz, scope, rl, node, tree.structInitOne(&fields, node)); + return structInitExpr(gz, scope, ri, node, tree.structInitOne(&fields, node)); }, .struct_init_dot_two, .struct_init_dot_two_comma => { var fields: [2]Ast.Node.Index = undefined; - return structInitExpr(gz, scope, rl, node, tree.structInitDotTwo(&fields, node)); + return structInitExpr(gz, scope, ri, node, tree.structInitDotTwo(&fields, node)); }, .struct_init_dot, .struct_init_dot_comma, - => return structInitExpr(gz, scope, rl, node, tree.structInitDot(node)), + => return structInitExpr(gz, scope, ri, node, tree.structInitDot(node)), .struct_init, .struct_init_comma, - => return structInitExpr(gz, scope, rl, node, tree.structInit(node)), + => return structInitExpr(gz, scope, ri, node, tree.structInit(node)), .fn_proto_simple => { var params: [1]Ast.Node.Index = undefined; - return fnProtoExpr(gz, scope, rl, node, tree.fnProtoSimple(¶ms, node)); + return fnProtoExpr(gz, scope, ri, node, tree.fnProtoSimple(¶ms, node)); }, .fn_proto_multi => { - return fnProtoExpr(gz, scope, rl, node, tree.fnProtoMulti(node)); + return fnProtoExpr(gz, scope, ri, node, tree.fnProtoMulti(node)); }, .fn_proto_one => { var params: [1]Ast.Node.Index = undefined; - return fnProtoExpr(gz, scope, rl, node, tree.fnProtoOne(¶ms, node)); + return fnProtoExpr(gz, scope, ri, node, tree.fnProtoOne(¶ms, node)); }, .fn_proto => { - return fnProtoExpr(gz, scope, rl, node, tree.fnProto(node)); + return fnProtoExpr(gz, scope, ri, node, tree.fnProto(node)); }, } } @@ -1052,7 +1070,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr fn nosuspendExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; @@ -1067,7 +1085,7 @@ fn nosuspendExpr( } gz.nosuspend_node = node; defer gz.nosuspend_node = 0; - return expr(gz, scope, rl, body_node); + return expr(gz, scope, ri, body_node); } fn suspendExpr( @@ -1100,7 +1118,7 @@ fn suspendExpr( suspend_scope.suspend_node = node; defer suspend_scope.unstack(); - const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node); + const body_result = try expr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node); if (!gz.refIsNoReturn(body_result)) { _ = try suspend_scope.addBreak(.break_inline, suspend_inst, .void_value); } @@ -1112,7 +1130,7 @@ fn suspendExpr( fn awaitExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; @@ -1125,7 +1143,7 @@ fn awaitExpr( try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}), }); } - const operand = try expr(gz, scope, .none, rhs_node); + const operand = try expr(gz, scope, .{ .rl = .none }, rhs_node); const result = if (gz.nosuspend_node != 0) try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), @@ -1134,28 +1152,28 @@ fn awaitExpr( else try gz.addUnNode(.@"await", operand, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn resumeExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; const tree = astgen.tree; const node_datas = tree.nodes.items(.data); const rhs_node = node_datas[node].lhs; - const operand = try expr(gz, scope, .none, rhs_node); + const operand = try expr(gz, scope, .{ .rl = .none }, rhs_node); const result = try gz.addUnNode(.@"resume", operand, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn fnProtoExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, fn_proto: Ast.full.FnProto, ) InnerError!Zir.Inst.Ref { @@ -1221,7 +1239,7 @@ fn fnProtoExpr( assert(param_type_node != 0); var param_gz = block_scope.makeSubBlock(scope); defer param_gz.unstack(); - const param_type = try expr(¶m_gz, scope, coerced_type_rl, param_type_node); + const param_type = try expr(¶m_gz, scope, coerced_type_ri, param_type_node); const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); const main_tokens = tree.nodes.items(.main_token); @@ -1235,7 +1253,7 @@ fn fnProtoExpr( }; const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { - break :inst try expr(&block_scope, scope, align_rl, fn_proto.ast.align_expr); + break :inst try expr(&block_scope, scope, align_ri, fn_proto.ast.align_expr); }; if (fn_proto.ast.addrspace_expr != 0) { @@ -1250,7 +1268,7 @@ fn fnProtoExpr( try expr( &block_scope, scope, - .{ .ty = .calling_convention_type }, + .{ .rl = .{ .ty = .calling_convention_type } }, fn_proto.ast.callconv_expr, ) else @@ -1261,7 +1279,7 @@ fn fnProtoExpr( if (is_inferred_error) { return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); } - const ret_ty = try expr(&block_scope, scope, coerced_type_rl, fn_proto.ast.return_type); + const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type); const result = try block_scope.addFunc(.{ .src_node = fn_proto.ast.proto_node, @@ -1292,13 +1310,13 @@ fn fnProtoExpr( try block_scope.setBlockBody(block_inst); try gz.instructions.append(astgen.gpa, block_inst); - return rvalue(gz, rl, indexToRef(block_inst), fn_proto.ast.proto_node); + return rvalue(gz, ri, indexToRef(block_inst), fn_proto.ast.proto_node); } fn arrayInitExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, array_init: Ast.full.ArrayInit, ) InnerError!Zir.Inst.Ref { @@ -1340,7 +1358,7 @@ fn arrayInitExpr( .elem = elem_type, }; } else { - const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel); + const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel); const array_type_inst = try gz.addPlNode( .array_type_sentinel, array_init.ast.type_expr, @@ -1368,29 +1386,29 @@ fn arrayInitExpr( }; }; - switch (rl) { + switch (ri.rl) { .discard => { // TODO elements should still be coerced if type is provided for (array_init.ast.elements) |elem_init| { - _ = try expr(gz, scope, .discard, elem_init); + _ = try expr(gz, scope, .{ .rl = .discard }, elem_init); } return Zir.Inst.Ref.void_value; }, - .ref, .catch_ref => { + .ref => { const tag: Zir.Inst.Tag = if (types.array != .none) .array_init_ref else .array_init_anon_ref; return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag); }, - .none, .catch_none => { + .none => { const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon; return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag); }, - .ty, .ty_shift_operand, .coerced_ty => { + .ty, .coerced_ty => { const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon; const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .ptr => |ptr_res| { - return arrayInitExprRlPtr(gz, scope, rl, node, ptr_res.inst, array_init.ast.elements, types.array); + return arrayInitExprRlPtr(gz, scope, ri, node, ptr_res.inst, array_init.ast.elements, types.array); }, .inferred_ptr => |ptr_inst| { if (types.array == .none) { @@ -1398,9 +1416,9 @@ fn arrayInitExpr( // analyzing array_base_ptr against an alloc_inferred_mut. // See corresponding logic in structInitExpr. const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } else { - return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array); + return arrayInitExprRlPtr(gz, scope, ri, node, ptr_inst, array_init.ast.elements, types.array); } }, .block_ptr => |block_gz| { @@ -1408,9 +1426,9 @@ fn arrayInitExpr( // See corresponding logic in structInitExpr. if (types.array == .none and astgen.isInferred(block_gz.rl_ptr)) { const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } - return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, types.array); + return arrayInitExprRlPtr(gz, scope, ri, node, block_gz.rl_ptr, array_init.ast.elements, types.array); }, } } @@ -1430,7 +1448,7 @@ fn arrayInitExprRlNone( var extra_index = try reserveExtra(astgen, elements.len); for (elements) |elem_init| { - const elem_ref = try expr(gz, scope, .none, elem_init); + const elem_ref = try expr(gz, scope, .{ .rl = .none }, elem_init); astgen.extra.items[extra_index] = @enumToInt(elem_ref); extra_index += 1; } @@ -1459,9 +1477,9 @@ fn arrayInitExprInner( } for (elements) |elem_init, i| { - const rl = if (elem_ty != .none) - ResultLoc{ .coerced_ty = elem_ty } - else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) rl: { + const ri = if (elem_ty != .none) + ResultInfo{ .rl = .{ .coerced_ty = elem_ty } } + else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) ri: { const ty_expr = try gz.add(.{ .tag = .elem_type_index, .data = .{ .bin = .{ @@ -1469,10 +1487,10 @@ fn arrayInitExprInner( .rhs = @intToEnum(Zir.Inst.Ref, i), } }, }); - break :rl ResultLoc{ .coerced_ty = ty_expr }; - } else ResultLoc{ .none = {} }; + break :ri ResultInfo{ .rl = .{ .coerced_ty = ty_expr } }; + } else ResultInfo{ .rl = .{ .none = {} } }; - const elem_ref = try expr(gz, scope, rl, elem_init); + const elem_ref = try expr(gz, scope, ri, elem_init); astgen.extra.items[extra_index] = @enumToInt(elem_ref); extra_index += 1; } @@ -1483,7 +1501,7 @@ fn arrayInitExprInner( fn arrayInitExprRlPtr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, result_ptr: Zir.Inst.Ref, elements: []const Ast.Node.Index, @@ -1498,7 +1516,7 @@ fn arrayInitExprRlPtr( defer as_scope.unstack(); const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements); - return as_scope.finishCoercion(gz, rl, node, result, array_ty); + return as_scope.finishCoercion(gz, ri, node, result, array_ty); } fn arrayInitExprRlPtrInner( @@ -1522,7 +1540,7 @@ fn arrayInitExprRlPtrInner( }); astgen.extra.items[extra_index] = refToIndex(elem_ptr).?; extra_index += 1; - _ = try expr(gz, scope, .{ .ptr = .{ .inst = elem_ptr } }, elem_init); + _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = elem_ptr } } }, elem_init); } const tag: Zir.Inst.Tag = if (gz.force_comptime) @@ -1537,7 +1555,7 @@ fn arrayInitExprRlPtrInner( fn structInitExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, struct_init: Ast.full.StructInit, ) InnerError!Zir.Inst.Ref { @@ -1546,7 +1564,7 @@ fn structInitExpr( if (struct_init.ast.type_expr == 0) { if (struct_init.ast.fields.len == 0) { - return rvalue(gz, rl, .empty_struct, node); + return rvalue(gz, ri, .empty_struct, node); } } else array: { const node_tags = tree.nodes.items(.tag); @@ -1558,7 +1576,7 @@ fn structInitExpr( if (struct_init.ast.fields.len == 0) { const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); const result = try gz.addUnNode(.struct_init_empty, ty_inst, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } break :array; }, @@ -1575,7 +1593,7 @@ fn structInitExpr( .rhs = elem_type, }); } else blk: { - const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel); + const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel); break :blk try gz.addPlNode( .array_type_sentinel, struct_init.ast.type_expr, @@ -1587,11 +1605,11 @@ fn structInitExpr( ); }; const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); const result = try gz.addUnNode(.struct_init_empty, ty_inst, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } else { return astgen.failNode( struct_init.ast.type_expr, @@ -1601,7 +1619,7 @@ fn structInitExpr( } } - switch (rl) { + switch (ri.rl) { .discard => { if (struct_init.ast.type_expr != 0) { const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); @@ -1612,7 +1630,7 @@ fn structInitExpr( } return Zir.Inst.Ref.void_value; }, - .ref, .catch_ref => { + .ref => { if (struct_init.ast.type_expr != 0) { const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node); @@ -1621,7 +1639,7 @@ fn structInitExpr( return structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon_ref); } }, - .none, .catch_none => { + .none => { if (struct_init.ast.type_expr != 0) { const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node); @@ -1630,26 +1648,26 @@ fn structInitExpr( return structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon); } }, - .ty, .ty_shift_operand, .coerced_ty => |ty_inst| { + .ty, .coerced_ty => |ty_inst| { if (struct_init.ast.type_expr == 0) { const result = try structInitExprRlNone(gz, scope, node, struct_init, ty_inst, .struct_init_anon); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); _ = try gz.addUnNode(.validate_struct_init_ty, inner_ty_inst, node); const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, - .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_res.inst), + .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, ri, node, struct_init, ptr_res.inst), .inferred_ptr => |ptr_inst| { if (struct_init.ast.type_expr == 0) { // We treat this case differently so that we don't get a crash when // analyzing field_base_ptr against an alloc_inferred_mut. // See corresponding logic in arrayInitExpr. const result = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } else { - return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst); + return structInitExprRlPtr(gz, scope, ri, node, struct_init, ptr_inst); } }, .block_ptr => |block_gz| { @@ -1657,10 +1675,10 @@ fn structInitExpr( // See corresponding logic in arrayInitExpr. if (struct_init.ast.type_expr == 0 and astgen.isInferred(block_gz.rl_ptr)) { const result = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } - return structInitExprRlPtr(gz, scope, rl, node, struct_init, block_gz.rl_ptr); + return structInitExprRlPtr(gz, scope, ri, node, struct_init, block_gz.rl_ptr); }, } } @@ -1685,16 +1703,15 @@ fn structInitExprRlNone( for (struct_init.ast.fields) |field_init| { const name_token = tree.firstToken(field_init) - 2; const str_index = try astgen.identAsString(name_token); - const sub_rl: ResultLoc = if (ty_inst != .none) - ResultLoc{ .ty = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{ + const sub_ri: ResultInfo = if (ty_inst != .none) + ResultInfo{ .rl = .{ .ty = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{ .container_type = ty_inst, .name_start = str_index, - }) } - else - .none; + }) } } + else .{ .rl = .none }; setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{ .field_name = str_index, - .init = try expr(gz, scope, sub_rl, field_init), + .init = try expr(gz, scope, sub_ri, field_init), }); extra_index += field_size; } @@ -1705,7 +1722,7 @@ fn structInitExprRlNone( fn structInitExprRlPtr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, struct_init: Ast.full.StructInit, result_ptr: Zir.Inst.Ref, @@ -1721,7 +1738,7 @@ fn structInitExprRlPtr( defer as_scope.unstack(); const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr); - return as_scope.finishCoercion(gz, rl, node, result, ty_inst); + return as_scope.finishCoercion(gz, ri, node, result, ty_inst); } fn structInitExprRlPtrInner( @@ -1748,7 +1765,7 @@ fn structInitExprRlPtrInner( }); astgen.extra.items[extra_index] = refToIndex(field_ptr).?; extra_index += 1; - _ = try expr(gz, scope, .{ .ptr = .{ .inst = field_ptr } }, field_init); + _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = field_ptr } } }, field_init); } const tag: Zir.Inst.Tag = if (gz.force_comptime) @@ -1786,7 +1803,7 @@ fn structInitExprRlTy( }); setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{ .field_type = refToIndex(field_ty_inst).?, - .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init), + .init = try expr(gz, scope, .{ .rl = .{ .ty = field_ty_inst } }, field_init), }); extra_index += field_size; } @@ -1799,14 +1816,14 @@ fn structInitExprRlTy( fn comptimeExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const prev_force_comptime = gz.force_comptime; gz.force_comptime = true; defer gz.force_comptime = prev_force_comptime; - return expr(gz, scope, rl, node); + return expr(gz, scope, ri, node); } /// This one is for an actual `comptime` syntax, and will emit a compile error if @@ -1815,7 +1832,7 @@ fn comptimeExpr( fn comptimeExprAst( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; @@ -1826,7 +1843,7 @@ fn comptimeExprAst( const node_datas = tree.nodes.items(.data); const body_node = node_datas[node].lhs; gz.force_comptime = true; - const result = try expr(gz, scope, rl, body_node); + const result = try expr(gz, scope, ri, body_node); gz.force_comptime = false; return result; } @@ -1904,7 +1921,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn } block_gz.break_count += 1; - const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_loc, rhs, node); + const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_info, rhs, node); const search_index = @intCast(Zir.Inst.Index, astgen.instructions.len); try genDefers(parent_gz, scope, parent_scope, .normal_only); @@ -1915,14 +1932,14 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn try popErrorReturnTrace( parent_gz, scope, - block_gz.break_result_loc, + block_gz.break_result_info, rhs, operand, err_trace_index_to_restore, ); } - switch (block_gz.break_result_loc) { + switch (block_gz.break_result_info.rl) { .block_ptr => { const br = try parent_gz.addBreak(break_tag, block_inst, operand); try block_gz.labeled_breaks.append(astgen.gpa, .{ .br = br, .search = search_index }); @@ -2028,7 +2045,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) fn blockExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, block_node: Ast.Node.Index, statements: []const Ast.Node.Index, ) InnerError!Zir.Inst.Ref { @@ -2044,12 +2061,12 @@ fn blockExpr( if (token_tags[lbrace - 1] == .colon and token_tags[lbrace - 2] == .identifier) { - return labeledBlockExpr(gz, scope, rl, block_node, statements); + return labeledBlockExpr(gz, scope, ri, block_node, statements); } var sub_gz = gz.makeSubBlock(scope); try blockExprStmts(&sub_gz, &sub_gz.base, statements); - return rvalue(gz, rl, .void_value, block_node); + return rvalue(gz, ri, .void_value, block_node); } fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.TokenIndex) !void { @@ -2087,7 +2104,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke fn labeledBlockExpr( gz: *GenZir, parent_scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, block_node: Ast.Node.Index, statements: []const Ast.Node.Index, ) InnerError!Zir.Inst.Ref { @@ -2116,7 +2133,7 @@ fn labeledBlockExpr( .token = label_token, .block_inst = block_inst, }; - block_scope.setBreakResultLoc(rl); + block_scope.setBreakResultInfo(ri); defer block_scope.unstack(); defer block_scope.labeled_breaks.deinit(astgen.gpa); @@ -2132,7 +2149,7 @@ fn labeledBlockExpr( const zir_datas = gz.astgen.instructions.items(.data); const zir_tags = gz.astgen.instructions.items(.tag); - const strat = rl.strategy(&block_scope); + const strat = ri.rl.strategy(&block_scope); switch (strat.tag) { .break_void => { // The code took advantage of the result location as a pointer. @@ -2173,9 +2190,9 @@ fn labeledBlockExpr( } try block_scope.setBlockBody(block_inst); const block_ref = indexToRef(block_inst); - switch (rl) { - .ref, .catch_ref => return block_ref, - else => return rvalue(gz, rl, block_ref, block_node), + switch (ri.rl) { + .ref => return block_ref, + else => return rvalue(gz, ri, block_ref, block_node), } }, } @@ -2246,12 +2263,12 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod continue; }, - .while_simple => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileSimple(inner_node), true), - .while_cont => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileCont(inner_node), true), - .@"while" => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileFull(inner_node), true), + .while_simple => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileSimple(inner_node), true), + .while_cont => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileCont(inner_node), true), + .@"while" => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileFull(inner_node), true), - .for_simple => _ = try forExpr(gz, scope, .discard, inner_node, tree.forSimple(inner_node), true), - .@"for" => _ = try forExpr(gz, scope, .discard, inner_node, tree.forFull(inner_node), true), + .for_simple => _ = try forExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.forSimple(inner_node), true), + .@"for" => _ = try forExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.forFull(inner_node), true), else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node), // zig fmt: on @@ -2272,7 +2289,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner try emitDbgNode(gz, statement); // We need to emit an error if the result is not `noreturn` or `void`, but // we want to avoid adding the ZIR instruction if possible for performance. - const maybe_unused_result = try expr(gz, scope, .none, statement); + const maybe_unused_result = try expr(gz, scope, .{ .rl = .none }, statement); return addEnsureResult(gz, maybe_unused_result, statement); } @@ -2839,7 +2856,7 @@ fn varDecl( } const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0) - try expr(gz, scope, align_rl, var_decl.ast.align_node) + try expr(gz, scope, align_ri, var_decl.ast.align_node) else .none; @@ -2856,12 +2873,12 @@ fn varDecl( if (align_inst == .none and !nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node, type_node != 0)) { - const result_loc: ResultLoc = if (type_node != 0) .{ - .ty = try typeExpr(gz, scope, type_node), - } else .none; + const result_info: ResultInfo = if (type_node != 0) .{ + .rl = .{ .ty = try typeExpr(gz, scope, type_node) }, + } else .{ .rl = .none }; const prev_anon_name_strategy = gz.anon_name_strategy; gz.anon_name_strategy = .dbg_var; - const init_inst = try reachableExpr(gz, scope, result_loc, var_decl.ast.init_node, node); + const init_inst = try reachableExpr(gz, scope, result_info, var_decl.ast.init_node, node); gz.anon_name_strategy = prev_anon_name_strategy; try gz.addDbgVar(.dbg_var_val, ident_name, init_inst); @@ -2931,8 +2948,8 @@ fn varDecl( init_scope.rl_ptr = alloc; init_scope.rl_ty_inst = .none; } - const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope }; - const init_inst = try reachableExpr(&init_scope, &init_scope.base, init_result_loc, var_decl.ast.init_node, node); + const init_result_info: ResultInfo = .{ .rl = .{ .block_ptr = &init_scope } }; + const init_inst = try reachableExpr(&init_scope, &init_scope.base, init_result_info, var_decl.ast.init_node, node); const zir_tags = astgen.instructions.items(.tag); const zir_datas = astgen.instructions.items(.data); @@ -3021,7 +3038,7 @@ fn varDecl( const is_comptime = var_decl.comptime_token != null or gz.force_comptime; var resolve_inferred_alloc: Zir.Inst.Ref = .none; const var_data: struct { - result_loc: ResultLoc, + result_info: ResultInfo, alloc: Zir.Inst.Ref, } = if (var_decl.ast.type_node != 0) a: { const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node); @@ -3043,7 +3060,7 @@ fn varDecl( } }; gz.rl_ty_inst = type_inst; - break :a .{ .alloc = alloc, .result_loc = .{ .ptr = .{ .inst = alloc } } }; + break :a .{ .alloc = alloc, .result_info = .{ .rl = .{ .ptr = .{ .inst = alloc } } } }; } else a: { const alloc = alloc: { if (align_inst == .none) { @@ -3064,11 +3081,11 @@ fn varDecl( }; gz.rl_ty_inst = .none; resolve_inferred_alloc = alloc; - break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } }; + break :a .{ .alloc = alloc, .result_info = .{ .rl = .{ .inferred_ptr = alloc } } }; }; const prev_anon_name_strategy = gz.anon_name_strategy; gz.anon_name_strategy = .dbg_var; - _ = try reachableExprComptime(gz, scope, var_data.result_loc, var_decl.ast.init_node, node, is_comptime); + _ = try reachableExprComptime(gz, scope, var_data.result_info, var_decl.ast.init_node, node, is_comptime); gz.anon_name_strategy = prev_anon_name_strategy; if (resolve_inferred_alloc != .none) { _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); @@ -3138,15 +3155,15 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi // This intentionally does not support `@"_"` syntax. const ident_name = tree.tokenSlice(main_tokens[lhs]); if (mem.eql(u8, ident_name, "_")) { - _ = try expr(gz, scope, .discard, rhs); + _ = try expr(gz, scope, .{ .rl = .discard }, rhs); return; } } const lvalue = try lvalExpr(gz, scope, lhs); - _ = try expr(gz, scope, .{ .ptr = .{ + _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = lvalue, .src_node = infix_node, - } }, rhs); + } } }, rhs); } fn assignOp( @@ -3163,7 +3180,7 @@ fn assignOp( const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node); - const rhs = try expr(gz, scope, .{ .coerced_ty = lhs_type }, node_datas[infix_node].rhs); + const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs); const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{ .lhs = lhs, @@ -3186,7 +3203,7 @@ fn assignShift( const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node); - const rhs = try expr(gz, scope, .{ .ty = rhs_type }, node_datas[infix_node].rhs); + const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, node_datas[infix_node].rhs); const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{ .lhs = lhs, @@ -3204,7 +3221,7 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); // Saturating shift-left allows any integer type for both the LHS and RHS. - const rhs = try expr(gz, scope, .none, node_datas[infix_node].rhs); + const rhs = try expr(gz, scope, .{ .rl = .none }, node_datas[infix_node].rhs); const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{ .lhs = lhs, @@ -3216,7 +3233,7 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE fn ptrType( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ptr_info: Ast.full.PtrType, ) InnerError!Zir.Inst.Ref { @@ -3234,21 +3251,21 @@ fn ptrType( var trailing_count: u32 = 0; if (ptr_info.ast.sentinel != 0) { - sentinel_ref = try expr(gz, scope, .{ .ty = elem_type }, ptr_info.ast.sentinel); + sentinel_ref = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, ptr_info.ast.sentinel); trailing_count += 1; } if (ptr_info.ast.align_node != 0) { - align_ref = try expr(gz, scope, coerced_align_rl, ptr_info.ast.align_node); + align_ref = try expr(gz, scope, coerced_align_ri, ptr_info.ast.align_node); trailing_count += 1; } if (ptr_info.ast.addrspace_node != 0) { - addrspace_ref = try expr(gz, scope, .{ .ty = .address_space_type }, ptr_info.ast.addrspace_node); + addrspace_ref = try expr(gz, scope, .{ .rl = .{ .ty = .address_space_type } }, ptr_info.ast.addrspace_node); trailing_count += 1; } if (ptr_info.ast.bit_range_start != 0) { assert(ptr_info.ast.bit_range_end != 0); - bit_start_ref = try expr(gz, scope, .{ .coerced_ty = .u16_type }, ptr_info.ast.bit_range_start); - bit_end_ref = try expr(gz, scope, .{ .coerced_ty = .u16_type }, ptr_info.ast.bit_range_end); + bit_start_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start); + bit_end_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_end); trailing_count += 2; } @@ -3295,10 +3312,10 @@ fn ptrType( } }); gz.instructions.appendAssumeCapacity(new_index); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } -fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Zir.Inst.Ref { +fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref { const astgen = gz.astgen; const tree = astgen.tree; const node_datas = tree.nodes.items(.data); @@ -3311,17 +3328,17 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Z { return astgen.failNode(len_node, "unable to infer array size", .{}); } - const len = try expr(gz, scope, .{ .coerced_ty = .usize_type }, len_node); + const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node); const elem_type = try typeExpr(gz, scope, node_datas[node].rhs); const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{ .lhs = len, .rhs = elem_type, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } -fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Zir.Inst.Ref { +fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref { const astgen = gz.astgen; const tree = astgen.tree; const node_datas = tree.nodes.items(.data); @@ -3335,16 +3352,16 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I { return astgen.failNode(len_node, "unable to infer array size", .{}); } - const len = try reachableExpr(gz, scope, .{ .coerced_ty = .usize_type }, len_node, node); + const len = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node); const elem_type = try typeExpr(gz, scope, extra.elem_type); - const sentinel = try reachableExpr(gz, scope, .{ .coerced_ty = elem_type }, extra.sentinel, node); + const sentinel = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = elem_type } }, extra.sentinel, node); const result = try gz.addPlNode(.array_type_sentinel, node, Zir.Inst.ArrayTypeSentinel{ .len = len, .elem_type = elem_type, .sentinel = sentinel, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } const WipMembers = struct { @@ -3580,7 +3597,7 @@ fn fnDecl( assert(param_type_node != 0); var param_gz = decl_gz.makeSubBlock(scope); defer param_gz.unstack(); - const param_type = try expr(¶m_gz, params_scope, coerced_type_rl, param_type_node); + const param_type = try expr(¶m_gz, params_scope, coerced_type_ri, param_type_node); const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); @@ -3629,7 +3646,7 @@ fn fnDecl( var align_gz = decl_gz.makeSubBlock(params_scope); defer align_gz.unstack(); const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { - const inst = try expr(&decl_gz, params_scope, coerced_align_rl, fn_proto.ast.align_expr); + const inst = try expr(&decl_gz, params_scope, coerced_align_ri, fn_proto.ast.align_expr); if (align_gz.instructionsSlice().len == 0) { // In this case we will send a len=0 body which can be encoded more efficiently. break :inst inst; @@ -3641,7 +3658,7 @@ fn fnDecl( var addrspace_gz = decl_gz.makeSubBlock(params_scope); defer addrspace_gz.unstack(); const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: { - const inst = try expr(&decl_gz, params_scope, .{ .coerced_ty = .address_space_type }, fn_proto.ast.addrspace_expr); + const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .address_space_type } }, fn_proto.ast.addrspace_expr); if (addrspace_gz.instructionsSlice().len == 0) { // In this case we will send a len=0 body which can be encoded more efficiently. break :inst inst; @@ -3653,7 +3670,7 @@ fn fnDecl( var section_gz = decl_gz.makeSubBlock(params_scope); defer section_gz.unstack(); const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: { - const inst = try expr(&decl_gz, params_scope, .{ .coerced_ty = .const_slice_u8_type }, fn_proto.ast.section_expr); + const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .const_slice_u8_type } }, fn_proto.ast.section_expr); if (section_gz.instructionsSlice().len == 0) { // In this case we will send a len=0 body which can be encoded more efficiently. break :inst inst; @@ -3676,7 +3693,7 @@ fn fnDecl( const inst = try expr( &decl_gz, params_scope, - .{ .coerced_ty = .calling_convention_type }, + .{ .rl = .{ .coerced_ty = .calling_convention_type } }, fn_proto.ast.callconv_expr, ); if (cc_gz.instructionsSlice().len == 0) { @@ -3698,7 +3715,7 @@ fn fnDecl( var ret_gz = decl_gz.makeSubBlock(params_scope); defer ret_gz.unstack(); const ret_ref: Zir.Inst.Ref = inst: { - const inst = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type); + const inst = try expr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type); if (ret_gz.instructionsSlice().len == 0) { // In this case we will send a len=0 body which can be encoded more efficiently. break :inst inst; @@ -3752,7 +3769,7 @@ fn fnDecl( const lbrace_line = astgen.source_line - decl_gz.decl_line; const lbrace_column = astgen.source_column; - _ = try expr(&fn_gz, params_scope, .none, body_node); + _ = try expr(&fn_gz, params_scope, .{ .rl = .none }, body_node); try checkUsed(gz, &fn_gz.base, params_scope); if (!fn_gz.endsWithNoReturn()) { @@ -3848,13 +3865,13 @@ fn globalVarDecl( break :blk token_tags[maybe_extern_token] == .keyword_extern; }; const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: { - break :inst try expr(&block_scope, &block_scope.base, align_rl, var_decl.ast.align_node); + break :inst try expr(&block_scope, &block_scope.base, align_ri, var_decl.ast.align_node); }; const addrspace_inst: Zir.Inst.Ref = if (var_decl.ast.addrspace_node == 0) .none else inst: { - break :inst try expr(&block_scope, &block_scope.base, .{ .ty = .address_space_type }, var_decl.ast.addrspace_node); + break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node); }; const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: { - break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node); + break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .const_slice_u8_type } }, var_decl.ast.section_node); }; const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none; wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace); @@ -3894,7 +3911,7 @@ fn globalVarDecl( try expr( &block_scope, &block_scope.base, - .{ .ty = .type_type }, + .{ .rl = .{ .ty = .type_type } }, var_decl.ast.type_node, ) else @@ -3903,7 +3920,7 @@ fn globalVarDecl( const init_inst = try expr( &block_scope, &block_scope.base, - if (type_inst != .none) .{ .ty = type_inst } else .none, + if (type_inst != .none) .{ .rl = .{ .ty = type_inst } } else .{ .rl = .none }, var_decl.ast.init_node, ); @@ -3992,7 +4009,7 @@ fn comptimeDecl( }; defer decl_block.unstack(); - const block_result = try expr(&decl_block, &decl_block.base, .none, body_node); + const block_result = try expr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node); if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) { _ = try decl_block.addBreak(.break_inline, block_inst, .void_value); } @@ -4196,7 +4213,7 @@ fn testDecl( const lbrace_line = astgen.source_line - decl_block.decl_line; const lbrace_column = astgen.source_column; - const block_result = try expr(&fn_block, &fn_block.base, .none, body_node); + const block_result = try expr(&fn_block, &fn_block.base, .{ .rl = .none }, body_node); if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) { // Since we are adding the return instruction here, we must handle the coercion. // We do this by using the `ret_tok` instruction. @@ -4410,7 +4427,7 @@ fn structDeclInner( if (layout == .Packed) { try astgen.appendErrorNode(member.ast.align_expr, "unable to override alignment of packed struct fields", .{}); } - const align_ref = try expr(&block_scope, &namespace.base, coerced_align_rl, member.ast.align_expr); + const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, member.ast.align_expr); if (!block_scope.endsWithNoReturn()) { _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); } @@ -4423,9 +4440,9 @@ fn structDeclInner( } if (have_value) { - const rl: ResultLoc = if (field_type == .none) .none else .{ .coerced_ty = field_type }; + const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = field_type } }; - const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr); + const default_inst = try expr(&block_scope, &namespace.base, ri, member.ast.value_expr); if (!block_scope.endsWithNoReturn()) { _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst); } @@ -4554,7 +4571,7 @@ fn unionDeclInner( return astgen.failNode(member_node, "union field missing type", .{}); } if (have_align) { - const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr); + const align_inst = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .u32_type } }, member.ast.align_expr); wip_members.appendToField(@enumToInt(align_inst)); } if (have_value) { @@ -4586,7 +4603,7 @@ fn unionDeclInner( }, ); } - const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr); + const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); wip_members.appendToField(@enumToInt(tag_value)); } } @@ -4624,7 +4641,7 @@ fn unionDeclInner( fn containerDecl( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, container_decl: Ast.full.ContainerDecl, ) InnerError!Zir.Inst.Ref { @@ -4650,7 +4667,7 @@ fn containerDecl( } else std.builtin.Type.ContainerLayout.Auto; const result = try structDeclInner(gz, scope, node, container_decl, layout, container_decl.ast.arg); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .keyword_union => { const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) { @@ -4660,7 +4677,7 @@ fn containerDecl( } else std.builtin.Type.ContainerLayout.Auto; const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, container_decl.ast.arg, container_decl.ast.enum_token); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .keyword_enum => { if (container_decl.layout_token) |t| { @@ -4790,7 +4807,7 @@ fn containerDecl( _ = try astgen.scanDecls(&namespace, container_decl.ast.members); const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) - try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg) + try comptimeExpr(&block_scope, &namespace.base, .{ .rl = .{ .ty = .type_type } }, container_decl.ast.arg) else .none; @@ -4834,7 +4851,7 @@ fn containerDecl( }, ); } - const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr); + const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); wip_members.appendToField(@enumToInt(tag_value_inst)); } } @@ -4865,7 +4882,7 @@ fn containerDecl( block_scope.unstack(); try gz.addNamespaceCaptures(&namespace); - return rvalue(gz, rl, indexToRef(decl_inst), node); + return rvalue(gz, ri, indexToRef(decl_inst), node); }, .keyword_opaque => { assert(container_decl.ast.arg == 0); @@ -4915,7 +4932,7 @@ fn containerDecl( astgen.extra.appendSliceAssumeCapacity(decls_slice); try gz.addNamespaceCaptures(&namespace); - return rvalue(gz, rl, indexToRef(decl_inst), node); + return rvalue(gz, ri, indexToRef(decl_inst), node); }, else => unreachable, } @@ -5046,7 +5063,7 @@ fn containerMember( return .decl; } -fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { +fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; const gpa = astgen.gpa; const tree = astgen.tree; @@ -5101,13 +5118,13 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir .fields_len = @intCast(u32, fields_len), }); const result = try gz.addPlNodePayloadIndex(.error_set_decl, node, payload_index); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn tryExpr( parent_gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, operand_node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { @@ -5137,15 +5154,15 @@ fn tryExpr( const try_line = astgen.source_line - parent_gz.decl_line; const try_column = astgen.source_column; - const operand_rl: ResultLoc = switch (rl) { - .ref, .catch_ref => .catch_ref, - else => .catch_none, + const operand_ri: ResultInfo = switch (ri.rl) { + .ref => .{ .rl = .ref, .ctx = .error_handling_expr }, + else => .{ .rl = .none, .ctx = .error_handling_expr }, }; - // This could be a pointer or value depending on the `rl` parameter. - const operand = try reachableExpr(parent_gz, scope, operand_rl, operand_node, node); + // This could be a pointer or value depending on the `ri` parameter. + const operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, node); const is_inline = parent_gz.force_comptime; const is_inline_bit = @as(u2, @boolToInt(is_inline)); - const is_ptr_bit = @as(u2, @boolToInt(operand_rl == .ref or operand_rl == .catch_ref)) << 1; + const is_ptr_bit = @as(u2, @boolToInt(operand_ri.rl == .ref)) << 1; const block_tag: Zir.Inst.Tag = switch (is_inline_bit | is_ptr_bit) { 0b00 => .@"try", 0b01 => .@"try", @@ -5160,8 +5177,8 @@ fn tryExpr( var else_scope = parent_gz.makeSubBlock(scope); defer else_scope.unstack(); - const err_tag = switch (rl) { - .ref, .catch_ref => Zir.Inst.Tag.err_union_code_ptr, + const err_tag = switch (ri.rl) { + .ref => Zir.Inst.Tag.err_union_code_ptr, else => Zir.Inst.Tag.err_union_code, }; const err_code = try else_scope.addUnNode(err_tag, operand, node); @@ -5171,9 +5188,9 @@ fn tryExpr( try else_scope.setTryBody(try_inst, operand); const result = indexToRef(try_inst); - switch (rl) { - .ref, .catch_ref => return result, - else => return rvalue(parent_gz, rl, result, node), + switch (ri.rl) { + .ref => return result, + else => return rvalue(parent_gz, ri, result, node), } } @@ -5190,7 +5207,7 @@ fn tryExpr( fn popErrorReturnTrace( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, result_inst: Zir.Inst.Ref, error_trace_index: Zir.Inst.Ref, @@ -5201,13 +5218,8 @@ fn popErrorReturnTrace( const result_is_err = nodeMayEvalToError(tree, node); // If we are breaking to a try/catch/error-union-if/return, the error trace propagates. - const propagate_error_trace = switch (rl) { - .catch_none, .catch_ref => true, // Propagate to try/catch/error-union-if - .ptr, .ty => |ref| b: { // Otherwise, propagate if result loc is a return - const inst = refToIndex(ref) orelse break :b false; - const zir_tags = astgen.instructions.items(.tag); - break :b zir_tags[inst] == .ret_ptr or zir_tags[inst] == .ret_type; - }, + const propagate_error_trace = switch (ri.ctx) { + .error_handling_expr, .@"return" => true, else => false, }; @@ -5219,14 +5231,14 @@ fn popErrorReturnTrace( // We are returning to an error-handling operator with a maybe-error. // Restore only if it's a non-error, implying the catch was successfully handled. var block_scope = gz.makeSubBlock(scope); - block_scope.setBreakResultLoc(.discard); + block_scope.setBreakResultInfo(.{ .rl = .discard }); defer block_scope.unstack(); // Emit conditional branch for restoring error trace index - const is_non_err = switch (rl) { - .catch_ref => try block_scope.addUnNode(.is_non_err_ptr, result_inst, node), - .ptr => |ptr| try block_scope.addUnNode(.is_non_err_ptr, ptr, node), - .ty, .catch_none => try block_scope.addUnNode(.is_non_err, result_inst, node), + const is_non_err = switch (ri.rl) { + .ref => try block_scope.addUnNode(.is_non_err_ptr, result_inst, node), + .ptr => |ptr| try block_scope.addUnNode(.is_non_err_ptr, ptr.inst, node), + .ty, .none => try block_scope.addUnNode(.is_non_err, result_inst, node), else => unreachable, // Error-handling operators only generate the above result locations }; const condbr = try block_scope.addCondBr(.condbr, node); @@ -5255,7 +5267,7 @@ fn popErrorReturnTrace( fn orelseCatchExpr( parent_gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, lhs: Ast.Node.Index, cond_op: Zir.Inst.Tag, @@ -5270,21 +5282,21 @@ fn orelseCatchExpr( const do_err_trace = astgen.fn_block != null and (cond_op == .is_non_err or cond_op == .is_non_err_ptr); var block_scope = parent_gz.makeSubBlock(scope); - block_scope.setBreakResultLoc(rl); + block_scope.setBreakResultInfo(ri); defer block_scope.unstack(); const saved_err_trace_index = if (do_err_trace) try parent_gz.addNode(.save_err_ret_index, node) else .none; - const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { - .ref, .catch_ref => if (do_err_trace) ResultLoc{ .catch_ref = {} } else .ref, - else => if (do_err_trace) ResultLoc{ .catch_none = {} } else .none, + const operand_ri: ResultInfo = switch (block_scope.break_result_info.rl) { + .ref => .{ .rl = .ref, .ctx = if (do_err_trace) .error_handling_expr else .none }, + else => .{ .rl = .none, .ctx = if (do_err_trace) .error_handling_expr else .none }, }; block_scope.break_count += 1; - // This could be a pointer or value depending on the `operand_rl` parameter. - // We cannot use `block_scope.break_result_loc` because that has the bare + // This could be a pointer or value depending on the `operand_ri` parameter. + // We cannot use `block_scope.break_result_info` because that has the bare // type, whereas this expression has the optional type. Later we make // up for this fact by calling rvalue on the else branch. - const operand = try reachableExpr(&block_scope, &block_scope.base, operand_rl, lhs, rhs); + const operand = try reachableExpr(&block_scope, &block_scope.base, operand_ri, lhs, rhs); const cond = try block_scope.addUnNode(cond_op, operand, node); const condbr = try block_scope.addCondBr(.condbr, node); @@ -5298,9 +5310,9 @@ fn orelseCatchExpr( // This could be a pointer or value depending on `unwrap_op`. const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node); - const then_result = switch (rl) { - .ref, .catch_ref => unwrapped_payload, - else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node), + const then_result = switch (ri.rl) { + .ref => unwrapped_payload, + else => try rvalue(&then_scope, block_scope.break_result_info, unwrapped_payload, node), }; var else_scope = block_scope.makeSubBlock(scope); @@ -5334,7 +5346,7 @@ fn orelseCatchExpr( break :blk &err_val_scope.base; }; - const else_result = try expr(&else_scope, else_sub_scope, block_scope.break_result_loc, rhs); + const else_result = try expr(&else_scope, else_sub_scope, block_scope.break_result_info, rhs); if (!else_scope.endsWithNoReturn()) { block_scope.break_count += 1; @@ -5342,7 +5354,7 @@ fn orelseCatchExpr( try popErrorReturnTrace( &else_scope, else_sub_scope, - block_scope.break_result_loc, + block_scope.break_result_info, rhs, else_result, saved_err_trace_index, @@ -5358,7 +5370,7 @@ fn orelseCatchExpr( const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break"; const result = try finishThenElseBlock( parent_gz, - rl, + ri, node, &block_scope, &then_scope, @@ -5377,7 +5389,7 @@ fn orelseCatchExpr( /// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`. fn finishThenElseBlock( parent_gz: *GenZir, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, block_scope: *GenZir, then_scope: *GenZir, @@ -5392,7 +5404,7 @@ fn finishThenElseBlock( ) InnerError!Zir.Inst.Ref { // We now have enough information to decide whether the result instruction should // be communicated via result location pointer or break instructions. - const strat = rl.strategy(block_scope); + const strat = ri.rl.strategy(block_scope); // else_scope may be stacked on then_scope, so check for no-return on then_scope manually const tags = parent_gz.astgen.instructions.items(.tag); const then_slice = then_scope.instructionsSliceUpto(else_scope); @@ -5422,9 +5434,9 @@ fn finishThenElseBlock( try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break); } const block_ref = indexToRef(main_block); - switch (rl) { - .ref, .catch_ref => return block_ref, - else => return rvalue(parent_gz, rl, block_ref, node), + switch (ri.rl) { + .ref => return block_ref, + else => return rvalue(parent_gz, ri, block_ref, node), } }, } @@ -5443,14 +5455,14 @@ fn tokenIdentEql(astgen: *AstGen, token1: Ast.TokenIndex, token2: Ast.TokenIndex fn fieldAccess( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { - switch (rl) { - .ref, .catch_ref => return addFieldAccess(.field_ptr, gz, scope, .ref, node), + switch (ri.rl) { + .ref => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node), else => { - const access = try addFieldAccess(.field_val, gz, scope, .none, node); - return rvalue(gz, rl, access, node); + const access = try addFieldAccess(.field_val, gz, scope, .{ .rl = .none }, node); + return rvalue(gz, ri, access, node); }, } } @@ -5459,7 +5471,7 @@ fn addFieldAccess( tag: Zir.Inst.Tag, gz: *GenZir, scope: *Scope, - lhs_rl: ResultLoc, + lhs_ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; @@ -5473,7 +5485,7 @@ fn addFieldAccess( const str_index = try astgen.identAsString(field_ident); return gz.addPlNode(tag, node, Zir.Inst.Field{ - .lhs = try expr(gz, scope, lhs_rl, object_node), + .lhs = try expr(gz, scope, lhs_ri, object_node), .field_name_start = str_index, }); } @@ -5481,20 +5493,20 @@ fn addFieldAccess( fn arrayAccess( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; const tree = astgen.tree; const node_datas = tree.nodes.items(.data); - switch (rl) { - .ref, .catch_ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ - .lhs = try expr(gz, scope, .ref, node_datas[node].lhs), - .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs), + switch (ri.rl) { + .ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ + .lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs), + .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs), }), - else => return rvalue(gz, rl, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ - .lhs = try expr(gz, scope, .none, node_datas[node].lhs), - .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs), + else => return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ + .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs), + .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs), }), node), } } @@ -5502,7 +5514,7 @@ fn arrayAccess( fn simpleBinOp( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, op_inst_tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { @@ -5511,15 +5523,15 @@ fn simpleBinOp( const node_datas = tree.nodes.items(.data); const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{ - .lhs = try reachableExpr(gz, scope, .none, node_datas[node].lhs, node), - .rhs = try reachableExpr(gz, scope, .none, node_datas[node].rhs, node), + .lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node), + .rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn simpleStrTok( gz: *GenZir, - rl: ResultLoc, + ri: ResultInfo, ident_token: Ast.TokenIndex, node: Ast.Node.Index, op_inst_tag: Zir.Inst.Tag, @@ -5527,13 +5539,13 @@ fn simpleStrTok( const astgen = gz.astgen; const str_index = try astgen.identAsString(ident_token); const result = try gz.addStrTok(op_inst_tag, str_index, ident_token); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn boolBinOp( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, zir_tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { @@ -5541,25 +5553,25 @@ fn boolBinOp( const tree = astgen.tree; const node_datas = tree.nodes.items(.data); - const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs); + const lhs = try expr(gz, scope, bool_ri, node_datas[node].lhs); const bool_br = try gz.addBoolBr(zir_tag, lhs); var rhs_scope = gz.makeSubBlock(scope); defer rhs_scope.unstack(); - const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs); + const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_ri, node_datas[node].rhs); if (!gz.refIsNoReturn(rhs)) { _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs); } try rhs_scope.setBoolBrBody(bool_br); const block_ref = indexToRef(bool_br); - return rvalue(gz, rl, block_ref, node); + return rvalue(gz, ri, block_ref, node); } fn ifExpr( parent_gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, if_full: Ast.full.If, ) InnerError!Zir.Inst.Ref { @@ -5570,7 +5582,7 @@ fn ifExpr( const do_err_trace = astgen.fn_block != null and if_full.error_token != null; var block_scope = parent_gz.makeSubBlock(scope); - block_scope.setBreakResultLoc(rl); + block_scope.setBreakResultInfo(ri); defer block_scope.unstack(); const saved_err_trace_index = if (do_err_trace) try parent_gz.addNode(.save_err_ret_index, node) else .none; @@ -5586,23 +5598,23 @@ fn ifExpr( bool_bit: Zir.Inst.Ref, } = c: { if (if_full.error_token) |_| { - const cond_rl: ResultLoc = if (payload_is_ref) .catch_ref else .catch_none; - const err_union = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr); + const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none, .ctx = .error_handling_expr }; + const err_union = try expr(&block_scope, &block_scope.base, cond_ri, if_full.ast.cond_expr); const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err; break :c .{ .inst = err_union, .bool_bit = try block_scope.addUnNode(tag, err_union, if_full.ast.cond_expr), }; } else if (if_full.payload_token) |_| { - const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; - const optional = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr); + const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; + const optional = try expr(&block_scope, &block_scope.base, cond_ri, if_full.ast.cond_expr); const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; break :c .{ .inst = optional, .bool_bit = try block_scope.addUnNode(tag, optional, if_full.ast.cond_expr), }; } else { - const cond = try expr(&block_scope, &block_scope.base, bool_rl, if_full.ast.cond_expr); + const cond = try expr(&block_scope, &block_scope.base, bool_ri, if_full.ast.cond_expr); break :c .{ .inst = cond, .bool_bit = cond, @@ -5678,7 +5690,7 @@ fn ifExpr( } }; - const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, if_full.ast.then_expr); + const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, if_full.ast.then_expr); if (!then_scope.endsWithNoReturn()) { block_scope.break_count += 1; } @@ -5729,7 +5741,7 @@ fn ifExpr( break :s &else_scope.base; } }; - const e = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node); + const e = try expr(&else_scope, sub_scope, block_scope.break_result_info, else_node); if (!else_scope.endsWithNoReturn()) { block_scope.break_count += 1; @@ -5737,7 +5749,7 @@ fn ifExpr( try popErrorReturnTrace( &else_scope, sub_scope, - block_scope.break_result_loc, + block_scope.break_result_info, else_node, e, saved_err_trace_index, @@ -5752,9 +5764,9 @@ fn ifExpr( }; } else .{ .src = if_full.ast.then_expr, - .result = switch (rl) { + .result = switch (ri.rl) { // Explicitly store void to ptr result loc if there is no else branch - .ptr, .block_ptr => try rvalue(&else_scope, rl, .void_value, node), + .ptr, .block_ptr => try rvalue(&else_scope, ri, .void_value, node), else => .none, }, }; @@ -5762,7 +5774,7 @@ fn ifExpr( const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break"; const result = try finishThenElseBlock( parent_gz, - rl, + ri, node, &block_scope, &then_scope, @@ -5896,7 +5908,7 @@ fn setCondBrPayloadElideBlockStorePtr( fn whileExpr( parent_gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, while_full: Ast.full.While, is_statement: bool, @@ -5916,7 +5928,7 @@ fn whileExpr( var loop_scope = parent_gz.makeSubBlock(scope); loop_scope.is_inline = is_inline; - loop_scope.setBreakResultLoc(rl); + loop_scope.setBreakResultInfo(ri); defer loop_scope.unstack(); defer loop_scope.labeled_breaks.deinit(astgen.gpa); @@ -5934,23 +5946,23 @@ fn whileExpr( bool_bit: Zir.Inst.Ref, } = c: { if (while_full.error_token) |_| { - const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; - const err_union = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr); + const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; + const err_union = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr); const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err; break :c .{ .inst = err_union, .bool_bit = try continue_scope.addUnNode(tag, err_union, while_full.ast.then_expr), }; } else if (while_full.payload_token) |_| { - const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; - const optional = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr); + const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; + const optional = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr); const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; break :c .{ .inst = optional, .bool_bit = try continue_scope.addUnNode(tag, optional, while_full.ast.then_expr), }; } else { - const cond = try expr(&continue_scope, &continue_scope.base, bool_rl, while_full.ast.cond_expr); + const cond = try expr(&continue_scope, &continue_scope.base, bool_ri, while_full.ast.cond_expr); break :c .{ .inst = cond, .bool_bit = cond, @@ -6069,7 +6081,7 @@ fn whileExpr( if (dbg_var_name) |some| { try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst); } - const then_result = try expr(&then_scope, then_sub_scope, .none, while_full.ast.then_expr); + const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, while_full.ast.then_expr); _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr); try checkUsed(parent_gz, &then_scope.base, then_sub_scope); @@ -6114,7 +6126,7 @@ fn whileExpr( // control flow apply to outer loops; not this one. loop_scope.continue_block = 0; loop_scope.break_block = 0; - const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node); + const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_info, else_node); if (is_statement) { _ = try addEnsureResult(&else_scope, else_result, else_node); } @@ -6141,7 +6153,7 @@ fn whileExpr( const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; const result = try finishThenElseBlock( parent_gz, - rl, + ri, node, &loop_scope, &then_scope, @@ -6163,7 +6175,7 @@ fn whileExpr( fn forExpr( parent_gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, for_full: Ast.full.While, is_statement: bool, @@ -6186,8 +6198,8 @@ fn forExpr( try emitDbgNode(parent_gz, for_full.ast.cond_expr); - const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; - const array_ptr = try expr(parent_gz, scope, cond_rl, for_full.ast.cond_expr); + const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; + const array_ptr = try expr(parent_gz, scope, cond_ri, for_full.ast.cond_expr); const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr); const index_ptr = blk: { @@ -6204,7 +6216,7 @@ fn forExpr( var loop_scope = parent_gz.makeSubBlock(scope); loop_scope.is_inline = is_inline; - loop_scope.setBreakResultLoc(rl); + loop_scope.setBreakResultInfo(ri); defer loop_scope.unstack(); defer loop_scope.labeled_breaks.deinit(astgen.gpa); @@ -6308,7 +6320,7 @@ fn forExpr( break :blk &index_scope.base; }; - const then_result = try expr(&then_scope, then_sub_scope, .none, for_full.ast.then_expr); + const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, for_full.ast.then_expr); _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr); try checkUsed(parent_gz, &then_scope.base, then_sub_scope); @@ -6327,7 +6339,7 @@ fn forExpr( // control flow apply to outer loops; not this one. loop_scope.continue_block = 0; loop_scope.break_block = 0; - const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node); + const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_info, else_node); if (is_statement) { _ = try addEnsureResult(&else_scope, else_result, else_node); } @@ -6352,7 +6364,7 @@ fn forExpr( const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; const result = try finishThenElseBlock( parent_gz, - rl, + ri, node, &loop_scope, &then_scope, @@ -6374,7 +6386,7 @@ fn forExpr( fn switchExpr( parent_gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, switch_node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const astgen = parent_gz.astgen; @@ -6505,13 +6517,13 @@ fn switchExpr( } } - const operand_rl: ResultLoc = if (any_payload_is_ref) .ref else .none; - const raw_operand = try expr(parent_gz, scope, operand_rl, operand_node); + const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none }; + const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node); const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond; const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node); // We need the type of the operand to use as the result location for all the prong items. const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node); - const item_rl: ResultLoc = .{ .ty = cond_ty_inst }; + const item_ri: ResultInfo = .{ .rl = .{ .ty = cond_ty_inst } }; // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti, // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with @@ -6528,7 +6540,7 @@ fn switchExpr( var block_scope = parent_gz.makeSubBlock(scope); // block_scope not used for collecting instructions block_scope.instructions_top = GenZir.unstacked_top; - block_scope.setBreakResultLoc(rl); + block_scope.setBreakResultInfo(ri); // This gets added to the parent block later, after the item expressions. const switch_block = try parent_gz.makeBlockInst(.switch_block, switch_node); @@ -6669,7 +6681,7 @@ fn switchExpr( if (node_tags[item_node] == .switch_range) continue; items_len += 1; - const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); + const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node); try payloads.append(gpa, @enumToInt(item_inst)); } @@ -6679,8 +6691,8 @@ fn switchExpr( if (node_tags[range] != .switch_range) continue; ranges_len += 1; - const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs); - const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs); + const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs); + const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs); try payloads.appendSlice(gpa, &[_]u32{ @enumToInt(first), @enumToInt(last), }); @@ -6698,7 +6710,7 @@ fn switchExpr( scalar_case_index += 1; try payloads.resize(gpa, header_index + 2); // item, body_len const item_node = case.ast.values[0]; - const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); + const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node); payloads.items[header_index] = @enumToInt(item_inst); break :blk header_index + 1; }; @@ -6717,7 +6729,7 @@ fn switchExpr( if (dbg_var_tag_name) |some| { try case_scope.addDbgVar(.dbg_var_val, some, dbg_var_tag_inst); } - const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); + const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, case.ast.target_expr); try checkUsed(parent_gz, &case_scope.base, sub_scope); try case_scope.addDbgBlockEnd(); if (!parent_gz.refIsNoReturn(case_result)) { @@ -6759,7 +6771,7 @@ fn switchExpr( zir_datas[switch_block].pl_node.payload_index = payload_index; - const strat = rl.strategy(&block_scope); + const strat = ri.rl.strategy(&block_scope); for (payloads.items[case_table_start..case_table_end]) |start_index, i| { var body_len_index = start_index; var end_index = start_index; @@ -6831,8 +6843,8 @@ fn switchExpr( } const block_ref = indexToRef(switch_block); - if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and rl != .ref and rl != .catch_ref) - return rvalue(parent_gz, rl, block_ref, switch_node); + if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and ri.rl != .ref) + return rvalue(parent_gz, ri, block_ref, switch_node); return block_ref; } @@ -6895,14 +6907,16 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref return Zir.Inst.Ref.unreachable_value; } - const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{ - .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) }, + const ri: ResultInfo = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{ + .rl = .{ .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) } }, + .ctx = .@"return", } else .{ - .ty = try gz.addNode(.ret_type, node), + .rl = .{ .ty = try gz.addNode(.ret_type, node) }, + .ctx = .@"return", }; const prev_anon_name_strategy = gz.anon_name_strategy; gz.anon_name_strategy = .func; - const operand = try reachableExpr(gz, scope, rl, operand_node, node); + const operand = try reachableExpr(gz, scope, ri, operand_node, node); gz.anon_name_strategy = prev_anon_name_strategy; // TODO: This should be almost identical for every break/ret @@ -6916,15 +6930,15 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref _ = try gz.addUnNode(.restore_err_ret_index, gz.outermost_err_trace_index, node); try emitDbgStmt(gz, ret_line, ret_column); - try gz.addRet(rl, operand, node); + try gz.addRet(ri, operand, node); return Zir.Inst.Ref.unreachable_value; }, .always => { // Value is always an error. Emit both error defers and regular defers. - const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand; + const err_code = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand; try genDefers(gz, defer_outer, scope, .{ .both = err_code }); try emitDbgStmt(gz, ret_line, ret_column); - try gz.addRet(rl, operand, node); + try gz.addRet(ri, operand, node); return Zir.Inst.Ref.unreachable_value; }, .maybe => { @@ -6933,12 +6947,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref // Only regular defers; no branch needed. try genDefers(gz, defer_outer, scope, .normal_only); try emitDbgStmt(gz, ret_line, ret_column); - try gz.addRet(rl, operand, node); + try gz.addRet(ri, operand, node); return Zir.Inst.Ref.unreachable_value; } // Emit conditional branch for generating errdefers. - const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand; + const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand; const is_non_err = try gz.addUnNode(.is_non_err, result, node); const condbr = try gz.addCondBr(.condbr, node); @@ -6952,7 +6966,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref _ = try then_scope.addUnNode(.restore_err_ret_index, then_scope.outermost_err_trace_index, node); try emitDbgStmt(&then_scope, ret_line, ret_column); - try then_scope.addRet(rl, operand, node); + try then_scope.addRet(ri, operand, node); var else_scope = gz.makeSubBlock(scope); defer else_scope.unstack(); @@ -6962,7 +6976,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref }; try genDefers(&else_scope, defer_outer, scope, which_ones); try emitDbgStmt(&else_scope, ret_line, ret_column); - try else_scope.addRet(rl, operand, node); + try else_scope.addRet(ri, operand, node); try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0); @@ -6995,7 +7009,7 @@ fn parseBitCount(buf: []const u8) std.fmt.ParseIntError!u16 { fn identifier( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, ident: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const tracy = trace(@src()); @@ -7014,7 +7028,7 @@ fn identifier( // if not @"" syntax, just use raw token slice if (ident_name_raw[0] != '@') { if (primitives.get(ident_name_raw)) |zir_const_ref| { - return rvalue(gz, rl, zir_const_ref, ident); + return rvalue(gz, ri, zir_const_ref, ident); } if (ident_name_raw.len >= 2) integer: { @@ -7047,19 +7061,19 @@ fn identifier( .bit_count = bit_count, } }, }); - return rvalue(gz, rl, result, ident); + return rvalue(gz, ri, result, ident); } } } // Local variables, including function parameters. - return localVarRef(gz, scope, rl, ident, ident_token); + return localVarRef(gz, scope, ri, ident, ident_token); } fn localVarRef( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, ident: Ast.Node.Index, ident_token: Ast.TokenIndex, ) InnerError!Zir.Inst.Ref { @@ -7077,7 +7091,7 @@ fn localVarRef( if (local_val.name == name_str_index) { // Locals cannot shadow anything, so we do not need to look for ambiguous // references in this case. - if (rl == .discard) { + if (ri.rl == .discard) { local_val.discarded = ident_token; } else { local_val.used = ident_token; @@ -7093,14 +7107,14 @@ fn localVarRef( gpa, ); - return rvalue(gz, rl, value_inst, ident); + return rvalue(gz, ri, value_inst, ident); } s = local_val.parent; }, .local_ptr => { const local_ptr = s.cast(Scope.LocalPtr).?; if (local_ptr.name == name_str_index) { - if (rl == .discard) { + if (ri.rl == .discard) { local_ptr.discarded = ident_token; } else { local_ptr.used = ident_token; @@ -7125,11 +7139,11 @@ fn localVarRef( gpa, ); - switch (rl) { - .ref, .catch_ref => return ptr_inst, + switch (ri.rl) { + .ref => return ptr_inst, else => { const loaded = try gz.addUnNode(.load, ptr_inst, ident); - return rvalue(gz, rl, loaded, ident); + return rvalue(gz, ri, loaded, ident); }, } } @@ -7162,11 +7176,11 @@ fn localVarRef( // Decl references happen by name rather than ZIR index so that when unrelated // decls are modified, ZIR code containing references to them can be unmodified. - switch (rl) { - .ref, .catch_ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token), + switch (ri.rl) { + .ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token), else => { const result = try gz.addStrTok(.decl_val, name_str_index, ident_token); - return rvalue(gz, rl, result, ident); + return rvalue(gz, ri, result, ident); }, } } @@ -7210,7 +7224,7 @@ fn tunnelThroughClosure( fn stringLiteral( gz: *GenZir, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; @@ -7225,12 +7239,12 @@ fn stringLiteral( .len = str.len, } }, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn multilineStringLiteral( gz: *GenZir, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; @@ -7242,10 +7256,10 @@ fn multilineStringLiteral( .len = str.len, } }, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } -fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { +fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; const tree = astgen.tree; const main_tokens = tree.nodes.items(.main_token); @@ -7255,7 +7269,7 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir. switch (std.zig.parseCharLiteral(slice)) { .success => |codepoint| { const result = try gz.addInt(codepoint); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .failure => |err| return astgen.failWithStrLitError(err, main_token, slice, 0), } @@ -7263,7 +7277,7 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir. const Sign = enum { negative, positive }; -fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref { +fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; const tree = astgen.tree; const main_tokens = tree.nodes.items(.main_token); @@ -7305,7 +7319,7 @@ fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node: const bigger_again: f128 = smaller_float; if (bigger_again == float_number) { const result = try gz.addFloat(smaller_float); - return rvalue(gz, rl, result, source_node); + return rvalue(gz, ri, result, source_node); } // We need to use 128 bits. Break the float into 4 u32 values so we can // put it into the `extra` array. @@ -7316,16 +7330,16 @@ fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node: .piece2 = @truncate(u32, int_bits >> 64), .piece3 = @truncate(u32, int_bits >> 96), }); - return rvalue(gz, rl, result, source_node); + return rvalue(gz, ri, result, source_node); }, .failure => |err| return astgen.failWithNumberError(err, num_token, bytes), }; if (sign == .positive) { - return rvalue(gz, rl, result, source_node); + return rvalue(gz, ri, result, source_node); } else { const negated = try gz.addUnNode(.negate, result, source_node); - return rvalue(gz, rl, negated, source_node); + return rvalue(gz, ri, negated, source_node); } } @@ -7361,7 +7375,7 @@ fn failWithNumberError(astgen: *AstGen, err: std.zig.number_literal.Error, token fn asmExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, full: Ast.full.Asm, ) InnerError!Zir.Inst.Ref { @@ -7384,7 +7398,7 @@ fn asmExpr( }, else => .{ .tag = .asm_expr, - .tmpl = @enumToInt(try comptimeExpr(gz, scope, .none, full.ast.template)), + .tmpl = @enumToInt(try comptimeExpr(gz, scope, .{ .rl = .none }, full.ast.template)), }, }; @@ -7436,7 +7450,7 @@ fn asmExpr( outputs[i] = .{ .name = name, .constraint = constraint, - .operand = try localVarRef(gz, scope, .ref, node, ident_token), + .operand = try localVarRef(gz, scope, .{ .rl = .ref }, node, ident_token), }; } } @@ -7452,7 +7466,7 @@ fn asmExpr( const name = try astgen.identAsString(symbolic_name); const constraint_token = symbolic_name + 2; const constraint = (try astgen.strLitAsString(constraint_token)).index; - const operand = try expr(gz, scope, .none, node_datas[input_node].lhs); + const operand = try expr(gz, scope, .{ .rl = .none }, node_datas[input_node].lhs); inputs[i] = .{ .name = name, .constraint = constraint, @@ -7497,31 +7511,31 @@ fn asmExpr( .inputs = inputs, .clobbers = clobbers_buffer[0..clobber_i], }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn as( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, lhs: Ast.Node.Index, rhs: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const dest_type = try typeExpr(gz, scope, lhs); - switch (rl) { - .none, .catch_none, .discard, .ref, .catch_ref, .ty, .ty_shift_operand, .coerced_ty => { - const result = try reachableExpr(gz, scope, .{ .ty = dest_type }, rhs, node); - return rvalue(gz, rl, result, node); + switch (ri.rl) { + .none, .discard, .ref, .ty, .coerced_ty => { + const result = try reachableExpr(gz, scope, .{ .rl = .{ .ty = dest_type } }, rhs, node); + return rvalue(gz, ri, result, node); }, .ptr => |result_ptr| { - return asRlPtr(gz, scope, rl, node, result_ptr.inst, rhs, dest_type); + return asRlPtr(gz, scope, ri, node, result_ptr.inst, rhs, dest_type); }, .inferred_ptr => |result_ptr| { - return asRlPtr(gz, scope, rl, node, result_ptr, rhs, dest_type); + return asRlPtr(gz, scope, ri, node, result_ptr, rhs, dest_type); }, .block_ptr => |block_scope| { - return asRlPtr(gz, scope, rl, node, block_scope.rl_ptr, rhs, dest_type); + return asRlPtr(gz, scope, ri, node, block_scope.rl_ptr, rhs, dest_type); }, } } @@ -7529,29 +7543,29 @@ fn as( fn unionInit( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, params: []const Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const union_type = try typeExpr(gz, scope, params[0]); - const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); + const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]); const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{ .container_type = union_type, .field_name = field_name, }); - const init = try reachableExpr(gz, scope, .{ .ty = field_type }, params[2], node); + const init = try reachableExpr(gz, scope, .{ .rl = .{ .ty = field_type } }, params[2], node); const result = try gz.addPlNode(.union_init, node, Zir.Inst.UnionInit{ .union_type = union_type, .init = init, .field_name = field_name, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn asRlPtr( parent_gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, src_node: Ast.Node.Index, result_ptr: Zir.Inst.Ref, operand_node: Ast.Node.Index, @@ -7560,31 +7574,31 @@ fn asRlPtr( var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr, src_node); defer as_scope.unstack(); - const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node); - return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type); + const result = try reachableExpr(&as_scope, &as_scope.base, .{ .rl = .{ .block_ptr = &as_scope } }, operand_node, src_node); + return as_scope.finishCoercion(parent_gz, ri, operand_node, result, dest_type); } fn bitCast( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, lhs: Ast.Node.Index, rhs: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const dest_type = try reachableTypeExpr(gz, scope, lhs, node); - const operand = try reachableExpr(gz, scope, .none, rhs, node); + const operand = try reachableExpr(gz, scope, .{ .rl = .none }, rhs, node); const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{ .lhs = dest_type, .rhs = operand, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn typeOf( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, args: []const Ast.Node.Index, ) InnerError!Zir.Inst.Ref { @@ -7600,7 +7614,7 @@ fn typeOf( typeof_scope.force_comptime = false; defer typeof_scope.unstack(); - const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, args[0], node); + const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .{ .rl = .none }, args[0], node); if (!gz.refIsNoReturn(ty_expr)) { _ = try typeof_scope.addBreak(.break_inline, typeof_inst, ty_expr); } @@ -7608,7 +7622,7 @@ fn typeOf( // typeof_scope unstacked now, can add new instructions to gz try gz.instructions.append(gpa, typeof_inst); - return rvalue(gz, rl, indexToRef(typeof_inst), node); + return rvalue(gz, ri, indexToRef(typeof_inst), node); } const payload_size: u32 = std.meta.fields(Zir.Inst.TypeOfPeer).len; const payload_index = try reserveExtra(astgen, payload_size + args.len); @@ -7620,7 +7634,7 @@ fn typeOf( typeof_scope.force_comptime = false; for (args) |arg, i| { - const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, arg, node); + const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .{ .rl = .none }, arg, node); astgen.extra.items[args_index + i] = @enumToInt(param_ref); } _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value); @@ -7636,13 +7650,13 @@ fn typeOf( astgen.appendBodyWithFixups(body); typeof_scope.unstack(); - return rvalue(gz, rl, typeof_inst, node); + return rvalue(gz, ri, typeof_inst, node); } fn builtinCall( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, params: []const Ast.Node.Index, ) InnerError!Zir.Inst.Ref { @@ -7694,7 +7708,7 @@ fn builtinCall( if (!gop.found_existing) { gop.value_ptr.* = str_lit_token; } - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .compile_log => { const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{ @@ -7702,32 +7716,32 @@ fn builtinCall( }); var extra_index = try reserveExtra(gz.astgen, params.len); for (params) |param| { - const param_ref = try expr(gz, scope, .none, param); + const param_ref = try expr(gz, scope, .{ .rl = .none }, param); astgen.extra.items[extra_index] = @enumToInt(param_ref); extra_index += 1; } const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log, payload_index, params.len); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .field => { - if (rl == .ref or rl == .catch_ref) { + if (ri.rl == .ref) { return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{ - .lhs = try expr(gz, scope, .ref, params[0]), - .field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]), + .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]), + .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]), }); } const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{ - .lhs = try expr(gz, scope, .none, params[0]), - .field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]), + .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]), + .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, // zig fmt: off - .as => return as( gz, scope, rl, node, params[0], params[1]), - .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]), - .TypeOf => return typeOf( gz, scope, rl, node, params), - .union_init => return unionInit(gz, scope, rl, node, params), + .as => return as( gz, scope, ri, node, params[0], params[1]), + .bit_cast => return bitCast( gz, scope, ri, node, params[0], params[1]), + .TypeOf => return typeOf( gz, scope, ri, node, params), + .union_init => return unionInit(gz, scope, ri, node, params), .c_import => return cImport( gz, scope, node, params[0]), // zig fmt: on @@ -7752,9 +7766,9 @@ fn builtinCall( local_val.used = ident_token; _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{ .operand = local_val.inst, - .options = try comptimeExpr(gz, scope, .{ .coerced_ty = .export_options_type }, params[1]), + .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]), }); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); } s = local_val.parent; }, @@ -7767,9 +7781,9 @@ fn builtinCall( const loaded = try gz.addUnNode(.load, local_ptr.ptr, node); _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{ .operand = loaded, - .options = try comptimeExpr(gz, scope, .{ .coerced_ty = .export_options_type }, params[1]), + .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]), }); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); } s = local_ptr.parent; }, @@ -7801,47 +7815,47 @@ fn builtinCall( }, else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}), } - const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]); + const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .export_options_type } }, params[1]); _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{ .namespace = namespace, .decl_name = decl_name, .options = options, }); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); }, .@"extern" => { const type_inst = try typeExpr(gz, scope, params[0]); - const options = try comptimeExpr(gz, scope, .{ .ty = .extern_options_type }, params[1]); + const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .extern_options_type } }, params[1]); const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{ .node = gz.nodeIndexToRelative(node), .lhs = type_inst, .rhs = options, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .fence => { - const order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[0]); + const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[0]); const result = try gz.addExtendedPayload(.fence, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = order, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .set_float_mode => { - const order = try expr(gz, scope, .{ .coerced_ty = .float_mode_type }, params[0]); + const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .float_mode_type } }, params[0]); const result = try gz.addExtendedPayload(.set_float_mode, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = order, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .set_align_stack => { - const order = try expr(gz, scope, align_rl, params[0]); + const order = try expr(gz, scope, align_ri, params[0]); const result = try gz.addExtendedPayload(.set_align_stack, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = order, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .src => { @@ -7853,62 +7867,62 @@ fn builtinCall( .line = astgen.source_line, .column = astgen.source_column, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, // zig fmt: off - .This => return rvalue(gz, rl, try gz.addNodeExtended(.this, node), node), - .return_address => return rvalue(gz, rl, try gz.addNodeExtended(.ret_addr, node), node), - .error_return_trace => return rvalue(gz, rl, try gz.addNodeExtended(.error_return_trace, node), node), - .frame => return rvalue(gz, rl, try gz.addNodeExtended(.frame, node), node), - .frame_address => return rvalue(gz, rl, try gz.addNodeExtended(.frame_address, node), node), - .breakpoint => return rvalue(gz, rl, try gz.addNodeExtended(.breakpoint, node), node), - - .type_info => return simpleUnOpType(gz, scope, rl, node, params[0], .type_info), - .size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .size_of), - .bit_size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .bit_size_of), - .align_of => return simpleUnOpType(gz, scope, rl, node, params[0], .align_of), - - .ptr_to_int => return simpleUnOp(gz, scope, rl, node, .none, params[0], .ptr_to_int), - .compile_error => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .compile_error), - .set_eval_branch_quota => return simpleUnOp(gz, scope, rl, node, .{ .coerced_ty = .u32_type }, params[0], .set_eval_branch_quota), - .enum_to_int => return simpleUnOp(gz, scope, rl, node, .none, params[0], .enum_to_int), - .bool_to_int => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .bool_to_int), - .embed_file => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .embed_file), - .error_name => return simpleUnOp(gz, scope, rl, node, .{ .ty = .anyerror_type }, params[0], .error_name), - .set_cold => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_cold), - .set_runtime_safety => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_runtime_safety), - .sqrt => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sqrt), - .sin => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sin), - .cos => return simpleUnOp(gz, scope, rl, node, .none, params[0], .cos), - .tan => return simpleUnOp(gz, scope, rl, node, .none, params[0], .tan), - .exp => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp), - .exp2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp2), - .log => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log), - .log2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log2), - .log10 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log10), - .fabs => return simpleUnOp(gz, scope, rl, node, .none, params[0], .fabs), - .floor => return simpleUnOp(gz, scope, rl, node, .none, params[0], .floor), - .ceil => return simpleUnOp(gz, scope, rl, node, .none, params[0], .ceil), - .trunc => return simpleUnOp(gz, scope, rl, node, .none, params[0], .trunc), - .round => return simpleUnOp(gz, scope, rl, node, .none, params[0], .round), - .tag_name => return simpleUnOp(gz, scope, rl, node, .none, params[0], .tag_name), - .type_name => return simpleUnOp(gz, scope, rl, node, .none, params[0], .type_name), - .Frame => return simpleUnOp(gz, scope, rl, node, .none, params[0], .frame_type), - .frame_size => return simpleUnOp(gz, scope, rl, node, .none, params[0], .frame_size), - - .float_to_int => return typeCast(gz, scope, rl, node, params[0], params[1], .float_to_int), - .int_to_float => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_float), - .int_to_ptr => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_ptr), - .int_to_enum => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_enum), - .float_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .float_cast), - .int_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .int_cast), - .ptr_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .ptr_cast), - .truncate => return typeCast(gz, scope, rl, node, params[0], params[1], .truncate), + .This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node), + .return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node), + .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node), + .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node), + .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node), + .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node), + + .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info), + .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of), + .bit_size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .bit_size_of), + .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of), + + .ptr_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ptr_to_int), + .compile_error => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .compile_error), + .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota), + .enum_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .enum_to_int), + .bool_to_int => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .bool_to_int), + .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .embed_file), + .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name), + .set_cold => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_cold), + .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety), + .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt), + .sin => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sin), + .cos => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .cos), + .tan => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tan), + .exp => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp), + .exp2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp2), + .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log), + .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2), + .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10), + .fabs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .fabs), + .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor), + .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil), + .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc), + .round => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .round), + .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name), + .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name), + .Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type), + .frame_size => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_size), + + .float_to_int => return typeCast(gz, scope, ri, node, params[0], params[1], .float_to_int), + .int_to_float => return typeCast(gz, scope, ri, node, params[0], params[1], .int_to_float), + .int_to_ptr => return typeCast(gz, scope, ri, node, params[0], params[1], .int_to_ptr), + .int_to_enum => return typeCast(gz, scope, ri, node, params[0], params[1], .int_to_enum), + .float_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .float_cast), + .int_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .int_cast), + .ptr_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .ptr_cast), + .truncate => return typeCast(gz, scope, ri, node, params[0], params[1], .truncate), // zig fmt: on .Type => { - const operand = try expr(gz, scope, .{ .coerced_ty = .type_info_type }, params[0]); + const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .type_info_type } }, params[0]); const gpa = gz.astgen.gpa; @@ -7930,219 +7944,219 @@ fn builtinCall( }); gz.instructions.appendAssumeCapacity(new_index); const result = indexToRef(new_index); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .panic => { try emitDbgNode(gz, node); - return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], if (gz.force_comptime) .panic_comptime else .panic); + return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], if (gz.force_comptime) .panic_comptime else .panic); }, .error_to_int => { - const operand = try expr(gz, scope, .none, params[0]); + const operand = try expr(gz, scope, .{ .rl = .none }, params[0]); const result = try gz.addExtendedPayload(.error_to_int, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = operand, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .int_to_error => { - const operand = try expr(gz, scope, .{ .coerced_ty = .u16_type }, params[0]); + const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, params[0]); const result = try gz.addExtendedPayload(.int_to_error, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = operand, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .align_cast => { - const dest_align = try comptimeExpr(gz, scope, align_rl, params[0]); - const rhs = try expr(gz, scope, .none, params[1]); + const dest_align = try comptimeExpr(gz, scope, align_ri, params[0]); + const rhs = try expr(gz, scope, .{ .rl = .none }, params[1]); const result = try gz.addPlNode(.align_cast, node, Zir.Inst.Bin{ .lhs = dest_align, .rhs = rhs, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .err_set_cast => { const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{ .lhs = try typeExpr(gz, scope, params[0]), - .rhs = try expr(gz, scope, .none, params[1]), + .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]), .node = gz.nodeIndexToRelative(node), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .addrspace_cast => { const result = try gz.addExtendedPayload(.addrspace_cast, Zir.Inst.BinNode{ - .lhs = try comptimeExpr(gz, scope, .{ .ty = .address_space_type }, params[0]), - .rhs = try expr(gz, scope, .none, params[1]), + .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .address_space_type } }, params[0]), + .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]), .node = gz.nodeIndexToRelative(node), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, // zig fmt: off - .has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl), - .has_field => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_field), + .has_decl => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_decl), + .has_field => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_field), - .clz => return bitBuiltin(gz, scope, rl, node, params[0], .clz), - .ctz => return bitBuiltin(gz, scope, rl, node, params[0], .ctz), - .pop_count => return bitBuiltin(gz, scope, rl, node, params[0], .pop_count), - .byte_swap => return bitBuiltin(gz, scope, rl, node, params[0], .byte_swap), - .bit_reverse => return bitBuiltin(gz, scope, rl, node, params[0], .bit_reverse), + .clz => return bitBuiltin(gz, scope, ri, node, params[0], .clz), + .ctz => return bitBuiltin(gz, scope, ri, node, params[0], .ctz), + .pop_count => return bitBuiltin(gz, scope, ri, node, params[0], .pop_count), + .byte_swap => return bitBuiltin(gz, scope, ri, node, params[0], .byte_swap), + .bit_reverse => return bitBuiltin(gz, scope, ri, node, params[0], .bit_reverse), - .div_exact => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_exact), - .div_floor => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_floor), - .div_trunc => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_trunc), - .mod => return divBuiltin(gz, scope, rl, node, params[0], params[1], .mod), - .rem => return divBuiltin(gz, scope, rl, node, params[0], params[1], .rem), + .div_exact => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_exact), + .div_floor => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_floor), + .div_trunc => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_trunc), + .mod => return divBuiltin(gz, scope, ri, node, params[0], params[1], .mod), + .rem => return divBuiltin(gz, scope, ri, node, params[0], params[1], .rem), - .shl_exact => return shiftOp(gz, scope, rl, node, params[0], params[1], .shl_exact), - .shr_exact => return shiftOp(gz, scope, rl, node, params[0], params[1], .shr_exact), + .shl_exact => return shiftOp(gz, scope, ri, node, params[0], params[1], .shl_exact), + .shr_exact => return shiftOp(gz, scope, ri, node, params[0], params[1], .shr_exact), - .bit_offset_of => return offsetOf(gz, scope, rl, node, params[0], params[1], .bit_offset_of), - .offset_of => return offsetOf(gz, scope, rl, node, params[0], params[1], .offset_of), + .bit_offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .bit_offset_of), + .offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .offset_of), - .c_undef => return simpleCBuiltin(gz, scope, rl, node, params[0], .c_undef), - .c_include => return simpleCBuiltin(gz, scope, rl, node, params[0], .c_include), + .c_undef => return simpleCBuiltin(gz, scope, ri, node, params[0], .c_undef), + .c_include => return simpleCBuiltin(gz, scope, ri, node, params[0], .c_include), - .cmpxchg_strong => return cmpxchg(gz, scope, rl, node, params, 1), - .cmpxchg_weak => return cmpxchg(gz, scope, rl, node, params, 0), + .cmpxchg_strong => return cmpxchg(gz, scope, ri, node, params, 1), + .cmpxchg_weak => return cmpxchg(gz, scope, ri, node, params, 0), // zig fmt: on .wasm_memory_size => { - const operand = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]); + const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]); const result = try gz.addExtendedPayload(.wasm_memory_size, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = operand, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .wasm_memory_grow => { - const index_arg = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]); - const delta_arg = try expr(gz, scope, .{ .coerced_ty = .u32_type }, params[1]); + const index_arg = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]); + const delta_arg = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[1]); const result = try gz.addExtendedPayload(.wasm_memory_grow, Zir.Inst.BinNode{ .node = gz.nodeIndexToRelative(node), .lhs = index_arg, .rhs = delta_arg, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .c_define => { if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{}); - const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[0]); - const value = try comptimeExpr(gz, scope, .none, params[1]); + const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0]); + const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]); const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{ .node = gz.nodeIndexToRelative(node), .lhs = name, .rhs = value, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .splat => { - const len = try expr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]); - const scalar = try expr(gz, scope, .none, params[1]); + const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]); + const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]); const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{ .lhs = len, .rhs = scalar, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .reduce => { - const op = try expr(gz, scope, .{ .ty = .reduce_op_type }, params[0]); - const scalar = try expr(gz, scope, .none, params[1]); + const op = try expr(gz, scope, .{ .rl = .{ .ty = .reduce_op_type } }, params[0]); + const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]); const result = try gz.addPlNode(.reduce, node, Zir.Inst.Bin{ .lhs = op, .rhs = scalar, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .max => { - const a = try expr(gz, scope, .none, params[0]); - const b = try expr(gz, scope, .none, params[1]); + const a = try expr(gz, scope, .{ .rl = .none }, params[0]); + const b = try expr(gz, scope, .{ .rl = .none }, params[1]); const result = try gz.addPlNode(.max, node, Zir.Inst.Bin{ .lhs = a, .rhs = b, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .min => { - const a = try expr(gz, scope, .none, params[0]); - const b = try expr(gz, scope, .none, params[1]); + const a = try expr(gz, scope, .{ .rl = .none }, params[0]); + const b = try expr(gz, scope, .{ .rl = .none }, params[1]); const result = try gz.addPlNode(.min, node, Zir.Inst.Bin{ .lhs = a, .rhs = b, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, - .add_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .add_with_overflow), - .sub_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .sub_with_overflow), - .mul_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .mul_with_overflow), + .add_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .add_with_overflow), + .sub_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .sub_with_overflow), + .mul_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .mul_with_overflow), .shl_with_overflow => { const int_type = try typeExpr(gz, scope, params[0]); const log2_int_type = try gz.addUnNode(.log2_int_type, int_type, params[0]); const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]); - const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]); - const rhs = try expr(gz, scope, .{ .ty = log2_int_type }, params[2]); - const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]); + const lhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[1]); + const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type } }, params[2]); + const ptr = try expr(gz, scope, .{ .rl = .{ .ty = ptr_type } }, params[3]); const result = try gz.addExtendedPayload(.shl_with_overflow, Zir.Inst.OverflowArithmetic{ .node = gz.nodeIndexToRelative(node), .lhs = lhs, .rhs = rhs, .ptr = ptr, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .atomic_load => { const result = try gz.addPlNode(.atomic_load, node, Zir.Inst.AtomicLoad{ // zig fmt: off - .elem_type = try typeExpr(gz, scope, params[0]), - .ptr = try expr (gz, scope, .none, params[1]), - .ordering = try expr (gz, scope, .{ .coerced_ty = .atomic_order_type }, params[2]), + .elem_type = try typeExpr(gz, scope, params[0]), + .ptr = try expr (gz, scope, .{ .rl = .none }, params[1]), + .ordering = try expr (gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[2]), // zig fmt: on }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .atomic_rmw => { const int_type = try typeExpr(gz, scope, params[0]); const result = try gz.addPlNode(.atomic_rmw, node, Zir.Inst.AtomicRmw{ // zig fmt: off - .ptr = try expr(gz, scope, .none, params[1]), - .operation = try expr(gz, scope, .{ .coerced_ty = .atomic_rmw_op_type }, params[2]), - .operand = try expr(gz, scope, .{ .ty = int_type }, params[3]), - .ordering = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[4]), + .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), + .operation = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_rmw_op_type } }, params[2]), + .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[3]), + .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[4]), // zig fmt: on }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .atomic_store => { const int_type = try typeExpr(gz, scope, params[0]); const result = try gz.addPlNode(.atomic_store, node, Zir.Inst.AtomicStore{ // zig fmt: off - .ptr = try expr(gz, scope, .none, params[1]), - .operand = try expr(gz, scope, .{ .ty = int_type }, params[2]), - .ordering = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[3]), + .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), + .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]), + .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[3]), // zig fmt: on }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .mul_add => { const float_type = try typeExpr(gz, scope, params[0]); - const mulend1 = try expr(gz, scope, .{ .coerced_ty = float_type }, params[1]); - const mulend2 = try expr(gz, scope, .{ .coerced_ty = float_type }, params[2]); - const addend = try expr(gz, scope, .{ .ty = float_type }, params[3]); + const mulend1 = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_type } }, params[1]); + const mulend2 = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_type } }, params[2]); + const addend = try expr(gz, scope, .{ .rl = .{ .ty = float_type } }, params[3]); const result = try gz.addPlNode(.mul_add, node, Zir.Inst.MulAdd{ .mulend1 = mulend1, .mulend2 = mulend2, .addend = addend, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .call => { - const options = try comptimeExpr(gz, scope, .{ .ty = .call_options_type }, params[0]); + const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .call_options_type } }, params[0]); const callee = try calleeExpr(gz, scope, params[1]); - const args = try expr(gz, scope, .none, params[2]); + const args = try expr(gz, scope, .{ .rl = .none }, params[2]); const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{ .options = options, .callee = callee, @@ -8153,115 +8167,115 @@ fn builtinCall( .ensure_result_used = false, }, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .field_parent_ptr => { const parent_type = try typeExpr(gz, scope, params[0]); - const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); + const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]); const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{ .parent_type = parent_type, .field_name = field_name, - .field_ptr = try expr(gz, scope, .none, params[2]), + .field_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .memcpy => { const result = try gz.addPlNode(.memcpy, node, Zir.Inst.Memcpy{ - .dest = try expr(gz, scope, .{ .coerced_ty = .manyptr_u8_type }, params[0]), - .source = try expr(gz, scope, .{ .coerced_ty = .manyptr_const_u8_type }, params[1]), - .byte_count = try expr(gz, scope, .{ .coerced_ty = .usize_type }, params[2]), + .dest = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_u8_type } }, params[0]), + .source = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_const_u8_type } }, params[1]), + .byte_count = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, params[2]), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .memset => { const result = try gz.addPlNode(.memset, node, Zir.Inst.Memset{ - .dest = try expr(gz, scope, .{ .coerced_ty = .manyptr_u8_type }, params[0]), - .byte = try expr(gz, scope, .{ .coerced_ty = .u8_type }, params[1]), - .byte_count = try expr(gz, scope, .{ .coerced_ty = .usize_type }, params[2]), + .dest = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_u8_type } }, params[0]), + .byte = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u8_type } }, params[1]), + .byte_count = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, params[2]), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .shuffle => { const result = try gz.addPlNode(.shuffle, node, Zir.Inst.Shuffle{ .elem_type = try typeExpr(gz, scope, params[0]), - .a = try expr(gz, scope, .none, params[1]), - .b = try expr(gz, scope, .none, params[2]), - .mask = try comptimeExpr(gz, scope, .none, params[3]), + .a = try expr(gz, scope, .{ .rl = .none }, params[1]), + .b = try expr(gz, scope, .{ .rl = .none }, params[2]), + .mask = try comptimeExpr(gz, scope, .{ .rl = .none }, params[3]), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .select => { const result = try gz.addExtendedPayload(.select, Zir.Inst.Select{ .node = gz.nodeIndexToRelative(node), .elem_type = try typeExpr(gz, scope, params[0]), - .pred = try expr(gz, scope, .none, params[1]), - .a = try expr(gz, scope, .none, params[2]), - .b = try expr(gz, scope, .none, params[3]), + .pred = try expr(gz, scope, .{ .rl = .none }, params[1]), + .a = try expr(gz, scope, .{ .rl = .none }, params[2]), + .b = try expr(gz, scope, .{ .rl = .none }, params[3]), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .async_call => { const result = try gz.addExtendedPayload(.builtin_async_call, Zir.Inst.AsyncCall{ .node = gz.nodeIndexToRelative(node), - .frame_buffer = try expr(gz, scope, .none, params[0]), - .result_ptr = try expr(gz, scope, .none, params[1]), - .fn_ptr = try expr(gz, scope, .none, params[2]), - .args = try expr(gz, scope, .none, params[3]), + .frame_buffer = try expr(gz, scope, .{ .rl = .none }, params[0]), + .result_ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), + .fn_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]), + .args = try expr(gz, scope, .{ .rl = .none }, params[3]), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .Vector => { const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{ - .lhs = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]), + .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]), .rhs = try typeExpr(gz, scope, params[1]), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, .prefetch => { - const ptr = try expr(gz, scope, .none, params[0]); - const options = try comptimeExpr(gz, scope, .{ .ty = .prefetch_options_type }, params[1]); + const ptr = try expr(gz, scope, .{ .rl = .none }, params[0]); + const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .prefetch_options_type } }, params[1]); const result = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{ .node = gz.nodeIndexToRelative(node), .lhs = ptr, .rhs = options, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); }, } } fn simpleNoOpVoid( gz: *GenZir, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { _ = try gz.addNode(tag, node); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); } fn hasDeclOrField( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, lhs_node: Ast.Node.Index, rhs_node: Ast.Node.Index, tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { const container_type = try typeExpr(gz, scope, lhs_node); - const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, rhs_node); + const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, rhs_node); const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ .lhs = container_type, .rhs = name, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn typeCast( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, lhs_node: Ast.Node.Index, rhs_node: Ast.Node.Index, @@ -8269,42 +8283,42 @@ fn typeCast( ) InnerError!Zir.Inst.Ref { const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ .lhs = try typeExpr(gz, scope, lhs_node), - .rhs = try expr(gz, scope, .none, rhs_node), + .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn simpleUnOpType( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, operand_node: Ast.Node.Index, tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { const operand = try typeExpr(gz, scope, operand_node); const result = try gz.addUnNode(tag, operand, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn simpleUnOp( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, - operand_rl: ResultLoc, + operand_ri: ResultInfo, operand_node: Ast.Node.Index, tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { - const operand = try expr(gz, scope, operand_rl, operand_node); + const operand = try expr(gz, scope, operand_ri, operand_node); const result = try gz.addUnNode(tag, operand, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn negation( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; @@ -8316,18 +8330,18 @@ fn negation( // its negativity rather than having it go through comptime subtraction. const operand_node = node_datas[node].lhs; if (node_tags[operand_node] == .number_literal) { - return numberLiteral(gz, rl, operand_node, node, .negative); + return numberLiteral(gz, ri, operand_node, node, .negative); } - const operand = try expr(gz, scope, .none, operand_node); + const operand = try expr(gz, scope, .{ .rl = .none }, operand_node); const result = try gz.addUnNode(.negate, operand, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn cmpxchg( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, params: []const Ast.Node.Index, small: u16, @@ -8336,98 +8350,98 @@ fn cmpxchg( const result = try gz.addExtendedPayloadSmall(.cmpxchg, small, Zir.Inst.Cmpxchg{ // zig fmt: off .node = gz.nodeIndexToRelative(node), - .ptr = try expr(gz, scope, .none, params[1]), - .expected_value = try expr(gz, scope, .{ .ty = int_type }, params[2]), - .new_value = try expr(gz, scope, .{ .coerced_ty = int_type }, params[3]), - .success_order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[4]), - .failure_order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[5]), + .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), + .expected_value = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]), + .new_value = try expr(gz, scope, .{ .rl = .{ .coerced_ty = int_type } }, params[3]), + .success_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[4]), + .failure_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[5]), // zig fmt: on }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn bitBuiltin( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, operand_node: Ast.Node.Index, tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { - const operand = try expr(gz, scope, .none, operand_node); + const operand = try expr(gz, scope, .{ .rl = .none }, operand_node); const result = try gz.addUnNode(tag, operand, node); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn divBuiltin( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, lhs_node: Ast.Node.Index, rhs_node: Ast.Node.Index, tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ - .lhs = try expr(gz, scope, .none, lhs_node), - .rhs = try expr(gz, scope, .none, rhs_node), + .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node), + .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node), }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn simpleCBuiltin( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, operand_node: Ast.Node.Index, tag: Zir.Inst.Extended, ) InnerError!Zir.Inst.Ref { const name: []const u8 = if (tag == .c_undef) "C undef" else "C include"; if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name}); - const operand = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, operand_node); + const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, operand_node); _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = operand, }); - return rvalue(gz, rl, .void_value, node); + return rvalue(gz, ri, .void_value, node); } fn offsetOf( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, lhs_node: Ast.Node.Index, rhs_node: Ast.Node.Index, tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { const type_inst = try typeExpr(gz, scope, lhs_node); - const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, rhs_node); + const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, rhs_node); const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ .lhs = type_inst, .rhs = field_name, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn shiftOp( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, lhs_node: Ast.Node.Index, rhs_node: Ast.Node.Index, tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { - const lhs = try expr(gz, scope, .none, lhs_node); + const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node); const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node); - const rhs = try expr(gz, scope, .{ .ty_shift_operand = log2_int_type }, rhs_node); + const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node); const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn cImport( @@ -8445,7 +8459,7 @@ fn cImport( defer block_scope.unstack(); const block_inst = try gz.makeBlockInst(.c_import, node); - const block_result = try expr(&block_scope, &block_scope.base, .none, body_node); + const block_result = try expr(&block_scope, &block_scope.base, .{ .rl = .none }, body_node); _ = try gz.addUnNode(.ensure_result_used, block_result, node); if (!gz.refIsNoReturn(block_result)) { _ = try block_scope.addBreak(.break_inline, block_inst, .void_value); @@ -8460,29 +8474,29 @@ fn cImport( fn overflowArithmetic( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, params: []const Ast.Node.Index, tag: Zir.Inst.Extended, ) InnerError!Zir.Inst.Ref { const int_type = try typeExpr(gz, scope, params[0]); const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]); - const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]); - const rhs = try expr(gz, scope, .{ .ty = int_type }, params[2]); - const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]); + const lhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[1]); + const rhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]); + const ptr = try expr(gz, scope, .{ .rl = .{ .ty = ptr_type } }, params[3]); const result = try gz.addExtendedPayload(tag, Zir.Inst.OverflowArithmetic{ .node = gz.nodeIndexToRelative(node), .lhs = lhs, .rhs = rhs, .ptr = ptr, }); - return rvalue(gz, rl, result, node); + return rvalue(gz, ri, result, node); } fn callExpr( gz: *GenZir, scope: *Scope, - rl: ResultLoc, + ri: ResultInfo, node: Ast.Node.Index, call: Ast.full.Call, ) InnerError!Zir.Inst.Ref { @@ -8534,7 +8548,7 @@ fn callExpr( defer arg_block.unstack(); // `call_inst` is reused to provide the param type. - const arg_ref = try expr(&arg_block, &arg_block.base, .{ .coerced_ty = call_inst }, param_node); + const arg_ref = try expr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst } }, param_node); _ = try arg_block.addBreak(.break_inline, call_index, arg_ref); const body = arg_block.instructionsSlice(); @@ -8547,13 +8561,8 @@ fn callExpr( // If our result location is a try/catch/error-union-if/return, the error trace propagates. // Otherwise, it should always be popped (handled in Sema). - const propagate_error_trace = switch (rl) { - .catch_none, .catch_ref => true, // Propagate to try/catch/error-union-if - .ptr, .ty => |ref| b: { // Otherwise, propagate if result loc is a return - const inst = refToIndex(ref) orelse break :b false; - const zir_tags = astgen.instructions.items(.tag); - break :b zir_tags[inst] == .ret_ptr or zir_tags[inst] == .ret_type; - }, + const propagate_error_trace = switch (ri.ctx) { + .error_handling_expr, .@"return" => true, // Propagate to try/catch/error-union-if and return else => false, }; @@ -8575,7 +8584,7 @@ fn callExpr( .payload_index = payload_index, } }, }); - return rvalue(gz, rl, call_inst, node); // TODO function call with result location + return rvalue(gz, ri, call_inst, node); // TODO function call with result location } /// calleeExpr generates the function part of a call expression (f in f(x)), or the @@ -8596,7 +8605,7 @@ fn calleeExpr( const tag = tree.nodes.items(.tag)[node]; switch (tag) { - .field_access => return addFieldAccess(.field_call_bind, gz, scope, .ref, node), + .field_access => return addFieldAccess(.field_call_bind, gz, scope, .{ .rl = .ref }, node), .builtin_call_two, .builtin_call_two_comma, @@ -8628,8 +8637,8 @@ fn calleeExpr( // If anything is wrong, fall back to builtinCall. // It will emit any necessary compile errors and notes. if (std.mem.eql(u8, builtin_name, "@field") and params.len == 2) { - const lhs = try expr(gz, scope, .ref, params[0]); - const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); + const lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]); + const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]); return gz.addExtendedPayload(.field_call_bind_named, Zir.Inst.FieldNamedNode{ .node = gz.nodeIndexToRelative(node), .lhs = lhs, @@ -8637,9 +8646,9 @@ fn calleeExpr( }); } - return builtinCall(gz, scope, .none, node, params); + return builtinCall(gz, scope, .{ .rl = .none }, node, params); }, - else => return expr(gz, scope, .none, node), + else => return expr(gz, scope, .{ .rl = .none }, node), } } @@ -9655,7 +9664,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool { /// Assumes nothing stacked on `gz`. fn rvalue( gz: *GenZir, - rl: ResultLoc, + ri: ResultInfo, raw_result: Zir.Inst.Ref, src_node: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { @@ -9670,14 +9679,14 @@ fn rvalue( break :r raw_result; }; if (gz.endsWithNoReturn()) return result; - switch (rl) { - .none, .catch_none, .coerced_ty => return result, + switch (ri.rl) { + .none, .coerced_ty => return result, .discard => { // Emit a compile error for discarding error values. _ = try gz.addUnNode(.ensure_result_non_error, result, src_node); return result; }, - .ref, .catch_ref => { + .ref => { // We need a pointer but we have a value. // Unfortunately it's not quite as simple as directly emitting a ref // instruction here because we need subsequent address-of operator on @@ -9696,7 +9705,7 @@ fn rvalue( } return indexToRef(gop.value_ptr.*); }, - .ty, .ty_shift_operand => |ty_inst| { + .ty => |ty_inst| { // Quickly eliminate some common, unnecessary type coercion. const as_ty = @as(u64, @enumToInt(Zir.Inst.Ref.type_type)) << 32; const as_comptime_int = @as(u64, @enumToInt(Zir.Inst.Ref.comptime_int_type)) << 32; @@ -9757,7 +9766,7 @@ fn rvalue( => return result, // type of result is already correct // Need an explicit type coercion instruction. - else => return gz.addPlNode(rl.zirTag(), src_node, Zir.Inst.As{ + else => return gz.addPlNode(ri.zirTag(), src_node, Zir.Inst.As{ .dest_type = ty_inst, .operand = result, }), @@ -10451,8 +10460,8 @@ const GenZir = struct { label: ?Label = null, break_block: Zir.Inst.Index = 0, continue_block: Zir.Inst.Index = 0, - /// Only valid when setBreakResultLoc is called. - break_result_loc: AstGen.ResultLoc = undefined, + /// Only valid when setBreakResultInfo is called. + break_result_info: AstGen.ResultInfo = undefined, /// When a block has a pointer result location, here it is. rl_ptr: Zir.Inst.Ref = .none, /// When a block has a type result location, here it is. @@ -10562,7 +10571,7 @@ const GenZir = struct { fn finishCoercion( as_scope: *GenZir, parent_gz: *GenZir, - rl: ResultLoc, + ri: ResultInfo, src_node: Ast.Node.Index, result: Zir.Inst.Ref, dest_type: Zir.Inst.Ref, @@ -10588,7 +10597,7 @@ const GenZir = struct { as_scope.instructions_top = GenZir.unstacked_top; // as_scope now unstacked, can add new instructions to parent_gz const casted_result = try parent_gz.addBin(.as, dest_type, result); - return rvalue(parent_gz, rl, casted_result, src_node); + return rvalue(parent_gz, ri, casted_result, src_node); } else { // implicitly move all as_scope instructions to parent_gz as_scope.instructions_top = GenZir.unstacked_top; @@ -10631,7 +10640,7 @@ const GenZir = struct { return gz.astgen.tree.firstToken(gz.decl_node_index); } - fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void { + fn setBreakResultInfo(gz: *GenZir, parent_ri: AstGen.ResultInfo) void { // Depending on whether the result location is a pointer or value, different // ZIR needs to be generated. In the former case we rely on storing to the // pointer to communicate the result, and use breakvoid; in the latter case @@ -10640,32 +10649,32 @@ const GenZir = struct { // the scenario where the result location is not consumed. In this case // we emit ZIR for the block break instructions to have the result values, // and then rvalue() on that to pass the value to the result location. - switch (parent_rl) { - .ty, .ty_shift_operand, .coerced_ty => |ty_inst| { + switch (parent_ri.rl) { + .ty, .coerced_ty => |ty_inst| { gz.rl_ty_inst = ty_inst; - gz.break_result_loc = parent_rl; + gz.break_result_info = parent_ri; }, - .discard, .none, .catch_none, .ref, .catch_ref => { + .discard, .none, .ref => { gz.rl_ty_inst = .none; - gz.break_result_loc = parent_rl; + gz.break_result_info = parent_ri; }, .ptr => |ptr_res| { gz.rl_ty_inst = .none; - gz.break_result_loc = .{ .ptr = .{ .inst = ptr_res.inst } }; + gz.break_result_info = .{ .rl = .{ .ptr = .{ .inst = ptr_res.inst } } }; }, .inferred_ptr => |ptr| { gz.rl_ty_inst = .none; gz.rl_ptr = ptr; - gz.break_result_loc = .{ .block_ptr = gz }; + gz.break_result_info = .{ .rl = .{ .block_ptr = gz }, .ctx = parent_ri.ctx }; }, .block_ptr => |parent_block_scope| { gz.rl_ty_inst = parent_block_scope.rl_ty_inst; gz.rl_ptr = parent_block_scope.rl_ptr; - gz.break_result_loc = .{ .block_ptr = gz }; + gz.break_result_info = .{ .rl = .{ .block_ptr = gz }, .ctx = parent_ri.ctx }; }, } } @@ -11815,10 +11824,10 @@ const GenZir = struct { return new_index; } - fn addRet(gz: *GenZir, rl: ResultLoc, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void { - switch (rl) { + fn addRet(gz: *GenZir, ri: ResultInfo, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void { + switch (ri.rl) { .ptr => |ptr_res| _ = try gz.addUnNode(.ret_load, ptr_res.inst, node), - .ty, .ty_shift_operand => _ = try gz.addUnNode(.ret_node, operand, node), + .ty => _ = try gz.addUnNode(.ret_node, operand, node), else => unreachable, } } |
