rvalueInner
Function parameters
Parameters
- gz:*GenZir
- raw_result:Zir.Inst.Ref
- src_node:Ast.Node.Index
- allow_coerce_pre_ref:bool
Functions in this namespace
Functions
Source
Implementation
fn rvalueInner(
gz: *GenZir,
ri: ResultInfo,
raw_result: Zir.Inst.Ref,
src_node: Ast.Node.Index,
allow_coerce_pre_ref: bool,
) InnerError!Zir.Inst.Ref {
const result = r: {
if (raw_result.toIndex()) |result_index| {
const zir_tags = gz.astgen.instructions.items(.tag);
const data = gz.astgen.instructions.items(.data)[@intFromEnum(result_index)];
if (zir_tags[@intFromEnum(result_index)].isAlwaysVoid(data)) {
break :r Zir.Inst.Ref.void_value;
}
}
break :r raw_result;
};
if (gz.endsWithNoReturn()) 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 .void_value;
},
.ref, .ref_coerced_ty => {
const coerced_result = if (allow_coerce_pre_ref and ri.rl == .ref_coerced_ty) res: {
const ptr_ty = ri.rl.ref_coerced_ty;
break :res try gz.addPlNode(.coerce_ptr_elem_ty, src_node, Zir.Inst.Bin{
.lhs = ptr_ty,
.rhs = result,
});
} else result;
// 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
// const locals to return the same address.
const astgen = gz.astgen;
const tree = astgen.tree;
const src_token = tree.firstToken(src_node);
const result_index = coerced_result.toIndex() orelse
return gz.addUnTok(.ref, coerced_result, src_token);
const gop = try astgen.ref_table.getOrPut(astgen.gpa, result_index);
if (!gop.found_existing) {
gop.value_ptr.* = try gz.makeUnTok(.ref, coerced_result, src_token);
}
return gop.value_ptr.*.toRef();
},
.ty => |ty_inst| {
// Quickly eliminate some common, unnecessary type coercion.
const as_ty = @as(u64, @intFromEnum(Zir.Inst.Ref.type_type)) << 32;
const as_bool = @as(u64, @intFromEnum(Zir.Inst.Ref.bool_type)) << 32;
const as_void = @as(u64, @intFromEnum(Zir.Inst.Ref.void_type)) << 32;
const as_comptime_int = @as(u64, @intFromEnum(Zir.Inst.Ref.comptime_int_type)) << 32;
const as_usize = @as(u64, @intFromEnum(Zir.Inst.Ref.usize_type)) << 32;
const as_u1 = @as(u64, @intFromEnum(Zir.Inst.Ref.u1_type)) << 32;
const as_u8 = @as(u64, @intFromEnum(Zir.Inst.Ref.u8_type)) << 32;
switch ((@as(u64, @intFromEnum(ty_inst)) << 32) | @as(u64, @intFromEnum(result))) {
as_ty | @intFromEnum(Zir.Inst.Ref.u1_type),
as_ty | @intFromEnum(Zir.Inst.Ref.u8_type),
as_ty | @intFromEnum(Zir.Inst.Ref.i8_type),
as_ty | @intFromEnum(Zir.Inst.Ref.u16_type),
as_ty | @intFromEnum(Zir.Inst.Ref.u29_type),
as_ty | @intFromEnum(Zir.Inst.Ref.i16_type),
as_ty | @intFromEnum(Zir.Inst.Ref.u32_type),
as_ty | @intFromEnum(Zir.Inst.Ref.i32_type),
as_ty | @intFromEnum(Zir.Inst.Ref.u64_type),
as_ty | @intFromEnum(Zir.Inst.Ref.i64_type),
as_ty | @intFromEnum(Zir.Inst.Ref.u128_type),
as_ty | @intFromEnum(Zir.Inst.Ref.i128_type),
as_ty | @intFromEnum(Zir.Inst.Ref.usize_type),
as_ty | @intFromEnum(Zir.Inst.Ref.isize_type),
as_ty | @intFromEnum(Zir.Inst.Ref.c_char_type),
as_ty | @intFromEnum(Zir.Inst.Ref.c_short_type),
as_ty | @intFromEnum(Zir.Inst.Ref.c_ushort_type),
as_ty | @intFromEnum(Zir.Inst.Ref.c_int_type),
as_ty | @intFromEnum(Zir.Inst.Ref.c_uint_type),
as_ty | @intFromEnum(Zir.Inst.Ref.c_long_type),
as_ty | @intFromEnum(Zir.Inst.Ref.c_ulong_type),
as_ty | @intFromEnum(Zir.Inst.Ref.c_longlong_type),
as_ty | @intFromEnum(Zir.Inst.Ref.c_ulonglong_type),
as_ty | @intFromEnum(Zir.Inst.Ref.c_longdouble_type),
as_ty | @intFromEnum(Zir.Inst.Ref.f16_type),
as_ty | @intFromEnum(Zir.Inst.Ref.f32_type),
as_ty | @intFromEnum(Zir.Inst.Ref.f64_type),
as_ty | @intFromEnum(Zir.Inst.Ref.f80_type),
as_ty | @intFromEnum(Zir.Inst.Ref.f128_type),
as_ty | @intFromEnum(Zir.Inst.Ref.anyopaque_type),
as_ty | @intFromEnum(Zir.Inst.Ref.bool_type),
as_ty | @intFromEnum(Zir.Inst.Ref.void_type),
as_ty | @intFromEnum(Zir.Inst.Ref.type_type),
as_ty | @intFromEnum(Zir.Inst.Ref.anyerror_type),
as_ty | @intFromEnum(Zir.Inst.Ref.comptime_int_type),
as_ty | @intFromEnum(Zir.Inst.Ref.comptime_float_type),
as_ty | @intFromEnum(Zir.Inst.Ref.noreturn_type),
as_ty | @intFromEnum(Zir.Inst.Ref.anyframe_type),
as_ty | @intFromEnum(Zir.Inst.Ref.null_type),
as_ty | @intFromEnum(Zir.Inst.Ref.undefined_type),
as_ty | @intFromEnum(Zir.Inst.Ref.enum_literal_type),
as_ty | @intFromEnum(Zir.Inst.Ref.ptr_usize_type),
as_ty | @intFromEnum(Zir.Inst.Ref.ptr_const_comptime_int_type),
as_ty | @intFromEnum(Zir.Inst.Ref.manyptr_u8_type),
as_ty | @intFromEnum(Zir.Inst.Ref.manyptr_const_u8_type),
as_ty | @intFromEnum(Zir.Inst.Ref.manyptr_const_u8_sentinel_0_type),
as_ty | @intFromEnum(Zir.Inst.Ref.slice_const_u8_type),
as_ty | @intFromEnum(Zir.Inst.Ref.slice_const_u8_sentinel_0_type),
as_ty | @intFromEnum(Zir.Inst.Ref.anyerror_void_error_union_type),
as_ty | @intFromEnum(Zir.Inst.Ref.generic_poison_type),
as_ty | @intFromEnum(Zir.Inst.Ref.empty_tuple_type),
as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero),
as_comptime_int | @intFromEnum(Zir.Inst.Ref.one),
as_comptime_int | @intFromEnum(Zir.Inst.Ref.negative_one),
as_usize | @intFromEnum(Zir.Inst.Ref.undef_usize),
as_usize | @intFromEnum(Zir.Inst.Ref.zero_usize),
as_usize | @intFromEnum(Zir.Inst.Ref.one_usize),
as_u1 | @intFromEnum(Zir.Inst.Ref.undef_u1),
as_u1 | @intFromEnum(Zir.Inst.Ref.zero_u1),
as_u1 | @intFromEnum(Zir.Inst.Ref.one_u1),
as_u8 | @intFromEnum(Zir.Inst.Ref.zero_u8),
as_u8 | @intFromEnum(Zir.Inst.Ref.one_u8),
as_u8 | @intFromEnum(Zir.Inst.Ref.four_u8),
as_bool | @intFromEnum(Zir.Inst.Ref.undef_bool),
as_bool | @intFromEnum(Zir.Inst.Ref.bool_true),
as_bool | @intFromEnum(Zir.Inst.Ref.bool_false),
as_void | @intFromEnum(Zir.Inst.Ref.void_value),
=> return result, // type of result is already correct
as_bool | @intFromEnum(Zir.Inst.Ref.undef) => return .undef_bool,
as_usize | @intFromEnum(Zir.Inst.Ref.undef) => return .undef_usize,
as_usize | @intFromEnum(Zir.Inst.Ref.undef_u1) => return .undef_usize,
as_u1 | @intFromEnum(Zir.Inst.Ref.undef) => return .undef_u1,
as_usize | @intFromEnum(Zir.Inst.Ref.zero) => return .zero_usize,
as_u1 | @intFromEnum(Zir.Inst.Ref.zero) => return .zero_u1,
as_u8 | @intFromEnum(Zir.Inst.Ref.zero) => return .zero_u8,
as_usize | @intFromEnum(Zir.Inst.Ref.one) => return .one_usize,
as_u1 | @intFromEnum(Zir.Inst.Ref.one) => return .one_u1,
as_u8 | @intFromEnum(Zir.Inst.Ref.one) => return .one_u8,
as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero_usize) => return .zero,
as_u1 | @intFromEnum(Zir.Inst.Ref.zero_usize) => return .zero_u1,
as_u8 | @intFromEnum(Zir.Inst.Ref.zero_usize) => return .zero_u8,
as_comptime_int | @intFromEnum(Zir.Inst.Ref.one_usize) => return .one,
as_u1 | @intFromEnum(Zir.Inst.Ref.one_usize) => return .one_u1,
as_u8 | @intFromEnum(Zir.Inst.Ref.one_usize) => return .one_u8,
as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero_u1) => return .zero,
as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero_u8) => return .zero,
as_usize | @intFromEnum(Zir.Inst.Ref.zero_u1) => return .zero_usize,
as_usize | @intFromEnum(Zir.Inst.Ref.zero_u8) => return .zero_usize,
as_comptime_int | @intFromEnum(Zir.Inst.Ref.one_u1) => return .one,
as_comptime_int | @intFromEnum(Zir.Inst.Ref.one_u8) => return .one,
as_usize | @intFromEnum(Zir.Inst.Ref.one_u1) => return .one_usize,
as_usize | @intFromEnum(Zir.Inst.Ref.one_u8) => return .one_usize,
// Need an explicit type coercion instruction.
else => return gz.addPlNode(ri.zirTag(), src_node, Zir.Inst.As{
.dest_type = ty_inst,
.operand = result,
}),
}
},
.ptr => |ptr_res| {
_ = try gz.addPlNode(.store_node, ptr_res.src_node orelse src_node, Zir.Inst.Bin{
.lhs = ptr_res.inst,
.rhs = result,
});
return .void_value;
},
.inferred_ptr => |alloc| {
_ = try gz.addPlNode(.store_to_inferred_ptr, src_node, Zir.Inst.Bin{
.lhs = alloc,
.rhs = result,
});
return .void_value;
},
.destructure => |destructure| {
const components = destructure.components;
_ = try gz.addPlNode(.validate_destructure, src_node, Zir.Inst.ValidateDestructure{
.operand = result,
.destructure_node = gz.nodeIndexToRelative(destructure.src_node),
.expect_len = @intCast(components.len),
});
for (components, 0..) |component, i| {
if (component == .discard) continue;
const elem_val = try gz.add(.{
.tag = .elem_val_imm,
.data = .{ .elem_val_imm = .{
.operand = result,
.idx = @intCast(i),
} },
});
switch (component) {
.typed_ptr => |ptr_res| {
_ = try gz.addPlNode(.store_node, ptr_res.src_node orelse src_node, Zir.Inst.Bin{
.lhs = ptr_res.inst,
.rhs = elem_val,
});
},
.inferred_ptr => |ptr_inst| {
_ = try gz.addPlNode(.store_to_inferred_ptr, src_node, Zir.Inst.Bin{
.lhs = ptr_inst,
.rhs = elem_val,
});
},
.discard => unreachable,
}
}
return .void_value;
},
}
}