diff options
Diffstat (limited to 'lib/Driver/ToolChains/Clang.cpp')
-rw-r--r-- | lib/Driver/ToolChains/Clang.cpp | 618 |
1 files changed, 354 insertions, 264 deletions
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index cb861f27aeda..55d631733add 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -22,6 +22,7 @@ #include "InputInfo.h" #include "PS4CPU.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" @@ -301,95 +302,6 @@ static void ParseMPreferVectorWidth(const Driver &D, const ArgList &Args, } } -static void getWebAssemblyTargetFeatures(const ArgList &Args, - std::vector<StringRef> &Features) { - handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); -} - -static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, - const ArgList &Args, ArgStringList &CmdArgs, - bool ForAS) { - const Driver &D = TC.getDriver(); - std::vector<StringRef> Features; - switch (Triple.getArch()) { - default: - break; - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - mips::getMIPSTargetFeatures(D, Triple, Args, Features); - break; - - case llvm::Triple::arm: - case llvm::Triple::armeb: - case llvm::Triple::thumb: - case llvm::Triple::thumbeb: - arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS); - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::ppc64le: - ppc::getPPCTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::riscv32: - case llvm::Triple::riscv64: - riscv::getRISCVTargetFeatures(D, Args, Features); - break; - case llvm::Triple::systemz: - systemz::getSystemZTargetFeatures(Args, Features); - break; - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_be: - aarch64::getAArch64TargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - x86::getX86TargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::hexagon: - hexagon::getHexagonTargetFeatures(D, Args, Features); - break; - case llvm::Triple::wasm32: - case llvm::Triple::wasm64: - getWebAssemblyTargetFeatures(Args, Features); - break; - case llvm::Triple::sparc: - case llvm::Triple::sparcel: - case llvm::Triple::sparcv9: - sparc::getSparcTargetFeatures(D, Args, Features); - break; - case llvm::Triple::r600: - case llvm::Triple::amdgcn: - amdgpu::getAMDGPUTargetFeatures(D, Args, Features); - break; - case llvm::Triple::msp430: - msp430::getMSP430TargetFeatures(D, Args, Features); - } - - // Find the last of each feature. - llvm::StringMap<unsigned> LastOpt; - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - StringRef Name = Features[I]; - assert(Name[0] == '-' || Name[0] == '+'); - LastOpt[Name.drop_front(1)] = I; - } - - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - // If this feature was overridden, ignore it. - StringRef Name = Features[I]; - llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name.drop_front(1)); - assert(LastI != LastOpt.end()); - unsigned Last = LastI->second; - if (Last != I) - continue; - - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back(Name.data()); - } -} - static bool shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime, const llvm::Triple &Triple) { @@ -501,8 +413,6 @@ static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) { return codegenoptions::LimitedDebugInfo; } -enum class FramePointerKind { None, NonLeaf, All }; - static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) { switch (Triple.getArch()){ default: @@ -579,22 +489,33 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args, return true; } -static FramePointerKind getFramePointerKind(const ArgList &Args, - const llvm::Triple &Triple) { +static CodeGenOptions::FramePointerKind +getFramePointerKind(const ArgList &Args, const llvm::Triple &Triple) { + // We have 4 states: + // + // 00) leaf retained, non-leaf retained + // 01) leaf retained, non-leaf omitted (this is invalid) + // 10) leaf omitted, non-leaf retained + // (what -momit-leaf-frame-pointer was designed for) + // 11) leaf omitted, non-leaf omitted + // + // "omit" options taking precedence over "no-omit" options is the only way + // to make 3 valid states representable Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer, options::OPT_fno_omit_frame_pointer); bool OmitFP = A && A->getOption().matches(options::OPT_fomit_frame_pointer); bool NoOmitFP = A && A->getOption().matches(options::OPT_fno_omit_frame_pointer); + bool KeepLeaf = + Args.hasFlag(options::OPT_momit_leaf_frame_pointer, + options::OPT_mno_omit_leaf_frame_pointer, Triple.isPS4CPU()); if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) || (!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) { - if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer, - options::OPT_mno_omit_leaf_frame_pointer, - Triple.isPS4CPU())) - return FramePointerKind::NonLeaf; - return FramePointerKind::All; + if (KeepLeaf) + return CodeGenOptions::FramePointerKind::NonLeaf; + return CodeGenOptions::FramePointerKind::All; } - return FramePointerKind::None; + return CodeGenOptions::FramePointerKind::None; } /// Add a CC1 option to specify the debug compilation directory. @@ -821,12 +742,14 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, } } - if (Args.hasArg(options::OPT_ftest_coverage) || - Args.hasArg(options::OPT_coverage)) + bool EmitCovNotes = Args.hasArg(options::OPT_ftest_coverage) || + Args.hasArg(options::OPT_coverage); + bool EmitCovData = Args.hasFlag(options::OPT_fprofile_arcs, + options::OPT_fno_profile_arcs, false) || + Args.hasArg(options::OPT_coverage); + if (EmitCovNotes) CmdArgs.push_back("-femit-coverage-notes"); - if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, - false) || - Args.hasArg(options::OPT_coverage)) + if (EmitCovData) CmdArgs.push_back("-femit-coverage-data"); if (Args.hasFlag(options::OPT_fcoverage_mapping, @@ -862,35 +785,43 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-filter-files=" + v))); } - if (C.getArgs().hasArg(options::OPT_c) || - C.getArgs().hasArg(options::OPT_S)) { - if (Output.isFilename()) { - CmdArgs.push_back("-coverage-notes-file"); - SmallString<128> OutputFilename; - if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) - OutputFilename = FinalOutput->getValue(); - else - OutputFilename = llvm::sys::path::filename(Output.getBaseInput()); - SmallString<128> CoverageFilename = OutputFilename; - if (llvm::sys::path::is_relative(CoverageFilename)) - (void)D.getVFS().makeAbsolute(CoverageFilename); - llvm::sys::path::replace_extension(CoverageFilename, "gcno"); - CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); - - // Leave -fprofile-dir= an unused argument unless .gcda emission is - // enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider - // the flag used. There is no -fno-profile-dir, so the user has no - // targeted way to suppress the warning. - if (Args.hasArg(options::OPT_fprofile_arcs) || - Args.hasArg(options::OPT_coverage)) { - CmdArgs.push_back("-coverage-data-file"); - if (Arg *FProfileDir = Args.getLastArg(options::OPT_fprofile_dir)) { - CoverageFilename = FProfileDir->getValue(); - llvm::sys::path::append(CoverageFilename, OutputFilename); - } - llvm::sys::path::replace_extension(CoverageFilename, "gcda"); - CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); + // Leave -fprofile-dir= an unused argument unless .gcda emission is + // enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider + // the flag used. There is no -fno-profile-dir, so the user has no + // targeted way to suppress the warning. + Arg *FProfileDir = nullptr; + if (Args.hasArg(options::OPT_fprofile_arcs) || + Args.hasArg(options::OPT_coverage)) + FProfileDir = Args.getLastArg(options::OPT_fprofile_dir); + + // Put the .gcno and .gcda files (if needed) next to the object file or + // bitcode file in the case of LTO. + // FIXME: There should be a simpler way to find the object file for this + // input, and this code probably does the wrong thing for commands that + // compile and link all at once. + if ((Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) && + (EmitCovNotes || EmitCovData) && Output.isFilename()) { + SmallString<128> OutputFilename; + if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) + OutputFilename = FinalOutput->getValue(); + else + OutputFilename = llvm::sys::path::filename(Output.getBaseInput()); + SmallString<128> CoverageFilename = OutputFilename; + if (llvm::sys::path::is_relative(CoverageFilename)) + (void)D.getVFS().makeAbsolute(CoverageFilename); + llvm::sys::path::replace_extension(CoverageFilename, "gcno"); + + CmdArgs.push_back("-coverage-notes-file"); + CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); + + if (EmitCovData) { + if (FProfileDir) { + CoverageFilename = FProfileDir->getValue(); + llvm::sys::path::append(CoverageFilename, OutputFilename); } + llvm::sys::path::replace_extension(CoverageFilename, "gcda"); + CmdArgs.push_back("-coverage-data-file"); + CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); } } } @@ -1045,7 +976,6 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, ArgStringList &CmdArgs, const InputInfo &Output, const InputInfoList &Inputs) const { - Arg *A; const bool IsIAMCU = getToolChain().getTriple().isOSIAMCU(); CheckPreprocessingOptions(D, Args); @@ -1054,9 +984,20 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_CC); // Handle dependency file generation. - if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) || - (A = Args.getLastArg(options::OPT_MD)) || - (A = Args.getLastArg(options::OPT_MMD))) { + Arg *ArgM = Args.getLastArg(options::OPT_MM); + if (!ArgM) + ArgM = Args.getLastArg(options::OPT_M); + Arg *ArgMD = Args.getLastArg(options::OPT_MMD); + if (!ArgMD) + ArgMD = Args.getLastArg(options::OPT_MD); + + // -M and -MM imply -w. + if (ArgM) + CmdArgs.push_back("-w"); + else + ArgM = ArgMD; + + if (ArgM) { // Determine the output location. const char *DepFile; if (Arg *MF = Args.getLastArg(options::OPT_MF)) { @@ -1064,8 +1005,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, C.addFailureResultFile(DepFile, &JA); } else if (Output.getType() == types::TY_Dependencies) { DepFile = Output.getFilename(); - } else if (A->getOption().matches(options::OPT_M) || - A->getOption().matches(options::OPT_MM)) { + } else if (!ArgMD) { DepFile = "-"; } else { DepFile = getDependencyFileName(Args, Inputs); @@ -1074,8 +1014,22 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, CmdArgs.push_back("-dependency-file"); CmdArgs.push_back(DepFile); + bool HasTarget = false; + for (const Arg *A : Args.filtered(options::OPT_MT, options::OPT_MQ)) { + HasTarget = true; + A->claim(); + if (A->getOption().matches(options::OPT_MT)) { + A->render(Args, CmdArgs); + } else { + CmdArgs.push_back("-MT"); + SmallString<128> Quoted; + QuoteTarget(A->getValue(), Quoted); + CmdArgs.push_back(Args.MakeArgString(Quoted)); + } + } + // Add a default target if one wasn't specified. - if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) { + if (!HasTarget) { const char *DepTarget; // If user provided -o, that is the dependency target, except @@ -1092,17 +1046,14 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, DepTarget = Args.MakeArgString(llvm::sys::path::filename(P)); } - if (!A->getOption().matches(options::OPT_MD) && !A->getOption().matches(options::OPT_MMD)) { - CmdArgs.push_back("-w"); - } CmdArgs.push_back("-MT"); SmallString<128> Quoted; QuoteTarget(DepTarget, Quoted); CmdArgs.push_back(Args.MakeArgString(Quoted)); } - if (A->getOption().matches(options::OPT_M) || - A->getOption().matches(options::OPT_MD)) + if (ArgM->getOption().matches(options::OPT_M) || + ArgM->getOption().matches(options::OPT_MD)) CmdArgs.push_back("-sys-header-deps"); if ((isa<PrecompileJobAction>(JA) && !Args.hasArg(options::OPT_fno_module_file_deps)) || @@ -1111,8 +1062,8 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, } if (Args.hasArg(options::OPT_MG)) { - if (!A || A->getOption().matches(options::OPT_MD) || - A->getOption().matches(options::OPT_MMD)) + if (!ArgM || ArgM->getOption().matches(options::OPT_MD) || + ArgM->getOption().matches(options::OPT_MMD)) D.Diag(diag::err_drv_mg_requires_m_or_mm); CmdArgs.push_back("-MG"); } @@ -1120,22 +1071,6 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_MP); Args.AddLastArg(CmdArgs, options::OPT_MV); - // Convert all -MQ <target> args to -MT <quoted target> - for (const Arg *A : Args.filtered(options::OPT_MT, options::OPT_MQ)) { - A->claim(); - - if (A->getOption().matches(options::OPT_MQ)) { - CmdArgs.push_back("-MT"); - SmallString<128> Quoted; - QuoteTarget(A->getValue(), Quoted); - CmdArgs.push_back(Args.MakeArgString(Quoted)); - - // -MT flag - no change - } else { - A->render(Args, CmdArgs); - } - } - // Add offload include arguments specific for CUDA. This must happen before // we -I or -include anything else, because we must pick up the CUDA headers // from the particular CUDA installation, rather than from e.g. @@ -1236,6 +1171,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, // Do not claim the argument so that the use of the argument does not // silently go unnoticed on toolchains which do not honour the option. continue; + } else if (A->getOption().matches(options::OPT_stdlibxx_isystem)) { + // Translated to -internal-isystem by the driver, no need to pass to cc1. + continue; } // Not translated, render as usual. @@ -1290,11 +1228,15 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, // of an offloading programming model. // Add C++ include arguments, if needed. - if (types::isCXX(Inputs[0].getType())) - forAllAssociatedToolChains(C, JA, getToolChain(), - [&Args, &CmdArgs](const ToolChain &TC) { - TC.AddClangCXXStdlibIncludeArgs(Args, CmdArgs); - }); + if (types::isCXX(Inputs[0].getType())) { + bool HasStdlibxxIsystem = Args.hasArg(options::OPT_stdlibxx_isystem); + forAllAssociatedToolChains( + C, JA, getToolChain(), + [&Args, &CmdArgs, HasStdlibxxIsystem](const ToolChain &TC) { + HasStdlibxxIsystem ? TC.AddClangCXXStdlibIsystemArgs(Args, CmdArgs) + : TC.AddClangCXXStdlibIncludeArgs(Args, CmdArgs); + }); + } // Add system include arguments for all targets but IAMCU. if (!IsIAMCU) @@ -1635,7 +1577,7 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName.data()); - mips::FloatABI ABI = mips::getMipsFloatABI(D, Args); + mips::FloatABI ABI = mips::getMipsFloatABI(D, Args, Triple); if (ABI == mips::FloatABI::Soft) { // Floating point operations and argument passing are soft. CmdArgs.push_back("-msoft-float"); @@ -1648,13 +1590,6 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, CmdArgs.push_back("hard"); } - if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) { - if (A->getOption().matches(options::OPT_mxgot)) { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-mxgot"); - } - } - if (Arg *A = Args.getLastArg(options::OPT_mldc1_sdc1, options::OPT_mno_ldc1_sdc1)) { if (A->getOption().matches(options::OPT_mno_ldc1_sdc1)) { @@ -1842,21 +1777,11 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, void Clang::AddRISCVTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { - // FIXME: currently defaults to the soft-float ABIs. Will need to be - // expanded to select ilp32f, ilp32d, lp64f, lp64d when appropriate. - const char *ABIName = nullptr; const llvm::Triple &Triple = getToolChain().getTriple(); - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) - ABIName = A->getValue(); - else if (Triple.getArch() == llvm::Triple::riscv32) - ABIName = "ilp32"; - else if (Triple.getArch() == llvm::Triple::riscv64) - ABIName = "lp64"; - else - llvm_unreachable("Unexpected triple!"); + StringRef ABIName = riscv::getRISCVABI(Args, Triple); CmdArgs.push_back("-target-abi"); - CmdArgs.push_back(ABIName); + CmdArgs.push_back(ABIName.data()); } void Clang::AddSparcTargetArgs(const ArgList &Args, @@ -1996,7 +1921,8 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, if (!CompilationDatabase) { std::error_code EC; - auto File = llvm::make_unique<llvm::raw_fd_ostream>(Filename, EC, llvm::sys::fs::F_Text); + auto File = std::make_unique<llvm::raw_fd_ostream>(Filename, EC, + llvm::sys::fs::OF_Text); if (EC) { D.Diag(clang::diag::err_drv_compilationdatabase) << Filename << EC.message(); @@ -2005,13 +1931,14 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, CompilationDatabase = std::move(File); } auto &CDB = *CompilationDatabase; - SmallString<128> Buf; - if (llvm::sys::fs::current_path(Buf)) - Buf = "."; - CDB << "{ \"directory\": \"" << escape(Buf) << "\""; + auto CWD = D.getVFS().getCurrentWorkingDirectory(); + if (!CWD) + CWD = "."; + CDB << "{ \"directory\": \"" << escape(*CWD) << "\""; CDB << ", \"file\": \"" << escape(Input.getFilename()) << "\""; CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\""; CDB << ", \"arguments\": [\"" << escape(D.ClangExecutable) << "\""; + SmallString<128> Buf; Buf = "-x"; Buf += types::getTypeName(Input.getType()); CDB << ", \"" << escape(Buf) << "\""; @@ -2029,6 +1956,8 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, // Skip writing dependency output and the compilation database itself. if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group) continue; + if (O.getID() == options::OPT_gen_cdb_fragment_path) + continue; // Skip inputs. if (O.getKind() == Option::InputClass) continue; @@ -2043,6 +1972,40 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, CDB << ", \"" << escape(Buf) << "\"]},\n"; } +void Clang::DumpCompilationDatabaseFragmentToDir( + StringRef Dir, Compilation &C, StringRef Target, const InputInfo &Output, + const InputInfo &Input, const llvm::opt::ArgList &Args) const { + // If this is a dry run, do not create the compilation database file. + if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) + return; + + if (CompilationDatabase) + DumpCompilationDatabase(C, "", Target, Output, Input, Args); + + SmallString<256> Path = Dir; + const auto &Driver = C.getDriver(); + Driver.getVFS().makeAbsolute(Path); + auto Err = llvm::sys::fs::create_directory(Path, /*IgnoreExisting=*/true); + if (Err) { + Driver.Diag(diag::err_drv_compilationdatabase) << Dir << Err.message(); + return; + } + + llvm::sys::path::append( + Path, + Twine(llvm::sys::path::filename(Input.getFilename())) + ".%%%%.json"); + int FD; + SmallString<256> TempPath; + Err = llvm::sys::fs::createUniqueFile(Path, FD, TempPath); + if (Err) { + Driver.Diag(diag::err_drv_compilationdatabase) << Path << Err.message(); + return; + } + CompilationDatabase = + std::make_unique<llvm::raw_fd_ostream>(FD, /*shouldClose=*/true); + DumpCompilationDatabase(C, "", Target, Output, Input, Args); +} + static void CollectArgsForIntegratedAssembler(Compilation &C, const ArgList &Args, ArgStringList &CmdArgs, @@ -2080,6 +2043,9 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, break; } + // If you add more args here, also add them to the block below that + // starts with "// If CollectArgsForIntegratedAssembler() isn't called below". + // When passing -I arguments to the assembler we sometimes need to // unconditionally take the next argument. For example, when parsing // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the @@ -2169,6 +2135,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, CmdArgs.push_back("-msave-temp-labels"); } else if (Value == "--fatal-warnings") { CmdArgs.push_back("-massembler-fatal-warnings"); + } else if (Value == "--no-warn" || Value == "-W") { + CmdArgs.push_back("-massembler-no-warn"); } else if (Value == "--noexecstack") { UseNoExecStack = true; } else if (Value.startswith("-compress-debug-sections") || @@ -2804,6 +2772,10 @@ static void RenderModulesOptions(Compilation &C, const Driver &D, std::string("-fprebuilt-module-path=") + A->getValue())); A->claim(); } + if (Args.hasFlag(options::OPT_fmodules_validate_input_files_content, + options::OPT_fno_modules_validate_input_files_content, + false)) + CmdArgs.push_back("-fvalidate-ast-input-files-content"); } // -fmodule-name specifies the module that is currently being built (or @@ -3342,7 +3314,6 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, Args.getLastArg(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames, options::OPT_gpubnames, options::OPT_gno_pubnames); if (DwarfFission != DwarfFissionKind::None || - DebuggerTuning == llvm::DebuggerKind::LLDB || (PubnamesArg && checkDebugInfoOption(PubnamesArg, Args, D, TC))) if (!PubnamesArg || (!PubnamesArg->getOption().matches(options::OPT_gno_gnu_pubnames) && @@ -3482,6 +3453,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) { DumpCompilationDatabase(C, MJ->getValue(), TripleStr, Output, Input, Args); Args.ClaimAllArgs(options::OPT_MJ); + } else if (const Arg *GenCDBFragment = + Args.getLastArg(options::OPT_gen_cdb_fragment_path)) { + DumpCompilationDatabaseFragmentToDir(GenCDBFragment->getValue(), C, + TripleStr, Output, Input, Args); + Args.ClaimAllArgs(options::OPT_gen_cdb_fragment_path); } if (IsCuda || IsHIP) { @@ -3544,6 +3520,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Select the appropriate action. RewriteKind rewriteKind = RK_None; + // If CollectArgsForIntegratedAssembler() isn't called below, claim the args + // it claims when not running an assembler. Otherwise, clang would emit + // "argument unused" warnings for assembler flags when e.g. adding "-E" to + // flags while debugging something. That'd be somewhat inconvenient, and it's + // also inconsistent with most other flags -- we don't warn on + // -ffunction-sections not being used in -E mode either for example, even + // though it's not really used either. + if (!isa<AssembleJobAction>(JA)) { + // The args claimed here should match the args used in + // CollectArgsForIntegratedAssembler(). + if (TC.useIntegratedAs()) { + Args.ClaimAllArgs(options::OPT_mrelax_all); + Args.ClaimAllArgs(options::OPT_mno_relax_all); + Args.ClaimAllArgs(options::OPT_mincremental_linker_compatible); + Args.ClaimAllArgs(options::OPT_mno_incremental_linker_compatible); + switch (C.getDefaultToolChain().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + Args.ClaimAllArgs(options::OPT_mimplicit_it_EQ); + break; + default: + break; + } + } + Args.ClaimAllArgs(options::OPT_Wa_COMMA); + Args.ClaimAllArgs(options::OPT_Xassembler); + } + if (isa<AnalyzeJobAction>(JA)) { assert(JA.getType() == types::TY_Plist && "Invalid output type."); CmdArgs.push_back("-analyze"); @@ -3587,25 +3593,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } else if (JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC) { CmdArgs.push_back("-emit-llvm-bc"); - } else if (JA.getType() == types::TY_IFS) { - StringRef StubFormat = - llvm::StringSwitch<StringRef>( - Args.hasArg(options::OPT_iterface_stub_version_EQ) - ? Args.getLastArgValue(options::OPT_iterface_stub_version_EQ) - : "") - .Case("experimental-yaml-elf-v1", "experimental-yaml-elf-v1") - .Case("experimental-tapi-elf-v1", "experimental-tapi-elf-v1") - .Default(""); - - if (StubFormat.empty()) - D.Diag(diag::err_drv_invalid_value) - << "Must specify a valid interface stub format type using " - << "-interface-stub-version=<experimental-tapi-elf-v1 | " - "experimental-yaml-elf-v1>"; - + } else if (JA.getType() == types::TY_IFS || + JA.getType() == types::TY_IFS_CPP) { + StringRef ArgStr = + Args.hasArg(options::OPT_interface_stub_version_EQ) + ? Args.getLastArgValue(options::OPT_interface_stub_version_EQ) + : "experimental-ifs-v1"; CmdArgs.push_back("-emit-interface-stubs"); CmdArgs.push_back( - Args.MakeArgString(Twine("-interface-stub-version=") + StubFormat)); + Args.MakeArgString(Twine("-interface-stub-version=") + ArgStr.str())); } else if (JA.getType() == types::TY_PP_Asm) { CmdArgs.push_back("-S"); } else if (JA.getType() == types::TY_AST) { @@ -3635,13 +3631,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (D.isUsingLTO() && !isDeviceOffloadAction) { Args.AddLastArg(CmdArgs, options::OPT_flto, options::OPT_flto_EQ); - - // The Darwin and PS4 linkers currently use the legacy LTO API, which - // does not support LTO unit features (CFI, whole program vtable opt) - // under ThinLTO. - if (!(RawTriple.isOSDarwin() || RawTriple.isPS4()) || - D.getLTOMode() == LTOK_Full) - CmdArgs.push_back("-flto-unit"); + CmdArgs.push_back("-flto-unit"); } } @@ -3761,7 +3751,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, II.getInputArg().renderAsInput(Args, CmdArgs); } - C.addCommand(llvm::make_unique<Command>(JA, *this, D.getClangProgramPath(), + C.addCommand(std::make_unique<Command>(JA, *this, D.getClangProgramPath(), CmdArgs, Inputs)); return; } @@ -3806,6 +3796,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (isa<AnalyzeJobAction>(JA)) RenderAnalyzerOptions(Args, CmdArgs, Triple, Input); + if (isa<AnalyzeJobAction>(JA) || + (isa<PreprocessJobAction>(JA) && Args.hasArg(options::OPT__analyze))) + CmdArgs.push_back("-setup-static-analyzer"); + // Enable compatilibily mode to avoid analyzer-config related errors. // Since we can't access frontend flags through hasArg, let's manually iterate // through them. @@ -3946,12 +3940,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) CmdArgs.push_back("-fdefault-calling-conv=stdcall"); - FramePointerKind FPKeepKind = getFramePointerKind(Args, RawTriple); - if (FPKeepKind != FramePointerKind::None) { - CmdArgs.push_back("-mdisable-fp-elim"); - if (FPKeepKind == FramePointerKind::NonLeaf) - CmdArgs.push_back("-momit-leaf-frame-pointer"); + CodeGenOptions::FramePointerKind FPKeepKind = + getFramePointerKind(Args, RawTriple); + const char *FPKeepKindStr = nullptr; + switch (FPKeepKind) { + case CodeGenOptions::FramePointerKind::None: + FPKeepKindStr = "-mframe-pointer=none"; + break; + case CodeGenOptions::FramePointerKind::NonLeaf: + FPKeepKindStr = "-mframe-pointer=non-leaf"; + break; + case CodeGenOptions::FramePointerKind::All: + FPKeepKindStr = "-mframe-pointer=all"; + break; } + assert(FPKeepKindStr && "unknown FramePointerKind"); + CmdArgs.push_back(FPKeepKindStr); + if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss, options::OPT_fno_zero_initialized_in_bss)) CmdArgs.push_back("-mno-zero-initialized-in-bss"); @@ -4003,11 +4008,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs); - if (Arg *A = Args.getLastArg(options::OPT_mlong_double_64, - options::OPT_mlong_double_128)) { + if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) { if (TC.getArch() == llvm::Triple::x86 || - TC.getArch() == llvm::Triple::x86_64 || - TC.getArch() == llvm::Triple::ppc || TC.getTriple().isPPC64()) + TC.getArch() == llvm::Triple::x86_64) + A->render(Args, CmdArgs); + else if ((TC.getArch() == llvm::Triple::ppc || TC.getTriple().isPPC64()) && + (A->getOption().getID() != options::OPT_mlong_double_80)) A->render(Args, CmdArgs); else D.Diag(diag::err_drv_unsupported_opt_for_target) @@ -4018,8 +4024,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // toolchains which have the integrated assembler on by default. bool IsIntegratedAssemblerDefault = TC.IsIntegratedAssemblerDefault(); if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm, - IsIntegratedAssemblerDefault) || - Args.hasArg(options::OPT_dA)) + IsIntegratedAssemblerDefault)) CmdArgs.push_back("-masm-verbose"); if (!TC.useIntegratedAs()) @@ -4386,6 +4391,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue()); } + if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter)) + CmdArgs.push_back("-fexperimental-new-constant-interpreter"); + + if (Args.hasArg(options::OPT_fforce_experimental_new_constant_interpreter)) + CmdArgs.push_back("-fforce-experimental-new-constant-interpreter"); + if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) { CmdArgs.push_back("-fbracket-depth"); CmdArgs.push_back(A->getValue()); @@ -4571,20 +4582,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (TC.SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_mfentry); - // -flax-vector-conversions is default. - if (!Args.hasFlag(options::OPT_flax_vector_conversions, - options::OPT_fno_lax_vector_conversions)) - CmdArgs.push_back("-fno-lax-vector-conversions"); - if (Args.getLastArg(options::OPT_fapple_kext) || (Args.hasArg(options::OPT_mkernel) && types::isCXX(InputType))) CmdArgs.push_back("-fapple-kext"); + Args.AddLastArg(CmdArgs, options::OPT_flax_vector_conversions_EQ); Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits); Args.AddLastArg(CmdArgs, options::OPT_ftime_report); Args.AddLastArg(CmdArgs, options::OPT_ftime_trace); + Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_granularity_EQ); Args.AddLastArg(CmdArgs, options::OPT_ftrapv); Args.AddLastArg(CmdArgs, options::OPT_malign_double); @@ -4667,6 +4675,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Forward -cl options to -cc1 RenderOpenCLOptions(Args, CmdArgs); + if (Args.hasFlag(options::OPT_fhip_new_launch_api, + options::OPT_fno_hip_new_launch_api, false)) + CmdArgs.push_back("-fhip-new-launch-api"); + if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) { CmdArgs.push_back( Args.MakeArgString(Twine("-fcf-protection=") + A->getValue())); @@ -4771,13 +4783,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fuse-line-directives"); // -fms-compatibility=0 is default. - if (Args.hasFlag(options::OPT_fms_compatibility, - options::OPT_fno_ms_compatibility, - (IsWindowsMSVC && - Args.hasFlag(options::OPT_fms_extensions, - options::OPT_fno_ms_extensions, true)))) + bool IsMSVCCompat = Args.hasFlag( + options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility, + (IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions, + options::OPT_fno_ms_extensions, true))); + if (IsMSVCCompat) CmdArgs.push_back("-fms-compatibility"); + // Handle -fgcc-version, if present. + VersionTuple GNUCVer; + if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) { + // Check that the version has 1 to 3 components and the minor and patch + // versions fit in two decimal digits. + StringRef Val = A->getValue(); + Val = Val.empty() ? "0" : Val; // Treat "" as 0 or disable. + bool Invalid = GNUCVer.tryParse(Val); + unsigned Minor = GNUCVer.getMinor().getValueOr(0); + unsigned Patch = GNUCVer.getSubminor().getValueOr(0); + if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) { + D.Diag(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + } + } else if (!IsMSVCCompat) { + // Imitate GCC 4.2.1 by default if -fms-compatibility is not in effect. + GNUCVer = VersionTuple(4, 2, 1); + } + if (!GNUCVer.empty()) { + CmdArgs.push_back( + Args.MakeArgString("-fgnuc-version=" + GNUCVer.getAsString())); + } + VersionTuple MSVT = TC.computeMSVCVersion(&D, Args); if (!MSVT.empty()) CmdArgs.push_back( @@ -4857,6 +4892,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Std && (Std->containsValue("c++2a") || Std->containsValue("c++latest")); RenderModulesOptions(C, D, Args, Input, Output, CmdArgs, HaveModules); + if (Args.hasFlag(options::OPT_fpch_validate_input_files_content, + options::OPT_fno_pch_validate_input_files_content, false)) + CmdArgs.push_back("-fvalidate-ast-input-files-content"); + Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager, options::OPT_fno_experimental_new_pass_manager); @@ -4873,9 +4912,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs); // Handle exception personalities - Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, - options::OPT_fseh_exceptions, - options::OPT_fdwarf_exceptions); + Arg *A = Args.getLastArg( + options::OPT_fsjlj_exceptions, options::OPT_fseh_exceptions, + options::OPT_fdwarf_exceptions, options::OPT_fwasm_exceptions); if (A) { const Option &Opt = A->getOption(); if (Opt.matches(options::OPT_fsjlj_exceptions)) @@ -4884,6 +4923,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fseh-exceptions"); if (Opt.matches(options::OPT_fdwarf_exceptions)) CmdArgs.push_back("-fdwarf-exceptions"); + if (Opt.matches(options::OPT_fwasm_exceptions)) + CmdArgs.push_back("-fwasm-exceptions"); } else { switch (TC.GetExceptionModel(Args)) { default: @@ -5322,9 +5363,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(TargetInfo.str())); } - bool WholeProgramVTables = - Args.hasFlag(options::OPT_fwhole_program_vtables, - options::OPT_fno_whole_program_vtables, false); + bool VirtualFunctionElimination = + Args.hasFlag(options::OPT_fvirtual_function_elimination, + options::OPT_fno_virtual_function_elimination, false); + if (VirtualFunctionElimination) { + // VFE requires full LTO (currently, this might be relaxed to allow ThinLTO + // in the future). + if (D.getLTOMode() != LTOK_Full) + D.Diag(diag::err_drv_argument_only_allowed_with) + << "-fvirtual-function-elimination" + << "-flto=full"; + + CmdArgs.push_back("-fvirtual-function-elimination"); + } + + // VFE requires whole-program-vtables, and enables it by default. + bool WholeProgramVTables = Args.hasFlag( + options::OPT_fwhole_program_vtables, + options::OPT_fno_whole_program_vtables, VirtualFunctionElimination); + if (VirtualFunctionElimination && !WholeProgramVTables) { + D.Diag(diag::err_drv_argument_not_allowed_with) + << "-fno-whole-program-vtables" + << "-fvirtual-function-elimination"; + } + if (WholeProgramVTables) { if (!D.isUsingLTO()) D.Diag(diag::err_drv_argument_only_allowed_with) @@ -5333,14 +5395,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fwhole-program-vtables"); } - bool RequiresSplitLTOUnit = WholeProgramVTables || Sanitize.needsLTO(); + bool DefaultsSplitLTOUnit = WholeProgramVTables || Sanitize.needsLTO(); bool SplitLTOUnit = Args.hasFlag(options::OPT_fsplit_lto_unit, - options::OPT_fno_split_lto_unit, RequiresSplitLTOUnit); - if (RequiresSplitLTOUnit && !SplitLTOUnit) - D.Diag(diag::err_drv_argument_not_allowed_with) - << "-fno-split-lto-unit" - << (WholeProgramVTables ? "-fwhole-program-vtables" : "-fsanitize=cfi"); + options::OPT_fno_split_lto_unit, DefaultsSplitLTOUnit); + if (Sanitize.needsLTO() && !SplitLTOUnit) + D.Diag(diag::err_drv_argument_not_allowed_with) << "-fno-split-lto-unit" + << "-fsanitize=cfi"; if (SplitLTOUnit) CmdArgs.push_back("-fsplit-lto-unit"); @@ -5469,16 +5530,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, (InputType == types::TY_C || InputType == types::TY_CXX)) { auto CLCommand = getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput); - C.addCommand(llvm::make_unique<FallbackCommand>( + C.addCommand(std::make_unique<FallbackCommand>( JA, *this, Exec, CmdArgs, Inputs, std::move(CLCommand))); } else if (Args.hasArg(options::OPT__SLASH_fallback) && isa<PrecompileJobAction>(JA)) { // In /fallback builds, run the main compilation even if the pch generation // fails, so that the main compilation's fallback to cl.exe runs. - C.addCommand(llvm::make_unique<ForceSuccessCommand>(JA, *this, Exec, + C.addCommand(std::make_unique<ForceSuccessCommand>(JA, *this, Exec, CmdArgs, Inputs)); } else { - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Make the compile command echo its inputs for /showFilenames. @@ -5489,7 +5550,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } if (Arg *A = Args.getLastArg(options::OPT_pg)) - if (FPKeepKind == FramePointerKind::None) + if (FPKeepKind == CodeGenOptions::FramePointerKind::None) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer" << A->getAsString(Args); @@ -5954,15 +6015,14 @@ const char *Clang::getBaseInputStem(const ArgList &Args, const char *Clang::getDependencyFileName(const ArgList &Args, const InputInfoList &Inputs) { // FIXME: Think about this more. - std::string Res; if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) { - std::string Str(OutputOpt->getValue()); - Res = Str.substr(0, Str.rfind('.')); - } else { - Res = getBaseInputStem(Args, Inputs); + SmallString<128> OutputFilename(OutputOpt->getValue()); + llvm::sys::path::replace_extension(OutputFilename, llvm::Twine('d')); + return Args.MakeArgString(OutputFilename); } - return Args.MakeArgString(Res + ".d"); + + return Args.MakeArgString(Twine(getBaseInputStem(Args, Inputs)) + ".d"); } // Begin ClangAs @@ -6205,7 +6265,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Input.getFilename()); const char *Exec = getToolChain().getDriver().getClangProgramPath(); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Begin OffloadBundler @@ -6288,7 +6348,7 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(TCArgs.MakeArgString(UB)); // All the inputs are encoded as commands. - C.addCommand(llvm::make_unique<Command>( + C.addCommand(std::make_unique<Command>( JA, *this, TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), CmdArgs, None)); @@ -6354,8 +6414,38 @@ void OffloadBundler::ConstructJobMultipleOutputs( CmdArgs.push_back("-unbundle"); // All the inputs are encoded as commands. - C.addCommand(llvm::make_unique<Command>( + C.addCommand(std::make_unique<Command>( JA, *this, TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), CmdArgs, None)); } + +void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + + const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); + + // Add the "effective" target triple. + CmdArgs.push_back("-target"); + CmdArgs.push_back(Args.MakeArgString(Triple.getTriple())); + + // Add the output file name. + assert(Output.isFilename() && "Invalid output."); + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + // Add inputs. + for (const InputInfo &I : Inputs) { + assert(I.isFilename() && "Invalid input."); + CmdArgs.push_back(I.getFilename()); + } + + C.addCommand(std::make_unique<Command>( + JA, *this, + Args.MakeArgString(getToolChain().GetProgramPath(getShortName())), + CmdArgs, Inputs)); +} |