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 "Context.h"
13 #include "Function.h"
14 #include "PrimType.h"
15 #include "Program.h"
16 #include "State.h"
17
18 using namespace clang;
19 using namespace clang::interp;
20
21 using APSInt = llvm::APSInt;
22 template <typename T> using Expected = llvm::Expected<T>;
23 template <typename T> using Optional = llvm::Optional<T>;
24
25 namespace clang {
26 namespace interp {
27
28 /// Scope used to handle temporaries in toplevel variable declarations.
29 template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
30 public:
DeclScope(ByteCodeExprGen<Emitter> * Ctx,const VarDecl * VD)31 DeclScope(ByteCodeExprGen<Emitter> *Ctx, const VarDecl *VD)
32 : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {}
33
addExtended(const Scope::Local & Local)34 void addExtended(const Scope::Local &Local) override {
35 return this->addLocal(Local);
36 }
37
38 private:
39 Program::DeclScope Scope;
40 };
41
42 /// Scope used to handle initialization methods.
43 template <class Emitter> class OptionScope {
44 public:
45 using InitFnRef = typename ByteCodeExprGen<Emitter>::InitFnRef;
46 using ChainedInitFnRef = std::function<bool(InitFnRef)>;
47
48 /// Root constructor, compiling or discarding primitives.
OptionScope(ByteCodeExprGen<Emitter> * Ctx,bool NewDiscardResult)49 OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult)
50 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
51 OldInitFn(std::move(Ctx->InitFn)) {
52 Ctx->DiscardResult = NewDiscardResult;
53 Ctx->InitFn = llvm::Optional<InitFnRef>{};
54 }
55
56 /// Root constructor, setting up compilation state.
OptionScope(ByteCodeExprGen<Emitter> * Ctx,InitFnRef NewInitFn)57 OptionScope(ByteCodeExprGen<Emitter> *Ctx, InitFnRef NewInitFn)
58 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
59 OldInitFn(std::move(Ctx->InitFn)) {
60 Ctx->DiscardResult = true;
61 Ctx->InitFn = NewInitFn;
62 }
63
64 /// Extends the chain of initialisation pointers.
OptionScope(ByteCodeExprGen<Emitter> * Ctx,ChainedInitFnRef NewInitFn)65 OptionScope(ByteCodeExprGen<Emitter> *Ctx, ChainedInitFnRef NewInitFn)
66 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
67 OldInitFn(std::move(Ctx->InitFn)) {
68 assert(OldInitFn && "missing initializer");
69 Ctx->InitFn = [this, NewInitFn] { return NewInitFn(*OldInitFn); };
70 }
71
~OptionScope()72 ~OptionScope() {
73 Ctx->DiscardResult = OldDiscardResult;
74 Ctx->InitFn = std::move(OldInitFn);
75 }
76
77 private:
78 /// Parent context.
79 ByteCodeExprGen<Emitter> *Ctx;
80 /// Old discard flag to restore.
81 bool OldDiscardResult;
82 /// Old pointer emitter to restore.
83 llvm::Optional<InitFnRef> OldInitFn;
84 };
85
86 } // namespace interp
87 } // namespace clang
88
89 template <class Emitter>
VisitCastExpr(const CastExpr * CE)90 bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
91 auto *SubExpr = CE->getSubExpr();
92 switch (CE->getCastKind()) {
93
94 case CK_LValueToRValue: {
95 return dereference(
96 CE->getSubExpr(), DerefKind::Read,
97 [](PrimType) {
98 // Value loaded - nothing to do here.
99 return true;
100 },
101 [this, CE](PrimType T) {
102 // Pointer on stack - dereference it.
103 if (!this->emitLoadPop(T, CE))
104 return false;
105 return DiscardResult ? this->emitPop(T, CE) : true;
106 });
107 }
108
109 case CK_ArrayToPointerDecay:
110 case CK_AtomicToNonAtomic:
111 case CK_ConstructorConversion:
112 case CK_FunctionToPointerDecay:
113 case CK_NonAtomicToAtomic:
114 case CK_NoOp:
115 case CK_UserDefinedConversion:
116 return this->Visit(SubExpr);
117
118 case CK_ToVoid:
119 return discard(SubExpr);
120
121 default: {
122 // TODO: implement other casts.
123 return this->bail(CE);
124 }
125 }
126 }
127
128 template <class Emitter>
VisitIntegerLiteral(const IntegerLiteral * LE)129 bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
130 if (DiscardResult)
131 return true;
132
133 auto Val = LE->getValue();
134 QualType LitTy = LE->getType();
135 if (Optional<PrimType> T = classify(LitTy))
136 return emitConst(*T, getIntWidth(LitTy), LE->getValue(), LE);
137 return this->bail(LE);
138 }
139
140 template <class Emitter>
VisitParenExpr(const ParenExpr * PE)141 bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) {
142 return this->Visit(PE->getSubExpr());
143 }
144
145 template <class Emitter>
VisitBinaryOperator(const BinaryOperator * BO)146 bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
147 const Expr *LHS = BO->getLHS();
148 const Expr *RHS = BO->getRHS();
149
150 // Deal with operations which have composite or void types.
151 switch (BO->getOpcode()) {
152 case BO_Comma:
153 if (!discard(LHS))
154 return false;
155 if (!this->Visit(RHS))
156 return false;
157 return true;
158 default:
159 break;
160 }
161
162 // Typecheck the args.
163 Optional<PrimType> LT = classify(LHS->getType());
164 Optional<PrimType> RT = classify(RHS->getType());
165 if (!LT || !RT) {
166 return this->bail(BO);
167 }
168
169 if (Optional<PrimType> T = classify(BO->getType())) {
170 if (!visit(LHS))
171 return false;
172 if (!visit(RHS))
173 return false;
174
175 auto Discard = [this, T, BO](bool Result) {
176 if (!Result)
177 return false;
178 return DiscardResult ? this->emitPop(*T, BO) : true;
179 };
180
181 switch (BO->getOpcode()) {
182 case BO_EQ:
183 return Discard(this->emitEQ(*LT, BO));
184 case BO_NE:
185 return Discard(this->emitNE(*LT, BO));
186 case BO_LT:
187 return Discard(this->emitLT(*LT, BO));
188 case BO_LE:
189 return Discard(this->emitLE(*LT, BO));
190 case BO_GT:
191 return Discard(this->emitGT(*LT, BO));
192 case BO_GE:
193 return Discard(this->emitGE(*LT, BO));
194 case BO_Sub:
195 return Discard(this->emitSub(*T, BO));
196 case BO_Add:
197 return Discard(this->emitAdd(*T, BO));
198 case BO_Mul:
199 return Discard(this->emitMul(*T, BO));
200 default:
201 return this->bail(BO);
202 }
203 }
204
205 return this->bail(BO);
206 }
207
208 template <class Emitter>
discard(const Expr * E)209 bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
210 OptionScope<Emitter> Scope(this, /*discardResult=*/true);
211 return this->Visit(E);
212 }
213
214 template <class Emitter>
visit(const Expr * E)215 bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
216 OptionScope<Emitter> Scope(this, /*discardResult=*/false);
217 return this->Visit(E);
218 }
219
220 template <class Emitter>
visitBool(const Expr * E)221 bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) {
222 if (Optional<PrimType> T = classify(E->getType())) {
223 return visit(E);
224 } else {
225 return this->bail(E);
226 }
227 }
228
229 template <class Emitter>
visitZeroInitializer(PrimType T,const Expr * E)230 bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, const Expr *E) {
231 switch (T) {
232 case PT_Bool:
233 return this->emitZeroBool(E);
234 case PT_Sint8:
235 return this->emitZeroSint8(E);
236 case PT_Uint8:
237 return this->emitZeroUint8(E);
238 case PT_Sint16:
239 return this->emitZeroSint16(E);
240 case PT_Uint16:
241 return this->emitZeroUint16(E);
242 case PT_Sint32:
243 return this->emitZeroSint32(E);
244 case PT_Uint32:
245 return this->emitZeroUint32(E);
246 case PT_Sint64:
247 return this->emitZeroSint64(E);
248 case PT_Uint64:
249 return this->emitZeroUint64(E);
250 case PT_Ptr:
251 return this->emitNullPtr(E);
252 }
253 llvm_unreachable("unknown primitive type");
254 }
255
256 template <class Emitter>
dereference(const Expr * LV,DerefKind AK,llvm::function_ref<bool (PrimType)> Direct,llvm::function_ref<bool (PrimType)> Indirect)257 bool ByteCodeExprGen<Emitter>::dereference(
258 const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
259 llvm::function_ref<bool(PrimType)> Indirect) {
260 if (Optional<PrimType> T = classify(LV->getType())) {
261 if (!LV->refersToBitField()) {
262 // Only primitive, non bit-field types can be dereferenced directly.
263 if (auto *DE = dyn_cast<DeclRefExpr>(LV)) {
264 if (!DE->getDecl()->getType()->isReferenceType()) {
265 if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
266 return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
267 if (auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
268 return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
269 }
270 }
271 }
272
273 if (!visit(LV))
274 return false;
275 return Indirect(*T);
276 }
277
278 return false;
279 }
280
281 template <class Emitter>
dereferenceParam(const Expr * LV,PrimType T,const ParmVarDecl * PD,DerefKind AK,llvm::function_ref<bool (PrimType)> Direct,llvm::function_ref<bool (PrimType)> Indirect)282 bool ByteCodeExprGen<Emitter>::dereferenceParam(
283 const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK,
284 llvm::function_ref<bool(PrimType)> Direct,
285 llvm::function_ref<bool(PrimType)> Indirect) {
286 auto It = this->Params.find(PD);
287 if (It != this->Params.end()) {
288 unsigned Idx = It->second;
289 switch (AK) {
290 case DerefKind::Read:
291 return DiscardResult ? true : this->emitGetParam(T, Idx, LV);
292
293 case DerefKind::Write:
294 if (!Direct(T))
295 return false;
296 if (!this->emitSetParam(T, Idx, LV))
297 return false;
298 return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
299
300 case DerefKind::ReadWrite:
301 if (!this->emitGetParam(T, Idx, LV))
302 return false;
303 if (!Direct(T))
304 return false;
305 if (!this->emitSetParam(T, Idx, LV))
306 return false;
307 return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
308 }
309 return true;
310 }
311
312 // If the param is a pointer, we can dereference a dummy value.
313 if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) {
314 if (auto Idx = P.getOrCreateDummy(PD))
315 return this->emitGetPtrGlobal(*Idx, PD);
316 return false;
317 }
318
319 // Value cannot be produced - try to emit pointer and do stuff with it.
320 return visit(LV) && Indirect(T);
321 }
322
323 template <class Emitter>
dereferenceVar(const Expr * LV,PrimType T,const VarDecl * VD,DerefKind AK,llvm::function_ref<bool (PrimType)> Direct,llvm::function_ref<bool (PrimType)> Indirect)324 bool ByteCodeExprGen<Emitter>::dereferenceVar(
325 const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK,
326 llvm::function_ref<bool(PrimType)> Direct,
327 llvm::function_ref<bool(PrimType)> Indirect) {
328 auto It = Locals.find(VD);
329 if (It != Locals.end()) {
330 const auto &L = It->second;
331 switch (AK) {
332 case DerefKind::Read:
333 if (!this->emitGetLocal(T, L.Offset, LV))
334 return false;
335 return DiscardResult ? this->emitPop(T, LV) : true;
336
337 case DerefKind::Write:
338 if (!Direct(T))
339 return false;
340 if (!this->emitSetLocal(T, L.Offset, LV))
341 return false;
342 return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
343
344 case DerefKind::ReadWrite:
345 if (!this->emitGetLocal(T, L.Offset, LV))
346 return false;
347 if (!Direct(T))
348 return false;
349 if (!this->emitSetLocal(T, L.Offset, LV))
350 return false;
351 return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
352 }
353 } else if (auto Idx = getGlobalIdx(VD)) {
354 switch (AK) {
355 case DerefKind::Read:
356 if (!this->emitGetGlobal(T, *Idx, LV))
357 return false;
358 return DiscardResult ? this->emitPop(T, LV) : true;
359
360 case DerefKind::Write:
361 if (!Direct(T))
362 return false;
363 if (!this->emitSetGlobal(T, *Idx, LV))
364 return false;
365 return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
366
367 case DerefKind::ReadWrite:
368 if (!this->emitGetGlobal(T, *Idx, LV))
369 return false;
370 if (!Direct(T))
371 return false;
372 if (!this->emitSetGlobal(T, *Idx, LV))
373 return false;
374 return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
375 }
376 }
377
378 // If the declaration is a constant value, emit it here even
379 // though the declaration was not evaluated in the current scope.
380 // The access mode can only be read in this case.
381 if (!DiscardResult && AK == DerefKind::Read) {
382 if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) {
383 QualType VT = VD->getType();
384 if (VT.isConstQualified() && VT->isFundamentalType())
385 return this->Visit(VD->getInit());
386 }
387 }
388
389 // Value cannot be produced - try to emit pointer.
390 return visit(LV) && Indirect(T);
391 }
392
393 template <class Emitter>
emitConst(PrimType T,unsigned NumBits,const APInt & Value,const Expr * E)394 bool ByteCodeExprGen<Emitter>::emitConst(PrimType T, unsigned NumBits,
395 const APInt &Value, const Expr *E) {
396 switch (T) {
397 case PT_Sint8:
398 return this->emitConstSint8(Value.getSExtValue(), E);
399 case PT_Uint8:
400 return this->emitConstUint8(Value.getZExtValue(), E);
401 case PT_Sint16:
402 return this->emitConstSint16(Value.getSExtValue(), E);
403 case PT_Uint16:
404 return this->emitConstUint16(Value.getZExtValue(), E);
405 case PT_Sint32:
406 return this->emitConstSint32(Value.getSExtValue(), E);
407 case PT_Uint32:
408 return this->emitConstUint32(Value.getZExtValue(), E);
409 case PT_Sint64:
410 return this->emitConstSint64(Value.getSExtValue(), E);
411 case PT_Uint64:
412 return this->emitConstUint64(Value.getZExtValue(), E);
413 case PT_Bool:
414 return this->emitConstBool(Value.getBoolValue(), E);
415 case PT_Ptr:
416 llvm_unreachable("Invalid integral type");
417 break;
418 }
419 llvm_unreachable("unknown primitive type");
420 }
421
422 template <class Emitter>
allocateLocalPrimitive(DeclTy && Src,PrimType Ty,bool IsConst,bool IsExtended)423 unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
424 PrimType Ty,
425 bool IsConst,
426 bool IsExtended) {
427 Descriptor *D = P.createDescriptor(Src, Ty, IsConst, Src.is<const Expr *>());
428 Scope::Local Local = this->createLocal(D);
429 if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>()))
430 Locals.insert({VD, Local});
431 VarScope->add(Local, IsExtended);
432 return Local.Offset;
433 }
434
435 template <class Emitter>
436 llvm::Optional<unsigned>
allocateLocal(DeclTy && Src,bool IsExtended)437 ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) {
438 QualType Ty;
439
440 const ValueDecl *Key = nullptr;
441 bool IsTemporary = false;
442 if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) {
443 Key = VD;
444 Ty = VD->getType();
445 }
446 if (auto *E = Src.dyn_cast<const Expr *>()) {
447 IsTemporary = true;
448 Ty = E->getType();
449 }
450
451 Descriptor *D = P.createDescriptor(Src, Ty.getTypePtr(),
452 Ty.isConstQualified(), IsTemporary);
453 if (!D)
454 return {};
455
456 Scope::Local Local = this->createLocal(D);
457 if (Key)
458 Locals.insert({Key, Local});
459 VarScope->add(Local, IsExtended);
460 return Local.Offset;
461 }
462
463 template <class Emitter>
visitInitializer(const Expr * Init,InitFnRef InitFn)464 bool ByteCodeExprGen<Emitter>::visitInitializer(
465 const Expr *Init, InitFnRef InitFn) {
466 OptionScope<Emitter> Scope(this, InitFn);
467 return this->Visit(Init);
468 }
469
470 template <class Emitter>
getPtrVarDecl(const VarDecl * VD,const Expr * E)471 bool ByteCodeExprGen<Emitter>::getPtrVarDecl(const VarDecl *VD, const Expr *E) {
472 // Generate a pointer to the local, loading refs.
473 if (Optional<unsigned> Idx = getGlobalIdx(VD)) {
474 if (VD->getType()->isReferenceType())
475 return this->emitGetGlobalPtr(*Idx, E);
476 else
477 return this->emitGetPtrGlobal(*Idx, E);
478 }
479 return this->bail(VD);
480 }
481
482 template <class Emitter>
483 llvm::Optional<unsigned>
getGlobalIdx(const VarDecl * VD)484 ByteCodeExprGen<Emitter>::getGlobalIdx(const VarDecl *VD) {
485 if (VD->isConstexpr()) {
486 // Constexpr decl - it must have already been defined.
487 return P.getGlobal(VD);
488 }
489 if (!VD->hasLocalStorage()) {
490 // Not constexpr, but a global var - can have pointer taken.
491 Program::DeclScope Scope(P, VD);
492 return P.getOrCreateGlobal(VD);
493 }
494 return {};
495 }
496
497 template <class Emitter>
getRecordTy(QualType Ty)498 const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) {
499 if (auto *PT = dyn_cast<PointerType>(Ty))
500 return PT->getPointeeType()->getAs<RecordType>();
501 else
502 return Ty->getAs<RecordType>();
503 }
504
505 template <class Emitter>
getRecord(QualType Ty)506 Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) {
507 if (auto *RecordTy = getRecordTy(Ty)) {
508 return getRecord(RecordTy->getDecl());
509 }
510 return nullptr;
511 }
512
513 template <class Emitter>
getRecord(const RecordDecl * RD)514 Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) {
515 return P.getOrCreateRecord(RD);
516 }
517
518 template <class Emitter>
visitExpr(const Expr * Exp)519 bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) {
520 ExprScope<Emitter> RootScope(this);
521 if (!visit(Exp))
522 return false;
523
524 if (Optional<PrimType> T = classify(Exp))
525 return this->emitRet(*T, Exp);
526 else
527 return this->emitRetValue(Exp);
528 }
529
530 template <class Emitter>
visitDecl(const VarDecl * VD)531 bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
532 const Expr *Init = VD->getInit();
533
534 if (Optional<unsigned> I = P.createGlobal(VD)) {
535 if (Optional<PrimType> T = classify(VD->getType())) {
536 {
537 // Primitive declarations - compute the value and set it.
538 DeclScope<Emitter> LocalScope(this, VD);
539 if (!visit(Init))
540 return false;
541 }
542
543 // If the declaration is global, save the value for later use.
544 if (!this->emitDup(*T, VD))
545 return false;
546 if (!this->emitInitGlobal(*T, *I, VD))
547 return false;
548 return this->emitRet(*T, VD);
549 } else {
550 {
551 // Composite declarations - allocate storage and initialize it.
552 DeclScope<Emitter> LocalScope(this, VD);
553 if (!visitGlobalInitializer(Init, *I))
554 return false;
555 }
556
557 // Return a pointer to the global.
558 if (!this->emitGetPtrGlobal(*I, VD))
559 return false;
560 return this->emitRetValue(VD);
561 }
562 }
563
564 return this->bail(VD);
565 }
566
567 template <class Emitter>
emitCleanup()568 void ByteCodeExprGen<Emitter>::emitCleanup() {
569 for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
570 C->emitDestruction();
571 }
572
573 namespace clang {
574 namespace interp {
575
576 template class ByteCodeExprGen<ByteCodeEmitter>;
577 template class ByteCodeExprGen<EvalEmitter>;
578
579 } // namespace interp
580 } // namespace clang
581