1//===--- InterpFrame.h - Call Frame implementation for the VM ---*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Defines the class storing information about stack frames in the interpreter.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_INTERP_INTERPFRAME_H
14#define LLVM_CLANG_AST_INTERP_INTERPFRAME_H
15
16#include "Frame.h"
17#include "Program.h"
18#include <cstdint>
19#include <vector>
20
21namespace clang {
22namespace interp {
23class Function;
24class InterpState;
25class Pointer;
26
27/// Frame storing local variables.
28class InterpFrame final : public Frame {
29public:
30 /// The frame of the previous function.
31 InterpFrame *Caller;
32
33 /// Creates a new frame for a method call.
34 InterpFrame(InterpState &S, const Function *Func, InterpFrame *Caller,
35 CodePtr RetPC, unsigned ArgSize);
36
37 /// 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.
41 InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC,
42 unsigned VarArgSize = 0);
43
44 /// Destroys the frame, killing all live pointers to stack slots.
45 ~InterpFrame();
46
47 /// Invokes the destructors for a scope.
48 void destroy(unsigned Idx);
49
50 /// Pops the arguments off the stack.
51 void popArgs();
52
53 /// Describes the frame with arguments for diagnostic purposes.
54 void describe(llvm::raw_ostream &OS) const override;
55
56 /// Returns the parent frame object.
57 Frame *getCaller() const override;
58
59 /// Returns the location of the call to the frame.
60 SourceRange getCallRange() const override;
61
62 /// Returns the caller.
63 const FunctionDecl *getCallee() const override;
64
65 /// Returns the current function.
66 const Function *getFunction() const { return Func; }
67
68 /// Returns the offset on the stack at which the frame starts.
69 size_t getFrameOffset() const { return FrameOffset; }
70
71 /// Returns the value of a local variable.
72 template <typename T> const T &getLocal(unsigned Offset) const {
73 return localRef<T>(Offset);
74 }
75
76 /// Mutates a local variable.
77 template <typename T> void setLocal(unsigned Offset, const T &Value) {
78 localRef<T>(Offset) = Value;
79 localInlineDesc(Offset)->IsInitialized = true;
80 }
81
82 /// Returns a pointer to a local variables.
83 Pointer getLocalPointer(unsigned Offset) const;
84
85 /// Returns the value of an argument.
86 template <typename T> const T &getParam(unsigned Offset) const {
87 auto Pt = Params.find(Val: Offset);
88 if (Pt == Params.end()) {
89 return stackRef<T>(Offset);
90 } else {
91 return Pointer(reinterpret_cast<Block *>(Pt->second.get())).deref<T>();
92 }
93 }
94
95 /// Mutates a local copy of a parameter.
96 template <typename T> void setParam(unsigned Offset, const T &Value) {
97 getParamPointer(Offset).deref<T>() = Value;
98 }
99
100 /// Returns a pointer to an argument - lazily creates a block.
101 Pointer getParamPointer(unsigned Offset);
102
103 /// Returns the 'this' pointer.
104 const Pointer &getThis() const { return This; }
105
106 /// Returns the RVO pointer, if the Function has one.
107 const Pointer &getRVOPtr() const { return RVOPtr; }
108
109 /// Checks if the frame is a root frame - return should quit the interpreter.
110 bool isRoot() const { return !Func; }
111
112 /// Returns the PC of the frame's code start.
113 CodePtr getPC() const { return Func->getCodeBegin(); }
114
115 /// Returns the return address of the frame.
116 CodePtr getRetPC() const { return RetPC; }
117
118 /// Map a location to a source.
119 virtual SourceInfo getSource(CodePtr PC) const;
120 const Expr *getExpr(CodePtr PC) const;
121 SourceLocation getLocation(CodePtr PC) const;
122 SourceRange getRange(CodePtr PC) const;
123
124 unsigned getDepth() const { return Depth; }
125
126 void dump() const { dump(OS&: llvm::errs(), Indent: 0); }
127 void dump(llvm::raw_ostream &OS, unsigned Indent = 0) const;
128
129private:
130 /// Returns an original argument from the stack.
131 template <typename T> const T &stackRef(unsigned Offset) const {
132 assert(Args);
133 return *reinterpret_cast<const T *>(Args - ArgSize + Offset);
134 }
135
136 /// Returns an offset to a local.
137 template <typename T> T &localRef(unsigned Offset) const {
138 return getLocalPointer(Offset).deref<T>();
139 }
140
141 /// Returns a pointer to a local's block.
142 Block *localBlock(unsigned Offset) const {
143 return reinterpret_cast<Block *>(Locals.get() + Offset - sizeof(Block));
144 }
145
146 /// Returns the inline descriptor of the local.
147 InlineDescriptor *localInlineDesc(unsigned Offset) const {
148 return reinterpret_cast<InlineDescriptor *>(Locals.get() + Offset);
149 }
150
151private:
152 /// Reference to the interpreter state.
153 InterpState &S;
154 /// Depth of this frame.
155 unsigned Depth;
156 /// Reference to the function being executed.
157 const Function *Func;
158 /// Current object pointer for methods.
159 Pointer This;
160 /// Pointer the non-primitive return value gets constructed in.
161 Pointer RVOPtr;
162 /// Return address.
163 CodePtr RetPC;
164 /// The size of all the arguments.
165 const unsigned ArgSize;
166 /// Pointer to the arguments in the callee's frame.
167 char *Args = nullptr;
168 /// Fixed, initial storage for known local variables.
169 std::unique_ptr<char[]> Locals;
170 /// Offset on the stack at entry.
171 const size_t FrameOffset;
172 /// Mapping from arg offsets to their argument blocks.
173 llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Params;
174};
175
176} // namespace interp
177} // namespace clang
178
179#endif
180

source code of clang/lib/AST/Interp/InterpFrame.h