Interpreter.h revision 0b12b5f50ec77a8bd01b92d287c52d748619bb4b
1//===-- Interpreter.h ------------------------------------------*- C++ -*--===// 2// 3// This header file defines the interpreter structure 4// 5//===----------------------------------------------------------------------===// 6 7#ifndef LLI_INTERPRETER_H 8#define LLI_INTERPRETER_H 9 10// Uncomment this line to enable profiling of structure field accesses. 11#define PROFILE_STRUCTURE_FIELDS 1 12 13 14#include "llvm/Module.h" 15#include "llvm/Function.h" 16#include "llvm/BasicBlock.h" 17#include "Support/DataTypes.h" 18#include "llvm/Assembly/CachedWriter.h" 19 20extern CachedWriter CW; // Object to accellerate printing of LLVM 21 22struct MethodInfo; // Defined in ExecutionAnnotations.h 23class CallInst; 24class ReturnInst; 25class BranchInst; 26class AllocationInst; 27 28typedef uint64_t PointerTy; 29 30union GenericValue { 31 bool BoolVal; 32 unsigned char UByteVal; 33 signed char SByteVal; 34 unsigned short UShortVal; 35 signed short ShortVal; 36 unsigned int UIntVal; 37 signed int IntVal; 38 uint64_t ULongVal; 39 int64_t LongVal; 40 double DoubleVal; 41 float FloatVal; 42 PointerTy PointerVal; 43}; 44 45// AllocaHolder - Object to track all of the blocks of memory allocated by 46// alloca. When the function returns, this object is poped off the execution 47// stack, which causes the dtor to be run, which frees all the alloca'd memory. 48// 49class AllocaHolder { 50 friend class AllocaHolderHandle; 51 std::vector<void*> Allocations; 52 unsigned RefCnt; 53public: 54 AllocaHolder() : RefCnt(0) {} 55 void add(void *mem) { Allocations.push_back(mem); } 56 ~AllocaHolder() { 57 for (unsigned i = 0; i < Allocations.size(); ++i) 58 free(Allocations[i]); 59 } 60}; 61 62// AllocaHolderHandle gives AllocaHolder value semantics so we can stick it into 63// a vector... 64// 65class AllocaHolderHandle { 66 AllocaHolder *H; 67public: 68 AllocaHolderHandle() : H(new AllocaHolder()) { H->RefCnt++; } 69 AllocaHolderHandle(const AllocaHolderHandle &AH) : H(AH.H) { H->RefCnt++; } 70 ~AllocaHolderHandle() { if (--H->RefCnt == 0) delete H; } 71 72 void add(void *mem) { H->add(mem); } 73}; 74 75typedef std::vector<GenericValue> ValuePlaneTy; 76 77// ExecutionContext struct - This struct represents one stack frame currently 78// executing. 79// 80struct ExecutionContext { 81 Function *CurMethod; // The currently executing function 82 BasicBlock *CurBB; // The currently executing BB 83 BasicBlock::iterator CurInst; // The next instruction to execute 84 MethodInfo *MethInfo; // The MethInfo annotation for the function 85 std::vector<ValuePlaneTy> Values;// ValuePlanes for each type 86 87 BasicBlock *PrevBB; // The previous BB or null if in first BB 88 CallInst *Caller; // Holds the call that called subframes. 89 // NULL if main func or debugger invoked fn 90 AllocaHolderHandle Allocas; // Track memory allocated by alloca 91}; 92 93// Interpreter - This class represents the entirety of the interpreter. 94// 95class Interpreter { 96 Module *CurMod; // The current Module being executed (0 if none) 97 int ExitCode; // The exit code to be returned by the lli util 98 bool Profile; // Profiling enabled? 99 bool Trace; // Tracing enabled? 100 int CurFrame; // The current stack frame being inspected 101 102 // The runtime stack of executing code. The top of the stack is the current 103 // function record. 104 std::vector<ExecutionContext> ECStack; 105 106public: 107 Interpreter(); 108 inline ~Interpreter() { CW.setModule(0); delete CurMod; } 109 110 // getExitCode - return the code that should be the exit code for the lli 111 // utility. 112 inline int getExitCode() const { return ExitCode; } 113 114 // enableProfiling() - Turn profiling on, clear stats? 115 void enableProfiling() { Profile = true; } 116 void enableTracing() { Trace = true; } 117 118 void handleUserInput(); 119 120 // User Interation Methods... 121 void loadModule(const std::string &Filename); 122 bool flushModule(); 123 bool callMethod(const std::string &Name); // return true on failure 124 void setBreakpoint(const std::string &Name); 125 void infoValue(const std::string &Name); 126 void print(const std::string &Name); 127 static void print(const Type *Ty, GenericValue V); 128 static void printValue(const Type *Ty, GenericValue V); 129 130 // Hack until we can parse command line args... 131 bool callMainMethod(const std::string &MainName, 132 const std::vector<std::string> &InputFilename); 133 134 void list(); // Do the 'list' command 135 void printStackTrace(); // Do the 'backtrace' command 136 137 // Code execution methods... 138 void callMethod(Function *F, const std::vector<GenericValue> &ArgVals); 139 bool executeInstruction(); // Execute one instruction... 140 141 void stepInstruction(); // Do the 'step' command 142 void nextInstruction(); // Do the 'next' command 143 void run(); // Do the 'run' command 144 void finish(); // Do the 'finish' command 145 146 // Opcode Implementations 147 void executeCallInst(CallInst &I, ExecutionContext &SF); 148 void executeRetInst(ReturnInst &I, ExecutionContext &SF); 149 void executeBrInst(BranchInst &I, ExecutionContext &SF); 150 void executeAllocInst(AllocationInst &I, ExecutionContext &SF); 151 GenericValue callExternalMethod(Function *F, 152 const std::vector<GenericValue> &ArgVals); 153 void exitCalled(GenericValue GV); 154 155 // getCurrentMethod - Return the currently executing method 156 inline Function *getCurrentMethod() const { 157 return CurFrame < 0 ? 0 : ECStack[CurFrame].CurMethod; 158 } 159 160 // isStopped - Return true if a program is stopped. Return false if no 161 // program is running. 162 // 163 inline bool isStopped() const { return !ECStack.empty(); } 164 165private: // Helper functions 166 // getCurrentExecutablePath() - Return the directory that the lli executable 167 // lives in. 168 // 169 std::string getCurrentExecutablePath() const; 170 171 // printCurrentInstruction - Print out the instruction that the virtual PC is 172 // at, or fail silently if no program is running. 173 // 174 void printCurrentInstruction(); 175 176 // printStackFrame - Print information about the specified stack frame, or -1 177 // for the default one. 178 // 179 void printStackFrame(int FrameNo = -1); 180 181 // LookupMatchingNames - Search the current function namespace, then the 182 // global namespace looking for values that match the specified name. Return 183 // ALL matches to that name. This is obviously slow, and should only be used 184 // for user interaction. 185 // 186 std::vector<Value*> LookupMatchingNames(const std::string &Name); 187 188 // ChooseOneOption - Prompt the user to choose among the specified options to 189 // pick one value. If no options are provided, emit an error. If a single 190 // option is provided, just return that option. 191 // 192 Value *ChooseOneOption(const std::string &Name, 193 const std::vector<Value*> &Opts); 194 195 196 void initializeExecutionEngine(); 197 void initializeExternalMethods(); 198}; 199 200#endif 201