1*a7dea167SDimitry Andric //===--- InterpFrame.h - Call Frame implementation for the VM ---*- C++ -*-===// 2*a7dea167SDimitry Andric // 3*a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*a7dea167SDimitry Andric // 7*a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8*a7dea167SDimitry Andric // 9*a7dea167SDimitry Andric // Defines the class storing information about stack frames in the interpreter. 10*a7dea167SDimitry Andric // 11*a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 12*a7dea167SDimitry Andric 13*a7dea167SDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_INTERPFRAME_H 14*a7dea167SDimitry Andric #define LLVM_CLANG_AST_INTERP_INTERPFRAME_H 15*a7dea167SDimitry Andric 16*a7dea167SDimitry Andric #include "Frame.h" 17*a7dea167SDimitry Andric #include "Pointer.h" 18*a7dea167SDimitry Andric #include "Program.h" 19*a7dea167SDimitry Andric #include "State.h" 20*a7dea167SDimitry Andric #include <cstdint> 21*a7dea167SDimitry Andric #include <vector> 22*a7dea167SDimitry Andric 23*a7dea167SDimitry Andric namespace clang { 24*a7dea167SDimitry Andric namespace interp { 25*a7dea167SDimitry Andric class Function; 26*a7dea167SDimitry Andric class InterpState; 27*a7dea167SDimitry Andric 28*a7dea167SDimitry Andric /// Frame storing local variables. 29*a7dea167SDimitry Andric class InterpFrame final : public Frame { 30*a7dea167SDimitry Andric public: 31*a7dea167SDimitry Andric /// The frame of the previous function. 32*a7dea167SDimitry Andric InterpFrame *Caller; 33*a7dea167SDimitry Andric 34*a7dea167SDimitry Andric /// Creates a new frame for a method call. 35*a7dea167SDimitry Andric InterpFrame(InterpState &S, Function *Func, InterpFrame *Caller, 36*a7dea167SDimitry Andric CodePtr RetPC, Pointer &&This); 37*a7dea167SDimitry Andric 38*a7dea167SDimitry Andric /// Destroys the frame, killing all live pointers to stack slots. 39*a7dea167SDimitry Andric ~InterpFrame(); 40*a7dea167SDimitry Andric 41*a7dea167SDimitry Andric /// Invokes the destructors for a scope. 42*a7dea167SDimitry Andric void destroy(unsigned Idx); 43*a7dea167SDimitry Andric 44*a7dea167SDimitry Andric /// Pops the arguments off the stack. 45*a7dea167SDimitry Andric void popArgs(); 46*a7dea167SDimitry Andric 47*a7dea167SDimitry Andric /// Describes the frame with arguments for diagnostic purposes. 48*a7dea167SDimitry Andric void describe(llvm::raw_ostream &OS); 49*a7dea167SDimitry Andric 50*a7dea167SDimitry Andric /// Returns the parent frame object. 51*a7dea167SDimitry Andric Frame *getCaller() const; 52*a7dea167SDimitry Andric 53*a7dea167SDimitry Andric /// Returns the location of the call to the frame. 54*a7dea167SDimitry Andric SourceLocation getCallLocation() const; 55*a7dea167SDimitry Andric 56*a7dea167SDimitry Andric /// Returns the caller. 57*a7dea167SDimitry Andric const FunctionDecl *getCallee() const; 58*a7dea167SDimitry Andric 59*a7dea167SDimitry Andric /// Returns the current function. 60*a7dea167SDimitry Andric Function *getFunction() const { return Func; } 61*a7dea167SDimitry Andric 62*a7dea167SDimitry Andric /// Returns the offset on the stack at which the frame starts. 63*a7dea167SDimitry Andric size_t getFrameOffset() const { return FrameOffset; } 64*a7dea167SDimitry Andric 65*a7dea167SDimitry Andric /// Returns the value of a local variable. 66*a7dea167SDimitry Andric template <typename T> const T &getLocal(unsigned Offset) { 67*a7dea167SDimitry Andric return localRef<T>(Offset); 68*a7dea167SDimitry Andric } 69*a7dea167SDimitry Andric 70*a7dea167SDimitry Andric /// Mutates a local variable. 71*a7dea167SDimitry Andric template <typename T> void setLocal(unsigned Offset, const T &Value) { 72*a7dea167SDimitry Andric localRef<T>(Offset) = Value; 73*a7dea167SDimitry Andric } 74*a7dea167SDimitry Andric 75*a7dea167SDimitry Andric /// Returns a pointer to a local variables. 76*a7dea167SDimitry Andric Pointer getLocalPointer(unsigned Offset); 77*a7dea167SDimitry Andric 78*a7dea167SDimitry Andric /// Returns the value of an argument. 79*a7dea167SDimitry Andric template <typename T> const T &getParam(unsigned Offset) { 80*a7dea167SDimitry Andric auto Pt = Params.find(Offset); 81*a7dea167SDimitry Andric if (Pt == Params.end()) { 82*a7dea167SDimitry Andric return stackRef<T>(Offset); 83*a7dea167SDimitry Andric } else { 84*a7dea167SDimitry Andric return Pointer(reinterpret_cast<Block *>(Pt->second.get())).deref<T>(); 85*a7dea167SDimitry Andric } 86*a7dea167SDimitry Andric } 87*a7dea167SDimitry Andric 88*a7dea167SDimitry Andric /// Mutates a local copy of a parameter. 89*a7dea167SDimitry Andric template <typename T> void setParam(unsigned Offset, const T &Value) { 90*a7dea167SDimitry Andric getParamPointer(Offset).deref<T>() = Value; 91*a7dea167SDimitry Andric } 92*a7dea167SDimitry Andric 93*a7dea167SDimitry Andric /// Returns a pointer to an argument - lazily creates a block. 94*a7dea167SDimitry Andric Pointer getParamPointer(unsigned Offset); 95*a7dea167SDimitry Andric 96*a7dea167SDimitry Andric /// Returns the 'this' pointer. 97*a7dea167SDimitry Andric const Pointer &getThis() const { return This; } 98*a7dea167SDimitry Andric 99*a7dea167SDimitry Andric /// Checks if the frame is a root frame - return should quit the interpreter. 100*a7dea167SDimitry Andric bool isRoot() const { return !Func; } 101*a7dea167SDimitry Andric 102*a7dea167SDimitry Andric /// Returns the PC of the frame's code start. 103*a7dea167SDimitry Andric CodePtr getPC() const { return Func->getCodeBegin(); } 104*a7dea167SDimitry Andric 105*a7dea167SDimitry Andric /// Returns the return address of the frame. 106*a7dea167SDimitry Andric CodePtr getRetPC() const { return RetPC; } 107*a7dea167SDimitry Andric 108*a7dea167SDimitry Andric /// Map a location to a source. 109*a7dea167SDimitry Andric virtual SourceInfo getSource(CodePtr PC) const; 110*a7dea167SDimitry Andric const Expr *getExpr(CodePtr PC) const; 111*a7dea167SDimitry Andric SourceLocation getLocation(CodePtr PC) const; 112*a7dea167SDimitry Andric 113*a7dea167SDimitry Andric private: 114*a7dea167SDimitry Andric /// Returns an original argument from the stack. 115*a7dea167SDimitry Andric template <typename T> const T &stackRef(unsigned Offset) { 116*a7dea167SDimitry Andric return *reinterpret_cast<const T *>(Args - ArgSize + Offset); 117*a7dea167SDimitry Andric } 118*a7dea167SDimitry Andric 119*a7dea167SDimitry Andric /// Returns an offset to a local. 120*a7dea167SDimitry Andric template <typename T> T &localRef(unsigned Offset) { 121*a7dea167SDimitry Andric return *reinterpret_cast<T *>(Locals.get() + Offset); 122*a7dea167SDimitry Andric } 123*a7dea167SDimitry Andric 124*a7dea167SDimitry Andric /// Returns a pointer to a local's block. 125*a7dea167SDimitry Andric void *localBlock(unsigned Offset) { 126*a7dea167SDimitry Andric return Locals.get() + Offset - sizeof(Block); 127*a7dea167SDimitry Andric } 128*a7dea167SDimitry Andric 129*a7dea167SDimitry Andric private: 130*a7dea167SDimitry Andric /// Reference to the interpreter state. 131*a7dea167SDimitry Andric InterpState &S; 132*a7dea167SDimitry Andric /// Reference to the function being executed. 133*a7dea167SDimitry Andric Function *Func; 134*a7dea167SDimitry Andric /// Current object pointer for methods. 135*a7dea167SDimitry Andric Pointer This; 136*a7dea167SDimitry Andric /// Return address. 137*a7dea167SDimitry Andric CodePtr RetPC; 138*a7dea167SDimitry Andric /// The size of all the arguments. 139*a7dea167SDimitry Andric const unsigned ArgSize; 140*a7dea167SDimitry Andric /// Pointer to the arguments in the callee's frame. 141*a7dea167SDimitry Andric char *Args = nullptr; 142*a7dea167SDimitry Andric /// Fixed, initial storage for known local variables. 143*a7dea167SDimitry Andric std::unique_ptr<char[]> Locals; 144*a7dea167SDimitry Andric /// Offset on the stack at entry. 145*a7dea167SDimitry Andric const size_t FrameOffset; 146*a7dea167SDimitry Andric /// Mapping from arg offsets to their argument blocks. 147*a7dea167SDimitry Andric llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Params; 148*a7dea167SDimitry Andric }; 149*a7dea167SDimitry Andric 150*a7dea167SDimitry Andric } // namespace interp 151*a7dea167SDimitry Andric } // namespace clang 152*a7dea167SDimitry Andric 153*a7dea167SDimitry Andric #endif 154