X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FExecutionEngine%2FInterpreter%2FExecution.cpp;h=5e1ae0629f8ee532379fb627ec6cf080b2740488;hp=3d6cf0bfb9cde10375e5a25cc25ad17b91ba867a;hb=551ccae044b0ff658fe629dd67edd5ffe75d10e8;hpb=bbdabce1e97f77d383def3f06a51c4fc75d114cf diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 3d6cf0bfb9c..5e1ae0629f8 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -1,79 +1,32 @@ //===-- Execution.cpp - Implement code to simulate the program ------------===// // +// 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 contains the actual instruction interpreter. // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "interpreter" #include "Interpreter.h" -#include "ExecutionAnnotations.h" -#include "llvm/iPHINode.h" -#include "llvm/iOther.h" -#include "llvm/iTerminators.h" -#include "llvm/iMemory.h" -#include "llvm/DerivedTypes.h" #include "llvm/Constants.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/Target/TargetData.h" -#include "Support/CommandLine.h" -#include "Support/Statistic.h" -#include // For fmod -#include -#include -using std::vector; -using std::cout; -using std::cerr; +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include // For fmod +using namespace llvm; namespace { Statistic<> NumDynamicInsts("lli", "Number of dynamic instructions executed"); -} - -static cl::opt -QuietMode("quiet", cl::desc("Do not emit any non-program output")); - -static cl::alias -QuietModeA("q", cl::desc("Alias for -quiet"), cl::aliasopt(QuietMode)); - -static cl::opt -ArrayChecksEnabled("array-checks", cl::desc("Enable array bound checks")); -static cl::opt -AbortOnExceptions("abort-on-exception", - cl::desc("Halt execution on a machine exception")); - -// Create a TargetData structure to handle memory addressing and size/alignment -// computations -// -TargetData TD("lli Interpreter"); -CachedWriter CW; // Object to accelerate printing of LLVM - - -#ifdef PROFILE_STRUCTURE_FIELDS -static cl::opt -ProfileStructureFields("profilestructfields", - cl::desc("Profile Structure Field Accesses")); -#include -static std::map > FieldAccessCounts; -#endif - -sigjmp_buf SignalRecoverBuffer; -static bool InInstruction = false; - -extern "C" { -static void SigHandler(int Signal) { - if (InInstruction) - siglongjmp(SignalRecoverBuffer, Signal); -} -} - -static void initializeSignalHandlers() { - struct sigaction Action; - Action.sa_handler = SigHandler; - Action.sa_flags = SA_SIGINFO; - sigemptyset(&Action.sa_mask); - sigaction(SIGSEGV, &Action, 0); - sigaction(SIGBUS, &Action, 0); - sigaction(SIGINT, &Action, 0); - sigaction(SIGFPE, &Action, 0); + Interpreter *TheEE = 0; } @@ -81,203 +34,142 @@ static void initializeSignalHandlers() { // Value Manipulation code //===----------------------------------------------------------------------===// -static unsigned getOperandSlot(Value *V) { - SlotNumber *SN = (SlotNumber*)V->getAnnotation(SlotNumberAID); - assert(SN && "Operand does not have a slot number annotation!"); - return SN->SlotNum; -} - -#define GET_CONST_VAL(TY, CLASS) \ - case Type::TY##TyID: Result.TY##Val = cast(C)->getValue(); break - -// Operations used by constant expr implementations... -static GenericValue executeCastOperation(Value *Src, const Type *DestTy, - ExecutionContext &SF); -static GenericValue executeGEPOperation(Value *Src, User::op_iterator IdxBegin, - User::op_iterator IdxEnd, - ExecutionContext &SF); static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF); - -static GenericValue getConstantValue(const Constant *C) { - GenericValue Result; - switch (C->getType()->getPrimitiveID()) { - GET_CONST_VAL(Bool , ConstantBool); - GET_CONST_VAL(UByte , ConstantUInt); - GET_CONST_VAL(SByte , ConstantSInt); - GET_CONST_VAL(UShort , ConstantUInt); - GET_CONST_VAL(Short , ConstantSInt); - GET_CONST_VAL(UInt , ConstantUInt); - GET_CONST_VAL(Int , ConstantSInt); - GET_CONST_VAL(ULong , ConstantUInt); - GET_CONST_VAL(Long , ConstantSInt); - GET_CONST_VAL(Float , ConstantFP); - GET_CONST_VAL(Double , ConstantFP); - case Type::PointerTyID: - if (isa(C)) { - Result.PointerVal = 0; - } else if (const ConstantPointerRef *CPR = dyn_cast(C)){ - GlobalAddress *Address = - (GlobalAddress*)CPR->getValue()->getOrCreateAnnotation(GlobalAddressAID); - Result.PointerVal = (PointerTy)Address->Ptr; - } else { - assert(0 && "Unknown constant pointer type!"); - } - break; + 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 executeRemInst(GenericValue Src1, GenericValue Src2, + const Type *Ty); +static GenericValue executeDivInst(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 executeSetEQInst(GenericValue Src1, GenericValue Src2, + const Type *Ty); +static GenericValue executeSetNEInst(GenericValue Src1, GenericValue Src2, + const Type *Ty); +static GenericValue executeSetLTInst(GenericValue Src1, GenericValue Src2, + const Type *Ty); +static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2, + const Type *Ty); +static GenericValue executeSetLEInst(GenericValue Src1, GenericValue Src2, + const Type *Ty); +static GenericValue executeSetGEInst(GenericValue Src1, GenericValue Src2, + const Type *Ty); +static GenericValue executeShlInst(GenericValue Src1, GenericValue Src2, + const Type *Ty); +static GenericValue executeShrInst(GenericValue Src1, GenericValue Src2, + const Type *Ty); +static GenericValue executeSelectInst(GenericValue Src1, GenericValue Src2, + GenericValue Src3); + +GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE, + ExecutionContext &SF) { + switch (CE->getOpcode()) { + case Instruction::Cast: + return executeCastOperation(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::Div: + return executeDivInst(getOperandValue(CE->getOperand(0), SF), + getOperandValue(CE->getOperand(1), SF), + CE->getOperand(0)->getType()); + case Instruction::Rem: + return executeRemInst(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::SetEQ: + return executeSetEQInst(getOperandValue(CE->getOperand(0), SF), + getOperandValue(CE->getOperand(1), SF), + CE->getOperand(0)->getType()); + case Instruction::SetNE: + return executeSetNEInst(getOperandValue(CE->getOperand(0), SF), + getOperandValue(CE->getOperand(1), SF), + CE->getOperand(0)->getType()); + case Instruction::SetLE: + return executeSetLEInst(getOperandValue(CE->getOperand(0), SF), + getOperandValue(CE->getOperand(1), SF), + CE->getOperand(0)->getType()); + case Instruction::SetGE: + return executeSetGEInst(getOperandValue(CE->getOperand(0), SF), + getOperandValue(CE->getOperand(1), SF), + CE->getOperand(0)->getType()); + case Instruction::SetLT: + return executeSetLTInst(getOperandValue(CE->getOperand(0), SF), + getOperandValue(CE->getOperand(1), SF), + CE->getOperand(0)->getType()); + case Instruction::SetGT: + return executeSetGTInst(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::Shr: + return executeShrInst(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: - cout << "ERROR: Constant unimp for type: " << C->getType() << "\n"; + std::cerr << "Unhandled ConstantExpr: " << *CE << "\n"; + abort(); + return GenericValue(); } - return Result; } -static GenericValue getOperandValue(Value *V, ExecutionContext &SF) { +GenericValue Interpreter::getOperandValue(Value *V, ExecutionContext &SF) { if (ConstantExpr *CE = dyn_cast(V)) { - switch (CE->getOpcode()) { - case Instruction::Cast: - return executeCastOperation(CE->getOperand(0), CE->getType(), SF); - case Instruction::GetElementPtr: - return executeGEPOperation(CE->getOperand(0), CE->op_begin()+1, - CE->op_end(), SF); - case Instruction::Add: - return executeAddInst(getOperandValue(CE->getOperand(0), SF), - getOperandValue(CE->getOperand(1), SF), - CE->getType(), SF); - default: - cerr << "Unhandled ConstantExpr: " << CE << "\n"; - abort(); - { GenericValue V; return V; } - } + return getConstantExprValue(CE, SF); } else if (Constant *CPV = dyn_cast(V)) { return getConstantValue(CPV); } else if (GlobalValue *GV = dyn_cast(V)) { - GlobalAddress *Address = - (GlobalAddress*)GV->getOrCreateAnnotation(GlobalAddressAID); - GenericValue Result; - Result.PointerVal = (PointerTy)(GenericValue*)Address->Ptr; - return Result; + return PTOGV(getPointerToGlobal(GV)); } else { - unsigned TyP = V->getType()->getUniqueID(); // TypePlane for value - unsigned OpSlot = getOperandSlot(V); - assert(TyP < SF.Values.size() && - OpSlot < SF.Values[TyP].size() && "Value out of range!"); - return SF.Values[TyP][getOperandSlot(V)]; + return SF.Values[V]; } } -static void printOperandInfo(Value *V, ExecutionContext &SF) { - if (isa(V)) { - cout << "Constant Pool Value\n"; - } else if (isa(V)) { - cout << "Global Value\n"; - } else { - unsigned TyP = V->getType()->getUniqueID(); // TypePlane for value - unsigned Slot = getOperandSlot(V); - cout << "Value=" << (void*)V << " TypeID=" << TyP << " Slot=" << Slot - << " Addr=" << &SF.Values[TyP][Slot] << " SF=" << &SF - << " Contents=0x"; - - const unsigned char *Buf = (const unsigned char*)&SF.Values[TyP][Slot]; - for (unsigned i = 0; i < sizeof(GenericValue); ++i) { - unsigned char Cur = Buf[i]; - cout << ( Cur >= 160? char((Cur>>4)+'A'-10) : char((Cur>>4) + '0')) - << ((Cur&15) >= 10? char((Cur&15)+'A'-10) : char((Cur&15) + '0')); - } - cout << "\n"; - } -} - - - static void SetValue(Value *V, GenericValue Val, ExecutionContext &SF) { - unsigned TyP = V->getType()->getUniqueID(); // TypePlane for value - - //cout << "Setting value: " << &SF.Values[TyP][getOperandSlot(V)] << "\n"; - SF.Values[TyP][getOperandSlot(V)] = Val; + SF.Values[V] = Val; } - -//===----------------------------------------------------------------------===// -// Annotation Wrangling code -//===----------------------------------------------------------------------===// - void Interpreter::initializeExecutionEngine() { - AnnotationManager::registerAnnotationFactory(MethodInfoAID, - &MethodInfo::Create); - AnnotationManager::registerAnnotationFactory(GlobalAddressAID, - &GlobalAddress::Create); - initializeSignalHandlers(); -} - -static void StoreValueToMemory(GenericValue Val, GenericValue *Ptr, - const Type *Ty); - -// InitializeMemory - Recursive function to apply a Constant value into the -// specified memory location... -// -static void InitializeMemory(const Constant *Init, char *Addr) { - - if (Init->getType()->isFirstClassType()) { - GenericValue Val = getConstantValue(Init); - StoreValueToMemory(Val, (GenericValue*)Addr, Init->getType()); - return; - } - - switch (Init->getType()->getPrimitiveID()) { - case Type::ArrayTyID: { - const ConstantArray *CPA = cast(Init); - const vector &Val = CPA->getValues(); - unsigned ElementSize = - TD.getTypeSize(cast(CPA->getType())->getElementType()); - for (unsigned i = 0; i < Val.size(); ++i) - InitializeMemory(cast(Val[i].get()), Addr+i*ElementSize); - return; - } - - case Type::StructTyID: { - const ConstantStruct *CPS = cast(Init); - const StructLayout *SL=TD.getStructLayout(cast(CPS->getType())); - const vector &Val = CPS->getValues(); - for (unsigned i = 0; i < Val.size(); ++i) - InitializeMemory(cast(Val[i].get()), - Addr+SL->MemberOffsets[i]); - return; - } - - default: - CW << "Bad Type: " << Init->getType() << "\n"; - assert(0 && "Unknown constant type to initialize memory with!"); - } -} - -Annotation *GlobalAddress::Create(AnnotationID AID, const Annotable *O, void *){ - assert(AID == GlobalAddressAID); - - // This annotation will only be created on GlobalValue objects... - GlobalValue *GVal = cast((Value*)O); - - if (isa(GVal)) { - // The GlobalAddress object for a function is just a pointer to function - // itself. Don't delete it when the annotation is gone though! - return new GlobalAddress(GVal, false); - } - - // Handle the case of a global variable... - assert(isa(GVal) && - "Global value found that isn't a function or global variable!"); - GlobalVariable *GV = cast(GVal); - - // First off, we must allocate space for the global variable to point at... - const Type *Ty = GV->getType()->getElementType(); // Type to be allocated - - // Allocate enough memory to hold the type... - void *Addr = calloc(1, TD.getTypeSize(Ty)); - assert(Addr != 0 && "Null pointer returned by malloc!"); - - // Initialize the memory if there is an initializer... - if (GV->hasInitializer()) - InitializeMemory(GV->getInitializer(), (char*)Addr); - - return new GlobalAddress(Addr, true); // Simply invoke the ctor + TheEE = this; } //===----------------------------------------------------------------------===// @@ -288,9 +180,9 @@ Annotation *GlobalAddress::Create(AnnotationID AID, const Annotable *O, void *){ case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.TY##Val; break static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(+, UByte); IMPLEMENT_BINARY_OPERATOR(+, SByte); IMPLEMENT_BINARY_OPERATOR(+, UShort); @@ -301,17 +193,17 @@ static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_BINARY_OPERATOR(+, Long); IMPLEMENT_BINARY_OPERATOR(+, Float); IMPLEMENT_BINARY_OPERATOR(+, Double); - IMPLEMENT_BINARY_OPERATOR(+, Pointer); default: - cout << "Unhandled type for Add instruction: " << Ty << "\n"; + std::cout << "Unhandled type for Add instruction: " << *Ty << "\n"; + abort(); } return Dest; } static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(-, UByte); IMPLEMENT_BINARY_OPERATOR(-, SByte); IMPLEMENT_BINARY_OPERATOR(-, UShort); @@ -322,17 +214,17 @@ static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_BINARY_OPERATOR(-, Long); IMPLEMENT_BINARY_OPERATOR(-, Float); IMPLEMENT_BINARY_OPERATOR(-, Double); - IMPLEMENT_BINARY_OPERATOR(-, Pointer); default: - cout << "Unhandled type for Sub instruction: " << Ty << "\n"; + std::cout << "Unhandled type for Sub instruction: " << *Ty << "\n"; + abort(); } return Dest; } static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(*, UByte); IMPLEMENT_BINARY_OPERATOR(*, SByte); IMPLEMENT_BINARY_OPERATOR(*, UShort); @@ -343,17 +235,17 @@ static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_BINARY_OPERATOR(*, Long); IMPLEMENT_BINARY_OPERATOR(*, Float); IMPLEMENT_BINARY_OPERATOR(*, Double); - IMPLEMENT_BINARY_OPERATOR(*, Pointer); default: - cout << "Unhandled type for Mul instruction: " << Ty << "\n"; + std::cout << "Unhandled type for Mul instruction: " << *Ty << "\n"; + abort(); } return Dest; } static GenericValue executeDivInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(/, UByte); IMPLEMENT_BINARY_OPERATOR(/, SByte); IMPLEMENT_BINARY_OPERATOR(/, UShort); @@ -364,17 +256,17 @@ static GenericValue executeDivInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_BINARY_OPERATOR(/, Long); IMPLEMENT_BINARY_OPERATOR(/, Float); IMPLEMENT_BINARY_OPERATOR(/, Double); - IMPLEMENT_BINARY_OPERATOR(/, Pointer); default: - cout << "Unhandled type for Div instruction: " << Ty << "\n"; + std::cout << "Unhandled type for Div instruction: " << *Ty << "\n"; + abort(); } return Dest; } static GenericValue executeRemInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(%, UByte); IMPLEMENT_BINARY_OPERATOR(%, SByte); IMPLEMENT_BINARY_OPERATOR(%, UShort); @@ -383,7 +275,6 @@ static GenericValue executeRemInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_BINARY_OPERATOR(%, Int); IMPLEMENT_BINARY_OPERATOR(%, ULong); IMPLEMENT_BINARY_OPERATOR(%, Long); - IMPLEMENT_BINARY_OPERATOR(%, Pointer); case Type::FloatTyID: Dest.FloatVal = fmod(Src1.FloatVal, Src2.FloatVal); break; @@ -391,15 +282,17 @@ static GenericValue executeRemInst(GenericValue Src1, GenericValue Src2, Dest.DoubleVal = fmod(Src1.DoubleVal, Src2.DoubleVal); break; default: - cout << "Unhandled type for Rem instruction: " << Ty << "\n"; + std::cout << "Unhandled type for Rem instruction: " << *Ty << "\n"; + abort(); } return Dest; } static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(&, Bool); IMPLEMENT_BINARY_OPERATOR(&, UByte); IMPLEMENT_BINARY_OPERATOR(&, SByte); IMPLEMENT_BINARY_OPERATOR(&, UShort); @@ -408,18 +301,18 @@ static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_BINARY_OPERATOR(&, Int); IMPLEMENT_BINARY_OPERATOR(&, ULong); IMPLEMENT_BINARY_OPERATOR(&, Long); - IMPLEMENT_BINARY_OPERATOR(&, Pointer); default: - cout << "Unhandled type for And instruction: " << Ty << "\n"; + std::cout << "Unhandled type for And instruction: " << *Ty << "\n"; + abort(); } return Dest; } - static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(|, Bool); IMPLEMENT_BINARY_OPERATOR(|, UByte); IMPLEMENT_BINARY_OPERATOR(|, SByte); IMPLEMENT_BINARY_OPERATOR(|, UShort); @@ -428,18 +321,18 @@ static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_BINARY_OPERATOR(|, Int); IMPLEMENT_BINARY_OPERATOR(|, ULong); IMPLEMENT_BINARY_OPERATOR(|, Long); - IMPLEMENT_BINARY_OPERATOR(|, Pointer); default: - cout << "Unhandled type for Or instruction: " << Ty << "\n"; + std::cout << "Unhandled type for Or instruction: " << *Ty << "\n"; + abort(); } return Dest; } - static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(^, Bool); IMPLEMENT_BINARY_OPERATOR(^, UByte); IMPLEMENT_BINARY_OPERATOR(^, SByte); IMPLEMENT_BINARY_OPERATOR(^, UShort); @@ -448,21 +341,29 @@ static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_BINARY_OPERATOR(^, Int); IMPLEMENT_BINARY_OPERATOR(^, ULong); IMPLEMENT_BINARY_OPERATOR(^, Long); - IMPLEMENT_BINARY_OPERATOR(^, Pointer); default: - cout << "Unhandled type for Xor instruction: " << Ty << "\n"; + std::cout << "Unhandled type for Xor instruction: " << *Ty << "\n"; + abort(); } return Dest; } - #define IMPLEMENT_SETCC(OP, TY) \ case Type::TY##TyID: Dest.BoolVal = Src1.TY##Val OP Src2.TY##Val; 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_POINTERSETCC(OP) \ + case Type::PointerTyID: \ + Dest.BoolVal = (void*)(intptr_t)Src1.PointerVal OP \ + (void*)(intptr_t)Src2.PointerVal; break + static GenericValue executeSetEQInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(==, UByte); IMPLEMENT_SETCC(==, SByte); IMPLEMENT_SETCC(==, UShort); @@ -473,17 +374,18 @@ static GenericValue executeSetEQInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_SETCC(==, Long); IMPLEMENT_SETCC(==, Float); IMPLEMENT_SETCC(==, Double); - IMPLEMENT_SETCC(==, Pointer); + IMPLEMENT_POINTERSETCC(==); default: - cout << "Unhandled type for SetEQ instruction: " << Ty << "\n"; + std::cout << "Unhandled type for SetEQ instruction: " << *Ty << "\n"; + abort(); } return Dest; } static GenericValue executeSetNEInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(!=, UByte); IMPLEMENT_SETCC(!=, SByte); IMPLEMENT_SETCC(!=, UShort); @@ -494,18 +396,19 @@ static GenericValue executeSetNEInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_SETCC(!=, Long); IMPLEMENT_SETCC(!=, Float); IMPLEMENT_SETCC(!=, Double); - IMPLEMENT_SETCC(!=, Pointer); + IMPLEMENT_POINTERSETCC(!=); default: - cout << "Unhandled type for SetNE instruction: " << Ty << "\n"; + std::cout << "Unhandled type for SetNE instruction: " << *Ty << "\n"; + abort(); } return Dest; } static GenericValue executeSetLEInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(<=, UByte); IMPLEMENT_SETCC(<=, SByte); IMPLEMENT_SETCC(<=, UShort); @@ -516,17 +419,18 @@ static GenericValue executeSetLEInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_SETCC(<=, Long); IMPLEMENT_SETCC(<=, Float); IMPLEMENT_SETCC(<=, Double); - IMPLEMENT_SETCC(<=, Pointer); + IMPLEMENT_POINTERSETCC(<=); default: - cout << "Unhandled type for SetLE instruction: " << Ty << "\n"; + std::cout << "Unhandled type for SetLE instruction: " << *Ty << "\n"; + abort(); } return Dest; } static GenericValue executeSetGEInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(>=, UByte); IMPLEMENT_SETCC(>=, SByte); IMPLEMENT_SETCC(>=, UShort); @@ -537,17 +441,18 @@ static GenericValue executeSetGEInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_SETCC(>=, Long); IMPLEMENT_SETCC(>=, Float); IMPLEMENT_SETCC(>=, Double); - IMPLEMENT_SETCC(>=, Pointer); + IMPLEMENT_POINTERSETCC(>=); default: - cout << "Unhandled type for SetGE instruction: " << Ty << "\n"; + std::cout << "Unhandled type for SetGE instruction: " << *Ty << "\n"; + abort(); } return Dest; } static GenericValue executeSetLTInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(<, UByte); IMPLEMENT_SETCC(<, SByte); IMPLEMENT_SETCC(<, UShort); @@ -558,17 +463,18 @@ static GenericValue executeSetLTInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_SETCC(<, Long); IMPLEMENT_SETCC(<, Float); IMPLEMENT_SETCC(<, Double); - IMPLEMENT_SETCC(<, Pointer); + IMPLEMENT_POINTERSETCC(<); default: - cout << "Unhandled type for SetLT instruction: " << Ty << "\n"; + std::cout << "Unhandled type for SetLT instruction: " << *Ty << "\n"; + abort(); } return Dest; } static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2, - const Type *Ty, ExecutionContext &SF) { + const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(>, UByte); IMPLEMENT_SETCC(>, SByte); IMPLEMENT_SETCC(>, UShort); @@ -579,106 +485,108 @@ static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_SETCC(>, Long); IMPLEMENT_SETCC(>, Float); IMPLEMENT_SETCC(>, Double); - IMPLEMENT_SETCC(>, Pointer); + IMPLEMENT_POINTERSETCC(>); default: - cout << "Unhandled type for SetGT instruction: " << Ty << "\n"; + std::cout << "Unhandled type for SetGT instruction: " << *Ty << "\n"; + abort(); } return Dest; } -static void executeBinaryInst(BinaryOperator &I, ExecutionContext &SF) { +void Interpreter::visitBinaryOperator(BinaryOperator &I) { + ExecutionContext &SF = ECStack.back(); const Type *Ty = I.getOperand(0)->getType(); GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); GenericValue R; // Result switch (I.getOpcode()) { - case Instruction::Add: R = executeAddInst (Src1, Src2, Ty, SF); break; - case Instruction::Sub: R = executeSubInst (Src1, Src2, Ty, SF); break; - case Instruction::Mul: R = executeMulInst (Src1, Src2, Ty, SF); break; - case Instruction::Div: R = executeDivInst (Src1, Src2, Ty, SF); break; - case Instruction::Rem: R = executeRemInst (Src1, Src2, Ty, SF); break; - case Instruction::And: R = executeAndInst (Src1, Src2, Ty, SF); break; - case Instruction::Or: R = executeOrInst (Src1, Src2, Ty, SF); break; - case Instruction::Xor: R = executeXorInst (Src1, Src2, Ty, SF); break; - case Instruction::SetEQ: R = executeSetEQInst(Src1, Src2, Ty, SF); break; - case Instruction::SetNE: R = executeSetNEInst(Src1, Src2, Ty, SF); break; - case Instruction::SetLE: R = executeSetLEInst(Src1, Src2, Ty, SF); break; - case Instruction::SetGE: R = executeSetGEInst(Src1, Src2, Ty, SF); break; - case Instruction::SetLT: R = executeSetLTInst(Src1, Src2, Ty, SF); break; - case Instruction::SetGT: R = executeSetGTInst(Src1, Src2, Ty, SF); break; + 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::Div: R = executeDivInst (Src1, Src2, Ty); break; + case Instruction::Rem: R = executeRemInst (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::SetEQ: R = executeSetEQInst(Src1, Src2, Ty); break; + case Instruction::SetNE: R = executeSetNEInst(Src1, Src2, Ty); break; + case Instruction::SetLE: R = executeSetLEInst(Src1, Src2, Ty); break; + case Instruction::SetGE: R = executeSetGEInst(Src1, Src2, Ty); break; + case Instruction::SetLT: R = executeSetLTInst(Src1, Src2, Ty); break; + case Instruction::SetGT: R = executeSetGTInst(Src1, Src2, Ty); break; default: - cout << "Don't know how to handle this binary operator!\n-->" << I; - R = Src1; + std::cout << "Don't know how to handle this binary operator!\n-->" << I; + abort(); } SetValue(&I, R, SF); } +static GenericValue executeSelectInst(GenericValue Src1, GenericValue Src2, + GenericValue Src3) { + return Src1.BoolVal ? Src2 : Src3; +} + +void Interpreter::visitSelectInst(SelectInst &I) { + ExecutionContext &SF = ECStack.back(); + 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); + SetValue(&I, R, SF); +} + + //===----------------------------------------------------------------------===// // Terminator Instruction Implementations //===----------------------------------------------------------------------===// -static void PerformExitStuff() { -#ifdef PROFILE_STRUCTURE_FIELDS - // Print out structure field accounting information... - if (!FieldAccessCounts.empty()) { - CW << "Profile Field Access Counts:\n"; - std::map >::iterator - I = FieldAccessCounts.begin(), E = FieldAccessCounts.end(); - for (; I != E; ++I) { - vector &OfC = I->second; - CW << " '" << (Value*)I->first << "'\t- Sum="; - - unsigned Sum = 0; - for (unsigned i = 0; i < OfC.size(); ++i) - Sum += OfC[i]; - CW << Sum << " - "; - - for (unsigned i = 0; i < OfC.size(); ++i) { - if (i) CW << ", "; - CW << OfC[i]; - } - CW << "\n"; - } - CW << "\n"; - - CW << "Profile Field Access Percentages:\n"; - cout.precision(3); - for (I = FieldAccessCounts.begin(); I != E; ++I) { - vector &OfC = I->second; - unsigned Sum = 0; - for (unsigned i = 0; i < OfC.size(); ++i) - Sum += OfC[i]; - - CW << " '" << (Value*)I->first << "'\t- "; - for (unsigned i = 0; i < OfC.size(); ++i) { - if (i) CW << ", "; - CW << double(OfC[i])/Sum; - } - CW << "\n"; - } - CW << "\n"; - - FieldAccessCounts.clear(); - } -#endif +void Interpreter::exitCalled(GenericValue GV) { + // runAtExitHandlers() assumes there are no stack frames, but + // if exit() was called, then it had a stack frame. Blow away + // the stack before interpreting atexit handlers. + ECStack.clear (); + runAtExitHandlers (); + exit (GV.IntVal); } -void Interpreter::exitCalled(GenericValue GV) { - if (!QuietMode) { - cout << "Program returned "; - print(Type::IntTy, GV); - cout << " via 'void exit(int)'\n"; - } +/// Pop the last stack frame off of ECStack and then copy the result +/// back into the result variable if we are not returning void. The +/// result variable may be the ExitCode, or the Value of the calling +/// CallInst if there was a previous stack frame. This method may +/// invalidate any ECStack iterators you have. This method also takes +/// care of switching to the normal destination BB, if we are returning +/// from an invoke. +/// +void Interpreter::popStackAndReturnValueToCaller (const Type *RetTy, + GenericValue Result) { + // Pop the current stack frame. + ECStack.pop_back(); - ExitCode = GV.SByteVal; - ECStack.clear(); - PerformExitStuff(); + if (ECStack.empty()) { // Finished main. Put result into exit code... + if (RetTy && RetTy->isIntegral()) { // Nonvoid return type? + ExitCode = Result.IntVal; // Capture the exit code of the program + } else { + ExitCode = 0; + } + } else { + // If we have a previous stack frame, and we have a previous call, + // fill in the return value... + ExecutionContext &CallingSF = ECStack.back(); + if (Instruction *I = CallingSF.Caller.getInstruction()) { + if (CallingSF.Caller.getType() != Type::VoidTy) // Save result... + SetValue(I, Result, CallingSF); + if (InvokeInst *II = dyn_cast (I)) + SwitchToNewBasicBlock (II->getNormalDest (), CallingSF); + CallingSF.Caller = CallSite(); // We returned from the call... + } + } } -void Interpreter::executeRetInst(ReturnInst &I, ExecutionContext &SF) { - const Type *RetTy = 0; +void Interpreter::visitReturnInst(ReturnInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *RetTy = Type::VoidTy; GenericValue Result; // Save away the return value... (if we are not 'ret void') @@ -687,81 +595,111 @@ void Interpreter::executeRetInst(ReturnInst &I, ExecutionContext &SF) { Result = getOperandValue(I.getReturnValue(), SF); } - // Save previously executing meth - const Function *M = ECStack.back().CurMethod; - - // Pop the current stack frame... this invalidates SF - ECStack.pop_back(); - - if (ECStack.empty()) { // Finished main. Put result into exit code... - if (RetTy) { // Nonvoid return type? - if (!QuietMode) { - CW << "Function " << M->getType() << " \"" << M->getName() - << "\" returned "; - print(RetTy, Result); - cout << "\n"; - } - - if (RetTy->isIntegral()) - ExitCode = Result.IntVal; // Capture the exit code of the program - } else { - ExitCode = 0; - } - - PerformExitStuff(); - return; - } + popStackAndReturnValueToCaller(RetTy, Result); +} - // If we have a previous stack frame, and we have a previous call, fill in - // the return value... - // - ExecutionContext &NewSF = ECStack.back(); - if (NewSF.Caller) { - if (NewSF.Caller->getType() != Type::VoidTy) // Save result... - SetValue(NewSF.Caller, Result, NewSF); - - NewSF.Caller = 0; // We returned from the call... - } else if (!QuietMode) { - // This must be a function that is executing because of a user 'call' - // instruction. - CW << "Function " << M->getType() << " \"" << M->getName() - << "\" returned "; - print(RetTy, Result); - cout << "\n"; - } +void Interpreter::visitUnwindInst(UnwindInst &I) { + // Unwind stack + Instruction *Inst; + do { + ECStack.pop_back (); + if (ECStack.empty ()) + abort (); + Inst = ECStack.back ().Caller.getInstruction (); + } while (!(Inst && isa (Inst))); + + // Return from invoke + ExecutionContext &InvokingSF = ECStack.back (); + InvokingSF.Caller = CallSite (); + + // Go to exceptional destination BB of invoke instruction + SwitchToNewBasicBlock(cast(Inst)->getUnwindDest(), InvokingSF); } -void Interpreter::executeBrInst(BranchInst &I, ExecutionContext &SF) { - SF.PrevBB = SF.CurBB; // Update PrevBB so that PHI nodes work... +void Interpreter::visitBranchInst(BranchInst &I) { + ExecutionContext &SF = ECStack.back(); BasicBlock *Dest; Dest = I.getSuccessor(0); // Uncond branches have a fixed dest... if (!I.isUnconditional()) { Value *Cond = I.getCondition(); - GenericValue CondVal = getOperandValue(Cond, SF); - if (CondVal.BoolVal == 0) // If false cond... + if (getOperandValue(Cond, SF).BoolVal == 0) // If false cond... Dest = I.getSuccessor(1); } + SwitchToNewBasicBlock(Dest, SF); +} + +void Interpreter::visitSwitchInst(SwitchInst &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue CondVal = getOperandValue(I.getOperand(0), SF); + const Type *ElTy = I.getOperand(0)->getType(); + + // Check to see if any of the cases match... + BasicBlock *Dest = 0; + for (unsigned i = 2, e = I.getNumOperands(); i != e; i += 2) + if (executeSetEQInst(CondVal, + getOperandValue(I.getOperand(i), SF), ElTy).BoolVal) { + Dest = cast(I.getOperand(i+1)); + break; + } + + if (!Dest) Dest = I.getDefaultDest(); // No cases matched: use default + SwitchToNewBasicBlock(Dest, SF); +} + +// SwitchToNewBasicBlock - This method is used to jump to a new basic block. +// This function handles the actual updating of block and instruction iterators +// as well as execution of all of the PHI nodes in the destination block. +// +// This method does this because all of the PHI nodes must be executed +// atomically, reading their inputs before any of the results are updated. Not +// doing this can cause problems if the PHI nodes depend on other PHI nodes for +// their inputs. If the input PHI node is updated before it is read, incorrect +// results can happen. Thus we use a two phase approach. +// +void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){ + BasicBlock *PrevBB = SF.CurBB; // Remember where we came from... SF.CurBB = Dest; // Update CurBB to branch destination SF.CurInst = SF.CurBB->begin(); // Update new instruction ptr... + + if (!isa(SF.CurInst)) return; // Nothing fancy to do + + // Loop over all of the PHI nodes in the current block, reading their inputs. + std::vector ResultValues; + + for (; PHINode *PN = dyn_cast(SF.CurInst); ++SF.CurInst) { + // Search for the value corresponding to this previous bb... + int i = PN->getBasicBlockIndex(PrevBB); + assert(i != -1 && "PHINode doesn't contain entry for predecessor??"); + Value *IncomingValue = PN->getIncomingValue(i); + + // Save the incoming value for this PHI node... + ResultValues.push_back(getOperandValue(IncomingValue, SF)); + } + + // Now loop over all of the PHI nodes setting their values... + SF.CurInst = SF.CurBB->begin(); + for (unsigned i = 0; PHINode *PN = dyn_cast(SF.CurInst); + ++SF.CurInst, ++i) + SetValue(PN, ResultValues[i], SF); } //===----------------------------------------------------------------------===// // Memory Instruction Implementations //===----------------------------------------------------------------------===// -void Interpreter::executeAllocInst(AllocationInst &I, ExecutionContext &SF) { +void Interpreter::visitAllocationInst(AllocationInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *Ty = I.getType()->getElementType(); // Type to be allocated // Get the number of elements being allocated by the array... unsigned NumElements = getOperandValue(I.getOperand(0), SF).UIntVal; // Allocate enough memory to hold the type... - // FIXME: Don't use CALLOC, use a tainted malloc. - void *Memory = calloc(NumElements, TD.getTypeSize(Ty)); + void *Memory = malloc(NumElements * TD.getTypeSize(Ty)); - GenericValue Result; - Result.PointerVal = (PointerTy)Memory; + GenericValue Result = PTOGV(Memory); assert(Result.PointerVal != 0 && "Null pointer returned by malloc!"); SetValue(&I, Result, SF); @@ -769,63 +707,51 @@ void Interpreter::executeAllocInst(AllocationInst &I, ExecutionContext &SF) { ECStack.back().Allocas.add(Memory); } -static void executeFreeInst(FreeInst &I, ExecutionContext &SF) { +void Interpreter::visitFreeInst(FreeInst &I) { + ExecutionContext &SF = ECStack.back(); assert(isa(I.getOperand(0)->getType()) && "Freeing nonptr?"); GenericValue Value = getOperandValue(I.getOperand(0), SF); // TODO: Check to make sure memory is allocated - free((void*)Value.PointerVal); // Free memory + free(GVTOP(Value)); // Free memory } - // getElementOffset - The workhorse for getelementptr. // -static GenericValue executeGEPOperation(Value *Ptr, User::op_iterator I, - User::op_iterator E, - ExecutionContext &SF) { +GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, + gep_type_iterator E, + ExecutionContext &SF) { assert(isa(Ptr->getType()) && "Cannot getElementOffset of a nonpointer type!"); PointerTy Total = 0; - const Type *Ty = Ptr->getType(); for (; I != E; ++I) { - if (const StructType *STy = dyn_cast(Ty)) { + if (const StructType *STy = dyn_cast(*I)) { const StructLayout *SLO = TD.getStructLayout(STy); - // Indicies must be ubyte constants... - const ConstantUInt *CPU = cast(*I); - assert(CPU->getType() == Type::UByteTy); + const ConstantUInt *CPU = cast(I.getOperand()); unsigned Index = CPU->getValue(); -#ifdef PROFILE_STRUCTURE_FIELDS - if (ProfileStructureFields) { - // Do accounting for this field... - vector &OfC = FieldAccessCounts[STy]; - if (OfC.size() == 0) OfC.resize(STy->getElementTypes().size()); - OfC[Index]++; - } -#endif - Total += SLO->MemberOffsets[Index]; - Ty = STy->getElementTypes()[Index]; - } else if (const SequentialType *ST = cast(Ty)) { - - // Get the index number for the array... which must be uint type... - assert((*I)->getType() == Type::LongTy); - unsigned Idx = getOperandValue(*I, SF).LongVal; - if (const ArrayType *AT = dyn_cast(ST)) - if (Idx >= AT->getNumElements() && ArrayChecksEnabled) { - cerr << "Out of range memory access to element #" << Idx - << " of a " << AT->getNumElements() << " element array." - << " Subscript #" << *I << "\n"; - // Get outta here!!! - siglongjmp(SignalRecoverBuffer, SIGTRAP); - } - - Ty = ST->getElementType(); - unsigned Size = TD.getTypeSize(Ty); - Total += Size*Idx; - } + } else { + const SequentialType *ST = cast(*I); + // Get the index number for the array... which must be long type... + GenericValue IdxGV = getOperandValue(I.getOperand(), SF); + + uint64_t Idx; + switch (I.getOperand()->getType()->getTypeID()) { + default: assert(0 && "Illegal getelementptr index for sequential type!"); + case Type::SByteTyID: Idx = IdxGV.SByteVal; break; + case Type::ShortTyID: Idx = IdxGV.ShortVal; break; + case Type::IntTyID: Idx = IdxGV.IntVal; break; + case Type::LongTyID: Idx = IdxGV.LongVal; break; + case Type::UByteTyID: Idx = IdxGV.UByteVal; break; + case Type::UShortTyID: Idx = IdxGV.UShortVal; break; + case Type::UIntTyID: Idx = IdxGV.UIntVal; break; + case Type::ULongTyID: Idx = IdxGV.ULongVal; break; + } + Total += TD.getTypeSize(ST->getElementType())*Idx; + } } GenericValue Result; @@ -833,225 +759,113 @@ static GenericValue executeGEPOperation(Value *Ptr, User::op_iterator I, return Result; } -static void executeGEPInst(GetElementPtrInst &I, ExecutionContext &SF) { - SetValue(&I, executeGEPOperation(I.getPointerOperand(), - I.idx_begin(), I.idx_end(), SF), SF); +void Interpreter::visitGetElementPtrInst(GetElementPtrInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, TheEE->executeGEPOperation(I.getPointerOperand(), + gep_type_begin(I), gep_type_end(I), SF), SF); } -static void executeLoadInst(LoadInst &I, ExecutionContext &SF) { +void Interpreter::visitLoadInst(LoadInst &I) { + ExecutionContext &SF = ECStack.back(); GenericValue SRC = getOperandValue(I.getPointerOperand(), SF); - GenericValue *Ptr = (GenericValue*)SRC.PointerVal; - GenericValue Result; - - if (TD.isLittleEndian()) { - switch (I.getType()->getPrimitiveID()) { - case Type::BoolTyID: - case Type::UByteTyID: - case Type::SByteTyID: Result.UByteVal = Ptr->Untyped[0]; break; - case Type::UShortTyID: - case Type::ShortTyID: Result.UShortVal = (unsigned)Ptr->Untyped[0] | - ((unsigned)Ptr->Untyped[1] << 8); - break; - case Type::FloatTyID: - case Type::UIntTyID: - case Type::IntTyID: Result.UIntVal = (unsigned)Ptr->Untyped[0] | - ((unsigned)Ptr->Untyped[1] << 8) | - ((unsigned)Ptr->Untyped[2] << 16) | - ((unsigned)Ptr->Untyped[3] << 24); - break; - case Type::DoubleTyID: - case Type::ULongTyID: - case Type::LongTyID: - case Type::PointerTyID: Result.ULongVal = (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: - cout << "Cannot load value of type " << I.getType() << "!\n"; - } - } else { - switch (I.getType()->getPrimitiveID()) { - case Type::BoolTyID: - case Type::UByteTyID: - case Type::SByteTyID: Result.UByteVal = Ptr->Untyped[0]; break; - case Type::UShortTyID: - case Type::ShortTyID: Result.UShortVal = (unsigned)Ptr->Untyped[1] | - ((unsigned)Ptr->Untyped[0] << 8); - break; - case Type::FloatTyID: - case Type::UIntTyID: - case Type::IntTyID: Result.UIntVal = (unsigned)Ptr->Untyped[3] | - ((unsigned)Ptr->Untyped[2] << 8) | - ((unsigned)Ptr->Untyped[1] << 16) | - ((unsigned)Ptr->Untyped[0] << 24); - break; - case Type::DoubleTyID: - case Type::ULongTyID: - case Type::LongTyID: - case Type::PointerTyID: Result.ULongVal = (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: - cout << "Cannot load value of type " << I.getType() << "!\n"; - } - } - + GenericValue *Ptr = (GenericValue*)GVTOP(SRC); + GenericValue Result = LoadValueFromMemory(Ptr, I.getType()); SetValue(&I, Result, SF); } -static void StoreValueToMemory(GenericValue Val, GenericValue *Ptr, - const Type *Ty) { - if (TD.isLittleEndian()) { - switch (Ty->getPrimitiveID()) { - case Type::BoolTyID: - case Type::UByteTyID: - case Type::SByteTyID: Ptr->Untyped[0] = Val.UByteVal; break; - case Type::UShortTyID: - case Type::ShortTyID: Ptr->Untyped[0] = Val.UShortVal & 255; - Ptr->Untyped[1] = (Val.UShortVal >> 8) & 255; - break; - case Type::FloatTyID: - case Type::UIntTyID: - case Type::IntTyID: Ptr->Untyped[0] = Val.UIntVal & 255; - Ptr->Untyped[1] = (Val.UIntVal >> 8) & 255; - Ptr->Untyped[2] = (Val.UIntVal >> 16) & 255; - Ptr->Untyped[3] = (Val.UIntVal >> 24) & 255; - break; - case Type::DoubleTyID: - case Type::ULongTyID: - case Type::LongTyID: - case Type::PointerTyID: Ptr->Untyped[0] = Val.ULongVal & 255; - Ptr->Untyped[1] = (Val.ULongVal >> 8) & 255; - Ptr->Untyped[2] = (Val.ULongVal >> 16) & 255; - Ptr->Untyped[3] = (Val.ULongVal >> 24) & 255; - Ptr->Untyped[4] = (Val.ULongVal >> 32) & 255; - Ptr->Untyped[5] = (Val.ULongVal >> 40) & 255; - Ptr->Untyped[6] = (Val.ULongVal >> 48) & 255; - Ptr->Untyped[7] = (Val.ULongVal >> 56) & 255; - break; - default: - cout << "Cannot store value of type " << Ty << "!\n"; - } - } else { - switch (Ty->getPrimitiveID()) { - case Type::BoolTyID: - case Type::UByteTyID: - case Type::SByteTyID: Ptr->Untyped[0] = Val.UByteVal; break; - case Type::UShortTyID: - case Type::ShortTyID: Ptr->Untyped[1] = Val.UShortVal & 255; - Ptr->Untyped[0] = (Val.UShortVal >> 8) & 255; - break; - case Type::FloatTyID: - case Type::UIntTyID: - case Type::IntTyID: Ptr->Untyped[3] = Val.UIntVal & 255; - Ptr->Untyped[2] = (Val.UIntVal >> 8) & 255; - Ptr->Untyped[1] = (Val.UIntVal >> 16) & 255; - Ptr->Untyped[0] = (Val.UIntVal >> 24) & 255; - break; - case Type::DoubleTyID: - case Type::ULongTyID: - case Type::LongTyID: - case Type::PointerTyID: Ptr->Untyped[7] = Val.ULongVal & 255; - Ptr->Untyped[6] = (Val.ULongVal >> 8) & 255; - Ptr->Untyped[5] = (Val.ULongVal >> 16) & 255; - Ptr->Untyped[4] = (Val.ULongVal >> 24) & 255; - Ptr->Untyped[3] = (Val.ULongVal >> 32) & 255; - Ptr->Untyped[2] = (Val.ULongVal >> 40) & 255; - Ptr->Untyped[1] = (Val.ULongVal >> 48) & 255; - Ptr->Untyped[0] = (Val.ULongVal >> 56) & 255; - break; - default: - cout << "Cannot store value of type " << Ty << "!\n"; - } - } -} - -static void executeStoreInst(StoreInst &I, ExecutionContext &SF) { +void Interpreter::visitStoreInst(StoreInst &I) { + ExecutionContext &SF = ECStack.back(); GenericValue Val = getOperandValue(I.getOperand(0), SF); GenericValue SRC = getOperandValue(I.getPointerOperand(), SF); - StoreValueToMemory(Val, (GenericValue *)SRC.PointerVal, + StoreValueToMemory(Val, (GenericValue *)GVTOP(SRC), I.getOperand(0)->getType()); } - -GenericValue Interpreter::CreateArgv(const std::vector &InputArgv){ - // Pointers are 64 bits... - PointerTy *Result = new PointerTy[InputArgv.size()+1]; // 64 bit assumption - - for (unsigned i = 0; i < InputArgv.size(); ++i) { - unsigned Size = InputArgv[i].size()+1; - char *Dest = new char[Size]; - copy(InputArgv[i].begin(), InputArgv[i].end(), Dest); - Dest[Size-1] = 0; - - GenericValue GV; GV.PointerVal = (PointerTy)Dest; - // Endian safe: Result[i] = (PointerTy)Dest; - StoreValueToMemory(GV, (GenericValue*)(Result+i), - Type::LongTy); // 64 bit assumption - } - - Result[InputArgv.size()] = 0; - GenericValue GV; GV.PointerVal = (PointerTy)Result; - return GV; -} - - //===----------------------------------------------------------------------===// // Miscellaneous Instruction Implementations //===----------------------------------------------------------------------===// -void Interpreter::executeCallInst(CallInst &I, ExecutionContext &SF) { - ECStack.back().Caller = &I; - vector ArgVals; - ArgVals.reserve(I.getNumOperands()-1); - for (unsigned i = 1; i < I.getNumOperands(); ++i) - ArgVals.push_back(getOperandValue(I.getOperand(i), SF)); - - // To handle indirect calls, we must get the pointer value from the argument - // and treat it as a function pointer. - GenericValue SRC = getOperandValue(I.getCalledValue(), SF); - - callMethod((Function*)SRC.PointerVal, ArgVals); -} - -static void executePHINode(PHINode &I, ExecutionContext &SF) { - BasicBlock *PrevBB = SF.PrevBB; - Value *IncomingValue = 0; +void Interpreter::visitCallSite(CallSite CS) { + ExecutionContext &SF = ECStack.back(); - // Search for the value corresponding to this previous bb... - for (unsigned i = I.getNumIncomingValues(); i > 0;) { - if (I.getIncomingBlock(--i) == PrevBB) { - IncomingValue = I.getIncomingValue(i); + // Check to see if this is an intrinsic function call... + if (Function *F = CS.getCalledFunction()) + if (F->isExternal ()) + switch (F->getIntrinsicID()) { + case Intrinsic::not_intrinsic: break; + case Intrinsic::vastart: { // va_start + GenericValue ArgIndex; + ArgIndex.UIntPairVal.first = ECStack.size() - 1; + ArgIndex.UIntPairVal.second = 0; + SetValue(CS.getInstruction(), ArgIndex, SF); + return; + } + case Intrinsic::vaend: // va_end is a noop for the interpreter + return; + case Intrinsic::vacopy: // va_copy: dest = src + SetValue(CS.getInstruction(), getOperandValue(*CS.arg_begin(), SF), SF); + return; + default: + // 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 *Parent = CS.getInstruction()->getParent(); + IL->LowerIntrinsicCall(cast(CS.getInstruction())); + + // Restore the CurInst pointer to the first instruction newly inserted, if + // any. + if (!Prev) { + SF.CurInst = Parent->begin(); + } else { + SF.CurInst = Prev; + ++SF.CurInst; + } + return; + } + + SF.Caller = CS; + std::vector ArgVals; + const unsigned NumArgs = SF.Caller.arg_size(); + ArgVals.reserve(NumArgs); + for (CallSite::arg_iterator i = SF.Caller.arg_begin(), + e = SF.Caller.arg_end(); i != e; ++i) { + Value *V = *i; + ArgVals.push_back(getOperandValue(V, SF)); + // Promote all integral types whose size is < sizeof(int) into ints. We do + // this by zero or sign extending the value as appropriate according to the + // source type. + const Type *Ty = V->getType(); + if (Ty->isIntegral() && Ty->getPrimitiveSize() < 4) { + if (Ty == Type::ShortTy) + ArgVals.back().IntVal = ArgVals.back().ShortVal; + else if (Ty == Type::UShortTy) + ArgVals.back().UIntVal = ArgVals.back().UShortVal; + else if (Ty == Type::SByteTy) + ArgVals.back().IntVal = ArgVals.back().SByteVal; + else if (Ty == Type::UByteTy) + ArgVals.back().UIntVal = ArgVals.back().UByteVal; + else if (Ty == Type::BoolTy) + ArgVals.back().UIntVal = ArgVals.back().BoolVal; + else + assert(0 && "Unknown type!"); } } - assert(IncomingValue && "No PHI node predecessor for current PrevBB!"); - // Found the value, set as the result... - SetValue(&I, getOperandValue(IncomingValue, SF), SF); + // To handle indirect calls, we must get the pointer value from the argument + // and treat it as a function pointer. + GenericValue SRC = getOperandValue(SF.Caller.getCalledValue(), SF); + callFunction((Function*)GVTOP(SRC), ArgVals); } #define IMPLEMENT_SHIFT(OP, TY) \ case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.UByteVal; break -static void executeShlInst(ShiftInst &I, ExecutionContext &SF) { - const Type *Ty = I.getOperand(0)->getType(); - GenericValue Src1 = getOperandValue(I.getOperand(0), SF); - GenericValue Src2 = getOperandValue(I.getOperand(1), SF); +static GenericValue executeShlInst(GenericValue Src1, GenericValue Src2, + const Type *Ty) { GenericValue Dest; - - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SHIFT(<<, UByte); IMPLEMENT_SHIFT(<<, SByte); IMPLEMENT_SHIFT(<<, UShort); @@ -1060,20 +874,16 @@ static void executeShlInst(ShiftInst &I, ExecutionContext &SF) { IMPLEMENT_SHIFT(<<, Int); IMPLEMENT_SHIFT(<<, ULong); IMPLEMENT_SHIFT(<<, Long); - IMPLEMENT_SHIFT(<<, Pointer); default: - cout << "Unhandled type for Shl instruction: " << Ty << "\n"; + std::cout << "Unhandled type for Shl instruction: " << *Ty << "\n"; } - SetValue(&I, Dest, SF); + return Dest; } -static void executeShrInst(ShiftInst &I, ExecutionContext &SF) { - const Type *Ty = I.getOperand(0)->getType(); - GenericValue Src1 = getOperandValue(I.getOperand(0), SF); - GenericValue Src2 = getOperandValue(I.getOperand(1), SF); +static GenericValue executeShrInst(GenericValue Src1, GenericValue Src2, + const Type *Ty) { GenericValue Dest; - - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SHIFT(>>, UByte); IMPLEMENT_SHIFT(>>, SByte); IMPLEMENT_SHIFT(>>, UShort); @@ -1082,10 +892,30 @@ static void executeShrInst(ShiftInst &I, ExecutionContext &SF) { IMPLEMENT_SHIFT(>>, Int); IMPLEMENT_SHIFT(>>, ULong); IMPLEMENT_SHIFT(>>, Long); - IMPLEMENT_SHIFT(>>, Pointer); default: - cout << "Unhandled type for Shr instruction: " << Ty << "\n"; + std::cout << "Unhandled type for Shr instruction: " << *Ty << "\n"; + abort(); } + return Dest; +} + +void Interpreter::visitShl(ShiftInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *Ty = I.getOperand(0)->getType(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Dest; + Dest = executeShlInst (Src1, Src2, Ty); + SetValue(&I, Dest, SF); +} + +void Interpreter::visitShr(ShiftInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *Ty = I.getOperand(0)->getType(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Dest; + Dest = executeShrInst (Src1, Src2, Ty); SetValue(&I, Dest, SF); } @@ -1094,7 +924,7 @@ static void executeShrInst(ShiftInst &I, ExecutionContext &SF) { #define IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY) \ case Type::DESTTY##TyID: \ - switch (SrcTy->getPrimitiveID()) { \ + switch (SrcTy->getTypeID()) { \ IMPLEMENT_CAST(DESTTY, DESTCTY, Bool); \ IMPLEMENT_CAST(DESTTY, DESTCTY, UByte); \ IMPLEMENT_CAST(DESTTY, DESTCTY, SByte); \ @@ -1111,8 +941,8 @@ static void executeShrInst(ShiftInst &I, ExecutionContext &SF) { IMPLEMENT_CAST(DESTTY, DESTCTY, Double) #define IMPLEMENT_CAST_CASE_END() \ - default: cout << "Unhandled cast: " << SrcTy << " to " << Ty << "\n"; \ - break; \ + default: std::cout << "Unhandled cast: " << *SrcTy << " to " << *Ty << "\n"; \ + abort(); \ } \ break @@ -1121,12 +951,12 @@ static void executeShrInst(ShiftInst &I, ExecutionContext &SF) { IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY); \ IMPLEMENT_CAST_CASE_END() -static GenericValue executeCastOperation(Value *SrcVal, const Type *Ty, - ExecutionContext &SF) { +GenericValue Interpreter::executeCastOperation(Value *SrcVal, const Type *Ty, + ExecutionContext &SF) { const Type *SrcTy = SrcVal->getType(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_CAST_CASE(UByte , (unsigned char)); IMPLEMENT_CAST_CASE(SByte , ( signed char)); IMPLEMENT_CAST_CASE(UShort , (unsigned short)); @@ -1138,367 +968,120 @@ static GenericValue executeCastOperation(Value *SrcVal, const Type *Ty, IMPLEMENT_CAST_CASE(Pointer, (PointerTy)); IMPLEMENT_CAST_CASE(Float , (float)); IMPLEMENT_CAST_CASE(Double , (double)); + IMPLEMENT_CAST_CASE(Bool , (bool)); default: - cout << "Unhandled dest type for cast instruction: " << Ty << "\n"; + std::cout << "Unhandled dest type for cast instruction: " << *Ty << "\n"; + abort(); } return Dest; } - -static void executeCastInst(CastInst &I, ExecutionContext &SF) { +void Interpreter::visitCastInst(CastInst &I) { + ExecutionContext &SF = ECStack.back(); SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF); } +void Interpreter::visitVANextInst(VANextInst &I) { + ExecutionContext &SF = ECStack.back(); -//===----------------------------------------------------------------------===// -// Dispatch and Execution Code -//===----------------------------------------------------------------------===// - -MethodInfo::MethodInfo(Function *F) : Annotation(MethodInfoAID) { - // Assign slot numbers to the function arguments... - for (Function::const_aiterator AI = F->abegin(), E = F->aend(); AI != E; ++AI) - AI->addAnnotation(new SlotNumber(getValueSlot(AI))); - - // Iterate over all of the instructions... - unsigned InstNum = 0; - for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB) - for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE; ++II) - // For each instruction... Add Annote - II->addAnnotation(new InstNumber(++InstNum, getValueSlot(II))); + // Get the incoming valist parameter. LLI treats the valist as a + // (ec-stack-depth var-arg-index) pair. + GenericValue VAList = getOperandValue(I.getOperand(0), SF); + + // Move the pointer to the next vararg. + ++VAList.UIntPairVal.second; + SetValue(&I, VAList, SF); } -unsigned MethodInfo::getValueSlot(const Value *V) { - unsigned Plane = V->getType()->getUniqueID(); - if (Plane >= NumPlaneElements.size()) - NumPlaneElements.resize(Plane+1, 0); - return NumPlaneElements[Plane]++; +#define IMPLEMENT_VAARG(TY) \ + case Type::TY##TyID: Dest.TY##Val = Src.TY##Val; break + +void Interpreter::visitVAArgInst(VAArgInst &I) { + ExecutionContext &SF = ECStack.back(); + + // Get the incoming valist parameter. LLI treats the valist as a + // (ec-stack-depth var-arg-index) pair. + GenericValue VAList = getOperandValue(I.getOperand(0), SF); + GenericValue Dest; + GenericValue Src = ECStack[VAList.UIntPairVal.first] + .VarArgs[VAList.UIntPairVal.second]; + const Type *Ty = I.getType(); + switch (Ty->getTypeID()) { + IMPLEMENT_VAARG(UByte); + IMPLEMENT_VAARG(SByte); + IMPLEMENT_VAARG(UShort); + IMPLEMENT_VAARG(Short); + IMPLEMENT_VAARG(UInt); + IMPLEMENT_VAARG(Int); + IMPLEMENT_VAARG(ULong); + IMPLEMENT_VAARG(Long); + IMPLEMENT_VAARG(Pointer); + IMPLEMENT_VAARG(Float); + IMPLEMENT_VAARG(Double); + IMPLEMENT_VAARG(Bool); + default: + std::cout << "Unhandled dest type for vaarg instruction: " << *Ty << "\n"; + abort(); + } + + // Set the Value of this Instruction. + SetValue(&I, Dest, SF); } +//===----------------------------------------------------------------------===// +// Dispatch and Execution Code +//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// -// callMethod - Execute the specified function... +// callFunction - Execute the specified function... // -void Interpreter::callMethod(Function *M, const vector &ArgVals) { - assert((ECStack.empty() || ECStack.back().Caller == 0 || - ECStack.back().Caller->getNumOperands()-1 == ArgVals.size()) && +void Interpreter::callFunction(Function *F, + const std::vector &ArgVals) { + assert((ECStack.empty() || ECStack.back().Caller.getInstruction() == 0 || + ECStack.back().Caller.arg_size() == ArgVals.size()) && "Incorrect number of arguments passed into function call!"); - if (M->isExternal()) { - GenericValue Result = callExternalMethod(M, ArgVals); - const Type *RetTy = M->getReturnType(); - - // Copy the result back into the result variable if we are not returning - // void. - if (RetTy != Type::VoidTy) { - if (!ECStack.empty() && ECStack.back().Caller) { - ExecutionContext &SF = ECStack.back(); - SetValue(SF.Caller, Result, SF); - - SF.Caller = 0; // We returned from the call... - } else if (!QuietMode) { - // print it. - CW << "Function " << M->getType() << " \"" << M->getName() - << "\" returned "; - print(RetTy, Result); - cout << "\n"; - - if (RetTy->isIntegral()) - ExitCode = Result.IntVal; // Capture the exit code of the program - } - } - + // Make a new stack frame... and fill it in. + ECStack.push_back(ExecutionContext()); + ExecutionContext &StackFrame = ECStack.back(); + StackFrame.CurFunction = F; + + // Special handling for external functions. + if (F->isExternal()) { + GenericValue Result = callExternalFunction (F, ArgVals); + // Simulate a 'ret' instruction of the appropriate type. + popStackAndReturnValueToCaller (F->getReturnType (), Result); return; } - // Process the function, assigning instruction numbers to the instructions in - // the function. Also calculate the number of values for each type slot - // active. - // - MethodInfo *MethInfo = (MethodInfo*)M->getOrCreateAnnotation(MethodInfoAID); - ECStack.push_back(ExecutionContext()); // Make a new stack frame... - - ExecutionContext &StackFrame = ECStack.back(); // Fill it in... - StackFrame.CurMethod = M; - StackFrame.CurBB = M->begin(); + // Get pointers to first LLVM BB & Instruction in function. + StackFrame.CurBB = F->begin(); StackFrame.CurInst = StackFrame.CurBB->begin(); - StackFrame.MethInfo = MethInfo; - - // Initialize the values to nothing... - StackFrame.Values.resize(MethInfo->NumPlaneElements.size()); - for (unsigned i = 0; i < MethInfo->NumPlaneElements.size(); ++i) { - StackFrame.Values[i].resize(MethInfo->NumPlaneElements[i]); - - // Taint the initial values of stuff - memset(&StackFrame.Values[i][0], 42, - MethInfo->NumPlaneElements[i]*sizeof(GenericValue)); - } - - StackFrame.PrevBB = 0; // No previous BB for PHI nodes... - // Run through the function arguments and initialize their values... - assert(ArgVals.size() == M->asize() && + assert((ArgVals.size() == F->asize() || + (ArgVals.size() > F->asize() && F->getFunctionType()->isVarArg())) && "Invalid number of values passed to function invocation!"); + + // Handle non-varargs arguments... unsigned i = 0; - for (Function::aiterator AI = M->abegin(), E = M->aend(); AI != E; ++AI, ++i) + for (Function::aiterator AI = F->abegin(), E = F->aend(); AI != E; ++AI, ++i) SetValue(AI, ArgVals[i], StackFrame); -} - -// executeInstruction - Interpret a single instruction, increment the "PC", and -// return true if the next instruction is a breakpoint... -// -bool Interpreter::executeInstruction() { - assert(!ECStack.empty() && "No program running, cannot execute inst!"); - - ExecutionContext &SF = ECStack.back(); // Current stack frame - Instruction &I = *SF.CurInst++; // Increment before execute - - if (Trace) - CW << "Run:" << I; - - // Track the number of dynamic instructions executed. - ++NumDynamicInsts; - - // Set a sigsetjmp buffer so that we can recover if an error happens during - // instruction execution... - // - if (int SigNo = sigsetjmp(SignalRecoverBuffer, 1)) { - --SF.CurInst; // Back up to erroring instruction - if (SigNo != SIGINT) { - cout << "EXCEPTION OCCURRED [" << strsignal(SigNo) << "]:\n"; - printStackTrace(); - // If -abort-on-exception was specified, terminate LLI instead of trying - // to debug it. - // - if (AbortOnExceptions) exit(1); - } else if (SigNo == SIGINT) { - cout << "CTRL-C Detected, execution halted.\n"; - } - InInstruction = false; - return true; - } - - InInstruction = true; - if (I.isBinaryOp()) { - executeBinaryInst(cast(I), SF); - } else { - switch (I.getOpcode()) { - // Terminators - case Instruction::Ret: executeRetInst (cast(I), SF); break; - case Instruction::Br: executeBrInst (cast(I), SF); break; - // Memory Instructions - case Instruction::Alloca: - case Instruction::Malloc: executeAllocInst((AllocationInst&)I, SF); break; - case Instruction::Free: executeFreeInst (cast (I), SF); break; - case Instruction::Load: executeLoadInst (cast (I), SF); break; - case Instruction::Store: executeStoreInst(cast(I), SF); break; - case Instruction::GetElementPtr: - executeGEPInst(cast(I), SF); break; - - // Miscellaneous Instructions - case Instruction::Call: executeCallInst (cast (I), SF); break; - case Instruction::PHINode: executePHINode (cast (I), SF); break; - case Instruction::Shl: executeShlInst (cast(I), SF); break; - case Instruction::Shr: executeShrInst (cast(I), SF); break; - case Instruction::Cast: executeCastInst (cast (I), SF); break; - default: - cout << "Don't know how to execute this instruction!\n-->" << I; - } - } - InInstruction = false; - - // Reset the current frame location to the top of stack - CurFrame = ECStack.size()-1; - - if (CurFrame == -1) return false; // No breakpoint if no code - - // Return true if there is a breakpoint annotation on the instruction... - return ECStack[CurFrame].CurInst->getAnnotation(BreakpointAID) != 0; -} -void Interpreter::stepInstruction() { // Do the 'step' command - if (ECStack.empty()) { - cout << "Error: no program running, cannot step!\n"; - return; - } - - // Run an instruction... - executeInstruction(); - - // Print the next instruction to execute... - printCurrentInstruction(); -} - -// --- UI Stuff... -void Interpreter::nextInstruction() { // Do the 'next' command - if (ECStack.empty()) { - cout << "Error: no program running, cannot 'next'!\n"; - return; - } - - // If this is a call instruction, step over the call instruction... - // TODO: ICALL, CALL WITH, ... - if (ECStack.back().CurInst->getOpcode() == Instruction::Call) { - unsigned StackSize = ECStack.size(); - // Step into the function... - if (executeInstruction()) { - // Hit a breakpoint, print current instruction, then return to user... - cout << "Breakpoint hit!\n"; - printCurrentInstruction(); - return; - } - - // If we we able to step into the function, finish it now. We might not be - // able the step into a function, if it's external for example. - if (ECStack.size() != StackSize) - finish(); // Finish executing the function... - else - printCurrentInstruction(); - - } else { - // Normal instruction, just step... - stepInstruction(); - } + // Handle varargs arguments... + StackFrame.VarArgs.assign(ArgVals.begin()+i, ArgVals.end()); } void Interpreter::run() { - if (ECStack.empty()) { - cout << "Error: no program running, cannot run!\n"; - return; - } - - bool HitBreakpoint = false; - while (!ECStack.empty() && !HitBreakpoint) { - // Run an instruction... - HitBreakpoint = executeInstruction(); - } - - if (HitBreakpoint) { - cout << "Breakpoint hit!\n"; - } - // Print the next instruction to execute... - printCurrentInstruction(); -} - -void Interpreter::finish() { - if (ECStack.empty()) { - cout << "Error: no program running, cannot run!\n"; - return; - } - - unsigned StackSize = ECStack.size(); - bool HitBreakpoint = false; - while (ECStack.size() >= StackSize && !HitBreakpoint) { - // Run an instruction... - HitBreakpoint = executeInstruction(); - } - - if (HitBreakpoint) { - cout << "Breakpoint hit!\n"; - } - - // Print the next instruction to execute... - printCurrentInstruction(); -} - - - -// printCurrentInstruction - Print out the instruction that the virtual PC is -// at, or fail silently if no program is running. -// -void Interpreter::printCurrentInstruction() { - if (!ECStack.empty()) { - if (ECStack.back().CurBB->begin() == ECStack.back().CurInst) // print label - WriteAsOperand(cout, ECStack.back().CurBB) << ":\n"; - - Instruction &I = *ECStack.back().CurInst; - InstNumber *IN = (InstNumber*)I.getAnnotation(SlotNumberAID); - assert(IN && "Instruction has no numbering annotation!"); - cout << "#" << IN->InstNum << I; - } -} - -void Interpreter::printValue(const Type *Ty, GenericValue V) { - switch (Ty->getPrimitiveID()) { - case Type::BoolTyID: cout << (V.BoolVal?"true":"false"); break; - case Type::SByteTyID: - cout << (int)V.SByteVal << " '" << V.SByteVal << "'"; break; - case Type::UByteTyID: - cout << (unsigned)V.UByteVal << " '" << V.UByteVal << "'"; break; - case Type::ShortTyID: cout << V.ShortVal; break; - case Type::UShortTyID: cout << V.UShortVal; break; - case Type::IntTyID: cout << V.IntVal; break; - case Type::UIntTyID: cout << V.UIntVal; break; - case Type::LongTyID: cout << (long)V.LongVal; break; - case Type::ULongTyID: cout << (unsigned long)V.ULongVal; break; - case Type::FloatTyID: cout << V.FloatVal; break; - case Type::DoubleTyID: cout << V.DoubleVal; break; - case Type::PointerTyID:cout << (void*)V.PointerVal; break; - default: - cout << "- Don't know how to print value of this type!"; - break; - } -} - -void Interpreter::print(const Type *Ty, GenericValue V) { - CW << Ty << " "; - printValue(Ty, V); -} - -void Interpreter::print(const std::string &Name) { - Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name)); - if (!PickedVal) return; - - if (const Function *F = dyn_cast(PickedVal)) { - CW << F; // Print the function - } else if (const Type *Ty = dyn_cast(PickedVal)) { - CW << "type %" << Name << " = " << Ty->getDescription() << "\n"; - } else if (const BasicBlock *BB = dyn_cast(PickedVal)) { - CW << BB; // Print the basic block - } else { // Otherwise there should be an annotation for the slot# - print(PickedVal->getType(), - getOperandValue(PickedVal, ECStack[CurFrame])); - cout << "\n"; - } -} - -void Interpreter::infoValue(const std::string &Name) { - Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name)); - if (!PickedVal) return; - - cout << "Value: "; - print(PickedVal->getType(), - getOperandValue(PickedVal, ECStack[CurFrame])); - cout << "\n"; - printOperandInfo(PickedVal, ECStack[CurFrame]); -} - -// printStackFrame - Print information about the specified stack frame, or -1 -// for the default one. -// -void Interpreter::printStackFrame(int FrameNo) { - if (FrameNo == -1) FrameNo = CurFrame; - Function *F = ECStack[FrameNo].CurMethod; - const Type *RetTy = F->getReturnType(); - - CW << ((FrameNo == CurFrame) ? '>' : '-') << "#" << FrameNo << ". " - << (Value*)RetTy << " \"" << F->getName() << "\"("; - - unsigned i = 0; - for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I, ++i) { - if (i != 0) cout << ", "; - CW << *I << "="; + while (!ECStack.empty()) { + // Interpret a single instruction & increment the "PC". + ExecutionContext &SF = ECStack.back(); // Current stack frame + Instruction &I = *SF.CurInst++; // Increment before execute - printValue(I->getType(), getOperandValue(I, ECStack[FrameNo])); - } - - cout << ")\n"; + // Track the number of dynamic instructions executed. + ++NumDynamicInsts; - if (FrameNo != int(ECStack.size()-1)) { - BasicBlock::iterator I = ECStack[FrameNo].CurInst; - CW << --I; - } else { - CW << *ECStack[FrameNo].CurInst; + DEBUG(std::cerr << "About to interpret: " << I); + visit(I); // Dispatch to one of the visit* methods... } } -