xref: /freebsd/contrib/llvm-project/clang/lib/AST/ByteCode/Context.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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