╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ target.zig ───────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
572 .x86, 573 .x86_64, 574 => true, 575 else => false, 576 }; 577 } 578 579 pub fn defaultUnwindTables(target: *const std.Target, libunwind: bool, libtsan: bool) std.lang.UnwindTables { 580 if (target.os.tag == .windows) { 581 // The old 32-bit x86 variant of SEH doesn't use tables. 582 return if (target.cpu.arch != .x86) .async else .none; 583 } 584 if (target.os.tag.isDarwin()) return .async; 585 if (libunwind) return .async; 586 if (libtsan) return .async; 587 if (std.debug.Dwarf.supportsUnwinding(target)) return .async; 588 return .none; 589 } 590 591 pub fn defaultAddressSpace( 592 target: *const std.Target, 593 context: enum { 594 /// Query the default address space for global constant values. 595 global_constant, 596 /// Query the default address space for global mutable values. 597 global_mutable, 598 /// Query the default address space for function-local values. 599 local, 600 /// Query the default address space for functions themselves. 601 function, 602 }, 603 ) AddressSpace { 604 // The default address space for functions on AVR is .flash to produce 605 // correct fixups into progmem. 606 if (context == .function and target.cpu.arch == .avr) return .flash; 607 if (context == .global_mutable and target.os.tag == .vulkan) return .private; 608 return .generic; 609 } 610 611 /// Returns true if pointers in `from` can be converted to a pointer in `to`. 612 pub fn addrSpaceCastIsValid( 613 target: *const std.Target, 614 from: AddressSpace, 615 to: AddressSpace, 616 ) bool { 617 switch (target.cpu.arch) { 618 .x86_64, .x86 => return target.supportsAddressSpace(from, null) and target.supportsAddressSpace(to, null), 619 .nvptx64, .nvptx, .amdgcn => { 620 const to_generic = target.supportsAddressSpace(from, null) and to == .generic; 621 const from_generic = target.supportsAddressSpace(to, null) and from == .generic; 622 return to_generic or from_generic; 623 }, 624 else => return from == .generic and to == .generic, 625 } 626 } 627 628 /// Returns whether pointer operations (arithmetic, indexing, etc.) should be blocked 629 /// for the given address space on the target architecture. 630 /// 631 /// Under SPIR-V with Vulkan 632 /// (a) all physical pointers (.physical_storage_buffer, .global) always support pointer operations, 633 /// (b) by default logical pointers (.constant, .input, .output, etc.) never support operations 634 /// (c) some logical pointers (.storage_buffer, .shared) do support operations when 635 /// the VariablePointers capability is enabled (which enables OpPtrAccessChain). 636 pub fn shouldBlockPointerOps(target: *const std.Target, as: AddressSpace) bool { 637 if (target.os.tag != .vulkan and target.os.tag != .opengl) return false; 638 639 return switch (as) { 640 // TODO: Vulkan doesn't support pointers in the generic address space, we 641 // should remove this case but this requires a change in defaultAddressSpace(). 642 .generic => true, 643 // For now, all global pointers are represented using StorageBuffer or CrossWorkgroup, 644 // so these are real pointers. 645 // Physical pointers always support operations 646 .global, .physical_storage_buffer => false, 647 // Logical pointers that support operations with VariablePointers capability 648 .shared => !target.cpu.features.isEnabled(@backingInt(std.Target.spirv.Feature.variable_pointers)), 649 .storage_buffer => !target.cpu.features.isEnabled(@backingInt(std.Target.spirv.Feature.variable_pointers)), 650 // Logical pointers that never support operations 651 .constant, 652 .local, 653 .private, 654 .input, 655 .output, 656 .uniform, 657 .push_constant, 658 => true, 659 else => unreachable, 660 }; 661 } 662 663 pub fn isDynamicAMDGCNFeature(target: *const std.Target, feature: std.Target.Cpu.Feature) bool { 664 if (target.cpu.arch != .amdgcn) return false; 665 666 const sramecc_only = &[_]*const std.Target.Cpu.Model{ 667 &std.Target.amdgcn.cpu.gfx1010, 668 &std.Target.amdgcn.cpu.gfx1011, 669 &std.Target.amdgcn.cpu.gfx1012, 670 &std.Target.amdgcn.cpu.gfx1013, 671 }; 672 const xnack_or_sramecc = &[_]*const std.Target.Cpu.Model{ 673 &std.Target.amdgcn.cpu.gfx1030, 674 &std.Target.amdgcn.cpu.gfx1031, 675 &std.Target.amdgcn.cpu.gfx1032, 676 &std.Target.amdgcn.cpu.gfx1033, 677 &std.Target.amdgcn.cpu.gfx1034, 678 &std.Target.amdgcn.cpu.gfx1035, 679 &std.Target.amdgcn.cpu.gfx1036, 680 &std.Target.amdgcn.cpu.gfx1100, 681 &std.Target.amdgcn.cpu.gfx1101, 682 &std.Target.amdgcn.cpu.gfx1102, 683 &std.Target.amdgcn.cpu.gfx1103, 684 &std.Target.amdgcn.cpu.gfx1150, 685 &std.Target.amdgcn.cpu.gfx1151, 686 &std.Target.amdgcn.cpu.gfx1152, 687 &std.Target.amdgcn.cpu.gfx1153, 688 &std.Target.amdgcn.cpu.gfx1200, 689 &std.Target.amdgcn.cpu.gfx1201, 690 }; 691 const feature_tag: std.Target.amdgcn.Feature = @fromBackingInt(@intCast(feature.index)); 692 693 if (feature_tag == .sramecc) { 694 if (std.mem.findScalar( 695 *const std.Target.Cpu.Model, 696 sramecc_only ++ xnack_or_sramecc, 697 target.cpu.model, 698 )) |_| return true; 699 } 700 if (feature_tag == .xnack) { 701 if (std.mem.findScalar( 702 *const std.Target.Cpu.Model, 703 xnack_or_sramecc, 704 target.cpu.model, 705 )) |_| return true; 706 } 707 708 return false; 709 } 710 711 pub fn llvmMachineAbi(target: *const std.Target) ?[:0]const u8 { 712 return switch (target.cpu.arch) { 713 .arm, .armeb, .thumb, .thumbeb => "aapcs", 714 .loongarch64 => switch (target.abi) { 715 .gnusf, .muslsf => "lp64s", 716 .gnuf32, .muslf32 => "lp64f", 717 else => "lp64d", 718 }, 719 .loongarch32 => switch (target.abi) { 720 .gnusf, .muslsf => "ilp32s", 721 .gnuf32, .muslf32 => "ilp32f", 722 else => "ilp32d", 723 }, 724 .mips, .mipsel => "o32", 725 .mips64, .mips64el => switch (target.abi) { 726 .gnuabin32, .muslabin32, .abin32 => "n32", 727 else => "n64", 728 }, 729 .powerpc64 => if (target.os.tag == .ps3) "elfv1" else "elfv2", 730 .powerpc64le => "elfv2", 731 .riscv64, .riscv64be => if (target.cpu.has(.riscv, .e)) 732 "lp64e" 733 else if (target.cpu.has(.riscv, .d)) 734 "lp64d" 735 else if (target.cpu.has(.riscv, .f)) 736 "lp64f" 737 else 738 "lp64", 739 .riscv32, .riscv32be => if (target.cpu.has(.riscv, .e)) 740 "ilp32e" 741 else if (target.cpu.has(.riscv, .d)) 742 "ilp32d" 743 else if (target.cpu.has(.riscv, .f)) 744 "ilp32f" 745 else 746 "ilp32", 747 else => null, 748 }; 749 } 750 751 /// This function returns 1 if function alignment is not observable or settable. Note that this 752 /// value will not necessarily match the backend's default function alignment (e.g. for LLVM). 753 pub fn defaultFunctionAlignment(target: *const std.Target) Alignment { 754 // Overrides of the minimum for performance. 755 return switch (target.cpu.arch) { 756 .csky, 757 .thumb, 758 .thumbeb, 759 .xcore, 760 => .@"4", 761 .aarch64, 762 .aarch64_be, 763 .hexagon, 764 .powerpc, 765 .powerpcle, 766 .powerpc64, 767 .powerpc64le, 768 .s390x, 769 .x86, 770 .x86_64, 771 => .@"16", 772 .loongarch32, 773 .loongarch64, 774 => .@"32", 775 else => minFunctionAlignment(target), 776 }; 777 } 778 779 /// This function returns 1 if function alignment is not observable or settable. 780 pub fn minFunctionAlignment(target: *const std.Target) Alignment { 781 return switch (target.cpu.arch) { 782 .riscv32, 783 .riscv32be, 784 .riscv64, 785 .riscv64be, 786 => if (target.cpu.hasAny(.riscv, &.{ .c, .zca })) .@"2" else .@"4", 787 .thumb, 788 .thumbeb, 789 .csky, 790 .m68k, 791 .msp430, 792 .sh, 793 .sheb, 794 .s390x, 795 .xcore, 796 => .@"2", 797 .aarch64, 798 .aarch64_be, 799 .alpha, 800 .arc, 801 .arceb, 802 .arm, 803 .armeb, 804 .hexagon, 805 .hppa, 806 .hppa64, 807 .lanai, 808 .loongarch32, 809 .loongarch64, 810 .microblaze, 811 .microblazeel, 812 .mips, 813 .mipsel, 814 .powerpc, 815 .powerpcle, 816 .powerpc64, 817 .powerpc64le, 818 .sparc, 819 .sparc64, 820 .xtensa, 821 .xtensaeb, 822 => .@"4", 823 .bpfeb, 824 .bpfel, 825 .kvx, 826 .mips64, 827 .mips64el, 828 => .@"8", 829 .ve, 830 => .@"16", 831 else => .@"1", 832 }; 833 } 834 835 pub fn supportsFunctionAlignment(target: *const std.Target) bool { 836 return switch (target.cpu.arch) { 837 .nvptx, 838 .nvptx64, 839 .spirv32, 840 .spirv64, 841 .wasm32, 842 .wasm64, 843 => false, 844 else => true, 845 }; 846 } 847 848 pub fn functionPointerMask(target: *const std.Target) ?u64 { 849 // 32-bit Arm uses the LSB to mean that the target function contains Thumb code. 850 // MIPS uses the LSB to mean that the target function contains MIPS16/microMIPS code. 851 return if (target.cpu.arch.isArm() or target.cpu.arch.isMIPS32()) 852 ~@as(u32, 1) 853 else if (target.cpu.arch.isMIPS64()) 854 ~@as(u64, 1) 855 else 856 null; 857 } 858 859 pub fn supportsTailCall(target: *const std.Target, backend: std.lang.CompilerBackend) bool { 860 switch (backend) { 861 .stage2_llvm => { 862 dev.check(.llvm_backend); 863 return @import("codegen/llvm.zig").supportsTailCall(target); 864 }, 865 .stage2_c => return true, 866 else => return false, 867 } 868 } 869 870 pub fn supportsThreads(target: *const std.Target, backend: std.lang.CompilerBackend) bool { 871 _ = target; 872 return switch (backend) { 873 .stage2_aarch64 => false, 874 .stage2_loongarch => false, 875 else => true, 876 }; 877 } 878 879 pub fn libcFloatPrefix(float_bits: u16) []const u8 { 880 return switch (float_bits) { 881 16, 80 => "__", 882 32, 64, 128 => "", 883 else => unreachable, 884 }; 885 } 886 887 pub fn libcFloatSuffix(float_bits: u16) []const u8 { 888 return switch (float_bits) { 889 16 => "h", // Non-standard 890 32 => "f", 891 64 => "", 892 80 => "x", // Non-standard 893 128 => "f128", 894 else => unreachable, 895 }; 896 } 897 898 pub fn compilerRtFloatAbbrev(target: *const std.Target, float_bits: u16) []const u8 { 899 return switch (float_bits) { 900 16 => "h", 901 32 => "s", 902 64 => "d", 903 80 => "x", 904 128 => if (target.cpu.arch.isPowerPC()) "k" else "t", 905 else => unreachable, 906 }; 907 } 908 909 pub fn compilerRtIntAbbrev(bits: u16) []const u8 { 910 return switch (bits) { 911 16 => "h", 912 32 => "s", 913 64 => "d", 914 128 => "t", 915 else => unreachable, 916 }; 917 } 918 919 pub fn fnCallConvAllowsZigTypes(cc: std.lang.CallingConvention) bool { 920 return switch (cc) { 921 .auto, .async, .@"inline" => true, 922 // For now we want to authorize PTX kernel to use zig objects, even if 923 // we end up exposing the ABI. The goal is to experiment with more 924 // integrated CPU/GPU code. 925 .nvptx_kernel => true, 926 else => false, 927 }; 928 } 929 930 pub fn zigBackend(target: *const std.Target, use_llvm: bool) std.lang.CompilerBackend { 931 if (use_llvm) return .stage2_llvm; 932 if (target.ofmt == .c) return .stage2_c; 933 return switch (target.cpu.arch) { 934 .aarch64, .aarch64_be => .stage2_aarch64, 935 .arm, .armeb, .thumb, .thumbeb => .stage2_arm, 936 .loongarch32, .loongarch64 => .stage2_loongarch, 937 .powerpc, .powerpcle, .powerpc64, .powerpc64le => .stage2_powerpc, 938 .riscv64 => .stage2_riscv64, 939 .sparc64 => .stage2_sparc64, 940 .spirv32, .spirv64 => .stage2_spirv, 941 .wasm32, .wasm64 => .stage2_wasm, 942 .x86 => .stage2_x86, 943 .x86_64 => .stage2_x86_64, 944 .spork8 => .zsf_spork8, 945 else => .other, 946 }; 947 } 948 949 pub inline fn backendSupportsFeature(backend: std.lang.CompilerBackend, comptime feature: Feature) bool { 950 return switch (feature) { 951 .panic_fn => switch (backend) { 952 .stage2_aarch64, 953 .stage2_c, 954 .stage2_llvm, 955 .stage2_x86_64, 956 .stage2_riscv64, 957 .stage2_wasm, 958 => true, 959 else => false, 960 }, 961 .error_return_trace => switch (backend) { 962 .stage2_llvm, .stage2_x86_64 => true, 963 else => false, 964 }, 965 .is_named_enum_value => switch (backend) { 966 .stage2_llvm, .stage2_x86_64, .stage2_wasm => true, 967 else => false, 968 }, 969 .error_set_has_value => switch (backend) { 970 .stage2_llvm, .stage2_wasm, .stage2_x86_64 => true, 971 else => false, 972 }, 973 .field_reordering => switch (backend) { 974 .stage2_aarch64, .stage2_c, .stage2_llvm, .stage2_loongarch, .stage2_x86_64, .stage2_wasm => true, 975 else => false, 976 }, 977 .separate_thread => switch (backend) { 978 // Supports a separate thread but does not support N separate 979 // threads because they would all just be locking the same mutex to 980 // protect Builder. 981 .stage2_llvm => false, 982 // Please do not make any more exceptions. Backends must support 983 // being run in a separate thread from now on. 984 else => true, 985 }, 986 }; 987 } 988