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