From: Rafael Espindola Date: Fri, 28 Nov 2014 16:41:24 +0000 (+0000) Subject: Add back r222727 with a fix. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a96f235c157c40b58e12e813faf97d8bc1004aa2;p=platform%2Fupstream%2Fllvm.git Add back r222727 with a fix. The original patch would fail when: * A dst opaque type (%A) is matched with a src type (%A). * A src opaque (%E) type is then speculatively matched with %A and the speculation fails afterward. * When rolling back the speculation we would cancel the source %A to dest %A mapping. The fix is to keep an explicit list of which resolutions are speculative. Original message: Fix overly aggressive type merging. If we find out that two types are *not* isomorphic, we learn nothing about opaque sub types in both the source and destination. llvm-svn: 222923 --- diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp index d3cb78c..8822a3a 100644 --- a/llvm/lib/Linker/LinkModules.cpp +++ b/llvm/lib/Linker/LinkModules.cpp @@ -47,6 +47,8 @@ class TypeMapTy : public ValueMapTypeRemapper { /// roll back. SmallVector SpeculativeTypes; + SmallVector SpeculativeDstOpaqueTypes; + /// This is a list of non-opaque structs in the source module that are mapped /// to an opaque struct in the destination module. SmallVector SrcDefinitionsToResolve; @@ -95,6 +97,7 @@ private: void TypeMapTy::addTypeMapping(Type *DstTy, Type *SrcTy) { assert(SpeculativeTypes.empty()); + assert(SpeculativeDstOpaqueTypes.empty()); // Check to see if these types are recursively isomorphic and establish a // mapping between them if so. @@ -103,8 +106,14 @@ void TypeMapTy::addTypeMapping(Type *DstTy, Type *SrcTy) { // any speculative mappings we've established. for (Type *Ty : SpeculativeTypes) MappedTypes.erase(Ty); + + SrcDefinitionsToResolve.resize(SrcDefinitionsToResolve.size() - + SpeculativeDstOpaqueTypes.size()); + for (StructType *Ty : SpeculativeDstOpaqueTypes) + DstResolvedOpaqueTypes.erase(Ty); } SpeculativeTypes.clear(); + SpeculativeDstOpaqueTypes.clear(); } /// Recursively walk this pair of types, returning true if they are isomorphic, @@ -139,14 +148,15 @@ bool TypeMapTy::areTypesIsomorphic(Type *DstTy, Type *SrcTy) { // 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(DstTy)->isOpaque()) { // We can only map one source type onto the opaque destination type. if (!DstResolvedOpaqueTypes.insert(cast(DstTy)).second) return false; SrcDefinitionsToResolve.push_back(SSTy); + SpeculativeTypes.push_back(SrcTy); + SpeculativeDstOpaqueTypes.push_back(cast(DstTy)); Entry = DstTy; return true; } diff --git a/llvm/test/Linker/Inputs/type-unique-opaque.ll b/llvm/test/Linker/Inputs/type-unique-opaque.ll new file mode 100644 index 0000000..872b601 --- /dev/null +++ b/llvm/test/Linker/Inputs/type-unique-opaque.ll @@ -0,0 +1,6 @@ +%t = type { i8 } +%t2 = type { %t*, i16 } + +define %t2* @f() { + ret %t2* null +} diff --git a/llvm/test/Linker/type-unique-opaque.ll b/llvm/test/Linker/type-unique-opaque.ll new file mode 100644 index 0000000..b4f6966 --- /dev/null +++ b/llvm/test/Linker/type-unique-opaque.ll @@ -0,0 +1,16 @@ +; RUN: llvm-link -S %s %p/Inputs/type-unique-opaque.ll | FileCheck %s + +; Test that a failed attempt at merging %u2 and %t2 (for the other file) will +; not cause %u and %t to get merged. + +; CHECK: %u = type opaque +; CHECK: define %u* @g() { + +%u = type opaque +%u2 = type { %u*, i8 } + +declare %u2* @f() + +define %u* @g() { + ret %u* null +}