aboutsummaryrefslogtreecommitdiff
path: root/tools/llc/llc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/llc/llc.cpp')
-rw-r--r--tools/llc/llc.cpp134
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() ||