1*700637cbSDimitry Andric //===--- Context.h - Context for the constexpr VM ---------------*- C++ -*-===// 2*700637cbSDimitry Andric // 3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*700637cbSDimitry Andric // 7*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 8*700637cbSDimitry Andric // 9*700637cbSDimitry Andric // Defines the constexpr execution context. 10*700637cbSDimitry Andric // 11*700637cbSDimitry Andric // The execution context manages cached bytecode and the global context. 12*700637cbSDimitry Andric // It invokes the compiler and interpreter, propagating errors. 13*700637cbSDimitry Andric // 14*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 15*700637cbSDimitry Andric 16*700637cbSDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_CONTEXT_H 17*700637cbSDimitry Andric #define LLVM_CLANG_AST_INTERP_CONTEXT_H 18*700637cbSDimitry Andric 19*700637cbSDimitry Andric #include "InterpStack.h" 20*700637cbSDimitry Andric 21*700637cbSDimitry Andric namespace clang { 22*700637cbSDimitry Andric class ASTContext; 23*700637cbSDimitry Andric class LangOptions; 24*700637cbSDimitry Andric class FunctionDecl; 25*700637cbSDimitry Andric class VarDecl; 26*700637cbSDimitry Andric class APValue; 27*700637cbSDimitry Andric class BlockExpr; 28*700637cbSDimitry Andric 29*700637cbSDimitry Andric namespace interp { 30*700637cbSDimitry Andric class Function; 31*700637cbSDimitry Andric class Program; 32*700637cbSDimitry Andric class State; 33*700637cbSDimitry Andric enum PrimType : unsigned; 34*700637cbSDimitry Andric 35*700637cbSDimitry Andric struct ParamOffset { 36*700637cbSDimitry Andric unsigned Offset; 37*700637cbSDimitry Andric bool IsPtr; 38*700637cbSDimitry Andric }; 39*700637cbSDimitry Andric 40*700637cbSDimitry Andric /// Holds all information required to evaluate constexpr code in a module. 41*700637cbSDimitry Andric class Context final { 42*700637cbSDimitry Andric public: 43*700637cbSDimitry Andric /// Initialises the constexpr VM. 44*700637cbSDimitry Andric Context(ASTContext &Ctx); 45*700637cbSDimitry Andric 46*700637cbSDimitry Andric /// Cleans up the constexpr VM. 47*700637cbSDimitry Andric ~Context(); 48*700637cbSDimitry Andric 49*700637cbSDimitry Andric /// Checks if a function is a potential constant expression. 50*700637cbSDimitry Andric bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl); 51*700637cbSDimitry Andric 52*700637cbSDimitry Andric /// Evaluates a toplevel expression as an rvalue. 53*700637cbSDimitry Andric bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result); 54*700637cbSDimitry Andric 55*700637cbSDimitry Andric /// Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion. 56*700637cbSDimitry Andric bool evaluate(State &Parent, const Expr *E, APValue &Result, 57*700637cbSDimitry Andric ConstantExprKind Kind); 58*700637cbSDimitry Andric 59*700637cbSDimitry Andric /// Evaluates a toplevel initializer. 60*700637cbSDimitry Andric bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result); 61*700637cbSDimitry Andric 62*700637cbSDimitry Andric bool evaluateCharRange(State &Parent, const Expr *SizeExpr, 63*700637cbSDimitry Andric const Expr *PtrExpr, APValue &Result); 64*700637cbSDimitry Andric bool evaluateCharRange(State &Parent, const Expr *SizeExpr, 65*700637cbSDimitry Andric const Expr *PtrExpr, std::string &Result); 66*700637cbSDimitry Andric 67*700637cbSDimitry Andric /// Returns the AST context. getASTContext()68*700637cbSDimitry Andric ASTContext &getASTContext() const { return Ctx; } 69*700637cbSDimitry Andric /// Returns the language options. 70*700637cbSDimitry Andric const LangOptions &getLangOpts() const; 71*700637cbSDimitry Andric /// Returns CHAR_BIT. 72*700637cbSDimitry Andric unsigned getCharBit() const; 73*700637cbSDimitry Andric /// Return the floating-point semantics for T. 74*700637cbSDimitry Andric const llvm::fltSemantics &getFloatSemantics(QualType T) const; 75*700637cbSDimitry Andric /// Return the size of T in bits. getBitWidth(QualType T)76*700637cbSDimitry Andric uint32_t getBitWidth(QualType T) const { return Ctx.getIntWidth(T); } 77*700637cbSDimitry Andric 78*700637cbSDimitry Andric /// Classifies a type. 79*700637cbSDimitry Andric std::optional<PrimType> classify(QualType T) const; 80*700637cbSDimitry Andric 81*700637cbSDimitry Andric /// Classifies an expression. classify(const Expr * E)82*700637cbSDimitry Andric std::optional<PrimType> classify(const Expr *E) const { 83*700637cbSDimitry Andric assert(E); 84*700637cbSDimitry Andric if (E->isGLValue()) 85*700637cbSDimitry Andric return PT_Ptr; 86*700637cbSDimitry Andric 87*700637cbSDimitry Andric return classify(E->getType()); 88*700637cbSDimitry Andric } 89*700637cbSDimitry Andric 90*700637cbSDimitry Andric const CXXMethodDecl * 91*700637cbSDimitry Andric getOverridingFunction(const CXXRecordDecl *DynamicDecl, 92*700637cbSDimitry Andric const CXXRecordDecl *StaticDecl, 93*700637cbSDimitry Andric const CXXMethodDecl *InitialFunction) const; 94*700637cbSDimitry Andric 95*700637cbSDimitry Andric const Function *getOrCreateFunction(const FunctionDecl *FuncDecl); 96*700637cbSDimitry Andric const Function *getOrCreateObjCBlock(const BlockExpr *E); 97*700637cbSDimitry Andric 98*700637cbSDimitry Andric /// Returns whether we should create a global variable for the 99*700637cbSDimitry Andric /// given ValueDecl. shouldBeGloballyIndexed(const ValueDecl * VD)100*700637cbSDimitry Andric static bool shouldBeGloballyIndexed(const ValueDecl *VD) { 101*700637cbSDimitry Andric if (const auto *V = dyn_cast<VarDecl>(VD)) 102*700637cbSDimitry Andric return V->hasGlobalStorage() || V->isConstexpr(); 103*700637cbSDimitry Andric 104*700637cbSDimitry Andric return false; 105*700637cbSDimitry Andric } 106*700637cbSDimitry Andric 107*700637cbSDimitry Andric /// Returns the program. This is only needed for unittests. getProgram()108*700637cbSDimitry Andric Program &getProgram() const { return *P; } 109*700637cbSDimitry Andric 110*700637cbSDimitry Andric unsigned collectBaseOffset(const RecordDecl *BaseDecl, 111*700637cbSDimitry Andric const RecordDecl *DerivedDecl) const; 112*700637cbSDimitry Andric 113*700637cbSDimitry Andric const Record *getRecord(const RecordDecl *D) const; 114*700637cbSDimitry Andric getEvalID()115*700637cbSDimitry Andric unsigned getEvalID() const { return EvalID; } 116*700637cbSDimitry Andric 117*700637cbSDimitry Andric /// Unevaluated builtins don't get their arguments put on the stack 118*700637cbSDimitry Andric /// automatically. They instead operate on the AST of their Call 119*700637cbSDimitry Andric /// Expression. 120*700637cbSDimitry Andric /// Similar information is available via ASTContext::BuiltinInfo, 121*700637cbSDimitry Andric /// but that is not correct for our use cases. 122*700637cbSDimitry Andric static bool isUnevaluatedBuiltin(unsigned ID); 123*700637cbSDimitry Andric 124*700637cbSDimitry Andric private: 125*700637cbSDimitry Andric /// Runs a function. 126*700637cbSDimitry Andric bool Run(State &Parent, const Function *Func); 127*700637cbSDimitry Andric 128*700637cbSDimitry Andric template <typename ResultT> 129*700637cbSDimitry Andric bool evaluateStringRepr(State &Parent, const Expr *SizeExpr, 130*700637cbSDimitry Andric const Expr *PtrExpr, ResultT &Result); 131*700637cbSDimitry Andric 132*700637cbSDimitry Andric /// Current compilation context. 133*700637cbSDimitry Andric ASTContext &Ctx; 134*700637cbSDimitry Andric /// Interpreter stack, shared across invocations. 135*700637cbSDimitry Andric InterpStack Stk; 136*700637cbSDimitry Andric /// Constexpr program. 137*700637cbSDimitry Andric std::unique_ptr<Program> P; 138*700637cbSDimitry Andric /// ID identifying an evaluation. 139*700637cbSDimitry Andric unsigned EvalID = 0; 140*700637cbSDimitry Andric /// Cached widths (in bits) of common types, for a faster classify(). 141*700637cbSDimitry Andric unsigned ShortWidth; 142*700637cbSDimitry Andric unsigned IntWidth; 143*700637cbSDimitry Andric unsigned LongWidth; 144*700637cbSDimitry Andric unsigned LongLongWidth; 145*700637cbSDimitry Andric }; 146*700637cbSDimitry Andric 147*700637cbSDimitry Andric } // namespace interp 148*700637cbSDimitry Andric } // namespace clang 149*700637cbSDimitry Andric 150*700637cbSDimitry Andric #endif 151