compiler: don't enforce PIC for x86-windows and thumb-windows

Only x86_64-windows and aarch64-windows actually require PIC.
This commit is contained in:
Alex Rønne Petersen 2026-01-23 19:45:34 +01:00
parent 20fae334ac
commit 909159ad8e
No known key found for this signature in database
4 changed files with 39 additions and 8 deletions

View file

@ -255,7 +255,7 @@ pub fn resolve(options: Options) ResolveError!Config {
.Exe => true,
};
if (target_util.cannotDynamicLink(target)) {
if (!target_util.canDynamicLink(target)) {
if (options.link_mode == .dynamic) return error.TargetCannotDynamicLink;
break :b .static;
}

View file

@ -178,7 +178,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
return error.PieRequiresPic;
break :b true;
}
if (options.global.link_mode == .dynamic) {
if (options.global.link_mode == .dynamic and target_util.requiresPicForDynamicLink(target)) {
if (options.inherited.pic == false)
return error.DynamicLinkingRequiresPic;
break :b true;

View file

@ -9180,7 +9180,15 @@ pub fn handleExternLibName(
);
break :blk;
}
if (!target.cpu.arch.isWasm() and !block.ownerModule().pic) {
if (!target_util.canDynamicLink(target)) {
return sema.fail(
block,
src_loc,
"dependency on dynamic library '{s}' cannot be satisfied because target does not support dynamic linking",
.{lib_name},
);
}
if (!block.ownerModule().pic and target_util.requiresPicForDynamicLink(target)) {
return sema.fail(
block,
src_loc,

View file

@ -10,10 +10,24 @@ const Feature = @import("Zcu.zig").Feature;
pub const default_stack_protector_buffer_size = 4;
pub fn cannotDynamicLink(target: *const std.Target) bool {
return switch (target.os.tag) {
.freestanding, .uefi => true,
else => target.cpu.arch.isSpirV(),
pub fn canDynamicLink(target: *const std.Target) bool {
return switch (target.cpu.arch) {
.amdgcn,
.bpfeb,
.bpfel,
.nvptx,
.nvptx64,
.spirv32,
.spirv64,
=> false,
.wasm32,
.wasm64,
=> true,
else => switch (target.os.tag) {
// This list is likely incomplete.
.freestanding, .uefi => false,
else => true,
},
};
}
@ -41,11 +55,20 @@ pub fn libCxxNeedsLibUnwind(target: *const std.Target) bool {
/// This function returns whether non-pic code is completely invalid on the given target.
pub fn requiresPIC(target: *const std.Target, linking_libc: bool) bool {
return target.abi.isAndroid() or
target.os.tag == .windows or target.os.tag == .uefi or
((target.os.tag == .windows or target.os.tag == .uefi) and (target.cpu.arch == .aarch64 or target.cpu.arch == .x86_64)) or
target.requiresLibC() or
(linking_libc and target.isGnuLibC());
}
pub fn requiresPicForDynamicLink(target: *const std.Target) bool {
assert(canDynamicLink(target));
return switch (target.os.tag) {
.windows => target.cpu.arch == .aarch64 or target.cpu.arch == .x86_64,
else => !target.cpu.arch.isWasm(),
};
}
pub fn picLevel(target: *const std.Target) u32 {
// MIPS always uses PIC level 1; other platforms vary in their default PIC levels, but they
// support both level 1 and 2, in which case we prefer 2.