diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp | 239 |
1 files changed, 207 insertions, 32 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp index d40bb95..e30177c 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp @@ -22,8 +22,13 @@ #include "llvm/Option/Option.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetParser.h" + using namespace clang::driver; +using namespace clang::driver::tools; using namespace clang; +using namespace llvm; using namespace llvm::opt; static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) { @@ -72,9 +77,7 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, ToolChain::~ToolChain() { } -const Driver &ToolChain::getDriver() const { - return D; -} +vfs::FileSystem &ToolChain::getVFS() const { return getDriver().getVFS(); } bool ToolChain::useIntegratedAs() const { return Args.hasFlag(options::OPT_fintegrated_as, @@ -88,6 +91,105 @@ const SanitizerArgs& ToolChain::getSanitizerArgs() const { return *SanitizerArguments.get(); } +namespace { +struct DriverSuffix { + const char *Suffix; + const char *ModeFlag; +}; + +const DriverSuffix *FindDriverSuffix(StringRef ProgName) { + // 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. + static const DriverSuffix DriverSuffixes[] = { + {"clang", nullptr}, + {"clang++", "--driver-mode=g++"}, + {"clang-c++", "--driver-mode=g++"}, +#ifdef __FreeBSD__ + {"clang-CC", "--driver-mode=g++"}, +#endif + {"clang-cc", nullptr}, + {"clang-cpp", "--driver-mode=cpp"}, + {"clang-g++", "--driver-mode=g++"}, + {"clang-gcc", nullptr}, + {"clang-cl", "--driver-mode=cl"}, +#ifdef __FreeBSD__ + {"CC", "--driver-mode=g++"}, +#endif + {"cc", nullptr}, + {"cpp", "--driver-mode=cpp"}, + {"cl", "--driver-mode=cl"}, + {"++", "--driver-mode=g++"}, + }; + + for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) + if (ProgName.endswith(DriverSuffixes[i].Suffix)) + return &DriverSuffixes[i]; + return nullptr; +} + +/// Normalize the program name from argv[0] by stripping the file extension if +/// present and lower-casing the string on Windows. +std::string normalizeProgramName(llvm::StringRef Argv0) { + std::string ProgName = llvm::sys::path::stem(Argv0); +#ifdef LLVM_ON_WIN32 + // Transform to lowercase for case insensitive file systems. + std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), ::tolower); +#endif + return ProgName; +} + +const DriverSuffix *parseDriverSuffix(StringRef ProgName) { + // Try to infer frontend type and default target from the program name by + // comparing it against DriverSuffixes in order. + + // If there is a match, the function tries to identify a target as prefix. + // 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); + + if (!DS) { + // Try again after stripping any trailing version number: + // clang++3.5 -> clang++ + ProgName = ProgName.rtrim("0123456789."); + DS = FindDriverSuffix(ProgName); + } + + if (!DS) { + // Try again after stripping trailing -component. + // clang++-tot -> clang++ + ProgName = ProgName.slice(0, ProgName.rfind('-')); + DS = FindDriverSuffix(ProgName); + } + return DS; +} +} // anonymous namespace + +std::pair<std::string, std::string> +ToolChain::getTargetAndModeFromProgramName(StringRef PN) { + std::string ProgName = normalizeProgramName(PN); + const DriverSuffix *DS = parseDriverSuffix(ProgName); + if (!DS) + return std::make_pair("", ""); + std::string ModeFlag = DS->ModeFlag == nullptr ? "" : DS->ModeFlag; + + std::string::size_type LastComponent = + ProgName.rfind('-', ProgName.size() - strlen(DS->Suffix)); + if (LastComponent == std::string::npos) + return std::make_pair("", ModeFlag); + + // 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); +} + StringRef ToolChain::getDefaultUniversalArchName() const { // In universal driver terms, the arch name accepted by -arch isn't exactly // the same as the ones that appear in the triple. Roughly speaking, this is @@ -171,9 +273,64 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { llvm_unreachable("Invalid tool kind."); } +static StringRef getArchNameForCompilerRTLib(const ToolChain &TC, + const ArgList &Args) { + 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(); +} + +std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, + bool Shared) const { + const llvm::Triple &TT = getTriple(); + const char *Env = TT.isAndroid() ? "-android" : ""; + bool IsITANMSVCWindows = + TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment(); + + StringRef Arch = getArchNameForCompilerRTLib(*this, Args); + const char *Prefix = IsITANMSVCWindows ? "" : "lib"; + 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); + llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" + + Arch + Env + Suffix); + return Path.str(); +} + +const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args, + StringRef Component, + bool Shared) const { + return Args.MakeArgString(getCompilerRT(Args, Component, Shared)); +} + +bool ToolChain::needsProfileRT(const ArgList &Args) { + if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, + false) || + Args.hasArg(options::OPT_fprofile_generate) || + Args.hasArg(options::OPT_fprofile_generate_EQ) || + Args.hasArg(options::OPT_fprofile_instr_generate) || + Args.hasArg(options::OPT_fprofile_instr_generate_EQ) || + Args.hasArg(options::OPT_fcreate_profile) || + Args.hasArg(options::OPT_coverage)) + return true; + + return false; +} + Tool *ToolChain::SelectTool(const JobAction &JA) const { - if (getDriver().ShouldUseClangCompiler(JA)) - return getClang(); + if (getDriver().ShouldUseClangCompiler(JA)) return getClang(); Action::ActionClass AC = JA.getKind(); if (AC == Action::AssembleJobClass && useIntegratedAs()) return getClangAs(); @@ -182,7 +339,6 @@ Tool *ToolChain::SelectTool(const JobAction &JA) const { std::string ToolChain::GetFilePath(const char *Name) const { return D.GetFilePath(Name, *this); - } std::string ToolChain::GetProgramPath(const char *Name) const { @@ -209,10 +365,9 @@ std::string ToolChain::GetLinkerPath() const { return ""; } - return GetProgramPath("ld"); + return GetProgramPath(DefaultLinker); } - types::ID ToolChain::LookupTypeForExtension(const char *Ext) const { return types::lookupTypeForExtension(Ext); } @@ -244,11 +399,13 @@ ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { bool ToolChain::isThreadModelSupported(const StringRef Model) const { if (Model == "single") { - // FIXME: 'single' is only supported on ARM so far. + // FIXME: 'single' is only supported on ARM and WebAssembly so far. return Triple.getArch() == llvm::Triple::arm || Triple.getArch() == llvm::Triple::armeb || Triple.getArch() == llvm::Triple::thumb || - Triple.getArch() == llvm::Triple::thumbeb; + Triple.getArch() == llvm::Triple::thumbeb || + Triple.getArch() == llvm::Triple::wasm32 || + Triple.getArch() == llvm::Triple::wasm64; } else if (Model == "posix") return true; @@ -310,15 +467,15 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, MCPU = A->getValue(); if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) MArch = A->getValue(); - std::string CPU = Triple.isOSBinFormatMachO() - ? tools::arm::getARMCPUForMArch(MArch, Triple) - : tools::arm::getARMTargetCPU(MCPU, MArch, Triple); - StringRef Suffix = - tools::arm::getLLVMArchSuffixForARM(CPU, - tools::arm::getARMArch(MArch, Triple)); - bool ThumbDefault = Suffix.startswith("v6m") || Suffix.startswith("v7m") || - Suffix.startswith("v7em") || - (Suffix.startswith("v7") && getTriple().isOSBinFormatMachO()); + std::string CPU = + Triple.isOSBinFormatMachO() + ? tools::arm::getARMCPUForMArch(MArch, Triple).str() + : tools::arm::getARMTargetCPU(MCPU, MArch, Triple); + StringRef Suffix = + tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple); + bool IsMProfile = ARM::parseArchProfile(Suffix) == ARM::PK_M; + bool ThumbDefault = IsMProfile || (ARM::parseArchVersion(Suffix) == 7 && + getTriple().isOSBinFormatMachO()); // FIXME: this is invalid for WindowsCE if (getTriple().isOSWindows()) ThumbDefault = true; @@ -328,10 +485,9 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, else ArchName = "arm"; - // Assembly files should start in ARM mode. - if (InputType != types::TY_PP_Asm && - Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault)) - { + // Assembly files should start in ARM mode, unless arch is M-profile. + if ((InputType != types::TY_PP_Asm && Args.hasFlag(options::OPT_mthumb, + options::OPT_mno_thumb, ThumbDefault)) || IsMProfile) { if (IsBigEndian) ArchName = "thumbeb"; else @@ -344,7 +500,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, } } -std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, +std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, types::ID InputType) const { return ComputeLLVMTriple(Args, InputType); } @@ -360,9 +516,16 @@ void ToolChain::addClangTargetOptions(const ArgList &DriverArgs, void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {} +void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const { + if (!needsProfileRT(Args)) return; + + CmdArgs.push_back(getCompilerRTArgString(Args, "profile")); + return; +} + ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( - const ArgList &Args) const -{ + const ArgList &Args) const { if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) { StringRef Value = A->getValue(); if (Value == "compiler-rt") @@ -424,10 +587,9 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs, /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs, ArgStringList &CC1Args, ArrayRef<StringRef> Paths) { - for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end(); - I != E; ++I) { + for (StringRef Path : Paths) { CC1Args.push_back("-internal-isystem"); - CC1Args.push_back(DriverArgs.MakeArgString(*I)); + CC1Args.push_back(DriverArgs.MakeArgString(Path)); } } @@ -460,6 +622,13 @@ void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, } } +void ToolChain::AddFilePathLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + for (const auto &LibPath : getFilePaths()) + if(LibPath.length() > 0) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); +} + void ToolChain::AddCCKextLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { CmdArgs.push_back("-lcc_kext"); @@ -491,9 +660,15 @@ bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args, SanitizerMask ToolChain::getSupportedSanitizers() const { // Return sanitizers which don't require runtime support and are not - // platform or architecture-dependent. + // platform dependent. using namespace SanitizerKind; - return (Undefined & ~Vptr & ~Function) | CFI | CFICastStrict | - UnsignedIntegerOverflow | LocalBounds; + SanitizerMask Res = (Undefined & ~Vptr & ~Function) | (CFI & ~CFIICall) | + CFICastStrict | UnsignedIntegerOverflow | LocalBounds; + if (getTriple().getArch() == llvm::Triple::x86 || + getTriple().getArch() == llvm::Triple::x86_64) + Res |= CFIICall; + return Res; } +void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const {} |