From 4c00e53b81de81ecf4ba0c4e287ea230c79e82ae Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 15 May 2003 16:30:55 +0000 Subject: [PATCH] Fix Bug: Linker/2003-05-15-TypeProblem.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6225 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Linker/LinkModules.cpp | 88 +++++++++++++++++++++++++-------- lib/Transforms/Utils/Linker.cpp | 88 +++++++++++++++++++++++++-------- lib/VMCore/Linker.cpp | 88 +++++++++++++++++++++++++-------- 3 files changed, 201 insertions(+), 63 deletions(-) diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index c4d4fc64ce8..3fdbc7f03db 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -24,6 +24,28 @@ static inline bool Error(std::string *E, const std::string &Message) { return true; } +// 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) { + // 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); + } 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); + else + DestST->insert(Name, SrcTy); + } + return false; +} + // 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. @@ -36,36 +58,60 @@ static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) { SymbolTable::const_iterator PI = SrcST->find(Type::TypeTy); if (PI == SrcST->end()) return false; // No named types, do nothing. + // Some types cannot be resolved immediately becuse they depend on other types + // being resolved to each other first. This contains a list of types we are + // waiting to recheck. + std::vector DelayedTypesToResolve; + const SymbolTable::VarMap &VM = PI->second; for (SymbolTable::type_const_iterator I = VM.begin(), E = VM.end(); I != E; ++I) { const std::string &Name = I->first; - const Type *RHS = cast(I->second); + Type *RHS = cast(I->second); // Check to see if this type name is already in the dest module... - const Type *Entry = cast_or_null(DestST->lookup(Type::TypeTy, Name)); - if (Entry && !isa(Entry)) { // Yup, the value already exists... - if (Entry != RHS) { - if (OpaqueType *OT = dyn_cast(const_cast(RHS))) { - OT->refineAbstractTypeTo(Entry); - } else { - // If it's the same, noop. Otherwise, error. - return Error(Err, "Type named '" + Name + - "' of different shape in modules.\n Src='" + - Entry->getDescription() + "'.\n Dst='" + - RHS->getDescription() + "'"); - } - } - } else { // Type not in dest module. Add it now. - if (Entry) { - OpaqueType *OT = cast(const_cast(Entry)); - OT->refineAbstractTypeTo(RHS); - } + Type *Entry = cast_or_null(DestST->lookup(Type::TypeTy, Name)); - // TODO: FIXME WHEN TYPES AREN'T CONST - DestST->insert(Name, const_cast(RHS)); + if (ResolveTypes(Entry, RHS, DestST, Name)) { + // They look different, save the types 'till later to resolve. + DelayedTypesToResolve.push_back(Name); } } + + // Iteratively resolve types while we can... + while (!DelayedTypesToResolve.empty()) { + // Loop over all of the types, attempting to resolve them if possible... + unsigned OldSize = DelayedTypesToResolve.size(); + + for (unsigned i = 0; i != DelayedTypesToResolve.size(); ++i) { + const std::string &Name = DelayedTypesToResolve[i]; + Type *T1 = cast(VM.find(Name)->second); + Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + if (!ResolveTypes(T2, T1, DestST, Name)) { + // We are making progress! + DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); + --i; + } + } + + // Did we not eliminate any types? + 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 false; } diff --git a/lib/Transforms/Utils/Linker.cpp b/lib/Transforms/Utils/Linker.cpp index c4d4fc64ce8..3fdbc7f03db 100644 --- a/lib/Transforms/Utils/Linker.cpp +++ b/lib/Transforms/Utils/Linker.cpp @@ -24,6 +24,28 @@ static inline bool Error(std::string *E, const std::string &Message) { return true; } +// 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) { + // 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); + } 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); + else + DestST->insert(Name, SrcTy); + } + return false; +} + // 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. @@ -36,36 +58,60 @@ static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) { SymbolTable::const_iterator PI = SrcST->find(Type::TypeTy); if (PI == SrcST->end()) return false; // No named types, do nothing. + // Some types cannot be resolved immediately becuse they depend on other types + // being resolved to each other first. This contains a list of types we are + // waiting to recheck. + std::vector DelayedTypesToResolve; + const SymbolTable::VarMap &VM = PI->second; for (SymbolTable::type_const_iterator I = VM.begin(), E = VM.end(); I != E; ++I) { const std::string &Name = I->first; - const Type *RHS = cast(I->second); + Type *RHS = cast(I->second); // Check to see if this type name is already in the dest module... - const Type *Entry = cast_or_null(DestST->lookup(Type::TypeTy, Name)); - if (Entry && !isa(Entry)) { // Yup, the value already exists... - if (Entry != RHS) { - if (OpaqueType *OT = dyn_cast(const_cast(RHS))) { - OT->refineAbstractTypeTo(Entry); - } else { - // If it's the same, noop. Otherwise, error. - return Error(Err, "Type named '" + Name + - "' of different shape in modules.\n Src='" + - Entry->getDescription() + "'.\n Dst='" + - RHS->getDescription() + "'"); - } - } - } else { // Type not in dest module. Add it now. - if (Entry) { - OpaqueType *OT = cast(const_cast(Entry)); - OT->refineAbstractTypeTo(RHS); - } + Type *Entry = cast_or_null(DestST->lookup(Type::TypeTy, Name)); - // TODO: FIXME WHEN TYPES AREN'T CONST - DestST->insert(Name, const_cast(RHS)); + if (ResolveTypes(Entry, RHS, DestST, Name)) { + // They look different, save the types 'till later to resolve. + DelayedTypesToResolve.push_back(Name); } } + + // Iteratively resolve types while we can... + while (!DelayedTypesToResolve.empty()) { + // Loop over all of the types, attempting to resolve them if possible... + unsigned OldSize = DelayedTypesToResolve.size(); + + for (unsigned i = 0; i != DelayedTypesToResolve.size(); ++i) { + const std::string &Name = DelayedTypesToResolve[i]; + Type *T1 = cast(VM.find(Name)->second); + Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + if (!ResolveTypes(T2, T1, DestST, Name)) { + // We are making progress! + DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); + --i; + } + } + + // Did we not eliminate any types? + 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 false; } diff --git a/lib/VMCore/Linker.cpp b/lib/VMCore/Linker.cpp index c4d4fc64ce8..3fdbc7f03db 100644 --- a/lib/VMCore/Linker.cpp +++ b/lib/VMCore/Linker.cpp @@ -24,6 +24,28 @@ static inline bool Error(std::string *E, const std::string &Message) { return true; } +// 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) { + // 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); + } 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); + else + DestST->insert(Name, SrcTy); + } + return false; +} + // 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. @@ -36,36 +58,60 @@ static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) { SymbolTable::const_iterator PI = SrcST->find(Type::TypeTy); if (PI == SrcST->end()) return false; // No named types, do nothing. + // Some types cannot be resolved immediately becuse they depend on other types + // being resolved to each other first. This contains a list of types we are + // waiting to recheck. + std::vector DelayedTypesToResolve; + const SymbolTable::VarMap &VM = PI->second; for (SymbolTable::type_const_iterator I = VM.begin(), E = VM.end(); I != E; ++I) { const std::string &Name = I->first; - const Type *RHS = cast(I->second); + Type *RHS = cast(I->second); // Check to see if this type name is already in the dest module... - const Type *Entry = cast_or_null(DestST->lookup(Type::TypeTy, Name)); - if (Entry && !isa(Entry)) { // Yup, the value already exists... - if (Entry != RHS) { - if (OpaqueType *OT = dyn_cast(const_cast(RHS))) { - OT->refineAbstractTypeTo(Entry); - } else { - // If it's the same, noop. Otherwise, error. - return Error(Err, "Type named '" + Name + - "' of different shape in modules.\n Src='" + - Entry->getDescription() + "'.\n Dst='" + - RHS->getDescription() + "'"); - } - } - } else { // Type not in dest module. Add it now. - if (Entry) { - OpaqueType *OT = cast(const_cast(Entry)); - OT->refineAbstractTypeTo(RHS); - } + Type *Entry = cast_or_null(DestST->lookup(Type::TypeTy, Name)); - // TODO: FIXME WHEN TYPES AREN'T CONST - DestST->insert(Name, const_cast(RHS)); + if (ResolveTypes(Entry, RHS, DestST, Name)) { + // They look different, save the types 'till later to resolve. + DelayedTypesToResolve.push_back(Name); } } + + // Iteratively resolve types while we can... + while (!DelayedTypesToResolve.empty()) { + // Loop over all of the types, attempting to resolve them if possible... + unsigned OldSize = DelayedTypesToResolve.size(); + + for (unsigned i = 0; i != DelayedTypesToResolve.size(); ++i) { + const std::string &Name = DelayedTypesToResolve[i]; + Type *T1 = cast(VM.find(Name)->second); + Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + if (!ResolveTypes(T2, T1, DestST, Name)) { + // We are making progress! + DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); + --i; + } + } + + // Did we not eliminate any types? + 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 false; }