diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 359af18e82..c44081c770 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -3831,10 +3831,14 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable, LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, ""); + LLVMTypeRef same_size_int = LLVMIntType(size_in_bits); + LLVMValueRef mask = LLVMConstAllOnes(LLVMIntType(size_in_bits)); + mask = LLVMConstZExt(mask, LLVMTypeOf(containing_int)); + LLVMValueRef masked_value = LLVMBuildAnd(g->builder, shifted_value, mask, ""); + if (handle_is_ptr(g, child_type)) { LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); - LLVMTypeRef same_size_int = LLVMIntType(size_in_bits); - LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, ""); + LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, masked_value, same_size_int, ""); LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, result_loc, LLVMPointerType(same_size_int, 0), ""); LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr); @@ -3842,12 +3846,11 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable, } if (child_type->id == ZigTypeIdFloat) { - LLVMTypeRef same_size_int = LLVMIntType(size_in_bits); - LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, ""); + LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, masked_value, same_size_int, ""); return LLVMBuildBitCast(g->builder, truncated_int, get_llvm_type(g, child_type), ""); } - return LLVMBuildTrunc(g->builder, shifted_value, get_llvm_type(g, child_type), ""); + return LLVMBuildTrunc(g->builder, masked_value, get_llvm_type(g, child_type), ""); } static bool value_is_all_undef_array(CodeGen *g, ZigValue *const_val, size_t len) { diff --git a/test/behavior.zig b/test/behavior.zig index 7c6e98daa9..bb55ec83f1 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -71,6 +71,7 @@ test { _ = @import("behavior/bugs/7047.zig"); _ = @import("behavior/bugs/7003.zig"); _ = @import("behavior/bugs/7250.zig"); + _ = @import("behavior/bugs/9584.zig"); _ = @import("behavior/bugs/394.zig"); _ = @import("behavior/bugs/421.zig"); _ = @import("behavior/bugs/529.zig"); diff --git a/test/behavior/bugs/9584.zig b/test/behavior/bugs/9584.zig new file mode 100644 index 0000000000..63a607981e --- /dev/null +++ b/test/behavior/bugs/9584.zig @@ -0,0 +1,60 @@ +const std = @import("std"); + +const A = packed struct { + a: bool, + b: bool, + c: bool, + d: bool, + + e: bool, + f: bool, + g: bool, + h: bool, +}; + +const X = union { + x: A, + y: u64, +}; + +pub fn a( + x0: i32, + x1: i32, + x2: i32, + x3: i32, + x4: i32, + flag_a: bool, + flag_b: bool, +) !void { + _ = x0; + _ = x1; + _ = x2; + _ = x3; + _ = x4; + _ = flag_a; + // With this bug present, `flag_b` would actually contain the value 17. + // Note: this bug only presents itself on debug mode. + try std.testing.expect(@ptrCast(*const u8, &flag_b).* == 1); +} + +pub fn b(x: *X) !void { + try a(0, 1, 2, 3, 4, x.x.a, x.x.b); +} + +test "bug 9584" { + var flags = A{ + .a = false, + .b = true, + .c = false, + .d = false, + + .e = false, + .f = true, + .g = false, + .h = false, + }; + var x = X{ + .x = flags, + }; + try b(&x); +}