Add support for reading ConstantExpr nodes.
authorVikram S. Adve <vadve@cs.uiuc.edu>
Sun, 14 Jul 2002 23:04:18 +0000 (23:04 +0000)
committerVikram S. Adve <vadve@cs.uiuc.edu>
Sun, 14 Jul 2002 23:04:18 +0000 (23:04 +0000)
Add class ConstantFwdRefs to resolve forward references to constants
and to globals (unified old code for globals into this).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2895 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Bytecode/Reader/Reader.cpp

index f84ad565cad2fabe5ffab75a9d606350d19dda85..c03191c9d9c66ba8e2b44179f921910dcc9661b9 100644 (file)
@@ -218,42 +218,119 @@ bool BytecodeParser::ParseSymbolTable(const uchar *&Buf, const uchar *EndBuf,
   return false;
 }
 
-// DeclareNewGlobalValue - Patch up forward references to global values in the
-// form of ConstantPointerRef.
-//
-void BytecodeParser::DeclareNewGlobalValue(GlobalValue *GV, unsigned Slot) {
-  // Check to see if there is a forward reference to this global variable...
-  // if there is, eliminate it and patch the reference to use the new def'n.
-  GlobalRefsType::iterator I = GlobalRefs.find(make_pair(GV->getType(), Slot));
-
+Value*
+ConstantFwdRefs::find(const Type* Ty, unsigned Slot) {
+  GlobalRefsType::iterator I = GlobalRefs.find(make_pair(Ty, Slot));
   if (I != GlobalRefs.end()) {
-    GlobalVariable *OldGV = I->second;   // Get the placeholder...
-    BCR_TRACE(3, "Mutating CPPR Forward Ref!\n");
-      
-    // Loop over all of the uses of the GlobalValue.  The only thing they are
-    // allowed to be at this point is ConstantPointerRef's.
-    assert(OldGV->use_size() == 1 && "Only one reference should exist!");
-    while (!OldGV->use_empty()) {
-      User *U = OldGV->use_back();  // Must be a ConstantPointerRef...
-      ConstantPointerRef *CPPR = cast<ConstantPointerRef>(U);
-      assert(CPPR->getValue() == OldGV && "Something isn't happy");
-      
-      BCR_TRACE(4, "Mutating Forward Ref!\n");
+    return I->second;
+  } else {
+    return failure<Value*>(0);
+  }
+}
+
+void
+ConstantFwdRefs::insert(const Type* Ty, unsigned Slot, Value* V) {
+  // Keep track of the fact that we have a forward ref to recycle it
+  const pair<GlobalRefsType::iterator, bool>& result =
+    GlobalRefs.insert(make_pair(make_pair(Ty, Slot), V));
+  assert(result.second == true && "Entry already exists for this slot?");
+}
+
+void
+ConstantFwdRefs::erase(const Type* Ty, unsigned Slot) {
+  GlobalRefsType::iterator I = GlobalRefs.find(make_pair(Ty, Slot));
+  if (I != GlobalRefs.end())
+    GlobalRefs.erase(I);
+}
+
+// GetFwdRefToConstant - Get a forward reference to a constant value.
+//                       Create a unique one if it does not exist already.
+// 
+Constant*
+ConstantFwdRefs::GetFwdRefToConstant(const Type* Ty, unsigned Slot) {
+  
+  Constant* C = cast_or_null<Constant>(find(Ty, Slot));
+  
+  if (C) {
+    BCR_TRACE(5, "Previous forward ref found!\n");
+  } else {
+    // Create a placeholder for the constant reference and
+    // keep track of the fact that we have a forward ref to recycle it
+    BCR_TRACE(5, "Creating new forward ref to a constant!\n");
+    C = new ConstPHolder(Ty, Slot);
+    insert(Ty, Slot, C);
+  }
+  
+  return C;
+}
+
+
+// GetFwdRefToGlobal - Get a forward reference to a global value.
+//                     Create a unique one if it does not exist already.
+// 
+GlobalValue*
+ConstantFwdRefs::GetFwdRefToGlobal(const PointerType* PT, unsigned Slot) {
+  
+  GlobalValue* GV = cast_or_null<GlobalValue>(find(PT, Slot));
+
+  if (GV) {
+    BCR_TRACE(5, "Previous forward ref found!\n");
+  } else {
+    BCR_TRACE(5, "Creating new forward ref to a global variable!\n");
+
+         // Create a placeholder for the global variable reference...
+    GlobalVariable *GVar =
+      new GlobalVariable(PT->getElementType(), false, true);
+
+         // Keep track of the fact that we have a forward ref to recycle it
+    insert(PT, Slot, GVar);
+  
+    // Must temporarily push this value into the module table...
+    TheModule->getGlobalList().push_back(GVar);
+    GV = GVar;
+  }
+
+  return GV;
+}
+
+void
+ConstantFwdRefs::ResolveRefsToValue(Value* NewV, unsigned Slot) {
+  if (Value* vph = find(NewV->getType(), Slot)) {
+    BCR_TRACE(3, "Mutating forward refs!\n");
+
+    // Loop over all of the uses of the Value.  What they are depends
+    // on what NewV is.  Replacing a use of the old reference takes the
+    // use off the use list, so loop with !use_empty(), not the use_iterator.
+    while (!vph->use_empty()) {
+      Constant *C = cast<Constant>(vph->use_back());
+      unsigned numReplaced = C->mutateReferences(vph, NewV);
+      assert(numReplaced > 0 && "Supposed user wasn't really a user?");
       
-      // Change the const pool reference to point to the real global variable
-      // now.  This should drop a use from the OldGV.
-      CPPR->mutateReference(GV);
+      if (GlobalValue* GVal = dyn_cast<GlobalValue>(NewV)) {
+        // Remove the placeholder GlobalValue from the module...
+        GVal->getParent()->getGlobalList().remove(cast<GlobalVariable>(vph));
+      }
     }
-    
-    // Remove GV from the module...
-    GV->getParent()->getGlobalList().remove(OldGV);
-    delete OldGV;                        // Delete the old placeholder
-    
-    // Remove the map entry for the global now that it has been created...
-    GlobalRefs.erase(I);
+
+    delete vph;                         // Delete the old placeholder
+    erase(NewV->getType(), Slot);       // Remove the map entry for it
   }
 }
 
+// resolveRefsToGlobal - Patch up forward references to global values in the
+// form of ConstantPointerRef.
+//
+void BytecodeParser::resolveRefsToGlobal(GlobalValue *GV, unsigned Slot) {
+  fwdRefs.ResolveRefsToValue(GV, Slot);
+}
+
+// resolveRefsToConstant - Patch up forward references to constants
+//
+void BytecodeParser::resolveRefsToConstant(Constant *C, unsigned Slot) {
+  fwdRefs.ResolveRefsToValue(C, Slot);
+}
+
+
 bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf, 
                                 Module *C) {
   // Clear out the local values table...
@@ -369,7 +446,7 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
   if (M->isExternal())
     M->getArgumentList().clear();
 
-  DeclareNewGlobalValue(M, MethSlot);
+  resolveRefsToGlobal(M, MethSlot);
 
   return false;
 }
@@ -417,7 +494,7 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
 
     Mod->getGlobalList().push_back(GV);
 
-    DeclareNewGlobalValue(GV, unsigned(DestSlot));
+    resolveRefsToGlobal(GV, unsigned(DestSlot));
 
     BCR_TRACE(2, "Global Variable of type: " << PTy->getDescription() 
              << " into slot #" << DestSlot << "\n");
@@ -492,6 +569,8 @@ bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf,
   BCR_TRACE(1, "FirstDerivedTyID = " << FirstDerivedTyID << "\n");
 
   TheModule = C = new Module();
+  fwdRefs.VisitingModule(TheModule);
+
   while (Buf < EndBuf) {
     const uchar *OldBuf = Buf;
     if (readBlock(Buf, EndBuf, Type, Size)) { delete C; return failure(true); }