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