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