mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-29 06:30:39 +00:00
Implement APInt support for the binary operators.
Move the getConstantExpr function towards the end of the file so we don't need a dozen forward declarations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34877 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
dea7ef1f17
commit
e1aa066216
@ -18,6 +18,7 @@
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/CodeGen/IntrinsicLowering.h"
|
||||
#include "llvm/Support/GetElementPtrTypeIterator.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
@ -27,47 +28,17 @@ using namespace llvm;
|
||||
STATISTIC(NumDynamicInsts, "Number of dynamic instructions executed");
|
||||
static Interpreter *TheEE = 0;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Value Manipulation code
|
||||
// Various Helper Functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeUDivInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeSDivInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeFDivInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeURemInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeSRemInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeFRemInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeCmpInst(unsigned predicate, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty);
|
||||
static GenericValue executeShlInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeLShrInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeAShrInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeSelectInst(GenericValue Src1, GenericValue Src2,
|
||||
GenericValue Src3);
|
||||
inline void initializeAPInt(GenericValue &GV, const Type* Ty,
|
||||
ExecutionContext &SF) {
|
||||
if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty))
|
||||
GV.APIntVal = SF.getAPInt(ITy->getBitWidth());
|
||||
}
|
||||
|
||||
inline uint64_t doSignExtension(uint64_t Val, const IntegerType* ITy) {
|
||||
static inline uint64_t doSignExtension(uint64_t Val, const IntegerType* ITy) {
|
||||
// Determine if the value is signed or not
|
||||
bool isSigned = (Val & (1 << (ITy->getBitWidth()-1))) != 0;
|
||||
// If its signed, extend the sign bits
|
||||
@ -76,122 +47,19 @@ inline uint64_t doSignExtension(uint64_t Val, const IntegerType* ITy) {
|
||||
return Val;
|
||||
}
|
||||
|
||||
GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
|
||||
ExecutionContext &SF) {
|
||||
switch (CE->getOpcode()) {
|
||||
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 executeBitCastInst(CE->getOperand(0), CE->getType(), SF);
|
||||
case Instruction::GetElementPtr:
|
||||
return executeGEPOperation(CE->getOperand(0), gep_type_begin(CE),
|
||||
gep_type_end(CE), SF);
|
||||
case Instruction::Add:
|
||||
return executeAddInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Sub:
|
||||
return executeSubInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Mul:
|
||||
return executeMulInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SDiv:
|
||||
return executeSDivInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::UDiv:
|
||||
return executeUDivInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::FDiv:
|
||||
return executeFDivInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::URem:
|
||||
return executeURemInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SRem:
|
||||
return executeSRemInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::FRem:
|
||||
return executeFRemInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::And:
|
||||
return executeAndInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Or:
|
||||
return executeOrInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Xor:
|
||||
return executeXorInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::FCmp:
|
||||
case Instruction::ICmp:
|
||||
return executeCmpInst(CE->getPredicate(),
|
||||
getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Shl:
|
||||
return executeShlInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::LShr:
|
||||
return executeLShrInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::AShr:
|
||||
return executeAShrInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Select:
|
||||
return executeSelectInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
getOperandValue(CE->getOperand(2), SF));
|
||||
default:
|
||||
cerr << "Unhandled ConstantExpr: " << *CE << "\n";
|
||||
abort();
|
||||
return GenericValue();
|
||||
}
|
||||
}
|
||||
|
||||
GenericValue Interpreter::getOperandValue(Value *V, ExecutionContext &SF) {
|
||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
|
||||
return getConstantExprValue(CE, SF);
|
||||
} else if (Constant *CPV = dyn_cast<Constant>(V)) {
|
||||
return getConstantValue(CPV);
|
||||
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
|
||||
return PTOGV(getPointerToGlobal(GV));
|
||||
} else {
|
||||
return SF.Values[V];
|
||||
static inline void maskToBitWidth(GenericValue& GV, unsigned BitWidth) {
|
||||
uint64_t BitMask = ~(uint64_t)(0ull) >> (64-BitWidth);
|
||||
if (BitWidth <= 8)
|
||||
GV.Int8Val &= BitMask;
|
||||
else if (BitWidth <= 16)
|
||||
GV.Int16Val &= BitMask;
|
||||
else if (BitWidth <= 32)
|
||||
GV.Int32Val &= BitMask;
|
||||
else if (BitWidth <= 64)
|
||||
GV.Int64Val &= BitMask;
|
||||
else {
|
||||
assert(GV.APIntVal && "Unallocated GV.APIntVal");
|
||||
*(GV.APIntVal) &= APInt::getAllOnesValue(BitWidth);
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,67 +81,72 @@ void Interpreter::initializeExecutionEngine() {
|
||||
#define IMPLEMENT_INTEGER_BINOP(OP, TY) \
|
||||
case Type::IntegerTyID: { \
|
||||
unsigned BitWidth = cast<IntegerType>(TY)->getBitWidth(); \
|
||||
if (BitWidth == 1) \
|
||||
if (BitWidth == 1) {\
|
||||
Dest.Int1Val = Src1.Int1Val OP Src2.Int1Val; \
|
||||
else if (BitWidth <= 8) \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else if (BitWidth <= 8) {\
|
||||
Dest.Int8Val = Src1.Int8Val OP Src2.Int8Val; \
|
||||
else if (BitWidth <= 16) \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else if (BitWidth <= 16) {\
|
||||
Dest.Int16Val = Src1.Int16Val OP Src2.Int16Val; \
|
||||
else if (BitWidth <= 32) \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else if (BitWidth <= 32) {\
|
||||
Dest.Int32Val = Src1.Int32Val OP Src2.Int32Val; \
|
||||
else if (BitWidth <= 64) \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else if (BitWidth <= 64) {\
|
||||
Dest.Int64Val = Src1.Int64Val OP Src2.Int64Val; \
|
||||
else \
|
||||
cerr << "Integer types > 64 bits not supported: " << *Ty << "\n"; \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else \
|
||||
*(Dest.APIntVal) = *(Src1.APIntVal) OP *(Src2.APIntVal); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_SIGNED_BINOP(OP, TY) \
|
||||
#define IMPLEMENT_SIGNED_BINOP(OP, TY, APOP) \
|
||||
if (const IntegerType *ITy = dyn_cast<IntegerType>(TY)) { \
|
||||
unsigned BitWidth = ITy->getBitWidth(); \
|
||||
if (BitWidth <= 8) \
|
||||
if (BitWidth <= 8) { \
|
||||
Dest.Int8Val = ((int8_t)Src1.Int8Val) OP ((int8_t)Src2.Int8Val); \
|
||||
else if (BitWidth <= 16) \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else if (BitWidth <= 16) { \
|
||||
Dest.Int16Val = ((int16_t)Src1.Int16Val) OP ((int16_t)Src2.Int16Val); \
|
||||
else if (BitWidth <= 32) \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else if (BitWidth <= 32) { \
|
||||
Dest.Int32Val = ((int32_t)Src1.Int32Val) OP ((int32_t)Src2.Int32Val); \
|
||||
else if (BitWidth <= 64) \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} 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(); \
|
||||
} \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else \
|
||||
*(Dest.APIntVal) = Src1.APIntVal->APOP(*(Src2.APIntVal)); \
|
||||
} else { \
|
||||
cerr << "Unhandled type for " #OP " operator: " << *Ty << "\n"; \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_UNSIGNED_BINOP(OP, TY) \
|
||||
#define IMPLEMENT_UNSIGNED_BINOP(OP, TY, APOP) \
|
||||
if (const IntegerType *ITy = dyn_cast<IntegerType>(TY)) { \
|
||||
unsigned BitWidth = ITy->getBitWidth(); \
|
||||
if (BitWidth <= 8) \
|
||||
if (BitWidth <= 8) {\
|
||||
Dest.Int8Val = ((uint8_t)Src1.Int8Val) OP ((uint8_t)Src2.Int8Val); \
|
||||
else if (BitWidth <= 16) \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else if (BitWidth <= 16) {\
|
||||
Dest.Int16Val = ((uint16_t)Src1.Int16Val) OP ((uint16_t)Src2.Int16Val); \
|
||||
else if (BitWidth <= 32) \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else if (BitWidth <= 32) {\
|
||||
Dest.Int32Val = ((uint32_t)Src1.Int32Val) OP ((uint32_t)Src2.Int32Val); \
|
||||
else if (BitWidth <= 64) \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} 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(); \
|
||||
} \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
maskToBitWidth(Dest, BitWidth); \
|
||||
} else \
|
||||
*(Dest.APIntVal) = Src1.APIntVal->APOP(*(Src2.APIntVal)); \
|
||||
} else { \
|
||||
cerr << "Unhandled type for " #OP " operator: " << *Ty << "\n"; \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
static void executeAddInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_INTEGER_BINOP(+, Ty);
|
||||
IMPLEMENT_BINARY_OPERATOR(+, Float);
|
||||
@ -282,12 +155,10 @@ static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2,
|
||||
cerr << "Unhandled type for Add instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
static void executeSubInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_INTEGER_BINOP(-, Ty);
|
||||
IMPLEMENT_BINARY_OPERATOR(-, Float);
|
||||
@ -296,12 +167,10 @@ static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2,
|
||||
cerr << "Unhandled type for Sub instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
static void executeMulInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_INTEGER_BINOP(*, Ty);
|
||||
IMPLEMENT_BINARY_OPERATOR(*, Float);
|
||||
@ -310,26 +179,20 @@ static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2,
|
||||
cerr << "Unhandled type for Mul instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeUDivInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
IMPLEMENT_UNSIGNED_BINOP(/,Ty)
|
||||
return Dest;
|
||||
static void executeUDivInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
IMPLEMENT_UNSIGNED_BINOP(/,Ty,udiv)
|
||||
}
|
||||
|
||||
static GenericValue executeSDivInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
IMPLEMENT_SIGNED_BINOP(/,Ty)
|
||||
return Dest;
|
||||
static void executeSDivInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
IMPLEMENT_SIGNED_BINOP(/,Ty,sdiv)
|
||||
}
|
||||
|
||||
static GenericValue executeFDivInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
static void executeFDivInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_BINARY_OPERATOR(/, Float);
|
||||
IMPLEMENT_BINARY_OPERATOR(/, Double);
|
||||
@ -337,26 +200,20 @@ static GenericValue executeFDivInst(GenericValue Src1, GenericValue Src2,
|
||||
cerr << "Unhandled type for FDiv instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeURemInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
IMPLEMENT_UNSIGNED_BINOP(%, Ty)
|
||||
return Dest;
|
||||
static void executeURemInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
IMPLEMENT_UNSIGNED_BINOP(%,Ty,urem)
|
||||
}
|
||||
|
||||
static GenericValue executeSRemInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
IMPLEMENT_SIGNED_BINOP(%, Ty)
|
||||
return Dest;
|
||||
static void executeSRemInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
IMPLEMENT_SIGNED_BINOP(%,Ty,srem)
|
||||
}
|
||||
|
||||
static GenericValue executeFRemInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
static void executeFRemInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::FloatTyID:
|
||||
Dest.FloatVal = fmod(Src1.FloatVal, Src2.FloatVal);
|
||||
@ -368,28 +225,21 @@ static GenericValue executeFRemInst(GenericValue Src1, GenericValue Src2,
|
||||
cerr << "Unhandled type for Rem instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
IMPLEMENT_UNSIGNED_BINOP(&, Ty)
|
||||
return Dest;
|
||||
static void executeAndInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
IMPLEMENT_UNSIGNED_BINOP(&,Ty,And)
|
||||
}
|
||||
|
||||
static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
IMPLEMENT_UNSIGNED_BINOP(|, Ty)
|
||||
return Dest;
|
||||
static void executeOrInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
IMPLEMENT_UNSIGNED_BINOP(|,Ty,Or)
|
||||
}
|
||||
|
||||
static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
IMPLEMENT_UNSIGNED_BINOP(^, Ty)
|
||||
return Dest;
|
||||
static void executeXorInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
IMPLEMENT_UNSIGNED_BINOP(^,Ty,Xor)
|
||||
}
|
||||
|
||||
#define IMPLEMENT_SIGNED_ICMP(OP, TY) \
|
||||
@ -845,20 +695,21 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) {
|
||||
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
|
||||
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
|
||||
GenericValue R; // Result
|
||||
initializeAPInt(R, Ty, SF);
|
||||
|
||||
switch (I.getOpcode()) {
|
||||
case Instruction::Add: R = executeAddInst (Src1, Src2, Ty); break;
|
||||
case Instruction::Sub: R = executeSubInst (Src1, Src2, Ty); break;
|
||||
case Instruction::Mul: R = executeMulInst (Src1, Src2, Ty); break;
|
||||
case Instruction::UDiv: R = executeUDivInst (Src1, Src2, Ty); break;
|
||||
case Instruction::SDiv: R = executeSDivInst (Src1, Src2, Ty); break;
|
||||
case Instruction::FDiv: R = executeFDivInst (Src1, Src2, Ty); break;
|
||||
case Instruction::URem: R = executeURemInst (Src1, Src2, Ty); break;
|
||||
case Instruction::SRem: R = executeSRemInst (Src1, Src2, Ty); break;
|
||||
case Instruction::FRem: R = executeFRemInst (Src1, Src2, Ty); break;
|
||||
case Instruction::And: R = executeAndInst (Src1, Src2, Ty); break;
|
||||
case Instruction::Or: R = executeOrInst (Src1, Src2, Ty); break;
|
||||
case Instruction::Xor: R = executeXorInst (Src1, Src2, Ty); break;
|
||||
case Instruction::Add: executeAddInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::Sub: executeSubInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::Mul: executeMulInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::UDiv: executeUDivInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::SDiv: executeSDivInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::FDiv: executeFDivInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::URem: executeURemInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::SRem: executeSRemInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::FRem: executeFRemInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::And: executeAndInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::Or: executeOrInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::Xor: executeXorInst (R, Src1, Src2, Ty); break;
|
||||
default:
|
||||
cerr << "Don't know how to handle this binary operator!\n-->" << I;
|
||||
abort();
|
||||
@ -877,7 +728,9 @@ void Interpreter::visitSelectInst(SelectInst &I) {
|
||||
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
|
||||
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
|
||||
GenericValue Src3 = getOperandValue(I.getOperand(2), SF);
|
||||
GenericValue R = executeSelectInst(Src1, Src2, Src3);
|
||||
GenericValue R;
|
||||
initializeAPInt(R, I.getOperand(1)->getType(), SF);
|
||||
R = executeSelectInst(Src1, Src2, Src3);
|
||||
SetValue(&I, R, SF);
|
||||
}
|
||||
|
||||
@ -1328,22 +1181,30 @@ GenericValue Interpreter::executeTruncInst(Value *SrcVal, const Type *DstTy,
|
||||
const IntegerType *SITy = cast<IntegerType>(SrcTy);
|
||||
unsigned DBitWidth = DITy->getBitWidth();
|
||||
unsigned SBitWidth = SITy->getBitWidth();
|
||||
assert(SBitWidth <= 64 && DBitWidth <= 64 &&
|
||||
"Integer types > 64 bits not supported");
|
||||
assert(SBitWidth > DBitWidth && "Invalid truncate");
|
||||
|
||||
if (DBitWidth > 64) {
|
||||
// Both values are APInt, just use the APInt trunc
|
||||
initializeAPInt(Dest, DstTy, SF);
|
||||
*(Dest.APIntVal) = Src.APIntVal->trunc(DBitWidth);
|
||||
return Dest;
|
||||
}
|
||||
|
||||
uint64_t MaskedVal = 0;
|
||||
uint64_t Mask = (1ULL << DBitWidth) - 1;
|
||||
|
||||
// Mask the source value to its actual bit width. This ensures that any
|
||||
// high order bits are cleared.
|
||||
uint64_t Mask = (1ULL << DBitWidth) - 1;
|
||||
uint64_t MaskedVal = 0;
|
||||
if (SBitWidth <= 8)
|
||||
MaskedVal = Src.Int8Val & Mask;
|
||||
else if (SBitWidth <= 16)
|
||||
MaskedVal = Src.Int16Val & Mask;
|
||||
else if (SBitWidth <= 32)
|
||||
MaskedVal = Src.Int32Val & Mask;
|
||||
else
|
||||
else if (SBitWidth <= 64)
|
||||
MaskedVal = Src.Int64Val & Mask;
|
||||
else
|
||||
MaskedVal = Src.APIntVal->trunc(DBitWidth).getZExtValue();
|
||||
|
||||
INTEGER_ASSIGN(Dest, DBitWidth, MaskedVal);
|
||||
return Dest;
|
||||
@ -1708,6 +1569,131 @@ void Interpreter::visitVAArgInst(VAArgInst &I) {
|
||||
++VAList.UIntPairVal.second;
|
||||
}
|
||||
|
||||
GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
|
||||
ExecutionContext &SF) {
|
||||
switch (CE->getOpcode()) {
|
||||
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 executeBitCastInst(CE->getOperand(0), CE->getType(), SF);
|
||||
case Instruction::GetElementPtr:
|
||||
return executeGEPOperation(CE->getOperand(0), gep_type_begin(CE),
|
||||
gep_type_end(CE), SF);
|
||||
default :
|
||||
break;
|
||||
}
|
||||
GenericValue Dest;
|
||||
initializeAPInt(Dest, CE->getType(), SF);
|
||||
switch (CE->getOpcode()) {
|
||||
case Instruction::Add:
|
||||
executeAddInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Sub:
|
||||
executeSubInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Mul:
|
||||
executeMulInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SDiv:
|
||||
executeSDivInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::UDiv:
|
||||
executeUDivInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::FDiv:
|
||||
executeFDivInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::URem:
|
||||
executeURemInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SRem:
|
||||
executeSRemInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::FRem:
|
||||
executeFRemInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::And:
|
||||
executeAndInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Or:
|
||||
executeOrInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Xor:
|
||||
executeXorInst(Dest, getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::FCmp:
|
||||
case Instruction::ICmp:
|
||||
return executeCmpInst(CE->getPredicate(),
|
||||
getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Shl:
|
||||
return executeShlInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::LShr:
|
||||
return executeLShrInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::AShr:
|
||||
return executeAShrInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Select:
|
||||
return executeSelectInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
getOperandValue(CE->getOperand(2), SF));
|
||||
default:
|
||||
cerr << "Unhandled ConstantExpr: " << *CE << "\n";
|
||||
abort();
|
||||
return GenericValue();
|
||||
}
|
||||
}
|
||||
|
||||
GenericValue Interpreter::getOperandValue(Value *V, ExecutionContext &SF) {
|
||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
|
||||
return getConstantExprValue(CE, SF);
|
||||
} else if (Constant *CPV = dyn_cast<Constant>(V)) {
|
||||
return getConstantValue(CPV);
|
||||
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
|
||||
return PTOGV(getPointerToGlobal(GV));
|
||||
} else {
|
||||
return SF.Values[V];
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Dispatch and Execution Code
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
Loading…
Reference in New Issue
Block a user