zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

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:
Msrc/stage1/codegen.cpp | 29++++++++++++++++++++++-------
Mtest/stage1/behavior.zig | 1+
Atest/stage1/behavior/bugs/7250.zig | 15+++++++++++++++
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); +}