| //===--- InterpFrame.h - Call Frame implementation for the VM ---*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Defines the class storing information about stack frames in the interpreter. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_AST_INTERP_INTERPFRAME_H |
| #define LLVM_CLANG_AST_INTERP_INTERPFRAME_H |
| |
| #include "Frame.h" |
| #include "Pointer.h" |
| #include "Program.h" |
| #include "State.h" |
| #include <cstdint> |
| #include <vector> |
| |
| namespace clang { |
| namespace interp { |
| class Function; |
| class InterpState; |
| |
| /// Frame storing local variables. |
| class InterpFrame final : public Frame { |
| public: |
| /// The frame of the previous function. |
| InterpFrame *Caller; |
| |
| /// Creates a new frame for a method call. |
| InterpFrame(InterpState &S, Function *Func, InterpFrame *Caller, |
| CodePtr RetPC, Pointer &&This); |
| |
| /// Destroys the frame, killing all live pointers to stack slots. |
| ~InterpFrame(); |
| |
| /// Invokes the destructors for a scope. |
| void destroy(unsigned Idx); |
| |
| /// Pops the arguments off the stack. |
| void popArgs(); |
| |
| /// Describes the frame with arguments for diagnostic purposes. |
| void describe(llvm::raw_ostream &OS); |
| |
| /// Returns the parent frame object. |
| Frame *getCaller() const; |
| |
| /// Returns the location of the call to the frame. |
| SourceLocation getCallLocation() const; |
| |
| /// Returns the caller. |
| const FunctionDecl *getCallee() const; |
| |
| /// Returns the current function. |
| Function *getFunction() const { return Func; } |
| |
| /// Returns the offset on the stack at which the frame starts. |
| size_t getFrameOffset() const { return FrameOffset; } |
| |
| /// Returns the value of a local variable. |
| template <typename T> const T &getLocal(unsigned Offset) { |
| return localRef<T>(Offset); |
| } |
| |
| /// Mutates a local variable. |
| template <typename T> void setLocal(unsigned Offset, const T &Value) { |
| localRef<T>(Offset) = Value; |
| } |
| |
| /// Returns a pointer to a local variables. |
| Pointer getLocalPointer(unsigned Offset); |
| |
| /// Returns the value of an argument. |
| template <typename T> const T &getParam(unsigned Offset) { |
| auto Pt = Params.find(Offset); |
| if (Pt == Params.end()) { |
| return stackRef<T>(Offset); |
| } else { |
| return Pointer(reinterpret_cast<Block *>(Pt->second.get())).deref<T>(); |
| } |
| } |
| |
| /// Mutates a local copy of a parameter. |
| template <typename T> void setParam(unsigned Offset, const T &Value) { |
| getParamPointer(Offset).deref<T>() = Value; |
| } |
| |
| /// Returns a pointer to an argument - lazily creates a block. |
| Pointer getParamPointer(unsigned Offset); |
| |
| /// Returns the 'this' pointer. |
| const Pointer &getThis() const { return This; } |
| |
| /// Checks if the frame is a root frame - return should quit the interpreter. |
| bool isRoot() const { return !Func; } |
| |
| /// Returns the PC of the frame's code start. |
| CodePtr getPC() const { return Func->getCodeBegin(); } |
| |
| /// Returns the return address of the frame. |
| CodePtr getRetPC() const { return RetPC; } |
| |
| /// Map a location to a source. |
| virtual SourceInfo getSource(CodePtr PC) const; |
| const Expr *getExpr(CodePtr PC) const; |
| SourceLocation getLocation(CodePtr PC) const; |
| |
| private: |
| /// Returns an original argument from the stack. |
| template <typename T> const T &stackRef(unsigned Offset) { |
| return *reinterpret_cast<const T *>(Args - ArgSize + Offset); |
| } |
| |
| /// Returns an offset to a local. |
| template <typename T> T &localRef(unsigned Offset) { |
| return *reinterpret_cast<T *>(Locals.get() + Offset); |
| } |
| |
| /// Returns a pointer to a local's block. |
| void *localBlock(unsigned Offset) { |
| return Locals.get() + Offset - sizeof(Block); |
| } |
| |
| private: |
| /// Reference to the interpreter state. |
| InterpState &S; |
| /// Reference to the function being executed. |
| Function *Func; |
| /// Current object pointer for methods. |
| Pointer This; |
| /// Return address. |
| CodePtr RetPC; |
| /// The size of all the arguments. |
| const unsigned ArgSize; |
| /// Pointer to the arguments in the callee's frame. |
| char *Args = nullptr; |
| /// Fixed, initial storage for known local variables. |
| std::unique_ptr<char[]> Locals; |
| /// Offset on the stack at entry. |
| const size_t FrameOffset; |
| /// Mapping from arg offsets to their argument blocks. |
| llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Params; |
| }; |
| |
| } // namespace interp |
| } // namespace clang |
| |
| #endif |