summaryrefslogtreecommitdiff
path: root/tools/driver
diff options
context:
space:
mode:
Diffstat (limited to 'tools/driver')
-rw-r--r--tools/driver/CMakeLists.txt24
-rw-r--r--tools/driver/cc1_main.cpp25
-rw-r--r--tools/driver/cc1as_main.cpp87
-rw-r--r--tools/driver/cc1gen_reproducer_main.cpp196
-rw-r--r--tools/driver/driver.cpp40
5 files changed, 292 insertions, 80 deletions
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 22a498422aef0..15b0519e4111b 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -4,6 +4,7 @@ set( LLVM_LINK_COMPONENTS
CodeGen
Core
IPO
+ AggressiveInstCombine
InstCombine
Instrumentation
MC
@@ -32,6 +33,7 @@ add_clang_tool(clang
driver.cpp
cc1_main.cpp
cc1as_main.cpp
+ cc1gen_reproducer_main.cpp
DEPENDS
${tablegen_deps}
@@ -61,10 +63,6 @@ add_dependencies(clang clang-headers)
if(NOT CLANG_LINKS_TO_CREATE)
set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp)
-
- if (MSVC)
- list(APPEND CLANG_LINKS_TO_CREATE ../msbuild-bin/cl)
- endif()
endif()
foreach(link ${CLANG_LINKS_TO_CREATE})
@@ -96,20 +94,16 @@ if (APPLE)
set(TOOL_INFO_BUILD_VERSION)
endif()
-if(CLANG_ORDER_FILE AND (LD64_EXECUTABLE OR GOLD_EXECUTABLE))
- include(CMakePushCheckState)
-
- function(check_linker_flag flag out_var)
- cmake_push_check_state()
- set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${flag}")
- check_cxx_compiler_flag("" ${out_var})
- cmake_pop_check_state()
- endfunction()
+if(CLANG_ORDER_FILE AND
+ (LLVM_LINKER_IS_LD64 OR LLVM_LINKER_IS_GOLD OR LLVM_LINKER_IS_LLD))
+ include(CheckLinkerFlag)
- if (LD64_EXECUTABLE)
+ if (LLVM_LINKER_IS_LD64)
set(LINKER_ORDER_FILE_OPTION "-Wl,-order_file,${CLANG_ORDER_FILE}")
- elseif (GOLD_EXECUTABLE)
+ elseif (LLVM_LINKER_IS_GOLD)
set(LINKER_ORDER_FILE_OPTION "-Wl,--section-ordering-file,${CLANG_ORDER_FILE}")
+ elseif (LLVM_LINKER_IS_LLD)
+ set(LINKER_ORDER_FILE_OPTION "-Wl,--symbol-ordering-file,${CLANG_ORDER_FILE}")
endif()
# This is a test to ensure the actual order file works with the linker.
diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp
index 1a16746d589d3..ef5a191bda0a6 100644
--- a/tools/driver/cc1_main.cpp
+++ b/tools/driver/cc1_main.cpp
@@ -16,6 +16,7 @@
#include "llvm/Option/Arg.h"
#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
#include "clang/Config/config.h"
+#include "clang/Basic/Stack.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -26,6 +27,7 @@
#include "clang/Frontend/Utils.h"
#include "clang/FrontendTool/Utils.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
@@ -72,13 +74,6 @@ void initializePollyPasses(llvm::PassRegistry &Registry);
#endif
#ifdef CLANG_HAVE_RLIMITS
-// The amount of stack we think is "sufficient". If less than this much is
-// available, we may be unable to reach our template instantiation depth
-// limit and other similar limits.
-// FIXME: Unify this with the stack we request when spawning a thread to build
-// a module.
-static const int kSufficientStack = 8 << 20;
-
#if defined(__linux__) && defined(__PIE__)
static size_t getCurrentStackAllocation() {
// If we can't compute the current stack usage, allow for 512K of command
@@ -116,7 +111,7 @@ static size_t getCurrentStackAllocation() {
#include <alloca.h>
LLVM_ATTRIBUTE_NOINLINE
-static void ensureStackAddressSpace(int ExtraChunks = 0) {
+static void ensureStackAddressSpace() {
// Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary
// relatively close to the stack (they are only guaranteed to be 128MiB
// apart). This results in crashes if we happen to heap-allocate more than
@@ -125,7 +120,7 @@ static void ensureStackAddressSpace(int ExtraChunks = 0) {
// To avoid these crashes, ensure that we have sufficient virtual memory
// pages allocated before we start running.
size_t Curr = getCurrentStackAllocation();
- const int kTargetStack = kSufficientStack - 256 * 1024;
+ const int kTargetStack = DesiredStackSize - 256 * 1024;
if (Curr < kTargetStack) {
volatile char *volatile Alloc =
static_cast<volatile char *>(alloca(kTargetStack - Curr));
@@ -145,21 +140,23 @@ static void ensureSufficientStack() {
// Increase the soft stack limit to our desired level, if necessary and
// possible.
- if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < kSufficientStack) {
+ if (rlim.rlim_cur != RLIM_INFINITY &&
+ rlim.rlim_cur < rlim_t(DesiredStackSize)) {
// Try to allocate sufficient stack.
- if (rlim.rlim_max == RLIM_INFINITY || rlim.rlim_max >= kSufficientStack)
- rlim.rlim_cur = kSufficientStack;
+ if (rlim.rlim_max == RLIM_INFINITY ||
+ rlim.rlim_max >= rlim_t(DesiredStackSize))
+ rlim.rlim_cur = DesiredStackSize;
else if (rlim.rlim_cur == rlim.rlim_max)
return;
else
rlim.rlim_cur = rlim.rlim_max;
if (setrlimit(RLIMIT_STACK, &rlim) != 0 ||
- rlim.rlim_cur != kSufficientStack)
+ rlim.rlim_cur != DesiredStackSize)
return;
}
- // We should now have a stack of size at least kSufficientStack. Ensure
+ // We should now have a stack of size at least DesiredStackSize. Ensure
// that we can actually use that much, if necessary.
ensureStackAddressSpace();
}
diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp
index 9b90562af903a..09db014019bf0 100644
--- a/tools/driver/cc1as_main.cpp
+++ b/tools/driver/cc1as_main.cpp
@@ -29,6 +29,7 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -61,7 +62,7 @@ using namespace llvm::opt;
namespace {
-/// \brief Helper class for representing a single invocation of the assembler.
+/// Helper class for representing a single invocation of the assembler.
struct AssemblerInvocation {
/// @name Target Options
/// @{
@@ -93,9 +94,11 @@ struct AssemblerInvocation {
std::string DwarfDebugFlags;
std::string DwarfDebugProducer;
std::string DebugCompilationDir;
+ std::map<const std::string, const std::string> DebugPrefixMap;
llvm::DebugCompressionType CompressDebugSections =
llvm::DebugCompressionType::None;
std::string MainFileName;
+ std::string SplitDwarfFile;
/// @}
/// @name Frontend Options
@@ -181,7 +184,13 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
// Issue errors on unknown arguments.
for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
- Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
+ auto ArgString = A->getAsString(Args);
+ std::string Nearest;
+ if (OptTbl->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
+ Diags.Report(diag::err_drv_unknown_argument) << ArgString;
+ else
+ Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
+ << ArgString << Nearest;
Success = false;
}
@@ -225,6 +234,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
+ for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
+ Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
+
// Frontend Options
if (Args.hasArg(OPT_INPUT)) {
bool First = true;
@@ -240,6 +252,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
}
Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
Opts.OutputPath = Args.getLastArgValue(OPT_o);
+ Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
if (Arg *A = Args.getLastArg(OPT_filetype)) {
StringRef Name = A->getValue();
unsigned OutputType = StringSwitch<unsigned>(Name)
@@ -275,22 +288,17 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
}
static std::unique_ptr<raw_fd_ostream>
-getOutputStream(AssemblerInvocation &Opts, DiagnosticsEngine &Diags,
- bool Binary) {
- if (Opts.OutputPath.empty())
- Opts.OutputPath = "-";
-
+getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
// Make sure that the Out file gets unlinked from the disk if we get a
// SIGINT.
- if (Opts.OutputPath != "-")
- sys::RemoveFileOnSignal(Opts.OutputPath);
+ if (Path != "-")
+ sys::RemoveFileOnSignal(Path);
std::error_code EC;
auto Out = llvm::make_unique<raw_fd_ostream>(
- Opts.OutputPath, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
+ Path, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
if (EC) {
- Diags.Report(diag::err_fe_unable_to_open_output) << Opts.OutputPath
- << EC.message();
+ Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
return nullptr;
}
@@ -335,9 +343,15 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations);
bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
- std::unique_ptr<raw_fd_ostream> FDOS = getOutputStream(Opts, Diags, IsBinary);
+ if (Opts.OutputPath.empty())
+ Opts.OutputPath = "-";
+ std::unique_ptr<raw_fd_ostream> FDOS =
+ getOutputStream(Opts.OutputPath, Diags, IsBinary);
if (!FDOS)
return true;
+ std::unique_ptr<raw_fd_ostream> DwoOS;
+ if (!Opts.SplitDwarfFile.empty())
+ DwoOS = getOutputStream(Opts.SplitDwarfFile, Diags, IsBinary);
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
@@ -367,6 +381,9 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));
if (!Opts.DebugCompilationDir.empty())
Ctx.setCompilationDir(Opts.DebugCompilationDir);
+ if (!Opts.DebugPrefixMap.empty())
+ for (const auto &KV : Opts.DebugPrefixMap)
+ Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
if (!Opts.MainFileName.empty())
Ctx.setMainFileName(StringRef(Opts.MainFileName));
Ctx.setDwarfVersion(Opts.DwarfVersion);
@@ -392,17 +409,19 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
MCInstPrinter *IP = TheTarget->createMCInstPrinter(
llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI);
- MCCodeEmitter *CE = nullptr;
- MCAsmBackend *MAB = nullptr;
- if (Opts.ShowEncoding) {
- CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
- MCTargetOptions Options;
- MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU, Options);
- }
+
+ std::unique_ptr<MCCodeEmitter> CE;
+ if (Opts.ShowEncoding)
+ CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
+ MCTargetOptions MCOptions;
+ std::unique_ptr<MCAsmBackend> MAB(
+ TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
+
auto FOut = llvm::make_unique<formatted_raw_ostream>(*Out);
Str.reset(TheTarget->createAsmStreamer(
Ctx, std::move(FOut), /*asmverbose*/ true,
- /*useDwarfDirectory*/ true, IP, CE, MAB, Opts.ShowInst));
+ /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB),
+ Opts.ShowInst));
} else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
Str.reset(createNullStreamer(Ctx));
} else {
@@ -413,18 +432,26 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
Out = BOS.get();
}
- MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
- MCTargetOptions Options;
- MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,
- Opts.CPU, Options);
+ std::unique_ptr<MCCodeEmitter> CE(
+ TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
+ MCTargetOptions MCOptions;
+ std::unique_ptr<MCAsmBackend> MAB(
+ TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
+ std::unique_ptr<MCObjectWriter> OW =
+ DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)
+ : MAB->createObjectWriter(*Out);
+
Triple T(Opts.Triple);
Str.reset(TheTarget->createMCObjectStreamer(
- T, Ctx, std::unique_ptr<MCAsmBackend>(MAB), *Out, std::unique_ptr<MCCodeEmitter>(CE), *STI,
+ T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ true));
Str.get()->InitSections(Opts.NoExecStack);
}
+ // Assembly to object compilation should leverage assembly info.
+ Str->setUseAssemblerInfoForParsing(true);
+
bool Failed = false;
std::unique_ptr<MCAsmParser> Parser(
@@ -461,8 +488,12 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
FDOS.reset();
// Delete output file if there were errors.
- if (Failed && Opts.OutputPath != "-")
- sys::fs::remove(Opts.OutputPath);
+ if (Failed) {
+ if (Opts.OutputPath != "-")
+ sys::fs::remove(Opts.OutputPath);
+ if (!Opts.SplitDwarfFile.empty() && Opts.SplitDwarfFile != "-")
+ sys::fs::remove(Opts.SplitDwarfFile);
+ }
return Failed;
}
diff --git a/tools/driver/cc1gen_reproducer_main.cpp b/tools/driver/cc1gen_reproducer_main.cpp
new file mode 100644
index 0000000000000..a4c034d8d3572
--- /dev/null
+++ b/tools/driver/cc1gen_reproducer_main.cpp
@@ -0,0 +1,196 @@
+//===-- cc1gen_reproducer_main.cpp - Clang reproducer generator ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the entry point to the clang -cc1gen-reproducer functionality, which
+// generates reproducers for invocations for clang-based tools.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+namespace {
+
+struct UnsavedFileHash {
+ std::string Name;
+ std::string MD5;
+};
+
+struct ClangInvocationInfo {
+ std::string Toolchain;
+ std::string LibclangOperation;
+ std::string LibclangOptions;
+ std::vector<std::string> Arguments;
+ std::vector<std::string> InvocationArguments;
+ std::vector<UnsavedFileHash> UnsavedFileHashes;
+ bool Dump = false;
+};
+
+} // end anonymous namespace
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(UnsavedFileHash)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<UnsavedFileHash> {
+ static void mapping(IO &IO, UnsavedFileHash &Info) {
+ IO.mapRequired("name", Info.Name);
+ IO.mapRequired("md5", Info.MD5);
+ }
+};
+
+template <> struct MappingTraits<ClangInvocationInfo> {
+ static void mapping(IO &IO, ClangInvocationInfo &Info) {
+ IO.mapRequired("toolchain", Info.Toolchain);
+ IO.mapOptional("libclang.operation", Info.LibclangOperation);
+ IO.mapOptional("libclang.opts", Info.LibclangOptions);
+ IO.mapRequired("args", Info.Arguments);
+ IO.mapOptional("invocation-args", Info.InvocationArguments);
+ IO.mapOptional("unsaved_file_hashes", Info.UnsavedFileHashes);
+ }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+static std::string generateReproducerMetaInfo(const ClangInvocationInfo &Info) {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ OS << '{';
+ bool NeedComma = false;
+ auto EmitKey = [&](StringRef Key) {
+ if (NeedComma)
+ OS << ", ";
+ NeedComma = true;
+ OS << '"' << Key << "\": ";
+ };
+ auto EmitStringKey = [&](StringRef Key, StringRef Value) {
+ if (Value.empty())
+ return;
+ EmitKey(Key);
+ OS << '"' << Value << '"';
+ };
+ EmitStringKey("libclang.operation", Info.LibclangOperation);
+ EmitStringKey("libclang.opts", Info.LibclangOptions);
+ if (!Info.InvocationArguments.empty()) {
+ EmitKey("invocation-args");
+ OS << '[';
+ for (const auto &Arg : llvm::enumerate(Info.InvocationArguments)) {
+ if (Arg.index())
+ OS << ',';
+ OS << '"' << Arg.value() << '"';
+ }
+ OS << ']';
+ }
+ OS << '}';
+ // FIXME: Compare unsaved file hashes and report mismatch in the reproducer.
+ if (Info.Dump)
+ llvm::outs() << "REPRODUCER METAINFO: " << OS.str() << "\n";
+ return std::move(OS.str());
+}
+
+/// Generates a reproducer for a set of arguments from a specific invocation.
+static llvm::Optional<driver::Driver::CompilationDiagnosticReport>
+generateReproducerForInvocationArguments(ArrayRef<const char *> Argv,
+ const ClangInvocationInfo &Info) {
+ using namespace driver;
+ auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(Argv[0]);
+
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions;
+
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, new IgnoringDiagConsumer());
+ ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
+ Driver TheDriver(Argv[0], llvm::sys::getDefaultTargetTriple(), Diags);
+ TheDriver.setTargetAndMode(TargetAndMode);
+
+ std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Argv));
+ if (C && !C->containsError()) {
+ for (const auto &J : C->getJobs()) {
+ if (const Command *Cmd = dyn_cast<Command>(&J)) {
+ Driver::CompilationDiagnosticReport Report;
+ TheDriver.generateCompilationDiagnostics(
+ *C, *Cmd, generateReproducerMetaInfo(Info), &Report);
+ return Report;
+ }
+ }
+ }
+
+ return None;
+}
+
+std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes);
+
+static void printReproducerInformation(
+ llvm::raw_ostream &OS, const ClangInvocationInfo &Info,
+ const driver::Driver::CompilationDiagnosticReport &Report) {
+ OS << "REPRODUCER:\n";
+ OS << "{\n";
+ OS << R"("files":[)";
+ for (const auto &File : llvm::enumerate(Report.TemporaryFiles)) {
+ if (File.index())
+ OS << ',';
+ OS << '"' << File.value() << '"';
+ }
+ OS << "]\n}\n";
+}
+
+int cc1gen_reproducer_main(ArrayRef<const char *> Argv, const char *Argv0,
+ void *MainAddr) {
+ if (Argv.size() < 1) {
+ llvm::errs() << "error: missing invocation file\n";
+ return 1;
+ }
+ // Parse the invocation descriptor.
+ StringRef Input = Argv[0];
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
+ llvm::MemoryBuffer::getFile(Input);
+ if (!Buffer) {
+ llvm::errs() << "error: failed to read " << Input << ": "
+ << Buffer.getError().message() << "\n";
+ return 1;
+ }
+ llvm::yaml::Input YAML(Buffer.get()->getBuffer());
+ ClangInvocationInfo InvocationInfo;
+ YAML >> InvocationInfo;
+ if (Argv.size() > 1 && Argv[1] == StringRef("-v"))
+ InvocationInfo.Dump = true;
+
+ // Create an invocation that will produce the reproducer.
+ std::vector<const char *> DriverArgs;
+ for (const auto &Arg : InvocationInfo.Arguments)
+ DriverArgs.push_back(Arg.c_str());
+ std::string Path = GetExecutablePath(Argv0, /*CanonicalPrefixes=*/true);
+ DriverArgs[0] = Path.c_str();
+ llvm::Optional<driver::Driver::CompilationDiagnosticReport> Report =
+ generateReproducerForInvocationArguments(DriverArgs, InvocationInfo);
+
+ // Emit the information about the reproduce files to stdout.
+ int Result = 1;
+ if (Report) {
+ printReproducerInformation(llvm::outs(), InvocationInfo, *Report);
+ Result = 0;
+ }
+
+ // Remove the input file.
+ llvm::sys::fs::remove(Input);
+ return Result;
+}
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index fa757da9535c2..0455ba029c654 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -12,9 +12,9 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Driver/Driver.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Compilation.h"
-#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
@@ -26,7 +26,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
@@ -34,9 +33,8 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Regex.h"
@@ -205,6 +203,8 @@ extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
void *MainAddr);
extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
void *MainAddr);
+extern int cc1gen_reproducer_main(ArrayRef<const char *> Argv,
+ const char *Argv0, void *MainAddr);
static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
SmallVectorImpl<const char *> &ArgVector,
@@ -212,20 +212,21 @@ static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
// Put target and mode arguments at the start of argument list so that
// arguments specified in command line could override them. Avoid putting
// them at index 0, as an option like '-cc1' must remain the first.
- auto InsertionPoint = ArgVector.begin();
- if (InsertionPoint != ArgVector.end())
+ int InsertionPoint = 0;
+ if (ArgVector.size() > 0)
++InsertionPoint;
if (NameParts.DriverMode) {
// Add the mode flag to the arguments.
- ArgVector.insert(InsertionPoint,
+ ArgVector.insert(ArgVector.begin() + InsertionPoint,
GetStableCStr(SavedStrings, NameParts.DriverMode));
}
if (NameParts.TargetIsValid) {
const char *arr[] = {"-target", GetStableCStr(SavedStrings,
NameParts.TargetPrefix)};
- ArgVector.insert(InsertionPoint, std::begin(arr), std::end(arr));
+ ArgVector.insert(ArgVector.begin() + InsertionPoint,
+ std::begin(arr), std::end(arr));
}
}
@@ -309,29 +310,22 @@ static int ExecuteCC1Tool(ArrayRef<const char *> argv, StringRef Tool) {
return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP);
if (Tool == "as")
return cc1as_main(argv.slice(2), argv[0], GetExecutablePathVP);
+ if (Tool == "gen-reproducer")
+ return cc1gen_reproducer_main(argv.slice(2), argv[0], GetExecutablePathVP);
// Reject unknown tools.
- llvm::errs() << "error: unknown integrated tool '" << Tool << "'\n";
+ llvm::errs() << "error: unknown integrated tool '" << Tool << "'. "
+ << "Valid tools include '-cc1' and '-cc1as'.\n";
return 1;
}
int main(int argc_, const char **argv_) {
- llvm::sys::PrintStackTraceOnErrorSignal(argv_[0]);
- llvm::PrettyStackTraceProgram X(argc_, argv_);
- llvm::llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ llvm::InitLLVM X(argc_, argv_);
+ SmallVector<const char *, 256> argv(argv_, argv_ + argc_);
if (llvm::sys::Process::FixupStandardFileDescriptors())
return 1;
- SmallVector<const char *, 256> argv;
- llvm::SpecificBumpPtrAllocator<char> ArgAllocator;
- std::error_code EC = llvm::sys::Process::GetArgumentVector(
- argv, llvm::makeArrayRef(argv_, argc_), ArgAllocator);
- if (EC) {
- llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';
- return 1;
- }
-
llvm::InitializeAllTargets();
auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(argv[0]);
@@ -490,7 +484,7 @@ int main(int argc_, const char **argv_) {
// On Windows, abort will return an exit code of 3. In these cases,
// generate additional diagnostic information if possible.
bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70;
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
DiagnoseCrash |= CommandRes == 3;
#endif
if (DiagnoseCrash) {
@@ -506,7 +500,7 @@ int main(int argc_, const char **argv_) {
// results now. This happens in -disable-free mode.
llvm::TimerGroup::printAll(llvm::errs());
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
// Exit status should not be negative on Win32, unless abnormal termination.
// Once abnormal termiation was caught, negative status should not be
// propagated.