#include "llvm/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/IRReader.h"
#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
-#include "llvm/Config/config.h"
+#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/System/Host.h"
-#include "llvm/System/Signals.h"
-#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetSelect.h"
#include <memory>
using namespace llvm;
cl::desc("Target specific attributes (-mattr=help for details)"),
cl::value_desc("a1,+a2,-a3,..."));
+static cl::opt<Reloc::Model>
+RelocModel("relocation-model",
+ cl::desc("Choose relocation model"),
+ cl::init(Reloc::Default),
+ cl::values(
+ clEnumValN(Reloc::Default, "default",
+ "Target default relocation model"),
+ clEnumValN(Reloc::Static, "static",
+ "Non-relocatable code"),
+ clEnumValN(Reloc::PIC_, "pic",
+ "Fully relocatable, position independent code"),
+ clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+ "Relocatable external references, non-relocatable code"),
+ clEnumValEnd));
+
+static cl::opt<llvm::CodeModel::Model>
+CMModel("code-model",
+ cl::desc("Choose code model"),
+ cl::init(CodeModel::Default),
+ cl::values(clEnumValN(CodeModel::Default, "default",
+ "Target default code model"),
+ clEnumValN(CodeModel::Small, "small",
+ "Small code model"),
+ clEnumValN(CodeModel::Kernel, "kernel",
+ "Kernel code model"),
+ clEnumValN(CodeModel::Medium, "medium",
+ "Medium code model"),
+ clEnumValN(CodeModel::Large, "large",
+ "Large code model"),
+ clEnumValEnd));
+
+static cl::opt<bool>
+RelaxAll("mc-relax-all",
+ cl::desc("When used with filetype=obj, "
+ "relax all fixups in the emitted object file"));
+
cl::opt<TargetMachine::CodeGenFileType>
FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
cl::desc("Choose a file type (not all types are supported by all targets):"),
clEnumValN(TargetMachine::CGFT_AssemblyFile, "asm",
"Emit an assembly ('.s') file"),
clEnumValN(TargetMachine::CGFT_ObjectFile, "obj",
- "Emit a native object ('.o') file [experimental]"),
+ "Emit a native object ('.o') file"),
clEnumValN(TargetMachine::CGFT_Null, "null",
"Emit nothing, for performance testing"),
clEnumValEnd));
cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
cl::desc("Do not verify input module"));
+cl::opt<bool> DisableDotLoc("disable-dot-loc", cl::Hidden,
+ cl::desc("Do not use .loc entries"));
+
+cl::opt<bool> DisableCFI("disable-cfi", cl::Hidden,
+ cl::desc("Do not use .cfi_* directives"));
+
+cl::opt<bool> EnableDwarfDirectory("enable-dwarf-directory", cl::Hidden,
+ cl::desc("Use .file directives with an explicit directory."));
static cl::opt<bool>
DisableRedZone("disable-red-zone",
cl::init(false));
static cl::opt<bool>
-NoImplicitFloats("no-implicit-float",
- cl::desc("Don't generate implicit floating point instructions (x86-only)"),
+EnableFPMAD("enable-fp-mad",
+ cl::desc("Enable less precise MAD instructions to be generated"),
+ cl::init(false));
+
+static cl::opt<bool>
+DisableFPElim("disable-fp-elim",
+ cl::desc("Disable frame pointer elimination optimization"),
+ cl::init(false));
+
+static cl::opt<bool>
+DisableFPElimNonLeaf("disable-non-leaf-fp-elim",
+ cl::desc("Disable frame pointer elimination optimization for non-leaf funcs"),
+ cl::init(false));
+
+static cl::opt<bool>
+DisableExcessPrecision("disable-excess-fp-precision",
+ cl::desc("Disable optimizations that may increase FP precision"),
+ cl::init(false));
+
+static cl::opt<bool>
+EnableUnsafeFPMath("enable-unsafe-fp-math",
+ cl::desc("Enable optimizations that may decrease FP precision"),
+ cl::init(false));
+
+static cl::opt<bool>
+EnableNoInfsFPMath("enable-no-infs-fp-math",
+ cl::desc("Enable FP math optimizations that assume no +-Infs"),
+ cl::init(false));
+
+static cl::opt<bool>
+EnableNoNaNsFPMath("enable-no-nans-fp-math",
+ cl::desc("Enable FP math optimizations that assume no NaNs"),
+ cl::init(false));
+
+static cl::opt<bool>
+EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math",
+ cl::Hidden,
+ cl::desc("Force codegen to assume rounding mode can change dynamically"),
+ cl::init(false));
+
+static cl::opt<bool>
+GenerateSoftFloatCalls("soft-float",
+ cl::desc("Generate software floating point library calls"),
+ cl::init(false));
+
+static cl::opt<llvm::FloatABI::ABIType>
+FloatABIForCalls("float-abi",
+ cl::desc("Choose float ABI type"),
+ cl::init(FloatABI::Default),
+ cl::values(
+ clEnumValN(FloatABI::Default, "default",
+ "Target default float ABI type"),
+ clEnumValN(FloatABI::Soft, "soft",
+ "Soft float ABI (implied by -soft-float)"),
+ clEnumValN(FloatABI::Hard, "hard",
+ "Hard float ABI (uses FP registers)"),
+ clEnumValEnd));
+
+static cl::opt<bool>
+DontPlaceZerosInBSS("nozero-initialized-in-bss",
+ cl::desc("Don't place zero-initialized symbols into bss section"),
+ cl::init(false));
+
+static cl::opt<bool>
+EnableGuaranteedTailCallOpt("tailcallopt",
+ cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."),
+ cl::init(false));
+
+static cl::opt<bool>
+DisableTailCalls("disable-tail-calls",
+ cl::desc("Never emit tail calls"),
+ cl::init(false));
+
+static cl::opt<unsigned>
+OverrideStackAlignment("stack-alignment",
+ cl::desc("Override default stack alignment"),
+ cl::init(0));
+
+static cl::opt<bool>
+EnableRealignStack("realign-stack",
+ cl::desc("Realign stack if needed"),
+ cl::init(true));
+
+static cl::opt<bool>
+DisableSwitchTables(cl::Hidden, "disable-jump-tables",
+ cl::desc("Do not generate jump tables."),
+ cl::init(false));
+
+static cl::opt<std::string>
+TrapFuncName("trap-func", cl::Hidden,
+ cl::desc("Emit a call to trap function rather than a trap instruction"),
+ cl::init(""));
+
+static cl::opt<bool>
+EnablePIE("enable-pie",
+ cl::desc("Assume the creation of a position independent executable."),
+ cl::init(false));
+
+static cl::opt<bool>
+SegmentedStacks("segmented-stacks",
+ cl::desc("Use segmented stacks if possible."),
+ cl::init(false));
+
+static cl::opt<bool>
+UseInitArray("use-init-array",
+ cl::desc("Use .init_array instead of .ctors."),
cl::init(false));
// GetFileNameRoot - Helper function to get the basename of a filename.
return outputFilename;
}
-static formatted_raw_ostream *GetOutputStream(const char *TargetName,
- Triple::OSType OS,
- const char *ProgName) {
- if (OutputFilename != "") {
- if (OutputFilename == "-")
- return &fouts();
-
- // Make sure that the Out file gets unlinked from the disk if we get a
- // SIGINT
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
- std::string error;
- raw_fd_ostream *FDOut =
- new raw_fd_ostream(OutputFilename.c_str(), error,
- raw_fd_ostream::F_Binary);
- if (!error.empty()) {
- errs() << error << '\n';
- delete FDOut;
- return 0;
+static 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 {
+ OutputFilename = GetFileNameRoot(InputFilename);
+
+ 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;
+ }
}
- formatted_raw_ostream *Out =
- new formatted_raw_ostream(*FDOut, formatted_raw_ostream::DELETE_STREAM);
-
- return Out;
- }
-
- if (InputFilename == "-") {
- OutputFilename = "-";
- return &fouts();
}
- OutputFilename = GetFileNameRoot(InputFilename);
-
+ // Decide if we need "binary" output.
bool Binary = false;
switch (FileType) {
- default: assert(0 && "Unknown file type");
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";
- Binary = true;
- break;
case TargetMachine::CGFT_Null:
- OutputFilename += ".null";
Binary = true;
break;
}
- // Make sure that the Out file gets unlinked from the disk if we get a
- // SIGINT
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
+ // Open the file.
std::string error;
unsigned OpenFlags = 0;
if (Binary) OpenFlags |= raw_fd_ostream::F_Binary;
- raw_fd_ostream *FDOut = new raw_fd_ostream(OutputFilename.c_str(), error,
- OpenFlags);
+ tool_output_file *FDOut = new tool_output_file(OutputFilename.c_str(), error,
+ OpenFlags);
if (!error.empty()) {
errs() << error << '\n';
delete FDOut;
return 0;
}
- formatted_raw_ostream *Out =
- new formatted_raw_ostream(*FDOut, formatted_raw_ostream::DELETE_STREAM);
-
- return Out;
+ return FDOut;
}
// main - Entry point for the llc compiler.
// Initialize targets first, so that --version shows registered targets.
InitializeAllTargets();
+ InitializeAllTargetMCs();
InitializeAllAsmPrinters();
InitializeAllAsmParsers();
+ // Register the target printer for --version.
+ cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
+
cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
-
+
// Load the module to be compiled...
SMDiagnostic Err;
std::auto_ptr<Module> M;
M.reset(ParseIRFile(InputFilename, Err, Context));
if (M.get() == 0) {
- Err.Print(argv[0], errs());
+ Err.print(argv[0], errs());
return 1;
}
Module &mod = *M.get();
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
- mod.setTargetTriple(TargetTriple);
+ mod.setTargetTriple(Triple::normalize(TargetTriple));
+ // Figure out the target triple.
Triple TheTriple(mod.getTargetTriple());
if (TheTriple.getTriple().empty())
- TheTriple.setTriple(sys::getHostTriple());
-
- // Allocate target machine. First, check whether the user has explicitly
- // specified an architecture to compile for. If so we have to look it up by
- // name, because it might be a backend that has no mapping to a target triple.
- const Target *TheTarget = 0;
- if (!MArch.empty()) {
- for (TargetRegistry::iterator it = TargetRegistry::begin(),
- ie = TargetRegistry::end(); it != ie; ++it) {
- if (MArch == it->getName()) {
- TheTarget = &*it;
- break;
- }
- }
-
- if (!TheTarget) {
- errs() << argv[0] << ": error: invalid target '" << MArch << "'.\n";
- return 1;
- }
-
- // Adjust the triple to match (if known), otherwise stick with the
- // module/host triple.
- Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch);
- if (Type != Triple::UnknownArch)
- TheTriple.setArch(Type);
- } else {
- std::string Err;
- TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Err);
- if (TheTarget == 0) {
- errs() << argv[0] << ": error auto-selecting target for module '"
- << Err << "'. Please use the -march option to explicitly "
- << "pick a target.\n";
- return 1;
- }
+ 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;
}
// Package up features to be passed to target/subtarget
std::string FeaturesStr;
- if (MCPU.size() || MAttrs.size()) {
+ if (MAttrs.size()) {
SubtargetFeatures Features;
- Features.setCPU(MCPU);
for (unsigned i = 0; i != MAttrs.size(); ++i)
Features.AddFeature(MAttrs[i]);
FeaturesStr = Features.getString();
}
- std::auto_ptr<TargetMachine>
- target(TheTarget->createTargetMachine(TheTriple.getTriple(), FeaturesStr));
- assert(target.get() && "Could not allocate target machine!");
- TargetMachine &Target = *target.get();
-
- // Figure out where we are going to send the output...
- formatted_raw_ostream *Out = GetOutputStream(TheTarget->getName(),
- TheTriple.getOS(), argv[0]);
- if (Out == 0) return 1;
-
CodeGenOpt::Level OLvl = CodeGenOpt::Default;
switch (OptLevel) {
default:
case '3': OLvl = CodeGenOpt::Aggressive; break;
}
- // Request that addPassesToEmitFile run the Verifier after running
- // passes which modify the IR.
-#ifndef NDEBUG
- bool DisableVerify = false;
-#else
- bool DisableVerify = true;
-#endif
-
- // If this target requires addPassesToEmitWholeFile, do it now. This is
- // used by strange things like the C backend.
- if (Target.WantsWholeFile()) {
- PassManager PM;
-
- // Add the target data from the target machine, if it exists, or the module.
- if (const TargetData *TD = Target.getTargetData())
- PM.add(new TargetData(*TD));
- else
- PM.add(new TargetData(&mod));
+ TargetOptions Options;
+ Options.LessPreciseFPMADOption = EnableFPMAD;
+ Options.NoFramePointerElim = DisableFPElim;
+ Options.NoFramePointerElimNonLeaf = DisableFPElimNonLeaf;
+ Options.NoExcessFPPrecision = DisableExcessPrecision;
+ Options.UnsafeFPMath = EnableUnsafeFPMath;
+ Options.NoInfsFPMath = EnableNoInfsFPMath;
+ Options.NoNaNsFPMath = EnableNoNaNsFPMath;
+ Options.HonorSignDependentRoundingFPMathOption =
+ EnableHonorSignDependentRoundingFPMath;
+ Options.UseSoftFloat = GenerateSoftFloatCalls;
+ if (FloatABIForCalls != FloatABI::Default)
+ Options.FloatABIType = FloatABIForCalls;
+ Options.NoZerosInBSS = DontPlaceZerosInBSS;
+ Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
+ Options.DisableTailCalls = DisableTailCalls;
+ Options.StackAlignmentOverride = OverrideStackAlignment;
+ Options.RealignStack = EnableRealignStack;
+ Options.DisableJumpTables = DisableSwitchTables;
+ Options.TrapFuncName = TrapFuncName;
+ Options.PositionIndependentExecutable = EnablePIE;
+ Options.EnableSegmentedStacks = SegmentedStacks;
+ Options.UseInitArray = UseInitArray;
+
+ std::auto_ptr<TargetMachine>
+ target(TheTarget->createTargetMachine(TheTriple.getTriple(),
+ MCPU, FeaturesStr, Options,
+ RelocModel, CMModel, OLvl));
+ assert(target.get() && "Could not allocate target machine!");
+ TargetMachine &Target = *target.get();
- if (!NoVerify)
- PM.add(createVerifierPass());
+ if (DisableDotLoc)
+ Target.setMCUseLoc(false);
- // Ask the target to add backend passes as necessary.
- if (Target.addPassesToEmitWholeFile(PM, *Out, FileType, OLvl,
- DisableVerify)) {
- errs() << argv[0] << ": target does not support generation of this"
- << " file type!\n";
- if (Out != &fouts()) delete Out;
- // And the Out file is empty and useless, so remove it now.
- sys::Path(OutputFilename).eraseFromDisk();
- return 1;
- }
- PM.run(mod);
- } else {
- // Build up all of the passes that we want to do to the module.
- FunctionPassManager Passes(M.get());
+ if (DisableCFI)
+ Target.setMCUseCFI(false);
- // Add the target data from the target machine, if it exists, or the module.
- if (const TargetData *TD = Target.getTargetData())
- Passes.add(new TargetData(*TD));
- else
- Passes.add(new TargetData(&mod));
+ if (EnableDwarfDirectory)
+ Target.setMCUseDwarfDirectory(true);
-#ifndef NDEBUG
- if (!NoVerify)
- Passes.add(createVerifierPass());
-#endif
+ if (GenerateSoftFloatCalls)
+ FloatABIForCalls = FloatABI::Soft;
- // Override default to generate verbose assembly.
- Target.setAsmVerbosityDefault(true);
+ // Disable .loc support for older OS X versions.
+ if (TheTriple.isMacOSX() &&
+ TheTriple.isMacOSXVersionLT(10, 6))
+ Target.setMCUseLoc(false);
- if (Target.addPassesToEmitFile(Passes, *Out, FileType, OLvl,
- DisableVerify)) {
+ // Figure out where we are going to send the output...
+ OwningPtr<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.
+ PassManager PM;
+
+ // Add the target data from the target machine, if it exists, or the module.
+ if (const TargetData *TD = Target.getTargetData())
+ PM.add(new TargetData(*TD));
+ else
+ PM.add(new TargetData(&mod));
+
+ // Override default to generate verbose assembly.
+ Target.setAsmVerbosityDefault(true);
+
+ if (RelaxAll) {
+ if (FileType != TargetMachine::CGFT_ObjectFile)
+ errs() << argv[0]
+ << ": warning: ignoring -mc-relax-all because filetype != obj";
+ else
+ Target.setMCRelaxAll(true);
+ }
+
+ {
+ formatted_raw_ostream FOS(Out->os());
+
+ // Ask the target to add backend passes as necessary.
+ if (Target.addPassesToEmitFile(PM, FOS, FileType, NoVerify)) {
errs() << argv[0] << ": target does not support generation of this"
<< " file type!\n";
- if (Out != &fouts()) delete Out;
- // And the Out file is empty and useless, so remove it now.
- sys::Path(OutputFilename).eraseFromDisk();
return 1;
}
- Passes.doInitialization();
-
- // Run our queue of passes all at once now, efficiently.
- // TODO: this could lazily stream functions out of the module.
- for (Module::iterator I = mod.begin(), E = mod.end(); I != E; ++I)
- if (!I->isDeclaration()) {
- if (DisableRedZone)
- I->addFnAttr(Attribute::NoRedZone);
- if (NoImplicitFloats)
- I->addFnAttr(Attribute::NoImplicitFloat);
- Passes.run(*I);
- }
+ // Before executing passes, print the final values of the LLVM options.
+ cl::PrintOptionValues();
- Passes.doFinalization();
+ PM.run(mod);
}
- // Delete the ostream if it's not a stdout stream
- if (Out != &fouts()) delete Out;
+ // Declare success.
+ Out->keep();
return 0;
}