clang 24.0.0git
Context.h
Go to the documentation of this file.
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 "FrameAllocator.h"
20#include "InterpStack.h"
22
23namespace clang {
24class LangOptions;
25class FunctionDecl;
26class VarDecl;
27class APValue;
28class BlockExpr;
29
30namespace interp {
31class Function;
32class Program;
33class State;
34enum PrimType : uint8_t;
35struct EvalSettings;
36
38 unsigned Offset;
39 bool IsPtr;
40};
41
42struct FuncParam {
43 unsigned Index;
44 bool IsPtr;
45};
46
47class EvalIDScope;
48/// Holds all information required to evaluate constexpr code in a module.
49class Context final {
50public:
51 /// Initialises the constexpr VM.
52 explicit Context(ASTContext &Ctx);
53
54 /// Cleans up the constexpr VM.
56
57 /// Checks if a function is a potential constant expression.
58 bool isPotentialConstantExpr(const EvalSettings &Settings,
59 const FunctionDecl *FD);
61 const Expr *E,
62 const FunctionDecl *FD);
63
64 /// Evaluates a toplevel expression as an rvalue.
65 bool evaluateAsRValue(const EvalSettings &Settings, const Expr *E,
67
68 /// Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
69 bool evaluate(const EvalSettings &Settings, const Expr *E, APValue &Result);
70
71 /// Evaluates a toplevel initializer.
72 bool evaluateAsInitializer(const EvalSettings &Settings, const VarDecl *VD,
73 const Expr *Init, APValue &Result);
74 void registerRedecl(const VarDecl *VD, const APValue &V);
75
76 /// Evaluates the destruction of a variable.
77 bool evaluateDestruction(const EvalSettings &Settings, const VarDecl *VD,
79
80 bool evaluateCharRange(const EvalSettings &Settings, const Expr *SizeExpr,
81 const Expr *PtrExpr, APValue &Result);
82 bool evaluateCharRange(const EvalSettings &Settings, const Expr *SizeExpr,
83 const Expr *PtrExpr, std::string &Result);
84
85 /// Evaluate \param E and if it can be evaluated to a null-terminated string,
86 /// copy the result into \param Result.
87 bool evaluateString(const EvalSettings &Settings, const Expr *E,
88 std::string &Result);
89
90 /// Evalute \param E and if it can be evaluated to a string literal,
91 /// run strlen() on it.
92 std::optional<uint64_t> evaluateStrlen(const EvalSettings &Settings,
93 const Expr *E);
94
95 /// If \param E evaluates to a pointer the number of accessible bytes
96 /// past the pointer is estimated in \param Result as if evaluated by
97 /// the builtin function __builtin_object_size. This is a best effort
98 /// approximation, when Kind & 2 == 0 the object size is less
99 /// than or equal to the estimated size, when Kind & 2 == 1 the
100 /// true value is greater than or equal to the estimated size.
101 /// When Kind & 1 == 1 only bytes belonging to the same subobject
102 /// as the one referred to by E are considered, when Kind & 1 == 0
103 /// bytes belonging to the same storage (stack, heap allocation,
104 /// global variable) are considered.
105 std::optional<uint64_t> tryEvaluateObjectSize(const EvalSettings &Settings,
106 const Expr *E, unsigned Kind,
107 bool IsDynamic);
108
109 std::optional<bool> evaluateWithSubstitution(const EvalSettings &Settings,
110 const FunctionDecl *Callee,
112 const Expr *This,
113 const Expr *Condition);
114
115 /// Returns the AST context.
116 ASTContext &getASTContext() const { return Ctx; }
117 /// Returns the language options.
118 const LangOptions &getLangOpts() const;
119 /// Returns CHAR_BIT.
120 unsigned getCharBit() const;
121 /// Return the floating-point semantics for T.
122 const llvm::fltSemantics &getFloatSemantics(QualType T) const;
123 /// Return the size of T in bits.
124 uint32_t getBitWidth(QualType T) const { return Ctx.getIntWidth(T); }
125
126 /// Classifies a type.
128
129 /// Classifies an expression.
130 OptPrimType classify(const Expr *E) const {
131 assert(E);
132 if (E->isGLValue())
133 return PT_Ptr;
134
135 return classify(E->getType());
136 }
137
138 bool canClassify(QualType T) const {
139 T = T.getCanonicalType();
140 if (const auto *BT = dyn_cast<BuiltinType>(T)) {
141 if (BT->isInteger() || BT->isFloatingPoint())
142 return true;
143 if (BT->getKind() == BuiltinType::NullPtr ||
144 BT->getKind() == BuiltinType::BoundMember)
145 return true;
146 }
147 if (T->isPointerOrReferenceType())
148 return true;
149
150 if (T->isArrayType() || T->isRecordType() || T->isAnyComplexType() ||
151 T->isVectorType())
152 return false;
153
154 if (T->isEnumeralType())
155 return true;
156
157 return classify(T) != std::nullopt;
158 }
159 bool canClassify(const Expr *E) const {
160 if (E->isGLValue())
161 return true;
162 return canClassify(E->getType());
163 }
164
165 const CXXMethodDecl *
166 getOverridingFunction(const CXXRecordDecl *DynamicDecl,
167 const CXXRecordDecl *StaticDecl,
168 const CXXMethodDecl *InitialFunction) const;
169
170 const Function *getOrCreateFunction(const FunctionDecl *FuncDecl);
171 const Function *getOrCreateObjCBlock(const BlockExpr *E);
172
173 /// Returns whether we should create a global variable for the
174 /// given ValueDecl.
175 static bool shouldBeGloballyIndexed(const ValueDecl *VD) {
176 if (const auto *V = dyn_cast<VarDecl>(VD))
177 return V->hasGlobalStorage() || V->isConstexpr();
178
179 return false;
180 }
181
182 /// Returns the program. This is only needed for unittests.
183 Program &getProgram() const { return *P; }
184
185 unsigned collectBaseOffset(const RecordDecl *BaseDecl,
186 const RecordDecl *DerivedDecl) const;
187
188 const Record *getRecord(const RecordDecl *D) const;
189
190 unsigned getEvalID() const { return EvalID; }
191
192 /// Unevaluated builtins don't get their arguments put on the stack
193 /// automatically. They instead operate on the AST of their Call
194 /// Expression.
195 /// Similar information is available via ASTContext::BuiltinInfo,
196 /// but that is not correct for our use cases.
197 static bool isUnevaluatedBuiltin(unsigned ID);
198
199private:
200 friend class EvalIDScope;
201 /// Runs a function.
202 bool Run(const EvalSettings &Settings, const Function *Func);
203
204 template <typename ResultT>
205 bool evaluateStringRepr(const EvalSettings &Settings, const Expr *SizeExpr,
206 const Expr *PtrExpr, ResultT &Result);
207
208 /// Current compilation context.
209 ASTContext &Ctx;
210 /// Interpreter stack, shared across invocations.
211 InterpStack Stk;
212 /// (Function) frame allocator, also shared.
213 FrameAllocator FrameAlloc;
214 /// Constexpr program.
215 std::unique_ptr<Program> P;
216 /// ID identifying an evaluation.
217 unsigned EvalID = 0;
218 /// Cached widths (in bits) of common types, for a faster classify().
219 unsigned ShortWidth;
220 unsigned IntWidth;
221 unsigned LongWidth;
222 unsigned LongLongWidth;
223};
224
226public:
227 EvalIDScope(Context &Ctx) : Ctx(Ctx), OldID(Ctx.EvalID) { ++Ctx.EvalID; }
228 ~EvalIDScope() { Ctx.EvalID = OldID; }
229 EvalIDScope(const EvalIDScope &) = delete;
231
232private:
233 Context &Ctx;
234 const unsigned OldID;
235};
236
237} // namespace interp
238} // namespace clang
239
240#endif
Defines the clang::ASTContext interface.
#define V(N, I)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:158
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition Expr.h:6726
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2150
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
This represents one expression.
Definition Expr.h:113
bool isGLValue() const
Definition Expr.h:288
QualType getType() const
Definition Expr.h:145
Represents a function declaration or definition.
Definition Decl.h:2059
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A (possibly-)qualified type.
Definition TypeBase.h:938
Represents a struct/union/class.
Definition Decl.h:4464
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
Represents a variable declaration or definition.
Definition Decl.h:933
Holds all information required to evaluate constexpr code in a module.
Definition Context.h:49
std::optional< uint64_t > tryEvaluateObjectSize(const EvalSettings &Settings, const Expr *E, unsigned Kind, bool IsDynamic)
If.
Definition Context.cpp:431
const LangOptions & getLangOpts() const
Returns the language options.
Definition Context.cpp:487
void registerRedecl(const VarDecl *VD, const APValue &V)
Definition Context.cpp:188
OptPrimType classify(const Expr *E) const
Classifies an expression.
Definition Context.h:130
const Function * getOrCreateObjCBlock(const BlockExpr *E)
Definition Context.cpp:766
bool evaluateString(const EvalSettings &Settings, const Expr *E, std::string &Result)
Evaluate.
Definition Context.cpp:298
~Context()
Cleans up the constexpr VM.
bool evaluateDestruction(const EvalSettings &Settings, const VarDecl *VD, APValue Value)
Evaluates the destruction of a variable.
Definition Context.cpp:170
Context(ASTContext &Ctx)
Initialises the constexpr VM.
Definition Context.cpp:30
friend class EvalIDScope
Definition Context.h:200
bool isPotentialConstantExpr(const EvalSettings &Settings, const FunctionDecl *FD)
Checks if a function is a potential constant expression.
Definition Context.cpp:41
static bool isUnevaluatedBuiltin(unsigned ID)
Unevaluated builtins don't get their arguments put on the stack automatically.
Definition Context.cpp:839
unsigned getCharBit() const
Returns CHAR_BIT.
Definition Context.cpp:604
bool canClassify(const Expr *E) const
Definition Context.h:159
std::optional< bool > evaluateWithSubstitution(const EvalSettings &Settings, const FunctionDecl *Callee, ArrayRef< const Expr * > Args, const Expr *This, const Expr *Condition)
Definition Context.cpp:461
Program & getProgram() const
Returns the program. This is only needed for unittests.
Definition Context.h:183
bool evaluate(const EvalSettings &Settings, const Expr *E, APValue &Result)
Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
Definition Context.cpp:106
const llvm::fltSemantics & getFloatSemantics(QualType T) const
Return the floating-point semantics for T.
Definition Context.cpp:610
static bool shouldBeGloballyIndexed(const ValueDecl *VD)
Returns whether we should create a global variable for the given ValueDecl.
Definition Context.h:175
bool evaluateAsInitializer(const EvalSettings &Settings, const VarDecl *VD, const Expr *Init, APValue &Result)
Evaluates a toplevel initializer.
Definition Context.cpp:137
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
Definition Context.cpp:804
const Record * getRecord(const RecordDecl *D) const
Definition Context.cpp:835
bool evaluateAsRValue(const EvalSettings &Settings, const Expr *E, APValue &Result)
Evaluates a toplevel expression as an rvalue.
Definition Context.cpp:76
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
Definition Context.cpp:669
ASTContext & getASTContext() const
Returns the AST context.
Definition Context.h:116
uint32_t getBitWidth(QualType T) const
Return the size of T in bits.
Definition Context.h:124
OptPrimType classify(QualType T) const
Classifies a type.
Definition Context.cpp:521
bool evaluateCharRange(const EvalSettings &Settings, const Expr *SizeExpr, const Expr *PtrExpr, APValue &Result)
Definition Context.cpp:280
std::optional< uint64_t > evaluateStrlen(const EvalSettings &Settings, const Expr *E)
Evalute.
Definition Context.cpp:363
bool canClassify(QualType T) const
Definition Context.h:138
const CXXMethodDecl * getOverridingFunction(const CXXRecordDecl *DynamicDecl, const CXXRecordDecl *StaticDecl, const CXXMethodDecl *InitialFunction) const
Definition Context.cpp:633
unsigned getEvalID() const
Definition Context.h:190
void isPotentialConstantExprUnevaluated(const EvalSettings &Settings, const Expr *E, const FunctionDecl *FD)
Definition Context.cpp:62
EvalIDScope & operator=(const EvalIDScope &)=delete
EvalIDScope(const EvalIDScope &)=delete
EvalIDScope(Context &Ctx)
Definition Context.h:227
Allocator for function frames.
Bytecode function.
Definition Function.h:98
Stack frame storing temporaries and parameters.
Definition InterpStack.h:26
The program contains and links the bytecode for all functions.
Definition Program.h:38
Structure/Class descriptor.
Definition Record.h:27
Interface for the VM to interact with the AST walker's context.
Definition State.h:79
bool This(InterpState &S, CodePtr OpPC)
Definition Interp.h:3223
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:35
bool Init(InterpState &S, CodePtr OpPC)
Definition Interp.h:2420
Top level wrappers for InstallAPI frontend operations.
@ Result
The result type of a method or function.
Definition TypeBase.h:906
const FunctionProtoType * T
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 uint8_t