From d13726f1e91218bc3f7103adf6cd98676bc477e2 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Wed, 15 Oct 2008 20:10:50 +0000 Subject: [PATCH] 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 --- lib/Linker/LinkModules.cpp | 64 +++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index b958e34fc78..b8b36ad4750 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(DGV) && !SGV->isDeclaration()) - return Error(Err, "Global-Alias Collision on '" + SGV->getName() + - "': symbol multiple defined"); + // SGV is global, but DGV is alias. + if (isa(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(RemapOperand(SGV->getInitializer(), ValueMap)); - - GlobalVariable *DGV = - cast(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(ValueMap[SGV]->stripPointerCasts()); + + // If dest if global variable, check that initializers match. + if (GlobalVariable *DGVar = dyn_cast(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()); } } } -- 2.34.1