commit 1b544f447ac373ad676ccf921a2e8f2d05def15f (tree)
parent 5c42193b177e4b56ca91acb256cad36dd7cd4dec
Author: Alex Rønne Petersen <alex@alexrp.com>
Date: Sat, 24 Jan 2026 02:09:41 +0100
Merge pull request 'enable `thumb-windows-gnu` module tests' (#30968) from alexrp/zig:windows-pic into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30968
Diffstat:
5 files changed, 78 insertions(+), 38 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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 => 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.
@@ -56,9 +79,7 @@ pub fn picLevel(target: *const std.Target) u32 {
/// C compiler argument is valid to Clang.
pub fn supports_fpic(target: *const std.Target) bool {
return switch (target.os.tag) {
- .windows,
- .uefi,
- => target.abi == .gnu,
+ .windows, .uefi => false, // Technically allowed for `Abi.gnu`, but completely ignored by Clang (by design) anyway.
else => true,
};
}
diff --git a/test/tests.zig b/test/tests.zig
@@ -28,6 +28,8 @@ const TestTarget = struct {
use_lld: ?bool = null,
pic: ?bool = null,
strip: ?bool = null,
+ function_sections: ?bool = null,
+ data_sections: ?bool = null,
skip_modules: []const []const u8 = &.{},
// This is intended for targets that, for any reason, shouldn't be run as part of a normal test
@@ -40,7 +42,7 @@ const test_targets = blk: {
// getBaselineCpuFeatures calls populateDependencies which has a O(N ^ 2) algorithm
// (where N is roughly 160, which technically makes it O(1), but it adds up to a
// lot of branches)
- @setEvalBranchQuota(60000);
+ @setEvalBranchQuota(80_000);
break :blk [_]TestTarget{
// Native Targets
@@ -1526,36 +1528,43 @@ const test_targets = blk: {
},
.{
- .target = .{
- .cpu_arch = .thumb,
- .os_tag = .windows,
- .abi = .msvc,
- },
+ .target = std.Target.Query.parse(.{
+ .arch_os_abi = "thumb-windows-msvc",
+ .cpu_features = "baseline+long_calls",
+ }) catch unreachable,
+ .pic = false, // Long calls don't work with PIC.
+ .function_sections = true,
+ .data_sections = true,
},
.{
- .target = .{
- .cpu_arch = .thumb,
- .os_tag = .windows,
- .abi = .msvc,
- },
+ .target = std.Target.Query.parse(.{
+ .arch_os_abi = "thumb-windows-msvc",
+ .cpu_features = "baseline+long_calls",
+ }) catch unreachable,
.link_libc = true,
+ .pic = false, // Long calls don't work with PIC.
+ .function_sections = true,
+ .data_sections = true,
+ },
+ .{
+ .target = std.Target.Query.parse(.{
+ .arch_os_abi = "thumb-windows-gnu",
+ .cpu_features = "baseline+long_calls",
+ }) catch unreachable,
+ .pic = false, // Long calls don't work with PIC.
+ .function_sections = true,
+ .data_sections = true,
+ },
+ .{
+ .target = std.Target.Query.parse(.{
+ .arch_os_abi = "thumb-windows-gnu",
+ .cpu_features = "baseline+long_calls",
+ }) catch unreachable,
+ .link_libc = true,
+ .pic = false, // Long calls don't work with PIC.
+ .function_sections = true,
+ .data_sections = true,
},
- // https://github.com/ziglang/zig/issues/24016
- // .{
- // .target = .{
- // .cpu_arch = .thumb,
- // .os_tag = .windows,
- // .abi = .gnu,
- // },
- // },
- // .{
- // .target = .{
- // .cpu_arch = .thumb,
- // .os_tag = .windows,
- // .abi = .gnu,
- // },
- // .link_libc = true,
- // },
.{
.target = .{
@@ -2454,6 +2463,8 @@ fn addOneModuleTest(
if (options.build_options) |build_options| {
these_tests.root_module.addOptions("build_options", build_options);
}
+ if (test_target.function_sections) |fs| these_tests.link_function_sections = fs;
+ if (test_target.data_sections) |ds| these_tests.link_data_sections = ds;
const single_threaded_suffix = if (test_target.single_threaded == true) "-single" else "";
const backend_suffix = if (test_target.use_llvm == true)
"-llvm"