xref: /llvm-project/clang/lib/AST/ByteCode/Context.cpp (revision 2c934dc5e1a3ef7b717400f27d6b9ea21f4e20a0)
1a07aba5dSTimm Baeder //===--- Context.cpp - Context for the constexpr VM -------------*- C++ -*-===//
2a07aba5dSTimm Baeder //
3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information.
5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a07aba5dSTimm Baeder //
7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
8a07aba5dSTimm Baeder 
9a07aba5dSTimm Baeder #include "Context.h"
10a07aba5dSTimm Baeder #include "ByteCodeEmitter.h"
11a07aba5dSTimm Baeder #include "Compiler.h"
12a07aba5dSTimm Baeder #include "EvalEmitter.h"
13a07aba5dSTimm Baeder #include "Interp.h"
14a07aba5dSTimm Baeder #include "InterpFrame.h"
15a07aba5dSTimm Baeder #include "InterpStack.h"
16a07aba5dSTimm Baeder #include "PrimType.h"
17a07aba5dSTimm Baeder #include "Program.h"
18a07aba5dSTimm Baeder #include "clang/AST/Expr.h"
19a07aba5dSTimm Baeder #include "clang/Basic/TargetInfo.h"
20a07aba5dSTimm Baeder 
21a07aba5dSTimm Baeder using namespace clang;
22a07aba5dSTimm Baeder using namespace clang::interp;
23a07aba5dSTimm Baeder 
24a07aba5dSTimm Baeder Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {}
25a07aba5dSTimm Baeder 
26a07aba5dSTimm Baeder Context::~Context() {}
27a07aba5dSTimm Baeder 
28a07aba5dSTimm Baeder bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
29a07aba5dSTimm Baeder   assert(Stk.empty());
30*2c934dc5STimm Baeder   const Function *Func = getOrCreateFunction(FD);
31a07aba5dSTimm Baeder   if (!Func)
32a07aba5dSTimm Baeder     return false;
33a07aba5dSTimm Baeder 
3482ed9c03STimm Baeder   if (!Run(Parent, Func))
35a07aba5dSTimm Baeder     return false;
36a07aba5dSTimm Baeder 
37a07aba5dSTimm Baeder   return Func->isConstexpr();
38a07aba5dSTimm Baeder }
39a07aba5dSTimm Baeder 
40a07aba5dSTimm Baeder bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
41a07aba5dSTimm Baeder   ++EvalID;
42a07aba5dSTimm Baeder   bool Recursing = !Stk.empty();
43eef8116bSTimm Baeder   size_t StackSizeBefore = Stk.size();
44a07aba5dSTimm Baeder   Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
45a07aba5dSTimm Baeder 
46a07aba5dSTimm Baeder   auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());
47a07aba5dSTimm Baeder 
48a07aba5dSTimm Baeder   if (Res.isInvalid()) {
49a07aba5dSTimm Baeder     C.cleanup();
50eef8116bSTimm Baeder     Stk.clearTo(StackSizeBefore);
51a07aba5dSTimm Baeder     return false;
52a07aba5dSTimm Baeder   }
53a07aba5dSTimm Baeder 
54a07aba5dSTimm Baeder   if (!Recursing) {
55a07aba5dSTimm Baeder     assert(Stk.empty());
56a07aba5dSTimm Baeder     C.cleanup();
57a07aba5dSTimm Baeder #ifndef NDEBUG
58a07aba5dSTimm Baeder     // Make sure we don't rely on some value being still alive in
59a07aba5dSTimm Baeder     // InterpStack memory.
60eef8116bSTimm Baeder     Stk.clearTo(StackSizeBefore);
61a07aba5dSTimm Baeder #endif
62a07aba5dSTimm Baeder   }
63a07aba5dSTimm Baeder 
64a07aba5dSTimm Baeder   Result = Res.toAPValue();
65a07aba5dSTimm Baeder 
66a07aba5dSTimm Baeder   return true;
67a07aba5dSTimm Baeder }
68a07aba5dSTimm Baeder 
6983fea8b8STimm Baeder bool Context::evaluate(State &Parent, const Expr *E, APValue &Result,
7083fea8b8STimm Baeder                        ConstantExprKind Kind) {
71a07aba5dSTimm Baeder   ++EvalID;
72a07aba5dSTimm Baeder   bool Recursing = !Stk.empty();
73eef8116bSTimm Baeder   size_t StackSizeBefore = Stk.size();
74a07aba5dSTimm Baeder   Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
75a07aba5dSTimm Baeder 
7683fea8b8STimm Baeder   auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/false,
773eaf4a9dSTimm Baeder                              /*DestroyToplevelScope=*/true);
78a07aba5dSTimm Baeder   if (Res.isInvalid()) {
79a07aba5dSTimm Baeder     C.cleanup();
80eef8116bSTimm Baeder     Stk.clearTo(StackSizeBefore);
81a07aba5dSTimm Baeder     return false;
82a07aba5dSTimm Baeder   }
83a07aba5dSTimm Baeder 
84a07aba5dSTimm Baeder   if (!Recursing) {
85a07aba5dSTimm Baeder     assert(Stk.empty());
86a07aba5dSTimm Baeder     C.cleanup();
87a07aba5dSTimm Baeder #ifndef NDEBUG
88a07aba5dSTimm Baeder     // Make sure we don't rely on some value being still alive in
89a07aba5dSTimm Baeder     // InterpStack memory.
90eef8116bSTimm Baeder     Stk.clearTo(StackSizeBefore);
91a07aba5dSTimm Baeder #endif
92a07aba5dSTimm Baeder   }
93a07aba5dSTimm Baeder 
94a07aba5dSTimm Baeder   Result = Res.toAPValue();
95a07aba5dSTimm Baeder   return true;
96a07aba5dSTimm Baeder }
97a07aba5dSTimm Baeder 
98a07aba5dSTimm Baeder bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
99a07aba5dSTimm Baeder                                     APValue &Result) {
100a07aba5dSTimm Baeder   ++EvalID;
101a07aba5dSTimm Baeder   bool Recursing = !Stk.empty();
102eef8116bSTimm Baeder   size_t StackSizeBefore = Stk.size();
103a07aba5dSTimm Baeder   Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
104a07aba5dSTimm Baeder 
105a07aba5dSTimm Baeder   bool CheckGlobalInitialized =
106a07aba5dSTimm Baeder       shouldBeGloballyIndexed(VD) &&
107a07aba5dSTimm Baeder       (VD->getType()->isRecordType() || VD->getType()->isArrayType());
108a07aba5dSTimm Baeder   auto Res = C.interpretDecl(VD, CheckGlobalInitialized);
109a07aba5dSTimm Baeder   if (Res.isInvalid()) {
110a07aba5dSTimm Baeder     C.cleanup();
111eef8116bSTimm Baeder     Stk.clearTo(StackSizeBefore);
112eef8116bSTimm Baeder 
113a07aba5dSTimm Baeder     return false;
114a07aba5dSTimm Baeder   }
115a07aba5dSTimm Baeder 
116a07aba5dSTimm Baeder   if (!Recursing) {
117a07aba5dSTimm Baeder     assert(Stk.empty());
118a07aba5dSTimm Baeder     C.cleanup();
119a07aba5dSTimm Baeder #ifndef NDEBUG
120a07aba5dSTimm Baeder     // Make sure we don't rely on some value being still alive in
121a07aba5dSTimm Baeder     // InterpStack memory.
122eef8116bSTimm Baeder     Stk.clearTo(StackSizeBefore);
123a07aba5dSTimm Baeder #endif
124a07aba5dSTimm Baeder   }
125a07aba5dSTimm Baeder 
126a07aba5dSTimm Baeder   Result = Res.toAPValue();
127a07aba5dSTimm Baeder   return true;
128a07aba5dSTimm Baeder }
129a07aba5dSTimm Baeder 
130a07aba5dSTimm Baeder const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
131a07aba5dSTimm Baeder 
132a07aba5dSTimm Baeder std::optional<PrimType> Context::classify(QualType T) const {
133a07aba5dSTimm Baeder   if (T->isBooleanType())
134a07aba5dSTimm Baeder     return PT_Bool;
135a07aba5dSTimm Baeder 
136a07aba5dSTimm Baeder   // We map these to primitive arrays.
137a07aba5dSTimm Baeder   if (T->isAnyComplexType() || T->isVectorType())
138a07aba5dSTimm Baeder     return std::nullopt;
139a07aba5dSTimm Baeder 
140a07aba5dSTimm Baeder   if (T->isSignedIntegerOrEnumerationType()) {
141a07aba5dSTimm Baeder     switch (Ctx.getIntWidth(T)) {
142a07aba5dSTimm Baeder     case 64:
143a07aba5dSTimm Baeder       return PT_Sint64;
144a07aba5dSTimm Baeder     case 32:
145a07aba5dSTimm Baeder       return PT_Sint32;
146a07aba5dSTimm Baeder     case 16:
147a07aba5dSTimm Baeder       return PT_Sint16;
148a07aba5dSTimm Baeder     case 8:
149a07aba5dSTimm Baeder       return PT_Sint8;
150a07aba5dSTimm Baeder     default:
151a07aba5dSTimm Baeder       return PT_IntAPS;
152a07aba5dSTimm Baeder     }
153a07aba5dSTimm Baeder   }
154a07aba5dSTimm Baeder 
155a07aba5dSTimm Baeder   if (T->isUnsignedIntegerOrEnumerationType()) {
156a07aba5dSTimm Baeder     switch (Ctx.getIntWidth(T)) {
157a07aba5dSTimm Baeder     case 64:
158a07aba5dSTimm Baeder       return PT_Uint64;
159a07aba5dSTimm Baeder     case 32:
160a07aba5dSTimm Baeder       return PT_Uint32;
161a07aba5dSTimm Baeder     case 16:
162a07aba5dSTimm Baeder       return PT_Uint16;
163a07aba5dSTimm Baeder     case 8:
164a07aba5dSTimm Baeder       return PT_Uint8;
165f620c5b6STimm Baeder     case 1:
166f620c5b6STimm Baeder       // Might happen for enum types.
167f620c5b6STimm Baeder       return PT_Bool;
168a07aba5dSTimm Baeder     default:
169a07aba5dSTimm Baeder       return PT_IntAP;
170a07aba5dSTimm Baeder     }
171a07aba5dSTimm Baeder   }
172a07aba5dSTimm Baeder 
173a07aba5dSTimm Baeder   if (T->isNullPtrType())
174a07aba5dSTimm Baeder     return PT_Ptr;
175a07aba5dSTimm Baeder 
176a07aba5dSTimm Baeder   if (T->isFloatingType())
177a07aba5dSTimm Baeder     return PT_Float;
178a07aba5dSTimm Baeder 
179a07aba5dSTimm Baeder   if (T->isSpecificBuiltinType(BuiltinType::BoundMember) ||
180a07aba5dSTimm Baeder       T->isMemberPointerType())
181a07aba5dSTimm Baeder     return PT_MemberPtr;
182a07aba5dSTimm Baeder 
183a07aba5dSTimm Baeder   if (T->isFunctionPointerType() || T->isFunctionReferenceType() ||
184ca148b21STimm Baeder       T->isFunctionType() || T->isBlockPointerType())
185a07aba5dSTimm Baeder     return PT_FnPtr;
186a07aba5dSTimm Baeder 
187a07aba5dSTimm Baeder   if (T->isPointerOrReferenceType() || T->isObjCObjectPointerType())
188a07aba5dSTimm Baeder     return PT_Ptr;
189a07aba5dSTimm Baeder 
190a07aba5dSTimm Baeder   if (const auto *AT = T->getAs<AtomicType>())
191a07aba5dSTimm Baeder     return classify(AT->getValueType());
192a07aba5dSTimm Baeder 
193a07aba5dSTimm Baeder   if (const auto *DT = dyn_cast<DecltypeType>(T))
194a07aba5dSTimm Baeder     return classify(DT->getUnderlyingType());
195a07aba5dSTimm Baeder 
196048bc672STimm Baeder   if (T->isFixedPointType())
197048bc672STimm Baeder     return PT_FixedPoint;
198048bc672STimm Baeder 
199a07aba5dSTimm Baeder   return std::nullopt;
200a07aba5dSTimm Baeder }
201a07aba5dSTimm Baeder 
202a07aba5dSTimm Baeder unsigned Context::getCharBit() const {
203a07aba5dSTimm Baeder   return Ctx.getTargetInfo().getCharWidth();
204a07aba5dSTimm Baeder }
205a07aba5dSTimm Baeder 
206a07aba5dSTimm Baeder /// Simple wrapper around getFloatTypeSemantics() to make code a
207a07aba5dSTimm Baeder /// little shorter.
208a07aba5dSTimm Baeder const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
209a07aba5dSTimm Baeder   return Ctx.getFloatTypeSemantics(T);
210a07aba5dSTimm Baeder }
211a07aba5dSTimm Baeder 
21282ed9c03STimm Baeder bool Context::Run(State &Parent, const Function *Func) {
213a07aba5dSTimm Baeder 
214a07aba5dSTimm Baeder   {
215a07aba5dSTimm Baeder     InterpState State(Parent, *P, Stk, *this);
216a07aba5dSTimm Baeder     State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, CodePtr(),
217a07aba5dSTimm Baeder                                     Func->getArgSize());
21882ed9c03STimm Baeder     if (Interpret(State)) {
219a07aba5dSTimm Baeder       assert(Stk.empty());
220a07aba5dSTimm Baeder       return true;
221a07aba5dSTimm Baeder     }
222a07aba5dSTimm Baeder 
223a07aba5dSTimm Baeder     // State gets destroyed here, so the Stk.clear() below doesn't accidentally
224a07aba5dSTimm Baeder     // remove values the State's destructor might access.
225a07aba5dSTimm Baeder   }
226a07aba5dSTimm Baeder 
227a07aba5dSTimm Baeder   Stk.clear();
228a07aba5dSTimm Baeder   return false;
229a07aba5dSTimm Baeder }
230a07aba5dSTimm Baeder 
231a07aba5dSTimm Baeder // TODO: Virtual bases?
232a07aba5dSTimm Baeder const CXXMethodDecl *
233a07aba5dSTimm Baeder Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl,
234a07aba5dSTimm Baeder                                const CXXRecordDecl *StaticDecl,
235a07aba5dSTimm Baeder                                const CXXMethodDecl *InitialFunction) const {
236a07aba5dSTimm Baeder   assert(DynamicDecl);
237a07aba5dSTimm Baeder   assert(StaticDecl);
238a07aba5dSTimm Baeder   assert(InitialFunction);
239a07aba5dSTimm Baeder 
240a07aba5dSTimm Baeder   const CXXRecordDecl *CurRecord = DynamicDecl;
241a07aba5dSTimm Baeder   const CXXMethodDecl *FoundFunction = InitialFunction;
242a07aba5dSTimm Baeder   for (;;) {
243a07aba5dSTimm Baeder     const CXXMethodDecl *Overrider =
244a07aba5dSTimm Baeder         FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false);
245a07aba5dSTimm Baeder     if (Overrider)
246a07aba5dSTimm Baeder       return Overrider;
247a07aba5dSTimm Baeder 
248a07aba5dSTimm Baeder     // Common case of only one base class.
249a07aba5dSTimm Baeder     if (CurRecord->getNumBases() == 1) {
250a07aba5dSTimm Baeder       CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl();
251a07aba5dSTimm Baeder       continue;
252a07aba5dSTimm Baeder     }
253a07aba5dSTimm Baeder 
254a07aba5dSTimm Baeder     // Otherwise, go to the base class that will lead to the StaticDecl.
255a07aba5dSTimm Baeder     for (const CXXBaseSpecifier &Spec : CurRecord->bases()) {
256a07aba5dSTimm Baeder       const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl();
257a07aba5dSTimm Baeder       if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) {
258a07aba5dSTimm Baeder         CurRecord = Base;
259a07aba5dSTimm Baeder         break;
260a07aba5dSTimm Baeder       }
261a07aba5dSTimm Baeder     }
262a07aba5dSTimm Baeder   }
263a07aba5dSTimm Baeder 
264a07aba5dSTimm Baeder   llvm_unreachable(
265a07aba5dSTimm Baeder       "Couldn't find an overriding function in the class hierarchy?");
266a07aba5dSTimm Baeder   return nullptr;
267a07aba5dSTimm Baeder }
268a07aba5dSTimm Baeder 
269a07aba5dSTimm Baeder const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {
270a07aba5dSTimm Baeder   assert(FD);
271*2c934dc5STimm Baeder   FD = FD->getMostRecentDecl();
272a07aba5dSTimm Baeder   const Function *Func = P->getFunction(FD);
273a07aba5dSTimm Baeder   bool IsBeingCompiled = Func && Func->isDefined() && !Func->isFullyCompiled();
274a07aba5dSTimm Baeder   bool WasNotDefined = Func && !Func->isConstexpr() && !Func->isDefined();
275a07aba5dSTimm Baeder 
276a07aba5dSTimm Baeder   if (IsBeingCompiled)
277a07aba5dSTimm Baeder     return Func;
278a07aba5dSTimm Baeder 
279a07aba5dSTimm Baeder   if (!Func || WasNotDefined) {
280a07aba5dSTimm Baeder     if (auto F = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD))
281a07aba5dSTimm Baeder       Func = F;
282a07aba5dSTimm Baeder   }
283a07aba5dSTimm Baeder 
284a07aba5dSTimm Baeder   return Func;
285a07aba5dSTimm Baeder }
286a07aba5dSTimm Baeder 
287a07aba5dSTimm Baeder unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
288a07aba5dSTimm Baeder                                     const RecordDecl *DerivedDecl) const {
289a07aba5dSTimm Baeder   assert(BaseDecl);
290a07aba5dSTimm Baeder   assert(DerivedDecl);
291a07aba5dSTimm Baeder   const auto *FinalDecl = cast<CXXRecordDecl>(BaseDecl);
292a07aba5dSTimm Baeder   const RecordDecl *CurDecl = DerivedDecl;
293a07aba5dSTimm Baeder   const Record *CurRecord = P->getOrCreateRecord(CurDecl);
294a07aba5dSTimm Baeder   assert(CurDecl && FinalDecl);
295a07aba5dSTimm Baeder 
296a07aba5dSTimm Baeder   unsigned OffsetSum = 0;
297a07aba5dSTimm Baeder   for (;;) {
298a07aba5dSTimm Baeder     assert(CurRecord->getNumBases() > 0);
299a07aba5dSTimm Baeder     // One level up
300a07aba5dSTimm Baeder     for (const Record::Base &B : CurRecord->bases()) {
301a07aba5dSTimm Baeder       const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);
302a07aba5dSTimm Baeder 
303a07aba5dSTimm Baeder       if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
304a07aba5dSTimm Baeder         OffsetSum += B.Offset;
305a07aba5dSTimm Baeder         CurRecord = B.R;
306a07aba5dSTimm Baeder         CurDecl = BaseDecl;
307a07aba5dSTimm Baeder         break;
308a07aba5dSTimm Baeder       }
309a07aba5dSTimm Baeder     }
310a07aba5dSTimm Baeder     if (CurDecl == FinalDecl)
311a07aba5dSTimm Baeder       break;
312a07aba5dSTimm Baeder   }
313a07aba5dSTimm Baeder 
314a07aba5dSTimm Baeder   assert(OffsetSum > 0);
315a07aba5dSTimm Baeder   return OffsetSum;
316a07aba5dSTimm Baeder }
317a07aba5dSTimm Baeder 
318a07aba5dSTimm Baeder const Record *Context::getRecord(const RecordDecl *D) const {
319a07aba5dSTimm Baeder   return P->getOrCreateRecord(D);
320a07aba5dSTimm Baeder }
321