commit c80d196094de3e0258b4a1146cff56576ec8e95d (tree)
parent 48660371a2f66b3859831abb276180c557a12f93
Author: LemonBoy <thatlemon@gmail.com>
Date: Sun, 29 Nov 2020 11:53:08 +0100
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
Diffstat:
3 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp
@@ -3887,15 +3887,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,
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
@@ -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");
diff --git a/test/stage1/behavior/bugs/7250.zig b/test/stage1/behavior/bugs/7250.zig
@@ -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);
+}