mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
implement linking of globals to functions, in one direction
(replacing a function with a global). This is needed when building llvm itself with LTO on darwin, because of the EXPLICIT_SYMBOL hack in lib/system/DynamicLibrary.cpp. Implementation of linking the other way will need to wait for a cleanup of LinkFunctionProtos. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53546 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0bb8757997
commit
d1ec48c641
@ -534,27 +534,23 @@ static bool LinkGlobals(Module *Dest, const Module *Src,
|
|||||||
std::map<const Value*, Value*> &ValueMap,
|
std::map<const Value*, Value*> &ValueMap,
|
||||||
std::multimap<std::string, GlobalVariable *> &AppendingVars,
|
std::multimap<std::string, GlobalVariable *> &AppendingVars,
|
||||||
std::string *Err) {
|
std::string *Err) {
|
||||||
|
ValueSymbolTable &DestSymTab = Dest->getValueSymbolTable();
|
||||||
|
|
||||||
// Loop over all of the globals in the src module, mapping them over as we go
|
// Loop over all of the globals in the src module, mapping them over as we go
|
||||||
for (Module::const_global_iterator I = Src->global_begin(),
|
for (Module::const_global_iterator I = Src->global_begin(),
|
||||||
E = Src->global_end(); I != E; ++I) {
|
E = Src->global_end(); I != E; ++I) {
|
||||||
const GlobalVariable *SGV = I;
|
const GlobalVariable *SGV = I;
|
||||||
GlobalValue *DGV = 0;
|
GlobalValue *DGV = 0;
|
||||||
|
|
||||||
// Check to see if may have to link the global with the global
|
// Check to see if may have to link the global with the global, alias or
|
||||||
if (SGV->hasName() && !SGV->hasInternalLinkage()) {
|
// function.
|
||||||
DGV = Dest->getGlobalVariable(SGV->getName());
|
if (SGV->hasName() && !SGV->hasInternalLinkage())
|
||||||
if (DGV && DGV->getType() != SGV->getType())
|
DGV = cast_or_null<GlobalValue>(DestSymTab.lookup(SGV->getNameStart(),
|
||||||
// If types don't agree due to opaque types, try to resolve them.
|
SGV->getNameEnd()));
|
||||||
RecursiveResolveTypes(SGV->getType(), DGV->getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if may have to link the global with the alias
|
|
||||||
if (!DGV && SGV->hasName() && !SGV->hasInternalLinkage()) {
|
|
||||||
DGV = Dest->getNamedAlias(SGV->getName());
|
|
||||||
if (DGV && DGV->getType() != SGV->getType())
|
|
||||||
// If types don't agree due to opaque types, try to resolve them.
|
// If types don't agree due to opaque types, try to resolve them.
|
||||||
|
if (DGV && DGV->getType() != SGV->getType())
|
||||||
RecursiveResolveTypes(SGV->getType(), DGV->getType());
|
RecursiveResolveTypes(SGV->getType(), DGV->getType());
|
||||||
}
|
|
||||||
|
|
||||||
if (DGV && DGV->hasInternalLinkage())
|
if (DGV && DGV->hasInternalLinkage())
|
||||||
DGV = 0;
|
DGV = 0;
|
||||||
@ -571,7 +567,7 @@ static bool LinkGlobals(Module *Dest, const Module *Src,
|
|||||||
if (!DGV) {
|
if (!DGV) {
|
||||||
// No linking to be performed, simply create an identical version of the
|
// No linking to be performed, simply create an identical version of the
|
||||||
// symbol over in the dest module... the initializer will be filled in
|
// symbol over in the dest module... the initializer will be filled in
|
||||||
// later by LinkGlobalInits...
|
// later by LinkGlobalInits.
|
||||||
GlobalVariable *NewDGV =
|
GlobalVariable *NewDGV =
|
||||||
new GlobalVariable(SGV->getType()->getElementType(),
|
new GlobalVariable(SGV->getType()->getElementType(),
|
||||||
SGV->isConstant(), SGV->getLinkage(), /*init*/0,
|
SGV->isConstant(), SGV->getLinkage(), /*init*/0,
|
||||||
@ -589,8 +585,8 @@ static bool LinkGlobals(Module *Dest, const Module *Src,
|
|||||||
// Make sure to remember this mapping...
|
// Make sure to remember this mapping...
|
||||||
ValueMap[SGV] = NewDGV;
|
ValueMap[SGV] = NewDGV;
|
||||||
|
|
||||||
|
// Keep track that this is an appending variable.
|
||||||
if (SGV->hasAppendingLinkage())
|
if (SGV->hasAppendingLinkage())
|
||||||
// Keep track that this is an appending variable...
|
|
||||||
AppendingVars.insert(std::make_pair(SGV->getName(), NewDGV));
|
AppendingVars.insert(std::make_pair(SGV->getName(), NewDGV));
|
||||||
} else if (DGV->hasAppendingLinkage()) {
|
} else if (DGV->hasAppendingLinkage()) {
|
||||||
// No linking is performed yet. Just insert a new copy of the global, and
|
// No linking is performed yet. Just insert a new copy of the global, and
|
||||||
@ -617,61 +613,64 @@ static bool LinkGlobals(Module *Dest, const Module *Src,
|
|||||||
// SGV is global, but DGV is alias. The only valid mapping is when SGV is
|
// SGV is global, but DGV is alias. The only valid mapping is when SGV is
|
||||||
// external declaration, which is effectively a no-op. Also make sure
|
// external declaration, which is effectively a no-op. Also make sure
|
||||||
// linkage calculation was correct.
|
// linkage calculation was correct.
|
||||||
if (SGV->isDeclaration() && !LinkFromSrc) {
|
if (!SGV->isDeclaration() || LinkFromSrc)
|
||||||
// Make sure to remember this mapping...
|
|
||||||
ValueMap[SGV] = DGA;
|
|
||||||
} else
|
|
||||||
return Error(Err, "Global-Alias Collision on '" + SGV->getName() +
|
return Error(Err, "Global-Alias Collision on '" + SGV->getName() +
|
||||||
"': symbol multiple defined");
|
"': symbol multiple defined");
|
||||||
} else if (GlobalVariable *DGVar = dyn_cast<GlobalVariable>(DGV)) {
|
|
||||||
// Otherwise, perform the global-global mapping as instructed by
|
|
||||||
// GetLinkageResult.
|
|
||||||
if (LinkFromSrc) {
|
|
||||||
// Propagate alignment, section, and visibility info.
|
|
||||||
CopyGVAttributes(DGVar, SGV);
|
|
||||||
|
|
||||||
|
// Make sure to remember this mapping.
|
||||||
|
ValueMap[SGV] = DGA;
|
||||||
|
} else if (LinkFromSrc) {
|
||||||
// If the types don't match, and if we are to link from the source, nuke
|
// If the types don't match, and if we are to link from the source, nuke
|
||||||
// DGV and create a new one of the appropriate type.
|
// DGV and create a new one of the appropriate type. Note that the thing
|
||||||
if (SGV->getType() != DGVar->getType()) {
|
// we are replacing may be a function (if a prototype, weak, etc) or a
|
||||||
|
// global variable.
|
||||||
GlobalVariable *NewDGV =
|
GlobalVariable *NewDGV =
|
||||||
new GlobalVariable(SGV->getType()->getElementType(),
|
new GlobalVariable(SGV->getType()->getElementType(),
|
||||||
DGVar->isConstant(), DGVar->getLinkage(),
|
SGV->isConstant(), SGV->getLinkage(),
|
||||||
/*init*/0, DGVar->getName(), Dest, false,
|
/*init*/0, DGV->getName(), Dest, false,
|
||||||
SGV->getType()->getAddressSpace());
|
SGV->getType()->getAddressSpace());
|
||||||
CopyGVAttributes(NewDGV, DGVar);
|
|
||||||
DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDGV,
|
// Propagate alignment, section, and visibility info.
|
||||||
DGVar->getType()));
|
CopyGVAttributes(NewDGV, SGV);
|
||||||
// DGVar will conflict with NewDGV because they both had the same
|
DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDGV, DGV->getType()));
|
||||||
|
|
||||||
|
// DGV will conflict with NewDGV because they both had the same
|
||||||
// name. We must erase this now so ForceRenaming doesn't assert
|
// name. We must erase this now so ForceRenaming doesn't assert
|
||||||
// because DGV might not have internal linkage.
|
// because DGV might not have internal linkage.
|
||||||
DGVar->eraseFromParent();
|
if (GlobalVariable *Var = dyn_cast<GlobalVariable>(DGV))
|
||||||
|
Var->eraseFromParent();
|
||||||
|
else
|
||||||
|
cast<Function>(DGV)->eraseFromParent();
|
||||||
|
DGV = NewDGV;
|
||||||
|
|
||||||
// If the symbol table renamed the global, but it is an externally
|
// If the symbol table renamed the global, but it is an externally visible
|
||||||
// visible symbol, DGV must be an existing global with internal
|
// symbol, DGV must be an existing global with internal linkage. Rename.
|
||||||
// linkage. Rename it.
|
if (NewDGV->getValueName() != SGV->getValueName() &&
|
||||||
if (NewDGV->getName() != SGV->getName() &&
|
|
||||||
!NewDGV->hasInternalLinkage())
|
!NewDGV->hasInternalLinkage())
|
||||||
ForceRenaming(NewDGV, SGV->getName());
|
ForceRenaming(NewDGV, SGV->getName());
|
||||||
|
|
||||||
DGVar = NewDGV;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inherit const as appropriate
|
// Inherit const as appropriate
|
||||||
DGVar->setConstant(SGV->isConstant());
|
NewDGV->setConstant(SGV->isConstant());
|
||||||
|
|
||||||
// Set initializer to zero, so we can link the stuff later
|
|
||||||
DGVar->setInitializer(0);
|
|
||||||
} else {
|
|
||||||
// Special case for const propagation
|
|
||||||
if (DGVar->isDeclaration() && SGV->isConstant() && !DGVar->isConstant())
|
|
||||||
DGVar->setConstant(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set calculated linkage
|
// Set calculated linkage
|
||||||
DGVar->setLinkage(NewLinkage);
|
NewDGV->setLinkage(NewLinkage);
|
||||||
|
|
||||||
// Make sure to remember this mapping...
|
// Make sure to remember this mapping...
|
||||||
ValueMap[SGV] = ConstantExpr::getBitCast(DGVar, SGV->getType());
|
ValueMap[SGV] = ConstantExpr::getBitCast(NewDGV, SGV->getType());
|
||||||
|
} else {
|
||||||
|
// Not "link from source", keep the one in the DestModule and remap the
|
||||||
|
// input onto it.
|
||||||
|
|
||||||
|
// Special case for const propagation.
|
||||||
|
if (GlobalVariable *DGVar = dyn_cast<GlobalVariable>(DGV))
|
||||||
|
if (DGVar->isDeclaration() && SGV->isConstant() && !DGVar->isConstant())
|
||||||
|
DGVar->setConstant(true);
|
||||||
|
|
||||||
|
// Set calculated linkage
|
||||||
|
DGV->setLinkage(NewLinkage);
|
||||||
|
|
||||||
|
// Make sure to remember this mapping...
|
||||||
|
ValueMap[SGV] = ConstantExpr::getBitCast(DGV, SGV->getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -844,7 +843,6 @@ static bool LinkAlias(Module *Dest, const Module *Src,
|
|||||||
static bool LinkGlobalInits(Module *Dest, const Module *Src,
|
static bool LinkGlobalInits(Module *Dest, const Module *Src,
|
||||||
std::map<const Value*, Value*> &ValueMap,
|
std::map<const Value*, Value*> &ValueMap,
|
||||||
std::string *Err) {
|
std::string *Err) {
|
||||||
|
|
||||||
// Loop over all of the globals in the src module, mapping them over as we go
|
// Loop over all of the globals in the src module, mapping them over as we go
|
||||||
for (Module::const_global_iterator I = Src->global_begin(),
|
for (Module::const_global_iterator I = Src->global_begin(),
|
||||||
E = Src->global_end(); I != E; ++I) {
|
E = Src->global_end(); I != E; ++I) {
|
||||||
@ -889,27 +887,23 @@ static bool LinkGlobalInits(Module *Dest, const Module *Src,
|
|||||||
static bool LinkFunctionProtos(Module *Dest, const Module *Src,
|
static bool LinkFunctionProtos(Module *Dest, const Module *Src,
|
||||||
std::map<const Value*, Value*> &ValueMap,
|
std::map<const Value*, Value*> &ValueMap,
|
||||||
std::string *Err) {
|
std::string *Err) {
|
||||||
|
ValueSymbolTable &DestSymTab = Dest->getValueSymbolTable();
|
||||||
|
|
||||||
// Loop over all of the functions in the src module, mapping them over
|
// Loop over all of the functions in the src module, mapping them over
|
||||||
for (Module::const_iterator I = Src->begin(), E = Src->end(); I != E; ++I) {
|
for (Module::const_iterator I = Src->begin(), E = Src->end(); I != E; ++I) {
|
||||||
const Function *SF = I; // SrcFunction
|
const Function *SF = I; // SrcFunction
|
||||||
|
|
||||||
GlobalValue *DGV = 0;
|
GlobalValue *DGV = 0;
|
||||||
Value *MappedDF;
|
Value *MappedDF;
|
||||||
|
|
||||||
// If this function is internal or has no name, it doesn't participate in
|
// Check to see if may have to link the function with the global, alias or
|
||||||
// linkage.
|
// function.
|
||||||
if (SF->hasName() && !SF->hasInternalLinkage()) {
|
if (SF->hasName() && !SF->hasInternalLinkage())
|
||||||
// Check to see if may have to link the function.
|
DGV = cast_or_null<GlobalValue>(DestSymTab.lookup(SF->getNameStart(),
|
||||||
DGV = Dest->getFunction(SF->getName());
|
SF->getNameEnd()));
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if may have to link the function with the alias
|
|
||||||
if (!DGV && SF->hasName() && !SF->hasInternalLinkage()) {
|
|
||||||
DGV = Dest->getNamedAlias(SF->getName());
|
|
||||||
if (DGV && DGV->getType() != SF->getType())
|
|
||||||
// If types don't agree due to opaque types, try to resolve them.
|
// If types don't agree due to opaque types, try to resolve them.
|
||||||
|
if (DGV && DGV->getType() != SF->getType())
|
||||||
RecursiveResolveTypes(SF->getType(), DGV->getType());
|
RecursiveResolveTypes(SF->getType(), DGV->getType());
|
||||||
}
|
|
||||||
|
|
||||||
if (DGV && DGV->hasInternalLinkage())
|
if (DGV && DGV->hasInternalLinkage())
|
||||||
DGV = 0;
|
DGV = 0;
|
||||||
|
13
test/Linker/link-global-to-func.ll
Normal file
13
test/Linker/link-global-to-func.ll
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
; RUN: llvm-as %s -o %t1.bc -f
|
||||||
|
; RUN: echo {declare void @__eprintf(i8*, i8*, i32, i8*) noreturn define void @foo() { tail call void @__eprintf( i8* undef, i8* undef, i32 4, i8* null ) noreturn nounwind unreachable }} | llvm-as -o %t2.bc -f
|
||||||
|
; RUN: llvm-link %t2.bc %t1.bc -o - | llvm-dis | grep __eprintf
|
||||||
|
; RN: llvm-link %t1.bc %t2.bc -o - | llvm-dis | grep __eprintf
|
||||||
|
|
||||||
|
; rdar://6072702
|
||||||
|
|
||||||
|
@__eprintf = external global i8* ; <i8**> [#uses=1]
|
||||||
|
|
||||||
|
define i8* @test() {
|
||||||
|
%A = load i8** @__eprintf ; <i8*> [#uses=1]
|
||||||
|
ret i8* %A
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user