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