Commit 0a4a99ec87

LemonBoy <thatlemon@gmail.com>
2020-11-29 11:53:08
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
1 parent be2adff
Changed files (3)
src
test
stage1
behavior
src/stage1/codegen.cpp
@@ -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,
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);
+}
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");