summaryrefslogtreecommitdiff
path: root/lib/VMCore
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-05-15 16:30:55 +0000
committerChris Lattner <sabre@nondot.org>2003-05-15 16:30:55 +0000
commit4c00e53b81de81ecf4ba0c4e287ea230c79e82ae (patch)
tree8ea9a931960e49e4aacdab5f935c69be18e29615 /lib/VMCore
parentf5838397cbfc783994d52472df6a797519bff6aa (diff)
downloadllvm-4c00e53b81de81ecf4ba0c4e287ea230c79e82ae.tar.gz
llvm-4c00e53b81de81ecf4ba0c4e287ea230c79e82ae.tar.bz2
llvm-4c00e53b81de81ecf4ba0c4e287ea230c79e82ae.tar.xz
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/VMCore')
-rw-r--r--lib/VMCore/Linker.cpp86
1 files changed, 66 insertions, 20 deletions
diff --git a/lib/VMCore/Linker.cpp b/lib/VMCore/Linker.cpp
index c4d4fc64ce..3fdbc7f03d 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<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;
}