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