forked from OSchip/llvm-project
[RuntimeDyld][Orc][MCJIT] Add partial weak-symbol support to RuntimeDyld.
This patch causes RuntimeDyld to check for existing definitions when it encounters weak symbols. If a definition already exists then the new weak definition is discarded. All symbol lookups within a "logical dylib" should now agree on the address of any given weak symbol. This allows the JIT to better match the behavior of the static linker for C++ code. This support is only partial, as it does not allow strong definitions that occur after the first weak definition (in JIT symbol lookup order) to override the previous weak definitions. Support for this will be added in a future patch. llvm-svn: 278065
This commit is contained in:
parent
30a3d8e402
commit
33c0b6bfca
|
@ -116,11 +116,13 @@ class OrcMCJITReplacement : public ExecutionEngine {
|
|||
LinkingResolver(OrcMCJITReplacement &M) : M(M) {}
|
||||
|
||||
JITSymbol findSymbol(const std::string &Name) override {
|
||||
return M.findMangledSymbol(Name);
|
||||
return M.ClientResolver->findSymbol(Name);
|
||||
}
|
||||
|
||||
JITSymbol findSymbolInLogicalDylib(const std::string &Name) override {
|
||||
return M.ClientResolver->findSymbol(Name);
|
||||
if (auto Sym = M.findMangledSymbol(Name))
|
||||
return Sym;
|
||||
return M.ClientResolver->findSymbolInLogicalDylib(Name);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -226,6 +226,24 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
|||
// Compute JIT symbol flags.
|
||||
JITSymbolFlags JITSymFlags = JITSymbolFlags::fromObjectSymbol(*I);
|
||||
|
||||
// If this is a weak definition, check to see if there's a strong one.
|
||||
// If there is, skip this symbol (we won't be providing it: the strong
|
||||
// definition will). If there's no strong definition, make this definition
|
||||
// strong.
|
||||
if (JITSymFlags.isWeak()) {
|
||||
// First check whether there's already a definition in this instance.
|
||||
// FIXME: Override existing weak definitions with strong ones.
|
||||
if (GlobalSymbolTable.count(Name))
|
||||
continue;
|
||||
// Then check the symbol resolver to see if there's a definition
|
||||
// elsewhere in this logical dylib.
|
||||
if (auto Sym = Resolver.findSymbolInLogicalDylib(Name))
|
||||
if (Sym.getFlags().isStrongDefinition())
|
||||
continue;
|
||||
// else
|
||||
JITSymFlags &= ~JITSymbolFlags::Weak;
|
||||
}
|
||||
|
||||
if (Flags & SymbolRef::SF_Absolute &&
|
||||
SymType != object::SymbolRef::ST_File) {
|
||||
uint64_t Addr = 0;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
define linkonce_odr i32 @baz() #0 {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i8* @bar() {
|
||||
entry:
|
||||
ret i8* bitcast (i32 ()* @baz to i8*)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
; RUN: lli -jit-kind=mcjit -extra-module %p/Inputs/weak-function-2.ll %s
|
||||
;
|
||||
; Check that functions in two different modules agree on the address of weak
|
||||
; function 'baz'
|
||||
|
||||
define linkonce_odr i32 @baz() {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i8* @foo() {
|
||||
entry:
|
||||
ret i8* bitcast (i32 ()* @baz to i8*)
|
||||
}
|
||||
|
||||
declare i8* @bar()
|
||||
|
||||
define i32 @main(i32 %argc, i8** %argv) {
|
||||
entry:
|
||||
%call = tail call i8* @foo()
|
||||
%call1 = tail call i8* @bar()
|
||||
%cmp = icmp ne i8* %call, %call1
|
||||
%conv = zext i1 %cmp to i32
|
||||
ret i32 %conv
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
define linkonce_odr i32 @baz() #0 {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i8* @bar() {
|
||||
entry:
|
||||
ret i8* bitcast (i32 ()* @baz to i8*)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
; RUN: lli -jit-kind=orc-mcjit -extra-module %p/Inputs/weak-function-2.ll %s
|
||||
;
|
||||
; Check that functions in two different modules agree on the address of weak
|
||||
; function 'baz'
|
||||
|
||||
define linkonce_odr i32 @baz() {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i8* @foo() {
|
||||
entry:
|
||||
ret i8* bitcast (i32 ()* @baz to i8*)
|
||||
}
|
||||
|
||||
declare i8* @bar()
|
||||
|
||||
define i32 @main(i32 %argc, i8** %argv) {
|
||||
entry:
|
||||
%call = tail call i8* @foo()
|
||||
%call1 = tail call i8* @bar()
|
||||
%cmp = icmp ne i8* %call, %call1
|
||||
%conv = zext i1 %cmp to i32
|
||||
ret i32 %conv
|
||||
}
|
||||
|
Loading…
Reference in New Issue