Commit 5ed8bd5c85

Alex Rønne Petersen <alex@alexrp.com>
2025-04-14 18:40:47
Sema: Fix some ptr alignment checks to handle a potential ISA tag bit.
Closes #23570.
1 parent e7b4636
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -22614,8 +22614,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 = .{
@@ -23131,7 +23139,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().?,
test/behavior/align.zig
@@ -596,3 +596,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;
+}