/// references.
bool DoneLinkingBodies;
+ bool HasError = false;
+
public:
ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM,
DiagnosticHandlerFunction DiagnosticHandler, unsigned Flags,
/// 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;
}
void upgradeMismatchedGlobalArray(StringRef Name);
void upgradeMismatchedGlobals();
+ bool linkIfNeeded(GlobalValue &GV);
bool linkAppendingVarProto(GlobalVariable *DstGV,
const GlobalVariable *SrcGV);
if (doneLinkingBodies())
return nullptr;
- GlobalValue *DGV = copyGlobalValueProto(TypeMap, SGV);
-
- if (Comdat *SC = SGV->getComdat()) {
- if (auto *DGO = dyn_cast<GlobalObject>(DGV)) {
- Comdat *DC = DstM->getOrInsertComdat(SC->getName());
- DGO->setComdat(DC);
- }
- }
-
- return DGV;
+ linkGlobalValueProto(SGV);
+ if (HasError)
+ return nullptr;
+ Value *Ret = ValueMap[SGV];
+ assert(Ret);
+ return Ret;
}
void ValueMaterializerTy::materializeInitFor(GlobalValue *New,
}
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;
+ }
+
+ if (Old->isDeclaration())
+ return;
+
if (isPerformingImport() && !doImportAsDefinition(Old))
return;
- // Skip declarations that ValueMaterializer may have created in
- // case we link in only some of SrcM.
- if (shouldLinkOnlyNeeded() && Old->isDeclaration())
+ if (!New->hasLocalLinkage() && DoNotLinkFromSource.count(Old))
return;
- assert(!Old->isDeclaration() && "users should not pass down decls");
linkGlobalValueBody(*Old);
}
std::tie(SK, LinkFromSrc) = ComdatsChosen[SC];
C = DstM->getOrInsertComdat(SC->getName());
C->setSelectionKind(SK);
- ComdatMembers[SC].push_back(SGV);
+ if (SGV->hasInternalLinkage())
+ LinkFromSrc = true;
} else if (DGV) {
if (shouldLinkFromSource(LinkFromSrc, *DGV, *SGV))
return 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 (isPerformingImport() && !doImportAsDefinition(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())
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 (AppendingVarInfo &AppendingVar : AppendingVars)
MapValue(GV, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer);
}
- // 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;
-
- 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);
- }
-
// Note that we are done linking global value bodies. This prevents
// metadata linking from creating new references.
DoneLinkingBodies = true;