stage1: Add missing bitcast when rendering var ptr

Some types require this extra bitcast, eg. structs or unions with extra
padding fields inserted by the compiler.

Fixes #7250
This commit is contained in:
LemonBoy 2020-11-29 11:53:08 +01:00 committed by Andrew Kelley
parent be2adff087
commit 0a4a99ec87
3 changed files with 38 additions and 7 deletions

View File

@ -3893,15 +3893,30 @@ static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutableGen *exe
}
static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenVarPtr *instruction) {
if (instruction->base.value->special != ConstValSpecialRuntime)
return ir_llvm_value(g, &instruction->base);
ZigVar *var = instruction->var;
if (type_has_bits(g, var->var_type)) {
assert(var->value_ref);
return var->value_ref;
} else {
Error err;
ZigType *ptr_type = instruction->base.value->type;
assert(ptr_type->id == ZigTypeIdPointer);
bool ptr_type_has_bits;
if ((err = type_has_bits2(g, ptr_type, &ptr_type_has_bits)))
codegen_report_errors_and_exit(g);
if (!ptr_type_has_bits) {
return nullptr;
}
// The extra bitcasts are needed in case the LLVM value is an unnamed
// struct, as it happens when rendering container types with extra alignment
// fields.
if (instruction->base.value->special != ConstValSpecialRuntime) {
return LLVMBuildBitCast(g->builder, ir_llvm_value(g, &instruction->base),
get_llvm_type(g, ptr_type), "");
}
ZigVar *var = instruction->var;
assert(var->value_ref);
return LLVMBuildBitCast(g->builder, var->value_ref,
get_llvm_type(g, ptr_type), "");
}
static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutableGen *executable,

View File

@ -60,6 +60,7 @@ comptime {
_ = @import("behavior/bugs/7027.zig");
_ = @import("behavior/bugs/7047.zig");
_ = @import("behavior/bugs/7003.zig");
_ = @import("behavior/bugs/7250.zig");
_ = @import("behavior/bugs/394.zig");
_ = @import("behavior/bugs/421.zig");
_ = @import("behavior/bugs/529.zig");

View File

@ -0,0 +1,15 @@
const nrfx_uart_t = extern struct {
p_reg: [*c]u32,
drv_inst_idx: u8,
};
pub fn nrfx_uart_rx(p_instance: [*c]const nrfx_uart_t) void {}
threadlocal var g_uart0 = nrfx_uart_t{
.p_reg = 0,
.drv_inst_idx = 0,
};
test "reference a global threadlocal variable" {
_ = nrfx_uart_rx(&g_uart0);
}