mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 19:49:36 +00:00
Add support for lazily linking bitcode files (using a new
-mlink-bitcode-file flag), and more generally llvm::Modules, before running optimisations. llvm-svn: 143314
This commit is contained in:
parent
9cdb9ffa43
commit
f1d76db466
@ -25,6 +25,7 @@ set(LLVM_LINK_COMPONENTS
|
||||
bitwriter
|
||||
codegen
|
||||
ipo
|
||||
linker
|
||||
selectiondag
|
||||
)
|
||||
|
||||
|
@ -16,7 +16,7 @@ NO_INSTALL = 1
|
||||
TOOL_NO_EXPORTS = 1
|
||||
|
||||
LINK_COMPONENTS := jit interpreter nativecodegen bitreader bitwriter ipo \
|
||||
selectiondag asmparser instrumentation
|
||||
linker selectiondag asmparser instrumentation
|
||||
USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a clangCodeGen.a \
|
||||
clangParse.a clangSema.a clangStaticAnalyzerFrontend.a \
|
||||
clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a \
|
||||
|
@ -19,6 +19,8 @@ def err_fe_invalid_ast_action : Error<"invalid action for AST input">,
|
||||
// Error generated by the backend.
|
||||
def err_fe_inline_asm : Error<"%0">, CatInlineAsm;
|
||||
def note_fe_inline_asm_here : Note<"instantiated into assembly here">;
|
||||
def err_fe_cannot_link_module : Error<"cannot link module '%0': %1">,
|
||||
DefaultFatal;
|
||||
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@ class CodeGenAction : public ASTFrontendAction {
|
||||
private:
|
||||
unsigned Act;
|
||||
llvm::OwningPtr<llvm::Module> TheModule;
|
||||
llvm::Module *LinkModule;
|
||||
llvm::LLVMContext *VMContext;
|
||||
bool OwnsVMContext;
|
||||
|
||||
@ -46,6 +47,11 @@ protected:
|
||||
public:
|
||||
~CodeGenAction();
|
||||
|
||||
/// setLinkModule - Set the link module to be used by this action. If a link
|
||||
/// module is not provided, and CodeGenOptions::LinkBitcodeFile is non-empty,
|
||||
/// the action will load it from the specified file.
|
||||
void setLinkModule(llvm::Module *Mod) { LinkModule = Mod; }
|
||||
|
||||
/// takeModule - Take the generated LLVM module, for use after the action has
|
||||
/// been run. The result may be null on failure.
|
||||
llvm::Module *takeModule();
|
||||
|
@ -196,6 +196,8 @@ def mms_bitfields : Flag<"-mms-bitfields">,
|
||||
HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">;
|
||||
def mstackrealign : Flag<"-mstackrealign">,
|
||||
HelpText<"Force realign the stack at entry to every function.">;
|
||||
def mlink_bitcode_file : Separate<"-mlink-bitcode-file">,
|
||||
HelpText<"Link the given bitcode file before performing optimizations.">;
|
||||
def O : Joined<"-O">, HelpText<"Optimization level">;
|
||||
def Os : Flag<"-Os">, HelpText<"Optimize for size">;
|
||||
def Oz : Flag<"-Oz">, HelpText<"Optimize for size, regardless of performance">;
|
||||
|
@ -128,6 +128,9 @@ public:
|
||||
/// The float precision limit to use, if non-empty.
|
||||
std::string LimitFloatPrecision;
|
||||
|
||||
/// The name of the bitcode file to link before optzns.
|
||||
std::string LinkBitcodeFile;
|
||||
|
||||
/// The kind of inlining to perform.
|
||||
InliningMethod Inlining;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
24
clang/test/CodeGen/link-bitcode-file.c
Normal file
24
clang/test/CodeGen/link-bitcode-file.c
Normal file
@ -0,0 +1,24 @@
|
||||
// RUN: %clang_cc1 -triple i386-pc-linux-gnu -DBITCODE -emit-llvm-bc -o %t.bc %s
|
||||
// RUN: %clang_cc1 -triple i386-pc-linux-gnu -mlink-bitcode-file %t.bc -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NO-BC %s
|
||||
// RUN: %clang_cc1 -triple i386-pc-linux-gnu -DBITCODE -mlink-bitcode-file %t.bc -O3 -emit-llvm -o - %s 2>&1 | FileCheck -check-prefix=CHECK-BC %s
|
||||
|
||||
int f(void);
|
||||
|
||||
#ifdef BITCODE
|
||||
|
||||
// CHECK-BC: 'f': symbol multiply defined
|
||||
int f(void) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// CHECK-NO-BC: define i32 @g
|
||||
// CHECK-NO-BC: ret i32 42
|
||||
int g(void) {
|
||||
return f();
|
||||
}
|
||||
|
||||
// CHECK-NO-BC: define i32 @f
|
||||
|
||||
#endif
|
@ -1,11 +1,11 @@
|
||||
set( LLVM_USED_LIBS
|
||||
clangFrontendTool
|
||||
clangAST
|
||||
clangAnalysis
|
||||
clangBasic
|
||||
clangCodeGen
|
||||
clangDriver
|
||||
clangFrontend
|
||||
clangFrontendTool
|
||||
clangIndex
|
||||
clangLex
|
||||
clangParse
|
||||
@ -26,6 +26,7 @@ set( LLVM_LINK_COMPONENTS
|
||||
codegen
|
||||
instrumentation
|
||||
ipo
|
||||
linker
|
||||
selectiondag
|
||||
)
|
||||
|
||||
|
@ -30,7 +30,7 @@ TOOL_INFO_PLIST := Info.plist
|
||||
include $(CLANG_LEVEL)/../../Makefile.config
|
||||
|
||||
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter codegen \
|
||||
instrumentation ipo selectiondag
|
||||
instrumentation ipo linker selectiondag
|
||||
USEDLIBS = clangFrontendTool.a clangFrontend.a clangDriver.a \
|
||||
clangSerialization.a clangCodeGen.a clangParse.a clangSema.a \
|
||||
clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a \
|
||||
|
Loading…
Reference in New Issue
Block a user