diff options
Diffstat (limited to 'clang/lib/Driver/ToolChain.cpp')
-rw-r--r-- | clang/lib/Driver/ToolChain.cpp | 238 |
1 files changed, 183 insertions, 55 deletions
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 3ebbd30195b31..b8c12fc9241a6 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -68,8 +68,7 @@ static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args, } // -frtti is default, except for the PS4 CPU. - return (Triple.isPS4CPU() || Triple.isNVPTX()) ? ToolChain::RM_Disabled - : ToolChain::RM_Enabled; + return (Triple.isPS4CPU()) ? ToolChain::RM_Disabled : ToolChain::RM_Enabled; } ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, @@ -169,7 +168,7 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) { /// Normalize the program name from argv[0] by stripping the file extension if /// present and lower-casing the string on Windows. static std::string normalizeProgramName(llvm::StringRef Argv0) { - std::string ProgName = llvm::sys::path::stem(Argv0); + std::string ProgName = std::string(llvm::sys::path::stem(Argv0)); #ifdef _WIN32 // Transform to lowercase for case insensitive file systems. std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), ::tolower); @@ -222,16 +221,21 @@ ToolChain::getTargetAndModeFromProgramName(StringRef PN) { StringRef Prefix(ProgName); Prefix = Prefix.slice(0, LastComponent); std::string IgnoredError; - bool IsRegistered = llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError); - return ParsedClangName{Prefix, ModeSuffix, DS->ModeFlag, IsRegistered}; + bool IsRegistered = + llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError); + return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag, + IsRegistered}; } 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 - // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the - // only interesting special case is powerpc. + // an inverse of the darwin::getArchTypeForDarwinArchName() function. switch (Triple.getArch()) { + case llvm::Triple::aarch64: + return "arm64"; + case llvm::Triple::aarch64_32: + return "arm64_32"; case llvm::Triple::ppc: return "ppc"; case llvm::Triple::ppc64: @@ -271,6 +275,10 @@ Tool *ToolChain::buildLinker() const { llvm_unreachable("Linking is not supported by this toolchain"); } +Tool *ToolChain::buildStaticLibTool() const { + llvm_unreachable("Creating static lib is not supported by this toolchain"); +} + Tool *ToolChain::getAssemble() const { if (!Assemble) Assemble.reset(buildAssembler()); @@ -289,6 +297,12 @@ Tool *ToolChain::getLink() const { return Link.get(); } +Tool *ToolChain::getStaticLibTool() const { + if (!StaticLibTool) + StaticLibTool.reset(buildStaticLibTool()); + return StaticLibTool.get(); +} + Tool *ToolChain::getIfsMerge() const { if (!IfsMerge) IfsMerge.reset(new tools::ifstool::Merger(*this)); @@ -318,6 +332,9 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::LinkJobClass: return getLink(); + case Action::StaticLibJobClass: + return getStaticLibTool(); + case Action::InputClass: case Action::BindArchClass: case Action::OffloadClass: @@ -386,11 +403,12 @@ std::string ToolChain::getCompilerRTPath() const { } else { llvm::sys::path::append(Path, "lib", getOSLibName()); } - return Path.str(); + return std::string(Path.str()); } -std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, - FileType Type) const { +std::string ToolChain::getCompilerRTBasename(const ArgList &Args, + StringRef Component, FileType Type, + bool AddArch) const { const llvm::Triple &TT = getTriple(); bool IsITANMSVCWindows = TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment(); @@ -412,19 +430,33 @@ std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, break; } + std::string ArchAndEnv; + if (AddArch) { + StringRef Arch = getArchNameForCompilerRTLib(*this, Args); + const char *Env = TT.isAndroid() ? "-android" : ""; + ArchAndEnv = ("-" + Arch + Env).str(); + } + return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str(); +} + +std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, + FileType Type) const { + // Check for runtime files in the new layout without the architecture first. + std::string CRTBasename = + getCompilerRTBasename(Args, Component, Type, /*AddArch=*/false); for (const auto &LibPath : getLibraryPaths()) { SmallString<128> P(LibPath); - llvm::sys::path::append(P, Prefix + Twine("clang_rt.") + Component + Suffix); + llvm::sys::path::append(P, CRTBasename); if (getVFS().exists(P)) - return P.str(); + return std::string(P.str()); } - StringRef Arch = getArchNameForCompilerRTLib(*this, Args); - const char *Env = TT.isAndroid() ? "-android" : ""; + // Fall back to the old expected compiler-rt name if the new one does not + // exist. + CRTBasename = getCompilerRTBasename(Args, Component, Type, /*AddArch=*/true); SmallString<128> Path(getCompilerRTPath()); - llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" + - Arch + Env + Suffix); - return Path.str(); + llvm::sys::path::append(Path, CRTBasename); + return std::string(Path.str()); } const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args, @@ -441,13 +473,13 @@ Optional<std::string> ToolChain::getRuntimePath() const { P.assign(D.ResourceDir); llvm::sys::path::append(P, "lib", D.getTargetTriple()); if (getVFS().exists(P)) - return llvm::Optional<std::string>(P.str()); + return llvm::Optional<std::string>(std::string(P.str())); // Second try the normalized triple. P.assign(D.ResourceDir); llvm::sys::path::append(P, "lib", Triple.str()); if (getVFS().exists(P)) - return llvm::Optional<std::string>(P.str()); + return llvm::Optional<std::string>(std::string(P.str())); return None; } @@ -459,13 +491,13 @@ Optional<std::string> ToolChain::getCXXStdlibPath() const { P.assign(D.Dir); llvm::sys::path::append(P, "..", "lib", D.getTargetTriple(), "c++"); if (getVFS().exists(P)) - return llvm::Optional<std::string>(P.str()); + return llvm::Optional<std::string>(std::string(P.str())); // Second try the normalized triple. P.assign(D.Dir); llvm::sys::path::append(P, "..", "lib", Triple.str(), "c++"); if (getVFS().exists(P)) - return llvm::Optional<std::string>(P.str()); + return llvm::Optional<std::string>(std::string(P.str())); return None; } @@ -474,31 +506,27 @@ std::string ToolChain::getArchSpecificLibPath() const { SmallString<128> Path(getDriver().ResourceDir); llvm::sys::path::append(Path, "lib", getOSLibName(), llvm::Triple::getArchTypeName(getArch())); - return Path.str(); + return std::string(Path.str()); } bool ToolChain::needsProfileRT(const ArgList &Args) { if (Args.hasArg(options::OPT_noprofilelib)) return false; - if (needsGCovInstrumentation(Args) || - Args.hasArg(options::OPT_fprofile_generate) || - Args.hasArg(options::OPT_fprofile_generate_EQ) || - Args.hasArg(options::OPT_fcs_profile_generate) || - Args.hasArg(options::OPT_fcs_profile_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_forder_file_instrumentation)) - return true; - - return false; + return Args.hasArg(options::OPT_fprofile_generate) || + Args.hasArg(options::OPT_fprofile_generate_EQ) || + Args.hasArg(options::OPT_fcs_profile_generate) || + Args.hasArg(options::OPT_fcs_profile_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_forder_file_instrumentation); } bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) { - return Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, - false) || - Args.hasArg(options::OPT_coverage); + return Args.hasArg(options::OPT_coverage) || + Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, + false); } Tool *ToolChain::SelectTool(const JobAction &JA) const { @@ -526,7 +554,7 @@ std::string ToolChain::GetLinkerPath() const { // If we're passed what looks like an absolute path, don't attempt to // second-guess that. if (llvm::sys::fs::can_execute(UseLinker)) - return UseLinker; + return std::string(UseLinker); } else if (UseLinker.empty() || UseLinker == "ld") { // If we're passed -fuse-ld= with no argument, or with the argument ld, // then use whatever the default system linker is. @@ -550,6 +578,11 @@ std::string ToolChain::GetLinkerPath() const { return GetProgramPath(getDefaultLinker()); } +std::string ToolChain::GetStaticLibToolPath() const { + // TODO: Add support for static lib archiving on Windows + return GetProgramPath("llvm-ar"); +} + types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const { types::ID id = types::lookupTypeForExtension(Ext); @@ -735,6 +768,10 @@ std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, return ComputeLLVMTriple(Args, InputType); } +std::string ToolChain::computeSysRoot() const { + return D.SysRoot; +} + void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { // Each toolchain should provide the appropriate include flags. @@ -748,7 +785,8 @@ void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {} void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const { - if (!needsProfileRT(Args)) return; + if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args)) + return; CmdArgs.push_back(getCompilerRTArgString(Args, "profile")); } @@ -916,28 +954,35 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args, CmdArgs.push_back("-lcc_kext"); } -bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args, - ArgStringList &CmdArgs) const { +bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args, + std::string &Path) const { // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed // (to keep the linker options consistent with gcc and clang itself). if (!isOptimizationLevelFast(Args)) { // Check if -ffast-math or -funsafe-math. Arg *A = - Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math, - options::OPT_funsafe_math_optimizations, - options::OPT_fno_unsafe_math_optimizations); + Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations); if (!A || A->getOption().getID() == options::OPT_fno_fast_math || A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations) return false; } // If crtfastmath.o exists add it to the arguments. - std::string Path = GetFilePath("crtfastmath.o"); - if (Path == "crtfastmath.o") // Not found. - return false; + Path = GetFilePath("crtfastmath.o"); + return (Path != "crtfastmath.o"); // Not found. +} - CmdArgs.push_back(Args.MakeArgString(Path)); - return true; +bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args, + ArgStringList &CmdArgs) const { + std::string Path; + if (isFastMathRuntimeAvailable(Args, Path)) { + CmdArgs.push_back(Args.MakeArgString(Path)); + return true; + } + + return false; } SanitizerMask ToolChain::getSupportedSanitizers() const { @@ -955,15 +1000,12 @@ SanitizerMask ToolChain::getSupportedSanitizers() const { if (getTriple().getArch() == llvm::Triple::x86 || getTriple().getArch() == llvm::Triple::x86_64 || getTriple().getArch() == llvm::Triple::arm || - getTriple().getArch() == llvm::Triple::aarch64 || getTriple().getArch() == llvm::Triple::wasm32 || - getTriple().getArch() == llvm::Triple::wasm64) + getTriple().getArch() == llvm::Triple::wasm64 || getTriple().isAArch64()) Res |= SanitizerKind::CFIICall; - if (getTriple().getArch() == llvm::Triple::x86_64 || - getTriple().getArch() == llvm::Triple::aarch64) + if (getTriple().getArch() == llvm::Triple::x86_64 || getTriple().isAArch64()) Res |= SanitizerKind::ShadowCallStack; - if (getTriple().getArch() == llvm::Triple::aarch64 || - getTriple().getArch() == llvm::Triple::aarch64_be) + if (getTriple().isAArch64()) Res |= SanitizerKind::MemTag; return Res; } @@ -971,6 +1013,9 @@ SanitizerMask ToolChain::getSupportedSanitizers() const { void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const {} +void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const {} + void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const {} @@ -1094,3 +1139,86 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs( delete DAL; return nullptr; } + +// TODO: Currently argument values separated by space e.g. +// -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be +// fixed. +void ToolChain::TranslateXarchArgs( + const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A, + llvm::opt::DerivedArgList *DAL, + SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const { + const OptTable &Opts = getDriver().getOpts(); + unsigned ValuePos = 1; + if (A->getOption().matches(options::OPT_Xarch_device) || + A->getOption().matches(options::OPT_Xarch_host)) + ValuePos = 0; + + unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos)); + unsigned Prev = Index; + std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index)); + + // If the argument parsing failed or more than one argument was + // consumed, the -Xarch_ argument's parameter tried to consume + // extra arguments. Emit an error and ignore. + // + // We also want to disallow any options which would alter the + // driver behavior; that isn't going to work in our model. We + // use isDriverOption() as an approximation, although things + // like -O4 are going to slip through. + if (!XarchArg || Index > Prev + 1) { + getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args) + << A->getAsString(Args); + return; + } else if (XarchArg->getOption().hasFlag(options::DriverOption)) { + getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver) + << A->getAsString(Args); + return; + } + XarchArg->setBaseArg(A); + A = XarchArg.release(); + if (!AllocatedArgs) + DAL->AddSynthesizedArg(A); + else + AllocatedArgs->push_back(A); +} + +llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs( + const llvm::opt::DerivedArgList &Args, StringRef BoundArch, + Action::OffloadKind OFK, + SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const { + DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); + bool Modified = false; + + bool IsGPU = OFK == Action::OFK_Cuda || OFK == Action::OFK_HIP; + for (Arg *A : Args) { + bool NeedTrans = false; + bool Skip = false; + if (A->getOption().matches(options::OPT_Xarch_device)) { + NeedTrans = IsGPU; + Skip = !IsGPU; + } else if (A->getOption().matches(options::OPT_Xarch_host)) { + NeedTrans = !IsGPU; + Skip = IsGPU; + } else if (A->getOption().matches(options::OPT_Xarch__) && IsGPU) { + // Do not translate -Xarch_ options for non CUDA/HIP toolchain since + // they may need special translation. + // Skip this argument unless the architecture matches BoundArch + if (BoundArch.empty() || A->getValue(0) != BoundArch) + Skip = true; + else + NeedTrans = true; + } + if (NeedTrans || Skip) + Modified = true; + if (NeedTrans) + TranslateXarchArgs(Args, A, DAL, AllocatedArgs); + if (!Skip) + DAL->append(A); + } + + if (Modified) + return DAL; + + delete DAL; + return nullptr; +} |