class ValueMaterializerTy : public ValueMaterializer {
TypeMapTy &TypeMap;
Module *DstM;
- std::vector<Function *> &LazilyLinkFunctions;
+ std::vector<GlobalValue *> &LazilyLinkGlobalValues;
public:
ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM,
- std::vector<Function *> &LazilyLinkFunctions)
+ std::vector<GlobalValue *> &LazilyLinkGlobalValues)
: ValueMaterializer(), TypeMap(TypeMap), DstM(DstM),
- LazilyLinkFunctions(LazilyLinkFunctions) {}
+ LazilyLinkGlobalValues(LazilyLinkGlobalValues) {}
Value *materializeValueFor(Value *V) override;
};
// Set of items not to link in from source.
SmallPtrSet<const Value *, 16> DoNotLinkFromSource;
- // Vector of functions to lazily link in.
- std::vector<Function *> LazilyLinkFunctions;
+ // Vector of GlobalValues to lazily link in.
+ std::vector<GlobalValue *> LazilyLinkGlobalValues;
Linker::DiagnosticHandlerFunction DiagnosticHandler;
ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM,
Linker::DiagnosticHandlerFunction DiagnosticHandler)
: DstM(dstM), SrcM(srcM), TypeMap(Set),
- ValMaterializer(TypeMap, DstM, LazilyLinkFunctions),
+ ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues),
DiagnosticHandler(DiagnosticHandler) {}
bool run();
const GlobalVariable *SrcGV);
bool linkGlobalValueProto(GlobalValue *GV);
- GlobalValue *linkGlobalVariableProto(const GlobalVariable *SGVar);
- GlobalValue *linkFunctionProto(const Function *SF, GlobalValue *DGV);
- GlobalValue *linkGlobalAliasProto(const GlobalAlias *SGA);
-
bool linkModuleFlagsMetadata();
void linkAppendingVarInit(const AppendingVarInfo &AVI);
- void linkGlobalInits();
- bool linkFunctionBody(Function &Src);
- void linkAliasBodies();
+
+ void linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src);
+ bool linkFunctionBody(Function &Dst, Function &Src);
+ void linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src);
+ bool linkGlobalValueBody(GlobalValue &Src);
+
void linkNamedMDNodes();
};
}
return false;
}
+/// Loop through the global variables in the src module and merge them into the
+/// dest module.
+static GlobalVariable *copyGlobalVariableProto(TypeMapTy &TypeMap, Module &DstM,
+ const GlobalVariable *SGVar) {
+ // No linking to be performed or linking from the source: simply create an
+ // identical version of the symbol over in the dest module... the
+ // initializer will be filled in later by LinkGlobalInits.
+ GlobalVariable *NewDGV = new GlobalVariable(
+ DstM, TypeMap.get(SGVar->getType()->getElementType()),
+ SGVar->isConstant(), SGVar->getLinkage(), /*init*/ nullptr,
+ SGVar->getName(), /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(),
+ SGVar->getType()->getAddressSpace());
+
+ return NewDGV;
+}
+
+/// Link the function in the source module into the destination module if
+/// needed, setting up mapping information.
+static Function *copyFunctionProto(TypeMapTy &TypeMap, Module &DstM,
+ const Function *SF) {
+ // If there is no linkage to be performed or we are linking from the source,
+ // bring SF over.
+ return Function::Create(TypeMap.get(SF->getFunctionType()), SF->getLinkage(),
+ SF->getName(), &DstM);
+}
+
+/// Set up prototypes for any aliases that come over from the source module.
+static GlobalAlias *copyGlobalAliasProto(TypeMapTy &TypeMap, Module &DstM,
+ const GlobalAlias *SGA) {
+ // If there is no linkage to be performed or we're linking from the source,
+ // bring over SGA.
+ auto *PTy = cast<PointerType>(TypeMap.get(SGA->getType()));
+ return GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(),
+ SGA->getLinkage(), SGA->getName(), &DstM);
+}
+
+static GlobalValue *copyGlobalValueProto(TypeMapTy &TypeMap, Module &DstM,
+ const GlobalValue *SGV) {
+ GlobalValue *NewGV;
+ if (auto *SGVar = dyn_cast<GlobalVariable>(SGV))
+ NewGV = copyGlobalVariableProto(TypeMap, DstM, SGVar);
+ else if (auto *SF = dyn_cast<Function>(SGV))
+ NewGV = copyFunctionProto(TypeMap, DstM, SF);
+ else
+ NewGV = copyGlobalAliasProto(TypeMap, DstM, cast<GlobalAlias>(SGV));
+ copyGVAttributes(NewGV, SGV);
+ return NewGV;
+}
+
Value *ValueMaterializerTy::materializeValueFor(Value *V) {
- Function *SF = dyn_cast<Function>(V);
- if (!SF)
+ auto *SGV = dyn_cast<GlobalValue>(V);
+ if (!SGV)
return nullptr;
- Function *DF = Function::Create(TypeMap.get(SF->getFunctionType()),
- SF->getLinkage(), SF->getName(), DstM);
- copyGVAttributes(DF, SF);
+ GlobalValue *DGV = copyGlobalValueProto(TypeMap, *DstM, SGV);
- if (Comdat *SC = SF->getComdat()) {
- Comdat *DC = DstM->getOrInsertComdat(SC->getName());
- DF->setComdat(DC);
+ if (Comdat *SC = SGV->getComdat()) {
+ if (auto *DGO = dyn_cast<GlobalObject>(DGV)) {
+ Comdat *DC = DstM->getOrInsertComdat(SC->getName());
+ DGO->setComdat(DC);
+ }
}
- LazilyLinkFunctions.push_back(SF);
- return DF;
+ LazilyLinkGlobalValues.push_back(SGV);
+ return DGV;
}
bool ModuleLinker::getComdatLeader(Module *M, StringRef ComdatName,
if (!LinkFromSrc) {
NewGV = DGV;
} else {
- if (auto *SGVar = dyn_cast<GlobalVariable>(SGV))
- NewGV = linkGlobalVariableProto(SGVar);
- else if (auto *SF = dyn_cast<Function>(SGV))
- NewGV = linkFunctionProto(SF, DGV);
- else
- NewGV = linkGlobalAliasProto(cast<GlobalAlias>(SGV));
- }
-
- if (!NewGV)
- return false;
+ // 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 && (SGV->hasLocalLinkage() || SGV->hasLinkOnceLinkage() ||
+ SGV->hasAvailableExternallyLinkage())) {
+ DoNotLinkFromSource.insert(SGV);
+ return false;
+ }
- if (NewGV != DGV)
- copyGVAttributes(NewGV, SGV);
+ NewGV = copyGlobalValueProto(TypeMap, *DstM, SGV);
+ }
NewGV->setUnnamedAddr(HasUnnamedAddr);
NewGV->setVisibility(Visibility);
return false;
}
-/// Loop through the global variables in the src module and merge them into the
-/// dest module.
-GlobalValue *
-ModuleLinker::linkGlobalVariableProto(const GlobalVariable *SGVar) {
- // No linking to be performed or linking from the source: simply create an
- // identical version of the symbol over in the dest module... the
- // initializer will be filled in later by LinkGlobalInits.
- GlobalVariable *NewDGV = new GlobalVariable(
- *DstM, TypeMap.get(SGVar->getType()->getElementType()),
- SGVar->isConstant(), SGVar->getLinkage(), /*init*/ nullptr,
- SGVar->getName(), /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(),
- SGVar->getType()->getAddressSpace());
-
- return NewDGV;
-}
-
-/// Link the function in the source module into the destination module if
-/// needed, setting up mapping information.
-GlobalValue *ModuleLinker::linkFunctionProto(const Function *SF,
- GlobalValue *DGV) {
- // If the function is to be lazily linked, don't create it just yet.
- // The ValueMaterializerTy will deal with creating it if it's used.
- if (!DGV && (SF->hasLocalLinkage() || SF->hasLinkOnceLinkage() ||
- SF->hasAvailableExternallyLinkage())) {
- DoNotLinkFromSource.insert(SF);
- return nullptr;
- }
-
- // If there is no linkage to be performed or we are linking from the source,
- // bring SF over.
- return Function::Create(TypeMap.get(SF->getFunctionType()), SF->getLinkage(),
- SF->getName(), DstM);
-}
-
-/// Set up prototypes for any aliases that come over from the source module.
-GlobalValue *ModuleLinker::linkGlobalAliasProto(const GlobalAlias *SGA) {
- // If there is no linkage to be performed or we're linking from the source,
- // bring over SGA.
- auto *PTy = cast<PointerType>(TypeMap.get(SGA->getType()));
- return GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(),
- SGA->getLinkage(), SGA->getName(), DstM);
-}
-
static void getArrayElements(const Constant *C,
SmallVectorImpl<Constant *> &Dest) {
unsigned NumElements = cast<ArrayType>(C->getType())->getNumElements();
/// Update the initializers in the Dest module now that all globals that may be
/// referenced are in Dest.
-void ModuleLinker::linkGlobalInits() {
- // Loop over all of the globals in the src module, mapping them over as we go
- for (GlobalVariable &Src : SrcM->globals()) {
- // Only process initialized GV's or ones not already in dest.
- if (!Src.hasInitializer() || DoNotLinkFromSource.count(&Src))
- continue;
-
- // Grab destination global variable.
- GlobalVariable *Dst = cast<GlobalVariable>(ValueMap[&Src]);
- // Figure out what the initializer looks like in the dest module.
- Dst->setInitializer(MapValue(Src.getInitializer(), ValueMap, RF_None,
- &TypeMap, &ValMaterializer));
- }
+void ModuleLinker::linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src) {
+ // Figure out what the initializer looks like in the dest module.
+ Dst.setInitializer(MapValue(Src.getInitializer(), ValueMap, RF_None, &TypeMap,
+ &ValMaterializer));
}
/// Copy the source function over into the dest function and fix up references
/// to values. At this point we know that Dest is an external function, and
/// that Src is not.
-bool ModuleLinker::linkFunctionBody(Function &Src) {
- Function *Dst = cast<Function>(ValueMap[&Src]);
- assert(Dst && Dst->isDeclaration() && !Src.isDeclaration());
+bool ModuleLinker::linkFunctionBody(Function &Dst, Function &Src) {
+ assert(Dst.isDeclaration() && !Src.isDeclaration());
// Materialize if needed.
if (std::error_code EC = Src.materialize())
// Link in the prefix data.
if (Src.hasPrefixData())
- Dst->setPrefixData(MapValue(Src.getPrefixData(), ValueMap, RF_None,
- &TypeMap, &ValMaterializer));
+ Dst.setPrefixData(MapValue(Src.getPrefixData(), ValueMap, RF_None, &TypeMap,
+ &ValMaterializer));
// Link in the prologue data.
if (Src.hasPrologueData())
- Dst->setPrologueData(MapValue(Src.getPrologueData(), ValueMap, RF_None,
+ Dst.setPrologueData(MapValue(Src.getPrologueData(), ValueMap, RF_None,
&TypeMap, &ValMaterializer));
-
// Go through and convert function arguments over, remembering the mapping.
- Function::arg_iterator DI = Dst->arg_begin();
+ Function::arg_iterator DI = Dst.arg_begin();
for (Argument &Arg : Src.args()) {
DI->setName(Arg.getName()); // Copy the name over.
}
// Splice the body of the source function into the dest function.
- Dst->getBasicBlockList().splice(Dst->end(), Src.getBasicBlockList());
+ Dst.getBasicBlockList().splice(Dst.end(), Src.getBasicBlockList());
// At this point, all of the instructions and values of the function are now
// copied over. The only problem is that they are still referencing values in
// the Source function as operands. Loop through all of the operands of the
// functions and patch them up to point to the local versions.
- for (BasicBlock &BB : *Dst)
+ for (BasicBlock &BB : Dst)
for (Instruction &I : BB)
RemapInstruction(&I, ValueMap, RF_IgnoreMissingEntries, &TypeMap,
&ValMaterializer);
return false;
}
-/// Insert all of the aliases in Src into the Dest module.
-void ModuleLinker::linkAliasBodies() {
- for (GlobalAlias &Src : SrcM->aliases()) {
- if (DoNotLinkFromSource.count(&Src))
- continue;
- if (Constant *Aliasee = Src.getAliasee()) {
- GlobalAlias *DA = cast<GlobalAlias>(ValueMap[&Src]);
- Constant *Val =
- MapValue(Aliasee, ValueMap, RF_None, &TypeMap, &ValMaterializer);
- DA->setAliasee(Val);
- }
+void ModuleLinker::linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src) {
+ Constant *Aliasee = Src.getAliasee();
+ Constant *Val =
+ MapValue(Aliasee, ValueMap, RF_None, &TypeMap, &ValMaterializer);
+ Dst.setAliasee(Val);
+}
+
+bool ModuleLinker::linkGlobalValueBody(GlobalValue &Src) {
+ Value *Dst = ValueMap[&Src];
+ assert(Dst);
+ if (auto *F = dyn_cast<Function>(&Src))
+ return linkFunctionBody(cast<Function>(*Dst), *F);
+ if (auto *GVar = dyn_cast<GlobalVariable>(&Src)) {
+ linkGlobalInit(cast<GlobalVariable>(*Dst), *GVar);
+ return false;
}
+ linkAliasBody(cast<GlobalAlias>(*Dst), cast<GlobalAlias>(Src));
+ return false;
}
/// Insert all of the named MDNodes in Src into the Dest module.
if (DoNotLinkFromSource.count(&SF))
continue;
- if (linkFunctionBody(SF))
+ if (linkGlobalValueBody(SF))
return true;
}
// Resolve all uses of aliases with aliasees.
- linkAliasBodies();
+ for (GlobalAlias &Src : SrcM->aliases()) {
+ if (DoNotLinkFromSource.count(&Src))
+ continue;
+ linkGlobalValueBody(Src);
+ }
// Remap all of the named MDNodes in Src into the DstM module. We do this
// after linking GlobalValues so that MDNodes that reference GlobalValues
// Update the initializers in the DstM module now that all globals that may
// be referenced are in DstM.
- linkGlobalInits();
+ 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 (!LazilyLinkFunctions.empty()) {
- Function *SF = LazilyLinkFunctions.back();
- LazilyLinkFunctions.pop_back();
+ while (!LazilyLinkGlobalValues.empty()) {
+ GlobalValue *SGV = LazilyLinkGlobalValues.back();
+ LazilyLinkGlobalValues.pop_back();
- if (linkFunctionBody(*SF))
+ if (linkGlobalValueBody(*SGV))
return true;
}