fix nested bitcast passed as tuple element

This commit is contained in:
Andrew Kelley 2020-01-27 17:30:39 -05:00
parent e2778c03e0
commit c0fee9dfc7
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
4 changed files with 91 additions and 46 deletions

View File

@ -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)))

View File

@ -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);

View File

@ -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-

View File

@ -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))});
}