summaryrefslogtreecommitdiff
path: root/lib/Linker
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2008-10-15 20:10:50 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2008-10-15 20:10:50 +0000
commitd13726f1e91218bc3f7103adf6cd98676bc477e2 (patch)
tree588cdc3927861b03a32f115d5a343506bd29b7e3 /lib/Linker
parente655e3703280d001375ffa44093f8f4ec879c77b (diff)
downloadllvm-d13726f1e91218bc3f7103adf6cd98676bc477e2.tar.gz
llvm-d13726f1e91218bc3f7103adf6cd98676bc477e2.tar.bz2
llvm-d13726f1e91218bc3f7103adf6cd98676bc477e2.tar.xz
Also properly handle linking of strong alias and weak global
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57595 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Linker')
-rw-r--r--lib/Linker/LinkModules.cpp64
1 files changed, 39 insertions, 25 deletions
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index b958e34fc7..b8b36ad475 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -662,12 +662,15 @@ static bool LinkGlobals(Module *Dest, const Module *Src,
if (DGVar->isDeclaration() && SGV->isConstant() && !DGVar->isConstant())
DGVar->setConstant(true);
- // 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
- // linkage calculation was correct.
- if (isa<GlobalAlias>(DGV) && !SGV->isDeclaration())
- return Error(Err, "Global-Alias Collision on '" + SGV->getName() +
- "': symbol multiple defined");
+ // SGV is global, but DGV is alias.
+ if (isa<GlobalAlias>(DGV)) {
+ // The only valid mappings are:
+ // - SGV is external declaration, which is effectively a no-op.
+ // - SGV is weak, when we just need to throw SGV out.
+ if (!SGV->isDeclaration() && !SGV->mayBeOverridden())
+ return Error(Err, "Global-Alias Collision on '" + SGV->getName() +
+ "': symbol multiple defined");
+ }
// Set calculated linkage
DGV->setLinkage(NewLinkage);
@@ -854,28 +857,39 @@ static bool LinkGlobalInits(Module *Dest, const Module *Src,
// Figure out what the initializer looks like in the dest module...
Constant *SInit =
cast<Constant>(RemapOperand(SGV->getInitializer(), ValueMap));
-
- GlobalVariable *DGV =
- cast<GlobalVariable>(ValueMap[SGV]->stripPointerCasts());
- if (DGV->hasInitializer()) {
- if (SGV->hasExternalLinkage()) {
- if (DGV->getInitializer() != SInit)
- return Error(Err, "Global Variable Collision on '" + SGV->getName() +
- "': global variables have different initializers");
- } else if (DGV->mayBeOverridden()) {
- // Nothing is required, mapped values will take the new global
- // automatically.
- } else if (SGV->mayBeOverridden()) {
- // Nothing is required, mapped values will take the new global
- // automatically.
- } else if (DGV->hasAppendingLinkage()) {
- assert(0 && "Appending linkage unimplemented!");
+ // Grab destination global variable or alias.
+ GlobalValue *DGV = cast<GlobalValue>(ValueMap[SGV]->stripPointerCasts());
+
+ // If dest if global variable, check that initializers match.
+ if (GlobalVariable *DGVar = dyn_cast<GlobalVariable>(DGV)) {
+ if (DGVar->hasInitializer()) {
+ if (SGV->hasExternalLinkage()) {
+ if (DGVar->getInitializer() != SInit)
+ return Error(Err, "Global Variable Collision on '" +
+ SGV->getName() +
+ "': global variables have different initializers");
+ } else if (DGVar->mayBeOverridden()) {
+ // Nothing is required, mapped values will take the new global
+ // automatically.
+ } else if (SGV->mayBeOverridden()) {
+ // Nothing is required, mapped values will take the new global
+ // automatically.
+ } else if (DGVar->hasAppendingLinkage()) {
+ assert(0 && "Appending linkage unimplemented!");
+ } else {
+ assert(0 && "Unknown linkage!");
+ }
} else {
- assert(0 && "Unknown linkage!");
+ // Copy the initializer over now...
+ DGVar->setInitializer(SInit);
}
} else {
- // Copy the initializer over now...
- DGV->setInitializer(SInit);
+ // Destination is alias, the only valid situation is when source is
+ // weak. Also, note, that we already checked linkage in LinkGlobals(),
+ // thus we assert here.
+ // FIXME: Should we weaken this assumption, 'dereference' alias and
+ // check for initializer of aliasee?
+ assert(SGV->mayBeOverridden());
}
}
}