xref: /llvm-project/clang/lib/AST/ByteCode/InterpState.h (revision a024a0ceedae886c254b496c9321f9ef253cd7f8)
1a07aba5dSTimm Baeder //===--- InterpState.h - Interpreter state for the constexpr VM -*- C++ -*-===//
2a07aba5dSTimm Baeder //
3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information.
5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a07aba5dSTimm Baeder //
7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
8a07aba5dSTimm Baeder //
9a07aba5dSTimm Baeder // Definition of the interpreter state and entry point.
10a07aba5dSTimm Baeder //
11a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
12a07aba5dSTimm Baeder 
13a07aba5dSTimm Baeder #ifndef LLVM_CLANG_AST_INTERP_INTERPSTATE_H
14a07aba5dSTimm Baeder #define LLVM_CLANG_AST_INTERP_INTERPSTATE_H
15a07aba5dSTimm Baeder 
16a07aba5dSTimm Baeder #include "Context.h"
17a07aba5dSTimm Baeder #include "DynamicAllocator.h"
18a07aba5dSTimm Baeder #include "Function.h"
19a07aba5dSTimm Baeder #include "InterpFrame.h"
20a07aba5dSTimm Baeder #include "InterpStack.h"
21a07aba5dSTimm Baeder #include "State.h"
22a07aba5dSTimm Baeder #include "clang/AST/APValue.h"
23a07aba5dSTimm Baeder #include "clang/AST/ASTDiagnostic.h"
24a07aba5dSTimm Baeder #include "clang/AST/Expr.h"
25a07aba5dSTimm Baeder #include "clang/AST/OptionalDiagnostic.h"
26a07aba5dSTimm Baeder 
27a07aba5dSTimm Baeder namespace clang {
28a07aba5dSTimm Baeder namespace interp {
29a07aba5dSTimm Baeder class Context;
30a07aba5dSTimm Baeder class Function;
31a07aba5dSTimm Baeder class InterpStack;
32a07aba5dSTimm Baeder class InterpFrame;
33a07aba5dSTimm Baeder class SourceMapper;
34a07aba5dSTimm Baeder 
35a07aba5dSTimm Baeder /// Interpreter context.
36a07aba5dSTimm Baeder class InterpState final : public State, public SourceMapper {
37a07aba5dSTimm Baeder public:
38a07aba5dSTimm Baeder   InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx,
39a07aba5dSTimm Baeder               SourceMapper *M = nullptr);
40a07aba5dSTimm Baeder 
41a07aba5dSTimm Baeder   ~InterpState();
42a07aba5dSTimm Baeder 
43a07aba5dSTimm Baeder   void cleanup();
44a07aba5dSTimm Baeder 
45a07aba5dSTimm Baeder   InterpState(const InterpState &) = delete;
46a07aba5dSTimm Baeder   InterpState &operator=(const InterpState &) = delete;
47a07aba5dSTimm Baeder 
48a07aba5dSTimm Baeder   // Stack frame accessors.
49a07aba5dSTimm Baeder   Frame *getSplitFrame() { return Parent.getCurrentFrame(); }
50a07aba5dSTimm Baeder   Frame *getCurrentFrame() override;
51a07aba5dSTimm Baeder   unsigned getCallStackDepth() override {
52a07aba5dSTimm Baeder     return Current ? (Current->getDepth() + 1) : 1;
53a07aba5dSTimm Baeder   }
54a07aba5dSTimm Baeder   const Frame *getBottomFrame() const override {
55a07aba5dSTimm Baeder     return Parent.getBottomFrame();
56a07aba5dSTimm Baeder   }
57a07aba5dSTimm Baeder 
58a07aba5dSTimm Baeder   // Access objects from the walker context.
59a07aba5dSTimm Baeder   Expr::EvalStatus &getEvalStatus() const override {
60a07aba5dSTimm Baeder     return Parent.getEvalStatus();
61a07aba5dSTimm Baeder   }
62d9e72860Syronglin   ASTContext &getASTContext() const override { return Parent.getASTContext(); }
63a07aba5dSTimm Baeder 
64a07aba5dSTimm Baeder   // Forward status checks and updates to the walker.
65a07aba5dSTimm Baeder   bool checkingForUndefinedBehavior() const override {
66a07aba5dSTimm Baeder     return Parent.checkingForUndefinedBehavior();
67a07aba5dSTimm Baeder   }
68a07aba5dSTimm Baeder   bool keepEvaluatingAfterFailure() const override {
69a07aba5dSTimm Baeder     return Parent.keepEvaluatingAfterFailure();
70a07aba5dSTimm Baeder   }
7183fea8b8STimm Baeder   bool keepEvaluatingAfterSideEffect() const override {
7283fea8b8STimm Baeder     return Parent.keepEvaluatingAfterSideEffect();
7383fea8b8STimm Baeder   }
74a07aba5dSTimm Baeder   bool checkingPotentialConstantExpression() const override {
75a07aba5dSTimm Baeder     return Parent.checkingPotentialConstantExpression();
76a07aba5dSTimm Baeder   }
77a07aba5dSTimm Baeder   bool noteUndefinedBehavior() override {
78a07aba5dSTimm Baeder     return Parent.noteUndefinedBehavior();
79a07aba5dSTimm Baeder   }
80*a024a0ceSTimm Baeder   bool inConstantContext() const;
81a07aba5dSTimm Baeder   bool hasActiveDiagnostic() override { return Parent.hasActiveDiagnostic(); }
82a07aba5dSTimm Baeder   void setActiveDiagnostic(bool Flag) override {
83a07aba5dSTimm Baeder     Parent.setActiveDiagnostic(Flag);
84a07aba5dSTimm Baeder   }
85a07aba5dSTimm Baeder   void setFoldFailureDiagnostic(bool Flag) override {
86a07aba5dSTimm Baeder     Parent.setFoldFailureDiagnostic(Flag);
87a07aba5dSTimm Baeder   }
88a07aba5dSTimm Baeder   bool hasPriorDiagnostic() override { return Parent.hasPriorDiagnostic(); }
8983fea8b8STimm Baeder   bool noteSideEffect() override { return Parent.noteSideEffect(); }
90a07aba5dSTimm Baeder 
91a07aba5dSTimm Baeder   /// Reports overflow and return true if evaluation should continue.
92a07aba5dSTimm Baeder   bool reportOverflow(const Expr *E, const llvm::APSInt &Value);
93a07aba5dSTimm Baeder 
94a07aba5dSTimm Baeder   /// Deallocates a pointer.
95a07aba5dSTimm Baeder   void deallocate(Block *B);
96a07aba5dSTimm Baeder 
97a07aba5dSTimm Baeder   /// Delegates source mapping to the mapper.
98a07aba5dSTimm Baeder   SourceInfo getSource(const Function *F, CodePtr PC) const override {
99a07aba5dSTimm Baeder     if (M)
100a07aba5dSTimm Baeder       return M->getSource(F, PC);
101a07aba5dSTimm Baeder 
102a07aba5dSTimm Baeder     assert(F && "Function cannot be null");
103a07aba5dSTimm Baeder     return F->getSource(PC);
104a07aba5dSTimm Baeder   }
105a07aba5dSTimm Baeder 
106a07aba5dSTimm Baeder   Context &getContext() const { return Ctx; }
107a07aba5dSTimm Baeder 
108a07aba5dSTimm Baeder   void setEvalLocation(SourceLocation SL) { this->EvalLocation = SL; }
109a07aba5dSTimm Baeder 
110a07aba5dSTimm Baeder   DynamicAllocator &getAllocator() { return Alloc; }
111a07aba5dSTimm Baeder 
112a07aba5dSTimm Baeder   /// Diagnose any dynamic allocations that haven't been freed yet.
113a07aba5dSTimm Baeder   /// Will return \c false if there were any allocations to diagnose,
114a07aba5dSTimm Baeder   /// \c true otherwise.
115a07aba5dSTimm Baeder   bool maybeDiagnoseDanglingAllocations();
116a07aba5dSTimm Baeder 
117a07aba5dSTimm Baeder private:
118a07aba5dSTimm Baeder   friend class EvaluationResult;
119*a024a0ceSTimm Baeder   friend class InterpStateCCOverride;
120a07aba5dSTimm Baeder   /// AST Walker state.
121a07aba5dSTimm Baeder   State &Parent;
122a07aba5dSTimm Baeder   /// Dead block chain.
123a07aba5dSTimm Baeder   DeadBlock *DeadBlocks = nullptr;
124a07aba5dSTimm Baeder   /// Reference to the offset-source mapping.
125a07aba5dSTimm Baeder   SourceMapper *M;
126a07aba5dSTimm Baeder   /// Allocator used for dynamic allocations performed via the program.
127a07aba5dSTimm Baeder   DynamicAllocator Alloc;
128*a024a0ceSTimm Baeder   std::optional<bool> ConstantContextOverride;
129a07aba5dSTimm Baeder 
130a07aba5dSTimm Baeder public:
131a07aba5dSTimm Baeder   /// Reference to the module containing all bytecode.
132a07aba5dSTimm Baeder   Program &P;
133a07aba5dSTimm Baeder   /// Temporary stack.
134a07aba5dSTimm Baeder   InterpStack &Stk;
135a07aba5dSTimm Baeder   /// Interpreter Context.
136a07aba5dSTimm Baeder   Context &Ctx;
137a07aba5dSTimm Baeder   /// The current frame.
138a07aba5dSTimm Baeder   InterpFrame *Current = nullptr;
139a07aba5dSTimm Baeder   /// Source location of the evaluating expression
140a07aba5dSTimm Baeder   SourceLocation EvalLocation;
141a07aba5dSTimm Baeder   /// Declaration we're initializing/evaluting, if any.
142a07aba5dSTimm Baeder   const VarDecl *EvaluatingDecl = nullptr;
143a07aba5dSTimm Baeder 
144a07aba5dSTimm Baeder   llvm::SmallVector<
145a07aba5dSTimm Baeder       std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>>
146a07aba5dSTimm Baeder       SeenGlobalTemporaries;
147a07aba5dSTimm Baeder };
148a07aba5dSTimm Baeder 
149*a024a0ceSTimm Baeder class InterpStateCCOverride final {
150*a024a0ceSTimm Baeder public:
151*a024a0ceSTimm Baeder   InterpStateCCOverride(InterpState &Ctx, bool Value)
152*a024a0ceSTimm Baeder       : Ctx(Ctx), OldCC(Ctx.ConstantContextOverride) {
153*a024a0ceSTimm Baeder     // We only override this if the new value is true.
154*a024a0ceSTimm Baeder     Enabled = Value;
155*a024a0ceSTimm Baeder     if (Enabled)
156*a024a0ceSTimm Baeder       Ctx.ConstantContextOverride = Value;
157*a024a0ceSTimm Baeder   }
158*a024a0ceSTimm Baeder   ~InterpStateCCOverride() {
159*a024a0ceSTimm Baeder     if (Enabled)
160*a024a0ceSTimm Baeder       Ctx.ConstantContextOverride = OldCC;
161*a024a0ceSTimm Baeder   }
162*a024a0ceSTimm Baeder 
163*a024a0ceSTimm Baeder private:
164*a024a0ceSTimm Baeder   bool Enabled;
165*a024a0ceSTimm Baeder   InterpState &Ctx;
166*a024a0ceSTimm Baeder   std::optional<bool> OldCC;
167*a024a0ceSTimm Baeder };
168*a024a0ceSTimm Baeder 
169a07aba5dSTimm Baeder } // namespace interp
170a07aba5dSTimm Baeder } // namespace clang
171a07aba5dSTimm Baeder 
172a07aba5dSTimm Baeder #endif
173