Changes in directory llvm/lib/Bytecode/Reader:
Reader.cpp updated: 1.206 -> 1.207 Reader.h updated: 1.38 -> 1.39 --- Log message: For PR950: http://llvm.org/PR950 : The long awaited CAST patch. This introduces 12 new instructions into LLVM to replace the cast instruction. Corresponding changes throughout LLVM are provided. This passes llvm-test, llvm/test, and SPEC CPUINT2000 with the exception of 175.vpr which fails only on a slight floating point output difference. --- Diffs of the changes: (+198 -46) Reader.cpp | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++----------- Reader.h | 13 +-- 2 files changed, 198 insertions(+), 46 deletions(-) Index: llvm/lib/Bytecode/Reader/Reader.cpp diff -u llvm/lib/Bytecode/Reader/Reader.cpp:1.206 llvm/lib/Bytecode/Reader/Reader.cpp:1.207 --- llvm/lib/Bytecode/Reader/Reader.cpp:1.206 Fri Nov 17 22:37:19 2006 +++ llvm/lib/Bytecode/Reader/Reader.cpp Sun Nov 26 19:05:09 2006 @@ -461,24 +461,23 @@ 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. Generally this function just produces a new -// Opcode value (first argument). In a few cases (VAArg, VANext) the upgrade -// path requies that the instruction (sequence) be generated differently from -// the normal case in order to preserve the original semantics. In these -// cases the result of the function will be a non-zero Instruction pointer. In -// all other cases, zero will be returned indicating that the *normal* -// instruction generation should be used, but with the new Opcode value. -// +/// 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. Generally this function just produces a new +/// Opcode value (first argument). In a few cases (VAArg, VANext) the upgrade +/// path requies that the instruction (sequence) be generated differently from +/// the normal case in order to preserve the original semantics. In these +/// cases the result of the function will be a non-zero Instruction pointer. In +/// all other cases, zero will be returned indicating that the *normal* +/// instruction generation should be used, but with the new Opcode value. Instruction* BytecodeReader::upgradeInstrOpcodes( 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 + const Type *InstTy, ///< The type of the instruction + BasicBlock *BB ///< The basic block to insert into, if we need to ) { // First, short circuit this if no conversion is required. When signless @@ -632,8 +631,27 @@ Opcode = Instruction::PHI; break; case 28: // Cast - Opcode = Instruction::Cast; + { + Value *Source = getValue(iType, Oprnds[0]); + const Type *DestTy = getType(Oprnds[1]); + // The previous definition of cast to bool was a compare against zero. + // We have to retain that semantic so we do it here. + if (DestTy == Type::BoolTy) { // if its a cast to bool + Opcode = Instruction::SetNE; + Result = new SetCondInst(Instruction::SetNE, Source, + Constant::getNullValue(Source->getType())); + } else if (Source->getType()->isFloatingPoint() && + isa<PointerType>(DestTy)) { + // Upgrade what is now an illegal cast (fp -> ptr) into two casts, + // fp -> ui, and ui -> ptr + CastInst *CI = new FPToUIInst(Source, Type::ULongTy); + BB->getInstList().push_back(CI); + Result = new IntToPtrInst(CI, DestTy); + } else { + Result = CastInst::createInferredCast(Source, DestTy); + } break; + } case 29: // Call Opcode = Instruction::Call; break; @@ -720,8 +738,66 @@ case 40: // ShuffleVector Opcode = Instruction::ShuffleVector; break; - case 56: // Invoke with encoded CC - case 57: // Invoke Fast CC + case 56: // Invoke with encoded CC + case 57: { // Invoke Fast 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(); + } + Opcode = Instruction::Invoke; + + 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); + + 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])); + + // Must be type/value pairs. If not, error out. + if (Oprnds.size()-FirstVariableArgument & 1) + 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 58: // Call with extra operand for calling conv case 59: // tail call, Fast CC case 60: // normal call, Fast CC @@ -889,12 +965,78 @@ Result = new ShuffleVectorInst(V1, V2, V3); break; } - case Instruction::Cast: + case Instruction::Trunc: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new TruncInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; + case Instruction::ZExt: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new ZExtInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; + case Instruction::SExt: if (Oprnds.size() != 2) error("Invalid Cast instruction!"); - Result = new CastInst(getValue(iType, Oprnds[0]), + Result = new SExtInst(getValue(iType, Oprnds[0]), getType(Oprnds[1])); break; + case Instruction::FPTrunc: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new FPTruncInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; + case Instruction::FPExt: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new FPExtInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; + case Instruction::UIToFP: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new UIToFPInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; + case Instruction::SIToFP: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new SIToFPInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; + case Instruction::FPToUI: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new FPToUIInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; + case Instruction::FPToSI: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new FPToSIInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; + case Instruction::IntToPtr: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new IntToPtrInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; + case Instruction::PtrToInt: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new PtrToIntInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; + case Instruction::BitCast: + if (Oprnds.size() != 2) + error("Invalid cast instruction!"); + Result = new BitCastInst(getValue(iType, Oprnds[0]), + getType(Oprnds[1])); + break; case Instruction::Select: if (Oprnds.size() != 3) error("Invalid Select instruction!"); @@ -914,7 +1056,6 @@ Result = PN; break; } - case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: @@ -960,7 +1101,6 @@ case Instruction::Call: { // Normal Call, C Calling Convention if (Oprnds.size() == 0) error("Invalid call instruction encountered!"); - Value *F = getValue(iType, Oprnds[0]); unsigned CallingConv = CallingConv::C; @@ -1021,8 +1161,6 @@ 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!"); @@ -1038,14 +1176,8 @@ 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(); - } + unsigned CallingConv = Oprnds.back(); + Oprnds.pop_back(); if (!FTy->isVarArg()) { Normal = getBasicBlock(Oprnds[1]); @@ -1486,12 +1618,12 @@ // We can't use that function because of that functions argument requirements. // This function only deals with the subset of opcodes that are applicable to // constant expressions and is therefore simpler than upgradeInstrOpcodes. -inline unsigned BytecodeReader::upgradeCEOpcodes( - unsigned Opcode, const std::vector<Constant*> &ArgVec +inline Constant *BytecodeReader::upgradeCEOpcodes( + unsigned &Opcode, const std::vector<Constant*> &ArgVec, unsigned TypeID ) { // Determine if no upgrade necessary if (!hasSignlessDivRem && !hasSignlessShrCastSetcc) - return Opcode; + return 0; // If this is bytecode version 6, that only had signed Rem and Div // instructions, then we must compensate for those two instructions only. @@ -1587,9 +1719,25 @@ case 26: // GetElementPtr Opcode = Instruction::GetElementPtr; break; - case 28: // Cast - Opcode = Instruction::Cast; + case 28: { // Cast + const Type *Ty = getType(TypeID); + if (Ty == Type::BoolTy) { + // The previous definition of cast to bool was a compare against zero. + // We have to retain that semantic so we do it here. + Opcode = Instruction::SetEQ; + return ConstantExpr::get(Instruction::SetEQ, ArgVec[0], + Constant::getNullValue(ArgVec[0]->getType())); + } else if (ArgVec[0]->getType()->isFloatingPoint() && + isa<PointerType>(Ty)) { + // Upgrade what is now an illegal cast (fp -> ptr) into two casts, + // fp -> ui, and ui -> ptr + Constant *CE = ConstantExpr::getFPToUI(ArgVec[0], Type::ULongTy); + return ConstantExpr::getIntToPtr(CE, Ty); + } else { + Opcode = CastInst::getCastOpcode(ArgVec[0], Ty); + } break; + } case 30: // Shl Opcode = Instruction::Shl; break; @@ -1612,7 +1760,7 @@ Opcode = Instruction::ShuffleVector; break; } - return Opcode; + return 0; } /// Parse a single constant value @@ -1663,19 +1811,22 @@ } // Handle backwards compatibility for the opcode numbers - Opcode = upgradeCEOpcodes(Opcode, ArgVec); + if (Constant *C = upgradeCEOpcodes(Opcode, ArgVec, TypeID)) { + if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, C); + return C; + } // Construct a ConstantExpr of the appropriate kind if (isExprNumArgs == 1) { // All one-operand expressions - if (Opcode != Instruction::Cast) + if (!Instruction::isCast(Opcode)) error("Only cast instruction has one argument for ConstantExpr"); - Constant* Result = ConstantExpr::getCast(ArgVec[0], getType(TypeID)); + Constant *Result = ConstantExpr::getCast(ArgVec[0], getType(TypeID)); if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, Result); return Result; } else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr std::vector<Constant*> IdxList(ArgVec.begin()+1, ArgVec.end()); - Constant* Result = ConstantExpr::getGetElementPtr(ArgVec[0], IdxList); + Constant *Result = ConstantExpr::getGetElementPtr(ArgVec[0], IdxList); if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, Result); return Result; } else if (Opcode == Instruction::Select) { Index: llvm/lib/Bytecode/Reader/Reader.h diff -u llvm/lib/Bytecode/Reader/Reader.h:1.38 llvm/lib/Bytecode/Reader/Reader.h:1.39 --- llvm/lib/Bytecode/Reader/Reader.h:1.38 Mon Nov 13 22:47:22 2006 +++ llvm/lib/Bytecode/Reader/Reader.h Sun Nov 26 19:05:09 2006 @@ -230,19 +230,20 @@ /// 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* upgradeInstrOpcodes( + Instruction *upgradeInstrOpcodes( 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 + const Type *InstTy, ///< The type of the instruction + BasicBlock *BB ///< The basic block to insert into, if we need to ); /// @brief Convert previous opcode values for ConstantExpr into the current /// value. - unsigned upgradeCEOpcodes( - unsigned Opcode, ///< Opcode read from bytecode - const std::vector<Constant*> &ArgVec ///< Arguments of instruction + Constant *upgradeCEOpcodes( + unsigned &Opcode, ///< Opcode read from bytecode + const std::vector<Constant*> &ArgVec, ///< Arguments of instruction + unsigned TypeID ///< TypeID of the instruction type ); /// @brief Parse a single instruction. _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits