mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
fix nested bitcast passed as tuple element
This commit is contained in:
parent
e2778c03e0
commit
c0fee9dfc7
@ -593,9 +593,9 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
|
||||
}
|
||||
|
||||
if (inferred_struct_field != nullptr) {
|
||||
entry->abi_size = g->builtin_types.entry_usize->abi_size;
|
||||
entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
|
||||
entry->abi_align = g->builtin_types.entry_usize->abi_align;
|
||||
entry->abi_size = SIZE_MAX;
|
||||
entry->size_in_bits = SIZE_MAX;
|
||||
entry->abi_align = UINT32_MAX;
|
||||
} else if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
|
||||
if (type_has_bits(child_type)) {
|
||||
entry->abi_size = g->builtin_types.entry_usize->abi_size;
|
||||
@ -6474,7 +6474,21 @@ static Error resolve_pointer_zero_bits(CodeGen *g, ZigType *ty) {
|
||||
}
|
||||
ty->data.pointer.resolve_loop_flag_zero_bits = true;
|
||||
|
||||
ZigType *elem_type = ty->data.pointer.child_type;
|
||||
ZigType *elem_type;
|
||||
InferredStructField *isf = ty->data.pointer.inferred_struct_field;
|
||||
if (isf != nullptr) {
|
||||
TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
|
||||
assert(field != nullptr);
|
||||
if (field->is_comptime) {
|
||||
ty->abi_size = 0;
|
||||
ty->size_in_bits = 0;
|
||||
ty->abi_align = 0;
|
||||
return ErrorNone;
|
||||
}
|
||||
elem_type = field->type_entry;
|
||||
} else {
|
||||
elem_type = ty->data.pointer.child_type;
|
||||
}
|
||||
|
||||
bool has_bits;
|
||||
if ((err = type_has_bits2(g, elem_type, &has_bits)))
|
||||
|
||||
@ -3120,8 +3120,14 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutableGen *executab
|
||||
static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable,
|
||||
IrInstGenCast *cast_instruction)
|
||||
{
|
||||
Error err;
|
||||
ZigType *actual_type = cast_instruction->value->value->type;
|
||||
ZigType *wanted_type = cast_instruction->base.value->type;
|
||||
bool wanted_type_has_bits;
|
||||
if ((err = type_has_bits2(g, wanted_type, &wanted_type_has_bits)))
|
||||
codegen_report_errors_and_exit(g);
|
||||
if (!wanted_type_has_bits)
|
||||
return nullptr;
|
||||
LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);
|
||||
ir_assert(expr_val, &cast_instruction->base);
|
||||
|
||||
|
||||
92
src/ir.cpp
92
src/ir.cpp
@ -880,7 +880,6 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte
|
||||
case ZigTypeIdComptimeFloat:
|
||||
case ZigTypeIdComptimeInt:
|
||||
case ZigTypeIdEnumLiteral:
|
||||
case ZigTypeIdPointer:
|
||||
case ZigTypeIdUndefined:
|
||||
case ZigTypeIdNull:
|
||||
case ZigTypeIdBoundFn:
|
||||
@ -889,6 +888,8 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte
|
||||
case ZigTypeIdAnyFrame:
|
||||
case ZigTypeIdFn:
|
||||
return true;
|
||||
case ZigTypeIdPointer:
|
||||
return expected->data.pointer.inferred_struct_field == actual->data.pointer.inferred_struct_field;
|
||||
case ZigTypeIdFloat:
|
||||
return expected->data.floating.bit_count == actual->data.floating.bit_count;
|
||||
case ZigTypeIdInt:
|
||||
@ -7014,6 +7015,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
|
||||
ResultLocBitCast *result_loc_bit_cast = allocate<ResultLocBitCast>(1);
|
||||
result_loc_bit_cast->base.id = ResultLocIdBitCast;
|
||||
result_loc_bit_cast->base.source_instruction = dest_type;
|
||||
result_loc_bit_cast->base.allow_write_through_const = result_loc->allow_write_through_const;
|
||||
ir_ref_instruction(dest_type, irb->current_basic_block);
|
||||
result_loc_bit_cast->parent = result_loc;
|
||||
|
||||
@ -13597,32 +13599,31 @@ static IrInstGen *ir_analyze_null_to_c_pointer(IrAnalyze *ira, IrInst *source_in
|
||||
return result;
|
||||
}
|
||||
|
||||
static IrInstGen *ir_get_ref(IrAnalyze *ira, IrInst* source_instruction, IrInstGen *value,
|
||||
bool is_const, bool is_volatile)
|
||||
static IrInstGen *ir_get_ref2(IrAnalyze *ira, IrInst* source_instruction, IrInstGen *value,
|
||||
ZigType *elem_type, bool is_const, bool is_volatile)
|
||||
{
|
||||
Error err;
|
||||
|
||||
if (type_is_invalid(value->value->type))
|
||||
if (type_is_invalid(elem_type))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
if (instr_is_comptime(value)) {
|
||||
ZigValue *val = ir_resolve_const(ira, value, LazyOk);
|
||||
if (!val)
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
return ir_get_const_ptr(ira, source_instruction, val, value->value->type,
|
||||
return ir_get_const_ptr(ira, source_instruction, val, elem_type,
|
||||
ConstPtrMutComptimeConst, is_const, is_volatile, 0);
|
||||
}
|
||||
|
||||
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value->type,
|
||||
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type,
|
||||
is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
|
||||
|
||||
if ((err = type_resolve(ira->codegen, ptr_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
IrInstGen *result_loc;
|
||||
if (type_has_bits(ptr_type) && !handle_is_ptr(value->value->type)) {
|
||||
result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value->type,
|
||||
nullptr, true, true);
|
||||
if (type_has_bits(ptr_type) && !handle_is_ptr(elem_type)) {
|
||||
result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), elem_type, nullptr, true, true);
|
||||
} else {
|
||||
result_loc = nullptr;
|
||||
}
|
||||
@ -13632,6 +13633,12 @@ static IrInstGen *ir_get_ref(IrAnalyze *ira, IrInst* source_instruction, IrInstG
|
||||
return new_instruction;
|
||||
}
|
||||
|
||||
static IrInstGen *ir_get_ref(IrAnalyze *ira, IrInst* source_instruction, IrInstGen *value,
|
||||
bool is_const, bool is_volatile)
|
||||
{
|
||||
return ir_get_ref2(ira, source_instruction, value, value->value->type, is_const, is_volatile);
|
||||
}
|
||||
|
||||
static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, AstNode *source_node, ZigType *union_type) {
|
||||
assert(union_type->id == ZigTypeIdUnion);
|
||||
|
||||
@ -18204,6 +18211,21 @@ static IrInstGen *ir_resolve_no_result_loc(IrAnalyze *ira, IrInst *suspend_sourc
|
||||
return result_loc->resolved_loc;
|
||||
}
|
||||
|
||||
static bool result_loc_is_discard(ResultLoc *result_loc_pass1) {
|
||||
if (result_loc_pass1->id == ResultLocIdInstruction &&
|
||||
result_loc_pass1->source_instruction->id == IrInstSrcIdConst)
|
||||
{
|
||||
IrInstSrcConst *const_inst = reinterpret_cast<IrInstSrcConst *>(result_loc_pass1->source_instruction);
|
||||
if (value_is_comptime(const_inst->value) &&
|
||||
const_inst->value->type->id == ZigTypeIdPointer &&
|
||||
const_inst->value->data.x_ptr.special == ConstPtrSpecialDiscard)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// when calling this function, at the callsite must check for result type noreturn and propagate it up
|
||||
static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_instr,
|
||||
ResultLoc *result_loc, ZigType *value_type, IrInstGen *value, bool force_runtime,
|
||||
@ -18494,13 +18516,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
|
||||
assert(parent_ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *child_type = parent_ptr_type->data.pointer.child_type;
|
||||
|
||||
bool has_bits;
|
||||
if ((err = type_has_bits2(ira->codegen, child_type, &has_bits))) {
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
|
||||
// This happens when the bitCast result is assigned to _
|
||||
if (!has_bits) {
|
||||
if (result_loc_is_discard(result_bit_cast->parent)) {
|
||||
assert(allow_discard);
|
||||
return parent_result_loc;
|
||||
}
|
||||
@ -18531,16 +18547,8 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr
|
||||
bool allow_discard)
|
||||
{
|
||||
Error err;
|
||||
if (!allow_discard && result_loc_pass1->id == ResultLocIdInstruction &&
|
||||
result_loc_pass1->source_instruction->id == IrInstSrcIdConst)
|
||||
{
|
||||
IrInstSrcConst *const_inst = reinterpret_cast<IrInstSrcConst *>(result_loc_pass1->source_instruction);
|
||||
if (value_is_comptime(const_inst->value) &&
|
||||
const_inst->value->type->id == ZigTypeIdPointer &&
|
||||
const_inst->value->data.x_ptr.special == ConstPtrSpecialDiscard)
|
||||
{
|
||||
result_loc_pass1 = no_result_loc();
|
||||
}
|
||||
if (!allow_discard && result_loc_is_discard(result_loc_pass1)) {
|
||||
result_loc_pass1 = no_result_loc();
|
||||
}
|
||||
bool was_written = result_loc_pass1->written;
|
||||
IrInstGen *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type,
|
||||
@ -21062,7 +21070,7 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins
|
||||
IrInstGen *elem = ir_const(ira, source_instr, field_type);
|
||||
memoize_field_init_val(ira->codegen, struct_type, field);
|
||||
copy_const_val(elem->value, field->init_val);
|
||||
return ir_get_ref(ira, source_instr, elem, true, false);
|
||||
return ir_get_ref2(ira, source_instr, elem, field_type, true, false);
|
||||
}
|
||||
switch (type_has_one_possible_value(ira->codegen, field_type)) {
|
||||
case OnePossibleValueInvalid:
|
||||
@ -27708,7 +27716,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
|
||||
if ((err = type_resolve(ira->codegen, src_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
|
||||
if (type_has_bits(dest_type) && !type_has_bits(src_type) && safety_check_on) {
|
||||
ErrorMsg *msg = ir_add_error(ira, source_instr,
|
||||
buf_sprintf("'%s' and '%s' do not have the same in-memory representation",
|
||||
buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
|
||||
@ -27723,7 +27731,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
|
||||
bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type);
|
||||
UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad;
|
||||
ZigValue *val = ir_resolve_const(ira, ptr, is_undef_allowed);
|
||||
if (!val)
|
||||
if (val == nullptr)
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
if (value_is_comptime(val) && val->special != ConstValSpecialUndef) {
|
||||
@ -27738,15 +27746,31 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
|
||||
}
|
||||
|
||||
IrInstGen *result;
|
||||
if (ptr->value->data.x_ptr.mut == ConstPtrMutInfer) {
|
||||
if (val->data.x_ptr.mut == ConstPtrMutInfer) {
|
||||
result = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
|
||||
|
||||
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
} else {
|
||||
result = ir_const(ira, source_instr, dest_type);
|
||||
}
|
||||
copy_const_val(result->value, val);
|
||||
InferredStructField *isf = (val->type->id == ZigTypeIdPointer) ?
|
||||
val->type->data.pointer.inferred_struct_field : nullptr;
|
||||
if (isf == nullptr) {
|
||||
copy_const_val(result->value, val);
|
||||
} else {
|
||||
// The destination value should have x_ptr struct pointing to underlying struct value
|
||||
result->value->data.x_ptr.mut = val->data.x_ptr.mut;
|
||||
TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
|
||||
assert(field != nullptr);
|
||||
if (field->is_comptime) {
|
||||
result->value->data.x_ptr.special = ConstPtrSpecialRef;
|
||||
result->value->data.x_ptr.data.ref.pointee = field->init_val;
|
||||
} else {
|
||||
assert(val->data.x_ptr.special == ConstPtrSpecialRef);
|
||||
result->value->data.x_ptr.special = ConstPtrSpecialBaseStruct;
|
||||
result->value->data.x_ptr.data.base_struct.struct_val = val->data.x_ptr.data.ref.pointee;
|
||||
result->value->data.x_ptr.data.base_struct.field_index = field->src_index;
|
||||
}
|
||||
result->value->special = ConstValSpecialStatic;
|
||||
}
|
||||
result->value->type = dest_type;
|
||||
|
||||
// Keep the bigger alignment, it can only help-
|
||||
|
||||
@ -168,11 +168,12 @@ test "nested bitcast" {
|
||||
comptime S.foo(42);
|
||||
}
|
||||
|
||||
//test "bitcast passed as tuple element" {
|
||||
// const S = struct {
|
||||
// fn foo(args: var) void {
|
||||
// expect(args[0] == 1.00000e-09);
|
||||
// }
|
||||
// };
|
||||
// S.foo(.{@bitCast(f32, @as(u32, 814313563))});
|
||||
//}
|
||||
test "bitcast passed as tuple element" {
|
||||
const S = struct {
|
||||
fn foo(args: var) void {
|
||||
comptime expect(@TypeOf(args[0]) == f32);
|
||||
expect(args[0] == 12.34);
|
||||
}
|
||||
};
|
||||
S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user