Add support for reading ConstantExpr nodes.
authorVikram S. Adve <vadve@cs.uiuc.edu>
Sun, 14 Jul 2002 23:05:09 +0000 (23:05 +0000)
committerVikram S. Adve <vadve@cs.uiuc.edu>
Sun, 14 Jul 2002 23:05:09 +0000 (23:05 +0000)
Add class ConstantFwdRefs to resolve forward references to constants
and to globals. (Hmm... this class could be renamed I guess.)

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

lib/Bytecode/Reader/ConstantReader.cpp
lib/Bytecode/Reader/ReaderInternals.h

index 7e00cd234317c0be050adb15e993d756a1d0de9c..2fa392e5db55f19d58454e459c9ee30dacfd8e99 100644 (file)
@@ -179,6 +179,54 @@ bool BytecodeParser::parseTypeConstants(const uchar *&Buf, const uchar *EndBuf,
 
 bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
                                         const Type *Ty, Constant *&V) {
+
+  // We must check for a ConstantExpr before switching by type because
+  // a ConstantExpr can be of any type, and has no explicit value.
+  // 
+  unsigned isExprNumArgs;               // 0 if not expr; numArgs if is expr
+  if (read_vbr(Buf, EndBuf, isExprNumArgs)) return failure(true);
+  if (isExprNumArgs) {
+    unsigned opCode;
+    vector<Constant*> argVec;
+    argVec.reserve(isExprNumArgs);
+    
+    if (read_vbr(Buf, EndBuf, opCode)) return failure(true);
+    
+    // Read the slot number and types of each of the arguments
+    for (unsigned i=0; i < isExprNumArgs; ++i) {
+      unsigned argValSlot, argTypeSlot;
+      if (read_vbr(Buf, EndBuf, argValSlot)) return failure(true);
+      if (read_vbr(Buf, EndBuf, argTypeSlot)) return failure(true);
+      const Type *argTy = getType(argTypeSlot);
+      if (argTy == 0) return failure(true);
+      
+      BCR_TRACE(4, "CE Arg " << i << ": Type: '" << argTy << "'  slot: " << argValSlot << "\n");
+      
+      // Get the arg value from its slot if it exists, otherwise a placeholder
+      Value *Val = getValue(argTy, argValSlot, false);
+      Constant* C;
+      if (Val) {
+        if (!(C = dyn_cast<Constant>(Val))) return failure(true);
+        BCR_TRACE(5, "Constant Found in ValueTable!\n");
+      } else {         // Nope... find or create a forward ref. for it
+        C = fwdRefs.GetFwdRefToConstant(argTy, argValSlot);
+      }
+      argVec.push_back(C);
+    }
+    
+    // Construct a ConstantExpr of the appropriate kind
+    if (isExprNumArgs == 1) {           // All one-operand expressions
+      V = ConstantExpr::get(opCode, argVec[0], Ty);
+    } else if (opCode == Instruction::GetElementPtr) { // GetElementPtr
+      vector<Value*> IdxList(argVec.begin()+1, argVec.end());
+      V = ConstantExpr::get(opCode, argVec[0], IdxList, Ty);
+    } else {                            // All other 2-operand expressions
+      V = ConstantExpr::get(opCode, argVec[0], argVec[1], Ty);
+    }
+    return false;
+  }
+  
+  // Ok, not an ConstantExpr.  We now know how to read the given type...
   switch (Ty->getPrimitiveID()) {
   case Type::BoolTyID: {
     unsigned Val;
@@ -286,38 +334,21 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
     case 1: {  // ConstantPointerRef value...
       unsigned Slot;
       if (read_vbr(Buf, EndBuf, Slot)) return failure(true);
-      BCR_TRACE(4, "CPPR: Type: '" << Ty << "'  slot: " << Slot << "\n");
+      BCR_TRACE(4, "CPR: Type: '" << Ty << "'  slot: " << Slot << "\n");
 
       // Check to see if we have already read this global variable yet...
       Value *Val = getValue(PT, Slot, false);
-      GlobalValue *GV;
+      GlobalValueGV;
       if (Val) {
-       if (!(GV = dyn_cast<GlobalValue>(Val))) return failure(true);
-       BCR_TRACE(5, "Value Found in ValueTable!\n");
-      } else {         // Nope... see if we have previously forward ref'd it
-       GlobalRefsType::iterator I = GlobalRefs.find(make_pair(PT, Slot));
-       if (I != GlobalRefs.end()) {
-         BCR_TRACE(5, "Previous forward ref found!\n");
-         GV = I->second;
-       } else {
-         BCR_TRACE(5, "Creating new forward ref 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
-         GlobalRefs.insert(make_pair(make_pair(PT, Slot), GVar));
-
-         // Must temporarily push this value into the module table...
-         TheModule->getGlobalList().push_back(GVar);
-         GV = GVar;
-       }
+        if (!(GV = dyn_cast<GlobalValue>(Val))) return failure(true);
+        BCR_TRACE(5, "Value Found in ValueTable!\n");
+      } else {         // Nope... find or create a forward ref. for it
+        GV = fwdRefs.GetFwdRefToGlobal(PT, Slot);
       }
-      
       V = ConstantPointerRef::get(GV);
       break;
     }
+    
     default:
       BCR_TRACE(5, "UNKNOWN Pointer Constant Type!\n");
       return failure(true);
@@ -352,9 +383,12 @@ bool BytecodeParser::ParseConstantPool(const uchar *&Buf, const uchar *EndBuf,
     } else {
       for (unsigned i = 0; i < NumEntries; ++i) {
        Constant *I;
+        int Slot;
        if (parseConstantValue(Buf, EndBuf, Ty, I)) return failure(true);
+        assert(I && "parseConstantValue returned `!failure' and NULL result");
        BCR_TRACE(4, "Read Constant: '" << I << "'\n");
-       if (insertValue(I, Tab) == -1) return failure(true);
+       if ((Slot = insertValue(I, Tab)) < 0) return failure(true);
+        resolveRefsToConstant(I, (unsigned) Slot);
       }
     }
   }
index f98db725bc7946fd6741a7b8639f86b5b5d5a28f..4b1974e01963b4270a33a7724f0975e6b128d2fc 100644 (file)
@@ -12,6 +12,8 @@
 #include "llvm/BasicBlock.h"
 #include "llvm/Instruction.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/Constant.h"
+#include "Support/NonCopyable.h"
 #include <map>
 #include <utility>
 #include <list>
@@ -39,6 +41,36 @@ struct RawInst {       // The raw fields out of the bytecode stream...
   };
 };
 
+
+class ConstantFwdRefs: public NonCopyable {
+  Module* TheModule;
+  
+  // GlobalRefs - This maintains a mapping between <Type, Slot #>'s and forward
+  // references to global values or constants.  Such values may be referenced
+  // before they are defined, and if so, the temporary object that they
+  // represent is held here.
+  //
+  typedef std::map<std::pair<const Type *, unsigned>,
+                   Value*>  GlobalRefsType;
+  GlobalRefsType GlobalRefs;
+
+  Value*       find                   (const Type* Ty, unsigned Slot);
+  void         insert                 (const Type* Ty, unsigned Slot, Value* V);
+  void         erase                  (const Type* Ty, unsigned Slot);
+
+public:
+  // sets the current module pointer: needed to insert placeholder globals
+  void         VisitingModule         (Module* M) { TheModule = M; }
+  
+  // get a forward reference to a global or a constant
+  GlobalValue* GetFwdRefToGlobal      (const PointerType* PT, unsigned Slot);
+  Constant*    GetFwdRefToConstant    (const Type* Ty,        unsigned Slot);
+
+  // resolve all references to the placeholder (if any) for the given value
+  void         ResolveRefsToValue     (Value* val, unsigned Slot);
+};
+
+
 class BytecodeParser : public AbstractTypeUser {
   std::string Error;     // Error message string goes here...
 public:
@@ -63,14 +95,8 @@ private:          // All of this data is transient across calls to ParseBytecode
   ValueTable Values, LateResolveValues;
   ValueTable ModuleValues, LateResolveModuleValues;
 
-  // GlobalRefs - This maintains a mapping between <Type, Slot #>'s and forward
-  // references to global values.  Global values may be referenced before they
-  // are defined, and if so, the temporary object that they represent is held
-  // here.
-  //
-  typedef std::map<std::pair<const PointerType *, unsigned>,
-                   GlobalVariable*>  GlobalRefsType;
-  GlobalRefsType GlobalRefs;
+  // fwdRefs - This manages forward references to global values.
+  ConstantFwdRefs fwdRefs;
 
   // TypesLoaded - This vector mirrors the Values[TypeTyID] plane.  It is used
   // to deal with forward references to types.
@@ -114,11 +140,12 @@ private:
 
   bool getTypeSlot(const Type *Ty, unsigned &Slot);
 
-  // DeclareNewGlobalValue - Patch up forward references to global values in the
-  // form of ConstantPointerRefs.
-  //
-  void DeclareNewGlobalValue(GlobalValue *GV, unsigned Slot);
-
+  // resolveRefsToGlobal   -- resolve forward references to a global
+  // resolveRefsToConstant -- resolve forward references to a constant
+  // 
+  void resolveRefsToGlobal(GlobalValue* GV, unsigned Slot);
+  void resolveRefsToConstant(Constant* C, unsigned Slot);
+  
   // refineAbstractType - The callback method is invoked when one of the
   // elements of TypeValues becomes more concrete...
   //
@@ -128,6 +155,7 @@ private:
 template<class SuperType>
 class PlaceholderDef : public SuperType {
   unsigned ID;
+  PlaceholderDef();                     // do not implement
 public:
   PlaceholderDef(const Type *Ty, unsigned id) : SuperType(Ty), ID(id) {}
   unsigned getID() { return ID; }
@@ -152,11 +180,23 @@ struct MethPlaceHolderHelper : public Function {
   }
 };
 
+struct ConstantPlaceHolderHelper : public Constant {
+  ConstantPlaceHolderHelper(const Type *Ty)
+    : Constant(Ty) {}
+  virtual bool isNullValue() const { return false; }
+};
+
 typedef PlaceholderDef<InstPlaceHolderHelper>  DefPHolder;
 typedef PlaceholderDef<BBPlaceHolderHelper>    BBPHolder;
 typedef PlaceholderDef<MethPlaceHolderHelper>  MethPHolder;
+typedef PlaceholderDef<ConstantPlaceHolderHelper>  ConstPHolder;
+
 
 static inline unsigned getValueIDNumberFromPlaceHolder(Value *Def) {
+  if (isa<Constant>(Def))
+    return ((ConstPHolder*)Def)->getID();
+  
+  // else discriminate by type
   switch (Def->getType()->getPrimitiveID()) {
   case Type::LabelTyID:    return ((BBPHolder*)Def)->getID();
   case Type::FunctionTyID: return ((MethPHolder*)Def)->getID();