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