diff options
Diffstat (limited to 'lib/Driver')
58 files changed, 1631 insertions, 994 deletions
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp index 47b03f6643b84..0eb4c7257e7a8 100644 --- a/lib/Driver/Action.cpp +++ b/lib/Driver/Action.cpp @@ -31,6 +31,7 @@ const char *Action::getClassName(ActionClass AC) { case CompileJobClass: return "compiler"; case BackendJobClass: return "backend"; case AssembleJobClass: return "assembler"; + case IfsMergeJobClass: return "interface-stub-merger"; case LinkJobClass: return "linker"; case LipoJobClass: return "lipo"; case DsymutilJobClass: return "dsymutil"; @@ -40,6 +41,8 @@ const char *Action::getClassName(ActionClass AC) { return "clang-offload-bundler"; case OffloadUnbundlingJobClass: return "clang-offload-unbundler"; + case OffloadWrapperJobClass: + return "clang-offload-wrapper"; } llvm_unreachable("invalid class"); @@ -357,6 +360,11 @@ void AssembleJobAction::anchor() {} AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType) : JobAction(AssembleJobClass, Input, OutputType) {} +void IfsMergeJobAction::anchor() {} + +IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type) + : JobAction(IfsMergeJobClass, Inputs, Type) {} + void LinkJobAction::anchor() {} LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type) @@ -401,3 +409,9 @@ void OffloadUnbundlingJobAction::anchor() {} OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input) : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {} + +void OffloadWrapperJobAction::anchor() {} + +OffloadWrapperJobAction::OffloadWrapperJobAction(ActionList &Inputs, + types::ID Type) + : JobAction(OffloadWrapperJobClass, Inputs, Type) {} diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index 5f3026e6ce508..ba188f5c4083c 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -161,7 +161,7 @@ int Compilation::ExecuteCommand(const Command &C, std::error_code EC; OwnedStream.reset(new llvm::raw_fd_ostream( getDriver().CCPrintOptionsFilename, EC, - llvm::sys::fs::F_Append | llvm::sys::fs::F_Text)); + llvm::sys::fs::OF_Append | llvm::sys::fs::OF_Text)); if (EC) { getDriver().Diag(diag::err_drv_cc_print_options_failure) << EC.message(); diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 396ddf4dd8162..f6016b43b6920 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -120,20 +120,20 @@ std::string Driver::GetResourcesPath(StringRef BinaryPath, Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple, DiagnosticsEngine &Diags, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) - : Opts(createDriverOptTable()), Diags(Diags), VFS(std::move(VFS)), - Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), - LTOMode(LTOK_None), ClangExecutable(ClangExecutable), - SysRoot(DEFAULT_SYSROOT), DriverTitle("clang LLVM compiler"), - CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr), - CCLogDiagnosticsFilename(nullptr), CCCPrintBindings(false), - CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), - CCGenDiagnostics(false), TargetTriple(TargetTriple), - CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true), - GenReproducer(false), SuppressMissingInputWarning(false) { + : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode), + SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None), + ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), + DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr), + CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr), + CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false), + CCLogDiagnostics(false), CCGenDiagnostics(false), + TargetTriple(TargetTriple), CCCGenericGCCName(""), Saver(Alloc), + CheckInputsExist(true), GenReproducer(false), + SuppressMissingInputWarning(false) { // Provide a sane fallback if no VFS is specified. if (!this->VFS) - this->VFS = llvm::vfs::createPhysicalFileSystem().release(); + this->VFS = llvm::vfs::getRealFileSystem(); Name = llvm::sys::path::filename(ClangExecutable); Dir = llvm::sys::path::parent_path(ClangExecutable); @@ -274,11 +274,11 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) { FinalPhase = phases::Preprocess; - // --precompile only runs up to precompilation. + // --precompile only runs up to precompilation. } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile))) { FinalPhase = phases::Precompile; - // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. + // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) || (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) || @@ -286,21 +286,23 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) || (PhaseArg = DAL.getLastArg(options::OPT__migrate)) || - (PhaseArg = DAL.getLastArg(options::OPT_emit_iterface_stubs)) || - (PhaseArg = DAL.getLastArg(options::OPT__analyze, - options::OPT__analyze_auto)) || + (PhaseArg = DAL.getLastArg(options::OPT__analyze)) || (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) { FinalPhase = phases::Compile; - // -S only runs up to the backend. + // clang interface stubs + } else if ((PhaseArg = DAL.getLastArg(options::OPT_emit_interface_stubs))) { + FinalPhase = phases::IfsMerge; + + // -S only runs up to the backend. } else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) { FinalPhase = phases::Backend; - // -c compilation only runs up to the assembler. + // -c compilation only runs up to the assembler. } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) { FinalPhase = phases::Assemble; - // Otherwise do everything. + // Otherwise do everything. } else FinalPhase = phases::Link; @@ -310,7 +312,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, return FinalPhase; } -static Arg *MakeInputArg(DerivedArgList &Args, OptTable &Opts, +static Arg *MakeInputArg(DerivedArgList &Args, const OptTable &Opts, StringRef Value, bool Claim = true) { Arg *A = new Arg(Opts.getOption(options::OPT_INPUT), Value, Args.getBaseArgs().MakeIndex(Value), Value.data()); @@ -321,6 +323,7 @@ static Arg *MakeInputArg(DerivedArgList &Args, OptTable &Opts, } DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { + const llvm::opt::OptTable &Opts = getOpts(); DerivedArgList *DAL = new DerivedArgList(Args); bool HasNostdlib = Args.hasArg(options::OPT_nostdlib); @@ -337,12 +340,12 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { A->getOption().matches(options::OPT_Xlinker)) && A->containsValue("--no-demangle")) { // Add the rewritten no-demangle argument. - DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_Xlinker__no_demangle)); + DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_Xlinker__no_demangle)); // Add the remaining values as Xlinker arguments. for (StringRef Val : A->getValues()) if (Val != "--no-demangle") - DAL->AddSeparateArg(A, Opts->getOption(options::OPT_Xlinker), Val); + DAL->AddSeparateArg(A, Opts.getOption(options::OPT_Xlinker), Val); continue; } @@ -355,12 +358,11 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { A->getValue(0) == StringRef("-MMD"))) { // Rewrite to -MD/-MMD along with -MF. if (A->getValue(0) == StringRef("-MD")) - DAL->AddFlagArg(A, Opts->getOption(options::OPT_MD)); + DAL->AddFlagArg(A, Opts.getOption(options::OPT_MD)); else - DAL->AddFlagArg(A, Opts->getOption(options::OPT_MMD)); + DAL->AddFlagArg(A, Opts.getOption(options::OPT_MMD)); if (A->getNumValues() == 2) - DAL->AddSeparateArg(A, Opts->getOption(options::OPT_MF), - A->getValue(1)); + DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue(1)); continue; } @@ -371,13 +373,13 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { // Rewrite unless -nostdlib is present. if (!HasNostdlib && !HasNodefaultlib && !HasNostdlibxx && Value == "stdc++") { - DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_reserved_lib_stdcxx)); + DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_stdcxx)); continue; } // Rewrite unconditionally. if (Value == "cc_kext") { - DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_reserved_lib_cckext)); + DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_cckext)); continue; } } @@ -386,7 +388,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { if (A->getOption().matches(options::OPT__DASH_DASH)) { A->claim(); for (StringRef Val : A->getValues()) - DAL->append(MakeInputArg(*DAL, *Opts, Val, false)); + DAL->append(MakeInputArg(*DAL, Opts, Val, false)); continue; } @@ -395,14 +397,14 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { // Enforce -static if -miamcu is present. if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) - DAL->AddFlagArg(0, Opts->getOption(options::OPT_static)); + DAL->AddFlagArg(0, Opts.getOption(options::OPT_static)); // Add a default value of -mlinker-version=, if one was given and the user // didn't specify one. #if defined(HOST_LINK_VERSION) if (!Args.hasArg(options::OPT_mlinker_version_EQ) && strlen(HOST_LINK_VERSION) > 0) { - DAL->AddJoinedArg(0, Opts->getOption(options::OPT_mlinker_version_EQ), + DAL->AddJoinedArg(0, Opts.getOption(options::OPT_mlinker_version_EQ), HOST_LINK_VERSION); DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim(); } @@ -626,7 +628,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, // because the device toolchain we create depends on both. auto &CudaTC = ToolChains[CudaTriple.str() + "/" + HostTriple.str()]; if (!CudaTC) { - CudaTC = llvm::make_unique<toolchains::CudaToolChain>( + CudaTC = std::make_unique<toolchains::CudaToolChain>( *this, CudaTriple, *HostTC, C.getInputArgs(), OFK); } C.addOffloadDeviceToolChain(CudaTC.get(), OFK); @@ -641,7 +643,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, // because the device toolchain we create depends on both. auto &HIPTC = ToolChains[HIPTriple.str() + "/" + HostTriple.str()]; if (!HIPTC) { - HIPTC = llvm::make_unique<toolchains::HIPToolChain>( + HIPTC = std::make_unique<toolchains::HIPToolChain>( *this, HIPTriple, *HostTC, C.getInputArgs()); } C.addOffloadDeviceToolChain(HIPTC.get(), OFK); @@ -699,7 +701,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, auto &CudaTC = ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()]; if (!CudaTC) - CudaTC = llvm::make_unique<toolchains::CudaToolChain>( + CudaTC = std::make_unique<toolchains::CudaToolChain>( *this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP); TC = CudaTC.get(); } else @@ -760,7 +762,7 @@ bool Driver::readConfigFile(StringRef FileName) { llvm::sys::path::native(CfgFileName); ConfigFile = CfgFileName.str(); bool ContainErrors; - CfgOptions = llvm::make_unique<InputArgList>( + CfgOptions = std::make_unique<InputArgList>( ParseArgStrings(NewCfgArgs, IsCLMode(), ContainErrors)); if (ContainErrors) { CfgOptions.reset(); @@ -954,7 +956,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // Arguments specified in command line. bool ContainsError; - CLOptions = llvm::make_unique<InputArgList>( + CLOptions = std::make_unique<InputArgList>( ParseArgStrings(ArgList.slice(1), IsCLMode(), ContainsError)); // Try parsing configuration file. @@ -1000,7 +1002,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { if (!CLModePassThroughArgList.empty()) { // Parse any pass through args using default clang processing rather // than clang-cl processing. - auto CLModePassThroughOptions = llvm::make_unique<InputArgList>( + auto CLModePassThroughOptions = std::make_unique<InputArgList>( ParseArgStrings(CLModePassThroughArgList, false, ContainsError)); if (!ContainsError) @@ -1093,7 +1095,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { } std::unique_ptr<llvm::opt::InputArgList> UArgs = - llvm::make_unique<InputArgList>(std::move(Args)); + std::make_unique<InputArgList>(std::move(Args)); // Perform the default argument translations. DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs); @@ -1592,16 +1594,17 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const { if (llvm::is_contained(Flags, "-Xclang") || llvm::is_contained(Flags, "-cc1")) DisableFlags &= ~options::NoDriverOption; + const llvm::opt::OptTable &Opts = getOpts(); StringRef Cur; Cur = Flags.at(Flags.size() - 1); StringRef Prev; if (Flags.size() >= 2) { Prev = Flags.at(Flags.size() - 2); - SuggestedCompletions = Opts->suggestValueCompletions(Prev, Cur); + SuggestedCompletions = Opts.suggestValueCompletions(Prev, Cur); } if (SuggestedCompletions.empty()) - SuggestedCompletions = Opts->suggestValueCompletions(Cur, ""); + SuggestedCompletions = Opts.suggestValueCompletions(Cur, ""); // If Flags were empty, it means the user typed `clang [tab]` where we should // list all possible flags. If there was no value completion and the user @@ -1619,7 +1622,7 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const { // If the flag is in the form of "--autocomplete=-foo", // we were requested to print out all option names that start with "-foo". // For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only". - SuggestedCompletions = Opts->findByPrefix(Cur, DisableFlags); + SuggestedCompletions = Opts.findByPrefix(Cur, DisableFlags); // We have to query the -W flags manually as they're not in the OptTable. // TODO: Find a good way to add them to OptTable instead and them remove @@ -1799,23 +1802,36 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { return true; } +enum { + TopLevelAction = 0, + HeadSibAction = 1, + OtherSibAction = 2, +}; + // Display an action graph human-readably. Action A is the "sink" node // and latest-occuring action. Traversal is in pre-order, visiting the // inputs to each action before printing the action itself. static unsigned PrintActions1(const Compilation &C, Action *A, - std::map<Action *, unsigned> &Ids) { + std::map<Action *, unsigned> &Ids, + Twine Indent = {}, int Kind = TopLevelAction) { if (Ids.count(A)) // A was already visited. return Ids[A]; std::string str; llvm::raw_string_ostream os(str); + auto getSibIndent = [](int K) -> Twine { + return (K == HeadSibAction) ? " " : (K == OtherSibAction) ? "| " : ""; + }; + + Twine SibIndent = Indent + getSibIndent(Kind); + int SibKind = HeadSibAction; os << Action::getClassName(A->getKind()) << ", "; if (InputAction *IA = dyn_cast<InputAction>(A)) { os << "\"" << IA->getInputArg().getValue() << "\""; } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) { os << '"' << BIA->getArchName() << '"' << ", {" - << PrintActions1(C, *BIA->input_begin(), Ids) << "}"; + << PrintActions1(C, *BIA->input_begin(), Ids, SibIndent, SibKind) << "}"; } else if (OffloadAction *OA = dyn_cast<OffloadAction>(A)) { bool IsFirst = true; OA->doOnEachDependence( @@ -1838,8 +1854,9 @@ static unsigned PrintActions1(const Compilation &C, Action *A, os << ":" << BoundArch; os << ")"; os << '"'; - os << " {" << PrintActions1(C, A, Ids) << "}"; + os << " {" << PrintActions1(C, A, Ids, SibIndent, SibKind) << "}"; IsFirst = false; + SibKind = OtherSibAction; }); } else { const ActionList *AL = &A->getInputs(); @@ -1847,8 +1864,9 @@ static unsigned PrintActions1(const Compilation &C, Action *A, if (AL->size()) { const char *Prefix = "{"; for (Action *PreRequisite : *AL) { - os << Prefix << PrintActions1(C, PreRequisite, Ids); + os << Prefix << PrintActions1(C, PreRequisite, Ids, SibIndent, SibKind); Prefix = ", "; + SibKind = OtherSibAction; } os << "}"; } else @@ -1869,9 +1887,13 @@ static unsigned PrintActions1(const Compilation &C, Action *A, } } + auto getSelfIndent = [](int K) -> Twine { + return (K == HeadSibAction) ? "+- " : (K == OtherSibAction) ? "|- " : ""; + }; + unsigned Id = Ids.size(); Ids[A] = Id; - llvm::errs() << Id << ": " << os.str() << ", " + llvm::errs() << Indent + getSelfIndent(Kind) << Id << ": " << os.str() << ", " << types::getTypeName(A->getType()) << offload_os.str() << "\n"; return Id; @@ -2037,6 +2059,7 @@ bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value, // Construct a the list of inputs and their types. void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, InputList &Inputs) const { + const llvm::opt::OptTable &Opts = getOpts(); // Track the current user specified (-x) input. We also explicitly track the // argument used to set the type; we only want to claim the type when we // actually use it, so we warn about unused -x arguments. @@ -2160,7 +2183,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, StringRef Value = A->getValue(); if (DiagnoseInputExistence(Args, Value, types::TY_C, /*TypoCorrect=*/false)) { - Arg *InputArg = MakeInputArg(Args, *Opts, A->getValue()); + Arg *InputArg = MakeInputArg(Args, Opts, A->getValue()); Inputs.push_back(std::make_pair(types::TY_C, InputArg)); } A->claim(); @@ -2168,7 +2191,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, StringRef Value = A->getValue(); if (DiagnoseInputExistence(Args, Value, types::TY_CXX, /*TypoCorrect=*/false)) { - Arg *InputArg = MakeInputArg(Args, *Opts, A->getValue()); + Arg *InputArg = MakeInputArg(Args, Opts, A->getValue()); Inputs.push_back(std::make_pair(types::TY_CXX, InputArg)); } A->claim(); @@ -2202,7 +2225,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, if (CCCIsCPP() && Inputs.empty()) { // If called as standalone preprocessor, stdin is processed // if no other input is present. - Arg *A = MakeInputArg(Args, *Opts, "-"); + Arg *A = MakeInputArg(Args, Opts, "-"); Inputs.push_back(std::make_pair(types::TY_C, A)); } } @@ -2223,7 +2246,7 @@ class OffloadingActionBuilder final { /// Builder interface. It doesn't build anything or keep any state. class DeviceActionBuilder { public: - typedef llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PhasesTy; + typedef const llvm::SmallVectorImpl<phases::ID> PhasesTy; enum ActionBuilderReturnCode { // The builder acted successfully on the current action. @@ -2276,12 +2299,13 @@ class OffloadingActionBuilder final { return ABRT_Inactive; } - /// Append top level actions generated by the builder. Return true if errors - /// were found. + /// Append top level actions generated by the builder. virtual void appendTopLevelActions(ActionList &AL) {} - /// Append linker actions generated by the builder. Return true if errors - /// were found. + /// Append linker actions generated by the builder. + virtual void appendLinkActions(ActionList &AL) {} + + /// Append linker actions generated by the builder. virtual void appendLinkDependences(OffloadAction::DeviceDependences &DA) {} /// Initialize the builder. Return true if any initialization errors are @@ -2309,6 +2333,8 @@ class OffloadingActionBuilder final { /// compilation. bool CompileHostOnly = false; bool CompileDeviceOnly = false; + bool EmitLLVM = false; + bool EmitAsm = false; /// List of GPU architectures to use in this compilation. SmallVector<CudaArch, 4> GpuArchList; @@ -2324,6 +2350,10 @@ class OffloadingActionBuilder final { /// Flag for -fgpu-rdc. bool Relocatable = false; + + /// Default GPU architecture if there's no one specified. + CudaArch DefaultCudaArch = CudaArch::UNKNOWN; + public: CudaActionBuilderBase(Compilation &C, DerivedArgList &Args, const Driver::InputList &Inputs, @@ -2475,6 +2505,8 @@ class OffloadingActionBuilder final { CompileDeviceOnly = PartialCompilationArg && PartialCompilationArg->getOption().matches( options::OPT_cuda_device_only); + EmitLLVM = Args.getLastArg(options::OPT_emit_llvm); + EmitAsm = Args.getLastArg(options::OPT_S); // Collect all cuda_gpu_arch parameters, removing duplicates. std::set<CudaArch> GpuArchs; @@ -2511,7 +2543,7 @@ class OffloadingActionBuilder final { // supported GPUs. sm_20 code should work correctly, if // suboptimally, on all newer GPUs. if (GpuArchList.empty()) - GpuArchList.push_back(CudaArch::SM_20); + GpuArchList.push_back(DefaultCudaArch); return Error; } @@ -2523,7 +2555,9 @@ class OffloadingActionBuilder final { public: CudaActionBuilder(Compilation &C, DerivedArgList &Args, const Driver::InputList &Inputs) - : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) {} + : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) { + DefaultCudaArch = CudaArch::SM_20; + } ActionBuilderReturnCode getDeviceDependences(OffloadAction::DeviceDependences &DA, @@ -2638,7 +2672,9 @@ class OffloadingActionBuilder final { public: HIPActionBuilder(Compilation &C, DerivedArgList &Args, const Driver::InputList &Inputs) - : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {} + : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) { + DefaultCudaArch = CudaArch::GFX803; + } bool canUseBundlerUnbundler() const override { return true; } @@ -2661,7 +2697,8 @@ class OffloadingActionBuilder final { assert(!CompileHostOnly && "Not expecting CUDA actions in host-only compilation."); - if (!Relocatable && CurPhase == phases::Backend) { + if (!Relocatable && CurPhase == phases::Backend && !EmitLLVM && + !EmitAsm) { // If we are in backend phase, we attempt to generate the fat binary. // We compile each arch to IR and use a link action to generate code // object containing ISA. Then we use a special "link" action to create @@ -2729,7 +2766,8 @@ class OffloadingActionBuilder final { A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A, AssociatedOffloadKind); - return ABRT_Success; + return (CompileDeviceOnly && CurPhase == FinalPhase) ? ABRT_Ignore_Host + : ABRT_Success; } void appendLinkDependences(OffloadAction::DeviceDependences &DA) override { @@ -2870,7 +2908,7 @@ class OffloadingActionBuilder final { OpenMPDeviceActions.clear(); } - void appendLinkDependences(OffloadAction::DeviceDependences &DA) override { + void appendLinkActions(ActionList &AL) override { assert(ToolChains.size() == DeviceLinkerInputs.size() && "Toolchains and linker inputs sizes do not match."); @@ -2879,12 +2917,18 @@ class OffloadingActionBuilder final { for (auto &LI : DeviceLinkerInputs) { auto *DeviceLinkAction = C.MakeAction<LinkJobAction>(LI, types::TY_Image); - DA.add(*DeviceLinkAction, **TC, /*BoundArch=*/nullptr, - Action::OFK_OpenMP); + OffloadAction::DeviceDependences DeviceLinkDeps; + DeviceLinkDeps.add(*DeviceLinkAction, **TC, /*BoundArch=*/nullptr, + Action::OFK_OpenMP); + AL.push_back(C.MakeAction<OffloadAction>(DeviceLinkDeps, + DeviceLinkAction->getType())); ++TC; } + DeviceLinkerInputs.clear(); } + void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {} + bool initialize() override { // Get the OpenMP toolchains. If we don't get any, the action builder will // know there is nothing to do related to OpenMP offloading. @@ -3088,7 +3132,8 @@ public: // the resulting list. Otherwise, just append the device actions. For // device only compilation, HostAction is a null pointer, therefore only do // this when HostAction is not a null pointer. - if (CanUseBundler && HostAction && !OffloadAL.empty()) { + if (CanUseBundler && HostAction && + HostAction->getType() != types::TY_Nothing && !OffloadAL.empty()) { // Add the host action to the list in order to create the bundling action. OffloadAL.push_back(HostAction); @@ -3108,6 +3153,25 @@ public: return false; } + Action* makeHostLinkAction() { + // Build a list of device linking actions. + ActionList DeviceAL; + for (DeviceActionBuilder *SB : SpecializedBuilders) { + if (!SB->isValid()) + continue; + SB->appendLinkActions(DeviceAL); + } + + if (DeviceAL.empty()) + return nullptr; + + // Create wrapper bitcode from the result of device link actions and compile + // it to an object which will be added to the host link command. + auto *BC = C.MakeAction<OffloadWrapperJobAction>(DeviceAL, types::TY_LLVM_BC); + auto *ASM = C.MakeAction<BackendJobAction>(BC, types::TY_PP_Asm); + return C.MakeAction<AssembleJobAction>(ASM, types::TY_Object); + } + /// Processes the host linker action. This currently consists of replacing it /// with an offload action if there are device link objects and propagate to /// the host action all the offload kinds used in the current compilation. The @@ -3148,63 +3212,9 @@ public: }; } // anonymous namespace. -void Driver::BuildActions(Compilation &C, DerivedArgList &Args, - const InputList &Inputs, ActionList &Actions) const { - llvm::PrettyStackTraceString CrashInfo("Building compilation actions"); - - if (!SuppressMissingInputWarning && Inputs.empty()) { - Diag(clang::diag::err_drv_no_input_files); - return; - } - - Arg *FinalPhaseArg; - phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg); - - if (FinalPhase == phases::Link) { - if (Args.hasArg(options::OPT_emit_llvm)) - Diag(clang::diag::err_drv_emit_llvm_link); - if (IsCLMode() && LTOMode != LTOK_None && - !Args.getLastArgValue(options::OPT_fuse_ld_EQ).equals_lower("lld")) - Diag(clang::diag::err_drv_lto_without_lld); - } - - // Reject -Z* at the top level, these options should never have been exposed - // by gcc. - if (Arg *A = Args.getLastArg(options::OPT_Z_Joined)) - Diag(clang::diag::err_drv_use_of_Z_option) << A->getAsString(Args); - - // Diagnose misuse of /Fo. - if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) { - StringRef V = A->getValue(); - if (Inputs.size() > 1 && !V.empty() && - !llvm::sys::path::is_separator(V.back())) { - // Check whether /Fo tries to name an output file for multiple inputs. - Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) - << A->getSpelling() << V; - Args.eraseArg(options::OPT__SLASH_Fo); - } - } - - // Diagnose misuse of /Fa. - if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) { - StringRef V = A->getValue(); - if (Inputs.size() > 1 && !V.empty() && - !llvm::sys::path::is_separator(V.back())) { - // Check whether /Fa tries to name an asm file for multiple inputs. - Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) - << A->getSpelling() << V; - Args.eraseArg(options::OPT__SLASH_Fa); - } - } - - // Diagnose misuse of /o. - if (Arg *A = Args.getLastArg(options::OPT__SLASH_o)) { - if (A->getValue()[0] == '\0') { - // It has to have a value. - Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1; - Args.eraseArg(options::OPT__SLASH_o); - } - } +void Driver::handleArguments(Compilation &C, DerivedArgList &Args, + const InputList &Inputs, + ActionList &Actions) const { // Ignore /Yc/Yu if both /Yc and /Yu passed but with different filenames. Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc); @@ -3220,6 +3230,18 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, Args.eraseArg(options::OPT__SLASH_Yc); YcArg = nullptr; } + + Arg *FinalPhaseArg; + phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg); + + if (FinalPhase == phases::Link) { + if (Args.hasArg(options::OPT_emit_llvm)) + Diag(clang::diag::err_drv_emit_llvm_link); + if (IsCLMode() && LTOMode != LTOK_None && + !Args.getLastArgValue(options::OPT_fuse_ld_EQ).equals_lower("lld")) + Diag(clang::diag::err_drv_lto_without_lld); + } + if (FinalPhase == phases::Preprocess || Args.hasArg(options::OPT__SLASH_Y_)) { // If only preprocessing or /Y- is used, all pch handling is disabled. // Rather than check for it everywhere, just remove clang-cl pch-related @@ -3230,20 +3252,14 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, YcArg = YuArg = nullptr; } - // Builder to be used to build offloading actions. - OffloadingActionBuilder OffloadBuilder(C, Args, Inputs); - - // Construct the actions to perform. - HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr; - ActionList LinkerInputs; - - llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL; + unsigned LastPLSize = 0; for (auto &I : Inputs) { types::ID InputType = I.first; const Arg *InputArg = I.second; - PL.clear(); + llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL; types::getCompilationPhases(InputType, PL); + LastPLSize = PL.size(); // If the first step comes after the final phase we are doing as part of // this compilation, warn the user about it. @@ -3267,7 +3283,10 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, // Special case '-E' warning on a previously preprocessed file to make // more sense. else if (InitialPhase == phases::Compile && - FinalPhase == phases::Preprocess && + (Args.getLastArg(options::OPT__SLASH_EP, + options::OPT__SLASH_P) || + Args.getLastArg(options::OPT_E) || + Args.getLastArg(options::OPT_M, options::OPT_MM)) && getPreprocessedType(InputType) == types::TY_INVALID) Diag(clang::diag::warn_drv_preprocessed_input_file_unused) << InputArg->getAsString(Args) << !!FinalPhaseArg @@ -3287,8 +3306,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PCHPL; types::getCompilationPhases(HeaderType, PCHPL); // Build the pipeline for the pch file. - Action *ClangClPch = - C.MakeAction<InputAction>(*InputArg, HeaderType); + Action *ClangClPch = C.MakeAction<InputAction>(*InputArg, HeaderType); for (phases::ID Phase : PCHPL) ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch); assert(ClangClPch); @@ -3300,6 +3318,85 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, // probably not be considered successful either. } } + } + + // If we are linking, claim any options which are obviously only used for + // compilation. + // FIXME: Understand why the last Phase List length is used here. + if (FinalPhase == phases::Link && LastPLSize == 1) { + Args.ClaimAllArgs(options::OPT_CompileOnly_Group); + Args.ClaimAllArgs(options::OPT_cl_compile_Group); + } +} + +void Driver::BuildActions(Compilation &C, DerivedArgList &Args, + const InputList &Inputs, ActionList &Actions) const { + llvm::PrettyStackTraceString CrashInfo("Building compilation actions"); + + if (!SuppressMissingInputWarning && Inputs.empty()) { + Diag(clang::diag::err_drv_no_input_files); + return; + } + + // Reject -Z* at the top level, these options should never have been exposed + // by gcc. + if (Arg *A = Args.getLastArg(options::OPT_Z_Joined)) + Diag(clang::diag::err_drv_use_of_Z_option) << A->getAsString(Args); + + // Diagnose misuse of /Fo. + if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) { + StringRef V = A->getValue(); + if (Inputs.size() > 1 && !V.empty() && + !llvm::sys::path::is_separator(V.back())) { + // Check whether /Fo tries to name an output file for multiple inputs. + Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) + << A->getSpelling() << V; + Args.eraseArg(options::OPT__SLASH_Fo); + } + } + + // Diagnose misuse of /Fa. + if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) { + StringRef V = A->getValue(); + if (Inputs.size() > 1 && !V.empty() && + !llvm::sys::path::is_separator(V.back())) { + // Check whether /Fa tries to name an asm file for multiple inputs. + Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) + << A->getSpelling() << V; + Args.eraseArg(options::OPT__SLASH_Fa); + } + } + + // Diagnose misuse of /o. + if (Arg *A = Args.getLastArg(options::OPT__SLASH_o)) { + if (A->getValue()[0] == '\0') { + // It has to have a value. + Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1; + Args.eraseArg(options::OPT__SLASH_o); + } + } + + handleArguments(C, Args, Inputs, Actions); + + // Builder to be used to build offloading actions. + OffloadingActionBuilder OffloadBuilder(C, Args, Inputs); + + // Construct the actions to perform. + HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr; + ActionList LinkerInputs; + ActionList MergerInputs; + + for (auto &I : Inputs) { + types::ID InputType = I.first; + const Arg *InputArg = I.second; + + llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL; + types::getCompilationPhases(*this, Args, InputType, PL); + if (PL.empty()) + continue; + + llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> FullPL; + types::getCompilationPhases(InputType, FullPL); // Build the pipeline for this file. Action *Current = C.MakeAction<InputAction>(*InputArg, InputType); @@ -3309,28 +3406,33 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg)) break; - for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end(); - i != e; ++i) { - phases::ID Phase = *i; - - // We are done if this step is past what the user requested. - if (Phase > FinalPhase) - break; + for (phases::ID Phase : PL) { // Add any offload action the host action depends on. Current = OffloadBuilder.addDeviceDependencesToHostAction( - Current, InputArg, Phase, FinalPhase, PL); + Current, InputArg, Phase, PL.back(), FullPL); if (!Current) break; // Queue linker inputs. if (Phase == phases::Link) { - assert((i + 1) == e && "linking must be final compilation step."); + assert(Phase == PL.back() && "linking must be final compilation step."); LinkerInputs.push_back(Current); Current = nullptr; break; } + // TODO: Consider removing this because the merged may not end up being + // the final Phase in the pipeline. Perhaps the merged could just merge + // and then pass an artifact of some sort to the Link Phase. + // Queue merger inputs. + if (Phase == phases::IfsMerge) { + assert(Phase == PL.back() && "merging must be final compilation step."); + MergerInputs.push_back(Current); + Current = nullptr; + break; + } + // Each precompiled header file after a module file action is a module // header of that same module file, rather than being compiled to a // separate PCH. @@ -3375,17 +3477,17 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, // Add a link action if necessary. if (!LinkerInputs.empty()) { + if (Action *Wrapper = OffloadBuilder.makeHostLinkAction()) + LinkerInputs.push_back(Wrapper); Action *LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image); LA = OffloadBuilder.processHostLinkAction(LA); Actions.push_back(LA); } - // If we are linking, claim any options which are obviously only used for - // compilation. - if (FinalPhase == phases::Link && PL.size() == 1) { - Args.ClaimAllArgs(options::OPT_CompileOnly_Group); - Args.ClaimAllArgs(options::OPT_cl_compile_Group); - } + // Add an interface stubs merge action if necessary. + if (!MergerInputs.empty()) + Actions.push_back( + C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image)); // If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a custom // Compile phase that prints out supported cpu models and quits. @@ -3423,10 +3525,14 @@ Action *Driver::ConstructPhaseAction( switch (Phase) { case phases::Link: llvm_unreachable("link action invalid here."); + case phases::IfsMerge: + llvm_unreachable("ifsmerge action invalid here."); case phases::Preprocess: { types::ID OutputTy; - // -{M, MM} alter the output type. - if (Args.hasArg(options::OPT_M, options::OPT_MM)) { + // -M and -MM specify the dependency file name by altering the output type, + // -if -MD and -MMD are not specified. + if (Args.hasArg(options::OPT_M, options::OPT_MM) && + !Args.hasArg(options::OPT_MD, options::OPT_MMD)) { OutputTy = types::TY_Dependencies; } else { OutputTy = Input->getType(); @@ -3474,7 +3580,7 @@ Action *Driver::ConstructPhaseAction( if (Args.hasArg(options::OPT_rewrite_legacy_objc)) return C.MakeAction<CompileJobAction>(Input, types::TY_RewrittenLegacyObjC); - if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) + if (Args.hasArg(options::OPT__analyze)) return C.MakeAction<AnalyzeJobAction>(Input, types::TY_Plist); if (Args.hasArg(options::OPT__migrate)) return C.MakeAction<MigrateJobAction>(Input, types::TY_Remap); @@ -3484,8 +3590,8 @@ Action *Driver::ConstructPhaseAction( return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile); if (Args.hasArg(options::OPT_verify_pch)) return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing); - if (Args.hasArg(options::OPT_emit_iterface_stubs)) - return C.MakeAction<CompileJobAction>(Input, types::TY_IFS); + if (Args.hasArg(options::OPT_emit_interface_stubs)) + return C.MakeAction<CompileJobAction>(Input, types::TY_IFS_CPP); return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC); } case phases::Backend: { @@ -3759,18 +3865,8 @@ class ToolSelector final { if (!AJ || !BJ) return nullptr; - // Retrieve the compile job, backend action must always be preceded by one. - ActionList CompileJobOffloadActions; - auto *CJ = getPrevDependentAction(BJ->getInputs(), CompileJobOffloadActions, - /*CanBeCollapsed=*/false); - if (!AJ || !BJ || !CJ) - return nullptr; - - assert(isa<CompileJobAction>(CJ) && - "Expecting compile job preceding backend job."); - - // Get compiler tool. - const Tool *T = TC.SelectTool(*CJ); + // Get backend tool. + const Tool *T = TC.SelectTool(*BJ); if (!T) return nullptr; @@ -4175,6 +4271,13 @@ InputInfo Driver::BuildJobsForActionNoCache( A->getOffloadingDeviceKind(), TC->getTriple().normalize(), /*CreatePrefixForHost=*/!!A->getOffloadingHostActiveKinds() && !AtTopLevel); + if (isa<OffloadWrapperJobAction>(JA)) { + OffloadingPrefix += "-wrapper"; + if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) + BaseInput = FinalOutput->getValue(); + else + BaseInput = getDefaultImageName(); + } Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch, AtTopLevel, MultipleArchs, OffloadingPrefix), @@ -4358,11 +4461,22 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, MakeCLOutputFilename(C.getArgs(), "", BaseName, types::TY_Image); } else { SmallString<128> Output(getDefaultImageName()); + // HIP image for device compilation with -fno-gpu-rdc is per compilation + // unit. + bool IsHIPNoRDC = JA.getOffloadingDeviceKind() == Action::OFK_HIP && + !C.getArgs().hasFlag(options::OPT_fgpu_rdc, + options::OPT_fno_gpu_rdc, false); + if (IsHIPNoRDC) { + Output = BaseName; + llvm::sys::path::replace_extension(Output, ""); + } Output += OffloadingPrefix; if (MultipleArchs && !BoundArch.empty()) { Output += "-"; Output.append(BoundArch); } + if (IsHIPNoRDC) + Output += ".out"; NamedOutput = C.getArgs().MakeArgString(Output.c_str()); } } else if (JA.getType() == types::TY_PCH && IsCLMode()) { @@ -4586,152 +4700,152 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, if (!TC) { switch (Target.getOS()) { case llvm::Triple::Haiku: - TC = llvm::make_unique<toolchains::Haiku>(*this, Target, Args); + TC = std::make_unique<toolchains::Haiku>(*this, Target, Args); break; case llvm::Triple::Ananas: - TC = llvm::make_unique<toolchains::Ananas>(*this, Target, Args); + TC = std::make_unique<toolchains::Ananas>(*this, Target, Args); break; case llvm::Triple::CloudABI: - TC = llvm::make_unique<toolchains::CloudABI>(*this, Target, Args); + TC = std::make_unique<toolchains::CloudABI>(*this, Target, Args); break; case llvm::Triple::Darwin: case llvm::Triple::MacOSX: case llvm::Triple::IOS: case llvm::Triple::TvOS: case llvm::Triple::WatchOS: - TC = llvm::make_unique<toolchains::DarwinClang>(*this, Target, Args); + TC = std::make_unique<toolchains::DarwinClang>(*this, Target, Args); break; case llvm::Triple::DragonFly: - TC = llvm::make_unique<toolchains::DragonFly>(*this, Target, Args); + TC = std::make_unique<toolchains::DragonFly>(*this, Target, Args); break; case llvm::Triple::OpenBSD: - TC = llvm::make_unique<toolchains::OpenBSD>(*this, Target, Args); + TC = std::make_unique<toolchains::OpenBSD>(*this, Target, Args); break; case llvm::Triple::NetBSD: - TC = llvm::make_unique<toolchains::NetBSD>(*this, Target, Args); + TC = std::make_unique<toolchains::NetBSD>(*this, Target, Args); break; case llvm::Triple::FreeBSD: - TC = llvm::make_unique<toolchains::FreeBSD>(*this, Target, Args); + TC = std::make_unique<toolchains::FreeBSD>(*this, Target, Args); break; case llvm::Triple::Minix: - TC = llvm::make_unique<toolchains::Minix>(*this, Target, Args); + TC = std::make_unique<toolchains::Minix>(*this, Target, Args); break; case llvm::Triple::Linux: case llvm::Triple::ELFIAMCU: if (Target.getArch() == llvm::Triple::hexagon) - TC = llvm::make_unique<toolchains::HexagonToolChain>(*this, Target, + TC = std::make_unique<toolchains::HexagonToolChain>(*this, Target, Args); else if ((Target.getVendor() == llvm::Triple::MipsTechnologies) && !Target.hasEnvironment()) - TC = llvm::make_unique<toolchains::MipsLLVMToolChain>(*this, Target, + TC = std::make_unique<toolchains::MipsLLVMToolChain>(*this, Target, Args); else if (Target.getArch() == llvm::Triple::ppc || Target.getArch() == llvm::Triple::ppc64 || Target.getArch() == llvm::Triple::ppc64le) - TC = llvm::make_unique<toolchains::PPCLinuxToolChain>(*this, Target, + TC = std::make_unique<toolchains::PPCLinuxToolChain>(*this, Target, Args); else - TC = llvm::make_unique<toolchains::Linux>(*this, Target, Args); + TC = std::make_unique<toolchains::Linux>(*this, Target, Args); break; case llvm::Triple::NaCl: - TC = llvm::make_unique<toolchains::NaClToolChain>(*this, Target, Args); + TC = std::make_unique<toolchains::NaClToolChain>(*this, Target, Args); break; case llvm::Triple::Fuchsia: - TC = llvm::make_unique<toolchains::Fuchsia>(*this, Target, Args); + TC = std::make_unique<toolchains::Fuchsia>(*this, Target, Args); break; case llvm::Triple::Solaris: - TC = llvm::make_unique<toolchains::Solaris>(*this, Target, Args); + TC = std::make_unique<toolchains::Solaris>(*this, Target, Args); break; case llvm::Triple::AMDHSA: case llvm::Triple::AMDPAL: case llvm::Triple::Mesa3D: - TC = llvm::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args); + TC = std::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args); break; case llvm::Triple::Win32: switch (Target.getEnvironment()) { default: if (Target.isOSBinFormatELF()) - TC = llvm::make_unique<toolchains::Generic_ELF>(*this, Target, Args); + TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args); else if (Target.isOSBinFormatMachO()) - TC = llvm::make_unique<toolchains::MachO>(*this, Target, Args); + TC = std::make_unique<toolchains::MachO>(*this, Target, Args); else - TC = llvm::make_unique<toolchains::Generic_GCC>(*this, Target, Args); + TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args); break; case llvm::Triple::GNU: - TC = llvm::make_unique<toolchains::MinGW>(*this, Target, Args); + TC = std::make_unique<toolchains::MinGW>(*this, Target, Args); break; case llvm::Triple::Itanium: - TC = llvm::make_unique<toolchains::CrossWindowsToolChain>(*this, Target, + TC = std::make_unique<toolchains::CrossWindowsToolChain>(*this, Target, Args); break; case llvm::Triple::MSVC: case llvm::Triple::UnknownEnvironment: if (Args.getLastArgValue(options::OPT_fuse_ld_EQ) .startswith_lower("bfd")) - TC = llvm::make_unique<toolchains::CrossWindowsToolChain>( + TC = std::make_unique<toolchains::CrossWindowsToolChain>( *this, Target, Args); else TC = - llvm::make_unique<toolchains::MSVCToolChain>(*this, Target, Args); + std::make_unique<toolchains::MSVCToolChain>(*this, Target, Args); break; } break; case llvm::Triple::PS4: - TC = llvm::make_unique<toolchains::PS4CPU>(*this, Target, Args); + TC = std::make_unique<toolchains::PS4CPU>(*this, Target, Args); break; case llvm::Triple::Contiki: - TC = llvm::make_unique<toolchains::Contiki>(*this, Target, Args); + TC = std::make_unique<toolchains::Contiki>(*this, Target, Args); break; case llvm::Triple::Hurd: - TC = llvm::make_unique<toolchains::Hurd>(*this, Target, Args); + TC = std::make_unique<toolchains::Hurd>(*this, Target, Args); break; default: // Of these targets, Hexagon is the only one that might have // an OS of Linux, in which case it got handled above already. switch (Target.getArch()) { case llvm::Triple::tce: - TC = llvm::make_unique<toolchains::TCEToolChain>(*this, Target, Args); + TC = std::make_unique<toolchains::TCEToolChain>(*this, Target, Args); break; case llvm::Triple::tcele: - TC = llvm::make_unique<toolchains::TCELEToolChain>(*this, Target, Args); + TC = std::make_unique<toolchains::TCELEToolChain>(*this, Target, Args); break; case llvm::Triple::hexagon: - TC = llvm::make_unique<toolchains::HexagonToolChain>(*this, Target, + TC = std::make_unique<toolchains::HexagonToolChain>(*this, Target, Args); break; case llvm::Triple::lanai: - TC = llvm::make_unique<toolchains::LanaiToolChain>(*this, Target, Args); + TC = std::make_unique<toolchains::LanaiToolChain>(*this, Target, Args); break; case llvm::Triple::xcore: - TC = llvm::make_unique<toolchains::XCoreToolChain>(*this, Target, Args); + TC = std::make_unique<toolchains::XCoreToolChain>(*this, Target, Args); break; case llvm::Triple::wasm32: case llvm::Triple::wasm64: - TC = llvm::make_unique<toolchains::WebAssembly>(*this, Target, Args); + TC = std::make_unique<toolchains::WebAssembly>(*this, Target, Args); break; case llvm::Triple::avr: - TC = llvm::make_unique<toolchains::AVRToolChain>(*this, Target, Args); + TC = std::make_unique<toolchains::AVRToolChain>(*this, Target, Args); break; case llvm::Triple::msp430: TC = - llvm::make_unique<toolchains::MSP430ToolChain>(*this, Target, Args); + std::make_unique<toolchains::MSP430ToolChain>(*this, Target, Args); break; case llvm::Triple::riscv32: case llvm::Triple::riscv64: - TC = llvm::make_unique<toolchains::RISCVToolChain>(*this, Target, Args); + TC = std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args); break; default: if (Target.getVendor() == llvm::Triple::Myriad) - TC = llvm::make_unique<toolchains::MyriadToolChain>(*this, Target, + TC = std::make_unique<toolchains::MyriadToolChain>(*this, Target, Args); else if (toolchains::BareMetal::handlesTarget(Target)) - TC = llvm::make_unique<toolchains::BareMetal>(*this, Target, Args); + TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args); else if (Target.isOSBinFormatELF()) - TC = llvm::make_unique<toolchains::Generic_ELF>(*this, Target, Args); + TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args); else if (Target.isOSBinFormatMachO()) - TC = llvm::make_unique<toolchains::MachO>(*this, Target, Args); + TC = std::make_unique<toolchains::MachO>(*this, Target, Args); else - TC = llvm::make_unique<toolchains::Generic_GCC>(*this, Target, Args); + TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args); } } } diff --git a/lib/Driver/DriverOptions.cpp b/lib/Driver/DriverOptions.cpp index 1ad188838edaf..67d4198d222aa 100644 --- a/lib/Driver/DriverOptions.cpp +++ b/lib/Driver/DriverOptions.cpp @@ -39,14 +39,17 @@ public: } -std::unique_ptr<OptTable> clang::driver::createDriverOptTable() { - auto Result = llvm::make_unique<DriverOptTable>(); - // Options.inc is included in DriverOptions.cpp, and calls OptTable's - // addValues function. - // Opt is a variable used in the code fragment in Options.inc. - OptTable &Opt = *Result; +const llvm::opt::OptTable &clang::driver::getDriverOptTable() { + static const DriverOptTable *Table = []() { + auto Result = std::make_unique<DriverOptTable>(); + // Options.inc is included in DriverOptions.cpp, and calls OptTable's + // addValues function. + // Opt is a variable used in the code fragment in Options.inc. + OptTable &Opt = *Result; #define OPTTABLE_ARG_INIT #include "clang/Driver/Options.inc" #undef OPTTABLE_ARG_INIT - return std::move(Result); + return Result.release(); + }(); + return *Table; } diff --git a/lib/Driver/Phases.cpp b/lib/Driver/Phases.cpp index 5b776c63f713a..01598c59bd9eb 100644 --- a/lib/Driver/Phases.cpp +++ b/lib/Driver/Phases.cpp @@ -20,6 +20,7 @@ const char *phases::getPhaseName(ID Id) { case Backend: return "backend"; case Assemble: return "assembler"; case Link: return "linker"; + case IfsMerge: return "ifsmerger"; } llvm_unreachable("Invalid phase id."); diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index 6b6a9feec42c5..cc6c5e6ef438d 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -46,7 +46,8 @@ static const SanitizerMask SupportsCoverage = SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | SanitizerKind::DataFlow | SanitizerKind::Fuzzer | - SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero; + SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero | + SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack; static const SanitizerMask RecoverableByDefault = SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | @@ -635,6 +636,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, D.Diag(diag::err_drv_argument_not_allowed_with) << "-fsanitize-cfi-cross-dso" << "-fsanitize-cfi-icall-generalize-pointers"; + + CfiCanonicalJumpTables = + Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables, + options::OPT_fno_sanitize_cfi_canonical_jump_tables, true); } Stats = Args.hasFlag(options::OPT_fsanitize_stats, @@ -824,9 +829,15 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, SafeStackRuntime = !TC.getTriple().isOSFuchsia(); } + LinkRuntimes = + Args.hasFlag(options::OPT_fsanitize_link_runtime, + options::OPT_fno_sanitize_link_runtime, LinkRuntimes); + // Parse -link-cxx-sanitizer flag. - LinkCXXRuntimes = - Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX(); + LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime, + options::OPT_fno_sanitize_link_cxx_runtime, + LinkCXXRuntimes) || + D.CCCIsCXX(); // Finally, initialize the set of available and recoverable sanitizers. Sanitizers.Mask |= Kinds; @@ -862,6 +873,18 @@ static void addIncludeLinkerOption(const ToolChain &TC, CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag)); } +static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) { + for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End; ++Start) { + auto It = std::find(Start, End, StringRef("+mte")); + if (It == End) + break; + if (It > Start && *std::prev(It) == StringRef("-target-feature")) + return true; + Start = It; + } + return false; +} + void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const { @@ -969,6 +992,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, if (CfiICallGeneralizePointers) CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers"); + if (CfiCanonicalJumpTables) + CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables"); + if (Stats) CmdArgs.push_back("-fsanitize-stats"); @@ -1006,6 +1032,11 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi)); } + if (Sanitizers.has(SanitizerKind::HWAddress)) { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+tagged-globals"); + } + // MSan: Workaround for PR16386. // ASan: This is mainly to help LSan with cases such as // https://github.com/google/sanitizers/issues/373 @@ -1024,6 +1055,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, Sanitizers.Mask & CFIClasses) << "-fvisibility="; } + + if (Sanitizers.has(SanitizerKind::MemTag) && !hasTargetFeatureMTE(CmdArgs)) + TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature); } SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index b1fddb0af55d2..357a5106ab393 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -10,6 +10,7 @@ #include "InputInfo.h" #include "ToolChains/Arch/ARM.h" #include "ToolChains/Clang.h" +#include "ToolChains/InterfaceStubs.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Sanitizers.h" #include "clang/Config/config.h" @@ -279,17 +280,32 @@ Tool *ToolChain::getLink() const { return Link.get(); } +Tool *ToolChain::getIfsMerge() const { + if (!IfsMerge) + IfsMerge.reset(new tools::ifstool::Merger(*this)); + return IfsMerge.get(); +} + Tool *ToolChain::getOffloadBundler() const { if (!OffloadBundler) OffloadBundler.reset(new tools::OffloadBundler(*this)); return OffloadBundler.get(); } +Tool *ToolChain::getOffloadWrapper() const { + if (!OffloadWrapper) + OffloadWrapper.reset(new tools::OffloadWrapper(*this)); + return OffloadWrapper.get(); +} + Tool *ToolChain::getTool(Action::ActionClass AC) const { switch (AC) { case Action::AssembleJobClass: return getAssemble(); + case Action::IfsMergeJobClass: + return getIfsMerge(); + case Action::LinkJobClass: return getLink(); @@ -314,6 +330,9 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::OffloadBundlingJobClass: case Action::OffloadUnbundlingJobClass: return getOffloadBundler(); + + case Action::OffloadWrapperJobClass: + return getOffloadWrapper(); } llvm_unreachable("Invalid tool kind."); @@ -832,6 +851,16 @@ void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ); } +void ToolChain::AddClangCXXStdlibIsystemArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem); + if (!DriverArgs.hasArg(options::OPT_nostdincxx)) + for (const auto &P : + DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem)) + addSystemInclude(DriverArgs, CC1Args, P); +} + bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const { return getDriver().CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, @@ -913,6 +942,9 @@ SanitizerMask ToolChain::getSupportedSanitizers() const { if (getTriple().getArch() == llvm::Triple::x86_64 || getTriple().getArch() == llvm::Triple::aarch64) Res |= SanitizerKind::ShadowCallStack; + if (getTriple().getArch() == llvm::Triple::aarch64 || + getTriple().getArch() == llvm::Triple::aarch64_be) + Res |= SanitizerKind::MemTag; return Res; } diff --git a/lib/Driver/ToolChains/AMDGPU.cpp b/lib/Driver/ToolChains/AMDGPU.cpp index df4e7ee202bfd..71a2c68b4197b 100644 --- a/lib/Driver/ToolChains/AMDGPU.cpp +++ b/lib/Driver/ToolChains/AMDGPU.cpp @@ -31,7 +31,7 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-shared"); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), CmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/AVR.cpp b/lib/Driver/ToolChains/AVR.cpp index 4a60d9ec589b7..e8a3a7b38c31f 100644 --- a/lib/Driver/ToolChains/AVR.cpp +++ b/lib/Driver/ToolChains/AVR.cpp @@ -144,7 +144,7 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName)); } - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), CmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/Ananas.cpp b/lib/Driver/ToolChains/Ananas.cpp index e3511198cb2d8..2f11c9739a0eb 100644 --- a/lib/Driver/ToolChains/Ananas.cpp +++ b/lib/Driver/ToolChains/Ananas.cpp @@ -39,7 +39,7 @@ void ananas::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -123,7 +123,7 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Ananas - Ananas tool chain which can call as(1) and ld(1) directly. diff --git a/lib/Driver/ToolChains/Arch/AArch64.cpp b/lib/Driver/ToolChains/Arch/AArch64.cpp index 35d11f4e2d3b3..3a5fe6ddeaed5 100644 --- a/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -12,6 +12,7 @@ #include "clang/Driver/Options.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/Host.h" using namespace clang::driver; using namespace clang::driver::tools; diff --git a/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp index d1db583e52802..68a57310ad402 100644 --- a/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/lib/Driver/ToolChains/Arch/ARM.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/Host.h" using namespace clang::driver; using namespace clang::driver::tools; @@ -460,11 +461,12 @@ fp16_fml_fallthrough: // now just be explicit and disable all known dependent features // as well. for (std::string Feature : { - "vfp2", "vfp2sp", "vfp2d16", "vfp2d16sp", + "vfp2", "vfp2sp", "vfp3", "vfp3sp", "vfp3d16", "vfp3d16sp", "vfp4", "vfp4sp", "vfp4d16", "vfp4d16sp", "fp-armv8", "fp-armv8sp", "fp-armv8d16", "fp-armv8d16sp", "fullfp16", "neon", "crypto", "dotprod", "fp16fml", + "mve", "mve.fp", "fp64", "d32", "fpregs"}) Features.push_back(Args.MakeArgString("-" + Feature)); } @@ -477,23 +479,35 @@ fp16_fml_fallthrough: Features.push_back("-crc"); } - // For Arch >= ARMv8.0: crypto = sha2 + aes + // For Arch >= ARMv8.0 && A profile: crypto = sha2 + aes // FIXME: this needs reimplementation after the TargetParser rewrite - if (ArchName.find_lower("armv8a") != StringRef::npos || - ArchName.find_lower("armv8.1a") != StringRef::npos || - ArchName.find_lower("armv8.2a") != StringRef::npos || - ArchName.find_lower("armv8.3a") != StringRef::npos || - ArchName.find_lower("armv8.4a") != StringRef::npos) { - if (ArchName.find_lower("+crypto") != StringRef::npos) { - if (ArchName.find_lower("+nosha2") == StringRef::npos) - Features.push_back("+sha2"); - if (ArchName.find_lower("+noaes") == StringRef::npos) - Features.push_back("+aes"); - } else if (ArchName.find_lower("-crypto") != StringRef::npos) { - if (ArchName.find_lower("+sha2") == StringRef::npos) - Features.push_back("-sha2"); - if (ArchName.find_lower("+aes") == StringRef::npos) - Features.push_back("-aes"); + auto CryptoIt = llvm::find_if(llvm::reverse(Features), [](const StringRef F) { + return F.contains("crypto"); + }); + if (CryptoIt != Features.rend()) { + if (CryptoIt->take_front() == "+") { + StringRef ArchSuffix = arm::getLLVMArchSuffixForARM( + arm::getARMTargetCPU(CPUName, ArchName, Triple), ArchName, Triple); + if (llvm::ARM::parseArchVersion(ArchSuffix) >= 8 && + llvm::ARM::parseArchProfile(ArchSuffix) == + llvm::ARM::ProfileKind::A) { + if (ArchName.find_lower("+nosha2") == StringRef::npos && + CPUName.find_lower("+nosha2") == StringRef::npos) + Features.push_back("+sha2"); + if (ArchName.find_lower("+noaes") == StringRef::npos && + CPUName.find_lower("+noaes") == StringRef::npos) + Features.push_back("+aes"); + } else { + D.Diag(clang::diag::warn_target_unsupported_extension) + << "crypto" + << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix)); + // With -fno-integrated-as -mfpu=crypto-neon-fp-armv8 some assemblers such as the GNU assembler + // will permit the use of crypto instructions as the fpu will override the architecture. + // We keep the crypto feature in this case to preserve compatibility. + // In all other cases we remove the crypto feature. + if (!Args.hasArg(options::OPT_fno_integrated_as)) + Features.push_back("-crypto"); + } } } @@ -655,7 +669,7 @@ std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch, llvm::ARM::ArchKind arm::getLLVMArchKindForARM(StringRef CPU, StringRef Arch, const llvm::Triple &Triple) { llvm::ARM::ArchKind ArchKind; - if (CPU == "generic") { + if (CPU == "generic" || CPU.empty()) { std::string ARMArch = tools::arm::getARMArch(Arch, Triple); ArchKind = llvm::ARM::parseArch(ARMArch); if (ArchKind == llvm::ARM::ArchKind::INVALID) diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp index b512ff64b0c62..7b4dd703c0c7e 100644 --- a/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/lib/Driver/ToolChains/Arch/Mips.cpp @@ -149,7 +149,8 @@ StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) { // Select the MIPS float ABI as determined by -msoft-float, -mhard-float, // and -mfloat-abi=. -mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args) { +mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args, + const llvm::Triple &Triple) { mips::FloatABI ABI = mips::FloatABI::Invalid; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, @@ -172,10 +173,15 @@ mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args) { // If unspecified, choose the default based on the platform. if (ABI == mips::FloatABI::Invalid) { - // Assume "hard", because it's a default value used by gcc. - // When we start to recognize specific target MIPS processors, - // we will be able to select the default more correctly. - ABI = mips::FloatABI::Hard; + if (Triple.isOSFreeBSD()) { + // For FreeBSD, assume "soft" on all flavors of MIPS. + ABI = mips::FloatABI::Soft; + } else { + // Assume "hard", because it's a default value used by gcc. + // When we start to recognize specific target MIPS processors, + // we will be able to select the default more correctly. + ABI = mips::FloatABI::Hard; + } } assert(ABI != mips::FloatABI::Invalid && "must select an ABI"); @@ -267,7 +273,14 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, D.Diag(diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1); } - mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args); + if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) { + if (A->getOption().matches(options::OPT_mxgot)) + Features.push_back("+xgot"); + else + Features.push_back("-xgot"); + } + + mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple); if (FloatABI == mips::FloatABI::Soft) { // FIXME: Note, this is a hack. We need to pass the selected float // mode to the MipsTargetInfoBase to define appropriate macros there. diff --git a/lib/Driver/ToolChains/Arch/Mips.h b/lib/Driver/ToolChains/Arch/Mips.h index 23e0cf79e154f..074012f40fe58 100644 --- a/lib/Driver/ToolChains/Arch/Mips.h +++ b/lib/Driver/ToolChains/Arch/Mips.h @@ -38,7 +38,8 @@ void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args, std::vector<StringRef> &Features); StringRef getGnuCompatibleMipsABIName(StringRef ABI); -mips::FloatABI getMipsFloatABI(const Driver &D, const llvm::opt::ArgList &Args); +mips::FloatABI getMipsFloatABI(const Driver &D, const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); std::string getMipsABILibSuffix(const llvm::opt::ArgList &Args, const llvm::Triple &Triple); bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value); diff --git a/lib/Driver/ToolChains/Arch/PPC.cpp b/lib/Driver/ToolChains/Arch/PPC.cpp index 30f1a0d9022c2..3e02e57e0f6c7 100644 --- a/lib/Driver/ToolChains/Arch/PPC.cpp +++ b/lib/Driver/ToolChains/Arch/PPC.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/Options.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/Host.h" using namespace clang::driver; using namespace clang::driver::tools; @@ -115,7 +116,8 @@ ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Tripl const ArgList &Args) { if (Args.getLastArg(options::OPT_msecure_plt)) return ppc::ReadGOTPtrMode::SecurePlt; - if (Triple.isOSNetBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) + if ((Triple.isOSFreeBSD() && Triple.getOSMajorVersion() >= 13) || + Triple.isOSNetBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) return ppc::ReadGOTPtrMode::SecurePlt; else return ppc::ReadGOTPtrMode::Bss; diff --git a/lib/Driver/ToolChains/Arch/RISCV.cpp b/lib/Driver/ToolChains/Arch/RISCV.cpp index b6768de4d2991..624788a5874e3 100644 --- a/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -12,6 +12,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "llvm/Option/ArgList.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/TargetParser.h" #include "llvm/Support/raw_ostream.h" #include "ToolChains/CommonArgs.h" @@ -189,168 +190,182 @@ static void getExtensionFeatures(const Driver &D, } } -void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args, - std::vector<StringRef> &Features) { - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - StringRef MArch = A->getValue(); +// Returns false if an error is diagnosed. +static bool getArchFeatures(const Driver &D, StringRef MArch, + std::vector<StringRef> &Features, + const ArgList &Args) { + // RISC-V ISA strings must be lowercase. + if (llvm::any_of(MArch, [](char c) { return isupper(c); })) { + D.Diag(diag::err_drv_invalid_riscv_arch_name) + << MArch << "string must be lowercase"; + return false; + } - // RISC-V ISA strings must be lowercase. - if (llvm::any_of(MArch, [](char c) { return isupper(c); })) { - D.Diag(diag::err_drv_invalid_riscv_arch_name) - << MArch << "string must be lowercase"; - return; - } + // ISA string must begin with rv32 or rv64. + if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) || + (MArch.size() < 5)) { + D.Diag(diag::err_drv_invalid_riscv_arch_name) + << MArch << "string must begin with rv32{i,e,g} or rv64{i,g}"; + return false; + } - // ISA string must begin with rv32 or rv64. - if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) || - (MArch.size() < 5)) { - D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch - << "string must begin with rv32{i,e,g} or rv64{i,g}"; - return; - } + bool HasRV64 = MArch.startswith("rv64"); + + // The canonical order specified in ISA manual. + // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 + StringRef StdExts = "mafdqlcbjtpvn"; + bool HasF = false, HasD = false; + char Baseline = MArch[4]; + + // First letter should be 'e', 'i' or 'g'. + switch (Baseline) { + default: + D.Diag(diag::err_drv_invalid_riscv_arch_name) + << MArch << "first letter should be 'e', 'i' or 'g'"; + return false; + case 'e': { + StringRef Error; + // Currently LLVM does not support 'e'. + // Extension 'e' is not allowed in rv64. + if (HasRV64) + Error = "standard user-level extension 'e' requires 'rv32'"; + else + Error = "unsupported standard user-level extension 'e'"; + D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch << Error; + return false; + } + case 'i': + break; + case 'g': + // g = imafd + StdExts = StdExts.drop_front(4); + Features.push_back("+m"); + Features.push_back("+a"); + Features.push_back("+f"); + Features.push_back("+d"); + HasF = true; + HasD = true; + break; + } - bool HasRV64 = MArch.startswith("rv64"); + // Skip rvxxx + StringRef Exts = MArch.substr(5); + + // Remove non-standard extensions and supervisor-level extensions. + // They have 'x', 's', 'sx' prefixes. Parse them at the end. + // Find the very first occurrence of 's' or 'x'. + StringRef OtherExts; + size_t Pos = Exts.find_first_of("sx"); + if (Pos != StringRef::npos) { + OtherExts = Exts.substr(Pos); + Exts = Exts.substr(0, Pos); + } - // The canonical order specified in ISA manual. - // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 - StringRef StdExts = "mafdqlcbjtpvn"; - bool HasF = false, HasD = false; - char Baseline = MArch[4]; + std::string Major, Minor; + if (!getExtensionVersion(D, MArch, std::string(1, Baseline), Exts, Major, + Minor)) + return false; - // First letter should be 'e', 'i' or 'g'. - switch (Baseline) { - default: - D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch - << "first letter should be 'e', 'i' or 'g'"; - return; - case 'e': { + // TODO: Use version number when setting target features + // and consume the underscore '_' that might follow. + + auto StdExtsItr = StdExts.begin(); + auto StdExtsEnd = StdExts.end(); + + for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) { + char c = *I; + + // Check ISA extensions are specified in the canonical order. + while (StdExtsItr != StdExtsEnd && *StdExtsItr != c) + ++StdExtsItr; + + if (StdExtsItr == StdExtsEnd) { + // Either c contains a valid extension but it was not given in + // canonical order or it is an invalid extension. StringRef Error; - // Currently LLVM does not support 'e'. - // Extension 'e' is not allowed in rv64. - if (HasRV64) - Error = "standard user-level extension 'e' requires 'rv32'"; + if (StdExts.contains(c)) + Error = "standard user-level extension not given in canonical order"; else - Error = "unsupported standard user-level extension 'e'"; - D.Diag(diag::err_drv_invalid_riscv_arch_name) - << MArch << Error; - return; + Error = "invalid standard user-level extension"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << std::string(1, c); + return false; } - case 'i': - break; - case 'g': - // g = imafd - StdExts = StdExts.drop_front(4); + + // Move to next char to prevent repeated letter. + ++StdExtsItr; + + if (std::next(I) != E) { + // Skip c. + std::string Next = std::string(std::next(I), E); + std::string Major, Minor; + if (!getExtensionVersion(D, MArch, std::string(1, c), Next, Major, Minor)) + return false; + + // TODO: Use version number when setting target features + // and consume the underscore '_' that might follow. + } + + // The order is OK, then push it into features. + switch (c) { + default: + // Currently LLVM supports only "mafdc". + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << "unsupported standard user-level extension" + << std::string(1, c); + return false; + case 'm': Features.push_back("+m"); + break; + case 'a': Features.push_back("+a"); + break; + case 'f': Features.push_back("+f"); - Features.push_back("+d"); HasF = true; + break; + case 'd': + Features.push_back("+d"); HasD = true; break; + case 'c': + Features.push_back("+c"); + break; } + } - // Skip rvxxx - StringRef Exts = MArch.substr(5); - - // Remove non-standard extensions and supervisor-level extensions. - // They have 'x', 's', 'sx' prefixes. Parse them at the end. - // Find the very first occurrence of 's' or 'x'. - StringRef OtherExts; - size_t Pos = Exts.find_first_of("sx"); - if (Pos != StringRef::npos) { - OtherExts = Exts.substr(Pos); - Exts = Exts.substr(0, Pos); - } - - std::string Major, Minor; - if (!getExtensionVersion(D, MArch, std::string(1, Baseline), - Exts, Major, Minor)) - return; - - // TODO: Use version number when setting target features - // and consume the underscore '_' that might follow. - - auto StdExtsItr = StdExts.begin(); - auto StdExtsEnd = StdExts.end(); - - for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) { - char c = *I; - - // Check ISA extensions are specified in the canonical order. - while (StdExtsItr != StdExtsEnd && *StdExtsItr != c) - ++StdExtsItr; - - if (StdExtsItr == StdExtsEnd) { - // Either c contains a valid extension but it was not given in - // canonical order or it is an invalid extension. - StringRef Error; - if (StdExts.contains(c)) - Error = "standard user-level extension not given in canonical order"; - else - Error = "invalid standard user-level extension"; - D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) - << MArch << Error << std::string(1, c); - return; - } - - // Move to next char to prevent repeated letter. - ++StdExtsItr; + // Dependency check. + // It's illegal to specify the 'd' (double-precision floating point) + // extension without also specifying the 'f' (single precision + // floating-point) extension. + if (HasD && !HasF) { + D.Diag(diag::err_drv_invalid_riscv_arch_name) + << MArch << "d requires f extension to also be specified"; + return false; + } - if (std::next(I) != E) { - // Skip c. - std::string Next = std::string(std::next(I), E); - std::string Major, Minor; - if (!getExtensionVersion(D, MArch, std::string(1, c), - Next, Major, Minor)) - return; - - // TODO: Use version number when setting target features - // and consume the underscore '_' that might follow. - } - - // The order is OK, then push it into features. - switch (c) { - default: - // Currently LLVM supports only "mafdc". - D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) - << MArch << "unsupported standard user-level extension" - << std::string(1, c); - return; - case 'm': - Features.push_back("+m"); - break; - case 'a': - Features.push_back("+a"); - break; - case 'f': - Features.push_back("+f"); - HasF = true; - break; - case 'd': - Features.push_back("+d"); - HasD = true; - break; - case 'c': - Features.push_back("+c"); - break; - } - } + // Additional dependency checks. + // TODO: The 'q' extension requires rv64. + // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. - // Dependency check. - // It's illegal to specify the 'd' (double-precision floating point) - // extension without also specifying the 'f' (single precision - // floating-point) extension. - if (HasD && !HasF) - D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch - << "d requires f extension to also be specified"; + // Handle all other types of extensions. + getExtensionFeatures(D, Args, Features, MArch, OtherExts); - // Additional dependency checks. - // TODO: The 'q' extension requires rv64. - // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. + return true; +} - // Handle all other types of extensions. - getExtensionFeatures(D, Args, Features, MArch, OtherExts); - } +void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, + std::vector<StringRef> &Features) { + llvm::Optional<StringRef> MArch; + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) + MArch = A->getValue(); + else if (Triple.getOS() == llvm::Triple::Linux) + // RISC-V Linux defaults to rv{32,64}gc. + MArch = Triple.getArch() == llvm::Triple::riscv32 ? "rv32gc" : "rv64gc"; + + if (MArch.hasValue() && !getArchFeatures(D, *MArch, Features, Args)) + return; // -mrelax is default, unless -mno-relax is specified. if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true)) @@ -372,8 +387,16 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args, } StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) { - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) + assert((Triple.getArch() == llvm::Triple::riscv32 || + Triple.getArch() == llvm::Triple::riscv64) && + "Unexpected triple"); + + if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) return A->getValue(); - return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64"; + // RISC-V Linux defaults to ilp32d/lp64d + if (Triple.getOS() == llvm::Triple::Linux) + return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32d" : "lp64d"; + else + return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64"; } diff --git a/lib/Driver/ToolChains/Arch/RISCV.h b/lib/Driver/ToolChains/Arch/RISCV.h index 443526900aae0..10eaf3c897b68 100644 --- a/lib/Driver/ToolChains/Arch/RISCV.h +++ b/lib/Driver/ToolChains/Arch/RISCV.h @@ -19,7 +19,8 @@ namespace clang { namespace driver { namespace tools { namespace riscv { -void getRISCVTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, +void getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, std::vector<llvm::StringRef> &Features); StringRef getRISCVABI(const llvm::opt::ArgList &Args, const llvm::Triple &Triple); diff --git a/lib/Driver/ToolChains/Arch/X86.cpp b/lib/Driver/ToolChains/Arch/X86.cpp index 34be226b69e98..d2b97bf6ad719 100644 --- a/lib/Driver/ToolChains/Arch/X86.cpp +++ b/lib/Driver/ToolChains/Arch/X86.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/Options.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/Host.h" using namespace clang::driver; using namespace clang::driver::tools; diff --git a/lib/Driver/ToolChains/BareMetal.cpp b/lib/Driver/ToolChains/BareMetal.cpp index 1544727050f4f..dff0e04183ef9 100644 --- a/lib/Driver/ToolChains/BareMetal.cpp +++ b/lib/Driver/ToolChains/BareMetal.cpp @@ -191,7 +191,7 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index cb861f27aedab..55d631733add2 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)); +} diff --git a/lib/Driver/ToolChains/Clang.h b/lib/Driver/ToolChains/Clang.h index fc4f5ecdd28a4..b345c02489d4d 100644 --- a/lib/Driver/ToolChains/Clang.h +++ b/lib/Driver/ToolChains/Clang.h @@ -95,6 +95,10 @@ private: const InputInfo &Output, const InputInfo &Input, const llvm::opt::ArgList &Args) const; + void DumpCompilationDatabaseFragmentToDir( + StringRef Dir, Compilation &C, StringRef Target, const InputInfo &Output, + const InputInfo &Input, const llvm::opt::ArgList &Args) const; + public: Clang(const ToolChain &TC); ~Clang() override; @@ -148,6 +152,20 @@ public: const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; + +/// Offload wrapper tool. +class LLVM_LIBRARY_VISIBILITY OffloadWrapper final : public Tool { +public: + OffloadWrapper(const ToolChain &TC) + : Tool("offload wrapper", "clang-offload-wrapper", TC) {} + + bool hasIntegratedCPP() const override { return false; } + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; + } // end namespace tools } // end namespace driver diff --git a/lib/Driver/ToolChains/CloudABI.cpp b/lib/Driver/ToolChains/CloudABI.cpp index cc1ac3ab7e790..cf1d0d551e570 100644 --- a/lib/Driver/ToolChains/CloudABI.cpp +++ b/lib/Driver/ToolChains/CloudABI.cpp @@ -92,7 +92,7 @@ void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // CloudABI - CloudABI tool chain which can call ld(1) directly. diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 99691cb43dc42..10743559e0481 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -11,8 +11,12 @@ #include "Arch/ARM.h" #include "Arch/Mips.h" #include "Arch/PPC.h" +#include "Arch/RISCV.h" +#include "Arch/Sparc.h" #include "Arch/SystemZ.h" #include "Arch/X86.h" +#include "AMDGPU.h" +#include "MSP430.h" #include "HIP.h" #include "Hexagon.h" #include "InputInfo.h" @@ -145,6 +149,11 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, // (constructed via -Xarch_). Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input); + // LIBRARY_PATH are included before user inputs and only supported on native + // toolchains. + if (!TC.isCrossCompiling()) + addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); + for (const auto &II : Inputs) { // If the current tool chain refers to an OpenMP or HIP offloading host, we // should ignore inputs that refer to OpenMP or HIP offloading devices - @@ -182,12 +191,6 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, A.renderAsInput(Args, CmdArgs); } } - - // LIBRARY_PATH - included following the user specified library paths. - // and only supported on native toolchains. - if (!TC.isCrossCompiling()) { - addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); - } } void tools::AddTargetFeature(const ArgList &Args, @@ -485,6 +488,14 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, if (!StatsFile.empty()) CmdArgs.push_back( Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile)); + + getTargetFeatures(ToolChain, ToolChain.getTriple(), Args, CmdArgs, + /* ForAS= */ false, /* ForLTOPlugin= */ true); + + StringRef ABIName = tools::getTargetABI(Args, ToolChain.getTriple()); + if (!ABIName.empty()) + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=-target-abi=") + ABIName)); } void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, @@ -501,30 +512,41 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, } bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, - const ArgList &Args, bool IsOffloadingHost, - bool GompNeedsRT) { + const ArgList &Args, bool ForceStaticHostRuntime, + bool IsOffloadingHost, bool GompNeedsRT) { if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, options::OPT_fno_openmp, false)) return false; - switch (TC.getDriver().getOpenMPRuntime(Args)) { + Driver::OpenMPRuntimeKind RTKind = TC.getDriver().getOpenMPRuntime(Args); + + if (RTKind == Driver::OMPRT_Unknown) + // Already diagnosed. + return false; + + if (ForceStaticHostRuntime) + CmdArgs.push_back("-Bstatic"); + + switch (RTKind) { case Driver::OMPRT_OMP: CmdArgs.push_back("-lomp"); break; case Driver::OMPRT_GOMP: CmdArgs.push_back("-lgomp"); - - if (GompNeedsRT) - CmdArgs.push_back("-lrt"); break; case Driver::OMPRT_IOMP5: CmdArgs.push_back("-liomp5"); break; case Driver::OMPRT_Unknown: - // Already diagnosed. - return false; + break; } + if (ForceStaticHostRuntime) + CmdArgs.push_back("-Bdynamic"); + + if (RTKind == Driver::OMPRT_GOMP && GompNeedsRT) + CmdArgs.push_back("-lrt"); + if (IsOffloadingHost) CmdArgs.push_back("-lomptarget"); @@ -605,29 +627,29 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); // Collect shared runtimes. if (SanArgs.needsSharedRt()) { - if (SanArgs.needsAsanRt()) { + if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) { SharedRuntimes.push_back("asan"); if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) HelperStaticRuntimes.push_back("asan-preinit"); } - if (SanArgs.needsUbsanRt()) { + if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) SharedRuntimes.push_back("ubsan_minimal"); else SharedRuntimes.push_back("ubsan_standalone"); } - if (SanArgs.needsScudoRt()) { + if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) SharedRuntimes.push_back("scudo_minimal"); else SharedRuntimes.push_back("scudo"); } - if (SanArgs.needsHwasanRt()) + if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) SharedRuntimes.push_back("hwasan"); } // The stats_client library is also statically linked into DSOs. - if (SanArgs.needsStatsRt()) + if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("stats_client"); // Collect static runtimes. @@ -635,32 +657,32 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, // Don't link static runtimes into DSOs or if -shared-libasan. return; } - if (SanArgs.needsAsanRt()) { + if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("asan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("asan_cxx"); } - if (SanArgs.needsHwasanRt()) { + if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("hwasan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("hwasan_cxx"); } - if (SanArgs.needsDfsanRt()) + if (SanArgs.needsDfsanRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("dfsan"); - if (SanArgs.needsLsanRt()) + if (SanArgs.needsLsanRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("lsan"); - if (SanArgs.needsMsanRt()) { + if (SanArgs.needsMsanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("msan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("msan_cxx"); } - if (SanArgs.needsTsanRt()) { + if (SanArgs.needsTsanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("tsan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("tsan_cxx"); } - if (SanArgs.needsUbsanRt()) { + if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) { StaticRuntimes.push_back("ubsan_minimal"); } else { @@ -669,22 +691,22 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, StaticRuntimes.push_back("ubsan_standalone_cxx"); } } - if (SanArgs.needsSafeStackRt()) { + if (SanArgs.needsSafeStackRt() && SanArgs.linkRuntimes()) { NonWholeStaticRuntimes.push_back("safestack"); RequiredSymbols.push_back("__safestack_init"); } - if (SanArgs.needsCfiRt()) + if (SanArgs.needsCfiRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("cfi"); - if (SanArgs.needsCfiDiagRt()) { + if (SanArgs.needsCfiDiagRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("cfi_diag"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("ubsan_standalone_cxx"); } - if (SanArgs.needsStatsRt()) { + if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) { NonWholeStaticRuntimes.push_back("stats"); RequiredSymbols.push_back("__sanitizer_stats_register"); } - if (SanArgs.needsScudoRt()) { + if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) { StaticRuntimes.push_back("scudo_minimal"); if (SanArgs.linkCXXRuntimes()) @@ -707,9 +729,10 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols); + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); // Inject libfuzzer dependencies. - if (TC.getSanitizerArgs().needsFuzzer() - && !Args.hasArg(options::OPT_shared)) { + if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() && + !Args.hasArg(options::OPT_shared)) { addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true); if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx)) @@ -738,7 +761,6 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, if (AddExportDynamic) CmdArgs.push_back("--export-dynamic"); - const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic) CmdArgs.push_back("-export-dynamic-symbol=__cfi_check"); @@ -823,10 +845,10 @@ void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename()); // First extract the dwo sections. - C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs, II)); + C.addCommand(std::make_unique<Command>(JA, T, Exec, ExtractArgs, II)); // Then remove them from the original .o file. - C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs, II)); + C.addCommand(std::make_unique<Command>(JA, T, Exec, StripArgs, II)); } // Claim options we don't want to warn if they are unused. We do this for @@ -1176,7 +1198,6 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, case ToolChain::UNW_None: return; case ToolChain::UNW_Libgcc: { - LibGccType LGT = getLibGccType(D, Args); if (LGT == LibGccType::StaticLibGcc) CmdArgs.push_back("-lgcc_eh"); else @@ -1235,131 +1256,6 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, } } -/// Add OpenMP linker script arguments at the end of the argument list so that -/// the fat binary is built by embedding each of the device images into the -/// host. The linker script also defines a few symbols required by the code -/// generation so that the images can be easily retrieved at runtime by the -/// offloading library. This should be used only in tool chains that support -/// linker scripts. -void tools::AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, ArgStringList &CmdArgs, - const JobAction &JA) { - - // If this is not an OpenMP host toolchain, we don't need to do anything. - if (!JA.isHostOffloading(Action::OFK_OpenMP)) - return; - - // Create temporary linker script. Keep it if save-temps is enabled. - const char *LKS; - SmallString<256> Name = llvm::sys::path::filename(Output.getFilename()); - if (C.getDriver().isSaveTempsEnabled()) { - llvm::sys::path::replace_extension(Name, "lk"); - LKS = C.getArgs().MakeArgString(Name.c_str()); - } else { - llvm::sys::path::replace_extension(Name, ""); - Name = C.getDriver().GetTemporaryPath(Name, "lk"); - LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str())); - } - - // Add linker script option to the command. - CmdArgs.push_back("-T"); - CmdArgs.push_back(LKS); - - // Create a buffer to write the contents of the linker script. - std::string LksBuffer; - llvm::raw_string_ostream LksStream(LksBuffer); - - // Get the OpenMP offload tool chains so that we can extract the triple - // associated with each device input. - auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>(); - assert(OpenMPToolChains.first != OpenMPToolChains.second && - "No OpenMP toolchains??"); - - // Track the input file name and device triple in order to build the script, - // inserting binaries in the designated sections. - SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo; - - // Add commands to embed target binaries. We ensure that each section and - // image is 16-byte aligned. This is not mandatory, but increases the - // likelihood of data to be aligned with a cache block in several main host - // machines. - LksStream << "/*\n"; - LksStream << " OpenMP Offload Linker Script\n"; - LksStream << " *** Automatically generated by Clang ***\n"; - LksStream << "*/\n"; - LksStream << "TARGET(binary)\n"; - auto DTC = OpenMPToolChains.first; - for (auto &II : Inputs) { - const Action *A = II.getAction(); - // Is this a device linking action? - if (A && isa<LinkJobAction>(A) && - A->isDeviceOffloading(Action::OFK_OpenMP)) { - assert(DTC != OpenMPToolChains.second && - "More device inputs than device toolchains??"); - InputBinaryInfo.push_back(std::make_pair( - DTC->second->getTriple().normalize(), II.getFilename())); - ++DTC; - LksStream << "INPUT(" << II.getFilename() << ")\n"; - } - } - - assert(DTC == OpenMPToolChains.second && - "Less device inputs than device toolchains??"); - - LksStream << "SECTIONS\n"; - LksStream << "{\n"; - - // Put each target binary into a separate section. - for (const auto &BI : InputBinaryInfo) { - LksStream << " .omp_offloading." << BI.first << " :\n"; - LksStream << " ALIGN(0x10)\n"; - LksStream << " {\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first - << " = .);\n"; - LksStream << " " << BI.second << "\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first - << " = .);\n"; - LksStream << " }\n"; - } - - // Add commands to define host entries begin and end. We use 1-byte subalign - // so that the linker does not add any padding and the elements in this - // section form an array. - LksStream << " .omp_offloading.entries :\n"; - LksStream << " ALIGN(0x10)\n"; - LksStream << " SUBALIGN(0x01)\n"; - LksStream << " {\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n"; - LksStream << " *(.omp_offloading.entries)\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n"; - LksStream << " }\n"; - LksStream << "}\n"; - LksStream << "INSERT BEFORE .data\n"; - LksStream.flush(); - - // Dump the contents of the linker script if the user requested that. We - // support this option to enable testing of behavior with -###. - if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script)) - llvm::errs() << LksBuffer; - - // If this is a dry run, do not create the linker script file. - if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) - return; - - // Open script file and write the contents. - std::error_code EC; - llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None); - - if (EC) { - C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message(); - return; - } - - Lksf << LksBuffer; -} - /// Add HIP linker script arguments at the end of the argument list so that /// the fat binary is built by embedding the device images into the host. The /// linker script also defines a symbol required by the code generation so that @@ -1389,14 +1285,12 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, // Create temporary linker script. Keep it if save-temps is enabled. const char *LKS; - SmallString<256> Name = llvm::sys::path::filename(Output.getFilename()); + std::string Name = llvm::sys::path::filename(Output.getFilename()); if (C.getDriver().isSaveTempsEnabled()) { - llvm::sys::path::replace_extension(Name, "lk"); - LKS = C.getArgs().MakeArgString(Name.c_str()); + LKS = C.getArgs().MakeArgString(Name + ".lk"); } else { - llvm::sys::path::replace_extension(Name, ""); - Name = C.getDriver().GetTemporaryPath(Name, "lk"); - LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str())); + auto TmpName = C.getDriver().GetTemporaryPath(Name, "lk"); + LKS = C.addTempFile(C.getArgs().MakeArgString(TmpName)); } // Add linker script option to the command. @@ -1414,11 +1308,13 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, "Wrong platform"); (void)HIPTC; - // The output file name needs to persist through the compilation, therefore - // it needs to be created through MakeArgString. - std::string BundleFileName = C.getDriver().GetTemporaryPath("BUNDLE", "hipfb"); - const char *BundleFile = - C.addTempFile(C.getArgs().MakeArgString(BundleFileName.c_str())); + const char *BundleFile; + if (C.getDriver().isSaveTempsEnabled()) { + BundleFile = C.getArgs().MakeArgString(Name + ".hipfb"); + } else { + auto TmpName = C.getDriver().GetTemporaryPath(Name, "hipfb"); + BundleFile = C.addTempFile(C.getArgs().MakeArgString(TmpName)); + } AMDGCN::constructHIPFatbinCommand(C, JA, BundleFile, DeviceInputs, Args, T); // Add commands to embed target binaries. We ensure that each section and @@ -1430,14 +1326,14 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, LksStream << " *** Automatically generated by Clang ***\n"; LksStream << "*/\n"; LksStream << "TARGET(binary)\n"; - LksStream << "INPUT(" << BundleFileName << ")\n"; + LksStream << "INPUT(" << BundleFile << ")\n"; LksStream << "SECTIONS\n"; LksStream << "{\n"; LksStream << " .hip_fatbin :\n"; LksStream << " ALIGN(0x10)\n"; LksStream << " {\n"; LksStream << " PROVIDE_HIDDEN(__hip_fatbin = .);\n"; - LksStream << " " << BundleFileName << "\n"; + LksStream << " " << BundleFile << "\n"; LksStream << " }\n"; LksStream << " /DISCARD/ :\n"; LksStream << " {\n"; @@ -1458,7 +1354,7 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, // Open script file and write the contents. std::error_code EC; - llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None); + llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::OF_None); if (EC) { C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message(); @@ -1496,3 +1392,111 @@ void tools::addMultilibFlag(bool Enabled, const char *const Flag, Multilib::flags_list &Flags) { Flags.push_back(std::string(Enabled ? "+" : "-") + Flag); } + +static void getWebAssemblyTargetFeatures(const ArgList &Args, + std::vector<StringRef> &Features) { + handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); +} + +void tools::getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, + const ArgList &Args, ArgStringList &CmdArgs, bool ForAS, + bool ForLTOPlugin) { + + 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, Triple, 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; + if (!ForLTOPlugin) { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back(Name.data()); + } else { + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=-mattr=") + Name)); + } + } +} + +StringRef tools::getTargetABI(const ArgList &Args, const llvm::Triple &Triple) { + // TODO: Support the other target ABI + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + return tools::riscv::getRISCVABI(Args, Triple); + break; + } + return StringRef(); +} diff --git a/lib/Driver/ToolChains/CommonArgs.h b/lib/Driver/ToolChains/CommonArgs.h index 9a311708f3ae3..79468e6b89262 100644 --- a/lib/Driver/ToolChains/CommonArgs.h +++ b/lib/Driver/ToolChains/CommonArgs.h @@ -45,13 +45,6 @@ void AddRunTimeLibs(const ToolChain &TC, const Driver &D, llvm::opt::ArgStringList &CmdArgs, const llvm::opt::ArgList &Args); -void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs, - const JobAction &JA); - void AddHIPLinkerScript(const ToolChain &TC, Compilation &C, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, @@ -84,6 +77,7 @@ void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args, /// Returns true, if an OpenMP runtime has been added. bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC, const llvm::opt::ArgList &Args, + bool ForceStaticHostRuntime = false, bool IsOffloadingHost = false, bool GompNeedsRT = false); llvm::opt::Arg *getLastProfileUseArg(const llvm::opt::ArgList &Args); @@ -124,6 +118,14 @@ SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args, void addMultilibFlag(bool Enabled, const char *const Flag, Multilib::flags_list &Flags); +StringRef getTargetABI(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); + +void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, bool ForAS, + bool ForLTOPlugin = false); + } // end namespace tools } // end namespace driver } // end namespace clang diff --git a/lib/Driver/ToolChains/CrossWindows.cpp b/lib/Driver/ToolChains/CrossWindows.cpp index bd3a6e11c9285..dbf6114eb2ecc 100644 --- a/lib/Driver/ToolChains/CrossWindows.cpp +++ b/lib/Driver/ToolChains/CrossWindows.cpp @@ -57,7 +57,7 @@ void tools::CrossWindows::Assembler::ConstructJob( const std::string Assembler = TC.GetProgramPath("as"); Exec = Args.MakeArgString(Assembler); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void tools::CrossWindows::Linker::ConstructJob( @@ -202,7 +202,7 @@ void tools::CrossWindows::Linker::ConstructJob( Exec = Args.MakeArgString(TC.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D, diff --git a/lib/Driver/ToolChains/Cuda.cpp b/lib/Driver/ToolChains/Cuda.cpp index 96f8c513bb56b..8c704a3078adc 100644 --- a/lib/Driver/ToolChains/Cuda.cpp +++ b/lib/Driver/ToolChains/Cuda.cpp @@ -121,7 +121,7 @@ CudaInstallationDetector::CudaInstallationDetector( Candidates.emplace_back(D.SysRoot + "/usr/lib/cuda"); } - bool NoCudaLib = Args.hasArg(options::OPT_nocudalib); + bool NoCudaLib = Args.hasArg(options::OPT_nogpulib); for (const auto &Candidate : Candidates) { InstallPath = Candidate.Path; @@ -422,7 +422,7 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA, Exec = A->getValue(); else Exec = Args.MakeArgString(TC.GetProgramPath("ptxas")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } static bool shouldIncludePTX(const ArgList &Args, const char *gpu_arch) { @@ -488,7 +488,7 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(A)); const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, @@ -563,11 +563,9 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(CubinF); } - AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("nvlink")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// CUDA toolchain. Our assembler is ptxas, and our "linker" is fatbinary, @@ -628,7 +626,7 @@ void CudaToolChain::addClangTargetOptions( CC1Args.push_back("-fgpu-rdc"); } - if (DriverArgs.hasArg(options::OPT_nocudalib)) + if (DriverArgs.hasArg(options::OPT_nogpulib)) return; std::string LibDeviceFile = CudaInstallation.getLibDeviceFile(GpuArch); diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp index 5de7d7132df81..ee08b8208d939 100644 --- a/lib/Driver/ToolChains/Darwin.cpp +++ b/lib/Driver/ToolChains/Darwin.cpp @@ -146,7 +146,7 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA, // asm_final spec is empty. const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void darwin::MachOTool::anchor() {} @@ -451,7 +451,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("touch")); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, None)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, None)); return; } @@ -653,7 +653,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); std::unique_ptr<Command> Cmd = - llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs); + std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs); Cmd->setInputFileList(std::move(InputFileList)); C.addCommand(std::move(Cmd)); } @@ -677,7 +677,7 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, @@ -697,7 +697,7 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dsymutil")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, @@ -720,7 +720,7 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) @@ -1128,7 +1128,6 @@ void Darwin::addProfileRTLibs(const ArgList &Args, } else { addExportedSymbol(CmdArgs, "___llvm_profile_filename"); addExportedSymbol(CmdArgs, "___llvm_profile_raw_version"); - addExportedSymbol(CmdArgs, "_lprofCurFilename"); } addExportedSymbol(CmdArgs, "_lprofDirMode"); } @@ -1480,22 +1479,6 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver, Targets[I.index()] = Env; } - // Do not allow conflicts with the watchOS target. - if (!Targets[Darwin::WatchOS].empty() && - (!Targets[Darwin::IPhoneOS].empty() || !Targets[Darwin::TvOS].empty())) { - TheDriver.Diag(diag::err_drv_conflicting_deployment_targets) - << "WATCHOS_DEPLOYMENT_TARGET" - << (!Targets[Darwin::IPhoneOS].empty() ? "IPHONEOS_DEPLOYMENT_TARGET" - : "TVOS_DEPLOYMENT_TARGET"); - } - - // Do not allow conflicts with the tvOS target. - if (!Targets[Darwin::TvOS].empty() && !Targets[Darwin::IPhoneOS].empty()) { - TheDriver.Diag(diag::err_drv_conflicting_deployment_targets) - << "TVOS_DEPLOYMENT_TARGET" - << "IPHONEOS_DEPLOYMENT_TARGET"; - } - // Allow conflicts among OSX and iOS for historical reasons, but choose the // default platform. if (!Targets[Darwin::MacOS].empty() && @@ -1508,6 +1491,18 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver, else Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] = Targets[Darwin::TvOS] = ""; + } else { + // Don't allow conflicts in any other platform. + int FirstTarget = llvm::array_lengthof(Targets); + for (int I = 0; I != llvm::array_lengthof(Targets); ++I) { + if (Targets[I].empty()) + continue; + if (FirstTarget == llvm::array_lengthof(Targets)) + FirstTarget = I; + else + TheDriver.Diag(diag::err_drv_conflicting_deployment_targets) + << Targets[FirstTarget] << Targets[I]; + } } for (const auto &Target : llvm::enumerate(llvm::makeArrayRef(Targets))) { diff --git a/lib/Driver/ToolChains/DragonFly.cpp b/lib/Driver/ToolChains/DragonFly.cpp index 0a7c8b1615e79..424331fbc6fe0 100644 --- a/lib/Driver/ToolChains/DragonFly.cpp +++ b/lib/Driver/ToolChains/DragonFly.cpp @@ -45,7 +45,7 @@ void dragonfly::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -169,7 +169,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. diff --git a/lib/Driver/ToolChains/FreeBSD.cpp b/lib/Driver/ToolChains/FreeBSD.cpp index 3a0bab8d07f52..7c891a24ba304 100644 --- a/lib/Driver/ToolChains/FreeBSD.cpp +++ b/lib/Driver/ToolChains/FreeBSD.cpp @@ -112,7 +112,7 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -197,6 +197,14 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back("elf64ltsmip_fbsd"); break; + case llvm::Triple::riscv32: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf32lriscv"); + break; + case llvm::Triple::riscv64: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf64lriscv"); + break; default: break; } @@ -262,7 +270,11 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { - addOpenMPRuntime(CmdArgs, ToolChain, Args); + // Use the static OpenMP runtime with -static-openmp + bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && + !Args.hasArg(options::OPT_static); + addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); @@ -331,7 +343,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, ToolChain.addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. @@ -356,6 +368,12 @@ ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const { return ToolChain::CST_Libstdcxx; } +unsigned FreeBSD::GetDefaultDwarfVersion() const { + if (getTriple().getOSMajorVersion() < 12) + return 2; + return 4; +} + void FreeBSD::addLibStdCxxIncludePaths( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { diff --git a/lib/Driver/ToolChains/FreeBSD.h b/lib/Driver/ToolChains/FreeBSD.h index adfe21da372f3..d17b3808ffacc 100644 --- a/lib/Driver/ToolChains/FreeBSD.h +++ b/lib/Driver/ToolChains/FreeBSD.h @@ -69,7 +69,7 @@ public: const llvm::opt::ArgList &Args) const override; bool isPIEDefault() const override; SanitizerMask getSupportedSanitizers() const override; - unsigned GetDefaultDwarfVersion() const override { return 2; } + unsigned GetDefaultDwarfVersion() const override; // Until dtrace (via CTF) and LLDB can deal with distributed debug info, // FreeBSD defaults to standalone/full debug info. bool GetDefaultStandaloneDebug() const override { return true; } diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp index 1f5ec9ebb16d5..e7d38ff9f227b 100644 --- a/lib/Driver/ToolChains/Fuchsia.cpp +++ b/lib/Driver/ToolChains/Fuchsia.cpp @@ -51,6 +51,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, llvm::sys::path::stem(Exec).equals_lower("ld.lld")) { CmdArgs.push_back("-z"); CmdArgs.push_back("rodynamic"); + CmdArgs.push_back("-z"); + CmdArgs.push_back("separate-loadable-segments"); } if (!D.SysRoot.empty()) @@ -154,7 +156,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lc"); } - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly. diff --git a/lib/Driver/ToolChains/Fuchsia.h b/lib/Driver/ToolChains/Fuchsia.h index dd7c5c650352e..fee0e018f3ce3 100644 --- a/lib/Driver/ToolChains/Fuchsia.h +++ b/lib/Driver/ToolChains/Fuchsia.h @@ -17,9 +17,9 @@ namespace clang { namespace driver { namespace tools { namespace fuchsia { -class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool { +class LLVM_LIBRARY_VISIBILITY Linker : public Tool { public: - Linker(const ToolChain &TC) : GnuTool("fuchsia::Linker", "ld.lld", TC) {} + Linker(const ToolChain &TC) : Tool("fuchsia::Linker", "ld.lld", TC) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index 33cdd3585c297..c302a31cd2e10 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -189,7 +189,7 @@ void tools::gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, GCCName = "gcc"; const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void tools::gcc::Preprocessor::RenderExtraToolArgs( @@ -499,7 +499,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, P = ToolChain.GetFilePath(crtbegin); } CmdArgs.push_back(Args.MakeArgString(P)); - } + } // Add crtfastmath.o if available and fast math is enabled. ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs); @@ -555,9 +555,13 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, bool WantPthread = Args.hasArg(options::OPT_pthread) || Args.hasArg(options::OPT_pthreads); + // Use the static OpenMP runtime with -static-openmp + bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && + !Args.hasArg(options::OPT_static); + // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that // require librt. Most modern Linux platforms do, but some may not. - if (addOpenMPRuntime(CmdArgs, ToolChain, Args, + if (addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP, JA.isHostOffloading(Action::OFK_OpenMP), /* GompNeedsRT= */ true)) // OpenMP runtimes implies pthreads when using the GNU toolchain. @@ -619,15 +623,12 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } - // Add OpenMP offloading linker script args if required. - AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA); - // Add HIP offloading linker script args if required. AddHIPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA, *this); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void tools::gnutools::Assembler::ConstructJob(Compilation &C, @@ -819,7 +820,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, A->render(Args, CmdArgs); } else if (mips::shouldUseFPXX( Args, getToolChain().getTriple(), CPUName, ABIName, - mips::getMipsFloatABI(getToolChain().getDriver(), Args))) + mips::getMipsFloatABI(getToolChain().getDriver(), Args, + getToolChain().getTriple()))) CmdArgs.push_back("-mfpxx"); // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of @@ -878,7 +880,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); // Handle the debug info splitting at object creation time if we're // creating an object. @@ -2017,7 +2019,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"}; static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu", "riscv64-linux-gnu", - "riscv64-unknown-elf"}; + "riscv64-unknown-elf", + "riscv64-suse-linux"}; static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"}; static const char *const SPARCv8Triples[] = {"sparc-linux-gnu", diff --git a/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp index 2ec97e798fd05..ad9384df6a242 100644 --- a/lib/Driver/ToolChains/HIP.cpp +++ b/lib/Driver/ToolChains/HIP.cpp @@ -23,7 +23,7 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; -#if _WIN32 || _WIN64 +#if defined(_WIN32) || defined(_WIN64) #define NULL_FILE "nul" #else #define NULL_FILE "/dev/null" @@ -48,6 +48,20 @@ static void addBCLib(const Driver &D, const ArgList &Args, D.Diag(diag::err_drv_no_such_file) << BCName; } +static const char *getOutputFileName(Compilation &C, StringRef Base, + const char *Postfix, + const char *Extension) { + const char *OutputFileName; + if (C.getDriver().isSaveTempsEnabled()) { + OutputFileName = + C.getArgs().MakeArgString(Base.str() + Postfix + "." + Extension); + } else { + std::string TmpName = + C.getDriver().GetTemporaryPath(Base.str() + Postfix, Extension); + OutputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName)); + } + return OutputFileName; +} } // namespace const char *AMDGCN::Linker::constructLLVMLinkCommand( @@ -61,15 +75,12 @@ const char *AMDGCN::Linker::constructLLVMLinkCommand( // Add an intermediate output file. CmdArgs.push_back("-o"); - std::string TmpName = - C.getDriver().GetTemporaryPath(OutputFilePrefix.str() + "-linked", "bc"); - const char *OutputFileName = - C.addTempFile(C.getArgs().MakeArgString(TmpName)); + auto OutputFileName = getOutputFileName(C, OutputFilePrefix, "-linked", "bc"); CmdArgs.push_back(OutputFileName); SmallString<128> ExecPath(C.getDriver().Dir); llvm::sys::path::append(ExecPath, "llvm-link"); const char *Exec = Args.MakeArgString(ExecPath); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); return OutputFileName; } @@ -109,26 +120,26 @@ const char *AMDGCN::Linker::constructOptCommand( } OptArgs.push_back("-o"); - std::string TmpFileName = C.getDriver().GetTemporaryPath( - OutputFilePrefix.str() + "-optimized", "bc"); - const char *OutputFileName = - C.addTempFile(C.getArgs().MakeArgString(TmpFileName)); + auto OutputFileName = + getOutputFileName(C, OutputFilePrefix, "-optimized", "bc"); OptArgs.push_back(OutputFileName); SmallString<128> OptPath(C.getDriver().Dir); llvm::sys::path::append(OptPath, "opt"); const char *OptExec = Args.MakeArgString(OptPath); - C.addCommand(llvm::make_unique<Command>(JA, *this, OptExec, OptArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, OptExec, OptArgs, Inputs)); return OutputFileName; } const char *AMDGCN::Linker::constructLlcCommand( Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, llvm::StringRef SubArchName, - llvm::StringRef OutputFilePrefix, const char *InputFileName) const { + llvm::StringRef OutputFilePrefix, const char *InputFileName, + bool OutputIsAsm) const { // Construct llc command. - ArgStringList LlcArgs{InputFileName, "-mtriple=amdgcn-amd-amdhsa", - "-filetype=obj", - Args.MakeArgString("-mcpu=" + SubArchName)}; + ArgStringList LlcArgs{ + InputFileName, "-mtriple=amdgcn-amd-amdhsa", + Args.MakeArgString(Twine("-filetype=") + (OutputIsAsm ? "asm" : "obj")), + Args.MakeArgString("-mcpu=" + SubArchName)}; // Extract all the -m options std::vector<llvm::StringRef> Features; @@ -151,15 +162,13 @@ const char *AMDGCN::Linker::constructLlcCommand( // Add output filename LlcArgs.push_back("-o"); - std::string LlcOutputFileName = - C.getDriver().GetTemporaryPath(OutputFilePrefix, "o"); - const char *LlcOutputFile = - C.addTempFile(C.getArgs().MakeArgString(LlcOutputFileName)); + auto LlcOutputFile = + getOutputFileName(C, OutputFilePrefix, "", OutputIsAsm ? "s" : "o"); LlcArgs.push_back(LlcOutputFile); SmallString<128> LlcPath(C.getDriver().Dir); llvm::sys::path::append(LlcPath, "llc"); const char *Llc = Args.MakeArgString(LlcPath); - C.addCommand(llvm::make_unique<Command>(JA, *this, Llc, LlcArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Llc, LlcArgs, Inputs)); return LlcOutputFile; } @@ -175,7 +184,7 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA, SmallString<128> LldPath(C.getDriver().Dir); llvm::sys::path::append(LldPath, "lld"); const char *Lld = Args.MakeArgString(LldPath); - C.addCommand(llvm::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs)); } // Construct a clang-offload-bundler command to bundle code objects for @@ -209,7 +218,7 @@ void AMDGCN::constructHIPFatbinCommand(Compilation &C, const JobAction &JA, SmallString<128> BundlerPath(C.getDriver().Dir); llvm::sys::path::append(BundlerPath, "clang-offload-bundler"); const char *Bundler = Args.MakeArgString(BundlerPath); - C.addCommand(llvm::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs)); } // For amdgcn the inputs of the linker job are device bitcode and output is @@ -230,14 +239,18 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA, assert(StringRef(SubArchName).startswith("gfx") && "Unsupported sub arch"); // Prefix for temporary file name. - std::string Prefix = - llvm::sys::path::stem(Inputs[0].getFilename()).str() + "-" + SubArchName; + std::string Prefix = llvm::sys::path::stem(Inputs[0].getFilename()).str(); + if (!C.getDriver().isSaveTempsEnabled()) + Prefix += "-" + SubArchName; // Each command outputs different files. const char *LLVMLinkCommand = constructLLVMLinkCommand(C, JA, Inputs, Args, SubArchName, Prefix); const char *OptCommand = constructOptCommand(C, JA, Inputs, Args, SubArchName, Prefix, LLVMLinkCommand); + if (C.getDriver().isSaveTempsEnabled()) + constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand, + /*OutputIsAsm=*/true); const char *LlcCommand = constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand); constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand); @@ -286,6 +299,9 @@ void HIPToolChain::addClangTargetOptions( CC1Args.append({"-fvisibility", "hidden"}); CC1Args.push_back("-fapply-global-visibility-to-externs"); } + + if (DriverArgs.hasArg(options::OPT_nogpulib)) + return; ArgStringList LibraryPaths; // Find in --hip-device-lib-path and HIP_LIBRARY_PATH. diff --git a/lib/Driver/ToolChains/HIP.h b/lib/Driver/ToolChains/HIP.h index a650095d054d7..2d146ce5cc6fd 100644 --- a/lib/Driver/ToolChains/HIP.h +++ b/lib/Driver/ToolChains/HIP.h @@ -58,7 +58,8 @@ private: const llvm::opt::ArgList &Args, llvm::StringRef SubArchName, llvm::StringRef OutputFilePrefix, - const char *InputFileName) const; + const char *InputFileName, + bool OutputIsAsm = false) const; void constructLldCommand(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const InputInfo &Output, diff --git a/lib/Driver/ToolChains/Hexagon.cpp b/lib/Driver/ToolChains/Hexagon.cpp index f2c3ea11a9f3f..96cc084e2821e 100644 --- a/lib/Driver/ToolChains/Hexagon.cpp +++ b/lib/Driver/ToolChains/Hexagon.cpp @@ -183,7 +183,7 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA, } auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName)); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA, @@ -370,7 +370,7 @@ void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA, LinkingOutput); const char *Exec = Args.MakeArgString(HTC.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Hexagon tools end. diff --git a/lib/Driver/ToolChains/InterfaceStubs.cpp b/lib/Driver/ToolChains/InterfaceStubs.cpp new file mode 100644 index 0000000000000..6677843b2c533 --- /dev/null +++ b/lib/Driver/ToolChains/InterfaceStubs.cpp @@ -0,0 +1,37 @@ +//===--- InterfaceStubs.cpp - Base InterfaceStubs Implementations C++ ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "InterfaceStubs.h" +#include "CommonArgs.h" +#include "clang/Driver/Compilation.h" + +namespace clang { +namespace driver { +namespace tools { +namespace ifstool { +void Merger::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &Args, + const char *LinkingOutput) const { + std::string Merger = getToolChain().GetProgramPath(getShortName()); + llvm::opt::ArgStringList CmdArgs; + CmdArgs.push_back("-action"); + CmdArgs.push_back(Args.getLastArg(options::OPT_emit_merged_ifs) + ? "write-ifs" + : "write-bin"); + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + for (const auto &Input : Inputs) + CmdArgs.push_back(Input.getFilename()); + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Merger), + CmdArgs, Inputs)); +} +} // namespace ifstool +} // namespace tools +} // namespace driver +} // namespace clang diff --git a/lib/Driver/ToolChains/InterfaceStubs.h b/lib/Driver/ToolChains/InterfaceStubs.h new file mode 100644 index 0000000000000..4afa73701a4c5 --- /dev/null +++ b/lib/Driver/ToolChains/InterfaceStubs.h @@ -0,0 +1,36 @@ +//===--- InterfaceStubs.cpp - Base InterfaceStubs Implementations C++ ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H + +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { +namespace tools { +namespace ifstool { +class LLVM_LIBRARY_VISIBILITY Merger : public Tool { +public: + Merger(const ToolChain &TC) : Tool("IFS::Merger", "llvm-ifs", TC) {} + + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return false; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; +} // end namespace ifstool +} // end namespace tools +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp index d900508ad9385..087783875ffe2 100644 --- a/lib/Driver/ToolChains/Linux.cpp +++ b/lib/Driver/ToolChains/Linux.cpp @@ -658,11 +658,11 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include"); - if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { - SmallString<128> P(D.ResourceDir); - llvm::sys::path::append(P, "include"); - addSystemInclude(DriverArgs, CC1Args, P); - } + SmallString<128> ResourceDirInclude(D.ResourceDir); + llvm::sys::path::append(ResourceDirInclude, "include"); + if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && + (!getTriple().isMusl() || DriverArgs.hasArg(options::OPT_nostdlibinc))) + addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude); if (DriverArgs.hasArg(options::OPT_nostdlibinc)) return; @@ -860,6 +860,9 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include"); addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && getTriple().isMusl()) + addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude); } static std::string DetectLibcxxIncludePath(llvm::vfs::FileSystem &vfs, @@ -1026,8 +1029,6 @@ SanitizerMask Linux::getSupportedSanitizers() const { Res |= SanitizerKind::HWAddress; Res |= SanitizerKind::KernelHWAddress; } - if (IsAArch64) - Res |= SanitizerKind::MemTag; return Res; } diff --git a/lib/Driver/ToolChains/MSP430.cpp b/lib/Driver/ToolChains/MSP430.cpp index fc6048f17d785..bc77f015915dc 100644 --- a/lib/Driver/ToolChains/MSP430.cpp +++ b/lib/Driver/ToolChains/MSP430.cpp @@ -227,6 +227,6 @@ void msp430::Linker::ConstructJob(Compilation &C, const JobAction &JA, } CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), CmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp index 6ed80a8f47523..1d31844bfcc88 100644 --- a/lib/Driver/ToolChains/MSVC.cpp +++ b/lib/Driver/ToolChains/MSVC.cpp @@ -331,6 +331,11 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, TC.getSubDirectoryPath( toolchains::MSVCToolChain::SubDirectoryType::Lib))); + CmdArgs.push_back(Args.MakeArgString( + Twine("-libpath:") + + TC.getSubDirectoryPath(toolchains::MSVCToolChain::SubDirectoryType::Lib, + "atlmfc"))); + if (TC.useUniversalCRT()) { std::string UniversalCRTLibPath; if (TC.getUniversalCRTLibraryPath(UniversalCRTLibPath)) @@ -548,7 +553,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, EnvVar.substr(0, PrefixLen) + TC.getSubDirectoryPath(SubDirectoryType::Bin) + llvm::Twine(llvm::sys::EnvPathSeparator) + - TC.getSubDirectoryPath(SubDirectoryType::Bin, HostArch) + + TC.getSubDirectoryPath(SubDirectoryType::Bin, "", HostArch) + (EnvVar.size() > PrefixLen ? llvm::Twine(llvm::sys::EnvPathSeparator) + EnvVar.substr(PrefixLen) @@ -565,7 +570,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, linkPath = TC.GetProgramPath(Linker.str().c_str()); } - auto LinkCmd = llvm::make_unique<Command>( + auto LinkCmd = std::make_unique<Command>( JA, *this, Args.MakeArgString(linkPath), CmdArgs, Inputs); if (!Environment.empty()) LinkCmd->setEnvironment(Environment); @@ -695,7 +700,7 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand( CmdArgs.push_back(Fo); std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe"); - return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), + return std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs); } @@ -824,6 +829,7 @@ static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) { // of hardcoding paths. std::string MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type, + llvm::StringRef SubdirParent, llvm::Triple::ArchType TargetArch) const { const char *SubdirName; const char *IncludeName; @@ -843,6 +849,9 @@ MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type, } llvm::SmallString<256> Path(VCToolChainPath); + if (!SubdirParent.empty()) + llvm::sys::path::append(Path, SubdirParent); + switch (Type) { case SubDirectoryType::Bin: if (VSLayout == ToolsetLayout::VS2017OrNewer) { @@ -1228,6 +1237,8 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, if (!VCToolChainPath.empty()) { addSystemInclude(DriverArgs, CC1Args, getSubDirectoryPath(SubDirectoryType::Include)); + addSystemInclude(DriverArgs, CC1Args, + getSubDirectoryPath(SubDirectoryType::Include, "atlmfc")); if (useUniversalCRT()) { std::string UniversalCRTSdkPath; diff --git a/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h index aba9417c97279..41a69a82fecfe 100644 --- a/lib/Driver/ToolChains/MSVC.h +++ b/lib/Driver/ToolChains/MSVC.h @@ -78,10 +78,12 @@ public: bool isPIEDefault() const override; bool isPICDefaultForced() const override; - /// Set CodeView as the default debug info format. Users can use -gcodeview - /// and -gdwarf to override the default. + /// Set CodeView as the default debug info format for non-MachO binary + /// formats, and to DWARF otherwise. Users can use -gcodeview and -gdwarf to + /// override the default. codegenoptions::DebugInfoFormat getDefaultDebugFormat() const override { - return codegenoptions::DIF_CodeView; + return getTriple().isOSBinFormatMachO() ? codegenoptions::DIF_DWARF + : codegenoptions::DIF_CodeView; } /// Set the debugger tuning to "default", since we're definitely not tuning @@ -96,12 +98,14 @@ public: Lib, }; std::string getSubDirectoryPath(SubDirectoryType Type, + llvm::StringRef SubdirParent, llvm::Triple::ArchType TargetArch) const; // Convenience overload. // Uses the current target arch. - std::string getSubDirectoryPath(SubDirectoryType Type) const { - return getSubDirectoryPath(Type, getArch()); + std::string getSubDirectoryPath(SubDirectoryType Type, + llvm::StringRef SubdirParent = "") const { + return getSubDirectoryPath(Type, SubdirParent, getArch()); } enum class ToolsetLayout { diff --git a/lib/Driver/ToolChains/MinGW.cpp b/lib/Driver/ToolChains/MinGW.cpp index 0e1873cce25be..0d851114c225b 100644 --- a/lib/Driver/ToolChains/MinGW.cpp +++ b/lib/Driver/ToolChains/MinGW.cpp @@ -49,7 +49,7 @@ void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); if (Args.hasArg(options::OPT_gsplit_dwarf)) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, @@ -294,7 +294,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. diff --git a/lib/Driver/ToolChains/MinGW.h b/lib/Driver/ToolChains/MinGW.h index 08298e910ebbd..6752a405be879 100644 --- a/lib/Driver/ToolChains/MinGW.h +++ b/lib/Driver/ToolChains/MinGW.h @@ -34,7 +34,8 @@ public: class LLVM_LIBRARY_VISIBILITY Linker : public Tool { public: - Linker(const ToolChain &TC) : Tool("MinGW::Linker", "linker", TC) {} + Linker(const ToolChain &TC) + : Tool("MinGW::Linker", "linker", TC, Tool::RF_Full) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } diff --git a/lib/Driver/ToolChains/Minix.cpp b/lib/Driver/ToolChains/Minix.cpp index dbcc1f8908c4b..6947049ea52ee 100644 --- a/lib/Driver/ToolChains/Minix.cpp +++ b/lib/Driver/ToolChains/Minix.cpp @@ -36,7 +36,7 @@ void tools::minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -88,7 +88,7 @@ void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// Minix - Minix tool chain which can call as(1) and ld(1) directly. diff --git a/lib/Driver/ToolChains/Myriad.cpp b/lib/Driver/ToolChains/Myriad.cpp index 16eea1f13b142..2ce0f13ce3d1a 100644 --- a/lib/Driver/ToolChains/Myriad.cpp +++ b/lib/Driver/ToolChains/Myriad.cpp @@ -77,7 +77,7 @@ void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA, std::string Exec = Args.MakeArgString(getToolChain().GetProgramPath("moviCompile")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs)); } @@ -112,7 +112,7 @@ void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA, std::string Exec = Args.MakeArgString(getToolChain().GetProgramPath("moviAsm")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs)); } @@ -198,7 +198,7 @@ void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA, std::string Exec = Args.MakeArgString(TC.GetProgramPath("sparc-myriad-rtems-ld")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/NaCl.cpp b/lib/Driver/ToolChains/NaCl.cpp index 984afc1758b1a..97241c8840273 100644 --- a/lib/Driver/ToolChains/NaCl.cpp +++ b/lib/Driver/ToolChains/NaCl.cpp @@ -193,7 +193,7 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// NaCl Toolchain diff --git a/lib/Driver/ToolChains/NetBSD.cpp b/lib/Driver/ToolChains/NetBSD.cpp index 3219a5d1e4f4f..405142204199d 100644 --- a/lib/Driver/ToolChains/NetBSD.cpp +++ b/lib/Driver/ToolChains/NetBSD.cpp @@ -103,7 +103,7 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -289,7 +289,11 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { - addOpenMPRuntime(CmdArgs, getToolChain(), Args); + // Use the static OpenMP runtime with -static-openmp + bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && + !Args.hasArg(options::OPT_static); + addOpenMPRuntime(CmdArgs, getToolChain(), Args, StaticOpenMP); + if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); @@ -333,7 +337,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, ToolChain.addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly. @@ -485,10 +489,23 @@ SanitizerMask NetBSD::getSupportedSanitizers() const { return Res; } -void NetBSD::addClangTargetOptions(const ArgList &, +void NetBSD::addClangTargetOptions(const ArgList &DriverArgs, ArgStringList &CC1Args, Action::OffloadKind) const { const SanitizerArgs &SanArgs = getSanitizerArgs(); if (SanArgs.hasAnySanitizer()) CC1Args.push_back("-D_REENTRANT"); + + unsigned Major, Minor, Micro; + getTriple().getOSVersion(Major, Minor, Micro); + bool UseInitArrayDefault = + Major >= 9 || Major == 0 || + getTriple().getArch() == llvm::Triple::aarch64 || + getTriple().getArch() == llvm::Triple::aarch64_be || + getTriple().getArch() == llvm::Triple::arm || + getTriple().getArch() == llvm::Triple::armeb; + + if (DriverArgs.hasFlag(options::OPT_fuse_init_array, + options::OPT_fno_use_init_array, UseInitArrayDefault)) + CC1Args.push_back("-fuse-init-array"); } diff --git a/lib/Driver/ToolChains/OpenBSD.cpp b/lib/Driver/ToolChains/OpenBSD.cpp index 8441b83c29a93..e93f5fcc3d819 100644 --- a/lib/Driver/ToolChains/OpenBSD.cpp +++ b/lib/Driver/ToolChains/OpenBSD.cpp @@ -89,7 +89,7 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -227,7 +227,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } SanitizerMask OpenBSD::getSupportedSanitizers() const { diff --git a/lib/Driver/ToolChains/PPCLinux.cpp b/lib/Driver/ToolChains/PPCLinux.cpp index 5221e5d0e22cb..af2e3a21a0af7 100644 --- a/lib/Driver/ToolChains/PPCLinux.cpp +++ b/lib/Driver/ToolChains/PPCLinux.cpp @@ -16,10 +16,7 @@ using namespace llvm::opt; void PPCLinuxToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { - // PPC wrapper headers are implementation of x86 intrinsics on PowerPC, which - // is not supported on PPC32 platform. - if (getArch() != llvm::Triple::ppc && - !DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) && + if (!DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) && !DriverArgs.hasArg(options::OPT_nobuiltininc)) { const Driver &D = getDriver(); SmallString<128> P(D.ResourceDir); diff --git a/lib/Driver/ToolChains/PS4CPU.cpp b/lib/Driver/ToolChains/PS4CPU.cpp index 7be471365668a..4e8840296205d 100644 --- a/lib/Driver/ToolChains/PS4CPU.cpp +++ b/lib/Driver/ToolChains/PS4CPU.cpp @@ -62,7 +62,7 @@ void tools::PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("orbis-as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) { @@ -141,7 +141,7 @@ static void ConstructPS4LinkJob(const Tool &T, Compilation &C, const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld")); - C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs)); } static void ConstructGoldLinkJob(const Tool &T, Compilation &C, @@ -319,7 +319,7 @@ static void ConstructGoldLinkJob(const Tool &T, Compilation &C, Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld")); #endif - C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs)); } void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA, diff --git a/lib/Driver/ToolChains/RISCVToolchain.cpp b/lib/Driver/ToolChains/RISCVToolchain.cpp index c5fdd129c3a8d..22dc5117f1962 100644 --- a/lib/Driver/ToolChains/RISCVToolchain.cpp +++ b/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "RISCVToolchain.h" +#include "Arch/RISCV.h" #include "CommonArgs.h" #include "InputInfo.h" #include "clang/Driver/Compilation.h" @@ -100,6 +101,12 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, std::string Linker = getToolChain().GetProgramPath(getShortName()); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0], + D.getLTOMode() == LTOK_Thin); + } + bool WantCRTs = !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles); @@ -134,7 +141,7 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), CmdArgs, Inputs)); } // RISCV tools end. diff --git a/lib/Driver/ToolChains/RISCVToolchain.h b/lib/Driver/ToolChains/RISCVToolchain.h index b2b56b066efd2..673d749d76ff7 100644 --- a/lib/Driver/ToolChains/RISCVToolchain.h +++ b/lib/Driver/ToolChains/RISCVToolchain.h @@ -25,6 +25,7 @@ public: void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind) const override; + bool HasNativeLLVMSupport() const override { return true; } void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; diff --git a/lib/Driver/ToolChains/Solaris.cpp b/lib/Driver/ToolChains/Solaris.cpp index 38f24d4cf7e74..fc4e2cf151ef1 100644 --- a/lib/Driver/ToolChains/Solaris.cpp +++ b/lib/Driver/ToolChains/Solaris.cpp @@ -8,6 +8,7 @@ #include "Solaris.h" #include "CommonArgs.h" +#include "clang/Basic/LangStandard.h" #include "clang/Config/config.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" @@ -40,7 +41,7 @@ void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -86,8 +87,28 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(getToolChain().GetFilePath("crt1.o"))); CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o"))); + + const Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi); + bool HaveAnsi = false; + const LangStandard *LangStd = nullptr; + if (Std) { + HaveAnsi = Std->getOption().matches(options::OPT_ansi); + if (!HaveAnsi) + LangStd = LangStandard::getLangStandardForName(Std->getValue()); + } + + const char *values_X = "values-Xa.o"; + // Use values-Xc.o for -ansi, -std=c*, -std=iso9899:199409. + if (HaveAnsi || (LangStd && !LangStd->isGNUMode())) + values_X = "values-Xc.o"; + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(values_X))); + + const char *values_xpg = "values-xpg6.o"; + // Use values-xpg4.o for -std=c90, -std=gnu90, -std=iso9899:199409. + if (LangStd && LangStd->getLanguage() == Language::C && !LangStd->isC99()) + values_xpg = "values-xpg4.o"; CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("values-Xa.o"))); + Args.MakeArgString(getToolChain().GetFilePath(values_xpg))); CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); } @@ -129,7 +150,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } static StringRef getSolarisLibSuffix(const llvm::Triple &Triple) { @@ -177,6 +198,7 @@ Solaris::Solaris(const Driver &D, const llvm::Triple &Triple, SanitizerMask Solaris::getSupportedSanitizers() const { const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; + const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; SanitizerMask Res = ToolChain::getSupportedSanitizers(); // FIXME: Omit X86_64 until 64-bit support is figured out. if (IsX86) { @@ -184,6 +206,8 @@ SanitizerMask Solaris::getSupportedSanitizers() const { Res |= SanitizerKind::PointerCompare; Res |= SanitizerKind::PointerSubtract; } + if (IsX86 || IsX86_64) + Res |= SanitizerKind::Function; Res |= SanitizerKind::Vptr; return Res; } diff --git a/lib/Driver/ToolChains/WebAssembly.cpp b/lib/Driver/ToolChains/WebAssembly.cpp index 7a40c13c065a4..3add913b700fa 100644 --- a/lib/Driver/ToolChains/WebAssembly.cpp +++ b/lib/Driver/ToolChains/WebAssembly.cpp @@ -89,7 +89,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs)); } WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, @@ -141,7 +141,7 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs, options::OPT_fno_use_init_array, true)) CC1Args.push_back("-fuse-init-array"); - // '-pthread' implies atomics, bulk-memory, and mutable-globals + // '-pthread' implies atomics, bulk-memory, mutable-globals, and sign-ext if (DriverArgs.hasFlag(options::OPT_pthread, options::OPT_no_pthread, false)) { if (DriverArgs.hasFlag(options::OPT_mno_atomics, options::OPT_matomics, @@ -159,12 +159,39 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs, getDriver().Diag(diag::err_drv_argument_not_allowed_with) << "-pthread" << "-mno-mutable-globals"; + if (DriverArgs.hasFlag(options::OPT_mno_sign_ext, options::OPT_msign_ext, + false)) + getDriver().Diag(diag::err_drv_argument_not_allowed_with) + << "-pthread" + << "-mno-sign-ext"; CC1Args.push_back("-target-feature"); CC1Args.push_back("+atomics"); CC1Args.push_back("-target-feature"); CC1Args.push_back("+bulk-memory"); CC1Args.push_back("-target-feature"); CC1Args.push_back("+mutable-globals"); + CC1Args.push_back("-target-feature"); + CC1Args.push_back("+sign-ext"); + } + + if (DriverArgs.getLastArg(options::OPT_fwasm_exceptions)) { + // '-fwasm-exceptions' is not compatible with '-mno-exception-handling' + if (DriverArgs.hasFlag(options::OPT_mno_exception_handing, + options::OPT_mexception_handing, false)) + getDriver().Diag(diag::err_drv_argument_not_allowed_with) + << "-fwasm-exceptions" + << "-mno-exception-handling"; + // '-fwasm-exceptions' is not compatible with + // '-mllvm -enable-emscripten-cxx-exceptions' + for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) { + if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions") + getDriver().Diag(diag::err_drv_argument_not_allowed_with) + << "-fwasm-exceptions" + << "-mllvm -enable-emscripten-cxx-exceptions"; + } + // '-fwasm-exceptions' implies exception-handling + CC1Args.push_back("-target-feature"); + CC1Args.push_back("+exception-handling"); } } diff --git a/lib/Driver/ToolChains/XCore.cpp b/lib/Driver/ToolChains/XCore.cpp index 477cdb7609149..ba3a6d44addaf 100644 --- a/lib/Driver/ToolChains/XCore.cpp +++ b/lib/Driver/ToolChains/XCore.cpp @@ -52,7 +52,7 @@ void tools::XCore::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void tools::XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -80,7 +80,7 @@ void tools::XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// XCore tool chain diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp index 96937678ac6b0..a30710645af3a 100644 --- a/lib/Driver/Types.cpp +++ b/lib/Driver/Types.cpp @@ -7,24 +7,29 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/Types.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Option/Arg.h" #include <cassert> -#include <string.h> +#include <cstring> using namespace clang::driver; using namespace clang::driver::types; struct TypeInfo { const char *Name; - const char *Flags; const char *TempSuffix; ID PreprocessedType; + const llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> Phases; }; static const TypeInfo TypeInfos[] = { -#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) \ - { NAME, FLAGS, TEMP_SUFFIX, TY_##PP_TYPE, }, +#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, ...) \ + { NAME, TEMP_SUFFIX, TY_##PP_TYPE, { __VA_ARGS__ }, }, #include "clang/Driver/Types.def" #undef TYPE }; @@ -40,11 +45,19 @@ const char *types::getTypeName(ID Id) { } types::ID types::getPreprocessedType(ID Id) { - return getInfo(Id).PreprocessedType; + ID PPT = getInfo(Id).PreprocessedType; + assert((llvm::is_contained(getInfo(Id).Phases, phases::Preprocess) != + (PPT == TY_INVALID)) && + "Unexpected Preprocess Type."); + return PPT; +} + +static bool isPrepeocessedModuleType(ID Id) { + return Id == TY_CXXModule || Id == TY_PP_CXXModule; } types::ID types::getPrecompiledType(ID Id) { - if (strchr(getInfo(Id).Flags, 'm')) + if (isPrepeocessedModuleType(Id)) return TY_ModuleFile; if (onlyPrecompileType(Id)) return TY_PCH; @@ -69,19 +82,31 @@ const char *types::getTypeTempSuffix(ID Id, bool CLMode) { } bool types::onlyAssembleType(ID Id) { - return strchr(getInfo(Id).Flags, 'a'); + return llvm::is_contained(getInfo(Id).Phases, phases::Assemble) && + !llvm::is_contained(getInfo(Id).Phases, phases::Compile) && + !llvm::is_contained(getInfo(Id).Phases, phases::Backend); } bool types::onlyPrecompileType(ID Id) { - return strchr(getInfo(Id).Flags, 'p'); + return llvm::is_contained(getInfo(Id).Phases, phases::Precompile) && + !isPrepeocessedModuleType(Id); } bool types::canTypeBeUserSpecified(ID Id) { - return strchr(getInfo(Id).Flags, 'u'); + static const clang::driver::types::ID kStaticLangageTypes[] = { + TY_CUDA_DEVICE, TY_HIP_DEVICE, TY_PP_CHeader, + TY_PP_ObjCHeader, TY_PP_CXXHeader, TY_PP_ObjCXXHeader, + TY_PP_CXXModule, TY_LTO_IR, TY_LTO_BC, + TY_Plist, TY_RewrittenObjC, TY_RewrittenLegacyObjC, + TY_Remap, TY_PCH, TY_Object, + TY_Image, TY_dSYM, TY_Dependencies, + TY_CUDA_FATBIN, TY_HIP_FATBIN}; + return !llvm::is_contained(kStaticLangageTypes, Id); } bool types::appendSuffixForType(ID Id) { - return strchr(getInfo(Id).Flags, 'A'); + return Id == TY_PCH || Id == TY_dSYM || Id == TY_CUDA_FATBIN || + Id == TY_HIP_FATBIN; } bool types::canLipoType(ID Id) { @@ -244,6 +269,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { .Case("lib", TY_Object) .Case("mii", TY_PP_ObjCXX) .Case("obj", TY_Object) + .Case("ifs", TY_IFS) .Case("pch", TY_PCH) .Case("pcm", TY_ModuleFile) .Case("c++m", TY_CXXModule) @@ -264,30 +290,77 @@ types::ID types::lookupTypeForTypeSpecifier(const char *Name) { } // FIXME: Why don't we just put this list in the defs file, eh. +// FIXME: The list is now in Types.def but for now this function will verify +// the old behavior and a subsequent change will delete most of the body. void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) { - if (Id != TY_Object) { - if (getPreprocessedType(Id) != TY_INVALID) { - P.push_back(phases::Preprocess); - } - - if (getPrecompiledType(Id) != TY_INVALID) { - P.push_back(phases::Precompile); - } + P = getInfo(Id).Phases; + assert(0 < P.size() && "Not enough phases in list"); + assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list"); +} - if (!onlyPrecompileType(Id)) { - if (!onlyAssembleType(Id)) { - P.push_back(phases::Compile); - P.push_back(phases::Backend); - } - P.push_back(phases::Assemble); +void types::getCompilationPhases(const clang::driver::Driver &Driver, + llvm::opt::DerivedArgList &DAL, ID Id, + llvm::SmallVectorImpl<phases::ID> &P) { + llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PhaseList; + types::getCompilationPhases(Id, PhaseList); + + // Filter to compiler mode. When the compiler is run as a preprocessor then + // compilation is not an option. + // -S runs the compiler in Assembly listing mode. + if (Driver.CCCIsCPP() || DAL.getLastArg(options::OPT_E) || + DAL.getLastArg(options::OPT__SLASH_EP) || + DAL.getLastArg(options::OPT_M, options::OPT_MM) || + DAL.getLastArg(options::OPT__SLASH_P)) + llvm::copy_if(PhaseList, std::back_inserter(P), + [](phases::ID Phase) { return Phase <= phases::Preprocess; }); + + // --precompile only runs up to precompilation. + // This is a clang extension and is not compatible with GCC. + else if (DAL.getLastArg(options::OPT__precompile)) + llvm::copy_if(PhaseList, std::back_inserter(P), + [](phases::ID Phase) { return Phase <= phases::Precompile; }); + + // Treat Interface Stubs like its own compilation mode. + else if (DAL.getLastArg(options::OPT_emit_interface_stubs)) { + llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> IfsModePhaseList; + llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> &PL = PhaseList; + phases::ID LastPhase = phases::IfsMerge; + if (Id != types::TY_IFS) { + if (DAL.hasArg(options::OPT_c)) + LastPhase = phases::Compile; + PL = IfsModePhaseList; + types::getCompilationPhases(types::TY_IFS_CPP, PL); } + llvm::copy_if(PL, std::back_inserter(P), [&](phases::ID Phase) { + return Phase <= LastPhase; + }); } - if (!onlyPrecompileType(Id)) { - P.push_back(phases::Link); - } - assert(0 < P.size() && "Not enough phases in list"); - assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list"); + // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. + else if (DAL.getLastArg(options::OPT_fsyntax_only) || + DAL.getLastArg(options::OPT_print_supported_cpus) || + DAL.getLastArg(options::OPT_module_file_info) || + DAL.getLastArg(options::OPT_verify_pch) || + DAL.getLastArg(options::OPT_rewrite_objc) || + DAL.getLastArg(options::OPT_rewrite_legacy_objc) || + DAL.getLastArg(options::OPT__migrate) || + DAL.getLastArg(options::OPT__analyze) || + DAL.getLastArg(options::OPT_emit_ast)) + llvm::copy_if(PhaseList, std::back_inserter(P), + [](phases::ID Phase) { return Phase <= phases::Compile; }); + + else if (DAL.getLastArg(options::OPT_S) || + DAL.getLastArg(options::OPT_emit_llvm)) + llvm::copy_if(PhaseList, std::back_inserter(P), + [](phases::ID Phase) { return Phase <= phases::Backend; }); + + else if (DAL.getLastArg(options::OPT_c)) + llvm::copy_if(PhaseList, std::back_inserter(P), + [](phases::ID Phase) { return Phase <= phases::Assemble; }); + + // Generally means, do every phase until Link. + else + P = PhaseList; } ID types::lookupCXXTypeForCType(ID Id) { diff --git a/lib/Driver/XRayArgs.cpp b/lib/Driver/XRayArgs.cpp index 45ef96e12b3b7..16e7c7ecf36b4 100644 --- a/lib/Driver/XRayArgs.cpp +++ b/lib/Driver/XRayArgs.cpp @@ -52,7 +52,7 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) { } else if (Triple.isOSFreeBSD() || Triple.isOSOpenBSD() || Triple.isOSNetBSD() || - Triple.getOS() == llvm::Triple::Darwin) { + Triple.isMacOSX()) { if (Triple.getArch() != llvm::Triple::x86_64) { D.Diag(diag::err_drv_clang_unsupported) << (std::string(XRayInstrumentOption) + " on " + Triple.str()); |