summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/Driver.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Driver.cpp506
1 files changed, 284 insertions, 222 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
index ef26bfa..1664d0d 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
@@ -50,7 +50,6 @@ Driver::Driver(StringRef ClangExecutable,
: Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode),
ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple),
- DefaultImageName("a.out"),
DriverTitle("clang LLVM compiler"),
CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr),
CCLogDiagnosticsFilename(nullptr),
@@ -65,10 +64,13 @@ Driver::Driver(StringRef ClangExecutable,
// Compute the path to the resource directory.
StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
SmallString<128> P(Dir);
- if (ClangResourceDir != "")
+ if (ClangResourceDir != "") {
llvm::sys::path::append(P, ClangResourceDir);
- else
- llvm::sys::path::append(P, "..", "lib", "clang", CLANG_VERSION_STRING);
+ } else {
+ StringRef ClangLibdirSuffix(CLANG_LIBDIR_SUFFIX);
+ llvm::sys::path::append(P, "..", Twine("lib") + ClangLibdirSuffix, "clang",
+ CLANG_VERSION_STRING);
+ }
ResourceDir = P.str();
}
@@ -83,6 +85,9 @@ void Driver::ParseDriverMode(ArrayRef<const char *> Args) {
getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
for (size_t I = 0, E = Args.size(); I != E; ++I) {
+ // Ingore nullptrs, they are response file's EOL markers
+ if (Args[I] == nullptr)
+ continue;
const StringRef Arg = Args[I];
if (!Arg.startswith(OptName))
continue;
@@ -102,7 +107,7 @@ void Driver::ParseDriverMode(ArrayRef<const char *> Args) {
}
}
-InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) {
+InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
unsigned IncludedFlagsBitmask;
@@ -111,7 +116,7 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) {
getIncludeExcludeOptionFlagMasks();
unsigned MissingArgIndex, MissingArgCount;
- InputArgList *Args = getOpts().ParseArgs(ArgList.begin(), ArgList.end(),
+ InputArgList *Args = getOpts().ParseArgs(ArgStrings.begin(), ArgStrings.end(),
MissingArgIndex, MissingArgCount,
IncludedFlagsBitmask,
ExcludedFlagsBitmask);
@@ -122,9 +127,7 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) {
<< Args->getArgString(MissingArgIndex) << MissingArgCount;
// Check for unsupported options.
- for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
- it != ie; ++it) {
- Arg *A = *it;
+ for (const Arg *A : *Args) {
if (A->getOption().hasFlag(options::Unsupported)) {
Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args);
continue;
@@ -162,7 +165,7 @@ const {
(PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
FinalPhase = phases::Preprocess;
- // -{fsyntax-only,-analyze,emit-ast,S} 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_module_file_info)) ||
(PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||
@@ -171,10 +174,13 @@ const {
(PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
(PhaseArg = DAL.getLastArg(options::OPT__analyze,
options::OPT__analyze_auto)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_emit_ast)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_S))) {
+ (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
FinalPhase = phases::Compile;
+ // -S only runs up to the backend.
+ } else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {
+ FinalPhase = phases::Backend;
+
// -c only runs up to the assembler.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {
FinalPhase = phases::Assemble;
@@ -202,10 +208,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
DerivedArgList *DAL = new DerivedArgList(Args);
bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);
- for (ArgList::const_iterator it = Args.begin(),
- ie = Args.end(); it != ie; ++it) {
- const Arg *A = *it;
-
+ for (Arg *A : Args) {
// Unfortunately, we have to parse some forwarding options (-Xassembler,
// -Xlinker, -Xpreprocessor) because we either integrate their functionality
// (assembler and preprocessor), or bypass a previous driver ('collect2').
@@ -271,7 +274,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
continue;
}
- DAL->append(*it);
+ DAL->append(A);
}
// Add a default value of -mlinker-version=, if one was given and the user
@@ -400,13 +403,13 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// preprocessed source file(s). Request that the developer attach the
// diagnostic information to a bug report.
void Driver::generateCompilationDiagnostics(Compilation &C,
- const Command *FailingCommand) {
+ const Command &FailingCommand) {
if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics))
return;
// Don't try to generate diagnostics for link or dsymutil jobs.
- if (FailingCommand && (FailingCommand->getCreator().isLinkJob() ||
- FailingCommand->getCreator().isDsymutilJob()))
+ if (FailingCommand.getCreator().isLinkJob() ||
+ FailingCommand.getCreator().isDsymutilJob())
return;
// Print the version of the compiler.
@@ -421,15 +424,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
CCGenDiagnostics = true;
// Save the original job command(s).
- std::string Cmd;
- llvm::raw_string_ostream OS(Cmd);
- if (FailingCommand)
- FailingCommand->Print(OS, "\n", /*Quote*/ false, /*CrashReport*/ true);
- else
- // Crash triggered by FORCE_CLANG_DIAGNOSTICS_CRASH, which doesn't have an
- // associated FailingCommand, so just pass all jobs.
- C.getJobs().Print(OS, "\n", /*Quote*/ false, /*CrashReport*/ true);
- OS.flush();
+ Command Cmd = FailingCommand;
// Keep track of whether we produce any errors while trying to produce
// preprocessed sources.
@@ -473,9 +468,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
// Don't attempt to generate preprocessed files if multiple -arch options are
// used, unless they're all duplicates.
llvm::StringSet<> ArchNames;
- for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
- it != ie; ++it) {
- Arg *A = *it;
+ for (const Arg *A : C.getArgs()) {
if (A->getOption().matches(options::OPT_arch)) {
StringRef ArchName = A->getValue();
ArchNames.insert(ArchName);
@@ -509,70 +502,86 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
C.ExecuteJob(C.getJobs(), FailingCommands);
- // If the command succeeded, we are done.
- if (FailingCommands.empty()) {
+ // If any of the preprocessing commands failed, clean up and exit.
+ if (!FailingCommands.empty()) {
+ if (!C.getArgs().hasArg(options::OPT_save_temps))
+ C.CleanupFileList(C.getTempFiles(), true);
+
Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "Error generating preprocessed source(s).";
+ return;
+ }
+
+ const ArgStringList &TempFiles = C.getTempFiles();
+ if (TempFiles.empty()) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "Error generating preprocessed source(s).";
+ return;
+ }
+
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "\n********************\n\n"
- "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n"
- "Preprocessed source(s) and associated run script(s) are located at:";
- ArgStringList Files = C.getTempFiles();
- for (ArgStringList::const_iterator it = Files.begin(), ie = Files.end();
- it != ie; ++it) {
- Diag(clang::diag::note_drv_command_failed_diag_msg) << *it;
- std::string Script = StringRef(*it).rsplit('.').first;
+ "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n"
+ "Preprocessed source(s) and associated run script(s) are located at:";
+
+ SmallString<128> VFS;
+ for (const char *TempFile : TempFiles) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile;
+ if (StringRef(TempFile).endswith(".cache")) {
// In some cases (modules) we'll dump extra data to help with reproducing
// the crash into a directory next to the output.
- SmallString<128> VFS;
- if (llvm::sys::fs::exists(Script + ".cache")) {
- Diag(clang::diag::note_drv_command_failed_diag_msg)
- << Script + ".cache";
- VFS = llvm::sys::path::filename(Script + ".cache");
- llvm::sys::path::append(VFS, "vfs", "vfs.yaml");
- }
-
- std::string Err;
- Script += ".sh";
- llvm::raw_fd_ostream ScriptOS(Script.c_str(), Err, llvm::sys::fs::F_Excl);
- if (!Err.empty()) {
- Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "Error generating run script: " + Script + " " + Err;
- } else {
- // Replace the original filename with the preprocessed one.
- size_t I, E;
- I = Cmd.find("-main-file-name ");
- assert (I != std::string::npos && "Expected to find -main-file-name");
- I += 16;
- E = Cmd.find(" ", I);
- assert (E != std::string::npos && "-main-file-name missing argument?");
- StringRef OldFilename = StringRef(Cmd).slice(I, E);
- StringRef NewFilename = llvm::sys::path::filename(*it);
- I = StringRef(Cmd).rfind(OldFilename);
- E = I + OldFilename.size();
- I = Cmd.rfind(" ", I) + 1;
- Cmd.replace(I, E - I, NewFilename.data(), NewFilename.size());
- if (!VFS.empty()) {
- // Add the VFS overlay to the reproduction script.
- I += NewFilename.size();
- Cmd.insert(I, std::string(" -ivfsoverlay ") + VFS.c_str());
- }
- ScriptOS << Cmd;
- Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
- }
+ VFS = llvm::sys::path::filename(TempFile);
+ llvm::sys::path::append(VFS, "vfs", "vfs.yaml");
}
+ }
+
+ // Assume associated files are based off of the first temporary file.
+ CrashReportInfo CrashInfo(TempFiles[0], VFS);
+
+ std::string Script = CrashInfo.Filename.rsplit('.').first.str() + ".sh";
+ std::error_code EC;
+ llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::F_Excl);
+ if (EC) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "\n\n********************";
+ << "Error generating run script: " + Script + " " + EC.message();
} else {
- // Failure, remove preprocessed files.
- if (!C.getArgs().hasArg(options::OPT_save_temps))
- C.CleanupFileList(C.getTempFiles(), true);
+ Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo);
+ Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
+ }
- Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "Error generating preprocessed source(s).";
+ for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file,
+ options::OPT_frewrite_map_file_EQ))
+ Diag(clang::diag::note_drv_command_failed_diag_msg) << A->getValue();
+
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "\n\n********************";
+}
+
+void Driver::setUpResponseFiles(Compilation &C, Job &J) {
+ if (JobList *Jobs = dyn_cast<JobList>(&J)) {
+ for (auto &Job : *Jobs)
+ setUpResponseFiles(C, Job);
+ return;
}
+
+ Command *CurCommand = dyn_cast<Command>(&J);
+ if (!CurCommand)
+ return;
+
+ // Since argumentsFitWithinSystemLimits() may underestimate system's capacity
+ // if the tool does not support response files, there is a chance/ that things
+ // will just work without a response file, so we silently just skip it.
+ if (CurCommand->getCreator().getResponseFilesSupport() == Tool::RF_None ||
+ llvm::sys::argumentsFitWithinSystemLimits(CurCommand->getArguments()))
+ return;
+
+ std::string TmpName = GetTemporaryPath("response", "txt");
+ CurCommand->setResponseFile(C.addTempFile(C.getArgs().MakeArgString(
+ TmpName.c_str())));
}
-int Driver::ExecuteCompilation(const Compilation &C,
- SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) const {
+int Driver::ExecuteCompilation(Compilation &C,
+ SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) {
// Just print if -### was present.
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
C.getJobs().Print(llvm::errs(), "\n", true);
@@ -583,6 +592,9 @@ int Driver::ExecuteCompilation(const Compilation &C,
if (Diags.hasErrorOccurred())
return 1;
+ // Set up response file names for each command, if necessary
+ setUpResponseFiles(C, C.getJobs());
+
C.ExecuteJob(C.getJobs(), FailingCommands);
// Remove temp files.
@@ -653,9 +665,13 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
OS << "Target: " << TC.getTripleString() << '\n';
// Print the threading model.
- //
- // FIXME: Implement correctly.
- OS << "Thread model: " << "posix" << '\n';
+ if (Arg *A = C.getArgs().getLastArg(options::OPT_mthread_model)) {
+ // Don't print if the ToolChain would have barfed on it already
+ if (TC.isThreadModelSupported(A->getValue()))
+ OS << "Thread model: " << A->getValue();
+ } else
+ OS << "Thread model: " << TC.getThreadModel();
+ OS << '\n';
}
/// PrintDiagnosticCategories - Implement the --print-diagnostic-categories
@@ -836,7 +852,9 @@ void Driver::PrintActions(const Compilation &C) const {
/// \brief Check whether the given input tree contains any compilation or
/// assembly actions.
static bool ContainsCompileOrAssembleAction(const Action *A) {
- if (isa<CompileJobAction>(A) || isa<AssembleJobAction>(A))
+ if (isa<CompileJobAction>(A) ||
+ isa<BackendJobAction>(A) ||
+ isa<AssembleJobAction>(A))
return true;
for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it)
@@ -855,10 +873,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
// be handled once (in the order seen).
llvm::StringSet<> ArchNames;
SmallVector<const char *, 4> Archs;
- for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
- it != ie; ++it) {
- Arg *A = *it;
-
+ for (Arg *A : Args) {
if (A->getOption().matches(options::OPT_arch)) {
// Validate the option here; we don't save the type here because its
// particular spelling may participate in other driver choices.
@@ -871,7 +886,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
}
A->claim();
- if (ArchNames.insert(A->getValue()))
+ if (ArchNames.insert(A->getValue()).second)
Archs.push_back(A->getValue());
}
}
@@ -901,7 +916,8 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
ActionList Inputs;
for (unsigned i = 0, e = Archs.size(); i != e; ++i) {
- Inputs.push_back(new BindArchAction(Act, Archs[i]));
+ Inputs.push_back(
+ new BindArchAction(std::unique_ptr<Action>(Act), Archs[i]));
if (i != 0)
Inputs.back()->setOwnsInputs(false);
}
@@ -932,9 +948,9 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
// Verify the debug info output.
if (Args.hasArg(options::OPT_verify_debug_info)) {
- Action *VerifyInput = Actions.back();
+ std::unique_ptr<Action> VerifyInput(Actions.back());
Actions.pop_back();
- Actions.push_back(new VerifyDebugInfoJobAction(VerifyInput,
+ Actions.push_back(new VerifyDebugInfoJobAction(std::move(VerifyInput),
types::TY_Nothing));
}
}
@@ -981,8 +997,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
Arg *InputTypeArg = nullptr;
// The last /TC or /TP option sets the input type to C or C++ globally.
- if (Arg *TCTP = Args.getLastArg(options::OPT__SLASH_TC,
- options::OPT__SLASH_TP)) {
+ if (Arg *TCTP = Args.getLastArgNoClaim(options::OPT__SLASH_TC,
+ options::OPT__SLASH_TP)) {
InputTypeArg = TCTP;
InputType = TCTP->getOption().matches(options::OPT__SLASH_TC)
? types::TY_C : types::TY_CXX;
@@ -1005,10 +1021,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
assert(!Args.hasArg(options::OPT_x) && "-x and /TC or /TP is not allowed");
}
- for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
- it != ie; ++it) {
- Arg *A = *it;
-
+ for (Arg *A : Args) {
if (A->getOption().getKind() == Option::InputClass) {
const char *Value = A->getValue();
types::ID Ty = types::TY_INVALID;
@@ -1070,8 +1083,17 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
}
} else {
assert(InputTypeArg && "InputType set w/o InputTypeArg");
- InputTypeArg->claim();
- Ty = InputType;
+ if (!InputTypeArg->getOption().matches(options::OPT_x)) {
+ // If emulating cl.exe, make sure that /TC and /TP don't affect input
+ // object files.
+ const char *Ext = strrchr(Value, '.');
+ if (Ext && TC.LookupTypeForExtension(Ext + 1) == types::TY_Object)
+ Ty = types::TY_Object;
+ }
+ if (Ty == types::TY_INVALID) {
+ Ty = InputType;
+ InputTypeArg->claim();
+ }
}
if (DiagnoseInputExistence(*this, Args, Value))
@@ -1142,11 +1164,8 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
// Diagnose misuse of /Fo.
if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) {
StringRef V = A->getValue();
- if (V.empty()) {
- // It has to have a value.
- Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1;
- Args.eraseArg(options::OPT__SLASH_Fo);
- } else if (Inputs.size() > 1 && !llvm::sys::path::is_separator(V.back())) {
+ 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;
@@ -1157,7 +1176,8 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
// Diagnose misuse of /Fa.
if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) {
StringRef V = A->getValue();
- if (Inputs.size() > 1 && !llvm::sys::path::is_separator(V.back())) {
+ 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;
@@ -1165,12 +1185,12 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
}
}
- // Diagnose misuse of /Fe.
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fe)) {
+ // 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_Fe);
+ Args.eraseArg(options::OPT__SLASH_o);
}
}
@@ -1244,7 +1264,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
continue;
// Otherwise construct the appropriate action.
- Current.reset(ConstructPhaseAction(Args, Phase, Current.release()));
+ Current = ConstructPhaseAction(Args, Phase, std::move(Current));
if (Current->getType() == types::TY_Nothing)
break;
}
@@ -1269,8 +1289,9 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
Args.ClaimAllArgs(options::OPT_cl_ignored_Group);
}
-Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
- Action *Input) const {
+std::unique_ptr<Action>
+Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
+ std::unique_ptr<Action> Input) const {
llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
// Build the appropriate action.
switch (Phase) {
@@ -1289,7 +1310,7 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
assert(OutputTy != types::TY_INVALID &&
"Cannot preprocess this input type!");
}
- return new PreprocessJobAction(Input, OutputTy);
+ return llvm::make_unique<PreprocessJobAction>(std::move(Input), OutputTy);
}
case phases::Precompile: {
types::ID OutputTy = types::TY_PCH;
@@ -1297,39 +1318,53 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
// Syntax checks should not emit a PCH file
OutputTy = types::TY_Nothing;
}
- return new PrecompileJobAction(Input, OutputTy);
+ return llvm::make_unique<PrecompileJobAction>(std::move(Input), OutputTy);
}
case phases::Compile: {
- if (Args.hasArg(options::OPT_fsyntax_only)) {
- return new CompileJobAction(Input, types::TY_Nothing);
- } else if (Args.hasArg(options::OPT_rewrite_objc)) {
- return new CompileJobAction(Input, types::TY_RewrittenObjC);
- } else if (Args.hasArg(options::OPT_rewrite_legacy_objc)) {
- return new CompileJobAction(Input, types::TY_RewrittenLegacyObjC);
- } else if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) {
- return new AnalyzeJobAction(Input, types::TY_Plist);
- } else if (Args.hasArg(options::OPT__migrate)) {
- return new MigrateJobAction(Input, types::TY_Remap);
- } else if (Args.hasArg(options::OPT_emit_ast)) {
- return new CompileJobAction(Input, types::TY_AST);
- } else if (Args.hasArg(options::OPT_module_file_info)) {
- return new CompileJobAction(Input, types::TY_ModuleFile);
- } else if (Args.hasArg(options::OPT_verify_pch)) {
- return new VerifyPCHJobAction(Input, types::TY_Nothing);
- } else if (IsUsingLTO(Args)) {
+ if (Args.hasArg(options::OPT_fsyntax_only))
+ return llvm::make_unique<CompileJobAction>(std::move(Input),
+ types::TY_Nothing);
+ if (Args.hasArg(options::OPT_rewrite_objc))
+ return llvm::make_unique<CompileJobAction>(std::move(Input),
+ types::TY_RewrittenObjC);
+ if (Args.hasArg(options::OPT_rewrite_legacy_objc))
+ return llvm::make_unique<CompileJobAction>(std::move(Input),
+ types::TY_RewrittenLegacyObjC);
+ if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto))
+ return llvm::make_unique<AnalyzeJobAction>(std::move(Input),
+ types::TY_Plist);
+ if (Args.hasArg(options::OPT__migrate))
+ return llvm::make_unique<MigrateJobAction>(std::move(Input),
+ types::TY_Remap);
+ if (Args.hasArg(options::OPT_emit_ast))
+ return llvm::make_unique<CompileJobAction>(std::move(Input),
+ types::TY_AST);
+ if (Args.hasArg(options::OPT_module_file_info))
+ return llvm::make_unique<CompileJobAction>(std::move(Input),
+ types::TY_ModuleFile);
+ if (Args.hasArg(options::OPT_verify_pch))
+ return llvm::make_unique<VerifyPCHJobAction>(std::move(Input),
+ types::TY_Nothing);
+ return llvm::make_unique<CompileJobAction>(std::move(Input),
+ types::TY_LLVM_BC);
+ }
+ case phases::Backend: {
+ if (IsUsingLTO(Args)) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
- return new CompileJobAction(Input, Output);
- } else if (Args.hasArg(options::OPT_emit_llvm)) {
+ return llvm::make_unique<BackendJobAction>(std::move(Input), Output);
+ }
+ if (Args.hasArg(options::OPT_emit_llvm)) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
- return new CompileJobAction(Input, Output);
- } else {
- return new CompileJobAction(Input, types::TY_PP_Asm);
+ return llvm::make_unique<BackendJobAction>(std::move(Input), Output);
}
+ return llvm::make_unique<BackendJobAction>(std::move(Input),
+ types::TY_PP_Asm);
}
case phases::Assemble:
- return new AssembleJobAction(Input, types::TY_Object);
+ return llvm::make_unique<AssembleJobAction>(std::move(Input),
+ types::TY_Object);
}
llvm_unreachable("invalid phase in ConstructPhaseAction");
@@ -1351,9 +1386,8 @@ void Driver::BuildJobs(Compilation &C) const {
// files.
if (FinalOutput) {
unsigned NumOutputs = 0;
- for (ActionList::const_iterator it = C.getActions().begin(),
- ie = C.getActions().end(); it != ie; ++it)
- if ((*it)->getType() != types::TY_Nothing)
+ for (const Action *A : C.getActions())
+ if (A->getType() != types::TY_Nothing)
++NumOutputs;
if (NumOutputs > 1) {
@@ -1364,19 +1398,12 @@ void Driver::BuildJobs(Compilation &C) const {
// Collect the list of architectures.
llvm::StringSet<> ArchNames;
- if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO()) {
- for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
- it != ie; ++it) {
- Arg *A = *it;
+ if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO())
+ for (const Arg *A : C.getArgs())
if (A->getOption().matches(options::OPT_arch))
ArchNames.insert(A->getValue());
- }
- }
-
- for (ActionList::const_iterator it = C.getActions().begin(),
- ie = C.getActions().end(); it != ie; ++it) {
- Action *A = *it;
+ for (Action *A : C.getActions()) {
// If we are linking an image for multiple archs then the linker wants
// -arch_multiple and -final_output <final image name>. Unfortunately, this
// doesn't fit in cleanly because we have to pass this information down.
@@ -1388,7 +1415,7 @@ void Driver::BuildJobs(Compilation &C) const {
if (FinalOutput)
LinkingOutput = FinalOutput->getValue();
else
- LinkingOutput = DefaultImageName.c_str();
+ LinkingOutput = getDefaultImageName();
}
InputInfo II;
@@ -1412,10 +1439,7 @@ void Driver::BuildJobs(Compilation &C) const {
// Claim --driver-mode, it was handled earlier.
(void) C.getArgs().hasArg(options::OPT_driver_mode);
- for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
- it != ie; ++it) {
- Arg *A = *it;
-
+ for (Arg *A : C.getArgs()) {
// FIXME: It would be nice to be able to send the argument to the
// DiagnosticsEngine, so that extra values, position, and so on could be
// printed.
@@ -1462,12 +1486,34 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
!C.getArgs().hasArg(options::OPT__SLASH_FA) &&
!C.getArgs().hasArg(options::OPT__SLASH_Fa) &&
isa<AssembleJobAction>(JA) &&
- Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) {
- const Tool *Compiler =
- TC->SelectTool(cast<JobAction>(**Inputs->begin()));
+ Inputs->size() == 1 && isa<BackendJobAction>(*Inputs->begin())) {
+ // A BackendJob is always preceded by a CompileJob, and without
+ // -save-temps they will always get combined together, so instead of
+ // checking the backend tool, check if the tool for the CompileJob
+ // has an integrated assembler.
+ const ActionList *BackendInputs = &(*Inputs)[0]->getInputs();
+ JobAction *CompileJA = cast<CompileJobAction>(*BackendInputs->begin());
+ const Tool *Compiler = TC->SelectTool(*CompileJA);
if (!Compiler)
return nullptr;
if (Compiler->hasIntegratedAssembler()) {
+ Inputs = &(*BackendInputs)[0]->getInputs();
+ ToolForJob = Compiler;
+ }
+ }
+
+ // A backend job should always be combined with the preceding compile job
+ // unless OPT_save_temps is enabled and the compiler is capable of emitting
+ // LLVM IR as an intermediate output.
+ if (isa<BackendJobAction>(JA)) {
+ // Check if the compiler supports emitting LLVM IR.
+ assert(Inputs->size() == 1);
+ JobAction *CompileJA = cast<CompileJobAction>(*Inputs->begin());
+ const Tool *Compiler = TC->SelectTool(*CompileJA);
+ if (!Compiler)
+ return nullptr;
+ if (!Compiler->canEmitIR() ||
+ !C.getArgs().hasArg(options::OPT_save_temps)) {
Inputs = &(*Inputs)[0]->getInputs();
ToolForJob = Compiler;
}
@@ -1537,8 +1583,7 @@ void Driver::BuildJobsForAction(Compilation &C,
// Only use pipes when there is exactly one input.
InputInfoList InputInfos;
- for (ActionList::const_iterator it = Inputs->begin(), ie = Inputs->end();
- it != ie; ++it) {
+ for (const Action *Input : *Inputs) {
// Treat dsymutil and verify sub-jobs as being at the top-level too, they
// shouldn't get temporary output names.
// FIXME: Clean this up.
@@ -1547,7 +1592,7 @@ void Driver::BuildJobsForAction(Compilation &C,
SubJobAtTopLevel = true;
InputInfo II;
- BuildJobsForAction(C, *it, TC, BoundArch, SubJobAtTopLevel, MultipleArchs,
+ BuildJobsForAction(C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs,
LinkingOutput, II);
InputInfos.push_back(II);
}
@@ -1583,6 +1628,11 @@ void Driver::BuildJobsForAction(Compilation &C,
}
}
+const char *Driver::getDefaultImageName() const {
+ llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple));
+ return Target.isOSWindows() ? "a.exe" : "a.out";
+}
+
/// \brief Create output filename based on ArgValue, which could either be a
/// full filename, filename without extension, or a directory. If ArgValue
/// does not provide a filename, then use BaseName, and use the extension
@@ -1634,7 +1684,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
assert(AtTopLevel && isa<PreprocessJobAction>(JA));
StringRef BaseName = llvm::sys::path::filename(BaseInput);
StringRef NameArg;
- if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi))
+ if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi,
+ options::OPT__SLASH_o))
NameArg = A->getValue();
return C.addResultFile(MakeCLOutputFilename(C.getArgs(), NameArg, BaseName,
types::TY_PP_C), &JA);
@@ -1681,15 +1732,17 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
const char *NamedOutput;
if (JA.getType() == types::TY_Object &&
- C.getArgs().hasArg(options::OPT__SLASH_Fo)) {
- // The /Fo flag decides the object filename.
- StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo)->getValue();
+ C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) {
+ // The /Fo or /o flag decides the object filename.
+ StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo,
+ options::OPT__SLASH_o)->getValue();
NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
types::TY_Object);
} else if (JA.getType() == types::TY_Image &&
- C.getArgs().hasArg(options::OPT__SLASH_Fe)) {
- // The /Fe flag names the linked file.
- StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fe)->getValue();
+ C.getArgs().hasArg(options::OPT__SLASH_Fe, options::OPT__SLASH_o)) {
+ // The /Fe or /o flag names the linked file.
+ StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fe,
+ options::OPT__SLASH_o)->getValue();
NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
types::TY_Image);
} else if (JA.getType() == types::TY_Image) {
@@ -1698,12 +1751,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
NamedOutput = MakeCLOutputFilename(C.getArgs(), "", BaseName,
types::TY_Image);
} else if (MultipleArchs && BoundArch) {
- SmallString<128> Output(DefaultImageName.c_str());
+ SmallString<128> Output(getDefaultImageName());
Output += "-";
Output.append(BoundArch);
NamedOutput = C.getArgs().MakeArgString(Output.c_str());
} else
- NamedOutput = DefaultImageName.c_str();
+ NamedOutput = getDefaultImageName();
} else {
const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode());
assert(Suffix && "All types used for output should have a suffix.");
@@ -1716,6 +1769,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
Suffixed += "-";
Suffixed.append(BoundArch);
}
+ // When using both -save-temps and -emit-llvm, use a ".tmp.bc" suffix for
+ // the unoptimized bitcode so that it does not get overwritten by the ".bc"
+ // optimized bitcode output.
+ if (!AtTopLevel && C.getArgs().hasArg(options::OPT_emit_llvm) &&
+ JA.getType() == types::TY_LLVM_BC)
+ Suffixed += ".tmp";
Suffixed += '.';
Suffixed += Suffix;
NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());
@@ -1793,51 +1852,56 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
return Name;
}
+void
+Driver::generatePrefixedToolNames(const char *Tool, const ToolChain &TC,
+ SmallVectorImpl<std::string> &Names) const {
+ // FIXME: Needs a better variable than DefaultTargetTriple
+ Names.push_back(DefaultTargetTriple + "-" + Tool);
+ Names.push_back(Tool);
+}
+
+static bool ScanDirForExecutable(SmallString<128> &Dir,
+ ArrayRef<std::string> Names) {
+ for (const auto &Name : Names) {
+ llvm::sys::path::append(Dir, Name);
+ if (llvm::sys::fs::can_execute(Twine(Dir)))
+ return true;
+ llvm::sys::path::remove_filename(Dir);
+ }
+ return false;
+}
+
std::string Driver::GetProgramPath(const char *Name,
const ToolChain &TC) const {
- // FIXME: Needs a better variable than DefaultTargetTriple
- std::string TargetSpecificExecutable(DefaultTargetTriple + "-" + Name);
+ SmallVector<std::string, 2> TargetSpecificExecutables;
+ generatePrefixedToolNames(Name, TC, TargetSpecificExecutables);
+
// Respect a limited subset of the '-Bprefix' functionality in GCC by
// attempting to use this prefix when looking for program paths.
- for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(),
- ie = PrefixDirs.end(); it != ie; ++it) {
- if (llvm::sys::fs::is_directory(*it)) {
- SmallString<128> P(*it);
- llvm::sys::path::append(P, TargetSpecificExecutable);
- if (llvm::sys::fs::can_execute(Twine(P)))
- return P.str();
- llvm::sys::path::remove_filename(P);
- llvm::sys::path::append(P, Name);
- if (llvm::sys::fs::can_execute(Twine(P)))
+ for (const auto &PrefixDir : PrefixDirs) {
+ if (llvm::sys::fs::is_directory(PrefixDir)) {
+ SmallString<128> P(PrefixDir);
+ if (ScanDirForExecutable(P, TargetSpecificExecutables))
return P.str();
} else {
- SmallString<128> P(*it + Name);
+ SmallString<128> P(PrefixDir + Name);
if (llvm::sys::fs::can_execute(Twine(P)))
return P.str();
}
}
const ToolChain::path_list &List = TC.getProgramPaths();
- for (ToolChain::path_list::const_iterator
- it = List.begin(), ie = List.end(); it != ie; ++it) {
- SmallString<128> P(*it);
- llvm::sys::path::append(P, TargetSpecificExecutable);
- if (llvm::sys::fs::can_execute(Twine(P)))
- return P.str();
- llvm::sys::path::remove_filename(P);
- llvm::sys::path::append(P, Name);
- if (llvm::sys::fs::can_execute(Twine(P)))
+ for (const auto &Path : List) {
+ SmallString<128> P(Path);
+ if (ScanDirForExecutable(P, TargetSpecificExecutables))
return P.str();
}
// If all else failed, search the path.
- std::string P(llvm::sys::FindProgramByName(TargetSpecificExecutable));
- if (!P.empty())
- return P;
-
- P = llvm::sys::FindProgramByName(Name);
- if (!P.empty())
- return P;
+ for (const auto &TargetSpecificExecutable : TargetSpecificExecutables)
+ if (llvm::ErrorOr<std::string> P =
+ llvm::sys::findProgramByName(TargetSpecificExecutable))
+ return *P;
return Name;
}
@@ -1893,8 +1957,6 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
Target.setArch(llvm::Triple::mips64el);
else if (Target.getArch() == llvm::Triple::aarch64_be)
Target.setArch(llvm::Triple::aarch64);
- else if (Target.getArch() == llvm::Triple::arm64_be)
- Target.setArch(llvm::Triple::arm64);
} else {
if (Target.getArch() == llvm::Triple::mipsel)
Target.setArch(llvm::Triple::mips);
@@ -1902,15 +1964,11 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
Target.setArch(llvm::Triple::mips64);
else if (Target.getArch() == llvm::Triple::aarch64)
Target.setArch(llvm::Triple::aarch64_be);
- else if (Target.getArch() == llvm::Triple::arm64)
- Target.setArch(llvm::Triple::arm64_be);
}
}
// Skip further flag support on OSes which don't support '-m32' or '-m64'.
- if (Target.getArchName() == "tce" ||
- Target.getOS() == llvm::Triple::AuroraUX ||
- Target.getOS() == llvm::Triple::Minix)
+ if (Target.getArchName() == "tce" || Target.getOS() == llvm::Triple::Minix)
return Target;
// Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'.
@@ -1918,21 +1976,25 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
options::OPT_m32, options::OPT_m16)) {
llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;
- if (A->getOption().matches(options::OPT_m64))
+ if (A->getOption().matches(options::OPT_m64)) {
AT = Target.get64BitArchVariant().getArch();
- else if (A->getOption().matches(options::OPT_mx32) &&
+ if (Target.getEnvironment() == llvm::Triple::GNUX32)
+ Target.setEnvironment(llvm::Triple::GNU);
+ } else if (A->getOption().matches(options::OPT_mx32) &&
Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {
AT = llvm::Triple::x86_64;
Target.setEnvironment(llvm::Triple::GNUX32);
- } else if (A->getOption().matches(options::OPT_m32))
+ } else if (A->getOption().matches(options::OPT_m32)) {
AT = Target.get32BitArchVariant().getArch();
- else if (A->getOption().matches(options::OPT_m16) &&
+ if (Target.getEnvironment() == llvm::Triple::GNUX32)
+ Target.setEnvironment(llvm::Triple::GNU);
+ } else if (A->getOption().matches(options::OPT_m16) &&
Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {
AT = llvm::Triple::x86;
Target.setEnvironment(llvm::Triple::CODE16);
}
- if (AT != llvm::Triple::UnknownArch)
+ if (AT != llvm::Triple::UnknownArch && AT != Target.getArch())
Target.setArch(AT);
}
@@ -1947,9 +2009,6 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
ToolChain *&TC = ToolChains[Target.str()];
if (!TC) {
switch (Target.getOS()) {
- case llvm::Triple::AuroraUX:
- TC = new toolchains::AuroraUX(*this, Target, Args);
- break;
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
@@ -2000,9 +2059,12 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
else
TC = new toolchains::Generic_GCC(*this, Target, Args);
break;
+ case llvm::Triple::Itanium:
+ TC = new toolchains::CrossWindowsToolChain(*this, Target, Args);
+ break;
case llvm::Triple::MSVC:
case llvm::Triple::UnknownEnvironment:
- TC = new toolchains::Windows(*this, Target, Args);
+ TC = new toolchains::MSVCToolChain(*this, Target, Args);
break;
}
break;
@@ -2025,7 +2087,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
TC = new toolchains::Generic_ELF(*this, Target, Args);
break;
}
- if (Target.getObjectFormat() == llvm::Triple::MachO) {
+ if (Target.isOSBinFormatMachO()) {
TC = new toolchains::MachO(*this, Target, Args);
break;
}
@@ -2045,7 +2107,7 @@ bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
// Otherwise make sure this is an action clang understands.
if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) &&
- !isa<CompileJobAction>(JA))
+ !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
return false;
return true;
OpenPOWER on IntegriCloud