aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2011-10-30 17:30:44 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2011-10-30 17:30:44 +0000
commit22a7dfea585703d6755db69b83e29a0e6ee10369 (patch)
treecfb53988caccc1f9a94f66ec59c8da2c0f2f0cb1 /lib
parent80b32b8c6546a12cf0d4af9c2cd785ec1f123188 (diff)
Add support for lazily linking bitcode files (using a new
-mlink-bitcode-file flag), and more generally llvm::Modules, before running optimisations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143314 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/CodeGenAction.cpp59
-rw-r--r--lib/Frontend/CompilerInvocation.cpp1
2 files changed, 54 insertions, 6 deletions
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index 11d6075582..db2bab9bf6 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/AST/ASTConsumer.h"
@@ -18,9 +19,11 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/LLVMContext.h"
+#include "llvm/Linker.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/IRReader.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
@@ -42,7 +45,7 @@ namespace clang {
llvm::OwningPtr<CodeGenerator> Gen;
- llvm::OwningPtr<llvm::Module> TheModule;
+ llvm::OwningPtr<llvm::Module> TheModule, LinkModule;
public:
BackendConsumer(BackendAction action, DiagnosticsEngine &_Diags,
@@ -50,7 +53,9 @@ namespace clang {
const TargetOptions &targetopts,
const LangOptions &langopts,
bool TimePasses,
- const std::string &infile, raw_ostream *OS,
+ const std::string &infile,
+ llvm::Module *LinkModule,
+ raw_ostream *OS,
LLVMContext &C) :
Diags(_Diags),
Action(action),
@@ -59,11 +64,13 @@ namespace clang {
LangOpts(langopts),
AsmOutStream(OS),
LLVMIRGeneration("LLVM IR Generation Time"),
- Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)) {
+ Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)),
+ LinkModule(LinkModule) {
llvm::TimePassesIsEnabled = TimePasses;
}
llvm::Module *takeModule() { return TheModule.take(); }
+ llvm::Module *takeLinkModule() { return LinkModule.take(); }
virtual void Initialize(ASTContext &Ctx) {
Context = &Ctx;
@@ -122,6 +129,17 @@ namespace clang {
assert(TheModule.get() == M &&
"Unexpected module change during IR generation");
+ // Link LinkModule into this module if present, preserving its validity.
+ if (LinkModule) {
+ std::string ErrorMsg;
+ if (Linker::LinkModules(M, LinkModule.get(), Linker::PreserveSource,
+ &ErrorMsg)) {
+ Diags.Report(diag::err_fe_cannot_link_module)
+ << LinkModule->getModuleIdentifier() << ErrorMsg;
+ return;
+ }
+ }
+
// Install an inline asm handler so that diagnostics get printed through
// our diagnostics hooks.
LLVMContext &Ctx = TheModule->getContext();
@@ -238,7 +256,8 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
//
CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
- : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext),
+ : Act(_Act), LinkModule(0),
+ VMContext(_VMContext ? _VMContext : new LLVMContext),
OwnsVMContext(!_VMContext) {}
CodeGenAction::~CodeGenAction() {
@@ -254,6 +273,10 @@ void CodeGenAction::EndSourceFileAction() {
if (!getCompilerInstance().hasASTConsumer())
return;
+ // If we were given a link module, release consumer's ownership of it.
+ if (LinkModule)
+ BEConsumer->takeLinkModule();
+
// Steal the module from the consumer.
TheModule.reset(BEConsumer->takeModule());
}
@@ -294,12 +317,36 @@ ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
if (BA != Backend_EmitNothing && !OS)
return 0;
+ llvm::Module *LinkModuleToUse = LinkModule;
+
+ // If we were not given a link module, and the user requested that one be
+ // loaded from bitcode, do so now.
+ const std::string &LinkBCFile = CI.getCodeGenOpts().LinkBitcodeFile;
+ if (!LinkModuleToUse && !LinkBCFile.empty()) {
+ std::string ErrorStr;
+
+ llvm::MemoryBuffer *BCBuf =
+ CI.getFileManager().getBufferForFile(LinkBCFile, &ErrorStr);
+ if (!BCBuf) {
+ CI.getDiagnostics().Report(diag::err_cannot_open_file)
+ << LinkBCFile << ErrorStr;
+ return 0;
+ }
+
+ LinkModuleToUse = getLazyBitcodeModule(BCBuf, *VMContext, &ErrorStr);
+ if (!LinkModuleToUse) {
+ CI.getDiagnostics().Report(diag::err_cannot_open_file)
+ << LinkBCFile << ErrorStr;
+ return 0;
+ }
+ }
+
BEConsumer =
new BackendConsumer(BA, CI.getDiagnostics(),
CI.getCodeGenOpts(), CI.getTargetOpts(),
CI.getLangOpts(),
- CI.getFrontendOpts().ShowTimers, InFile, OS.take(),
- *VMContext);
+ CI.getFrontendOpts().ShowTimers, InFile,
+ LinkModuleToUse, OS.take(), *VMContext);
return BEConsumer;
}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index a4851f1740..6950647cab 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1078,6 +1078,7 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes);
Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
+ Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) {
StringRef Name = A->getValue(Args);