summaryrefslogtreecommitdiff
path: root/lib/Linker
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Linker')
-rw-r--r--lib/Linker/LinkModules.cpp31
1 files changed, 25 insertions, 6 deletions
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index dca523c7ab..765fcc8823 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -596,10 +596,14 @@ void ModuleLinker::computeTypeMapping() {
// it had the same type, it would have been renamed to "%foo.42 = { i32 }".
std::vector<StructType*> SrcStructTypes;
SrcM->findUsedStructTypes(SrcStructTypes);
-
SmallPtrSet<StructType*, 32> SrcStructTypesSet(SrcStructTypes.begin(),
SrcStructTypes.end());
-
+
+ std::vector<StructType*> DstStructTypes;
+ DstM->findUsedStructTypes(DstStructTypes);
+ SmallPtrSet<StructType*, 32> DstStructTypesSet(DstStructTypes.begin(),
+ DstStructTypes.end());
+
for (unsigned i = 0, e = SrcStructTypes.size(); i != e; ++i) {
StructType *ST = SrcStructTypes[i];
if (!ST->hasName()) continue;
@@ -612,9 +616,24 @@ void ModuleLinker::computeTypeMapping() {
// Check to see if the destination module has a struct with the prefix name.
if (StructType *DST = DstM->getTypeByName(ST->getName().substr(0, DotPos)))
- // Don't use it if this actually came from the source module. They're in
- // the same LLVMContext after all.
- if (!SrcStructTypesSet.count(DST))
+ // Don't use it if this actually came from the source module. They're in
+ // the same LLVMContext after all. Also don't use it unless the type is
+ // actually used in the destination module. This can happen in situations
+ // like this:
+ //
+ // Module A Module B
+ // -------- --------
+ // %Z = type { %A } %B = type { %C.1 }
+ // %A = type { %B.1, [7 x i8] } %C.1 = type { i8* }
+ // %B.1 = type { %C } %A.2 = type { %B.3, [5 x i8] }
+ // %C = type { i8* } %B.3 = type { %C.1 }
+ //
+ // When we link Module B with Module A, the '%B' in Module B is
+ // used. However, that would then use '%C.1'. But when we process '%C.1',
+ // 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))
TypeMap.addTypeMapping(DST, ST);
}
@@ -1313,6 +1332,6 @@ bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode,
if (ErrorMsg) *ErrorMsg = TheLinker.ErrorMsg;
return true;
}
-
+
return false;
}