authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-04-14 18:40:47+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-04-28 00:58:53+02:00
loge6a71e9e7a6c9708f568bc8a024e91bdd027cae9
tree9ed2d25dd4e59fdfcce84c3627150ce8cce30187
parent168981c67825fbdb3b70da8ff9f0f3b691bd36e5
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

Sema: Fix some ptr alignment checks to handle a potential ISA tag bit.

Closes #23570.

2 files changed, 26 insertions(+), 3 deletions(-)

src/Sema.zig+16-3
......@@ -23235,8 +23235,16 @@ fn ptrFromIntVal(
2323523235 const addr = try operand_val.toUnsignedIntSema(pt);
2323623236 if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0)
2323723237 return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(pt)});
23238 if (addr != 0 and ptr_align != .none and !ptr_align.check(addr))
23239 return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(pt)});
23238 if (addr != 0 and ptr_align != .none) {
23239 const masked_addr = if (ptr_ty.childType(zcu).fnPtrMaskOrNull(zcu)) |mask|
23240 addr & mask
23241 else
23242 addr;
23243
23244 if (!ptr_align.check(masked_addr)) {
23245 return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(pt)});
23246 }
23247 }
2324023248
2324123249 return switch (ptr_ty.zigTypeTag(zcu)) {
2324223250 .optional => Value.fromInterned(try pt.intern(.{ .opt = .{
......@@ -23752,7 +23760,12 @@ fn ptrCastFull(
2375223760
2375323761 if (dest_align.compare(.gt, src_align)) {
2375423762 if (try ptr_val.getUnsignedIntSema(pt)) |addr| {
23755 if (!dest_align.check(addr)) {
23763 const masked_addr = if (Type.fromInterned(dest_info.child).fnPtrMaskOrNull(zcu)) |mask|
23764 addr & mask
23765 else
23766 addr;
23767
23768 if (!dest_align.check(masked_addr)) {
2375623769 return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{
2375723770 addr,
2375823771 dest_align.toByteUnits().?,
test/behavior/align.zig+10
......@@ -635,3 +635,13 @@ test "function pointer @intFromPtr/@ptrFromInt roundtrip" {
635635
636636 try std.testing.expectEqual(nothing_ptr, nothing_ptr2);
637637}
638
639test "function pointer align mask" {
640 if (!(builtin.cpu.arch.isArm() or builtin.cpu.arch.isMIPS())) return error.SkipZigTest;
641
642 const a: *const fn () callconv(.c) void = @ptrFromInt(0x20202021);
643 _ = &a;
644
645 const b: *align(16) const fn () callconv(.c) void = @alignCast(a);
646 _ = &b;
647}