diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-09-08 12:51:12 +0300 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2022-09-08 12:51:40 +0300 |
| commit | c7e45aebafef0372fe231816eeffd18198240f14 (patch) | |
| tree | 15ec0a8376e8f578df1a0c86b6931327a76f795f | |
| parent | 44b9a1d031cb72cd64909b3a7bd0c65b2e16815b (diff) | |
| download | zig-c7e45aebafef0372fe231816eeffd18198240f14.tar.gz zig-c7e45aebafef0372fe231816eeffd18198240f14.zip | |
llvm: handle pointers in packed structs in more places
Closes #12776
| -rw-r--r-- | src/codegen/llvm.zig | 11 | ||||
| -rw-r--r-- | test/behavior.zig | 1 | ||||
| -rw-r--r-- | test/behavior/bugs/12776.zig | 42 |
3 files changed, 53 insertions, 1 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 80ffd7a665..043f0bbdc7 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -9204,6 +9204,12 @@ pub const FuncGen = struct { return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); } + if (info.pointee_type.isPtrAtRuntime()) { + const same_size_int = self.context.intType(elem_bits); + const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); + return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); + } + return self.builder.buildTrunc(shifted_value, elem_llvm_ty, ""); } @@ -9235,7 +9241,10 @@ pub const FuncGen = struct { // Convert to equally-sized integer type in order to perform the bit // operations on the value to store const value_bits_type = self.context.intType(elem_bits); - const value_bits = self.builder.buildBitCast(elem, value_bits_type, ""); + const value_bits = if (elem_ty.isPtrAtRuntime()) + self.builder.buildPtrToInt(elem, value_bits_type, "") + else + self.builder.buildBitCast(elem, value_bits_type, ""); var mask_val = value_bits_type.constAllOnes(); mask_val = mask_val.constZExt(containing_int_ty); diff --git a/test/behavior.zig b/test/behavior.zig index 4b55913af5..db107bcbb1 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -86,6 +86,7 @@ test { _ = @import("behavior/bugs/12430.zig"); _ = @import("behavior/bugs/12486.zig"); _ = @import("behavior/bugs/12680.zig"); + _ = @import("behavior/bugs/12776.zig"); _ = @import("behavior/byteswap.zig"); _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call.zig"); diff --git a/test/behavior/bugs/12776.zig b/test/behavior/bugs/12776.zig new file mode 100644 index 0000000000..e8fe106ac7 --- /dev/null +++ b/test/behavior/bugs/12776.zig @@ -0,0 +1,42 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +const RAM = struct { + data: [0xFFFF + 1]u8, + fn new() !RAM { + return RAM{ .data = [_]u8{0} ** 0x10000 }; + } + fn get(self: *RAM, addr: u16) u8 { + return self.data[addr]; + } +}; + +const CPU = packed struct { + interrupts: bool, + ram: *RAM, + fn new(ram: *RAM) !CPU { + return CPU{ + .ram = ram, + .interrupts = false, + }; + } + fn tick(self: *CPU) !void { + var queued_interrupts = self.ram.get(0xFFFF) & self.ram.get(0xFF0F); + if (self.interrupts and queued_interrupts != 0) { + self.interrupts = false; + } + } +}; + +test { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + + var ram = try RAM.new(); + var cpu = try CPU.new(&ram); + try cpu.tick(); + try std.testing.expect(cpu.interrupts == false); +} |
