diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/BackendUtil.cpp | 325 | ||||
-rw-r--r-- | lib/CodeGen/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenAction.cpp | 348 |
3 files changed, 675 insertions, 0 deletions
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp new file mode 100644 index 0000000000..766b239c4c --- /dev/null +++ b/lib/CodeGen/BackendUtil.cpp @@ -0,0 +1,325 @@ +//===--- BackendUtil.cpp - LLVM Backend Utilities -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/CodeGen/BackendUtil.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/TargetOptions.h" +#include "clang/CodeGen/CodeGenOptions.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/StandardPasses.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#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 EmitAssemblyHelper { + Diagnostic &Diags; + const CodeGenOptions &CodeGenOpts; + const TargetOptions &TargetOpts; + Module *TheModule; + + Timer CodeGenerationTime; + + mutable FunctionPassManager *CodeGenPasses; + mutable PassManager *PerModulePasses; + mutable FunctionPassManager *PerFunctionPasses; + +private: + FunctionPassManager *getCodeGenPasses() const { + if (!CodeGenPasses) { + CodeGenPasses = new FunctionPassManager(TheModule); + CodeGenPasses->add(new TargetData(TheModule)); + } + return CodeGenPasses; + } + + PassManager *getPerModulePasses() const { + if (!PerModulePasses) { + PerModulePasses = new PassManager(); + PerModulePasses->add(new TargetData(TheModule)); + } + return PerModulePasses; + } + + FunctionPassManager *getPerFunctionPasses() const { + if (!PerFunctionPasses) { + PerFunctionPasses = new FunctionPassManager(TheModule); + PerFunctionPasses->add(new TargetData(TheModule)); + } + return PerFunctionPasses; + } + + void CreatePasses(); + + /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR. + /// + /// \return True on success. + bool AddEmitPasses(BackendAction Action, formatted_raw_ostream &OS); + +public: + EmitAssemblyHelper(Diagnostic &_Diags, + const CodeGenOptions &CGOpts, const TargetOptions &TOpts, + Module *M) + : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), + TheModule(M), CodeGenerationTime("Code Generation Time"), + CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {} + + ~EmitAssemblyHelper() { + delete CodeGenPasses; + delete PerModulePasses; + delete PerFunctionPasses; + } + + void EmitAssembly(BackendAction Action, raw_ostream *OS); +}; + +} + +void EmitAssemblyHelper::CreatePasses() { + unsigned OptLevel = CodeGenOpts.OptimizationLevel; + CodeGenOptions::InliningMethod Inlining = CodeGenOpts.Inlining; + + // Handle disabling of LLVM optimization, where we want to preserve the + // internal module before any optimization. + if (CodeGenOpts.DisableLLVMOpts) { + OptLevel = 0; + Inlining = CodeGenOpts.NoInlining; + } + + // In -O0 if checking is disabled, we don't even have per-function passes. + if (CodeGenOpts.VerifyModule) + getPerFunctionPasses()->add(createVerifierPass()); + + // Assume that standard function passes aren't run for -O0. + if (OptLevel > 0) + llvm::createStandardFunctionPasses(getPerFunctionPasses(), OptLevel); + + llvm::Pass *InliningPass = 0; + switch (Inlining) { + case CodeGenOptions::NoInlining: break; + case CodeGenOptions::NormalInlining: { + // Set the inline threshold following llvm-gcc. + // + // FIXME: Derive these constants in a principled fashion. + unsigned Threshold = 225; + if (CodeGenOpts.OptimizeSize) + Threshold = 75; + else if (OptLevel > 2) + Threshold = 275; + InliningPass = createFunctionInliningPass(Threshold); + break; + } + case CodeGenOptions::OnlyAlwaysInlining: + InliningPass = createAlwaysInlinerPass(); // Respect always_inline + break; + } + + // For now we always create per module passes. + llvm::createStandardModulePasses(getPerModulePasses(), OptLevel, + CodeGenOpts.OptimizeSize, + CodeGenOpts.UnitAtATime, + CodeGenOpts.UnrollLoops, + CodeGenOpts.SimplifyLibCalls, + /*HaveExceptions=*/true, + InliningPass); +} + +bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, + formatted_raw_ostream &OS) { + // Create the TargetMachine for generating code. + std::string Error; + std::string Triple = TheModule->getTargetTriple(); + const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); + if (!TheTarget) { + 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); + + TargetMachine::setFunctionSections(CodeGenOpts.FunctionSections); + TargetMachine::setDataSections (CodeGenOpts.DataSections); + + // 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.DebugPass.empty()) { + BackendArgs.push_back("-debug-pass"); + BackendArgs.push_back(CodeGenOpts.DebugPass.c_str()); + } + if (!CodeGenOpts.LimitFloatPrecision.empty()) { + BackendArgs.push_back("-limit-float-precision"); + BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str()); + } + if (llvm::TimePassesIsEnabled) + BackendArgs.push_back("-time-passes"); + BackendArgs.push_back(0); + llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, + const_cast<char **>(&BackendArgs[0])); + + std::string FeaturesStr; + if (TargetOpts.CPU.size() || TargetOpts.Features.size()) { + SubtargetFeatures Features; + Features.setCPU(TargetOpts.CPU); + for (std::vector<std::string>::const_iterator + it = TargetOpts.Features.begin(), + ie = TargetOpts.Features.end(); it != ie; ++it) + Features.AddFeature(*it); + FeaturesStr = Features.getString(); + } + TargetMachine *TM = TheTarget->createTargetMachine(Triple, FeaturesStr); + + if (CodeGenOpts.RelaxAll) + TM->setMCRelaxAll(true); + + // Create the code generator passes. + FunctionPassManager *PM = getCodeGenPasses(); + CodeGenOpt::Level OptLevel = CodeGenOpt::Default; + + switch (CodeGenOpts.OptimizationLevel) { + default: break; + case 0: OptLevel = CodeGenOpt::None; break; + case 3: OptLevel = CodeGenOpt::Aggressive; break; + } + + // Normal mode, emit a .s or .o file by running the code generator. Note, + // this also adds codegenerator level optimization passes. + TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile; + if (Action == Backend_EmitObj) + CGFT = TargetMachine::CGFT_ObjectFile; + else if (Action == Backend_EmitMCNull) + CGFT = TargetMachine::CGFT_Null; + else + assert(Action == Backend_EmitAssembly && "Invalid action!"); + if (TM->addPassesToEmitFile(*PM, OS, CGFT, OptLevel, + /*DisableVerify=*/!CodeGenOpts.VerifyModule)) { + Diags.Report(diag::err_fe_unable_to_interface_with_target); + return false; + } + + return true; +} + +void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) { + TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : 0); + llvm::formatted_raw_ostream FormattedOS; + + CreatePasses(); + switch (Action) { + case Backend_EmitNothing: + break; + + case Backend_EmitBC: + getPerModulePasses()->add(createBitcodeWriterPass(*OS)); + break; + + case Backend_EmitLL: + FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM); + getPerModulePasses()->add(createPrintModulePass(&FormattedOS)); + break; + + default: + FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM); + if (!AddEmitPasses(Action, FormattedOS)) + return; + } + + // Run passes. For now we do all passes at once, but eventually we + // would like to have the option of streaming code generation. + + if (PerFunctionPasses) { + PrettyStackTraceString CrashInfo("Per-function optimization"); + + PerFunctionPasses->doInitialization(); + for (Module::iterator I = TheModule->begin(), + E = TheModule->end(); I != E; ++I) + if (!I->isDeclaration()) + PerFunctionPasses->run(*I); + PerFunctionPasses->doFinalization(); + } + + if (PerModulePasses) { + PrettyStackTraceString CrashInfo("Per-module optimization passes"); + PerModulePasses->run(*TheModule); + } + + if (CodeGenPasses) { + PrettyStackTraceString CrashInfo("Code generation"); + + CodeGenPasses->doInitialization(); + for (Module::iterator I = TheModule->begin(), + E = TheModule->end(); I != E; ++I) + if (!I->isDeclaration()) + CodeGenPasses->run(*I); + CodeGenPasses->doFinalization(); + } +} + +void clang::EmitBackendOutput(Diagnostic &Diags, const CodeGenOptions &CGOpts, + const TargetOptions &TOpts, Module *M, + BackendAction Action, raw_ostream *OS) { + EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, M); + + AsmHelper.EmitAssembly(Action, OS); +} diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index bb2160e2c4..be2f3dc4cc 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_NO_RTTI 1) add_clang_library(clangCodeGen + BackendUtil.cpp CGBlocks.cpp CGBuiltin.cpp CGCall.cpp @@ -25,6 +26,7 @@ add_clang_library(clangCodeGen CGTemporaries.cpp CGVTables.cpp CGVTT.cpp + CodeGenAction.cpp CodeGenFunction.cpp CodeGenModule.cpp CodeGenTypes.cpp diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp new file mode 100644 index 0000000000..51c55a1a83 --- /dev/null +++ b/lib/CodeGen/CodeGenAction.cpp @@ -0,0 +1,348 @@ +//===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclGroup.h" +#include "clang/CodeGen/BackendUtil.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/IRReader.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/Timer.h" +using namespace clang; +using namespace llvm; + +namespace { + class BackendConsumer : public ASTConsumer { + Diagnostic &Diags; + BackendAction Action; + const CodeGenOptions &CodeGenOpts; + const TargetOptions &TargetOpts; + llvm::raw_ostream *AsmOutStream; + ASTContext *Context; + + Timer LLVMIRGeneration; + + llvm::OwningPtr<CodeGenerator> Gen; + + llvm::OwningPtr<llvm::Module> TheModule; + + public: + BackendConsumer(BackendAction action, Diagnostic &_Diags, + const CodeGenOptions &compopts, + const TargetOptions &targetopts, bool TimePasses, + const std::string &infile, llvm::raw_ostream *OS, + LLVMContext &C) : + Diags(_Diags), + Action(action), + CodeGenOpts(compopts), + TargetOpts(targetopts), + AsmOutStream(OS), + LLVMIRGeneration("LLVM IR Generation Time"), + Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)) { + llvm::TimePassesIsEnabled = TimePasses; + } + + llvm::Module *takeModule() { return TheModule.take(); } + + virtual void Initialize(ASTContext &Ctx) { + Context = &Ctx; + + if (llvm::TimePassesIsEnabled) + LLVMIRGeneration.startTimer(); + + Gen->Initialize(Ctx); + + TheModule.reset(Gen->GetModule()); + + if (llvm::TimePassesIsEnabled) + LLVMIRGeneration.stopTimer(); + } + + virtual void HandleTopLevelDecl(DeclGroupRef D) { + PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), + Context->getSourceManager(), + "LLVM IR generation of declaration"); + + if (llvm::TimePassesIsEnabled) + LLVMIRGeneration.startTimer(); + + Gen->HandleTopLevelDecl(D); + + if (llvm::TimePassesIsEnabled) + LLVMIRGeneration.stopTimer(); + } + + virtual void HandleTranslationUnit(ASTContext &C) { + { + PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); + if (llvm::TimePassesIsEnabled) + LLVMIRGeneration.startTimer(); + + Gen->HandleTranslationUnit(C); + + if (llvm::TimePassesIsEnabled) + LLVMIRGeneration.stopTimer(); + } + + // Silently ignore if we weren't initialized for some reason. + if (!TheModule) + return; + + // Make sure IR generation is happy with the module. This is released by + // the module provider. + Module *M = Gen->ReleaseModule(); + if (!M) { + // The module has been released by IR gen on failures, do not double + // free. + TheModule.take(); + return; + } + + assert(TheModule.get() == M && + "Unexpected module change during IR generation"); + + // Install an inline asm handler so that diagnostics get printed through + // our diagnostics hooks. + LLVMContext &Ctx = TheModule->getContext(); + void *OldHandler = Ctx.getInlineAsmDiagnosticHandler(); + void *OldContext = Ctx.getInlineAsmDiagnosticContext(); + Ctx.setInlineAsmDiagnosticHandler((void*)(intptr_t)InlineAsmDiagHandler, + this); + + EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, + TheModule.get(), Action, AsmOutStream); + + Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); + } + + virtual void HandleTagDeclDefinition(TagDecl *D) { + PrettyStackTraceDecl CrashInfo(D, SourceLocation(), + Context->getSourceManager(), + "LLVM IR generation of declaration"); + Gen->HandleTagDeclDefinition(D); + } + + virtual void CompleteTentativeDefinition(VarDecl *D) { + Gen->CompleteTentativeDefinition(D); + } + + virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { + Gen->HandleVTable(RD, DefinitionRequired); + } + + static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, + unsigned LocCookie) { + SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); + ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); + } + + void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, + SourceLocation LocCookie); + }; +} + +/// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr +/// buffer to be a valid FullSourceLoc. +static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, + SourceManager &CSM) { + // Get both the clang and llvm source managers. The location is relative to + // a memory buffer that the LLVM Source Manager is handling, we need to add + // a copy to the Clang source manager. + const llvm::SourceMgr &LSM = *D.getSourceMgr(); + + // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr + // already owns its one and clang::SourceManager wants to own its one. + const MemoryBuffer *LBuf = + LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); + + // Create the copy and transfer ownership to clang::SourceManager. + llvm::MemoryBuffer *CBuf = + llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), + LBuf->getBufferIdentifier()); + FileID FID = CSM.createFileIDForMemBuffer(CBuf); + + // Translate the offset into the file. + unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); + SourceLocation NewLoc = + CSM.getLocForStartOfFile(FID).getFileLocWithOffset(Offset); + return FullSourceLoc(NewLoc, CSM); +} + + +/// InlineAsmDiagHandler2 - This function is invoked when the backend hits an +/// error parsing inline asm. The SMDiagnostic indicates the error relative to +/// the temporary memory buffer that the inline asm parser has set up. +void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, + SourceLocation LocCookie) { + // There are a couple of different kinds of errors we could get here. First, + // we re-format the SMDiagnostic in terms of a clang diagnostic. + + // Strip "error: " off the start of the message string. + llvm::StringRef Message = D.getMessage(); + if (Message.startswith("error: ")) + Message = Message.substr(7); + + // If the SMDiagnostic has an inline asm source location, translate it. + FullSourceLoc Loc; + if (D.getLoc() != SMLoc()) + Loc = ConvertBackendLocation(D, Context->getSourceManager()); + + + // If this problem has clang-level source location information, report the + // issue as being an error in the source with a note showing the instantiated + // code. + if (LocCookie.isValid()) { + Diags.Report(FullSourceLoc(LocCookie, Context->getSourceManager()), + diag::err_fe_inline_asm).AddString(Message); + + if (D.getLoc().isValid()) + Diags.Report(Loc, diag::note_fe_inline_asm_here); + return; + } + + // Otherwise, report the backend error as occuring in the generated .s file. + // If Loc is invalid, we still need to report the error, it just gets no + // location info. + Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message); +} + +// + +CodeGenAction::CodeGenAction(unsigned _Act) : Act(_Act) {} + +CodeGenAction::~CodeGenAction() {} + +bool CodeGenAction::hasIRSupport() const { return true; } + +void CodeGenAction::EndSourceFileAction() { + // If the consumer creation failed, do nothing. + if (!getCompilerInstance().hasASTConsumer()) + return; + + // Steal the module from the consumer. + BackendConsumer *Consumer = static_cast<BackendConsumer*>( + &getCompilerInstance().getASTConsumer()); + + TheModule.reset(Consumer->takeModule()); +} + +llvm::Module *CodeGenAction::takeModule() { + return TheModule.take(); +} + +static raw_ostream *GetOutputStream(CompilerInstance &CI, + llvm::StringRef InFile, + BackendAction Action) { + switch (Action) { + case Backend_EmitAssembly: + return CI.createDefaultOutputFile(false, InFile, "s"); + case Backend_EmitLL: + return CI.createDefaultOutputFile(false, InFile, "ll"); + case Backend_EmitBC: + return CI.createDefaultOutputFile(true, InFile, "bc"); + case Backend_EmitNothing: + return 0; + case Backend_EmitMCNull: + case Backend_EmitObj: + return CI.createDefaultOutputFile(true, InFile, "o"); + } + + assert(0 && "Invalid action!"); + return 0; +} + +ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile) { + BackendAction BA = static_cast<BackendAction>(Act); + llvm::OwningPtr<llvm::raw_ostream> OS(GetOutputStream(CI, InFile, BA)); + if (BA != Backend_EmitNothing && !OS) + return 0; + + return new BackendConsumer(BA, CI.getDiagnostics(), + CI.getCodeGenOpts(), CI.getTargetOpts(), + CI.getFrontendOpts().ShowTimers, InFile, OS.take(), + CI.getLLVMContext()); +} + +void CodeGenAction::ExecuteAction() { + // If this is an IR file, we have to treat it specially. + if (getCurrentFileKind() == IK_LLVM_IR) { + BackendAction BA = static_cast<BackendAction>(Act); + CompilerInstance &CI = getCompilerInstance(); + raw_ostream *OS = GetOutputStream(CI, getCurrentFile(), BA); + if (BA != Backend_EmitNothing && !OS) + return; + + bool Invalid; + SourceManager &SM = CI.getSourceManager(); + const llvm::MemoryBuffer *MainFile = SM.getBuffer(SM.getMainFileID(), + &Invalid); + if (Invalid) + return; + + // FIXME: This is stupid, IRReader shouldn't take ownership. + llvm::MemoryBuffer *MainFileCopy = + llvm::MemoryBuffer::getMemBufferCopy(MainFile->getBuffer(), + getCurrentFile().c_str()); + + llvm::SMDiagnostic Err; + TheModule.reset(ParseIR(MainFileCopy, Err, CI.getLLVMContext())); + if (!TheModule) { + // Translate from the diagnostic info to the SourceManager location. + SourceLocation Loc = SM.getLocation( + SM.getFileEntryForID(SM.getMainFileID()), Err.getLineNo(), + Err.getColumnNo() + 1); + + // Get a custom diagnostic for the error. We strip off a leading + // diagnostic code if there is one. + llvm::StringRef Msg = Err.getMessage(); + if (Msg.startswith("error: ")) + Msg = Msg.substr(7); + unsigned DiagID = CI.getDiagnostics().getCustomDiagID(Diagnostic::Error, + Msg); + + CI.getDiagnostics().Report(FullSourceLoc(Loc, SM), DiagID); + return; + } + + EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), + CI.getTargetOpts(), TheModule.get(), + BA, OS); + return; + } + + // Otherwise follow the normal AST path. + this->ASTFrontendAction::ExecuteAction(); +} + +// + +EmitAssemblyAction::EmitAssemblyAction() + : CodeGenAction(Backend_EmitAssembly) {} + +EmitBCAction::EmitBCAction() : CodeGenAction(Backend_EmitBC) {} + +EmitLLVMAction::EmitLLVMAction() : CodeGenAction(Backend_EmitLL) {} + +EmitLLVMOnlyAction::EmitLLVMOnlyAction() : CodeGenAction(Backend_EmitNothing) {} + +EmitCodeGenOnlyAction::EmitCodeGenOnlyAction() : CodeGenAction(Backend_EmitMCNull) {} + +EmitObjAction::EmitObjAction() : CodeGenAction(Backend_EmitObj) {} |