[llvm-commits] CVS: llvm/lib/Bytecode/Reader/Reader.cpp

LLVM llvm at cs.uiuc.edu
Sun Jul 4 06:35:02 PDT 2004


Changes in directory llvm/lib/Bytecode/Reader:

Reader.cpp updated: 1.108 -> 1.109

---
Log message:

- Don't use macros to call the BytecodeHandler
- Don't use PARSE_ERROR macro unnecessarily (for simple strings)
- Add comments before each function
- Convert for bug 122: http://llvm.cs.uiuc.edu/PR122  (Type != Value)
- Handle new value range on Type::PrimitiveTypeId enumeration by augmenting
  the reader with a new read_typeid method and sanitizeTypeId method.
- Remove BytecodeHandler's default method implementations to header file.


---
Diffs of the changes:  (+434 -278)

Index: llvm/lib/Bytecode/Reader/Reader.cpp
diff -u llvm/lib/Bytecode/Reader/Reader.cpp:1.108 llvm/lib/Bytecode/Reader/Reader.cpp:1.109
--- llvm/lib/Bytecode/Reader/Reader.cpp:1.108	Tue Jun 29 18:29:38 2004
+++ llvm/lib/Bytecode/Reader/Reader.cpp	Sun Jul  4 06:33:49 2004
@@ -20,10 +20,8 @@
 #include "llvm/Bytecode/BytecodeHandler.h"
 #include "llvm/BasicBlock.h"
 #include "llvm/Constants.h"
-#include "llvm/iMemory.h"
-#include "llvm/iOther.h"
-#include "llvm/iPHINode.h"
-#include "llvm/iTerminators.h"
+#include "llvm/Instructions.h"
+#include "llvm/SymbolTable.h"
 #include "llvm/Bytecode/Format.h"
 #include "llvm/Support/GetElementPtrTypeIterator.h"
 #include "Support/StringExtras.h"
@@ -31,11 +29,6 @@
 
 using namespace llvm;
 
-/// A convenience macro for calling the handler. Makes maintenance easier in
-/// case the interface to handler methods changes.
-#define HANDLE(method) \
-  if ( Handler ) Handler->handle ## method
-
 /// A convenience macro for handling parsing errors.
 #define PARSE_ERROR(inserters) { \
     std::ostringstream errormsg; \
@@ -66,31 +59,36 @@
 // Bytecode Reading Methods
 //===----------------------------------------------------------------------===//
 
+/// Determine if the current block being read contains any more data.
 inline bool BytecodeReader::moreInBlock() {
   return At < BlockEnd;
 }
 
+/// Throw an error if we've read past the end of the current block
 inline void BytecodeReader::checkPastBlockEnd(const char * block_name) {
   if ( At > BlockEnd )
     PARSE_ERROR("Attempt to read past the end of " << block_name << " block.");
 }
 
+/// Align the buffer position to a 32 bit boundary
 inline void BytecodeReader::align32() {
   BufPtr Save = At;
   At = (const unsigned char *)((unsigned long)(At+3) & (~3UL));
   if ( At > Save ) 
-    HANDLE(Alignment( At - Save ));
+    if (Handler) Handler->handleAlignment( At - Save );
   if (At > BlockEnd) 
-    PARSE_ERROR("Ran out of data while aligning!");
+    throw std::string("Ran out of data while aligning!");
 }
 
+/// Read a whole unsigned integer
 inline unsigned BytecodeReader::read_uint() {
   if (At+4 > BlockEnd) 
-    PARSE_ERROR("Ran out of data reading uint!");
+    throw std::string("Ran out of data reading uint!");
   At += 4;
   return At[-4] | (At[-3] << 8) | (At[-2] << 16) | (At[-1] << 24);
 }
 
+/// Read a variable-bit-rate encoded unsigned integer
 inline unsigned BytecodeReader::read_vbr_uint() {
   unsigned Shift = 0;
   unsigned Result = 0;
@@ -98,14 +96,15 @@
   
   do {
     if (At == BlockEnd) 
-      PARSE_ERROR("Ran out of data reading vbr_uint!");
+      throw std::string("Ran out of data reading vbr_uint!");
     Result |= (unsigned)((*At++) & 0x7F) << Shift;
     Shift += 7;
   } while (At[-1] & 0x80);
-  HANDLE(VBR32(At-Save));
+  if (Handler) Handler->handleVBR32(At-Save);
   return Result;
 }
 
+/// Read a variable-bit-rate encoded unsigned 64-bit integer.
 inline uint64_t BytecodeReader::read_vbr_uint64() {
   unsigned Shift = 0;
   uint64_t Result = 0;
@@ -113,14 +112,15 @@
   
   do {
     if (At == BlockEnd) 
-      PARSE_ERROR("Ran out of data reading vbr_uint64!");
+      throw std::string("Ran out of data reading vbr_uint64!");
     Result |= (uint64_t)((*At++) & 0x7F) << Shift;
     Shift += 7;
   } while (At[-1] & 0x80);
-  HANDLE(VBR64(At-Save));
+  if (Handler) Handler->handleVBR64(At-Save);
   return Result;
 }
 
+/// Read a variable-bit-rate encoded signed 64-bit integer.
 inline int64_t BytecodeReader::read_vbr_int64() {
   uint64_t R = read_vbr_uint64();
   if (R & 1) {
@@ -133,45 +133,88 @@
     return  (int64_t)(R >> 1);
 }
 
+/// Read a pascal-style string (length followed by text)
 inline std::string BytecodeReader::read_str() {
   unsigned Size = read_vbr_uint();
   const unsigned char *OldAt = At;
   At += Size;
   if (At > BlockEnd)             // Size invalid?
-    PARSE_ERROR("Ran out of data reading a string!");
+    throw std::string("Ran out of data reading a string!");
   return std::string((char*)OldAt, Size);
 }
 
+/// Read an arbitrary block of data
 inline void BytecodeReader::read_data(void *Ptr, void *End) {
   unsigned char *Start = (unsigned char *)Ptr;
   unsigned Amount = (unsigned char *)End - Start;
   if (At+Amount > BlockEnd) 
-    PARSE_ERROR("Ran out of data!");
+    throw std::string("Ran out of data!");
   std::copy(At, At+Amount, Start);
   At += Amount;
 }
 
+/// Read a block header and obtain its type and size
 inline void BytecodeReader::read_block(unsigned &Type, unsigned &Size) {
   Type = read_uint();
   Size = read_uint();
   BlockStart = At;
   if ( At + Size > BlockEnd )
-    PARSE_ERROR("Attempt to size a block past end of memory");
+    throw std::string("Attempt to size a block past end of memory");
   BlockEnd = At + Size;
-  HANDLE(Block( Type, BlockStart, Size ));
+  if (Handler) Handler->handleBlock( Type, BlockStart, Size );
+}
+
+
+/// In LLVM 1.2 and before, Types were derived from Value and so they were
+/// written as part of the type planes along with any other Value. In LLVM
+/// 1.3 this changed so that Type does not derive from Value. Consequently,
+/// the BytecodeReader's containers for Values can't contain Types because
+/// there's no inheritance relationship. This means that the "Type Type"
+/// plane is defunct along with the Type::TypeTyID TypeID. In LLVM 1.3 
+/// whenever a bytecode construct must have both types and values together, 
+/// the types are always read/written first and then the Values. Furthermore
+/// since Type::TypeTyID no longer exists, its value (12) now corresponds to
+/// Type::LabelTyID. In order to overcome this we must "sanitize" all the
+/// type TypeIDs we encounter. For LLVM 1.3 bytecode files, there's no change.
+/// For LLVM 1.2 and before, this function will decrement the type id by
+/// one to account for the missing Type::TypeTyID enumerator if the value is
+/// larger than 12 (Type::LabelTyID). If the value is exactly 12, then this
+/// function returns true, otherwise false. This helps detect situations
+/// where the pre 1.3 bytecode is indicating that what follows is a type.
+/// @returns true iff type id corresponds to pre 1.3 "type type" 
+inline bool BytecodeReader::sanitizeTypeId(unsigned &TypeId ) {
+  if ( hasTypeDerivedFromValue ) { /// do nothing if 1.3 or later
+    if ( TypeId == Type::LabelTyID ) {
+      TypeId = Type::VoidTyID; // sanitize it
+      return true; // indicate we got TypeTyID in pre 1.3 bytecode
+    } else if ( TypeId > Type::LabelTyID )
+      --TypeId; // shift all planes down because type type plane is missing
+  }
+  return false;
+}
+
+/// Reads a vbr uint to read in a type id and does the necessary
+/// conversion on it by calling sanitizeTypeId.
+/// @returns true iff \p TypeId read corresponds to a pre 1.3 "type type"
+/// @see sanitizeTypeId
+inline bool BytecodeReader::read_typeid(unsigned &TypeId) {
+  TypeId = read_vbr_uint();
+  return sanitizeTypeId(TypeId);
 }
 
 //===----------------------------------------------------------------------===//
 // IR Lookup Methods
 //===----------------------------------------------------------------------===//
 
+/// Determine if a type id has an implicit null value
 inline bool BytecodeReader::hasImplicitNull(unsigned TyID ) {
   if (!hasExplicitPrimitiveZeros)
-    return TyID != Type::LabelTyID && TyID != Type::TypeTyID &&
-           TyID != Type::VoidTyID;
+    return TyID != Type::LabelTyID && TyID != Type::VoidTyID;
   return TyID >= Type::FirstDerivedTyID;
 }
 
+/// Obtain a type given a typeid and account for things like compaction tables,
+/// function level vs module level, and the offsetting for the primitive types.
 const Type *BytecodeReader::getType(unsigned ID) {
   if (ID < Type::FirstDerivedTyID)
     if (const Type *T = Type::getPrimitiveType((Type::TypeID)ID))
@@ -182,7 +225,7 @@
 
   if (!CompactionTypes.empty()) {
     if (ID >= CompactionTypes.size())
-      PARSE_ERROR("Type ID out of range for compaction table!");
+      throw std::string("Type ID out of range for compaction table!");
     return CompactionTypes[ID];
   }
 
@@ -195,10 +238,31 @@
     if (ID < FunctionTypes.size())
       return FunctionTypes[ID].get();
 
-    PARSE_ERROR("Illegal type reference!");
+    throw std::string("Illegal type reference!");
     return Type::VoidTy;
 }
 
+/// Get a sanitized type id. This just makes sure that the \p ID
+/// is both sanitized and not the "type type" of pre-1.3 bytecode.
+/// @see sanitizeTypeId
+inline const Type* BytecodeReader::getSanitizedType(unsigned& ID) {
+  bool isTypeType = sanitizeTypeId(ID);
+  assert(!isTypeType && "Invalid type id occurred");
+  return getType(ID);
+}
+
+/// This method just saves some coding. It uses read_typeid to read
+/// in a sanitized type id, asserts that its not the type type, and
+/// then calls getType to return the type value.
+inline const Type* BytecodeReader::readSanitizedType() {
+  unsigned ID;
+  bool isTypeType = read_typeid(ID);
+  assert(!isTypeType && "Invalid type id occurred");
+  return getType(ID);
+}
+
+/// Get the slot number associated with a type accounting for primitive
+/// types, compaction tables, and function level vs module level.
 unsigned BytecodeReader::getTypeSlot(const Type *Ty) {
   if (Ty->isPrimitiveType())
     return Ty->getTypeID();
@@ -206,10 +270,10 @@
   // Scan the compaction table for the type if needed.
   if (!CompactionTypes.empty()) {
       std::vector<const Type*>::const_iterator I = 
-	find(CompactionTypes.begin(), CompactionTypes.end(), Ty);
+        find(CompactionTypes.begin(), CompactionTypes.end(), Ty);
 
       if (I == CompactionTypes.end())
-	PARSE_ERROR("Couldn't find type specified in compaction table!");
+        throw std::string("Couldn't find type specified in compaction table!");
       return Type::FirstDerivedTyID + (&*I - &CompactionTypes[0]);
   }
 
@@ -218,15 +282,18 @@
 
   if (I != FunctionTypes.end())
     return Type::FirstDerivedTyID + ModuleTypes.size() +
-	     (&*I - &FunctionTypes[0]);
+             (&*I - &FunctionTypes[0]);
 
   // Check the module level types now...
   I = find(ModuleTypes.begin(), ModuleTypes.end(), Ty);
   if (I == ModuleTypes.end())
-    PARSE_ERROR("Didn't find type in ModuleTypes.");
+    throw std::string("Didn't find type in ModuleTypes.");
   return Type::FirstDerivedTyID + (&*I - &ModuleTypes[0]);
 }
 
+/// This is just like getType, but when a compaction table is in use, it is
+/// ignored.  It also ignores function level types.
+/// @see getType
 const Type *BytecodeReader::getGlobalTableType(unsigned Slot) {
   if (Slot < Type::FirstDerivedTyID) {
     const Type *Ty = Type::getPrimitiveType((Type::TypeID)Slot);
@@ -235,22 +302,25 @@
   }
   Slot -= Type::FirstDerivedTyID;
   if (Slot >= ModuleTypes.size())
-    PARSE_ERROR("Illegal compaction table type reference!");
+    throw std::string("Illegal compaction table type reference!");
   return ModuleTypes[Slot];
 }
 
+/// This is just like getTypeSlot, but when a compaction table is in use, it
+/// is ignored. It also ignores function level types.
 unsigned BytecodeReader::getGlobalTableTypeSlot(const Type *Ty) {
   if (Ty->isPrimitiveType())
     return Ty->getTypeID();
   TypeListTy::iterator I = find(ModuleTypes.begin(),
-				      ModuleTypes.end(), Ty);
+                                      ModuleTypes.end(), Ty);
   if (I == ModuleTypes.end())
-    PARSE_ERROR("Didn't find type in ModuleTypes.");
+    throw std::string("Didn't find type in ModuleTypes.");
   return Type::FirstDerivedTyID + (&*I - &ModuleTypes[0]);
 }
 
+/// Retrieve a value of a given type and slot number, possibly creating 
+/// it if it doesn't already exist. 
 Value * BytecodeReader::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;
 
@@ -266,25 +336,23 @@
 
     // If the type plane was compactified, figure out the global type ID
     // by adding the derived type ids and the distance.
-    if (CompactionValues.size() > Type::TypeTyID &&
-	!CompactionTypes.empty() &&
-	type >= Type::FirstDerivedTyID) {
+    if (!CompactionTypes.empty() && type >= Type::FirstDerivedTyID) {
       const Type *Ty = CompactionTypes[type-Type::FirstDerivedTyID];
       TypeListTy::iterator I = 
-	find(ModuleTypes.begin(), ModuleTypes.end(), Ty);
+        find(ModuleTypes.begin(), ModuleTypes.end(), Ty);
       assert(I != ModuleTypes.end());
       GlobalTyID = Type::FirstDerivedTyID + (&*I - &ModuleTypes[0]);
     }
 
     if (hasImplicitNull(GlobalTyID)) {
       if (Num == 0)
-	return Constant::getNullValue(getType(type));
+        return Constant::getNullValue(getType(type));
       --Num;
     }
 
     if (GlobalTyID < ModuleValues.size() && ModuleValues[GlobalTyID]) {
       if (Num < ModuleValues[GlobalTyID]->size())
-	return ModuleValues[GlobalTyID]->getOperand(Num);
+        return ModuleValues[GlobalTyID]->getOperand(Num);
       Num -= ModuleValues[GlobalTyID]->size();
     }
   }
@@ -306,6 +374,9 @@
   return Val;
 }
 
+/// This is just like getValue, but when a compaction table is in use, it 
+/// is ignored.  Also, no forward references or other fancy features are 
+/// supported.
 Value* BytecodeReader::getGlobalTableValue(const Type *Ty, unsigned SlotNo) {
   // FIXME: getTypeSlot is inefficient!
   unsigned TyID = getGlobalTableTypeSlot(Ty);
@@ -319,13 +390,18 @@
   if (TyID >= ModuleValues.size() || ModuleValues[TyID] == 0 ||
       SlotNo >= ModuleValues[TyID]->size()) {
     PARSE_ERROR("Corrupt compaction table entry!" 
-	<< TyID << ", " << SlotNo << ": " << ModuleValues.size() << ", "
-	<< (void*)ModuleValues[TyID] << ", "
-	<< ModuleValues[TyID]->size() << "\n");
+        << TyID << ", " << SlotNo << ": " << ModuleValues.size() << ", "
+        << (void*)ModuleValues[TyID] << ", "
+        << ModuleValues[TyID]->size() << "\n");
   }
   return ModuleValues[TyID]->getOperand(SlotNo);
 }
 
+/// 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
+/// constant hasn't been parsed yet, a placeholder is defined and used.  
+/// Later, after the real value is parsed, the placeholder is eliminated.
 Constant* BytecodeReader::getConstantValue(unsigned TypeSlot, unsigned Slot) {
   if (Value *V = getValue(TypeSlot, Slot, false))
     if (Constant *C = dyn_cast<Constant>(V))
@@ -335,7 +411,7 @@
       // to infest bytecode files.
       return ConstantPointerRef::get(GV);
     else
-      PARSE_ERROR("Reference of a value is expected to be a constant!");
+      throw std::string("Reference of a value is expected to be a constant!");
 
   const Type *Ty = getType(TypeSlot);
   std::pair<const Type*, unsigned> Key(Ty, Slot);
@@ -358,12 +434,14 @@
 // IR Construction Methods
 //===----------------------------------------------------------------------===//
 
+/// As values are created, they are inserted into the appropriate place
+/// with this method. The ValueTable argument must be one of ModuleValues
+/// or FunctionValues data members of this class.
 unsigned BytecodeReader::insertValue(
     Value *Val, unsigned type, ValueTable &ValueTab) {
   assert((!isa<Constant>(Val) || !cast<Constant>(Val)->isNullValue()) ||
-	  !hasImplicitNull(type) &&
-	 "Cannot read null values from bytecode!");
-  assert(type != Type::TypeTyID && "Types should never be insertValue'd!");
+          !hasImplicitNull(type) &&
+         "Cannot read null values from bytecode!");
 
   if (ValueTab.size() <= type)
     ValueTab.resize(type+1);
@@ -376,6 +454,7 @@
   return ValueTab[type]->size()-1 + HasOffset;
 }
 
+/// Insert the arguments of a function as new values in the reader.
 void BytecodeReader::insertArguments(Function* F ) {
   const FunctionType *FT = F->getFunctionType();
   Function::aiterator AI = F->abegin();
@@ -388,6 +467,9 @@
 // Bytecode Parsing Methods
 //===----------------------------------------------------------------------===//
 
+/// This method parses a single instruction. The instruction is
+/// inserted at the end of the \p BB provided. The arguments of
+/// the instruction are provided in the \p Args vector.
 void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
                                               BasicBlock* BB) {
   BufPtr SaveAt = At;
@@ -452,7 +534,7 @@
     Oprnds.resize(NumOprnds);
 
     if (NumOprnds == 0)
-      PARSE_ERROR("Zero-argument instruction found; this is invalid.");
+      throw std::string("Zero-argument instruction found; this is invalid.");
 
     for (unsigned i = 0; i != NumOprnds; ++i)
       Oprnds[i] = read_vbr_uint();
@@ -460,11 +542,10 @@
     break;
   }
 
-  // Get the type of the instruction
-  const Type *InstTy = getType(iType);
+  const Type *InstTy = getSanitizedType(iType);
 
   // Hae enough to inform the handler now
-  HANDLE(Instruction(Opcode, InstTy, Oprnds, At-SaveAt));
+  if (Handler) Handler->handleInstruction(Opcode, InstTy, Oprnds, At-SaveAt);
 
   // Declare the resulting instruction we'll build.
   Instruction *Result = 0;
@@ -478,16 +559,20 @@
 
   switch (Opcode) {
   default: 
-    if (Result == 0) PARSE_ERROR("Illegal instruction read!");
+    if (Result == 0) 
+      throw std::string("Illegal instruction read!");
     break;
   case Instruction::VAArg:
-    Result = new VAArgInst(getValue(iType, Oprnds[0]), getType(Oprnds[1]));
+    Result = new VAArgInst(getValue(iType, Oprnds[0]), 
+	                   getSanitizedType(Oprnds[1]));
     break;
   case Instruction::VANext:
-    Result = new VANextInst(getValue(iType, Oprnds[0]), getType(Oprnds[1]));
+    Result = new VANextInst(getValue(iType, Oprnds[0]), 
+	                    getSanitizedType(Oprnds[1]));
     break;
   case Instruction::Cast:
-    Result = new CastInst(getValue(iType, Oprnds[0]), getType(Oprnds[1]));
+    Result = new CastInst(getValue(iType, Oprnds[0]), 
+	                  getSanitizedType(Oprnds[1]));
     break;
   case Instruction::Select:
     Result = new SelectInst(getValue(Type::BoolTyID, Oprnds[0]),
@@ -496,7 +581,7 @@
     break;
   case Instruction::PHI: {
     if (Oprnds.size() == 0 || (Oprnds.size() & 1))
-      PARSE_ERROR("Invalid phi node encountered!\n");
+      throw std::string("Invalid phi node encountered!");
 
     PHINode *PN = new PHINode(InstTy);
     PN->op_reserve(Oprnds.size());
@@ -518,7 +603,7 @@
     else if (Oprnds.size() == 1)
       Result = new ReturnInst(getValue(iType, Oprnds[0]));
     else
-      PARSE_ERROR("Unrecognized instruction!");
+      throw std::string("Unrecognized instruction!");
     break;
 
   case Instruction::Br:
@@ -526,13 +611,13 @@
       Result = new BranchInst(getBasicBlock(Oprnds[0]));
     else if (Oprnds.size() == 3)
       Result = new BranchInst(getBasicBlock(Oprnds[0]), 
-	  getBasicBlock(Oprnds[1]), getValue(Type::BoolTyID , Oprnds[2]));
+          getBasicBlock(Oprnds[1]), getValue(Type::BoolTyID , Oprnds[2]));
     else
-      PARSE_ERROR("Invalid number of operands for a 'br' instruction!");
+      throw std::string("Invalid number of operands for a 'br' instruction!");
     break;
   case Instruction::Switch: {
     if (Oprnds.size() & 1)
-      PARSE_ERROR("Switch statement with odd number of arguments!");
+      throw std::string("Switch statement with odd number of arguments!");
 
     SwitchInst *I = new SwitchInst(getValue(iType, Oprnds[0]),
                                    getBasicBlock(Oprnds[1]));
@@ -545,15 +630,15 @@
 
   case Instruction::Call: {
     if (Oprnds.size() == 0)
-      PARSE_ERROR("Invalid call instruction encountered!");
+      throw std::string("Invalid call instruction encountered!");
 
     Value *F = getValue(iType, Oprnds[0]);
 
     // Check to make sure we have a pointer to function type
     const PointerType *PTy = dyn_cast<PointerType>(F->getType());
-    if (PTy == 0) PARSE_ERROR("Call to non function pointer value!");
+    if (PTy == 0) throw std::string("Call to non function pointer value!");
     const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType());
-    if (FTy == 0) PARSE_ERROR("Call to non function pointer value!");
+    if (FTy == 0) throw std::string("Call to non function pointer value!");
 
     std::vector<Value *> Params;
     if (!FTy->isVarArg()) {
@@ -561,17 +646,17 @@
 
       for (unsigned i = 1, e = Oprnds.size(); i != e; ++i) {
         if (It == FTy->param_end())
-          PARSE_ERROR("Invalid call instruction!");
+          throw std::string("Invalid call instruction!");
         Params.push_back(getValue(getTypeSlot(*It++), Oprnds[i]));
       }
       if (It != FTy->param_end())
-        PARSE_ERROR("Invalid call instruction!");
+        throw std::string("Invalid call instruction!");
     } else {
       Oprnds.erase(Oprnds.begin(), Oprnds.begin()+1);
 
       unsigned FirstVariableOperand;
       if (Oprnds.size() < FTy->getNumParams())
-        PARSE_ERROR("Call instruction missing operands!");
+        throw std::string("Call instruction missing operands!");
 
       // Read all of the fixed arguments
       for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
@@ -580,10 +665,10 @@
       FirstVariableOperand = FTy->getNumParams();
 
       if ((Oprnds.size()-FirstVariableOperand) & 1) // Must be pairs of type/value
-        PARSE_ERROR("Invalid call instruction!");
+        throw std::string("Invalid call instruction!");
         
       for (unsigned i = FirstVariableOperand, e = Oprnds.size(); 
-	   i != e; i += 2)
+           i != e; i += 2)
         Params.push_back(getValue(Oprnds[i], Oprnds[i+1]));
     }
 
@@ -591,14 +676,17 @@
     break;
   }
   case Instruction::Invoke: {
-    if (Oprnds.size() < 3) PARSE_ERROR("Invalid invoke instruction!");
+    if (Oprnds.size() < 3) 
+      throw std::string("Invalid invoke instruction!");
     Value *F = getValue(iType, Oprnds[0]);
 
     // Check to make sure we have a pointer to function type
     const PointerType *PTy = dyn_cast<PointerType>(F->getType());
-    if (PTy == 0) PARSE_ERROR("Invoke to non function pointer value!");
+    if (PTy == 0) 
+      throw std::string("Invoke to non function pointer value!");
     const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType());
-    if (FTy == 0) PARSE_ERROR("Invoke to non function pointer value!");
+    if (FTy == 0) 
+      throw std::string("Invoke to non function pointer value!");
 
     std::vector<Value *> Params;
     BasicBlock *Normal, *Except;
@@ -610,11 +698,11 @@
       FunctionType::param_iterator It = FTy->param_begin();
       for (unsigned i = 3, e = Oprnds.size(); i != e; ++i) {
         if (It == FTy->param_end())
-          PARSE_ERROR("Invalid invoke instruction!");
+          throw std::string("Invalid invoke instruction!");
         Params.push_back(getValue(getTypeSlot(*It++), Oprnds[i]));
       }
       if (It != FTy->param_end())
-        PARSE_ERROR("Invalid invoke instruction!");
+        throw std::string("Invalid invoke instruction!");
     } else {
       Oprnds.erase(Oprnds.begin(), Oprnds.begin()+1);
 
@@ -627,7 +715,7 @@
                                   Oprnds[i]));
       
       if (Oprnds.size()-FirstVariableArgument & 1) // Must be type/value pairs
-        PARSE_ERROR("Invalid invoke instruction!");
+        throw std::string("Invalid invoke instruction!");
 
       for (unsigned i = FirstVariableArgument; i < Oprnds.size(); i += 2)
         Params.push_back(getValue(Oprnds[i], Oprnds[i+1]));
@@ -637,9 +725,10 @@
     break;
   }
   case Instruction::Malloc:
-    if (Oprnds.size() > 2) PARSE_ERROR("Invalid malloc instruction!");
+    if (Oprnds.size() > 2) 
+      throw std::string("Invalid malloc instruction!");
     if (!isa<PointerType>(InstTy))
-      PARSE_ERROR("Invalid malloc instruction!");
+      throw std::string("Invalid malloc instruction!");
 
     Result = new MallocInst(cast<PointerType>(InstTy)->getElementType(),
                             Oprnds.size() ? getValue(Type::UIntTyID,
@@ -647,29 +736,31 @@
     break;
 
   case Instruction::Alloca:
-    if (Oprnds.size() > 2) PARSE_ERROR("Invalid alloca instruction!");
+    if (Oprnds.size() > 2) 
+      throw std::string("Invalid alloca instruction!");
     if (!isa<PointerType>(InstTy))
-      PARSE_ERROR("Invalid alloca instruction!");
+      throw std::string("Invalid alloca instruction!");
 
     Result = new AllocaInst(cast<PointerType>(InstTy)->getElementType(),
                             Oprnds.size() ? getValue(Type::UIntTyID, 
-			    Oprnds[0]) :0);
+                            Oprnds[0]) :0);
     break;
   case Instruction::Free:
     if (!isa<PointerType>(InstTy))
-      PARSE_ERROR("Invalid free instruction!");
+      throw std::string("Invalid free instruction!");
     Result = new FreeInst(getValue(iType, Oprnds[0]));
     break;
   case Instruction::GetElementPtr: {
     if (Oprnds.size() == 0 || !isa<PointerType>(InstTy))
-      PARSE_ERROR("Invalid getelementptr instruction!");
+      throw std::string("Invalid getelementptr instruction!");
 
     std::vector<Value*> Idx;
 
     const Type *NextTy = InstTy;
     for (unsigned i = 1, e = Oprnds.size(); i != e; ++i) {
       const CompositeType *TopTy = dyn_cast_or_null<CompositeType>(NextTy);
-      if (!TopTy) PARSE_ERROR("Invalid getelementptr instruction!"); 
+      if (!TopTy) 
+	throw std::string("Invalid getelementptr instruction!"); 
 
       unsigned ValIdx = Oprnds[i];
       unsigned IdxTy = 0;
@@ -710,14 +801,14 @@
   case 62:   // volatile load
   case Instruction::Load:
     if (Oprnds.size() != 1 || !isa<PointerType>(InstTy))
-      PARSE_ERROR("Invalid load instruction!");
+      throw std::string("Invalid load instruction!");
     Result = new LoadInst(getValue(iType, Oprnds[0]), "", Opcode == 62);
     break;
 
   case 63:   // volatile store 
   case Instruction::Store: {
     if (!isa<PointerType>(InstTy) || Oprnds.size() != 2)
-      PARSE_ERROR("Invalid store instruction!");
+      throw std::string("Invalid store instruction!");
 
     Value *Ptr = getValue(iType, Oprnds[1]);
     const Type *ValTy = cast<PointerType>(Ptr->getType())->getElementType();
@@ -726,7 +817,8 @@
     break;
   }
   case Instruction::Unwind:
-    if (Oprnds.size() != 0) PARSE_ERROR("Invalid unwind instruction!");
+    if (Oprnds.size() != 0) 
+      throw std::string("Invalid unwind instruction!");
     Result = new UnwindInst();
     break;
   }  // end switch(Opcode) 
@@ -741,9 +833,11 @@
   BB->getInstList().push_back(Result);
 }
 
-/// 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.
+/// 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.  This function is used when constructing phi, br, switch, 
+/// and other instructions that reference basic blocks. Blocks are numbered 
+/// sequentially as they appear in the function.
 BasicBlock *BytecodeReader::getBasicBlock(unsigned ID) {
   // Make sure there is room in the table...
   if (ParsedBasicBlocks.size() <= ID) ParsedBasicBlocks.resize(ID+1);
@@ -759,10 +853,12 @@
   return ParsedBasicBlocks[ID] = new BasicBlock();
 }
 
-/// ParseBasicBlock - In LLVM 1.0 bytecode files, we used to output one
-/// basicblock at a time.  This method reads in one of the basicblock packets.
+/// In LLVM 1.0 bytecode files, we used to output one basicblock at a time.  
+/// This method reads in one of the basicblock packets. This method is not used
+/// for bytecode files after LLVM 1.0
+/// @returns The basic block constructed.
 BasicBlock *BytecodeReader::ParseBasicBlock( unsigned BlockNo) {
-  HANDLE(BasicBlockBegin( BlockNo ));
+  if (Handler) Handler->handleBasicBlockBegin( BlockNo );
 
   BasicBlock *BB = 0;
 
@@ -777,19 +873,20 @@
   while ( moreInBlock() )
     ParseInstruction(Operands, BB);
 
-  HANDLE(BasicBlockEnd( BlockNo ));
+  if (Handler) Handler->handleBasicBlockEnd( BlockNo );
   return BB;
 }
 
-/// ParseInstructionList - Parse all of the BasicBlock's & Instruction's in the
-/// body of a function.  In post 1.0 bytecode files, we no longer emit basic
-/// block individually, in order to avoid per-basic-block overhead.
+/// Parse all of the BasicBlock's & Instruction's in the body of a function.
+/// In post 1.0 bytecode files, we no longer emit basic block individually, 
+/// in order to avoid per-basic-block overhead.
+/// @returns Rhe number of basic blocks encountered.
 unsigned BytecodeReader::ParseInstructionList(Function* F) {
   unsigned BlockNo = 0;
   std::vector<unsigned> Args;
 
   while ( moreInBlock() ) {
-    HANDLE(BasicBlockBegin( BlockNo ));
+    if (Handler) Handler->handleBasicBlockBegin( BlockNo );
     BasicBlock *BB;
     if (ParsedBasicBlocks.size() == BlockNo)
       ParsedBasicBlocks.push_back(BB = new BasicBlock());
@@ -797,7 +894,7 @@
       BB = ParsedBasicBlocks[BlockNo] = new BasicBlock();
     else
       BB = ParsedBasicBlocks[BlockNo];
-    HANDLE(BasicBlockEnd( BlockNo ));
+    if (Handler) Handler->handleBasicBlockEnd( BlockNo );
     ++BlockNo;
     F->getBasicBlockList().push_back(BB);
 
@@ -806,15 +903,20 @@
       ParseInstruction(Args, BB);
 
     if (!BB->getTerminator())
-      PARSE_ERROR("Non-terminated basic block found!");
+      throw std::string("Non-terminated basic block found!");
   }
 
   return BlockNo;
 }
 
+/// Parse a symbol table. This works for both module level and function
+/// level symbol tables.  For function level symbol tables, the CurrentFunction
+/// parameter must be non-zero and the ST parameter must correspond to
+/// CurrentFunction's symbol table. For Module level symbol tables, the
+/// CurrentFunction argument must be zero.
 void BytecodeReader::ParseSymbolTable(Function *CurrentFunction,
-				      SymbolTable *ST) {
-  HANDLE(SymbolTableBegin(CurrentFunction,ST));
+                                      SymbolTable *ST) {
+  if (Handler) Handler->handleSymbolTableBegin(CurrentFunction,ST);
 
   // Allow efficient basic block lookup by number.
   std::vector<BasicBlock*> BBMap;
@@ -823,10 +925,26 @@
            E = CurrentFunction->end(); I != E; ++I)
       BBMap.push_back(I);
 
+  /// In LLVM 1.3 we write types separately from values so
+  /// The types are always first in the symbol table. This is
+  /// because Type no longer derives from Value.
+  if ( ! hasTypeDerivedFromValue ) {
+    // Symtab block header: [num entries]
+    unsigned NumEntries = read_vbr_uint();
+    for ( unsigned i = 0; i < NumEntries; ++i ) {
+      // Symtab entry: [def slot #][name]
+      unsigned slot = read_vbr_uint();
+      std::string Name = read_str();
+      const Type* T = getType(slot);
+      ST->insert(Name, T);
+    }
+  }
+
   while ( moreInBlock() ) {
     // Symtab block header: [num entries][type id number]
     unsigned NumEntries = read_vbr_uint();
-    unsigned Typ = read_vbr_uint();
+    unsigned Typ = 0;
+    bool isTypeType = read_typeid(Typ);
     const Type *Ty = getType(Typ);
 
     for (unsigned i = 0; i != NumEntries; ++i) {
@@ -834,75 +952,104 @@
       unsigned slot = read_vbr_uint();
       std::string Name = read_str();
 
-      Value *V = 0;
-      if (Typ == Type::TypeTyID)
-        V = (Value*)getType(slot);
-      else if (Typ == Type::LabelTyID) {
-        if (slot < BBMap.size())
-          V = BBMap[slot];
+      // if we're reading a pre 1.3 bytecode file and the type plane
+      // is the "type type", handle it here
+      if ( isTypeType ) {
+	const Type* T = getType(slot);
+	if ( T == 0 )
+	  PARSE_ERROR("Failed type look-up for name '" << Name << "'");
+	ST->insert(Name, T);
+	continue; // code below must be short circuited
       } else {
-        V = getValue(Typ, slot, false); // Find mapping...
+	Value *V = 0;
+	if (Typ == Type::LabelTyID) {
+	  if (slot < BBMap.size())
+	    V = BBMap[slot];
+	} else {
+	  V = getValue(Typ, slot, false); // Find mapping...
+	}
+	if (V == 0)
+	  PARSE_ERROR("Failed value look-up for name '" << Name << "'");
+	V->setName(Name, ST);
       }
-      if (V == 0)
-        PARSE_ERROR("Failed value look-up for name '" << Name << "'");
-
-      V->setName(Name, ST);
     }
   }
   checkPastBlockEnd("Symbol Table");
-  HANDLE(SymbolTableEnd());
+  if (Handler) Handler->handleSymbolTableEnd();
+}
+
+/// Read in the types portion of a compaction table. 
+void BytecodeReader::ParseCompactionTypes( unsigned NumEntries ) {
+  for (unsigned i = 0; i != NumEntries; ++i) {
+    unsigned TypeSlot = 0;
+    bool isTypeType = read_typeid(TypeSlot);
+    assert(!isTypeType && "Invalid type in compaction table: type type");
+    const Type *Typ = getGlobalTableType(TypeSlot);
+    CompactionTypes.push_back(Typ);
+    if (Handler) Handler->handleCompactionTableType( i, TypeSlot, Typ );
+  }
 }
 
+/// Parse a compaction table.
 void BytecodeReader::ParseCompactionTable() {
 
-  HANDLE(CompactionTableBegin());
+  if (Handler) Handler->handleCompactionTableBegin();
+
+  /// In LLVM 1.3 Type no longer derives from Value. So, 
+  /// we always write them first in the compaction table
+  /// because they can't occupy a "type plane" where the
+  /// Values reside.
+  if ( ! hasTypeDerivedFromValue ) {
+    unsigned NumEntries = read_vbr_uint();
+    ParseCompactionTypes( NumEntries );
+  }
 
   while ( moreInBlock() ) {
     unsigned NumEntries = read_vbr_uint();
-    unsigned Ty;
+    unsigned Ty = 0;
+    unsigned isTypeType = false;
 
     if ((NumEntries & 3) == 3) {
       NumEntries >>= 2;
-      Ty = read_vbr_uint();
+      isTypeType = read_typeid(Ty);
     } else {
       Ty = NumEntries >> 2;
+      isTypeType = sanitizeTypeId(Ty);
       NumEntries &= 3;
     }
 
-    if (Ty >= CompactionValues.size())
-      CompactionValues.resize(Ty+1);
+    // if we're reading a pre 1.3 bytecode file and the type plane
+    // is the "type type", handle it here
+    if ( isTypeType ) {
+      ParseCompactionTypes(NumEntries);
+    } else {
+      if (Ty >= CompactionValues.size())
+	CompactionValues.resize(Ty+1);
 
-    if (!CompactionValues[Ty].empty())
-      PARSE_ERROR("Compaction table plane contains multiple entries!");
+      if (!CompactionValues[Ty].empty())
+	throw std::string("Compaction table plane contains multiple entries!");
 
-    HANDLE(CompactionTablePlane( Ty, NumEntries ));
+      if (Handler) Handler->handleCompactionTablePlane( Ty, NumEntries );
 
-    if (Ty == Type::TypeTyID) {
-      for (unsigned i = 0; i != NumEntries; ++i) {
-        unsigned TypeSlot = read_vbr_uint();
-        const Type *Typ = getGlobalTableType(TypeSlot);
-        CompactionTypes.push_back(Typ);
-        HANDLE(CompactionTableType( i, TypeSlot, Typ ));
-      }
-      CompactionTypes.resize(NumEntries+Type::FirstDerivedTyID);
-    } else {
       const Type *Typ = getType(Ty);
       // Push the implicit zero
       CompactionValues[Ty].push_back(Constant::getNullValue(Typ));
       for (unsigned i = 0; i != NumEntries; ++i) {
-        unsigned ValSlot = read_vbr_uint();
-        Value *V = getGlobalTableValue(Typ, ValSlot);
-        CompactionValues[Ty].push_back(V);
-        HANDLE(CompactionTableValue( i, Ty, ValSlot, Typ ));
+	unsigned ValSlot = read_vbr_uint();
+	Value *V = getGlobalTableValue(Typ, ValSlot);
+	CompactionValues[Ty].push_back(V);
+	if (Handler) Handler->handleCompactionTableValue( i, Ty, ValSlot, Typ );
       }
     }
   }
-  HANDLE(CompactionTableEnd());
+  if (Handler) Handler->handleCompactionTableEnd();
 }
     
 // Parse a single type constant.
 const Type *BytecodeReader::ParseTypeConstant() {
-  unsigned PrimType = read_vbr_uint();
+  unsigned PrimType = 0;
+  bool isTypeType = read_typeid(PrimType);
+  assert(!isTypeType && "Invalid type (type type) in type constants!");
 
   const Type *Result = 0;
   if ((Result = Type::getPrimitiveType((Type::TypeID)PrimType)))
@@ -910,13 +1057,13 @@
   
   switch (PrimType) {
   case Type::FunctionTyID: {
-    const Type *RetType = getType(read_vbr_uint());
+    const Type *RetType = readSanitizedType();
 
     unsigned NumParams = read_vbr_uint();
 
     std::vector<const Type*> Params;
-    while (NumParams--)
-      Params.push_back(getType(read_vbr_uint()));
+    while (NumParams--) 
+      Params.push_back(readSanitizedType());
 
     bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
     if (isVarArg) Params.pop_back();
@@ -925,28 +1072,27 @@
     break;
   }
   case Type::ArrayTyID: {
-    unsigned ElTyp = read_vbr_uint();
-    const Type *ElementType = getType(ElTyp);
-
+    const Type *ElementType = readSanitizedType();
     unsigned NumElements = read_vbr_uint();
-
     Result =  ArrayType::get(ElementType, NumElements);
     break;
   }
   case Type::StructTyID: {
     std::vector<const Type*> Elements;
-    unsigned Typ = read_vbr_uint();
+    unsigned Typ = 0;
+    bool isTypeType = read_typeid(Typ);
+    assert(!isTypeType && "Invalid element type (type type) for structure!");
     while (Typ) {         // List is terminated by void/0 typeid
       Elements.push_back(getType(Typ));
-      Typ = read_vbr_uint();
+      bool isTypeType = read_typeid(Typ);
+      assert(!isTypeType && "Invalid element type (type type) for structure!");
     }
 
     Result = StructType::get(Elements);
     break;
   }
   case Type::PointerTyID: {
-    unsigned ElTyp = read_vbr_uint();
-    Result = PointerType::get(getType(ElTyp));
+    Result = PointerType::get(readSanitizedType());
     break;
   }
 
@@ -956,10 +1102,11 @@
   }
 
   default:
-    PARSE_ERROR("Don't know how to deserialize primitive type" << PrimType << "\n");
+    PARSE_ERROR("Don't know how to deserialize primitive type" 
+	<< PrimType << "\n");
     break;
   }
-  HANDLE(Type( Result ));
+  if (Handler) Handler->handleType( Result );
   return Result;
 }
 
@@ -985,8 +1132,10 @@
   // opaque types just inserted.
   //
   for (unsigned i = 0; i != NumEntries; ++i) {
-    const Type *NewTy = ParseTypeConstant(), *OldTy = Tab[i].get();
-    if (NewTy == 0) PARSE_ERROR("Couldn't parse type!");
+    const Type* NewTy = ParseTypeConstant();
+    const Type* OldTy = Tab[i].get();
+    if (NewTy == 0) 
+      throw std::string("Couldn't parse type!");
 
     // Don't directly push the new type on the Tab. Instead we want to replace 
     // the opaque type we previously inserted with the new concrete value. This
@@ -1003,6 +1152,7 @@
   }
 }
 
+/// Parse a single constant value
 Constant *BytecodeReader::ParseConstantValue( unsigned TypeID) {
   // We must check for a ConstantExpr before switching by type because
   // a ConstantExpr can be of any type, and has no explicit value.
@@ -1019,7 +1169,9 @@
     // Read the slot number and types of each of the arguments
     for (unsigned i = 0; i != isExprNumArgs; ++i) {
       unsigned ArgValSlot = read_vbr_uint();
-      unsigned ArgTypeSlot = read_vbr_uint();
+      unsigned ArgTypeSlot = 0;
+      bool isTypeType = read_typeid(ArgTypeSlot);
+      assert(!isTypeType && "Invalid argument type (type type) for constant value");
       
       // Get the arg value from its slot if it exists, otherwise a placeholder
       ArgVec.push_back(getConstantValue(ArgTypeSlot, ArgValSlot));
@@ -1029,7 +1181,7 @@
     if (isExprNumArgs == 1) {           // All one-operand expressions
       assert(Opcode == Instruction::Cast);
       Constant* Result = ConstantExpr::getCast(ArgVec[0], getType(TypeID));
-      HANDLE(ConstantExpression(Opcode, ArgVec, Result));
+      if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, Result);
       return Result;
     } else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr
       std::vector<Constant*> IdxList(ArgVec.begin()+1, ArgVec.end());
@@ -1042,23 +1194,23 @@
         for (unsigned i = 0; GTI != E; ++GTI, ++i)
           if (isa<StructType>(*GTI)) {
             if (IdxList[i]->getType() != Type::UByteTy)
-              PARSE_ERROR("Invalid index for getelementptr!");
+              throw std::string("Invalid index for getelementptr!");
             IdxList[i] = ConstantExpr::getCast(IdxList[i], Type::UIntTy);
           }
       }
 
       Constant* Result = ConstantExpr::getGetElementPtr(ArgVec[0], IdxList);
-      HANDLE(ConstantExpression(Opcode, ArgVec, Result));
+      if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, Result);
       return Result;
     } else if (Opcode == Instruction::Select) {
       assert(ArgVec.size() == 3);
       Constant* Result = ConstantExpr::getSelect(ArgVec[0], ArgVec[1], 
-	                                         ArgVec[2]);
-      HANDLE(ConstantExpression(Opcode, ArgVec, Result));
+                                                 ArgVec[2]);
+      if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, Result);
       return Result;
     } else {                            // All other 2-operand expressions
       Constant* Result = ConstantExpr::get(Opcode, ArgVec[0], ArgVec[1]);
-      HANDLE(ConstantExpression(Opcode, ArgVec, Result));
+      if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, Result);
       return Result;
     }
   }
@@ -1069,9 +1221,9 @@
   case Type::BoolTyID: {
     unsigned Val = read_vbr_uint();
     if (Val != 0 && Val != 1) 
-      PARSE_ERROR("Invalid boolean value read.");
+      throw std::string("Invalid boolean value read.");
     Constant* Result = ConstantBool::get(Val == 1);
-    HANDLE(ConstantValue(Result));
+    if (Handler) Handler->handleConstantValue(Result);
     return Result;
   }
 
@@ -1080,15 +1232,15 @@
   case Type::UIntTyID: {
     unsigned Val = read_vbr_uint();
     if (!ConstantUInt::isValueValidForType(Ty, Val)) 
-      PARSE_ERROR("Invalid unsigned byte/short/int read.");
+      throw std::string("Invalid unsigned byte/short/int read.");
     Constant* Result =  ConstantUInt::get(Ty, Val);
-    HANDLE(ConstantValue(Result));
+    if (Handler) Handler->handleConstantValue(Result);
     return Result;
   }
 
   case Type::ULongTyID: {
     Constant* Result = ConstantUInt::get(Ty, read_vbr_uint64());
-    HANDLE(ConstantValue(Result));
+    if (Handler) Handler->handleConstantValue(Result);
     return Result;
   }
 
@@ -1098,9 +1250,9 @@
   case Type::LongTyID:
     int64_t Val = read_vbr_int64();
     if (!ConstantSInt::isValueValidForType(Ty, Val)) 
-      PARSE_ERROR("Invalid signed byte/short/int/long read.");
+      throw std::string("Invalid signed byte/short/int/long read.");
     Constant* Result = ConstantSInt::get(Ty, Val);
-    HANDLE(ConstantValue(Result));
+    if (Handler) Handler->handleConstantValue(Result);
     return Result;
   }
 
@@ -1108,7 +1260,7 @@
     float F;
     read_data(&F, &F+1);
     Constant* Result = ConstantFP::get(Ty, F);
-    HANDLE(ConstantValue(Result));
+    if (Handler) Handler->handleConstantValue(Result);
     return Result;
   }
 
@@ -1116,14 +1268,10 @@
     double Val;
     read_data(&Val, &Val+1);
     Constant* Result = ConstantFP::get(Ty, Val);
-    HANDLE(ConstantValue(Result));
+    if (Handler) Handler->handleConstantValue(Result);
     return Result;
   }
 
-  case Type::TypeTyID:
-    PARSE_ERROR("Type constants shouldn't live in constant table!");
-    break;
-
   case Type::ArrayTyID: {
     const ArrayType *AT = cast<ArrayType>(Ty);
     unsigned NumElements = AT->getNumElements();
@@ -1134,7 +1282,7 @@
       Elements.push_back(getConstantValue(TypeSlot,
                                           read_vbr_uint()));
     Constant* Result = ConstantArray::get(AT, Elements);
-    HANDLE(ConstantArray(AT, Elements, TypeSlot, Result));
+    if (Handler) Handler->handleConstantArray(AT, Elements, TypeSlot, Result);
     return Result;
   }
 
@@ -1148,7 +1296,7 @@
                                           read_vbr_uint()));
 
     Constant* Result = ConstantStruct::get(ST, Elements);
-    HANDLE(ConstantStruct(ST, Elements, Result));
+    if (Handler) Handler->handleConstantStruct(ST, Elements, Result);
     return Result;
   }    
 
@@ -1161,13 +1309,13 @@
     GlobalValue *GV;
     if (Val) {
       if (!(GV = dyn_cast<GlobalValue>(Val))) 
-        PARSE_ERROR("Value of ConstantPointerRef not in ValueTable!");
+        throw std::string("Value of ConstantPointerRef not in ValueTable!");
     } else {
-      PARSE_ERROR("Forward references are not allowed here.");
+      throw std::string("Forward references are not allowed here.");
     }
     
     Constant* Result = ConstantPointerRef::get(GV);
-    HANDLE(ConstantPointer(PT, Slot, GV, Result));
+    if (Handler) Handler->handleConstantPointer(PT, Slot, GV, Result);
     return Result;
   }
 
@@ -1178,6 +1326,10 @@
   }
 }
 
+/// Resolve references for constants. This function resolves the forward 
+/// referenced constants in the ConstantFwdRefs map. It uses the 
+/// replaceAllUsesWith method of Value class to substitute the placeholder
+/// instance with the actual instance.
 void BytecodeReader::ResolveReferencesToConstant(Constant *NewV, unsigned Slot){
   ConstantRefsType::iterator I =
     ConstantFwdRefs.find(std::make_pair(NewV->getType(), Slot));
@@ -1189,17 +1341,20 @@
   ConstantFwdRefs.erase(I);                // Remove the map entry for it
 }
 
+/// Parse the constant strings section.
 void BytecodeReader::ParseStringConstants(unsigned NumEntries, ValueTable &Tab){
   for (; NumEntries; --NumEntries) {
-    unsigned Typ = read_vbr_uint();
+    unsigned Typ = 0;
+    bool isTypeType = read_typeid(Typ);
+    assert(!isTypeType && "Invalid type (type type) for string constant");
     const Type *Ty = getType(Typ);
     if (!isa<ArrayType>(Ty))
-      PARSE_ERROR("String constant data invalid!");
+      throw std::string("String constant data invalid!");
     
     const ArrayType *ATy = cast<ArrayType>(Ty);
     if (ATy->getElementType() != Type::SByteTy &&
         ATy->getElementType() != Type::UByteTy)
-      PARSE_ERROR("String constant data invalid!");
+      throw std::string("String constant data invalid!");
     
     // Read character data.  The type tells us how long the string is.
     char Data[ATy->getNumElements()]; 
@@ -1217,19 +1372,37 @@
     Constant *C = ConstantArray::get(ATy, Elements);
     unsigned Slot = insertValue(C, Typ, Tab);
     ResolveReferencesToConstant(C, Slot);
-    HANDLE(ConstantString(cast<ConstantArray>(C)));
+    if (Handler) Handler->handleConstantString(cast<ConstantArray>(C));
   }
 }
 
+/// Parse the constant pool.
 void BytecodeReader::ParseConstantPool(ValueTable &Tab, 
-                                       TypeListTy &TypeTab) {
-  HANDLE(GlobalConstantsBegin());
+                                       TypeListTy &TypeTab,
+				       bool isFunction) {
+  if (Handler) Handler->handleGlobalConstantsBegin();
+
+  /// In LLVM 1.3 Type does not derive from Value so the types
+  /// do not occupy a plane. Consequently, we read the types
+  /// first in the constant pool.
+  if ( isFunction && !hasTypeDerivedFromValue ) {
+    unsigned NumEntries = read_vbr_uint();
+    ParseTypeConstants(TypeTab, NumEntries);
+  }
+
   while ( moreInBlock() ) {
     unsigned NumEntries = read_vbr_uint();
-    unsigned Typ = read_vbr_uint();
-    if (Typ == Type::TypeTyID) {
+    unsigned Typ = 0;
+    bool isTypeType = read_typeid(Typ);
+
+    /// In LLVM 1.2 and before, Types were written to the
+    /// bytecode file in the "Type Type" plane (#12).
+    /// In 1.3 plane 12 is now the label plane.  Handle this here.
+    if ( isTypeType ) {
       ParseTypeConstants(TypeTab, NumEntries);
     } else if (Typ == Type::VoidTyID) {
+      /// Use of Type::VoidTyID is a misnomer. It actually means
+      /// that the following plane is constant strings
       assert(&Tab == &ModuleValues && "Cannot read strings in functions!");
       ParseStringConstants(NumEntries, Tab);
     } else {
@@ -1249,9 +1422,12 @@
     }
   }
   checkPastBlockEnd("Constant Pool");
-  HANDLE(GlobalConstantsEnd());
+  if (Handler) Handler->handleGlobalConstantsEnd();
 }
 
+/// Parse the contents of a function. Note that this function can be
+/// called lazily by materializeFunction
+/// @see materializeFunction
 void BytecodeReader::ParseFunctionBody(Function* F ) {
 
   unsigned FuncSize = BlockEnd - At;
@@ -1265,13 +1441,13 @@
   case 3: Linkage = GlobalValue::InternalLinkage; break;
   case 4: Linkage = GlobalValue::LinkOnceLinkage; break;
   default:
-    PARSE_ERROR("Invalid linkage type for Function.");
+    throw std::string("Invalid linkage type for Function.");
     Linkage = GlobalValue::InternalLinkage;
     break;
   }
 
   F->setLinkage( Linkage );
-  HANDLE(FunctionBegin(F,FuncSize));
+  if (Handler) Handler->handleFunctionBegin(F,FuncSize);
 
   // Keep track of how many basic blocks we have read in...
   unsigned BlockNum = 0;
@@ -1289,11 +1465,11 @@
         // Insert arguments into the value table before we parse the first basic
         // block in the function, but after we potentially read in the
         // compaction table.
-	insertArguments(F);
+        insertArguments(F);
         InsertedArguments = true;
       }
 
-      ParseConstantPool(FunctionValues, FunctionTypes);
+      ParseConstantPool(FunctionValues, FunctionTypes, true);
       break;
 
     case BytecodeFormat::CompactionTable:
@@ -1305,7 +1481,7 @@
         // Insert arguments into the value table before we parse the first basic
         // block in the function, but after we potentially read in the
         // compaction table.
-	insertArguments(F);
+        insertArguments(F);
         InsertedArguments = true;
       }
 
@@ -1319,12 +1495,12 @@
       // list for the function, but after we potentially read in the compaction
       // table.
       if (!InsertedArguments) {
-	insertArguments(F);
+        insertArguments(F);
         InsertedArguments = true;
       }
 
       if (BlockNum) 
-	PARSE_ERROR("Already parsed basic blocks!");
+        throw std::string("Already parsed basic blocks!");
       BlockNum = ParseInstructionList(F);
       break;
     }
@@ -1336,7 +1512,7 @@
     default:
       At += Size;
       if (OldAt > At) 
-        PARSE_ERROR("Wrapped around reading bytecode.");
+        throw std::string("Wrapped around reading bytecode.");
       break;
     }
     BlockEnd = MyEnd;
@@ -1347,7 +1523,7 @@
 
   // Make sure there were no references to non-existant basic blocks.
   if (BlockNum != ParsedBasicBlocks.size())
-    PARSE_ERROR("Illegal basic block operand reference");
+    throw std::string("Illegal basic block operand reference");
 
   ParsedBasicBlocks.clear();
 
@@ -1394,12 +1570,16 @@
   CompactionValues.clear();
   freeTable(FunctionValues);
 
-  HANDLE(FunctionEnd(F));
+  if (Handler) Handler->handleFunctionEnd(F);
 }
 
+/// This function parses LLVM functions lazily. It obtains the type of the
+/// function and records where the body of the function is in the bytecode
+/// buffer. The caller can then use the ParseNextFunction and 
+/// ParseAllFunctionBodies to get handler events for the functions.
 void BytecodeReader::ParseFunctionLazily() {
   if (FunctionSignatureList.empty())
-    PARSE_ERROR("FunctionSignatureList empty!");
+    throw std::string("FunctionSignatureList empty!");
 
   Function *Func = FunctionSignatureList.back();
   FunctionSignatureList.pop_back();
@@ -1411,6 +1591,12 @@
   At = BlockEnd;
 }
 
+/// The ParserFunction method lazily parses one function. Use this method to 
+/// casue the parser to parse a specific function in the module. Note that 
+/// this will remove the function from what is to be included by 
+/// ParseAllFunctionBodies.
+/// @see ParseAllFunctionBodies
+/// @see ParseBytecode
 void BytecodeReader::ParseFunction(Function* Func) {
   // Find {start, end} pointers and slot in the map. If not there, we're done.
   LazyFunctionMap::iterator Fi = LazyFunctionLoadMap.find(Func);
@@ -1430,6 +1616,13 @@
   this->ParseFunctionBody( Func );
 }
 
+/// The ParseAllFunctionBodies method parses through all the previously
+/// unparsed functions in the bytecode file. If you want to completely parse
+/// a bytecode file, this method should be called after Parsebytecode because
+/// Parsebytecode only records the locations in the bytecode file of where
+/// the function definitions are located. This function uses that information
+/// to materialize the functions.
+/// @see ParseBytecode
 void BytecodeReader::ParseAllFunctionBodies() {
   LazyFunctionMap::iterator Fi = LazyFunctionLoadMap.begin();
   LazyFunctionMap::iterator Fe = LazyFunctionLoadMap.end();
@@ -1443,14 +1636,17 @@
   }
 }
 
+/// Parse the global type list
 void BytecodeReader::ParseGlobalTypes() {
-  ValueTable T;
-  ParseConstantPool(T, ModuleTypes);
+  // Read the number of types
+  unsigned NumEntries = read_vbr_uint();
+  ParseTypeConstants(ModuleTypes, NumEntries);
 }
 
+/// Parse the Global info (types, global vars, constants)
 void BytecodeReader::ParseModuleGlobalInfo() {
 
-  HANDLE(ModuleGlobalsBegin());
+  if (Handler) Handler->handleModuleGlobalsBegin();
 
   // Read global variables...
   unsigned VarType = read_vbr_uint();
@@ -1458,6 +1654,8 @@
     // VarType Fields: bit0 = isConstant, bit1 = hasInitializer, bit2,3,4 =
     // Linkage, bit4+ = slot#
     unsigned SlotNo = VarType >> 5;
+    bool isTypeType = sanitizeTypeId(SlotNo);
+    assert(!isTypeType && "Invalid type (type type) for global var!");
     unsigned LinkageID = (VarType >> 2) & 7;
     bool isConstant = VarType & 1;
     bool hasInitializer = VarType & 2;
@@ -1498,14 +1696,16 @@
     }
 
     // Notify handler about the global value.
-    HANDLE(GlobalVariable( ElTy, isConstant, Linkage, SlotNo, initSlot ));
+    if (Handler) Handler->handleGlobalVariable( ElTy, isConstant, Linkage, SlotNo, initSlot );
 
     // Get next item
     VarType = read_vbr_uint();
   }
 
   // Read the function objects for all of the functions that are coming
-  unsigned FnSignature = read_vbr_uint();
+  unsigned FnSignature = 0;
+  bool isTypeType = read_typeid(FnSignature);
+  assert(!isTypeType && "Invalid function type (type type) found");
   while (FnSignature != Type::VoidTyID) { // List is terminated by Void
     const Type *Ty = getType(FnSignature);
     if (!isa<PointerType>(Ty) ||
@@ -1521,16 +1721,17 @@
 
     // Insert the place hodler
     Function* Func = new Function(FTy, GlobalValue::InternalLinkage, 
-	                          "", TheModule);
+                                  "", TheModule);
     insertValue(Func, FnSignature, ModuleValues);
 
     // Save this for later so we know type of lazily instantiated functions
     FunctionSignatureList.push_back(Func);
 
-    HANDLE(FunctionDeclaration(Func));
+    if (Handler) Handler->handleFunctionDeclaration(Func);
 
     // Get Next function signature
-    FnSignature = read_vbr_uint();
+    isTypeType = read_typeid(FnSignature);
+    assert(!isTypeType && "Invalid function type (type type) found");
   }
 
   if (hasInconsistentModuleGlobalInfo)
@@ -1545,9 +1746,11 @@
   //
   At = BlockEnd;
 
-  HANDLE(ModuleGlobalsEnd());
+  if (Handler) Handler->handleModuleGlobalsEnd();
 }
 
+/// Parse the version information and decode it by setting flags on the
+/// Reader that enable backward compatibility of the reader.
 void BytecodeReader::ParseVersionInfo() {
   unsigned Version = read_vbr_uint();
 
@@ -1566,12 +1769,14 @@
   hasInconsistentModuleGlobalInfo = false;
   hasExplicitPrimitiveZeros = false;
   hasRestrictedGEPTypes = false;
+  hasTypeDerivedFromValue = false;
 
   switch (RevisionNum) {
   case 0:               //  LLVM 1.0, 1.1 release version
     // Base LLVM 1.0 bytecode format.
     hasInconsistentModuleGlobalInfo = true;
     hasExplicitPrimitiveZeros = true;
+
     // FALL THROUGH
   case 1:               // LLVM 1.2 release version
     // LLVM 1.2 added explicit support for emitting strings efficiently.
@@ -1584,6 +1789,12 @@
     // structures and longs for sequential types.
     hasRestrictedGEPTypes = true;
 
+    // LLVM 1.2 and before had the Type class derive from Value class. This
+    // changed in release 1.3 and consequently LLVM 1.3 bytecode files are
+    // written differently because Types can no longer be part of the 
+    // type planes for Values.
+    hasTypeDerivedFromValue = true;
+
     // FALL THROUGH
   case 2:               // LLVM 1.3 release version
     break;
@@ -1595,9 +1806,10 @@
   if (hasNoEndianness) Endianness  = Module::AnyEndianness;
   if (hasNoPointerSize) PointerSize = Module::AnyPointerSize;
 
-  HANDLE(VersionInfo(RevisionNum, Endianness, PointerSize ));
+  if (Handler) Handler->handleVersionInfo(RevisionNum, Endianness, PointerSize );
 }
 
+/// Parse a whole module.
 void BytecodeReader::ParseModule() {
   unsigned Type, Size;
 
@@ -1618,7 +1830,7 @@
 
     case BytecodeFormat::GlobalTypePlane:
       if ( SeenGlobalTypePlane )
-        PARSE_ERROR("Two GlobalTypePlane Blocks Encountered!");
+        throw std::string("Two GlobalTypePlane Blocks Encountered!");
 
       ParseGlobalTypes();
       SeenGlobalTypePlane = true;
@@ -1626,13 +1838,13 @@
 
     case BytecodeFormat::ModuleGlobalInfo: 
       if ( SeenModuleGlobalInfo )
-        PARSE_ERROR("Two ModuleGlobalInfo Blocks Encountered!");
+        throw std::string("Two ModuleGlobalInfo Blocks Encountered!");
       ParseModuleGlobalInfo();
       SeenModuleGlobalInfo = true;
       break;
 
     case BytecodeFormat::ConstantPool:
-      ParseConstantPool(ModuleValues, ModuleTypes);
+      ParseConstantPool(ModuleValues, ModuleTypes,false);
       break;
 
     case BytecodeFormat::Function:
@@ -1668,20 +1880,22 @@
     unsigned TypeSlot = getTypeSlot(GVType->getElementType());
     if (Constant *CV = getConstantValue(TypeSlot, Slot)) {
       if (GV->hasInitializer()) 
-        PARSE_ERROR("Global *already* has an initializer?!");
-      HANDLE(GlobalInitializer(GV,CV));
+        throw std::string("Global *already* has an initializer?!");
+      if (Handler) Handler->handleGlobalInitializer(GV,CV);
       GV->setInitializer(CV);
     } else
-      PARSE_ERROR("Cannot find initializer value.");
+      throw std::string("Cannot find initializer value.");
   }
 
   /// Make sure we pulled them all out. If we didn't then there's a declaration
   /// but a missing body. That's not allowed.
   if (!FunctionSignatureList.empty())
-    PARSE_ERROR(
+    throw std::string(
       "Function declared, but bytecode stream ended before definition");
 }
 
+/// This function completely parses a bytecode buffer given by the \p Buf
+/// and \p Length parameters.
 void BytecodeReader::ParseBytecode(
        BufPtr Buf, unsigned Length,
        const std::string &ModuleID) {
@@ -1693,7 +1907,7 @@
     // Create the module
     TheModule = new Module(ModuleID);
 
-    HANDLE(Start(TheModule, Length));
+    if (Handler) Handler->handleStart(TheModule, Length);
 
     // Read and check signature...
     unsigned Sig = read_uint();
@@ -1703,42 +1917,42 @@
 
 
     // Tell the handler we're starting a module
-    HANDLE(ModuleBegin(ModuleID));
+    if (Handler) Handler->handleModuleBegin(ModuleID);
 
     // Get the module block and size and verify
     unsigned Type, Size;
     read_block(Type, Size);
     if ( Type != BytecodeFormat::Module ) {
       PARSE_ERROR("Expected Module Block! At: " << unsigned(intptr_t(At))
-	<< ", Type:" << Type << ", Size:" << Size);
+        << ", Type:" << Type << ", Size:" << Size);
     }
     if ( At + Size != MemEnd ) {
       PARSE_ERROR("Invalid Top Level Block Length! At: " 
-	<< unsigned(intptr_t(At)) << ", Type:" << Type << ", Size:" << Size);
+        << unsigned(intptr_t(At)) << ", Type:" << Type << ", Size:" << Size);
     }
 
     // Parse the module contents
     this->ParseModule();
 
     // Tell the handler we're done
-    HANDLE(ModuleEnd(ModuleID));
+    if (Handler) Handler->handleModuleEnd(ModuleID);
 
     // Check for missing functions
     if ( hasFunctions() )
-      PARSE_ERROR("Function expected, but bytecode stream ended!");
+      throw std::string("Function expected, but bytecode stream ended!");
 
     // Tell the handler we're
-    HANDLE(Finish());
+    if (Handler) Handler->handleFinish();
 
   } catch (std::string& errstr ) {
-    HANDLE(Error(errstr));
+    if (Handler) Handler->handleError(errstr);
     freeState();
     delete TheModule;
     TheModule = 0;
     throw;
   } catch (...) {
     std::string msg("Unknown Exception Occurred");
-    HANDLE(Error(msg));
+    if (Handler) Handler->handleError(msg);
     freeState();
     delete TheModule;
     TheModule = 0;
@@ -1751,63 +1965,5 @@
 //===----------------------------------------------------------------------===//
 
 BytecodeHandler::~BytecodeHandler() {}
-void BytecodeHandler::handleError(const std::string& str ) { }
-void BytecodeHandler::handleStart(Module*m, unsigned Length ) { }
-void BytecodeHandler::handleFinish() { }
-void BytecodeHandler::handleModuleBegin(const std::string& id) { }
-void BytecodeHandler::handleModuleEnd(const std::string& id) { }
-void BytecodeHandler::handleVersionInfo( unsigned char RevisionNum,
-  Module::Endianness Endianness, Module::PointerSize PointerSize) { }
-void BytecodeHandler::handleModuleGlobalsBegin() { }
-void BytecodeHandler::handleGlobalVariable( 
-  const Type* ElemType, bool isConstant, GlobalValue::LinkageTypes,
-  unsigned SlotNo, unsigned initSlot ) { }
-void BytecodeHandler::handleType( const Type* Ty ) {}
-void BytecodeHandler::handleFunctionDeclaration( 
-  Function* Func ) {}
-void BytecodeHandler::handleGlobalInitializer(GlobalVariable*, Constant* ) {}
-void BytecodeHandler::handleModuleGlobalsEnd() { } 
-void BytecodeHandler::handleCompactionTableBegin() { } 
-void BytecodeHandler::handleCompactionTablePlane( 
-  unsigned Ty, unsigned NumEntries) {}
-void BytecodeHandler::handleCompactionTableType( 
-  unsigned i, unsigned TypSlot, const Type* ) {}
-void BytecodeHandler::handleCompactionTableValue( 
-  unsigned i, unsigned TypSlot, unsigned ValSlot, const Type* ) {}
-void BytecodeHandler::handleCompactionTableEnd() { }
-void BytecodeHandler::handleSymbolTableBegin(Function*, SymbolTable*) { }
-void BytecodeHandler::handleSymbolTablePlane( unsigned Ty, unsigned NumEntries, 
-  const Type* Typ) { }
-void BytecodeHandler::handleSymbolTableType( unsigned i, unsigned slot, 
-  const std::string& name ) { }
-void BytecodeHandler::handleSymbolTableValue( unsigned i, unsigned slot, 
-  const std::string& name ) { }
-void BytecodeHandler::handleSymbolTableEnd() { }
-void BytecodeHandler::handleFunctionBegin( Function* Func, 
-  unsigned Size ) {}
-void BytecodeHandler::handleFunctionEnd( Function* Func) { }
-void BytecodeHandler::handleBasicBlockBegin( unsigned blocknum) { } 
-bool BytecodeHandler::handleInstruction( unsigned Opcode, const Type* iType,
-  std::vector<unsigned>& Operands, unsigned Size) { 
-    return Instruction::isTerminator(Opcode); 
-  }
-void BytecodeHandler::handleBasicBlockEnd(unsigned blocknum) { }
-void BytecodeHandler::handleGlobalConstantsBegin() { }
-void BytecodeHandler::handleConstantExpression( unsigned Opcode, 
-  std::vector<Constant*> ArgVec, Constant* Val) { }
-void BytecodeHandler::handleConstantValue( Constant * c ) { }
-void BytecodeHandler::handleConstantArray( const ArrayType* AT, 
-  std::vector<Constant*>& Elements, unsigned TypeSlot, Constant* Val ) { }
-void BytecodeHandler::handleConstantStruct( const StructType* ST,
-  std::vector<Constant*>& ElementSlots, Constant* Val ) { }
-void BytecodeHandler::handleConstantPointer( 
-  const PointerType* PT, unsigned TypeSlot, GlobalValue*, Constant* Val) { }
-void BytecodeHandler::handleConstantString( const ConstantArray* CA ) {}
-void BytecodeHandler::handleGlobalConstantsEnd() {}
-void BytecodeHandler::handleAlignment(unsigned numBytes) {}
-void BytecodeHandler::handleBlock(
-  unsigned BType, const unsigned char* StartPtr, unsigned Size) {}
-void BytecodeHandler::handleVBR32(unsigned Size ) {}
-void BytecodeHandler::handleVBR64(unsigned Size ) {}
 
 // vim: sw=2





More information about the llvm-commits mailing list