Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/InterpFrame.h
213799 views
//===--- InterpFrame.h - Call Frame implementation for the VM ---*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Defines the class storing information about stack frames in the interpreter.9//10//===----------------------------------------------------------------------===//1112#ifndef LLVM_CLANG_AST_INTERP_INTERPFRAME_H13#define LLVM_CLANG_AST_INTERP_INTERPFRAME_H1415#include "Frame.h"16#include "Program.h"1718namespace clang {19namespace interp {20class Function;21class InterpState;22class Pointer;2324/// Frame storing local variables.25class InterpFrame final : public Frame {26public:27/// The frame of the previous function.28InterpFrame *Caller;2930/// Bottom Frame.31InterpFrame(InterpState &S);3233/// Creates a new frame for a method call.34InterpFrame(InterpState &S, const Function *Func, InterpFrame *Caller,35CodePtr RetPC, unsigned ArgSize);3637/// Creates a new frame with the values that make sense.38/// I.e., the caller is the current frame of S,39/// the This() pointer is the current Pointer on the top of S's stack,40/// and the RVO pointer is before that.41InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC,42unsigned VarArgSize = 0);4344/// Destroys the frame, killing all live pointers to stack slots.45~InterpFrame();4647static void free(InterpFrame *F) {48if (!F->isBottomFrame())49delete F;50}5152/// Invokes the destructors for a scope.53void destroy(unsigned Idx);54void initScope(unsigned Idx);55void destroyScopes();5657/// Describes the frame with arguments for diagnostic purposes.58void describe(llvm::raw_ostream &OS) const override;5960/// Returns the parent frame object.61Frame *getCaller() const override;6263/// Returns the location of the call to the frame.64SourceRange getCallRange() const override;6566/// Returns the caller.67const FunctionDecl *getCallee() const override;6869/// Returns the current function.70const Function *getFunction() const { return Func; }7172/// Returns the offset on the stack at which the frame starts.73size_t getFrameOffset() const { return FrameOffset; }7475/// Returns the value of a local variable.76template <typename T> const T &getLocal(unsigned Offset) const {77return localRef<T>(Offset);78}7980/// Mutates a local variable.81template <typename T> void setLocal(unsigned Offset, const T &Value) {82localRef<T>(Offset) = Value;83localInlineDesc(Offset)->IsInitialized = true;84}8586/// Returns a pointer to a local variables.87Pointer getLocalPointer(unsigned Offset) const;8889/// Returns the value of an argument.90template <typename T> const T &getParam(unsigned Offset) const {91auto Pt = Params.find(Offset);92if (Pt == Params.end())93return stackRef<T>(Offset);94return Pointer(reinterpret_cast<Block *>(Pt->second.get())).deref<T>();95}9697/// Mutates a local copy of a parameter.98template <typename T> void setParam(unsigned Offset, const T &Value) {99getParamPointer(Offset).deref<T>() = Value;100}101102/// Returns a pointer to an argument - lazily creates a block.103Pointer getParamPointer(unsigned Offset);104105/// Returns the 'this' pointer.106const Pointer &getThis() const { return This; }107108/// Returns the RVO pointer, if the Function has one.109const Pointer &getRVOPtr() const { return RVOPtr; }110111/// Checks if the frame is a root frame - return should quit the interpreter.112bool isRoot() const { return !Func; }113114/// Returns the PC of the frame's code start.115CodePtr getPC() const { return Func->getCodeBegin(); }116117/// Returns the return address of the frame.118CodePtr getRetPC() const { return RetPC; }119120/// Map a location to a source.121SourceInfo getSource(CodePtr PC) const;122const Expr *getExpr(CodePtr PC) const;123SourceLocation getLocation(CodePtr PC) const;124SourceRange getRange(CodePtr PC) const;125126unsigned getDepth() const { return Depth; }127128bool isStdFunction() const;129130bool isBottomFrame() const { return IsBottom; }131132void dump() const { dump(llvm::errs(), 0); }133void dump(llvm::raw_ostream &OS, unsigned Indent = 0) const;134135private:136/// Returns an original argument from the stack.137template <typename T> const T &stackRef(unsigned Offset) const {138assert(Args);139return *reinterpret_cast<const T *>(Args - ArgSize + Offset);140}141142/// Returns an offset to a local.143template <typename T> T &localRef(unsigned Offset) const {144return getLocalPointer(Offset).deref<T>();145}146147/// Returns a pointer to a local's block.148Block *localBlock(unsigned Offset) const {149return reinterpret_cast<Block *>(Locals.get() + Offset - sizeof(Block));150}151152/// Returns the inline descriptor of the local.153InlineDescriptor *localInlineDesc(unsigned Offset) const {154return reinterpret_cast<InlineDescriptor *>(Locals.get() + Offset);155}156157private:158/// Reference to the interpreter state.159InterpState &S;160/// Depth of this frame.161unsigned Depth;162/// Reference to the function being executed.163const Function *Func;164/// Current object pointer for methods.165Pointer This;166/// Pointer the non-primitive return value gets constructed in.167Pointer RVOPtr;168/// Return address.169CodePtr RetPC;170/// The size of all the arguments.171const unsigned ArgSize;172/// Pointer to the arguments in the callee's frame.173char *Args = nullptr;174/// Fixed, initial storage for known local variables.175std::unique_ptr<char[]> Locals;176/// Offset on the stack at entry.177const size_t FrameOffset;178/// Mapping from arg offsets to their argument blocks.179llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Params;180bool IsBottom = false;181};182183} // namespace interp184} // namespace clang185186#endif187188189