diff options
Diffstat (limited to 'lib/Frontend/CodeGenAction.cpp')
-rw-r--r-- | lib/Frontend/CodeGenAction.cpp | 88 |
1 files changed, 74 insertions, 14 deletions
diff --git a/lib/Frontend/CodeGenAction.cpp b/lib/Frontend/CodeGenAction.cpp index 99af838a33..22b3bd416d 100644 --- a/lib/Frontend/CodeGenAction.cpp +++ b/lib/Frontend/CodeGenAction.cpp @@ -22,6 +22,7 @@ #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" @@ -220,6 +221,8 @@ 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()) @@ -236,27 +239,31 @@ llvm::Module *CodeGenAction::takeModule() { return TheModule.take(); } -ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile) { - BackendAction BA = static_cast<BackendAction>(Act); - llvm::OwningPtr<llvm::raw_ostream> OS; - switch (BA) { +static raw_ostream *GetOutputStream(CompilerInstance &CI, + llvm::StringRef InFile, + BackendAction Action) { + switch (Action) { case Backend_EmitAssembly: - OS.reset(CI.createDefaultOutputFile(false, InFile, "s")); - break; + return CI.createDefaultOutputFile(false, InFile, "s"); case Backend_EmitLL: - OS.reset(CI.createDefaultOutputFile(false, InFile, "ll")); - break; + return CI.createDefaultOutputFile(false, InFile, "ll"); case Backend_EmitBC: - OS.reset(CI.createDefaultOutputFile(true, InFile, "bc")); - break; + return CI.createDefaultOutputFile(true, InFile, "bc"); case Backend_EmitNothing: - break; + return 0; case Backend_EmitMCNull: case Backend_EmitObj: - OS.reset(CI.createDefaultOutputFile(true, InFile, "o")); - break; + 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; @@ -266,6 +273,59 @@ ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI, 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) {} |