Changes in directory llvm/lib/Bytecode/Reader:
Reader.cpp updated: 1.198.2.3 -> 1.198.2.4 Reader.h updated: 1.34 -> 1.34.2.1 --- Log message: Implement backwards compatibility in bytecode reader for signless types. Bump bytecode writer version number (to 6). Fix bugs in DIV -> SDIV/UDIV changes. --- Diffs of the changes: (+703 -379) Reader.cpp | 1055 +++++++++++++++++++++++++++++++++++++++---------------------- Reader.h | 27 + 2 files changed, 703 insertions(+), 379 deletions(-) Index: llvm/lib/Bytecode/Reader/Reader.cpp diff -u llvm/lib/Bytecode/Reader/Reader.cpp:1.198.2.3 llvm/lib/Bytecode/Reader/Reader.cpp:1.198.2.4 --- llvm/lib/Bytecode/Reader/Reader.cpp:1.198.2.3 Thu Oct 19 23:27:17 2006 +++ llvm/lib/Bytecode/Reader/Reader.cpp Sat Oct 21 03:59:42 2006 @@ -562,6 +562,219 @@ insertValue(AI, getTypeSlot(AI->getType()), FunctionValues); } +/// Convert previous opcode values into the current value and/or construct +/// the instruction. This function handles all *abnormal* cases for instruction +/// generation based on obsolete opcode values. The normal cases are handled +/// in ParseInstruction below. +Instruction* +BytecodeReader::handleObsoleteOpcodes( + unsigned &Opcode, ///< The old opcode, possibly updated by this function + std::vector<unsigned> &Oprnds, ///< The operands to the instruction + unsigned &iType, ///< The type code from the bytecode file + const Type* InstTy, ///< The type of the instruction + BasicBlock* BB ///< The basic block to insert into, if we need to +) { + + // Declare the resulting instruction we might build. + Instruction *Result = 0; + + // If this is a bytecode format that did not include the unreachable + // instruction, bump up the opcode number to adjust + if (hasNoUnreachableInst) { + if (Opcode >= Instruction::Unreachable && + Opcode < 62) { // 62 + ++Opcode; + } + } + + // First, short circuit this if no conversion is required. When signless + // instructions were implemented the entire opcode sequence was revised so + // we key on this first which means that the opcode value read is the one + // we should use. + if (!hasSignlessInstructions) + return Result; + + // We're dealing with an upgrade situation. For each of the opcode values, + // perform the necessary convertion. + switch (Opcode) { + default: // Pass Through + // If we don't match any of the cases here then the opcode is fine the + // way it is. + break; + case 1: // Ret + Opcode = Instruction::Ret; + break; + case 2: // Br + Opcode = Instruction::Br; + break; + case 3: // Switch + Opcode = Instruction::Switch; + break; + case 4: // Invoke + Opcode = Instruction::Invoke; + break; + case 5: // Unwind + Opcode = Instruction::Unwind; + break; + case 6: // Unreachable + Opcode = Instruction::Unreachable; + break; + case 7: // Add + Opcode = Instruction::Add; + break; + case 8: // Sub + Opcode = Instruction::Sub; + break; + case 9: // Mul + Opcode = Instruction::Mul; + break; + case 10: // Div + // The type of the instruction is based on the operands. We need to select + // either udiv or sdiv based on that type. This expression selects the + // cases where the type is floating point or signed in which case we + // generated an sdiv instruction. + if (iType == 10 || iType == 11 || // select floating point + (iType >= 2 && iType <= 9 && iType % 2 != 0)) + Opcode = Instruction::SDiv; + else + Opcode = Instruction::UDiv; + break; + + case 11: // Rem + // As with "Div", make the signed/unsigned Rem instruction choice based + // on the type of the instruction. + if (iType == 10 || iType == 11 || // select floating point + (iType >= 2 && iType <= 9 && iType % 2 != 0)) + Opcode = Instruction::Rem; + else + Opcode = Instruction::Rem; + break; + + case 12: // And + Opcode = Instruction::And; + break; + case 13: // Or + Opcode = Instruction::Or; + break; + case 14: // Xor + Opcode = Instruction::Xor; + break; + case 15: // SetEQ + Opcode = Instruction::SetEQ; + break; + case 16: // SetNE + Opcode = Instruction::SetNE; + break; + case 17: // SetLE + Opcode = Instruction::SetLE; + break; + case 18: // SetGE + Opcode = Instruction::SetGE; + break; + case 19: // SetLT + Opcode = Instruction::SetLT; + break; + case 20: // SetGT + Opcode = Instruction::SetGT; + break; + case 21: // Malloc + Opcode = Instruction::Malloc; + break; + case 22: // Free + Opcode = Instruction::Free; + break; + case 23: // Alloca + Opcode = Instruction::Alloca; + break; + case 24: // Load + Opcode = Instruction::Load; + break; + case 25: // Store + Opcode = Instruction::Store; + break; + case 26: // GetElementPtr + Opcode = Instruction::GetElementPtr; + break; + case 27: // PHI + Opcode = Instruction::PHI; + break; + case 28: // Cast + Opcode = Instruction::Cast; + break; + case 29: // Call + Opcode = Instruction::Call; + break; + case 30: // Shl + Opcode = Instruction::Shl; + break; + case 31: // Shr + Opcode = Instruction::Shr; + break; + case 32: { //VANext_old ( <= llvm 1.5 ) + const Type* ArgTy = getValue(iType, Oprnds[0])->getType(); + Function* NF = TheModule->getOrInsertFunction( + "llvm.va_copy", ArgTy, ArgTy, (Type *)0); + + //b = vanext a, t -> + //foo = alloca 1 of t + //bar = vacopy a + //store bar -> foo + //tmp = vaarg foo, t + //b = load foo + AllocaInst* foo = new AllocaInst(ArgTy, 0, "vanext.fix"); + BB->getInstList().push_back(foo); + CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0])); + BB->getInstList().push_back(bar); + BB->getInstList().push_back(new StoreInst(bar, foo)); + Instruction* tmp = new VAArgInst(foo, getSanitizedType(Oprnds[1])); + BB->getInstList().push_back(tmp); + Result = new LoadInst(foo); + break; + } + case 33: { //VAArg_old + const Type* ArgTy = getValue(iType, Oprnds[0])->getType(); + Function* NF = TheModule->getOrInsertFunction( + "llvm.va_copy", ArgTy, ArgTy, (Type *)0); + + //b = vaarg a, t -> + //foo = alloca 1 of t + //bar = vacopy a + //store bar -> foo + //b = vaarg foo, t + AllocaInst* foo = new AllocaInst(ArgTy, 0, "vaarg.fix"); + BB->getInstList().push_back(foo); + CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0])); + BB->getInstList().push_back(bar); + BB->getInstList().push_back(new StoreInst(bar, foo)); + Result = new VAArgInst(foo, getSanitizedType(Oprnds[1])); + break; + } + case 34: // Select + Opcode = Instruction::Select; + break; + case 35: // UserOp1 + Opcode = Instruction::UserOp1; + break; + case 36: // UserOp2 + Opcode = Instruction::UserOp2; + break; + case 37: // VAArg + Opcode = Instruction::VAArg; + break; + case 38: // ExtractElement + Opcode = Instruction::ExtractElement; + break; + case 39: // InsertElement + Opcode = Instruction::InsertElement; + break; + case 40: // ShuffleVector + Opcode = Instruction::ShuffleVector; + break; + } + + return Result; +} + //===----------------------------------------------------------------------===// // Bytecode Parsing Methods //===----------------------------------------------------------------------===// @@ -643,413 +856,382 @@ const Type *InstTy = getSanitizedType(iType); + // Make the necessary adjustments for dealing with backwards compatibility + // of opcodes. + Instruction* Result = + handleObsoleteOpcodes(Opcode, Oprnds, iType, InstTy, BB); + // We have enough info to inform the handler now. if (Handler) Handler->handleInstruction(Opcode, InstTy, Oprnds, At-SaveAt); - // Declare the resulting instruction we'll build. - Instruction *Result = 0; - - // If this is a bytecode format that did not include the unreachable - // instruction, bump up all opcodes numbers to make space. - if (hasNoUnreachableInst) { - if (Opcode >= Instruction::Unreachable && - Opcode < 62) { - ++Opcode; - } - } - - // Handle binary operators - if (Opcode >= Instruction::BinaryOpsBegin && - Opcode < Instruction::BinaryOpsEnd && Oprnds.size() == 2) - Result = BinaryOperator::create((Instruction::BinaryOps)Opcode, - getValue(iType, Oprnds[0]), - getValue(iType, Oprnds[1])); - - bool isCall = false; - switch (Opcode) { - default: - if (Result == 0) - error("Illegal instruction read!"); - break; - case Instruction::VAArg: - Result = new VAArgInst(getValue(iType, Oprnds[0]), - getSanitizedType(Oprnds[1])); - break; -#if 0 // FIXME: This needs to be handled - case 32: { //VANext_old - const Type* ArgTy = getValue(iType, Oprnds[0])->getType(); - Function* NF = TheModule->getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, - (Type *)0); - - //b = vanext a, t -> - //foo = alloca 1 of t - //bar = vacopy a - //store bar -> foo - //tmp = vaarg foo, t - //b = load foo - AllocaInst* foo = new AllocaInst(ArgTy, 0, "vanext.fix"); - BB->getInstList().push_back(foo); - CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0])); - BB->getInstList().push_back(bar); - BB->getInstList().push_back(new StoreInst(bar, foo)); - Instruction* tmp = new VAArgInst(foo, getSanitizedType(Oprnds[1])); - BB->getInstList().push_back(tmp); - Result = new LoadInst(foo); - break; - } - case 33: { //VAArg_old - const Type* ArgTy = getValue(iType, Oprnds[0])->getType(); - Function* NF = TheModule->getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, - (Type *)0); - - //b = vaarg a, t -> - //foo = alloca 1 of t - //bar = vacopy a - //store bar -> foo - //b = vaarg foo, t - AllocaInst* foo = new AllocaInst(ArgTy, 0, "vaarg.fix"); - BB->getInstList().push_back(foo); - CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0])); - BB->getInstList().push_back(bar); - BB->getInstList().push_back(new StoreInst(bar, foo)); - Result = new VAArgInst(foo, getSanitizedType(Oprnds[1])); - break; - } -#endif - case Instruction::ExtractElement: { - if (Oprnds.size() != 2) - error("Invalid extractelement instruction!"); - Value *V1 = getValue(iType, Oprnds[0]); - Value *V2 = getValue(Type::UIntTyID, Oprnds[1]); - - if (!ExtractElementInst::isValidOperands(V1, V2)) - error("Invalid extractelement instruction!"); - - Result = new ExtractElementInst(V1, V2); - break; - } - case Instruction::InsertElement: { - const PackedType *PackedTy = dyn_cast<PackedType>(InstTy); - if (!PackedTy || Oprnds.size() != 3) - error("Invalid insertelement instruction!"); - - Value *V1 = getValue(iType, Oprnds[0]); - Value *V2 = getValue(getTypeSlot(PackedTy->getElementType()), Oprnds[1]); - Value *V3 = getValue(Type::UIntTyID, Oprnds[2]); - - if (!InsertElementInst::isValidOperands(V1, V2, V3)) - error("Invalid insertelement instruction!"); - Result = new InsertElementInst(V1, V2, V3); - break; - } - case Instruction::ShuffleVector: { - const PackedType *PackedTy = dyn_cast<PackedType>(InstTy); - if (!PackedTy || Oprnds.size() != 3) - error("Invalid shufflevector instruction!"); - Value *V1 = getValue(iType, Oprnds[0]); - Value *V2 = getValue(iType, Oprnds[1]); - const PackedType *EltTy = - PackedType::get(Type::UIntTy, PackedTy->getNumElements()); - Value *V3 = getValue(getTypeSlot(EltTy), Oprnds[2]); - if (!ShuffleVectorInst::isValidOperands(V1, V2, V3)) - error("Invalid shufflevector instruction!"); - Result = new ShuffleVectorInst(V1, V2, V3); - break; - } - case Instruction::Cast: - Result = new CastInst(getValue(iType, Oprnds[0]), - getSanitizedType(Oprnds[1])); - break; - case Instruction::Select: - Result = new SelectInst(getValue(Type::BoolTyID, Oprnds[0]), - getValue(iType, Oprnds[1]), - getValue(iType, Oprnds[2])); - break; - case Instruction::PHI: { - if (Oprnds.size() == 0 || (Oprnds.size() & 1)) - error("Invalid phi node encountered!"); - - PHINode *PN = new PHINode(InstTy); - PN->reserveOperandSpace(Oprnds.size()); - for (unsigned i = 0, e = Oprnds.size(); i != e; i += 2) - PN->addIncoming(getValue(iType, Oprnds[i]), getBasicBlock(Oprnds[i+1])); - Result = PN; - break; - } + // If the backwards compatibility code didn't produce an instruction then + // we do the *normal* thing .. + if (!Result) { + + // First, handle the easy binary operators case + if (Opcode >= Instruction::BinaryOpsBegin && + Opcode < Instruction::BinaryOpsEnd && Oprnds.size() == 2) + Result = BinaryOperator::create(Instruction::BinaryOps(Opcode), + getValue(iType, Oprnds[0]), + getValue(iType, Oprnds[1])); + + // Indicate that we don't think this is a call instruction (yet). + bool isCall = false; + + // Process based on the Opcode read + switch (Opcode) { + default: // There was an error, this shouldn't happen. + if (Result == 0) + error("Illegal instruction read!"); + break; + case Instruction::VAArg: + if (Oprnds.size() != 2) + error("Invalid VAArg instruction!"); + Result = new VAArgInst(getValue(iType, Oprnds[0]), + getSanitizedType(Oprnds[1])); + break; + case Instruction::ExtractElement: { + if (Oprnds.size() != 2) + error("Invalid extractelement instruction!"); + Value *V1 = getValue(iType, Oprnds[0]); + Value *V2 = getValue(Type::UIntTyID, Oprnds[1]); + + if (!ExtractElementInst::isValidOperands(V1, V2)) + error("Invalid extractelement instruction!"); - case Instruction::Shl: - case Instruction::Shr: - Result = new ShiftInst((Instruction::OtherOps)Opcode, - getValue(iType, Oprnds[0]), - getValue(Type::UByteTyID, Oprnds[1])); - break; - case Instruction::Ret: - if (Oprnds.size() == 0) - Result = new ReturnInst(); - else if (Oprnds.size() == 1) - Result = new ReturnInst(getValue(iType, Oprnds[0])); - else - error("Unrecognized instruction!"); - break; + Result = new ExtractElementInst(V1, V2); + break; + } + case Instruction::InsertElement: { + const PackedType *PackedTy = dyn_cast<PackedType>(InstTy); + if (!PackedTy || Oprnds.size() != 3) + error("Invalid insertelement instruction!"); + + Value *V1 = getValue(iType, Oprnds[0]); + Value *V2 = getValue(getTypeSlot(PackedTy->getElementType()),Oprnds[1]); + Value *V3 = getValue(Type::UIntTyID, Oprnds[2]); + + if (!InsertElementInst::isValidOperands(V1, V2, V3)) + error("Invalid insertelement instruction!"); + Result = new InsertElementInst(V1, V2, V3); + break; + } + case Instruction::ShuffleVector: { + const PackedType *PackedTy = dyn_cast<PackedType>(InstTy); + if (!PackedTy || Oprnds.size() != 3) + error("Invalid shufflevector instruction!"); + Value *V1 = getValue(iType, Oprnds[0]); + Value *V2 = getValue(iType, Oprnds[1]); + const PackedType *EltTy = + PackedType::get(Type::UIntTy, PackedTy->getNumElements()); + Value *V3 = getValue(getTypeSlot(EltTy), Oprnds[2]); + if (!ShuffleVectorInst::isValidOperands(V1, V2, V3)) + error("Invalid shufflevector instruction!"); + Result = new ShuffleVectorInst(V1, V2, V3); + break; + } + case Instruction::Cast: + if (Oprnds.size() != 2) + error("Invalid Cast instruction!"); + Result = new CastInst(getValue(iType, Oprnds[0]), + getSanitizedType(Oprnds[1])); + break; + case Instruction::Select: + if (Oprnds.size() != 3) + error("Invalid Select instruction!"); + Result = new SelectInst(getValue(Type::BoolTyID, Oprnds[0]), + getValue(iType, Oprnds[1]), + getValue(iType, Oprnds[2])); + break; + case Instruction::PHI: { + if (Oprnds.size() == 0 || (Oprnds.size() & 1)) + error("Invalid phi node encountered!"); + + PHINode *PN = new PHINode(InstTy); + PN->reserveOperandSpace(Oprnds.size()); + for (unsigned i = 0, e = Oprnds.size(); i != e; i += 2) + PN->addIncoming( + getValue(iType, Oprnds[i]), getBasicBlock(Oprnds[i+1])); + Result = PN; + break; + } - case Instruction::Br: - if (Oprnds.size() == 1) - Result = new BranchInst(getBasicBlock(Oprnds[0])); - else if (Oprnds.size() == 3) - Result = new BranchInst(getBasicBlock(Oprnds[0]), - getBasicBlock(Oprnds[1]), getValue(Type::BoolTyID , Oprnds[2])); - else - error("Invalid number of operands for a 'br' instruction!"); - break; - case Instruction::Switch: { - if (Oprnds.size() & 1) - error("Switch statement with odd number of arguments!"); + case Instruction::Shl: + case Instruction::Shr: + Result = new ShiftInst(Instruction::OtherOps(Opcode), + getValue(iType, Oprnds[0]), + getValue(Type::UByteTyID, Oprnds[1])); + break; + case Instruction::Ret: + if (Oprnds.size() == 0) + Result = new ReturnInst(); + else if (Oprnds.size() == 1) + Result = new ReturnInst(getValue(iType, Oprnds[0])); + else + error("Unrecognized instruction!"); + break; + + case Instruction::Br: + if (Oprnds.size() == 1) + Result = new BranchInst(getBasicBlock(Oprnds[0])); + else if (Oprnds.size() == 3) + Result = new BranchInst(getBasicBlock(Oprnds[0]), + getBasicBlock(Oprnds[1]), getValue(Type::BoolTyID , Oprnds[2])); + else + error("Invalid number of operands for a 'br' instruction!"); + break; + case Instruction::Switch: { + if (Oprnds.size() & 1) + error("Switch statement with odd number of arguments!"); + + SwitchInst *I = new SwitchInst(getValue(iType, Oprnds[0]), + getBasicBlock(Oprnds[1]), + Oprnds.size()/2-1); + for (unsigned i = 2, e = Oprnds.size(); i != e; i += 2) + I->addCase(cast<ConstantInt>(getValue(iType, Oprnds[i])), + getBasicBlock(Oprnds[i+1])); + Result = I; + break; + } - SwitchInst *I = new SwitchInst(getValue(iType, Oprnds[0]), - getBasicBlock(Oprnds[1]), - Oprnds.size()/2-1); - for (unsigned i = 2, e = Oprnds.size(); i != e; i += 2) - I->addCase(cast<ConstantInt>(getValue(iType, Oprnds[i])), - getBasicBlock(Oprnds[i+1])); - Result = I; - break; - } + case 58: // Call with extra operand for calling conv + case 59: // tail call, Fast CC + case 60: // normal call, Fast CC + case 61: // tail call, C Calling Conv + case Instruction::Call: { // Normal Call, C Calling Convention + if (Oprnds.size() == 0) + error("Invalid call instruction encountered!"); - case 58: // Call with extra operand for calling conv - case 59: // tail call, Fast CC - case 60: // normal call, Fast CC - case 61: // tail call, C Calling Conv - case Instruction::Call: { // Normal Call, C Calling Convention - if (Oprnds.size() == 0) - error("Invalid call instruction encountered!"); + Value *F = getValue(iType, Oprnds[0]); - Value *F = getValue(iType, Oprnds[0]); + unsigned CallingConv = CallingConv::C; + bool isTailCall = false; - unsigned CallingConv = CallingConv::C; - bool isTailCall = false; + if (Opcode == 61 || Opcode == 59) + isTailCall = true; + + if (Opcode == 58) { + isTailCall = Oprnds.back() & 1; + CallingConv = Oprnds.back() >> 1; + Oprnds.pop_back(); + } else if (Opcode == 59 || Opcode == 60) { + CallingConv = CallingConv::Fast; + } + + // Check to make sure we have a pointer to function type + const PointerType *PTy = dyn_cast<PointerType>(F->getType()); + if (PTy == 0) error("Call to non function pointer value!"); + const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType()); + if (FTy == 0) error("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 = Oprnds.size(); i != e; ++i) { + if (It == FTy->param_end()) + error("Invalid call instruction!"); + Params.push_back(getValue(getTypeSlot(*It++), Oprnds[i])); + } + if (It != FTy->param_end()) + error("Invalid call instruction!"); + } else { + Oprnds.erase(Oprnds.begin(), Oprnds.begin()+1); - if (Opcode == 61 || Opcode == 59) - isTailCall = true; - - if (Opcode == 58) { - isTailCall = Oprnds.back() & 1; - CallingConv = Oprnds.back() >> 1; - Oprnds.pop_back(); - } else if (Opcode == 59 || Opcode == 60) { - CallingConv = CallingConv::Fast; - } - - // Check to make sure we have a pointer to function type - const PointerType *PTy = dyn_cast<PointerType>(F->getType()); - if (PTy == 0) error("Call to non function pointer value!"); - const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType()); - if (FTy == 0) error("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 = Oprnds.size(); i != e; ++i) { - if (It == FTy->param_end()) - error("Invalid call instruction!"); - Params.push_back(getValue(getTypeSlot(*It++), Oprnds[i])); - } - if (It != FTy->param_end()) - error("Invalid call instruction!"); - } else { - Oprnds.erase(Oprnds.begin(), Oprnds.begin()+1); + unsigned FirstVariableOperand; + if (Oprnds.size() < FTy->getNumParams()) + error("Call instruction missing operands!"); - unsigned FirstVariableOperand; - if (Oprnds.size() < FTy->getNumParams()) - error("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)),Oprnds[i])); - // Read all of the fixed arguments - for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) - Params.push_back(getValue(getTypeSlot(FTy->getParamType(i)),Oprnds[i])); + FirstVariableOperand = FTy->getNumParams(); - FirstVariableOperand = FTy->getNumParams(); + if ((Oprnds.size()-FirstVariableOperand) & 1) + error("Invalid call instruction!"); // Must be pairs of type/value - if ((Oprnds.size()-FirstVariableOperand) & 1) - error("Invalid call instruction!"); // Must be pairs of type/value + for (unsigned i = FirstVariableOperand, e = Oprnds.size(); + i != e; i += 2) + Params.push_back(getValue(Oprnds[i], Oprnds[i+1])); + } - for (unsigned i = FirstVariableOperand, e = Oprnds.size(); - i != e; i += 2) - Params.push_back(getValue(Oprnds[i], Oprnds[i+1])); - } + Result = new CallInst(F, Params); + if (isTailCall) cast<CallInst>(Result)->setTailCall(); + if (CallingConv) cast<CallInst>(Result)->setCallingConv(CallingConv); + break; + } + case 56: // Invoke with encoded CC + case 57: // Invoke Fast CC + case Instruction::Invoke: { // Invoke C CC + if (Oprnds.size() < 3) + error("Invalid invoke instruction!"); + Value *F = getValue(iType, Oprnds[0]); - Result = new CallInst(F, Params); - if (isTailCall) cast<CallInst>(Result)->setTailCall(); - if (CallingConv) cast<CallInst>(Result)->setCallingConv(CallingConv); - break; - } - case 56: // Invoke with encoded CC - case 57: // Invoke Fast CC - case Instruction::Invoke: { // Invoke C CC - if (Oprnds.size() < 3) - error("Invalid invoke instruction!"); - Value *F = getValue(iType, Oprnds[0]); + // Check to make sure we have a pointer to function type + const PointerType *PTy = dyn_cast<PointerType>(F->getType()); + if (PTy == 0) + error("Invoke to non function pointer value!"); + const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType()); + if (FTy == 0) + error("Invoke to non function pointer value!"); + + std::vector<Value *> Params; + BasicBlock *Normal, *Except; + unsigned CallingConv = CallingConv::C; + + if (Opcode == 57) + CallingConv = CallingConv::Fast; + else if (Opcode == 56) { + CallingConv = Oprnds.back(); + Oprnds.pop_back(); + } - // Check to make sure we have a pointer to function type - const PointerType *PTy = dyn_cast<PointerType>(F->getType()); - if (PTy == 0) - error("Invoke to non function pointer value!"); - const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType()); - if (FTy == 0) - error("Invoke to non function pointer value!"); + if (!FTy->isVarArg()) { + Normal = getBasicBlock(Oprnds[1]); + Except = getBasicBlock(Oprnds[2]); + + FunctionType::param_iterator It = FTy->param_begin(); + for (unsigned i = 3, e = Oprnds.size(); i != e; ++i) { + if (It == FTy->param_end()) + error("Invalid invoke instruction!"); + Params.push_back(getValue(getTypeSlot(*It++), Oprnds[i])); + } + if (It != FTy->param_end()) + error("Invalid invoke instruction!"); + } else { + Oprnds.erase(Oprnds.begin(), Oprnds.begin()+1); - std::vector<Value *> Params; - BasicBlock *Normal, *Except; - unsigned CallingConv = CallingConv::C; + Normal = getBasicBlock(Oprnds[0]); + Except = getBasicBlock(Oprnds[1]); - if (Opcode == 57) - CallingConv = CallingConv::Fast; - else if (Opcode == 56) { - CallingConv = Oprnds.back(); - Oprnds.pop_back(); - } + unsigned FirstVariableArgument = FTy->getNumParams()+2; + for (unsigned i = 2; i != FirstVariableArgument; ++i) + Params.push_back(getValue(getTypeSlot(FTy->getParamType(i-2)), + Oprnds[i])); + + // Must be type/value pairs. If not, error out. + if (Oprnds.size()-FirstVariableArgument & 1) + error("Invalid invoke instruction!"); - if (!FTy->isVarArg()) { - Normal = getBasicBlock(Oprnds[1]); - Except = getBasicBlock(Oprnds[2]); + for (unsigned i = FirstVariableArgument; i < Oprnds.size(); i += 2) + Params.push_back(getValue(Oprnds[i], Oprnds[i+1])); + } - FunctionType::param_iterator It = FTy->param_begin(); - for (unsigned i = 3, e = Oprnds.size(); i != e; ++i) { - if (It == FTy->param_end()) - error("Invalid invoke instruction!"); - Params.push_back(getValue(getTypeSlot(*It++), Oprnds[i])); + Result = new InvokeInst(F, Normal, Except, Params); + if (CallingConv) cast<InvokeInst>(Result)->setCallingConv(CallingConv); + break; } - if (It != FTy->param_end()) - error("Invalid invoke instruction!"); - } else { - Oprnds.erase(Oprnds.begin(), Oprnds.begin()+1); - - Normal = getBasicBlock(Oprnds[0]); - Except = getBasicBlock(Oprnds[1]); - - unsigned FirstVariableArgument = FTy->getNumParams()+2; - for (unsigned i = 2; i != FirstVariableArgument; ++i) - Params.push_back(getValue(getTypeSlot(FTy->getParamType(i-2)), - Oprnds[i])); - - if (Oprnds.size()-FirstVariableArgument & 1) // Must be type/value pairs - error("Invalid invoke instruction!"); - - for (unsigned i = FirstVariableArgument; i < Oprnds.size(); i += 2) - Params.push_back(getValue(Oprnds[i], Oprnds[i+1])); - } - - Result = new InvokeInst(F, Normal, Except, Params); - if (CallingConv) cast<InvokeInst>(Result)->setCallingConv(CallingConv); - break; - } - case Instruction::Malloc: { - unsigned Align = 0; - if (Oprnds.size() == 2) - Align = (1 << Oprnds[1]) >> 1; - else if (Oprnds.size() > 2) - error("Invalid malloc instruction!"); - if (!isa<PointerType>(InstTy)) - error("Invalid malloc instruction!"); - - Result = new MallocInst(cast<PointerType>(InstTy)->getElementType(), - getValue(Type::UIntTyID, Oprnds[0]), Align); - break; - } - - case Instruction::Alloca: { - unsigned Align = 0; - if (Oprnds.size() == 2) - Align = (1 << Oprnds[1]) >> 1; - else if (Oprnds.size() > 2) - error("Invalid alloca instruction!"); - if (!isa<PointerType>(InstTy)) - error("Invalid alloca instruction!"); - - Result = new AllocaInst(cast<PointerType>(InstTy)->getElementType(), - getValue(Type::UIntTyID, Oprnds[0]), Align); - break; - } - case Instruction::Free: - if (!isa<PointerType>(InstTy)) - error("Invalid free instruction!"); - Result = new FreeInst(getValue(iType, Oprnds[0])); - break; - case Instruction::GetElementPtr: { - if (Oprnds.size() == 0 || !isa<PointerType>(InstTy)) - error("Invalid getelementptr instruction!"); - - std::vector<Value*> Idx; - - const Type *NextTy = InstTy; - for (unsigned i = 1, e = Oprnds.size(); i != e; ++i) { - const CompositeType *TopTy = dyn_cast_or_null<CompositeType>(NextTy); - if (!TopTy) - error("Invalid getelementptr instruction!"); - - unsigned ValIdx = Oprnds[i]; - unsigned IdxTy = 0; - if (!hasRestrictedGEPTypes) { - // Struct indices are always uints, sequential type indices can be any - // of the 32 or 64-bit integer types. The actual choice of type is - // encoded in the low two bits of the slot number. - if (isa<StructType>(TopTy)) - IdxTy = Type::UIntTyID; - else { - switch (ValIdx & 3) { - default: - case 0: IdxTy = Type::UIntTyID; break; - case 1: IdxTy = Type::IntTyID; break; - case 2: IdxTy = Type::ULongTyID; break; - case 3: IdxTy = Type::LongTyID; break; - } - ValIdx >>= 2; - } - } else { - IdxTy = isa<StructType>(TopTy) ? Type::UByteTyID : Type::LongTyID; + case Instruction::Malloc: { + unsigned Align = 0; + if (Oprnds.size() == 2) + Align = (1 << Oprnds[1]) >> 1; + else if (Oprnds.size() > 2) + error("Invalid malloc instruction!"); + if (!isa<PointerType>(InstTy)) + error("Invalid malloc instruction!"); + + Result = new MallocInst(cast<PointerType>(InstTy)->getElementType(), + getValue(Type::UIntTyID, Oprnds[0]), Align); + break; } - Idx.push_back(getValue(IdxTy, ValIdx)); + case Instruction::Alloca: { + unsigned Align = 0; + if (Oprnds.size() == 2) + Align = (1 << Oprnds[1]) >> 1; + else if (Oprnds.size() > 2) + error("Invalid alloca instruction!"); + if (!isa<PointerType>(InstTy)) + error("Invalid alloca instruction!"); + + Result = new AllocaInst(cast<PointerType>(InstTy)->getElementType(), + getValue(Type::UIntTyID, Oprnds[0]), Align); + break; + } + case Instruction::Free: + if (!isa<PointerType>(InstTy)) + error("Invalid free instruction!"); + Result = new FreeInst(getValue(iType, Oprnds[0])); + break; + case Instruction::GetElementPtr: { + if (Oprnds.size() == 0 || !isa<PointerType>(InstTy)) + error("Invalid getelementptr instruction!"); + + std::vector<Value*> Idx; + + const Type *NextTy = InstTy; + for (unsigned i = 1, e = Oprnds.size(); i != e; ++i) { + const CompositeType *TopTy = dyn_cast_or_null<CompositeType>(NextTy); + if (!TopTy) + error("Invalid getelementptr instruction!"); + + unsigned ValIdx = Oprnds[i]; + unsigned IdxTy = 0; + if (!hasRestrictedGEPTypes) { + // Struct indices are always uints, sequential type indices can be + // any of the 32 or 64-bit integer types. The actual choice of + // type is encoded in the low two bits of the slot number. + if (isa<StructType>(TopTy)) + IdxTy = Type::UIntTyID; + else { + switch (ValIdx & 3) { + default: + case 0: IdxTy = Type::UIntTyID; break; + case 1: IdxTy = Type::IntTyID; break; + case 2: IdxTy = Type::ULongTyID; break; + case 3: IdxTy = Type::LongTyID; break; + } + ValIdx >>= 2; + } + } else { + IdxTy = isa<StructType>(TopTy) ? Type::UByteTyID : Type::LongTyID; + } - // Convert ubyte struct indices into uint struct indices. - if (isa<StructType>(TopTy) && hasRestrictedGEPTypes) - if (ConstantInt *C = dyn_cast<ConstantInt>(Idx.back())) - if (C->getType() == Type::UByteTy) - Idx[Idx.size()-1] = ConstantExpr::getCast(C, Type::UIntTy); + Idx.push_back(getValue(IdxTy, ValIdx)); - NextTy = GetElementPtrInst::getIndexedType(InstTy, Idx, true); - } + // Convert ubyte struct indices into uint struct indices. + if (isa<StructType>(TopTy) && hasRestrictedGEPTypes) + if (ConstantInt *C = dyn_cast<ConstantInt>(Idx.back())) + if (C->getType() == Type::UByteTy) + Idx[Idx.size()-1] = ConstantExpr::getCast(C, Type::UIntTy); - Result = new GetElementPtrInst(getValue(iType, Oprnds[0]), Idx); - break; - } - - case 62: // volatile load - case Instruction::Load: - if (Oprnds.size() != 1 || !isa<PointerType>(InstTy)) - error("Invalid load instruction!"); - Result = new LoadInst(getValue(iType, Oprnds[0]), "", Opcode == 62); - break; + NextTy = GetElementPtrInst::getIndexedType(InstTy, Idx, true); + } - case 63: // volatile store - case Instruction::Store: { - if (!isa<PointerType>(InstTy) || Oprnds.size() != 2) - error("Invalid store instruction!"); + Result = new GetElementPtrInst(getValue(iType, Oprnds[0]), Idx); + break; + } - Value *Ptr = getValue(iType, Oprnds[1]); - const Type *ValTy = cast<PointerType>(Ptr->getType())->getElementType(); - Result = new StoreInst(getValue(getTypeSlot(ValTy), Oprnds[0]), Ptr, - Opcode == 63); - break; - } - case Instruction::Unwind: - if (Oprnds.size() != 0) error("Invalid unwind instruction!"); - Result = new UnwindInst(); - break; - case Instruction::Unreachable: - if (Oprnds.size() != 0) error("Invalid unreachable instruction!"); - Result = new UnreachableInst(); - break; - } // end switch(Opcode) + case 62: // volatile load + case Instruction::Load: + if (Oprnds.size() != 1 || !isa<PointerType>(InstTy)) + error("Invalid load instruction!"); + Result = new LoadInst(getValue(iType, Oprnds[0]), "", Opcode == 62); + break; + + case 63: // volatile store + case Instruction::Store: { + if (!isa<PointerType>(InstTy) || Oprnds.size() != 2) + error("Invalid store instruction!"); + + Value *Ptr = getValue(iType, Oprnds[1]); + const Type *ValTy = cast<PointerType>(Ptr->getType())->getElementType(); + Result = new StoreInst(getValue(getTypeSlot(ValTy), Oprnds[0]), Ptr, + Opcode == 63); + break; + } + case Instruction::Unwind: + if (Oprnds.size() != 0) error("Invalid unwind instruction!"); + Result = new UnwindInst(); + break; + case Instruction::Unreachable: + if (Oprnds.size() != 0) error("Invalid unreachable instruction!"); + Result = new UnreachableInst(); + break; + } // end switch(Opcode) + } // end if *normal* BB->getInstList().push_back(Result); @@ -1416,6 +1598,98 @@ } } +inline unsigned fixCEOpcodes( + unsigned Opcode, const std::vector<Constant*> &ArgVec +) { + switch (Opcode) { + default: // Pass Through + // If we don't match any of the cases here then the opcode is fine the + // way it is. + break; + case 7: // Add + Opcode = Instruction::Add; + break; + case 8: // Sub + Opcode = Instruction::Sub; + break; + case 9: // Mul + Opcode = Instruction::Mul; + break; + case 10: // Div + // The type of the instruction is based on the operands. We need to select + // either udiv or sdiv based on that type. This expression selects the + // cases where the type is floating point or signed in which case we + // generated an sdiv instruction. + if (ArgVec[0]->getType()->isSigned()) + Opcode = Instruction::SDiv; + else + Opcode = Instruction::UDiv; + break; + + case 11: // Rem + // As with "Div", make the signed/unsigned Rem instruction choice based + // on the type of the instruction. + if (ArgVec[0]->getType()->isSigned()) + Opcode = Instruction::Rem; + else + Opcode = Instruction::Rem; + break; + + case 12: // And + Opcode = Instruction::And; + break; + case 13: // Or + Opcode = Instruction::Or; + break; + case 14: // Xor + Opcode = Instruction::Xor; + break; + case 15: // SetEQ + Opcode = Instruction::SetEQ; + break; + case 16: // SetNE + Opcode = Instruction::SetNE; + break; + case 17: // SetLE + Opcode = Instruction::SetLE; + break; + case 18: // SetGE + Opcode = Instruction::SetGE; + break; + case 19: // SetLT + Opcode = Instruction::SetLT; + break; + case 20: // SetGT + Opcode = Instruction::SetGT; + break; + case 26: // GetElementPtr + Opcode = Instruction::GetElementPtr; + break; + case 28: // Cast + Opcode = Instruction::Cast; + break; + case 30: // Shl + Opcode = Instruction::Shl; + break; + case 31: // Shr + Opcode = Instruction::Shr; + break; + case 34: // Select + Opcode = Instruction::Select; + break; + case 38: // ExtractElement + Opcode = Instruction::ExtractElement; + break; + case 39: // InsertElement + Opcode = Instruction::InsertElement; + break; + case 40: // ShuffleVector + Opcode = Instruction::ShuffleVector; + break; + } + return Opcode; +} + /// Parse a single constant value Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) { // We must check for a ConstantExpr before switching by type because @@ -1470,6 +1744,10 @@ ArgVec.push_back(getConstantValue(ArgTypeSlot, ArgValSlot)); } + // Handle backwards compatibility for the opcode numbers + if (hasSignlessInstructions) + Opcode = fixCEOpcodes(Opcode, ArgVec); + // Construct a ConstantExpr of the appropriate kind if (isExprNumArgs == 1) { // All one-operand expressions if (Opcode != Instruction::Cast) @@ -2242,7 +2520,11 @@ hasNoUndefValue = false; hasNoFlagsForFunctions = false; hasNoUnreachableInst = false; + hasSignlessInstructions = false; + hasSignedIntegers = false; + // Determine which backwards compatibility flags to set based on the + // bytecode file's version number switch (RevisionNum) { case 0: // LLVM 1.0, 1.1 (Released) // Base LLVM 1.0 bytecode format. @@ -2313,11 +2595,26 @@ // In version 4 and above, we did not include the 'unreachable' instruction // in the opcode numbering in the bytecode file. hasNoUnreachableInst = true; - break; // FALL THROUGH case 5: // 1.4 (Released) + // In version 5 and prior, instructions were signless while integer types + // were signed. In version 6, instructions became signed and types became + // signless. For example in version 5 we have the DIV instruction but in + // version 6 we have SDIV and UDIV to replace it. This causes a renumbering + // of the instruction codes in version 6 that must be factored in. + hasSignlessInstructions = true; + + // In version 5 and prior, the integer types were distinguished by sign. + // That is we have UIntTy and IntTy as well as ConstantSInt and + // ConstantUInt. In version 6, the integer types became signless so we + // need to note that we have signed integer types in prior versions. + hasSignedIntegers = true; + + // FALL THROUGH + + case 6: // SignlessTypes Implementation (1.10 release) break; default: Index: llvm/lib/Bytecode/Reader/Reader.h diff -u llvm/lib/Bytecode/Reader/Reader.h:1.34 llvm/lib/Bytecode/Reader/Reader.h:1.34.2.1 --- llvm/lib/Bytecode/Reader/Reader.h:1.34 Thu Oct 12 13:32:30 2006 +++ llvm/lib/Bytecode/Reader/Reader.h Sat Oct 21 03:59:42 2006 @@ -226,6 +226,18 @@ Function* F ///< The function into which BBs will be inserted ); + /// Convert previous opcode values into the current value and/or construct + /// the instruction. This function handles all *abnormal* cases for + /// instruction generation based on obsolete opcode values. The normal cases + /// are handled by the ParseInstruction function. + Instruction* handleObsoleteOpcodes( + unsigned &opcode, ///< The old opcode, possibly updated by this function + std::vector<unsigned> &Oprnds, ///< The operands to the instruction + unsigned &iType, ///< The type code from the bytecode file + const Type* InstTy, ///< The type of the instruction + BasicBlock* BB ///< The basic block to insert into, if we need to + ); + /// @brief Parse a single instruction. void ParseInstruction( std::vector<unsigned>& Args, ///< The arguments to be filled in @@ -336,6 +348,21 @@ // unreachable instruction. bool hasNoUnreachableInst; + // In LLVM 1.6 the VAArg instruction was changed and the VANext instruction + // was dropped. version 4 + // In version 5 and prior, instructions were signless. In version 6, + // instructions became signed. For example in version 5 we have the DIV + // instruction but in version 6 we have SDIV and UDIV to replace it. This + // causes a renumbering of the instruction codes in version 6 that must be + // factored in. + bool hasSignlessInstructions; + + // In version 5 and prior, the integer types were distinguished by sign. + // That is we have UIntTy and IntTy as well as ConstantSInt and + // ConstantUInt. In version 6, the integer types became signless so we + // need to note that we have signed integer types in prior versions. + bool hasSignedIntegers; + /// In release 1.7 we changed intrinsic functions to not be overloaded. There /// is no bytecode change for this, but to optimize the auto-upgrade of calls /// to intrinsic functions, we save a mapping of old function definitions to _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits