/// Dump out the type map for debugging purposes.
void dump() const {
- for (DenseMap<Type*, Type*>::const_iterator
- I = MappedTypes.begin(), E = MappedTypes.end(); I != E; ++I) {
+ for (auto &Pair : MappedTypes) {
dbgs() << "TypeMap: ";
- I->first->print(dbgs());
+ Pair.first->print(dbgs());
dbgs() << " => ";
- I->second->print(dbgs());
+ Pair.second->print(dbgs());
dbgs() << '\n';
}
}
// Check to see if these types are recursively isomorphic and establish a
// mapping between them if so.
- if (!areTypesIsomorphic(DstTy, SrcTy)) {
- // Oops, they aren't isomorphic. Just discard this request by rolling out
- // any speculative mappings we've established.
- for (unsigned i = 0, e = SpeculativeTypes.size(); i != e; ++i)
- MappedTypes.erase(SpeculativeTypes[i]);
+ if (areTypesIsomorphic(DstTy, SrcTy)) {
+ SpeculativeTypes.clear();
+ return;
+ }
+
+ // Oops, they aren't isomorphic. Just discard this request by rolling out
+ // any speculative mappings we've established.
+ unsigned Removed = 0;
+ for (unsigned I = 0, E = SpeculativeTypes.size(); I != E; ++I) {
+ Type *SrcTy = SpeculativeTypes[I];
+ auto Iter = MappedTypes.find(SrcTy);
+ auto *DstTy = dyn_cast<StructType>(Iter->second);
+ if (DstTy && DstResolvedOpaqueTypes.erase(DstTy))
+ Removed++;
+ MappedTypes.erase(Iter);
}
+ SrcDefinitionsToResolve.resize(SrcDefinitionsToResolve.size() - Removed);
SpeculativeTypes.clear();
}
// Mapping a non-opaque source type to an opaque dest. If this is the first
// type that we're mapping onto this destination type then we succeed. Keep
- // the dest, but fill it in later. This doesn't need to be speculative. If
- // this is the second (different) type that we're trying to map onto the
- // same opaque type then we fail.
+ // the dest, but fill it in later. If this is the second (different) type
+ // that we're trying to map onto the same opaque type then we fail.
if (cast<StructType>(DstTy)->isOpaque()) {
// We can only map one source type onto the opaque destination type.
if (!DstResolvedOpaqueTypes.insert(cast<StructType>(DstTy)).second)
return false;
SrcDefinitionsToResolve.push_back(SSTy);
+ SpeculativeTypes.push_back(SrcTy);
Entry = DstTy;
return true;
}
//===----------------------------------------------------------------------===//
namespace {
- class ModuleLinker;
-
- /// Creates prototypes for functions that are lazily linked on the fly. This
- /// speeds up linking for modules with many/ lazily linked functions of which
- /// few get used.
- class ValueMaterializerTy : public ValueMaterializer {
- TypeMapTy &TypeMap;
- Module *DstM;
- std::vector<Function*> &LazilyLinkFunctions;
- public:
- ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM,
- std::vector<Function*> &LazilyLinkFunctions) :
- ValueMaterializer(), TypeMap(TypeMap), DstM(DstM),
- LazilyLinkFunctions(LazilyLinkFunctions) {
- }
+class ModuleLinker;
- Value *materializeValueFor(Value *V) override;
- };
+/// Creates prototypes for functions that are lazily linked on the fly. This
+/// speeds up linking for modules with many/ lazily linked functions of which
+/// few get used.
+class ValueMaterializerTy : public ValueMaterializer {
+ TypeMapTy &TypeMap;
+ Module *DstM;
+ std::vector<Function *> &LazilyLinkFunctions;
- namespace {
- class LinkDiagnosticInfo : public DiagnosticInfo {
- const Twine &Msg;
+public:
+ ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM,
+ std::vector<Function *> &LazilyLinkFunctions)
+ : ValueMaterializer(), TypeMap(TypeMap), DstM(DstM),
+ LazilyLinkFunctions(LazilyLinkFunctions) {}
- public:
- LinkDiagnosticInfo(DiagnosticSeverity Severity, const Twine &Msg);
- void print(DiagnosticPrinter &DP) const override;
- };
- LinkDiagnosticInfo::LinkDiagnosticInfo(DiagnosticSeverity Severity,
- const Twine &Msg)
- : DiagnosticInfo(DK_Linker, Severity), Msg(Msg) {}
- void LinkDiagnosticInfo::print(DiagnosticPrinter &DP) const { DP << Msg; }
- }
+ Value *materializeValueFor(Value *V) override;
+};
- /// This is an implementation class for the LinkModules function, which is the
- /// entrypoint for this file.
- class ModuleLinker {
- Module *DstM, *SrcM;
+class LinkDiagnosticInfo : public DiagnosticInfo {
+ const Twine &Msg;
- TypeMapTy TypeMap;
- ValueMaterializerTy ValMaterializer;
+public:
+ LinkDiagnosticInfo(DiagnosticSeverity Severity, const Twine &Msg);
+ void print(DiagnosticPrinter &DP) const override;
+};
+LinkDiagnosticInfo::LinkDiagnosticInfo(DiagnosticSeverity Severity,
+ const Twine &Msg)
+ : DiagnosticInfo(DK_Linker, Severity), Msg(Msg) {}
+void LinkDiagnosticInfo::print(DiagnosticPrinter &DP) const { DP << Msg; }
+
+/// This is an implementation class for the LinkModules function, which is the
+/// entrypoint for this file.
+class ModuleLinker {
+ Module *DstM, *SrcM;
+
+ TypeMapTy TypeMap;
+ ValueMaterializerTy ValMaterializer;
+
+ /// Mapping of values from what they used to be in Src, to what they are now
+ /// in DstM. ValueToValueMapTy is a ValueMap, which involves some overhead
+ /// due to the use of Value handles which the Linker doesn't actually need,
+ /// but this allows us to reuse the ValueMapper code.
+ ValueToValueMapTy ValueMap;
+
+ struct AppendingVarInfo {
+ GlobalVariable *NewGV; // New aggregate global in dest module.
+ const Constant *DstInit; // Old initializer from dest module.
+ const Constant *SrcInit; // Old initializer from src module.
+ };
- /// Mapping of values from what they used to be in Src, to what they are now
- /// in DstM. ValueToValueMapTy is a ValueMap, which involves some overhead
- /// due to the use of Value handles which the Linker doesn't actually need,
- /// but this allows us to reuse the ValueMapper code.
- ValueToValueMapTy ValueMap;
+ std::vector<AppendingVarInfo> AppendingVars;
- struct AppendingVarInfo {
- GlobalVariable *NewGV; // New aggregate global in dest module.
- const Constant *DstInit; // Old initializer from dest module.
- const Constant *SrcInit; // Old initializer from src module.
- };
+ // Set of items not to link in from source.
+ SmallPtrSet<const Value *, 16> DoNotLinkFromSource;
- std::vector<AppendingVarInfo> AppendingVars;
+ // Vector of functions to lazily link in.
+ std::vector<Function *> LazilyLinkFunctions;
- // Set of items not to link in from source.
- SmallPtrSet<const Value*, 16> DoNotLinkFromSource;
+ Linker::DiagnosticHandlerFunction DiagnosticHandler;
- // Vector of functions to lazily link in.
- std::vector<Function*> LazilyLinkFunctions;
+public:
+ ModuleLinker(Module *dstM, TypeSet &Set, Module *srcM,
+ Linker::DiagnosticHandlerFunction DiagnosticHandler)
+ : DstM(dstM), SrcM(srcM), TypeMap(Set),
+ ValMaterializer(TypeMap, DstM, LazilyLinkFunctions),
+ DiagnosticHandler(DiagnosticHandler) {}
- Linker::DiagnosticHandlerFunction DiagnosticHandler;
+ bool run();
- public:
- ModuleLinker(Module *dstM, TypeSet &Set, Module *srcM,
- Linker::DiagnosticHandlerFunction DiagnosticHandler)
- : DstM(dstM), SrcM(srcM), TypeMap(Set),
- ValMaterializer(TypeMap, DstM, LazilyLinkFunctions),
- DiagnosticHandler(DiagnosticHandler) {}
+private:
+ bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest,
+ const GlobalValue &Src);
- bool run();
+ /// Helper method for setting a message and returning an error code.
+ bool emitError(const Twine &Message) {
+ DiagnosticHandler(LinkDiagnosticInfo(DS_Error, Message));
+ return true;
+ }
- private:
- bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest,
- const GlobalValue &Src);
+ void emitWarning(const Twine &Message) {
+ DiagnosticHandler(LinkDiagnosticInfo(DS_Warning, Message));
+ }
- /// Helper method for setting a message and returning an error code.
- bool emitError(const Twine &Message) {
- DiagnosticHandler(LinkDiagnosticInfo(DS_Error, Message));
- return true;
- }
+ bool getComdatLeader(Module *M, StringRef ComdatName,
+ const GlobalVariable *&GVar);
+ bool computeResultingSelectionKind(StringRef ComdatName,
+ Comdat::SelectionKind Src,
+ Comdat::SelectionKind Dst,
+ Comdat::SelectionKind &Result,
+ bool &LinkFromSrc);
+ std::map<const Comdat *, std::pair<Comdat::SelectionKind, bool>>
+ ComdatsChosen;
+ bool getComdatResult(const Comdat *SrcC, Comdat::SelectionKind &SK,
+ bool &LinkFromSrc);
+
+ /// 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())
+ return nullptr;
+
+ // Otherwise see if we have a match in the destination module's symtab.
+ GlobalValue *DGV = DstM->getNamedValue(SrcGV->getName());
+ if (!DGV)
+ return nullptr;
- void emitWarning(const Twine &Message) {
- DiagnosticHandler(LinkDiagnosticInfo(DS_Warning, Message));
- }
+ // If we found a global with the same name in the dest module, but it has
+ // internal linkage, we are really not doing any linkage here.
+ if (DGV->hasLocalLinkage())
+ return nullptr;
- bool getComdatLeader(Module *M, StringRef ComdatName,
- const GlobalVariable *&GVar);
- bool computeResultingSelectionKind(StringRef ComdatName,
- Comdat::SelectionKind Src,
- Comdat::SelectionKind Dst,
- Comdat::SelectionKind &Result,
- bool &LinkFromSrc);
- std::map<const Comdat *, std::pair<Comdat::SelectionKind, bool>>
- ComdatsChosen;
- bool getComdatResult(const Comdat *SrcC, Comdat::SelectionKind &SK,
- bool &LinkFromSrc);
-
- /// 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())
- return nullptr;
-
- // Otherwise see if we have a match in the destination module's symtab.
- GlobalValue *DGV = DstM->getNamedValue(SrcGV->getName());
- if (!DGV) return nullptr;
-
- // If we found a global with the same name in the dest module, but it has
- // internal linkage, we are really not doing any linkage here.
- if (DGV->hasLocalLinkage())
- return nullptr;
-
- // Otherwise, we do in fact link to the destination global.
- return DGV;
- }
+ // Otherwise, we do in fact link to the destination global.
+ return DGV;
+ }
- void computeTypeMapping();
+ void computeTypeMapping();
- void upgradeMismatchedGlobalArray(StringRef Name);
- void upgradeMismatchedGlobals();
+ void upgradeMismatchedGlobalArray(StringRef Name);
+ void upgradeMismatchedGlobals();
- bool linkAppendingVarProto(GlobalVariable *DstGV,
- const GlobalVariable *SrcGV);
+ bool linkAppendingVarProto(GlobalVariable *DstGV,
+ const GlobalVariable *SrcGV);
- bool linkGlobalValueProto(GlobalValue *GV);
- GlobalValue *linkGlobalVariableProto(const GlobalVariable *SGVar,
- GlobalValue *DGV, bool LinkFromSrc);
- GlobalValue *linkFunctionProto(const Function *SF, GlobalValue *DGV,
- bool LinkFromSrc);
- GlobalValue *linkGlobalAliasProto(const GlobalAlias *SGA, GlobalValue *DGV,
- bool LinkFromSrc);
+ bool linkGlobalValueProto(GlobalValue *GV);
+ GlobalValue *linkGlobalVariableProto(const GlobalVariable *SGVar,
+ GlobalValue *DGV, bool LinkFromSrc);
+ GlobalValue *linkFunctionProto(const Function *SF, GlobalValue *DGV,
+ bool LinkFromSrc);
+ GlobalValue *linkGlobalAliasProto(const GlobalAlias *SGA, GlobalValue *DGV,
+ bool LinkFromSrc);
- bool linkModuleFlagsMetadata();
+ bool linkModuleFlagsMetadata();
- void linkAppendingVarInit(const AppendingVarInfo &AVI);
- void linkGlobalInits();
- void linkFunctionBody(Function *Dst, Function *Src);
- void linkAliasBodies();
- void linkNamedMDNodes();
- };
+ void linkAppendingVarInit(const AppendingVarInfo &AVI);
+ void linkGlobalInits();
+ void linkFunctionBody(Function *Dst, Function *Src);
+ void linkAliasBodies();
+ void linkNamedMDNodes();
+};
}
/// The LLVM SymbolTable class autorenames globals that conflict in the symbol
TypeMap.addTypeMapping(DGV->getType(), SGV.getType());
}
+ for (GlobalValue &SGV : SrcM->aliases()) {
+ if (GlobalValue *DGV = getLinkedToGlobal(&SGV))
+ TypeMap.addTypeMapping(DGV->getType(), SGV.getType());
+ }
+
// Incorporate types by name, scanning all the types in the source module.
// At this point, the destination module may have a type "%foo = { i32 }" for
// example. When the source module got loaded into the same LLVMContext, if
TypeMap.addTypeMapping(DST, ST);
}
- // Don't bother incorporating aliases, they aren't generally typed well.
-
// Now that we have discovered all of the type equivalences, get a body for
// any 'opaque' types in the dest module that are now resolved.
TypeMap.linkDefinedTypeBodies();