X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FLinker%2FLinkModules.cpp;h=5c26b2610b1da78f4554004ecebb6dfeadacb4a6;hb=0526d167a9f8fcd476f4382d933dda208a4eb5c8;hp=1f4c3c13238e770d6904987ea16a72266a4d47dd;hpb=cb7da63124395e74219a245397f40140dcb524df;p=oota-llvm.git diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 1f4c3c13238..5c26b2610b1 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -78,9 +78,9 @@ public: for (DenseMap::const_iterator I = MappedTypes.begin(), E = MappedTypes.end(); I != E; ++I) { dbgs() << "TypeMap: "; - I->first->dump(); + I->first->print(dbgs()); dbgs() << " => "; - I->second->dump(); + I->second->print(dbgs()); dbgs() << '\n'; } } @@ -469,6 +469,9 @@ namespace { void computeTypeMapping(); + void upgradeMismatchedGlobalArray(StringRef Name); + void upgradeMismatchedGlobals(); + bool linkAppendingVarProto(GlobalVariable *DstGV, GlobalVariable *SrcGV); bool linkGlobalProto(GlobalVariable *SrcGV); bool linkFunctionProto(Function *SrcF); @@ -543,6 +546,11 @@ Value *ValueMaterializerTy::materializeValueFor(Value *V) { SF->getLinkage(), SF->getName(), DstM); copyGVAttributes(DF, SF); + if (Comdat *SC = SF->getComdat()) { + Comdat *DC = DstM->getOrInsertComdat(SC->getName()); + DF->setComdat(DC); + } + LazilyLinkFunctions.push_back(SF); return DF; } @@ -644,15 +652,19 @@ bool ModuleLinker::computeResultingSelectionKind(StringRef ComdatName, bool ModuleLinker::getComdatResult(const Comdat *SrcC, Comdat::SelectionKind &Result, bool &LinkFromSrc) { + Comdat::SelectionKind SSK = SrcC->getSelectionKind(); StringRef ComdatName = SrcC->getName(); Module::ComdatSymTabType &ComdatSymTab = DstM->getComdatSymbolTable(); Module::ComdatSymTabType::iterator DstCI = ComdatSymTab.find(ComdatName); - if (DstCI == ComdatSymTab.end()) + if (DstCI == ComdatSymTab.end()) { + // Use the comdat if it is only available in one of the modules. + LinkFromSrc = true; + Result = SSK; return false; + } const Comdat *DstC = &DstCI->second; - Comdat::SelectionKind SSK = SrcC->getSelectionKind(); Comdat::SelectionKind DSK = DstC->getSelectionKind(); return computeResultingSelectionKind(ComdatName, SSK, DSK, Result, LinkFromSrc); @@ -812,6 +824,83 @@ void ModuleLinker::computeTypeMapping() { TypeMap.linkDefinedTypeBodies(); } +static void upgradeGlobalArray(GlobalVariable *GV) { + ArrayType *ATy = cast(GV->getType()->getElementType()); + StructType *OldTy = cast(ATy->getElementType()); + assert(OldTy->getNumElements() == 2 && "Expected to upgrade from 2 elements"); + + // Get the upgraded 3 element type. + PointerType *VoidPtrTy = Type::getInt8Ty(GV->getContext())->getPointerTo(); + Type *Tys[3] = {OldTy->getElementType(0), OldTy->getElementType(1), + VoidPtrTy}; + StructType *NewTy = StructType::get(GV->getContext(), Tys, false); + + // Build new constants with a null third field filled in. + Constant *OldInitC = GV->getInitializer(); + ConstantArray *OldInit = dyn_cast(OldInitC); + if (!OldInit && !isa(OldInitC)) + // Invalid initializer; give up. + return; + std::vector Initializers; + if (OldInit && OldInit->getNumOperands()) { + Value *Null = Constant::getNullValue(VoidPtrTy); + for (Use &U : OldInit->operands()) { + ConstantStruct *Init = cast(U.get()); + Initializers.push_back(ConstantStruct::get( + NewTy, Init->getOperand(0), Init->getOperand(1), Null, nullptr)); + } + } + assert(Initializers.size() == ATy->getNumElements() && + "Failed to copy all array elements"); + + // Replace the old GV with a new one. + ATy = ArrayType::get(NewTy, Initializers.size()); + Constant *NewInit = ConstantArray::get(ATy, Initializers); + GlobalVariable *NewGV = new GlobalVariable( + *GV->getParent(), ATy, GV->isConstant(), GV->getLinkage(), NewInit, "", + GV, GV->getThreadLocalMode(), GV->getType()->getAddressSpace(), + GV->isExternallyInitialized()); + NewGV->copyAttributesFrom(GV); + NewGV->takeName(GV); + assert(GV->use_empty() && "program cannot use initializer list"); + GV->eraseFromParent(); +} + +void ModuleLinker::upgradeMismatchedGlobalArray(StringRef Name) { + // Look for the global arrays. + auto *DstGV = dyn_cast_or_null(DstM->getNamedValue(Name)); + if (!DstGV) + return; + auto *SrcGV = dyn_cast_or_null(SrcM->getNamedValue(Name)); + if (!SrcGV) + return; + + // Check if the types already match. + auto *DstTy = cast(DstGV->getType()->getElementType()); + auto *SrcTy = + cast(TypeMap.get(SrcGV->getType()->getElementType())); + if (DstTy == SrcTy) + return; + + // Grab the element types. We can only upgrade an array of a two-field + // struct. Only bother if the other one has three-fields. + auto *DstEltTy = cast(DstTy->getElementType()); + auto *SrcEltTy = cast(SrcTy->getElementType()); + if (DstEltTy->getNumElements() == 2 && SrcEltTy->getNumElements() == 3) { + upgradeGlobalArray(DstGV); + return; + } + if (DstEltTy->getNumElements() == 3 && SrcEltTy->getNumElements() == 2) + upgradeGlobalArray(SrcGV); + + // We can't upgrade any other differences. +} + +void ModuleLinker::upgradeMismatchedGlobals() { + upgradeMismatchedGlobalArray("llvm.global_ctors"); + upgradeMismatchedGlobalArray("llvm.global_dtors"); +} + /// linkAppendingVarProto - If there were any appending global variables, link /// them together now. Return true on error. bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV, @@ -1450,6 +1539,9 @@ bool ModuleLinker::run() { ComdatsChosen[&C] = std::make_pair(SK, LinkFromSrc); } + // Upgrade mismatched global arrays. + upgradeMismatchedGlobals(); + // Insert all of the globals in src into the DstM module... without linking // initializers (which could refer to functions not yet mapped over). for (Module::global_iterator I = SrcM->global_begin(),