Reapply "[clang][bytecode] Stack-allocate bottom function frame" (#12… (#125349)
[llvm-project.git] / clang / lib / AST / ByteCode / InterpState.h
blobd6adfff1a713ac20c23bbe84b151b3353b061d16
1 //===--- InterpState.h - Interpreter state for the constexpr 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 // Definition of the interpreter state and entry point.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_AST_INTERP_INTERPSTATE_H
14 #define LLVM_CLANG_AST_INTERP_INTERPSTATE_H
16 #include "Context.h"
17 #include "DynamicAllocator.h"
18 #include "Function.h"
19 #include "InterpFrame.h"
20 #include "InterpStack.h"
21 #include "State.h"
22 #include "clang/AST/APValue.h"
23 #include "clang/AST/ASTDiagnostic.h"
24 #include "clang/AST/Expr.h"
25 #include "clang/AST/OptionalDiagnostic.h"
27 namespace clang {
28 namespace interp {
29 class Context;
30 class Function;
31 class InterpStack;
32 class InterpFrame;
33 class SourceMapper;
35 /// Interpreter context.
36 class InterpState final : public State, public SourceMapper {
37 public:
38 InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx,
39 SourceMapper *M = nullptr);
40 InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx,
41 const Function *Func);
43 ~InterpState();
45 void cleanup();
47 InterpState(const InterpState &) = delete;
48 InterpState &operator=(const InterpState &) = delete;
50 // Stack frame accessors.
51 Frame *getSplitFrame() { return Parent.getCurrentFrame(); }
52 Frame *getCurrentFrame() override;
53 unsigned getCallStackDepth() override {
54 return Current ? (Current->getDepth() + 1) : 1;
56 const Frame *getBottomFrame() const override {
57 return Parent.getBottomFrame();
60 // Access objects from the walker context.
61 Expr::EvalStatus &getEvalStatus() const override {
62 return Parent.getEvalStatus();
64 ASTContext &getASTContext() const override { return Parent.getASTContext(); }
66 // Forward status checks and updates to the walker.
67 bool checkingForUndefinedBehavior() const override {
68 return Parent.checkingForUndefinedBehavior();
70 bool keepEvaluatingAfterFailure() const override {
71 return Parent.keepEvaluatingAfterFailure();
73 bool keepEvaluatingAfterSideEffect() const override {
74 return Parent.keepEvaluatingAfterSideEffect();
76 bool checkingPotentialConstantExpression() const override {
77 return Parent.checkingPotentialConstantExpression();
79 bool noteUndefinedBehavior() override {
80 return Parent.noteUndefinedBehavior();
82 bool inConstantContext() const;
83 bool hasActiveDiagnostic() override { return Parent.hasActiveDiagnostic(); }
84 void setActiveDiagnostic(bool Flag) override {
85 Parent.setActiveDiagnostic(Flag);
87 void setFoldFailureDiagnostic(bool Flag) override {
88 Parent.setFoldFailureDiagnostic(Flag);
90 bool hasPriorDiagnostic() override { return Parent.hasPriorDiagnostic(); }
91 bool noteSideEffect() override { return Parent.noteSideEffect(); }
93 /// Reports overflow and return true if evaluation should continue.
94 bool reportOverflow(const Expr *E, const llvm::APSInt &Value);
96 /// Deallocates a pointer.
97 void deallocate(Block *B);
99 /// Delegates source mapping to the mapper.
100 SourceInfo getSource(const Function *F, CodePtr PC) const override {
101 if (M)
102 return M->getSource(F, PC);
104 assert(F && "Function cannot be null");
105 return F->getSource(PC);
108 Context &getContext() const { return Ctx; }
110 void setEvalLocation(SourceLocation SL) { this->EvalLocation = SL; }
112 DynamicAllocator &getAllocator() { return Alloc; }
114 /// Diagnose any dynamic allocations that haven't been freed yet.
115 /// Will return \c false if there were any allocations to diagnose,
116 /// \c true otherwise.
117 bool maybeDiagnoseDanglingAllocations();
119 private:
120 friend class EvaluationResult;
121 friend class InterpStateCCOverride;
122 /// AST Walker state.
123 State &Parent;
124 /// Dead block chain.
125 DeadBlock *DeadBlocks = nullptr;
126 /// Reference to the offset-source mapping.
127 SourceMapper *M;
128 /// Allocator used for dynamic allocations performed via the program.
129 DynamicAllocator Alloc;
130 std::optional<bool> ConstantContextOverride;
132 public:
133 /// Reference to the module containing all bytecode.
134 Program &P;
135 /// Temporary stack.
136 InterpStack &Stk;
137 /// Interpreter Context.
138 Context &Ctx;
139 /// Bottom function frame.
140 InterpFrame BottomFrame;
141 /// The current frame.
142 InterpFrame *Current = nullptr;
143 /// Source location of the evaluating expression
144 SourceLocation EvalLocation;
145 /// Declaration we're initializing/evaluting, if any.
146 const VarDecl *EvaluatingDecl = nullptr;
148 llvm::SmallVector<
149 std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>>
150 SeenGlobalTemporaries;
153 class InterpStateCCOverride final {
154 public:
155 InterpStateCCOverride(InterpState &Ctx, bool Value)
156 : Ctx(Ctx), OldCC(Ctx.ConstantContextOverride) {
157 // We only override this if the new value is true.
158 Enabled = Value;
159 if (Enabled)
160 Ctx.ConstantContextOverride = Value;
162 ~InterpStateCCOverride() {
163 if (Enabled)
164 Ctx.ConstantContextOverride = OldCC;
167 private:
168 bool Enabled;
169 InterpState &Ctx;
170 std::optional<bool> OldCC;
173 } // namespace interp
174 } // namespace clang
176 #endif