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=26ef06bc982a01bd87935c8744b00d32eee6f896;hb=551ccae044b0ff658fe629dd67edd5ffe75d10e8;hpb=77113b627237fe2850676cccd809de1e05f03952 diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 26ef06bc982..5e1ae0629f8 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -1,74 +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/Module.h" -#include "llvm/Instructions.h" -#include "llvm/DerivedTypes.h" #include "llvm/Constants.h" -#include "llvm/Assembly/Writer.h" -#include "Support/CommandLine.h" -#include "Support/Statistic.h" -#include // For fmod -#include -#include - -Interpreter *TheEE = 0; +#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"); - cl::opt - QuietMode("quiet", cl::desc("Do not emit any non-program output"), - cl::init(true)); - - cl::alias - QuietModeA("q", cl::desc("Alias for -quiet"), cl::aliasopt(QuietMode)); - - cl::opt - ArrayChecksEnabled("array-checks", cl::desc("Enable array bound checks")); - - 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 -// -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; } @@ -76,90 +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; -} - -// Operations used by constant expr implementations... -static GenericValue executeCastOperation(Value *Src, const Type *DestTy, - ExecutionContext &SF); 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 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: + std::cerr << "Unhandled ConstantExpr: " << *CE << "\n"; + abort(); + return GenericValue(); + } +} - -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 TheEE->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()); - default: - std::cerr << "Unhandled ConstantExpr: " << CE << "\n"; - abort(); - return GenericValue(); - } + return getConstantExprValue(CE, SF); } else if (Constant *CPV = dyn_cast(V)) { - return TheEE->getConstantValue(CPV); + return getConstantValue(CPV); } else if (GlobalValue *GV = dyn_cast(V)) { - return PTOGV(TheEE->getPointerToGlobal(GV)); + 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)) { - std::cout << "Constant Pool Value\n"; - } else if (isa(V)) { - std::cout << "Global Value\n"; - } else { - unsigned TyP = V->getType()->getUniqueID(); // TypePlane for value - unsigned Slot = getOperandSlot(V); - std::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]; - std::cout << ( Cur >= 160?char((Cur>>4)+'A'-10):char((Cur>>4) + '0')) - << ((Cur&15) >= 10?char((Cur&15)+'A'-10):char((Cur&15) + '0')); - } - std::cout << "\n"; - } -} - - - static void SetValue(Value *V, GenericValue Val, ExecutionContext &SF) { - unsigned TyP = V->getType()->getUniqueID(); // TypePlane for value - - //std::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() { TheEE = this; - AnnotationManager::registerAnnotationFactory(FunctionInfoAID, - &FunctionInfo::Create); - initializeSignalHandlers(); } //===----------------------------------------------------------------------===// @@ -172,7 +182,7 @@ void Interpreter::initializeExecutionEngine() { static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(+, UByte); IMPLEMENT_BINARY_OPERATOR(+, SByte); IMPLEMENT_BINARY_OPERATOR(+, UShort); @@ -193,7 +203,7 @@ static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(-, UByte); IMPLEMENT_BINARY_OPERATOR(-, SByte); IMPLEMENT_BINARY_OPERATOR(-, UShort); @@ -214,7 +224,7 @@ static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2, static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(*, UByte); IMPLEMENT_BINARY_OPERATOR(*, SByte); IMPLEMENT_BINARY_OPERATOR(*, UShort); @@ -226,7 +236,7 @@ static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_BINARY_OPERATOR(*, Float); IMPLEMENT_BINARY_OPERATOR(*, Double); default: - std::cout << "Unhandled type for Mul instruction: " << Ty << "\n"; + std::cout << "Unhandled type for Mul instruction: " << *Ty << "\n"; abort(); } return Dest; @@ -235,7 +245,7 @@ static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2, static GenericValue executeDivInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(/, UByte); IMPLEMENT_BINARY_OPERATOR(/, SByte); IMPLEMENT_BINARY_OPERATOR(/, UShort); @@ -256,7 +266,7 @@ static GenericValue executeDivInst(GenericValue Src1, GenericValue Src2, static GenericValue executeRemInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(%, UByte); IMPLEMENT_BINARY_OPERATOR(%, SByte); IMPLEMENT_BINARY_OPERATOR(%, UShort); @@ -281,7 +291,7 @@ static GenericValue executeRemInst(GenericValue Src1, GenericValue Src2, static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(&, Bool); IMPLEMENT_BINARY_OPERATOR(&, UByte); IMPLEMENT_BINARY_OPERATOR(&, SByte); @@ -298,11 +308,10 @@ static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2, return Dest; } - static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(|, Bool); IMPLEMENT_BINARY_OPERATOR(|, UByte); IMPLEMENT_BINARY_OPERATOR(|, SByte); @@ -319,11 +328,10 @@ static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2, return Dest; } - static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(^, Bool); IMPLEMENT_BINARY_OPERATOR(^, UByte); IMPLEMENT_BINARY_OPERATOR(^, SByte); @@ -340,7 +348,6 @@ static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2, return Dest; } - #define IMPLEMENT_SETCC(OP, TY) \ case Type::TY##TyID: Dest.BoolVal = Src1.TY##Val OP Src2.TY##Val; break @@ -356,7 +363,7 @@ static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2, static GenericValue executeSetEQInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(==, UByte); IMPLEMENT_SETCC(==, SByte); IMPLEMENT_SETCC(==, UShort); @@ -378,7 +385,7 @@ static GenericValue executeSetEQInst(GenericValue Src1, GenericValue Src2, static GenericValue executeSetNEInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(!=, UByte); IMPLEMENT_SETCC(!=, SByte); IMPLEMENT_SETCC(!=, UShort); @@ -401,7 +408,7 @@ static GenericValue executeSetNEInst(GenericValue Src1, GenericValue Src2, static GenericValue executeSetLEInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(<=, UByte); IMPLEMENT_SETCC(<=, SByte); IMPLEMENT_SETCC(<=, UShort); @@ -414,7 +421,7 @@ static GenericValue executeSetLEInst(GenericValue Src1, GenericValue Src2, IMPLEMENT_SETCC(<=, Double); IMPLEMENT_POINTERSETCC(<=); default: - std::cout << "Unhandled type for SetLE instruction: " << Ty << "\n"; + std::cout << "Unhandled type for SetLE instruction: " << *Ty << "\n"; abort(); } return Dest; @@ -423,7 +430,7 @@ static GenericValue executeSetLEInst(GenericValue Src1, GenericValue Src2, static GenericValue executeSetGEInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(>=, UByte); IMPLEMENT_SETCC(>=, SByte); IMPLEMENT_SETCC(>=, UShort); @@ -445,7 +452,7 @@ static GenericValue executeSetGEInst(GenericValue Src1, GenericValue Src2, static GenericValue executeSetLTInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(<, UByte); IMPLEMENT_SETCC(<, SByte); IMPLEMENT_SETCC(<, UShort); @@ -467,7 +474,7 @@ static GenericValue executeSetLTInst(GenericValue Src1, GenericValue Src2, static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2, const Type *Ty) { GenericValue Dest; - switch (Ty->getPrimitiveID()) { + switch (Ty->getTypeID()) { IMPLEMENT_SETCC(>, UByte); IMPLEMENT_SETCC(>, SByte); IMPLEMENT_SETCC(>, UShort); @@ -486,7 +493,8 @@ static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2, 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); @@ -515,70 +523,70 @@ static void executeBinaryInst(BinaryOperator &I, ExecutionContext &SF) { 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) { - std::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"; - std::cout.precision(3); - for (I = FieldAccessCounts.begin(); I != E; ++I) { - std::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) { - std::cout << "Program returned "; - print(Type::IntTy, GV); - std::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') @@ -587,51 +595,29 @@ void Interpreter::executeRetInst(ReturnInst &I, ExecutionContext &SF) { Result = getOperandValue(I.getReturnValue(), SF); } - // Save previously executing meth - const Function *M = ECStack.back().CurFunction; - - // 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); - std::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); - std::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) { +void Interpreter::visitBranchInst(BranchInst &I) { + ExecutionContext &SF = ECStack.back(); BasicBlock *Dest; Dest = I.getSuccessor(0); // Uncond branches have a fixed dest... @@ -643,7 +629,8 @@ void Interpreter::executeBrInst(BranchInst &I, ExecutionContext &SF) { SwitchToNewBasicBlock(Dest, SF); } -void Interpreter::executeSwitchInst(SwitchInst &I, ExecutionContext &SF) { +void Interpreter::visitSwitchInst(SwitchInst &I) { + ExecutionContext &SF = ECStack.back(); GenericValue CondVal = getOperandValue(I.getOperand(0), SF); const Type *ElTy = I.getOperand(0)->getType(); @@ -697,20 +684,20 @@ void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){ 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 = PTOGV(Memory); assert(Result.PointerVal != 0 && "Null pointer returned by malloc!"); @@ -720,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(GVTOP(Value)); // Free memory } - // getElementOffset - The workhorse for getelementptr. // -GenericValue Interpreter::executeGEPOperation(Value *Ptr, User::op_iterator I, - User::op_iterator E, +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... - std::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)) { - + } else { + const SequentialType *ST = cast(*I); // Get the index number for the array... which must be long type... - assert((*I)->getType() == Type::LongTy); - unsigned Idx = getOperandValue(*I, SF).LongVal; - if (const ArrayType *AT = dyn_cast(ST)) - if (Idx >= AT->getNumElements() && ArrayChecksEnabled) { - std::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; - } + 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; @@ -784,43 +759,85 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, User::op_iterator I, return Result; } -static void executeGEPInst(GetElementPtrInst &I, ExecutionContext &SF) { +void Interpreter::visitGetElementPtrInst(GetElementPtrInst &I) { + ExecutionContext &SF = ECStack.back(); SetValue(&I, TheEE->executeGEPOperation(I.getPointerOperand(), - I.idx_begin(), I.idx_end(), SF), SF); + gep_type_begin(I), gep_type_end(I), SF), SF); } -void Interpreter::executeLoadInst(LoadInst &I, ExecutionContext &SF) { +void Interpreter::visitLoadInst(LoadInst &I) { + ExecutionContext &SF = ECStack.back(); GenericValue SRC = getOperandValue(I.getPointerOperand(), SF); GenericValue *Ptr = (GenericValue*)GVTOP(SRC); GenericValue Result = LoadValueFromMemory(Ptr, I.getType()); SetValue(&I, Result, SF); } -void Interpreter::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 *)GVTOP(SRC), I.getOperand(0)->getType()); } - - //===----------------------------------------------------------------------===// // Miscellaneous Instruction Implementations //===----------------------------------------------------------------------===// -void Interpreter::executeCallInst(CallInst &I, ExecutionContext &SF) { - ECStack.back().Caller = &I; +void Interpreter::visitCallSite(CallSite CS) { + ExecutionContext &SF = ECStack.back(); + + // 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; - ArgVals.reserve(I.getNumOperands()-1); - for (unsigned i = 1; i < I.getNumOperands(); ++i) { - ArgVals.push_back(getOperandValue(I.getOperand(i), SF)); + 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. - if (I.getOperand(i)->getType()->isIntegral() && - I.getOperand(i)->getType()->getPrimitiveSize() < 4) { - const Type *Ty = I.getOperand(i)->getType(); + 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) @@ -838,21 +855,17 @@ void Interpreter::executeCallInst(CallInst &I, ExecutionContext &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); - + 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); @@ -864,16 +877,13 @@ static void executeShlInst(ShiftInst &I, ExecutionContext &SF) { default: 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); @@ -886,6 +896,26 @@ static void executeShrInst(ShiftInst &I, ExecutionContext &SF) { 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); } @@ -894,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); \ @@ -911,7 +941,7 @@ static void executeShrInst(ShiftInst &I, ExecutionContext &SF) { IMPLEMENT_CAST(DESTTY, DESTCTY, Double) #define IMPLEMENT_CAST_CASE_END() \ - default: std::cout << "Unhandled cast: " << SrcTy << " to " << Ty << "\n"; \ + default: std::cout << "Unhandled cast: " << *SrcTy << " to " << *Ty << "\n"; \ abort(); \ } \ break @@ -921,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)); @@ -947,116 +977,86 @@ static GenericValue executeCastOperation(Value *SrcVal, const Type *Ty, 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); } -static void executeVarArgInst(VarArgInst &I, ExecutionContext &SF) { - // Get the pointer to the valist element. LLI treats the valist in memory as - // an integer. - GenericValue VAListPtr = getOperandValue(I.getOperand(0), SF); +void Interpreter::visitVANextInst(VANextInst &I) { + ExecutionContext &SF = ECStack.back(); - // Load the pointer - GenericValue VAList = - TheEE->LoadValueFromMemory((GenericValue *)GVTOP(VAListPtr), Type::UIntTy); + // 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 Argument = VAList.IntVal++; +#define IMPLEMENT_VAARG(TY) \ + case Type::TY##TyID: Dest.TY##Val = Src.TY##Val; break - // Update the valist to point to the next argument... - TheEE->StoreValueToMemory(VAList, (GenericValue *)GVTOP(VAListPtr), - Type::UIntTy); +void Interpreter::visitVAArgInst(VAArgInst &I) { + ExecutionContext &SF = ECStack.back(); - // Set the value... - assert(Argument < SF.VarArgs.size() && - "Accessing past the last vararg argument!"); - SetValue(&I, SF.VarArgs[Argument], SF); + // 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 //===----------------------------------------------------------------------===// -FunctionInfo::FunctionInfo(Function *F) : Annotation(FunctionInfoAID) { - // 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))); -} - -unsigned FunctionInfo::getValueSlot(const Value *V) { - unsigned Plane = V->getType()->getUniqueID(); - if (Plane >= NumPlaneElements.size()) - NumPlaneElements.resize(Plane+1, 0); - return NumPlaneElements[Plane]++; -} - - //===----------------------------------------------------------------------===// // callFunction - Execute the specified function... // void Interpreter::callFunction(Function *F, const std::vector &ArgVals) { - assert((ECStack.empty() || ECStack.back().Caller == 0 || - ECStack.back().Caller->getNumOperands()-1 == ArgVals.size()) && + assert((ECStack.empty() || ECStack.back().Caller.getInstruction() == 0 || + ECStack.back().Caller.arg_size() == ArgVals.size()) && "Incorrect number of arguments passed into function call!"); - if (F->isExternal()) { - GenericValue Result = callExternalFunction(F, ArgVals); - const Type *RetTy = F->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 " << F->getType() << " \"" << F->getName() - << "\" returned "; - print(RetTy, Result); - std::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. - // - FunctionInfo *FuncInfo = - (FunctionInfo*)F->getOrCreateAnnotation(FunctionInfoAID); - ECStack.push_back(ExecutionContext()); // Make a new stack frame... - - ExecutionContext &StackFrame = ECStack.back(); // Fill it in... - StackFrame.CurFunction = F; + // Get pointers to first LLVM BB & Instruction in function. StackFrame.CurBB = F->begin(); StackFrame.CurInst = StackFrame.CurBB->begin(); - StackFrame.FuncInfo = FuncInfo; - - // Initialize the values to nothing... - StackFrame.Values.resize(FuncInfo->NumPlaneElements.size()); - for (unsigned i = 0; i < FuncInfo->NumPlaneElements.size(); ++i) { - StackFrame.Values[i].resize(FuncInfo->NumPlaneElements[i]); - - // Taint the initial values of stuff - memset(&StackFrame.Values[i][0], 42, - FuncInfo->NumPlaneElements[i]*sizeof(GenericValue)); - } - // Run through the function arguments and initialize their values... assert((ArgVals.size() == F->asize() || @@ -1072,265 +1072,16 @@ void Interpreter::callFunction(Function *F, StackFrame.VarArgs.assign(ArgVals.begin()+i, ArgVals.end()); } -// 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) { - std::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) { - std::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; - case Instruction::Switch: executeSwitchInst(cast(I), SF);break; - // Invoke not handled! - - // 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: assert(0 && "PHI nodes already handled!"); - case Instruction::Cast: executeCastInst (cast (I), SF); break; - case Instruction::Shl: executeShlInst (cast(I), SF); break; - case Instruction::Shr: executeShrInst (cast(I), SF); break; - case Instruction::VarArg: executeVarArgInst(cast(I),SF); break; - default: - std::cout << "Don't know how to execute this instruction!\n-->" << I; - abort(); - } - } - 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()) { - std::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()) { - std::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... - std::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(); - } -} - void Interpreter::run() { - if (ECStack.empty()) { - std::cout << "Error: no program running, cannot run!\n"; - return; - } - - bool HitBreakpoint = false; - while (!ECStack.empty() && !HitBreakpoint) { - // Run an instruction... - HitBreakpoint = executeInstruction(); - } - - if (HitBreakpoint) - std::cout << "Breakpoint hit!\n"; - - // Print the next instruction to execute... - printCurrentInstruction(); -} - -void Interpreter::finish() { - if (ECStack.empty()) { - std::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) - std::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(std::cout, ECStack.back().CurBB) << ":\n"; - - Instruction &I = *ECStack.back().CurInst; - InstNumber *IN = (InstNumber*)I.getAnnotation(SlotNumberAID); - assert(IN && "Instruction has no numbering annotation!"); - std::cout << "#" << IN->InstNum << I; - } -} - -void Interpreter::printValue(const Type *Ty, GenericValue V) { - switch (Ty->getPrimitiveID()) { - case Type::BoolTyID: std::cout << (V.BoolVal?"true":"false"); break; - case Type::SByteTyID: - std::cout << (int)V.SByteVal << " '" << V.SByteVal << "'"; break; - case Type::UByteTyID: - std::cout << (unsigned)V.UByteVal << " '" << V.UByteVal << "'"; break; - case Type::ShortTyID: std::cout << V.ShortVal; break; - case Type::UShortTyID: std::cout << V.UShortVal; break; - case Type::IntTyID: std::cout << V.IntVal; break; - case Type::UIntTyID: std::cout << V.UIntVal; break; - case Type::LongTyID: std::cout << (long)V.LongVal; break; - case Type::ULongTyID: std::cout << (unsigned long)V.ULongVal; break; - case Type::FloatTyID: std::cout << V.FloatVal; break; - case Type::DoubleTyID: std::cout << V.DoubleVal; break; - case Type::PointerTyID:std::cout << (void*)GVTOP(V); break; - default: - std::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])); - std::cout << "\n"; - } -} - -void Interpreter::infoValue(const std::string &Name) { - Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name)); - if (!PickedVal) return; - - std::cout << "Value: "; - print(PickedVal->getType(), - getOperandValue(PickedVal, ECStack[CurFrame])); - std::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].CurFunction; - 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) std::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])); - } - - std::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... } } -