mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
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.
This commit is contained in:
+860
-851
@@ -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,
|
||||
pub const ResultInfo = struct {
|
||||
/// The semantics requested for the result location
|
||||
rl: Loc,
|
||||
|
||||
const PtrResultLoc = struct {
|
||||
inst: Zir.Inst.Ref,
|
||||
src_node: ?Ast.Node.Index = null,
|
||||
};
|
||||
|
||||
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: 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,
|
||||
},
|
||||
.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,
|
||||
};
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
/// The "operator" consuming the result location
|
||||
ctx: Context = .none,
|
||||
|
||||
/// 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,
|
||||
fn br(ri: ResultInfo) ResultInfo {
|
||||
return switch (ri.rl) {
|
||||
.coerced_ty => |ty| .{
|
||||
.rl = .{ .ty = ty },
|
||||
.ctx = ri.ctx,
|
||||
},
|
||||
else => ri,
|
||||
};
|
||||
}
|
||||
|
||||
fn zirTag(rl: ResultLoc) Zir.Inst.Tag {
|
||||
return switch (rl) {
|
||||
.ty => .as_node,
|
||||
.ty_shift_operand => .as_shift_operand,
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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),
|
||||
.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, 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),
|
||||
.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, 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),
|
||||
.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),
|
||||
.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, rl, 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),
|
||||
.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, 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),
|
||||
.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, 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),
|
||||
.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, 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),
|
||||
.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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ test "issue12891" {
|
||||
try std.testing.expect(i < f);
|
||||
}
|
||||
test "nan" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
const f = comptime std.math.nan(f64);
|
||||
|
||||
Reference in New Issue
Block a user