authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-09 09:57:20+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-10 08:36:08+02:00
log93316d6e613cbcf0b1f94da42bffdf9eac3223de
tree7419c1d4910c58c5dddf35f661c3133c56eacfde
parent03422925b127a8d369fc82ce333e2d77366c3849
signature Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.zig.target: move isNative() here from test harness


5 files changed, 165 insertions(+), 163 deletions(-)

lib/std/zig/target.zig+158
...@@ -537,6 +537,164 @@ pub fn compilerRtFloatAbi(target: *const std.Target, bits: u16) std.Target.Abi.F...@@ -537,6 +537,164 @@ pub fn compilerRtFloatAbi(target: *const std.Target, bits: u16) std.Target.Abi.F
537 return .hard;537 return .hard;
538}538}
539539
540fn supportedCompatArch(host: *const std.Target, arch: std.Target.Cpu.Arch) bool {
541 // aarch64-freebsd and aarch64-linux can technically run 32-bit ARM binaries, but that depends
542 // on AArch32 support in the CPU. Since modern AArch64 CPUs have largely dropped this support,
543 // avoid reporting compatibility for 32-bit here since we'd just build a bunch of test binaries
544 // that never get run anyway. This added almost an hour's worth of useless work to aarch64-linux
545 // CI, for example.
546 //
547 // riscv64-linux and riscv64-netbsd similarly support 32-bit binaries. However, this requires a
548 // very recent kernel and for the kernel feature to be enabled. Additionally, contemporary
549 // RISC-V hardware is just too slow to justify building the 32-bit binaries.
550 return switch (host.os.tag) {
551 .illumos => switch (host.cpu.arch) {
552 .x86_64 => arch == .x86,
553 else => false,
554 },
555 .linux => switch (host.cpu.arch) {
556 .mips64 => arch == .mips,
557 .mips64el => arch == .mipsel,
558 .powerpc64 => arch == .powerpc,
559 .sparc64 => arch == .sparc,
560 .x86_64 => arch == .x86,
561 else => false,
562 },
563 .netbsd => switch (host.cpu.arch) {
564 .sparc64 => arch == .sparc,
565 .x86_64 => arch == .x86,
566 else => false,
567 },
568 .windows => switch (host.cpu.arch) {
569 .x86_64 => arch == .x86,
570 else => false,
571 },
572 else => false,
573 };
574}
575
576/// Intended for test code to determine whether it makes sense to run a test for a particular target
577/// on the host. This is not an objective check; it is best-effort and also makes subjective
578/// judgements for some targets.
579pub fn isNative(query: *const std.Target.Query, target: *const std.Target, host: *const std.Target) bool {
580 if (query.isNative()) return true;
581
582 if (target.cpu.arch != host.cpu.arch and !supportedCompatArch(host, target.cpu.arch))
583 return false;
584
585 if (target.os.tag != host.os.tag)
586 return false;
587
588 // This check is really only necessary for the case where `host.cpu.arch.isAarch64()` and
589 // `target.cpu.arch.isArm()`. As they are wholly separate `std.Target` families with their own
590 // feature bits, the logic below would produce complete nonsense.
591 //
592 // This does mean that we aren't actually checking feature compatibility between these two
593 // families even though we should. That's not a problem currently, but in the future, we may
594 // need to add a special code path just for this specific case...
595 if (target.cpu.arch.family() != host.cpu.arch.family())
596 return true;
597
598 // Remove features that don't actually affect compatibility.
599 const irrelevant: std.Target.Cpu.Feature.Set = switch (host.cpu.arch) {
600 .x86_64 => std.Target.x86.featureSet(&.{
601 .@"16bit_mode",
602 .@"32bit_mode",
603 .@"64bit",
604 .false_deps_bls,
605 .false_deps_compress,
606 .false_deps_expand,
607 .false_deps_getmant,
608 .false_deps_lzcnt,
609 .false_deps_mulc,
610 .false_deps_mullq,
611 .false_deps_perm,
612 .false_deps_popcnt,
613 .false_deps_range,
614 .false_deps_tzcnt,
615 .fast_11bytenop,
616 .fast_15bytenop,
617 .fast_7bytenop,
618 .fast_bextr,
619 .fast_dpwssd,
620 .fast_gather,
621 .fast_hops,
622 .fast_imm16,
623 .fast_lzcnt,
624 .fast_movbe,
625 .fast_scalar_fsqrt,
626 .fast_scalar_shift_masks,
627 .fast_shld_rotate,
628 .fast_variable_crosslane_shuffle,
629 .fast_variable_perlane_shuffle,
630 .fast_vector_fsqrt,
631 .fast_vector_shift_masks,
632 .faster_shift_than_shuffle,
633 .no_bypass_delay,
634 .no_bypass_delay_blend,
635 .no_bypass_delay_mov,
636 .no_bypass_delay_shuffle,
637 .prefer_128_bit,
638 .prefer_256_bit,
639 .prefer_legacy_setcc,
640 .prefer_mask_registers,
641 .prefer_movmsk_over_vtest,
642 .prefer_ndd_mem,
643 .prefer_no_gather,
644 .prefer_no_scatter,
645 .slow_3ops_lea,
646 .slow_incdec,
647 .slow_indirect_call,
648 .slow_lea,
649 .slow_pmaddwd,
650 .slow_pmulld,
651 .slow_pmullq,
652 .slow_shld,
653 .slow_two_mem_ops,
654 .slow_unaligned_mem_16,
655 .slow_unaligned_mem_32,
656 }),
657 .aarch64, .aarch64_be => std.Target.aarch64.featureSet(&.{
658 .addr_lsl_slow_14,
659 .align_cmp_csel_pairs,
660 .alu_lsl_fast,
661 .avoid_ldapur,
662 .disable_fast_inc_vl,
663 .exynos_cheap_as_move,
664 .fast_ld1_single,
665 .fixed_load_latency_4,
666 .fuse_address,
667 .fuse_addsub_2reg_const1,
668 .fuse_adrp_add,
669 .fuse_aes,
670 .fuse_arith_logic,
671 .fuse_crypto_eor,
672 .fuse_csel,
673 .fuse_cset,
674 .fuse_fcsel,
675 .fuse_literals,
676 .has_limited_64bit_vector_mul_bandwidth,
677 .predictable_select_expensive,
678 .slow_misaligned_128store,
679 .slow_paired_128,
680 .slow_strqro_store,
681 .use_experimental_zeroing_pseudos,
682 .use_fixed_over_scalable_if_equal_cost,
683 .use_postra_scheduler,
684 .use_reciprocal_square_root,
685 .use_wzr_to_vec_move,
686 }),
687 else => .empty,
688 };
689 var set = target.cpu.features;
690 set.removeFeatureSet(irrelevant);
691
692 if (!host.cpu.features.isSuperSetOf(set))
693 return false;
694
695 return true;
696}
697
540const std = @import("std");698const std = @import("std");
541const assert = std.debug.assert;699const assert = std.debug.assert;
542const Allocator = std.mem.Allocator;700const Allocator = std.mem.Allocator;
test/src/Cases.zig+1-1
...@@ -495,7 +495,7 @@ pub fn lowerToBuildSteps(...@@ -495,7 +495,7 @@ pub fn lowerToBuildSteps(
495495
496 if (case.case.? == .Error and options.skip_compile_errors) continue;496 if (case.case.? == .Error and options.skip_compile_errors) continue;
497497
498 if (options.skip_non_native and !@import("../tests.zig").isNative(&case.target, &b.graph.host.result))498 if (options.skip_non_native and !std.zig.target.isNative(&case.target.query, &case.target.result, &b.graph.host.result))
499 continue;499 continue;
500500
501 if (options.skip_spirv and case.target.query.cpu_arch != null and case.target.query.cpu_arch.?.isSpirV()) continue;501 if (options.skip_spirv and case.target.query.cpu_arch != null and case.target.query.cpu_arch.?.isSpirV()) continue;
test/src/ErrorTrace.zig+1-1
...@@ -385,7 +385,7 @@ pub fn addCases(self: *ErrorTrace) void {...@@ -385,7 +385,7 @@ pub fn addCases(self: *ErrorTrace) void {
385385
386 if (!self.options.test_extra_targets and params.extra_target) continue;386 if (!self.options.test_extra_targets and params.extra_target) continue;
387387
388 if (self.options.skip_non_native and !tests.isNative(&resolved_target, &b.graph.host.result)) continue;388 if (self.options.skip_non_native and !std.zig.target.isNative(&resolved_target.query, &resolved_target.result, &b.graph.host.result)) continue;
389389
390 if (self.options.skip_freebsd and target.os.tag == .freebsd) continue;390 if (self.options.skip_freebsd and target.os.tag == .freebsd) continue;
391 if (self.options.skip_netbsd and target.os.tag == .netbsd) continue;391 if (self.options.skip_netbsd and target.os.tag == .netbsd) continue;
test/src/StackTrace.zig+1-1
...@@ -995,7 +995,7 @@ pub fn addCases(self: *StackTrace) void {...@@ -995,7 +995,7 @@ pub fn addCases(self: *StackTrace) void {
995995
996 if (!self.options.test_extra_targets and params.extra_target) continue;996 if (!self.options.test_extra_targets and params.extra_target) continue;
997997
998 if (self.options.skip_non_native and !tests.isNative(&resolved_target, &b.graph.host.result)) continue;998 if (self.options.skip_non_native and !std.zig.target.isNative(&resolved_target.query, &resolved_target.result, &b.graph.host.result)) continue;
999999
1000 if (self.options.skip_freebsd and target.os.tag == .freebsd) continue;1000 if (self.options.skip_freebsd and target.os.tag == .freebsd) continue;
1001 if (self.options.skip_netbsd and target.os.tag == .netbsd) continue;1001 if (self.options.skip_netbsd and target.os.tag == .netbsd) continue;
test/tests.zig+4-160
...@@ -2323,162 +2323,6 @@ pub const debugger_matrix: []const RunnerTarget = &.{...@@ -2323,162 +2323,6 @@ pub const debugger_matrix: []const RunnerTarget = &.{
2323 },2323 },
2324};2324};
23252325
2326fn supportedCompatArch(host: *const std.Target, arch: std.Target.Cpu.Arch) bool {
2327 // aarch64-freebsd and aarch64-linux can technically run 32-bit ARM binaries, but that depends
2328 // on AArch32 support in the CPU. Since modern AArch64 CPUs have largely dropped this support,
2329 // avoid reporting compatibility for 32-bit here since we'd just build a bunch of test binaries
2330 // that never get run anyway. This added almost an hour's worth of useless work to aarch64-linux
2331 // CI, for example.
2332 //
2333 // riscv64-linux and riscv64-netbsd similarly support 32-bit binaries. However, this requires a
2334 // very recent kernel and for the kernel feature to be enabled. Additionally, contemporary
2335 // RISC-V hardware is just too slow to justify building the 32-bit binaries.
2336 return switch (host.os.tag) {
2337 .illumos => switch (host.cpu.arch) {
2338 .x86_64 => arch == .x86,
2339 else => false,
2340 },
2341 .linux => switch (host.cpu.arch) {
2342 .mips64 => arch == .mips,
2343 .mips64el => arch == .mipsel,
2344 .powerpc64 => arch == .powerpc,
2345 .sparc64 => arch == .sparc,
2346 .x86_64 => arch == .x86,
2347 else => false,
2348 },
2349 .netbsd => switch (host.cpu.arch) {
2350 .sparc64 => arch == .sparc,
2351 .x86_64 => arch == .x86,
2352 else => false,
2353 },
2354 .windows => switch (host.cpu.arch) {
2355 .x86_64 => arch == .x86,
2356 else => false,
2357 },
2358 else => false,
2359 };
2360}
2361
2362pub fn isNative(actual_target: *const std.Build.ResolvedTarget, host: *const std.Target) bool {
2363 if (actual_target.query.isNative()) return true;
2364 const actual = &actual_target.result;
2365
2366 if (actual.cpu.arch != host.cpu.arch and !supportedCompatArch(host, actual.cpu.arch))
2367 return false;
2368
2369 if (actual.os.tag != host.os.tag)
2370 return false;
2371
2372 // This check is really only necessary for the case where `host.cpu.arch.isAarch64()` and
2373 // `actual.cpu.arch.isArm()`. As they are wholly separate `std.Target` families with their own
2374 // feature bits, the logic below would produce complete nonsense.
2375 //
2376 // This does mean that we aren't actually checking feature compatibility between these two
2377 // families even though we should. That's not a problem currently, but in the future, we may
2378 // need to add a special code path just for this specific case...
2379 if (actual.cpu.arch.family() != host.cpu.arch.family())
2380 return true;
2381
2382 // Remove features that don't actually affect compatibility.
2383 const irrelevant: std.Target.Cpu.Feature.Set = switch (host.cpu.arch) {
2384 .x86_64 => std.Target.x86.featureSet(&.{
2385 .@"16bit_mode",
2386 .@"32bit_mode",
2387 .@"64bit",
2388 .false_deps_bls,
2389 .false_deps_compress,
2390 .false_deps_expand,
2391 .false_deps_getmant,
2392 .false_deps_lzcnt,
2393 .false_deps_mulc,
2394 .false_deps_mullq,
2395 .false_deps_perm,
2396 .false_deps_popcnt,
2397 .false_deps_range,
2398 .false_deps_tzcnt,
2399 .fast_11bytenop,
2400 .fast_15bytenop,
2401 .fast_7bytenop,
2402 .fast_bextr,
2403 .fast_dpwssd,
2404 .fast_gather,
2405 .fast_hops,
2406 .fast_imm16,
2407 .fast_lzcnt,
2408 .fast_movbe,
2409 .fast_scalar_fsqrt,
2410 .fast_scalar_shift_masks,
2411 .fast_shld_rotate,
2412 .fast_variable_crosslane_shuffle,
2413 .fast_variable_perlane_shuffle,
2414 .fast_vector_fsqrt,
2415 .fast_vector_shift_masks,
2416 .faster_shift_than_shuffle,
2417 .no_bypass_delay,
2418 .no_bypass_delay_blend,
2419 .no_bypass_delay_mov,
2420 .no_bypass_delay_shuffle,
2421 .prefer_128_bit,
2422 .prefer_256_bit,
2423 .prefer_legacy_setcc,
2424 .prefer_mask_registers,
2425 .prefer_movmsk_over_vtest,
2426 .prefer_ndd_mem,
2427 .prefer_no_gather,
2428 .prefer_no_scatter,
2429 .slow_3ops_lea,
2430 .slow_incdec,
2431 .slow_indirect_call,
2432 .slow_lea,
2433 .slow_pmaddwd,
2434 .slow_pmulld,
2435 .slow_pmullq,
2436 .slow_shld,
2437 .slow_two_mem_ops,
2438 .slow_unaligned_mem_16,
2439 .slow_unaligned_mem_32,
2440 }),
2441 .aarch64, .aarch64_be => std.Target.aarch64.featureSet(&.{
2442 .addr_lsl_slow_14,
2443 .align_cmp_csel_pairs,
2444 .alu_lsl_fast,
2445 .avoid_ldapur,
2446 .disable_fast_inc_vl,
2447 .exynos_cheap_as_move,
2448 .fast_ld1_single,
2449 .fixed_load_latency_4,
2450 .fuse_address,
2451 .fuse_addsub_2reg_const1,
2452 .fuse_adrp_add,
2453 .fuse_aes,
2454 .fuse_arith_logic,
2455 .fuse_crypto_eor,
2456 .fuse_csel,
2457 .fuse_cset,
2458 .fuse_fcsel,
2459 .fuse_literals,
2460 .has_limited_64bit_vector_mul_bandwidth,
2461 .predictable_select_expensive,
2462 .slow_misaligned_128store,
2463 .slow_paired_128,
2464 .slow_strqro_store,
2465 .use_experimental_zeroing_pseudos,
2466 .use_fixed_over_scalable_if_equal_cost,
2467 .use_postra_scheduler,
2468 .use_reciprocal_square_root,
2469 .use_wzr_to_vec_move,
2470 }),
2471 else => .empty,
2472 };
2473 var set = actual.cpu.features;
2474 set.removeFeatureSet(irrelevant);
2475
2476 if (!host.cpu.features.isSuperSetOf(set))
2477 return false;
2478
2479 return true;
2480}
2481
2482pub fn addStackTraceTests(b: *std.Build, options: StackTracesContext.Options) *Step {2326pub fn addStackTraceTests(b: *std.Build, options: StackTracesContext.Options) *Step {
2483 const step = b.step("test-stack-traces", "Run the stack trace tests");2327 const step = b.step("test-stack-traces", "Run the stack trace tests");
24842328
...@@ -2830,7 +2674,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -2830,7 +2674,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
28302674
2831 if (!options.test_extra_targets and test_target.extra_target) continue;2675 if (!options.test_extra_targets and test_target.extra_target) continue;
28322676
2833 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result))2677 if (options.skip_non_native and !std.zig.target.isNative(&resolved_target.query, &resolved_target.result, &b.graph.host.result))
2834 continue;2678 continue;
28352679
2836 const target = &resolved_target.result;2680 const target = &resolved_target.result;
...@@ -3156,7 +3000,7 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {...@@ -3156,7 +3000,7 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {
3156 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");3000 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
3157 const target = &resolved_target.result;3001 const target = &resolved_target.result;
31583002
3159 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result))3003 if (options.skip_non_native and !std.zig.target.isNative(&resolved_target.query, &resolved_target.result, &b.graph.host.result))
3160 continue;3004 continue;
31613005
3162 if (options.test_target_filters.len > 0) {3006 if (options.test_target_filters.len > 0) {
...@@ -3249,7 +3093,7 @@ pub fn addLinkTests(b: *std.Build, options: LinkTestOptions) *Step {...@@ -3249,7 +3093,7 @@ pub fn addLinkTests(b: *std.Build, options: LinkTestOptions) *Step {
3249 for (link_targets) |link_target| {3093 for (link_targets) |link_target| {
3250 const resolved_target = b.resolveTargetQuery(link_target.target);3094 const resolved_target = b.resolveTargetQuery(link_target.target);
32513095
3252 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result))3096 if (options.skip_non_native and !std.zig.target.isNative(&resolved_target.query, &resolved_target.result, &b.graph.host.result))
3253 continue;3097 continue;
32543098
3255 const target = &resolved_target.result;3099 const target = &resolved_target.result;
...@@ -3399,7 +3243,7 @@ pub fn addRunnerTests(...@@ -3399,7 +3243,7 @@ pub fn addRunnerTests(
3399 for (matrix) |test_target| {3243 for (matrix) |test_target| {
3400 const resolved_target = b.resolveTargetQuery(test_target.target);3244 const resolved_target = b.resolveTargetQuery(test_target.target);
34013245
3402 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result))3246 if (options.skip_non_native and !std.zig.target.isNative(&resolved_target.query, &resolved_target.result, &b.graph.host.result))
3403 continue;3247 continue;
34043248
3405 const target = &resolved_target.result;3249 const target = &resolved_target.result;