diff options
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r-- | lib/ExecutionEngine/ExecutionEngine.cpp | 303 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Execution.cpp | 1065 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp | 14 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Interpreter.h | 37 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/JIT.cpp | 48 |
5 files changed, 967 insertions, 500 deletions
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index e5f9ea1f40..26f51d0502 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -296,6 +296,28 @@ void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) { return state.getGlobalAddressMap(locked)[GV]; } +/// This macro is used to handle a variety of situations involing integer +/// values where the action should be done to one of the GenericValue members. +/// THEINTTY is a const Type * for the integer type. ACTION1 comes before +/// the GenericValue, ACTION2 comes after. +#define DO_FOR_INTEGER(THEINTTY, ACTION) \ + { \ + unsigned BitWidth = cast<IntegerType>(THEINTTY)->getBitWidth(); \ + if (BitWidth == 1) {\ + ACTION(Int1Val); \ + } else if (BitWidth <= 8) {\ + ACTION(Int8Val); \ + } else if (BitWidth <= 16) {\ + ACTION(Int16Val); \ + } else if (BitWidth <= 32) { \ + ACTION(Int32Val); \ + } else if (BitWidth <= 64) { \ + ACTION(Int64Val); \ + } else {\ + assert(0 && "Not implemented: integer types > 64 bits"); \ + } \ + } + /// This function converts a Constant* into a GenericValue. The interesting /// part is if C is a ConstantExpr. /// @brief Get a GenericValue for a Constnat* @@ -350,34 +372,21 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { // 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::Int1TyID: return PTOGV((void*)(uintptr_t)GV.Int1Val); - case Type::Int8TyID: return PTOGV((void*)(uintptr_t)GV.Int8Val); - case Type::Int16TyID: return PTOGV((void*)(uintptr_t)GV.Int16Val); - case Type::Int32TyID: return PTOGV((void*)(uintptr_t)GV.Int32Val); - case Type::Int64TyID: return PTOGV((void*)(uintptr_t)GV.Int64Val); - default: assert(0 && "Unknown integral type!"); - } +#define INT_TO_PTR_ACTION(FIELD) \ + return PTOGV((void*)(uintptr_t)GV.FIELD) + DO_FOR_INTEGER(Op->getType(), INT_TO_PTR_ACTION) +#undef INT_TO_PTR_ACTION break; } case Instruction::Add: switch (CE->getOperand(0)->getType()->getTypeID()) { default: assert(0 && "Bad add type!"); abort(); - case Type::Int64TyID: - Result.Int64Val = getConstantValue(CE->getOperand(0)).Int64Val + - getConstantValue(CE->getOperand(1)).Int64Val; - break; - case Type::Int32TyID: - Result.Int32Val = getConstantValue(CE->getOperand(0)).Int32Val + - getConstantValue(CE->getOperand(1)).Int32Val; - break; - case Type::Int16TyID: - Result.Int16Val = getConstantValue(CE->getOperand(0)).Int16Val + - getConstantValue(CE->getOperand(1)).Int16Val; - break; - case Type::Int8TyID: - Result.Int8Val = getConstantValue(CE->getOperand(0)).Int8Val + - getConstantValue(CE->getOperand(1)).Int8Val; + case Type::IntegerTyID: +#define ADD_ACTION(FIELD) \ + Result.FIELD = getConstantValue(CE->getOperand(0)).FIELD + \ + getConstantValue(CE->getOperand(1)).FIELD; + DO_FOR_INTEGER(CE->getOperand(0)->getType(),ADD_ACTION); +#undef ADD_ACTION break; case Type::FloatTyID: Result.FloatVal = getConstantValue(CE->getOperand(0)).FloatVal + @@ -399,14 +408,26 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { switch (C->getType()->getTypeID()) { #define GET_CONST_VAL(TY, CTY, CLASS, GETMETH) \ case Type::TY##TyID: Result.TY##Val = (CTY)cast<CLASS>(C)->GETMETH(); break - GET_CONST_VAL(Int1 , bool , ConstantInt, getZExtValue); - GET_CONST_VAL(Int8 , unsigned char , ConstantInt, getZExtValue); - GET_CONST_VAL(Int16 , unsigned short, ConstantInt, getZExtValue); - GET_CONST_VAL(Int32 , unsigned int , ConstantInt, getZExtValue); - GET_CONST_VAL(Int64 , uint64_t , ConstantInt, getZExtValue); GET_CONST_VAL(Float , float , ConstantFP, getValue); GET_CONST_VAL(Double, double , ConstantFP, getValue); #undef GET_CONST_VAL + case Type::IntegerTyID: { + unsigned BitWidth = cast<IntegerType>(C->getType())->getBitWidth(); + if (BitWidth == 1) + Result.Int1Val = (bool)cast<ConstantInt>(C)->getZExtValue(); + else if (BitWidth <= 8) + Result.Int8Val = (uint8_t )cast<ConstantInt>(C)->getZExtValue(); + else if (BitWidth <= 16) + Result.Int16Val = (uint16_t )cast<ConstantInt>(C)->getZExtValue(); + else if (BitWidth <= 32) + Result.Int32Val = (uint32_t )cast<ConstantInt>(C)->getZExtValue(); + else if (BitWidth <= 64) + Result.Int64Val = (uint64_t )cast<ConstantInt>(C)->getZExtValue(); + else + assert("Integers with > 64-bits not implemented"); + break; + } + case Type::PointerTyID: if (isa<ConstantPointerNull>(C)) Result.PointerVal = 0; @@ -433,22 +454,43 @@ void ExecutionEngine::StoreValueToMemory(GenericValue Val, GenericValue *Ptr, const Type *Ty) { if (getTargetData()->isLittleEndian()) { switch (Ty->getTypeID()) { - case Type::Int1TyID: - case Type::Int8TyID: Ptr->Untyped[0] = Val.Int8Val; break; - case Type::Int16TyID: Ptr->Untyped[0] = Val.Int16Val & 255; - Ptr->Untyped[1] = (Val.Int16Val >> 8) & 255; - break; - Store4BytesLittleEndian: + case Type::IntegerTyID: { + unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth(); + if (BitWidth <= 8) + Ptr->Untyped[0] = Val.Int8Val; + else if (BitWidth <= 16) { + Ptr->Untyped[0] = Val.Int16Val & 255; + Ptr->Untyped[1] = (Val.Int16Val >> 8) & 255; + } else if (BitWidth <= 32) { + Ptr->Untyped[0] = Val.Int32Val & 255; + Ptr->Untyped[1] = (Val.Int32Val >> 8) & 255; + Ptr->Untyped[2] = (Val.Int32Val >> 16) & 255; + Ptr->Untyped[3] = (Val.Int32Val >> 24) & 255; + } else if (BitWidth <= 64) { + Ptr->Untyped[0] = (unsigned char)(Val.Int64Val ); + Ptr->Untyped[1] = (unsigned char)(Val.Int64Val >> 8); + Ptr->Untyped[2] = (unsigned char)(Val.Int64Val >> 16); + Ptr->Untyped[3] = (unsigned char)(Val.Int64Val >> 24); + Ptr->Untyped[4] = (unsigned char)(Val.Int64Val >> 32); + Ptr->Untyped[5] = (unsigned char)(Val.Int64Val >> 40); + Ptr->Untyped[6] = (unsigned char)(Val.Int64Val >> 48); + Ptr->Untyped[7] = (unsigned char)(Val.Int64Val >> 56); + } else + assert(0 && "Integer types > 64 bits not supported"); + break; + } +Store4BytesLittleEndian: case Type::FloatTyID: - case Type::Int32TyID: Ptr->Untyped[0] = Val.Int32Val & 255; - Ptr->Untyped[1] = (Val.Int32Val >> 8) & 255; - Ptr->Untyped[2] = (Val.Int32Val >> 16) & 255; - Ptr->Untyped[3] = (Val.Int32Val >> 24) & 255; - break; - case Type::PointerTyID: if (getTargetData()->getPointerSize() == 4) - goto Store4BytesLittleEndian; + Ptr->Untyped[0] = Val.Int32Val & 255; + Ptr->Untyped[1] = (Val.Int32Val >> 8) & 255; + Ptr->Untyped[2] = (Val.Int32Val >> 16) & 255; + Ptr->Untyped[3] = (Val.Int32Val >> 24) & 255; + break; + case Type::PointerTyID: + if (getTargetData()->getPointerSize() == 4) + goto Store4BytesLittleEndian; + /* FALL THROUGH */ case Type::DoubleTyID: - case Type::Int64TyID: Ptr->Untyped[0] = (unsigned char)(Val.Int64Val ); Ptr->Untyped[1] = (unsigned char)(Val.Int64Val >> 8); Ptr->Untyped[2] = (unsigned char)(Val.Int64Val >> 16); @@ -463,22 +505,43 @@ void ExecutionEngine::StoreValueToMemory(GenericValue Val, GenericValue *Ptr, } } else { switch (Ty->getTypeID()) { - case Type::Int1TyID: - case Type::Int8TyID: Ptr->Untyped[0] = Val.Int8Val; break; - case Type::Int16TyID: Ptr->Untyped[1] = Val.Int16Val & 255; - Ptr->Untyped[0] = (Val.Int16Val >> 8) & 255; - break; + case Type::IntegerTyID: { + unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth(); + if (BitWidth <= 8) + Ptr->Untyped[0] = Val.Int8Val; + else if (BitWidth <= 16) { + Ptr->Untyped[1] = Val.Int16Val & 255; + Ptr->Untyped[0] = (Val.Int16Val >> 8) & 255; + } else if (BitWidth <= 32) { + Ptr->Untyped[3] = Val.Int32Val & 255; + Ptr->Untyped[2] = (Val.Int32Val >> 8) & 255; + Ptr->Untyped[1] = (Val.Int32Val >> 16) & 255; + Ptr->Untyped[0] = (Val.Int32Val >> 24) & 255; + } else if (BitWidth <= 64) { + Ptr->Untyped[7] = (unsigned char)(Val.Int64Val ); + Ptr->Untyped[6] = (unsigned char)(Val.Int64Val >> 8); + Ptr->Untyped[5] = (unsigned char)(Val.Int64Val >> 16); + Ptr->Untyped[4] = (unsigned char)(Val.Int64Val >> 24); + Ptr->Untyped[3] = (unsigned char)(Val.Int64Val >> 32); + Ptr->Untyped[2] = (unsigned char)(Val.Int64Val >> 40); + Ptr->Untyped[1] = (unsigned char)(Val.Int64Val >> 48); + Ptr->Untyped[0] = (unsigned char)(Val.Int64Val >> 56); + } else + assert(0 && "Integer types > 64 bits not supported"); + break; + } Store4BytesBigEndian: case Type::FloatTyID: - case Type::Int32TyID: Ptr->Untyped[3] = Val.Int32Val & 255; - Ptr->Untyped[2] = (Val.Int32Val >> 8) & 255; - Ptr->Untyped[1] = (Val.Int32Val >> 16) & 255; - Ptr->Untyped[0] = (Val.Int32Val >> 24) & 255; - break; - case Type::PointerTyID: if (getTargetData()->getPointerSize() == 4) - goto Store4BytesBigEndian; + Ptr->Untyped[3] = Val.Int32Val & 255; + Ptr->Untyped[2] = (Val.Int32Val >> 8) & 255; + Ptr->Untyped[1] = (Val.Int32Val >> 16) & 255; + Ptr->Untyped[0] = (Val.Int32Val >> 24) & 255; + break; + case Type::PointerTyID: + if (getTargetData()->getPointerSize() == 4) + goto Store4BytesBigEndian; + /* FALL THROUGH */ case Type::DoubleTyID: - case Type::Int64TyID: Ptr->Untyped[7] = (unsigned char)(Val.Int64Val ); Ptr->Untyped[6] = (unsigned char)(Val.Int64Val >> 8); Ptr->Untyped[5] = (unsigned char)(Val.Int64Val >> 16); @@ -501,60 +564,104 @@ GenericValue ExecutionEngine::LoadValueFromMemory(GenericValue *Ptr, GenericValue Result; if (getTargetData()->isLittleEndian()) { switch (Ty->getTypeID()) { - case Type::Int1TyID: - case Type::Int8TyID: Result.Int8Val = Ptr->Untyped[0]; break; - case Type::Int16TyID: Result.Int16Val = (unsigned)Ptr->Untyped[0] | - ((unsigned)Ptr->Untyped[1] << 8); - break; + case Type::IntegerTyID: { + unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth(); + if (BitWidth <= 8) + Result.Int8Val = Ptr->Untyped[0]; + else if (BitWidth <= 16) { + Result.Int16Val = (unsigned)Ptr->Untyped[0] | + ((unsigned)Ptr->Untyped[1] << 8); + } else if (BitWidth <= 32) { + Result.Int32Val = (unsigned)Ptr->Untyped[0] | + ((unsigned)Ptr->Untyped[1] << 8) | + ((unsigned)Ptr->Untyped[2] << 16) | + ((unsigned)Ptr->Untyped[3] << 24); + } else if (BitWidth <= 64) { + Result.Int64Val = (uint64_t)Ptr->Untyped[0] | + ((uint64_t)Ptr->Untyped[1] << 8) | + ((uint64_t)Ptr->Untyped[2] << 16) | + ((uint64_t)Ptr->Untyped[3] << 24) | + ((uint64_t)Ptr->Untyped[4] << 32) | + ((uint64_t)Ptr->Untyped[5] << 40) | + ((uint64_t)Ptr->Untyped[6] << 48) | + ((uint64_t)Ptr->Untyped[7] << 56); + } else + assert(0 && "Integer types > 64 bits not supported"); + break; + } Load4BytesLittleEndian: case Type::FloatTyID: - case Type::Int32TyID: Result.Int32Val = (unsigned)Ptr->Untyped[0] | - ((unsigned)Ptr->Untyped[1] << 8) | - ((unsigned)Ptr->Untyped[2] << 16) | - ((unsigned)Ptr->Untyped[3] << 24); - break; - case Type::PointerTyID: if (getTargetData()->getPointerSize() == 4) - goto Load4BytesLittleEndian; + Result.Int32Val = (unsigned)Ptr->Untyped[0] | + ((unsigned)Ptr->Untyped[1] << 8) | + ((unsigned)Ptr->Untyped[2] << 16) | + ((unsigned)Ptr->Untyped[3] << 24); + break; + case Type::PointerTyID: + if (getTargetData()->getPointerSize() == 4) + goto Load4BytesLittleEndian; + /* FALL THROUGH */ case Type::DoubleTyID: - case Type::Int64TyID: Result.Int64Val = (uint64_t)Ptr->Untyped[0] | - ((uint64_t)Ptr->Untyped[1] << 8) | - ((uint64_t)Ptr->Untyped[2] << 16) | - ((uint64_t)Ptr->Untyped[3] << 24) | - ((uint64_t)Ptr->Untyped[4] << 32) | - ((uint64_t)Ptr->Untyped[5] << 40) | - ((uint64_t)Ptr->Untyped[6] << 48) | - ((uint64_t)Ptr->Untyped[7] << 56); - break; + Result.Int64Val = (uint64_t)Ptr->Untyped[0] | + ((uint64_t)Ptr->Untyped[1] << 8) | + ((uint64_t)Ptr->Untyped[2] << 16) | + ((uint64_t)Ptr->Untyped[3] << 24) | + ((uint64_t)Ptr->Untyped[4] << 32) | + ((uint64_t)Ptr->Untyped[5] << 40) | + ((uint64_t)Ptr->Untyped[6] << 48) | + ((uint64_t)Ptr->Untyped[7] << 56); + break; default: cerr << "Cannot load value of type " << *Ty << "!\n"; abort(); } } else { switch (Ty->getTypeID()) { - case Type::Int1TyID: - case Type::Int8TyID: Result.Int8Val = Ptr->Untyped[0]; break; - case Type::Int16TyID: Result.Int16Val = (unsigned)Ptr->Untyped[1] | - ((unsigned)Ptr->Untyped[0] << 8); - break; + case Type::IntegerTyID: { + unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth(); + if (BitWidth <= 8) + Result.Int8Val = Ptr->Untyped[0]; + else if (BitWidth <= 16) { + Result.Int16Val = (unsigned)Ptr->Untyped[1] | + ((unsigned)Ptr->Untyped[0] << 8); + } else if (BitWidth <= 32) { + Result.Int32Val = (unsigned)Ptr->Untyped[3] | + ((unsigned)Ptr->Untyped[2] << 8) | + ((unsigned)Ptr->Untyped[1] << 16) | + ((unsigned)Ptr->Untyped[0] << 24); + } else if (BitWidth <= 64) { + Result.Int64Val = (uint64_t)Ptr->Untyped[7] | + ((uint64_t)Ptr->Untyped[6] << 8) | + ((uint64_t)Ptr->Untyped[5] << 16) | + ((uint64_t)Ptr->Untyped[4] << 24) | + ((uint64_t)Ptr->Untyped[3] << 32) | + ((uint64_t)Ptr->Untyped[2] << 40) | + ((uint64_t)Ptr->Untyped[1] << 48) | + ((uint64_t)Ptr->Untyped[0] << 56); + } else + assert(0 && "Integer types > 64 bits not supported"); + break; + } Load4BytesBigEndian: case Type::FloatTyID: - case Type::Int32TyID: Result.Int32Val =(unsigned)Ptr->Untyped[3] | - ((unsigned)Ptr->Untyped[2] << 8) | - ((unsigned)Ptr->Untyped[1] << 16) | - ((unsigned)Ptr->Untyped[0] << 24); + Result.Int32Val = (unsigned)Ptr->Untyped[3] | + ((unsigned)Ptr->Untyped[2] << 8) | + ((unsigned)Ptr->Untyped[1] << 16) | + ((unsigned)Ptr->Untyped[0] << 24); break; - case Type::PointerTyID: if (getTargetData()->getPointerSize() == 4) - goto Load4BytesBigEndian; + case Type::PointerTyID: + if (getTargetData()->getPointerSize() == 4) + goto Load4BytesBigEndian; + /* FALL THROUGH */ case Type::DoubleTyID: - case Type::Int64TyID: Result.Int64Val = (uint64_t)Ptr->Untyped[7] | - ((uint64_t)Ptr->Untyped[6] << 8) | - ((uint64_t)Ptr->Untyped[5] << 16) | - ((uint64_t)Ptr->Untyped[4] << 24) | - ((uint64_t)Ptr->Untyped[3] << 32) | - ((uint64_t)Ptr->Untyped[2] << 40) | - ((uint64_t)Ptr->Untyped[1] << 48) | - ((uint64_t)Ptr->Untyped[0] << 56); - break; + Result.Int64Val = (uint64_t)Ptr->Untyped[7] | + ((uint64_t)Ptr->Untyped[6] << 8) | + ((uint64_t)Ptr->Untyped[5] << 16) | + ((uint64_t)Ptr->Untyped[4] << 24) | + ((uint64_t)Ptr->Untyped[3] << 32) | + ((uint64_t)Ptr->Untyped[2] << 40) | + ((uint64_t)Ptr->Untyped[1] << 48) | + ((uint64_t)Ptr->Untyped[0] << 56); + break; default: cerr << "Cannot load value of type " << *Ty << "!\n"; abort(); @@ -708,8 +815,8 @@ void ExecutionEngine::emitGlobals() { } } - // Now that all of the globals are set up in memory, loop through them all and - // initialize their contents. + // Now that all of the globals are set up in memory, loop through them all + // and initialize their contents. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { if (!I->isExternal()) { diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 0a0fbce134..681fb67b92 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -20,6 +20,7 @@ #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" #include <cmath> using namespace llvm; @@ -69,20 +70,30 @@ static GenericValue executeSelectInst(GenericValue Src1, GenericValue Src2, GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE, ExecutionContext &SF) { switch (CE->getOpcode()) { - case Instruction::Trunc: + case Instruction::Trunc: + return executeTruncInst(CE->getOperand(0), CE->getType(), SF); case Instruction::ZExt: + return executeZExtInst(CE->getOperand(0), CE->getType(), SF); case Instruction::SExt: + return executeSExtInst(CE->getOperand(0), CE->getType(), SF); case Instruction::FPTrunc: + return executeFPTruncInst(CE->getOperand(0), CE->getType(), SF); case Instruction::FPExt: + return executeFPExtInst(CE->getOperand(0), CE->getType(), SF); case Instruction::UIToFP: + return executeUIToFPInst(CE->getOperand(0), CE->getType(), SF); case Instruction::SIToFP: + return executeSIToFPInst(CE->getOperand(0), CE->getType(), SF); case Instruction::FPToUI: + return executeFPToUIInst(CE->getOperand(0), CE->getType(), SF); case Instruction::FPToSI: + return executeFPToSIInst(CE->getOperand(0), CE->getType(), SF); case Instruction::PtrToInt: + return executePtrToIntInst(CE->getOperand(0), CE->getType(), SF); case Instruction::IntToPtr: + return executeIntToPtrInst(CE->getOperand(0), CE->getType(), SF); case Instruction::BitCast: - return executeCastOperation(Instruction::CastOps(CE->getOpcode()), - CE->getOperand(0), CE->getType(), SF); + return executeBitCastInst(CE->getOperand(0), CE->getType(), SF); case Instruction::GetElementPtr: return executeGEPOperation(CE->getOperand(0), gep_type_begin(CE), gep_type_end(CE), SF); @@ -190,14 +201,69 @@ void Interpreter::initializeExecutionEngine() { #define IMPLEMENT_BINARY_OPERATOR(OP, TY) \ case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.TY##Val; break +#define IMPLEMENT_INTEGER_BINOP(OP, TY) \ + case Type::IntegerTyID: { \ + unsigned BitWidth = cast<IntegerType>(TY)->getBitWidth(); \ + if (BitWidth == 1) \ + Dest.Int1Val = Src1.Int1Val OP Src2.Int1Val; \ + else if (BitWidth <= 8) \ + Dest.Int8Val = Src1.Int8Val OP Src2.Int8Val; \ + else if (BitWidth <= 16) \ + Dest.Int16Val = Src1.Int16Val OP Src2.Int16Val; \ + else if (BitWidth <= 32) \ + Dest.Int32Val = Src1.Int32Val OP Src2.Int32Val; \ + else if (BitWidth <= 64) \ + Dest.Int64Val = Src1.Int64Val OP Src2.Int64Val; \ + else \ + cerr << "Integer types > 64 bits not supported: " << *Ty << "\n"; \ + break; \ + } + +#define IMPLEMENT_SIGNED_BINOP(OP, TY) \ + if (const IntegerType *ITy = dyn_cast<IntegerType>(TY)) { \ + unsigned BitWidth = ITy->getBitWidth(); \ + if (BitWidth <= 8) \ + Dest.Int8Val = ((int8_t)Src1.Int8Val) OP ((int8_t)Src2.Int8Val); \ + else if (BitWidth <= 16) \ + Dest.Int16Val = ((int16_t)Src1.Int16Val) OP ((int16_t)Src2.Int16Val); \ + else if (BitWidth <= 32) \ + Dest.Int32Val = ((int32_t)Src1.Int32Val) OP ((int32_t)Src2.Int32Val); \ + else if (BitWidth <= 64) \ + Dest.Int64Val = ((int64_t)Src1.Int64Val) OP ((int64_t)Src2.Int64Val); \ + else { \ + cerr << "Integer types > 64 bits not supported: " << *Ty << "\n"; \ + abort(); \ + } \ + } else { \ + cerr << "Unhandled type for " #OP " operator: " << *Ty << "\n"; \ + abort(); \ + } + +#define IMPLEMENT_UNSIGNED_BINOP(OP, TY) \ + if (const IntegerType *ITy = dyn_cast<IntegerType>(TY)) { \ + unsigned BitWidth = ITy->getBitWidth(); \ + if (BitWidth <= 8) \ + Dest.Int8Val = ((uint8_t)Src1.Int8Val) OP ((uint8_t)Src2.Int8Val); \ + else if (BitWidth <= 16) \ + Dest.Int16Val = ((uint16_t)Src1.Int16Val) OP ((uint16_t)Src2.Int16Val); \ + else if (BitWidth <= 32) \ + Dest.Int32Val = ((uint32_t)Src1.Int32Val) OP ((uint32_t)Src2.Int32Val); \ + else if (BitWidth <= 64) \ + Dest.Int64Val = ((uint64_t)Src1.Int64Val) OP ((uint64_t)Src2.Int64Val); \ + else { \ + cerr << "Integer types > 64 bits not supported: " << *Ty << "\n"; \ + abort(); \ + } \ + } else { \ + cerr << "Unhandled type for " #OP " operator: " << *Ty << "\n"; \ + abort(); \ + } + static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { - IMPLEMENT_BINARY_OPERATOR(+, Int8); - IMPLEMENT_BINARY_OPERATOR(+, Int16); - IMPLEMENT_BINARY_OPERATOR(+, Int32); - IMPLEMENT_BINARY_OPERATOR(+, Int64); + IMPLEMENT_INTEGER_BINOP(+, Ty); IMPLEMENT_BINARY_OPERATOR(+, Float); IMPLEMENT_BINARY_OPERATOR(+, Double); default: @@ -211,10 +277,7 @@ static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { - IMPLEMENT_BINARY_OPERATOR(-, Int8); - IMPLEMENT_BINARY_OPERATOR(-, Int16); - IMPLEMENT_BINARY_OPERATOR(-, Int32); - IMPLEMENT_BINARY_OPERATOR(-, Int64); + IMPLEMENT_INTEGER_BINOP(-, Ty); IMPLEMENT_BINARY_OPERATOR(-, Float); IMPLEMENT_BINARY_OPERATOR(-, Double); default: @@ -228,10 +291,7 @@ static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { - IMPLEMENT_BINARY_OPERATOR(*, Int8); - IMPLEMENT_BINARY_OPERATOR(*, Int16); - IMPLEMENT_BINARY_OPERATOR(*, Int32); - IMPLEMENT_BINARY_OPERATOR(*, Int64); + IMPLEMENT_INTEGER_BINOP(*, Ty); IMPLEMENT_BINARY_OPERATOR(*, Float); IMPLEMENT_BINARY_OPERATOR(*, Double); default: @@ -241,37 +301,17 @@ static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2, return Dest; } -#define IMPLEMENT_SIGNLESS_BINOP(OP, TY, CAST) \ - case Type::TY##TyID: Dest.TY##Val = \ - ((CAST)Src1.TY##Val) OP ((CAST)Src2.TY##Val); break - static GenericValue executeUDivInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getTypeID()) { - IMPLEMENT_SIGNLESS_BINOP(/, Int8, uint8_t); - IMPLEMENT_SIGNLESS_BINOP(/, Int16, uint16_t); - IMPLEMENT_SIGNLESS_BINOP(/, Int32, uint32_t); - IMPLEMENT_SIGNLESS_BINOP(/, Int64, uint64_t); - default: - cerr << "Unhandled type for UDiv instruction: " << *Ty << "\n"; - abort(); - } + IMPLEMENT_UNSIGNED_BINOP(/,Ty) return Dest; } static GenericValue executeSDivInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getTypeID()) { - IMPLEMENT_SIGNLESS_BINOP(/, Int8, int8_t); - IMPLEMENT_SIGNLESS_BINOP(/, Int16, int16_t); - IMPLEMENT_SIGNLESS_BINOP(/, Int32, int32_t); - IMPLEMENT_SIGNLESS_BINOP(/, Int64, int64_t); - default: - cerr << "Unhandled type for SDiv instruction: " << *Ty << "\n"; - abort(); - } + IMPLEMENT_SIGNED_BINOP(/,Ty) return Dest; } @@ -282,7 +322,7 @@ static GenericValue executeFDivInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_BINARY_OPERATOR(/, Float); IMPLEMENT_BINARY_OPERATOR(/, Double); default: - cerr << "Unhandled type for Div instruction: " << *Ty << "\n"; + cerr << "Unhandled type for FDiv instruction: " << *Ty << "\n"; abort(); } return Dest; @@ -291,30 +331,14 @@ static GenericValue executeFDivInst(GenericValue Src1, GenericValue Src2, static GenericValue executeURemInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getTypeID()) { - IMPLEMENT_SIGNLESS_BINOP(%, Int8, uint8_t); - IMPLEMENT_SIGNLESS_BINOP(%, Int16, uint16_t); - IMPLEMENT_SIGNLESS_BINOP(%, Int32, uint32_t); - IMPLEMENT_SIGNLESS_BINOP(%, Int64, uint64_t ); - default: - cerr << "Unhandled type for URem instruction: " << *Ty << "\n"; - abort(); - } + IMPLEMENT_UNSIGNED_BINOP(%, Ty) return Dest; } static GenericValue executeSRemInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getTypeID()) { - IMPLEMENT_SIGNLESS_BINOP(%, Int8, int8_t); - IMPLEMENT_SIGNLESS_BINOP(%, Int16, int16_t); - IMPLEMENT_SIGNLESS_BINOP(%, Int32, int32_t); - IMPLEMENT_SIGNLESS_BINOP(%, Int64, int64_t); - default: - cerr << "Unhandled type for Rem instruction: " << *Ty << "\n"; - abort(); - } + IMPLEMENT_SIGNED_BINOP(%, Ty) return Dest; } @@ -338,60 +362,69 @@ static GenericValue executeFRemInst(GenericValue Src1, GenericValue Src2, static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getTypeID()) { - IMPLEMENT_BINARY_OPERATOR(&, Int1); - IMPLEMENT_BINARY_OPERATOR(&, Int8); - IMPLEMENT_BINARY_OPERATOR(&, Int16); - IMPLEMENT_BINARY_OPERATOR(&, Int32); - IMPLEMENT_BINARY_OPERATOR(&, Int64); - default: - cerr << "Unhandled type for And instruction: " << *Ty << "\n"; - abort(); - } + IMPLEMENT_UNSIGNED_BINOP(&, Ty) return Dest; } static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getTypeID()) { - IMPLEMENT_BINARY_OPERATOR(|, Int1); - IMPLEMENT_BINARY_OPERATOR(|, Int8); - IMPLEMENT_BINARY_OPERATOR(|, Int16); - IMPLEMENT_BINARY_OPERATOR(|, Int32); - IMPLEMENT_BINARY_OPERATOR(|, Int64); - default: - cerr << "Unhandled type for Or instruction: " << *Ty << "\n"; - abort(); - } + IMPLEMENT_UNSIGNED_BINOP(|, Ty) return Dest; } static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getTypeID()) { - IMPLEMENT_BINARY_OPERATOR(^, Int1); - IMPLEMENT_BINARY_OPERATOR(^, Int8); - IMPLEMENT_BINARY_OPERATOR(^, Int16); - IMPLEMENT_BINARY_OPERATOR(^, Int32); - IMPLEMENT_BINARY_OPERATOR(^, Int64); - default: - cerr << "Unhandled type for Xor instruction: " << *Ty << "\n"; - abort(); - } + IMPLEMENT_UNSIGNED_BINOP(^, Ty) return Dest; } -#define IMPLEMENT_ICMP(OP, TY, CAST) \ - case Type::TY##TyID: Dest.Int1Val = \ - ((CAST)Src1.TY##Val) OP ((CAST)Src2.TY##Val); break +#define IMPLEMENT_SIGNED_ICMP(OP, TY) \ + case Type::IntegerTyID: { \ + unsigned BitWidth = cast<IntegerType>(TY)->getBitWidth(); \ + if (BitWidth == 1) \ + Dest.Int1Val = ((int8_t)Src1.Int1Val) OP ((int8_t)Src2.Int1Val); \ + else if (BitWidth <= 8) \ + Dest.Int1Val = ((int8_t)Src1.Int8Val) OP ((int8_t)Src2.Int8Val); \ + else if (BitWidth <= 16) \ + Dest.Int1Val = ((int16_t)Src1.Int16Val) OP ((int16_t)Src2.Int16Val); \ + else if (BitWidth <= 32) \ + Dest.Int1Val = ((int32_t)Src1.Int32Val) OP ((int32_t)Src2.Int32Val); \ + else if (BitWidth <= 64) \ + Dest.Int1Val = ((int64_t)Src1.Int64Val) OP ((int64_t)Src2.Int64Val); \ + else { \ + cerr << "Integer types > 64 bits not supported: " << *Ty << "\n"; \ + abort(); \ + } \ + break; \ + } + +#define IMPLEMENT_UNSIGNED_ICMP(OP, TY) \ + case Type::IntegerTyID: { \ + unsigned BitWidth = cast<IntegerType>(TY)->getBitWidth(); \ + if (BitWidth == 1) \ + Dest.Int1Val = ((uint8_t)Src1.Int1Val) OP ((uint8_t)Src2.Int1Val); \ + else if (BitWidth <= 8) \ + Dest.Int1Val = ((uint8_t)Src1.Int8Val) OP ((uint8_t)Src2.Int8Val); \ + else if (BitWidth <= 16) \ + Dest.Int1Val = ((uint16_t)Src1.Int16Val) OP ((uint16_t)Src2.Int16Val); \ + else if (BitWidth <= 32) \ + Dest.Int1Val = ((uint32_t)Src1.Int32Val) OP ((uint32_t)Src2.Int32Val); \ + else if (BitWidth <= 64) \ + Dest.Int1Val = ((uint64_t)Src1.Int64Val) OP ((uint64_t)Src2.Int64Val); \ + else { \ + cerr << "Integer types > 64 bits not supported: " << *Ty << "\n"; \ + abort(); \ + } \ + break; \ + } // Handle pointers specially because they must be compared with only as much // width as the host has. We _do not_ want to be comparing 64 bit values when // running on a 32-bit target, otherwise the upper 32 bits might mess up // comparisons if they contain garbage. -#define IMPLEMENT_POINTERCMP(OP) \ +#define IMPLEMENT_POINTER_ICMP(OP) \ case Type::PointerTyID: \ Dest.Int1Val = (void*)(intptr_t)Src1.PointerVal OP \ (void*)(intptr_t)Src2.PointerVal; break @@ -400,11 +433,8 @@ static GenericValue executeICMP_EQ(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { - IMPLEMENT_ICMP(==, Int8, uint8_t); - IMPLEMENT_ICMP(==, Int16, uint16_t); - IMPLEMENT_ICMP(==, Int32, uint32_t); - IMPLEMENT_ICMP(==, Int64, uint64_t); - IMPLEMENT_POINTERCMP(==); + IMPLEMENT_UNSIGNED_ICMP(==, Ty); + IMPLEMENT_POINTER_ICMP(==); default: cerr << "Unhandled type for ICMP_EQ predicate: " << *Ty << "\n"; abort(); @@ -416,11 +446,8 @@ static GenericValue executeICMP_NE(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { - IMPLEMENT_ICMP(!=, Int8, uint8_t); - IMPLEMENT_ICMP(!=, Int16, uint16_t); - IMPLEMENT_ICMP(!=, Int32, uint32_t); - IMPLEMENT_ICMP(!=, Int64, uint64_t); - IMPLEMENT_POINTERCMP(!=); + IMPLEMENT_UNSIGNED_ICMP(!=, Ty); + IMPLEMENT_POINTER_ICMP(!=); default: cerr << "Unhandled type for ICMP_NE predicate: " << *Ty << "\n"; abort(); @@ -432,11 +459,8 @@ static GenericValue executeICMP_ULT(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { - IMPLEMENT_ICMP(<, Int8, uint8_t); - IMPLEMENT_ICMP(<, Int16, uint16_t); - IMPLEMENT_ICMP(<, Int32, uint32_t); - IMPLEMENT_ICMP(<, Int64, uint64_t); - IMPLEMENT_POINTERCMP(<); + IMPLEMENT_UNSIGNED_ICMP(<, Ty); + IMPLEMENT_POINTER_ICMP(<); default: cerr << "Unhandled type for ICMP_ULT predicate: " << *Ty << "\n"; abort(); @@ -448,11 +472,8 @@ static GenericValue executeICMP_SLT(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { - IMPLEMENT_ICMP(<, Int8, int8_t); - IMPLEMENT_ICMP(<, Int16, int16_t); - IMPLEMENT_ICMP(<, Int32, int32_t); - IMPLEMENT_ICMP(<, Int64, int64_t); - IMPLEMENT_POINTERCMP(<); + IMPLEMENT_SIGNED_ICMP(<, Ty); + IMPLEMENT_POINTER_ICMP(<); default: cerr << "Unhandled type for ICMP_SLT predicate: " << *Ty << "\n"; abort(); @@ -464,11 +485,8 @@ static GenericValue executeICMP_UGT(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { - IMPLEMENT_ICMP(>, Int8, uint8_t); - IMPLEMENT_ICMP(>, Int16, uint16_t); - IMPLEMENT_ICMP(>, Int32, uint32_t); - IMPLEMENT_ICMP(>, Int64, uint64_t); - IMPLEMENT_POINTERCMP(>); + IMPLEMENT_UNSIGNED_ICMP(>, Ty); + IMPLEMENT_POINTER_ICMP(>); default: cerr << "Unhandled type for ICMP_UGT predicate: " << *Ty << "\n"; abort(); @@ -480,11 +498,8 @@ static GenericValue executeICMP_SGT(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { - IMPLEMENT_ICMP(>, Int8, int8_t); - IMPLEMENT_ICMP(>, Int16, int16_t); - IMPLEMENT_ICMP(>, Int32, int32_t); - IMPLEMENT_ICMP(>, Int64, int64_t); - IMPLEMENT_POINTERCMP(>); + IMPLEMENT_SIGNED_ICMP(>, Ty); + IMPLEMENT_POINTER_ICMP(>); default: cerr << "Unhandled type for ICMP_SGT predicate: " << *Ty << "\n"; abort(); @@ -496,11 +511,8 @@ static GenericValue executeICMP_ULE(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { - IMPLEMENT_ICMP(<=, Int8, uint8_t); |