For PR950:
The long awaited CAST patch. This introduces 12 new instructions into LLVM
to replace the cast instruction. Corresponding changes throughout LLVM are
provided. This passes llvm-test, llvm/test, and SPEC CPUINT2000 with the
exception of 175.vpr which fails only on a slight floating point output
difference.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31931 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index 9b50669..3c4d9d5 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -213,7 +213,7 @@
           break;  // Found a null terminator, exit.
       
         if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
-          if (CE->getOpcode() == Instruction::Cast)
+          if (CE->isCast())
             FP = CE->getOperand(0);
         if (Function *F = dyn_cast<Function>(FP)) {
           // Execute the ctor/dtor function!
@@ -299,15 +299,21 @@
   return state.getGlobalAddressMap(locked)[GV];
 }
 
-/// FIXME: document
-///
+/// This function converts a Constant* into a GenericValue. The interesting 
+/// part is if C is a ConstantExpr.
+/// @brief Get a GenericValue for a Constnat*
 GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
+  // Declare the result as garbage.
   GenericValue Result;
+
+  // If its undefined, return the garbage.
   if (isa<UndefValue>(C)) return Result;
 
-  if (ConstantExpr *CE = const_cast<ConstantExpr*>(dyn_cast<ConstantExpr>(C))) {
+  // If the value is a ConstantExpr
+  if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
     switch (CE->getOpcode()) {
     case Instruction::GetElementPtr: {
+      // Compute the index 
       Result = getConstantValue(CE->getOperand(0));
       std::vector<Value*> Indexes(CE->op_begin()+1, CE->op_end());
       uint64_t Offset =
@@ -319,24 +325,35 @@
         Result.LongVal += Offset;
       return Result;
     }
-    case Instruction::Cast: {
-      // We only need to handle a few cases here.  Almost all casts will
-      // automatically fold, just the ones involving pointers won't.
-      //
+    case Instruction::Trunc:
+    case Instruction::ZExt:
+    case Instruction::SExt:
+    case Instruction::FPTrunc:
+    case Instruction::FPExt:
+    case Instruction::UIToFP:
+    case Instruction::SIToFP:
+    case Instruction::FPToUI:
+    case Instruction::FPToSI:
+      break;
+    case Instruction::PtrToInt: {
       Constant *Op = CE->getOperand(0);
       GenericValue GV = getConstantValue(Op);
-
-      // Handle cast of pointer to pointer...
+      return GV;
+    }
+    case Instruction::BitCast: {
+      // Bit casts are no-ops but we can only return the GV of the operand if
+      // they are the same basic type (pointer->pointer, packed->packed, etc.)
+      Constant *Op = CE->getOperand(0);
+      GenericValue GV = getConstantValue(Op);
       if (Op->getType()->getTypeID() == C->getType()->getTypeID())
         return GV;
-
-      // Handle a cast of pointer to any integral type...
-      if (isa<PointerType>(Op->getType()) && C->getType()->isIntegral())
-        return GV;
-
-      // Handle cast of integer to a pointer...
-      if (isa<PointerType>(C->getType()) && Op->getType()->isIntegral())
-        switch (Op->getType()->getTypeID()) {
+      break;
+    }
+    case Instruction::IntToPtr: {
+      // IntToPtr casts are just so special. Cast to intptr_t first.
+      Constant *Op = CE->getOperand(0);
+      GenericValue GV = getConstantValue(Op);
+      switch (Op->getType()->getTypeID()) {
         case Type::BoolTyID:    return PTOGV((void*)(uintptr_t)GV.BoolVal);
         case Type::SByteTyID:   return PTOGV((void*)( intptr_t)GV.SByteVal);
         case Type::UByteTyID:   return PTOGV((void*)(uintptr_t)GV.UByteVal);
@@ -347,10 +364,9 @@
         case Type::LongTyID:    return PTOGV((void*)( intptr_t)GV.LongVal);
         case Type::ULongTyID:   return PTOGV((void*)(uintptr_t)GV.ULongVal);
         default: assert(0 && "Unknown integral type!");
-        }
+      }
       break;
     }
-
     case Instruction::Add:
       switch (CE->getOperand(0)->getType()->getTypeID()) {
       default: assert(0 && "Bad add type!"); abort();
diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp
index 928a819..46d30fb 100644
--- a/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/lib/ExecutionEngine/Interpreter/Execution.cpp
@@ -81,8 +81,20 @@
 GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
                                                 ExecutionContext &SF) {
   switch (CE->getOpcode()) {
-  case Instruction::Cast:
-    return executeCastOperation(CE->getOperand(0), CE->getType(), SF);
+  case Instruction::Trunc:
+  case Instruction::ZExt:
+  case Instruction::SExt:
+  case Instruction::FPTrunc:
+  case Instruction::FPExt:
+  case Instruction::UIToFP:
+  case Instruction::SIToFP:
+  case Instruction::FPToUI:
+  case Instruction::FPToSI:
+  case Instruction::PtrToInt:
+  case Instruction::IntToPtr:
+  case Instruction::BitCast:
+    return executeCastOperation(Instruction::CastOps(CE->getOpcode()), 
+                                CE->getOperand(0), CE->getType(), SF);
   case Instruction::GetElementPtr:
     return executeGEPOperation(CE->getOperand(0), gep_type_begin(CE),
                                gep_type_end(CE), SF);
@@ -1030,12 +1042,15 @@
   SetValue(&I, Dest, SF);
 }
 
-#define IMPLEMENT_CAST(DTY, DCTY, STY) \
-   case Type::STY##TyID: Dest.DTY##Val = DCTY Src.STY##Val; break;
+#define IMPLEMENT_CAST_START \
+  switch (DstTy->getTypeID()) {
 
-#define IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY)    \
+#define IMPLEMENT_CAST(DTY, DCTY, STY) \
+     case Type::STY##TyID: Dest.DTY##Val = DCTY Src.STY##Val; break;
+
+#define IMPLEMENT_CAST_CASE(DESTTY, DESTCTY)    \
   case Type::DESTTY##TyID:                      \
-    switch (SrcTy->getTypeID()) {          \
+    switch (SrcTy->getTypeID()) {               \
       IMPLEMENT_CAST(DESTTY, DESTCTY, Bool);    \
       IMPLEMENT_CAST(DESTTY, DESTCTY, UByte);   \
       IMPLEMENT_CAST(DESTTY, DESTCTY, SByte);   \
@@ -1045,52 +1060,182 @@
       IMPLEMENT_CAST(DESTTY, DESTCTY, Int);     \
       IMPLEMENT_CAST(DESTTY, DESTCTY, ULong);   \
       IMPLEMENT_CAST(DESTTY, DESTCTY, Long);    \
-      IMPLEMENT_CAST(DESTTY, DESTCTY, Pointer);
-
-#define IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY) \
+      IMPLEMENT_CAST(DESTTY, DESTCTY, Pointer); \
       IMPLEMENT_CAST(DESTTY, DESTCTY, Float);   \
-      IMPLEMENT_CAST(DESTTY, DESTCTY, Double)
-
-#define IMPLEMENT_CAST_CASE_END()    \
-    default: std::cout << "Unhandled cast: " << *SrcTy << " to " << *Ty << "\n"; \
+      IMPLEMENT_CAST(DESTTY, DESTCTY, Double)   \
+    default:                                    \
+      std::cout << "Unhandled cast: "           \
+        << *SrcTy << " to " << *DstTy << "\n";  \
       abort();                                  \
     }                                           \
     break
 
-#define IMPLEMENT_CAST_CASE(DESTTY, DESTCTY) \
-   IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY);   \
-   IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY); \
-   IMPLEMENT_CAST_CASE_END()
+#define IMPLEMENT_CAST_END                      \
+  default: std::cout                            \
+      << "Unhandled dest type for cast instruction: "  \
+      << *DstTy << "\n";                        \
+    abort();                                    \
+  }
 
-GenericValue Interpreter::executeCastOperation(Value *SrcVal, const Type *Ty,
+GenericValue Interpreter::executeCastOperation(Instruction::CastOps opcode,
+                                               Value *SrcVal, const Type *DstTy,
                                                ExecutionContext &SF) {
   const Type *SrcTy = SrcVal->getType();
   GenericValue Dest, Src = getOperandValue(SrcVal, SF);
 
-  switch (Ty->getTypeID()) {
-    IMPLEMENT_CAST_CASE(UByte  , (unsigned char));
-    IMPLEMENT_CAST_CASE(SByte  , (  signed char));
-    IMPLEMENT_CAST_CASE(UShort , (unsigned short));
-    IMPLEMENT_CAST_CASE(Short  , (  signed short));
-    IMPLEMENT_CAST_CASE(UInt   , (unsigned int ));
-    IMPLEMENT_CAST_CASE(Int    , (  signed int ));
-    IMPLEMENT_CAST_CASE(ULong  , (uint64_t));
-    IMPLEMENT_CAST_CASE(Long   , ( int64_t));
-    IMPLEMENT_CAST_CASE(Pointer, (PointerTy));
-    IMPLEMENT_CAST_CASE(Float  , (float));
-    IMPLEMENT_CAST_CASE(Double , (double));
-    IMPLEMENT_CAST_CASE(Bool   , (bool));
-  default:
-    std::cout << "Unhandled dest type for cast instruction: " << *Ty << "\n";
-    abort();
+  if (opcode == Instruction::Trunc && DstTy->getTypeID() == Type::BoolTyID) {
+    // For truncations to bool, we must clear the high order bits of the source
+    switch (SrcTy->getTypeID()) {
+      case Type::BoolTyID:   Src.BoolVal   &= 1; break;
+      case Type::SByteTyID:  Src.SByteVal  &= 1; break;
+      case Type::UByteTyID:  Src.UByteVal  &= 1; break;
+      case Type::ShortTyID:  Src.ShortVal  &= 1; break;
+      case Type::UShortTyID: Src.UShortVal &= 1; break;
+      case Type::IntTyID:    Src.IntVal    &= 1; break;
+      case Type::UIntTyID:   Src.UIntVal   &= 1; break;
+      case Type::LongTyID:   Src.LongVal   &= 1; break;
+      case Type::ULongTyID:  Src.ULongVal  &= 1; break;
+      default:
+        assert(0 && "Can't trunc a non-integer!");
+        break;
+    }
+  } else if (opcode == Instruction::SExt && 
+             SrcTy->getTypeID() == Type::BoolTyID) {
+    // For sign extension from bool, we must extend the source bits.
+    SrcTy = Type::LongTy;
+    Src.LongVal = 0 - Src.BoolVal;
   }
 
+  switch (opcode) {
+    case Instruction::Trunc:     // src integer, dest integral (can't be long)
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(Bool   , (bool));
+      IMPLEMENT_CAST_CASE(UByte  , (unsigned char));
+      IMPLEMENT_CAST_CASE(SByte  , (  signed char));
+      IMPLEMENT_CAST_CASE(UShort , (unsigned short));
+      IMPLEMENT_CAST_CASE(Short  , (  signed short));
+      IMPLEMENT_CAST_CASE(UInt   , (unsigned int ));
+      IMPLEMENT_CAST_CASE(Int    , (  signed int ));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::ZExt:      // src integral (can't be long), dest integer
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(UByte  , (unsigned char));
+      IMPLEMENT_CAST_CASE(SByte  , (signed char)(unsigned char));
+      IMPLEMENT_CAST_CASE(UShort , (unsigned short));
+      IMPLEMENT_CAST_CASE(Short  , (signed short)(unsigned short));
+      IMPLEMENT_CAST_CASE(UInt   , (unsigned int ));
+      IMPLEMENT_CAST_CASE(Int    , (signed int)(unsigned int ));
+      IMPLEMENT_CAST_CASE(ULong  , (uint64_t));
+      IMPLEMENT_CAST_CASE(Long   , (int64_t)(uint64_t));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::SExt:      // src integral (can't be long), dest integer
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(UByte  , (unsigned char)(signed char));
+      IMPLEMENT_CAST_CASE(SByte  , (signed char));
+      IMPLEMENT_CAST_CASE(UShort , (unsigned short)(signed short));
+      IMPLEMENT_CAST_CASE(Short  , (signed short));
+      IMPLEMENT_CAST_CASE(UInt   , (unsigned int )(signed int));
+      IMPLEMENT_CAST_CASE(Int    , (signed int));
+      IMPLEMENT_CAST_CASE(ULong  , (uint64_t)(int64_t));
+      IMPLEMENT_CAST_CASE(Long   , (int64_t));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::FPTrunc:   // src double, dest float
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(Float  , (float));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::FPExt:     // src float, dest double
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(Double , (double));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::UIToFP:    // src integral, dest floating
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(Float  , (float)(uint64_t));
+      IMPLEMENT_CAST_CASE(Double , (double)(uint64_t));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::SIToFP:    // src integeral, dest floating
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(Float  , (float)(int64_t));
+      IMPLEMENT_CAST_CASE(Double , (double)(int64_t));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::FPToUI:    // src floating, dest integral
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(Bool   , (bool));
+      IMPLEMENT_CAST_CASE(UByte  , (unsigned char));
+      IMPLEMENT_CAST_CASE(SByte  , (signed char)(unsigned char));
+      IMPLEMENT_CAST_CASE(UShort , (unsigned short));
+      IMPLEMENT_CAST_CASE(Short  , (signed short)(unsigned short));
+      IMPLEMENT_CAST_CASE(UInt   , (unsigned int ));
+      IMPLEMENT_CAST_CASE(Int    , (signed int)(unsigned int ));
+      IMPLEMENT_CAST_CASE(ULong  , (uint64_t));
+      IMPLEMENT_CAST_CASE(Long   , (int64_t)(uint64_t));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::FPToSI:    // src floating, dest integral
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(Bool   , (bool));
+      IMPLEMENT_CAST_CASE(UByte  , (unsigned char)(signed char));
+      IMPLEMENT_CAST_CASE(SByte  , (signed char));
+      IMPLEMENT_CAST_CASE(UShort , (unsigned short)(signed short));
+      IMPLEMENT_CAST_CASE(Short  , (signed short));
+      IMPLEMENT_CAST_CASE(UInt   , (unsigned int )(signed int));
+      IMPLEMENT_CAST_CASE(Int    , (signed int));
+      IMPLEMENT_CAST_CASE(ULong  , (uint64_t)(int64_t));
+      IMPLEMENT_CAST_CASE(Long   , (int64_t));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::PtrToInt:  // src pointer,  dest integral
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(Bool   , (bool));
+      IMPLEMENT_CAST_CASE(UByte  , (unsigned char));
+      IMPLEMENT_CAST_CASE(SByte  , (signed char)(unsigned char));
+      IMPLEMENT_CAST_CASE(UShort , (unsigned short));
+      IMPLEMENT_CAST_CASE(Short  , (signed short)(unsigned short));
+      IMPLEMENT_CAST_CASE(UInt   , (unsigned int));
+      IMPLEMENT_CAST_CASE(Int    , (signed int)(unsigned int));
+      IMPLEMENT_CAST_CASE(ULong  , (uint64_t));
+      IMPLEMENT_CAST_CASE(Long   , (int64_t)(uint64_t));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::IntToPtr:  // src integral, dest pointer
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(Pointer, (PointerTy));
+      IMPLEMENT_CAST_END
+      break;
+    case Instruction::BitCast:   // src any, dest any (same size)
+      IMPLEMENT_CAST_START
+      IMPLEMENT_CAST_CASE(Bool   , (bool));
+      IMPLEMENT_CAST_CASE(UByte  , (unsigned char));
+      IMPLEMENT_CAST_CASE(SByte  , (  signed char));
+      IMPLEMENT_CAST_CASE(UShort , (unsigned short));
+      IMPLEMENT_CAST_CASE(Short  , (  signed short));
+      IMPLEMENT_CAST_CASE(UInt   , (unsigned int));
+      IMPLEMENT_CAST_CASE(Int    , (  signed int));
+      IMPLEMENT_CAST_CASE(ULong  , (uint64_t));
+      IMPLEMENT_CAST_CASE(Long   , ( int64_t));
+      IMPLEMENT_CAST_CASE(Pointer, (PointerTy));
+      IMPLEMENT_CAST_CASE(Float  , (float));
+      IMPLEMENT_CAST_CASE(Double , (double));
+      IMPLEMENT_CAST_END
+      break;
+    default:
+      std::cout 
+        << "Invalid cast opcode for cast instruction: " << opcode << "\n";
+      abort();
+  }
   return Dest;
 }
 
 void Interpreter::visitCastInst(CastInst &I) {
   ExecutionContext &SF = ECStack.back();
-  SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF);
+  SetValue(&I, executeCastOperation(I.getOpcode(), I.getOperand(0), 
+                                    I.getType(), SF), SF);
 }
 
 #define IMPLEMENT_VAARG(TY) \
diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h
index ced624f..67fb703 100644
--- a/lib/ExecutionEngine/Interpreter/Interpreter.h
+++ b/lib/ExecutionEngine/Interpreter/Interpreter.h
@@ -192,8 +192,8 @@
   void initializeExternalFunctions();
   GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF);
   GenericValue getOperandValue(Value *V, ExecutionContext &SF);
-  GenericValue executeCastOperation(Value *SrcVal, const Type *Ty,
-                                    ExecutionContext &SF);
+  GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal, 
+                                    const Type *Ty, ExecutionContext &SF);
   void popStackAndReturnValueToCaller(const Type *RetTy, GenericValue Result);
 };