Read volatile loads/stores
[oota-llvm.git] / lib / Bytecode / Reader / InstructionReader.cpp
index 0916b2b876aaa8847606cebcd9161a3db129cb4b..603c20564caa0b7aeea5a1fab00cebc296af31a0 100644 (file)
 #include "llvm/iMemory.h"
 #include "llvm/iPHINode.h"
 #include "llvm/iOther.h"
-#include <iostream>
-using std::vector;
-using std::cerr;
 
-bool BytecodeParser::ParseRawInst(const uchar *&Buf, const uchar *EndBuf, 
+bool BytecodeParser::ParseRawInst(const unsigned char *&Buf,
+                                  const unsigned char *EndBuf, 
                                  RawInst &Result) {
   unsigned Op, Typ;
-  if (read(Buf, EndBuf, Op)) return failure(true);
+  if (read(Buf, EndBuf, Op)) return true;
 
   // bits   Instruction format:        Common to all formats
   // --------------------------
@@ -70,65 +68,61 @@ bool BytecodeParser::ParseRawInst(const uchar *&Buf, const uchar *EndBuf,
     break;
   case 0:
     Buf -= 4;  // Hrm, try this again...
-    if (read_vbr(Buf, EndBuf, Result.Opcode)) return failure(true);
+    if (read_vbr(Buf, EndBuf, Result.Opcode)) return true;
     Result.Opcode >>= 2;
-    if (read_vbr(Buf, EndBuf, Typ)) return failure(true);
+    if (read_vbr(Buf, EndBuf, Typ)) return true;
     Result.Ty = getType(Typ);
-    if (Result.Ty == 0) return failure(true);
-    if (read_vbr(Buf, EndBuf, Result.NumOperands)) return failure(true);
+    if (Result.Ty == 0) return true;
+    if (read_vbr(Buf, EndBuf, Result.NumOperands)) return true;
 
     switch (Result.NumOperands) {
     case 0: 
-      cerr << "Zero Arg instr found!\n"; 
-      return failure(true);  // This encoding is invalid!
+      std::cerr << "Zero Arg instr found!\n"; 
+      return true;  // This encoding is invalid!
     case 1: 
-      if (read_vbr(Buf, EndBuf, Result.Arg1)) return failure(true);
+      if (read_vbr(Buf, EndBuf, Result.Arg1)) return true;
       break;
     case 2:
       if (read_vbr(Buf, EndBuf, Result.Arg1) || 
-         read_vbr(Buf, EndBuf, Result.Arg2)) return failure(true);
+         read_vbr(Buf, EndBuf, Result.Arg2)) return 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);
+          read_vbr(Buf, EndBuf, Result.Arg3)) return true;
       break;
     default:
       if (read_vbr(Buf, EndBuf, Result.Arg1) || 
-         read_vbr(Buf, EndBuf, Result.Arg2)) return failure(true);
+         read_vbr(Buf, EndBuf, Result.Arg2)) return true;
 
       // Allocate a vector to hold arguments 3, 4, 5, 6 ...
-      Result.VarArgs = new vector<unsigned>(Result.NumOperands-2);
+      Result.VarArgs = new std::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);
+       if (read_vbr(Buf, EndBuf, (*Result.VarArgs)[a])) return true;
       break;
     }
-    if (align32(Buf, EndBuf)) return failure(true);
+    if (align32(Buf, EndBuf)) return true;
     break;
   }
 
 #if 0
-  cerr << "NO: "  << Result.NumOperands   << " opcode: " << Result.Opcode 
-       << " Ty: " << Result.Ty->getDescription() << " arg1: "   << Result.Arg1 
-       << " arg2: "   << Result.Arg2 << " arg3: "   << Result.Arg3 << "\n";
+  std::cerr << "NO: "  << Result.NumOperands   << " opcode: " << Result.Opcode 
+            << " Ty: " << Result.Ty->getDescription() << " arg1: "<< Result.Arg1
+            << " arg2: "   << Result.Arg2 << " arg3: "   << Result.Arg3 << "\n";
 #endif
   return false;
 }
 
 
-bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
+bool BytecodeParser::ParseInstruction(const unsigned char *&Buf,
+                                      const unsigned char *EndBuf,
                                      Instruction *&Res) {
   RawInst Raw;
   if (ParseRawInst(Buf, EndBuf, Raw))
-    return failure(true);
+    return 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) {
+  if (Raw.Opcode >= Instruction::BinaryOpsBegin &&
+      Raw.Opcode <  Instruction::BinaryOpsEnd  && Raw.NumOperands == 2) {
     Res = BinaryOperator::create((Instruction::BinaryOps)Raw.Opcode,
                                 getValue(Raw.Ty, Raw.Arg1),
                                 getValue(Raw.Ty, Raw.Arg2));
@@ -137,11 +131,15 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
 
   Value *V;
   switch (Raw.Opcode) {
+  case Instruction::VarArg:
   case Instruction::Cast: {
     V = getValue(Raw.Ty, Raw.Arg1);
     const Type *Ty = getType(Raw.Arg2);
-    if (V == 0 || Ty == 0) { cerr << "Invalid cast!\n"; return true; }
-    Res = new CastInst(V, Ty);
+    if (V == 0 || Ty == 0) { std::cerr << "Invalid cast!\n"; return true; }
+    if (Raw.Opcode == Instruction::Cast)
+      Res = new CastInst(V, Ty);
+    else
+      Res = new VarArgInst(V, Ty);
     return false;
   }
   case Instruction::PHINode: {
@@ -149,9 +147,9 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
     switch (Raw.NumOperands) {
     case 0: 
     case 1: 
-    case 3: cerr << "Invalid phi node encountered!\n"; 
+    case 3: std::cerr << "Invalid phi node encountered!\n"; 
             delete PN; 
-           return failure(true);
+           return true;
     case 2: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1),
                            cast<BasicBlock>(getValue(Type::LabelTy,Raw.Arg2)));
       break;
@@ -159,11 +157,11 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
       PN->addIncoming(getValue(Raw.Ty, Raw.Arg1), 
                      cast<BasicBlock>(getValue(Type::LabelTy, Raw.Arg2)));
       if (Raw.VarArgs->size() & 1) {
-       cerr << "PHI Node with ODD number of arguments!\n";
+       std::cerr << "PHI Node with ODD number of arguments!\n";
        delete PN;
-       return failure(true);
+       return true;
       } else {
-        vector<unsigned> &args = *Raw.VarArgs;
+        std::vector<unsigned> &args = *Raw.VarArgs;
         for (unsigned i = 0; i < args.size(); i+=2)
           PN->addIncoming(getValue(Raw.Ty, args[i]),
                          cast<BasicBlock>(getValue(Type::LabelTy, args[i+1])));
@@ -209,241 +207,223 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
     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";
+      std::cerr << "Switch statement with odd number of arguments!\n";
       delete I;
-      return failure(true);
+      return true;
     }      
     
-    vector<unsigned> &args = *Raw.VarArgs;
+    std::vector<unsigned> &args = *Raw.VarArgs;
     for (unsigned i = 0; i < args.size(); i += 2)
-      I->dest_push_back(cast<Constant>(getValue(Raw.Ty, args[i])),
-                        cast<BasicBlock>(getValue(Type::LabelTy, args[i+1])));
+      I->addCase(cast<Constant>(getValue(Raw.Ty, args[i])),
+                 cast<BasicBlock>(getValue(Type::LabelTy, args[i+1])));
 
     delete Raw.VarArgs;
     return false;
   }
 
   case Instruction::Call: {
-    Value *M = getValue(Raw.Ty, Raw.Arg1);
-    if (M == 0) return failure(true);
+    Value *F = getValue(Raw.Ty, Raw.Arg1);
+    if (F == 0) return true;
 
     // Check to make sure we have a pointer to method type
-    const PointerType *PTy = dyn_cast<PointerType>(M->getType());
-    if (PTy == 0) return failure(true);
-    const FunctionType *MTy = dyn_cast<FunctionType>(PTy->getElementType());
-    if (MTy == 0) return failure(true);
+    const PointerType *PTy = dyn_cast<PointerType>(F->getType());
+    if (PTy == 0) return true;
+    const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType());
+    if (FTy == 0) return true;
 
-    vector<Value *> Params;
-    const FunctionType::ParamTypes &PL = MTy->getParamTypes();
+    std::vector<Value *> Params;
+    const FunctionType::ParamTypes &PL = FTy->getParamTypes();
 
-    if (!MTy->isVarArg()) {
+    if (!FTy->isVarArg()) {
       FunctionType::ParamTypes::const_iterator It = PL.begin();
 
       switch (Raw.NumOperands) {
-      case 0: cerr << "Invalid call instruction encountered!\n";
-       return failure(true);
+      case 0: std::cerr << "Invalid call instruction encountered!\n";
+       return 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);
+       if (It == PL.end()) return true;
        Params.push_back(getValue(*It++, Raw.Arg3)); break;
       default:
        Params.push_back(getValue(*It++, Raw.Arg2));
        {
-         vector<unsigned> &args = *Raw.VarArgs;
+         std::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!
+           if (It == PL.end()) return true;
            Params.push_back(getValue(*It++, args[i]));
+            if (Params.back() == 0) return true;
          }
        }
        delete Raw.VarArgs;
       }
-      if (It != PL.end()) return failure(true);
+      if (It != PL.end()) return true;
     } else {
       if (Raw.NumOperands > 2) {
-       vector<unsigned> &args = *Raw.VarArgs;
-       if (args.size() < 1) return failure(true);
+       std::vector<unsigned> &args = *Raw.VarArgs;
+       if (args.size() < 1) return true;
 
        if ((args.size() & 1) != 0)
-         return failure(true);  // Must be pairs of type/value
+         return true;  // Must be pairs of type/value
        for (unsigned i = 0; i < args.size(); i+=2) {
          const Type *Ty = getType(args[i]);
          if (Ty == 0)
-           return failure(true);
+           return true;
          
          Value *V = getValue(Ty, args[i+1]);
-         if (V == 0) return failure(true);
+         if (V == 0) return true;
          Params.push_back(V);
        }
        delete Raw.VarArgs;
       }
     }
 
-    Res = new CallInst(M, Params);
+    Res = new CallInst(F, Params);
     return false;
   }
   case Instruction::Invoke: {
-    Value *M = getValue(Raw.Ty, Raw.Arg1);
-    if (M == 0) return failure(true);
+    Value *F = getValue(Raw.Ty, Raw.Arg1);
+    if (F == 0) return true;
 
     // Check to make sure we have a pointer to method type
-    const PointerType *PTy = dyn_cast<PointerType>(M->getType());
-    if (PTy == 0) return failure(true);
-    const FunctionType *MTy = dyn_cast<FunctionType>(PTy->getElementType());
-    if (MTy == 0) return failure(true);
+    const PointerType *PTy = dyn_cast<PointerType>(F->getType());
+    if (PTy == 0) return true;
+    const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType());
+    if (FTy == 0) return true;
 
-    vector<Value *> Params;
-    const FunctionType::ParamTypes &PL = MTy->getParamTypes();
-    vector<unsigned> &args = *Raw.VarArgs;
+    std::vector<Value *> Params;
+    const FunctionType::ParamTypes &PL = FTy->getParamTypes();
+    std::vector<unsigned> &args = *Raw.VarArgs;
 
     BasicBlock *Normal, *Except;
 
-    if (!MTy->isVarArg()) {
-      if (Raw.NumOperands < 3) return failure(true);
+    if (!FTy->isVarArg()) {
+      if (Raw.NumOperands < 3) return true;
 
       Normal = cast<BasicBlock>(getValue(Type::LabelTy, Raw.Arg2));
-      Except = cast<BasicBlock>(getValue(Type::LabelTy, args[0]));
-
-      FunctionType::ParamTypes::const_iterator It = PL.begin();
-      for (unsigned i = 1; i < args.size(); i++) {
-       if (It == PL.end()) return failure(true);
-       // TODO: Check getValue for null!
-       Params.push_back(getValue(*It++, args[i]));
+      if (Raw.NumOperands == 3)
+        Except = cast<BasicBlock>(getValue(Type::LabelTy, Raw.Arg3));
+      else {
+        Except = cast<BasicBlock>(getValue(Type::LabelTy, args[0]));
+
+        FunctionType::ParamTypes::const_iterator It = PL.begin();
+        for (unsigned i = 1; i < args.size(); i++) {
+          if (It == PL.end()) return true;
+          Params.push_back(getValue(*It++, args[i]));
+          if (Params.back() == 0) return true;
+        }
+        if (It != PL.end()) return true;
       }
-
-      if (It != PL.end()) return failure(true);
     } else {
-      if (args.size() < 4) return failure(true);
-
-      Normal = cast<BasicBlock>(getValue(Type::LabelTy, args[0]));
-      Except = cast<BasicBlock>(getValue(Type::LabelTy, args[2]));
+      if (args.size() < 4) return true;
+      if (getType(args[0]) != Type::LabelTy || 
+          getType(args[2]) != Type::LabelTy) return true;
+      Normal = cast<BasicBlock>(getValue(Type::LabelTy, args[1]));
+      Except = cast<BasicBlock>(getValue(Type::LabelTy, args[3]));
 
       if ((args.size() & 1) != 0)
-       return failure(true);  // Must be pairs of type/value
+       return true;  // Must be pairs of type/value
       for (unsigned i = 4; i < args.size(); i+=2) {
-       // TODO: Check getValue for null!
-       Params.push_back(getValue(getType(args[i]), args[i+1]));
+        Params.push_back(getValue(getType(args[i]), args[i+1]));
+        if (Params.back() == 0) return true;
       }
     }
 
-    delete Raw.VarArgs;
-    Res = new InvokeInst(M, Normal, Except, Params);
+    if (Raw.NumOperands > 3)
+      delete Raw.VarArgs;
+    Res = new InvokeInst(F, Normal, Except, Params);
     return false;
   }
   case Instruction::Malloc:
-    if (Raw.NumOperands > 2) return failure(true);
+    if (Raw.NumOperands > 2) return true;
     V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0;
-    Res = new MallocInst(Raw.Ty, V);
+    if (const PointerType *PTy = dyn_cast<PointerType>(Raw.Ty))
+      Res = new MallocInst(PTy->getElementType(), V);
+    else
+      return true;
     return false;
 
   case Instruction::Alloca:
-    if (Raw.NumOperands > 2) return failure(true);
+    if (Raw.NumOperands > 2) return true;
     V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0;
-    Res = new AllocaInst(Raw.Ty, V);
+    if (const PointerType *PTy = dyn_cast<PointerType>(Raw.Ty))
+      Res = new AllocaInst(PTy->getElementType(), V);
+    else
+      return true;
     return false;
 
   case Instruction::Free:
     V = getValue(Raw.Ty, Raw.Arg1);
-    if (!isa<PointerType>(V->getType())) return failure(true);
+    if (!isa<PointerType>(V->getType())) return true;
     Res = new FreeInst(V);
     return false;
 
-  case Instruction::Load:
   case Instruction::GetElementPtr: {
-    vector<Value*> Idx;
-    if (!isa<PointerType>(Raw.Ty)) return failure(true);
+    std::vector<Value*> Idx;
+    if (!isa<PointerType>(Raw.Ty)) return true;
     const CompositeType *TopTy = dyn_cast<CompositeType>(Raw.Ty);
 
     switch (Raw.NumOperands) {
-    case 0: cerr << "Invalid load encountered!\n"; return failure(true);
+    case 0: std::cerr << "Invalid getelementptr encountered!\n"; return true;
     case 1: break;
     case 2:
-      if (!TopTy) return failure(true);
+      if (!TopTy) return true;
       Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2));
-      if (!V) return failure(true);
+      if (!V) return true;
       break;
     case 3: {
-      if (!TopTy) return failure(true);
+      if (!TopTy) return true;
       Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2));
-      if (!V) return failure(true);
+      if (!V) return true;
 
-      const Type *ETy = MemAccessInst::getIndexedType(TopTy, Idx, true);
+      const Type *ETy = GetElementPtrInst::getIndexedType(TopTy, Idx, true);
       const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy);
-      if (!ElTy) return failure(true);
+      if (!ElTy) return true;
 
       Idx.push_back(V = getValue(ElTy->getIndexType(), Raw.Arg3));
-      if (!V) return failure(true);
+      if (!V) return true;
       break;
     }
     default:
-      if (!TopTy) return failure(true);
+      if (!TopTy) return true;
       Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2));
-      if (!V) return failure(true);
+      if (!V) return true;
 
-      vector<unsigned> &args = *Raw.VarArgs;
+      std::vector<unsigned> &args = *Raw.VarArgs;
       for (unsigned i = 0, E = args.size(); i != E; ++i) {
-        const Type *ETy = MemAccessInst::getIndexedType(Raw.Ty, Idx, true);
+        const Type *ETy = GetElementPtrInst::getIndexedType(Raw.Ty, Idx, true);
         const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy);
-        if (!ElTy) return failure(true);
+        if (!ElTy) return true;
        Idx.push_back(V = getValue(ElTy->getIndexType(), args[i]));
-       if (!V) return failure(true);
+       if (!V) return true;
       }
       delete Raw.VarArgs; 
       break;
     }
 
-    if (Raw.Opcode == Instruction::Load) {
-      assert(MemAccessInst::getIndexedType(Raw.Ty, Idx) && 
-             "Bad indices for 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();
+    Res = new GetElementPtrInst(getValue(Raw.Ty, Raw.Arg1), Idx);
     return false;
   }
-  case Instruction::Store: {
-    vector<Value*> Idx;
-    if (!isa<PointerType>(Raw.Ty)) return failure(true);
-    const CompositeType *TopTy = dyn_cast<CompositeType>(Raw.Ty);
 
-    switch (Raw.NumOperands) {
-    case 0: 
-    case 1: cerr << "Invalid store encountered!\n"; return failure(true);
-    case 2: break;
-    case 3:
-      if (!TopTy) return failure(true);
-      Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg3));
-      if (!V) return failure(true);
-      break;
-    default:
-      vector<unsigned> &args = *Raw.VarArgs;
-      const CompositeType *ElTy = TopTy;
-      unsigned i, E;
-      for (i = 0, E = args.size(); ElTy && i != E; ++i) {
-       Idx.push_back(V = getValue(ElTy->getIndexType(), args[i]));
-       if (!V) return failure(true);
-
-        const Type *ETy = MemAccessInst::getIndexedType(Raw.Ty, Idx, true);
-        ElTy = dyn_cast_or_null<CompositeType>(ETy);
-      }
-      if (i != E)
-        return failure(true);  // didn't use up all of the indices!
+  case 62:   // volatile load
+  case Instruction::Load:
+    if (Raw.NumOperands != 1) return true;
+    if (!isa<PointerType>(Raw.Ty)) return true;
+    Res = new LoadInst(getValue(Raw.Ty, Raw.Arg1), "", Raw.Opcode == 62);
+    return false;
 
-      delete Raw.VarArgs; 
-      break;
-    }
+  case 63:   // volatile store 
+  case Instruction::Store: {
+    if (!isa<PointerType>(Raw.Ty) || Raw.NumOperands != 2) return true;
 
-    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);
+    Value *Ptr = getValue(Raw.Ty, Raw.Arg2);
+    const Type *ValTy = cast<PointerType>(Ptr->getType())->getElementType();
+    Res = new StoreInst(getValue(ValTy, Raw.Arg1), Ptr, Raw.Opcode == 63);
     return false;
   }
   }  // end switch(Raw.Opcode) 
 
-  cerr << "Unrecognized instruction! " << Raw.Opcode 
-       << " ADDR = 0x" << (void*)Buf << "\n";
-  return failure(true);
+  std::cerr << "Unrecognized instruction! " << Raw.Opcode 
+            << " ADDR = 0x" << (void*)Buf << "\n";
+  return true;
 }