234 lines · c
1//===-- Interpreter.h ------------------------------------------*- C++ -*--===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This header file defines the interpreter structure10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_EXECUTIONENGINE_INTERPRETER_INTERPRETER_H14#define LLVM_LIB_EXECUTIONENGINE_INTERPRETER_INTERPRETER_H15 16#include "llvm/ExecutionEngine/ExecutionEngine.h"17#include "llvm/ExecutionEngine/GenericValue.h"18#include "llvm/IR/DataLayout.h"19#include "llvm/IR/Function.h"20#include "llvm/IR/InstVisitor.h"21#include "llvm/Support/DataTypes.h"22#include "llvm/Support/ErrorHandling.h"23#include "llvm/Support/raw_ostream.h"24namespace llvm {25 26class IntrinsicLowering;27template<typename T> class generic_gep_type_iterator;28class ConstantExpr;29typedef generic_gep_type_iterator<User::const_op_iterator> gep_type_iterator;30 31 32// AllocaHolder - Object to track all of the blocks of memory allocated by33// alloca. When the function returns, this object is popped off the execution34// stack, which causes the dtor to be run, which frees all the alloca'd memory.35//36class AllocaHolder {37 std::vector<void *> Allocations;38 39public:40 AllocaHolder() = default;41 42 // Make this type move-only.43 AllocaHolder(AllocaHolder &&) = default;44 AllocaHolder &operator=(AllocaHolder &&RHS) = default;45 46 ~AllocaHolder() {47 for (void *Allocation : Allocations)48 free(Allocation);49 }50 51 void add(void *Mem) { Allocations.push_back(Mem); }52};53 54typedef std::vector<GenericValue> ValuePlaneTy;55 56// ExecutionContext struct - This struct represents one stack frame currently57// executing.58//59struct ExecutionContext {60 Function *CurFunction;// The currently executing function61 BasicBlock *CurBB; // The currently executing BB62 BasicBlock::iterator CurInst; // The next instruction to execute63 CallBase *Caller; // Holds the call that called subframes.64 // NULL if main func or debugger invoked fn65 std::map<Value *, GenericValue> Values; // LLVM values used in this invocation66 std::vector<GenericValue> VarArgs; // Values passed through an ellipsis67 AllocaHolder Allocas; // Track memory allocated by alloca68 69 ExecutionContext() : CurFunction(nullptr), CurBB(nullptr), CurInst(nullptr) {}70};71 72// Interpreter - This class represents the entirety of the interpreter.73//74class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> {75 GenericValue ExitValue; // The return value of the called function76 IntrinsicLowering *IL;77 78 // The runtime stack of executing code. The top of the stack is the current79 // function record.80 std::vector<ExecutionContext> ECStack;81 82 // AtExitHandlers - List of functions to call when the program exits,83 // registered with the atexit() library function.84 std::vector<Function*> AtExitHandlers;85 86public:87 explicit Interpreter(std::unique_ptr<Module> M);88 ~Interpreter() override;89 90 /// runAtExitHandlers - Run any functions registered by the program's calls to91 /// atexit(3), which we intercept and store in AtExitHandlers.92 ///93 void runAtExitHandlers();94 95 static void Register() {96 InterpCtor = create;97 }98 99 /// Create an interpreter ExecutionEngine.100 ///101 static ExecutionEngine *create(std::unique_ptr<Module> M,102 std::string *ErrorStr = nullptr);103 104 /// run - Start execution with the specified function and arguments.105 ///106 GenericValue runFunction(Function *F,107 ArrayRef<GenericValue> ArgValues) override;108 109 void *getPointerToNamedFunction(StringRef Name,110 bool AbortOnFailure = true) override {111 // FIXME: not implemented.112 return nullptr;113 }114 115 // Methods used to execute code:116 // Place a call on the stack117 void callFunction(Function *F, ArrayRef<GenericValue> ArgVals);118 void run(); // Execute instructions until nothing left to do119 120 // Opcode Implementations121 void visitReturnInst(ReturnInst &I);122 void visitBranchInst(BranchInst &I);123 void visitSwitchInst(SwitchInst &I);124 void visitIndirectBrInst(IndirectBrInst &I);125 126 void visitUnaryOperator(UnaryOperator &I);127 void visitBinaryOperator(BinaryOperator &I);128 void visitICmpInst(ICmpInst &I);129 void visitFCmpInst(FCmpInst &I);130 void visitAllocaInst(AllocaInst &I);131 void visitLoadInst(LoadInst &I);132 void visitStoreInst(StoreInst &I);133 void visitGetElementPtrInst(GetElementPtrInst &I);134 void visitPHINode(PHINode &PN) {135 llvm_unreachable("PHI nodes already handled!");136 }137 void visitTruncInst(TruncInst &I);138 void visitZExtInst(ZExtInst &I);139 void visitSExtInst(SExtInst &I);140 void visitFPTruncInst(FPTruncInst &I);141 void visitFPExtInst(FPExtInst &I);142 void visitUIToFPInst(UIToFPInst &I);143 void visitSIToFPInst(SIToFPInst &I);144 void visitFPToUIInst(FPToUIInst &I);145 void visitFPToSIInst(FPToSIInst &I);146 void visitPtrToIntInst(PtrToIntInst &I);147 void visitIntToPtrInst(IntToPtrInst &I);148 void visitBitCastInst(BitCastInst &I);149 void visitSelectInst(SelectInst &I);150 151 void visitVAStartInst(VAStartInst &I);152 void visitVAEndInst(VAEndInst &I);153 void visitVACopyInst(VACopyInst &I);154 void visitIntrinsicInst(IntrinsicInst &I);155 void visitCallBase(CallBase &I);156 void visitUnreachableInst(UnreachableInst &I);157 158 void visitShl(BinaryOperator &I);159 void visitLShr(BinaryOperator &I);160 void visitAShr(BinaryOperator &I);161 162 void visitVAArgInst(VAArgInst &I);163 void visitExtractElementInst(ExtractElementInst &I);164 void visitInsertElementInst(InsertElementInst &I);165 void visitShuffleVectorInst(ShuffleVectorInst &I);166 167 void visitExtractValueInst(ExtractValueInst &I);168 void visitInsertValueInst(InsertValueInst &I);169 170 void visitInstruction(Instruction &I) {171 errs() << I << "\n";172 llvm_unreachable("Instruction not interpretable yet!");173 }174 175 GenericValue callExternalFunction(Function *F,176 ArrayRef<GenericValue> ArgVals);177 void exitCalled(GenericValue GV);178 179 void addAtExitHandler(Function *F) {180 AtExitHandlers.push_back(F);181 }182 183 GenericValue *getFirstVarArg () {184 return &(ECStack.back ().VarArgs[0]);185 }186 187private: // Helper functions188 GenericValue executeGEPOperation(Value *Ptr, gep_type_iterator I,189 gep_type_iterator E, ExecutionContext &SF);190 191 // SwitchToNewBasicBlock - Start execution in a new basic block and run any192 // PHI nodes in the top of the block. This is used for intraprocedural193 // control flow.194 //195 void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF);196 197 void *getPointerToFunction(Function *F) override { return (void*)F; }198 199 void initializeExecutionEngine() { }200 void initializeExternalFunctions();201 GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF);202 GenericValue getOperandValue(Value *V, ExecutionContext &SF);203 GenericValue executeTruncInst(Value *SrcVal, Type *DstTy,204 ExecutionContext &SF);205 GenericValue executeSExtInst(Value *SrcVal, Type *DstTy,206 ExecutionContext &SF);207 GenericValue executeZExtInst(Value *SrcVal, Type *DstTy,208 ExecutionContext &SF);209 GenericValue executeFPTruncInst(Value *SrcVal, Type *DstTy,210 ExecutionContext &SF);211 GenericValue executeFPExtInst(Value *SrcVal, Type *DstTy,212 ExecutionContext &SF);213 GenericValue executeFPToUIInst(Value *SrcVal, Type *DstTy,214 ExecutionContext &SF);215 GenericValue executeFPToSIInst(Value *SrcVal, Type *DstTy,216 ExecutionContext &SF);217 GenericValue executeUIToFPInst(Value *SrcVal, Type *DstTy,218 ExecutionContext &SF);219 GenericValue executeSIToFPInst(Value *SrcVal, Type *DstTy,220 ExecutionContext &SF);221 GenericValue executePtrToIntInst(Value *SrcVal, Type *DstTy,222 ExecutionContext &SF);223 GenericValue executeIntToPtrInst(Value *SrcVal, Type *DstTy,224 ExecutionContext &SF);225 GenericValue executeBitCastInst(Value *SrcVal, Type *DstTy,226 ExecutionContext &SF);227 void popStackAndReturnValueToCaller(Type *RetTy, GenericValue Result);228 229};230 231} // End llvm namespace232 233#endif234