diff options
Diffstat (limited to 'tools/llc/llc.cpp')
-rw-r--r-- | tools/llc/llc.cpp | 134 |
1 files changed, 115 insertions, 19 deletions
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index bffa39fd9e5c..9b6086ad4ea8 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -21,7 +21,12 @@ #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" #include "llvm/CodeGen/MIRParser/MIRParser.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" @@ -68,6 +73,11 @@ static cl::opt<bool> NoIntegratedAssembler("no-integrated-as", cl::Hidden, cl::desc("Disable integrated assembler")); +static cl::opt<bool> + PreserveComments("preserve-as-comments", cl::Hidden, + cl::desc("Preserve Comments in outputted assembly"), + cl::init(true)); + // Determine optimization level. static cl::opt<char> OptLevel("O", @@ -103,6 +113,33 @@ static cl::opt<bool> "manager and verify the result is the same."), cl::init(false)); +static cl::opt<bool> DiscardValueNames( + "discard-value-names", + cl::desc("Discard names from Value (other than GlobalValue)."), + cl::init(false), cl::Hidden); + +namespace { +static ManagedStatic<std::vector<std::string>> RunPassNames; + +struct RunPassOption { + void operator=(const std::string &Val) const { + if (Val.empty()) + return; + SmallVector<StringRef, 8> PassNames; + StringRef(Val).split(PassNames, ',', -1, false); + for (auto PassName : PassNames) + RunPassNames->push_back(PassName); + } +}; +} + +static RunPassOption RunPassOpt; + +static cl::opt<RunPassOption, true, cl::parser<std::string>> RunPass( + "run-pass", + cl::desc("Run compiler only for specified passes (comma separated list)"), + cl::value_desc("pass-name"), cl::ZeroOrMore, cl::location(RunPassOpt)); + static int compileModule(char **, LLVMContext &); static std::unique_ptr<tool_output_file> @@ -173,16 +210,27 @@ GetOutputStream(const char *TargetName, Triple::OSType OS, return FDOut; } +static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context) { + bool *HasError = static_cast<bool *>(Context); + if (DI.getSeverity() == DS_Error) + *HasError = true; + + DiagnosticPrinterRawOStream DP(errs()); + errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; + DI.print(DP); + errs() << "\n"; +} + // main - Entry point for the llc compiler. // int main(int argc, char **argv) { - sys::PrintStackTraceOnErrorSignal(); + sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; - LLVMContext &Context = getGlobalContext(); + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets first, so that --version shows registered targets. @@ -198,13 +246,19 @@ int main(int argc, char **argv) { initializeCodeGen(*Registry); initializeLoopStrengthReducePass(*Registry); initializeLowerIntrinsicsPass(*Registry); - initializeUnreachableBlockElimPass(*Registry); + initializeUnreachableBlockElimLegacyPassPass(*Registry); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); + Context.setDiscardValueNames(DiscardValueNames); + + // Set a diagnostic handler that doesn't exit on the first error + bool HasError = false; + Context.setDiagnosticHandler(DiagnosticHandler, &HasError); + // Compile the module TimeCompilations times to give better compile time // metrics. for (unsigned I = TimeCompilations; I; --I) @@ -213,6 +267,34 @@ int main(int argc, char **argv) { return 0; } +static bool addPass(PassManagerBase &PM, const char *argv0, + StringRef PassName, TargetPassConfig &TPC) { + if (PassName == "none") + return false; + + const PassRegistry *PR = PassRegistry::getPassRegistry(); + const PassInfo *PI = PR->getPassInfo(PassName); + if (!PI) { + errs() << argv0 << ": run-pass " << PassName << " is not registered.\n"; + return true; + } + + Pass *P; + if (PI->getTargetMachineCtor()) + P = PI->getTargetMachineCtor()(&TPC.getTM<TargetMachine>()); + else if (PI->getNormalCtor()) + P = PI->getNormalCtor()(); + else { + errs() << argv0 << ": cannot create pass: " << PI->getPassName() << "\n"; + return true; + } + std::string Banner = std::string("After ") + std::string(P->getPassName()); + PM.add(P); + TPC.printAndVerify(Banner); + + return false; +} + static int compileModule(char **argv, LLVMContext &Context) { // Load the module to be compiled... SMDiagnostic Err; @@ -227,10 +309,8 @@ static int compileModule(char **argv, LLVMContext &Context) { if (!SkipModule) { if (StringRef(InputFilename).endswith_lower(".mir")) { MIR = createMIRParserFromFile(InputFilename, Err, Context); - if (MIR) { + if (MIR) M = MIR->parseLLVMModule(); - assert(M && "parseLLVMModule should exit on failure"); - } } else M = parseIRFile(InputFilename, Err, Context); if (!M) { @@ -285,10 +365,11 @@ static int compileModule(char **argv, LLVMContext &Context) { Options.MCOptions.ShowMCEncoding = ShowMCEncoding; Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory; Options.MCOptions.AsmVerbose = AsmVerbose; + Options.MCOptions.PreserveAsmComments = PreserveComments; std::unique_ptr<TargetMachine> Target( TheTarget->createTargetMachine(TheTriple.getTriple(), CPUStr, FeaturesStr, - Options, RelocModel, CMModel, OLvl)); + Options, getRelocModel(), CMModel, OLvl)); assert(Target && "Could not allocate target machine!"); @@ -348,18 +429,28 @@ static int compileModule(char **argv, LLVMContext &Context) { AnalysisID StartAfterID = nullptr; AnalysisID StopAfterID = nullptr; const PassRegistry *PR = PassRegistry::getPassRegistry(); - if (!RunPass.empty()) { + if (!RunPassNames->empty()) { if (!StartAfter.empty() || !StopAfter.empty()) { errs() << argv[0] << ": start-after and/or stop-after passes are " "redundant when run-pass is specified.\n"; return 1; } - const PassInfo *PI = PR->getPassInfo(RunPass); - if (!PI) { - errs() << argv[0] << ": run-pass pass is not registered.\n"; + if (!MIR) { + errs() << argv[0] << ": run-pass needs a .mir input.\n"; return 1; } - StopAfterID = StartBeforeID = PI->getTypeInfo(); + LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine&>(*Target); + TargetPassConfig &TPC = *LLVMTM.createPassConfig(PM); + PM.add(&TPC); + LLVMTM.addMachineModuleInfo(PM); + LLVMTM.addMachineFunctionAnalysis(PM, MIR.get()); + TPC.printAndVerify(""); + + for (const std::string &RunPassName : *RunPassNames) { + if (addPass(PM, argv[0], RunPassName, TPC)) + return 1; + } + PM.add(createPrintMIRPass(*OS)); } else { if (!StartAfter.empty()) { const PassInfo *PI = PR->getPassInfo(StartAfter); @@ -377,14 +468,15 @@ static int compileModule(char **argv, LLVMContext &Context) { } StopAfterID = PI->getTypeInfo(); } - } - // Ask the target to add backend passes as necessary. - if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, StartBeforeID, - StartAfterID, StopAfterID, MIR.get())) { - errs() << argv[0] << ": target does not support generation of this" - << " file type!\n"; - return 1; + // Ask the target to add backend passes as necessary. + if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, + StartBeforeID, StartAfterID, StopAfterID, + MIR.get())) { + errs() << argv[0] << ": target does not support generation of this" + << " file type!\n"; + return 1; + } } // Before executing passes, print the final values of the LLVM options. @@ -404,6 +496,10 @@ static int compileModule(char **argv, LLVMContext &Context) { PM.run(*M); + auto HasError = *static_cast<bool *>(Context.getDiagnosticContext()); + if (HasError) + return 1; + // Compare the two outputs and make sure they're the same if (CompileTwice) { if (Buffer.size() != CompileTwiceBuffer.size() || |