Path: blob/main/contrib/llvm-project/clang/lib/AST/Interp/InterpFrame.h
35292 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/// Creates a new frame for a method call.31InterpFrame(InterpState &S, const Function *Func, InterpFrame *Caller,32CodePtr RetPC, unsigned ArgSize);3334/// Creates a new frame with the values that make sense.35/// I.e., the caller is the current frame of S,36/// the This() pointer is the current Pointer on the top of S's stack,37/// and the RVO pointer is before that.38InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC,39unsigned VarArgSize = 0);4041/// Destroys the frame, killing all live pointers to stack slots.42~InterpFrame();4344/// Invokes the destructors for a scope.45void destroy(unsigned Idx);4647/// Pops the arguments off the stack.48void popArgs();4950/// Describes the frame with arguments for diagnostic purposes.51void describe(llvm::raw_ostream &OS) const override;5253/// Returns the parent frame object.54Frame *getCaller() const override;5556/// Returns the location of the call to the frame.57SourceRange getCallRange() const override;5859/// Returns the caller.60const FunctionDecl *getCallee() const override;6162/// Returns the current function.63const Function *getFunction() const { return Func; }6465/// Returns the offset on the stack at which the frame starts.66size_t getFrameOffset() const { return FrameOffset; }6768/// Returns the value of a local variable.69template <typename T> const T &getLocal(unsigned Offset) const {70return localRef<T>(Offset);71}7273/// Mutates a local variable.74template <typename T> void setLocal(unsigned Offset, const T &Value) {75localRef<T>(Offset) = Value;76localInlineDesc(Offset)->IsInitialized = true;77}7879/// Returns a pointer to a local variables.80Pointer getLocalPointer(unsigned Offset) const;8182/// Returns the value of an argument.83template <typename T> const T &getParam(unsigned Offset) const {84auto Pt = Params.find(Offset);85if (Pt == Params.end())86return stackRef<T>(Offset);87return Pointer(reinterpret_cast<Block *>(Pt->second.get())).deref<T>();88}8990/// Mutates a local copy of a parameter.91template <typename T> void setParam(unsigned Offset, const T &Value) {92getParamPointer(Offset).deref<T>() = Value;93}9495/// Returns a pointer to an argument - lazily creates a block.96Pointer getParamPointer(unsigned Offset);9798/// Returns the 'this' pointer.99const Pointer &getThis() const { return This; }100101/// Returns the RVO pointer, if the Function has one.102const Pointer &getRVOPtr() const { return RVOPtr; }103104/// Checks if the frame is a root frame - return should quit the interpreter.105bool isRoot() const { return !Func; }106107/// Returns the PC of the frame's code start.108CodePtr getPC() const { return Func->getCodeBegin(); }109110/// Returns the return address of the frame.111CodePtr getRetPC() const { return RetPC; }112113/// Map a location to a source.114virtual SourceInfo getSource(CodePtr PC) const;115const Expr *getExpr(CodePtr PC) const;116SourceLocation getLocation(CodePtr PC) const;117SourceRange getRange(CodePtr PC) const;118119unsigned getDepth() const { return Depth; }120121void dump() const { dump(llvm::errs(), 0); }122void dump(llvm::raw_ostream &OS, unsigned Indent = 0) const;123124private:125/// Returns an original argument from the stack.126template <typename T> const T &stackRef(unsigned Offset) const {127assert(Args);128return *reinterpret_cast<const T *>(Args - ArgSize + Offset);129}130131/// Returns an offset to a local.132template <typename T> T &localRef(unsigned Offset) const {133return getLocalPointer(Offset).deref<T>();134}135136/// Returns a pointer to a local's block.137Block *localBlock(unsigned Offset) const {138return reinterpret_cast<Block *>(Locals.get() + Offset - sizeof(Block));139}140141/// Returns the inline descriptor of the local.142InlineDescriptor *localInlineDesc(unsigned Offset) const {143return reinterpret_cast<InlineDescriptor *>(Locals.get() + Offset);144}145146private:147/// Reference to the interpreter state.148InterpState &S;149/// Depth of this frame.150unsigned Depth;151/// Reference to the function being executed.152const Function *Func;153/// Current object pointer for methods.154Pointer This;155/// Pointer the non-primitive return value gets constructed in.156Pointer RVOPtr;157/// Return address.158CodePtr RetPC;159/// The size of all the arguments.160const unsigned ArgSize;161/// Pointer to the arguments in the callee's frame.162char *Args = nullptr;163/// Fixed, initial storage for known local variables.164std::unique_ptr<char[]> Locals;165/// Offset on the stack at entry.166const size_t FrameOffset;167/// Mapping from arg offsets to their argument blocks.168llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Params;169};170171} // namespace interp172} // namespace clang173174#endif175176177