]> granicus.if.org Git - clang/commitdiff
Frontend: Add CodeGenAction support for handling LLVM IR.\r - This magically enables...
authorDaniel Dunbar <daniel@zuster.org>
Mon, 7 Jun 2010 23:27:59 +0000 (23:27 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Mon, 7 Jun 2010 23:27:59 +0000 (23:27 +0000)
and 'llvm-dis' is:\r  $ 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).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105583 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/CodeGenAction.h
include/clang/Frontend/FrontendAction.h
lib/Frontend/CodeGenAction.cpp
test/Frontend/ir-support-codegen.ll [new file with mode: 0644]
test/Frontend/ir-support-errors.ll [new file with mode: 0644]
tools/driver/CMakeLists.txt
tools/driver/Makefile

index dfc117a0b06ccfcbbf10d93033aa492b3065539c..e05176a6892678c49c7c26993ce5c53093e87f83 100644 (file)
@@ -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:
index 5a627ef960def589dc91dc367d94f6420311df1b..b16a6aa5093de45b8b4bfb63c58a366e75a05a74 100644 (file)
@@ -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.
   ///
index 99af838a33ca0658e5de554fcd7bcc6ca413f8ba..22b3bd416d8cdad31119a3a418f2f5110780bbdb 100644 (file)
@@ -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 (file)
index 0000000..046b3af
--- /dev/null
@@ -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 (file)
index 0000000..98227d4
--- /dev/null
@@ -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
+}
index 706f05051c52e9b6112483316a65f8866064b0c6..0eaddba4739d43bf098817a979b5a82812d89a24 100644 (file)
@@ -16,6 +16,7 @@ set( LLVM_USED_LIBS
 
 set( LLVM_LINK_COMPONENTS
   ${LLVM_TARGETS_TO_BUILD}
+  asmparser
   bitreader
   bitwriter
   codegen
index f88d229d00c1d1fb087cd632176751a5ac54a673..ac98730328f880874a1077c98c6fd4e75fce19ee 100644 (file)
@@ -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