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