[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang / lib / AST / Interp / ByteCodeExprGen.h
blob83986d3dd579ed6a67930e4b1f91edfe7372bc5d
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.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
14 #define LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
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"
26 namespace clang {
27 class QualType;
29 namespace interp {
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;
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;
49 /// Current compilation context.
50 Context &Ctx;
51 /// Program to link to.
52 Program &P;
54 public:
55 /// Initializes the compiler and the backend emitter.
56 template <typename... Tys>
57 ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args)
58 : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}
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 VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
69 bool VisitCallExpr(const CallExpr *E);
70 bool VisitBuiltinCallExpr(const CallExpr *E);
71 bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *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);
111 protected:
112 bool visitExpr(const Expr *E) override;
113 bool visitDecl(const VarDecl *VD) override;
115 protected:
116 /// Emits scope cleanup instructions.
117 void emitCleanup();
119 /// Returns a record type from a record or pointer type.
120 const RecordType *getRecordTy(QualType Ty);
122 /// Returns a record from a record or pointer type.
123 Record *getRecord(QualType Ty);
124 Record *getRecord(const RecordDecl *RD);
126 // Returns a function for the given FunctionDecl.
127 // If the function does not exist yet, it is compiled.
128 const Function *getFunction(const FunctionDecl *FD);
130 /// Classifies a type.
131 std::optional<PrimType> classify(const Expr *E) const {
132 return E->isGLValue() ? PT_Ptr : classify(E->getType());
134 std::optional<PrimType> classify(QualType Ty) const {
135 return Ctx.classify(Ty);
138 /// Classifies a known primitive type
139 PrimType classifyPrim(QualType Ty) const {
140 if (auto T = classify(Ty)) {
141 return *T;
143 llvm_unreachable("not a primitive type");
145 /// Evaluates an expression and places the result on the stack. If the
146 /// expression is of composite type, a local variable will be created
147 /// and a pointer to said variable will be placed on the stack.
148 bool visit(const Expr *E);
149 /// Compiles an initializer. This is like visit() but it will never
150 /// create a variable and instead rely on a variable already having
151 /// been created. visitInitializer() then relies on a pointer to this
152 /// variable being on top of the stack.
153 bool visitInitializer(const Expr *E);
154 /// Evaluates an expression for side effects and discards the result.
155 bool discard(const Expr *E);
156 /// Just pass evaluation on to \p E. This leaves all the parsing flags
157 /// intact.
158 bool delegate(const Expr *E);
160 /// Creates and initializes a variable from the given decl.
161 bool visitVarDecl(const VarDecl *VD);
162 /// Visit an APValue.
163 bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
165 /// Visits an expression and converts it to a boolean.
166 bool visitBool(const Expr *E);
168 /// Visits an initializer for a local.
169 bool visitLocalInitializer(const Expr *Init, unsigned I) {
170 if (!this->emitGetPtrLocal(I, Init))
171 return false;
173 if (!visitInitializer(Init))
174 return false;
176 return this->emitPopPtr(Init);
179 /// Visits an initializer for a global.
180 bool visitGlobalInitializer(const Expr *Init, unsigned I) {
181 if (!this->emitGetPtrGlobal(I, Init))
182 return false;
184 if (!visitInitializer(Init))
185 return false;
187 if ((Init->getType()->isArrayType() || Init->getType()->isRecordType()) &&
188 !this->emitCheckGlobalCtor(Init))
189 return false;
191 return this->emitPopPtr(Init);
194 /// Visits a delegated initializer.
195 bool visitThisInitializer(const Expr *I) {
196 if (!this->emitThis(I))
197 return false;
199 if (!visitInitializer(I))
200 return false;
202 return this->emitPopPtr(I);
205 bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *E);
207 /// Creates a local primitive value.
208 unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst,
209 bool IsExtended = false);
211 /// Allocates a space storing a local given its type.
212 std::optional<unsigned> allocateLocal(DeclTy &&Decl, bool IsExtended = false);
214 private:
215 friend class VariableScope<Emitter>;
216 friend class LocalScope<Emitter>;
217 friend class DestructorScope<Emitter>;
218 friend class RecordScope<Emitter>;
219 friend class DeclScope<Emitter>;
220 friend class OptionScope<Emitter>;
221 friend class ArrayIndexScope<Emitter>;
222 friend class SourceLocScope<Emitter>;
224 /// Emits a zero initializer.
225 bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);
226 bool visitZeroRecordInitializer(const Record *R, const Expr *E);
228 enum class DerefKind {
229 /// Value is read and pushed to stack.
230 Read,
231 /// Direct method generates a value which is written. Returns pointer.
232 Write,
233 /// Direct method receives the value, pushes mutated value. Returns pointer.
234 ReadWrite,
237 /// Method to directly load a value. If the value can be fetched directly,
238 /// the direct handler is called. Otherwise, a pointer is left on the stack
239 /// and the indirect handler is expected to operate on that.
240 bool dereference(const Expr *LV, DerefKind AK,
241 llvm::function_ref<bool(PrimType)> Direct,
242 llvm::function_ref<bool(PrimType)> Indirect);
243 bool dereferenceParam(const Expr *LV, PrimType T, const ParmVarDecl *PD,
244 DerefKind AK,
245 llvm::function_ref<bool(PrimType)> Direct,
246 llvm::function_ref<bool(PrimType)> Indirect);
247 bool dereferenceVar(const Expr *LV, PrimType T, const VarDecl *PD,
248 DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
249 llvm::function_ref<bool(PrimType)> Indirect);
251 /// Emits an APSInt constant.
252 bool emitConst(const llvm::APSInt &Value, PrimType Ty, const Expr *E);
253 bool emitConst(const llvm::APSInt &Value, const Expr *E);
254 bool emitConst(const llvm::APInt &Value, const Expr *E) {
255 return emitConst(static_cast<llvm::APSInt>(Value), E);
258 /// Emits an integer constant.
259 template <typename T> bool emitConst(T Value, PrimType Ty, const Expr *E);
260 template <typename T> bool emitConst(T Value, const Expr *E);
262 /// Returns the CXXRecordDecl for the type of the given expression,
263 /// or nullptr if no such decl exists.
264 const CXXRecordDecl *getRecordDecl(const Expr *E) const {
265 QualType T = E->getType();
266 if (const auto *RD = T->getPointeeCXXRecordDecl())
267 return RD;
268 return T->getAsCXXRecordDecl();
271 llvm::RoundingMode getRoundingMode(const Expr *E) const {
272 FPOptions FPO = E->getFPFeaturesInEffect(Ctx.getLangOpts());
274 if (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic)
275 return llvm::RoundingMode::NearestTiesToEven;
277 return FPO.getRoundingMode();
280 bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E);
281 bool emitRecordDestruction(const Descriptor *Desc);
282 unsigned collectBaseOffset(const RecordType *BaseType,
283 const RecordType *DerivedType);
285 protected:
286 /// Variable to storage mapping.
287 llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
289 /// OpaqueValueExpr to location mapping.
290 llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs;
292 /// Current scope.
293 VariableScope<Emitter> *VarScope = nullptr;
295 /// Current argument index. Needed to emit ArrayInitIndexExpr.
296 std::optional<uint64_t> ArrayIndex;
298 /// DefaultInit- or DefaultArgExpr, needed for SourceLocExpr.
299 const Expr *SourceLocDefaultExpr = nullptr;
301 /// Flag indicating if return value is to be discarded.
302 bool DiscardResult = false;
304 /// Flag inidicating if we're initializing an already created
305 /// variable. This is set in visitInitializer().
306 bool Initializing = false;
308 /// Flag indicating if we're initializing a global variable.
309 bool GlobalDecl = false;
312 extern template class ByteCodeExprGen<ByteCodeEmitter>;
313 extern template class ByteCodeExprGen<EvalEmitter>;
315 /// Scope chain managing the variable lifetimes.
316 template <class Emitter> class VariableScope {
317 public:
318 VariableScope(ByteCodeExprGen<Emitter> *Ctx)
319 : Ctx(Ctx), Parent(Ctx->VarScope) {
320 Ctx->VarScope = this;
323 virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
325 void add(const Scope::Local &Local, bool IsExtended) {
326 if (IsExtended)
327 this->addExtended(Local);
328 else
329 this->addLocal(Local);
332 virtual void addLocal(const Scope::Local &Local) {
333 if (this->Parent)
334 this->Parent->addLocal(Local);
337 virtual void addExtended(const Scope::Local &Local) {
338 if (this->Parent)
339 this->Parent->addExtended(Local);
342 virtual void emitDestruction() {}
343 virtual void emitDestructors() {}
344 VariableScope *getParent() const { return Parent; }
346 protected:
347 /// ByteCodeExprGen instance.
348 ByteCodeExprGen<Emitter> *Ctx;
349 /// Link to the parent scope.
350 VariableScope *Parent;
353 /// Generic scope for local variables.
354 template <class Emitter> class LocalScope : public VariableScope<Emitter> {
355 public:
356 LocalScope(ByteCodeExprGen<Emitter> *Ctx) : VariableScope<Emitter>(Ctx) {}
358 /// Emit a Destroy op for this scope.
359 ~LocalScope() override {
360 if (!Idx)
361 return;
362 this->Ctx->emitDestroy(*Idx, SourceInfo{});
365 /// Overriden to support explicit destruction.
366 void emitDestruction() override {
367 if (!Idx)
368 return;
369 this->emitDestructors();
370 this->Ctx->emitDestroy(*Idx, SourceInfo{});
371 this->Idx = std::nullopt;
374 void addLocal(const Scope::Local &Local) override {
375 if (!Idx) {
376 Idx = this->Ctx->Descriptors.size();
377 this->Ctx->Descriptors.emplace_back();
380 this->Ctx->Descriptors[*Idx].emplace_back(Local);
383 void emitDestructors() override {
384 if (!Idx)
385 return;
386 // Emit destructor calls for local variables of record
387 // type with a destructor.
388 for (Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
389 if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) {
390 this->Ctx->emitGetPtrLocal(Local.Offset, SourceInfo{});
391 this->Ctx->emitRecordDestruction(Local.Desc);
396 /// Index of the scope in the chain.
397 std::optional<unsigned> Idx;
400 /// Emits the destructors of the variables of \param OtherScope
401 /// when this scope is destroyed. Does not create a Scope in the bytecode at
402 /// all, this is just a RAII object to emit destructors.
403 template <class Emitter> class DestructorScope final {
404 public:
405 DestructorScope(LocalScope<Emitter> &OtherScope) : OtherScope(OtherScope) {}
407 ~DestructorScope() { OtherScope.emitDestructors(); }
409 private:
410 LocalScope<Emitter> &OtherScope;
413 /// Like a regular LocalScope, except that the destructors of all local
414 /// variables are automatically emitted when the AutoScope is destroyed.
415 template <class Emitter> class AutoScope : public LocalScope<Emitter> {
416 public:
417 AutoScope(ByteCodeExprGen<Emitter> *Ctx)
418 : LocalScope<Emitter>(Ctx), DS(*this) {}
420 private:
421 DestructorScope<Emitter> DS;
424 /// Scope for storage declared in a compound statement.
425 template <class Emitter> class BlockScope final : public AutoScope<Emitter> {
426 public:
427 BlockScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
429 void addExtended(const Scope::Local &Local) override {
430 // If we to this point, just add the variable as a normal local
431 // variable. It will be destroyed at the end of the block just
432 // like all others.
433 this->addLocal(Local);
437 /// Expression scope which tracks potentially lifetime extended
438 /// temporaries which are hoisted to the parent scope on exit.
439 template <class Emitter> class ExprScope final : public AutoScope<Emitter> {
440 public:
441 ExprScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
443 void addExtended(const Scope::Local &Local) override {
444 if (this->Parent)
445 this->Parent->addLocal(Local);
449 template <class Emitter> class ArrayIndexScope final {
450 public:
451 ArrayIndexScope(ByteCodeExprGen<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
452 OldArrayIndex = Ctx->ArrayIndex;
453 Ctx->ArrayIndex = Index;
456 ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }
458 private:
459 ByteCodeExprGen<Emitter> *Ctx;
460 std::optional<uint64_t> OldArrayIndex;
463 template <class Emitter> class SourceLocScope final {
464 public:
465 SourceLocScope(ByteCodeExprGen<Emitter> *Ctx, const Expr *DefaultExpr)
466 : Ctx(Ctx) {
467 assert(DefaultExpr);
468 // We only switch if the current SourceLocDefaultExpr is null.
469 if (!Ctx->SourceLocDefaultExpr) {
470 Enabled = true;
471 Ctx->SourceLocDefaultExpr = DefaultExpr;
475 ~SourceLocScope() {
476 if (Enabled)
477 Ctx->SourceLocDefaultExpr = nullptr;
480 private:
481 ByteCodeExprGen<Emitter> *Ctx;
482 bool Enabled = false;
485 } // namespace interp
486 } // namespace clang
488 #endif