Commit eac87ea8d6

mlugg <mlugg@mlugg.co.uk>
2024-12-18 21:29:54
compiler: disallow `align` etc annotations on comptime-only globals
This includes function aliases, but not function declarations. Also, re-introduce a target check for function alignment which was inadvertently removed in the prior commit.
1 parent 7408679
Changed files (3)
src/Zcu/PerThread.zig
@@ -1314,11 +1314,11 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
         };
     }
 
-    const queue_linker_work = switch (ip.indexToKey(decl_val.toIntern())) {
-        .func => true, // mote that this lets function aliases reach codegen
-        .variable => |v| v.owner_nav == nav_index,
-        .@"extern" => false,
-        else => true,
+    const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(decl_val.toIntern())) {
+        .func => |f| .{ true, f.owner_nav == nav_index }, // note that this lets function aliases reach codegen
+        .variable => |v| .{ v.owner_nav == nav_index, false },
+        .@"extern" => |e| .{ false, Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn" },
+        else => .{ true, false },
     };
 
     // Keep in sync with logic in `Sema.zirVarExtended`.
@@ -1363,6 +1363,28 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
         break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);
     };
 
+    if (is_owned_fn) {
+        // linksection etc are legal, except some targets do not support function alignment.
+        if (decl_bodies.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) {
+            return sema.fail(&block, align_src, "target does not support function alignment", .{});
+        }
+    } else if (try decl_ty.comptimeOnlySema(pt)) {
+        // alignment, linksection, addrspace annotations are not allowed for comptime-only types.
+        const reason: []const u8 = switch (ip.indexToKey(decl_val.toIntern())) {
+            .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations*
+            else => "comptime-only type",
+        };
+        if (decl_bodies.align_body != null) {
+            return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason});
+        }
+        if (decl_bodies.linksection_body != null) {
+            return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason});
+        }
+        if (decl_bodies.addrspace_body != null) {
+            return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason});
+        }
+    }
+
     ip.resolveNavValue(nav_index, .{
         .val = decl_val.toIntern(),
         .alignment = alignment,
test/behavior/type_info.zig
@@ -373,6 +373,17 @@ fn testFunction() !void {
     try expect(!foo_ptr_fn_info.pointer.is_allowzero);
     try expect(foo_ptr_fn_info.pointer.sentinel == null);
 
+    // Avoid looking at `typeInfoFooAligned` on targets which don't support function alignment.
+    switch (builtin.target.cpu.arch) {
+        .spirv,
+        .spirv32,
+        .spirv64,
+        .wasm32,
+        .wasm64,
+        => return,
+        else => {},
+    }
+
     const aligned_foo_fn_type = @TypeOf(typeInfoFooAligned);
     const aligned_foo_fn_info = @typeInfo(aligned_foo_fn_type);
     try expect(aligned_foo_fn_info.@"fn".calling_convention.eql(.c));
test/cases/compile_errors/comptime_only_global_align_section_addrspace.zig
@@ -0,0 +1,37 @@
+fn okay_func() void {}
+
+const a align(64) = okay_func;
+const b addrspace(.generic) = okay_func;
+const c linksection("irrelevant") = okay_func;
+
+const d align(64) = 1.23;
+const e addrspace(.generic) = 1.23;
+const f linksection("irrelevant") = 1.23;
+
+const g: comptime_float align(64) = 1.23;
+const h: comptime_float addrspace(.generic) = 1.23;
+const i: comptime_float linksection("irrelevant") = 1.23;
+
+// zig fmt: off
+comptime { _ = a; }
+comptime { _ = b; }
+comptime { _ = c; }
+comptime { _ = d; }
+comptime { _ = e; }
+comptime { _ = f; }
+comptime { _ = g; }
+comptime { _ = h; }
+comptime { _ = i; }
+// zig fmt: on
+
+// error
+//
+// :3:15: error: cannot specify alignment of function alias
+// :4:20: error: cannot specify addrspace of function alias
+// :5:21: error: cannot specify linksection of function alias
+// :7:15: error: cannot specify alignment of comptime-only type
+// :8:20: error: cannot specify addrspace of comptime-only type
+// :9:21: error: cannot specify linksection of comptime-only type
+// :11:31: error: cannot specify alignment of comptime-only type
+// :12:36: error: cannot specify addrspace of comptime-only type
+// :13:37: error: cannot specify linksection of comptime-only type