From eac87ea8d646ccf07d25152649a9ff9ede23fc3d Mon Sep 17 00:00:00 2001 From: mlugg Date: Wed, 18 Dec 2024 20:29:54 +0000 Subject: [PATCH] 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. --- src/Zcu/PerThread.zig | 32 +++++++++++++--- test/behavior/type_info.zig | 11 ++++++ ...me_only_global_align_section_addrspace.zig | 37 +++++++++++++++++++ 3 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 test/cases/compile_errors/comptime_only_global_align_section_addrspace.zig diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 03576708e7..dd55978354 100644 --- a/src/Zcu/PerThread.zig +++ b/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, diff --git a/test/behavior/type_info.zig b/test/behavior/type_info.zig index 542d6b31b2..15be7cbcad 100644 --- a/test/behavior/type_info.zig +++ b/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)); diff --git a/test/cases/compile_errors/comptime_only_global_align_section_addrspace.zig b/test/cases/compile_errors/comptime_only_global_align_section_addrspace.zig new file mode 100644 index 0000000000..4ccc9ca18f --- /dev/null +++ b/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