zig

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

commit c7e45aebafef0372fe231816eeffd18198240f14 (tree)
parent 44b9a1d031cb72cd64909b3a7bd0c65b2e16815b
Author: Veikka Tuominen <git@vexu.eu>
Date:   Thu,  8 Sep 2022 12:51:12 +0300

llvm: handle pointers in packed structs in more places

Closes #12776

Diffstat:
Msrc/codegen/llvm.zig | 11++++++++++-
Mtest/behavior.zig | 1+
Atest/behavior/bugs/12776.zig | 42++++++++++++++++++++++++++++++++++++++++++
3 files changed, 53 insertions(+), 1 deletion(-)

diff --git 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 @@ -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 @@ -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); +}