| //===-- 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/Target/TargetData.h" | |
| #include "llvm/Support/CallSite.h" | |
| #include "llvm/Support/DataTypes.h" | |
| #include "llvm/Support/ErrorHandling.h" | |
| #include "llvm/Support/InstVisitor.h" | |
| #include "llvm/Support/raw_ostream.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(Module *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(Module *M, std::string *ErrorStr = 0); | |
| /// 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 visitIndirectBrInst(IndirectBrInst &I); | |
| void visitBinaryOperator(BinaryOperator &I); | |
| void visitICmpInst(ICmpInst &I); | |
| void visitFCmpInst(FCmpInst &I); | |
| void visitAllocaInst(AllocaInst &I); | |
| void visitLoadInst(LoadInst &I); | |
| void visitStoreInst(StoreInst &I); | |
| void visitGetElementPtrInst(GetElementPtrInst &I); | |
| void visitPHINode(PHINode &PN) { | |
| llvm_unreachable("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) { | |
| errs() << I << "\n"; | |
| llvm_unreachable("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]); | |
| } | |
| private: // Helper functions | |
| GenericValue executeGEPOperation(Value *Ptr, gep_type_iterator I, | |
| gep_type_iterator E, ExecutionContext &SF); | |
| // 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 *getPointerToBasicBlock(BasicBlock *BB) { return (void*)BB; } | |
| void initializeExecutionEngine() { } | |
| void initializeExternalFunctions(); | |
| GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF); | |
| GenericValue getOperandValue(Value *V, ExecutionContext &SF); | |
| GenericValue executeTruncInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeSExtInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeZExtInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeFPTruncInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeFPExtInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeFPToUIInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeFPToSIInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeUIToFPInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeSIToFPInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executePtrToIntInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeIntToPtrInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeBitCastInst(Value *SrcVal, Type *DstTy, | |
| ExecutionContext &SF); | |
| GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal, | |
| Type *Ty, ExecutionContext &SF); | |
| void popStackAndReturnValueToCaller(Type *RetTy, GenericValue Result); | |
| }; | |
| } // End llvm namespace | |
| #endif |