Major refactoring of the bytecode reader. This includes the following
[oota-llvm.git] / lib / Bytecode / Reader / Reader.cpp
index 29812da561ee91cfa4f6790790f6239464bf6a6b..e649cdc08f142e6e14d4c6b23d1fdb0981a413aa 100644 (file)
@@ -49,17 +49,15 @@ unsigned BytecodeParser::getTypeSlot(const Type *Ty) {
 }
 
 const Type *BytecodeParser::getType(unsigned ID) {
-  if (ID < Type::NumPrimitiveIDs) {
-    const Type *T = Type::getPrimitiveType((Type::PrimitiveID)ID);
-    if (T) return T;
-  }
+  if (ID < Type::NumPrimitiveIDs)
+    if (const Type *T = Type::getPrimitiveType((Type::PrimitiveID)ID))
+      return T;
   
   //cerr << "Looking up Type ID: " << ID << "\n";
 
-  if (ID < Type::NumPrimitiveIDs) {
-    const Type *T = Type::getPrimitiveType((Type::PrimitiveID)ID);
-    if (T) return T;   // Asked for a primitive type...
-  }
+  if (ID < Type::NumPrimitiveIDs)
+    if (const Type *T = Type::getPrimitiveType((Type::PrimitiveID)ID))
+      return T;   // Asked for a primitive type...
 
   // Otherwise, derived types need offset...
   ID -= FirstDerivedTyID;
@@ -73,10 +71,10 @@ const Type *BytecodeParser::getType(unsigned ID) {
   if (ID < FunctionTypeValues.size())
     return FunctionTypeValues[ID].get();
 
-  return 0;
+  throw std::string("Illegal type reference!");
 }
 
-int BytecodeParser::insertValue(Value *Val, ValueTable &ValueTab) {
+unsigned BytecodeParser::insertValue(Value *Val, ValueTable &ValueTab) {
   assert((!HasImplicitZeroInitializer || !isa<Constant>(Val) ||
           Val->getType()->isPrimitiveType() ||
           !cast<Constant>(Val)->isNullValue()) &&
@@ -102,23 +100,13 @@ int BytecodeParser::insertValue(Value *Val, ValueTable &ValueTab) {
 }
 
 
-void BytecodeParser::setValueTo(ValueTable &ValueTab, unsigned Slot,
-                                Value *Val) {
-  assert(&ValueTab == &ModuleValues && "Can only setValueTo on Module values!");
-  assert((!HasImplicitZeroInitializer || Slot != 0) &&
-         "Cannot change zero init");
-  unsigned type = getTypeSlot(Val->getType());
-  assert(type < ValueTab.size() && Slot <= ValueTab[type]->size());
-  ValueTab[type]->setOperand(Slot-HasImplicitZeroInitializer, Val);
-}
-
-
 Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) {
   return getValue(getTypeSlot(Ty), oNum, Create);
 }
 
 Value *BytecodeParser::getValue(unsigned type, unsigned oNum, bool Create) {
   assert(type != Type::TypeTyID && "getValue() cannot get types!");
+  assert(type != Type::LabelTyID && "getValue() cannot get blocks!");
   unsigned Num = oNum;
 
   if (HasImplicitZeroInitializer && type >= FirstDerivedTyID) {
@@ -138,15 +126,36 @@ Value *BytecodeParser::getValue(unsigned type, unsigned oNum, bool Create) {
 
   if (!Create) return 0;  // Do not create a placeholder?
 
-  const Type *Ty = getType(type);
-  Value *Val = type == Type::LabelTyID ? (Value*)new BBPHolder(Ty, oNum) : 
-                                         (Value*)new ValPHolder(Ty, oNum);
+  std::pair<unsigned,unsigned> KeyValue(type, oNum);
+  std::map<std::pair<unsigned,unsigned>, Value*>::iterator I = 
+    ForwardReferences.lower_bound(KeyValue);
+  if (I != ForwardReferences.end() && I->first == KeyValue)
+    return I->second;   // We have already created this placeholder
 
-  assert(Val != 0 && "How did we not make something?");
-  if (insertValue(Val, LateResolveValues) == -1) return 0;
+  Value *Val = new Argument(getType(type));
+  ForwardReferences.insert(I, std::make_pair(KeyValue, Val));
   return Val;
 }
 
+/// getBasicBlock - Get a particular numbered basic block, which might be a
+/// forward reference.  This works together with ParseBasicBlock to handle these
+/// forward references in a clean manner.
+///
+BasicBlock *BytecodeParser::getBasicBlock(unsigned ID) {
+  // Make sure there is room in the table...
+  if (ParsedBasicBlocks.size() <= ID) ParsedBasicBlocks.resize(ID+1);
+
+  // First check to see if this is a backwards reference, i.e., ParseBasicBlock
+  // has already created this block, or if the forward reference has already
+  // been created.
+  if (ParsedBasicBlocks[ID])
+    return ParsedBasicBlocks[ID];
+
+  // Otherwise, the basic block has not yet been created.  Do so and add it to
+  // the ParsedBasicBlocks list.
+  return ParsedBasicBlocks[ID] = new BasicBlock();
+}
+
 /// getConstantValue - Just like getValue, except that it returns a null pointer
 /// only on error.  It always returns a constant (meaning that if the value is
 /// defined, but is not a constant, that is an error).  If the specified
@@ -176,20 +185,20 @@ Constant *BytecodeParser::getConstantValue(const Type *Ty, unsigned Slot) {
 }
 
 
-std::auto_ptr<BasicBlock>
-BytecodeParser::ParseBasicBlock(const unsigned char *&Buf,
-                                const unsigned char *EndBuf) {
-  std::auto_ptr<BasicBlock> BB(new BasicBlock());
+BasicBlock *BytecodeParser::ParseBasicBlock(const unsigned char *&Buf,
+                                            const unsigned char *EndBuf,
+                                            unsigned BlockNo) {
+  BasicBlock *BB;
+  if (ParsedBasicBlocks.size() == BlockNo)
+    ParsedBasicBlocks.push_back(BB = new BasicBlock());
+  else if (ParsedBasicBlocks[BlockNo] == 0)
+    BB = ParsedBasicBlocks[BlockNo] = new BasicBlock();
+  else
+    BB = ParsedBasicBlocks[BlockNo];
 
   while (Buf < EndBuf) {
-    Instruction *Inst;
-    ParseInstruction(Buf, EndBuf, Inst);
-
-    if (Inst == 0) { throw std::string("Could not parse Instruction."); }
-    if (insertValue(Inst, Values) == -1) { 
-      throw std::string("Could not insert value.");
-    }
-
+    Instruction *Inst = ParseInstruction(Buf, EndBuf);
+    insertValue(Inst, Values);
     BB->getInstList().push_back(Inst);
     BCR_TRACE(4, Inst);
   }
@@ -199,16 +208,15 @@ BytecodeParser::ParseBasicBlock(const unsigned char *&Buf,
 
 void BytecodeParser::ParseSymbolTable(const unsigned char *&Buf,
                                       const unsigned char *EndBuf,
-                                      SymbolTable *ST) {
+                                      SymbolTable *ST,
+                                      Function *CurrentFunction) {
   while (Buf < EndBuf) {
     // Symtab block header: [num entries][type id number]
     unsigned NumEntries, Typ;
     if (read_vbr(Buf, EndBuf, NumEntries) ||
         read_vbr(Buf, EndBuf, Typ)) throw Error_readvbr;
     const Type *Ty = getType(Typ);
-    if (Ty == 0) throw std::string("Invalid type read in symbol table.");
-
-    BCR_TRACE(3, "Plane Type: '" << Ty << "' with " << NumEntries <<
+    BCR_TRACE(3, "Plane Type: '" << *Ty << "' with " << NumEntries <<
                  " entries\n");
 
     for (unsigned i = 0; i < NumEntries; ++i) {
@@ -219,10 +227,17 @@ void BytecodeParser::ParseSymbolTable(const unsigned char *&Buf,
       if (read(Buf, EndBuf, Name, false))  // Not aligned...
         throw std::string("Buffer not aligned.");
 
-      Value *V;
+      Value *V = 0;
       if (Typ == Type::TypeTyID)
         V = (Value*)getType(slot);
-      else
+      else if (Typ == Type::LabelTyID) {
+        if (CurrentFunction) {
+          // FIXME: THIS IS N^2!!!
+          Function::iterator BlockIterator = CurrentFunction->begin();
+          std::advance(BlockIterator, slot);
+          V = BlockIterator;
+        }
+      } else
         V = getValue(Typ, slot, false); // Find mapping...
       if (V == 0) throw std::string("Failed value look-up.");
       BCR_TRACE(4, "Map: '" << Name << "' to #" << slot << ":" << *V;
@@ -254,9 +269,8 @@ void BytecodeParser::ResolveReferencesToValue(Value *NewV, unsigned Slot) {
   GlobalRefs.erase(I);                // Remove the map entry for it
 }
 
-void
-BytecodeParser::ParseFunction(const unsigned char *&Buf,
-                              const unsigned char *EndBuf) {
+void BytecodeParser::ParseFunction(const unsigned char *&Buf,
+                                   const unsigned char *EndBuf) {
   if (FunctionSignatureList.empty())
     throw std::string("FunctionSignatureList empty!");
 
@@ -307,10 +321,11 @@ void BytecodeParser::materializeFunction(Function* F) {
   const FunctionType::ParamTypes &Params =F->getFunctionType()->getParamTypes();
   Function::aiterator AI = F->abegin();
   for (FunctionType::ParamTypes::const_iterator It = Params.begin();
-       It != Params.end(); ++It, ++AI) {
-    if (insertValue(AI, Values) == -1)
-      throw std::string("Error reading function arguments!");
-  }
+       It != Params.end(); ++It, ++AI)
+    insertValue(AI, Values);
+
+  // Keep track of how many basic blocks we have read in...
+  unsigned BlockNum = 0;
 
   while (Buf < EndBuf) {
     unsigned Type, Size;
@@ -326,17 +341,14 @@ void BytecodeParser::materializeFunction(Function* F) {
 
     case BytecodeFormat::BasicBlock: {
       BCR_TRACE(2, "BLOCK BytecodeFormat::BasicBlock: {\n");
-      std::auto_ptr<BasicBlock> BB = ParseBasicBlock(Buf, Buf+Size);
-      if (!BB.get() || insertValue(BB.get(), Values) == -1)
-        throw std::string("Parse error: BasicBlock");
-
-      F->getBasicBlockList().push_back(BB.release());
+      BasicBlock *BB = ParseBasicBlock(Buf, Buf+Size, BlockNum++);
+      F->getBasicBlockList().push_back(BB);
       break;
     }
 
     case BytecodeFormat::SymbolTable: {
       BCR_TRACE(2, "BLOCK BytecodeFormat::SymbolTable: {\n");
-      ParseSymbolTable(Buf, Buf+Size, &F->getSymbolTable());
+      ParseSymbolTable(Buf, Buf+Size, &F->getSymbolTable(), F);
       break;
     }
 
@@ -353,31 +365,33 @@ void BytecodeParser::materializeFunction(Function* F) {
     ALIGN32(Buf, EndBuf);
   }
 
-  // Check for unresolvable references
-  while (!LateResolveValues.empty()) {
-    ValueList &VL = *LateResolveValues.back();
-    LateResolveValues.pop_back();    
+  // Make sure there were no references to non-existant basic blocks.
+  if (BlockNum != ParsedBasicBlocks.size())
+    throw std::string("Illegal basic block operand reference");
+  ParsedBasicBlocks.clear();
+
 
-    while (!VL.empty()) {
-      Value *V = VL.back();
-      unsigned IDNumber = getValueIDNumberFromPlaceHolder(V);
-      VL.pop_back();
+  // Resolve forward references
+  while (!ForwardReferences.empty()) {
+    std::map<std::pair<unsigned,unsigned>, Value*>::iterator I = ForwardReferences.begin();
+    unsigned type = I->first.first;
+    unsigned Slot = I->first.second;
+    Value *PlaceHolder = I->second;
+    ForwardReferences.erase(I);
 
-      Value *NewVal = getValue(V->getType(), IDNumber, false);
-      if (NewVal == 0)
-        throw std::string("Unresolvable reference found: <" +
-                          V->getType()->getDescription() + ">:" + 
-                          utostr(IDNumber) + ".");
+    Value *NewVal = getValue(type, Slot, false);
+    if (NewVal == 0)
+      throw std::string("Unresolvable reference found: <" +
+                        PlaceHolder->getType()->getDescription() + ">:" + 
+                        utostr(Slot) + ".");
 
-      // Fixup all of the uses of this placeholder def...
-      V->replaceAllUsesWith(NewVal);
+    // Fixup all of the uses of this placeholder def...
+    PlaceHolder->replaceAllUsesWith(NewVal);
       
-      // Now that all the uses are gone, delete the placeholder...
-      // If we couldn't find a def (error case), then leak a little
-      // memory, because otherwise we can't remove all uses!
-      delete V;
-    }
-    delete &VL;
+    // Now that all the uses are gone, delete the placeholder...
+    // If we couldn't find a def (error case), then leak a little
+    // memory, because otherwise we can't remove all uses!
+    delete PlaceHolder;
   }
 
   // Clear out function-level types...
@@ -412,7 +426,7 @@ void BytecodeParser::ParseModuleGlobalInfo(const unsigned char *&Buf,
     }
 
     const Type *Ty = getType(SlotNo);
-    if (!Ty || !isa<PointerType>(Ty))
+    if (!isa<PointerType>(Ty))
       throw std::string("Global not pointer type!  Ty = " + 
                         Ty->getDescription());
 
@@ -421,10 +435,8 @@ void BytecodeParser::ParseModuleGlobalInfo(const unsigned char *&Buf,
     // Create the global variable...
     GlobalVariable *GV = new GlobalVariable(ElTy, VarType & 1, Linkage,
                                             0, "", TheModule);
-    int DestSlot = insertValue(GV, ModuleValues);
-    if (DestSlot == -1) throw Error_DestSlot;
     BCR_TRACE(2, "Global Variable of type: " << *Ty << "\n");
-    ResolveReferencesToValue(GV, (unsigned)DestSlot);
+    ResolveReferencesToValue(GV, insertValue(GV, ModuleValues));
 
     if (VarType & 2) { // Does it have an initializer?
       unsigned InitSlot;
@@ -439,11 +451,10 @@ void BytecodeParser::ParseModuleGlobalInfo(const unsigned char *&Buf,
   if (read_vbr(Buf, End, FnSignature)) throw Error_readvbr;
   while (FnSignature != Type::VoidTyID) { // List is terminated by Void
     const Type *Ty = getType(FnSignature);
-    if (!Ty || !isa<PointerType>(Ty) ||
-        !isa<FunctionType>(cast<PointerType>(Ty)->getElementType())) { 
+    if (!isa<PointerType>(Ty) ||
+        !isa<FunctionType>(cast<PointerType>(Ty)->getElementType()))
       throw std::string("Function not ptr to func type!  Ty = " +
                         Ty->getDescription());
-    }
 
     // We create functions by passing the underlying FunctionType to create...
     Ty = cast<PointerType>(Ty)->getElementType();
@@ -456,9 +467,8 @@ void BytecodeParser::ParseModuleGlobalInfo(const unsigned char *&Buf,
     // Insert the placeholder...
     Function *Func = new Function(cast<FunctionType>(Ty),
                                   GlobalValue::InternalLinkage, "", TheModule);
-    int DestSlot = insertValue(Func, ModuleValues);
-    if (DestSlot == -1) throw Error_DestSlot;
-    ResolveReferencesToValue(Func, (unsigned)DestSlot);
+    unsigned DestSlot = insertValue(Func, ModuleValues);
+    ResolveReferencesToValue(Func, DestSlot);
 
     // Keep track of this information in a list that is emptied as functions are
     // loaded...
@@ -582,7 +592,7 @@ void BytecodeParser::ParseModule(const unsigned char *Buf,
 
     case BytecodeFormat::SymbolTable:
       BCR_TRACE(1, "BLOCK BytecodeFormat::SymbolTable: {\n");
-      ParseSymbolTable(Buf, Buf+Size, &TheModule->getSymbolTable());
+      ParseSymbolTable(Buf, Buf+Size, &TheModule->getSymbolTable(), 0);
       break;
 
     default: