aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-06-07 23:27:59 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-06-07 23:27:59 +0000
commit6f8362c6bf854b809e270a7d1bf727e0e21f7d2e (patch)
tree7c425bb0045ff30f87b36cce1ae09f5afb98a5b2
parent9507f9cc054da3b8148ac294ea5ced79625a897f (diff)
downloadllvm-6f8362c6bf854b809e270a7d1bf727e0e21f7d2e.zip
llvm-6f8362c6bf854b809e270a7d1bf727e0e21f7d2e.tar.gz
llvm-6f8362c6bf854b809e270a7d1bf727e0e21f7d2e.tar.bz2
Frontend: Add CodeGenAction support for handling LLVM IR.
- This magically enables using 'clang -cc1' as a replacement for most of 'llvm-as', 'llvm-dis', 'llc' and 'opt' functionality. For example, 'llvm-as' is: $ clang -cc1 -emit-llvm-bc FOO.ll -o FOO.bc and 'llvm-dis' is: $ clang -cc1 -emit-llvm FOO.bc -o - and 'opt' is, e.g.: $ clang -cc1 -emit-llvm -O3 -o FOO.opt.ll FOO.ll and 'llc' is, e.g.: $ clang -cc1 -S -o - FOO.ll The nice thing about using the backend tools this way is that they are guaranteed to exactly match how the compiler generates code (for example, setting the same backend options). llvm-svn: 105583
-rw-r--r--clang/include/clang/Frontend/CodeGenAction.h4
-rw-r--r--clang/include/clang/Frontend/FrontendAction.h1
-rw-r--r--clang/lib/Frontend/CodeGenAction.cpp88
-rw-r--r--clang/test/Frontend/ir-support-codegen.ll8
-rw-r--r--clang/test/Frontend/ir-support-errors.ll8
-rw-r--r--clang/tools/driver/CMakeLists.txt1
-rw-r--r--clang/tools/driver/Makefile3
7 files changed, 98 insertions, 15 deletions
diff --git a/clang/include/clang/Frontend/CodeGenAction.h b/clang/include/clang/Frontend/CodeGenAction.h
index dfc117a..e05176a 100644
--- a/clang/include/clang/Frontend/CodeGenAction.h
+++ b/clang/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/clang/include/clang/Frontend/FrontendAction.h b/clang/include/clang/Frontend/FrontendAction.h
index 5a627ef..b16a6aa 100644
--- a/clang/include/clang/Frontend/FrontendAction.h
+++ b/clang/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/clang/lib/Frontend/CodeGenAction.cpp b/clang/lib/Frontend/CodeGenAction.cpp
index 99af838..22b3bd4 100644
--- a/clang/lib/Frontend/CodeGenAction.cpp
+++ b/clang/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/clang/test/Frontend/ir-support-codegen.ll b/clang/test/Frontend/ir-support-codegen.ll
new file mode 100644
index 0000000..046b3af
--- /dev/null
+++ b/clang/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/clang/test/Frontend/ir-support-errors.ll b/clang/test/Frontend/ir-support-errors.ll
new file mode 100644
index 0000000..98227d4
--- /dev/null
+++ b/clang/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/clang/tools/driver/CMakeLists.txt b/clang/tools/driver/CMakeLists.txt
index 706f050..0eaddba 100644
--- a/clang/tools/driver/CMakeLists.txt
+++ b/clang/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/clang/tools/driver/Makefile b/clang/tools/driver/Makefile
index f88d229d..ac98730 100644
--- a/clang/tools/driver/Makefile
+++ b/clang/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