|  | //===-- Interpreter.h ------------------------------------------*- C++ -*--===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This header file defines the interpreter structure | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLI_INTERPRETER_H | 
|  | #define LLI_INTERPRETER_H | 
|  |  | 
|  | #include "llvm/Function.h" | 
|  | #include "llvm/ExecutionEngine/ExecutionEngine.h" | 
|  | #include "llvm/ExecutionEngine/GenericValue.h" | 
|  | #include "llvm/Support/InstVisitor.h" | 
|  | #include "llvm/Support/CallSite.h" | 
|  | #include "llvm/Target/TargetData.h" | 
|  | #include "llvm/Support/DataTypes.h" | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | class IntrinsicLowering; | 
|  | struct FunctionInfo; | 
|  | template<typename T> class generic_gep_type_iterator; | 
|  | class ConstantExpr; | 
|  | typedef generic_gep_type_iterator<User::const_op_iterator> gep_type_iterator; | 
|  |  | 
|  |  | 
|  | // AllocaHolder - Object to track all of the blocks of memory allocated by | 
|  | // alloca.  When the function returns, this object is popped off the execution | 
|  | // stack, which causes the dtor to be run, which frees all the alloca'd memory. | 
|  | // | 
|  | class AllocaHolder { | 
|  | friend class AllocaHolderHandle; | 
|  | std::vector<void*> Allocations; | 
|  | unsigned RefCnt; | 
|  | public: | 
|  | AllocaHolder() : RefCnt(0) {} | 
|  | void add(void *mem) { Allocations.push_back(mem); } | 
|  | ~AllocaHolder() { | 
|  | for (unsigned i = 0; i < Allocations.size(); ++i) | 
|  | free(Allocations[i]); | 
|  | } | 
|  | }; | 
|  |  | 
|  | // AllocaHolderHandle gives AllocaHolder value semantics so we can stick it into | 
|  | // a vector... | 
|  | // | 
|  | class AllocaHolderHandle { | 
|  | AllocaHolder *H; | 
|  | public: | 
|  | AllocaHolderHandle() : H(new AllocaHolder()) { H->RefCnt++; } | 
|  | AllocaHolderHandle(const AllocaHolderHandle &AH) : H(AH.H) { H->RefCnt++; } | 
|  | ~AllocaHolderHandle() { if (--H->RefCnt == 0) delete H; } | 
|  |  | 
|  | void add(void *mem) { H->add(mem); } | 
|  | }; | 
|  |  | 
|  | typedef std::vector<GenericValue> ValuePlaneTy; | 
|  |  | 
|  | // ExecutionContext struct - This struct represents one stack frame currently | 
|  | // executing. | 
|  | // | 
|  | struct ExecutionContext { | 
|  | Function             *CurFunction;// The currently executing function | 
|  | BasicBlock           *CurBB;      // The currently executing BB | 
|  | BasicBlock::iterator  CurInst;    // The next instruction to execute | 
|  | std::map<Value *, GenericValue> Values; // LLVM values used in this invocation | 
|  | std::vector<GenericValue>  VarArgs; // Values passed through an ellipsis | 
|  | CallSite             Caller;     // Holds the call that called subframes. | 
|  | // NULL if main func or debugger invoked fn | 
|  | AllocaHolderHandle    Allocas;    // Track memory allocated by alloca | 
|  | }; | 
|  |  | 
|  | // Interpreter - This class represents the entirety of the interpreter. | 
|  | // | 
|  | class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> { | 
|  | GenericValue ExitValue;          // The return value of the called function | 
|  | TargetData TD; | 
|  | IntrinsicLowering *IL; | 
|  |  | 
|  | // The runtime stack of executing code.  The top of the stack is the current | 
|  | // function record. | 
|  | std::vector<ExecutionContext> ECStack; | 
|  |  | 
|  | // AtExitHandlers - List of functions to call when the program exits, | 
|  | // registered with the atexit() library function. | 
|  | std::vector<Function*> AtExitHandlers; | 
|  |  | 
|  | public: | 
|  | explicit Interpreter(ModuleProvider *M); | 
|  | ~Interpreter(); | 
|  |  | 
|  | /// runAtExitHandlers - Run any functions registered by the program's calls to | 
|  | /// atexit(3), which we intercept and store in AtExitHandlers. | 
|  | /// | 
|  | void runAtExitHandlers(); | 
|  |  | 
|  | static void Register() { | 
|  | InterpCtor = create; | 
|  | } | 
|  |  | 
|  | /// create - Create an interpreter ExecutionEngine. This can never fail. | 
|  | /// | 
|  | static ExecutionEngine *create(ModuleProvider *M, std::string *ErrorStr = 0, | 
|  | CodeGenOpt::Level = CodeGenOpt::Default); | 
|  |  | 
|  | /// run - Start execution with the specified function and arguments. | 
|  | /// | 
|  | virtual GenericValue runFunction(Function *F, | 
|  | const std::vector<GenericValue> &ArgValues); | 
|  |  | 
|  | /// recompileAndRelinkFunction - For the interpreter, functions are always | 
|  | /// up-to-date. | 
|  | /// | 
|  | virtual void *recompileAndRelinkFunction(Function *F) { | 
|  | return getPointerToFunction(F); | 
|  | } | 
|  |  | 
|  | /// freeMachineCodeForFunction - The interpreter does not generate any code. | 
|  | /// | 
|  | void freeMachineCodeForFunction(Function *F) { } | 
|  |  | 
|  | // Methods used to execute code: | 
|  | // Place a call on the stack | 
|  | void callFunction(Function *F, const std::vector<GenericValue> &ArgVals); | 
|  | void run();                // Execute instructions until nothing left to do | 
|  |  | 
|  | // Opcode Implementations | 
|  | void visitReturnInst(ReturnInst &I); | 
|  | void visitBranchInst(BranchInst &I); | 
|  | void visitSwitchInst(SwitchInst &I); | 
|  |  | 
|  | void visitBinaryOperator(BinaryOperator &I); | 
|  | void visitICmpInst(ICmpInst &I); | 
|  | void visitFCmpInst(FCmpInst &I); | 
|  | void visitAllocationInst(AllocationInst &I); | 
|  | void visitFreeInst(FreeInst &I); | 
|  | void visitLoadInst(LoadInst &I); | 
|  | void visitStoreInst(StoreInst &I); | 
|  | void visitGetElementPtrInst(GetElementPtrInst &I); | 
|  | void visitPHINode(PHINode &PN) { assert(0 && "PHI nodes already handled!"); } | 
|  | void visitTruncInst(TruncInst &I); | 
|  | void visitZExtInst(ZExtInst &I); | 
|  | void visitSExtInst(SExtInst &I); | 
|  | void visitFPTruncInst(FPTruncInst &I); | 
|  | void visitFPExtInst(FPExtInst &I); | 
|  | void visitUIToFPInst(UIToFPInst &I); | 
|  | void visitSIToFPInst(SIToFPInst &I); | 
|  | void visitFPToUIInst(FPToUIInst &I); | 
|  | void visitFPToSIInst(FPToSIInst &I); | 
|  | void visitPtrToIntInst(PtrToIntInst &I); | 
|  | void visitIntToPtrInst(IntToPtrInst &I); | 
|  | void visitBitCastInst(BitCastInst &I); | 
|  | void visitSelectInst(SelectInst &I); | 
|  |  | 
|  |  | 
|  | void visitCallSite(CallSite CS); | 
|  | void visitCallInst(CallInst &I) { visitCallSite (CallSite (&I)); } | 
|  | void visitInvokeInst(InvokeInst &I) { visitCallSite (CallSite (&I)); } | 
|  | void visitUnwindInst(UnwindInst &I); | 
|  | void visitUnreachableInst(UnreachableInst &I); | 
|  |  | 
|  | void visitShl(BinaryOperator &I); | 
|  | void visitLShr(BinaryOperator &I); | 
|  | void visitAShr(BinaryOperator &I); | 
|  |  | 
|  | void visitVAArgInst(VAArgInst &I); | 
|  | void visitInstruction(Instruction &I) { | 
|  | cerr << I; | 
|  | assert(0 && "Instruction not interpretable yet!"); | 
|  | } | 
|  |  | 
|  | GenericValue callExternalFunction(Function *F, | 
|  | const std::vector<GenericValue> &ArgVals); | 
|  | void exitCalled(GenericValue GV); | 
|  |  | 
|  | void addAtExitHandler(Function *F) { | 
|  | AtExitHandlers.push_back(F); | 
|  | } | 
|  |  | 
|  | GenericValue *getFirstVarArg () { | 
|  | return &(ECStack.back ().VarArgs[0]); | 
|  | } | 
|  |  | 
|  | //FIXME: private: | 
|  | public: | 
|  | GenericValue executeGEPOperation(Value *Ptr, gep_type_iterator I, | 
|  | gep_type_iterator E, ExecutionContext &SF); | 
|  |  | 
|  | private:  // Helper functions | 
|  | // SwitchToNewBasicBlock - Start execution in a new basic block and run any | 
|  | // PHI nodes in the top of the block.  This is used for intraprocedural | 
|  | // control flow. | 
|  | // | 
|  | void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF); | 
|  |  | 
|  | void *getPointerToFunction(Function *F) { return (void*)F; } | 
|  |  | 
|  | void initializeExecutionEngine(); | 
|  | void initializeExternalFunctions(); | 
|  | GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF); | 
|  | GenericValue getOperandValue(Value *V, ExecutionContext &SF); | 
|  | GenericValue executeTruncInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeSExtInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeZExtInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeFPTruncInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeFPExtInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeFPToUIInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeFPToSIInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeUIToFPInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeSIToFPInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executePtrToIntInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeIntToPtrInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeBitCastInst(Value *SrcVal, const Type *DstTy, | 
|  | ExecutionContext &SF); | 
|  | GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal, | 
|  | const Type *Ty, ExecutionContext &SF); | 
|  | void popStackAndReturnValueToCaller(const Type *RetTy, GenericValue Result); | 
|  |  | 
|  | }; | 
|  |  | 
|  | } // End llvm namespace | 
|  |  | 
|  | #endif |