#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"
CodeGenAction::~CodeGenAction() {}
+bool CodeGenAction::hasIRSupport() const { return true; }
+
void CodeGenAction::EndSourceFileAction() {
// If the consumer creation failed, do nothing.
if (!getCompilerInstance().hasASTConsumer())
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;
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) {}