[llvm-commits] CVS: llvm/lib/Bytecode/Reader/Reader.cpp Reader.h

Reid Spencer reid at x10sys.com
Wed Oct 25 23:16:27 PDT 2006



Changes in directory llvm/lib/Bytecode/Reader:

Reader.cpp updated: 1.199 -> 1.200
Reader.h updated: 1.34 -> 1.35
---
Log message:

For PR950: http://llvm.org/PR950 :
Make necessary changes to support DIV -> [SUF]Div. This changes llvm to
have three division instructions: signed, unsigned, floating point. The
bytecode and assembler are bacwards compatible, however.


---
Diffs of the changes:  (+713 -370)

 Reader.cpp | 1064 +++++++++++++++++++++++++++++++++++++++----------------------
 Reader.h   |   19 +
 2 files changed, 713 insertions(+), 370 deletions(-)


Index: llvm/lib/Bytecode/Reader/Reader.cpp
diff -u llvm/lib/Bytecode/Reader/Reader.cpp:1.199 llvm/lib/Bytecode/Reader/Reader.cpp:1.200
--- llvm/lib/Bytecode/Reader/Reader.cpp:1.199	Fri Oct 20 02:07:24 2006
+++ llvm/lib/Bytecode/Reader/Reader.cpp	Thu Oct 26 01:15:43 2006
@@ -562,6 +562,244 @@
     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.
+// 
+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
+) {
+
+  // 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 0; // The opcode is fine the way it is.
+
+  // 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) {
+    default: // Error
+      // This switch statement provides cases for all known opcodes prior to
+      // version 6 bytecode format. We know we're in an upgrade situation so
+      // if there isn't a match in this switch, then something is horribly
+      // wrong.
+      error("Unknown obsolete opcode encountered.");
+      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
+      // fdiv, udiv or sdiv based on that type. The iType values are hardcoded
+      // to the values used in bytecode version 5 (and prior) because it is
+      // likely these codes will change in future versions of LLVM.
+      if (iType == 10 || iType == 11 )
+        Opcode = Instruction::FDiv;
+      else if (iType >= 2 && iType <= 9 && iType % 2 != 0)
+        Opcode = Instruction::SDiv;
+      else
+        Opcode = Instruction::UDiv;
+      break;
+
+    case 11: // Rem
+        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);
+
+      // In llvm 1.6 the VANext instruction was dropped because it was only 
+      // necessary to have a VAArg instruction. The code below transforms an
+      // old vanext instruction into the equivalent code given only the 
+      // availability of the new vaarg instruction. Essentially, the transform
+      // is as follows:
+      //    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);
+
+      // In llvm 1.6 the VAArg's instruction semantics were changed.  The code 
+      // below transforms an old vaarg instruction into the equivalent code 
+      // given only the availability of the new vaarg instruction. Essentially,
+      // the transform is as follows:
+      //    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;
+    case 56: // Invoke with encoded CC
+    case 57: // Invoke Fast CC
+    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 62: // volatile load
+    case 63: // volatile store
+      // In all these cases, we pass the opcode through. The new version uses
+      // the same code (for now, this might change in 2.0). These are listed
+      // here to document the opcodes in use in vers 5 bytecode and to make it
+      // easier to migrate these opcodes in the future.
+      break;
+  }
+  return Result;
+}
+
 //===----------------------------------------------------------------------===//
 // Bytecode Parsing Methods
 //===----------------------------------------------------------------------===//
@@ -643,411 +881,376 @@
 
   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);
+  if (Handler) 
+    Handler->handleInstruction(Opcode, InstTy, Oprnds, At-SaveAt);
 
-  // Declare the resulting instruction we'll build.
-  Instruction *Result = 0;
+  // 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).
+    // 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!");
 
-  // 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;
+      Result = new ExtractElementInst(V1, V2);
+      break;
     }
-  }
-
-  // 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;
-  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;
-  }
-  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]);
+    case Instruction::InsertElement: {
+      const PackedType *PackedTy = dyn_cast<PackedType>(InstTy);
+      if (!PackedTy || Oprnds.size() != 3)
+        error("Invalid insertelement instruction!");
       
-    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;
-  }
-
-  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;
-  }
-
-  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 *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;
+    }
 
-    unsigned CallingConv = CallingConv::C;
-    bool isTailCall = false;
+    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;
 
-    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;
+    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;
     }
-    
-    // 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();
+    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!");
 
-      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);
+      Value *F = getValue(iType, Oprnds[0]);
 
-      unsigned FirstVariableOperand;
-      if (Oprnds.size() < FTy->getNumParams())
-        error("Call instruction missing operands!");
+      unsigned CallingConv = CallingConv::C;
+      bool isTailCall = false;
 
-      // 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();
+      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 ((Oprnds.size()-FirstVariableOperand) & 1)
-        error("Invalid call instruction!");   // Must be pairs of type/value
+        unsigned FirstVariableOperand;
+        if (Oprnds.size() < FTy->getNumParams())
+          error("Call instruction missing operands!");
 
-      for (unsigned i = FirstVariableOperand, e = Oprnds.size();
-           i != e; i += 2)
-        Params.push_back(getValue(Oprnds[i], Oprnds[i+1]));
-    }
+        // 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]));
 
-    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]);
+        FirstVariableOperand = FTy->getNumParams();
 
-    // 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 ((Oprnds.size()-FirstVariableOperand) & 1)
+          error("Invalid call instruction!");   // Must be pairs of type/value
 
-    std::vector<Value *> Params;
-    BasicBlock *Normal, *Except;
-    unsigned CallingConv = CallingConv::C;
+        for (unsigned i = FirstVariableOperand, e = Oprnds.size();
+             i != e; i += 2)
+          Params.push_back(getValue(Oprnds[i], Oprnds[i+1]));
+      }
 
-    if (Opcode == 57)
-      CallingConv = CallingConv::Fast;
-    else if (Opcode == 56) {
-      CallingConv = Oprnds.back();
-      Oprnds.pop_back();
+      Result = new CallInst(F, Params);
+      if (isTailCall) cast<CallInst>(Result)->setTailCall();
+      if (CallingConv) cast<CallInst>(Result)->setCallingConv(CallingConv);
+      break;
     }
-
-    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())
+    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!");
-    } else {
-      Oprnds.erase(Oprnds.begin(), Oprnds.begin()+1);
-
-      Normal = getBasicBlock(Oprnds[0]);
-      Except = getBasicBlock(Oprnds[1]);
+      Value *F = getValue(iType, Oprnds[0]);
 
-      unsigned FirstVariableArgument = FTy->getNumParams()+2;
-      for (unsigned i = 2; i != FirstVariableArgument; ++i)
-        Params.push_back(getValue(getTypeSlot(FTy->getParamType(i-2)),
-                                  Oprnds[i]));
+      // 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();
+      }
 
-      if (Oprnds.size()-FirstVariableArgument & 1) // Must be type/value pairs
-        error("Invalid invoke instruction!");
+      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);
 
-      for (unsigned i = FirstVariableArgument; i < Oprnds.size(); i += 2)
-        Params.push_back(getValue(Oprnds[i], Oprnds[i+1]));
-    }
+        Normal = getBasicBlock(Oprnds[0]);
+        Except = getBasicBlock(Oprnds[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!");
+        unsigned FirstVariableArgument = FTy->getNumParams()+2;
+        for (unsigned i = 2; i != FirstVariableArgument; ++i)
+          Params.push_back(getValue(getTypeSlot(FTy->getParamType(i-2)),
+                                    Oprnds[i]));
 
-    Result = new MallocInst(cast<PointerType>(InstTy)->getElementType(),
-                            getValue(Type::UIntTyID, Oprnds[0]), Align);
-    break;
-  }
+        // Must be type/value pairs. If not, error out.
+        if (Oprnds.size()-FirstVariableArgument & 1) 
+          error("Invalid invoke instruction!");
 
-  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!");
+        for (unsigned i = FirstVariableArgument; i < Oprnds.size(); i += 2)
+          Params.push_back(getValue(Oprnds[i], Oprnds[i+1]));
+      }
 
-    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!");
+      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!");
 
-    std::vector<Value*> Idx;
+      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!");
 
-    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)
+      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!");
 
-      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;
+      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;
           }
-          ValIdx >>= 2;
+        } else {
+          IdxTy = isa<StructType>(TopTy) ? Type::UByteTyID : Type::LongTyID;
         }
-      } else {
-        IdxTy = isa<StructType>(TopTy) ? Type::UByteTyID : Type::LongTyID;
-      }
-
-      Idx.push_back(getValue(IdxTy, ValIdx));
-
-      // 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);
 
-      NextTy = GetElementPtrInst::getIndexedType(InstTy, Idx, true);
-    }
+        Idx.push_back(getValue(IdxTy, ValIdx));
 
-    Result = new GetElementPtrInst(getValue(iType, Oprnds[0]), Idx);
-    break;
-  }
+        // 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);
 
-  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!");
+        NextTy = GetElementPtrInst::getIndexedType(InstTy, Idx, true);
+      }
 
-    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)
+      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;
+    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);
 
@@ -1414,6 +1617,110 @@
   }
 }
 
+// Upgrade obsolete constant expression opcodes (ver. 5 and prior) to the new 
+// 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. 
+// 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(
+  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()->isFloatingPoint())
+        Opcode = Instruction::FDiv;
+      else 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()->isFloatingPoint())
+        Opcode = Instruction::Rem;
+      else 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
@@ -1468,6 +1775,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)
@@ -2240,7 +2551,10 @@
   hasNoUndefValue = false;
   hasNoFlagsForFunctions = false;
   hasNoUnreachableInst = false;
+  hasSignlessInstructions = 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.
@@ -2311,11 +2625,21 @@
     // 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 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;
+
+    // FALL THROUGH
+    
+  case 6:               // SignlessTypes Implementation (1.9 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.35
--- llvm/lib/Bytecode/Reader/Reader.h:1.34	Thu Oct 12 13:32:30 2006
+++ llvm/lib/Bytecode/Reader/Reader.h	Thu Oct 26 01:15:43 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,13 @@
   // 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 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






More information about the llvm-commits mailing list