Start using the new and improve interface to FunctionType arguments
[oota-llvm.git] / lib / Bytecode / Reader / InstructionReader.cpp
index 300c40999eb17d599957cf34d8e9d4abf29ce90a..8912704c6f624d59bb4b2b4ff0c88580eefcf085 100644 (file)
@@ -1,4 +1,11 @@
-//===- ReadInst.cpp - Code to read an instruction from bytecode -------------===
+//===- ReadInst.cpp - Code to read an instruction from bytecode -----------===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
 //
 // This file defines the mechanism to read an instruction from a bytecode 
 // stream.
 // Note that this library should be as fast as possible, reentrant, and 
 // threadsafe!!
 //
-// TODO: Change from getValue(Raw.Arg1) etc, to getArg(Raw, 1)
-//       Make it check type, so that casts are checked.
-//
-//===------------------------------------------------------------------------===
+//===----------------------------------------------------------------------===//
 
-#include "llvm/iOther.h"
+#include "ReaderInternals.h"
 #include "llvm/iTerminators.h"
 #include "llvm/iMemory.h"
-#include "llvm/DerivedTypes.h"
-#include "ReaderInternals.h"
+#include "llvm/iPHINode.h"
+#include "llvm/iOther.h"
+#include "llvm/Module.h"
+using namespace llvm;
 
-bool BytecodeParser::ParseRawInst(const uchar *&Buf, const uchar *EndBuf, 
-                                 RawInst &Result) {
-  unsigned Op, Typ;
-  if (read(Buf, EndBuf, Op)) return failure(true);
+namespace {
+  struct RawInst {       // The raw fields out of the bytecode stream...
+    unsigned NumOperands;
+    unsigned Opcode;
+    unsigned Type;
+    
+    RawInst(const unsigned char *&Buf, const unsigned char *EndBuf,
+            std::vector<unsigned> &Args);
+  };
+}
+
+RawInst::RawInst(const unsigned char *&Buf, const unsigned char *EndBuf,
+                 std::vector<unsigned> &Args) {
+  unsigned Op = read(Buf, EndBuf);
 
-  Result.NumOperands =  Op >> 30;
-  Result.Opcode      = (Op >> 24) & 63;
+  // bits   Instruction format:        Common to all formats
+  // --------------------------
+  // 01-00: Opcode type, fixed to 1.
+  // 07-02: Opcode
+  Opcode    = (Op >> 2) & 63;
+  Args.resize((Op >> 0) & 03);
 
-  switch (Result.NumOperands) {
+  switch (Args.size()) {
   case 1:
-    Result.Ty   = getType((Op >> 12) & 4095);
-    Result.Arg1 = Op & 4095;
-    if (Result.Arg1 == 4095)    // Handle special encoding for 0 operands...
-      Result.NumOperands = 0;
+    // bits   Instruction format:
+    // --------------------------
+    // 19-08: Resulting type plane
+    // 31-20: Operand #1 (if set to (2^12-1), then zero operands)
+    //
+    Type    = (Op >>  8) & 4095;
+    Args[0] = (Op >> 20) & 4095;
+    if (Args[0] == 4095)    // Handle special encoding for 0 operands...
+      Args.resize(0);
     break;
   case 2:
-    Result.Ty   = getType((Op >> 16) & 255);
-    Result.Arg1 = (Op >> 8 ) & 255;
-    Result.Arg2 = (Op >> 0 ) & 255;
+    // bits   Instruction format:
+    // --------------------------
+    // 15-08: Resulting type plane
+    // 23-16: Operand #1
+    // 31-24: Operand #2  
+    //
+    Type    = (Op >>  8) & 255;
+    Args[0] = (Op >> 16) & 255;
+    Args[1] = (Op >> 24) & 255;
     break;
   case 3:
-    Result.Ty   = getType((Op >> 18) & 63);
-    Result.Arg1 = (Op >> 12) & 63;
-    Result.Arg2 = (Op >> 6 ) & 63;
-    Result.Arg3 = (Op >> 0 ) & 63;
+    // bits   Instruction format:
+    // --------------------------
+    // 13-08: Resulting type plane
+    // 19-14: Operand #1
+    // 25-20: Operand #2
+    // 31-26: Operand #3
+    //
+    Type    = (Op >>  8) & 63;
+    Args[0] = (Op >> 14) & 63;
+    Args[1] = (Op >> 20) & 63;
+    Args[2] = (Op >> 26) & 63;
     break;
   case 0:
     Buf -= 4;  // Hrm, try this again...
-    if (read_vbr(Buf, EndBuf, Result.Opcode)) return failure(true);
-    if (read_vbr(Buf, EndBuf, Typ)) return failure(true);
-    Result.Ty = getType(Typ);
-    if (read_vbr(Buf, EndBuf, Result.NumOperands)) return failure(true);
-
-    switch (Result.NumOperands) {
-    case 0: 
-      cerr << "Zero Arg instr found!\n"; 
-      return failure(true);  // This encoding is invalid!
-    case 1: 
-      if (read_vbr(Buf, EndBuf, Result.Arg1)) return failure(true);
-      break;
-    case 2:
-      if (read_vbr(Buf, EndBuf, Result.Arg1) || 
-         read_vbr(Buf, EndBuf, Result.Arg2)) return failure(true);
-      break;
-    case 3:
-      if (read_vbr(Buf, EndBuf, Result.Arg1) || 
-         read_vbr(Buf, EndBuf, Result.Arg2) ||
-          read_vbr(Buf, EndBuf, Result.Arg3)) return failure(true);
-      break;
-    default:
-      if (read_vbr(Buf, EndBuf, Result.Arg1) || 
-         read_vbr(Buf, EndBuf, Result.Arg2)) return failure(true);
-
-      // Allocate a vector to hold arguments 3, 4, 5, 6 ...
-      Result.VarArgs = new vector<unsigned>(Result.NumOperands-2);
-      for (unsigned a = 0; a < Result.NumOperands-2; a++)
-       if (read_vbr(Buf, EndBuf, (*Result.VarArgs)[a])) return failure(true);
-      break;
-    }
-    if (align32(Buf, EndBuf)) return failure(true);
+    Opcode = read_vbr_uint(Buf, EndBuf);
+    Opcode >>= 2;
+    Type = read_vbr_uint(Buf, EndBuf);
+
+    unsigned NumOperands = read_vbr_uint(Buf, EndBuf);
+    Args.resize(NumOperands);
+
+    if (NumOperands == 0)
+      throw std::string("Zero-argument instruction found; this is invalid.");
+
+    for (unsigned i = 0; i != NumOperands; ++i)
+      Args[i] = read_vbr_uint(Buf, EndBuf);
+    align32(Buf, EndBuf);
     break;
   }
-
-#if 0
-  cerr << "NO: "  << Result.NumOperands   << " opcode: " << Result.Opcode 
-       << " Ty: " << Result.Ty->getDescription() << " arg1: "   << Result.Arg1 
-       << " arg2: "   << Result.Arg2 << " arg3: "   << Result.Arg3 << endl;
-#endif
-  return false;
 }
 
 
-bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
-                                     Instruction *&Res) {
-  RawInst Raw;
-  if (ParseRawInst(Buf, EndBuf, Raw)) return failure(true);
-
-  if (Raw.Opcode >= Instruction::FirstUnaryOp && 
-      Raw.Opcode <  Instruction::NumUnaryOps  && Raw.NumOperands == 1) {
-    Res = UnaryOperator::create((Instruction::UnaryOps)Raw.Opcode,
-                               getValue(Raw.Ty,Raw.Arg1));
-    return false;
-  } else if (Raw.Opcode >= Instruction::FirstBinaryOp &&
-            Raw.Opcode <  Instruction::NumBinaryOps  && Raw.NumOperands == 2) {
-    Res = BinaryOperator::create((Instruction::BinaryOps)Raw.Opcode,
-                                getValue(Raw.Ty, Raw.Arg1),
-                                getValue(Raw.Ty, Raw.Arg2));
-    return false;
-  } 
-
-  Value *V;
-  switch (Raw.Opcode) {
-  case Instruction::Cast:
-    Res = new CastInst(getValue(Raw.Ty, Raw.Arg1), getType(Raw.Arg2));
-    return false;
-
-  case Instruction::PHINode: {
-    PHINode *PN = new PHINode(Raw.Ty);
-    switch (Raw.NumOperands) {
-    case 0: 
-    case 1: 
-    case 3: cerr << "Invalid phi node encountered!\n"; 
-            delete PN; 
-           return failure(true);
-    case 2: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1),
-                           (BasicBlock*)getValue(Type::LabelTy, Raw.Arg2)); 
-      break;
-    default:
-      PN->addIncoming(getValue(Raw.Ty, Raw.Arg1), 
-                     (BasicBlock*)getValue(Type::LabelTy, Raw.Arg2));
-      if (Raw.VarArgs->size() & 1) {
-       cerr << "PHI Node with ODD number of arguments!\n";
-       delete PN;
-       return failure(true);
-      } else {
-        vector<unsigned> &args = *Raw.VarArgs;
-        for (unsigned i = 0; i < args.size(); i+=2)
-          PN->addIncoming(getValue(Raw.Ty, args[i]),
-                         (BasicBlock*)getValue(Type::LabelTy, args[i+1]));
+void BytecodeParser::ParseInstruction(const unsigned char *&Buf,
+                                      const unsigned char *EndBuf,
+                                      std::vector<unsigned> &Args,
+                                      BasicBlock *BB) {
+  Args.clear();
+  RawInst RI(Buf, EndBuf, Args);
+  const Type *InstTy = getType(RI.Type);
+
+  Instruction *Result = 0;
+  if (RI.Opcode >= Instruction::BinaryOpsBegin &&
+      RI.Opcode <  Instruction::BinaryOpsEnd  && Args.size() == 2)
+    Result = BinaryOperator::create((Instruction::BinaryOps)RI.Opcode,
+                                    getValue(RI.Type, Args[0]),
+                                    getValue(RI.Type, Args[1]));
+
+  switch (RI.Opcode) {
+  default: 
+    if (Result == 0) throw std::string("Illegal instruction read!");
+    break;
+  case Instruction::VAArg:
+    Result = new VAArgInst(getValue(RI.Type, Args[0]), getType(Args[1]));
+    break;
+  case Instruction::VANext:
+    if (!hasOldStyleVarargs) {
+      Result = new VANextInst(getValue(RI.Type, Args[0]), getType(Args[1]));
+    } else {
+      // In the old-style varargs scheme, this was the "va_arg" instruction.
+      // Emit emulation code now.
+      if (!usesOldStyleVarargs) {
+        usesOldStyleVarargs = true;
+        std::cerr << "WARNING: this bytecode file uses obsolete features.  "
+                  << "Disassemble and assemble to update it.\n";
       }
-      delete Raw.VarArgs; 
-      break;
+
+      Value *VAListPtr = getValue(RI.Type, Args[0]);
+      const Type *ArgTy = getType(Args[1]);
+
+      // First, load the valist...
+      Instruction *CurVAList = new LoadInst(VAListPtr, "");
+      BB->getInstList().push_back(CurVAList);
+      
+      // Construct the vaarg
+      Result = new VAArgInst(CurVAList, ArgTy);
+      
+      // Now we must advance the pointer and update it in memory.
+      Instruction *TheVANext = new VANextInst(CurVAList, ArgTy);
+      BB->getInstList().push_back(TheVANext);
+      
+      BB->getInstList().push_back(new StoreInst(TheVANext, VAListPtr));
     }
-    Res = PN;
-    return false;
+
+    break;
+  case Instruction::Cast:
+    Result = new CastInst(getValue(RI.Type, Args[0]), getType(Args[1]));
+    break;
+  case Instruction::PHI: {
+    if (Args.size() == 0 || (Args.size() & 1))
+      throw std::string("Invalid phi node encountered!\n");
+
+    PHINode *PN = new PHINode(InstTy);
+    PN->op_reserve(Args.size());
+    for (unsigned i = 0, e = Args.size(); i != e; i += 2)
+      PN->addIncoming(getValue(RI.Type, Args[i]), getBasicBlock(Args[i+1]));
+    Result = PN;
+    break;
   }
 
   case Instruction::Shl:
   case Instruction::Shr:
-    Res = new ShiftInst((Instruction::OtherOps)Raw.Opcode,
-                       getValue(Raw.Ty, Raw.Arg1),
-                       getValue(Type::UByteTy, Raw.Arg2));
-    return false;
+    Result = new ShiftInst((Instruction::OtherOps)RI.Opcode,
+                           getValue(RI.Type, Args[0]),
+                           getValue(Type::UByteTyID, Args[1]));
+    break;
   case Instruction::Ret:
-    if (Raw.NumOperands == 0) {
-      Res = new ReturnInst(); return false; 
-    } else if (Raw.NumOperands == 1) {
-      Res = new ReturnInst(getValue(Raw.Ty, Raw.Arg1)); return false; 
-    }
+    if (Args.size() == 0)
+      Result = new ReturnInst();
+    else if (Args.size() == 1)
+      Result = new ReturnInst(getValue(RI.Type, Args[0]));
+    else
+      throw std::string("Unrecognized instruction!");
     break;
 
   case Instruction::Br:
-    if (Raw.NumOperands == 1) {
-      Res = new BranchInst((BasicBlock*)getValue(Type::LabelTy, Raw.Arg1));
-      return false;
-    } else if (Raw.NumOperands == 3) {
-      Res = new BranchInst((BasicBlock*)getValue(Type::LabelTy, Raw.Arg1),
-                          (BasicBlock*)getValue(Type::LabelTy, Raw.Arg2),
-                                       getValue(Type::BoolTy , Raw.Arg3));
-      return false;
-    }
+    if (Args.size() == 1)
+      Result = new BranchInst(getBasicBlock(Args[0]));
+    else if (Args.size() == 3)
+      Result = new BranchInst(getBasicBlock(Args[0]), getBasicBlock(Args[1]),
+                              getValue(Type::BoolTyID , Args[2]));
+    else
+      throw std::string("Invalid number of operands for a 'br' instruction!");
     break;
-    
   case Instruction::Switch: {
-    SwitchInst *I = 
-      new SwitchInst(getValue(Raw.Ty, Raw.Arg1), 
-                     (BasicBlock*)getValue(Type::LabelTy, Raw.Arg2));
-    Res = I;
-    if (Raw.NumOperands < 3) return false;  // No destinations?  Wierd.
-
-    if (Raw.NumOperands == 3 || Raw.VarArgs->size() & 1) {
-      cerr << "Switch statement with odd number of arguments!\n";
-      delete I;
-      return failure(true);
-    }      
-    
-    vector<unsigned> &args = *Raw.VarArgs;
-    for (unsigned i = 0; i < args.size(); i += 2)
-      I->dest_push_back((ConstPoolVal*)getValue(Raw.Ty, args[i]),
-                        (BasicBlock*)getValue(Type::LabelTy, args[i+1]));
+    if (Args.size() & 1)
+      throw std::string("Switch statement with odd number of arguments!");
 
-    delete Raw.VarArgs;
-    return false;
+    SwitchInst *I = new SwitchInst(getValue(RI.Type, Args[0]),
+                                   getBasicBlock(Args[1]));
+    for (unsigned i = 2, e = Args.size(); i != e; i += 2)
+      I->addCase(cast<Constant>(getValue(RI.Type, Args[i])),
+                 getBasicBlock(Args[i+1]));
+    Result = I;
+    break;
   }
 
   case Instruction::Call: {
-    Method *M = (Method*)getValue(Raw.Ty, Raw.Arg1);
-    if (M == 0) return failure(true);
-
-    vector<Value *> Params;
-    const MethodType::ParamTypes &PL = M->getType()->getParamTypes();
-
-    if (!M->getType()->isVarArg()) {
-      MethodType::ParamTypes::const_iterator It = PL.begin();
-
-      switch (Raw.NumOperands) {
-      case 0: cerr << "Invalid call instruction encountered!\n";
-       return failure(true);
-      case 1: break;
-      case 2: Params.push_back(getValue(*It++, Raw.Arg2)); break;
-      case 3: Params.push_back(getValue(*It++, Raw.Arg2)); 
-       if (It == PL.end()) return failure(true);
-       Params.push_back(getValue(*It++, Raw.Arg3)); break;
-      default:
-       Params.push_back(getValue(*It++, Raw.Arg2));
-       {
-         vector<unsigned> &args = *Raw.VarArgs;
-         for (unsigned i = 0; i < args.size(); i++) {
-           if (It == PL.end()) return failure(true);
-           // TODO: Check getValue for null!
-           Params.push_back(getValue(*It++, args[i]));
-         }
-       }
-       delete Raw.VarArgs;
+    if (Args.size() == 0)
+      throw std::string("Invalid call instruction encountered!");
+
+    Value *F = getValue(RI.Type, Args[0]);
+
+    // Check to make sure we have a pointer to function type
+    const PointerType *PTy = dyn_cast<PointerType>(F->getType());
+    if (PTy == 0) throw std::string("Call to non function pointer value!");
+    const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType());
+    if (FTy == 0) throw std::string("Call to non function pointer value!");
+
+    std::vector<Value *> Params;
+    if (!FTy->isVarArg()) {
+      FunctionType::param_iterator It = FTy->param_begin();
+
+      for (unsigned i = 1, e = Args.size(); i != e; ++i) {
+        if (It == FTy->param_end())
+          throw std::string("Invalid call instruction!");
+        Params.push_back(getValue(getTypeSlot(*It++), Args[i]));
       }
-      if (It != PL.end()) return failure(true);
+      if (It != FTy->param_end())
+        throw std::string("Invalid call instruction!");
     } else {
-      // The first parameter does not have a type specifier... because there
-      // must be at least one concrete argument to a vararg type...
-      Params.push_back(getValue(PL.front(), Raw.Arg2));
-
-      vector<unsigned> &args = *Raw.VarArgs;
-      if ((args.size() & 1) != 0)
-       return failure(true);  // Must be pairs of type/value
-      for (unsigned i = 0; i < args.size(); i+=2) {
-       // TODO: Check getValue for null!
-       Params.push_back(getValue(getType(args[i]), args[i+1]));
+      Args.erase(Args.begin(), Args.begin()+1+hasVarArgCallPadding);
+
+      unsigned FirstVariableOperand;
+      if (!hasVarArgCallPadding) {
+        if (Args.size() < FTy->getNumParams())
+          throw std::string("Call instruction missing operands!");
+
+        // Read all of the fixed arguments
+        for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
+          Params.push_back(getValue(getTypeSlot(FTy->getParamType(i)),Args[i]));
+
+        FirstVariableOperand = FTy->getNumParams();
+      } else {
+        FirstVariableOperand = 0;
       }
-      delete Raw.VarArgs;
+
+      if ((Args.size()-FirstVariableOperand) & 1) // Must be pairs of type/value
+        throw std::string("Invalid call instruction!");
+        
+      for (unsigned i = FirstVariableOperand, e = Args.size(); i != e; i += 2)
+        Params.push_back(getValue(Args[i], Args[i+1]));
     }
 
-    Res = new CallInst(M, Params);
-    return false;
+    Result = new CallInst(F, Params);
+    break;
+  }
+  case Instruction::Invoke: {
+    if (Args.size() < 3) throw std::string("Invalid invoke instruction!");
+    Value *F = getValue(RI.Type, Args[0]);
+
+    // Check to make sure we have a pointer to function type
+    const PointerType *PTy = dyn_cast<PointerType>(F->getType());
+    if (PTy == 0) throw std::string("Invoke to non function pointer value!");
+    const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType());
+    if (FTy == 0) throw std::string("Invoke to non function pointer value!");
+
+    std::vector<Value *> Params;
+    BasicBlock *Normal, *Except;
+
+    if (!FTy->isVarArg()) {
+      Normal = getBasicBlock(Args[1]);
+      Except = getBasicBlock(Args[2]);
+
+      FunctionType::param_iterator It = FTy->param_begin();
+      for (unsigned i = 3, e = Args.size(); i != e; ++i) {
+        if (It == FTy->param_end())
+          throw std::string("Invalid invoke instruction!");
+        Params.push_back(getValue(getTypeSlot(*It++), Args[i]));
+      }
+      if (It != FTy->param_end())
+        throw std::string("Invalid invoke instruction!");
+    } else {
+      Args.erase(Args.begin(), Args.begin()+1+hasVarArgCallPadding);
+
+      unsigned FirstVariableArgument;
+      if (!hasVarArgCallPadding) {
+        Normal = getBasicBlock(Args[0]);
+        Except = getBasicBlock(Args[1]);
+
+        FirstVariableArgument = FTy->getNumParams()+2;
+        for (unsigned i = 2; i != FirstVariableArgument; ++i)
+          Params.push_back(getValue(getTypeSlot(FTy->getParamType(i-2)),
+                                    Args[i]));
+          
+      } else {
+        if (Args.size() < 4) throw std::string("Invalid invoke instruction!");
+        if (Args[0] != Type::LabelTyID || Args[2] != Type::LabelTyID)
+          throw std::string("Invalid invoke instruction!");
+        Normal = getBasicBlock(Args[1]);
+        Except = getBasicBlock(Args[3]);
+
+        FirstVariableArgument = 4;
+      }
+
+      if (Args.size()-FirstVariableArgument & 1)  // Must be pairs of type/value
+        throw std::string("Invalid invoke instruction!");
+
+      for (unsigned i = FirstVariableArgument; i < Args.size(); i += 2)
+        Params.push_back(getValue(Args[i], Args[i+1]));
+    }
+
+    Result = new InvokeInst(F, Normal, Except, Params);
+    break;
   }
   case Instruction::Malloc:
-    if (Raw.NumOperands > 2) return failure(true);
-    V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0;
-    Res = new MallocInst(Raw.Ty, V);
-    return false;
+    if (Args.size() > 2) throw std::string("Invalid malloc instruction!");
+    if (!isa<PointerType>(InstTy))
+      throw std::string("Invalid malloc instruction!");
+
+    Result = new MallocInst(cast<PointerType>(InstTy)->getElementType(),
+                            Args.size() ? getValue(Type::UIntTyID,
+                                                   Args[0]) : 0);
+    break;
 
   case Instruction::Alloca:
-    if (Raw.NumOperands > 2) return failure(true);
-    V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0;
-    Res = new AllocaInst(Raw.Ty, V);
-    return false;
+    if (Args.size() > 2) throw std::string("Invalid alloca instruction!");
+    if (!isa<PointerType>(InstTy))
+      throw std::string("Invalid alloca instruction!");
 
+    Result = new AllocaInst(cast<PointerType>(InstTy)->getElementType(),
+                            Args.size() ? getValue(Type::UIntTyID, Args[0]) :0);
+    break;
   case Instruction::Free:
-    V = getValue(Raw.Ty, Raw.Arg1);
-    if (!V->getType()->isPointerType()) return failure(true);
-    Res = new FreeInst(V);
-    return false;
-
-  case Instruction::Load:
+    if (!isa<PointerType>(InstTy))
+      throw std::string("Invalid free instruction!");
+    Result = new FreeInst(getValue(RI.Type, Args[0]));
+    break;
   case Instruction::GetElementPtr: {
-    vector<ConstPoolVal*> Idx;
-    switch (Raw.NumOperands) {
-    case 0: cerr << "Invalid load encountered!\n"; return failure(true);
-    case 1: break;
-    case 2: V = getValue(Type::UByteTy, Raw.Arg2);
-            if (!isa<ConstPoolVal>(V)) return failure(true);
-            Idx.push_back(cast<ConstPoolVal>(V));
-            break;
-    case 3: V = getValue(Type::UByteTy, Raw.Arg2);
-            if (!isa<ConstPoolVal>(V)) return failure(true);
-            Idx.push_back(cast<ConstPoolVal>(V));
-           V = getValue(Type::UByteTy, Raw.Arg3);
-            if (!isa<ConstPoolVal>(V)) return failure(true);
-            Idx.push_back(cast<ConstPoolVal>(V));
-            break;
-    default:
-      V = getValue(Type::UByteTy, Raw.Arg2);
-      if (!isa<ConstPoolVal>(V)) return failure(true);
-      Idx.push_back(cast<ConstPoolVal>(V));
-      vector<unsigned> &args = *Raw.VarArgs;
-      for (unsigned i = 0, E = args.size(); i != E; ++i) {
-       V = getValue(Type::UByteTy, args[i]);
-       if (!isa<ConstPoolVal>(V)) return failure(true);
-       Idx.push_back(cast<ConstPoolVal>(V));
-      }
-      delete Raw.VarArgs; 
-      break;
+    if (Args.size() == 0 || !isa<PointerType>(InstTy))
+      throw std::string("Invalid getelementptr instruction!");
+
+    std::vector<Value*> Idx;
+
+    const Type *NextTy = InstTy;
+    for (unsigned i = 1, e = Args.size(); i != e; ++i) {
+      const CompositeType *TopTy = dyn_cast_or_null<CompositeType>(NextTy);
+      if (!TopTy) throw std::string("Invalid getelementptr instruction!"); 
+      // FIXME: when PR82 is resolved.
+      unsigned IdxTy = isa<StructType>(TopTy) ? Type::UByteTyID :Type::LongTyID;
+        
+      Idx.push_back(getValue(IdxTy, Args[i]));
+      NextTy = GetElementPtrInst::getIndexedType(InstTy, Idx, true);
     }
-    if (Raw.Opcode == Instruction::Load)
-      Res = new LoadInst(getValue(Raw.Ty, Raw.Arg1), Idx);
-    else if (Raw.Opcode == Instruction::GetElementPtr)
-      Res = new GetElementPtrInst(getValue(Raw.Ty, Raw.Arg1), Idx);
-    else
-      abort();
-    return false;
+
+    Result = new GetElementPtrInst(getValue(RI.Type, Args[0]), Idx);
+    break;
   }
+
+  case 62:   // volatile load
+  case Instruction::Load:
+    if (Args.size() != 1 || !isa<PointerType>(InstTy))
+      throw std::string("Invalid load instruction!");
+    Result = new LoadInst(getValue(RI.Type, Args[0]), "", RI.Opcode == 62);
+    break;
+
+  case 63:   // volatile store 
   case Instruction::Store: {
-    vector<ConstPoolVal*> Idx;
-    switch (Raw.NumOperands) {
-    case 0: 
-    case 1: cerr << "Invalid store encountered!\n"; return failure(true);
-    case 2: break;
-    case 3: V = getValue(Type::UByteTy, Raw.Arg3);
-            if (!isa<ConstPoolVal>(V)) return failure(true);
-            Idx.push_back(cast<ConstPoolVal>(V));
-            break;
-    default:
-      vector<unsigned> &args = *Raw.VarArgs;
-      for (unsigned i = 0, E = args.size(); i != E; ++i) {
-       V = getValue(Type::UByteTy, args[i]);
-       if (!isa<ConstPoolVal>(V)) return failure(true);
-       Idx.push_back(cast<ConstPoolVal>(V));
-      }
-      delete Raw.VarArgs; 
-      break;
-    }
+    if (!isa<PointerType>(InstTy) || Args.size() != 2)
+      throw std::string("Invalid store instruction!");
 
-    const Type *ElType = StoreInst::getIndexedType(Raw.Ty, Idx);
-    if (ElType == 0) return failure(true);
-    Res = new StoreInst(getValue(ElType, Raw.Arg1), getValue(Raw.Ty, Raw.Arg2),
-                       Idx);
-    return false;
+    Value *Ptr = getValue(RI.Type, Args[1]);
+    const Type *ValTy = cast<PointerType>(Ptr->getType())->getElementType();
+    Result = new StoreInst(getValue(getTypeSlot(ValTy), Args[0]), Ptr,
+                           RI.Opcode == 63);
+    break;
   }
-  }  // end switch(Raw.Opcode) 
+  case Instruction::Unwind:
+    if (Args.size() != 0) throw std::string("Invalid unwind instruction!");
+    Result = new UnwindInst();
+    break;
+  }  // end switch(RI.Opcode) 
+
+  unsigned TypeSlot;
+  if (Result->getType() == InstTy)
+    TypeSlot = RI.Type;
+  else
+    TypeSlot = getTypeSlot(Result->getType());
 
-  cerr << "Unrecognized instruction! " << Raw.Opcode 
-       << " ADDR = 0x" << (void*)Buf << endl;
-  return failure(true);
+  insertValue(Result, TypeSlot, Values);
+  BB->getInstList().push_back(Result);
+  BCR_TRACE(4, *Result);
 }