+static GlobalValue::LinkageTypes
+CalculateAliasLinkage(const GlobalValue *SGV, const GlobalValue *DGV) {
+ GlobalValue::LinkageTypes SL = SGV->getLinkage();
+ GlobalValue::LinkageTypes DL = DGV->getLinkage();
+ if (SL == GlobalValue::ExternalLinkage || DL == GlobalValue::ExternalLinkage)
+ return GlobalValue::ExternalLinkage;
+ else if (SL == GlobalValue::WeakAnyLinkage ||
+ DL == GlobalValue::WeakAnyLinkage)
+ return GlobalValue::WeakAnyLinkage;
+ else if (SL == GlobalValue::WeakODRLinkage ||
+ DL == GlobalValue::WeakODRLinkage)
+ return GlobalValue::WeakODRLinkage;
+ else if (SL == GlobalValue::InternalLinkage &&
+ DL == GlobalValue::InternalLinkage)
+ return GlobalValue::InternalLinkage;
+ else if (SL == GlobalValue::LinkerPrivateLinkage &&
+ DL == GlobalValue::LinkerPrivateLinkage)
+ return GlobalValue::LinkerPrivateLinkage;
+ else {
+ assert (SL == GlobalValue::PrivateLinkage &&
+ DL == GlobalValue::PrivateLinkage && "Unexpected linkage type");
+ return GlobalValue::PrivateLinkage;
+ }
+}
+
+// LinkAlias - Loop through the alias in the src module and link them into the
+// dest module. We're assuming, that all functions/global variables were already
+// linked in.
+static bool LinkAlias(Module *Dest, const Module *Src,
+ std::map<const Value*, Value*> &ValueMap,
+ std::string *Err) {
+ // Loop over all alias in the src module
+ for (Module::const_alias_iterator I = Src->alias_begin(),
+ E = Src->alias_end(); I != E; ++I) {
+ const GlobalAlias *SGA = I;
+ const GlobalValue *SAliasee = SGA->getAliasedGlobal();
+ GlobalAlias *NewGA = NULL;
+
+ // Globals were already linked, thus we can just query ValueMap for variant
+ // of SAliasee in Dest.
+ std::map<const Value*,Value*>::const_iterator VMI = ValueMap.find(SAliasee);
+ assert(VMI != ValueMap.end() && "Aliasee not linked");
+ GlobalValue* DAliasee = cast<GlobalValue>(VMI->second);
+ GlobalValue* DGV = NULL;
+
+ // Try to find something 'similar' to SGA in destination module.
+ if (!DGV && !SGA->hasLocalLinkage()) {
+ DGV = Dest->getNamedAlias(SGA->getName());
+
+ // If types don't agree due to opaque types, try to resolve them.
+ if (DGV && DGV->getType() != SGA->getType())
+ RecursiveResolveTypes(SGA->getType(), DGV->getType());
+ }
+
+ if (!DGV && !SGA->hasLocalLinkage()) {
+ DGV = Dest->getGlobalVariable(SGA->getName());
+
+ // If types don't agree due to opaque types, try to resolve them.
+ if (DGV && DGV->getType() != SGA->getType())
+ RecursiveResolveTypes(SGA->getType(), DGV->getType());
+ }
+
+ if (!DGV && !SGA->hasLocalLinkage()) {
+ DGV = Dest->getFunction(SGA->getName());
+
+ // If types don't agree due to opaque types, try to resolve them.
+ if (DGV && DGV->getType() != SGA->getType())
+ RecursiveResolveTypes(SGA->getType(), DGV->getType());
+ }
+
+ // No linking to be performed on internal stuff.
+ if (DGV && DGV->hasLocalLinkage())
+ DGV = NULL;
+
+ if (GlobalAlias *DGA = dyn_cast_or_null<GlobalAlias>(DGV)) {
+ // Types are known to be the same, check whether aliasees equal. As
+ // globals are already linked we just need query ValueMap to find the
+ // mapping.
+ if (DAliasee == DGA->getAliasedGlobal()) {
+ // This is just two copies of the same alias. Propagate linkage, if
+ // necessary.
+ DGA->setLinkage(CalculateAliasLinkage(SGA, DGA));
+
+ NewGA = DGA;
+ // Proceed to 'common' steps
+ } else
+ return Error(Err, "Alias Collision on '" + SGA->getName()+
+ "': aliases have different aliasees");
+ } else if (GlobalVariable *DGVar = dyn_cast_or_null<GlobalVariable>(DGV)) {
+ // The only allowed way is to link alias with external declaration or weak
+ // symbol..
+ if (DGVar->isDeclaration() || DGVar->isWeakForLinker()) {
+ // But only if aliasee is global too...
+ if (!isa<GlobalVariable>(DAliasee))
+ return Error(Err, "Global-Alias Collision on '" + SGA->getName() +
+ "': aliasee is not global variable");
+
+ NewGA = new GlobalAlias(SGA->getType(), SGA->getLinkage(),
+ SGA->getName(), DAliasee, Dest);
+ CopyGVAttributes(NewGA, SGA);
+
+ // Any uses of DGV need to change to NewGA, with cast, if needed.
+ if (SGA->getType() != DGVar->getType())
+ DGVar->replaceAllUsesWith(ConstantExpr::getBitCast(NewGA,
+ DGVar->getType()));
+ else
+ DGVar->replaceAllUsesWith(NewGA);
+
+ // DGVar will conflict with NewGA because they both had the same
+ // name. We must erase this now so ForceRenaming doesn't assert
+ // because DGV might not have internal linkage.
+ DGVar->eraseFromParent();
+
+ // Proceed to 'common' steps
+ } else
+ return Error(Err, "Global-Alias Collision on '" + SGA->getName() +
+ "': symbol multiple defined");
+ } else if (Function *DF = dyn_cast_or_null<Function>(DGV)) {
+ // The only allowed way is to link alias with external declaration or weak
+ // symbol...
+ if (DF->isDeclaration() || DF->isWeakForLinker()) {
+ // But only if aliasee is function too...
+ if (!isa<Function>(DAliasee))
+ return Error(Err, "Function-Alias Collision on '" + SGA->getName() +
+ "': aliasee is not function");
+
+ NewGA = new GlobalAlias(SGA->getType(), SGA->getLinkage(),
+ SGA->getName(), DAliasee, Dest);
+ CopyGVAttributes(NewGA, SGA);
+
+ // Any uses of DF need to change to NewGA, with cast, if needed.
+ if (SGA->getType() != DF->getType())
+ DF->replaceAllUsesWith(ConstantExpr::getBitCast(NewGA,
+ DF->getType()));
+ else
+ DF->replaceAllUsesWith(NewGA);
+
+ // DF will conflict with NewGA because they both had the same
+ // name. We must erase this now so ForceRenaming doesn't assert
+ // because DF might not have internal linkage.
+ DF->eraseFromParent();
+
+ // Proceed to 'common' steps
+ } else
+ return Error(Err, "Function-Alias Collision on '" + SGA->getName() +
+ "': symbol multiple defined");
+ } else {
+ // No linking to be performed, simply create an identical version of the
+ // alias over in the dest module...
+
+ NewGA = new GlobalAlias(SGA->getType(), SGA->getLinkage(),
+ SGA->getName(), DAliasee, Dest);
+ CopyGVAttributes(NewGA, SGA);
+
+ // Proceed to 'common' steps
+ }
+
+ assert(NewGA && "No alias was created in destination module!");
+
+ // If the symbol table renamed the alias, but it is an externally visible
+ // symbol, DGA must be an global value with internal linkage. Rename it.
+ if (NewGA->getName() != SGA->getName() &&
+ !NewGA->hasLocalLinkage())
+ ForceRenaming(NewGA, SGA->getName());
+
+ // Remember this mapping so uses in the source module get remapped
+ // later by RemapOperand.
+ ValueMap[SGA] = NewGA;
+ }
+
+ return false;
+}
+