diff options
author | Chris Lattner <sabre@nondot.org> | 2003-10-09 20:22:47 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2003-10-09 20:22:47 +0000 |
commit | 927b185c175a8eb6d64ea97e1735fc6102114766 (patch) | |
tree | 61b9ae5b740d44fe2ec5292181b989e444d83155 /lib/Bytecode/Reader/InstructionReader.cpp | |
parent | 3483f54367e990c61eda61a6a550ba2634a13cb9 (diff) |
Major refactoring of the bytecode reader. This includes the following
changes:
* BytecodeReader::getType(...) used to return a null pointer
on error. This was only checked about half the time. Now we convert
it to throw an exception, and delete the half that checked for error.
This was checked in before, but psmith crashed and lost the change :(
* insertValue no longer returns -1 on error, so callers don't need to
check for it.
* Substantial rewrite of InstructionReader.cpp, to use more efficient,
simpler, data structures. This provides another 5% speedup. This also
makes the code much easier to read and understand.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8984 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Bytecode/Reader/InstructionReader.cpp')
-rw-r--r-- | lib/Bytecode/Reader/InstructionReader.cpp | 382 |
1 files changed, 140 insertions, 242 deletions
diff --git a/lib/Bytecode/Reader/InstructionReader.cpp b/lib/Bytecode/Reader/InstructionReader.cpp index aee6ba34f4..b085581c60 100644 --- a/lib/Bytecode/Reader/InstructionReader.cpp +++ b/lib/Bytecode/Reader/InstructionReader.cpp @@ -6,9 +6,6 @@ // 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 "ReaderInternals.h" @@ -17,11 +14,21 @@ #include "llvm/iPHINode.h" #include "llvm/iOther.h" -std::auto_ptr<RawInst> -BytecodeParser::ParseRawInst(const unsigned char *&Buf, - const unsigned char *EndBuf) { +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, Typ; - std::auto_ptr<RawInst> Result = std::auto_ptr<RawInst>(new RawInst()); if (read(Buf, EndBuf, Op)) throw std::string("Error reading from buffer."); @@ -29,20 +36,20 @@ BytecodeParser::ParseRawInst(const unsigned char *&Buf, // -------------------------- // 01-00: Opcode type, fixed to 1. // 07-02: Opcode - Result->NumOperands = (Op >> 0) & 03; - Result->Opcode = (Op >> 2) & 63; + Opcode = (Op >> 2) & 63; + Args.resize((Op >> 0) & 03); - switch (Result->NumOperands) { + switch (Args.size()) { case 1: // bits Instruction format: // -------------------------- // 19-08: Resulting type plane // 31-20: Operand #1 (if set to (2^12-1), then zero operands) // - Result->Ty = getType((Op >> 8) & 4095); - Result->Arg1 = (Op >> 20) & 4095; - if (Result->Arg1 == 4095) // Handle special encoding for 0 operands... - Result->NumOperands = 0; + 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: // bits Instruction format: @@ -51,9 +58,9 @@ BytecodeParser::ParseRawInst(const unsigned char *&Buf, // 23-16: Operand #1 // 31-24: Operand #2 // - Result->Ty = getType((Op >> 8) & 255); - Result->Arg1 = (Op >> 16) & 255; - Result->Arg2 = (Op >> 24) & 255; + Type = (Op >> 8) & 255; + Args[0] = (Op >> 16) & 255; + Args[1] = (Op >> 24) & 255; break; case 3: // bits Instruction format: @@ -63,159 +70,101 @@ BytecodeParser::ParseRawInst(const unsigned char *&Buf, // 25-20: Operand #2 // 31-26: Operand #3 // - Result->Ty = getType((Op >> 8) & 63); - Result->Arg1 = (Op >> 14) & 63; - Result->Arg2 = (Op >> 20) & 63; - Result->Arg3 = (Op >> 26) & 63; + 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)) + if (read_vbr(Buf, EndBuf, Opcode)) throw std::string("Error reading from buffer."); - Result->Opcode >>= 2; - if (read_vbr(Buf, EndBuf, Typ)) + Opcode >>= 2; + if (read_vbr(Buf, EndBuf, Type)) throw std::string("Error reading from buffer."); - Result->Ty = getType(Typ); - if (Result->Ty == 0) - throw std::string("Invalid type read in instruction."); - if (read_vbr(Buf, EndBuf, Result->NumOperands)) + + unsigned NumOperands; + if (read_vbr(Buf, EndBuf, NumOperands)) throw std::string("Error reading from buffer."); + Args.resize(NumOperands); - switch (Result->NumOperands) { - case 0: + if (NumOperands == 0) throw std::string("Zero-argument instruction found; this is invalid."); - case 1: - if (read_vbr(Buf, EndBuf, Result->Arg1)) - throw std::string("Error reading from buffer"); - break; - case 2: - if (read_vbr(Buf, EndBuf, Result->Arg1) || - read_vbr(Buf, EndBuf, Result->Arg2)) - throw std::string("Error reading from buffer"); - break; - case 3: - if (read_vbr(Buf, EndBuf, Result->Arg1) || - read_vbr(Buf, EndBuf, Result->Arg2) || - read_vbr(Buf, EndBuf, Result->Arg3)) - throw std::string("Error reading from buffer"); - break; - default: - if (read_vbr(Buf, EndBuf, Result->Arg1) || - read_vbr(Buf, EndBuf, Result->Arg2)) - throw std::string("Error reading from buffer"); - - // Allocate a vector to hold arguments 3, 4, 5, 6 ... - 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])) - throw std::string("Error reading from buffer"); - break; - } - if (align32(Buf, EndBuf)) + for (unsigned i = 0; i != NumOperands; ++i) + if (read_vbr(Buf, EndBuf, Args[i])) + throw std::string("Error reading from buffer"); + if (align32(Buf, EndBuf)) throw std::string("Unaligned bytecode buffer."); break; } - -#if 0 - std::cerr << "NO: " << Result->NumOperands << " opcode: " << Result->Opcode - << " Ty: "<< Result->Ty->getDescription()<< " arg1: "<< Result->Arg1 - << " arg2: " << Result->Arg2 << " arg3: " << Result->Arg3 << "\n"; -#endif - return Result; } Instruction *BytecodeParser::ParseInstruction(const unsigned char *&Buf, const unsigned char *EndBuf) { - std::auto_ptr<RawInst> Raw = ParseRawInst(Buf, EndBuf); + std::vector<unsigned> Args; + RawInst RI(Buf, EndBuf, Args); + const Type *InstTy = getType(RI.Type); - if (Raw->Opcode >= Instruction::BinaryOpsBegin && - Raw->Opcode < Instruction::BinaryOpsEnd && Raw->NumOperands == 2) - return BinaryOperator::create((Instruction::BinaryOps)Raw->Opcode, - getValue(Raw->Ty, Raw->Arg1), - getValue(Raw->Ty, Raw->Arg2)); + if (RI.Opcode >= Instruction::BinaryOpsBegin && + RI.Opcode < Instruction::BinaryOpsEnd && Args.size() == 2) + return BinaryOperator::create((Instruction::BinaryOps)RI.Opcode, + getValue(InstTy, Args[0]), + getValue(InstTy, Args[1])); - switch (Raw->Opcode) { + switch (RI.Opcode) { case Instruction::VarArg: - case Instruction::Cast: { - Value *V = getValue(Raw->Ty, Raw->Arg1); - const Type *Ty = getType(Raw->Arg2); - if (Ty == 0) throw std::string("Invalid cast!\n"); - if (Raw->Opcode == Instruction::Cast) - return new CastInst(V, Ty); - else - return new VarArgInst(V, Ty); - } + return new VarArgInst(getValue(InstTy, Args[0]), getType(Args[1])); + case Instruction::Cast: + return new CastInst(getValue(InstTy, Args[0]), getType(Args[1])); case Instruction::PHINode: { - PHINode *PN = new PHINode(Raw->Ty); - switch (Raw->NumOperands) { - case 0: - case 1: - case 3: - delete PN; + if (Args.size() == 0 || (Args.size() & 1)) throw std::string("Invalid phi node encountered!\n"); - case 2: - PN->addIncoming(getValue(Raw->Ty, Raw->Arg1), getBasicBlock(Raw->Arg2)); - break; - default: - PN->addIncoming(getValue(Raw->Ty, Raw->Arg1), getBasicBlock(Raw->Arg2)); - if (Raw->VarArgs->size() & 1) { - delete PN; - throw std::string("PHI Node with ODD number of arguments!\n"); - } else { - std::vector<unsigned> &args = *Raw->VarArgs; - for (unsigned i = 0; i < args.size(); i+=2) - PN->addIncoming(getValue(Raw->Ty, args[i]), getBasicBlock(args[i+1])); - } - delete Raw->VarArgs; - break; - } + + PHINode *PN = new PHINode(InstTy); + for (unsigned i = 0, e = Args.size(); i != e; i += 2) + PN->addIncoming(getValue(InstTy, Args[i]), getBasicBlock(Args[i+1])); return PN; } case Instruction::Shl: case Instruction::Shr: - return new ShiftInst((Instruction::OtherOps)Raw->Opcode, - getValue(Raw->Ty, Raw->Arg1), - getValue(Type::UByteTyID, Raw->Arg2)); + return new ShiftInst((Instruction::OtherOps)RI.Opcode, + getValue(InstTy, Args[0]), + getValue(Type::UByteTyID, Args[1])); case Instruction::Ret: - if (Raw->NumOperands == 0) + if (Args.size() == 0) return new ReturnInst(); - else if (Raw->NumOperands == 1) - return new ReturnInst(getValue(Raw->Ty, Raw->Arg1)); + else if (Args.size() == 1) + return new ReturnInst(getValue(InstTy, Args[0])); break; case Instruction::Br: - if (Raw->NumOperands == 1) - return new BranchInst(getBasicBlock(Raw->Arg1)); - else if (Raw->NumOperands == 3) - return new BranchInst(getBasicBlock(Raw->Arg1), getBasicBlock(Raw->Arg2), - getValue(Type::BoolTyID , Raw->Arg3)); + if (Args.size() == 1) + return new BranchInst(getBasicBlock(Args[0])); + else if (Args.size() == 3) + return new BranchInst(getBasicBlock(Args[0]), getBasicBlock(Args[1]), + getValue(Type::BoolTyID , Args[2])); throw std::string("Invalid number of operands for a 'br' instruction!"); case Instruction::Switch: { - SwitchInst *I = new SwitchInst(getValue(Raw->Ty, Raw->Arg1), - getBasicBlock(Raw->Arg2)); - if (Raw->NumOperands < 3) - return I; - - if (Raw->NumOperands == 3 || Raw->VarArgs->size() & 1) { - delete I; + if (Args.size() & 1) throw std::string("Switch statement with odd number of arguments!"); - } - - std::vector<unsigned> &args = *Raw->VarArgs; - for (unsigned i = 0; i < args.size(); i += 2) - I->addCase(cast<Constant>(getValue(Raw->Ty, args[i])), - getBasicBlock(args[i+1])); - delete Raw->VarArgs; + SwitchInst *I = new SwitchInst(getValue(InstTy, Args[0]), + getBasicBlock(Args[1])); + for (unsigned i = 2, e = Args.size(); i != e; i += 2) + I->addCase(cast<Constant>(getValue(InstTy, Args[i])), + getBasicBlock(Args[i+1])); return I; } case Instruction::Call: { - Value *F = getValue(Raw->Ty, Raw->Arg1); + if (Args.size() == 0) + throw std::string("Invalid call instruction encountered!"); + + Value *F = getValue(InstTy, Args[0]); // Check to make sure we have a pointer to function type const PointerType *PTy = dyn_cast<PointerType>(F->getType()); @@ -229,45 +178,26 @@ Instruction *BytecodeParser::ParseInstruction(const unsigned char *&Buf, if (!FTy->isVarArg()) { FunctionType::ParamTypes::const_iterator It = PL.begin(); - switch (Raw->NumOperands) { - case 0: throw std::string("Invalid call instruction encountered!"); - 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()) throw std::string("Invalid call instruction!"); - Params.push_back(getValue(*It++, Raw->Arg3)); break; - default: - Params.push_back(getValue(*It++, Raw->Arg2)); - { - std::vector<unsigned> &args = *Raw->VarArgs; - for (unsigned i = 0; i < args.size(); i++) { - if (It == PL.end()) throw std::string("Invalid call instruction!"); - Params.push_back(getValue(*It++, args[i])); - } - } - delete Raw->VarArgs; + for (unsigned i = 1, e = Args.size(); i != e; ++i) { + if (It == PL.end()) throw std::string("Invalid call instruction!"); + Params.push_back(getValue(*It++, Args[i])); } if (It != PL.end()) throw std::string("Invalid call instruction!"); } else { - if (Raw->NumOperands > 2) { - std::vector<unsigned> &args = *Raw->VarArgs; - if (args.size() < 1) throw std::string("Invalid call instruction!"); - - if ((args.size() & 1) != 0) // Must be pairs of type/value - throw std::string("Invalid call instruction!"); - for (unsigned i = 0; i < args.size(); i+=2) { - const Type *Ty = getType(args[i]); - if (Ty == 0) throw std::string("Invalid call instruction!"); - Params.push_back(getValue(Ty, args[i+1])); - } - delete Raw->VarArgs; - } + // FIXME: Args[1] is currently just a dummy padding field! + + if (Args.size() & 1) // Must be pairs of type/value + throw std::string("Invalid call instruction!"); + + for (unsigned i = 2, e = Args.size(); i != e; i += 2) + Params.push_back(getValue(getType(Args[i]), Args[i+1])); } return new CallInst(F, Params); } case Instruction::Invoke: { - Value *F = getValue(Raw->Ty, Raw->Arg1); + if (Args.size() < 3) throw std::string("Invalid invoke instruction!"); + Value *F = getValue(InstTy, Args[0]); // Check to make sure we have a pointer to function type const PointerType *PTy = dyn_cast<PointerType>(F->getType()); @@ -276,131 +206,99 @@ Instruction *BytecodeParser::ParseInstruction(const unsigned char *&Buf, if (FTy == 0) throw std::string("Invoke to non function pointer value!"); std::vector<Value *> Params; - const FunctionType::ParamTypes &PL = FTy->getParamTypes(); - std::vector<unsigned> &args = *Raw->VarArgs; - BasicBlock *Normal, *Except; + const FunctionType::ParamTypes &PL = FTy->getParamTypes(); + if (!FTy->isVarArg()) { - if (Raw->NumOperands < 3) throw std::string("Invalid call instruction!"); - - Normal = getBasicBlock(Raw->Arg2); - if (Raw->NumOperands == 3) - Except = getBasicBlock(Raw->Arg3); - else { - Except = getBasicBlock(args[0]); - - FunctionType::ParamTypes::const_iterator It = PL.begin(); - for (unsigned i = 1; i < args.size(); i++) { - if (It == PL.end()) throw std::string("Invalid invoke instruction!"); - Params.push_back(getValue(*It++, args[i])); - } - if (It != PL.end()) throw std::string("Invalid invoke instruction!"); + Normal = getBasicBlock(Args[1]); + Except = getBasicBlock(Args[2]); + + FunctionType::ParamTypes::const_iterator It = PL.begin(); + for (unsigned i = 3, e = Args.size(); i != e; ++i) { + if (It == PL.end()) throw std::string("Invalid invoke instruction!"); + Params.push_back(getValue(*It++, Args[i])); } + if (It != PL.end()) throw std::string("Invalid invoke instruction!"); } else { - if (args.size() < 4) throw std::string("Invalid invoke instruction!"); - if (args[0] != Type::LabelTyID || args[2] != Type::LabelTyID) + // FIXME: Args[1] is a dummy padding field + + if (Args.size() < 6) throw std::string("Invalid invoke instruction!"); + if (Args[2] != Type::LabelTyID || Args[4] != Type::LabelTyID) throw std::string("Invalid invoke instruction!"); - Normal = getBasicBlock(args[1]); - Except = getBasicBlock(args[3]); + Normal = getBasicBlock(Args[3]); + Except = getBasicBlock(Args[5]); - if ((args.size() & 1) != 0) // Must be pairs of type/value + if (Args.size() & 1) // Must be pairs of type/value throw std::string("Invalid invoke instruction!"); - for (unsigned i = 4; i < args.size(); i += 2) - Params.push_back(getValue(args[i], args[i+1])); + for (unsigned i = 6; i < Args.size(); i += 2) + Params.push_back(getValue(Args[i], Args[i+1])); } - if (Raw->NumOperands > 3) - delete Raw->VarArgs; return new InvokeInst(F, Normal, Except, Params); } case Instruction::Malloc: - if (Raw->NumOperands > 2) throw std::string("Invalid malloc instruction!"); - if (!isa<PointerType>(Raw->Ty)) + if (Args.size() > 2) throw std::string("Invalid malloc instruction!"); + if (!isa<PointerType>(InstTy)) throw std::string("Invalid malloc instruction!"); - return new MallocInst(cast<PointerType>(Raw->Ty)->getElementType(), - Raw->NumOperands ? getValue(Type::UIntTyID, - Raw->Arg1) : 0); + return new MallocInst(cast<PointerType>(InstTy)->getElementType(), + Args.size() ? getValue(Type::UIntTyID, + Args[0]) : 0); case Instruction::Alloca: - if (Raw->NumOperands > 2) throw std::string("Invalid alloca instruction!"); - if (!isa<PointerType>(Raw->Ty)) + if (Args.size() > 2) throw std::string("Invalid alloca instruction!"); + if (!isa<PointerType>(InstTy)) throw std::string("Invalid alloca instruction!"); - return new AllocaInst(cast<PointerType>(Raw->Ty)->getElementType(), - Raw->NumOperands ? getValue(Type::UIntTyID, - Raw->Arg1) : 0); + return new AllocaInst(cast<PointerType>(InstTy)->getElementType(), + Args.size() ? getValue(Type::UIntTyID, + Args[0]) : 0); case Instruction::Free: - if (!isa<PointerType>(Raw->Ty)) + if (!isa<PointerType>(InstTy)) throw std::string("Invalid free instruction!"); - return new FreeInst(getValue(Raw->Ty, Raw->Arg1)); + return new FreeInst(getValue(InstTy, Args[0])); case Instruction::GetElementPtr: { - std::vector<Value*> Idx; - if (!isa<PointerType>(Raw->Ty)) + if (Args.size() == 0 || !isa<PointerType>(InstTy)) throw std::string("Invalid getelementptr instruction!"); - const CompositeType *TopTy = dyn_cast<CompositeType>(Raw->Ty); - - switch (Raw->NumOperands) { - case 0: throw std::string("Invalid getelementptr instruction!"); - case 1: break; - case 2: - if (!TopTy) throw std::string("Invalid getelementptr instruction!"); - Idx.push_back(getValue(TopTy->getIndexType(), Raw->Arg2)); - break; - case 3: { - if (!TopTy) throw std::string("Invalid getelementptr instruction!"); - Idx.push_back(getValue(TopTy->getIndexType(), Raw->Arg2)); - - const Type *ETy = GetElementPtrInst::getIndexedType(TopTy, Idx, true); - const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy); - if (!ElTy) throw std::string("Invalid getelementptr instruction!"); - - Idx.push_back(getValue(ElTy->getIndexType(), Raw->Arg3)); - break; - } - default: - if (!TopTy) throw std::string("Invalid getelementptr instruction!"); - Idx.push_back(getValue(TopTy->getIndexType(), Raw->Arg2)); - - std::vector<unsigned> &args = *Raw->VarArgs; - for (unsigned i = 0, E = args.size(); i != E; ++i) { - const Type *ETy = GetElementPtrInst::getIndexedType(Raw->Ty, Idx, true); - const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy); - if (!ElTy) throw std::string("Invalid getelementptr instruction!"); - Idx.push_back(getValue(ElTy->getIndexType(), args[i])); - } - delete Raw->VarArgs; - break; + + 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!"); + Idx.push_back(getValue(TopTy->getIndexType(), Args[i])); + NextTy = GetElementPtrInst::getIndexedType(InstTy, Idx, true); } - return new GetElementPtrInst(getValue(Raw->Ty, Raw->Arg1), Idx); + return new GetElementPtrInst(getValue(InstTy, Args[0]), Idx); } case 62: // volatile load case Instruction::Load: - if (Raw->NumOperands != 1 || !isa<PointerType>(Raw->Ty)) + if (Args.size() != 1 || !isa<PointerType>(InstTy)) throw std::string("Invalid load instruction!"); - return new LoadInst(getValue(Raw->Ty, Raw->Arg1), "", Raw->Opcode == 62); + return new LoadInst(getValue(InstTy, Args[0]), "", RI.Opcode == 62); case 63: // volatile store case Instruction::Store: { - if (!isa<PointerType>(Raw->Ty) || Raw->NumOperands != 2) + if (!isa<PointerType>(InstTy) || Args.size() != 2) throw std::string("Invalid store instruction!"); - Value *Ptr = getValue(Raw->Ty, Raw->Arg2); + Value *Ptr = getValue(InstTy, Args[1]); const Type *ValTy = cast<PointerType>(Ptr->getType())->getElementType(); - return new StoreInst(getValue(ValTy, Raw->Arg1), Ptr, Raw->Opcode == 63); + return new StoreInst(getValue(ValTy, Args[0]), Ptr, RI.Opcode == 63); } case Instruction::Unwind: - if (Raw->NumOperands != 0) throw std::string("Invalid unwind instruction!"); + if (Args.size() != 0) throw std::string("Invalid unwind instruction!"); return new UnwindInst(); - } // end switch(Raw->Opcode) + } // end switch(RI.Opcode) - std::cerr << "Unrecognized instruction! " << Raw->Opcode + std::cerr << "Unrecognized instruction! " << RI.Opcode << " ADDR = 0x" << (void*)Buf << "\n"; throw std::string("Unrecognized instruction!"); } |