xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===-- Interpreter.h ------------------------------------------*- C++ -*--===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This header file defines the interpreter structure
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_EXECUTIONENGINE_INTERPRETER_INTERPRETER_H
140b57cec5SDimitry Andric #define LLVM_LIB_EXECUTIONENGINE_INTERPRETER_INTERPRETER_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/ExecutionEngine/ExecutionEngine.h"
170b57cec5SDimitry Andric #include "llvm/ExecutionEngine/GenericValue.h"
180b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
190b57cec5SDimitry Andric #include "llvm/IR/Function.h"
200b57cec5SDimitry Andric #include "llvm/IR/InstVisitor.h"
210b57cec5SDimitry Andric #include "llvm/Support/DataTypes.h"
220b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
230b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
240b57cec5SDimitry Andric namespace llvm {
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric class IntrinsicLowering;
270b57cec5SDimitry Andric template<typename T> class generic_gep_type_iterator;
280b57cec5SDimitry Andric class ConstantExpr;
290b57cec5SDimitry Andric typedef generic_gep_type_iterator<User::const_op_iterator> gep_type_iterator;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric // AllocaHolder - Object to track all of the blocks of memory allocated by
330b57cec5SDimitry Andric // alloca.  When the function returns, this object is popped off the execution
340b57cec5SDimitry Andric // stack, which causes the dtor to be run, which frees all the alloca'd memory.
350b57cec5SDimitry Andric //
360b57cec5SDimitry Andric class AllocaHolder {
370b57cec5SDimitry Andric   std::vector<void *> Allocations;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric public:
40*81ad6265SDimitry Andric   AllocaHolder() = default;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   // Make this type move-only.
430b57cec5SDimitry Andric   AllocaHolder(AllocaHolder &&) = default;
440b57cec5SDimitry Andric   AllocaHolder &operator=(AllocaHolder &&RHS) = default;
450b57cec5SDimitry Andric 
~AllocaHolder()460b57cec5SDimitry Andric   ~AllocaHolder() {
470b57cec5SDimitry Andric     for (void *Allocation : Allocations)
480b57cec5SDimitry Andric       free(Allocation);
490b57cec5SDimitry Andric   }
500b57cec5SDimitry Andric 
add(void * Mem)510b57cec5SDimitry Andric   void add(void *Mem) { Allocations.push_back(Mem); }
520b57cec5SDimitry Andric };
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric typedef std::vector<GenericValue> ValuePlaneTy;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric // ExecutionContext struct - This struct represents one stack frame currently
570b57cec5SDimitry Andric // executing.
580b57cec5SDimitry Andric //
590b57cec5SDimitry Andric struct ExecutionContext {
600b57cec5SDimitry Andric   Function             *CurFunction;// The currently executing function
610b57cec5SDimitry Andric   BasicBlock           *CurBB;      // The currently executing BB
620b57cec5SDimitry Andric   BasicBlock::iterator  CurInst;    // The next instruction to execute
635ffd83dbSDimitry Andric   CallBase             *Caller;     // Holds the call that called subframes.
640b57cec5SDimitry Andric                                     // NULL if main func or debugger invoked fn
650b57cec5SDimitry Andric   std::map<Value *, GenericValue> Values; // LLVM values used in this invocation
660b57cec5SDimitry Andric   std::vector<GenericValue>  VarArgs; // Values passed through an ellipsis
670b57cec5SDimitry Andric   AllocaHolder Allocas;            // Track memory allocated by alloca
680b57cec5SDimitry Andric 
ExecutionContextExecutionContext690b57cec5SDimitry Andric   ExecutionContext() : CurFunction(nullptr), CurBB(nullptr), CurInst(nullptr) {}
700b57cec5SDimitry Andric };
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric // Interpreter - This class represents the entirety of the interpreter.
730b57cec5SDimitry Andric //
740b57cec5SDimitry Andric class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> {
750b57cec5SDimitry Andric   GenericValue ExitValue;          // The return value of the called function
760b57cec5SDimitry Andric   IntrinsicLowering *IL;
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   // The runtime stack of executing code.  The top of the stack is the current
790b57cec5SDimitry Andric   // function record.
800b57cec5SDimitry Andric   std::vector<ExecutionContext> ECStack;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   // AtExitHandlers - List of functions to call when the program exits,
830b57cec5SDimitry Andric   // registered with the atexit() library function.
840b57cec5SDimitry Andric   std::vector<Function*> AtExitHandlers;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric public:
870b57cec5SDimitry Andric   explicit Interpreter(std::unique_ptr<Module> M);
880b57cec5SDimitry Andric   ~Interpreter() override;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   /// runAtExitHandlers - Run any functions registered by the program's calls to
910b57cec5SDimitry Andric   /// atexit(3), which we intercept and store in AtExitHandlers.
920b57cec5SDimitry Andric   ///
930b57cec5SDimitry Andric   void runAtExitHandlers();
940b57cec5SDimitry Andric 
Register()950b57cec5SDimitry Andric   static void Register() {
960b57cec5SDimitry Andric     InterpCtor = create;
970b57cec5SDimitry Andric   }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   /// Create an interpreter ExecutionEngine.
1000b57cec5SDimitry Andric   ///
1010b57cec5SDimitry Andric   static ExecutionEngine *create(std::unique_ptr<Module> M,
1020b57cec5SDimitry Andric                                  std::string *ErrorStr = nullptr);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   /// run - Start execution with the specified function and arguments.
1050b57cec5SDimitry Andric   ///
1060b57cec5SDimitry Andric   GenericValue runFunction(Function *F,
1070b57cec5SDimitry Andric                            ArrayRef<GenericValue> ArgValues) override;
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   void *getPointerToNamedFunction(StringRef Name,
1100b57cec5SDimitry Andric                                   bool AbortOnFailure = true) override {
1110b57cec5SDimitry Andric     // FIXME: not implemented.
1120b57cec5SDimitry Andric     return nullptr;
1130b57cec5SDimitry Andric   }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   // Methods used to execute code:
1160b57cec5SDimitry Andric   // Place a call on the stack
1170b57cec5SDimitry Andric   void callFunction(Function *F, ArrayRef<GenericValue> ArgVals);
1180b57cec5SDimitry Andric   void run();                // Execute instructions until nothing left to do
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   // Opcode Implementations
1210b57cec5SDimitry Andric   void visitReturnInst(ReturnInst &I);
1220b57cec5SDimitry Andric   void visitBranchInst(BranchInst &I);
1230b57cec5SDimitry Andric   void visitSwitchInst(SwitchInst &I);
1240b57cec5SDimitry Andric   void visitIndirectBrInst(IndirectBrInst &I);
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   void visitUnaryOperator(UnaryOperator &I);
1270b57cec5SDimitry Andric   void visitBinaryOperator(BinaryOperator &I);
1280b57cec5SDimitry Andric   void visitICmpInst(ICmpInst &I);
1290b57cec5SDimitry Andric   void visitFCmpInst(FCmpInst &I);
1300b57cec5SDimitry Andric   void visitAllocaInst(AllocaInst &I);
1310b57cec5SDimitry Andric   void visitLoadInst(LoadInst &I);
1320b57cec5SDimitry Andric   void visitStoreInst(StoreInst &I);
1330b57cec5SDimitry Andric   void visitGetElementPtrInst(GetElementPtrInst &I);
visitPHINode(PHINode & PN)1340b57cec5SDimitry Andric   void visitPHINode(PHINode &PN) {
1350b57cec5SDimitry Andric     llvm_unreachable("PHI nodes already handled!");
1360b57cec5SDimitry Andric   }
1370b57cec5SDimitry Andric   void visitTruncInst(TruncInst &I);
1380b57cec5SDimitry Andric   void visitZExtInst(ZExtInst &I);
1390b57cec5SDimitry Andric   void visitSExtInst(SExtInst &I);
1400b57cec5SDimitry Andric   void visitFPTruncInst(FPTruncInst &I);
1410b57cec5SDimitry Andric   void visitFPExtInst(FPExtInst &I);
1420b57cec5SDimitry Andric   void visitUIToFPInst(UIToFPInst &I);
1430b57cec5SDimitry Andric   void visitSIToFPInst(SIToFPInst &I);
1440b57cec5SDimitry Andric   void visitFPToUIInst(FPToUIInst &I);
1450b57cec5SDimitry Andric   void visitFPToSIInst(FPToSIInst &I);
1460b57cec5SDimitry Andric   void visitPtrToIntInst(PtrToIntInst &I);
1470b57cec5SDimitry Andric   void visitIntToPtrInst(IntToPtrInst &I);
1480b57cec5SDimitry Andric   void visitBitCastInst(BitCastInst &I);
1490b57cec5SDimitry Andric   void visitSelectInst(SelectInst &I);
1500b57cec5SDimitry Andric 
1515ffd83dbSDimitry Andric   void visitVAStartInst(VAStartInst &I);
1525ffd83dbSDimitry Andric   void visitVAEndInst(VAEndInst &I);
1535ffd83dbSDimitry Andric   void visitVACopyInst(VACopyInst &I);
1545ffd83dbSDimitry Andric   void visitIntrinsicInst(IntrinsicInst &I);
1555ffd83dbSDimitry Andric   void visitCallBase(CallBase &I);
1560b57cec5SDimitry Andric   void visitUnreachableInst(UnreachableInst &I);
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   void visitShl(BinaryOperator &I);
1590b57cec5SDimitry Andric   void visitLShr(BinaryOperator &I);
1600b57cec5SDimitry Andric   void visitAShr(BinaryOperator &I);
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   void visitVAArgInst(VAArgInst &I);
1630b57cec5SDimitry Andric   void visitExtractElementInst(ExtractElementInst &I);
1640b57cec5SDimitry Andric   void visitInsertElementInst(InsertElementInst &I);
1650b57cec5SDimitry Andric   void visitShuffleVectorInst(ShuffleVectorInst &I);
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   void visitExtractValueInst(ExtractValueInst &I);
1680b57cec5SDimitry Andric   void visitInsertValueInst(InsertValueInst &I);
1690b57cec5SDimitry Andric 
visitInstruction(Instruction & I)1700b57cec5SDimitry Andric   void visitInstruction(Instruction &I) {
1710b57cec5SDimitry Andric     errs() << I << "\n";
1720b57cec5SDimitry Andric     llvm_unreachable("Instruction not interpretable yet!");
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   GenericValue callExternalFunction(Function *F,
1760b57cec5SDimitry Andric                                     ArrayRef<GenericValue> ArgVals);
1770b57cec5SDimitry Andric   void exitCalled(GenericValue GV);
1780b57cec5SDimitry Andric 
addAtExitHandler(Function * F)1790b57cec5SDimitry Andric   void addAtExitHandler(Function *F) {
1800b57cec5SDimitry Andric     AtExitHandlers.push_back(F);
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
getFirstVarArg()1830b57cec5SDimitry Andric   GenericValue *getFirstVarArg () {
1840b57cec5SDimitry Andric     return &(ECStack.back ().VarArgs[0]);
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric private:  // Helper functions
1880b57cec5SDimitry Andric   GenericValue executeGEPOperation(Value *Ptr, gep_type_iterator I,
1890b57cec5SDimitry Andric                                    gep_type_iterator E, ExecutionContext &SF);
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   // SwitchToNewBasicBlock - Start execution in a new basic block and run any
1920b57cec5SDimitry Andric   // PHI nodes in the top of the block.  This is used for intraprocedural
1930b57cec5SDimitry Andric   // control flow.
1940b57cec5SDimitry Andric   //
1950b57cec5SDimitry Andric   void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF);
1960b57cec5SDimitry Andric 
getPointerToFunction(Function * F)1970b57cec5SDimitry Andric   void *getPointerToFunction(Function *F) override { return (void*)F; }
1980b57cec5SDimitry Andric 
initializeExecutionEngine()1990b57cec5SDimitry Andric   void initializeExecutionEngine() { }
2000b57cec5SDimitry Andric   void initializeExternalFunctions();
2010b57cec5SDimitry Andric   GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF);
2020b57cec5SDimitry Andric   GenericValue getOperandValue(Value *V, ExecutionContext &SF);
2030b57cec5SDimitry Andric   GenericValue executeTruncInst(Value *SrcVal, Type *DstTy,
2040b57cec5SDimitry Andric                                 ExecutionContext &SF);
2050b57cec5SDimitry Andric   GenericValue executeSExtInst(Value *SrcVal, Type *DstTy,
2060b57cec5SDimitry Andric                                ExecutionContext &SF);
2070b57cec5SDimitry Andric   GenericValue executeZExtInst(Value *SrcVal, Type *DstTy,
2080b57cec5SDimitry Andric                                ExecutionContext &SF);
2090b57cec5SDimitry Andric   GenericValue executeFPTruncInst(Value *SrcVal, Type *DstTy,
2100b57cec5SDimitry Andric                                   ExecutionContext &SF);
2110b57cec5SDimitry Andric   GenericValue executeFPExtInst(Value *SrcVal, Type *DstTy,
2120b57cec5SDimitry Andric                                 ExecutionContext &SF);
2130b57cec5SDimitry Andric   GenericValue executeFPToUIInst(Value *SrcVal, Type *DstTy,
2140b57cec5SDimitry Andric                                  ExecutionContext &SF);
2150b57cec5SDimitry Andric   GenericValue executeFPToSIInst(Value *SrcVal, Type *DstTy,
2160b57cec5SDimitry Andric                                  ExecutionContext &SF);
2170b57cec5SDimitry Andric   GenericValue executeUIToFPInst(Value *SrcVal, Type *DstTy,
2180b57cec5SDimitry Andric                                  ExecutionContext &SF);
2190b57cec5SDimitry Andric   GenericValue executeSIToFPInst(Value *SrcVal, Type *DstTy,
2200b57cec5SDimitry Andric                                  ExecutionContext &SF);
2210b57cec5SDimitry Andric   GenericValue executePtrToIntInst(Value *SrcVal, Type *DstTy,
2220b57cec5SDimitry Andric                                    ExecutionContext &SF);
2230b57cec5SDimitry Andric   GenericValue executeIntToPtrInst(Value *SrcVal, Type *DstTy,
2240b57cec5SDimitry Andric                                    ExecutionContext &SF);
2250b57cec5SDimitry Andric   GenericValue executeBitCastInst(Value *SrcVal, Type *DstTy,
2260b57cec5SDimitry Andric                                   ExecutionContext &SF);
2270b57cec5SDimitry Andric   void popStackAndReturnValueToCaller(Type *RetTy, GenericValue Result);
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric };
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric } // End llvm namespace
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric #endif
234