1a7dea167SDimitry Andric //===--- Context.h - Context 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 // Defines the constexpr execution context. 10a7dea167SDimitry Andric // 11a7dea167SDimitry Andric // The execution context manages cached bytecode and the global context. 12a7dea167SDimitry Andric // It invokes the compiler and interpreter, propagating errors. 13a7dea167SDimitry Andric // 14a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 15a7dea167SDimitry Andric 16a7dea167SDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_CONTEXT_H 17a7dea167SDimitry Andric #define LLVM_CLANG_AST_INTERP_CONTEXT_H 18a7dea167SDimitry Andric 19a7dea167SDimitry Andric #include "InterpStack.h" 20a7dea167SDimitry Andric 21a7dea167SDimitry Andric namespace clang { 22a7dea167SDimitry Andric class ASTContext; 23a7dea167SDimitry Andric class LangOptions; 24a7dea167SDimitry Andric class FunctionDecl; 25a7dea167SDimitry Andric class VarDecl; 265f757f3fSDimitry Andric class APValue; 27a7dea167SDimitry Andric 28a7dea167SDimitry Andric namespace interp { 29a7dea167SDimitry Andric class Function; 30a7dea167SDimitry Andric class Program; 31a7dea167SDimitry Andric class State; 32a7dea167SDimitry Andric enum PrimType : unsigned; 33a7dea167SDimitry Andric 345f757f3fSDimitry Andric struct ParamOffset { 355f757f3fSDimitry Andric unsigned Offset; 365f757f3fSDimitry Andric bool IsPtr; 375f757f3fSDimitry Andric }; 385f757f3fSDimitry Andric 39a7dea167SDimitry Andric /// Holds all information required to evaluate constexpr code in a module. 40bdd1243dSDimitry Andric class Context final { 41a7dea167SDimitry Andric public: 42a7dea167SDimitry Andric /// Initialises the constexpr VM. 43a7dea167SDimitry Andric Context(ASTContext &Ctx); 44a7dea167SDimitry Andric 45a7dea167SDimitry Andric /// Cleans up the constexpr VM. 46a7dea167SDimitry Andric ~Context(); 47a7dea167SDimitry Andric 48a7dea167SDimitry Andric /// Checks if a function is a potential constant expression. 49480093f4SDimitry Andric bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl); 50a7dea167SDimitry Andric 51a7dea167SDimitry Andric /// Evaluates a toplevel expression as an rvalue. 52480093f4SDimitry Andric bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result); 53a7dea167SDimitry Andric 547a6dacacSDimitry Andric /// Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion. 557a6dacacSDimitry Andric bool evaluate(State &Parent, const Expr *E, APValue &Result); 567a6dacacSDimitry Andric 57a7dea167SDimitry Andric /// Evaluates a toplevel initializer. 58480093f4SDimitry Andric bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result); 59a7dea167SDimitry Andric 60a7dea167SDimitry Andric /// Returns the AST context. 61a7dea167SDimitry Andric ASTContext &getASTContext() const { return Ctx; } 62a7dea167SDimitry Andric /// Returns the language options. 63a7dea167SDimitry Andric const LangOptions &getLangOpts() const; 64a7dea167SDimitry Andric /// Returns the interpreter stack. 65a7dea167SDimitry Andric InterpStack &getStack() { return Stk; } 66a7dea167SDimitry Andric /// Returns CHAR_BIT. 67a7dea167SDimitry Andric unsigned getCharBit() const; 6806c3fb27SDimitry Andric /// Return the floating-point semantics for T. 6906c3fb27SDimitry Andric const llvm::fltSemantics &getFloatSemantics(QualType T) const; 705f757f3fSDimitry Andric /// Return the size of T in bits. 715f757f3fSDimitry Andric uint32_t getBitWidth(QualType T) const { return Ctx.getIntWidth(T); } 72a7dea167SDimitry Andric 73*0fca6ea1SDimitry Andric /// Classifies a type. 74bdd1243dSDimitry Andric std::optional<PrimType> classify(QualType T) const; 75a7dea167SDimitry Andric 76*0fca6ea1SDimitry Andric /// Classifies an expression. 77*0fca6ea1SDimitry Andric std::optional<PrimType> classify(const Expr *E) const { 78*0fca6ea1SDimitry Andric assert(E); 79*0fca6ea1SDimitry Andric if (E->isGLValue()) { 80*0fca6ea1SDimitry Andric if (E->getType()->isFunctionType()) 81*0fca6ea1SDimitry Andric return PT_FnPtr; 82*0fca6ea1SDimitry Andric return PT_Ptr; 83*0fca6ea1SDimitry Andric } 84*0fca6ea1SDimitry Andric 85*0fca6ea1SDimitry Andric return classify(E->getType()); 86*0fca6ea1SDimitry Andric } 87*0fca6ea1SDimitry Andric 8806c3fb27SDimitry Andric const CXXMethodDecl * 8906c3fb27SDimitry Andric getOverridingFunction(const CXXRecordDecl *DynamicDecl, 9006c3fb27SDimitry Andric const CXXRecordDecl *StaticDecl, 9106c3fb27SDimitry Andric const CXXMethodDecl *InitialFunction) const; 925f757f3fSDimitry Andric 935f757f3fSDimitry Andric const Function *getOrCreateFunction(const FunctionDecl *FD); 945f757f3fSDimitry Andric 9506c3fb27SDimitry Andric /// Returns whether we should create a global variable for the 9606c3fb27SDimitry Andric /// given ValueDecl. 9706c3fb27SDimitry Andric static bool shouldBeGloballyIndexed(const ValueDecl *VD) { 9806c3fb27SDimitry Andric if (const auto *V = dyn_cast<VarDecl>(VD)) 9906c3fb27SDimitry Andric return V->hasGlobalStorage() || V->isConstexpr(); 10006c3fb27SDimitry Andric 10106c3fb27SDimitry Andric return false; 10206c3fb27SDimitry Andric } 10306c3fb27SDimitry Andric 1045f757f3fSDimitry Andric /// Returns the program. This is only needed for unittests. 1055f757f3fSDimitry Andric Program &getProgram() const { return *P.get(); } 1065f757f3fSDimitry Andric 107*0fca6ea1SDimitry Andric unsigned collectBaseOffset(const RecordDecl *BaseDecl, 108*0fca6ea1SDimitry Andric const RecordDecl *DerivedDecl) const; 109*0fca6ea1SDimitry Andric 110*0fca6ea1SDimitry Andric const Record *getRecord(const RecordDecl *D) const; 111*0fca6ea1SDimitry Andric 112*0fca6ea1SDimitry Andric unsigned getEvalID() const { return EvalID; } 113*0fca6ea1SDimitry Andric 114a7dea167SDimitry Andric private: 115a7dea167SDimitry Andric /// Runs a function. 11606c3fb27SDimitry Andric bool Run(State &Parent, const Function *Func, APValue &Result); 117a7dea167SDimitry Andric 118a7dea167SDimitry Andric /// Current compilation context. 119a7dea167SDimitry Andric ASTContext &Ctx; 120a7dea167SDimitry Andric /// Interpreter stack, shared across invocations. 121a7dea167SDimitry Andric InterpStack Stk; 122a7dea167SDimitry Andric /// Constexpr program. 123a7dea167SDimitry Andric std::unique_ptr<Program> P; 124*0fca6ea1SDimitry Andric /// ID identifying an evaluation. 125*0fca6ea1SDimitry Andric unsigned EvalID = 0; 126a7dea167SDimitry Andric }; 127a7dea167SDimitry Andric 128a7dea167SDimitry Andric } // namespace interp 129a7dea167SDimitry Andric } // namespace clang 130a7dea167SDimitry Andric 131a7dea167SDimitry Andric #endif 132