[llvm-commits] CVS: llvm/lib/Bitcode/Reader/BitcodeReader.cpp BitcodeReader.h

Chris Lattner sabre at nondot.org
Tue May 1 00:02:15 PDT 2007



Changes in directory llvm/lib/Bitcode/Reader:

BitcodeReader.cpp updated: 1.20 -> 1.21
BitcodeReader.h updated: 1.14 -> 1.15
---
Log message:

handle function-level forward references, read binops.


---
Diffs of the changes:  (+147 -22)

 BitcodeReader.cpp |  150 ++++++++++++++++++++++++++++++++++++++++++++++--------
 BitcodeReader.h   |   19 ++++++
 2 files changed, 147 insertions(+), 22 deletions(-)


Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp
diff -u llvm/lib/Bitcode/Reader/BitcodeReader.cpp:1.20 llvm/lib/Bitcode/Reader/BitcodeReader.cpp:1.21
--- llvm/lib/Bitcode/Reader/BitcodeReader.cpp:1.20	Tue May  1 00:52:21 2007
+++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp	Tue May  1 02:01:57 2007
@@ -15,6 +15,7 @@
 #include "BitcodeReader.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/Instructions.h"
 #include "llvm/Module.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/MathExtras.h"
@@ -125,10 +126,9 @@
     NumOperands = Idx+1;
   }
 
-  if (Uses[Idx]) {
-    assert(Ty == getOperand(Idx)->getType() &&
-           "Type mismatch in constant table!");
-    return cast<Constant>(getOperand(Idx));
+  if (Value *V = Uses[Idx]) {
+    assert(Ty == V->getType() && "Type mismatch in constant table!");
+    return cast<Constant>(V);
   }
 
   // Create and return a placeholder, which will later be RAUW'd.
@@ -137,6 +137,25 @@
   return C;
 }
 
+Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) {
+  if (Idx >= size()) {
+    // Insert a bunch of null values.
+    Uses.resize(Idx+1);
+    OperandList = &Uses[0];
+    NumOperands = Idx+1;
+  }
+  
+  if (Value *V = Uses[Idx]) {
+    assert((Ty == 0 || Ty == V->getType()) && "Type mismatch in value table!");
+    return V;
+  }
+  
+  // Create and return a placeholder, which will later be RAUW'd.
+  Value *V = new Argument(Ty);
+  Uses[Idx].init(V, this);
+  return V;
+}
+
 
 const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) {
   // If the TypeID is in range, return it.
@@ -151,7 +170,6 @@
   return TypeList.back().get();
 }
 
-
 bool BitcodeReader::ParseTypeTable() {
   if (Stream.EnterSubBlock())
     return Error("Malformed block record");
@@ -643,18 +661,7 @@
     }
     }
     
-    if (NextCstNo == ValueList.size())
-      ValueList.push_back(V);
-    else if (ValueList[NextCstNo] == 0)
-      ValueList.initVal(NextCstNo, V);
-    else {
-      // If there was a forward reference to this constant, 
-      Value *OldV = ValueList[NextCstNo];
-      ValueList.setOperand(NextCstNo, V);
-      OldV->replaceAllUsesWith(V);
-      delete OldV;
-    }
-    
+    ValueList.AssignValue(V, NextCstNo);
     ++NextCstNo;
   }
 }
@@ -998,6 +1005,8 @@
   for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
     ValueList.push_back(I);
   
+  unsigned NextValueNo = ValueList.size();
+  
   // Read all the records.
   SmallVector<uint64_t, 64> Record;
   while (1) {
@@ -1016,6 +1025,7 @@
         break;
       case bitc::CONSTANTS_BLOCK_ID:
         if (ParseConstants()) return true;
+        NextValueNo = ValueList.size();
         break;
       case bitc::VALUE_SYMTAB_BLOCK_ID:
         if (ParseValueSymbolTable()) return true;
@@ -1031,19 +1041,115 @@
     
     // Read a record.
     Record.clear();
+    Instruction *I = 0;
+    BasicBlock *CurBB = 0;
+    unsigned CurBBNo = 0;
     switch (Stream.ReadRecord(Code, Record)) {
-    default:  // Default behavior: unknown constant
+    default: // Default behavior: reject
+      return Error("Unknown instruction");
     case bitc::FUNC_CODE_DECLAREBLOCKS:     // DECLAREBLOCKS: [nblocks]
-      if (Record.size() < 1)
-        return Error("Invalid FUNC_CODE_DECLAREBLOCKS record");
+      if (Record.size() < 1 || Record[0] == 0)
+        return Error("Invalid DECLAREBLOCKS record");
       // Create all the basic blocks for the function.
       FunctionBBs.resize(Record.size());
       for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i)
         FunctionBBs[i] = new BasicBlock("", F);
-      break;
-    }
+      CurBB = FunctionBBs[0];
+      continue;
+      
+    case bitc::FUNC_CODE_INST_BINOP: {
+      // BINOP:      [opcode, ty, opval, opval]
+      if (Record.size() < 4) return Error("Invalid BINOP record");
+      const Type *Ty = getTypeByID(Record[1]);
+      int Opc = GetDecodedBinaryOpcode(Record[0], Ty);
+      Value *LHS = getFnValueByID(Record[2], Ty);
+      Value *RHS = getFnValueByID(Record[3], Ty);
+      if (Opc == -1 || Ty == 0 || LHS == 0 || RHS == 0)
+         return Error("Invalid BINOP record");
+      I = BinaryOperator::create((Instruction::BinaryOps)Opc, LHS, RHS);
+      break;
+    }
+#if 0
+    case bitc::FUNC_CODE_INST_CAST:
+      // CAST:       [opcode, ty, opty, opval]
+    case bitc::FUNC_CODE_INST_GEP:
+      // GEP:        [n, n x operands]
+    case bitc::FUNC_CODE_INST_SELECT:
+      // SELECT:     [ty, opval, opval, opval]
+    case bitc::FUNC_CODE_INST_EXTRACTELT:
+      // EXTRACTELT: [opty, opval, opval]
+    case bitc::FUNC_CODE_INST_INSERTELT:
+      // INSERTELT:  [ty, opval, opval, opval]
+    case bitc::FUNC_CODE_INST_SHUFFLEVEC:
+      // SHUFFLEVEC: [ty, opval, opval, opval]
+    case bitc::FUNC_CODE_INST_CMP:
+      // CMP:        [opty, opval, opval, pred]
+        
+    case bitc::FUNC_CODE_INST_RET:
+      // RET:        [opty,opval<optional>]
+    case bitc::FUNC_CODE_INST_BR:
+      // BR:         [opval, bb#, bb#] or [bb#]
+    case bitc::FUNC_CODE_INST_SWITCH:
+      // SWITCH:     [opty, opval, n, n x ops]
+    case bitc::FUNC_CODE_INST_INVOKE:
+      // INVOKE:     [fnty, op0,op1,op2, ...]
+    case bitc::FUNC_CODE_INST_UNWIND:
+      // UNWIND
+    case bitc::FUNC_CODE_INST_UNREACHABLE:
+      // UNREACHABLE
+        
+    case bitc::FUNC_CODE_INST_PHI:
+      // PHI:        [ty, #ops, val0,bb0, ...]
+    case bitc::FUNC_CODE_INST_MALLOC:
+      // MALLOC:     [instty, op, align]
+    case bitc::FUNC_CODE_INST_FREE:
+      // FREE:       [opty, op]
+    case bitc::FUNC_CODE_INST_ALLOCA:
+      // ALLOCA:     [instty, op, align]
+    case bitc::FUNC_CODE_INST_LOAD:
+      // LOAD:       [opty, op, align, vol]
+    case bitc::FUNC_CODE_INST_STORE:
+      // STORE:      [ptrty,val,ptr, align, vol]
+    case bitc::FUNC_CODE_INST_CALL:
+      // CALL:       [fnty, fnid, arg0, arg1...]
+    case bitc::FUNC_CODE_INST_VAARG:
+      // VAARG:      [valistty, valist, instty]
+      break;
+#endif
+    }
+
+    // Add instruction to end of current BB.  If there is no current BB, reject
+    // this file.
+    if (CurBB == 0) {
+      delete I;
+      return Error("Invalid instruction with no BB");
+    }
+    CurBB->getInstList().push_back(I);
+    
+    // If this was a terminator instruction, move to the next block.
+    if (isa<TerminatorInst>(I)) {
+      ++CurBBNo;
+      CurBB = CurBBNo < FunctionBBs.size() ? FunctionBBs[CurBBNo] : 0;
+    }
+    
+    // Non-void values get registered in the value table for future use.
+    if (I && I->getType() != Type::VoidTy)
+      ValueList.AssignValue(I, NextValueNo++);
   }
   
+  // Check the function list for unresolved values.
+  if (Argument *A = dyn_cast<Argument>(ValueList.back())) {
+    if (A->getParent() == 0) {
+      // We found at least one unresolved value.  Nuke them all to avoid leaks.
+      for (unsigned i = ModuleValueListSize, e = ValueList.size(); i != e; ++i){
+        if ((A = dyn_cast<Argument>(ValueList.back())) && A->getParent() == 0) {
+          A->replaceAllUsesWith(UndefValue::get(A->getType()));
+          delete A;
+        }
+      }
+    }
+    return Error("Never resolved value found in function!");
+  }
   
   // Trim the value list down to the size it was before we parsed this function.
   ValueList.shrinkTo(ModuleValueListSize);


Index: llvm/lib/Bitcode/Reader/BitcodeReader.h
diff -u llvm/lib/Bitcode/Reader/BitcodeReader.h:1.14 llvm/lib/Bitcode/Reader/BitcodeReader.h:1.15
--- llvm/lib/Bitcode/Reader/BitcodeReader.h:1.14	Tue May  1 00:52:21 2007
+++ llvm/lib/Bitcode/Reader/BitcodeReader.h	Tue May  1 02:01:57 2007
@@ -51,6 +51,22 @@
   virtual void print(std::ostream&) const {}
   
   Constant *getConstantFwdRef(unsigned Idx, const Type *Ty);
+  Value *getValueFwdRef(unsigned Idx, const Type *Ty);
+  
+  void AssignValue(Value *V, unsigned Idx) {
+    if (Idx == size()) {
+      push_back(V);
+    } else if (Value *OldV = getOperand(Idx)) {
+      // If there was a forward reference to this value, replace it.
+      setOperand(Idx, V);
+      OldV->replaceAllUsesWith(V);
+      delete OldV;
+    } else {
+      initVal(Idx, V);
+    }
+  }
+  
+private:
   void initVal(unsigned Idx, Value *V) {
     assert(Uses[Idx] == 0 && "Cannot init an already init'd Use!");
     Uses[Idx].init(V, this);
@@ -113,6 +129,9 @@
   bool ParseBitcode();
 private:
   const Type *getTypeByID(unsigned ID, bool isTypeTable = false);
+  Value *getFnValueByID(unsigned ID, const Type *Ty) {
+    return ValueList.getValueFwdRef(ID, Ty);
+  }
   
   bool ParseModule(const std::string &ModuleID);
   bool ParseTypeTable();






More information about the llvm-commits mailing list