/src/llvm-project/clang/lib/AST/Interp/ByteCodeExprGen.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- ByteCodeExprGen.cpp - Code generator for expressions ---*- 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 "ByteCodeExprGen.h" |
10 | | #include "ByteCodeEmitter.h" |
11 | | #include "ByteCodeGenError.h" |
12 | | #include "ByteCodeStmtGen.h" |
13 | | #include "Context.h" |
14 | | #include "Floating.h" |
15 | | #include "Function.h" |
16 | | #include "PrimType.h" |
17 | | #include "Program.h" |
18 | | |
19 | | using namespace clang; |
20 | | using namespace clang::interp; |
21 | | |
22 | | using APSInt = llvm::APSInt; |
23 | | |
24 | | namespace clang { |
25 | | namespace interp { |
26 | | |
27 | | /// Scope used to handle temporaries in toplevel variable declarations. |
28 | | template <class Emitter> class DeclScope final : public VariableScope<Emitter> { |
29 | | public: |
30 | | DeclScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD) |
31 | | : VariableScope<Emitter>(Ctx), Scope(Ctx->P, VD), |
32 | 0 | OldGlobalDecl(Ctx->GlobalDecl) { |
33 | 0 | Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD); |
34 | 0 | } Unexecuted instantiation: clang::interp::DeclScope<clang::interp::ByteCodeEmitter>::DeclScope(clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>*, clang::ValueDecl const*) Unexecuted instantiation: clang::interp::DeclScope<clang::interp::EvalEmitter>::DeclScope(clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>*, clang::ValueDecl const*) |
35 | | |
36 | 0 | void addExtended(const Scope::Local &Local) override { |
37 | 0 | return this->addLocal(Local); |
38 | 0 | } Unexecuted instantiation: clang::interp::DeclScope<clang::interp::ByteCodeEmitter>::addExtended(clang::interp::Scope::Local const&) Unexecuted instantiation: clang::interp::DeclScope<clang::interp::EvalEmitter>::addExtended(clang::interp::Scope::Local const&) |
39 | | |
40 | 0 | ~DeclScope() { this->Ctx->GlobalDecl = OldGlobalDecl; } Unexecuted instantiation: clang::interp::DeclScope<clang::interp::ByteCodeEmitter>::~DeclScope() Unexecuted instantiation: clang::interp::DeclScope<clang::interp::EvalEmitter>::~DeclScope() |
41 | | |
42 | | private: |
43 | | Program::DeclScope Scope; |
44 | | bool OldGlobalDecl; |
45 | | }; |
46 | | |
47 | | /// Scope used to handle initialization methods. |
48 | | template <class Emitter> class OptionScope final { |
49 | | public: |
50 | | /// Root constructor, compiling or discarding primitives. |
51 | | OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult, |
52 | | bool NewInitializing) |
53 | | : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult), |
54 | 0 | OldInitializing(Ctx->Initializing) { |
55 | 0 | Ctx->DiscardResult = NewDiscardResult; |
56 | 0 | Ctx->Initializing = NewInitializing; |
57 | 0 | } Unexecuted instantiation: clang::interp::OptionScope<clang::interp::ByteCodeEmitter>::OptionScope(clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>*, bool, bool) Unexecuted instantiation: clang::interp::OptionScope<clang::interp::EvalEmitter>::OptionScope(clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>*, bool, bool) |
58 | | |
59 | 0 | ~OptionScope() { |
60 | 0 | Ctx->DiscardResult = OldDiscardResult; |
61 | 0 | Ctx->Initializing = OldInitializing; |
62 | 0 | } Unexecuted instantiation: clang::interp::OptionScope<clang::interp::ByteCodeEmitter>::~OptionScope() Unexecuted instantiation: clang::interp::OptionScope<clang::interp::EvalEmitter>::~OptionScope() |
63 | | |
64 | | private: |
65 | | /// Parent context. |
66 | | ByteCodeExprGen<Emitter> *Ctx; |
67 | | /// Old discard flag to restore. |
68 | | bool OldDiscardResult; |
69 | | bool OldInitializing; |
70 | | }; |
71 | | |
72 | | } // namespace interp |
73 | | } // namespace clang |
74 | | |
75 | | template <class Emitter> |
76 | 0 | bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { |
77 | 0 | const Expr *SubExpr = CE->getSubExpr(); |
78 | 0 | switch (CE->getCastKind()) { |
79 | | |
80 | 0 | case CK_LValueToRValue: { |
81 | 0 | return dereference( |
82 | 0 | SubExpr, DerefKind::Read, |
83 | 0 | [](PrimType) { |
84 | | // Value loaded - nothing to do here. |
85 | 0 | return true; |
86 | 0 | }, Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCastExpr(clang::CastExpr const*)::{lambda(clang::interp::PrimType)#1}::operator()(clang::interp::PrimType) const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCastExpr(clang::CastExpr const*)::{lambda(clang::interp::PrimType)#1}::operator()(clang::interp::PrimType) const |
87 | 0 | [this, CE](PrimType T) { |
88 | | // Pointer on stack - dereference it. |
89 | 0 | if (!this->emitLoadPop(T, CE)) |
90 | 0 | return false; |
91 | 0 | return DiscardResult ? this->emitPop(T, CE) : true; |
92 | 0 | }); Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCastExpr(clang::CastExpr const*)::{lambda(clang::interp::PrimType)#2}::operator()(clang::interp::PrimType) const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCastExpr(clang::CastExpr const*)::{lambda(clang::interp::PrimType)#2}::operator()(clang::interp::PrimType) const |
93 | 0 | } |
94 | | |
95 | 0 | case CK_UncheckedDerivedToBase: |
96 | 0 | case CK_DerivedToBase: { |
97 | 0 | if (!this->visit(SubExpr)) |
98 | 0 | return false; |
99 | | |
100 | 0 | unsigned DerivedOffset = collectBaseOffset(getRecordTy(CE->getType()), |
101 | 0 | getRecordTy(SubExpr->getType())); |
102 | |
|
103 | 0 | return this->emitGetPtrBasePop(DerivedOffset, CE); |
104 | 0 | } |
105 | | |
106 | 0 | case CK_BaseToDerived: { |
107 | 0 | if (!this->visit(SubExpr)) |
108 | 0 | return false; |
109 | | |
110 | 0 | unsigned DerivedOffset = collectBaseOffset(getRecordTy(SubExpr->getType()), |
111 | 0 | getRecordTy(CE->getType())); |
112 | |
|
113 | 0 | return this->emitGetPtrDerivedPop(DerivedOffset, CE); |
114 | 0 | } |
115 | | |
116 | 0 | case CK_FloatingCast: { |
117 | 0 | if (DiscardResult) |
118 | 0 | return this->discard(SubExpr); |
119 | 0 | if (!this->visit(SubExpr)) |
120 | 0 | return false; |
121 | 0 | const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType()); |
122 | 0 | return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE); |
123 | 0 | } |
124 | | |
125 | 0 | case CK_IntegralToFloating: { |
126 | 0 | if (DiscardResult) |
127 | 0 | return this->discard(SubExpr); |
128 | 0 | std::optional<PrimType> FromT = classify(SubExpr->getType()); |
129 | 0 | if (!FromT) |
130 | 0 | return false; |
131 | | |
132 | 0 | if (!this->visit(SubExpr)) |
133 | 0 | return false; |
134 | | |
135 | 0 | const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType()); |
136 | 0 | llvm::RoundingMode RM = getRoundingMode(CE); |
137 | 0 | return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE); |
138 | 0 | } |
139 | | |
140 | 0 | case CK_FloatingToBoolean: |
141 | 0 | case CK_FloatingToIntegral: { |
142 | 0 | if (DiscardResult) |
143 | 0 | return this->discard(SubExpr); |
144 | | |
145 | 0 | std::optional<PrimType> ToT = classify(CE->getType()); |
146 | |
|
147 | 0 | if (!ToT) |
148 | 0 | return false; |
149 | | |
150 | 0 | if (!this->visit(SubExpr)) |
151 | 0 | return false; |
152 | | |
153 | 0 | if (ToT == PT_IntAP) |
154 | 0 | return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(CE->getType()), |
155 | 0 | CE); |
156 | 0 | if (ToT == PT_IntAPS) |
157 | 0 | return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(CE->getType()), |
158 | 0 | CE); |
159 | | |
160 | 0 | return this->emitCastFloatingIntegral(*ToT, CE); |
161 | 0 | } |
162 | | |
163 | 0 | case CK_NullToPointer: |
164 | 0 | if (DiscardResult) |
165 | 0 | return true; |
166 | 0 | return this->emitNull(classifyPrim(CE->getType()), CE); |
167 | | |
168 | 0 | case CK_PointerToIntegral: { |
169 | | // TODO: Discard handling. |
170 | 0 | if (!this->visit(SubExpr)) |
171 | 0 | return false; |
172 | | |
173 | 0 | PrimType T = classifyPrim(CE->getType()); |
174 | 0 | return this->emitCastPointerIntegral(T, CE); |
175 | 0 | } |
176 | | |
177 | 0 | case CK_ArrayToPointerDecay: { |
178 | 0 | if (!this->visit(SubExpr)) |
179 | 0 | return false; |
180 | 0 | if (!this->emitArrayDecay(CE)) |
181 | 0 | return false; |
182 | 0 | if (DiscardResult) |
183 | 0 | return this->emitPopPtr(CE); |
184 | 0 | return true; |
185 | 0 | } |
186 | | |
187 | 0 | case CK_AtomicToNonAtomic: |
188 | 0 | case CK_ConstructorConversion: |
189 | 0 | case CK_FunctionToPointerDecay: |
190 | 0 | case CK_NonAtomicToAtomic: |
191 | 0 | case CK_NoOp: |
192 | 0 | case CK_UserDefinedConversion: |
193 | 0 | case CK_BitCast: |
194 | 0 | return this->delegate(SubExpr); |
195 | | |
196 | 0 | case CK_IntegralToBoolean: |
197 | 0 | case CK_IntegralCast: { |
198 | 0 | if (DiscardResult) |
199 | 0 | return this->discard(SubExpr); |
200 | 0 | std::optional<PrimType> FromT = classify(SubExpr->getType()); |
201 | 0 | std::optional<PrimType> ToT = classify(CE->getType()); |
202 | |
|
203 | 0 | if (!FromT || !ToT) |
204 | 0 | return false; |
205 | | |
206 | 0 | if (!this->visit(SubExpr)) |
207 | 0 | return false; |
208 | | |
209 | 0 | if (ToT == PT_IntAP) |
210 | 0 | return this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE); |
211 | 0 | if (ToT == PT_IntAPS) |
212 | 0 | return this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE); |
213 | | |
214 | 0 | if (FromT == ToT) |
215 | 0 | return true; |
216 | 0 | return this->emitCast(*FromT, *ToT, CE); |
217 | 0 | } |
218 | | |
219 | 0 | case CK_PointerToBoolean: { |
220 | 0 | PrimType PtrT = classifyPrim(SubExpr->getType()); |
221 | | |
222 | | // Just emit p != nullptr for this. |
223 | 0 | if (!this->visit(SubExpr)) |
224 | 0 | return false; |
225 | | |
226 | 0 | if (!this->emitNull(PtrT, CE)) |
227 | 0 | return false; |
228 | | |
229 | 0 | return this->emitNE(PtrT, CE); |
230 | 0 | } |
231 | | |
232 | 0 | case CK_IntegralComplexToBoolean: |
233 | 0 | case CK_FloatingComplexToBoolean: { |
234 | 0 | std::optional<PrimType> ElemT = |
235 | 0 | classifyComplexElementType(SubExpr->getType()); |
236 | 0 | if (!ElemT) |
237 | 0 | return false; |
238 | | // We emit the expression (__real(E) != 0 || __imag(E) != 0) |
239 | | // for us, that means (bool)E[0] || (bool)E[1] |
240 | 0 | if (!this->visit(SubExpr)) |
241 | 0 | return false; |
242 | 0 | if (!this->emitConstUint8(0, CE)) |
243 | 0 | return false; |
244 | 0 | if (!this->emitArrayElemPtrUint8(CE)) |
245 | 0 | return false; |
246 | 0 | if (!this->emitLoadPop(*ElemT, CE)) |
247 | 0 | return false; |
248 | 0 | if (*ElemT == PT_Float) { |
249 | 0 | if (!this->emitCastFloatingIntegral(PT_Bool, CE)) |
250 | 0 | return false; |
251 | 0 | } else { |
252 | 0 | if (!this->emitCast(*ElemT, PT_Bool, CE)) |
253 | 0 | return false; |
254 | 0 | } |
255 | | |
256 | | // We now have the bool value of E[0] on the stack. |
257 | 0 | LabelTy LabelTrue = this->getLabel(); |
258 | 0 | if (!this->jumpTrue(LabelTrue)) |
259 | 0 | return false; |
260 | | |
261 | 0 | if (!this->emitConstUint8(1, CE)) |
262 | 0 | return false; |
263 | 0 | if (!this->emitArrayElemPtrPopUint8(CE)) |
264 | 0 | return false; |
265 | 0 | if (!this->emitLoadPop(*ElemT, CE)) |
266 | 0 | return false; |
267 | 0 | if (*ElemT == PT_Float) { |
268 | 0 | if (!this->emitCastFloatingIntegral(PT_Bool, CE)) |
269 | 0 | return false; |
270 | 0 | } else { |
271 | 0 | if (!this->emitCast(*ElemT, PT_Bool, CE)) |
272 | 0 | return false; |
273 | 0 | } |
274 | | // Leave the boolean value of E[1] on the stack. |
275 | 0 | LabelTy EndLabel = this->getLabel(); |
276 | 0 | this->jump(EndLabel); |
277 | |
|
278 | 0 | this->emitLabel(LabelTrue); |
279 | 0 | if (!this->emitPopPtr(CE)) |
280 | 0 | return false; |
281 | 0 | if (!this->emitConstBool(true, CE)) |
282 | 0 | return false; |
283 | | |
284 | 0 | this->fallthrough(EndLabel); |
285 | 0 | this->emitLabel(EndLabel); |
286 | |
|
287 | 0 | return true; |
288 | 0 | } |
289 | | |
290 | 0 | case CK_ToVoid: |
291 | 0 | return discard(SubExpr); |
292 | | |
293 | 0 | default: |
294 | 0 | assert(false && "Cast not implemented"); |
295 | 0 | } |
296 | 0 | llvm_unreachable("Unhandled clang::CastKind enum"); |
297 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCastExpr(clang::CastExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCastExpr(clang::CastExpr const*) |
298 | | |
299 | | template <class Emitter> |
300 | 0 | bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) { |
301 | 0 | if (DiscardResult) |
302 | 0 | return true; |
303 | | |
304 | 0 | return this->emitConst(LE->getValue(), LE); |
305 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitIntegerLiteral(clang::IntegerLiteral const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitIntegerLiteral(clang::IntegerLiteral const*) |
306 | | |
307 | | template <class Emitter> |
308 | 0 | bool ByteCodeExprGen<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) { |
309 | 0 | if (DiscardResult) |
310 | 0 | return true; |
311 | | |
312 | 0 | return this->emitConstFloat(E->getValue(), E); |
313 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitFloatingLiteral(clang::FloatingLiteral const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitFloatingLiteral(clang::FloatingLiteral const*) |
314 | | |
315 | | template <class Emitter> |
316 | 0 | bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *E) { |
317 | 0 | return this->delegate(E->getSubExpr()); |
318 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitParenExpr(clang::ParenExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitParenExpr(clang::ParenExpr const*) |
319 | | |
320 | | template <class Emitter> |
321 | 0 | bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) { |
322 | | // Need short-circuiting for these. |
323 | 0 | if (BO->isLogicalOp()) |
324 | 0 | return this->VisitLogicalBinOp(BO); |
325 | | |
326 | 0 | if (BO->getType()->isAnyComplexType()) |
327 | 0 | return this->VisitComplexBinOp(BO); |
328 | | |
329 | 0 | const Expr *LHS = BO->getLHS(); |
330 | 0 | const Expr *RHS = BO->getRHS(); |
331 | |
|
332 | 0 | if (BO->isPtrMemOp()) |
333 | 0 | return this->visit(RHS); |
334 | | |
335 | | // Typecheck the args. |
336 | 0 | std::optional<PrimType> LT = classify(LHS->getType()); |
337 | 0 | std::optional<PrimType> RT = classify(RHS->getType()); |
338 | 0 | std::optional<PrimType> T = classify(BO->getType()); |
339 | | |
340 | | // Deal with operations which have composite or void types. |
341 | 0 | if (BO->isCommaOp()) { |
342 | 0 | if (!this->discard(LHS)) |
343 | 0 | return false; |
344 | 0 | if (RHS->getType()->isVoidType()) |
345 | 0 | return this->discard(RHS); |
346 | | |
347 | 0 | return this->delegate(RHS); |
348 | 0 | } |
349 | | |
350 | | // Special case for C++'s three-way/spaceship operator <=>, which |
351 | | // returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't |
352 | | // have a PrimType). |
353 | 0 | if (!T) { |
354 | 0 | if (DiscardResult) |
355 | 0 | return true; |
356 | 0 | const ComparisonCategoryInfo *CmpInfo = |
357 | 0 | Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType()); |
358 | 0 | assert(CmpInfo); |
359 | | |
360 | | // We need a temporary variable holding our return value. |
361 | 0 | if (!Initializing) { |
362 | 0 | std::optional<unsigned> ResultIndex = this->allocateLocal(BO, false); |
363 | 0 | if (!this->emitGetPtrLocal(*ResultIndex, BO)) |
364 | 0 | return false; |
365 | 0 | } |
366 | | |
367 | 0 | if (!visit(LHS) || !visit(RHS)) |
368 | 0 | return false; |
369 | | |
370 | 0 | return this->emitCMP3(*LT, CmpInfo, BO); |
371 | 0 | } |
372 | | |
373 | 0 | if (!LT || !RT || !T) |
374 | 0 | return this->bail(BO); |
375 | | |
376 | | // Pointer arithmetic special case. |
377 | 0 | if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) { |
378 | 0 | if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr)) |
379 | 0 | return this->VisitPointerArithBinOp(BO); |
380 | 0 | } |
381 | | |
382 | 0 | if (!visit(LHS) || !visit(RHS)) |
383 | 0 | return false; |
384 | | |
385 | | // For languages such as C, cast the result of one |
386 | | // of our comparision opcodes to T (which is usually int). |
387 | 0 | auto MaybeCastToBool = [this, T, BO](bool Result) { |
388 | 0 | if (!Result) |
389 | 0 | return false; |
390 | 0 | if (DiscardResult) |
391 | 0 | return this->emitPop(*T, BO); |
392 | 0 | if (T != PT_Bool) |
393 | 0 | return this->emitCast(PT_Bool, *T, BO); |
394 | 0 | return true; |
395 | 0 | }; Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitBinaryOperator(clang::BinaryOperator const*)::{lambda(bool)#1}::operator()(bool) const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitBinaryOperator(clang::BinaryOperator const*)::{lambda(bool)#1}::operator()(bool) const |
396 | |
|
397 | 0 | auto Discard = [this, T, BO](bool Result) { |
398 | 0 | if (!Result) |
399 | 0 | return false; |
400 | 0 | return DiscardResult ? this->emitPop(*T, BO) : true; |
401 | 0 | }; Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitBinaryOperator(clang::BinaryOperator const*)::{lambda(bool)#2}::operator()(bool) const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitBinaryOperator(clang::BinaryOperator const*)::{lambda(bool)#2}::operator()(bool) const |
402 | |
|
403 | 0 | switch (BO->getOpcode()) { |
404 | 0 | case BO_EQ: |
405 | 0 | return MaybeCastToBool(this->emitEQ(*LT, BO)); |
406 | 0 | case BO_NE: |
407 | 0 | return MaybeCastToBool(this->emitNE(*LT, BO)); |
408 | 0 | case BO_LT: |
409 | 0 | return MaybeCastToBool(this->emitLT(*LT, BO)); |
410 | 0 | case BO_LE: |
411 | 0 | return MaybeCastToBool(this->emitLE(*LT, BO)); |
412 | 0 | case BO_GT: |
413 | 0 | return MaybeCastToBool(this->emitGT(*LT, BO)); |
414 | 0 | case BO_GE: |
415 | 0 | return MaybeCastToBool(this->emitGE(*LT, BO)); |
416 | 0 | case BO_Sub: |
417 | 0 | if (BO->getType()->isFloatingType()) |
418 | 0 | return Discard(this->emitSubf(getRoundingMode(BO), BO)); |
419 | 0 | return Discard(this->emitSub(*T, BO)); |
420 | 0 | case BO_Add: |
421 | 0 | if (BO->getType()->isFloatingType()) |
422 | 0 | return Discard(this->emitAddf(getRoundingMode(BO), BO)); |
423 | 0 | return Discard(this->emitAdd(*T, BO)); |
424 | 0 | case BO_Mul: |
425 | 0 | if (BO->getType()->isFloatingType()) |
426 | 0 | return Discard(this->emitMulf(getRoundingMode(BO), BO)); |
427 | 0 | return Discard(this->emitMul(*T, BO)); |
428 | 0 | case BO_Rem: |
429 | 0 | return Discard(this->emitRem(*T, BO)); |
430 | 0 | case BO_Div: |
431 | 0 | if (BO->getType()->isFloatingType()) |
432 | 0 | return Discard(this->emitDivf(getRoundingMode(BO), BO)); |
433 | 0 | return Discard(this->emitDiv(*T, BO)); |
434 | 0 | case BO_Assign: |
435 | 0 | if (DiscardResult) |
436 | 0 | return LHS->refersToBitField() ? this->emitStoreBitFieldPop(*T, BO) |
437 | 0 | : this->emitStorePop(*T, BO); |
438 | 0 | return LHS->refersToBitField() ? this->emitStoreBitField(*T, BO) |
439 | 0 | : this->emitStore(*T, BO); |
440 | 0 | case BO_And: |
441 | 0 | return Discard(this->emitBitAnd(*T, BO)); |
442 | 0 | case BO_Or: |
443 | 0 | return Discard(this->emitBitOr(*T, BO)); |
444 | 0 | case BO_Shl: |
445 | 0 | return Discard(this->emitShl(*LT, *RT, BO)); |
446 | 0 | case BO_Shr: |
447 | 0 | return Discard(this->emitShr(*LT, *RT, BO)); |
448 | 0 | case BO_Xor: |
449 | 0 | return Discard(this->emitBitXor(*T, BO)); |
450 | 0 | case BO_LOr: |
451 | 0 | case BO_LAnd: |
452 | 0 | llvm_unreachable("Already handled earlier"); |
453 | 0 | default: |
454 | 0 | return this->bail(BO); |
455 | 0 | } |
456 | | |
457 | 0 | llvm_unreachable("Unhandled binary op"); |
458 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitBinaryOperator(clang::BinaryOperator const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitBinaryOperator(clang::BinaryOperator const*) |
459 | | |
460 | | /// Perform addition/subtraction of a pointer and an integer or |
461 | | /// subtraction of two pointers. |
462 | | template <class Emitter> |
463 | 0 | bool ByteCodeExprGen<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) { |
464 | 0 | BinaryOperatorKind Op = E->getOpcode(); |
465 | 0 | const Expr *LHS = E->getLHS(); |
466 | 0 | const Expr *RHS = E->getRHS(); |
467 | |
|
468 | 0 | if ((Op != BO_Add && Op != BO_Sub) || |
469 | 0 | (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType())) |
470 | 0 | return false; |
471 | | |
472 | 0 | std::optional<PrimType> LT = classify(LHS); |
473 | 0 | std::optional<PrimType> RT = classify(RHS); |
474 | |
|
475 | 0 | if (!LT || !RT) |
476 | 0 | return false; |
477 | | |
478 | 0 | if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) { |
479 | 0 | if (Op != BO_Sub) |
480 | 0 | return false; |
481 | | |
482 | 0 | assert(E->getType()->isIntegerType()); |
483 | 0 | if (!visit(RHS) || !visit(LHS)) |
484 | 0 | return false; |
485 | | |
486 | 0 | return this->emitSubPtr(classifyPrim(E->getType()), E); |
487 | 0 | } |
488 | | |
489 | 0 | PrimType OffsetType; |
490 | 0 | if (LHS->getType()->isIntegerType()) { |
491 | 0 | if (!visit(RHS) || !visit(LHS)) |
492 | 0 | return false; |
493 | 0 | OffsetType = *LT; |
494 | 0 | } else if (RHS->getType()->isIntegerType()) { |
495 | 0 | if (!visit(LHS) || !visit(RHS)) |
496 | 0 | return false; |
497 | 0 | OffsetType = *RT; |
498 | 0 | } else { |
499 | 0 | return false; |
500 | 0 | } |
501 | | |
502 | 0 | if (Op == BO_Add) |
503 | 0 | return this->emitAddOffset(OffsetType, E); |
504 | 0 | else if (Op == BO_Sub) |
505 | 0 | return this->emitSubOffset(OffsetType, E); |
506 | | |
507 | 0 | return this->bail(E); |
508 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitPointerArithBinOp(clang::BinaryOperator const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitPointerArithBinOp(clang::BinaryOperator const*) |
509 | | |
510 | | template <class Emitter> |
511 | 0 | bool ByteCodeExprGen<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) { |
512 | 0 | assert(E->isLogicalOp()); |
513 | 0 | BinaryOperatorKind Op = E->getOpcode(); |
514 | 0 | const Expr *LHS = E->getLHS(); |
515 | 0 | const Expr *RHS = E->getRHS(); |
516 | 0 | std::optional<PrimType> T = classify(E->getType()); |
517 | |
|
518 | 0 | if (Op == BO_LOr) { |
519 | | // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE. |
520 | 0 | LabelTy LabelTrue = this->getLabel(); |
521 | 0 | LabelTy LabelEnd = this->getLabel(); |
522 | |
|
523 | 0 | if (!this->visitBool(LHS)) |
524 | 0 | return false; |
525 | 0 | if (!this->jumpTrue(LabelTrue)) |
526 | 0 | return false; |
527 | | |
528 | 0 | if (!this->visitBool(RHS)) |
529 | 0 | return false; |
530 | 0 | if (!this->jump(LabelEnd)) |
531 | 0 | return false; |
532 | | |
533 | 0 | this->emitLabel(LabelTrue); |
534 | 0 | this->emitConstBool(true, E); |
535 | 0 | this->fallthrough(LabelEnd); |
536 | 0 | this->emitLabel(LabelEnd); |
537 | |
|
538 | 0 | } else { |
539 | 0 | assert(Op == BO_LAnd); |
540 | | // Logical AND. |
541 | | // Visit LHS. Only visit RHS if LHS was TRUE. |
542 | 0 | LabelTy LabelFalse = this->getLabel(); |
543 | 0 | LabelTy LabelEnd = this->getLabel(); |
544 | |
|
545 | 0 | if (!this->visitBool(LHS)) |
546 | 0 | return false; |
547 | 0 | if (!this->jumpFalse(LabelFalse)) |
548 | 0 | return false; |
549 | | |
550 | 0 | if (!this->visitBool(RHS)) |
551 | 0 | return false; |
552 | 0 | if (!this->jump(LabelEnd)) |
553 | 0 | return false; |
554 | | |
555 | 0 | this->emitLabel(LabelFalse); |
556 | 0 | this->emitConstBool(false, E); |
557 | 0 | this->fallthrough(LabelEnd); |
558 | 0 | this->emitLabel(LabelEnd); |
559 | 0 | } |
560 | | |
561 | 0 | if (DiscardResult) |
562 | 0 | return this->emitPopBool(E); |
563 | | |
564 | | // For C, cast back to integer type. |
565 | 0 | assert(T); |
566 | 0 | if (T != PT_Bool) |
567 | 0 | return this->emitCast(PT_Bool, *T, E); |
568 | 0 | return true; |
569 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitLogicalBinOp(clang::BinaryOperator const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitLogicalBinOp(clang::BinaryOperator const*) |
570 | | |
571 | | template <class Emitter> |
572 | 0 | bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) { |
573 | 0 | assert(Initializing); |
574 | | |
575 | 0 | const Expr *LHS = E->getLHS(); |
576 | 0 | const Expr *RHS = E->getRHS(); |
577 | 0 | PrimType LHSElemT = *this->classifyComplexElementType(LHS->getType()); |
578 | 0 | PrimType RHSElemT = *this->classifyComplexElementType(RHS->getType()); |
579 | |
|
580 | 0 | unsigned LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, true, false); |
581 | 0 | unsigned RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, true, false); |
582 | 0 | unsigned ResultOffset = ~0u; |
583 | 0 | if (!this->DiscardResult) |
584 | 0 | ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, true, false); |
585 | |
|
586 | 0 | assert(LHSElemT == RHSElemT); |
587 | | |
588 | | // Save result pointer in ResultOffset |
589 | 0 | if (!this->DiscardResult) { |
590 | 0 | if (!this->emitDupPtr(E)) |
591 | 0 | return false; |
592 | 0 | if (!this->emitSetLocal(PT_Ptr, ResultOffset, E)) |
593 | 0 | return false; |
594 | 0 | } |
595 | | |
596 | | // Evaluate LHS and save value to LHSOffset. |
597 | 0 | if (!this->visit(LHS)) |
598 | 0 | return false; |
599 | 0 | if (!this->emitSetLocal(PT_Ptr, LHSOffset, E)) |
600 | 0 | return false; |
601 | | |
602 | | // Same with RHS. |
603 | 0 | if (!this->visit(RHS)) |
604 | 0 | return false; |
605 | 0 | if (!this->emitSetLocal(PT_Ptr, RHSOffset, E)) |
606 | 0 | return false; |
607 | | |
608 | | // Now we can get pointers to the LHS and RHS from the offsets above. |
609 | 0 | BinaryOperatorKind Op = E->getOpcode(); |
610 | 0 | for (unsigned ElemIndex = 0; ElemIndex != 2; ++ElemIndex) { |
611 | | // Result pointer for the store later. |
612 | 0 | if (!this->DiscardResult) { |
613 | 0 | if (!this->emitGetLocal(PT_Ptr, ResultOffset, E)) |
614 | 0 | return false; |
615 | 0 | } |
616 | | |
617 | 0 | if (!this->emitGetLocal(PT_Ptr, LHSOffset, E)) |
618 | 0 | return false; |
619 | 0 | if (!this->emitConstUint8(ElemIndex, E)) |
620 | 0 | return false; |
621 | 0 | if (!this->emitArrayElemPtrPopUint8(E)) |
622 | 0 | return false; |
623 | 0 | if (!this->emitLoadPop(LHSElemT, E)) |
624 | 0 | return false; |
625 | | |
626 | 0 | if (!this->emitGetLocal(PT_Ptr, RHSOffset, E)) |
627 | 0 | return false; |
628 | 0 | if (!this->emitConstUint8(ElemIndex, E)) |
629 | 0 | return false; |
630 | 0 | if (!this->emitArrayElemPtrPopUint8(E)) |
631 | 0 | return false; |
632 | 0 | if (!this->emitLoadPop(RHSElemT, E)) |
633 | 0 | return false; |
634 | | |
635 | | // The actual operation. |
636 | 0 | switch (Op) { |
637 | 0 | case BO_Add: |
638 | 0 | if (LHSElemT == PT_Float) { |
639 | 0 | if (!this->emitAddf(getRoundingMode(E), E)) |
640 | 0 | return false; |
641 | 0 | } else { |
642 | 0 | if (!this->emitAdd(LHSElemT, E)) |
643 | 0 | return false; |
644 | 0 | } |
645 | 0 | break; |
646 | 0 | case BO_Sub: |
647 | 0 | if (LHSElemT == PT_Float) { |
648 | 0 | if (!this->emitSubf(getRoundingMode(E), E)) |
649 | 0 | return false; |
650 | 0 | } else { |
651 | 0 | if (!this->emitSub(LHSElemT, E)) |
652 | 0 | return false; |
653 | 0 | } |
654 | 0 | break; |
655 | | |
656 | 0 | default: |
657 | 0 | return false; |
658 | 0 | } |
659 | | |
660 | 0 | if (!this->DiscardResult) { |
661 | | // Initialize array element with the value we just computed. |
662 | 0 | if (!this->emitInitElemPop(LHSElemT, ElemIndex, E)) |
663 | 0 | return false; |
664 | 0 | } else { |
665 | 0 | if (!this->emitPop(LHSElemT, E)) |
666 | 0 | return false; |
667 | 0 | } |
668 | 0 | } |
669 | 0 | return true; |
670 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitComplexBinOp(clang::BinaryOperator const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitComplexBinOp(clang::BinaryOperator const*) |
671 | | |
672 | | template <class Emitter> |
673 | 0 | bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { |
674 | 0 | QualType QT = E->getType(); |
675 | |
|
676 | 0 | if (std::optional<PrimType> T = classify(QT)) |
677 | 0 | return this->visitZeroInitializer(*T, QT, E); |
678 | | |
679 | 0 | if (QT->isRecordType()) |
680 | 0 | return false; |
681 | | |
682 | 0 | if (QT->isIncompleteArrayType()) |
683 | 0 | return true; |
684 | | |
685 | 0 | if (QT->isArrayType()) { |
686 | 0 | const ArrayType *AT = QT->getAsArrayTypeUnsafe(); |
687 | 0 | assert(AT); |
688 | 0 | const auto *CAT = cast<ConstantArrayType>(AT); |
689 | 0 | size_t NumElems = CAT->getSize().getZExtValue(); |
690 | 0 | PrimType ElemT = classifyPrim(CAT->getElementType()); |
691 | |
|
692 | 0 | for (size_t I = 0; I != NumElems; ++I) { |
693 | 0 | if (!this->visitZeroInitializer(ElemT, CAT->getElementType(), E)) |
694 | 0 | return false; |
695 | 0 | if (!this->emitInitElem(ElemT, I, E)) |
696 | 0 | return false; |
697 | 0 | } |
698 | | |
699 | 0 | return true; |
700 | 0 | } |
701 | | |
702 | 0 | return false; |
703 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitImplicitValueInitExpr(clang::ImplicitValueInitExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitImplicitValueInitExpr(clang::ImplicitValueInitExpr const*) |
704 | | |
705 | | template <class Emitter> |
706 | | bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr( |
707 | 0 | const ArraySubscriptExpr *E) { |
708 | 0 | const Expr *Base = E->getBase(); |
709 | 0 | const Expr *Index = E->getIdx(); |
710 | |
|
711 | 0 | if (DiscardResult) |
712 | 0 | return this->discard(Base) && this->discard(Index); |
713 | | |
714 | | // Take pointer of LHS, add offset from RHS. |
715 | | // What's left on the stack after this is a pointer. |
716 | 0 | if (!this->visit(Base)) |
717 | 0 | return false; |
718 | | |
719 | 0 | if (!this->visit(Index)) |
720 | 0 | return false; |
721 | | |
722 | 0 | PrimType IndexT = classifyPrim(Index->getType()); |
723 | 0 | return this->emitArrayElemPtrPop(IndexT, E); |
724 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitArraySubscriptExpr(clang::ArraySubscriptExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitArraySubscriptExpr(clang::ArraySubscriptExpr const*) |
725 | | |
726 | | template <class Emitter> |
727 | | bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, |
728 | 0 | const Expr *E) { |
729 | 0 | assert(E->getType()->isRecordType()); |
730 | 0 | const Record *R = getRecord(E->getType()); |
731 | |
|
732 | 0 | unsigned InitIndex = 0; |
733 | 0 | for (const Expr *Init : Inits) { |
734 | 0 | if (!this->emitDupPtr(E)) |
735 | 0 | return false; |
736 | | |
737 | 0 | if (std::optional<PrimType> T = classify(Init)) { |
738 | 0 | const Record::Field *FieldToInit = R->getField(InitIndex); |
739 | 0 | if (!this->visit(Init)) |
740 | 0 | return false; |
741 | | |
742 | 0 | if (FieldToInit->isBitField()) { |
743 | 0 | if (!this->emitInitBitField(*T, FieldToInit, E)) |
744 | 0 | return false; |
745 | 0 | } else { |
746 | 0 | if (!this->emitInitField(*T, FieldToInit->Offset, E)) |
747 | 0 | return false; |
748 | 0 | } |
749 | | |
750 | 0 | if (!this->emitPopPtr(E)) |
751 | 0 | return false; |
752 | 0 | ++InitIndex; |
753 | 0 | } else { |
754 | | // Initializer for a direct base class. |
755 | 0 | if (const Record::Base *B = R->getBase(Init->getType())) { |
756 | 0 | if (!this->emitGetPtrBasePop(B->Offset, Init)) |
757 | 0 | return false; |
758 | | |
759 | 0 | if (!this->visitInitializer(Init)) |
760 | 0 | return false; |
761 | | |
762 | 0 | if (!this->emitInitPtrPop(E)) |
763 | 0 | return false; |
764 | | // Base initializers don't increase InitIndex, since they don't count |
765 | | // into the Record's fields. |
766 | 0 | } else { |
767 | 0 | const Record::Field *FieldToInit = R->getField(InitIndex); |
768 | | // Non-primitive case. Get a pointer to the field-to-initialize |
769 | | // on the stack and recurse into visitInitializer(). |
770 | 0 | if (!this->emitGetPtrField(FieldToInit->Offset, Init)) |
771 | 0 | return false; |
772 | | |
773 | 0 | if (!this->visitInitializer(Init)) |
774 | 0 | return false; |
775 | | |
776 | 0 | if (!this->emitPopPtr(E)) |
777 | 0 | return false; |
778 | 0 | ++InitIndex; |
779 | 0 | } |
780 | 0 | } |
781 | 0 | } |
782 | 0 | return true; |
783 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitInitList(llvm::ArrayRef<clang::Expr const*>, clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitInitList(llvm::ArrayRef<clang::Expr const*>, clang::Expr const*) |
784 | | |
785 | | /// Pointer to the array(not the element!) must be on the stack when calling |
786 | | /// this. |
787 | | template <class Emitter> |
788 | | bool ByteCodeExprGen<Emitter>::visitArrayElemInit(unsigned ElemIndex, |
789 | 0 | const Expr *Init) { |
790 | 0 | if (std::optional<PrimType> T = classify(Init->getType())) { |
791 | | // Visit the primitive element like normal. |
792 | 0 | if (!this->visit(Init)) |
793 | 0 | return false; |
794 | 0 | return this->emitInitElem(*T, ElemIndex, Init); |
795 | 0 | } |
796 | | |
797 | | // Advance the pointer currently on the stack to the given |
798 | | // dimension. |
799 | 0 | if (!this->emitConstUint32(ElemIndex, Init)) |
800 | 0 | return false; |
801 | 0 | if (!this->emitArrayElemPtrUint32(Init)) |
802 | 0 | return false; |
803 | 0 | if (!this->visitInitializer(Init)) |
804 | 0 | return false; |
805 | 0 | return this->emitPopPtr(Init); |
806 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitArrayElemInit(unsigned int, clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitArrayElemInit(unsigned int, clang::Expr const*) |
807 | | |
808 | | template <class Emitter> |
809 | 0 | bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) { |
810 | | // Handle discarding first. |
811 | 0 | if (DiscardResult) { |
812 | 0 | for (const Expr *Init : E->inits()) { |
813 | 0 | if (!this->discard(Init)) |
814 | 0 | return false; |
815 | 0 | } |
816 | 0 | return true; |
817 | 0 | } |
818 | | |
819 | | // Primitive values. |
820 | 0 | if (std::optional<PrimType> T = classify(E->getType())) { |
821 | 0 | assert(!DiscardResult); |
822 | 0 | if (E->getNumInits() == 0) |
823 | 0 | return this->visitZeroInitializer(*T, E->getType(), E); |
824 | 0 | assert(E->getNumInits() == 1); |
825 | 0 | return this->delegate(E->inits()[0]); |
826 | 0 | } |
827 | | |
828 | 0 | QualType T = E->getType(); |
829 | 0 | if (T->isRecordType()) |
830 | 0 | return this->visitInitList(E->inits(), E); |
831 | | |
832 | 0 | if (T->isArrayType()) { |
833 | | // FIXME: Array fillers. |
834 | 0 | unsigned ElementIndex = 0; |
835 | 0 | for (const Expr *Init : E->inits()) { |
836 | 0 | if (!this->visitArrayElemInit(ElementIndex, Init)) |
837 | 0 | return false; |
838 | 0 | ++ElementIndex; |
839 | 0 | } |
840 | 0 | return true; |
841 | 0 | } |
842 | | |
843 | 0 | if (T->isAnyComplexType()) { |
844 | 0 | unsigned NumInits = E->getNumInits(); |
845 | 0 | QualType ElemQT = E->getType()->getAs<ComplexType>()->getElementType(); |
846 | 0 | PrimType ElemT = classifyPrim(ElemQT); |
847 | 0 | if (NumInits == 0) { |
848 | | // Zero-initialize both elements. |
849 | 0 | for (unsigned I = 0; I < 2; ++I) { |
850 | 0 | if (!this->visitZeroInitializer(ElemT, ElemQT, E)) |
851 | 0 | return false; |
852 | 0 | if (!this->emitInitElem(ElemT, I, E)) |
853 | 0 | return false; |
854 | 0 | } |
855 | 0 | } else if (NumInits == 2) { |
856 | 0 | unsigned InitIndex = 0; |
857 | 0 | for (const Expr *Init : E->inits()) { |
858 | 0 | if (!this->visit(Init)) |
859 | 0 | return false; |
860 | | |
861 | 0 | if (!this->emitInitElem(ElemT, InitIndex, E)) |
862 | 0 | return false; |
863 | 0 | ++InitIndex; |
864 | 0 | } |
865 | 0 | } |
866 | 0 | return true; |
867 | 0 | } |
868 | | |
869 | 0 | return false; |
870 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitInitListExpr(clang::InitListExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitInitListExpr(clang::InitListExpr const*) |
871 | | |
872 | | template <class Emitter> |
873 | | bool ByteCodeExprGen<Emitter>::VisitCXXParenListInitExpr( |
874 | 0 | const CXXParenListInitExpr *E) { |
875 | 0 | if (DiscardResult) { |
876 | 0 | for (const Expr *Init : E->getInitExprs()) { |
877 | 0 | if (!this->discard(Init)) |
878 | 0 | return false; |
879 | 0 | } |
880 | 0 | return true; |
881 | 0 | } |
882 | | |
883 | 0 | assert(E->getType()->isRecordType()); |
884 | 0 | return this->visitInitList(E->getInitExprs(), E); |
885 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXParenListInitExpr(clang::CXXParenListInitExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXParenListInitExpr(clang::CXXParenListInitExpr const*) |
886 | | |
887 | | template <class Emitter> |
888 | | bool ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr( |
889 | 0 | const SubstNonTypeTemplateParmExpr *E) { |
890 | 0 | return this->delegate(E->getReplacement()); |
891 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitSubstNonTypeTemplateParmExpr(clang::SubstNonTypeTemplateParmExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitSubstNonTypeTemplateParmExpr(clang::SubstNonTypeTemplateParmExpr const*) |
892 | | |
893 | | template <class Emitter> |
894 | 0 | bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) { |
895 | | // Try to emit the APValue directly, without visiting the subexpr. |
896 | | // This will only fail if we can't emit the APValue, so won't emit any |
897 | | // diagnostics or any double values. |
898 | 0 | std::optional<PrimType> T = classify(E->getType()); |
899 | 0 | if (T && E->hasAPValueResult() && |
900 | 0 | this->visitAPValue(E->getAPValueResult(), *T, E)) |
901 | 0 | return true; |
902 | | |
903 | 0 | return this->delegate(E->getSubExpr()); |
904 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitConstantExpr(clang::ConstantExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitConstantExpr(clang::ConstantExpr const*) |
905 | | |
906 | | static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx, |
907 | 0 | UnaryExprOrTypeTrait Kind) { |
908 | 0 | bool AlignOfReturnsPreferred = |
909 | 0 | ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7; |
910 | | |
911 | | // C++ [expr.alignof]p3: |
912 | | // When alignof is applied to a reference type, the result is the |
913 | | // alignment of the referenced type. |
914 | 0 | if (const auto *Ref = T->getAs<ReferenceType>()) |
915 | 0 | T = Ref->getPointeeType(); |
916 | | |
917 | | // __alignof is defined to return the preferred alignment. |
918 | | // Before 8, clang returned the preferred alignment for alignof and |
919 | | // _Alignof as well. |
920 | 0 | if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred) |
921 | 0 | return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T)); |
922 | | |
923 | 0 | return ASTCtx.getTypeAlignInChars(T); |
924 | 0 | } |
925 | | |
926 | | template <class Emitter> |
927 | | bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr( |
928 | 0 | const UnaryExprOrTypeTraitExpr *E) { |
929 | 0 | UnaryExprOrTypeTrait Kind = E->getKind(); |
930 | 0 | ASTContext &ASTCtx = Ctx.getASTContext(); |
931 | |
|
932 | 0 | if (Kind == UETT_SizeOf) { |
933 | 0 | QualType ArgType = E->getTypeOfArgument(); |
934 | 0 | CharUnits Size; |
935 | 0 | if (ArgType->isVoidType() || ArgType->isFunctionType()) |
936 | 0 | Size = CharUnits::One(); |
937 | 0 | else { |
938 | 0 | if (ArgType->isDependentType() || !ArgType->isConstantSizeType()) |
939 | 0 | return false; |
940 | | |
941 | 0 | Size = ASTCtx.getTypeSizeInChars(ArgType); |
942 | 0 | } |
943 | | |
944 | 0 | if (DiscardResult) |
945 | 0 | return true; |
946 | | |
947 | 0 | return this->emitConst(Size.getQuantity(), E); |
948 | 0 | } |
949 | | |
950 | 0 | if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) { |
951 | 0 | CharUnits Size; |
952 | |
|
953 | 0 | if (E->isArgumentType()) { |
954 | 0 | QualType ArgType = E->getTypeOfArgument(); |
955 | |
|
956 | 0 | Size = AlignOfType(ArgType, ASTCtx, Kind); |
957 | 0 | } else { |
958 | | // Argument is an expression, not a type. |
959 | 0 | const Expr *Arg = E->getArgumentExpr()->IgnoreParens(); |
960 | | |
961 | | // The kinds of expressions that we have special-case logic here for |
962 | | // should be kept up to date with the special checks for those |
963 | | // expressions in Sema. |
964 | | |
965 | | // alignof decl is always accepted, even if it doesn't make sense: we |
966 | | // default to 1 in those cases. |
967 | 0 | if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg)) |
968 | 0 | Size = ASTCtx.getDeclAlign(DRE->getDecl(), |
969 | 0 | /*RefAsPointee*/ true); |
970 | 0 | else if (const auto *ME = dyn_cast<MemberExpr>(Arg)) |
971 | 0 | Size = ASTCtx.getDeclAlign(ME->getMemberDecl(), |
972 | 0 | /*RefAsPointee*/ true); |
973 | 0 | else |
974 | 0 | Size = AlignOfType(Arg->getType(), ASTCtx, Kind); |
975 | 0 | } |
976 | |
|
977 | 0 | if (DiscardResult) |
978 | 0 | return true; |
979 | | |
980 | 0 | return this->emitConst(Size.getQuantity(), E); |
981 | 0 | } |
982 | | |
983 | 0 | return false; |
984 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitUnaryExprOrTypeTraitExpr(clang::UnaryExprOrTypeTraitExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitUnaryExprOrTypeTraitExpr(clang::UnaryExprOrTypeTraitExpr const*) |
985 | | |
986 | | template <class Emitter> |
987 | 0 | bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) { |
988 | | // 'Base.Member' |
989 | 0 | const Expr *Base = E->getBase(); |
990 | |
|
991 | 0 | if (DiscardResult) |
992 | 0 | return this->discard(Base); |
993 | | |
994 | 0 | if (!this->visit(Base)) |
995 | 0 | return false; |
996 | | |
997 | | // Base above gives us a pointer on the stack. |
998 | | // TODO: Implement non-FieldDecl members. |
999 | 0 | const ValueDecl *Member = E->getMemberDecl(); |
1000 | 0 | if (const auto *FD = dyn_cast<FieldDecl>(Member)) { |
1001 | 0 | const RecordDecl *RD = FD->getParent(); |
1002 | 0 | const Record *R = getRecord(RD); |
1003 | 0 | const Record::Field *F = R->getField(FD); |
1004 | | // Leave a pointer to the field on the stack. |
1005 | 0 | if (F->Decl->getType()->isReferenceType()) |
1006 | 0 | return this->emitGetFieldPop(PT_Ptr, F->Offset, E); |
1007 | 0 | return this->emitGetPtrField(F->Offset, E); |
1008 | 0 | } |
1009 | | |
1010 | 0 | return false; |
1011 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitMemberExpr(clang::MemberExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitMemberExpr(clang::MemberExpr const*) |
1012 | | |
1013 | | template <class Emitter> |
1014 | | bool ByteCodeExprGen<Emitter>::VisitArrayInitIndexExpr( |
1015 | 0 | const ArrayInitIndexExpr *E) { |
1016 | | // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated |
1017 | | // stand-alone, e.g. via EvaluateAsInt(). |
1018 | 0 | if (!ArrayIndex) |
1019 | 0 | return false; |
1020 | 0 | return this->emitConst(*ArrayIndex, E); |
1021 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitArrayInitIndexExpr(clang::ArrayInitIndexExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitArrayInitIndexExpr(clang::ArrayInitIndexExpr const*) |
1022 | | |
1023 | | template <class Emitter> |
1024 | | bool ByteCodeExprGen<Emitter>::VisitArrayInitLoopExpr( |
1025 | 0 | const ArrayInitLoopExpr *E) { |
1026 | 0 | assert(Initializing); |
1027 | 0 | assert(!DiscardResult); |
1028 | | // TODO: This compiles to quite a lot of bytecode if the array is larger. |
1029 | | // Investigate compiling this to a loop. |
1030 | | |
1031 | 0 | const Expr *SubExpr = E->getSubExpr(); |
1032 | 0 | const Expr *CommonExpr = E->getCommonExpr(); |
1033 | 0 | size_t Size = E->getArraySize().getZExtValue(); |
1034 | | |
1035 | | // If the common expression is an opaque expression, we visit it |
1036 | | // here once so we have its value cached. |
1037 | | // FIXME: This might be necessary (or useful) for all expressions. |
1038 | 0 | if (isa<OpaqueValueExpr>(CommonExpr)) { |
1039 | 0 | if (!this->discard(CommonExpr)) |
1040 | 0 | return false; |
1041 | 0 | } |
1042 | | |
1043 | | // So, every iteration, we execute an assignment here |
1044 | | // where the LHS is on the stack (the target array) |
1045 | | // and the RHS is our SubExpr. |
1046 | 0 | for (size_t I = 0; I != Size; ++I) { |
1047 | 0 | ArrayIndexScope<Emitter> IndexScope(this, I); |
1048 | 0 | BlockScope<Emitter> BS(this); |
1049 | |
|
1050 | 0 | if (!this->visitArrayElemInit(I, SubExpr)) |
1051 | 0 | return false; |
1052 | 0 | } |
1053 | 0 | return true; |
1054 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitArrayInitLoopExpr(clang::ArrayInitLoopExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitArrayInitLoopExpr(clang::ArrayInitLoopExpr const*) |
1055 | | |
1056 | | template <class Emitter> |
1057 | 0 | bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) { |
1058 | 0 | if (Initializing) |
1059 | 0 | return this->visitInitializer(E->getSourceExpr()); |
1060 | | |
1061 | 0 | PrimType SubExprT = classify(E->getSourceExpr()).value_or(PT_Ptr); |
1062 | 0 | if (auto It = OpaqueExprs.find(E); It != OpaqueExprs.end()) |
1063 | 0 | return this->emitGetLocal(SubExprT, It->second, E); |
1064 | | |
1065 | 0 | if (!this->visit(E->getSourceExpr())) |
1066 | 0 | return false; |
1067 | | |
1068 | | // At this point we either have the evaluated source expression or a pointer |
1069 | | // to an object on the stack. We want to create a local variable that stores |
1070 | | // this value. |
1071 | 0 | std::optional<unsigned> LocalIndex = |
1072 | 0 | allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true); |
1073 | 0 | if (!LocalIndex) |
1074 | 0 | return false; |
1075 | 0 | if (!this->emitSetLocal(SubExprT, *LocalIndex, E)) |
1076 | 0 | return false; |
1077 | | |
1078 | | // Here the local variable is created but the value is removed from the stack, |
1079 | | // so we put it back, because the caller might need it. |
1080 | 0 | if (!DiscardResult) { |
1081 | 0 | if (!this->emitGetLocal(SubExprT, *LocalIndex, E)) |
1082 | 0 | return false; |
1083 | 0 | } |
1084 | | |
1085 | | // FIXME: Ideally the cached value should be cleaned up later. |
1086 | 0 | OpaqueExprs.insert({E, *LocalIndex}); |
1087 | |
|
1088 | 0 | return true; |
1089 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitOpaqueValueExpr(clang::OpaqueValueExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitOpaqueValueExpr(clang::OpaqueValueExpr const*) |
1090 | | |
1091 | | template <class Emitter> |
1092 | | bool ByteCodeExprGen<Emitter>::VisitAbstractConditionalOperator( |
1093 | 0 | const AbstractConditionalOperator *E) { |
1094 | 0 | const Expr *Condition = E->getCond(); |
1095 | 0 | const Expr *TrueExpr = E->getTrueExpr(); |
1096 | 0 | const Expr *FalseExpr = E->getFalseExpr(); |
1097 | |
|
1098 | 0 | LabelTy LabelEnd = this->getLabel(); // Label after the operator. |
1099 | 0 | LabelTy LabelFalse = this->getLabel(); // Label for the false expr. |
1100 | |
|
1101 | 0 | if (!this->visitBool(Condition)) |
1102 | 0 | return false; |
1103 | | |
1104 | 0 | if (!this->jumpFalse(LabelFalse)) |
1105 | 0 | return false; |
1106 | | |
1107 | 0 | if (!this->delegate(TrueExpr)) |
1108 | 0 | return false; |
1109 | 0 | if (!this->jump(LabelEnd)) |
1110 | 0 | return false; |
1111 | | |
1112 | 0 | this->emitLabel(LabelFalse); |
1113 | |
|
1114 | 0 | if (!this->delegate(FalseExpr)) |
1115 | 0 | return false; |
1116 | | |
1117 | 0 | this->fallthrough(LabelEnd); |
1118 | 0 | this->emitLabel(LabelEnd); |
1119 | |
|
1120 | 0 | return true; |
1121 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitAbstractConditionalOperator(clang::AbstractConditionalOperator const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitAbstractConditionalOperator(clang::AbstractConditionalOperator const*) |
1122 | | |
1123 | | template <class Emitter> |
1124 | 0 | bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) { |
1125 | 0 | if (DiscardResult) |
1126 | 0 | return true; |
1127 | | |
1128 | 0 | if (!Initializing) { |
1129 | 0 | unsigned StringIndex = P.createGlobalString(E); |
1130 | 0 | return this->emitGetPtrGlobal(StringIndex, E); |
1131 | 0 | } |
1132 | | |
1133 | | // We are initializing an array on the stack. |
1134 | 0 | const ConstantArrayType *CAT = |
1135 | 0 | Ctx.getASTContext().getAsConstantArrayType(E->getType()); |
1136 | 0 | assert(CAT && "a string literal that's not a constant array?"); |
1137 | | |
1138 | | // If the initializer string is too long, a diagnostic has already been |
1139 | | // emitted. Read only the array length from the string literal. |
1140 | 0 | unsigned ArraySize = CAT->getSize().getZExtValue(); |
1141 | 0 | unsigned N = std::min(ArraySize, E->getLength()); |
1142 | 0 | size_t CharWidth = E->getCharByteWidth(); |
1143 | |
|
1144 | 0 | for (unsigned I = 0; I != N; ++I) { |
1145 | 0 | uint32_t CodeUnit = E->getCodeUnit(I); |
1146 | |
|
1147 | 0 | if (CharWidth == 1) { |
1148 | 0 | this->emitConstSint8(CodeUnit, E); |
1149 | 0 | this->emitInitElemSint8(I, E); |
1150 | 0 | } else if (CharWidth == 2) { |
1151 | 0 | this->emitConstUint16(CodeUnit, E); |
1152 | 0 | this->emitInitElemUint16(I, E); |
1153 | 0 | } else if (CharWidth == 4) { |
1154 | 0 | this->emitConstUint32(CodeUnit, E); |
1155 | 0 | this->emitInitElemUint32(I, E); |
1156 | 0 | } else { |
1157 | 0 | llvm_unreachable("unsupported character width"); |
1158 | 0 | } |
1159 | 0 | } |
1160 | | |
1161 | | // Fill up the rest of the char array with NUL bytes. |
1162 | 0 | for (unsigned I = N; I != ArraySize; ++I) { |
1163 | 0 | if (CharWidth == 1) { |
1164 | 0 | this->emitConstSint8(0, E); |
1165 | 0 | this->emitInitElemSint8(I, E); |
1166 | 0 | } else if (CharWidth == 2) { |
1167 | 0 | this->emitConstUint16(0, E); |
1168 | 0 | this->emitInitElemUint16(I, E); |
1169 | 0 | } else if (CharWidth == 4) { |
1170 | 0 | this->emitConstUint32(0, E); |
1171 | 0 | this->emitInitElemUint32(I, E); |
1172 | 0 | } else { |
1173 | 0 | llvm_unreachable("unsupported character width"); |
1174 | 0 | } |
1175 | 0 | } |
1176 | |
|
1177 | 0 | return true; |
1178 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitStringLiteral(clang::StringLiteral const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitStringLiteral(clang::StringLiteral const*) |
1179 | | |
1180 | | template <class Emitter> |
1181 | | bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral( |
1182 | 0 | const CharacterLiteral *E) { |
1183 | 0 | if (DiscardResult) |
1184 | 0 | return true; |
1185 | 0 | return this->emitConst(E->getValue(), E); |
1186 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCharacterLiteral(clang::CharacterLiteral const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCharacterLiteral(clang::CharacterLiteral const*) |
1187 | | |
1188 | | template <class Emitter> |
1189 | | bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator( |
1190 | 0 | const CompoundAssignOperator *E) { |
1191 | |
|
1192 | 0 | const Expr *LHS = E->getLHS(); |
1193 | 0 | const Expr *RHS = E->getRHS(); |
1194 | 0 | QualType LHSType = LHS->getType(); |
1195 | 0 | QualType LHSComputationType = E->getComputationLHSType(); |
1196 | 0 | QualType ResultType = E->getComputationResultType(); |
1197 | 0 | std::optional<PrimType> LT = classify(LHSComputationType); |
1198 | 0 | std::optional<PrimType> RT = classify(ResultType); |
1199 | |
|
1200 | 0 | assert(ResultType->isFloatingType()); |
1201 | | |
1202 | 0 | if (!LT || !RT) |
1203 | 0 | return false; |
1204 | | |
1205 | 0 | PrimType LHST = classifyPrim(LHSType); |
1206 | | |
1207 | | // C++17 onwards require that we evaluate the RHS first. |
1208 | | // Compute RHS and save it in a temporary variable so we can |
1209 | | // load it again later. |
1210 | 0 | if (!visit(RHS)) |
1211 | 0 | return false; |
1212 | | |
1213 | 0 | unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true); |
1214 | 0 | if (!this->emitSetLocal(*RT, TempOffset, E)) |
1215 | 0 | return false; |
1216 | | |
1217 | | // First, visit LHS. |
1218 | 0 | if (!visit(LHS)) |
1219 | 0 | return false; |
1220 | 0 | if (!this->emitLoad(LHST, E)) |
1221 | 0 | return false; |
1222 | | |
1223 | | // If necessary, convert LHS to its computation type. |
1224 | 0 | if (!this->emitPrimCast(LHST, classifyPrim(LHSComputationType), |
1225 | 0 | LHSComputationType, E)) |
1226 | 0 | return false; |
1227 | | |
1228 | | // Now load RHS. |
1229 | 0 | if (!this->emitGetLocal(*RT, TempOffset, E)) |
1230 | 0 | return false; |
1231 | | |
1232 | 0 | llvm::RoundingMode RM = getRoundingMode(E); |
1233 | 0 | switch (E->getOpcode()) { |
1234 | 0 | case BO_AddAssign: |
1235 | 0 | if (!this->emitAddf(RM, E)) |
1236 | 0 | return false; |
1237 | 0 | break; |
1238 | 0 | case BO_SubAssign: |
1239 | 0 | if (!this->emitSubf(RM, E)) |
1240 | 0 | return false; |
1241 | 0 | break; |
1242 | 0 | case BO_MulAssign: |
1243 | 0 | if (!this->emitMulf(RM, E)) |
1244 | 0 | return false; |
1245 | 0 | break; |
1246 | 0 | case BO_DivAssign: |
1247 | 0 | if (!this->emitDivf(RM, E)) |
1248 | 0 | return false; |
1249 | 0 | break; |
1250 | 0 | default: |
1251 | 0 | return false; |
1252 | 0 | } |
1253 | | |
1254 | 0 | if (!this->emitPrimCast(classifyPrim(ResultType), LHST, LHS->getType(), E)) |
1255 | 0 | return false; |
1256 | | |
1257 | 0 | if (DiscardResult) |
1258 | 0 | return this->emitStorePop(LHST, E); |
1259 | 0 | return this->emitStore(LHST, E); |
1260 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitFloatCompoundAssignOperator(clang::CompoundAssignOperator const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitFloatCompoundAssignOperator(clang::CompoundAssignOperator const*) |
1261 | | |
1262 | | template <class Emitter> |
1263 | | bool ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator( |
1264 | 0 | const CompoundAssignOperator *E) { |
1265 | 0 | BinaryOperatorKind Op = E->getOpcode(); |
1266 | 0 | const Expr *LHS = E->getLHS(); |
1267 | 0 | const Expr *RHS = E->getRHS(); |
1268 | 0 | std::optional<PrimType> LT = classify(LHS->getType()); |
1269 | 0 | std::optional<PrimType> RT = classify(RHS->getType()); |
1270 | |
|
1271 | 0 | if (Op != BO_AddAssign && Op != BO_SubAssign) |
1272 | 0 | return false; |
1273 | | |
1274 | 0 | if (!LT || !RT) |
1275 | 0 | return false; |
1276 | 0 | assert(*LT == PT_Ptr); |
1277 | | |
1278 | 0 | if (!visit(LHS)) |
1279 | 0 | return false; |
1280 | | |
1281 | 0 | if (!this->emitLoadPtr(LHS)) |
1282 | 0 | return false; |
1283 | | |
1284 | 0 | if (!visit(RHS)) |
1285 | 0 | return false; |
1286 | | |
1287 | 0 | if (Op == BO_AddAssign) |
1288 | 0 | this->emitAddOffset(*RT, E); |
1289 | 0 | else |
1290 | 0 | this->emitSubOffset(*RT, E); |
1291 | |
|
1292 | 0 | if (DiscardResult) |
1293 | 0 | return this->emitStorePopPtr(E); |
1294 | 0 | return this->emitStorePtr(E); |
1295 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitPointerCompoundAssignOperator(clang::CompoundAssignOperator const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitPointerCompoundAssignOperator(clang::CompoundAssignOperator const*) |
1296 | | |
1297 | | template <class Emitter> |
1298 | | bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator( |
1299 | 0 | const CompoundAssignOperator *E) { |
1300 | |
|
1301 | 0 | const Expr *LHS = E->getLHS(); |
1302 | 0 | const Expr *RHS = E->getRHS(); |
1303 | 0 | std::optional<PrimType> LHSComputationT = |
1304 | 0 | classify(E->getComputationLHSType()); |
1305 | 0 | std::optional<PrimType> LT = classify(LHS->getType()); |
1306 | 0 | std::optional<PrimType> RT = classify(E->getComputationResultType()); |
1307 | 0 | std::optional<PrimType> ResultT = classify(E->getType()); |
1308 | |
|
1309 | 0 | if (!LT || !RT || !ResultT || !LHSComputationT) |
1310 | 0 | return false; |
1311 | | |
1312 | | // Handle floating point operations separately here, since they |
1313 | | // require special care. |
1314 | | |
1315 | 0 | if (ResultT == PT_Float || RT == PT_Float) |
1316 | 0 | return VisitFloatCompoundAssignOperator(E); |
1317 | | |
1318 | 0 | if (E->getType()->isPointerType()) |
1319 | 0 | return VisitPointerCompoundAssignOperator(E); |
1320 | | |
1321 | 0 | assert(!E->getType()->isPointerType() && "Handled above"); |
1322 | 0 | assert(!E->getType()->isFloatingType() && "Handled above"); |
1323 | | |
1324 | | // C++17 onwards require that we evaluate the RHS first. |
1325 | | // Compute RHS and save it in a temporary variable so we can |
1326 | | // load it again later. |
1327 | | // FIXME: Compound assignments are unsequenced in C, so we might |
1328 | | // have to figure out how to reject them. |
1329 | 0 | if (!visit(RHS)) |
1330 | 0 | return false; |
1331 | | |
1332 | 0 | unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true); |
1333 | |
|
1334 | 0 | if (!this->emitSetLocal(*RT, TempOffset, E)) |
1335 | 0 | return false; |
1336 | | |
1337 | | // Get LHS pointer, load its value and cast it to the |
1338 | | // computation type if necessary. |
1339 | 0 | if (!visit(LHS)) |
1340 | 0 | return false; |
1341 | 0 | if (!this->emitLoad(*LT, E)) |
1342 | 0 | return false; |
1343 | 0 | if (*LT != *LHSComputationT) { |
1344 | 0 | if (!this->emitCast(*LT, *LHSComputationT, E)) |
1345 | 0 | return false; |
1346 | 0 | } |
1347 | | |
1348 | | // Get the RHS value on the stack. |
1349 | 0 | if (!this->emitGetLocal(*RT, TempOffset, E)) |
1350 | 0 | return false; |
1351 | | |
1352 | | // Perform operation. |
1353 | 0 | switch (E->getOpcode()) { |
1354 | 0 | case BO_AddAssign: |
1355 | 0 | if (!this->emitAdd(*LHSComputationT, E)) |
1356 | 0 | return false; |
1357 | 0 | break; |
1358 | 0 | case BO_SubAssign: |
1359 | 0 | if (!this->emitSub(*LHSComputationT, E)) |
1360 | 0 | return false; |
1361 | 0 | break; |
1362 | 0 | case BO_MulAssign: |
1363 | 0 | if (!this->emitMul(*LHSComputationT, E)) |
1364 | 0 | return false; |
1365 | 0 | break; |
1366 | 0 | case BO_DivAssign: |
1367 | 0 | if (!this->emitDiv(*LHSComputationT, E)) |
1368 | 0 | return false; |
1369 | 0 | break; |
1370 | 0 | case BO_RemAssign: |
1371 | 0 | if (!this->emitRem(*LHSComputationT, E)) |
1372 | 0 | return false; |
1373 | 0 | break; |
1374 | 0 | case BO_ShlAssign: |
1375 | 0 | if (!this->emitShl(*LHSComputationT, *RT, E)) |
1376 | 0 | return false; |
1377 | 0 | break; |
1378 | 0 | case BO_ShrAssign: |
1379 | 0 | if (!this->emitShr(*LHSComputationT, *RT, E)) |
1380 | 0 | return false; |
1381 | 0 | break; |
1382 | 0 | case BO_AndAssign: |
1383 | 0 | if (!this->emitBitAnd(*LHSComputationT, E)) |
1384 | 0 | return false; |
1385 | 0 | break; |
1386 | 0 | case BO_XorAssign: |
1387 | 0 | if (!this->emitBitXor(*LHSComputationT, E)) |
1388 | 0 | return false; |
1389 | 0 | break; |
1390 | 0 | case BO_OrAssign: |
1391 | 0 | if (!this->emitBitOr(*LHSComputationT, E)) |
1392 | 0 | return false; |
1393 | 0 | break; |
1394 | 0 | default: |
1395 | 0 | llvm_unreachable("Unimplemented compound assign operator"); |
1396 | 0 | } |
1397 | | |
1398 | | // And now cast from LHSComputationT to ResultT. |
1399 | 0 | if (*ResultT != *LHSComputationT) { |
1400 | 0 | if (!this->emitCast(*LHSComputationT, *ResultT, E)) |
1401 | 0 | return false; |
1402 | 0 | } |
1403 | | |
1404 | | // And store the result in LHS. |
1405 | 0 | if (DiscardResult) { |
1406 | 0 | if (LHS->refersToBitField()) |
1407 | 0 | return this->emitStoreBitFieldPop(*ResultT, E); |
1408 | 0 | return this->emitStorePop(*ResultT, E); |
1409 | 0 | } |
1410 | 0 | if (LHS->refersToBitField()) |
1411 | 0 | return this->emitStoreBitField(*ResultT, E); |
1412 | 0 | return this->emitStore(*ResultT, E); |
1413 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCompoundAssignOperator(clang::CompoundAssignOperator const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCompoundAssignOperator(clang::CompoundAssignOperator const*) |
1414 | | |
1415 | | template <class Emitter> |
1416 | | bool ByteCodeExprGen<Emitter>::VisitExprWithCleanups( |
1417 | 0 | const ExprWithCleanups *E) { |
1418 | 0 | const Expr *SubExpr = E->getSubExpr(); |
1419 | |
|
1420 | 0 | assert(E->getNumObjects() == 0 && "TODO: Implement cleanups"); |
1421 | | |
1422 | 0 | return this->delegate(SubExpr); |
1423 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitExprWithCleanups(clang::ExprWithCleanups const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitExprWithCleanups(clang::ExprWithCleanups const*) |
1424 | | |
1425 | | template <class Emitter> |
1426 | | bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr( |
1427 | 0 | const MaterializeTemporaryExpr *E) { |
1428 | 0 | const Expr *SubExpr = E->getSubExpr(); |
1429 | |
|
1430 | 0 | if (Initializing) { |
1431 | | // We already have a value, just initialize that. |
1432 | 0 | return this->visitInitializer(SubExpr); |
1433 | 0 | } |
1434 | | // If we don't end up using the materialized temporary anyway, don't |
1435 | | // bother creating it. |
1436 | 0 | if (DiscardResult) |
1437 | 0 | return this->discard(SubExpr); |
1438 | | |
1439 | | // When we're initializing a global variable *or* the storage duration of |
1440 | | // the temporary is explicitly static, create a global variable. |
1441 | 0 | std::optional<PrimType> SubExprT = classify(SubExpr); |
1442 | 0 | bool IsStatic = E->getStorageDuration() == SD_Static; |
1443 | 0 | if (GlobalDecl || IsStatic) { |
1444 | 0 | std::optional<unsigned> GlobalIndex = P.createGlobal(E); |
1445 | 0 | if (!GlobalIndex) |
1446 | 0 | return false; |
1447 | | |
1448 | 0 | const LifetimeExtendedTemporaryDecl *TempDecl = |
1449 | 0 | E->getLifetimeExtendedTemporaryDecl(); |
1450 | 0 | if (IsStatic) |
1451 | 0 | assert(TempDecl); |
1452 | | |
1453 | 0 | if (SubExprT) { |
1454 | 0 | if (!this->visit(SubExpr)) |
1455 | 0 | return false; |
1456 | 0 | if (IsStatic) { |
1457 | 0 | if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E)) |
1458 | 0 | return false; |
1459 | 0 | } else { |
1460 | 0 | if (!this->emitInitGlobal(*SubExprT, *GlobalIndex, E)) |
1461 | 0 | return false; |
1462 | 0 | } |
1463 | 0 | return this->emitGetPtrGlobal(*GlobalIndex, E); |
1464 | 0 | } |
1465 | | |
1466 | | // Non-primitive values. |
1467 | 0 | if (!this->emitGetPtrGlobal(*GlobalIndex, E)) |
1468 | 0 | return false; |
1469 | 0 | if (!this->visitInitializer(SubExpr)) |
1470 | 0 | return false; |
1471 | 0 | if (IsStatic) |
1472 | 0 | return this->emitInitGlobalTempComp(TempDecl, E); |
1473 | 0 | return true; |
1474 | 0 | } |
1475 | | |
1476 | | // For everyhing else, use local variables. |
1477 | 0 | if (SubExprT) { |
1478 | 0 | if (std::optional<unsigned> LocalIndex = allocateLocalPrimitive( |
1479 | 0 | SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true)) { |
1480 | 0 | if (!this->visit(SubExpr)) |
1481 | 0 | return false; |
1482 | 0 | this->emitSetLocal(*SubExprT, *LocalIndex, E); |
1483 | 0 | return this->emitGetPtrLocal(*LocalIndex, E); |
1484 | 0 | } |
1485 | 0 | } else { |
1486 | 0 | if (std::optional<unsigned> LocalIndex = |
1487 | 0 | allocateLocal(SubExpr, /*IsExtended=*/true)) { |
1488 | 0 | if (!this->emitGetPtrLocal(*LocalIndex, E)) |
1489 | 0 | return false; |
1490 | 0 | return this->visitInitializer(SubExpr); |
1491 | 0 | } |
1492 | 0 | } |
1493 | 0 | return false; |
1494 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitMaterializeTemporaryExpr(clang::MaterializeTemporaryExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitMaterializeTemporaryExpr(clang::MaterializeTemporaryExpr const*) |
1495 | | |
1496 | | template <class Emitter> |
1497 | | bool ByteCodeExprGen<Emitter>::VisitCXXBindTemporaryExpr( |
1498 | 0 | const CXXBindTemporaryExpr *E) { |
1499 | 0 | return this->delegate(E->getSubExpr()); |
1500 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXBindTemporaryExpr(clang::CXXBindTemporaryExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXBindTemporaryExpr(clang::CXXBindTemporaryExpr const*) |
1501 | | |
1502 | | template <class Emitter> |
1503 | | bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr( |
1504 | 0 | const CompoundLiteralExpr *E) { |
1505 | 0 | const Expr *Init = E->getInitializer(); |
1506 | 0 | if (Initializing) { |
1507 | | // We already have a value, just initialize that. |
1508 | 0 | return this->visitInitializer(Init); |
1509 | 0 | } |
1510 | | |
1511 | 0 | std::optional<PrimType> T = classify(E->getType()); |
1512 | 0 | if (E->isFileScope()) { |
1513 | 0 | if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) { |
1514 | 0 | if (classify(E->getType())) |
1515 | 0 | return this->visit(Init); |
1516 | 0 | if (!this->emitGetPtrGlobal(*GlobalIndex, E)) |
1517 | 0 | return false; |
1518 | 0 | return this->visitInitializer(Init); |
1519 | 0 | } |
1520 | 0 | } |
1521 | | |
1522 | | // Otherwise, use a local variable. |
1523 | 0 | if (T) { |
1524 | | // For primitive types, we just visit the initializer. |
1525 | 0 | return this->delegate(Init); |
1526 | 0 | } else { |
1527 | 0 | if (std::optional<unsigned> LocalIndex = allocateLocal(Init)) { |
1528 | 0 | if (!this->emitGetPtrLocal(*LocalIndex, E)) |
1529 | 0 | return false; |
1530 | 0 | if (!this->visitInitializer(Init)) |
1531 | 0 | return false; |
1532 | 0 | if (DiscardResult) |
1533 | 0 | return this->emitPopPtr(E); |
1534 | 0 | return true; |
1535 | 0 | } |
1536 | 0 | } |
1537 | | |
1538 | 0 | return false; |
1539 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCompoundLiteralExpr(clang::CompoundLiteralExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCompoundLiteralExpr(clang::CompoundLiteralExpr const*) |
1540 | | |
1541 | | template <class Emitter> |
1542 | 0 | bool ByteCodeExprGen<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) { |
1543 | 0 | if (DiscardResult) |
1544 | 0 | return true; |
1545 | 0 | return this->emitConstBool(E->getValue(), E); |
1546 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitTypeTraitExpr(clang::TypeTraitExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitTypeTraitExpr(clang::TypeTraitExpr const*) |
1547 | | |
1548 | | template <class Emitter> |
1549 | 0 | bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) { |
1550 | 0 | assert(Initializing); |
1551 | 0 | const Record *R = P.getOrCreateRecord(E->getLambdaClass()); |
1552 | |
|
1553 | 0 | auto *CaptureInitIt = E->capture_init_begin(); |
1554 | | // Initialize all fields (which represent lambda captures) of the |
1555 | | // record with their initializers. |
1556 | 0 | for (const Record::Field &F : R->fields()) { |
1557 | 0 | const Expr *Init = *CaptureInitIt; |
1558 | 0 | ++CaptureInitIt; |
1559 | |
|
1560 | 0 | if (std::optional<PrimType> T = classify(Init)) { |
1561 | 0 | if (!this->visit(Init)) |
1562 | 0 | return false; |
1563 | | |
1564 | 0 | if (!this->emitSetField(*T, F.Offset, E)) |
1565 | 0 | return false; |
1566 | 0 | } else { |
1567 | 0 | if (!this->emitDupPtr(E)) |
1568 | 0 | return false; |
1569 | | |
1570 | 0 | if (!this->emitGetPtrField(F.Offset, E)) |
1571 | 0 | return false; |
1572 | | |
1573 | 0 | if (!this->visitInitializer(Init)) |
1574 | 0 | return false; |
1575 | | |
1576 | 0 | if (!this->emitPopPtr(E)) |
1577 | 0 | return false; |
1578 | 0 | } |
1579 | 0 | } |
1580 | | |
1581 | 0 | return true; |
1582 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitLambdaExpr(clang::LambdaExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitLambdaExpr(clang::LambdaExpr const*) |
1583 | | |
1584 | | template <class Emitter> |
1585 | 0 | bool ByteCodeExprGen<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) { |
1586 | 0 | if (DiscardResult) |
1587 | 0 | return true; |
1588 | | |
1589 | 0 | assert(!Initializing); |
1590 | 0 | return this->visit(E->getFunctionName()); |
1591 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitPredefinedExpr(clang::PredefinedExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitPredefinedExpr(clang::PredefinedExpr const*) |
1592 | | |
1593 | | template <class Emitter> |
1594 | 0 | bool ByteCodeExprGen<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) { |
1595 | 0 | if (E->getSubExpr() && !this->discard(E->getSubExpr())) |
1596 | 0 | return false; |
1597 | | |
1598 | 0 | return this->emitInvalid(E); |
1599 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXThrowExpr(clang::CXXThrowExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXThrowExpr(clang::CXXThrowExpr const*) |
1600 | | |
1601 | | template <class Emitter> |
1602 | | bool ByteCodeExprGen<Emitter>::VisitCXXReinterpretCastExpr( |
1603 | 0 | const CXXReinterpretCastExpr *E) { |
1604 | 0 | if (!this->discard(E->getSubExpr())) |
1605 | 0 | return false; |
1606 | | |
1607 | 0 | return this->emitInvalidCast(CastKind::Reinterpret, E); |
1608 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXReinterpretCastExpr(clang::CXXReinterpretCastExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXReinterpretCastExpr(clang::CXXReinterpretCastExpr const*) |
1609 | | |
1610 | | template <class Emitter> |
1611 | 0 | bool ByteCodeExprGen<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { |
1612 | 0 | assert(E->getType()->isBooleanType()); |
1613 | | |
1614 | 0 | if (DiscardResult) |
1615 | 0 | return true; |
1616 | 0 | return this->emitConstBool(E->getValue(), E); |
1617 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXNoexceptExpr(clang::CXXNoexceptExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXNoexceptExpr(clang::CXXNoexceptExpr const*) |
1618 | | |
1619 | | template <class Emitter> |
1620 | | bool ByteCodeExprGen<Emitter>::VisitCXXConstructExpr( |
1621 | 0 | const CXXConstructExpr *E) { |
1622 | 0 | QualType T = E->getType(); |
1623 | 0 | assert(!classify(T)); |
1624 | | |
1625 | 0 | if (T->isRecordType()) { |
1626 | 0 | const CXXConstructorDecl *Ctor = E->getConstructor(); |
1627 | | |
1628 | | // Trivial zero initialization. |
1629 | 0 | if (E->requiresZeroInitialization() && Ctor->isTrivial()) { |
1630 | 0 | const Record *R = getRecord(E->getType()); |
1631 | 0 | return this->visitZeroRecordInitializer(R, E); |
1632 | 0 | } |
1633 | | |
1634 | 0 | const Function *Func = getFunction(Ctor); |
1635 | |
|
1636 | 0 | if (!Func) |
1637 | 0 | return false; |
1638 | | |
1639 | 0 | assert(Func->hasThisPointer()); |
1640 | 0 | assert(!Func->hasRVO()); |
1641 | | |
1642 | | // If we're discarding a construct expression, we still need |
1643 | | // to allocate a variable and call the constructor and destructor. |
1644 | 0 | if (DiscardResult) { |
1645 | 0 | assert(!Initializing); |
1646 | 0 | std::optional<unsigned> LocalIndex = |
1647 | 0 | allocateLocal(E, /*IsExtended=*/true); |
1648 | |
|
1649 | 0 | if (!LocalIndex) |
1650 | 0 | return false; |
1651 | | |
1652 | 0 | if (!this->emitGetPtrLocal(*LocalIndex, E)) |
1653 | 0 | return false; |
1654 | 0 | } |
1655 | | |
1656 | | // The This pointer is already on the stack because this is an initializer, |
1657 | | // but we need to dup() so the call() below has its own copy. |
1658 | 0 | if (!this->emitDupPtr(E)) |
1659 | 0 | return false; |
1660 | | |
1661 | | // Constructor arguments. |
1662 | 0 | for (const auto *Arg : E->arguments()) { |
1663 | 0 | if (!this->visit(Arg)) |
1664 | 0 | return false; |
1665 | 0 | } |
1666 | | |
1667 | 0 | if (!this->emitCall(Func, E)) |
1668 | 0 | return false; |
1669 | | |
1670 | | // Immediately call the destructor if we have to. |
1671 | 0 | if (DiscardResult) { |
1672 | 0 | if (!this->emitPopPtr(E)) |
1673 | 0 | return false; |
1674 | 0 | } |
1675 | 0 | return true; |
1676 | 0 | } |
1677 | | |
1678 | 0 | if (T->isArrayType()) { |
1679 | 0 | const ConstantArrayType *CAT = |
1680 | 0 | Ctx.getASTContext().getAsConstantArrayType(E->getType()); |
1681 | 0 | assert(CAT); |
1682 | 0 | size_t NumElems = CAT->getSize().getZExtValue(); |
1683 | 0 | const Function *Func = getFunction(E->getConstructor()); |
1684 | 0 | if (!Func || !Func->isConstexpr()) |
1685 | 0 | return false; |
1686 | | |
1687 | | // FIXME(perf): We're calling the constructor once per array element here, |
1688 | | // in the old intepreter we had a special-case for trivial constructors. |
1689 | 0 | for (size_t I = 0; I != NumElems; ++I) { |
1690 | 0 | if (!this->emitConstUint64(I, E)) |
1691 | 0 | return false; |
1692 | 0 | if (!this->emitArrayElemPtrUint64(E)) |
1693 | 0 | return false; |
1694 | | |
1695 | | // Constructor arguments. |
1696 | 0 | for (const auto *Arg : E->arguments()) { |
1697 | 0 | if (!this->visit(Arg)) |
1698 | 0 | return false; |
1699 | 0 | } |
1700 | | |
1701 | 0 | if (!this->emitCall(Func, E)) |
1702 | 0 | return false; |
1703 | 0 | } |
1704 | 0 | return true; |
1705 | 0 | } |
1706 | | |
1707 | 0 | return false; |
1708 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXConstructExpr(clang::CXXConstructExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXConstructExpr(clang::CXXConstructExpr const*) |
1709 | | |
1710 | | template <class Emitter> |
1711 | 0 | bool ByteCodeExprGen<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) { |
1712 | 0 | if (DiscardResult) |
1713 | 0 | return true; |
1714 | | |
1715 | 0 | const APValue Val = |
1716 | 0 | E->EvaluateInContext(Ctx.getASTContext(), SourceLocDefaultExpr); |
1717 | | |
1718 | | // Things like __builtin_LINE(). |
1719 | 0 | if (E->getType()->isIntegerType()) { |
1720 | 0 | assert(Val.isInt()); |
1721 | 0 | const APSInt &I = Val.getInt(); |
1722 | 0 | return this->emitConst(I, E); |
1723 | 0 | } |
1724 | | // Otherwise, the APValue is an LValue, with only one element. |
1725 | | // Theoretically, we don't need the APValue at all of course. |
1726 | 0 | assert(E->getType()->isPointerType()); |
1727 | 0 | assert(Val.isLValue()); |
1728 | 0 | const APValue::LValueBase &Base = Val.getLValueBase(); |
1729 | 0 | if (const Expr *LValueExpr = Base.dyn_cast<const Expr *>()) |
1730 | 0 | return this->visit(LValueExpr); |
1731 | | |
1732 | | // Otherwise, we have a decl (which is the case for |
1733 | | // __builtin_source_location). |
1734 | 0 | assert(Base.is<const ValueDecl *>()); |
1735 | 0 | assert(Val.getLValuePath().size() == 0); |
1736 | 0 | const auto *BaseDecl = Base.dyn_cast<const ValueDecl *>(); |
1737 | 0 | assert(BaseDecl); |
1738 | | |
1739 | 0 | auto *UGCD = cast<UnnamedGlobalConstantDecl>(BaseDecl); |
1740 | |
|
1741 | 0 | std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(UGCD); |
1742 | 0 | if (!GlobalIndex) |
1743 | 0 | return false; |
1744 | | |
1745 | 0 | if (!this->emitGetPtrGlobal(*GlobalIndex, E)) |
1746 | 0 | return false; |
1747 | | |
1748 | 0 | const Record *R = getRecord(E->getType()); |
1749 | 0 | const APValue &V = UGCD->getValue(); |
1750 | 0 | for (unsigned I = 0, N = R->getNumFields(); I != N; ++I) { |
1751 | 0 | const Record::Field *F = R->getField(I); |
1752 | 0 | const APValue &FieldValue = V.getStructField(I); |
1753 | |
|
1754 | 0 | PrimType FieldT = classifyPrim(F->Decl->getType()); |
1755 | |
|
1756 | 0 | if (!this->visitAPValue(FieldValue, FieldT, E)) |
1757 | 0 | return false; |
1758 | 0 | if (!this->emitInitField(FieldT, F->Offset, E)) |
1759 | 0 | return false; |
1760 | 0 | } |
1761 | | |
1762 | | // Leave the pointer to the global on the stack. |
1763 | 0 | return true; |
1764 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitSourceLocExpr(clang::SourceLocExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitSourceLocExpr(clang::SourceLocExpr const*) |
1765 | | |
1766 | | template <class Emitter> |
1767 | 0 | bool ByteCodeExprGen<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) { |
1768 | 0 | unsigned N = E->getNumComponents(); |
1769 | 0 | if (N == 0) |
1770 | 0 | return false; |
1771 | | |
1772 | 0 | for (unsigned I = 0; I != N; ++I) { |
1773 | 0 | const OffsetOfNode &Node = E->getComponent(I); |
1774 | 0 | if (Node.getKind() == OffsetOfNode::Array) { |
1775 | 0 | const Expr *ArrayIndexExpr = E->getIndexExpr(Node.getArrayExprIndex()); |
1776 | 0 | PrimType IndexT = classifyPrim(ArrayIndexExpr->getType()); |
1777 | |
|
1778 | 0 | if (DiscardResult) { |
1779 | 0 | if (!this->discard(ArrayIndexExpr)) |
1780 | 0 | return false; |
1781 | 0 | continue; |
1782 | 0 | } |
1783 | | |
1784 | 0 | if (!this->visit(ArrayIndexExpr)) |
1785 | 0 | return false; |
1786 | | // Cast to Sint64. |
1787 | 0 | if (IndexT != PT_Sint64) { |
1788 | 0 | if (!this->emitCast(IndexT, PT_Sint64, E)) |
1789 | 0 | return false; |
1790 | 0 | } |
1791 | 0 | } |
1792 | 0 | } |
1793 | | |
1794 | 0 | if (DiscardResult) |
1795 | 0 | return true; |
1796 | | |
1797 | 0 | PrimType T = classifyPrim(E->getType()); |
1798 | 0 | return this->emitOffsetOf(T, E, E); |
1799 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitOffsetOfExpr(clang::OffsetOfExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitOffsetOfExpr(clang::OffsetOfExpr const*) |
1800 | | |
1801 | | template <class Emitter> |
1802 | | bool ByteCodeExprGen<Emitter>::VisitCXXScalarValueInitExpr( |
1803 | 0 | const CXXScalarValueInitExpr *E) { |
1804 | 0 | QualType Ty = E->getType(); |
1805 | |
|
1806 | 0 | if (Ty->isVoidType()) |
1807 | 0 | return true; |
1808 | | |
1809 | 0 | return this->visitZeroInitializer(classifyPrim(Ty), Ty, E); |
1810 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXScalarValueInitExpr(clang::CXXScalarValueInitExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXScalarValueInitExpr(clang::CXXScalarValueInitExpr const*) |
1811 | | |
1812 | | template <class Emitter> |
1813 | 0 | bool ByteCodeExprGen<Emitter>::VisitSizeOfPackExpr(const SizeOfPackExpr *E) { |
1814 | 0 | return this->emitConst(E->getPackLength(), E); |
1815 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitSizeOfPackExpr(clang::SizeOfPackExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitSizeOfPackExpr(clang::SizeOfPackExpr const*) |
1816 | | |
1817 | 0 | template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) { |
1818 | 0 | if (E->containsErrors()) |
1819 | 0 | return false; |
1820 | | |
1821 | 0 | OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true, |
1822 | 0 | /*NewInitializing=*/false); |
1823 | 0 | return this->Visit(E); |
1824 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::discard(clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::discard(clang::Expr const*) |
1825 | | |
1826 | | template <class Emitter> |
1827 | 0 | bool ByteCodeExprGen<Emitter>::delegate(const Expr *E) { |
1828 | 0 | if (E->containsErrors()) |
1829 | 0 | return false; |
1830 | | |
1831 | | // We're basically doing: |
1832 | | // OptionScope<Emitter> Scope(this, DicardResult, Initializing); |
1833 | | // but that's unnecessary of course. |
1834 | 0 | return this->Visit(E); |
1835 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::delegate(clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::delegate(clang::Expr const*) |
1836 | | |
1837 | 0 | template <class Emitter> bool ByteCodeExprGen<Emitter>::visit(const Expr *E) { |
1838 | 0 | if (E->containsErrors()) |
1839 | 0 | return false; |
1840 | | |
1841 | 0 | if (E->getType()->isVoidType()) |
1842 | 0 | return this->discard(E); |
1843 | | |
1844 | | // Create local variable to hold the return value. |
1845 | 0 | if (!E->isGLValue() && !E->getType()->isAnyComplexType() && |
1846 | 0 | !classify(E->getType())) { |
1847 | 0 | std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/true); |
1848 | 0 | if (!LocalIndex) |
1849 | 0 | return false; |
1850 | | |
1851 | 0 | if (!this->emitGetPtrLocal(*LocalIndex, E)) |
1852 | 0 | return false; |
1853 | 0 | return this->visitInitializer(E); |
1854 | 0 | } |
1855 | | |
1856 | | // Otherwise,we have a primitive return value, produce the value directly |
1857 | | // and push it on the stack. |
1858 | 0 | OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false, |
1859 | 0 | /*NewInitializing=*/false); |
1860 | 0 | return this->Visit(E); |
1861 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visit(clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visit(clang::Expr const*) |
1862 | | |
1863 | | template <class Emitter> |
1864 | 0 | bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *E) { |
1865 | 0 | assert(!classify(E->getType())); |
1866 | | |
1867 | 0 | if (E->containsErrors()) |
1868 | 0 | return false; |
1869 | | |
1870 | 0 | OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false, |
1871 | 0 | /*NewInitializing=*/true); |
1872 | 0 | return this->Visit(E); |
1873 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitInitializer(clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitInitializer(clang::Expr const*) |
1874 | | |
1875 | | template <class Emitter> |
1876 | 0 | bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) { |
1877 | 0 | std::optional<PrimType> T = classify(E->getType()); |
1878 | 0 | if (!T) |
1879 | 0 | return false; |
1880 | | |
1881 | 0 | if (!this->visit(E)) |
1882 | 0 | return false; |
1883 | | |
1884 | 0 | if (T == PT_Bool) |
1885 | 0 | return true; |
1886 | | |
1887 | | // Convert pointers to bool. |
1888 | 0 | if (T == PT_Ptr || T == PT_FnPtr) { |
1889 | 0 | if (!this->emitNull(*T, E)) |
1890 | 0 | return false; |
1891 | 0 | return this->emitNE(*T, E); |
1892 | 0 | } |
1893 | | |
1894 | | // Or Floats. |
1895 | 0 | if (T == PT_Float) |
1896 | 0 | return this->emitCastFloatingIntegralBool(E); |
1897 | | |
1898 | | // Or anything else we can. |
1899 | 0 | return this->emitCast(*T, PT_Bool, E); |
1900 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitBool(clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitBool(clang::Expr const*) |
1901 | | |
1902 | | template <class Emitter> |
1903 | | bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, QualType QT, |
1904 | 0 | const Expr *E) { |
1905 | 0 | switch (T) { |
1906 | 0 | case PT_Bool: |
1907 | 0 | return this->emitZeroBool(E); |
1908 | 0 | case PT_Sint8: |
1909 | 0 | return this->emitZeroSint8(E); |
1910 | 0 | case PT_Uint8: |
1911 | 0 | return this->emitZeroUint8(E); |
1912 | 0 | case PT_Sint16: |
1913 | 0 | return this->emitZeroSint16(E); |
1914 | 0 | case PT_Uint16: |
1915 | 0 | return this->emitZeroUint16(E); |
1916 | 0 | case PT_Sint32: |
1917 | 0 | return this->emitZeroSint32(E); |
1918 | 0 | case PT_Uint32: |
1919 | 0 | return this->emitZeroUint32(E); |
1920 | 0 | case PT_Sint64: |
1921 | 0 | return this->emitZeroSint64(E); |
1922 | 0 | case PT_Uint64: |
1923 | 0 | return this->emitZeroUint64(E); |
1924 | 0 | case PT_IntAP: |
1925 | 0 | return this->emitZeroIntAP(Ctx.getBitWidth(QT), E); |
1926 | 0 | case PT_IntAPS: |
1927 | 0 | return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E); |
1928 | 0 | case PT_Ptr: |
1929 | 0 | return this->emitNullPtr(E); |
1930 | 0 | case PT_FnPtr: |
1931 | 0 | return this->emitNullFnPtr(E); |
1932 | 0 | case PT_Float: { |
1933 | 0 | return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E); |
1934 | 0 | } |
1935 | 0 | } |
1936 | 0 | llvm_unreachable("unknown primitive type"); |
1937 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitZeroInitializer(clang::interp::PrimType, clang::QualType, clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitZeroInitializer(clang::interp::PrimType, clang::QualType, clang::Expr const*) |
1938 | | |
1939 | | template <class Emitter> |
1940 | | bool ByteCodeExprGen<Emitter>::visitZeroRecordInitializer(const Record *R, |
1941 | 0 | const Expr *E) { |
1942 | 0 | assert(E); |
1943 | 0 | assert(R); |
1944 | | // Fields |
1945 | 0 | for (const Record::Field &Field : R->fields()) { |
1946 | 0 | const Descriptor *D = Field.Desc; |
1947 | 0 | if (D->isPrimitive()) { |
1948 | 0 | QualType QT = D->getType(); |
1949 | 0 | PrimType T = classifyPrim(D->getType()); |
1950 | 0 | if (!this->visitZeroInitializer(T, QT, E)) |
1951 | 0 | return false; |
1952 | 0 | if (!this->emitInitField(T, Field.Offset, E)) |
1953 | 0 | return false; |
1954 | 0 | continue; |
1955 | 0 | } |
1956 | | |
1957 | | // TODO: Add GetPtrFieldPop and get rid of this dup. |
1958 | 0 | if (!this->emitDupPtr(E)) |
1959 | 0 | return false; |
1960 | 0 | if (!this->emitGetPtrField(Field.Offset, E)) |
1961 | 0 | return false; |
1962 | | |
1963 | 0 | if (D->isPrimitiveArray()) { |
1964 | 0 | QualType ET = D->getElemQualType(); |
1965 | 0 | PrimType T = classifyPrim(ET); |
1966 | 0 | for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) { |
1967 | 0 | if (!this->visitZeroInitializer(T, ET, E)) |
1968 | 0 | return false; |
1969 | 0 | if (!this->emitInitElem(T, I, E)) |
1970 | 0 | return false; |
1971 | 0 | } |
1972 | 0 | } else if (D->isCompositeArray()) { |
1973 | 0 | const Record *ElemRecord = D->ElemDesc->ElemRecord; |
1974 | 0 | assert(D->ElemDesc->ElemRecord); |
1975 | 0 | for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) { |
1976 | 0 | if (!this->emitConstUint32(I, E)) |
1977 | 0 | return false; |
1978 | 0 | if (!this->emitArrayElemPtr(PT_Uint32, E)) |
1979 | 0 | return false; |
1980 | 0 | if (!this->visitZeroRecordInitializer(ElemRecord, E)) |
1981 | 0 | return false; |
1982 | 0 | if (!this->emitPopPtr(E)) |
1983 | 0 | return false; |
1984 | 0 | } |
1985 | 0 | } else if (D->isRecord()) { |
1986 | 0 | if (!this->visitZeroRecordInitializer(D->ElemRecord, E)) |
1987 | 0 | return false; |
1988 | 0 | } else { |
1989 | 0 | assert(false); |
1990 | 0 | } |
1991 | | |
1992 | 0 | if (!this->emitPopPtr(E)) |
1993 | 0 | return false; |
1994 | 0 | } |
1995 | | |
1996 | 0 | for (const Record::Base &B : R->bases()) { |
1997 | 0 | if (!this->emitGetPtrBase(B.Offset, E)) |
1998 | 0 | return false; |
1999 | 0 | if (!this->visitZeroRecordInitializer(B.R, E)) |
2000 | 0 | return false; |
2001 | 0 | if (!this->emitInitPtrPop(E)) |
2002 | 0 | return false; |
2003 | 0 | } |
2004 | | |
2005 | | // FIXME: Virtual bases. |
2006 | | |
2007 | 0 | return true; |
2008 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitZeroRecordInitializer(clang::interp::Record const*, clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitZeroRecordInitializer(clang::interp::Record const*, clang::Expr const*) |
2009 | | |
2010 | | template <class Emitter> |
2011 | | bool ByteCodeExprGen<Emitter>::dereference( |
2012 | | const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct, |
2013 | 0 | llvm::function_ref<bool(PrimType)> Indirect) { |
2014 | 0 | if (std::optional<PrimType> T = classify(LV->getType())) { |
2015 | 0 | if (!LV->refersToBitField()) { |
2016 | | // Only primitive, non bit-field types can be dereferenced directly. |
2017 | 0 | if (const auto *DE = dyn_cast<DeclRefExpr>(LV)) { |
2018 | 0 | if (!DE->getDecl()->getType()->isReferenceType()) { |
2019 | 0 | if (const auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl())) |
2020 | 0 | return dereferenceParam(LV, *T, PD, AK, Direct, Indirect); |
2021 | 0 | if (const auto *VD = dyn_cast<VarDecl>(DE->getDecl())) |
2022 | 0 | return dereferenceVar(LV, *T, VD, AK, Direct, Indirect); |
2023 | 0 | } |
2024 | 0 | } |
2025 | 0 | } |
2026 | | |
2027 | 0 | if (!visit(LV)) |
2028 | 0 | return false; |
2029 | 0 | return Indirect(*T); |
2030 | 0 | } |
2031 | | |
2032 | 0 | if (LV->getType()->isAnyComplexType()) |
2033 | 0 | return visit(LV); |
2034 | | |
2035 | 0 | return false; |
2036 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::dereference(clang::Expr const*, clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::DerefKind, llvm::function_ref<bool (clang::interp::PrimType)>, llvm::function_ref<bool (clang::interp::PrimType)>) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::dereference(clang::Expr const*, clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::DerefKind, llvm::function_ref<bool (clang::interp::PrimType)>, llvm::function_ref<bool (clang::interp::PrimType)>) |
2037 | | |
2038 | | template <class Emitter> |
2039 | | bool ByteCodeExprGen<Emitter>::dereferenceParam( |
2040 | | const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK, |
2041 | | llvm::function_ref<bool(PrimType)> Direct, |
2042 | 0 | llvm::function_ref<bool(PrimType)> Indirect) { |
2043 | 0 | auto It = this->Params.find(PD); |
2044 | 0 | if (It != this->Params.end()) { |
2045 | 0 | unsigned Idx = It->second.Offset; |
2046 | 0 | switch (AK) { |
2047 | 0 | case DerefKind::Read: |
2048 | 0 | return DiscardResult ? true : this->emitGetParam(T, Idx, LV); |
2049 | | |
2050 | 0 | case DerefKind::Write: |
2051 | 0 | if (!Direct(T)) |
2052 | 0 | return false; |
2053 | 0 | if (!this->emitSetParam(T, Idx, LV)) |
2054 | 0 | return false; |
2055 | 0 | return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); |
2056 | | |
2057 | 0 | case DerefKind::ReadWrite: |
2058 | 0 | if (!this->emitGetParam(T, Idx, LV)) |
2059 | 0 | return false; |
2060 | 0 | if (!Direct(T)) |
2061 | 0 | return false; |
2062 | 0 | if (!this->emitSetParam(T, Idx, LV)) |
2063 | 0 | return false; |
2064 | 0 | return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); |
2065 | 0 | } |
2066 | 0 | return true; |
2067 | 0 | } |
2068 | | |
2069 | | // If the param is a pointer, we can dereference a dummy value. |
2070 | 0 | if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) { |
2071 | 0 | if (auto Idx = P.getOrCreateDummy(PD)) |
2072 | 0 | return this->emitGetPtrGlobal(*Idx, PD); |
2073 | 0 | return false; |
2074 | 0 | } |
2075 | | |
2076 | | // Value cannot be produced - try to emit pointer and do stuff with it. |
2077 | 0 | return visit(LV) && Indirect(T); |
2078 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::dereferenceParam(clang::Expr const*, clang::interp::PrimType, clang::ParmVarDecl const*, clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::DerefKind, llvm::function_ref<bool (clang::interp::PrimType)>, llvm::function_ref<bool (clang::interp::PrimType)>) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::dereferenceParam(clang::Expr const*, clang::interp::PrimType, clang::ParmVarDecl const*, clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::DerefKind, llvm::function_ref<bool (clang::interp::PrimType)>, llvm::function_ref<bool (clang::interp::PrimType)>) |
2079 | | |
2080 | | template <class Emitter> |
2081 | | bool ByteCodeExprGen<Emitter>::dereferenceVar( |
2082 | | const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK, |
2083 | | llvm::function_ref<bool(PrimType)> Direct, |
2084 | 0 | llvm::function_ref<bool(PrimType)> Indirect) { |
2085 | 0 | auto It = Locals.find(VD); |
2086 | 0 | if (It != Locals.end()) { |
2087 | 0 | const auto &L = It->second; |
2088 | 0 | switch (AK) { |
2089 | 0 | case DerefKind::Read: |
2090 | 0 | if (!this->emitGetLocal(T, L.Offset, LV)) |
2091 | 0 | return false; |
2092 | 0 | return DiscardResult ? this->emitPop(T, LV) : true; |
2093 | | |
2094 | 0 | case DerefKind::Write: |
2095 | 0 | if (!Direct(T)) |
2096 | 0 | return false; |
2097 | 0 | if (!this->emitSetLocal(T, L.Offset, LV)) |
2098 | 0 | return false; |
2099 | 0 | return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); |
2100 | | |
2101 | 0 | case DerefKind::ReadWrite: |
2102 | 0 | if (!this->emitGetLocal(T, L.Offset, LV)) |
2103 | 0 | return false; |
2104 | 0 | if (!Direct(T)) |
2105 | 0 | return false; |
2106 | 0 | if (!this->emitSetLocal(T, L.Offset, LV)) |
2107 | 0 | return false; |
2108 | 0 | return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); |
2109 | 0 | } |
2110 | 0 | } else if (auto Idx = P.getGlobal(VD)) { |
2111 | 0 | switch (AK) { |
2112 | 0 | case DerefKind::Read: |
2113 | 0 | if (!this->emitGetGlobal(T, *Idx, LV)) |
2114 | 0 | return false; |
2115 | 0 | return DiscardResult ? this->emitPop(T, LV) : true; |
2116 | | |
2117 | 0 | case DerefKind::Write: |
2118 | 0 | if (!Direct(T)) |
2119 | 0 | return false; |
2120 | 0 | if (!this->emitSetGlobal(T, *Idx, LV)) |
2121 | 0 | return false; |
2122 | 0 | return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); |
2123 | | |
2124 | 0 | case DerefKind::ReadWrite: |
2125 | 0 | if (!this->emitGetGlobal(T, *Idx, LV)) |
2126 | 0 | return false; |
2127 | 0 | if (!Direct(T)) |
2128 | 0 | return false; |
2129 | 0 | if (!this->emitSetGlobal(T, *Idx, LV)) |
2130 | 0 | return false; |
2131 | 0 | return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); |
2132 | 0 | } |
2133 | 0 | } |
2134 | | |
2135 | | // If the declaration is a constant value, emit it here even |
2136 | | // though the declaration was not evaluated in the current scope. |
2137 | | // The access mode can only be read in this case. |
2138 | 0 | if (!DiscardResult && AK == DerefKind::Read) { |
2139 | 0 | if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) { |
2140 | 0 | QualType VT = VD->getType(); |
2141 | 0 | if (VT.isConstQualified() && VT->isFundamentalType()) |
2142 | 0 | return this->visit(VD->getInit()); |
2143 | 0 | } |
2144 | 0 | } |
2145 | | |
2146 | | // Value cannot be produced - try to emit pointer. |
2147 | 0 | return visit(LV) && Indirect(T); |
2148 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::dereferenceVar(clang::Expr const*, clang::interp::PrimType, clang::VarDecl const*, clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::DerefKind, llvm::function_ref<bool (clang::interp::PrimType)>, llvm::function_ref<bool (clang::interp::PrimType)>) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::dereferenceVar(clang::Expr const*, clang::interp::PrimType, clang::VarDecl const*, clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::DerefKind, llvm::function_ref<bool (clang::interp::PrimType)>, llvm::function_ref<bool (clang::interp::PrimType)>) |
2149 | | |
2150 | | template <class Emitter> |
2151 | | template <typename T> |
2152 | 0 | bool ByteCodeExprGen<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) { |
2153 | 0 | switch (Ty) { |
2154 | 0 | case PT_Sint8: |
2155 | 0 | return this->emitConstSint8(Value, E); |
2156 | 0 | case PT_Uint8: |
2157 | 0 | return this->emitConstUint8(Value, E); |
2158 | 0 | case PT_Sint16: |
2159 | 0 | return this->emitConstSint16(Value, E); |
2160 | 0 | case PT_Uint16: |
2161 | 0 | return this->emitConstUint16(Value, E); |
2162 | 0 | case PT_Sint32: |
2163 | 0 | return this->emitConstSint32(Value, E); |
2164 | 0 | case PT_Uint32: |
2165 | 0 | return this->emitConstUint32(Value, E); |
2166 | 0 | case PT_Sint64: |
2167 | 0 | return this->emitConstSint64(Value, E); |
2168 | 0 | case PT_Uint64: |
2169 | 0 | return this->emitConstUint64(Value, E); |
2170 | 0 | case PT_IntAP: |
2171 | 0 | case PT_IntAPS: |
2172 | 0 | assert(false); |
2173 | 0 | return false; |
2174 | 0 | case PT_Bool: |
2175 | 0 | return this->emitConstBool(Value, E); |
2176 | 0 | case PT_Ptr: |
2177 | 0 | case PT_FnPtr: |
2178 | 0 | case PT_Float: |
2179 | 0 | llvm_unreachable("Invalid integral type"); |
2180 | 0 | break; |
2181 | 0 | } |
2182 | 0 | llvm_unreachable("unknown primitive type"); |
2183 | 0 | } Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitConst<int>(int, clang::interp::PrimType, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitConst<unsigned int>(unsigned int, clang::interp::PrimType, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitConst<long>(long, clang::interp::PrimType, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitConst<unsigned long>(unsigned long, clang::interp::PrimType, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitConst<int>(int, clang::interp::PrimType, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitConst<unsigned int>(unsigned int, clang::interp::PrimType, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitConst<long>(long, clang::interp::PrimType, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitConst<unsigned long>(unsigned long, clang::interp::PrimType, clang::Expr const*) |
2184 | | |
2185 | | template <class Emitter> |
2186 | | template <typename T> |
2187 | 0 | bool ByteCodeExprGen<Emitter>::emitConst(T Value, const Expr *E) { |
2188 | 0 | return this->emitConst(Value, classifyPrim(E->getType()), E); |
2189 | 0 | } Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitConst<int>(int, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitConst<long>(long, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitConst<unsigned long>(unsigned long, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitConst<unsigned int>(unsigned int, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitConst<int>(int, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitConst<long>(long, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitConst<unsigned long>(unsigned long, clang::Expr const*) Unexecuted instantiation: bool clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitConst<unsigned int>(unsigned int, clang::Expr const*) |
2190 | | |
2191 | | template <class Emitter> |
2192 | | bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, PrimType Ty, |
2193 | 0 | const Expr *E) { |
2194 | 0 | if (Value.isSigned()) |
2195 | 0 | return this->emitConst(Value.getSExtValue(), Ty, E); |
2196 | 0 | return this->emitConst(Value.getZExtValue(), Ty, E); |
2197 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitConst(llvm::APSInt const&, clang::interp::PrimType, clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitConst(llvm::APSInt const&, clang::interp::PrimType, clang::Expr const*) |
2198 | | |
2199 | | template <class Emitter> |
2200 | 0 | bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, const Expr *E) { |
2201 | 0 | return this->emitConst(Value, classifyPrim(E->getType()), E); |
2202 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitConst(llvm::APSInt const&, clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitConst(llvm::APSInt const&, clang::Expr const*) |
2203 | | |
2204 | | template <class Emitter> |
2205 | | unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src, |
2206 | | PrimType Ty, |
2207 | | bool IsConst, |
2208 | 0 | bool IsExtended) { |
2209 | | // Make sure we don't accidentally register the same decl twice. |
2210 | 0 | if (const auto *VD = |
2211 | 0 | dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { |
2212 | 0 | assert(!P.getGlobal(VD)); |
2213 | 0 | assert(!Locals.contains(VD)); |
2214 | 0 | } |
2215 | | |
2216 | | // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g. |
2217 | | // (int){12} in C. Consider using Expr::isTemporaryObject() instead |
2218 | | // or isa<MaterializeTemporaryExpr>(). |
2219 | 0 | Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst, |
2220 | 0 | Src.is<const Expr *>()); |
2221 | 0 | Scope::Local Local = this->createLocal(D); |
2222 | 0 | if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) |
2223 | 0 | Locals.insert({VD, Local}); |
2224 | 0 | VarScope->add(Local, IsExtended); |
2225 | 0 | return Local.Offset; |
2226 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::allocateLocalPrimitive(llvm::PointerUnion<clang::Decl const*, clang::Expr const*>&&, clang::interp::PrimType, bool, bool) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::allocateLocalPrimitive(llvm::PointerUnion<clang::Decl const*, clang::Expr const*>&&, clang::interp::PrimType, bool, bool) |
2227 | | |
2228 | | template <class Emitter> |
2229 | | std::optional<unsigned> |
2230 | 0 | ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) { |
2231 | | // Make sure we don't accidentally register the same decl twice. |
2232 | 0 | if ([[maybe_unused]] const auto *VD = |
2233 | 0 | dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { |
2234 | 0 | assert(!P.getGlobal(VD)); |
2235 | 0 | assert(!Locals.contains(VD)); |
2236 | 0 | } |
2237 | | |
2238 | 0 | QualType Ty; |
2239 | 0 | const ValueDecl *Key = nullptr; |
2240 | 0 | const Expr *Init = nullptr; |
2241 | 0 | bool IsTemporary = false; |
2242 | 0 | if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { |
2243 | 0 | Key = VD; |
2244 | 0 | Ty = VD->getType(); |
2245 | |
|
2246 | 0 | if (const auto *VarD = dyn_cast<VarDecl>(VD)) |
2247 | 0 | Init = VarD->getInit(); |
2248 | 0 | } |
2249 | 0 | if (auto *E = Src.dyn_cast<const Expr *>()) { |
2250 | 0 | IsTemporary = true; |
2251 | 0 | Ty = E->getType(); |
2252 | 0 | } |
2253 | |
|
2254 | 0 | Descriptor *D = P.createDescriptor( |
2255 | 0 | Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(), |
2256 | 0 | IsTemporary, /*IsMutable=*/false, Init); |
2257 | 0 | if (!D) |
2258 | 0 | return {}; |
2259 | | |
2260 | 0 | Scope::Local Local = this->createLocal(D); |
2261 | 0 | if (Key) |
2262 | 0 | Locals.insert({Key, Local}); |
2263 | 0 | VarScope->add(Local, IsExtended); |
2264 | 0 | return Local.Offset; |
2265 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::allocateLocal(llvm::PointerUnion<clang::Decl const*, clang::Expr const*>&&, bool) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::allocateLocal(llvm::PointerUnion<clang::Decl const*, clang::Expr const*>&&, bool) |
2266 | | |
2267 | | template <class Emitter> |
2268 | 0 | const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) { |
2269 | 0 | if (const PointerType *PT = dyn_cast<PointerType>(Ty)) |
2270 | 0 | return PT->getPointeeType()->getAs<RecordType>(); |
2271 | 0 | return Ty->getAs<RecordType>(); |
2272 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::getRecordTy(clang::QualType) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::getRecordTy(clang::QualType) |
2273 | | |
2274 | | template <class Emitter> |
2275 | 0 | Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) { |
2276 | 0 | if (const auto *RecordTy = getRecordTy(Ty)) |
2277 | 0 | return getRecord(RecordTy->getDecl()); |
2278 | 0 | return nullptr; |
2279 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::getRecord(clang::QualType) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::getRecord(clang::QualType) |
2280 | | |
2281 | | template <class Emitter> |
2282 | 0 | Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) { |
2283 | 0 | return P.getOrCreateRecord(RD); |
2284 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::getRecord(clang::RecordDecl const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::getRecord(clang::RecordDecl const*) |
2285 | | |
2286 | | template <class Emitter> |
2287 | 0 | const Function *ByteCodeExprGen<Emitter>::getFunction(const FunctionDecl *FD) { |
2288 | 0 | return Ctx.getOrCreateFunction(FD); |
2289 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::getFunction(clang::FunctionDecl const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::getFunction(clang::FunctionDecl const*) |
2290 | | |
2291 | | template <class Emitter> |
2292 | 0 | bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) { |
2293 | 0 | ExprScope<Emitter> RootScope(this); |
2294 | | // Void expressions. |
2295 | 0 | if (E->getType()->isVoidType()) { |
2296 | 0 | if (!visit(E)) |
2297 | 0 | return false; |
2298 | 0 | return this->emitRetVoid(E); |
2299 | 0 | } |
2300 | | |
2301 | | // Expressions with a primitive return type. |
2302 | 0 | if (std::optional<PrimType> T = classify(E)) { |
2303 | 0 | if (!visit(E)) |
2304 | 0 | return false; |
2305 | 0 | return this->emitRet(*T, E); |
2306 | 0 | } |
2307 | | |
2308 | | // Expressions with a composite return type. |
2309 | | // For us, that means everything we don't |
2310 | | // have a PrimType for. |
2311 | 0 | if (std::optional<unsigned> LocalOffset = this->allocateLocal(E)) { |
2312 | 0 | if (!this->visitLocalInitializer(E, *LocalOffset)) |
2313 | 0 | return false; |
2314 | | |
2315 | 0 | if (!this->emitGetPtrLocal(*LocalOffset, E)) |
2316 | 0 | return false; |
2317 | 0 | return this->emitRetValue(E); |
2318 | 0 | } |
2319 | | |
2320 | 0 | return false; |
2321 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitExpr(clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitExpr(clang::Expr const*) |
2322 | | |
2323 | | /// Toplevel visitDecl(). |
2324 | | /// We get here from evaluateAsInitializer(). |
2325 | | /// We need to evaluate the initializer and return its value. |
2326 | | template <class Emitter> |
2327 | 0 | bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { |
2328 | 0 | assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl"); |
2329 | | |
2330 | | // Create and initialize the variable. |
2331 | 0 | if (!this->visitVarDecl(VD)) |
2332 | 0 | return false; |
2333 | | |
2334 | 0 | std::optional<PrimType> VarT = classify(VD->getType()); |
2335 | | // Get a pointer to the variable |
2336 | 0 | if (Context::shouldBeGloballyIndexed(VD)) { |
2337 | 0 | auto GlobalIndex = P.getGlobal(VD); |
2338 | 0 | assert(GlobalIndex); // visitVarDecl() didn't return false. |
2339 | 0 | if (VarT) { |
2340 | 0 | if (!this->emitGetGlobalUnchecked(*VarT, *GlobalIndex, VD)) |
2341 | 0 | return false; |
2342 | 0 | } else { |
2343 | 0 | if (!this->emitGetPtrGlobal(*GlobalIndex, VD)) |
2344 | 0 | return false; |
2345 | 0 | } |
2346 | 0 | } else { |
2347 | 0 | auto Local = Locals.find(VD); |
2348 | 0 | assert(Local != Locals.end()); // Same here. |
2349 | 0 | if (VarT) { |
2350 | 0 | if (!this->emitGetLocal(*VarT, Local->second.Offset, VD)) |
2351 | 0 | return false; |
2352 | 0 | } else { |
2353 | 0 | if (!this->emitGetPtrLocal(Local->second.Offset, VD)) |
2354 | 0 | return false; |
2355 | 0 | } |
2356 | 0 | } |
2357 | | |
2358 | | // Return the value |
2359 | 0 | if (VarT) |
2360 | 0 | return this->emitRet(*VarT, VD); |
2361 | 0 | return this->emitRetValue(VD); |
2362 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitDecl(clang::VarDecl const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitDecl(clang::VarDecl const*) |
2363 | | |
2364 | | template <class Emitter> |
2365 | 0 | bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) { |
2366 | | // We don't know what to do with these, so just return false. |
2367 | 0 | if (VD->getType().isNull()) |
2368 | 0 | return false; |
2369 | | |
2370 | 0 | const Expr *Init = VD->getInit(); |
2371 | 0 | std::optional<PrimType> VarT = classify(VD->getType()); |
2372 | |
|
2373 | 0 | if (Context::shouldBeGloballyIndexed(VD)) { |
2374 | | // We've already seen and initialized this global. |
2375 | 0 | if (P.getGlobal(VD)) |
2376 | 0 | return true; |
2377 | | |
2378 | 0 | std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init); |
2379 | |
|
2380 | 0 | if (!GlobalIndex) |
2381 | 0 | return this->bail(VD); |
2382 | | |
2383 | 0 | assert(Init); |
2384 | 0 | { |
2385 | 0 | DeclScope<Emitter> LocalScope(this, VD); |
2386 | |
|
2387 | 0 | if (VarT) { |
2388 | 0 | if (!this->visit(Init)) |
2389 | 0 | return false; |
2390 | 0 | return this->emitInitGlobal(*VarT, *GlobalIndex, VD); |
2391 | 0 | } |
2392 | 0 | return this->visitGlobalInitializer(Init, *GlobalIndex); |
2393 | 0 | } |
2394 | 0 | } else { |
2395 | 0 | VariableScope<Emitter> LocalScope(this); |
2396 | 0 | if (VarT) { |
2397 | 0 | unsigned Offset = this->allocateLocalPrimitive( |
2398 | 0 | VD, *VarT, VD->getType().isConstQualified()); |
2399 | 0 | if (Init) { |
2400 | | // Compile the initializer in its own scope. |
2401 | 0 | ExprScope<Emitter> Scope(this); |
2402 | 0 | if (!this->visit(Init)) |
2403 | 0 | return false; |
2404 | | |
2405 | 0 | return this->emitSetLocal(*VarT, Offset, VD); |
2406 | 0 | } |
2407 | 0 | } else { |
2408 | 0 | if (std::optional<unsigned> Offset = this->allocateLocal(VD)) { |
2409 | 0 | if (Init) |
2410 | 0 | return this->visitLocalInitializer(Init, *Offset); |
2411 | 0 | } |
2412 | 0 | } |
2413 | 0 | return true; |
2414 | 0 | } |
2415 | | |
2416 | 0 | return false; |
2417 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitVarDecl(clang::VarDecl const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitVarDecl(clang::VarDecl const*) |
2418 | | |
2419 | | template <class Emitter> |
2420 | | bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val, |
2421 | 0 | PrimType ValType, const Expr *E) { |
2422 | 0 | assert(!DiscardResult); |
2423 | 0 | if (Val.isInt()) |
2424 | 0 | return this->emitConst(Val.getInt(), ValType, E); |
2425 | | |
2426 | 0 | if (Val.isLValue()) { |
2427 | 0 | APValue::LValueBase Base = Val.getLValueBase(); |
2428 | 0 | if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>()) |
2429 | 0 | return this->visit(BaseExpr); |
2430 | 0 | } |
2431 | | |
2432 | 0 | return false; |
2433 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitAPValue(clang::APValue const&, clang::interp::PrimType, clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitAPValue(clang::APValue const&, clang::interp::PrimType, clang::Expr const*) |
2434 | | |
2435 | | template <class Emitter> |
2436 | 0 | bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) { |
2437 | 0 | const Function *Func = getFunction(E->getDirectCallee()); |
2438 | 0 | if (!Func) |
2439 | 0 | return false; |
2440 | | |
2441 | 0 | if (!Func->isUnevaluatedBuiltin()) { |
2442 | | // Put arguments on the stack. |
2443 | 0 | for (const auto *Arg : E->arguments()) { |
2444 | 0 | if (!this->visit(Arg)) |
2445 | 0 | return false; |
2446 | 0 | } |
2447 | 0 | } |
2448 | | |
2449 | 0 | if (!this->emitCallBI(Func, E, E)) |
2450 | 0 | return false; |
2451 | | |
2452 | 0 | QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); |
2453 | 0 | if (DiscardResult && !ReturnType->isVoidType()) { |
2454 | 0 | PrimType T = classifyPrim(ReturnType); |
2455 | 0 | return this->emitPop(T, E); |
2456 | 0 | } |
2457 | | |
2458 | 0 | return true; |
2459 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitBuiltinCallExpr(clang::CallExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitBuiltinCallExpr(clang::CallExpr const*) |
2460 | | |
2461 | | template <class Emitter> |
2462 | 0 | bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) { |
2463 | 0 | if (E->getBuiltinCallee()) |
2464 | 0 | return VisitBuiltinCallExpr(E); |
2465 | | |
2466 | 0 | QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); |
2467 | 0 | std::optional<PrimType> T = classify(ReturnType); |
2468 | 0 | bool HasRVO = !ReturnType->isVoidType() && !T; |
2469 | |
|
2470 | 0 | if (HasRVO) { |
2471 | 0 | if (DiscardResult) { |
2472 | | // If we need to discard the return value but the function returns its |
2473 | | // value via an RVO pointer, we need to create one such pointer just |
2474 | | // for this call. |
2475 | 0 | if (std::optional<unsigned> LocalIndex = allocateLocal(E)) { |
2476 | 0 | if (!this->emitGetPtrLocal(*LocalIndex, E)) |
2477 | 0 | return false; |
2478 | 0 | } |
2479 | 0 | } else { |
2480 | 0 | assert(Initializing); |
2481 | 0 | if (!this->emitDupPtr(E)) |
2482 | 0 | return false; |
2483 | 0 | } |
2484 | 0 | } |
2485 | | |
2486 | | // Add the (optional, implicit) This pointer. |
2487 | 0 | if (const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) { |
2488 | 0 | if (!this->visit(MC->getImplicitObjectArgument())) |
2489 | 0 | return false; |
2490 | 0 | } |
2491 | | |
2492 | | // Put arguments on the stack. |
2493 | 0 | for (const auto *Arg : E->arguments()) { |
2494 | 0 | if (!this->visit(Arg)) |
2495 | 0 | return false; |
2496 | 0 | } |
2497 | | |
2498 | 0 | if (const FunctionDecl *FuncDecl = E->getDirectCallee()) { |
2499 | 0 | const Function *Func = getFunction(FuncDecl); |
2500 | 0 | if (!Func) |
2501 | 0 | return false; |
2502 | | // If the function is being compiled right now, this is a recursive call. |
2503 | | // In that case, the function can't be valid yet, even though it will be |
2504 | | // later. |
2505 | | // If the function is already fully compiled but not constexpr, it was |
2506 | | // found to be faulty earlier on, so bail out. |
2507 | 0 | if (Func->isFullyCompiled() && !Func->isConstexpr()) |
2508 | 0 | return false; |
2509 | | |
2510 | 0 | assert(HasRVO == Func->hasRVO()); |
2511 | | |
2512 | 0 | bool HasQualifier = false; |
2513 | 0 | if (const auto *ME = dyn_cast<MemberExpr>(E->getCallee())) |
2514 | 0 | HasQualifier = ME->hasQualifier(); |
2515 | |
|
2516 | 0 | bool IsVirtual = false; |
2517 | 0 | if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) |
2518 | 0 | IsVirtual = MD->isVirtual(); |
2519 | | |
2520 | | // In any case call the function. The return value will end up on the stack |
2521 | | // and if the function has RVO, we already have the pointer on the stack to |
2522 | | // write the result into. |
2523 | 0 | if (IsVirtual && !HasQualifier) { |
2524 | 0 | if (!this->emitCallVirt(Func, E)) |
2525 | 0 | return false; |
2526 | 0 | } else { |
2527 | 0 | if (!this->emitCall(Func, E)) |
2528 | 0 | return false; |
2529 | 0 | } |
2530 | 0 | } else { |
2531 | | // Indirect call. Visit the callee, which will leave a FunctionPointer on |
2532 | | // the stack. Cleanup of the returned value if necessary will be done after |
2533 | | // the function call completed. |
2534 | 0 | if (!this->visit(E->getCallee())) |
2535 | 0 | return false; |
2536 | | |
2537 | 0 | if (!this->emitCallPtr(E)) |
2538 | 0 | return false; |
2539 | 0 | } |
2540 | | |
2541 | | // Cleanup for discarded return values. |
2542 | 0 | if (DiscardResult && !ReturnType->isVoidType() && T) |
2543 | 0 | return this->emitPop(*T, E); |
2544 | | |
2545 | 0 | return true; |
2546 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCallExpr(clang::CallExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCallExpr(clang::CallExpr const*) |
2547 | | |
2548 | | template <class Emitter> |
2549 | | bool ByteCodeExprGen<Emitter>::VisitCXXDefaultInitExpr( |
2550 | 0 | const CXXDefaultInitExpr *E) { |
2551 | 0 | SourceLocScope<Emitter> SLS(this, E); |
2552 | 0 | if (Initializing) |
2553 | 0 | return this->visitInitializer(E->getExpr()); |
2554 | | |
2555 | 0 | assert(classify(E->getType())); |
2556 | 0 | return this->visit(E->getExpr()); |
2557 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXDefaultInitExpr(clang::CXXDefaultInitExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXDefaultInitExpr(clang::CXXDefaultInitExpr const*) |
2558 | | |
2559 | | template <class Emitter> |
2560 | | bool ByteCodeExprGen<Emitter>::VisitCXXDefaultArgExpr( |
2561 | 0 | const CXXDefaultArgExpr *E) { |
2562 | 0 | SourceLocScope<Emitter> SLS(this, E); |
2563 | |
|
2564 | 0 | const Expr *SubExpr = E->getExpr(); |
2565 | 0 | if (std::optional<PrimType> T = classify(E->getExpr())) |
2566 | 0 | return this->visit(SubExpr); |
2567 | | |
2568 | 0 | assert(Initializing); |
2569 | 0 | return this->visitInitializer(SubExpr); |
2570 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr const*) |
2571 | | |
2572 | | template <class Emitter> |
2573 | | bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr( |
2574 | 0 | const CXXBoolLiteralExpr *E) { |
2575 | 0 | if (DiscardResult) |
2576 | 0 | return true; |
2577 | | |
2578 | 0 | return this->emitConstBool(E->getValue(), E); |
2579 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXBoolLiteralExpr(clang::CXXBoolLiteralExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXBoolLiteralExpr(clang::CXXBoolLiteralExpr const*) |
2580 | | |
2581 | | template <class Emitter> |
2582 | | bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr( |
2583 | 0 | const CXXNullPtrLiteralExpr *E) { |
2584 | 0 | if (DiscardResult) |
2585 | 0 | return true; |
2586 | | |
2587 | 0 | return this->emitNullPtr(E); |
2588 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXNullPtrLiteralExpr(clang::CXXNullPtrLiteralExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXNullPtrLiteralExpr(clang::CXXNullPtrLiteralExpr const*) |
2589 | | |
2590 | | template <class Emitter> |
2591 | 0 | bool ByteCodeExprGen<Emitter>::VisitGNUNullExpr(const GNUNullExpr *E) { |
2592 | 0 | if (DiscardResult) |
2593 | 0 | return true; |
2594 | | |
2595 | 0 | assert(E->getType()->isIntegerType()); |
2596 | | |
2597 | 0 | PrimType T = classifyPrim(E->getType()); |
2598 | 0 | return this->emitZero(T, E); |
2599 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitGNUNullExpr(clang::GNUNullExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitGNUNullExpr(clang::GNUNullExpr const*) |
2600 | | |
2601 | | template <class Emitter> |
2602 | 0 | bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) { |
2603 | 0 | if (DiscardResult) |
2604 | 0 | return true; |
2605 | | |
2606 | 0 | if (this->LambdaThisCapture > 0) |
2607 | 0 | return this->emitGetThisFieldPtr(this->LambdaThisCapture, E); |
2608 | | |
2609 | 0 | return this->emitThis(E); |
2610 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitCXXThisExpr(clang::CXXThisExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitCXXThisExpr(clang::CXXThisExpr const*) |
2611 | | |
2612 | | template <class Emitter> |
2613 | 0 | bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) { |
2614 | 0 | const Expr *SubExpr = E->getSubExpr(); |
2615 | 0 | std::optional<PrimType> T = classify(SubExpr->getType()); |
2616 | |
|
2617 | 0 | switch (E->getOpcode()) { |
2618 | 0 | case UO_PostInc: { // x++ |
2619 | 0 | if (!this->visit(SubExpr)) |
2620 | 0 | return false; |
2621 | | |
2622 | 0 | if (T == PT_Ptr) { |
2623 | 0 | if (!this->emitIncPtr(E)) |
2624 | 0 | return false; |
2625 | | |
2626 | 0 | return DiscardResult ? this->emitPopPtr(E) : true; |
2627 | 0 | } |
2628 | | |
2629 | 0 | if (T == PT_Float) { |
2630 | 0 | return DiscardResult ? this->emitIncfPop(getRoundingMode(E), E) |
2631 | 0 | : this->emitIncf(getRoundingMode(E), E); |
2632 | 0 | } |
2633 | | |
2634 | 0 | return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E); |
2635 | 0 | } |
2636 | 0 | case UO_PostDec: { // x-- |
2637 | 0 | if (!this->visit(SubExpr)) |
2638 | 0 | return false; |
2639 | | |
2640 | 0 | if (T == PT_Ptr) { |
2641 | 0 | if (!this->emitDecPtr(E)) |
2642 | 0 | return false; |
2643 | | |
2644 | 0 | return DiscardResult ? this->emitPopPtr(E) : true; |
2645 | 0 | } |
2646 | | |
2647 | 0 | if (T == PT_Float) { |
2648 | 0 | return DiscardResult ? this->emitDecfPop(getRoundingMode(E), E) |
2649 | 0 | : this->emitDecf(getRoundingMode(E), E); |
2650 | 0 | } |
2651 | | |
2652 | 0 | return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E); |
2653 | 0 | } |
2654 | 0 | case UO_PreInc: { // ++x |
2655 | 0 | if (!this->visit(SubExpr)) |
2656 | 0 | return false; |
2657 | | |
2658 | 0 | if (T == PT_Ptr) { |
2659 | 0 | if (!this->emitLoadPtr(E)) |
2660 | 0 | return false; |
2661 | 0 | if (!this->emitConstUint8(1, E)) |
2662 | 0 | return false; |
2663 | 0 | if (!this->emitAddOffsetUint8(E)) |
2664 | 0 | return false; |
2665 | 0 | return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E); |
2666 | 0 | } |
2667 | | |
2668 | | // Post-inc and pre-inc are the same if the value is to be discarded. |
2669 | 0 | if (DiscardResult) { |
2670 | 0 | if (T == PT_Float) |
2671 | 0 | return this->emitIncfPop(getRoundingMode(E), E); |
2672 | 0 | return this->emitIncPop(*T, E); |
2673 | 0 | } |
2674 | | |
2675 | 0 | if (T == PT_Float) { |
2676 | 0 | const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType()); |
2677 | 0 | if (!this->emitLoadFloat(E)) |
2678 | 0 | return false; |
2679 | 0 | if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E)) |
2680 | 0 | return false; |
2681 | 0 | if (!this->emitAddf(getRoundingMode(E), E)) |
2682 | 0 | return false; |
2683 | 0 | return this->emitStoreFloat(E); |
2684 | 0 | } |
2685 | 0 | if (!this->emitLoad(*T, E)) |
2686 | 0 | return false; |
2687 | 0 | if (!this->emitConst(1, E)) |
2688 | 0 | return false; |
2689 | 0 | if (!this->emitAdd(*T, E)) |
2690 | 0 | return false; |
2691 | 0 | return this->emitStore(*T, E); |
2692 | 0 | } |
2693 | 0 | case UO_PreDec: { // --x |
2694 | 0 | if (!this->visit(SubExpr)) |
2695 | 0 | return false; |
2696 | | |
2697 | 0 | if (T == PT_Ptr) { |
2698 | 0 | if (!this->emitLoadPtr(E)) |
2699 | 0 | return false; |
2700 | 0 | if (!this->emitConstUint8(1, E)) |
2701 | 0 | return false; |
2702 | 0 | if (!this->emitSubOffsetUint8(E)) |
2703 | 0 | return false; |
2704 | 0 | return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E); |
2705 | 0 | } |
2706 | | |
2707 | | // Post-dec and pre-dec are the same if the value is to be discarded. |
2708 | 0 | if (DiscardResult) { |
2709 | 0 | if (T == PT_Float) |
2710 | 0 | return this->emitDecfPop(getRoundingMode(E), E); |
2711 | 0 | return this->emitDecPop(*T, E); |
2712 | 0 | } |
2713 | | |
2714 | 0 | if (T == PT_Float) { |
2715 | 0 | const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType()); |
2716 | 0 | if (!this->emitLoadFloat(E)) |
2717 | 0 | return false; |
2718 | 0 | if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E)) |
2719 | 0 | return false; |
2720 | 0 | if (!this->emitSubf(getRoundingMode(E), E)) |
2721 | 0 | return false; |
2722 | 0 | return this->emitStoreFloat(E); |
2723 | 0 | } |
2724 | 0 | if (!this->emitLoad(*T, E)) |
2725 | 0 | return false; |
2726 | 0 | if (!this->emitConst(1, E)) |
2727 | 0 | return false; |
2728 | 0 | if (!this->emitSub(*T, E)) |
2729 | 0 | return false; |
2730 | 0 | return this->emitStore(*T, E); |
2731 | 0 | } |
2732 | 0 | case UO_LNot: // !x |
2733 | 0 | if (DiscardResult) |
2734 | 0 | return this->discard(SubExpr); |
2735 | | |
2736 | 0 | if (!this->visitBool(SubExpr)) |
2737 | 0 | return false; |
2738 | | |
2739 | 0 | if (!this->emitInvBool(E)) |
2740 | 0 | return false; |
2741 | | |
2742 | 0 | if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool) |
2743 | 0 | return this->emitCast(PT_Bool, ET, E); |
2744 | 0 | return true; |
2745 | 0 | case UO_Minus: // -x |
2746 | 0 | if (!this->visit(SubExpr)) |
2747 | 0 | return false; |
2748 | 0 | return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E); |
2749 | 0 | case UO_Plus: // +x |
2750 | 0 | if (!this->visit(SubExpr)) // noop |
2751 | 0 | return false; |
2752 | 0 | return DiscardResult ? this->emitPop(*T, E) : true; |
2753 | 0 | case UO_AddrOf: // &x |
2754 | | // We should already have a pointer when we get here. |
2755 | 0 | return this->delegate(SubExpr); |
2756 | 0 | case UO_Deref: // *x |
2757 | 0 | return dereference( |
2758 | 0 | SubExpr, DerefKind::Read, |
2759 | 0 | [](PrimType) { |
2760 | 0 | llvm_unreachable("Dereferencing requires a pointer"); |
2761 | 0 | return false; |
2762 | 0 | }, Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitUnaryOperator(clang::UnaryOperator const*)::{lambda(clang::interp::PrimType)#1}::operator()(clang::interp::PrimType) const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitUnaryOperator(clang::UnaryOperator const*)::{lambda(clang::interp::PrimType)#1}::operator()(clang::interp::PrimType) const |
2763 | 0 | [this, E](PrimType T) { |
2764 | 0 | return DiscardResult ? this->emitPop(T, E) : true; |
2765 | 0 | }); Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitUnaryOperator(clang::UnaryOperator const*)::{lambda(clang::interp::PrimType)#2}::operator()(clang::interp::PrimType) const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitUnaryOperator(clang::UnaryOperator const*)::{lambda(clang::interp::PrimType)#2}::operator()(clang::interp::PrimType) const |
2766 | 0 | case UO_Not: // ~x |
2767 | 0 | if (!this->visit(SubExpr)) |
2768 | 0 | return false; |
2769 | 0 | return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E); |
2770 | 0 | case UO_Real: { // __real x |
2771 | 0 | if (T) |
2772 | 0 | return this->delegate(SubExpr); |
2773 | 0 | if (!this->visit(SubExpr)) |
2774 | 0 | return false; |
2775 | 0 | if (!this->emitConstUint8(0, E)) |
2776 | 0 | return false; |
2777 | 0 | if (!this->emitArrayElemPtrPopUint8(E)) |
2778 | 0 | return false; |
2779 | | |
2780 | | // Since our _Complex implementation does not map to a primitive type, |
2781 | | // we sometimes have to do the lvalue-to-rvalue conversion here manually. |
2782 | 0 | if (!SubExpr->isLValue()) |
2783 | 0 | return this->emitLoadPop(classifyPrim(E->getType()), E); |
2784 | 0 | return true; |
2785 | 0 | } |
2786 | 0 | case UO_Imag: { // __imag x |
2787 | 0 | if (T) { |
2788 | 0 | if (!this->discard(SubExpr)) |
2789 | 0 | return false; |
2790 | 0 | return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr); |
2791 | 0 | } |
2792 | 0 | if (!this->visit(SubExpr)) |
2793 | 0 | return false; |
2794 | 0 | if (!this->emitConstUint8(1, E)) |
2795 | 0 | return false; |
2796 | 0 | if (!this->emitArrayElemPtrPopUint8(E)) |
2797 | 0 | return false; |
2798 | | |
2799 | | // Since our _Complex implementation does not map to a primitive type, |
2800 | | // we sometimes have to do the lvalue-to-rvalue conversion here manually. |
2801 | 0 | if (!SubExpr->isLValue()) |
2802 | 0 | return this->emitLoadPop(classifyPrim(E->getType()), E); |
2803 | 0 | return true; |
2804 | 0 | } |
2805 | 0 | case UO_Extension: |
2806 | 0 | return this->delegate(SubExpr); |
2807 | 0 | case UO_Coawait: |
2808 | 0 | assert(false && "Unhandled opcode"); |
2809 | 0 | } |
2810 | | |
2811 | 0 | return false; |
2812 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitUnaryOperator(clang::UnaryOperator const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitUnaryOperator(clang::UnaryOperator const*) |
2813 | | |
2814 | | template <class Emitter> |
2815 | 0 | bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) { |
2816 | 0 | if (DiscardResult) |
2817 | 0 | return true; |
2818 | | |
2819 | 0 | const auto *D = E->getDecl(); |
2820 | |
|
2821 | 0 | if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) { |
2822 | 0 | return this->emitConst(ECD->getInitVal(), E); |
2823 | 0 | } else if (const auto *BD = dyn_cast<BindingDecl>(D)) { |
2824 | 0 | return this->visit(BD->getBinding()); |
2825 | 0 | } else if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) { |
2826 | 0 | const Function *F = getFunction(FuncDecl); |
2827 | 0 | return F && this->emitGetFnPtr(F, E); |
2828 | 0 | } |
2829 | | |
2830 | | // References are implemented via pointers, so when we see a DeclRefExpr |
2831 | | // pointing to a reference, we need to get its value directly (i.e. the |
2832 | | // pointer to the actual value) instead of a pointer to the pointer to the |
2833 | | // value. |
2834 | 0 | bool IsReference = D->getType()->isReferenceType(); |
2835 | | |
2836 | | // Check for local/global variables and parameters. |
2837 | 0 | if (auto It = Locals.find(D); It != Locals.end()) { |
2838 | 0 | const unsigned Offset = It->second.Offset; |
2839 | |
|
2840 | 0 | if (IsReference) |
2841 | 0 | return this->emitGetLocal(PT_Ptr, Offset, E); |
2842 | 0 | return this->emitGetPtrLocal(Offset, E); |
2843 | 0 | } else if (auto GlobalIndex = P.getGlobal(D)) { |
2844 | 0 | if (IsReference) |
2845 | 0 | return this->emitGetGlobalPtr(*GlobalIndex, E); |
2846 | | |
2847 | 0 | return this->emitGetPtrGlobal(*GlobalIndex, E); |
2848 | 0 | } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) { |
2849 | 0 | if (auto It = this->Params.find(PVD); It != this->Params.end()) { |
2850 | 0 | if (IsReference || !It->second.IsPtr) |
2851 | 0 | return this->emitGetParamPtr(It->second.Offset, E); |
2852 | | |
2853 | 0 | return this->emitGetPtrParam(It->second.Offset, E); |
2854 | 0 | } |
2855 | 0 | } |
2856 | | |
2857 | | // Handle lambda captures. |
2858 | 0 | if (auto It = this->LambdaCaptures.find(D); |
2859 | 0 | It != this->LambdaCaptures.end()) { |
2860 | 0 | auto [Offset, IsPtr] = It->second; |
2861 | |
|
2862 | 0 | if (IsPtr) |
2863 | 0 | return this->emitGetThisFieldPtr(Offset, E); |
2864 | 0 | return this->emitGetPtrThisField(Offset, E); |
2865 | 0 | } |
2866 | | |
2867 | | // Lazily visit global declarations we haven't seen yet. |
2868 | | // This happens in C. |
2869 | 0 | if (!Ctx.getLangOpts().CPlusPlus) { |
2870 | 0 | if (const auto *VD = dyn_cast<VarDecl>(D); |
2871 | 0 | VD && VD->hasGlobalStorage() && VD->getAnyInitializer() && |
2872 | 0 | VD->getType().isConstQualified()) { |
2873 | 0 | if (!this->visitVarDecl(VD)) |
2874 | 0 | return false; |
2875 | | // Retry. |
2876 | 0 | return this->VisitDeclRefExpr(E); |
2877 | 0 | } |
2878 | | |
2879 | 0 | if (std::optional<unsigned> I = P.getOrCreateDummy(D)) |
2880 | 0 | return this->emitGetPtrGlobal(*I, E); |
2881 | 0 | } |
2882 | | |
2883 | 0 | return this->emitInvalidDeclRef(E, E); |
2884 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::VisitDeclRefExpr(clang::DeclRefExpr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::VisitDeclRefExpr(clang::DeclRefExpr const*) |
2885 | | |
2886 | | template <class Emitter> |
2887 | 0 | void ByteCodeExprGen<Emitter>::emitCleanup() { |
2888 | 0 | for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent()) |
2889 | 0 | C->emitDestruction(); |
2890 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitCleanup() Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitCleanup() |
2891 | | |
2892 | | template <class Emitter> |
2893 | | unsigned |
2894 | | ByteCodeExprGen<Emitter>::collectBaseOffset(const RecordType *BaseType, |
2895 | 0 | const RecordType *DerivedType) { |
2896 | 0 | const auto *FinalDecl = cast<CXXRecordDecl>(BaseType->getDecl()); |
2897 | 0 | const RecordDecl *CurDecl = DerivedType->getDecl(); |
2898 | 0 | const Record *CurRecord = getRecord(CurDecl); |
2899 | 0 | assert(CurDecl && FinalDecl); |
2900 | | |
2901 | 0 | unsigned OffsetSum = 0; |
2902 | 0 | for (;;) { |
2903 | 0 | assert(CurRecord->getNumBases() > 0); |
2904 | | // One level up |
2905 | 0 | for (const Record::Base &B : CurRecord->bases()) { |
2906 | 0 | const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl); |
2907 | |
|
2908 | 0 | if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) { |
2909 | 0 | OffsetSum += B.Offset; |
2910 | 0 | CurRecord = B.R; |
2911 | 0 | CurDecl = BaseDecl; |
2912 | 0 | break; |
2913 | 0 | } |
2914 | 0 | } |
2915 | 0 | if (CurDecl == FinalDecl) |
2916 | 0 | break; |
2917 | 0 | } |
2918 | |
|
2919 | 0 | assert(OffsetSum > 0); |
2920 | 0 | return OffsetSum; |
2921 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::collectBaseOffset(clang::RecordType const*, clang::RecordType const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::collectBaseOffset(clang::RecordType const*, clang::RecordType const*) |
2922 | | |
2923 | | /// Emit casts from a PrimType to another PrimType. |
2924 | | template <class Emitter> |
2925 | | bool ByteCodeExprGen<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT, |
2926 | 0 | QualType ToQT, const Expr *E) { |
2927 | |
|
2928 | 0 | if (FromT == PT_Float) { |
2929 | | // Floating to floating. |
2930 | 0 | if (ToT == PT_Float) { |
2931 | 0 | const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT); |
2932 | 0 | return this->emitCastFP(ToSem, getRoundingMode(E), E); |
2933 | 0 | } |
2934 | | |
2935 | | // Float to integral. |
2936 | 0 | if (isIntegralType(ToT) || ToT == PT_Bool) |
2937 | 0 | return this->emitCastFloatingIntegral(ToT, E); |
2938 | 0 | } |
2939 | | |
2940 | 0 | if (isIntegralType(FromT) || FromT == PT_Bool) { |
2941 | | // Integral to integral. |
2942 | 0 | if (isIntegralType(ToT) || ToT == PT_Bool) |
2943 | 0 | return FromT != ToT ? this->emitCast(FromT, ToT, E) : true; |
2944 | | |
2945 | 0 | if (ToT == PT_Float) { |
2946 | | // Integral to floating. |
2947 | 0 | const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT); |
2948 | 0 | return this->emitCastIntegralFloating(FromT, ToSem, getRoundingMode(E), |
2949 | 0 | E); |
2950 | 0 | } |
2951 | 0 | } |
2952 | | |
2953 | 0 | return false; |
2954 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitPrimCast(clang::interp::PrimType, clang::interp::PrimType, clang::QualType, clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitPrimCast(clang::interp::PrimType, clang::interp::PrimType, clang::QualType, clang::Expr const*) |
2955 | | |
2956 | | /// When calling this, we have a pointer of the local-to-destroy |
2957 | | /// on the stack. |
2958 | | /// Emit destruction of record types (or arrays of record types). |
2959 | | template <class Emitter> |
2960 | 0 | bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Descriptor *Desc) { |
2961 | 0 | assert(Desc); |
2962 | 0 | assert(!Desc->isPrimitive()); |
2963 | 0 | assert(!Desc->isPrimitiveArray()); |
2964 | | |
2965 | | // Arrays. |
2966 | 0 | if (Desc->isArray()) { |
2967 | 0 | const Descriptor *ElemDesc = Desc->ElemDesc; |
2968 | 0 | assert(ElemDesc); |
2969 | | |
2970 | | // Don't need to do anything for these. |
2971 | 0 | if (ElemDesc->isPrimitiveArray()) |
2972 | 0 | return this->emitPopPtr(SourceInfo{}); |
2973 | | |
2974 | | // If this is an array of record types, check if we need |
2975 | | // to call the element destructors at all. If not, try |
2976 | | // to save the work. |
2977 | 0 | if (const Record *ElemRecord = ElemDesc->ElemRecord) { |
2978 | 0 | if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor(); |
2979 | 0 | !Dtor || Dtor->isTrivial()) |
2980 | 0 | return this->emitPopPtr(SourceInfo{}); |
2981 | 0 | } |
2982 | | |
2983 | 0 | for (ssize_t I = Desc->getNumElems() - 1; I >= 0; --I) { |
2984 | 0 | if (!this->emitConstUint64(I, SourceInfo{})) |
2985 | 0 | return false; |
2986 | 0 | if (!this->emitArrayElemPtrUint64(SourceInfo{})) |
2987 | 0 | return false; |
2988 | 0 | if (!this->emitRecordDestruction(ElemDesc)) |
2989 | 0 | return false; |
2990 | 0 | } |
2991 | 0 | return this->emitPopPtr(SourceInfo{}); |
2992 | 0 | } |
2993 | | |
2994 | 0 | const Record *R = Desc->ElemRecord; |
2995 | 0 | assert(R); |
2996 | | // First, destroy all fields. |
2997 | 0 | for (const Record::Field &Field : llvm::reverse(R->fields())) { |
2998 | 0 | const Descriptor *D = Field.Desc; |
2999 | 0 | if (!D->isPrimitive() && !D->isPrimitiveArray()) { |
3000 | 0 | if (!this->emitDupPtr(SourceInfo{})) |
3001 | 0 | return false; |
3002 | 0 | if (!this->emitGetPtrField(Field.Offset, SourceInfo{})) |
3003 | 0 | return false; |
3004 | 0 | if (!this->emitRecordDestruction(D)) |
3005 | 0 | return false; |
3006 | 0 | } |
3007 | 0 | } |
3008 | | |
3009 | | // FIXME: Unions need to be handled differently here. We don't want to |
3010 | | // call the destructor of its members. |
3011 | | |
3012 | | // Now emit the destructor and recurse into base classes. |
3013 | 0 | if (const CXXDestructorDecl *Dtor = R->getDestructor(); |
3014 | 0 | Dtor && !Dtor->isTrivial()) { |
3015 | 0 | if (const Function *DtorFunc = getFunction(Dtor)) { |
3016 | 0 | assert(DtorFunc->hasThisPointer()); |
3017 | 0 | assert(DtorFunc->getNumParams() == 1); |
3018 | 0 | if (!this->emitDupPtr(SourceInfo{})) |
3019 | 0 | return false; |
3020 | 0 | if (!this->emitCall(DtorFunc, SourceInfo{})) |
3021 | 0 | return false; |
3022 | 0 | } |
3023 | 0 | } |
3024 | | |
3025 | 0 | for (const Record::Base &Base : llvm::reverse(R->bases())) { |
3026 | 0 | if (!this->emitGetPtrBase(Base.Offset, SourceInfo{})) |
3027 | 0 | return false; |
3028 | 0 | if (!this->emitRecordDestruction(Base.Desc)) |
3029 | 0 | return false; |
3030 | 0 | } |
3031 | | // FIXME: Virtual bases. |
3032 | | |
3033 | | // Remove the instance pointer. |
3034 | 0 | return this->emitPopPtr(SourceInfo{}); |
3035 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitRecordDestruction(clang::interp::Descriptor const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitRecordDestruction(clang::interp::Descriptor const*) |
3036 | | |
3037 | | namespace clang { |
3038 | | namespace interp { |
3039 | | |
3040 | | template class ByteCodeExprGen<ByteCodeEmitter>; |
3041 | | template class ByteCodeExprGen<EvalEmitter>; |
3042 | | |
3043 | | } // namespace interp |
3044 | | } // namespace clang |