1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00
llvm-mirror/tools/llc/llc.cpp
Diana Picus 91b64d2b23 [llc] Remove exit-on-error flag (PR27759)
This flag was introduced in r269655 with the new diagnostic handler for llc. Its
purpose was to keep the old behavior for some of the tests that didn't recover
well after an error. Those tests have been fixed, so now it's safe to remove the
flag entirely.

Fixes PR27759.

Differential Revision: http://reviews.llvm.org/D21368

llvm-svn: 273554
2016-06-23 09:49:56 +00:00

513 lines
17 KiB
C++

//===-- llc.cpp - Implement the LLVM Native Code 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 llc code generator driver. It provides a convenient
// command-line interface for generating native assembly-language code
// or C code, given LLVM bitcode.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/CodeGen/CommandFlags.h"
#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"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <memory>
using namespace llvm;
// General options for llc. Other pass-specific options are specified
// within the corresponding llc passes, and target-specific options
// and back-end code generation options are specified with the target machine.
//
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
static cl::opt<unsigned>
TimeCompilations("time-compilations", cl::Hidden, cl::init(1u),
cl::value_desc("N"),
cl::desc("Repeat compilation N times for timing"));
static cl::opt<bool>
NoIntegratedAssembler("no-integrated-as", cl::Hidden,
cl::desc("Disable integrated assembler"));
// Determine optimization level.
static cl::opt<char>
OptLevel("O",
cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
"(default = '-O2')"),
cl::Prefix,
cl::ZeroOrMore,
cl::init(' '));
static cl::opt<std::string>
TargetTriple("mtriple", cl::desc("Override target triple for module"));
static cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
cl::desc("Do not verify input module"));
static cl::opt<bool> DisableSimplifyLibCalls("disable-simplify-libcalls",
cl::desc("Disable simplify-libcalls"));
static cl::opt<bool> ShowMCEncoding("show-mc-encoding", cl::Hidden,
cl::desc("Show encoding in .s output"));
static cl::opt<bool> EnableDwarfDirectory(
"enable-dwarf-directory", cl::Hidden,
cl::desc("Use .file directives with an explicit directory."));
static cl::opt<bool> AsmVerbose("asm-verbose",
cl::desc("Add comments to directives."),
cl::init(true));
static cl::opt<bool>
CompileTwice("compile-twice", cl::Hidden,
cl::desc("Run everything twice, re-using the same pass "
"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>
GetOutputStream(const char *TargetName, Triple::OSType OS,
const char *ProgName) {
// If we don't yet have an output filename, make one.
if (OutputFilename.empty()) {
if (InputFilename == "-")
OutputFilename = "-";
else {
// If InputFilename ends in .bc or .ll, remove it.
StringRef IFN = InputFilename;
if (IFN.endswith(".bc") || IFN.endswith(".ll"))
OutputFilename = IFN.drop_back(3);
else if (IFN.endswith(".mir"))
OutputFilename = IFN.drop_back(4);
else
OutputFilename = IFN;
switch (FileType) {
case TargetMachine::CGFT_AssemblyFile:
if (TargetName[0] == 'c') {
if (TargetName[1] == 0)
OutputFilename += ".cbe.c";
else if (TargetName[1] == 'p' && TargetName[2] == 'p')
OutputFilename += ".cpp";
else
OutputFilename += ".s";
} else
OutputFilename += ".s";
break;
case TargetMachine::CGFT_ObjectFile:
if (OS == Triple::Win32)
OutputFilename += ".obj";
else
OutputFilename += ".o";
break;
case TargetMachine::CGFT_Null:
OutputFilename += ".null";
break;
}
}
}
// Decide if we need "binary" output.
bool Binary = false;
switch (FileType) {
case TargetMachine::CGFT_AssemblyFile:
break;
case TargetMachine::CGFT_ObjectFile:
case TargetMachine::CGFT_Null:
Binary = true;
break;
}
// Open the file.
std::error_code EC;
sys::fs::OpenFlags OpenFlags = sys::fs::F_None;
if (!Binary)
OpenFlags |= sys::fs::F_Text;
auto FDOut = llvm::make_unique<tool_output_file>(OutputFilename, EC,
OpenFlags);
if (EC) {
errs() << EC.message() << '\n';
return nullptr;
}
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(argv[0]);
PrettyStackTraceProgram X(argc, argv);
// Enable debug stream buffering.
EnableDebugBuffering = true;
LLVMContext Context;
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Initialize targets first, so that --version shows registered targets.
InitializeAllTargets();
InitializeAllTargetMCs();
InitializeAllAsmPrinters();
InitializeAllAsmParsers();
// Initialize codegen and IR passes used by llc so that the -print-after,
// -print-before, and -stop-after options work.
PassRegistry *Registry = PassRegistry::getPassRegistry();
initializeCore(*Registry);
initializeCodeGen(*Registry);
initializeLoopStrengthReducePass(*Registry);
initializeLowerIntrinsicsPass(*Registry);
initializeUnreachableBlockElimPass(*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)
if (int RetVal = compileModule(argv, Context))
return RetVal;
return 0;
}
static int compileModule(char **argv, LLVMContext &Context) {
// Load the module to be compiled...
SMDiagnostic Err;
std::unique_ptr<Module> M;
std::unique_ptr<MIRParser> MIR;
Triple TheTriple;
bool SkipModule = MCPU == "help" ||
(!MAttrs.empty() && MAttrs.front() == "help");
// If user just wants to list available options, skip module loading
if (!SkipModule) {
if (StringRef(InputFilename).endswith_lower(".mir")) {
MIR = createMIRParserFromFile(InputFilename, Err, Context);
if (MIR)
M = MIR->parseLLVMModule();
} else
M = parseIRFile(InputFilename, Err, Context);
if (!M) {
Err.print(argv[0], errs());
return 1;
}
// Verify module immediately to catch problems before doInitialization() is
// called on any passes.
if (!NoVerify && verifyModule(*M, &errs())) {
errs() << argv[0] << ": " << InputFilename
<< ": error: input module is broken!\n";
return 1;
}
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
M->setTargetTriple(Triple::normalize(TargetTriple));
TheTriple = Triple(M->getTargetTriple());
} else {
TheTriple = Triple(Triple::normalize(TargetTriple));
}
if (TheTriple.getTriple().empty())
TheTriple.setTriple(sys::getDefaultTargetTriple());
// Get the target specific parser.
std::string Error;
const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple,
Error);
if (!TheTarget) {
errs() << argv[0] << ": " << Error;
return 1;
}
std::string CPUStr = getCPUStr(), FeaturesStr = getFeaturesStr();
CodeGenOpt::Level OLvl = CodeGenOpt::Default;
switch (OptLevel) {
default:
errs() << argv[0] << ": invalid optimization level.\n";
return 1;
case ' ': break;
case '0': OLvl = CodeGenOpt::None; break;
case '1': OLvl = CodeGenOpt::Less; break;
case '2': OLvl = CodeGenOpt::Default; break;
case '3': OLvl = CodeGenOpt::Aggressive; break;
}
TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Options.DisableIntegratedAS = NoIntegratedAssembler;
Options.MCOptions.ShowMCEncoding = ShowMCEncoding;
Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory;
Options.MCOptions.AsmVerbose = AsmVerbose;
std::unique_ptr<TargetMachine> Target(
TheTarget->createTargetMachine(TheTriple.getTriple(), CPUStr, FeaturesStr,
Options, getRelocModel(), CMModel, OLvl));
assert(Target && "Could not allocate target machine!");
// If we don't have a module then just exit now. We do this down
// here since the CPU/Feature help is underneath the target machine
// creation.
if (SkipModule)
return 0;
assert(M && "Should have exited if we didn't have a module!");
if (FloatABIForCalls != FloatABI::Default)
Options.FloatABIType = FloatABIForCalls;
// Figure out where we are going to send the output.
std::unique_ptr<tool_output_file> Out =
GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]);
if (!Out) return 1;
// Build up all of the passes that we want to do to the module.
legacy::PassManager PM;
// Add an appropriate TargetLibraryInfo pass for the module's triple.
TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
// The -disable-simplify-libcalls flag actually disables all builtin optzns.
if (DisableSimplifyLibCalls)
TLII.disableAllFunctions();
PM.add(new TargetLibraryInfoWrapperPass(TLII));
// Add the target data from the target machine, if it exists, or the module.
M->setDataLayout(Target->createDataLayout());
// Override function attributes based on CPUStr, FeaturesStr, and command line
// flags.
setFunctionAttributes(CPUStr, FeaturesStr, *M);
if (RelaxAll.getNumOccurrences() > 0 &&
FileType != TargetMachine::CGFT_ObjectFile)
errs() << argv[0]
<< ": warning: ignoring -mc-relax-all because filetype != obj";
{
raw_pwrite_stream *OS = &Out->os();
// Manually do the buffering rather than using buffer_ostream,
// so we can memcmp the contents in CompileTwice mode
SmallVector<char, 0> Buffer;
std::unique_ptr<raw_svector_ostream> BOS;
if ((FileType != TargetMachine::CGFT_AssemblyFile &&
!Out->os().supportsSeeking()) ||
CompileTwice) {
BOS = make_unique<raw_svector_ostream>(Buffer);
OS = BOS.get();
}
AnalysisID StartBeforeID = nullptr;
AnalysisID StartAfterID = nullptr;
AnalysisID StopAfterID = nullptr;
const PassRegistry *PR = PassRegistry::getPassRegistry();
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;
}
if (!MIR) {
errs() << argv[0] << ": run-pass needs a .mir input.\n";
return 1;
}
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 (std::string &RunPassName : *RunPassNames) {
const PassInfo *PI = PR->getPassInfo(RunPassName);
if (!PI) {
errs() << argv[0] << ": run-pass " << RunPassName << " is not registered.\n";
return 1;
}
Pass *P;
if (PI->getTargetMachineCtor())
P = PI->getTargetMachineCtor()(Target.get());
else if (PI->getNormalCtor())
P = PI->getNormalCtor()();
else {
errs() << argv[0] << ": cannot create pass: "
<< PI->getPassName() << "\n";
return 1;
}
std::string Banner
= std::string("After ") + std::string(P->getPassName());
PM.add(P);
TPC->printAndVerify(Banner);
}
PM.add(createPrintMIRPass(errs()));
} else {
if (!StartAfter.empty()) {
const PassInfo *PI = PR->getPassInfo(StartAfter);
if (!PI) {
errs() << argv[0] << ": start-after pass is not registered.\n";
return 1;
}
StartAfterID = PI->getTypeInfo();
}
if (!StopAfter.empty()) {
const PassInfo *PI = PR->getPassInfo(StopAfter);
if (!PI) {
errs() << argv[0] << ": stop-after pass is not registered.\n";
return 1;
}
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;
}
}
// Before executing passes, print the final values of the LLVM options.
cl::PrintOptionValues();
// If requested, run the pass manager over the same module again,
// to catch any bugs due to persistent state in the passes. Note that
// opt has the same functionality, so it may be worth abstracting this out
// in the future.
SmallVector<char, 0> CompileTwiceBuffer;
if (CompileTwice) {
std::unique_ptr<Module> M2(llvm::CloneModule(M.get()));
PM.run(*M2);
CompileTwiceBuffer = Buffer;
Buffer.clear();
}
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() ||
(memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) !=
0)) {
errs()
<< "Running the pass manager twice changed the output.\n"
"Writing the result of the second run to the specified output\n"
"To generate the one-run comparison binary, just run without\n"
"the compile-twice option\n";
Out->os() << Buffer;
Out->keep();
return 1;
}
}
if (BOS) {
Out->os() << Buffer;
}
}
// Declare success.
Out->keep();
return 0;
}