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