aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Frontend/CodeGenAction.h4
-rw-r--r--include/clang/Frontend/FrontendAction.h1
-rw-r--r--lib/Frontend/CodeGenAction.cpp88
-rw-r--r--test/Frontend/ir-support-codegen.ll8
-rw-r--r--test/Frontend/ir-support-errors.ll8
-rw-r--r--tools/driver/CMakeLists.txt1
-rw-r--r--tools/driver/Makefile3
7 files changed, 98 insertions, 15 deletions
diff --git a/include/clang/Frontend/CodeGenAction.h b/include/clang/Frontend/CodeGenAction.h
index dfc117a0b0..e05176a689 100644
--- a/include/clang/Frontend/CodeGenAction.h
+++ b/include/clang/Frontend/CodeGenAction.h
@@ -24,9 +24,13 @@ private:
protected:
CodeGenAction(unsigned _Act);
+ virtual bool hasIRSupport() const;
+
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile);
+ virtual void ExecuteAction();
+
virtual void EndSourceFileAction();
public:
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index 5a627ef960..b16a6aa509 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -202,6 +202,7 @@ public:
/// ASTFrontendAction - Abstract base class to use for AST consumer based
/// frontend actions.
class ASTFrontendAction : public FrontendAction {
+protected:
/// ExecuteAction - Implement the ExecuteAction interface by running Sema on
/// the already initialized AST consumer.
///
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) {}
diff --git a/test/Frontend/ir-support-codegen.ll b/test/Frontend/ir-support-codegen.ll
new file mode 100644
index 0000000000..046b3af1c3
--- /dev/null
+++ b/test/Frontend/ir-support-codegen.ll
@@ -0,0 +1,8 @@
+; RUN: %clang_cc1 -S -o - %s | FileCheck %s
+
+target triple = "x86_64-apple-darwin10"
+
+; CHECK: .globl _f0
+define i32 @f0() nounwind ssp {
+ ret i32 0
+}
diff --git a/test/Frontend/ir-support-errors.ll b/test/Frontend/ir-support-errors.ll
new file mode 100644
index 0000000000..98227d46f7
--- /dev/null
+++ b/test/Frontend/ir-support-errors.ll
@@ -0,0 +1,8 @@
+; RUN: %clang_cc1 -S -o - %s 2>&1 | FileCheck %s
+
+target triple = "x86_64-apple-darwin10"
+
+define i32 @f0() nounwind ssp {
+; CHECK: {{.*}}ir-support-errors.ll:7:16: error: expected value token
+ ret i32 x
+}
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 706f05051c..0eaddba473 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -16,6 +16,7 @@ set( LLVM_USED_LIBS
set( LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
+ asmparser
bitreader
bitwriter
codegen
diff --git a/tools/driver/Makefile b/tools/driver/Makefile
index f88d229d00..ac98730328 100644
--- a/tools/driver/Makefile
+++ b/tools/driver/Makefile
@@ -26,7 +26,8 @@ TOOL_NO_EXPORTS = 1
# LINK_COMPONENTS before including Makefile.rules
include $(LEVEL)/Makefile.config
-LINK_COMPONENTS := $(TARGETS_TO_BUILD) bitreader bitwriter codegen ipo selectiondag
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter codegen \
+ ipo selectiondag
USEDLIBS = clangFrontend.a clangDriver.a clangCodeGen.a clangSema.a \
clangChecker.a clangAnalysis.a clangRewrite.a clangAST.a \
clangParse.a clangLex.a clangBasic.a