aboutsummaryrefslogtreecommitdiff
path: root/src/Zcu/PerThread.zig
diff options
context:
space:
mode:
authorMatthew Lugg <mlugg@mlugg.co.uk>2024-12-19 07:57:16 +0000
committerGitHub <noreply@github.com>2024-12-19 07:57:16 +0000
commite2e3633612be656177512873a9de6524082d04dd (patch)
treec71b592a592e21b108fccc0be3f99a45b6a13c6e /src/Zcu/PerThread.zig
parentf857bf72e2239718bbbe4cba08d6961ad77fc69a (diff)
parent58b8b1ac2af642e886f3a561bf6dfd971bb80a96 (diff)
downloadzig-e2e3633612be656177512873a9de6524082d04dd.tar.gz
zig-e2e3633612be656177512873a9de6524082d04dd.zip
Merge pull request #22264 from mlugg/no-generic-callconv
compiler: disallow `callconv` etc from depending on function parameters Also, disallow `align`/`linksection`/`addrspace` annotations on container-level declarations with comptime-only types.
Diffstat (limited to 'src/Zcu/PerThread.zig')
-rw-r--r--src/Zcu/PerThread.zig124
1 files changed, 70 insertions, 54 deletions
diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
index acd14135fa..dd55978354 100644
--- a/src/Zcu/PerThread.zig
+++ b/src/Zcu/PerThread.zig
@@ -1314,68 +1314,84 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
};
}
- const nav_already_populated, const queue_linker_work = switch (ip.indexToKey(decl_val.toIntern())) {
- .func => |f| .{ f.owner_nav == nav_index, true },
- .variable => |v| .{ false, v.owner_nav == nav_index },
- .@"extern" => .{ false, false },
- else => .{ false, 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 },
};
- if (nav_already_populated) {
- // This is a function declaration.
- // Logic in `Sema.funcCommon` has already populated the `Nav` for us.
- assert(ip.getNav(nav_index).status.resolved.val == decl_val.toIntern());
- } else {
- // Keep in sync with logic in `Sema.zirVarExtended`.
- const alignment: InternPool.Alignment = a: {
- const align_body = decl_bodies.align_body orelse break :a .none;
- const align_ref = try sema.resolveInlineBody(&block, align_body, inst_info.inst);
- break :a try sema.analyzeAsAlign(&block, align_src, align_ref);
- };
+ // Keep in sync with logic in `Sema.zirVarExtended`.
+ const alignment: InternPool.Alignment = a: {
+ const align_body = decl_bodies.align_body orelse break :a .none;
+ const align_ref = try sema.resolveInlineBody(&block, align_body, inst_info.inst);
+ break :a try sema.analyzeAsAlign(&block, align_src, align_ref);
+ };
- const @"linksection": InternPool.OptionalNullTerminatedString = ls: {
- const linksection_body = decl_bodies.linksection_body orelse break :ls .none;
- const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_info.inst);
- const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{
- .needed_comptime_reason = "linksection must be comptime-known",
- });
- if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
- return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{});
- } else if (bytes.len == 0) {
- return sema.fail(&block, section_src, "linksection cannot be empty", .{});
- }
- break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);
- };
+ const @"linksection": InternPool.OptionalNullTerminatedString = ls: {
+ const linksection_body = decl_bodies.linksection_body orelse break :ls .none;
+ const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_info.inst);
+ const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{
+ .needed_comptime_reason = "linksection must be comptime-known",
+ });
+ if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
+ return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{});
+ } else if (bytes.len == 0) {
+ return sema.fail(&block, section_src, "linksection cannot be empty", .{});
+ }
+ break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);
+ };
- const @"addrspace": std.builtin.AddressSpace = as: {
- const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) {
- .func => .function,
- .variable => .variable,
- .@"extern" => |e| if (ip.indexToKey(e.ty) == .func_type)
- .function
- else
- .variable,
- else => .constant,
- };
- const target = zcu.getTarget();
- const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) {
- .function => target_util.defaultAddressSpace(target, .function),
- .variable => target_util.defaultAddressSpace(target, .global_mutable),
- .constant => target_util.defaultAddressSpace(target, .global_constant),
- else => unreachable,
- };
- const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_info.inst);
- break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);
+ const @"addrspace": std.builtin.AddressSpace = as: {
+ const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) {
+ .func => .function,
+ .variable => .variable,
+ .@"extern" => |e| if (ip.indexToKey(e.ty) == .func_type)
+ .function
+ else
+ .variable,
+ else => .constant,
};
+ const target = zcu.getTarget();
+ const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) {
+ .function => target_util.defaultAddressSpace(target, .function),
+ .variable => target_util.defaultAddressSpace(target, .global_mutable),
+ .constant => target_util.defaultAddressSpace(target, .global_constant),
+ else => unreachable,
+ };
+ const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_info.inst);
+ break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);
+ };
- ip.resolveNavValue(nav_index, .{
- .val = decl_val.toIntern(),
- .alignment = alignment,
- .@"linksection" = @"linksection",
- .@"addrspace" = @"addrspace",
- });
+ 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,
+ .@"linksection" = @"linksection",
+ .@"addrspace" = @"addrspace",
+ });
+
// Mark the `Cau` as completed before evaluating the export!
assert(zcu.analysis_in_progress.swapRemove(anal_unit));