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(F: FD); |
31 | if (!Func || !Func->hasBody()) |
32 | Func = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FuncDecl: FD); |
33 | |
34 | if (!Func) |
35 | return false; |
36 | |
37 | APValue DummyResult; |
38 | if (!Run(Parent, Func, Result&: 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, CheckFullyInitialized: 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(K: 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(T: AT->getValueType()); |
185 | |
186 | if (const auto *DT = dyn_cast<DecltypeType>(Val&: T)) |
187 | return classify(T: 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(S&: 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(RD: CurRecord, MayBeBase: 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(Base: 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(F: 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(FuncDecl: 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>(Val: BaseDecl); |
281 | const RecordDecl *CurDecl = DerivedDecl; |
282 | const Record *CurRecord = P->getOrCreateRecord(RD: 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>(Val: B.Decl); |
291 | |
292 | if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(Base: 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(RD: D); |
309 | } |
310 | |