diff options
| author | Chris Lattner <sabre@nondot.org> | 2001-06-06 20:29:01 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2001-06-06 20:29:01 +0000 | 
| commit | 009505452b713ed2e3a8e99c5545a6e721c65495 (patch) | |
| tree | 136a71c5b87bdf534d1f20a67558b49226b5a4d6 /lib/Bytecode/Reader/InstructionReader.cpp | |
| parent | 8d0afd3d32d1d67f9aa5df250a1d6955aa8f1ac9 (diff) | |
Initial revision
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Bytecode/Reader/InstructionReader.cpp')
| -rw-r--r-- | lib/Bytecode/Reader/InstructionReader.cpp | 213 | 
1 files changed, 213 insertions, 0 deletions
diff --git a/lib/Bytecode/Reader/InstructionReader.cpp b/lib/Bytecode/Reader/InstructionReader.cpp new file mode 100644 index 0000000000..667e144673 --- /dev/null +++ b/lib/Bytecode/Reader/InstructionReader.cpp @@ -0,0 +1,213 @@ +//===- ReadInst.cpp - Code to read an instruction from bytecode -------------=== +// +// 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 "llvm/iTerminators.h" +#include "llvm/iMemory.h" +#include "llvm/DerivedTypes.h" +#include "ReaderInternals.h" + +bool BytecodeParser::ParseRawInst(const uchar *&Buf, const uchar *EndBuf,  +				  RawInst &Result) { +  unsigned Op, Typ; +  if (read(Buf, EndBuf, Op)) return true; + +  Result.NumOperands =  Op >> 30; +  Result.Opcode      = (Op >> 24) & 63; + +  switch (Result.NumOperands) { +  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; +    break; +  case 2: +    Result.Ty   = getType((Op >> 16) & 255); +    Result.Arg1 = (Op >> 8 ) & 255; +    Result.Arg2 = (Op >> 0 ) & 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; +    break; +  case 0: +    Buf -= 4;  // Hrm, try this again... +    if (read_vbr(Buf, EndBuf, Result.Opcode)) return true; +    if (read_vbr(Buf, EndBuf, Typ)) return true; +    Result.Ty = getType(Typ); +    if (read_vbr(Buf, EndBuf, Result.NumOperands)) return true; + +    switch (Result.NumOperands) { +    case 0:  +      cerr << "Zero Arg instr found!\n";  +      return true;  // This encoding is invalid! +    case 1:  +      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 true; +      break; +    case 3: +      if (read_vbr(Buf, EndBuf, Result.Arg1) ||  +	  read_vbr(Buf, EndBuf, Result.Arg2) || +	  read_vbr(Buf, EndBuf, Result.Arg3)) return true; +      break; +    default: +      if (read_vbr(Buf, EndBuf, Result.Arg1) ||  +	  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); +      for (unsigned a = 0; a < Result.NumOperands-2; a++) +	if (read_vbr(Buf, EndBuf, (*Result.VarArgs)[a])) return true; +      break; +    } +    if (align32(Buf, EndBuf)) return true; +    break; +  } + +  //cerr << "NO: "  << Result.NumOperands   << " opcode: " << Result.Opcode  +  //   << " Ty: " << Result.Ty->getName() << " arg1: "   << Result.Arg1 << endl; +  return false; +} + + +bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf, +				      Instruction *&Res) { +  RawInst Raw; +  if (ParseRawInst(Buf, EndBuf, Raw)) return true;; + +  if (Raw.Opcode >= Instruction::FirstUnaryOp &&  +      Raw.Opcode <  Instruction::NumUnaryOps  && Raw.NumOperands == 1) { +    Res = Instruction::getUnaryOperator(Raw.Opcode, getValue(Raw.Ty, Raw.Arg1)); +    return false; +  } else if (Raw.Opcode >= Instruction::FirstBinaryOp && +	     Raw.Opcode <  Instruction::NumBinaryOps  && Raw.NumOperands == 2) { +    Res = Instruction::getBinaryOperator(Raw.Opcode, getValue(Raw.Ty, Raw.Arg1), +					 getValue(Raw.Ty, Raw.Arg2)); +    return false; +  } else if (Raw.Opcode == Instruction::PHINode) { +    PHINode *PN = new PHINode(Raw.Ty); +    switch (Raw.NumOperands) { +    case 0: cerr << "Invalid phi node encountered!\n";  +            delete PN;  +	    return true; +    case 1: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1)); break; +    case 2: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1));  +            PN->addIncoming(getValue(Raw.Ty, Raw.Arg2)); break; +    case 3: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1));  +            PN->addIncoming(getValue(Raw.Ty, Raw.Arg2));  +            PN->addIncoming(getValue(Raw.Ty, Raw.Arg3)); break; +    default: +      PN->addIncoming(getValue(Raw.Ty, Raw.Arg1));  +      PN->addIncoming(getValue(Raw.Ty, Raw.Arg2)); +      { +        vector<unsigned> &args = *Raw.VarArgs; +        for (unsigned i = 0; i < args.size(); i++) +          PN->addIncoming(getValue(Raw.Ty, args[i])); +      } +      delete Raw.VarArgs; +    } +    Res = PN; +    return false; +  } else if (Raw.Opcode == 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;  +    } +  } else if (Raw.Opcode == 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; +    } +  } else if (Raw.Opcode == 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 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])); + +    delete Raw.VarArgs; +    return false; +  } else if (Raw.Opcode == Instruction::Call) { +    Method *M = (Method*)getValue(Raw.Ty, Raw.Arg1); +    if (M == 0) return true; + +    const MethodType::ParamTypes &PL = M->getMethodType()->getParamTypes(); +    MethodType::ParamTypes::const_iterator It = PL.begin(); + +    vector<Value *> Params; +    switch (Raw.NumOperands) { +    case 0: 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 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 true; +          Params.push_back(getValue(*It++, args[i])); +	} +      } +      delete Raw.VarArgs; +    } +    if (It != PL.end()) return true; + +    Res = new CallInst(M, Params); +    return false; +  } else if (Raw.Opcode == Instruction::Malloc) { +    if (Raw.NumOperands > 2) return true; +    Value *Sz = (Raw.NumOperands == 2) ? getValue(Type::UIntTy, Raw.Arg2) : 0; +    Res = new MallocInst((ConstPoolType*)getValue(Type::TypeTy, Raw.Arg1), Sz); +    return false; +  } else if (Raw.Opcode == Instruction::Alloca) { +    if (Raw.NumOperands > 2) return true; +    Value *Sz = (Raw.NumOperands == 2) ? getValue(Type::UIntTy, Raw.Arg2) : 0; +    Res = new AllocaInst((ConstPoolType*)getValue(Type::TypeTy, Raw.Arg1), Sz); +    return false; +  } else if (Raw.Opcode == Instruction::Free) { +    Value *Val = getValue(Raw.Ty, Raw.Arg1); +    if (!Val->getType()->isPointerType()) return true; +    Res = new FreeInst(Val); +    return false; +  } + +  cerr << "Unrecognized instruction! " << Raw.Opcode << endl; +  return true; +}  | 
