Bump the bytecode version number to 7. Implement upgrade of version 6 and

version 6 bytecode.

llvm-svn: 31573
This commit is contained in:
Reid Spencer 2006-11-08 21:27:54 +00:00
parent 3b3b786f03
commit c4ecf9ff47
3 changed files with 107 additions and 29 deletions

View File

@ -574,7 +574,7 @@ void BytecodeReader::insertArguments(Function* F) {
// instruction generation should be used, but with the new Opcode value.
//
Instruction*
BytecodeReader::handleObsoleteOpcodes(
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
@ -583,24 +583,53 @@ BytecodeReader::handleObsoleteOpcodes(
) {
// 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)
// instructions were implemented the entire opcode sequence was revised in
// two stages: first Div/Rem became signed, then Shr/Cast/Setcc became
// signed. If all of these instructions are signed then we don't have to
// upgrade the opcode.
if (!hasSignlessDivRem && !hasSignlessShrCastSetcc)
return 0; // The opcode is fine the way it is.
// If this is a bytecode format that did not include the unreachable
// instruction, bump up the opcode number to adjust it.
if (hasNoUnreachableInst)
if (Opcode >= 6 && Opcode < 62)
++Opcode;
// If this is bytecode version 6, that only had signed Rem and Div
// instructions, then we must compensate for those two instructions only.
// So that the switch statement below works, we're trying to turn this into
// a version 5 opcode. To do that we must adjust the opcode to 10 (Div) if its
// any of the UDiv, SDiv or FDiv instructions; or, adjust the opcode to
// 11 (Rem) if its any of the URem, SRem, or FRem instructions; or, simply
// decrement the instruction code if its beyond FRem.
if (!hasSignlessDivRem) {
// If its one of the signed Div/Rem opcodes, its fine the way it is
if (Opcode >= 10 && Opcode <= 12) // UDiv through FDiv
Opcode = 10; // Div
else if (Opcode >=13 && Opcode <= 15) // URem through FRem
Opcode = 11; // Rem
else if (Opcode >= 16 && Opcode <= 35) // And through Shr
// Adjust for new instruction codes
Opcode -= 4;
else if (Opcode >= 36 && Opcode <= 42) // Everything after Select
// In vers 6 bytecode we eliminated the placeholders for the obsolete
// VAARG and VANEXT instructions. Consequently those two slots were
// filled starting with Select (36) which was 34. So now we only need
// to subtract two. This circumvents hitting opcodes 32 and 33
Opcode -= 2;
else { // Opcode < 10 or > 42
// No upgrade necessary.
return 0;
}
}
// Declare the resulting instruction we might build. In general we just
// change the Opcode argument but in a few cases we need to generate the
// Instruction here because the upgrade case is significantly different from
// the normal case.
Instruction *Result = 0;
// If this is a bytecode format that did not include the unreachable
// instruction, bump up the opcode number to adjust it.
if (hasNoUnreachableInst)
if (Opcode >= Instruction::Unreachable && Opcode < 62)
++Opcode;
// We're dealing with an upgrade situation. For each of the opcode values,
// perform the necessary conversion.
switch (Opcode) {
@ -899,7 +928,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
// Make the necessary adjustments for dealing with backwards compatibility
// of opcodes.
Instruction* Result =
handleObsoleteOpcodes(Opcode, Oprnds, iType, InstTy, BB);
upgradeInstrOpcodes(Opcode, Oprnds, iType, InstTy, BB);
// We have enough info to inform the handler now.
if (Handler)
@ -1636,13 +1665,43 @@ void BytecodeReader::ParseTypes(TypeListTy &Tab, unsigned NumEntries){
// values used after ver 6. bytecode format. The operands are provided to the
// function so that decisions based on the operand type can be made when
// auto-upgrading obsolete opcodes to the new ones.
// NOTE: This code needs to be kept synchronized with handleObsoleteOpcodes.
// NOTE: This code needs to be kept synchronized with upgradeInstrOpcodes.
// 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 handleObsoleteOpcodes.
inline unsigned fixCEOpcodes(
// constant expressions and is therefore simpler than upgradeInstrOpcodes.
inline unsigned BytecodeReader::upgradeCEOpcodes(
unsigned Opcode, const std::vector<Constant*> &ArgVec
) {
// Determine if no upgrade necessary
if (!hasSignlessDivRem && !hasSignlessShrCastSetcc)
return Opcode;
#if 0
// If this is a bytecode format that did not include the unreachable
// instruction, bump up the opcode number to adjust it.
if (hasNoUnreachableInst)
if (Opcode >= 6 && Opcode < 62)
++Opcode;
#endif
// If this is bytecode version 6, that only had signed Rem and Div
// instructions, then we must compensate for those two instructions only.
// So that the switch statement below works, we're trying to turn this into
// a version 5 opcode. To do that we must adjust the opcode to 10 (Div) if its
// any of the UDiv, SDiv or FDiv instructions; or, adjust the opcode to
// 11 (Rem) if its any of the URem, SRem, or FRem instructions; or, simply
// decrement the instruction code if its beyond FRem.
if (!hasSignlessDivRem) {
// If its one of the signed Div/Rem opcodes, its fine the way it is
if (Opcode >= 10 && Opcode <= 12) // UDiv through FDiv
Opcode = 10; // Div
else if (Opcode >=13 && Opcode <= 15) // URem through FRem
Opcode = 11; // Rem
else if (Opcode > 15) // Everything above FRem
// Adjust for new instruction codes
Opcode -= 4;
}
switch (Opcode) {
default: // Pass Through
// If we don't match any of the cases here then the opcode is fine the
@ -1792,8 +1851,7 @@ Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) {
}
// Handle backwards compatibility for the opcode numbers
if (hasSignlessInstructions)
Opcode = fixCEOpcodes(Opcode, ArgVec);
Opcode = upgradeCEOpcodes(Opcode, ArgVec);
// Construct a ConstantExpr of the appropriate kind
if (isExprNumArgs == 1) { // All one-operand expressions
@ -2567,7 +2625,8 @@ void BytecodeReader::ParseVersionInfo() {
hasNoUndefValue = false;
hasNoFlagsForFunctions = false;
hasNoUnreachableInst = false;
hasSignlessInstructions = false;
hasSignlessDivRem = false;
hasSignlessShrCastSetcc = false;
// Determine which backwards compatibility flags to set based on the
// bytecode file's version number
@ -2645,17 +2704,26 @@ void BytecodeReader::ParseVersionInfo() {
// FALL THROUGH
case 5: // 1.4 (Released)
// In version 6, the Div and Rem instructions were converted to their
// signed and floating point counterparts: UDiv, SDiv, FDiv, URem, SRem,
// and FRem. Versions prior to 6 need to indicate that they have the
// signless Div and Rem instructions.
hasSignlessDivRem = true;
// FALL THROUGH
case 6: // Signless Rem & Div Implementation (1.9 release)
// 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 FDIV, SDIV and UDIV to replace it. This caused a
// renumbering of the instruction codes in version 6 that must be dealt with
// when reading old bytecode files.
hasSignlessInstructions = true;
hasSignlessShrCastSetcc = true;
// FALL THROUGH
case 6: // SignlessTypes Implementation (1.9 release)
case 7:
break;
default:

View File

@ -230,7 +230,7 @@ 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* handleObsoleteOpcodes(
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
@ -238,6 +238,13 @@ protected:
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
);
/// @brief Parse a single instruction.
void ParseInstruction(
std::vector<unsigned>& Args, ///< The arguments to be filled in
@ -348,12 +355,15 @@ private:
// unreachable instruction.
bool hasNoUnreachableInst;
// 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 FDIV, SDIV and UDIV to replace it.
// This causes a renumbering of the instruction codes in version 6 that must
// be dealt with when reading old bytecode files.
bool hasSignlessInstructions;
// In version 6, the Div and Rem instructions were converted to be the
// signed instructions UDiv, SDiv, URem and SRem. This flag will be true if
// the Div and Rem instructions are signless (ver 5 and prior).
bool hasSignlessDivRem;
// In version 7, the Shr, Cast and Setcc instructions changed to their
// signed counterparts. This flag will be true if these instructions are
// signless (version 6 and prior).
bool hasSignlessShrCastSetcc;
/// 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

View File

@ -40,7 +40,7 @@ using namespace llvm;
/// so that the reader can distinguish which format of the bytecode file has
/// been written.
/// @brief The bytecode version number
const unsigned BCVersionNum = 6;
const unsigned BCVersionNum = 7;
static RegisterPass<WriteBytecodePass> X("emitbytecode", "Bytecode Writer");