aboutsummaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp303
-rw-r--r--lib/ExecutionEngine/Interpreter/Execution.cpp1065
-rw-r--r--lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp14
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.h37
-rw-r--r--lib/ExecutionEngine/JIT/JIT.cpp48
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);