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