From e76c57ad467ed57f09f2a3ef51628d4b6eb2b304 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 22 Aug 2003 06:07:12 +0000 Subject: [PATCH] Implement Linker/2003-08-20-OpaqueTypeResolve.ll Hopefully this will fix the 176.gcc spec test as well. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8051 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Linker/LinkModules.cpp | 111 +++++++++++++++++++++++++++----- lib/Transforms/Utils/Linker.cpp | 111 +++++++++++++++++++++++++++----- lib/VMCore/Linker.cpp | 111 +++++++++++++++++++++++++++----- 3 files changed, 285 insertions(+), 48 deletions(-) diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 3fdbc7f03db..a38d2c00229 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -27,25 +27,82 @@ static inline bool Error(std::string *E, const std::string &Message) { // ResolveTypes - Attempt to link the two specified types together. Return true // if there is an error and they cannot yet be linked. // -static bool ResolveTypes(Type *DestTy, Type *SrcTy, SymbolTable *DestST, - const std::string &Name) { +static bool ResolveTypes(const Type *DestTy, const Type *SrcTy, + SymbolTable *DestST, const std::string &Name) { + if (DestTy == SrcTy) return false; // If already equal, noop + // Does the type already exist in the module? if (DestTy && !isa(DestTy)) { // Yup, the type already exists... - if (DestTy == SrcTy) return false; // If already equal, noop - if (OpaqueType *OT = dyn_cast(SrcTy)) { - OT->refineAbstractTypeTo(DestTy); + if (const OpaqueType *OT = dyn_cast(SrcTy)) { + const_cast(OT)->refineAbstractTypeTo(DestTy); } else { return true; // Cannot link types... neither is opaque and not-equal } } else { // Type not in dest module. Add it now. if (DestTy) // Type _is_ in module, just opaque... - cast(DestTy)->refineAbstractTypeTo(SrcTy); + const_cast(cast(DestTy)) + ->refineAbstractTypeTo(SrcTy); else - DestST->insert(Name, SrcTy); + DestST->insert(Name, const_cast(SrcTy)); } return false; } + +// RecursiveResolveTypes - This is just like ResolveTypes, except that it +// recurses down into derived types, merging the used types if the parent types +// are compatible. +// +static bool RecursiveResolveTypes(const Type *DestTy, const Type *SrcTy, + SymbolTable *DestST, const std::string &Name){ + if (DestTy == SrcTy) return false; // If already equal, noop + + // If we found our opaque type, resolve it now! + if (isa(DestTy) || isa(SrcTy)) + return ResolveTypes(DestTy, SrcTy, DestST, Name); + + // Two types cannot be resolved together if they are of different primitive + // type. For example, we cannot resolve an int to a float. + if (DestTy->getPrimitiveID() != SrcTy->getPrimitiveID()) return true; + + // Otherwise, resolve the used type used by this derived type... + switch (DestTy->getPrimitiveID()) { + case Type::FunctionTyID: { + const FunctionType *DFT = cast(DestTy); + const FunctionType *SFT = cast(SrcTy); + if (DFT->isVarArg() != SFT->isVarArg()) return true; + for (unsigned i = 0, e = DFT->getNumContainedTypes(); i != e; ++i) + if (RecursiveResolveTypes(DFT->getContainedType(i), + SFT->getContainedType(i), DestST, Name)) + return true; + return false; + } + case Type::StructTyID: { + const StructType *DST = cast(DestTy); + const StructType *SST = cast(SrcTy); + if (DST->getNumContainedTypes() != SST->getNumContainedTypes()) return 1; + for (unsigned i = 0, e = DST->getNumContainedTypes(); i != e; ++i) + if (RecursiveResolveTypes(DST->getContainedType(i), + SST->getContainedType(i), DestST, Name)) + return true; + return false; + } + case Type::ArrayTyID: { + const ArrayType *DAT = cast(DestTy); + const ArrayType *SAT = cast(SrcTy); + if (DAT->getNumElements() != SAT->getNumElements()) return true; + return RecursiveResolveTypes(DAT->getElementType(), SAT->getElementType(), + DestST, Name); + } + case Type::PointerTyID: + return RecursiveResolveTypes(cast(DestTy)->getElementType(), + cast(SrcTy)->getElementType(), + DestST, Name); + default: assert(0 && "Unexpected type!"); return true; + } +} + + // LinkTypes - Go through the symbol table of the Src module and see if any // types are named in the src module that are not named in the Dst module. // Make sure there are no type name conflicts. @@ -83,6 +140,7 @@ static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) { // Loop over all of the types, attempting to resolve them if possible... unsigned OldSize = DelayedTypesToResolve.size(); + // Try direct resolution by name... for (unsigned i = 0; i != DelayedTypesToResolve.size(); ++i) { const std::string &Name = DelayedTypesToResolve[i]; Type *T1 = cast(VM.find(Name)->second); @@ -96,18 +154,39 @@ static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) { // Did we not eliminate any types? if (DelayedTypesToResolve.size() == OldSize) { - // Build up an error message of all of the mismatched types. - std::string ErrorMessage; + // Attempt to resolve subelements of types. This allows us to merge these + // two types: { int* } and { opaque* } for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) { const std::string &Name = DelayedTypesToResolve[i]; - const Type *T1 = cast(VM.find(Name)->second); - const Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); - ErrorMessage += " Type named '" + Name + - "' conflicts.\n Src='" + T1->getDescription() + - "'.\n Dest='" + T2->getDescription() + "'\n"; + Type *T1 = cast(VM.find(Name)->second); + Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + + if (!RecursiveResolveTypes(T2, T1, DestST, Name)) { + // We are making progress! + DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); + + // Go back to the main loop, perhaps we can resolve directly by name + // now... + break; + } + } + + // If we STILL cannot resolve the types, then there is something wrong. + // Report the error. + if (DelayedTypesToResolve.size() == OldSize) { + // Build up an error message of all of the mismatched types. + std::string ErrorMessage; + for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) { + const std::string &Name = DelayedTypesToResolve[i]; + const Type *T1 = cast(VM.find(Name)->second); + const Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + ErrorMessage += " Type named '" + Name + + "' conflicts.\n Src='" + T1->getDescription() + + "'.\n Dest='" + T2->getDescription() + "'\n"; + } + return Error(Err, "Type conflict between types in modules:\n" + + ErrorMessage); } - return Error(Err, "Type conflict between types in modules:\n" + - ErrorMessage); } } diff --git a/lib/Transforms/Utils/Linker.cpp b/lib/Transforms/Utils/Linker.cpp index 3fdbc7f03db..a38d2c00229 100644 --- a/lib/Transforms/Utils/Linker.cpp +++ b/lib/Transforms/Utils/Linker.cpp @@ -27,25 +27,82 @@ static inline bool Error(std::string *E, const std::string &Message) { // ResolveTypes - Attempt to link the two specified types together. Return true // if there is an error and they cannot yet be linked. // -static bool ResolveTypes(Type *DestTy, Type *SrcTy, SymbolTable *DestST, - const std::string &Name) { +static bool ResolveTypes(const Type *DestTy, const Type *SrcTy, + SymbolTable *DestST, const std::string &Name) { + if (DestTy == SrcTy) return false; // If already equal, noop + // Does the type already exist in the module? if (DestTy && !isa(DestTy)) { // Yup, the type already exists... - if (DestTy == SrcTy) return false; // If already equal, noop - if (OpaqueType *OT = dyn_cast(SrcTy)) { - OT->refineAbstractTypeTo(DestTy); + if (const OpaqueType *OT = dyn_cast(SrcTy)) { + const_cast(OT)->refineAbstractTypeTo(DestTy); } else { return true; // Cannot link types... neither is opaque and not-equal } } else { // Type not in dest module. Add it now. if (DestTy) // Type _is_ in module, just opaque... - cast(DestTy)->refineAbstractTypeTo(SrcTy); + const_cast(cast(DestTy)) + ->refineAbstractTypeTo(SrcTy); else - DestST->insert(Name, SrcTy); + DestST->insert(Name, const_cast(SrcTy)); } return false; } + +// RecursiveResolveTypes - This is just like ResolveTypes, except that it +// recurses down into derived types, merging the used types if the parent types +// are compatible. +// +static bool RecursiveResolveTypes(const Type *DestTy, const Type *SrcTy, + SymbolTable *DestST, const std::string &Name){ + if (DestTy == SrcTy) return false; // If already equal, noop + + // If we found our opaque type, resolve it now! + if (isa(DestTy) || isa(SrcTy)) + return ResolveTypes(DestTy, SrcTy, DestST, Name); + + // Two types cannot be resolved together if they are of different primitive + // type. For example, we cannot resolve an int to a float. + if (DestTy->getPrimitiveID() != SrcTy->getPrimitiveID()) return true; + + // Otherwise, resolve the used type used by this derived type... + switch (DestTy->getPrimitiveID()) { + case Type::FunctionTyID: { + const FunctionType *DFT = cast(DestTy); + const FunctionType *SFT = cast(SrcTy); + if (DFT->isVarArg() != SFT->isVarArg()) return true; + for (unsigned i = 0, e = DFT->getNumContainedTypes(); i != e; ++i) + if (RecursiveResolveTypes(DFT->getContainedType(i), + SFT->getContainedType(i), DestST, Name)) + return true; + return false; + } + case Type::StructTyID: { + const StructType *DST = cast(DestTy); + const StructType *SST = cast(SrcTy); + if (DST->getNumContainedTypes() != SST->getNumContainedTypes()) return 1; + for (unsigned i = 0, e = DST->getNumContainedTypes(); i != e; ++i) + if (RecursiveResolveTypes(DST->getContainedType(i), + SST->getContainedType(i), DestST, Name)) + return true; + return false; + } + case Type::ArrayTyID: { + const ArrayType *DAT = cast(DestTy); + const ArrayType *SAT = cast(SrcTy); + if (DAT->getNumElements() != SAT->getNumElements()) return true; + return RecursiveResolveTypes(DAT->getElementType(), SAT->getElementType(), + DestST, Name); + } + case Type::PointerTyID: + return RecursiveResolveTypes(cast(DestTy)->getElementType(), + cast(SrcTy)->getElementType(), + DestST, Name); + default: assert(0 && "Unexpected type!"); return true; + } +} + + // LinkTypes - Go through the symbol table of the Src module and see if any // types are named in the src module that are not named in the Dst module. // Make sure there are no type name conflicts. @@ -83,6 +140,7 @@ static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) { // Loop over all of the types, attempting to resolve them if possible... unsigned OldSize = DelayedTypesToResolve.size(); + // Try direct resolution by name... for (unsigned i = 0; i != DelayedTypesToResolve.size(); ++i) { const std::string &Name = DelayedTypesToResolve[i]; Type *T1 = cast(VM.find(Name)->second); @@ -96,18 +154,39 @@ static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) { // Did we not eliminate any types? if (DelayedTypesToResolve.size() == OldSize) { - // Build up an error message of all of the mismatched types. - std::string ErrorMessage; + // Attempt to resolve subelements of types. This allows us to merge these + // two types: { int* } and { opaque* } for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) { const std::string &Name = DelayedTypesToResolve[i]; - const Type *T1 = cast(VM.find(Name)->second); - const Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); - ErrorMessage += " Type named '" + Name + - "' conflicts.\n Src='" + T1->getDescription() + - "'.\n Dest='" + T2->getDescription() + "'\n"; + Type *T1 = cast(VM.find(Name)->second); + Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + + if (!RecursiveResolveTypes(T2, T1, DestST, Name)) { + // We are making progress! + DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); + + // Go back to the main loop, perhaps we can resolve directly by name + // now... + break; + } + } + + // If we STILL cannot resolve the types, then there is something wrong. + // Report the error. + if (DelayedTypesToResolve.size() == OldSize) { + // Build up an error message of all of the mismatched types. + std::string ErrorMessage; + for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) { + const std::string &Name = DelayedTypesToResolve[i]; + const Type *T1 = cast(VM.find(Name)->second); + const Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + ErrorMessage += " Type named '" + Name + + "' conflicts.\n Src='" + T1->getDescription() + + "'.\n Dest='" + T2->getDescription() + "'\n"; + } + return Error(Err, "Type conflict between types in modules:\n" + + ErrorMessage); } - return Error(Err, "Type conflict between types in modules:\n" + - ErrorMessage); } } diff --git a/lib/VMCore/Linker.cpp b/lib/VMCore/Linker.cpp index 3fdbc7f03db..a38d2c00229 100644 --- a/lib/VMCore/Linker.cpp +++ b/lib/VMCore/Linker.cpp @@ -27,25 +27,82 @@ static inline bool Error(std::string *E, const std::string &Message) { // ResolveTypes - Attempt to link the two specified types together. Return true // if there is an error and they cannot yet be linked. // -static bool ResolveTypes(Type *DestTy, Type *SrcTy, SymbolTable *DestST, - const std::string &Name) { +static bool ResolveTypes(const Type *DestTy, const Type *SrcTy, + SymbolTable *DestST, const std::string &Name) { + if (DestTy == SrcTy) return false; // If already equal, noop + // Does the type already exist in the module? if (DestTy && !isa(DestTy)) { // Yup, the type already exists... - if (DestTy == SrcTy) return false; // If already equal, noop - if (OpaqueType *OT = dyn_cast(SrcTy)) { - OT->refineAbstractTypeTo(DestTy); + if (const OpaqueType *OT = dyn_cast(SrcTy)) { + const_cast(OT)->refineAbstractTypeTo(DestTy); } else { return true; // Cannot link types... neither is opaque and not-equal } } else { // Type not in dest module. Add it now. if (DestTy) // Type _is_ in module, just opaque... - cast(DestTy)->refineAbstractTypeTo(SrcTy); + const_cast(cast(DestTy)) + ->refineAbstractTypeTo(SrcTy); else - DestST->insert(Name, SrcTy); + DestST->insert(Name, const_cast(SrcTy)); } return false; } + +// RecursiveResolveTypes - This is just like ResolveTypes, except that it +// recurses down into derived types, merging the used types if the parent types +// are compatible. +// +static bool RecursiveResolveTypes(const Type *DestTy, const Type *SrcTy, + SymbolTable *DestST, const std::string &Name){ + if (DestTy == SrcTy) return false; // If already equal, noop + + // If we found our opaque type, resolve it now! + if (isa(DestTy) || isa(SrcTy)) + return ResolveTypes(DestTy, SrcTy, DestST, Name); + + // Two types cannot be resolved together if they are of different primitive + // type. For example, we cannot resolve an int to a float. + if (DestTy->getPrimitiveID() != SrcTy->getPrimitiveID()) return true; + + // Otherwise, resolve the used type used by this derived type... + switch (DestTy->getPrimitiveID()) { + case Type::FunctionTyID: { + const FunctionType *DFT = cast(DestTy); + const FunctionType *SFT = cast(SrcTy); + if (DFT->isVarArg() != SFT->isVarArg()) return true; + for (unsigned i = 0, e = DFT->getNumContainedTypes(); i != e; ++i) + if (RecursiveResolveTypes(DFT->getContainedType(i), + SFT->getContainedType(i), DestST, Name)) + return true; + return false; + } + case Type::StructTyID: { + const StructType *DST = cast(DestTy); + const StructType *SST = cast(SrcTy); + if (DST->getNumContainedTypes() != SST->getNumContainedTypes()) return 1; + for (unsigned i = 0, e = DST->getNumContainedTypes(); i != e; ++i) + if (RecursiveResolveTypes(DST->getContainedType(i), + SST->getContainedType(i), DestST, Name)) + return true; + return false; + } + case Type::ArrayTyID: { + const ArrayType *DAT = cast(DestTy); + const ArrayType *SAT = cast(SrcTy); + if (DAT->getNumElements() != SAT->getNumElements()) return true; + return RecursiveResolveTypes(DAT->getElementType(), SAT->getElementType(), + DestST, Name); + } + case Type::PointerTyID: + return RecursiveResolveTypes(cast(DestTy)->getElementType(), + cast(SrcTy)->getElementType(), + DestST, Name); + default: assert(0 && "Unexpected type!"); return true; + } +} + + // LinkTypes - Go through the symbol table of the Src module and see if any // types are named in the src module that are not named in the Dst module. // Make sure there are no type name conflicts. @@ -83,6 +140,7 @@ static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) { // Loop over all of the types, attempting to resolve them if possible... unsigned OldSize = DelayedTypesToResolve.size(); + // Try direct resolution by name... for (unsigned i = 0; i != DelayedTypesToResolve.size(); ++i) { const std::string &Name = DelayedTypesToResolve[i]; Type *T1 = cast(VM.find(Name)->second); @@ -96,18 +154,39 @@ static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) { // Did we not eliminate any types? if (DelayedTypesToResolve.size() == OldSize) { - // Build up an error message of all of the mismatched types. - std::string ErrorMessage; + // Attempt to resolve subelements of types. This allows us to merge these + // two types: { int* } and { opaque* } for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) { const std::string &Name = DelayedTypesToResolve[i]; - const Type *T1 = cast(VM.find(Name)->second); - const Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); - ErrorMessage += " Type named '" + Name + - "' conflicts.\n Src='" + T1->getDescription() + - "'.\n Dest='" + T2->getDescription() + "'\n"; + Type *T1 = cast(VM.find(Name)->second); + Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + + if (!RecursiveResolveTypes(T2, T1, DestST, Name)) { + // We are making progress! + DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); + + // Go back to the main loop, perhaps we can resolve directly by name + // now... + break; + } + } + + // If we STILL cannot resolve the types, then there is something wrong. + // Report the error. + if (DelayedTypesToResolve.size() == OldSize) { + // Build up an error message of all of the mismatched types. + std::string ErrorMessage; + for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) { + const std::string &Name = DelayedTypesToResolve[i]; + const Type *T1 = cast(VM.find(Name)->second); + const Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + ErrorMessage += " Type named '" + Name + + "' conflicts.\n Src='" + T1->getDescription() + + "'.\n Dest='" + T2->getDescription() + "'\n"; + } + return Error(Err, "Type conflict between types in modules:\n" + + ErrorMessage); } - return Error(Err, "Type conflict between types in modules:\n" + - ErrorMessage); } } -- 2.34.1