| //===-- Interpreter.h ------------------------------------------*- C++ -*--===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This header file defines the interpreter structure |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_LIB_EXECUTIONENGINE_INTERPRETER_INTERPRETER_H |
| #define LLVM_LIB_EXECUTIONENGINE_INTERPRETER_INTERPRETER_H |
| |
| #include "llvm/ExecutionEngine/ExecutionEngine.h" |
| #include "llvm/ExecutionEngine/GenericValue.h" |
| #include "llvm/IR/CallSite.h" |
| #include "llvm/IR/DataLayout.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/InstVisitor.h" |
| #include "llvm/Support/DataTypes.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/raw_ostream.h" |
| namespace llvm { |
| |
| class IntrinsicLowering; |
| 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 { |
| std::vector<void *> Allocations; |
| |
| public: |
| AllocaHolder() {} |
| |
| // Make this type move-only. |
| AllocaHolder(AllocaHolder &&) = default; |
| AllocaHolder &operator=(AllocaHolder &&RHS) = default; |
| |
| ~AllocaHolder() { |
| for (void *Allocation : Allocations) |
| free(Allocation); |
| } |
| |
| void add(void *Mem) { Allocations.push_back(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 |
| CallSite Caller; // Holds the call that called subframes. |
| // NULL if main func or debugger invoked fn |
| std::map<Value *, GenericValue> Values; // LLVM values used in this invocation |
| std::vector<GenericValue> VarArgs; // Values passed through an ellipsis |
| AllocaHolder Allocas; // Track memory allocated by alloca |
| |
| ExecutionContext() : CurFunction(nullptr), CurBB(nullptr), CurInst(nullptr) {} |
| }; |
| |
| // 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 |
| 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(std::unique_ptr<Module> M); |
| ~Interpreter() override; |
| |
| /// 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 an interpreter ExecutionEngine. |
| /// |
| static ExecutionEngine *create(std::unique_ptr<Module> M, |
| std::string *ErrorStr = nullptr); |
| |
| /// run - Start execution with the specified function and arguments. |
| /// |
| GenericValue runFunction(Function *F, |
| ArrayRef<GenericValue> ArgValues) override; |
| |
| void *getPointerToNamedFunction(StringRef Name, |
| bool AbortOnFailure = true) override { |
| // FIXME: not implemented. |
| return nullptr; |
| } |
| |
| // Methods used to execute code: |
| // Place a call on the stack |
| void callFunction(Function *F, ArrayRef<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 visitUnaryOperator(UnaryOperator &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 visitUnreachableInst(UnreachableInst &I); |
| |
| void visitShl(BinaryOperator &I); |
| void visitLShr(BinaryOperator &I); |
| void visitAShr(BinaryOperator &I); |
| |
| void visitVAArgInst(VAArgInst &I); |
| void visitExtractElementInst(ExtractElementInst &I); |
| void visitInsertElementInst(InsertElementInst &I); |
| void visitShuffleVectorInst(ShuffleVectorInst &I); |
| |
| void visitExtractValueInst(ExtractValueInst &I); |
| void visitInsertValueInst(InsertValueInst &I); |
| |
| void visitInstruction(Instruction &I) { |
| errs() << I << "\n"; |
| llvm_unreachable("Instruction not interpretable yet!"); |
| } |
| |
| GenericValue callExternalFunction(Function *F, |
| ArrayRef<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) override { return (void*)F; } |
| |
| 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 |