diff --git a/include/llvm/Linker.h b/include/llvm/Linker.h index deaaca41551..3667b8521d9 100644 --- a/include/llvm/Linker.h +++ b/include/llvm/Linker.h @@ -10,12 +10,14 @@ #ifndef LLVM_LINKER_H #define LLVM_LINKER_H +#include "llvm/ADT/SmallPtrSet.h" #include namespace llvm { class Module; class StringRef; +class StructType; /// This class provides the core functionality of linking in LLVM. It keeps a /// pointer to the merged module so far. It doesn't take ownership of the @@ -47,6 +49,7 @@ class Linker { private: Module *Composite; + SmallPtrSet IdentifiedStructTypes; }; } // End llvm namespace diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 9801966f9d5..d2e13c91c43 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -29,6 +29,8 @@ using namespace llvm; //===----------------------------------------------------------------------===// namespace { + typedef SmallPtrSet TypeSet; + class TypeMapTy : public ValueMapTypeRemapper { /// MappedTypes - This is a mapping from a source type to a destination type /// to use. @@ -49,6 +51,9 @@ class TypeMapTy : public ValueMapTypeRemapper { SmallPtrSet DstResolvedOpaqueTypes; public: + TypeMapTy(TypeSet &Set) : DstStructTypesSet(Set) {} + + TypeSet &DstStructTypesSet; /// addTypeMapping - Indicate that the specified type in the destination /// module is conceptually equivalent to the specified type in the source /// module. @@ -325,13 +330,20 @@ Type *TypeMapTy::getImpl(Type *Ty) { StructType *STy = cast(Ty); // If the type is opaque, we can just use it directly. - if (STy->isOpaque()) + if (STy->isOpaque()) { + // A named structure type from src module is used. Add it to the Set of + // identified structs in the destination module. + DstStructTypesSet.insert(STy); return *Entry = STy; + } // Otherwise we create a new type and resolve its body later. This will be // resolved by the top level of get(). SrcDefinitionsToResolve.push_back(STy); StructType *DTy = StructType::create(STy->getContext()); + // A new identified structure type was created. Add it to the set of + // identified structs in the destination module. + DstStructTypesSet.insert(DTy); DstResolvedOpaqueTypes.insert(DTy); return *Entry = DTy; } @@ -373,8 +385,8 @@ namespace { public: std::string ErrorMsg; - ModuleLinker(Module *dstM, Module *srcM, unsigned mode) - : DstM(dstM), SrcM(srcM), Mode(mode) { } + ModuleLinker(Module *dstM, TypeSet &Set, Module *srcM, unsigned mode) + : DstM(dstM), SrcM(srcM), TypeMap(Set), Mode(mode) { } bool run(); @@ -588,11 +600,6 @@ void ModuleLinker::computeTypeMapping() { SmallPtrSet SrcStructTypesSet(SrcStructTypes.begin(), SrcStructTypes.end()); - TypeFinder DstStructTypes; - DstStructTypes.run(*DstM, true); - SmallPtrSet DstStructTypesSet(DstStructTypes.begin(), - DstStructTypes.end()); - for (unsigned i = 0, e = SrcStructTypes.size(); i != e; ++i) { StructType *ST = SrcStructTypes[i]; if (!ST->hasName()) continue; @@ -623,7 +630,7 @@ void ModuleLinker::computeTypeMapping() { // we prefer to take the '%C' version. So we are then left with both // '%C.1' and '%C' being used for the same types. This leads to some // variables using one type and some using the other. - if (!SrcStructTypesSet.count(DST) && DstStructTypesSet.count(DST)) + if (!SrcStructTypesSet.count(DST) && TypeMap.DstStructTypesSet.count(DST)) TypeMap.addTypeMapping(DST, ST); } @@ -1281,13 +1288,17 @@ bool ModuleLinker::run() { return false; } -Linker::Linker(Module *M) : Composite(M) {} +Linker::Linker(Module *M) : Composite(M) { + TypeFinder StructTypes; + StructTypes.run(*M, true); + IdentifiedStructTypes.insert(StructTypes.begin(), StructTypes.end()); +} Linker::~Linker() { } bool Linker::linkInModule(Module *Src, unsigned Mode, std::string *ErrorMsg) { - ModuleLinker TheLinker(Composite, Src, Mode); + ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, Mode); if (TheLinker.run()) { if (ErrorMsg) *ErrorMsg = TheLinker.ErrorMsg;