diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 13:34:49 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 13:34:49 +0000 | 
| commit | 0623d7483df5fc17b32ba7bc5cb9c7beebf6db9c (patch) | |
| tree | 28726ef2038e86121e353aabf52297b35a48efa2 /contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp | |
| parent | 7d523365ff1a3cc95bc058b33102500f61e8166d (diff) | |
| parent | 45b533945f0851ec234ca846e1af5ee1e4df0b6e (diff) | |
Notes
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 d40bb951e50a..e30177c29e09 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 {}  | 
