StringRef swift::getPlatformNameForTriple(const llvm::Triple &triple) { if (triple.isiOS()) { if (triple.isTvOS()) { if (tripleIsAppleTVSimulator(triple)) return "appletvsimulator"; return "appletvos"; } if (tripleIsiOSSimulator(triple)) return "iphonesimulator"; return "iphoneos"; } if (triple.isWatchOS()) { if (tripleIsWatchSimulator(triple)) return "watchsimulator"; return "watchos"; } if (triple.isAndroid()) { return "android"; } if (triple.isMacOSX()) return "macosx"; if (triple.isOSLinux()) return "linux"; if (triple.isOSFreeBSD()) return "freebsd"; return ""; }
static void updateRuntimeLibraryPath(SearchPathOptions &SearchPathOpts, llvm::Triple &Triple) { llvm::SmallString<128> LibPath(SearchPathOpts.RuntimeResourcePath); llvm::sys::path::append(LibPath, getPlatformNameForTriple(Triple)); SearchPathOpts.RuntimeLibraryPath = LibPath.str(); // The linux provided triple for ARM contains a trailing 'l' // denoting little-endian. This is not used in the path for // libraries. LLVM matches these SubArchTypes to the generic // ARMSubArch_v7 (for example) type. If that is the case, // use the base of the architecture type in the library path. if (Triple.isOSLinux()) { switch(Triple.getSubArch()) { default: llvm::sys::path::append(LibPath, Triple.getArchName()); break; case llvm::Triple::SubArchType::ARMSubArch_v7: llvm::sys::path::append(LibPath, "armv7"); break; case llvm::Triple::SubArchType::ARMSubArch_v6: llvm::sys::path::append(LibPath, "armv6"); break; } } else { llvm::sys::path::append(LibPath, Triple.getArchName()); } SearchPathOpts.RuntimeLibraryImportPath = LibPath.str(); }
OptionSet<SanitizerKind> swift::parseSanitizerArgValues( const llvm::opt::ArgList &Args, const llvm::opt::Arg *A, const llvm::Triple &Triple, DiagnosticEngine &Diags, llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists) { OptionSet<SanitizerKind> sanitizerSet; // Find the sanitizer kind. for (int i = 0, n = A->getNumValues(); i != n; ++i) { StringRef opt = A->getValue(i); if (opt == "address") { sanitizerSet |= SanitizerKind::Address; } else if (opt == "thread") { sanitizerSet |= SanitizerKind::Thread; } else if (opt == "fuzzer") { sanitizerSet |= SanitizerKind::Fuzzer; } else { Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument, A->getOption().getPrefixedName(), A->getValue(i)); } } // Sanitizers are only supported on Linux or Darwin. if (!(Triple.isOSDarwin() || Triple.isOSLinux())) { SmallString<128> b; Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target, (A->getOption().getPrefixedName() + StringRef(A->getAsString(Args))).toStringRef(b), Triple.getTriple()); } // Address and thread sanitizers can not be enabled concurrently. if ((sanitizerSet & SanitizerKind::Thread) && (sanitizerSet & SanitizerKind::Address)) { SmallString<128> b1; SmallString<128> b2; Diags.diagnose(SourceLoc(), diag::error_argument_not_allowed_with, (A->getOption().getPrefixedName() + toStringRef(SanitizerKind::Address)).toStringRef(b1), (A->getOption().getPrefixedName() + toStringRef(SanitizerKind::Thread)).toStringRef(b2)); } // Thread Sanitizer only works on OS X and the simulators. It's only supported // on 64 bit architectures. if ((sanitizerSet & SanitizerKind::Thread) && !isTSanSupported(Triple, sanitizerRuntimeLibExists)) { SmallString<128> b; Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target, (A->getOption().getPrefixedName() + toStringRef(SanitizerKind::Thread)).toStringRef(b), Triple.getTriple()); } return sanitizerSet; }
StringRef swift::getMajorArchitectureName(const llvm::Triple &Triple) { if (Triple.isOSLinux()) { switch(Triple.getSubArch()) { default: return Triple.getArchName(); break; case llvm::Triple::SubArchType::ARMSubArch_v7: return "armv7"; break; case llvm::Triple::SubArchType::ARMSubArch_v6: return "armv6"; break; } } else { return Triple.getArchName(); } }
// This function maps triples to the architecture component of the path // where the swift_begin.o and swift_end.o objects can be found. This // is a stop-gap until full Triple support (ala Clang) exists within swiftc. StringRef getSectionMagicArch(const llvm::Triple &Triple) { if (Triple.isOSLinux()) { switch(Triple.getSubArch()) { default: return Triple.getArchName(); break; case llvm::Triple::SubArchType::ARMSubArch_v7: return "armv7"; break; case llvm::Triple::SubArchType::ARMSubArch_v6: return "armv6"; break; } } else { return Triple.getArchName(); } }
StringRef swift::getPlatformNameForTriple(const llvm::Triple &triple) { if (triple.isOSDarwin()) return getPlatformNameForDarwin(getDarwinPlatformKind(triple)); if (triple.isAndroid()) return "android"; if (triple.isOSLinux()) return "linux"; if (triple.isOSFreeBSD()) return "freebsd"; if (triple.isOSWindows()) return "windows"; return ""; }
StringRef swift::getPlatformNameForTriple(const llvm::Triple &triple) { if (triple.isOSDarwin()) return getPlatformNameForDarwin(getDarwinPlatformKind(triple)); if (triple.isAndroid()) return "android"; if (triple.isOSLinux()) return "linux"; if (triple.isOSFreeBSD()) return "freebsd"; if (triple.isKnownWindowsMSVCEnvironment()) return "windows"; if (triple.isWindowsCygwinEnvironment()) return "cygwin"; if (triple.isWindowsGNUEnvironment()) return "mingw"; return ""; }
std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) { clearAllPlatformConditionValues(); if (triple.getOS() == llvm::Triple::Darwin && triple.getVendor() == llvm::Triple::Apple) { // Rewrite darwinX.Y triples to macosx10.X'.Y ones. // It affects code generation on our platform. llvm::SmallString<16> osxBuf; llvm::raw_svector_ostream osx(osxBuf); osx << llvm::Triple::getOSTypeName(llvm::Triple::MacOSX); unsigned major, minor, micro; triple.getMacOSXVersion(major, minor, micro); osx << major << "." << minor; if (micro != 0) osx << "." << micro; triple.setOSName(osx.str()); } Target = std::move(triple); bool UnsupportedOS = false; // Set the "os" platform condition. if (Target.isMacOSX()) addPlatformConditionValue(PlatformConditionKind::OS, "OSX"); else if (triple.isTvOS()) addPlatformConditionValue(PlatformConditionKind::OS, "tvOS"); else if (triple.isWatchOS()) addPlatformConditionValue(PlatformConditionKind::OS, "watchOS"); else if (triple.isiOS()) addPlatformConditionValue(PlatformConditionKind::OS, "iOS"); else if (triple.isAndroid()) addPlatformConditionValue(PlatformConditionKind::OS, "Android"); else if (triple.isOSLinux()) addPlatformConditionValue(PlatformConditionKind::OS, "Linux"); else if (triple.isOSFreeBSD()) addPlatformConditionValue(PlatformConditionKind::OS, "FreeBSD"); else if (triple.isOSWindows()) addPlatformConditionValue(PlatformConditionKind::OS, "Windows"); else if (triple.isWindowsCygwinEnvironment()) addPlatformConditionValue(PlatformConditionKind::OS, "Cygwin"); else if (triple.isPS4()) addPlatformConditionValue(PlatformConditionKind::OS, "PS4"); else UnsupportedOS = true; bool UnsupportedArch = false; // Set the "arch" platform condition. switch (Target.getArch()) { case llvm::Triple::ArchType::arm: case llvm::Triple::ArchType::thumb: addPlatformConditionValue(PlatformConditionKind::Arch, "arm"); break; case llvm::Triple::ArchType::aarch64: addPlatformConditionValue(PlatformConditionKind::Arch, "arm64"); break; case llvm::Triple::ArchType::ppc64: addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64"); break; case llvm::Triple::ArchType::ppc64le: addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64le"); break; case llvm::Triple::ArchType::x86: addPlatformConditionValue(PlatformConditionKind::Arch, "i386"); break; case llvm::Triple::ArchType::x86_64: addPlatformConditionValue(PlatformConditionKind::Arch, "x86_64"); break; case llvm::Triple::ArchType::systemz: addPlatformConditionValue(PlatformConditionKind::Arch, "s390x"); break; default: UnsupportedArch = true; } if (UnsupportedOS || UnsupportedArch) return { UnsupportedOS, UnsupportedArch }; // Set the "_endian" platform condition. switch (Target.getArch()) { case llvm::Triple::ArchType::arm: case llvm::Triple::ArchType::thumb: addPlatformConditionValue(PlatformConditionKind::Endianness, "little"); break; case llvm::Triple::ArchType::aarch64: addPlatformConditionValue(PlatformConditionKind::Endianness, "little"); break; case llvm::Triple::ArchType::ppc64: addPlatformConditionValue(PlatformConditionKind::Endianness, "big"); break; case llvm::Triple::ArchType::ppc64le: addPlatformConditionValue(PlatformConditionKind::Endianness, "little"); break; case llvm::Triple::ArchType::x86: addPlatformConditionValue(PlatformConditionKind::Endianness, "little"); break; case llvm::Triple::ArchType::x86_64: addPlatformConditionValue(PlatformConditionKind::Endianness, "little"); break; case llvm::Triple::ArchType::systemz: addPlatformConditionValue(PlatformConditionKind::Endianness, "big"); break; default: llvm_unreachable("undefined architecture endianness"); } // Set the "runtime" platform condition. if (EnableObjCInterop) addPlatformConditionValue(PlatformConditionKind::Runtime, "_ObjC"); else addPlatformConditionValue(PlatformConditionKind::Runtime, "_Native"); // If you add anything to this list, change the default size of // PlatformConditionValues to not require an extra allocation // in the common case. return { false, false }; }
OptionSet<SanitizerKind> swift::parseSanitizerArgValues( const llvm::opt::ArgList &Args, const llvm::opt::Arg *A, const llvm::Triple &Triple, DiagnosticEngine &Diags, llvm::function_ref<bool(llvm::StringRef, bool)> sanitizerRuntimeLibExists) { OptionSet<SanitizerKind> sanitizerSet; // Find the sanitizer kind. for (int i = 0, n = A->getNumValues(); i != n; ++i) { auto kind = llvm::StringSwitch<Optional<SanitizerKind>>(A->getValue(i)) .Case("address", SanitizerKind::Address) .Case("thread", SanitizerKind::Thread) .Case("fuzzer", SanitizerKind::Fuzzer) .Default(None); bool isShared = kind && *kind != SanitizerKind::Fuzzer; if (!kind) { Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument, A->getOption().getPrefixedName(), A->getValue(i)); } else { // Support is determined by existance of the sanitizer library. bool sanitizerSupported = sanitizerRuntimeLibExists(toFileName(*kind), isShared); // TSan is explicitly not supported for 32 bits. if (*kind == SanitizerKind::Thread && !Triple.isArch64Bit()) sanitizerSupported = false; if (!sanitizerSupported) { SmallString<128> b; Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target, (A->getOption().getPrefixedName() + toStringRef(*kind)) .toStringRef(b), Triple.getTriple()); } else { sanitizerSet |= *kind; } } } // Check that we're one of the known supported targets for sanitizers. if (!(Triple.isOSDarwin() || Triple.isOSLinux() || Triple.isOSWindows())) { SmallString<128> b; Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target, (A->getOption().getPrefixedName() + StringRef(A->getAsString(Args))).toStringRef(b), Triple.getTriple()); } // Address and thread sanitizers can not be enabled concurrently. if ((sanitizerSet & SanitizerKind::Thread) && (sanitizerSet & SanitizerKind::Address)) { SmallString<128> b1; SmallString<128> b2; Diags.diagnose(SourceLoc(), diag::error_argument_not_allowed_with, (A->getOption().getPrefixedName() + toStringRef(SanitizerKind::Address)).toStringRef(b1), (A->getOption().getPrefixedName() + toStringRef(SanitizerKind::Thread)).toStringRef(b2)); } return sanitizerSet; }
std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) { clearAllTargetConfigOptions(); if (triple.getOS() == llvm::Triple::Darwin && triple.getVendor() == llvm::Triple::Apple) { // Rewrite darwinX.Y triples to macosx10.X'.Y ones. // It affects code generation on our platform. llvm::SmallString<16> osxBuf; llvm::raw_svector_ostream osx(osxBuf); osx << llvm::Triple::getOSTypeName(llvm::Triple::MacOSX); unsigned major, minor, micro; triple.getMacOSXVersion(major, minor, micro); osx << major << "." << minor; if (micro != 0) osx << "." << micro; triple.setOSName(osx.str()); } Target = std::move(triple); bool UnsupportedOS = false; // Set the "os" target configuration. if (Target.isMacOSX()) addTargetConfigOption("os", "OSX"); else if (triple.isTvOS()) addTargetConfigOption("os", "tvOS"); else if (triple.isWatchOS()) addTargetConfigOption("os", "watchOS"); else if (triple.isiOS()) addTargetConfigOption("os", "iOS"); else if (triple.isOSLinux()) addTargetConfigOption("os", "Linux"); else { UnsupportedOS = true; } bool UnsupportedArch = false; // Set the "arch" target configuration. switch (Target.getArch()) { case llvm::Triple::ArchType::arm: addTargetConfigOption("arch", "arm"); break; case llvm::Triple::ArchType::aarch64: addTargetConfigOption("arch", "arm64"); break; case llvm::Triple::ArchType::x86: addTargetConfigOption("arch", "i386"); break; case llvm::Triple::ArchType::x86_64: addTargetConfigOption("arch", "x86_64"); break; default: UnsupportedArch = true; } if (UnsupportedOS || UnsupportedArch) return { UnsupportedOS, UnsupportedArch }; // Set the "runtime" target configuration. if (EnableObjCInterop) addTargetConfigOption("_runtime", "_ObjC"); else addTargetConfigOption("_runtime", "_Native"); return { false, false }; }
void arm::getARMTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, const ArgList &Args, ArgStringList &CmdArgs, std::vector<StringRef> &Features, bool ForAS) { const Driver &D = TC.getDriver(); bool KernelOrKext = Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); arm::FloatABI ABI = arm::getARMFloatABI(TC, Args); const Arg *WaCPU = nullptr, *WaFPU = nullptr; const Arg *WaHDiv = nullptr, *WaArch = nullptr; if (!ForAS) { // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these // yet (it uses the -mfloat-abi and -msoft-float options), and it is // stripped out by the ARM target. We should probably pass this a new // -target-option, which is handled by the -cc1/-cc1as invocation. // // FIXME2: For consistency, it would be ideal if we set up the target // machine state the same when using the frontend or the assembler. We don't // currently do that for the assembler, we pass the options directly to the // backend and never even instantiate the frontend TargetInfo. If we did, // and used its handleTargetFeatures hook, then we could ensure the // assembler and the frontend behave the same. // Use software floating point operations? if (ABI == arm::FloatABI::Soft) Features.push_back("+soft-float"); // Use software floating point argument passing? if (ABI != arm::FloatABI::Hard) Features.push_back("+soft-float-abi"); } else { // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down // to the assembler correctly. for (const Arg *A : Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { StringRef Value = A->getValue(); if (Value.startswith("-mfpu=")) { WaFPU = A; } else if (Value.startswith("-mcpu=")) { WaCPU = A; } else if (Value.startswith("-mhwdiv=")) { WaHDiv = A; } else if (Value.startswith("-march=")) { WaArch = A; } } } // Check -march. ClangAs gives preference to -Wa,-march=. const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ); StringRef ArchName; if (WaArch) { if (ArchArg) D.Diag(clang::diag::warn_drv_unused_argument) << ArchArg->getAsString(Args); ArchName = StringRef(WaArch->getValue()).substr(7); checkARMArchName(D, WaArch, Args, ArchName, Features, Triple); // FIXME: Set Arch. D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args); } else if (ArchArg) { ArchName = ArchArg->getValue(); checkARMArchName(D, ArchArg, Args, ArchName, Features, Triple); } // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=. const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ); StringRef CPUName; if (WaCPU) { if (CPUArg) D.Diag(clang::diag::warn_drv_unused_argument) << CPUArg->getAsString(Args); CPUName = StringRef(WaCPU->getValue()).substr(6); checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Features, Triple); } else if (CPUArg) { CPUName = CPUArg->getValue(); checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple); } // Add CPU features for generic CPUs if (CPUName == "native") { llvm::StringMap<bool> HostFeatures; if (llvm::sys::getHostCPUFeatures(HostFeatures)) for (auto &F : HostFeatures) Features.push_back( Args.MakeArgString((F.second ? "+" : "-") + F.first())); } else if (!CPUName.empty()) { DecodeARMFeaturesFromCPU(D, CPUName, Features); } // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=. const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ); if (WaFPU) { if (FPUArg) D.Diag(clang::diag::warn_drv_unused_argument) << FPUArg->getAsString(Args); getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6), Features); } else if (FPUArg) { getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features); } // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=. const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ); if (WaHDiv) { if (HDivArg) D.Diag(clang::diag::warn_drv_unused_argument) << HDivArg->getAsString(Args); getARMHWDivFeatures(D, WaHDiv, Args, StringRef(WaHDiv->getValue()).substr(8), Features); } else if (HDivArg) getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features); // Setting -msoft-float effectively disables NEON because of the GCC // implementation, although the same isn't true of VFP or VFP3. if (ABI == arm::FloatABI::Soft) { Features.push_back("-neon"); // Also need to explicitly disable features which imply NEON. Features.push_back("-crypto"); } // En/disable crc code generation. if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { if (A->getOption().matches(options::OPT_mcrc)) Features.push_back("+crc"); else Features.push_back("-crc"); } // Look for the last occurrence of -mlong-calls or -mno-long-calls. If // neither options are specified, see if we are compiling for kernel/kext and // decide whether to pass "+long-calls" based on the OS and its version. if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) { if (A->getOption().matches(options::OPT_mlong_calls)) Features.push_back("+long-calls"); } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) && !Triple.isWatchOS()) { Features.push_back("+long-calls"); } // Generate execute-only output (no data access to code sections). // This only makes sense for the compiler, not for the assembler. if (!ForAS) { // Supported only on ARMv6T2 and ARMv7 and above. // Cannot be combined with -mno-movt or -mlong-calls if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) { if (A->getOption().matches(options::OPT_mexecute_only)) { if (getARMSubArchVersionNumber(Triple) < 7 && llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2) D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName(); else if (Arg *B = Args.getLastArg(options::OPT_mno_movt)) D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); // Long calls create constant pool entries and have not yet been fixed up // to play nicely with execute-only. Hence, they cannot be used in // execute-only code for now else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) { if (B->getOption().matches(options::OPT_mlong_calls)) D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); } Features.push_back("+execute-only"); } } } // Kernel code has more strict alignment requirements. if (KernelOrKext) Features.push_back("+strict-align"); else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) { if (A->getOption().matches(options::OPT_munaligned_access)) { // No v6M core supports unaligned memory access (v6M ARM ARM A3.2). if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) D.Diag(diag::err_target_unsupported_unaligned) << "v6m"; // v8M Baseline follows on from v6M, so doesn't support unaligned memory // access either. else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline) D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base"; } else Features.push_back("+strict-align"); } else { // Assume pre-ARMv6 doesn't support unaligned accesses. // // ARMv6 may or may not support unaligned accesses depending on the // SCTLR.U bit, which is architecture-specific. We assume ARMv6 // Darwin and NetBSD targets support unaligned accesses, and others don't. // // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit // which raises an alignment fault on unaligned accesses. Linux // defaults this bit to 0 and handles it as a system-wide (not // per-process) setting. It is therefore safe to assume that ARMv7+ // Linux targets support unaligned accesses. The same goes for NaCl. // // The above behavior is consistent with GCC. int VersionNum = getARMSubArchVersionNumber(Triple); if (Triple.isOSDarwin() || Triple.isOSNetBSD()) { if (VersionNum < 6 || Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) Features.push_back("+strict-align"); } else if (Triple.isOSLinux() || Triple.isOSNaCl()) { if (VersionNum < 7) Features.push_back("+strict-align"); } else Features.push_back("+strict-align"); } // llvm does not support reserving registers in general. There is support // for reserving r9 on ARM though (defined as a platform-specific register // in ARM EABI). if (Args.hasArg(options::OPT_ffixed_r9)) Features.push_back("+reserve-r9"); // The kext linker doesn't know how to deal with movw/movt. if (KernelOrKext || Args.hasArg(options::OPT_mno_movt)) Features.push_back("+no-movt"); if (Args.hasArg(options::OPT_mno_neg_immediates)) Features.push_back("+no-neg-immediates"); }