//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
-#include "llvm/ParameterAttributes.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
+#include <algorithm>
#include <cmath>
+#include <cstring>
using namespace llvm;
STATISTIC(NumDynamicInsts, "Number of dynamic instructions executed");
static Interpreter *TheEE = 0;
+static cl::opt<bool> PrintVolatile("interpreter-print-volatile", cl::Hidden,
+ cl::desc("make the interpreter print every volatile load and store"));
+
//===----------------------------------------------------------------------===//
// Various Helper Functions
//===----------------------------------------------------------------------===//
Dest.TY##Val = Src1.TY##Val OP Src2.TY##Val; \
break
-#define IMPLEMENT_INTEGER_BINOP1(OP, TY) \
- case Type::IntegerTyID: { \
- Dest.IntVal = Src1.IntVal OP Src2.IntVal; \
- break; \
- }
-
-
-static void executeAddInst(GenericValue &Dest, GenericValue Src1,
- GenericValue Src2, const Type *Ty) {
+static void executeFAddInst(GenericValue &Dest, GenericValue Src1,
+ GenericValue Src2, const Type *Ty) {
switch (Ty->getTypeID()) {
- IMPLEMENT_INTEGER_BINOP1(+, Ty);
IMPLEMENT_BINARY_OPERATOR(+, Float);
IMPLEMENT_BINARY_OPERATOR(+, Double);
default:
- cerr << "Unhandled type for Add instruction: " << *Ty << "\n";
+ cerr << "Unhandled type for FAdd instruction: " << *Ty << "\n";
abort();
}
}
-static void executeSubInst(GenericValue &Dest, GenericValue Src1,
- GenericValue Src2, const Type *Ty) {
+static void executeFSubInst(GenericValue &Dest, GenericValue Src1,
+ GenericValue Src2, const Type *Ty) {
switch (Ty->getTypeID()) {
- IMPLEMENT_INTEGER_BINOP1(-, Ty);
IMPLEMENT_BINARY_OPERATOR(-, Float);
IMPLEMENT_BINARY_OPERATOR(-, Double);
default:
- cerr << "Unhandled type for Sub instruction: " << *Ty << "\n";
+ cerr << "Unhandled type for FSub instruction: " << *Ty << "\n";
abort();
}
}
-static void executeMulInst(GenericValue &Dest, GenericValue Src1,
- GenericValue Src2, const Type *Ty) {
+static void executeFMulInst(GenericValue &Dest, GenericValue Src1,
+ GenericValue Src2, const Type *Ty) {
switch (Ty->getTypeID()) {
- IMPLEMENT_INTEGER_BINOP1(*, Ty);
IMPLEMENT_BINARY_OPERATOR(*, Float);
IMPLEMENT_BINARY_OPERATOR(*, Double);
default:
- cerr << "Unhandled type for Mul instruction: " << *Ty << "\n";
+ cerr << "Unhandled type for FMul instruction: " << *Ty << "\n";
abort();
}
}
return Dest;
}
-#define IMPLEMENT_UNORDERED(TY, X,Y) \
- if (TY == Type::FloatTy) \
- if (X.FloatVal != X.FloatVal || Y.FloatVal != Y.FloatVal) { \
- Dest.IntVal = APInt(1,true); \
- return Dest; \
- } \
- else if (X.DoubleVal != X.DoubleVal || Y.DoubleVal != Y.DoubleVal) { \
- Dest.IntVal = APInt(1,true); \
- return Dest; \
- }
+#define IMPLEMENT_UNORDERED(TY, X,Y) \
+ if (TY == Type::FloatTy) { \
+ if (X.FloatVal != X.FloatVal || Y.FloatVal != Y.FloatVal) { \
+ Dest.IntVal = APInt(1,true); \
+ return Dest; \
+ } \
+ } else if (X.DoubleVal != X.DoubleVal || Y.DoubleVal != Y.DoubleVal) { \
+ Dest.IntVal = APInt(1,true); \
+ return Dest; \
+ }
static GenericValue executeFCMP_UEQ(GenericValue Src1, GenericValue Src2,
GenericValue R; // Result
switch (I.getOpcode()) {
- 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::FDiv: executeFDivInst (R, Src1, Src2, Ty); break;
- case Instruction::FRem: executeFRemInst (R, Src1, Src2, Ty); break;
+ case Instruction::Add: R.IntVal = Src1.IntVal + Src2.IntVal; break;
+ case Instruction::Sub: R.IntVal = Src1.IntVal - Src2.IntVal; break;
+ case Instruction::Mul: R.IntVal = Src1.IntVal * Src2.IntVal; break;
+ case Instruction::FAdd: executeFAddInst(R, Src1, Src2, Ty); break;
+ case Instruction::FSub: executeFSubInst(R, Src1, Src2, Ty); break;
+ case Instruction::FMul: executeFMulInst(R, Src1, Src2, Ty); break;
+ case Instruction::FDiv: executeFDivInst(R, Src1, Src2, Ty); break;
+ case Instruction::FRem: executeFRemInst(R, Src1, Src2, Ty); break;
case Instruction::UDiv: R.IntVal = Src1.IntVal.udiv(Src2.IntVal); break;
case Instruction::SDiv: R.IntVal = Src1.IntVal.sdiv(Src2.IntVal); break;
case Instruction::URem: R.IntVal = Src1.IntVal.urem(Src2.IntVal); break;
if (RetTy && RetTy->isInteger()) { // Nonvoid return type?
ExitValue = Result; // Capture the exit value of the program
} else {
- memset(&ExitValue, 0, sizeof(ExitValue));
+ memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped));
}
} else {
// If we have a previous stack frame, and we have a previous call,
unsigned NumElements =
getOperandValue(I.getOperand(0), SF).IntVal.getZExtValue();
- unsigned TypeSize = (size_t)TD.getTypeSize(Ty);
+ unsigned TypeSize = (size_t)TD.getTypeAllocSize(Ty);
- unsigned MemToAlloc = NumElements * TypeSize;
+ // Avoid malloc-ing zero bytes, use max()...
+ unsigned MemToAlloc = std::max(1U, NumElements * TypeSize);
// Allocate enough memory to hold the type...
void *Memory = malloc(MemToAlloc);
cast<IntegerType>(I.getOperand()->getType())->getBitWidth();
if (BitWidth == 32)
Idx = (int64_t)(int32_t)IdxGV.IntVal.getZExtValue();
- else if (BitWidth == 64)
+ else {
+ assert(BitWidth == 64 && "Invalid index type for getelementptr");
Idx = (int64_t)IdxGV.IntVal.getZExtValue();
- else
- assert(0 && "Invalid index type for getelementptr");
- Total += TD.getTypeSize(ST->getElementType())*Idx;
+ }
+ Total += TD.getTypeAllocSize(ST->getElementType())*Idx;
}
}
GenericValue Result;
LoadValueFromMemory(Result, Ptr, I.getType());
SetValue(&I, Result, SF);
+ if (I.isVolatile() && PrintVolatile)
+ cerr << "Volatile load " << I;
}
void Interpreter::visitStoreInst(StoreInst &I) {
GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
StoreValueToMemory(Val, (GenericValue *)GVTOP(SRC),
I.getOperand(0)->getType());
+ if (I.isVolatile() && PrintVolatile)
+ cerr << "Volatile store: " << I;
}
//===----------------------------------------------------------------------===//
// If it is an unknown intrinsic function, use the intrinsic lowering
// class to transform it into hopefully tasty LLVM code.
//
- Instruction *Prev = CS.getInstruction()->getPrev();
+ BasicBlock::iterator me(CS.getInstruction());
BasicBlock *Parent = CS.getInstruction()->getParent();
+ bool atBegin(Parent->begin() == me);
+ if (!atBegin)
+ --me;
IL->LowerIntrinsicCall(cast<CallInst>(CS.getInstruction()));
// Restore the CurInst pointer to the first instruction newly inserted, if
// any.
- if (!Prev) {
+ if (atBegin) {
SF.CurInst = Parent->begin();
} else {
- SF.CurInst = Prev;
+ SF.CurInst = me;
++SF.CurInst;
}
return;
e = SF.Caller.arg_end(); i != e; ++i, ++pNum) {
Value *V = *i;
ArgVals.push_back(getOperandValue(V, SF));
- if (F) {
- // Promote all integral types whose size is < sizeof(i32) into i32.
- // We do this by zero or sign extending the value as appropriate
- // according to the parameter attributes
- const Type *Ty = V->getType();
- if (Ty->isInteger() && (ArgVals.back().IntVal.getBitWidth() < 32))
- if (const ParamAttrsList *PA = F->getParamAttrs())
- if (PA->paramHasAttr(pNum, ParamAttr::ZExt))
- ArgVals.back().IntVal = ArgVals.back().IntVal.zext(32);
- else if (PA->paramHasAttr(pNum, ParamAttr::SExt))
- ArgVals.back().IntVal = ArgVals.back().IntVal.sext(32);
- }
+ // Promote all integral types whose size is < sizeof(i32) into i32.
+ // We do this by zero or sign extending the value as appropriate
+ // according to the parameter attributes
+ const Type *Ty = V->getType();
+ if (Ty->isInteger() && (ArgVals.back().IntVal.getBitWidth() < 32)) {
+ if (CS.paramHasAttr(pNum, Attribute::ZExt))
+ ArgVals.back().IntVal = ArgVals.back().IntVal.zext(32);
+ else if (CS.paramHasAttr(pNum, Attribute::SExt))
+ ArgVals.back().IntVal = ArgVals.back().IntVal.sext(32);
+ }
}
// To handle indirect calls, we must get the pointer value from the argument
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
GenericValue Dest;
- Dest.IntVal = Src1.IntVal.shl(Src2.IntVal.getZExtValue());
+ if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth())
+ Dest.IntVal = Src1.IntVal.shl(Src2.IntVal.getZExtValue());
+ else
+ Dest.IntVal = Src1.IntVal;
+
SetValue(&I, Dest, SF);
}
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
GenericValue Dest;
- Dest.IntVal = Src1.IntVal.lshr(Src2.IntVal.getZExtValue());
+ if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth())
+ Dest.IntVal = Src1.IntVal.lshr(Src2.IntVal.getZExtValue());
+ else
+ Dest.IntVal = Src1.IntVal;
+
SetValue(&I, Dest, SF);
}
ExecutionContext &SF = ECStack.back();
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
- GenericValue Dest;
- Dest.IntVal = Src1.IntVal.ashr(Src2.IntVal.getZExtValue());
+ GenericValue Dest;
+ if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth())
+ Dest.IntVal = Src1.IntVal.ashr(Src2.IntVal.getZExtValue());
+ else
+ Dest.IntVal = Src1.IntVal;
+
SetValue(&I, Dest, SF);
}
GenericValue Interpreter::executeTruncInst(Value *SrcVal, const Type *DstTy,
ExecutionContext &SF) {
- const Type *SrcTy = SrcVal->getType();
GenericValue Dest, Src = getOperandValue(SrcVal, SF);
const IntegerType *DITy = cast<IntegerType>(DstTy);
- const IntegerType *SITy = cast<IntegerType>(SrcTy);
unsigned DBitWidth = DITy->getBitWidth();
- unsigned SBitWidth = SITy->getBitWidth();
- assert(SBitWidth > DBitWidth && "Invalid truncate");
Dest.IntVal = Src.IntVal.trunc(DBitWidth);
return Dest;
}
GenericValue Interpreter::executeSExtInst(Value *SrcVal, const Type *DstTy,
ExecutionContext &SF) {
- const Type *SrcTy = SrcVal->getType();
GenericValue Dest, Src = getOperandValue(SrcVal, SF);
const IntegerType *DITy = cast<IntegerType>(DstTy);
- const IntegerType *SITy = cast<IntegerType>(SrcTy);
unsigned DBitWidth = DITy->getBitWidth();
- unsigned SBitWidth = SITy->getBitWidth();
- assert(SBitWidth < DBitWidth && "Invalid sign extend");
Dest.IntVal = Src.IntVal.sext(DBitWidth);
return Dest;
}
GenericValue Interpreter::executeZExtInst(Value *SrcVal, const Type *DstTy,
ExecutionContext &SF) {
- const Type *SrcTy = SrcVal->getType();
GenericValue Dest, Src = getOperandValue(SrcVal, SF);
const IntegerType *DITy = cast<IntegerType>(DstTy);
- const IntegerType *SITy = cast<IntegerType>(SrcTy);
unsigned DBitWidth = DITy->getBitWidth();
- unsigned SBitWidth = SITy->getBitWidth();
- assert(SBitWidth < DBitWidth && "Invalid sign extend");
Dest.IntVal = Src.IntVal.zext(DBitWidth);
return Dest;
}
GenericValue Interpreter::executeFPTruncInst(Value *SrcVal, const Type *DstTy,
ExecutionContext &SF) {
- const Type *SrcTy = SrcVal->getType();
GenericValue Dest, Src = getOperandValue(SrcVal, SF);
- assert(SrcTy == Type::DoubleTy && DstTy == Type::FloatTy &&
+ assert(SrcVal->getType() == Type::DoubleTy && DstTy == Type::FloatTy &&
"Invalid FPTrunc instruction");
Dest.FloatVal = (float) Src.DoubleVal;
return Dest;
GenericValue Interpreter::executeFPExtInst(Value *SrcVal, const Type *DstTy,
ExecutionContext &SF) {
- const Type *SrcTy = SrcVal->getType();
GenericValue Dest, Src = getOperandValue(SrcVal, SF);
- assert(SrcTy == Type::FloatTy && DstTy == Type::DoubleTy &&
+ assert(SrcVal->getType() == Type::FloatTy && DstTy == Type::DoubleTy &&
"Invalid FPTrunc instruction");
Dest.DoubleVal = (double) Src.FloatVal;
return Dest;
GenericValue Interpreter::executePtrToIntInst(Value *SrcVal, const Type *DstTy,
ExecutionContext &SF) {
- const Type *SrcTy = SrcVal->getType();
uint32_t DBitWidth = cast<IntegerType>(DstTy)->getBitWidth();
GenericValue Dest, Src = getOperandValue(SrcVal, SF);
- assert(isa<PointerType>(SrcTy) && "Invalid PtrToInt instruction");
+ assert(isa<PointerType>(SrcVal->getType()) && "Invalid PtrToInt instruction");
Dest.IntVal = APInt(DBitWidth, (intptr_t) Src.PointerVal);
return Dest;
if (PtrSize != Src.IntVal.getBitWidth())
Src.IntVal = Src.IntVal.zextOrTrunc(PtrSize);
- Dest.PointerVal = (PointerTy) Src.IntVal.getZExtValue();
+ Dest.PointerVal = PointerTy(intptr_t(Src.IntVal.getZExtValue()));
return Dest;
}
Dest.PointerVal = Src.PointerVal;
} else if (DstTy->isInteger()) {
if (SrcTy == Type::FloatTy) {
+ Dest.IntVal.zext(sizeof(Src.FloatVal) * CHAR_BIT);
Dest.IntVal.floatToBits(Src.FloatVal);
} else if (SrcTy == Type::DoubleTy) {
+ Dest.IntVal.zext(sizeof(Src.DoubleVal) * CHAR_BIT);
Dest.IntVal.doubleToBits(Src.DoubleVal);
} else if (SrcTy->isInteger()) {
Dest.IntVal = Src.IntVal;
GenericValue Dest;
const Type * Ty = CE->getOperand(0)->getType();
switch (CE->getOpcode()) {
- case Instruction::Add: executeAddInst (Dest, Op0, Op1, Ty); break;
- case Instruction::Sub: executeSubInst (Dest, Op0, Op1, Ty); break;
- case Instruction::Mul: executeMulInst (Dest, Op0, Op1, Ty); break;
+ case Instruction::Add: Dest.IntVal = Op0.IntVal + Op1.IntVal; break;
+ case Instruction::Sub: Dest.IntVal = Op0.IntVal - Op1.IntVal; break;
+ case Instruction::Mul: Dest.IntVal = Op0.IntVal * Op1.IntVal; break;
+ case Instruction::FAdd: executeFAddInst(Dest, Op0, Op1, Ty); break;
+ case Instruction::FSub: executeFSubInst(Dest, Op0, Op1, Ty); break;
+ case Instruction::FMul: executeFMulInst(Dest, Op0, Op1, Ty); break;
case Instruction::FDiv: executeFDivInst(Dest, Op0, Op1, Ty); break;
case Instruction::FRem: executeFRemInst(Dest, Op0, Op1, Ty); break;
case Instruction::SDiv: Dest.IntVal = Op0.IntVal.sdiv(Op1.IntVal); break;
case Instruction::UDiv: Dest.IntVal = Op0.IntVal.udiv(Op1.IntVal); break;
case Instruction::URem: Dest.IntVal = Op0.IntVal.urem(Op1.IntVal); break;
case Instruction::SRem: Dest.IntVal = Op0.IntVal.srem(Op1.IntVal); break;
- case Instruction::And: Dest.IntVal = Op0.IntVal.And(Op1.IntVal); break;
- case Instruction::Or: Dest.IntVal = Op0.IntVal.Or(Op1.IntVal); break;
- case Instruction::Xor: Dest.IntVal = Op0.IntVal.Xor(Op1.IntVal); break;
+ case Instruction::And: Dest.IntVal = Op0.IntVal & Op1.IntVal; break;
+ case Instruction::Or: Dest.IntVal = Op0.IntVal | Op1.IntVal; break;
+ case Instruction::Xor: Dest.IntVal = Op0.IntVal ^ Op1.IntVal; break;
case Instruction::Shl:
Dest.IntVal = Op0.IntVal.shl(Op1.IntVal.getZExtValue());
break;
StackFrame.VarArgs.assign(ArgVals.begin()+i, ArgVals.end());
}
+
void Interpreter::run() {
while (!ECStack.empty()) {
// Interpret a single instruction & increment the "PC".
DOUT << "About to interpret: " << I;
visit(I); // Dispatch to one of the visit* methods...
+#if 0
+ // This is not safe, as visiting the instruction could lower it and free I.
+#ifndef NDEBUG
+ if (!isa<CallInst>(I) && !isa<InvokeInst>(I) &&
+ I.getType() != Type::VoidTy) {
+ DOUT << " --> ";
+ const GenericValue &Val = SF.Values[&I];
+ switch (I.getType()->getTypeID()) {
+ default: assert(0 && "Invalid GenericValue Type");
+ case Type::VoidTyID: DOUT << "void"; break;
+ case Type::FloatTyID: DOUT << "float " << Val.FloatVal; break;
+ case Type::DoubleTyID: DOUT << "double " << Val.DoubleVal; break;
+ case Type::PointerTyID: DOUT << "void* " << intptr_t(Val.PointerVal);
+ break;
+ case Type::IntegerTyID:
+ DOUT << "i" << Val.IntVal.getBitWidth() << " "
+ << Val.IntVal.toStringUnsigned(10)
+ << " (0x" << Val.IntVal.toStringUnsigned(16) << ")\n";
+ break;
+ }
+ }
+#endif
+#endif
}
}