[llvm-branch-commits] [llvm-branch] r134687 - /llvm/branches/type-system-rewrite/lib/Linker/LinkModules.cpp
Chris Lattner
sabre at nondot.org
Thu Jul 7 23:03:01 PDT 2011
Author: lattner
Date: Fri Jul 8 01:03:01 2011
New Revision: 134687
URL: http://llvm.org/viewvc/llvm-project?rev=134687&view=rev
Log:
rewrite the type isomorphism code to be simpler and actually correct,
fixing almost all the remaining llvm-test failures.
Modified:
llvm/branches/type-system-rewrite/lib/Linker/LinkModules.cpp
Modified: llvm/branches/type-system-rewrite/lib/Linker/LinkModules.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/type-system-rewrite/lib/Linker/LinkModules.cpp?rev=134687&r1=134686&r2=134687&view=diff
==============================================================================
--- llvm/branches/type-system-rewrite/lib/Linker/LinkModules.cpp (original)
+++ llvm/branches/type-system-rewrite/lib/Linker/LinkModules.cpp Fri Jul 8 01:03:01 2011
@@ -30,6 +30,11 @@
/// to use.
DenseMap<Type*, Type*> MappedTypes;
+ /// SpeculativeTypes - When checking to see if two subgraphs are isomorphic,
+ /// we speculatively add types to MappedTypes, but keep track of them here in
+ /// case we need to roll back.
+ SmallVector<Type*, 16> SpeculativeTypes;
+
/// DefinitionsToResolve - This is a list of non-opaque structs in the source
/// module that are mapped to an opaque struct in the destination module.
SmallVector<StructType*, 16> DefinitionsToResolve;
@@ -37,10 +42,8 @@
/// addTypeMapping - Indicate that the specified type in the destination
/// module is conceptually equivalent to the specified type in the source
- /// module. This updates the type mapping for equivalent types, and returns
- /// false. If there is a hard type conflict (maybe merging "int x" with
- /// "extern float x") this returns true.
- bool addTypeMapping(Type *DstTy, Type *SrcTy);
+ /// module.
+ void addTypeMapping(Type *DstTy, Type *SrcTy);
/// linkDefinedTypeBodies - Produce a body for an opaque type in the dest
/// module from a type definition in the source module.
@@ -48,7 +51,7 @@
/// get - Return the mapped type to use for the specified input type from the
/// source module.
- Type *get(Type *T);
+ Type *get(Type *SrcTy);
FunctionType *get(FunctionType *T) {return cast<FunctionType>(get((Type*)T));}
@@ -59,114 +62,106 @@
return get(SrcTy);
}
- bool addTypeMappingRec(Type *DstTy, Type *SrcTy);
+ bool areTypesIsomorphic(Type *DstTy, Type *SrcTy);
};
}
-bool TypeMapTy::addTypeMapping(Type *DstTy, Type *SrcTy) {
- Type *&T = MappedTypes[SrcTy];
- if (T)
- return T != DstTy;
+void TypeMapTy::addTypeMapping(Type *DstTy, Type *SrcTy) {
+ Type *&Entry = MappedTypes[SrcTy];
+ if (Entry) return;
if (DstTy == SrcTy) {
- T = DstTy;
- return false;
+ Entry = DstTy;
+ return;
}
- return addTypeMappingRec(DstTy, SrcTy);
-}
+ // 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]);
+ }
+ SpeculativeTypes.clear();
+}
+
+/// areTypesIsomorphic - Recursively walk this pair of types, returning true
+/// if they are isomorphic, false if they are not.
+bool TypeMapTy::areTypesIsomorphic(Type *DstTy, Type *SrcTy) {
+ // Two types with differing kinds are clearly not isomorphic.
+ if (DstTy->getTypeID() != SrcTy->getTypeID()) return false;
+
+ // If we have an entry in the MappedTypes table, then we have our answer.
+ Type *&Entry = MappedTypes[SrcTy];
+ if (Entry)
+ return Entry == DstTy;
-
-/// addTypeMappingRec - This is the implementation function for addTypeMapping,
-/// which optimizes out the map lookup in the recursive walk.
-bool TypeMapTy::addTypeMappingRec(Type *DstTy, Type *SrcTy) {
- // Two types cannot be resolved together if they are of different primitive
- // type. For example, we cannot resolve an int to a float.
- if (DstTy->getTypeID() != SrcTy->getTypeID()) return true;
-
- // Otherwise, resolve the used type used by this derived type.
- switch (DstTy->getTypeID()) {
- default:
+ // Two identical types are clearly isomorphic. Remember this
+ // non-speculatively.
+ if (DstTy == SrcTy) {
+ Entry = DstTy;
return true;
- case Type::StructTyID: {
- StructType *DstST = cast<StructType>(DstTy);
- StructType *SrcST = cast<StructType>(SrcTy);
-
- // If the destination type is opaque, then it should be resolved to the
- // input type. If the source type is opaque, then it gets whatever the
- // destination type is.
- if (SrcST->isOpaque())
- break;
- // If the type is opaque in the dest module but not the src module, then we
- // should get the new type definition from the src module.
- if (DstST->isOpaque()) {
- DefinitionsToResolve.push_back(SrcST);
- break;
- }
-
- if (DstST->getNumContainedTypes() != SrcST->getNumContainedTypes() ||
- DstST->isPacked() != SrcST->isPacked())
- return true;
-
- Type *&Entry = MappedTypes[SrcST];
- if (Entry)
- return Entry != DstTy;
-
- // Otherwise, we speculatively assume that the structs can be merged, add an
- // entry to the type map so we don't infinitely recurse.
- Entry = DstST;
-
- // Then call addTypeMapping on each entry (not "Rec") so that we get the
- // caching behavior of the map check for each element.
- for (unsigned i = 0, e = DstST->getNumContainedTypes(); i != e; ++i) {
- Type *SE = SrcST->getContainedType(i), *DE = DstST->getContainedType(i);
- if (addTypeMapping(DE, SE))
- return true;
- }
- return false;
}
- case Type::FunctionTyID: {
- const FunctionType *DstFT = cast<FunctionType>(DstTy);
- const FunctionType *SrcFT = cast<FunctionType>(SrcTy);
- if (DstFT->isVarArg() != SrcFT->isVarArg() ||
- DstFT->getNumContainedTypes() != SrcFT->getNumContainedTypes())
- return true;
+
+ // Okay, we have two types with identical kinds that we haven't seen before.
- for (unsigned i = 0, e = DstFT->getNumContainedTypes(); i != e; ++i) {
- Type *SE = SrcFT->getContainedType(i), *DE = DstFT->getContainedType(i);
- if (SE != DE && addTypeMappingRec(DE, SE))
- return true;
- }
- break;
- }
- case Type::ArrayTyID: {
- ArrayType *DAT = cast<ArrayType>(DstTy);
- ArrayType *SAT = cast<ArrayType>(SrcTy);
- if (DAT->getNumElements() != SAT->getNumElements() ||
- addTypeMappingRec(DAT->getElementType(), SAT->getElementType()))
- return true;
- break;
- }
- case Type::VectorTyID: {
- VectorType *DVT = cast<VectorType>(DstTy);
- VectorType *SVT = cast<VectorType>(SrcTy);
- if (DVT->getNumElements() != SVT->getNumElements() ||
- addTypeMappingRec(DVT->getElementType(), SVT->getElementType()))
+ // If this is an opaque struct type, special case it.
+ if (StructType *SSTy = dyn_cast<StructType>(SrcTy)) {
+ // Mapping an opaque type to any struct, just keep the dest struct.
+ if (SSTy->isOpaque()) {
+ Entry = DstTy;
+ SpeculativeTypes.push_back(SrcTy);
return true;
- break;
- }
- case Type::PointerTyID: {
- PointerType *DstPT = cast<PointerType>(DstTy);
- PointerType *SrcPT = cast<PointerType>(SrcTy);
- if (DstPT->getAddressSpace() != SrcPT->getAddressSpace() ||
- addTypeMappingRec(DstPT->getElementType(), SrcPT->getElementType()))
+ }
+
+ // Mapping a non-opaque source type to an opaque dest. Keep the dest, but
+ // fill it in later. This doesn't need to be speculative.
+ if (cast<StructType>(DstTy)->isOpaque()) {
+ Entry = DstTy;
+ DefinitionsToResolve.push_back(SSTy);
return true;
- break;
+ }
}
+
+ // If the number of subtypes disagree between the two types, then we fail.
+ if (SrcTy->getNumContainedTypes() != DstTy->getNumContainedTypes())
+ return false;
+
+ // Fail if any of the extra properties (e.g. array size) of the type disagree.
+ if (isa<IntegerType>(DstTy))
+ return false; // bitwidth disagrees.
+ if (PointerType *PT = dyn_cast<PointerType>(DstTy)) {
+ if (PT->getAddressSpace() != cast<PointerType>(SrcTy)->getAddressSpace())
+ return false;
+ } else if (FunctionType *FT = dyn_cast<FunctionType>(DstTy)) {
+ if (FT->isVarArg() != cast<FunctionType>(SrcTy)->isVarArg())
+ return false;
+ } else if (StructType *DSTy = dyn_cast<StructType>(DstTy)) {
+ StructType *SSTy = cast<StructType>(SrcTy);
+ if (DSTy->isAnonymous() != SSTy->isAnonymous() ||
+ DSTy->isPacked() != SSTy->isPacked())
+ return false;
+ } else if (ArrayType *DATy = dyn_cast<ArrayType>(DstTy)) {
+ if (DATy->getNumElements() != cast<ArrayType>(SrcTy)->getNumElements())
+ return false;
+ } else if (VectorType *DVTy = dyn_cast<VectorType>(DstTy)) {
+ if (DVTy->getNumElements() != cast<ArrayType>(SrcTy)->getNumElements())
+ return false;
}
+
+ // Otherwise, we speculate that these two types will line up and recursively
+ // check the subelements.
+ Entry = DstTy;
+ SpeculativeTypes.push_back(SrcTy);
+
+ for (unsigned i = 0, e = SrcTy->getNumContainedTypes(); i != e; ++i)
+ if (!areTypesIsomorphic(DstTy->getContainedType(i),
+ SrcTy->getContainedType(i)))
+ return false;
- MappedTypes[SrcTy] = DstTy;
- return false;
+ // If everything seems to have lined up, then everything is great.
+ return true;
}
/// linkDefinedTypeBodies - Produce a body for an opaque type in the dest
More information about the llvm-branch-commits
mailing list