authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-12-18 20:29:54+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-12-19 03:21:56+00:00
logeac87ea8d646ccf07d25152649a9ff9ede23fc3d
tree5490d77c42080daec9443a889703f6c4d46dfc69
parent7408679234ae84afaf0130fb21c49b031ef52e3c
signaturelock-open Commit is signed but in an unrecognized format.

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.

3 files changed, 75 insertions(+), 5 deletions(-)

src/Zcu/PerThread.zig+27-5
...@@ -1314,11 +1314,11 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {...@@ -1314,11 +1314,11 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1314 };1314 };
1315 }1315 }
13161316
1317 const queue_linker_work = switch (ip.indexToKey(decl_val.toIntern())) {1317 const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(decl_val.toIntern())) {
1318 .func => true, // mote that this lets function aliases reach codegen1318 .func => |f| .{ true, f.owner_nav == nav_index }, // note that this lets function aliases reach codegen
1319 .variable => |v| v.owner_nav == nav_index,1319 .variable => |v| .{ v.owner_nav == nav_index, false },
1320 .@"extern" => false,1320 .@"extern" => |e| .{ false, Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn" },
1321 else => true,1321 else => .{ true, false },
1322 };1322 };
13231323
1324 // Keep in sync with logic in `Sema.zirVarExtended`.1324 // Keep in sync with logic in `Sema.zirVarExtended`.
...@@ -1363,6 +1363,28 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {...@@ -1363,6 +1363,28 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1363 break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);1363 break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);
1364 };1364 };
13651365
1366 if (is_owned_fn) {
1367 // linksection etc are legal, except some targets do not support function alignment.
1368 if (decl_bodies.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) {
1369 return sema.fail(&block, align_src, "target does not support function alignment", .{});
1370 }
1371 } else if (try decl_ty.comptimeOnlySema(pt)) {
1372 // alignment, linksection, addrspace annotations are not allowed for comptime-only types.
1373 const reason: []const u8 = switch (ip.indexToKey(decl_val.toIntern())) {
1374 .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations*
1375 else => "comptime-only type",
1376 };
1377 if (decl_bodies.align_body != null) {
1378 return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason});
1379 }
1380 if (decl_bodies.linksection_body != null) {
1381 return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason});
1382 }
1383 if (decl_bodies.addrspace_body != null) {
1384 return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason});
1385 }
1386 }
1387
1366 ip.resolveNavValue(nav_index, .{1388 ip.resolveNavValue(nav_index, .{
1367 .val = decl_val.toIntern(),1389 .val = decl_val.toIntern(),
1368 .alignment = alignment,1390 .alignment = alignment,
test/behavior/type_info.zig+11
...@@ -373,6 +373,17 @@ fn testFunction() !void {...@@ -373,6 +373,17 @@ fn testFunction() !void {
373 try expect(!foo_ptr_fn_info.pointer.is_allowzero);373 try expect(!foo_ptr_fn_info.pointer.is_allowzero);
374 try expect(foo_ptr_fn_info.pointer.sentinel == null);374 try expect(foo_ptr_fn_info.pointer.sentinel == null);
375375
376 // Avoid looking at `typeInfoFooAligned` on targets which don't support function alignment.
377 switch (builtin.target.cpu.arch) {
378 .spirv,
379 .spirv32,
380 .spirv64,
381 .wasm32,
382 .wasm64,
383 => return,
384 else => {},
385 }
386
376 const aligned_foo_fn_type = @TypeOf(typeInfoFooAligned);387 const aligned_foo_fn_type = @TypeOf(typeInfoFooAligned);
377 const aligned_foo_fn_info = @typeInfo(aligned_foo_fn_type);388 const aligned_foo_fn_info = @typeInfo(aligned_foo_fn_type);
378 try expect(aligned_foo_fn_info.@"fn".calling_convention.eql(.c));389 try expect(aligned_foo_fn_info.@"fn".calling_convention.eql(.c));
test/cases/compile_errors/comptime_only_global_align_section_addrspace.zig created+37
...@@ -0,0 +1,37 @@
1fn okay_func() void {}
2
3const a align(64) = okay_func;
4const b addrspace(.generic) = okay_func;
5const c linksection("irrelevant") = okay_func;
6
7const d align(64) = 1.23;
8const e addrspace(.generic) = 1.23;
9const f linksection("irrelevant") = 1.23;
10
11const g: comptime_float align(64) = 1.23;
12const h: comptime_float addrspace(.generic) = 1.23;
13const i: comptime_float linksection("irrelevant") = 1.23;
14
15// zig fmt: off
16comptime { _ = a; }
17comptime { _ = b; }
18comptime { _ = c; }
19comptime { _ = d; }
20comptime { _ = e; }
21comptime { _ = f; }
22comptime { _ = g; }
23comptime { _ = h; }
24comptime { _ = i; }
25// zig fmt: on
26
27// error
28//
29// :3:15: error: cannot specify alignment of function alias
30// :4:20: error: cannot specify addrspace of function alias
31// :5:21: error: cannot specify linksection of function alias
32// :7:15: error: cannot specify alignment of comptime-only type
33// :8:20: error: cannot specify addrspace of comptime-only type
34// :9:21: error: cannot specify linksection of comptime-only type
35// :11:31: error: cannot specify alignment of comptime-only type
36// :12:36: error: cannot specify addrspace of comptime-only type
37// :13:37: error: cannot specify linksection of comptime-only type