/* * Copyright (c) 2016 Andrew Kelley * * This file is part of zig, which is MIT licensed. * See http://opensource.org/licenses/MIT */ #include "buffer.hpp" #include "error.hpp" #include "target.hpp" #include "util.hpp" #include "os.hpp" #include "compiler.hpp" #include "glibc.hpp" #include static const SubArchList subarch_list_list[] = { SubArchListNone, SubArchListArm32, SubArchListArm64, SubArchListKalimba, SubArchListMips, }; static const ZigLLVM_SubArchType subarch_list_arm32[] = { ZigLLVM_ARMSubArch_v8_5a, ZigLLVM_ARMSubArch_v8_4a, ZigLLVM_ARMSubArch_v8_3a, ZigLLVM_ARMSubArch_v8_2a, ZigLLVM_ARMSubArch_v8_1a, ZigLLVM_ARMSubArch_v8, ZigLLVM_ARMSubArch_v8r, ZigLLVM_ARMSubArch_v8m_baseline, ZigLLVM_ARMSubArch_v8m_mainline, ZigLLVM_ARMSubArch_v7, ZigLLVM_ARMSubArch_v7em, ZigLLVM_ARMSubArch_v7m, ZigLLVM_ARMSubArch_v7s, ZigLLVM_ARMSubArch_v7k, ZigLLVM_ARMSubArch_v7ve, ZigLLVM_ARMSubArch_v6, ZigLLVM_ARMSubArch_v6m, ZigLLVM_ARMSubArch_v6k, ZigLLVM_ARMSubArch_v6t2, ZigLLVM_ARMSubArch_v5, ZigLLVM_ARMSubArch_v5te, ZigLLVM_ARMSubArch_v4t, }; static const ZigLLVM_SubArchType subarch_list_arm64[] = { ZigLLVM_ARMSubArch_v8_5a, ZigLLVM_ARMSubArch_v8_4a, ZigLLVM_ARMSubArch_v8_3a, ZigLLVM_ARMSubArch_v8_2a, ZigLLVM_ARMSubArch_v8_1a, ZigLLVM_ARMSubArch_v8, ZigLLVM_ARMSubArch_v8r, ZigLLVM_ARMSubArch_v8m_baseline, ZigLLVM_ARMSubArch_v8m_mainline, }; static const ZigLLVM_SubArchType subarch_list_kalimba[] = { ZigLLVM_KalimbaSubArch_v5, ZigLLVM_KalimbaSubArch_v4, ZigLLVM_KalimbaSubArch_v3, }; static const ZigLLVM_SubArchType subarch_list_mips[] = { ZigLLVM_MipsSubArch_r6, }; static const ZigLLVM_ArchType arch_list[] = { ZigLLVM_arm, // ARM (little endian): arm, armv.*, xscale ZigLLVM_armeb, // ARM (big endian): armeb ZigLLVM_aarch64, // AArch64 (little endian): aarch64 ZigLLVM_aarch64_be, // AArch64 (big endian): aarch64_be ZigLLVM_arc, // ARC: Synopsys ARC ZigLLVM_avr, // AVR: Atmel AVR microcontroller ZigLLVM_bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) ZigLLVM_bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) ZigLLVM_hexagon, // Hexagon: hexagon ZigLLVM_mips, // MIPS: mips, mipsallegrex, mipsr6 ZigLLVM_mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el ZigLLVM_mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6 ZigLLVM_mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el ZigLLVM_msp430, // MSP430: msp430 ZigLLVM_ppc, // PPC: powerpc ZigLLVM_ppc64, // PPC64: powerpc64, ppu ZigLLVM_ppc64le, // PPC64LE: powerpc64le ZigLLVM_r600, // R600: AMD GPUs HD2XXX - HD6XXX ZigLLVM_amdgcn, // AMDGCN: AMD GCN GPUs ZigLLVM_riscv32, // RISC-V (32-bit): riscv32 ZigLLVM_riscv64, // RISC-V (64-bit): riscv64 ZigLLVM_sparc, // Sparc: sparc ZigLLVM_sparcv9, // Sparcv9: Sparcv9 ZigLLVM_sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant ZigLLVM_systemz, // SystemZ: s390x ZigLLVM_tce, // TCE (http://tce.cs.tut.fi/): tce ZigLLVM_tcele, // TCE little endian (http://tce.cs.tut.fi/): tcele ZigLLVM_thumb, // Thumb (little endian): thumb, thumbv.* ZigLLVM_thumbeb, // Thumb (big endian): thumbeb ZigLLVM_x86, // X86: i[3-9]86 ZigLLVM_x86_64, // X86-64: amd64, x86_64 ZigLLVM_xcore, // XCore: xcore ZigLLVM_nvptx, // NVPTX: 32-bit ZigLLVM_nvptx64, // NVPTX: 64-bit ZigLLVM_le32, // le32: generic little-endian 32-bit CPU (PNaCl) ZigLLVM_le64, // le64: generic little-endian 64-bit CPU (PNaCl) ZigLLVM_amdil, // AMDIL ZigLLVM_amdil64, // AMDIL with 64-bit pointers ZigLLVM_hsail, // AMD HSAIL ZigLLVM_hsail64, // AMD HSAIL with 64-bit pointers ZigLLVM_spir, // SPIR: standard portable IR for OpenCL 32-bit version ZigLLVM_spir64, // SPIR: standard portable IR for OpenCL 64-bit version ZigLLVM_kalimba, // Kalimba: generic kalimba ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors ZigLLVM_lanai, // Lanai: Lanai 32-bit ZigLLVM_wasm32, // WebAssembly with 32-bit pointers ZigLLVM_wasm64, // WebAssembly with 64-bit pointers ZigLLVM_renderscript32, // 32-bit RenderScript ZigLLVM_renderscript64, // 64-bit RenderScript }; static const ZigLLVM_VendorType vendor_list[] = { ZigLLVM_Apple, ZigLLVM_PC, ZigLLVM_SCEI, ZigLLVM_BGP, ZigLLVM_BGQ, ZigLLVM_Freescale, ZigLLVM_IBM, ZigLLVM_ImaginationTechnologies, ZigLLVM_MipsTechnologies, ZigLLVM_NVIDIA, ZigLLVM_CSR, ZigLLVM_Myriad, ZigLLVM_AMD, ZigLLVM_Mesa, ZigLLVM_SUSE, }; static const Os os_list[] = { OsFreestanding, OsAnanas, OsCloudABI, OsDragonFly, OsFreeBSD, OsFuchsia, OsIOS, OsKFreeBSD, OsLinux, OsLv2, // PS3 OsMacOSX, OsNetBSD, OsOpenBSD, OsSolaris, OsWindows, OsHaiku, OsMinix, OsRTEMS, OsNaCl, // Native Client OsCNK, // BG/P Compute-Node Kernel OsAIX, OsCUDA, // NVIDIA CUDA OsNVCL, // NVIDIA OpenCL OsAMDHSA, // AMD HSA Runtime OsPS4, OsELFIAMCU, OsTvOS, // Apple tvOS OsWatchOS, // Apple watchOS OsMesa3D, OsContiki, OsAMDPAL, OsHermitCore, OsHurd, OsWASI, OsZen, OsUefi, }; // Coordinate with zig_llvm.h static const ZigLLVM_EnvironmentType abi_list[] = { ZigLLVM_UnknownEnvironment, ZigLLVM_GNU, ZigLLVM_GNUABIN32, ZigLLVM_GNUABI64, ZigLLVM_GNUEABI, ZigLLVM_GNUEABIHF, ZigLLVM_GNUX32, ZigLLVM_CODE16, ZigLLVM_EABI, ZigLLVM_EABIHF, ZigLLVM_Android, ZigLLVM_Musl, ZigLLVM_MuslEABI, ZigLLVM_MuslEABIHF, ZigLLVM_MSVC, ZigLLVM_Itanium, ZigLLVM_Cygnus, ZigLLVM_CoreCLR, ZigLLVM_Simulator, }; static const ZigLLVM_ObjectFormatType oformat_list[] = { ZigLLVM_UnknownObjectFormat, ZigLLVM_COFF, ZigLLVM_ELF, ZigLLVM_MachO, ZigLLVM_Wasm, }; size_t target_oformat_count(void) { return array_length(oformat_list); } ZigLLVM_ObjectFormatType target_oformat_enum(size_t index) { assert(index < array_length(oformat_list)); return oformat_list[index]; } const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat) { switch (oformat) { case ZigLLVM_UnknownObjectFormat: return "unknown"; case ZigLLVM_COFF: return "coff"; case ZigLLVM_ELF: return "elf"; case ZigLLVM_MachO: return "macho"; case ZigLLVM_Wasm: return "wasm"; } zig_unreachable(); } size_t target_arch_count(void) { return array_length(arch_list); } ZigLLVM_ArchType target_arch_enum(size_t index) { assert(index < array_length(arch_list)); return arch_list[index]; } size_t target_vendor_count(void) { return array_length(vendor_list); } ZigLLVM_VendorType target_vendor_enum(size_t index) { assert(index < array_length(vendor_list)); return vendor_list[index]; } size_t target_os_count(void) { return array_length(os_list); } Os target_os_enum(size_t index) { assert(index < array_length(os_list)); return os_list[index]; } ZigLLVM_OSType get_llvm_os_type(Os os_type) { switch (os_type) { case OsFreestanding: case OsZen: return ZigLLVM_UnknownOS; case OsAnanas: return ZigLLVM_Ananas; case OsCloudABI: return ZigLLVM_CloudABI; case OsDragonFly: return ZigLLVM_DragonFly; case OsFreeBSD: return ZigLLVM_FreeBSD; case OsFuchsia: return ZigLLVM_Fuchsia; case OsIOS: return ZigLLVM_IOS; case OsKFreeBSD: return ZigLLVM_KFreeBSD; case OsLinux: return ZigLLVM_Linux; case OsLv2: return ZigLLVM_Lv2; case OsMacOSX: return ZigLLVM_MacOSX; case OsNetBSD: return ZigLLVM_NetBSD; case OsOpenBSD: return ZigLLVM_OpenBSD; case OsSolaris: return ZigLLVM_Solaris; case OsWindows: case OsUefi: return ZigLLVM_Win32; case OsHaiku: return ZigLLVM_Haiku; case OsMinix: return ZigLLVM_Minix; case OsRTEMS: return ZigLLVM_RTEMS; case OsNaCl: return ZigLLVM_NaCl; case OsCNK: return ZigLLVM_CNK; case OsAIX: return ZigLLVM_AIX; case OsCUDA: return ZigLLVM_CUDA; case OsNVCL: return ZigLLVM_NVCL; case OsAMDHSA: return ZigLLVM_AMDHSA; case OsPS4: return ZigLLVM_PS4; case OsELFIAMCU: return ZigLLVM_ELFIAMCU; case OsTvOS: return ZigLLVM_TvOS; case OsWatchOS: return ZigLLVM_WatchOS; case OsMesa3D: return ZigLLVM_Mesa3D; case OsContiki: return ZigLLVM_Contiki; case OsAMDPAL: return ZigLLVM_AMDPAL; case OsHermitCore: return ZigLLVM_HermitCore; case OsHurd: return ZigLLVM_Hurd; case OsWASI: return ZigLLVM_WASI; } zig_unreachable(); } static Os get_zig_os_type(ZigLLVM_OSType os_type) { switch (os_type) { case ZigLLVM_UnknownOS: return OsFreestanding; case ZigLLVM_Ananas: return OsAnanas; case ZigLLVM_CloudABI: return OsCloudABI; case ZigLLVM_DragonFly: return OsDragonFly; case ZigLLVM_FreeBSD: return OsFreeBSD; case ZigLLVM_Fuchsia: return OsFuchsia; case ZigLLVM_IOS: return OsIOS; case ZigLLVM_KFreeBSD: return OsKFreeBSD; case ZigLLVM_Linux: return OsLinux; case ZigLLVM_Lv2: return OsLv2; case ZigLLVM_Darwin: case ZigLLVM_MacOSX: return OsMacOSX; case ZigLLVM_NetBSD: return OsNetBSD; case ZigLLVM_OpenBSD: return OsOpenBSD; case ZigLLVM_Solaris: return OsSolaris; case ZigLLVM_Win32: return OsWindows; case ZigLLVM_Haiku: return OsHaiku; case ZigLLVM_Minix: return OsMinix; case ZigLLVM_RTEMS: return OsRTEMS; case ZigLLVM_NaCl: return OsNaCl; case ZigLLVM_CNK: return OsCNK; case ZigLLVM_AIX: return OsAIX; case ZigLLVM_CUDA: return OsCUDA; case ZigLLVM_NVCL: return OsNVCL; case ZigLLVM_AMDHSA: return OsAMDHSA; case ZigLLVM_PS4: return OsPS4; case ZigLLVM_ELFIAMCU: return OsELFIAMCU; case ZigLLVM_TvOS: return OsTvOS; case ZigLLVM_WatchOS: return OsWatchOS; case ZigLLVM_Mesa3D: return OsMesa3D; case ZigLLVM_Contiki: return OsContiki; case ZigLLVM_AMDPAL: return OsAMDPAL; case ZigLLVM_HermitCore: return OsHermitCore; case ZigLLVM_Hurd: return OsHurd; case ZigLLVM_WASI: return OsWASI; } zig_unreachable(); } const char *target_os_name(Os os_type) { switch (os_type) { case OsFreestanding: return "freestanding"; case OsZen: return "zen"; case OsUefi: return "uefi"; case OsAnanas: case OsCloudABI: case OsDragonFly: case OsFreeBSD: case OsFuchsia: case OsIOS: case OsKFreeBSD: case OsLinux: case OsLv2: // PS3 case OsMacOSX: case OsNetBSD: case OsOpenBSD: case OsSolaris: case OsWindows: case OsHaiku: case OsMinix: case OsRTEMS: case OsNaCl: // Native Client case OsCNK: // BG/P Compute-Node Kernel case OsAIX: case OsCUDA: // NVIDIA CUDA case OsNVCL: // NVIDIA OpenCL case OsAMDHSA: // AMD HSA Runtime case OsPS4: case OsELFIAMCU: case OsTvOS: // Apple tvOS case OsWatchOS: // Apple watchOS case OsMesa3D: case OsContiki: case OsAMDPAL: case OsHermitCore: case OsHurd: case OsWASI: return ZigLLVMGetOSTypeName(get_llvm_os_type(os_type)); } zig_unreachable(); } size_t target_abi_count(void) { return array_length(abi_list); } ZigLLVM_EnvironmentType target_abi_enum(size_t index) { assert(index < array_length(abi_list)); return abi_list[index]; } const char *target_abi_name(ZigLLVM_EnvironmentType abi) { if (abi == ZigLLVM_UnknownEnvironment) return "none"; return ZigLLVMGetEnvironmentTypeName(abi); } Error target_parse_glibc_version(ZigGLibCVersion *glibc_ver, const char *text) { glibc_ver->major = 2; glibc_ver->minor = 0; glibc_ver->patch = 0; SplitIterator it = memSplit(str(text), str("GLIBC_.")); { Optional> opt_component = SplitIterator_next(&it); if (!opt_component.is_some) return ErrorUnknownABI; glibc_ver->major = strtoul(buf_ptr(buf_create_from_slice(opt_component.value)), nullptr, 10); } { Optional> opt_component = SplitIterator_next(&it); if (!opt_component.is_some) return ErrorNone; glibc_ver->minor = strtoul(buf_ptr(buf_create_from_slice(opt_component.value)), nullptr, 10); } { Optional> opt_component = SplitIterator_next(&it); if (!opt_component.is_some) return ErrorNone; glibc_ver->patch = strtoul(buf_ptr(buf_create_from_slice(opt_component.value)), nullptr, 10); } return ErrorNone; } void get_native_target(ZigTarget *target) { // first zero initialize *target = {}; ZigLLVM_OSType os_type; ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os ZigLLVMGetNativeTarget( &target->arch, &target->sub_arch, &target->vendor, &os_type, &target->abi, &oformat); target->os = get_zig_os_type(os_type); target->is_native = true; if (target->abi == ZigLLVM_UnknownEnvironment) { target->abi = target_default_abi(target->arch, target->os); } if (target_is_glibc(target)) { target->glibc_version = allocate(1); *target->glibc_version = {2, 17, 0}; #ifdef ZIG_OS_LINUX Error err; if ((err = glibc_detect_native_version(target->glibc_version))) { // Fall back to the default version. } #endif } } Error target_parse_archsub(ZigLLVM_ArchType *out_arch, ZigLLVM_SubArchType *out_sub, const char *archsub_ptr, size_t archsub_len) { *out_arch = ZigLLVM_UnknownArch; *out_sub = ZigLLVM_NoSubArch; for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) { ZigLLVM_ArchType arch = arch_list[arch_i]; SubArchList sub_arch_list = target_subarch_list(arch); size_t subarch_count = target_subarch_count(sub_arch_list); if (mem_eql_str(archsub_ptr, archsub_len, target_arch_name(arch))) { *out_arch = arch; if (subarch_count == 0) { return ErrorNone; } } for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) { ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); char arch_name[64]; int n = sprintf(arch_name, "%s%s", target_arch_name(arch), target_subarch_name(sub)); if (mem_eql_mem(arch_name, n, archsub_ptr, archsub_len)) { *out_arch = arch; *out_sub = sub; return ErrorNone; } } } return ErrorUnknownArchitecture; } SubArchList target_subarch_list(ZigLLVM_ArchType arch) { switch (arch) { case ZigLLVM_UnknownArch: zig_unreachable(); case ZigLLVM_arm: case ZigLLVM_armeb: case ZigLLVM_thumb: case ZigLLVM_thumbeb: return SubArchListArm32; case ZigLLVM_aarch64: case ZigLLVM_aarch64_be: return SubArchListArm64; case ZigLLVM_kalimba: return SubArchListKalimba; case ZigLLVM_arc: case ZigLLVM_avr: case ZigLLVM_bpfel: case ZigLLVM_bpfeb: case ZigLLVM_hexagon: case ZigLLVM_mips: case ZigLLVM_mipsel: case ZigLLVM_mips64: case ZigLLVM_mips64el: case ZigLLVM_msp430: case ZigLLVM_ppc: case ZigLLVM_ppc64: case ZigLLVM_ppc64le: case ZigLLVM_r600: case ZigLLVM_amdgcn: case ZigLLVM_riscv32: case ZigLLVM_riscv64: case ZigLLVM_sparc: case ZigLLVM_sparcv9: case ZigLLVM_sparcel: case ZigLLVM_systemz: case ZigLLVM_tce: case ZigLLVM_tcele: case ZigLLVM_x86: case ZigLLVM_x86_64: case ZigLLVM_xcore: case ZigLLVM_nvptx: case ZigLLVM_nvptx64: case ZigLLVM_le32: case ZigLLVM_le64: case ZigLLVM_amdil: case ZigLLVM_amdil64: case ZigLLVM_hsail: case ZigLLVM_hsail64: case ZigLLVM_spir: case ZigLLVM_spir64: case ZigLLVM_shave: case ZigLLVM_lanai: case ZigLLVM_wasm32: case ZigLLVM_wasm64: case ZigLLVM_renderscript32: case ZigLLVM_renderscript64: return SubArchListNone; } zig_unreachable(); } size_t target_subarch_count(SubArchList sub_arch_list) { switch (sub_arch_list) { case SubArchListNone: return 0; case SubArchListArm32: return array_length(subarch_list_arm32); case SubArchListArm64: return array_length(subarch_list_arm64); case SubArchListKalimba: return array_length(subarch_list_kalimba); case SubArchListMips: return array_length(subarch_list_mips); } zig_unreachable(); } ZigLLVM_SubArchType target_subarch_enum(SubArchList sub_arch_list, size_t i) { switch (sub_arch_list) { case SubArchListNone: zig_unreachable(); case SubArchListArm32: assert(i < array_length(subarch_list_arm32)); return subarch_list_arm32[i]; case SubArchListArm64: assert(i < array_length(subarch_list_arm64)); return subarch_list_arm64[i]; case SubArchListKalimba: assert(i < array_length(subarch_list_kalimba)); return subarch_list_kalimba[i]; case SubArchListMips: assert(i < array_length(subarch_list_mips)); return subarch_list_mips[i]; } zig_unreachable(); } const char *target_subarch_name(ZigLLVM_SubArchType subarch) { switch (subarch) { case ZigLLVM_NoSubArch: return ""; case ZigLLVM_ARMSubArch_v8_5a: return "v8_5a"; case ZigLLVM_ARMSubArch_v8_4a: return "v8_4a"; case ZigLLVM_ARMSubArch_v8_3a: return "v8_3a"; case ZigLLVM_ARMSubArch_v8_2a: return "v8_2a"; case ZigLLVM_ARMSubArch_v8_1a: return "v8_1a"; case ZigLLVM_ARMSubArch_v8: return "v8"; case ZigLLVM_ARMSubArch_v8r: return "v8r"; case ZigLLVM_ARMSubArch_v8m_baseline: return "v8m_baseline"; case ZigLLVM_ARMSubArch_v8m_mainline: return "v8m_mainline"; case ZigLLVM_ARMSubArch_v7: return "v7"; case ZigLLVM_ARMSubArch_v7em: return "v7em"; case ZigLLVM_ARMSubArch_v7m: return "v7m"; case ZigLLVM_ARMSubArch_v7s: return "v7s"; case ZigLLVM_ARMSubArch_v7k: return "v7k"; case ZigLLVM_ARMSubArch_v7ve: return "v7ve"; case ZigLLVM_ARMSubArch_v6: return "v6"; case ZigLLVM_ARMSubArch_v6m: return "v6m"; case ZigLLVM_ARMSubArch_v6k: return "v6k"; case ZigLLVM_ARMSubArch_v6t2: return "v6t2"; case ZigLLVM_ARMSubArch_v5: return "v5"; case ZigLLVM_ARMSubArch_v5te: return "v5te"; case ZigLLVM_ARMSubArch_v4t: return "v4t"; case ZigLLVM_KalimbaSubArch_v3: return "v3"; case ZigLLVM_KalimbaSubArch_v4: return "v4"; case ZigLLVM_KalimbaSubArch_v5: return "v5"; case ZigLLVM_MipsSubArch_r6: return "r6"; } zig_unreachable(); } size_t target_subarch_list_count(void) { return array_length(subarch_list_list); } SubArchList target_subarch_list_enum(size_t index) { assert(index < array_length(subarch_list_list)); return subarch_list_list[index]; } const char *target_subarch_list_name(SubArchList sub_arch_list) { switch (sub_arch_list) { case SubArchListNone: return "None"; case SubArchListArm32: return "Arm32"; case SubArchListArm64: return "Arm64"; case SubArchListKalimba: return "Kalimba"; case SubArchListMips: return "Mips"; } zig_unreachable(); } Error target_parse_os(Os *out_os, const char *os_ptr, size_t os_len) { for (size_t i = 0; i < array_length(os_list); i += 1) { Os os = os_list[i]; const char *os_name = target_os_name(os); if (mem_eql_str(os_ptr, os_len, os_name)) { *out_os = os; return ErrorNone; } } return ErrorUnknownOperatingSystem; } Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, size_t abi_len) { for (size_t i = 0; i < array_length(abi_list); i += 1) { ZigLLVM_EnvironmentType abi = abi_list[i]; const char *abi_name = target_abi_name(abi); if (mem_eql_str(abi_ptr, abi_len, abi_name)) { *out_abi = abi; return ErrorNone; } } return ErrorUnknownABI; } Error target_parse_triple(ZigTarget *target, const char *triple) { Error err; // first initialize all to zero *target = {}; SplitIterator it = memSplit(str(triple), str("-")); Optional> opt_archsub = SplitIterator_next(&it); Optional> opt_os = SplitIterator_next(&it); Optional> opt_abi = SplitIterator_next(&it); if (!opt_archsub.is_some) return ErrorMissingArchitecture; if ((err = target_parse_archsub(&target->arch, &target->sub_arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) { return err; } if (!opt_os.is_some) return ErrorMissingOperatingSystem; if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) { return err; } if (opt_abi.is_some) { if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) { return err; } } else { target->abi = target_default_abi(target->arch, target->os); } return ErrorNone; } const char *target_arch_name(ZigLLVM_ArchType arch) { return ZigLLVMGetArchTypeName(arch); } void init_all_targets(void) { LLVMInitializeAllTargets(); LLVMInitializeAllTargetInfos(); LLVMInitializeAllTargetMCs(); LLVMInitializeAllAsmPrinters(); LLVMInitializeAllAsmParsers(); } void target_triple_zig(Buf *triple, const ZigTarget *target) { buf_resize(triple, 0); buf_appendf(triple, "%s%s-%s-%s", ZigLLVMGetArchTypeName(target->arch), ZigLLVMGetSubArchTypeName(target->sub_arch), ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)), ZigLLVMGetEnvironmentTypeName(target->abi)); } void target_triple_llvm(Buf *triple, const ZigTarget *target) { buf_resize(triple, 0); buf_appendf(triple, "%s%s-%s-%s-%s", ZigLLVMGetArchTypeName(target->arch), ZigLLVMGetSubArchTypeName(target->sub_arch), ZigLLVMGetVendorTypeName(target->vendor), ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)), ZigLLVMGetEnvironmentTypeName(target->abi)); } bool target_os_is_darwin(Os os) { switch (os) { case OsMacOSX: case OsIOS: case OsWatchOS: case OsTvOS: return true; default: return false; } } ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target) { if (target->os == OsUefi || target->os == OsWindows) { return ZigLLVM_COFF; } else if (target_os_is_darwin(target->os)) { return ZigLLVM_MachO; } if (target->arch == ZigLLVM_wasm32 || target->arch == ZigLLVM_wasm64) { return ZigLLVM_Wasm; } return ZigLLVM_ELF; } // See lib/Support/Triple.cpp in LLVM for the source of this data. // getArchPointerBitWidth uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) { switch (arch) { case ZigLLVM_UnknownArch: return 0; case ZigLLVM_avr: case ZigLLVM_msp430: return 16; case ZigLLVM_arc: case ZigLLVM_arm: case ZigLLVM_armeb: case ZigLLVM_hexagon: case ZigLLVM_le32: case ZigLLVM_mips: case ZigLLVM_mipsel: case ZigLLVM_nvptx: case ZigLLVM_ppc: case ZigLLVM_r600: case ZigLLVM_riscv32: case ZigLLVM_sparc: case ZigLLVM_sparcel: case ZigLLVM_tce: case ZigLLVM_tcele: case ZigLLVM_thumb: case ZigLLVM_thumbeb: case ZigLLVM_x86: case ZigLLVM_xcore: case ZigLLVM_amdil: case ZigLLVM_hsail: case ZigLLVM_spir: case ZigLLVM_kalimba: case ZigLLVM_lanai: case ZigLLVM_shave: case ZigLLVM_wasm32: case ZigLLVM_renderscript32: return 32; case ZigLLVM_aarch64: case ZigLLVM_aarch64_be: case ZigLLVM_amdgcn: case ZigLLVM_bpfel: case ZigLLVM_bpfeb: case ZigLLVM_le64: case ZigLLVM_mips64: case ZigLLVM_mips64el: case ZigLLVM_nvptx64: case ZigLLVM_ppc64: case ZigLLVM_ppc64le: case ZigLLVM_riscv64: case ZigLLVM_sparcv9: case ZigLLVM_systemz: case ZigLLVM_x86_64: case ZigLLVM_amdil64: case ZigLLVM_hsail64: case ZigLLVM_spir64: case ZigLLVM_wasm64: case ZigLLVM_renderscript64: return 64; } zig_unreachable(); } uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch) { switch (arch) { case ZigLLVM_UnknownArch: zig_unreachable(); case ZigLLVM_avr: case ZigLLVM_msp430: return 16; case ZigLLVM_arc: case ZigLLVM_arm: case ZigLLVM_armeb: case ZigLLVM_hexagon: case ZigLLVM_le32: case ZigLLVM_mips: case ZigLLVM_mipsel: case ZigLLVM_nvptx: case ZigLLVM_ppc: case ZigLLVM_r600: case ZigLLVM_riscv32: case ZigLLVM_sparc: case ZigLLVM_sparcel: case ZigLLVM_tce: case ZigLLVM_tcele: case ZigLLVM_thumb: case ZigLLVM_thumbeb: case ZigLLVM_x86: case ZigLLVM_xcore: case ZigLLVM_amdil: case ZigLLVM_hsail: case ZigLLVM_spir: case ZigLLVM_kalimba: case ZigLLVM_lanai: case ZigLLVM_shave: case ZigLLVM_wasm32: case ZigLLVM_renderscript32: return 32; case ZigLLVM_aarch64: case ZigLLVM_aarch64_be: case ZigLLVM_amdgcn: case ZigLLVM_bpfel: case ZigLLVM_bpfeb: case ZigLLVM_le64: case ZigLLVM_mips64: case ZigLLVM_mips64el: case ZigLLVM_nvptx64: case ZigLLVM_ppc64: case ZigLLVM_ppc64le: case ZigLLVM_riscv64: case ZigLLVM_sparcv9: case ZigLLVM_systemz: case ZigLLVM_amdil64: case ZigLLVM_hsail64: case ZigLLVM_spir64: case ZigLLVM_wasm64: case ZigLLVM_renderscript64: return 64; case ZigLLVM_x86_64: return 128; } zig_unreachable(); } uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { switch (target->os) { case OsFreestanding: switch (target->arch) { case ZigLLVM_msp430: switch (id) { case CIntTypeShort: case CIntTypeUShort: return 16; case CIntTypeInt: case CIntTypeUInt: return 16; case CIntTypeLong: case CIntTypeULong: return 32; case CIntTypeLongLong: case CIntTypeULongLong: return 64; case CIntTypeCount: zig_unreachable(); } default: switch (id) { case CIntTypeShort: case CIntTypeUShort: return 16; case CIntTypeInt: case CIntTypeUInt: return 32; case CIntTypeLong: case CIntTypeULong: return target_arch_pointer_bit_width(target->arch); case CIntTypeLongLong: case CIntTypeULongLong: return 64; case CIntTypeCount: zig_unreachable(); } } case OsLinux: case OsMacOSX: case OsZen: case OsFreeBSD: case OsNetBSD: case OsOpenBSD: case OsWASI: switch (id) { case CIntTypeShort: case CIntTypeUShort: return 16; case CIntTypeInt: case CIntTypeUInt: return 32; case CIntTypeLong: case CIntTypeULong: return target_arch_pointer_bit_width(target->arch); case CIntTypeLongLong: case CIntTypeULongLong: return 64; case CIntTypeCount: zig_unreachable(); } case OsUefi: case OsWindows: switch (id) { case CIntTypeShort: case CIntTypeUShort: return 16; case CIntTypeInt: case CIntTypeUInt: case CIntTypeLong: case CIntTypeULong: return 32; case CIntTypeLongLong: case CIntTypeULongLong: return 64; case CIntTypeCount: zig_unreachable(); } case OsIOS: switch (id) { case CIntTypeShort: case CIntTypeUShort: return 16; case CIntTypeInt: case CIntTypeUInt: return 32; case CIntTypeLong: case CIntTypeULong: case CIntTypeLongLong: case CIntTypeULongLong: return 64; case CIntTypeCount: zig_unreachable(); } case OsAnanas: case OsCloudABI: case OsDragonFly: case OsKFreeBSD: case OsLv2: case OsSolaris: case OsHaiku: case OsMinix: case OsRTEMS: case OsNaCl: case OsCNK: case OsAIX: case OsCUDA: case OsNVCL: case OsAMDHSA: case OsPS4: case OsELFIAMCU: case OsTvOS: case OsWatchOS: case OsMesa3D: case OsFuchsia: case OsContiki: case OsAMDPAL: case OsHermitCore: case OsHurd: zig_panic("TODO c type size in bits for this target"); } zig_unreachable(); } bool target_allows_addr_zero(const ZigTarget *target) { return target->os == OsFreestanding; } const char *target_o_file_ext(const ZigTarget *target) { if (target->abi == ZigLLVM_MSVC || (target->os == OsWindows && !target_abi_is_gnu(target->abi)) || target->os == OsUefi) { return ".obj"; } else { return ".o"; } } const char *target_asm_file_ext(const ZigTarget *target) { return ".s"; } const char *target_llvm_ir_file_ext(const ZigTarget *target) { return ".ll"; } const char *target_exe_file_ext(const ZigTarget *target) { if (target->os == OsWindows) { return ".exe"; } else if (target->os == OsUefi) { return ".efi"; } else if (target_is_wasm(target)) { return ".wasm"; } else { return ""; } } const char *target_lib_file_prefix(const ZigTarget *target) { if ((target->os == OsWindows && !target_abi_is_gnu(target->abi)) || target->os == OsUefi || target_is_wasm(target)) { return ""; } else { return "lib"; } } const char *target_lib_file_ext(const ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) { if (target_is_wasm(target)) { return ".wasm"; } if (target->os == OsWindows || target->os == OsUefi) { if (is_static) { if (target->os == OsWindows && target_abi_is_gnu(target->abi)) { return ".a"; } else { return ".lib"; } } else { return ".dll"; } } else { if (is_static) { return ".a"; } else if (target_os_is_darwin(target->os)) { return buf_ptr(buf_sprintf(".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib", version_major, version_minor, version_patch)); } else { return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize, version_major, version_minor, version_patch)); } } } enum FloatAbi { FloatAbiHard, FloatAbiSoft, FloatAbiSoftFp, }; static FloatAbi get_float_abi(const ZigTarget *target) { const ZigLLVM_EnvironmentType env = target->abi; if (env == ZigLLVM_GNUEABIHF || env == ZigLLVM_EABIHF || env == ZigLLVM_MuslEABIHF) { return FloatAbiHard; } else { return FloatAbiSoft; } } static bool is_64_bit(ZigLLVM_ArchType arch) { return target_arch_pointer_bit_width(arch) == 64; } const char *target_dynamic_linker(const ZigTarget *target) { switch (target->os) { case OsFreeBSD: return "/libexec/ld-elf.so.1"; case OsNetBSD: return "/libexec/ld.elf_so"; case OsLinux: { const ZigLLVM_EnvironmentType abi = target->abi; if (abi == ZigLLVM_Android) { if (is_64_bit(target->arch)) { return "/system/bin/linker64"; } else { return "/system/bin/linker"; } } switch (target->arch) { case ZigLLVM_UnknownArch: zig_unreachable(); case ZigLLVM_x86: case ZigLLVM_sparc: case ZigLLVM_sparcel: return "/lib/ld-linux.so.2"; case ZigLLVM_aarch64: return "/lib/ld-linux-aarch64.so.1"; case ZigLLVM_aarch64_be: return "/lib/ld-linux-aarch64_be.so.1"; case ZigLLVM_arm: case ZigLLVM_thumb: if (get_float_abi(target) == FloatAbiHard) { return "/lib/ld-linux-armhf.so.3"; } else { return "/lib/ld-linux.so.3"; } case ZigLLVM_armeb: case ZigLLVM_thumbeb: if (get_float_abi(target) == FloatAbiHard) { return "/lib/ld-linux-armhf.so.3"; } else { return "/lib/ld-linux.so.3"; } case ZigLLVM_mips: case ZigLLVM_mipsel: case ZigLLVM_mips64: case ZigLLVM_mips64el: zig_panic("TODO implement target_dynamic_linker for mips"); case ZigLLVM_ppc: return "/lib/ld.so.1"; case ZigLLVM_ppc64: return "/lib64/ld64.so.2"; case ZigLLVM_ppc64le: return "/lib64/ld64.so.2"; case ZigLLVM_systemz: return "/lib64/ld64.so.1"; case ZigLLVM_sparcv9: return "/lib64/ld-linux.so.2"; case ZigLLVM_x86_64: if (abi == ZigLLVM_GNUX32) { return "/libx32/ld-linux-x32.so.2"; } if (abi == ZigLLVM_Musl || abi == ZigLLVM_MuslEABI || abi == ZigLLVM_MuslEABIHF) { return "/lib/ld-musl-x86_64.so.1"; } return "/lib64/ld-linux-x86-64.so.2"; case ZigLLVM_wasm32: case ZigLLVM_wasm64: return nullptr; case ZigLLVM_riscv32: return "/lib/ld-linux-riscv32-ilp32.so.1"; case ZigLLVM_riscv64: return "/lib/ld-linux-riscv64-lp64.so.1"; case ZigLLVM_arc: case ZigLLVM_avr: case ZigLLVM_bpfel: case ZigLLVM_bpfeb: case ZigLLVM_hexagon: case ZigLLVM_msp430: case ZigLLVM_r600: case ZigLLVM_amdgcn: case ZigLLVM_tce: case ZigLLVM_tcele: case ZigLLVM_xcore: case ZigLLVM_nvptx: case ZigLLVM_nvptx64: case ZigLLVM_le32: case ZigLLVM_le64: case ZigLLVM_amdil: case ZigLLVM_amdil64: case ZigLLVM_hsail: case ZigLLVM_hsail64: case ZigLLVM_spir: case ZigLLVM_spir64: case ZigLLVM_kalimba: case ZigLLVM_shave: case ZigLLVM_lanai: case ZigLLVM_renderscript32: case ZigLLVM_renderscript64: zig_panic("TODO implement target_dynamic_linker for this arch"); } zig_unreachable(); } case OsFreestanding: case OsIOS: case OsTvOS: case OsWatchOS: case OsMacOSX: case OsUefi: case OsWindows: return nullptr; case OsAnanas: case OsCloudABI: case OsDragonFly: case OsFuchsia: case OsKFreeBSD: case OsLv2: case OsOpenBSD: case OsSolaris: case OsHaiku: case OsMinix: case OsRTEMS: case OsNaCl: case OsCNK: case OsAIX: case OsCUDA: case OsNVCL: case OsAMDHSA: case OsPS4: case OsELFIAMCU: case OsMesa3D: case OsContiki: case OsAMDPAL: case OsZen: case OsHermitCore: case OsHurd: case OsWASI: zig_panic("TODO implement target_dynamic_linker for this OS"); } zig_unreachable(); } bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target) { assert(host_target != nullptr); if (guest_target == nullptr) { // null guest target means that the guest target is native return true; } if (guest_target->os == host_target->os && guest_target->arch == host_target->arch && guest_target->sub_arch == host_target->sub_arch) { // OS, arch, and sub-arch match return true; } if (guest_target->os == OsWindows && host_target->os == OsWindows && host_target->arch == ZigLLVM_x86_64 && guest_target->arch == ZigLLVM_x86) { // 64-bit windows can run 32-bit programs return true; } return false; } const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { switch (arch) { case ZigLLVM_UnknownArch: zig_unreachable(); case ZigLLVM_x86: return "esp"; case ZigLLVM_x86_64: return "rsp"; case ZigLLVM_aarch64: return "sp"; case ZigLLVM_arm: case ZigLLVM_thumb: case ZigLLVM_aarch64_be: case ZigLLVM_amdgcn: case ZigLLVM_amdil: case ZigLLVM_amdil64: case ZigLLVM_armeb: case ZigLLVM_arc: case ZigLLVM_avr: case ZigLLVM_bpfeb: case ZigLLVM_bpfel: case ZigLLVM_hexagon: case ZigLLVM_lanai: case ZigLLVM_hsail: case ZigLLVM_hsail64: case ZigLLVM_kalimba: case ZigLLVM_le32: case ZigLLVM_le64: case ZigLLVM_mips: case ZigLLVM_mips64: case ZigLLVM_mips64el: case ZigLLVM_mipsel: case ZigLLVM_msp430: case ZigLLVM_nvptx: case ZigLLVM_nvptx64: case ZigLLVM_ppc64le: case ZigLLVM_r600: case ZigLLVM_renderscript32: case ZigLLVM_renderscript64: case ZigLLVM_riscv32: case ZigLLVM_riscv64: case ZigLLVM_shave: case ZigLLVM_sparc: case ZigLLVM_sparcel: case ZigLLVM_sparcv9: case ZigLLVM_spir: case ZigLLVM_spir64: case ZigLLVM_systemz: case ZigLLVM_tce: case ZigLLVM_tcele: case ZigLLVM_thumbeb: case ZigLLVM_wasm32: case ZigLLVM_wasm64: case ZigLLVM_xcore: case ZigLLVM_ppc: case ZigLLVM_ppc64: zig_panic("TODO populate this table with stack pointer register name for this CPU architecture"); } zig_unreachable(); } bool target_is_arm(const ZigTarget *target) { switch (target->arch) { case ZigLLVM_UnknownArch: zig_unreachable(); case ZigLLVM_aarch64: case ZigLLVM_arm: case ZigLLVM_thumb: case ZigLLVM_aarch64_be: case ZigLLVM_armeb: case ZigLLVM_thumbeb: return true; case ZigLLVM_x86: case ZigLLVM_x86_64: case ZigLLVM_amdgcn: case ZigLLVM_amdil: case ZigLLVM_amdil64: case ZigLLVM_arc: case ZigLLVM_avr: case ZigLLVM_bpfeb: case ZigLLVM_bpfel: case ZigLLVM_hexagon: case ZigLLVM_lanai: case ZigLLVM_hsail: case ZigLLVM_hsail64: case ZigLLVM_kalimba: case ZigLLVM_le32: case ZigLLVM_le64: case ZigLLVM_mips: case ZigLLVM_mips64: case ZigLLVM_mips64el: case ZigLLVM_mipsel: case ZigLLVM_msp430: case ZigLLVM_nvptx: case ZigLLVM_nvptx64: case ZigLLVM_ppc64le: case ZigLLVM_r600: case ZigLLVM_renderscript32: case ZigLLVM_renderscript64: case ZigLLVM_riscv32: case ZigLLVM_riscv64: case ZigLLVM_shave: case ZigLLVM_sparc: case ZigLLVM_sparcel: case ZigLLVM_sparcv9: case ZigLLVM_spir: case ZigLLVM_spir64: case ZigLLVM_systemz: case ZigLLVM_tce: case ZigLLVM_tcele: case ZigLLVM_wasm32: case ZigLLVM_wasm64: case ZigLLVM_xcore: case ZigLLVM_ppc: case ZigLLVM_ppc64: return false; } zig_unreachable(); } // Valgrind supports more, but Zig does not support them yet. bool target_has_valgrind_support(const ZigTarget *target) { switch (target->arch) { case ZigLLVM_UnknownArch: zig_unreachable(); case ZigLLVM_x86_64: return (target->os == OsLinux || target_os_is_darwin(target->os) || target->os == OsSolaris || (target->os == OsWindows && target->abi != ZigLLVM_MSVC)); default: return false; } zig_unreachable(); } bool target_os_requires_libc(Os os) { // On Darwin, we always link libSystem which contains libc. // Similarly on FreeBSD and NetBSD we always link system libc // since this is the stable syscall interface. return (target_os_is_darwin(os) || os == OsFreeBSD || os == OsNetBSD); } bool target_supports_fpic(const ZigTarget *target) { // This is not whether the target supports Position Independent Code, but whether the -fPIC // C compiler argument is valid. return target->os != OsWindows; } bool target_supports_stack_probing(const ZigTarget *target) { return target->os != OsWindows && (target->arch == ZigLLVM_x86 || target->arch == ZigLLVM_x86_64); } bool target_requires_pic(const ZigTarget *target, bool linking_libc) { // This function returns whether non-pic code is completely invalid on the given target. return target->os == OsWindows || target_os_requires_libc(target->os) || (linking_libc && target_is_glibc(target)); } bool target_is_glibc(const ZigTarget *target) { return target->os == OsLinux && target_abi_is_gnu(target->abi); } bool target_is_musl(const ZigTarget *target) { return target->os == OsLinux && target_abi_is_musl(target->abi); } bool target_is_wasm(const ZigTarget *target) { return target->arch == ZigLLVM_wasm32 || target->arch == ZigLLVM_wasm64; } bool target_is_single_threaded(const ZigTarget *target) { return target_is_wasm(target); } ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { if (arch == ZigLLVM_wasm32 || arch == ZigLLVM_wasm64) { return ZigLLVM_Musl; } switch (os) { case OsFreestanding: case OsAnanas: case OsCloudABI: case OsDragonFly: case OsLv2: case OsSolaris: case OsHaiku: case OsMinix: case OsRTEMS: case OsNaCl: case OsCNK: case OsAIX: case OsCUDA: case OsNVCL: case OsAMDHSA: case OsPS4: case OsELFIAMCU: case OsMesa3D: case OsContiki: case OsAMDPAL: case OsZen: case OsHermitCore: return ZigLLVM_EABI; case OsOpenBSD: case OsMacOSX: case OsFreeBSD: case OsIOS: case OsTvOS: case OsWatchOS: case OsFuchsia: case OsKFreeBSD: case OsNetBSD: case OsHurd: return ZigLLVM_GNU; case OsUefi: case OsWindows: return ZigLLVM_MSVC; case OsLinux: case OsWASI: return ZigLLVM_Musl; } zig_unreachable(); } bool target_abi_is_gnu(ZigLLVM_EnvironmentType abi) { switch (abi) { case ZigLLVM_GNU: case ZigLLVM_GNUABIN32: case ZigLLVM_GNUABI64: case ZigLLVM_GNUEABI: case ZigLLVM_GNUEABIHF: case ZigLLVM_GNUX32: return true; default: return false; } } bool target_abi_is_musl(ZigLLVM_EnvironmentType abi) { switch (abi) { case ZigLLVM_Musl: case ZigLLVM_MuslEABI: case ZigLLVM_MuslEABIHF: return true; default: return false; } } struct AvailableLibC { ZigLLVM_ArchType arch; Os os; ZigLLVM_EnvironmentType abi; }; static const AvailableLibC libcs_available[] = { {ZigLLVM_aarch64_be, OsLinux, ZigLLVM_GNU}, {ZigLLVM_aarch64_be, OsLinux, ZigLLVM_Musl}, {ZigLLVM_aarch64_be, OsWindows, ZigLLVM_GNU}, {ZigLLVM_aarch64, OsLinux, ZigLLVM_GNU}, {ZigLLVM_aarch64, OsLinux, ZigLLVM_Musl}, {ZigLLVM_aarch64, OsWindows, ZigLLVM_GNU}, {ZigLLVM_armeb, OsLinux, ZigLLVM_GNUEABI}, {ZigLLVM_armeb, OsLinux, ZigLLVM_GNUEABIHF}, {ZigLLVM_armeb, OsLinux, ZigLLVM_MuslEABI}, {ZigLLVM_armeb, OsLinux, ZigLLVM_MuslEABIHF}, {ZigLLVM_armeb, OsWindows, ZigLLVM_GNU}, {ZigLLVM_arm, OsLinux, ZigLLVM_GNUEABI}, {ZigLLVM_arm, OsLinux, ZigLLVM_GNUEABIHF}, {ZigLLVM_arm, OsLinux, ZigLLVM_MuslEABI}, {ZigLLVM_arm, OsLinux, ZigLLVM_MuslEABIHF}, {ZigLLVM_arm, OsWindows, ZigLLVM_GNU}, {ZigLLVM_x86, OsLinux, ZigLLVM_GNU}, {ZigLLVM_x86, OsLinux, ZigLLVM_Musl}, {ZigLLVM_x86, OsWindows, ZigLLVM_GNU}, {ZigLLVM_mips64el, OsLinux, ZigLLVM_GNUABI64}, {ZigLLVM_mips64el, OsLinux, ZigLLVM_GNUABIN32}, {ZigLLVM_mips64el, OsLinux, ZigLLVM_Musl}, {ZigLLVM_mips64, OsLinux, ZigLLVM_GNUABI64}, {ZigLLVM_mips64, OsLinux, ZigLLVM_GNUABIN32}, {ZigLLVM_mips64, OsLinux, ZigLLVM_Musl}, {ZigLLVM_mipsel, OsLinux, ZigLLVM_GNU}, {ZigLLVM_mipsel, OsLinux, ZigLLVM_Musl}, {ZigLLVM_mips, OsLinux, ZigLLVM_GNU}, {ZigLLVM_mips, OsLinux, ZigLLVM_Musl}, {ZigLLVM_ppc64le, OsLinux, ZigLLVM_GNU}, {ZigLLVM_ppc64le, OsLinux, ZigLLVM_Musl}, {ZigLLVM_ppc64, OsLinux, ZigLLVM_GNU}, {ZigLLVM_ppc64, OsLinux, ZigLLVM_Musl}, {ZigLLVM_ppc, OsLinux, ZigLLVM_GNU}, {ZigLLVM_ppc, OsLinux, ZigLLVM_Musl}, {ZigLLVM_riscv64, OsLinux, ZigLLVM_GNU}, {ZigLLVM_riscv64, OsLinux, ZigLLVM_Musl}, {ZigLLVM_systemz, OsLinux, ZigLLVM_GNU}, {ZigLLVM_systemz, OsLinux, ZigLLVM_Musl}, {ZigLLVM_sparc, OsLinux, ZigLLVM_GNU}, {ZigLLVM_sparcv9, OsLinux, ZigLLVM_GNU}, {ZigLLVM_wasm32, OsFreestanding, ZigLLVM_Musl}, {ZigLLVM_x86_64, OsLinux, ZigLLVM_GNU}, {ZigLLVM_x86_64, OsLinux, ZigLLVM_GNUX32}, {ZigLLVM_x86_64, OsLinux, ZigLLVM_Musl}, {ZigLLVM_x86_64, OsWindows, ZigLLVM_GNU}, }; bool target_can_build_libc(const ZigTarget *target) { for (size_t i = 0; i < array_length(libcs_available); i += 1) { if (target->arch == libcs_available[i].arch && target->os == libcs_available[i].os && target->abi == libcs_available[i].abi) { return true; } } return false; } const char *target_libc_generic_name(const ZigTarget *target) { if (target->os == OsWindows) { return "mingw"; } switch (target->abi) { case ZigLLVM_GNU: case ZigLLVM_GNUABIN32: case ZigLLVM_GNUABI64: case ZigLLVM_GNUEABI: case ZigLLVM_GNUEABIHF: case ZigLLVM_GNUX32: return "glibc"; case ZigLLVM_Musl: case ZigLLVM_MuslEABI: case ZigLLVM_MuslEABIHF: case ZigLLVM_UnknownEnvironment: return "musl"; case ZigLLVM_CODE16: case ZigLLVM_EABI: case ZigLLVM_EABIHF: case ZigLLVM_Android: case ZigLLVM_MSVC: case ZigLLVM_Itanium: case ZigLLVM_Cygnus: case ZigLLVM_CoreCLR: case ZigLLVM_Simulator: zig_unreachable(); } zig_unreachable(); } bool target_is_libc_lib_name(const ZigTarget *target, const char *name) { if (strcmp(name, "c") == 0) return true; if (target_abi_is_gnu(target->abi) || target_abi_is_musl(target->abi) || target_os_is_darwin(target->os)) { if (strcmp(name, "m") == 0) return true; if (strcmp(name, "rt") == 0) return true; if (strcmp(name, "pthread") == 0) return true; if (strcmp(name, "crypt") == 0) return true; if (strcmp(name, "util") == 0) return true; if (strcmp(name, "xnet") == 0) return true; if (strcmp(name, "resolv") == 0) return true; if (strcmp(name, "dl") == 0) return true; } return false; } size_t target_libc_count(void) { return array_length(libcs_available); } void target_libc_enum(size_t index, ZigTarget *out_target) { assert(index < array_length(libcs_available)); out_target->arch = libcs_available[index].arch; out_target->os = libcs_available[index].os; out_target->abi = libcs_available[index].abi; out_target->sub_arch = ZigLLVM_NoSubArch; out_target->vendor = ZigLLVM_UnknownVendor; out_target->is_native = false; } bool target_has_debug_info(const ZigTarget *target) { return !target_is_wasm(target); } const char *target_arch_musl_name(ZigLLVM_ArchType arch) { switch (arch) { case ZigLLVM_aarch64: case ZigLLVM_aarch64_be: return "aarch64"; case ZigLLVM_arm: case ZigLLVM_armeb: return "arm"; case ZigLLVM_mips: case ZigLLVM_mipsel: return "mips"; case ZigLLVM_mips64el: case ZigLLVM_mips64: return "mips64"; case ZigLLVM_ppc: return "powerpc"; case ZigLLVM_ppc64: case ZigLLVM_ppc64le: return "powerpc64"; case ZigLLVM_systemz: return "s390x"; case ZigLLVM_x86: return "i386"; case ZigLLVM_x86_64: return "x86_64"; case ZigLLVM_riscv64: return "riscv64"; default: zig_unreachable(); } } bool target_supports_libunwind(const ZigTarget *target) { if (target->arch == ZigLLVM_arm || target->arch == ZigLLVM_armeb) { return false; } return true; } unsigned target_fn_align(const ZigTarget *target) { return 16; }