diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 1506a58497805ab61d5a12bb944eb21edb475aa1..e4f85b7a48094d82911c1831ca00e30b5f75c85d 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -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; } diff --git a/src/Package/Module.zig b/src/Package/Module.zig index cd7f573046fd41b8dd15beb54e0a3a189400d690..a922af2da5c26e2c2f2001889c1212d3af57893d 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -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; diff --git a/src/Sema.zig b/src/Sema.zig index 65311cafc188da131802235a34bc2582e76444a8..191da7c30dda58400f157c61d5739412cf08b7e0 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -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, diff --git a/src/target.zig b/src/target.zig index 100c0f690ba8fd099b13fa4e53626c8daf0234c7..fd6edbf0697958c376e82eaa9704459cec37a07e 100644 --- a/src/target.zig +++ b/src/target.zig @@ -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.