diff options
-rw-r--r-- | include/clang/Frontend/CodeGenAction.h | 4 | ||||
-rw-r--r-- | include/clang/Frontend/FrontendAction.h | 1 | ||||
-rw-r--r-- | lib/Frontend/CodeGenAction.cpp | 88 | ||||
-rw-r--r-- | test/Frontend/ir-support-codegen.ll | 8 | ||||
-rw-r--r-- | test/Frontend/ir-support-errors.ll | 8 | ||||
-rw-r--r-- | tools/driver/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tools/driver/Makefile | 3 |
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 |