summaryrefslogtreecommitdiff
path: root/lib/Driver
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver')
-rw-r--r--lib/Driver/Action.cpp14
-rw-r--r--lib/Driver/Compilation.cpp2
-rw-r--r--lib/Driver/Driver.cpp524
-rw-r--r--lib/Driver/DriverOptions.cpp17
-rw-r--r--lib/Driver/Phases.cpp1
-rw-r--r--lib/Driver/SanitizerArgs.cpp40
-rw-r--r--lib/Driver/ToolChain.cpp32
-rw-r--r--lib/Driver/ToolChains/AMDGPU.cpp2
-rw-r--r--lib/Driver/ToolChains/AVR.cpp2
-rw-r--r--lib/Driver/ToolChains/Ananas.cpp4
-rw-r--r--lib/Driver/ToolChains/Arch/AArch64.cpp1
-rw-r--r--lib/Driver/ToolChains/Arch/ARM.cpp50
-rw-r--r--lib/Driver/ToolChains/Arch/Mips.cpp25
-rw-r--r--lib/Driver/ToolChains/Arch/Mips.h3
-rw-r--r--lib/Driver/ToolChains/Arch/PPC.cpp4
-rw-r--r--lib/Driver/ToolChains/Arch/RISCV.cpp311
-rw-r--r--lib/Driver/ToolChains/Arch/RISCV.h3
-rw-r--r--lib/Driver/ToolChains/Arch/X86.cpp1
-rw-r--r--lib/Driver/ToolChains/BareMetal.cpp2
-rw-r--r--lib/Driver/ToolChains/Clang.cpp618
-rw-r--r--lib/Driver/ToolChains/Clang.h18
-rw-r--r--lib/Driver/ToolChains/CloudABI.cpp2
-rw-r--r--lib/Driver/ToolChains/CommonArgs.cpp356
-rw-r--r--lib/Driver/ToolChains/CommonArgs.h16
-rw-r--r--lib/Driver/ToolChains/CrossWindows.cpp4
-rw-r--r--lib/Driver/ToolChains/Cuda.cpp12
-rw-r--r--lib/Driver/ToolChains/Darwin.cpp41
-rw-r--r--lib/Driver/ToolChains/DragonFly.cpp4
-rw-r--r--lib/Driver/ToolChains/FreeBSD.cpp24
-rw-r--r--lib/Driver/ToolChains/FreeBSD.h2
-rw-r--r--lib/Driver/ToolChains/Fuchsia.cpp4
-rw-r--r--lib/Driver/ToolChains/Fuchsia.h4
-rw-r--r--lib/Driver/ToolChains/Gnu.cpp23
-rw-r--r--lib/Driver/ToolChains/HIP.cpp64
-rw-r--r--lib/Driver/ToolChains/HIP.h3
-rw-r--r--lib/Driver/ToolChains/Hexagon.cpp4
-rw-r--r--lib/Driver/ToolChains/InterfaceStubs.cpp37
-rw-r--r--lib/Driver/ToolChains/InterfaceStubs.h36
-rw-r--r--lib/Driver/ToolChains/Linux.cpp15
-rw-r--r--lib/Driver/ToolChains/MSP430.cpp2
-rw-r--r--lib/Driver/ToolChains/MSVC.cpp17
-rw-r--r--lib/Driver/ToolChains/MSVC.h14
-rw-r--r--lib/Driver/ToolChains/MinGW.cpp4
-rw-r--r--lib/Driver/ToolChains/MinGW.h3
-rw-r--r--lib/Driver/ToolChains/Minix.cpp4
-rw-r--r--lib/Driver/ToolChains/Myriad.cpp6
-rw-r--r--lib/Driver/ToolChains/NaCl.cpp2
-rw-r--r--lib/Driver/ToolChains/NetBSD.cpp25
-rw-r--r--lib/Driver/ToolChains/OpenBSD.cpp4
-rw-r--r--lib/Driver/ToolChains/PPCLinux.cpp5
-rw-r--r--lib/Driver/ToolChains/PS4CPU.cpp6
-rw-r--r--lib/Driver/ToolChains/RISCVToolchain.cpp9
-rw-r--r--lib/Driver/ToolChains/RISCVToolchain.h1
-rw-r--r--lib/Driver/ToolChains/Solaris.cpp30
-rw-r--r--lib/Driver/ToolChains/WebAssembly.cpp31
-rw-r--r--lib/Driver/ToolChains/XCore.cpp4
-rw-r--r--lib/Driver/Types.cpp131
-rw-r--r--lib/Driver/XRayArgs.cpp2
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());