1193323Sed//===--- InterpFrame.h - Call Frame implementation for the VM ---*- C++ -*-===// 2193323Sed// 3193323Sed// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4193323Sed// See https://llvm.org/LICENSE.txt for license information. 5193323Sed// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193323Sed// 7193323Sed//===----------------------------------------------------------------------===// 8193323Sed// 9193323Sed// Defines the class storing information about stack frames in the interpreter. 10193323Sed// 11193323Sed//===----------------------------------------------------------------------===// 12193323Sed 13193323Sed#ifndef LLVM_CLANG_AST_INTERP_INTERPFRAME_H 14193323Sed#define LLVM_CLANG_AST_INTERP_INTERPFRAME_H 15193323Sed 16193323Sed#include "Frame.h" 17193323Sed#include "Pointer.h" 18193323Sed#include "Program.h" 19193323Sed#include "State.h" 20193323Sed#include <cstdint> 21193323Sed#include <vector> 22193323Sed 23239462Sdimnamespace clang { 24198090Srdivackynamespace interp { 25193323Sedclass Function; 26193323Sedclass InterpState; 27198892Srdivacky 28193323Sed/// Frame storing local variables. 29239462Sdimclass InterpFrame final : public Frame { 30193323Sedpublic: 31193323Sed /// The frame of the previous function. 32193323Sed InterpFrame *Caller; 33193323Sed 34198892Srdivacky /// Creates a new frame for a method call. 35193323Sed InterpFrame(InterpState &S, Function *Func, InterpFrame *Caller, 36193323Sed CodePtr RetPC, Pointer &&This); 37193323Sed 38193323Sed /// Destroys the frame, killing all live pointers to stack slots. 39239462Sdim ~InterpFrame(); 40193323Sed 41239462Sdim /// Invokes the destructors for a scope. 42193323Sed void destroy(unsigned Idx); 43193323Sed 44193323Sed /// Pops the arguments off the stack. 45193323Sed void popArgs(); 46193323Sed 47193323Sed /// Describes the frame with arguments for diagnostic purposes. 48212904Sdim void describe(llvm::raw_ostream &OS) override; 49193323Sed 50239462Sdim /// Returns the parent frame object. 51239462Sdim Frame *getCaller() const override; 52239462Sdim 53239462Sdim /// Returns the location of the call to the frame. 54239462Sdim SourceLocation getCallLocation() const override; 55239462Sdim 56239462Sdim /// Returns the caller. 57239462Sdim const FunctionDecl *getCallee() const override; 58239462Sdim 59239462Sdim /// Returns the current function. 60193323Sed Function *getFunction() const { return Func; } 61193323Sed 62193323Sed /// Returns the offset on the stack at which the frame starts. 63206083Srdivacky size_t getFrameOffset() const { return FrameOffset; } 64193323Sed 65239462Sdim /// Returns the value of a local variable. 66239462Sdim template <typename T> const T &getLocal(unsigned Offset) { 67193323Sed return localRef<T>(Offset); 68234353Sdim } 69234353Sdim 70234353Sdim /// Mutates a local variable. 71234353Sdim template <typename T> void setLocal(unsigned Offset, const T &Value) { 72234353Sdim localRef<T>(Offset) = Value; 73234353Sdim } 74234353Sdim 75234353Sdim /// Returns a pointer to a local variables. 76234353Sdim Pointer getLocalPointer(unsigned Offset); 77234353Sdim 78234353Sdim /// Returns the value of an argument. 79234353Sdim template <typename T> const T &getParam(unsigned Offset) { 80234353Sdim auto Pt = Params.find(Offset); 81234353Sdim if (Pt == Params.end()) { 82234353Sdim return stackRef<T>(Offset); 83234353Sdim } else { 84234353Sdim return Pointer(reinterpret_cast<Block *>(Pt->second.get())).deref<T>(); 85234353Sdim } 86234353Sdim } 87234353Sdim 88234353Sdim /// Mutates a local copy of a parameter. 89234353Sdim template <typename T> void setParam(unsigned Offset, const T &Value) { 90234353Sdim getParamPointer(Offset).deref<T>() = Value; 91234353Sdim } 92234353Sdim 93234353Sdim /// Returns a pointer to an argument - lazily creates a block. 94239462Sdim Pointer getParamPointer(unsigned Offset); 95239462Sdim 96239462Sdim /// Returns the 'this' pointer. 97239462Sdim const Pointer &getThis() const { return This; } 98193323Sed 99193323Sed /// Checks if the frame is a root frame - return should quit the interpreter. 100239462Sdim bool isRoot() const { return !Func; } 101239462Sdim 102193323Sed /// Returns the PC of the frame's code start. 103204642Srdivacky CodePtr getPC() const { return Func->getCodeBegin(); } 104204642Srdivacky 105204642Srdivacky /// Returns the return address of the frame. 106239462Sdim CodePtr getRetPC() const { return RetPC; } 107239462Sdim 108239462Sdim /// Map a location to a source. 109239462Sdim virtual SourceInfo getSource(CodePtr PC) const; 110193323Sed const Expr *getExpr(CodePtr PC) const; 111193323Sed SourceLocation getLocation(CodePtr PC) const; 112239462Sdim 113239462Sdimprivate: 114193323Sed /// Returns an original argument from the stack. 115193323Sed template <typename T> const T &stackRef(unsigned Offset) { 116239462Sdim return *reinterpret_cast<const T *>(Args - ArgSize + Offset); 117239462Sdim } 118193323Sed 119193323Sed /// Returns an offset to a local. 120239462Sdim template <typename T> T &localRef(unsigned Offset) { 121239462Sdim return *reinterpret_cast<T *>(Locals.get() + Offset); 122239462Sdim } 123239462Sdim 124239462Sdim /// Returns a pointer to a local's block. 125239462Sdim void *localBlock(unsigned Offset) { 126239462Sdim return Locals.get() + Offset - sizeof(Block); 127193323Sed } 128207618Srdivacky 129239462Sdimprivate: 130239462Sdim /// Reference to the interpreter state. 131239462Sdim InterpState &S; 132239462Sdim /// Reference to the function being executed. 133207618Srdivacky Function *Func; 134212904Sdim /// Current object pointer for methods. 135193323Sed Pointer This; 136193323Sed /// Return address. 137193323Sed CodePtr RetPC; 138198090Srdivacky /// The size of all the arguments. 139193323Sed const unsigned ArgSize; 140218893Sdim /// Pointer to the arguments in the callee's frame. 141218893Sdim char *Args = nullptr; 142218893Sdim /// Fixed, initial storage for known local variables. 143218893Sdim std::unique_ptr<char[]> Locals; 144221345Sdim /// Offset on the stack at entry. 145221345Sdim const size_t FrameOffset; 146221345Sdim /// Mapping from arg offsets to their argument blocks. 147221345Sdim llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Params; 148221345Sdim}; 149218893Sdim 150243830Sdim} // namespace interp 151243830Sdim} // namespace clang 152243830Sdim 153243830Sdim#endif 154243830Sdim