1 //===--- ByteCodeExprGen.h - 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 // Defines the constexpr bytecode compiler.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
14 #define LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
15 
16 #include "ByteCodeEmitter.h"
17 #include "EvalEmitter.h"
18 #include "Pointer.h"
19 #include "PrimType.h"
20 #include "Record.h"
21 #include "clang/AST/Decl.h"
22 #include "clang/AST/Expr.h"
23 #include "clang/AST/StmtVisitor.h"
24 #include "clang/Basic/TargetInfo.h"
25 
26 namespace clang {
27 class QualType;
28 
29 namespace interp {
30 
31 template <class Emitter> class LocalScope;
32 template <class Emitter> class DestructorScope;
33 template <class Emitter> class RecordScope;
34 template <class Emitter> class VariableScope;
35 template <class Emitter> class DeclScope;
36 template <class Emitter> class OptionScope;
37 template <class Emitter> class ArrayIndexScope;
38 template <class Emitter> class SourceLocScope;
39 
40 /// Compilation context for expressions.
41 template <class Emitter>
42 class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
43                         public Emitter {
44 protected:
45   // Aliases for types defined in the emitter.
46   using LabelTy = typename Emitter::LabelTy;
47   using AddrTy = typename Emitter::AddrTy;
48 
49   /// Current compilation context.
50   Context &Ctx;
51   /// Program to link to.
52   Program &P;
53 
54 public:
55   /// Initializes the compiler and the backend emitter.
56   template <typename... Tys>
ByteCodeExprGen(Context & Ctx,Program & P,Tys &&...Args)57   ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args)
58       : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}
59 
60   // Expression visitors - result returned on interp stack.
61   bool VisitCastExpr(const CastExpr *E);
62   bool VisitIntegerLiteral(const IntegerLiteral *E);
63   bool VisitFloatingLiteral(const FloatingLiteral *E);
64   bool VisitParenExpr(const ParenExpr *E);
65   bool VisitBinaryOperator(const BinaryOperator *E);
66   bool VisitLogicalBinOp(const BinaryOperator *E);
67   bool VisitPointerArithBinOp(const BinaryOperator *E);
68   bool VisitComplexBinOp(const BinaryOperator *E);
69   bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
70   bool VisitCallExpr(const CallExpr *E);
71   bool VisitBuiltinCallExpr(const CallExpr *E);
72   bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E);
73   bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E);
74   bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E);
75   bool VisitGNUNullExpr(const GNUNullExpr *E);
76   bool VisitCXXThisExpr(const CXXThisExpr *E);
77   bool VisitUnaryOperator(const UnaryOperator *E);
78   bool VisitDeclRefExpr(const DeclRefExpr *E);
79   bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E);
80   bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);
81   bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
82   bool VisitInitListExpr(const InitListExpr *E);
83   bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E);
84   bool VisitConstantExpr(const ConstantExpr *E);
85   bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
86   bool VisitMemberExpr(const MemberExpr *E);
87   bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E);
88   bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E);
89   bool VisitOpaqueValueExpr(const OpaqueValueExpr *E);
90   bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E);
91   bool VisitStringLiteral(const StringLiteral *E);
92   bool VisitCharacterLiteral(const CharacterLiteral *E);
93   bool VisitCompoundAssignOperator(const CompoundAssignOperator *E);
94   bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E);
95   bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E);
96   bool VisitExprWithCleanups(const ExprWithCleanups *E);
97   bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
98   bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E);
99   bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
100   bool VisitTypeTraitExpr(const TypeTraitExpr *E);
101   bool VisitLambdaExpr(const LambdaExpr *E);
102   bool VisitPredefinedExpr(const PredefinedExpr *E);
103   bool VisitCXXThrowExpr(const CXXThrowExpr *E);
104   bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E);
105   bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
106   bool VisitCXXConstructExpr(const CXXConstructExpr *E);
107   bool VisitSourceLocExpr(const SourceLocExpr *E);
108   bool VisitOffsetOfExpr(const OffsetOfExpr *E);
109   bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E);
110   bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
111 
112 protected:
113   bool visitExpr(const Expr *E) override;
114   bool visitDecl(const VarDecl *VD) override;
115 
116 protected:
117   /// Emits scope cleanup instructions.
118   void emitCleanup();
119 
120   /// Returns a record type from a record or pointer type.
121   const RecordType *getRecordTy(QualType Ty);
122 
123   /// Returns a record from a record or pointer type.
124   Record *getRecord(QualType Ty);
125   Record *getRecord(const RecordDecl *RD);
126 
127   // Returns a function for the given FunctionDecl.
128   // If the function does not exist yet, it is compiled.
129   const Function *getFunction(const FunctionDecl *FD);
130 
131   /// Classifies a type.
classify(const Expr * E)132   std::optional<PrimType> classify(const Expr *E) const {
133     if (E->isGLValue()) {
134       if (E->getType()->isFunctionType())
135         return PT_FnPtr;
136       return PT_Ptr;
137     }
138 
139     return classify(E->getType());
140   }
classify(QualType Ty)141   std::optional<PrimType> classify(QualType Ty) const {
142     return Ctx.classify(Ty);
143   }
144 
145   /// Classifies a known primitive type
classifyPrim(QualType Ty)146   PrimType classifyPrim(QualType Ty) const {
147     if (auto T = classify(Ty)) {
148       return *T;
149     }
150     llvm_unreachable("not a primitive type");
151   }
152   /// Evaluates an expression and places the result on the stack. If the
153   /// expression is of composite type, a local variable will be created
154   /// and a pointer to said variable will be placed on the stack.
155   bool visit(const Expr *E);
156   /// Compiles an initializer. This is like visit() but it will never
157   /// create a variable and instead rely on a variable already having
158   /// been created. visitInitializer() then relies on a pointer to this
159   /// variable being on top of the stack.
160   bool visitInitializer(const Expr *E);
161   /// Evaluates an expression for side effects and discards the result.
162   bool discard(const Expr *E);
163   /// Just pass evaluation on to \p E. This leaves all the parsing flags
164   /// intact.
165   bool delegate(const Expr *E);
166 
167   /// Creates and initializes a variable from the given decl.
168   bool visitVarDecl(const VarDecl *VD);
169   /// Visit an APValue.
170   bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
171 
172   /// Visits an expression and converts it to a boolean.
173   bool visitBool(const Expr *E);
174 
175   /// Visits an initializer for a local.
visitLocalInitializer(const Expr * Init,unsigned I)176   bool visitLocalInitializer(const Expr *Init, unsigned I) {
177     if (!this->emitGetPtrLocal(I, Init))
178       return false;
179 
180     if (!visitInitializer(Init))
181       return false;
182 
183     return this->emitPopPtr(Init);
184   }
185 
186   /// Visits an initializer for a global.
visitGlobalInitializer(const Expr * Init,unsigned I)187   bool visitGlobalInitializer(const Expr *Init, unsigned I) {
188     if (!this->emitGetPtrGlobal(I, Init))
189       return false;
190 
191     if (!visitInitializer(Init))
192       return false;
193 
194     return this->emitPopPtr(Init);
195   }
196 
197   /// Visits a delegated initializer.
visitThisInitializer(const Expr * I)198   bool visitThisInitializer(const Expr *I) {
199     if (!this->emitThis(I))
200       return false;
201 
202     if (!visitInitializer(I))
203       return false;
204 
205     return this->emitPopPtr(I);
206   }
207 
208   bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *E);
209   bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init);
210 
211   /// Creates a local primitive value.
212   unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst,
213                                   bool IsExtended = false);
214 
215   /// Allocates a space storing a local given its type.
216   std::optional<unsigned> allocateLocal(DeclTy &&Decl, bool IsExtended = false);
217 
218 private:
219   friend class VariableScope<Emitter>;
220   friend class LocalScope<Emitter>;
221   friend class DestructorScope<Emitter>;
222   friend class RecordScope<Emitter>;
223   friend class DeclScope<Emitter>;
224   friend class OptionScope<Emitter>;
225   friend class ArrayIndexScope<Emitter>;
226   friend class SourceLocScope<Emitter>;
227 
228   /// Emits a zero initializer.
229   bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);
230   bool visitZeroRecordInitializer(const Record *R, const Expr *E);
231 
232   enum class DerefKind {
233     /// Value is read and pushed to stack.
234     Read,
235     /// Direct method generates a value which is written. Returns pointer.
236     Write,
237     /// Direct method receives the value, pushes mutated value. Returns pointer.
238     ReadWrite,
239   };
240 
241   /// Method to directly load a value. If the value can be fetched directly,
242   /// the direct handler is called. Otherwise, a pointer is left on the stack
243   /// and the indirect handler is expected to operate on that.
244   bool dereference(const Expr *LV, DerefKind AK,
245                    llvm::function_ref<bool(PrimType)> Direct,
246                    llvm::function_ref<bool(PrimType)> Indirect);
247   bool dereferenceParam(const Expr *LV, PrimType T, const ParmVarDecl *PD,
248                         DerefKind AK,
249                         llvm::function_ref<bool(PrimType)> Direct,
250                         llvm::function_ref<bool(PrimType)> Indirect);
251   bool dereferenceVar(const Expr *LV, PrimType T, const VarDecl *PD,
252                       DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
253                       llvm::function_ref<bool(PrimType)> Indirect);
254 
255   /// Emits an APSInt constant.
256   bool emitConst(const llvm::APSInt &Value, PrimType Ty, const Expr *E);
257   bool emitConst(const llvm::APSInt &Value, const Expr *E);
emitConst(const llvm::APInt & Value,const Expr * E)258   bool emitConst(const llvm::APInt &Value, const Expr *E) {
259     return emitConst(static_cast<llvm::APSInt>(Value), E);
260   }
261 
262   /// Emits an integer constant.
263   template <typename T> bool emitConst(T Value, PrimType Ty, const Expr *E);
264   template <typename T> bool emitConst(T Value, const Expr *E);
265 
266   /// Returns the CXXRecordDecl for the type of the given expression,
267   /// or nullptr if no such decl exists.
getRecordDecl(const Expr * E)268   const CXXRecordDecl *getRecordDecl(const Expr *E) const {
269     QualType T = E->getType();
270     if (const auto *RD = T->getPointeeCXXRecordDecl())
271       return RD;
272     return T->getAsCXXRecordDecl();
273   }
274 
getRoundingMode(const Expr * E)275   llvm::RoundingMode getRoundingMode(const Expr *E) const {
276     FPOptions FPO = E->getFPFeaturesInEffect(Ctx.getLangOpts());
277 
278     if (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic)
279       return llvm::RoundingMode::NearestTiesToEven;
280 
281     return FPO.getRoundingMode();
282   }
283 
284   bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E);
classifyComplexElementType(QualType T)285   std::optional<PrimType> classifyComplexElementType(QualType T) const {
286     assert(T->isAnyComplexType());
287 
288     QualType ElemType = T->getAs<ComplexType>()->getElementType();
289 
290     return this->classify(ElemType);
291   }
292 
293   bool emitComplexReal(const Expr *SubExpr);
294 
295   bool emitRecordDestruction(const Descriptor *Desc);
296   unsigned collectBaseOffset(const RecordType *BaseType,
297                              const RecordType *DerivedType);
298 
299 protected:
300   /// Variable to storage mapping.
301   llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
302 
303   /// OpaqueValueExpr to location mapping.
304   llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs;
305 
306   /// Current scope.
307   VariableScope<Emitter> *VarScope = nullptr;
308 
309   /// Current argument index. Needed to emit ArrayInitIndexExpr.
310   std::optional<uint64_t> ArrayIndex;
311 
312   /// DefaultInit- or DefaultArgExpr, needed for SourceLocExpr.
313   const Expr *SourceLocDefaultExpr = nullptr;
314 
315   /// Flag indicating if return value is to be discarded.
316   bool DiscardResult = false;
317 
318   /// Flag inidicating if we're initializing an already created
319   /// variable. This is set in visitInitializer().
320   bool Initializing = false;
321 
322   /// Flag indicating if we're initializing a global variable.
323   bool GlobalDecl = false;
324 };
325 
326 extern template class ByteCodeExprGen<ByteCodeEmitter>;
327 extern template class ByteCodeExprGen<EvalEmitter>;
328 
329 /// Scope chain managing the variable lifetimes.
330 template <class Emitter> class VariableScope {
331 public:
VariableScope(ByteCodeExprGen<Emitter> * Ctx)332   VariableScope(ByteCodeExprGen<Emitter> *Ctx)
333       : Ctx(Ctx), Parent(Ctx->VarScope) {
334     Ctx->VarScope = this;
335   }
336 
~VariableScope()337   virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
338 
add(const Scope::Local & Local,bool IsExtended)339   void add(const Scope::Local &Local, bool IsExtended) {
340     if (IsExtended)
341       this->addExtended(Local);
342     else
343       this->addLocal(Local);
344   }
345 
addLocal(const Scope::Local & Local)346   virtual void addLocal(const Scope::Local &Local) {
347     if (this->Parent)
348       this->Parent->addLocal(Local);
349   }
350 
addExtended(const Scope::Local & Local)351   virtual void addExtended(const Scope::Local &Local) {
352     if (this->Parent)
353       this->Parent->addExtended(Local);
354   }
355 
emitDestruction()356   virtual void emitDestruction() {}
emitDestructors()357   virtual void emitDestructors() {}
getParent()358   VariableScope *getParent() const { return Parent; }
359 
360 protected:
361   /// ByteCodeExprGen instance.
362   ByteCodeExprGen<Emitter> *Ctx;
363   /// Link to the parent scope.
364   VariableScope *Parent;
365 };
366 
367 /// Generic scope for local variables.
368 template <class Emitter> class LocalScope : public VariableScope<Emitter> {
369 public:
LocalScope(ByteCodeExprGen<Emitter> * Ctx)370   LocalScope(ByteCodeExprGen<Emitter> *Ctx) : VariableScope<Emitter>(Ctx) {}
371 
372   /// Emit a Destroy op for this scope.
~LocalScope()373   ~LocalScope() override {
374     if (!Idx)
375       return;
376     this->Ctx->emitDestroy(*Idx, SourceInfo{});
377   }
378 
379   /// Overriden to support explicit destruction.
emitDestruction()380   void emitDestruction() override {
381     if (!Idx)
382       return;
383     this->emitDestructors();
384     this->Ctx->emitDestroy(*Idx, SourceInfo{});
385     this->Idx = std::nullopt;
386   }
387 
addLocal(const Scope::Local & Local)388   void addLocal(const Scope::Local &Local) override {
389     if (!Idx) {
390       Idx = this->Ctx->Descriptors.size();
391       this->Ctx->Descriptors.emplace_back();
392     }
393 
394     this->Ctx->Descriptors[*Idx].emplace_back(Local);
395   }
396 
emitDestructors()397   void emitDestructors() override {
398     if (!Idx)
399       return;
400     // Emit destructor calls for local variables of record
401     // type with a destructor.
402     for (Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
403       if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) {
404         this->Ctx->emitGetPtrLocal(Local.Offset, SourceInfo{});
405         this->Ctx->emitRecordDestruction(Local.Desc);
406       }
407     }
408   }
409 
410   /// Index of the scope in the chain.
411   std::optional<unsigned> Idx;
412 };
413 
414 /// Emits the destructors of the variables of \param OtherScope
415 /// when this scope is destroyed. Does not create a Scope in the bytecode at
416 /// all, this is just a RAII object to emit destructors.
417 template <class Emitter> class DestructorScope final {
418 public:
DestructorScope(LocalScope<Emitter> & OtherScope)419   DestructorScope(LocalScope<Emitter> &OtherScope) : OtherScope(OtherScope) {}
420 
~DestructorScope()421   ~DestructorScope() { OtherScope.emitDestructors(); }
422 
423 private:
424   LocalScope<Emitter> &OtherScope;
425 };
426 
427 /// Like a regular LocalScope, except that the destructors of all local
428 /// variables are automatically emitted when the AutoScope is destroyed.
429 template <class Emitter> class AutoScope : public LocalScope<Emitter> {
430 public:
AutoScope(ByteCodeExprGen<Emitter> * Ctx)431   AutoScope(ByteCodeExprGen<Emitter> *Ctx)
432       : LocalScope<Emitter>(Ctx), DS(*this) {}
433 
434 private:
435   DestructorScope<Emitter> DS;
436 };
437 
438 /// Scope for storage declared in a compound statement.
439 template <class Emitter> class BlockScope final : public AutoScope<Emitter> {
440 public:
BlockScope(ByteCodeExprGen<Emitter> * Ctx)441   BlockScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
442 
addExtended(const Scope::Local & Local)443   void addExtended(const Scope::Local &Local) override {
444     // If we to this point, just add the variable as a normal local
445     // variable. It will be destroyed at the end of the block just
446     // like all others.
447     this->addLocal(Local);
448   }
449 };
450 
451 /// Expression scope which tracks potentially lifetime extended
452 /// temporaries which are hoisted to the parent scope on exit.
453 template <class Emitter> class ExprScope final : public AutoScope<Emitter> {
454 public:
ExprScope(ByteCodeExprGen<Emitter> * Ctx)455   ExprScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
456 
addExtended(const Scope::Local & Local)457   void addExtended(const Scope::Local &Local) override {
458     if (this->Parent)
459       this->Parent->addLocal(Local);
460   }
461 };
462 
463 template <class Emitter> class ArrayIndexScope final {
464 public:
ArrayIndexScope(ByteCodeExprGen<Emitter> * Ctx,uint64_t Index)465   ArrayIndexScope(ByteCodeExprGen<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
466     OldArrayIndex = Ctx->ArrayIndex;
467     Ctx->ArrayIndex = Index;
468   }
469 
~ArrayIndexScope()470   ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }
471 
472 private:
473   ByteCodeExprGen<Emitter> *Ctx;
474   std::optional<uint64_t> OldArrayIndex;
475 };
476 
477 template <class Emitter> class SourceLocScope final {
478 public:
SourceLocScope(ByteCodeExprGen<Emitter> * Ctx,const Expr * DefaultExpr)479   SourceLocScope(ByteCodeExprGen<Emitter> *Ctx, const Expr *DefaultExpr)
480       : Ctx(Ctx) {
481     assert(DefaultExpr);
482     // We only switch if the current SourceLocDefaultExpr is null.
483     if (!Ctx->SourceLocDefaultExpr) {
484       Enabled = true;
485       Ctx->SourceLocDefaultExpr = DefaultExpr;
486     }
487   }
488 
~SourceLocScope()489   ~SourceLocScope() {
490     if (Enabled)
491       Ctx->SourceLocDefaultExpr = nullptr;
492   }
493 
494 private:
495   ByteCodeExprGen<Emitter> *Ctx;
496   bool Enabled = false;
497 };
498 
499 } // namespace interp
500 } // namespace clang
501 
502 #endif
503