add reader support for a bunch of new instructions
[oota-llvm.git] / lib / Bitcode / Reader / BitcodeReader.cpp
index 9bc4f810be63f6f945fccdb2c8b357f5e9554ad9..0090d1fd0855da8f1f04f5ff9a53f2b5f5642a42 100644 (file)
@@ -150,6 +150,9 @@ Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) {
     return V;
   }
   
+  // No type specified, must be invalid reference.
+  if (Ty == 0) return 0;
+  
   // Create and return a placeholder, which will later be RAUW'd.
   Value *V = new Argument(Ty);
   Uses[Idx].init(V, this);
@@ -1006,7 +1009,9 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
     ValueList.push_back(I);
   
   unsigned NextValueNo = ValueList.size();
-  
+  BasicBlock *CurBB = 0;
+  unsigned CurBBNo = 0;
+
   // Read all the records.
   SmallVector<uint64_t, 64> Record;
   while (1) {
@@ -1042,8 +1047,6 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
     // Read a record.
     Record.clear();
     Instruction *I = 0;
-    BasicBlock *CurBB = 0;
-    unsigned CurBBNo = 0;
     switch (Stream.ReadRecord(Code, Record)) {
     default: // Default behavior: reject
       return Error("Unknown instruction");
@@ -1057,8 +1060,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
       CurBB = FunctionBBs[0];
       continue;
       
-    case bitc::FUNC_CODE_INST_BINOP: {
-      // BINOP:      [opcode, ty, opval, opval]
+    case bitc::FUNC_CODE_INST_BINOP: {    // BINOP: [opcode, ty, opval, opval]
       if (Record.size() < 4) return Error("Invalid BINOP record");
       const Type *Ty = getTypeByID(Record[1]);
       int Opc = GetDecodedBinaryOpcode(Record[0], Ty);
@@ -1069,35 +1071,132 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
       I = BinaryOperator::create((Instruction::BinaryOps)Opc, LHS, RHS);
       break;
     }
+    case bitc::FUNC_CODE_INST_CAST: {    // CAST: [opcode, ty, opty, opval]
+      if (Record.size() < 4) return Error("Invalid CAST record");
+      int Opc = GetDecodedCastOpcode(Record[0]);
+      const Type *ResTy = getTypeByID(Record[1]);
+      const Type *OpTy = getTypeByID(Record[2]);
+      Value *Op = getFnValueByID(Record[3], OpTy);
+      if (Opc == -1 || ResTy == 0 || OpTy == 0 || Op == 0)
+        return Error("Invalid CAST record");
+      I = CastInst::create((Instruction::CastOps)Opc, Op, ResTy);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_GEP: { // GEP: [n, n x operands]
+      if (Record.size() < 2 || (Record.size() & 1))
+        return Error("Invalid GEP record");
+      const Type *OpTy = getTypeByID(Record[0]);
+      Value *Op = getFnValueByID(Record[1], OpTy);
+      if (OpTy == 0 || Op == 0)
+        return Error("Invalid GEP record");
+
+      SmallVector<Value*, 8> GEPIdx;
+      for (unsigned i = 1, e = Record.size()/2; i != e; ++i) {
+        const Type *IdxTy = getTypeByID(Record[i*2]);
+        Value *Idx = getFnValueByID(Record[i*2+1], IdxTy);
+        if (IdxTy == 0 || Idx == 0)
+          return Error("Invalid GEP record");
+        GEPIdx.push_back(Idx);
+      }
+
+      I = new GetElementPtrInst(Op, &GEPIdx[0], GEPIdx.size());
+      break;
+    }
+      
+    case bitc::FUNC_CODE_INST_SELECT: { // SELECT: [ty, opval, opval, opval]
+      if (Record.size() < 4) return Error("Invalid SELECT record");
+      const Type *Ty = getTypeByID(Record[0]);
+      Value *Cond = getFnValueByID(Record[1], Type::Int1Ty);
+      Value *LHS = getFnValueByID(Record[2], Ty);
+      Value *RHS = getFnValueByID(Record[3], Ty);
+      if (Ty == 0 || Cond == 0 || LHS == 0 || RHS == 0)
+        return Error("Invalid SELECT record");
+      I = new SelectInst(Cond, LHS, RHS);
+      break;
+    }
+      
+    case bitc::FUNC_CODE_INST_EXTRACTELT: { // EXTRACTELT: [opty, opval, opval]
+      if (Record.size() < 3) return Error("Invalid EXTRACTELT record");
+      const Type *OpTy = getTypeByID(Record[0]);
+      Value *Vec = getFnValueByID(Record[1], OpTy);
+      Value *Idx = getFnValueByID(Record[2], Type::Int32Ty);
+      if (OpTy == 0 || Vec == 0 || Idx == 0)
+        return Error("Invalid EXTRACTELT record");
+      I = new ExtractElementInst(Vec, Idx);
+      break;
+    }
+      
+    case bitc::FUNC_CODE_INST_INSERTELT: { // INSERTELT: [ty, opval,opval,opval]
+      if (Record.size() < 4) return Error("Invalid INSERTELT record");
+      const VectorType *OpTy = 
+        dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
+      if (OpTy == 0) return Error("Invalid INSERTELT record");
+      Value *Vec = getFnValueByID(Record[1], OpTy);
+      Value *Elt = getFnValueByID(Record[2], OpTy->getElementType());
+      Value *Idx = getFnValueByID(Record[3], Type::Int32Ty);
+      if (Vec == 0 || Elt == 0 || Idx == 0)
+        return Error("Invalid INSERTELT record");
+      I = new InsertElementInst(Vec, Elt, Idx);
+      break;
+    }
+      
+    case bitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [ty,opval,opval,opval]
+      if (Record.size() < 4) return Error("Invalid SHUFFLEVEC record");
+      const VectorType *OpTy = 
+        dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
+      if (OpTy == 0) return Error("Invalid SHUFFLEVEC record");
+      Value *Vec1 = getFnValueByID(Record[1], OpTy);
+      Value *Vec2 = getFnValueByID(Record[2], OpTy);
+      Value *Mask = getFnValueByID(Record[3],
+                                   VectorType::get(Type::Int32Ty,
+                                                   OpTy->getNumElements()));
+      if (Vec1 == 0 || Vec2 == 0 || Mask == 0)
+        return Error("Invalid SHUFFLEVEC record");
+      I = new ShuffleVectorInst(Vec1, Vec2, Mask);
+      break;
+    }
+      
+    case bitc::FUNC_CODE_INST_CMP: { // CMP: [opty, opval, opval, pred]
+      if (Record.size() < 4) return Error("Invalid CMP record");
+      const Type *OpTy = getTypeByID(Record[0]);
+      Value *LHS = getFnValueByID(Record[1], OpTy);
+      Value *RHS = getFnValueByID(Record[2], OpTy);
+      if (OpTy == 0 || LHS == 0 || RHS == 0)
+        return Error("Invalid CMP record");
+      if (OpTy->isFPOrFPVector())
+        I = new FCmpInst((FCmpInst::Predicate)Record[3], LHS, RHS);
+      else
+        I = new ICmpInst((ICmpInst::Predicate)Record[3], LHS, RHS);
+      break;
+    }
+    
+    case bitc::FUNC_CODE_INST_RET: // RET: [opty,opval<optional>]
+      if (Record.size() == 0) {
+        I = new ReturnInst();
+        break;
+      }
+      if (Record.size() == 2) {
+        const Type *OpTy = getTypeByID(Record[0]);
+        Value *Op = getFnValueByID(Record[1], OpTy);
+        if (OpTy && Op);
+        I = new ReturnInst(Op);
+        break;
+      }
+      return Error("Invalid RET record");
 #if 0
-    case bitc::FUNC_CODE_INST_CAST:
-      // CAST:       [opcode, ty, opty, opval]
-    case bitc::FUNC_CODE_INST_GEP:
-      // GEP:        [n, n x operands]
-    case bitc::FUNC_CODE_INST_SELECT:
-      // SELECT:     [ty, opval, opval, opval]
-    case bitc::FUNC_CODE_INST_EXTRACTELT:
-      // EXTRACTELT: [opty, opval, opval]
-    case bitc::FUNC_CODE_INST_INSERTELT:
-      // INSERTELT:  [ty, opval, opval, opval]
-    case bitc::FUNC_CODE_INST_SHUFFLEVEC:
-      // SHUFFLEVEC: [ty, opval, opval, opval]
-    case bitc::FUNC_CODE_INST_CMP:
-      // CMP:        [opty, opval, opval, pred]
-        
-    case bitc::FUNC_CODE_INST_RET:
-      // RET:        [opty,opval<optional>]
     case bitc::FUNC_CODE_INST_BR:
       // BR:         [opval, bb#, bb#] or [bb#]
     case bitc::FUNC_CODE_INST_SWITCH:
       // SWITCH:     [opty, opval, n, n x ops]
     case bitc::FUNC_CODE_INST_INVOKE:
       // INVOKE:     [fnty, op0,op1,op2, ...]
-    case bitc::FUNC_CODE_INST_UNWIND:
-      // UNWIND
-    case bitc::FUNC_CODE_INST_UNREACHABLE:
-      // UNREACHABLE
-        
+    case bitc::FUNC_CODE_INST_UNWIND: // UNWIND
+      I = new UnwindInst();
+      break;
+    case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE
+      I = new UnreachableInst();
+      break;
+
     case bitc::FUNC_CODE_INST_PHI:
       // PHI:        [ty, #ops, val0,bb0, ...]
     case bitc::FUNC_CODE_INST_MALLOC: