diff options
Diffstat (limited to 'lib/Bytecode')
-rw-r--r-- | lib/Bytecode/Reader/Reader.cpp | 231 | ||||
-rw-r--r-- | lib/Bytecode/Reader/Reader.h | 13 | ||||
-rw-r--r-- | lib/Bytecode/Writer/Writer.cpp | 30 |
3 files changed, 210 insertions, 64 deletions
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp index 86e011eb0a..9a501f183a 100644 --- a/lib/Bytecode/Reader/Reader.cpp +++ b/lib/Bytecode/Reader/Reader.cpp @@ -461,24 +461,23 @@ void BytecodeReader::insertArguments(Function* F) { 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 @@ BytecodeReader::upgradeInstrOpcodes( 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 @@ BytecodeReader::upgradeInstrOpcodes( 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 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, 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 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, Result = PN; break; } - case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: @@ -960,7 +1101,6 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, 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 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, 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 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, 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 @@ void BytecodeReader::ParseTypes(TypeListTy &Tab, unsigned NumEntries){ // 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 @@ inline unsigned BytecodeReader::upgradeCEOpcodes( 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 @@ inline unsigned BytecodeReader::upgradeCEOpcodes( Opcode = Instruction::ShuffleVector; break; } - return Opcode; + return 0; } /// Parse a single constant value @@ -1663,19 +1811,22 @@ Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) { } // 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) { diff --git a/lib/Bytecode/Reader/Reader.h b/lib/Bytecode/Reader/Reader.h index 37c4324c3e..3ede6eb034 100644 --- a/lib/Bytecode/Reader/Reader.h +++ b/lib/Bytecode/Reader/Reader.h @@ -230,19 +230,20 @@ protected: /// 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. diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp index dbc789652a..f2ded65b07 100644 --- a/lib/Bytecode/Writer/Writer.cpp +++ b/lib/Bytecode/Writer/Writer.cpp @@ -291,7 +291,7 @@ void BytecodeWriter::outputConstant(const Constant *CPV) { if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV)) { // FIXME: Encoding of constant exprs could be much more compact! assert(CE->getNumOperands() > 0 && "ConstantExpr with 0 operands"); - assert(CE->getNumOperands() != 1 || CE->getOpcode() == Instruction::Cast); + assert(CE->getNumOperands() != 1 || CE->isCast()); output_vbr(1+CE->getNumOperands()); // flags as an expr output_vbr(CE->getOpcode()); // Put out the CE op code @@ -446,8 +446,8 @@ void BytecodeWriter::outputInstructionFormat0(const Instruction *I, output_typeid(Type); // Result type unsigned NumArgs = I->getNumOperands(); - output_vbr(NumArgs + (isa<CastInst>(I) || - isa<VAArgInst>(I) || Opcode == 56 || Opcode == 58)); + output_vbr(NumArgs + (isa<CastInst>(I) || isa<InvokeInst>(I) || + isa<VAArgInst>(I) || Opcode == 58)); if (!isa<GetElementPtrInst>(&I)) { for (unsigned i = 0; i < NumArgs; ++i) { @@ -460,7 +460,7 @@ void BytecodeWriter::outputInstructionFormat0(const Instruction *I, int Slot = Table.getSlot(I->getType()); assert(Slot != -1 && "Cast return type unknown?"); output_typeid((unsigned)Slot); - } else if (Opcode == 56) { // Invoke escape sequence + } else if (isa<InvokeInst>(I)) { output_vbr(cast<InvokeInst>(I)->getCallingConv()); } else if (Opcode == 58) { // Call escape sequence output_vbr((cast<CallInst>(I)->getCallingConv() << 1) | @@ -528,8 +528,8 @@ void BytecodeWriter::outputInstrVarArgsCall(const Instruction *I, // variable argument. NumFixedOperands = 3+NumParams; } - output_vbr(2 * I->getNumOperands()-NumFixedOperands + - unsigned(Opcode == 56 || Opcode == 58)); + output_vbr(2 * I->getNumOperands()-NumFixedOperands + + unsigned(Opcode == 58 || isa<InvokeInst>(I))); // The type for the function has already been emitted in the type field of the // instruction. Just emit the slot # now. @@ -551,12 +551,12 @@ void BytecodeWriter::outputInstrVarArgsCall(const Instruction *I, output_vbr((unsigned)Slot); } - // If this is the escape sequence for call, emit the tailcall/cc info. - if (Opcode == 58) { + if (isa<InvokeInst>(I)) { + // Emit the tail call/calling conv for invoke instructions + output_vbr(cast<InvokeInst>(I)->getCallingConv()); + } else if (Opcode == 58) { const CallInst *CI = cast<CallInst>(I); output_vbr((CI->getCallingConv() << 1) | unsigned(CI->isTailCall())); - } else if (Opcode == 56) { // Invoke escape sequence. - output_vbr(cast<InvokeInst>(I)->getCallingConv()); } } @@ -619,7 +619,7 @@ inline void BytecodeWriter::outputInstructionFormat3(const Instruction *I, } void BytecodeWriter::outputInstruction(const Instruction &I) { - assert(I.getOpcode() < 56 && "Opcode too big???"); + assert(I.getOpcode() < 57 && "Opcode too big???"); unsigned Opcode = I.getOpcode(); unsigned NumOperands = I.getNumOperands(); @@ -639,12 +639,6 @@ void BytecodeWriter::outputInstruction(const Instruction &I) { } else { Opcode = 58; // Call escape sequence. } - } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) { - if (II->getCallingConv() == CallingConv::Fast) - Opcode = 57; // FastCC invoke. - else if (II->getCallingConv() != CallingConv::C) - Opcode = 56; // Invoke escape sequence. - } else if (isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) { Opcode = 62; } else if (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()) { @@ -750,7 +744,7 @@ void BytecodeWriter::outputInstruction(const Instruction &I) { if (Slots[NumOperands-1] > MaxOpSlot) MaxOpSlot = Slots[NumOperands-1]; } - } else if (Opcode == 56) { + } else if (isa<InvokeInst>(I)) { // Invoke escape seq has at least 4 operands to encode. ++NumOperands; } |