For 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.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31195 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index 425d2ab..684b643 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -813,6 +813,43 @@
   return Ty;
 }
 
+/// This function is used to obtain the correct opcode for an instruction when 
+/// an obsolete opcode is encountered. The OI parameter (OpcodeInfo) has both 
+/// an opcode and an "obsolete" flag. These are generated by the lexer and 
+/// the "obsolete" member will be true when the lexer encounters the token for
+/// an obsolete opcode. For example, "div" was replaced by [usf]div but we need
+/// to maintain backwards compatibility for asm files that still have the "div"
+/// instruction. This function handles converting div -> [usf]div appropriately.
+/// @brief Convert obsolete opcodes to new values
+static void 
+sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const PATypeHolder& PATy)
+{
+  // If its not obsolete, don't do anything
+  if (!OI.obsolete) 
+    return;
+
+  // If its a packed type we want to use the element type
+  const Type* Ty = PATy;
+  if (const PackedType* PTy = dyn_cast<PackedType>(Ty))
+    Ty = PTy->getElementType();
+
+  // Depending on the opcode ..
+  switch (OI.opcode) {
+    default:
+      GenerateError("Invalid Obsolete OpCode");
+      break;
+    case Instruction::UDiv:
+      // Handle cases where the opcode needs to change
+      if (Ty->isFloatingPoint()) 
+        OI.opcode = Instruction::FDiv;
+      else if (Ty->isSigned())
+        OI.opcode = Instruction::SDiv;
+      break;
+  }
+  // Its not obsolete any more, we fixed it.
+  OI.obsolete = false;
+}
+
 
 // common code from the two 'RunVMAsmParser' functions
 static Module* RunParser(Module * M) {
@@ -1002,13 +1039,13 @@
   bool                              BoolVal;
 
   char                             *StrVal;   // This memory is strdup'd!
-  llvm::ValID                             ValIDVal; // strdup'd memory maybe!
+  llvm::ValID                       ValIDVal; // strdup'd memory maybe!
 
-  llvm::Instruction::BinaryOps            BinaryOpVal;
-  llvm::Instruction::TermOps              TermOpVal;
-  llvm::Instruction::MemoryOps            MemOpVal;
-  llvm::Instruction::OtherOps             OtherOpVal;
-  llvm::Module::Endianness                Endianness;
+  BinaryOpInfo                      BinaryOpVal;
+  TermOpInfo                        TermOpVal;
+  MemOpInfo                         MemOpVal;
+  OtherOpInfo                       OtherOpVal;
+  llvm::Module::Endianness          Endianness;
 }
 
 %type <ModuleVal>     Module FunctionList
@@ -1076,8 +1113,8 @@
 
 // Binary Operators
 %type  <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
-%token <BinaryOpVal> ADD SUB MUL DIV REM AND OR XOR
-%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE  // Binary Comarators
+%token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV REM AND OR XOR
+%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE  // Binary Comparators
 
 // Memory Instructions
 %token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
@@ -1114,7 +1151,7 @@
 // Operations that are notably excluded from this list include:
 // RET, BR, & SWITCH because they end basic blocks and are treated specially.
 //
-ArithmeticOps: ADD | SUB | MUL | DIV | REM;
+ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | REM ;
 LogicalOps   : AND | OR | XOR;
 SetCondOps   : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
 
@@ -1642,12 +1679,17 @@
   | ArithmeticOps '(' ConstVal ',' ConstVal ')' {
     if ($3->getType() != $5->getType())
       GEN_ERROR("Binary operator types must match!");
+    // First, make sure we're dealing with the right opcode by upgrading from
+    // obsolete versions.
+    sanitizeOpCode($1,$3->getType());
+    CHECK_FOR_ERROR;
+
     // HACK: llvm 1.3 and earlier used to emit invalid pointer constant exprs.
     // To retain backward compatibility with these early compilers, we emit a
     // cast to the appropriate integer type automatically if we are in the
     // broken case.  See PR424 for more information.
     if (!isa<PointerType>($3->getType())) {
-      $$ = ConstantExpr::get($1, $3, $5);
+      $$ = ConstantExpr::get($1.opcode, $3, $5);
     } else {
       const Type *IntPtrTy = 0;
       switch (CurModule.CurrentModule->getPointerSize()) {
@@ -1655,7 +1697,7 @@
       case Module::Pointer64: IntPtrTy = Type::LongTy; break;
       default: GEN_ERROR("invalid pointer binary constant expr!");
       }
-      $$ = ConstantExpr::get($1, ConstantExpr::getCast($3, IntPtrTy),
+      $$ = ConstantExpr::get($1.opcode, ConstantExpr::getCast($3, IntPtrTy),
                              ConstantExpr::getCast($5, IntPtrTy));
       $$ = ConstantExpr::getCast($$, $3->getType());
     }
@@ -1669,13 +1711,13 @@
           !cast<PackedType>($3->getType())->getElementType()->isIntegral())
         GEN_ERROR("Logical operator requires integral operands!");
     }
-    $$ = ConstantExpr::get($1, $3, $5);
+    $$ = ConstantExpr::get($1.opcode, $3, $5);
     CHECK_FOR_ERROR
   }
   | SetCondOps '(' ConstVal ',' ConstVal ')' {
     if ($3->getType() != $5->getType())
       GEN_ERROR("setcc operand types must match!");
-    $$ = ConstantExpr::get($1, $3, $5);
+    $$ = ConstantExpr::get($1.opcode, $3, $5);
     CHECK_FOR_ERROR
   }
   | ShiftOps '(' ConstVal ',' ConstVal ')' {
@@ -1683,7 +1725,7 @@
       GEN_ERROR("Shift count for shift constant must be unsigned byte!");
     if (!$3->getType()->isInteger())
       GEN_ERROR("Shift constant expression requires integer operand!");
-    $$ = ConstantExpr::get($1, $3, $5);
+    $$ = ConstantExpr::get($1.opcode, $3, $5);
     CHECK_FOR_ERROR
   }
   | EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' {
@@ -2423,13 +2465,16 @@
         !isa<PackedType>((*$2).get()))
       GEN_ERROR(
         "Arithmetic operator requires integer, FP, or packed operands!");
-    if (isa<PackedType>((*$2).get()) && $1 == Instruction::Rem)
+    if (isa<PackedType>((*$2).get()) && $1.opcode == Instruction::Rem)
       GEN_ERROR("Rem not supported on packed types!");
+    // Upgrade the opcode from obsolete versions before we do anything with it.
+    sanitizeOpCode($1,*$2);
+    CHECK_FOR_ERROR;
     Value* val1 = getVal(*$2, $3); 
     CHECK_FOR_ERROR
     Value* val2 = getVal(*$2, $5);
     CHECK_FOR_ERROR
-    $$ = BinaryOperator::create($1, val1, val2);
+    $$ = BinaryOperator::create($1.opcode, val1, val2);
     if ($$ == 0)
       GEN_ERROR("binary operator returned null!");
     delete $2;
@@ -2444,7 +2489,7 @@
     CHECK_FOR_ERROR
     Value* tmpVal2 = getVal(*$2, $5);
     CHECK_FOR_ERROR
-    $$ = BinaryOperator::create($1, tmpVal1, tmpVal2);
+    $$ = BinaryOperator::create($1.opcode, tmpVal1, tmpVal2);
     if ($$ == 0)
       GEN_ERROR("binary operator returned null!");
     delete $2;
@@ -2458,7 +2503,7 @@
     CHECK_FOR_ERROR
     Value* tmpVal2 = getVal(*$2, $5);
     CHECK_FOR_ERROR
-    $$ = new SetCondInst($1, tmpVal1, tmpVal2);
+    $$ = new SetCondInst($1.opcode, tmpVal1, tmpVal2);
     if ($$ == 0)
       GEN_ERROR("binary operator returned null!");
     delete $2;
@@ -2481,7 +2526,7 @@
       GEN_ERROR("Shift amount must be ubyte!");
     if (!$2->getType()->isInteger())
       GEN_ERROR("Shift constant expression requires integer operand!");
-    $$ = new ShiftInst($1, $2, $4);
+    $$ = new ShiftInst($1.opcode, $2, $4);
     CHECK_FOR_ERROR
   }
   | CAST ResolvedVal TO Types {