diff options
Diffstat (limited to 'lib/Driver/ToolChain.cpp')
-rw-r--r-- | lib/Driver/ToolChain.cpp | 212 |
1 files changed, 179 insertions, 33 deletions
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index 12afb18c23a88..f96a1182e3cab 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -27,6 +27,8 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/TargetParser.h" #include "llvm/Support/TargetRegistry.h" @@ -79,6 +81,12 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, getFilePaths().push_back(CandidateLibPath); } +void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) { + Triple.setEnvironment(Env); + if (EffectiveTriple != llvm::Triple()) + EffectiveTriple.setEnvironment(Env); +} + ToolChain::~ToolChain() { } @@ -90,6 +98,10 @@ bool ToolChain::useIntegratedAs() const { IsIntegratedAssemblerDefault()); } +bool ToolChain::useRelaxRelocations() const { + return ENABLE_X86_RELAX_RELOCATIONS; +} + const SanitizerArgs& ToolChain::getSanitizerArgs() const { if (!SanitizerArguments.get()) SanitizerArguments.reset(new SanitizerArgs(*this, Args)); @@ -108,7 +120,7 @@ struct DriverSuffix { const char *ModeFlag; }; -const DriverSuffix *FindDriverSuffix(StringRef ProgName) { +const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) { // A list of known driver suffixes. Suffixes are compared against the // program name in order. If there is a match, the frontend type is updated as // necessary by applying the ModeFlag. @@ -127,9 +139,13 @@ const DriverSuffix *FindDriverSuffix(StringRef ProgName) { {"++", "--driver-mode=g++"}, }; - for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) - if (ProgName.endswith(DriverSuffixes[i].Suffix)) + for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) { + StringRef Suffix(DriverSuffixes[i].Suffix); + if (ProgName.endswith(Suffix)) { + Pos = ProgName.size() - Suffix.size(); return &DriverSuffixes[i]; + } + } return nullptr; } @@ -144,7 +160,7 @@ std::string normalizeProgramName(llvm::StringRef Argv0) { return ProgName; } -const DriverSuffix *parseDriverSuffix(StringRef ProgName) { +const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) { // Try to infer frontend type and default target from the program name by // comparing it against DriverSuffixes in order. @@ -152,47 +168,46 @@ const DriverSuffix *parseDriverSuffix(StringRef ProgName) { // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target // prefix "x86_64-linux". If such a target prefix is found, it may be // added via -target as implicit first argument. - const DriverSuffix *DS = FindDriverSuffix(ProgName); + const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos); if (!DS) { // Try again after stripping any trailing version number: // clang++3.5 -> clang++ ProgName = ProgName.rtrim("0123456789."); - DS = FindDriverSuffix(ProgName); + DS = FindDriverSuffix(ProgName, Pos); } if (!DS) { // Try again after stripping trailing -component. // clang++-tot -> clang++ ProgName = ProgName.slice(0, ProgName.rfind('-')); - DS = FindDriverSuffix(ProgName); + DS = FindDriverSuffix(ProgName, Pos); } return DS; } } // anonymous namespace -std::pair<std::string, std::string> +ParsedClangName ToolChain::getTargetAndModeFromProgramName(StringRef PN) { std::string ProgName = normalizeProgramName(PN); - const DriverSuffix *DS = parseDriverSuffix(ProgName); + size_t SuffixPos; + const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos); if (!DS) - return std::make_pair("", ""); - std::string ModeFlag = DS->ModeFlag == nullptr ? "" : DS->ModeFlag; + return ParsedClangName(); + size_t SuffixEnd = SuffixPos + strlen(DS->Suffix); - std::string::size_type LastComponent = - ProgName.rfind('-', ProgName.size() - strlen(DS->Suffix)); + size_t LastComponent = ProgName.rfind('-', SuffixPos); if (LastComponent == std::string::npos) - return std::make_pair("", ModeFlag); + return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag); + std::string ModeSuffix = ProgName.substr(LastComponent + 1, + SuffixEnd - LastComponent - 1); // Infer target from the prefix. StringRef Prefix(ProgName); Prefix = Prefix.slice(0, LastComponent); std::string IgnoredError; - std::string Target; - if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) { - Target = Prefix; - } - return std::make_pair(Target, ModeFlag); + bool IsRegistered = llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError); + return ParsedClangName{Prefix, ModeSuffix, DS->ModeFlag, IsRegistered}; } StringRef ToolChain::getDefaultUniversalArchName() const { @@ -212,6 +227,10 @@ StringRef ToolChain::getDefaultUniversalArchName() const { } } +std::string ToolChain::getInputFilename(const InputInfo &Input) const { + return Input.getFilename(); +} + bool ToolChain::IsUnwindTablesDefault(const ArgList &Args) const { return false; } @@ -292,15 +311,27 @@ static StringRef getArchNameForCompilerRTLib(const ToolChain &TC, const llvm::Triple &Triple = TC.getTriple(); bool IsWindows = Triple.isOSWindows(); - if (Triple.isWindowsMSVCEnvironment() && TC.getArch() == llvm::Triple::x86) - return "i386"; - if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb) return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows) ? "armhf" : "arm"; - return TC.getArchName(); + // For historic reasons, Android library is using i686 instead of i386. + if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid()) + return "i686"; + + return llvm::Triple::getArchTypeName(TC.getArch()); +} + +std::string ToolChain::getCompilerRTPath() const { + SmallString<128> Path(getDriver().ResourceDir); + if (Triple.isOSUnknown()) { + llvm::sys::path::append(Path, "lib"); + } else { + StringRef OSLibName = Triple.isOSFreeBSD() ? "freebsd" : getOS(); + llvm::sys::path::append(Path, "lib", OSLibName); + } + return Path.str(); } std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, @@ -315,9 +346,7 @@ std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, const char *Suffix = Shared ? (Triple.isOSWindows() ? ".dll" : ".so") : (IsITANMSVCWindows ? ".lib" : ".a"); - SmallString<128> Path(getDriver().ResourceDir); - StringRef OSLibName = Triple.isOSFreeBSD() ? "freebsd" : getOS(); - llvm::sys::path::append(Path, "lib", OSLibName); + SmallString<128> Path(getCompilerRTPath()); llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" + Arch + Env + Suffix); return Path.str(); @@ -381,7 +410,11 @@ std::string ToolChain::GetLinkerPath() const { // then use whatever the default system linker is. return GetProgramPath(getDefaultLinker()); } else { - llvm::SmallString<8> LinkerName("ld."); + llvm::SmallString<8> LinkerName; + if (Triple.isOSDarwin()) + LinkerName.append("ld64."); + else + LinkerName.append("ld."); LinkerName.append(UseLinker); std::string LinkerPath(GetProgramPath(LinkerName.c_str())); @@ -424,6 +457,13 @@ ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { VersionTuple()); } +llvm::ExceptionHandling +ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const { + if (Triple.isOSWindows() && Triple.getArch() != llvm::Triple::x86) + return llvm::ExceptionHandling::WinEH; + return llvm::ExceptionHandling::None; +} + bool ToolChain::isThreadModelSupported(const StringRef Model) const { if (Model == "single") { // FIXME: 'single' is only supported on ARM and WebAssembly so far. @@ -500,7 +540,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, : tools::arm::getARMTargetCPU(MCPU, MArch, Triple); StringRef Suffix = tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple); - bool IsMProfile = ARM::parseArchProfile(Suffix) == ARM::PK_M; + bool IsMProfile = ARM::parseArchProfile(Suffix) == ARM::ProfileKind::M; bool ThumbDefault = IsMProfile || (ARM::parseArchVersion(Suffix) == 7 && getTriple().isOSBinFormatMachO()); // FIXME: this is invalid for WindowsCE @@ -512,11 +552,42 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, else ArchName = "arm"; - // Assembly files should start in ARM mode, unless arch is M-profile. - // Windows is always thumb. - if ((InputType != types::TY_PP_Asm && Args.hasFlag(options::OPT_mthumb, - options::OPT_mno_thumb, ThumbDefault)) || IsMProfile || - getTriple().isOSWindows()) { + // Check if ARM ISA was explicitly selected (using -mno-thumb or -marm) for + // M-Class CPUs/architecture variants, which is not supported. + bool ARMModeRequested = !Args.hasFlag(options::OPT_mthumb, + options::OPT_mno_thumb, ThumbDefault); + if (IsMProfile && ARMModeRequested) { + if (!MCPU.empty()) + getDriver().Diag(diag::err_cpu_unsupported_isa) << CPU << "ARM"; + else + getDriver().Diag(diag::err_arch_unsupported_isa) + << tools::arm::getARMArch(MArch, getTriple()) << "ARM"; + } + + // Check to see if an explicit choice to use thumb has been made via + // -mthumb. For assembler files we must check for -mthumb in the options + // passed to the assember via -Wa or -Xassembler. + bool IsThumb = false; + if (InputType != types::TY_PP_Asm) + IsThumb = Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, + ThumbDefault); + else { + // Ideally we would check for these flags in + // CollectArgsForIntegratedAssembler but we can't change the ArchName at + // that point. There is no assembler equivalent of -mno-thumb, -marm, or + // -mno-arm. + for (const Arg *A : + Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { + for (StringRef Value : A->getValues()) { + if (Value == "-mthumb") + IsThumb = true; + } + } + } + // Assembly files should start in ARM mode, unless arch is M-profile, or + // -mthumb has been passed explicitly to the assembler. Windows is always + // thumb. + if (IsThumb || IsMProfile || getTriple().isOSWindows()) { if (IsBigEndian) ArchName = "thumbeb"; else @@ -643,8 +714,16 @@ void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ); } +bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const { + return getDriver().CCCIsCXX() && + !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, + options::OPT_nostdlibxx); +} + void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { + assert(!Args.hasArg(options::OPT_nostdlibxx) && + "should not have called this"); CXXStdlibType Type = GetCXXStdlibType(Args); switch (Type) { @@ -770,3 +849,70 @@ ToolChain::computeMSVCVersion(const Driver *D, return VersionTuple(); } + +llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs( + const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost, + SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const { + DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); + const OptTable &Opts = getDriver().getOpts(); + bool Modified = false; + + // Handle -Xopenmp-target flags + for (Arg *A : Args) { + // Exclude flags which may only apply to the host toolchain. + // Do not exclude flags when the host triple (AuxTriple) + // matches the current toolchain triple. If it is not present + // at all, target and host share a toolchain. + if (A->getOption().matches(options::OPT_m_Group)) { + if (SameTripleAsHost) + DAL->append(A); + else + Modified = true; + continue; + } + + unsigned Index; + unsigned Prev; + bool XOpenMPTargetNoTriple = + A->getOption().matches(options::OPT_Xopenmp_target); + + if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) { + // Passing device args: -Xopenmp-target=<triple> -opt=val. + if (A->getValue(0) == getTripleString()) + Index = Args.getBaseArgs().MakeIndex(A->getValue(1)); + else + continue; + } else if (XOpenMPTargetNoTriple) { + // Passing device args: -Xopenmp-target -opt=val. + Index = Args.getBaseArgs().MakeIndex(A->getValue(0)); + } else { + DAL->append(A); + continue; + } + + // Parse the argument to -Xopenmp-target. + Prev = Index; + std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index)); + if (!XOpenMPTargetArg || Index > Prev + 1) { + getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args) + << A->getAsString(Args); + continue; + } + if (XOpenMPTargetNoTriple && XOpenMPTargetArg && + Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) { + getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple); + continue; + } + XOpenMPTargetArg->setBaseArg(A); + A = XOpenMPTargetArg.release(); + AllocatedArgs.push_back(A); + DAL->append(A); + Modified = true; + } + + if (Modified) + return DAL; + + delete DAL; + return nullptr; +} |