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