diff options
Diffstat (limited to 'llvm/lib/ExecutionEngine')
| -rw-r--r-- | llvm/lib/ExecutionEngine/ExecutionEngine.cpp | 56 | ||||
| -rw-r--r-- | llvm/lib/ExecutionEngine/Interpreter/Execution.cpp | 213 | ||||
| -rw-r--r-- | llvm/lib/ExecutionEngine/Interpreter/Interpreter.h | 4 | 
3 files changed, 217 insertions, 56 deletions
| diff --git a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp index 9b50669777d..3c4d9d500d3 100644 --- a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp @@ -213,7 +213,7 @@ void ExecutionEngine::runStaticConstructorsDestructors(bool isDtors) {            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 @@ void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) {    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 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {          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); +      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); - -      // Handle cast of pointer to pointer...        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 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {          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/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp b/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp index 928a819cd00..46d30fb0e24 100644 --- a/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -81,8 +81,20 @@ static GenericValue executeSelectInst(GenericValue Src1, GenericValue Src2,  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 @@ void Interpreter::visitAShr(ShiftInst &I) {    SetValue(&I, Dest, SF);  } +#define IMPLEMENT_CAST_START \ +  switch (DstTy->getTypeID()) { +  #define IMPLEMENT_CAST(DTY, DCTY, STY) \ -   case Type::STY##TyID: Dest.DTY##Val = DCTY Src.STY##Val; break; +     case Type::STY##TyID: Dest.DTY##Val = DCTY Src.STY##Val; break; -#define IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY)    \ +#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 @@ void Interpreter::visitAShr(ShiftInst &I) {        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/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h b/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h index ced624f6018..67fb7034411 100644 --- a/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -192,8 +192,8 @@ private:  // Helper functions    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);  }; | 

