diff options
| author | Chris Lattner <sabre@nondot.org> | 2003-05-15 16:30:55 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2003-05-15 16:30:55 +0000 | 
| commit | 4c00e53b81de81ecf4ba0c4e287ea230c79e82ae (patch) | |
| tree | 8ea9a931960e49e4aacdab5f935c69be18e29615 /lib/Transforms/Utils/Linker.cpp | |
| parent | f5838397cbfc783994d52472df6a797519bff6aa (diff) | |
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
Diffstat (limited to 'lib/Transforms/Utils/Linker.cpp')
| -rw-r--r-- | lib/Transforms/Utils/Linker.cpp | 86 | 
1 files changed, 66 insertions, 20 deletions
diff --git a/lib/Transforms/Utils/Linker.cpp b/lib/Transforms/Utils/Linker.cpp index c4d4fc64ce..3fdbc7f03d 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<OpaqueType>(DestTy)) {  // Yup, the type already exists... +    if (DestTy == SrcTy) return false;       // If already equal, noop +    if (OpaqueType *OT = dyn_cast<OpaqueType>(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<OpaqueType>(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<std::string> 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<Type>(I->second); +    Type *RHS = cast<Type>(I->second);      // Check to see if this type name is already in the dest module... -    const Type *Entry = cast_or_null<Type>(DestST->lookup(Type::TypeTy, Name)); -    if (Entry && !isa<OpaqueType>(Entry)) {  // Yup, the value already exists... -      if (Entry != RHS) { -        if (OpaqueType *OT = dyn_cast<OpaqueType>(const_cast<Type*>(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<OpaqueType>(const_cast<Type*>(Entry)); -        OT->refineAbstractTypeTo(RHS); +    Type *Entry = cast_or_null<Type>(DestST->lookup(Type::TypeTy, Name)); + +    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<Type>(VM.find(Name)->second); +      Type *T2 = cast<Type>(DestST->lookup(Type::TypeTy, Name)); +      if (!ResolveTypes(T2, T1, DestST, Name)) { +        // We are making progress! +        DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); +        --i;        } +    } -      // TODO: FIXME WHEN TYPES AREN'T CONST -      DestST->insert(Name, const_cast<Type*>(RHS)); +    // 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<Type>(VM.find(Name)->second); +        const Type *T2 = cast<Type>(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;  }  | 
