diff options
Diffstat (limited to 'lib/Frontend/Backend.cpp')
-rw-r--r-- | lib/Frontend/Backend.cpp | 101 |
1 files changed, 62 insertions, 39 deletions
diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp index 9dc109d..9be6786 100644 --- a/lib/Frontend/Backend.cpp +++ b/lib/Frontend/Backend.cpp @@ -15,6 +15,7 @@ #include "clang/Basic/TargetOptions.h" #include "clang/CodeGen/CodeGenOptions.h" #include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/FrontendDiagnostic.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/PassManager.h" @@ -31,12 +32,14 @@ #include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" using namespace clang; using namespace llvm; namespace { class BackendConsumer : public ASTConsumer { + Diagnostic &Diags; BackendAction Action; const CodeGenOptions &CodeGenOpts; const LangOptions &LangOpts; @@ -64,21 +67,20 @@ namespace { void CreatePasses(); - /// AddEmitPasses - Add passes necessary to emit assembly or LLVM - /// IR. + /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR. /// - /// \return True on success. On failure \arg Error will be set to - /// a user readable error message. - bool AddEmitPasses(std::string &Error); + /// \return True on success. + bool AddEmitPasses(); void EmitAssembly(); public: - BackendConsumer(BackendAction action, Diagnostic &Diags, + BackendConsumer(BackendAction action, Diagnostic &_Diags, const LangOptions &langopts, const CodeGenOptions &compopts, const TargetOptions &targetopts, bool TimePasses, const std::string &infile, llvm::raw_ostream *OS, LLVMContext& C) : + Diags(_Diags), Action(action), CodeGenOpts(compopts), LangOpts(langopts), @@ -195,7 +197,7 @@ FunctionPassManager *BackendConsumer::getPerFunctionPasses() const { return PerFunctionPasses; } -bool BackendConsumer::AddEmitPasses(std::string &Error) { +bool BackendConsumer::AddEmitPasses() { if (Action == Backend_EmitNothing) return true; @@ -207,48 +209,68 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) { bool Fast = CodeGenOpts.OptimizationLevel == 0; // Create the TargetMachine for generating code. + std::string Error; std::string Triple = TheModule->getTargetTriple(); const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); if (!TheTarget) { - Error = std::string("Unable to get target machine: ") + Error; + Diags.Report(diag::err_fe_unable_to_create_target) << Error; return false; } // FIXME: Expose these capabilities via actual APIs!!!! Aside from just // being gross, this is also totally broken if we ever care about // concurrency. + llvm::NoFramePointerElim = CodeGenOpts.DisableFPElim; + if (CodeGenOpts.FloatABI == "soft") + llvm::FloatABIType = llvm::FloatABI::Soft; + else if (CodeGenOpts.FloatABI == "hard") + llvm::FloatABIType = llvm::FloatABI::Hard; + else { + assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!"); + llvm::FloatABIType = llvm::FloatABI::Default; + } + NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; + llvm::UseSoftFloat = CodeGenOpts.SoftFloat; + UnwindTablesMandatory = CodeGenOpts.UnwindTables; + + TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose); + + // FIXME: Parse this earlier. + if (CodeGenOpts.RelocationModel == "static") { + TargetMachine::setRelocationModel(llvm::Reloc::Static); + } else if (CodeGenOpts.RelocationModel == "pic") { + TargetMachine::setRelocationModel(llvm::Reloc::PIC_); + } else { + assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" && + "Invalid PIC model!"); + TargetMachine::setRelocationModel(llvm::Reloc::DynamicNoPIC); + } + // FIXME: Parse this earlier. + if (CodeGenOpts.CodeModel == "small") { + TargetMachine::setCodeModel(llvm::CodeModel::Small); + } else if (CodeGenOpts.CodeModel == "kernel") { + TargetMachine::setCodeModel(llvm::CodeModel::Kernel); + } else if (CodeGenOpts.CodeModel == "medium") { + TargetMachine::setCodeModel(llvm::CodeModel::Medium); + } else if (CodeGenOpts.CodeModel == "large") { + TargetMachine::setCodeModel(llvm::CodeModel::Large); + } else { + assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!"); + TargetMachine::setCodeModel(llvm::CodeModel::Default); + } + std::vector<const char *> BackendArgs; BackendArgs.push_back("clang"); // Fake program name. - if (CodeGenOpts.AsmVerbose) - BackendArgs.push_back("-asm-verbose"); - if (!CodeGenOpts.CodeModel.empty()) { - BackendArgs.push_back("-code-model"); - BackendArgs.push_back(CodeGenOpts.CodeModel.c_str()); - } if (!CodeGenOpts.DebugPass.empty()) { BackendArgs.push_back("-debug-pass"); BackendArgs.push_back(CodeGenOpts.DebugPass.c_str()); } - if (CodeGenOpts.DisableFPElim) - BackendArgs.push_back("-disable-fp-elim"); - if (!CodeGenOpts.FloatABI.empty()) { - BackendArgs.push_back("-float-abi"); - BackendArgs.push_back(CodeGenOpts.FloatABI.c_str()); - } if (!CodeGenOpts.LimitFloatPrecision.empty()) { BackendArgs.push_back("-limit-float-precision"); BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str()); } - if (CodeGenOpts.NoZeroInitializedInBSS) - BackendArgs.push_back("-nozero-initialized-in-bss"); - if (CodeGenOpts.SoftFloat) - BackendArgs.push_back("-soft-float"); - BackendArgs.push_back("-relocation-model"); - BackendArgs.push_back(CodeGenOpts.RelocationModel.c_str()); if (llvm::TimePassesIsEnabled) BackendArgs.push_back("-time-passes"); - if (CodeGenOpts.UnwindTables) - BackendArgs.push_back("-unwind-tables"); BackendArgs.push_back(0); llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, (char**) &BackendArgs[0]); @@ -290,7 +312,7 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) { TargetMachine::AssemblyFile, OptLevel)) { default: case FileModel::Error: - Error = "Unable to interface with target machine!\n"; + Diags.Report(diag::err_fe_unable_to_interface_with_target); return false; case FileModel::AsmFile: break; @@ -298,7 +320,7 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) { if (TM->addPassesToEmitFileFinish(*CodeGenPasses, (MachineCodeEmitter *)0, OptLevel)) { - Error = "Unable to interface with target machine!\n"; + Diags.Report(diag::err_fe_unable_to_interface_with_target); return false; } } @@ -329,8 +351,14 @@ void BackendConsumer::CreatePasses() { switch (Inlining) { case CodeGenOptions::NoInlining: break; case CodeGenOptions::NormalInlining: { - // Inline small functions - unsigned Threshold = (CodeGenOpts.OptimizeSize || OptLevel < 3) ? 50 : 200; + // Set the inline threshold following llvm-gcc. + // + // FIXME: Derive these constants in a principled fashion. + unsigned Threshold = 200; + if (CodeGenOpts.OptimizeSize) + Threshold = 50; + else if (OptLevel > 2) + Threshold = 250; InliningPass = createFunctionInliningPass(Threshold); break; } @@ -372,13 +400,8 @@ void BackendConsumer::EmitAssembly() { assert(TheModule == M && "Unexpected module change during IR generation"); CreatePasses(); - - std::string Error; - if (!AddEmitPasses(Error)) { - // FIXME: Don't fail this way. - llvm::errs() << "ERROR: " << Error << "\n"; - ::exit(1); - } + if (!AddEmitPasses()) + return; // Run passes. For now we do all passes at once, but eventually we // would like to have the option of streaming code generation. |