/// speeds up linking for modules with many/ lazily linked functions of which
/// few get used.
class ValueMaterializerTy final : public ValueMaterializer {
- TypeMapTy &TypeMap;
- Module *DstM;
- std::vector<GlobalValue *> &LazilyLinkGlobalValues;
ModuleLinker *ModLinker;
public:
- ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM,
- std::vector<GlobalValue *> &LazilyLinkGlobalValues,
- ModuleLinker *ModLinker)
- : ValueMaterializer(), TypeMap(TypeMap), DstM(DstM),
- LazilyLinkGlobalValues(LazilyLinkGlobalValues), ModLinker(ModLinker) {}
+ ValueMaterializerTy(ModuleLinker *ModLinker) : ModLinker(ModLinker) {}
- Value *materializeValueFor(Value *V) override;
+ Value *materializeDeclFor(Value *V) override;
+ void materializeInitFor(GlobalValue *New, GlobalValue *Old) override;
};
class LinkDiagnosticInfo : public DiagnosticInfo {
std::vector<AppendingVarInfo> AppendingVars;
// Set of items not to link in from source.
- SmallPtrSet<const Value *, 16> DoNotLinkFromSource;
-
- // Vector of GlobalValues to lazily link in.
- std::vector<GlobalValue *> LazilyLinkGlobalValues;
-
- /// Functions that have replaced other functions.
- SmallPtrSet<const Function *, 16> OverridingFunctions;
+ SmallPtrSet<const GlobalValue *, 16> DoNotLinkFromSource;
DiagnosticHandlerFunction DiagnosticHandler;
/// Function index passed into ModuleLinker for using in function
/// importing/exporting handling.
- FunctionInfoIndex *ImportIndex;
+ const FunctionInfoIndex *ImportIndex;
/// Function to import from source module, all other functions are
/// imported as declarations instead of definitions.
/// as part of a different backend compilation process.
bool HasExportedFunctions;
+ /// Set to true when all global value body linking is complete (including
+ /// lazy linking). Used to prevent metadata linking from creating new
+ /// references.
+ bool DoneLinkingBodies;
+
+ bool HasError = false;
+
public:
ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM,
DiagnosticHandlerFunction DiagnosticHandler, unsigned Flags,
- FunctionInfoIndex *Index = nullptr,
+ const FunctionInfoIndex *Index = nullptr,
Function *FuncToImport = nullptr)
- : DstM(dstM), SrcM(srcM), TypeMap(Set),
- ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues, this),
+ : DstM(dstM), SrcM(srcM), TypeMap(Set), ValMaterializer(this),
DiagnosticHandler(DiagnosticHandler), Flags(Flags), ImportIndex(Index),
- ImportFunction(FuncToImport), HasExportedFunctions(false) {
+ ImportFunction(FuncToImport), HasExportedFunctions(false),
+ DoneLinkingBodies(false) {
assert((ImportIndex || !ImportFunction) &&
"Expect a FunctionInfoIndex when importing");
// If we have a FunctionInfoIndex but no function to import,
}
bool run();
+ Value *materializeDeclFor(Value *V);
+ void materializeInitFor(GlobalValue *New, GlobalValue *Old);
+private:
bool shouldOverrideFromSrc() { return Flags & Linker::OverrideFromSrc; }
bool shouldLinkOnlyNeeded() { return Flags & Linker::LinkOnlyNeeded; }
bool shouldInternalizeLinkedSymbols() {
/// Check if we should promote the given local value to global scope.
bool doPromoteLocalToGlobal(const GlobalValue *SGV);
-private:
+ /// Check if all global value body linking is complete.
+ bool doneLinkingBodies() { return DoneLinkingBodies; }
+
bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest,
const GlobalValue &Src);
/// Helper method for setting a message and returning an error code.
bool emitError(const Twine &Message) {
DiagnosticHandler(LinkDiagnosticInfo(DS_Error, Message));
+ HasError = true;
return true;
}
ComdatsChosen;
bool getComdatResult(const Comdat *SrcC, Comdat::SelectionKind &SK,
bool &LinkFromSrc);
+ // Keep track of the global value members of each comdat in source.
+ DenseMap<const Comdat *, std::vector<GlobalValue *>> ComdatMembers;
/// Given a global in the source module, return the global in the
/// destination module that is being linked to, if any.
GlobalValue *getLinkedToGlobal(const GlobalValue *SrcGV) {
// If the source has no name it can't link. If it has local linkage,
// there is no name match-up going on.
- if (!SrcGV->hasName() || SrcGV->hasLocalLinkage())
+ if (!SrcGV->hasName() || GlobalValue::isLocalLinkage(getLinkage(SrcGV)))
return nullptr;
// Otherwise see if we have a match in the destination module's symtab.
- GlobalValue *DGV = DstM->getNamedValue(SrcGV->getName());
+ GlobalValue *DGV = DstM->getNamedValue(getName(SrcGV));
if (!DGV)
return nullptr;
void upgradeMismatchedGlobalArray(StringRef Name);
void upgradeMismatchedGlobals();
+ bool linkIfNeeded(GlobalValue &GV);
bool linkAppendingVarProto(GlobalVariable *DstGV,
const GlobalVariable *SrcGV);
bool linkGlobalValueProto(GlobalValue *GV);
bool linkModuleFlagsMetadata();
- void linkAppendingVarInit(const AppendingVarInfo &AVI);
+ void linkAppendingVarInit(AppendingVarInfo &AVI);
void linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src);
bool linkFunctionBody(Function &Dst, Function &Src);
const GlobalValue *DGV = nullptr);
void linkNamedMDNodes();
- void stripReplacedSubprograms();
};
}
// being imported as a declaration. In that case copy the attributes from the
// base object.
if (GA && !dyn_cast<GlobalAlias>(NewGV)) {
- assert(isPerformingImport() &&
- (GA->hasWeakAnyLinkage() ||
- !doImportAsDefinition(GA->getBaseObject())));
+ assert(isPerformingImport() && !doImportAsDefinition(GA));
NewGV->copyAttributesFrom(GA->getBaseObject());
} else
NewGV->copyAttributesFrom(SrcGV);
forceRenaming(NewGV, getName(SrcGV));
}
-static bool isLessConstraining(GlobalValue::VisibilityTypes a,
- GlobalValue::VisibilityTypes b) {
- if (a == GlobalValue::HiddenVisibility)
- return false;
- if (b == GlobalValue::HiddenVisibility)
- return true;
- if (a == GlobalValue::ProtectedVisibility)
- return false;
- if (b == GlobalValue::ProtectedVisibility)
- return true;
- return false;
-}
-
bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) {
if (!isPerformingImport())
return false;
- // Always import GlobalVariable definitions. The linkage changes
+ auto *GA = dyn_cast<GlobalAlias>(SGV);
+ if (GA) {
+ if (GA->hasWeakAnyLinkage())
+ return false;
+ const GlobalObject *GO = GA->getBaseObject();
+ if (!GO->hasLinkOnceODRLinkage())
+ return false;
+ return doImportAsDefinition(GO);
+ }
+ // Always import GlobalVariable definitions, except for the special
+ // case of WeakAny which are imported as ExternalWeak declarations
+ // (see comments in ModuleLinker::getLinkage). The linkage changes
// described in ModuleLinker::getLinkage ensure the correct behavior (e.g.
// global variables with external linkage are transformed to
- // available_externally defintions, which are ultimately turned into
- // declaratios after the EliminateAvailableExternally pass).
- if (dyn_cast<GlobalVariable>(SGV) && !SGV->isDeclaration())
+ // available_externally definitions, which are ultimately turned into
+ // declarations after the EliminateAvailableExternally pass).
+ if (isa<GlobalVariable>(SGV) && !SGV->isDeclaration() &&
+ !SGV->hasWeakAnyLinkage())
return true;
// Only import the function requested for importing.
auto *SF = dyn_cast<Function>(SGV);
// definitions upon import, so that they are available for inlining
// and/or optimization, but are turned into declarations later
// during the EliminateAvailableExternally pass.
- if (doImportAsDefinition(SGV))
+ if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
return GlobalValue::AvailableExternallyLinkage;
// An imported external declaration stays external.
return SGV->getLinkage();
// equivalent, so the issue described above for weak_any does not exist,
// and the definition can be imported. It can be treated similarly
// to an imported externally visible global value.
- if (doImportAsDefinition(SGV))
+ if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
return GlobalValue::AvailableExternallyLinkage;
else
return GlobalValue::ExternalLinkage;
// since it would cause global constructors/destructors to be
// executed multiple times. This should have already been handled
// by linkGlobalValueProto.
- assert(false && "Cannot import appending linkage variable");
+ llvm_unreachable("Cannot import appending linkage variable");
case GlobalValue::InternalLinkage:
case GlobalValue::PrivateLinkage:
// If we are promoting the local to global scope, it is handled
// similarly to a normal externally visible global.
if (doPromoteLocalToGlobal(SGV)) {
- if (doImportAsDefinition(SGV))
+ if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
return GlobalValue::AvailableExternallyLinkage;
else
return GlobalValue::ExternalLinkage;
// as a declaration as well, which involves converting it to a non-alias.
// See comments in ModuleLinker::getLinkage for why we cannot import
// weak_any defintions.
- if (isPerformingImport() && (SGA->hasWeakAnyLinkage() ||
- !doImportAsDefinition(SGA->getBaseObject()))) {
+ if (isPerformingImport() && !doImportAsDefinition(SGA)) {
// Need to convert to declaration. All aliases must be definitions.
const GlobalValue *GVal = SGA->getBaseObject();
GlobalValue *NewGV;
assert(F);
NewGV = copyFunctionProto(TypeMap, F);
}
- // Set the linkage to ExternalWeak, see also comments in
- // ModuleLinker::getLinkage.
+ // Set the linkage to External or ExternalWeak (see comments in
+ // ModuleLinker::getLinkage for why WeakAny is converted to ExternalWeak).
if (SGA->hasWeakAnyLinkage())
NewGV->setLinkage(GlobalValue::ExternalWeakLinkage);
- // Don't attempt to link body, needs to be a declaration.
- DoNotLinkFromSource.insert(SGA);
+ else
+ NewGV->setLinkage(GlobalValue::ExternalLinkage);
return NewGV;
}
// If there is no linkage to be performed or we're linking from the source,
getLinkage(SGA), getName(SGA), DstM);
}
+static GlobalValue::VisibilityTypes
+getMinVisibility(GlobalValue::VisibilityTypes A,
+ GlobalValue::VisibilityTypes B) {
+ if (A == GlobalValue::HiddenVisibility || B == GlobalValue::HiddenVisibility)
+ return GlobalValue::HiddenVisibility;
+ if (A == GlobalValue::ProtectedVisibility ||
+ B == GlobalValue::ProtectedVisibility)
+ return GlobalValue::ProtectedVisibility;
+ return GlobalValue::DefaultVisibility;
+}
+
void ModuleLinker::setVisibility(GlobalValue *NewGV, const GlobalValue *SGV,
const GlobalValue *DGV) {
GlobalValue::VisibilityTypes Visibility = SGV->getVisibility();
if (DGV)
- Visibility = isLessConstraining(Visibility, DGV->getVisibility())
- ? DGV->getVisibility()
- : Visibility;
+ Visibility = getMinVisibility(DGV->getVisibility(), Visibility);
// For promoted locals, mark them hidden so that they can later be
// stripped from the symbol table to reduce bloat.
if (SGV->hasLocalLinkage() && doPromoteLocalToGlobal(SGV))
return NewGV;
}
-Value *ValueMaterializerTy::materializeValueFor(Value *V) {
+Value *ValueMaterializerTy::materializeDeclFor(Value *V) {
+ return ModLinker->materializeDeclFor(V);
+}
+
+Value *ModuleLinker::materializeDeclFor(Value *V) {
auto *SGV = dyn_cast<GlobalValue>(V);
if (!SGV)
return nullptr;
- GlobalValue *DGV = ModLinker->copyGlobalValueProto(TypeMap, SGV);
+ // If we are done linking global value bodies (i.e. we are performing
+ // metadata linking), don't link in the global value due to this
+ // reference, simply map it to null.
+ if (doneLinkingBodies())
+ return nullptr;
- if (Comdat *SC = SGV->getComdat()) {
- if (auto *DGO = dyn_cast<GlobalObject>(DGV)) {
- Comdat *DC = DstM->getOrInsertComdat(SC->getName());
- DGO->setComdat(DC);
- }
+ linkGlobalValueProto(SGV);
+ if (HasError)
+ return nullptr;
+ Value *Ret = ValueMap[SGV];
+ assert(Ret);
+ return Ret;
+}
+
+void ValueMaterializerTy::materializeInitFor(GlobalValue *New,
+ GlobalValue *Old) {
+ return ModLinker->materializeInitFor(New, Old);
+}
+
+void ModuleLinker::materializeInitFor(GlobalValue *New, GlobalValue *Old) {
+ if (auto *F = dyn_cast<Function>(New)) {
+ if (!F->isDeclaration())
+ return;
+ } else if (auto *V = dyn_cast<GlobalVariable>(New)) {
+ if (V->hasInitializer())
+ return;
+ } else {
+ auto *A = cast<GlobalAlias>(New);
+ if (A->getAliasee())
+ return;
}
- LazilyLinkGlobalValues.push_back(SGV);
- return DGV;
+ if (Old->isDeclaration())
+ return;
+
+ if (isPerformingImport() && !doImportAsDefinition(Old))
+ return;
+
+ if (DoNotLinkFromSource.count(Old)) {
+ if (!New->hasExternalLinkage() && !New->hasExternalWeakLinkage() &&
+ !New->hasAppendingLinkage())
+ emitError("Declaration points to discarded value");
+ return;
+ }
+
+ linkGlobalValueBody(*Old);
}
bool ModuleLinker::getComdatLeader(Module *M, StringRef ComdatName,
/// Return true on error.
bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
const GlobalVariable *SrcGV) {
-
- if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage())
- return emitError("Linking globals named '" + SrcGV->getName() +
- "': can only link appending global with another appending global!");
-
- ArrayType *DstTy = cast<ArrayType>(DstGV->getType()->getElementType());
ArrayType *SrcTy =
- cast<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()));
- Type *EltTy = DstTy->getElementType();
-
- // Check to see that they two arrays agree on type.
- if (EltTy != SrcTy->getElementType())
- return emitError("Appending variables with different element types!");
- if (DstGV->isConstant() != SrcGV->isConstant())
- return emitError("Appending variables linked with different const'ness!");
-
- if (DstGV->getAlignment() != SrcGV->getAlignment())
- return emitError(
- "Appending variables with different alignment need to be linked!");
-
- if (DstGV->getVisibility() != SrcGV->getVisibility())
- return emitError(
- "Appending variables with different visibility need to be linked!");
-
- if (DstGV->hasUnnamedAddr() != SrcGV->hasUnnamedAddr())
- return emitError(
- "Appending variables with different unnamed_addr need to be linked!");
-
- if (StringRef(DstGV->getSection()) != SrcGV->getSection())
- return emitError(
+ cast<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()));
+ Type *EltTy = SrcTy->getElementType();
+
+ uint64_t NewSize = SrcTy->getNumElements();
+ if (DstGV) {
+ ArrayType *DstTy = cast<ArrayType>(DstGV->getType()->getElementType());
+ NewSize += DstTy->getNumElements();
+
+ if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage())
+ return emitError(
+ "Linking globals named '" + SrcGV->getName() +
+ "': can only link appending global with another appending global!");
+
+ // Check to see that they two arrays agree on type.
+ if (EltTy != DstTy->getElementType())
+ return emitError("Appending variables with different element types!");
+ if (DstGV->isConstant() != SrcGV->isConstant())
+ return emitError("Appending variables linked with different const'ness!");
+
+ if (DstGV->getAlignment() != SrcGV->getAlignment())
+ return emitError(
+ "Appending variables with different alignment need to be linked!");
+
+ if (DstGV->getVisibility() != SrcGV->getVisibility())
+ return emitError(
+ "Appending variables with different visibility need to be linked!");
+
+ if (DstGV->hasUnnamedAddr() != SrcGV->hasUnnamedAddr())
+ return emitError(
+ "Appending variables with different unnamed_addr need to be linked!");
+
+ if (StringRef(DstGV->getSection()) != SrcGV->getSection())
+ return emitError(
"Appending variables with different section name need to be linked!");
+ }
- uint64_t NewSize = DstTy->getNumElements() + SrcTy->getNumElements();
ArrayType *NewType = ArrayType::get(EltTy, NewSize);
// Create the new global variable.
- GlobalVariable *NG =
- new GlobalVariable(*DstGV->getParent(), NewType, SrcGV->isConstant(),
- DstGV->getLinkage(), /*init*/nullptr, /*name*/"", DstGV,
- DstGV->getThreadLocalMode(),
- DstGV->getType()->getAddressSpace());
+ GlobalVariable *NG = new GlobalVariable(
+ *DstM, NewType, SrcGV->isConstant(), SrcGV->getLinkage(),
+ /*init*/ nullptr, /*name*/ "", DstGV, SrcGV->getThreadLocalMode(),
+ SrcGV->getType()->getAddressSpace());
// Propagate alignment, visibility and section info.
- copyGVAttributes(NG, DstGV);
+ copyGVAttributes(NG, SrcGV);
AppendingVarInfo AVI;
AVI.NewGV = NG;
- AVI.DstInit = DstGV->getInitializer();
+ AVI.DstInit = DstGV ? DstGV->getInitializer() : nullptr;
AVI.SrcInit = SrcGV->getInitializer();
AppendingVars.push_back(AVI);
// global.
ValueMap[SrcGV] = ConstantExpr::getBitCast(NG, TypeMap.get(SrcGV->getType()));
- DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType()));
- DstGV->eraseFromParent();
+ if (DstGV) {
+ DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType()));
+ DstGV->eraseFromParent();
+ }
// Track the source variable so we don't try to link it.
DoNotLinkFromSource.insert(SrcGV);
DoNotLinkFromSource.insert(SGV);
return false;
}
- if (DGV && DGV->hasAppendingLinkage())
- return linkAppendingVarProto(cast<GlobalVariable>(DGV),
+ if (SGV->hasAppendingLinkage())
+ return linkAppendingVarProto(cast_or_null<GlobalVariable>(DGV),
cast<GlobalVariable>(SGV));
bool LinkFromSrc = true;
if (DGV)
HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr();
- if (!LinkFromSrc && !DGV)
- return false;
-
GlobalValue *NewGV;
- if (!LinkFromSrc) {
+ if (!LinkFromSrc && DGV) {
NewGV = DGV;
// When linking from source we setVisibility from copyGlobalValueProto.
setVisibility(NewGV, SGV, DGV);
} else {
- // If the GV is to be lazily linked, don't create it just yet.
- // The ValueMaterializerTy will deal with creating it if it's used.
- if (!DGV && !shouldOverrideFromSrc() && SGV != ImportFunction &&
- (SGV->hasLocalLinkage() || SGV->hasLinkOnceLinkage() ||
- SGV->hasAvailableExternallyLinkage())) {
- DoNotLinkFromSource.insert(SGV);
- return false;
- }
-
- // When we only want to link in unresolved dependencies, blacklist
- // the symbol unless unless DestM has a matching declaration (DGV).
- if (shouldLinkOnlyNeeded() && !(DGV && DGV->isDeclaration())) {
- DoNotLinkFromSource.insert(SGV);
- return false;
- }
-
NewGV = copyGlobalValueProto(TypeMap, SGV, DGV);
- if (DGV && isa<Function>(DGV))
- if (auto *NewF = dyn_cast<Function>(NewGV))
- OverridingFunctions.insert(NewF);
+ if (isPerformingImport() && !doImportAsDefinition(SGV))
+ DoNotLinkFromSource.insert(SGV);
}
NewGV->setUnnamedAddr(HasUnnamedAddr);
if (auto *NewGO = dyn_cast<GlobalObject>(NewGV)) {
- if (C)
+ if (C && LinkFromSrc)
NewGO->setComdat(C);
if (DGV && DGV->hasCommonLinkage() && SGV->hasCommonLinkage())
Dest.push_back(C->getAggregateElement(i));
}
-void ModuleLinker::linkAppendingVarInit(const AppendingVarInfo &AVI) {
+void ModuleLinker::linkAppendingVarInit(AppendingVarInfo &AVI) {
// Merge the initializer.
SmallVector<Constant *, 16> DstElements;
- getArrayElements(AVI.DstInit, DstElements);
+ if (AVI.DstInit)
+ getArrayElements(AVI.DstInit, DstElements);
SmallVector<Constant *, 16> SrcElements;
getArrayElements(AVI.SrcInit, SrcElements);
for (auto *V : SrcElements) {
if (IsNewStructor) {
- Constant *Key = V->getAggregateElement(2);
+ auto *Key =
+ dyn_cast<GlobalValue>(V->getAggregateElement(2)->stripPointerCasts());
if (DoNotLinkFromSource.count(Key))
continue;
}
DstElements.push_back(
MapValue(V, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer));
}
- if (IsNewStructor) {
+ if (DstElements.size() != NewType->getNumElements()) {
NewType = ArrayType::get(NewType->getElementType(), DstElements.size());
- AVI.NewGV->mutateType(PointerType::get(NewType, 0));
+ GlobalVariable *Old = AVI.NewGV;
+ GlobalVariable *NG = new GlobalVariable(
+ *DstM, NewType, Old->isConstant(), Old->getLinkage(), /*init*/ nullptr,
+ /*name*/ "", Old, Old->getThreadLocalMode(),
+ Old->getType()->getAddressSpace());
+ copyGVAttributes(NG, Old);
+ AVI.NewGV->replaceAllUsesWith(
+ ConstantExpr::getBitCast(NG, AVI.NewGV->getType()));
+ AVI.NewGV->eraseFromParent();
+ AVI.NewGV = NG;
}
AVI.NewGV->setInitializer(ConstantArray::get(NewType, DstElements));
bool ModuleLinker::linkGlobalValueBody(GlobalValue &Src) {
Value *Dst = ValueMap[&Src];
assert(Dst);
+ if (const Comdat *SC = Src.getComdat()) {
+ // To ensure that we don't generate an incomplete comdat group,
+ // we must materialize and map in any other members that are not
+ // yet materialized in Dst, which also ensures their definitions
+ // are linked in. Otherwise, linkonce and other lazy linked GVs will
+ // not be materialized if they aren't referenced.
+ for (auto *SGV : ComdatMembers[SC]) {
+ auto *DGV = cast_or_null<GlobalValue>(ValueMap[SGV]);
+ if (DGV && !DGV->isDeclaration())
+ continue;
+ MapValue(SGV, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer);
+ }
+ }
if (shouldInternalizeLinkedSymbols())
if (auto *DGV = dyn_cast<GlobalValue>(Dst))
DGV->setLinkage(GlobalValue::InternalLinkage);
NamedMDNode *DestNMD = DstM->getOrInsertNamedMetadata(NMD.getName());
// Add Src elements into Dest node.
for (const MDNode *op : NMD.operands())
- DestNMD->addOperand(MapMetadata(op, ValueMap, RF_MoveDistinctMDs,
- &TypeMap, &ValMaterializer));
- }
-}
-
-/// Drop DISubprograms that have been superseded.
-///
-/// FIXME: this creates an asymmetric result: we strip functions from losing
-/// subprograms in DstM, but leave losing subprograms in SrcM.
-/// TODO: Remove this logic once the backend can correctly determine canonical
-/// subprograms.
-void ModuleLinker::stripReplacedSubprograms() {
- // Avoid quadratic runtime by returning early when there's nothing to do.
- if (OverridingFunctions.empty())
- return;
-
- // Move the functions now, so the set gets cleared even on early returns.
- auto Functions = std::move(OverridingFunctions);
- OverridingFunctions.clear();
-
- // Drop functions from subprograms if they've been overridden by the new
- // compile unit.
- NamedMDNode *CompileUnits = DstM->getNamedMetadata("llvm.dbg.cu");
- if (!CompileUnits)
- return;
- for (unsigned I = 0, E = CompileUnits->getNumOperands(); I != E; ++I) {
- auto *CU = cast<DICompileUnit>(CompileUnits->getOperand(I));
- assert(CU && "Expected valid compile unit");
-
- for (DISubprogram *SP : CU->getSubprograms()) {
- if (!SP || !SP->getFunction() || !Functions.count(SP->getFunction()))
- continue;
-
- // Prevent DebugInfoFinder from tagging this as the canonical subprogram,
- // since the canonical one is in the incoming module.
- SP->replaceFunction(nullptr);
- }
+ DestNMD->addOperand(MapMetadata(
+ op, ValueMap, RF_MoveDistinctMDs | RF_NullMapMissingGlobalValues,
+ &TypeMap, &ValMaterializer));
}
}
return DstTriple.str();
}
+bool ModuleLinker::linkIfNeeded(GlobalValue &GV) {
+ GlobalValue *DGV = getLinkedToGlobal(&GV);
+
+ if (shouldLinkOnlyNeeded() && !(DGV && DGV->isDeclaration()))
+ return false;
+
+ if (DGV && !GV.hasLocalLinkage()) {
+ GlobalValue::VisibilityTypes Visibility =
+ getMinVisibility(DGV->getVisibility(), GV.getVisibility());
+ DGV->setVisibility(Visibility);
+ GV.setVisibility(Visibility);
+ }
+
+ if (const Comdat *SC = GV.getComdat()) {
+ bool LinkFromSrc;
+ Comdat::SelectionKind SK;
+ std::tie(SK, LinkFromSrc) = ComdatsChosen[SC];
+ if (!LinkFromSrc) {
+ DoNotLinkFromSource.insert(&GV);
+ return false;
+ }
+ }
+
+ if (!DGV && !shouldOverrideFromSrc() &&
+ (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() ||
+ GV.hasAvailableExternallyLinkage())) {
+ return false;
+ }
+ MapValue(&GV, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer);
+ return HasError;
+}
+
bool ModuleLinker::run() {
assert(DstM && "Null destination module");
assert(SrcM && "Null source module");
// Upgrade mismatched global arrays.
upgradeMismatchedGlobals();
+ for (GlobalVariable &GV : SrcM->globals())
+ if (const Comdat *SC = GV.getComdat())
+ ComdatMembers[SC].push_back(&GV);
+
+ for (Function &SF : *SrcM)
+ if (const Comdat *SC = SF.getComdat())
+ ComdatMembers[SC].push_back(&SF);
+
+ for (GlobalAlias &GA : SrcM->aliases())
+ if (const Comdat *SC = GA.getComdat())
+ ComdatMembers[SC].push_back(&GA);
+
// Insert all of the globals in src into the DstM module... without linking
// initializers (which could refer to functions not yet mapped over).
for (GlobalVariable &GV : SrcM->globals())
- if (linkGlobalValueProto(&GV))
+ if (linkIfNeeded(GV))
return true;
- // Link the functions together between the two modules, without doing function
- // bodies... this just adds external function prototypes to the DstM
- // function... We do this so that when we begin processing function bodies,
- // all of the global values that may be referenced are available in our
- // ValueMap.
- for (Function &F :*SrcM)
- if (linkGlobalValueProto(&F))
+ for (Function &SF : *SrcM)
+ if (linkIfNeeded(SF))
return true;
- // If there were any aliases, link them now.
for (GlobalAlias &GA : SrcM->aliases())
- if (linkGlobalValueProto(&GA))
+ if (linkIfNeeded(GA))
return true;
- for (const AppendingVarInfo &AppendingVar : AppendingVars)
+ for (AppendingVarInfo &AppendingVar : AppendingVars)
linkAppendingVarInit(AppendingVar);
for (const auto &Entry : DstM->getComdatSymbolTable()) {
MapValue(GV, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer);
}
- // Strip replaced subprograms before mapping any metadata -- so that we're
- // not changing metadata from the source module (note that
- // linkGlobalValueBody() eventually calls RemapInstruction() and therefore
- // MapMetadata()) -- but after linking global value protocols -- so that
- // OverridingFunctions has been built.
- stripReplacedSubprograms();
-
- // Link in the function bodies that are defined in the source module into
- // DstM.
- for (Function &SF : *SrcM) {
- // Skip if no body (function is external).
- if (SF.isDeclaration())
- continue;
-
- // Skip if not linking from source.
- if (DoNotLinkFromSource.count(&SF))
- continue;
-
- // When importing, only materialize the function requested for import.
- if (isPerformingImport() && &SF != ImportFunction)
- continue;
-
- if (linkGlobalValueBody(SF))
- return true;
- }
-
- // Resolve all uses of aliases with aliasees.
- for (GlobalAlias &Src : SrcM->aliases()) {
- if (DoNotLinkFromSource.count(&Src))
- continue;
- linkGlobalValueBody(Src);
- }
-
- // Update the initializers in the DstM module now that all globals that may
- // be referenced are in DstM.
- for (GlobalVariable &Src : SrcM->globals()) {
- // Only process initialized GV's or ones not already in dest.
- if (!Src.hasInitializer() || DoNotLinkFromSource.count(&Src))
- continue;
- linkGlobalValueBody(Src);
- }
-
- // Process vector of lazily linked in functions.
- while (!LazilyLinkGlobalValues.empty()) {
- GlobalValue *SGV = LazilyLinkGlobalValues.back();
- LazilyLinkGlobalValues.pop_back();
- if (isPerformingImport() && !doImportAsDefinition(SGV))
- continue;
-
- // Skip declarations that ValueMaterializer may have created in
- // case we link in only some of SrcM.
- if (shouldLinkOnlyNeeded() && SGV->isDeclaration())
- continue;
-
- assert(!SGV->isDeclaration() && "users should not pass down decls");
- if (linkGlobalValueBody(*SGV))
- return true;
- }
+ // Note that we are done linking global value bodies. This prevents
+ // metadata linking from creating new references.
+ DoneLinkingBodies = true;
// Remap all of the named MDNodes in Src into the DstM module. We do this
// after linking GlobalValues so that MDNodes that reference GlobalValues
Composite = nullptr;
}
-bool Linker::linkInModule(Module *Src, unsigned Flags, FunctionInfoIndex *Index,
+bool Linker::linkInModule(Module *Src, unsigned Flags,
+ const FunctionInfoIndex *Index,
Function *FuncToImport) {
ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src,
DiagnosticHandler, Flags, Index, FuncToImport);