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