summaryrefslogtreecommitdiff
path: root/clang/lib/Driver/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Driver/Driver.cpp')
-rw-r--r--clang/lib/Driver/Driver.cpp149
1 files changed, 138 insertions, 11 deletions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index f6016b43b692..e718b8366df0 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -8,6 +8,7 @@
#include "clang/Driver/Driver.h"
#include "InputInfo.h"
+#include "ToolChains/AIX.h"
#include "ToolChains/AMDGPU.h"
#include "ToolChains/AVR.h"
#include "ToolChains/Ananas.h"
@@ -177,6 +178,7 @@ void Driver::setDriverModeFromOption(StringRef Opt) {
.Case("g++", GXXMode)
.Case("cpp", CPPMode)
.Case("cl", CLMode)
+ .Case("flang", FlangMode)
.Default(None))
Mode = *M;
else
@@ -290,10 +292,6 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
(PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
FinalPhase = phases::Compile;
- // 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;
@@ -539,6 +537,17 @@ static llvm::Triple computeTargetTriple(const Driver &D,
}
}
+ // If target is RISC-V adjust the target triple according to
+ // provided architecture name
+ A = Args.getLastArg(options::OPT_march_EQ);
+ if (A && Target.isRISCV()) {
+ StringRef ArchName = A->getValue();
+ if (ArchName.startswith_lower("rv32"))
+ Target.setArch(llvm::Triple::riscv32);
+ else if (ArchName.startswith_lower("rv64"))
+ Target.setArch(llvm::Triple::riscv64);
+ }
+
return Target;
}
@@ -735,7 +744,7 @@ static bool searchForFile(SmallVectorImpl<char> &FilePath,
ArrayRef<std::string> Dirs,
StringRef FileName) {
SmallString<128> WPath;
- for (const StringRef &Dir : Dirs) {
+ for (const std::string &Dir : Dirs) {
if (Dir.empty())
continue;
WPath.clear();
@@ -1981,8 +1990,9 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
// Handle debug info queries.
Arg *A = Args.getLastArg(options::OPT_g_Group);
- if (A && !A->getOption().matches(options::OPT_g0) &&
- !A->getOption().matches(options::OPT_gstabs) &&
+ bool enablesDebugInfo = A && !A->getOption().matches(options::OPT_g0) &&
+ !A->getOption().matches(options::OPT_gstabs);
+ if ((enablesDebugInfo || willEmitRemarks(Args)) &&
ContainsCompileOrAssembleAction(Actions.back())) {
// Add a 'dsymutil' step if necessary, when debug info is enabled and we
@@ -3489,6 +3499,68 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
Actions.push_back(
C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image));
+ if (Args.hasArg(options::OPT_emit_interface_stubs)) {
+ llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PhaseList;
+ if (Args.hasArg(options::OPT_c)) {
+ llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> CompilePhaseList;
+ types::getCompilationPhases(types::TY_IFS_CPP, CompilePhaseList);
+ llvm::copy_if(CompilePhaseList, std::back_inserter(PhaseList),
+ [&](phases::ID Phase) { return Phase <= phases::Compile; });
+ } else {
+ types::getCompilationPhases(types::TY_IFS_CPP, PhaseList);
+ }
+
+ ActionList MergerInputs;
+
+ for (auto &I : Inputs) {
+ types::ID InputType = I.first;
+ const Arg *InputArg = I.second;
+
+ // Currently clang and the llvm assembler do not support generating symbol
+ // stubs from assembly, so we skip the input on asm files. For ifs files
+ // we rely on the normal pipeline setup in the pipeline setup code above.
+ if (InputType == types::TY_IFS || InputType == types::TY_PP_Asm ||
+ InputType == types::TY_Asm)
+ continue;
+
+ Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
+
+ for (auto Phase : PhaseList) {
+ switch (Phase) {
+ default:
+ llvm_unreachable(
+ "IFS Pipeline can only consist of Compile followed by IfsMerge.");
+ case phases::Compile: {
+ // Only IfsMerge (llvm-ifs) can handle .o files by looking for ifs
+ // files where the .o file is located. The compile action can not
+ // handle this.
+ if (InputType == types::TY_Object)
+ break;
+
+ Current = C.MakeAction<CompileJobAction>(Current, types::TY_IFS_CPP);
+ break;
+ }
+ case phases::IfsMerge: {
+ assert(Phase == PhaseList.back() &&
+ "merging must be final compilation step.");
+ MergerInputs.push_back(Current);
+ Current = nullptr;
+ break;
+ }
+ }
+ }
+
+ // If we ended with something, add to the output list.
+ if (Current)
+ Actions.push_back(Current);
+ }
+
+ // 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.
if (Arg *A = Args.getLastArg(options::OPT_print_supported_cpus)) {
@@ -3590,8 +3662,6 @@ 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_interface_stubs))
- return C.MakeAction<CompileJobAction>(Input, types::TY_IFS_CPP);
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
}
case phases::Backend: {
@@ -3620,11 +3690,29 @@ void Driver::BuildJobs(Compilation &C) const {
Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
// It is an error to provide a -o option if we are making multiple output
- // files.
+ // files. There are exceptions:
+ //
+ // IfsMergeJob: when generating interface stubs enabled we want to be able to
+ // generate the stub file at the same time that we generate the real
+ // library/a.out. So when a .o, .so, etc are the output, with clang interface
+ // stubs there will also be a .ifs and .ifso at the same location.
+ //
+ // CompileJob of type TY_IFS_CPP: when generating interface stubs is enabled
+ // and -c is passed, we still want to be able to generate a .ifs file while
+ // we are also generating .o files. So we allow more than one output file in
+ // this case as well.
+ //
if (FinalOutput) {
unsigned NumOutputs = 0;
+ unsigned NumIfsOutputs = 0;
for (const Action *A : C.getActions())
- if (A->getType() != types::TY_Nothing)
+ if (A->getType() != types::TY_Nothing &&
+ !(A->getKind() == Action::IfsMergeJobClass ||
+ (A->getType() == clang::driver::types::TY_IFS_CPP &&
+ A->getKind() == clang::driver::Action::CompileJobClass &&
+ 0 == NumIfsOutputs++) ||
+ (A->getKind() == Action::BindArchClass && A->getInputs().size() &&
+ A->getInputs().front()->getKind() == Action::IfsMergeJobClass)))
++NumOutputs;
if (NumOutputs > 1) {
@@ -4699,6 +4787,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
auto &TC = ToolChains[Target.str()];
if (!TC) {
switch (Target.getOS()) {
+ case llvm::Triple::AIX:
+ TC = std::make_unique<toolchains::AIX>(*this, Target, Args);
+ break;
case llvm::Triple::Haiku:
TC = std::make_unique<toolchains::Haiku>(*this, Target, Args);
break;
@@ -4872,6 +4963,19 @@ bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
return true;
}
+bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {
+ // Say "no" if there is not exactly one input of a type flang understands.
+ if (JA.size() != 1 ||
+ !types::isFortran((*JA.input_begin())->getType()))
+ return false;
+
+ // And say "no" if this is not a kind of action flang understands.
+ if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
+ return false;
+
+ return true;
+}
+
/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the
/// grouped values as integers. Numbers which are not provided are set to 0.
///
@@ -4957,3 +5061,26 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
bool clang::driver::isOptimizationLevelFast(const ArgList &Args) {
return Args.hasFlag(options::OPT_Ofast, options::OPT_O_Group, false);
}
+
+bool clang::driver::willEmitRemarks(const ArgList &Args) {
+ // -fsave-optimization-record enables it.
+ if (Args.hasFlag(options::OPT_fsave_optimization_record,
+ options::OPT_fno_save_optimization_record, false))
+ return true;
+
+ // -fsave-optimization-record=<format> enables it as well.
+ if (Args.hasFlag(options::OPT_fsave_optimization_record_EQ,
+ options::OPT_fno_save_optimization_record, false))
+ return true;
+
+ // -foptimization-record-file alone enables it too.
+ if (Args.hasFlag(options::OPT_foptimization_record_file_EQ,
+ options::OPT_fno_save_optimization_record, false))
+ return true;
+
+ // -foptimization-record-passes alone enables it too.
+ if (Args.hasFlag(options::OPT_foptimization_record_passes_EQ,
+ options::OPT_fno_save_optimization_record, false))
+ return true;
+ return false;
+}