From e6a71e9e7a6c9708f568bc8a024e91bdd027cae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 14 Apr 2025 18:40:47 +0200 Subject: [PATCH] Sema: Fix some ptr alignment checks to handle a potential ISA tag bit. Closes #23570. --- src/Sema.zig | 19 ++++++++++++++++--- test/behavior/align.zig | 10 ++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 39d748c9ce..030a7c299a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -23235,8 +23235,16 @@ fn ptrFromIntVal( const addr = try operand_val.toUnsignedIntSema(pt); if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0) return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(pt)}); - if (addr != 0 and ptr_align != .none and !ptr_align.check(addr)) - return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(pt)}); + if (addr != 0 and ptr_align != .none) { + const masked_addr = if (ptr_ty.childType(zcu).fnPtrMaskOrNull(zcu)) |mask| + addr & mask + else + addr; + + if (!ptr_align.check(masked_addr)) { + return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(pt)}); + } + } return switch (ptr_ty.zigTypeTag(zcu)) { .optional => Value.fromInterned(try pt.intern(.{ .opt = .{ @@ -23752,7 +23760,12 @@ fn ptrCastFull( if (dest_align.compare(.gt, src_align)) { if (try ptr_val.getUnsignedIntSema(pt)) |addr| { - if (!dest_align.check(addr)) { + const masked_addr = if (Type.fromInterned(dest_info.child).fnPtrMaskOrNull(zcu)) |mask| + addr & mask + else + addr; + + if (!dest_align.check(masked_addr)) { return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align.toByteUnits().?, diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 2e015ea11f..5454fcf756 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -635,3 +635,13 @@ test "function pointer @intFromPtr/@ptrFromInt roundtrip" { try std.testing.expectEqual(nothing_ptr, nothing_ptr2); } + +test "function pointer align mask" { + if (!(builtin.cpu.arch.isArm() or builtin.cpu.arch.isMIPS())) return error.SkipZigTest; + + const a: *const fn () callconv(.c) void = @ptrFromInt(0x20202021); + _ = &a; + + const b: *align(16) const fn () callconv(.c) void = @alignCast(a); + _ = &b; +}