For PR786:
[oota-llvm.git] / lib / Target / CBackend / CBackend.cpp
index bc2f7bd5f1f86707e5d077e470e240f893947388..15bf06a6e2a955160db968251963f6cb75384a47 100644 (file)
@@ -121,6 +121,8 @@ namespace {
     
     void writeOperand(Value *Operand);
     void writeOperandInternal(Value *Operand);
+    void writeOperandWithCast(Value* Operand, unsigned Opcode);
+    bool writeInstructionCast(const Instruction &I);
 
   private :
     void lowerIntrinsics(Function &F);
@@ -136,6 +138,8 @@ namespace {
     void printLoop(Loop *L);
 
     void printConstant(Constant *CPV);
+    void printConstantWithCast(Constant *CPV, unsigned Opcode);
+    bool printConstExprCast(const ConstantExpr *CE);
     void printConstantArray(ConstantArray *CPA);
     void printConstantPacked(ConstantPacked *CP);
 
@@ -586,8 +590,12 @@ void CWriter::printConstant(Constant *CPV) {
     case Instruction::Add:
     case Instruction::Sub:
     case Instruction::Mul:
-    case Instruction::Div:
-    case Instruction::Rem:
+    case Instruction::SDiv:
+    case Instruction::UDiv:
+    case Instruction::FDiv:
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem:
     case Instruction::And:
     case Instruction::Or:
     case Instruction::Xor:
@@ -599,14 +607,20 @@ void CWriter::printConstant(Constant *CPV) {
     case Instruction::SetGE:
     case Instruction::Shl:
     case Instruction::Shr:
+    {
       Out << '(';
-      printConstant(CE->getOperand(0));
+      bool NeedsClosingParens = printConstExprCast(CE); 
+      printConstantWithCast(CE->getOperand(0), CE->getOpcode());
       switch (CE->getOpcode()) {
       case Instruction::Add: Out << " + "; break;
       case Instruction::Sub: Out << " - "; break;
       case Instruction::Mul: Out << " * "; break;
-      case Instruction::Div: Out << " / "; break;
-      case Instruction::Rem: Out << " % "; break;
+      case Instruction::URem:
+      case Instruction::SRem: 
+      case Instruction::FRem: Out << " % "; break;
+      case Instruction::UDiv: 
+      case Instruction::SDiv: 
+      case Instruction::FDiv: Out << " / "; break;
       case Instruction::And: Out << " & "; break;
       case Instruction::Or:  Out << " | "; break;
       case Instruction::Xor: Out << " ^ "; break;
@@ -620,9 +634,12 @@ void CWriter::printConstant(Constant *CPV) {
       case Instruction::Shr: Out << " >> "; break;
       default: assert(0 && "Illegal opcode here!");
       }
-      printConstant(CE->getOperand(1));
+      printConstantWithCast(CE->getOperand(1), CE->getOpcode());
+      if (NeedsClosingParens)
+        Out << "))";
       Out << ')';
       return;
+    }
 
     default:
       std::cerr << "CWriter Error: Unhandled constant expression: "
@@ -685,7 +702,7 @@ void CWriter::printConstant(Constant *CPV) {
         // The prefix for a quiet NaN is 0x7FF8. For a signalling NaN,
         // it's 0x7ff4.
         const unsigned long QuietNaN = 0x7ff8UL;
-        const unsigned long SignalNaN = 0x7ff4UL;
+        //const unsigned long SignalNaN = 0x7ff4UL;
 
         // We need to grab the first part of the FP #
         char Buffer[100];
@@ -805,6 +822,78 @@ void CWriter::printConstant(Constant *CPV) {
   }
 }
 
+// Some constant expressions need to be casted back to the original types
+// because their operands were casted to the expected type. This function takes
+// care of detecting that case and printing the cast for the ConstantExpr.
+bool CWriter::printConstExprCast(const ConstantExpr* CE) {
+  bool Result = false;
+  const Type* Ty = CE->getOperand(0)->getType();
+  switch (CE->getOpcode()) {
+  case Instruction::UDiv: 
+  case Instruction::URem: 
+    Result = Ty->isSigned(); break;
+  case Instruction::SDiv: 
+  case Instruction::SRem: 
+    Result = Ty->isUnsigned(); break;
+  default: break;
+  }
+  if (Result) {
+    Out << "((";
+    printType(Out, Ty);
+    Out << ")(";
+  }
+  return Result;
+}
+
+//  Print a constant assuming that it is the operand for a given Opcode. The
+//  opcodes that care about sign need to cast their operands to the expected
+//  type before the operation proceeds. This function does the casting.
+void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
+
+  // Extract the operand's type, we'll need it.
+  const Type* OpTy = CPV->getType();
+
+  // Indicate whether to do the cast or not.
+  bool shouldCast = false;
+
+  // Based on the Opcode for which this Constant is being written, determine
+  // the new type to which the operand should be casted by setting the value
+  // of OpTy. If we change OpTy, also set shouldCast to true.
+  switch (Opcode) {
+    default:
+      // for most instructions, it doesn't matter
+      break; 
+    case Instruction::UDiv:
+    case Instruction::URem:
+      // For UDiv/URem get correct type
+      if (OpTy->isSigned()) {
+        OpTy = OpTy->getUnsignedVersion();
+        shouldCast = true;
+      }
+      break;
+    case Instruction::SDiv:
+    case Instruction::SRem:
+      // For SDiv/SRem get correct type
+      if (OpTy->isUnsigned()) {
+        OpTy = OpTy->getSignedVersion();
+        shouldCast = true;
+      }
+      break;
+  }
+
+  // Write out the casted constnat if we should, otherwise just write the
+  // operand.
+  if (shouldCast) {
+    Out << "((";
+    printType(Out, OpTy);
+    Out << ")";
+    printConstant(CPV);
+    Out << ")";
+  } else 
+    writeOperand(CPV);
+
+}
+
 void CWriter::writeOperandInternal(Value *Operand) {
   if (Instruction *I = dyn_cast<Instruction>(Operand))
     if (isInlinableInst(*I) && !isDirectAlloca(I)) {
@@ -833,6 +922,78 @@ void CWriter::writeOperand(Value *Operand) {
     Out << ')';
 }
 
+// Some instructions need to have their result value casted back to the 
+// original types because their operands were casted to the expected type. 
+// This function takes care of detecting that case and printing the cast 
+// for the Instruction.
+bool CWriter::writeInstructionCast(const Instruction &I) {
+  bool Result = false;
+  const Type* Ty = I.getOperand(0)->getType();
+  switch (I.getOpcode()) {
+  case Instruction::UDiv: 
+  case Instruction::URem: 
+    Result = Ty->isSigned(); break;
+  case Instruction::SDiv: 
+  case Instruction::SRem: 
+    Result = Ty->isUnsigned(); break;
+  default: break;
+  }
+  if (Result) {
+    Out << "((";
+    printType(Out, Ty);
+    Out << ")(";
+  }
+  return Result;
+}
+
+// Write the operand with a cast to another type based on the Opcode being used.
+// This will be used in cases where an instruction has specific type
+// requirements (usually signedness) for its operands. 
+void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
+
+  // Extract the operand's type, we'll need it.
+  const Type* OpTy = Operand->getType();
+
+  // Indicate whether to do the cast or not.
+  bool shouldCast = false;
+
+  // Based on the Opcode for which this Operand is being written, determine
+  // the new type to which the operand should be casted by setting the value
+  // of OpTy. If we change OpTy, also set shouldCast to true.
+  switch (Opcode) {
+    default:
+      // for most instructions, it doesn't matter
+      break; 
+    case Instruction::UDiv:
+    case Instruction::URem:
+      // For UDiv to have unsigned operands
+      if (OpTy->isSigned()) {
+        OpTy = OpTy->getUnsignedVersion();
+        shouldCast = true;
+      }
+      break;
+    case Instruction::SDiv:
+    case Instruction::SRem:
+      if (OpTy->isUnsigned()) {
+        OpTy = OpTy->getSignedVersion();
+        shouldCast = true;
+      }
+      break;
+  }
+
+  // Write out the casted operand if we should, otherwise just write the
+  // operand.
+  if (shouldCast) {
+    Out << "((";
+    printType(Out, OpTy);
+    Out << ")";
+    writeOperand(Operand);
+    Out << ")";
+  } else 
+    writeOperand(Operand);
+
+}
+
 // generateCompilerSpecificCode - This is where we add conditional compilation
 // directives to cater to specific compilers as need be.
 //
@@ -1630,8 +1791,7 @@ void CWriter::visitBinaryOperator(Instruction &I) {
     Out << "-(";
     writeOperand(BinaryOperator::getNegArgument(cast<BinaryOperator>(&I)));
     Out << ")";
-  } else if (I.getOpcode() == Instruction::Rem && 
-             I.getType()->isFloatingPoint()) {
+  } else if (I.getOpcode() == Instruction::FRem) {
     // Output a call to fmod/fmodf instead of emitting a%b
     if (I.getType() == Type::FloatTy)
       Out << "fmodf(";
@@ -1642,14 +1802,26 @@ void CWriter::visitBinaryOperator(Instruction &I) {
     writeOperand(I.getOperand(1));
     Out << ")";
   } else {
-    writeOperand(I.getOperand(0));
+
+    // Write out the cast of the instruction's value back to the proper type
+    // if necessary.
+    bool NeedsClosingParens = writeInstructionCast(I);
+
+    // Certain instructions require the operand to be forced to a specific type
+    // so we use writeOperandWithCast here instead of writeOperand. Similarly
+    // below for operand 1
+    writeOperandWithCast(I.getOperand(0), I.getOpcode());
 
     switch (I.getOpcode()) {
     case Instruction::Add: Out << " + "; break;
     case Instruction::Sub: Out << " - "; break;
     case Instruction::Mul: Out << '*'; break;
-    case Instruction::Div: Out << '/'; break;
-    case Instruction::Rem: Out << '%'; break;
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem: Out << '%'; break;
+    case Instruction::UDiv:
+    case Instruction::SDiv: 
+    case Instruction::FDiv: Out << '/'; break;
     case Instruction::And: Out << " & "; break;
     case Instruction::Or: Out << " | "; break;
     case Instruction::Xor: Out << " ^ "; break;
@@ -1664,7 +1836,9 @@ void CWriter::visitBinaryOperator(Instruction &I) {
     default: std::cerr << "Invalid operator type!" << I; abort();
     }
 
-    writeOperand(I.getOperand(1));
+    writeOperandWithCast(I.getOperand(1), I.getOpcode());
+    if (NeedsClosingParens)
+      Out << "))";
   }
 
   if (needsCast) {
@@ -1966,7 +2140,7 @@ void CWriter::printIndexingExpression(Value *Ptr, gep_type_iterator I,
                                       gep_type_iterator E) {
   bool HasImplicitAddress = false;
   // If accessing a global value with no indexing, avoid *(&GV) syndrome
-  if (GlobalValue *V = dyn_cast<GlobalValue>(Ptr)) {
+  if (isa<GlobalValue>(Ptr)) {
     HasImplicitAddress = true;
   } else if (isDirectAlloca(Ptr)) {
     HasImplicitAddress = true;