1//===--- Compiler.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 "DeclOrExpr.h"
18#include "EvalEmitter.h"
19#include "Pointer.h"
20#include "PrimType.h"
21#include "Record.h"
22#include "clang/AST/Decl.h"
23#include "clang/AST/Expr.h"
24#include "clang/AST/StmtVisitor.h"
25
26namespace clang {
27class QualType;
28
29namespace interp {
30
31template <class Emitter> class LocalScope;
32template <class Emitter> class DestructorScope;
33template <class Emitter> class VariableScope;
34template <class Emitter> class DeclScope;
35template <class Emitter> class InitLinkScope;
36template <class Emitter> class InitStackScope;
37template <class Emitter> class OptionScope;
38template <class Emitter> class ArrayIndexScope;
39template <class Emitter> class SourceLocScope;
40template <class Emitter> class LoopScope;
41template <class Emitter> class LabelScope;
42template <class Emitter> class SwitchScope;
43template <class Emitter> class StmtExprScope;
44template <class Emitter> class LocOverrideScope;
45
46template <class Emitter> class Compiler;
47struct InitLink {
48public:
49 enum {
50 K_This = 0,
51 K_Field = 1,
52 K_Base = 2,
53 K_Temp = 3,
54 K_Decl = 4,
55 K_Elem = 6,
56 K_RVO = 7,
57 K_InitList = 8,
58 K_DIE = 9,
59 };
60
61 static InitLink This() { return InitLink{K_This}; }
62 static InitLink InitList() { return InitLink{K_InitList}; }
63 static InitLink RVO() { return InitLink{K_RVO}; }
64 static InitLink DIE() { return InitLink{K_DIE}; }
65 static InitLink Field(unsigned Offset) {
66 InitLink IL{K_Field};
67 IL.Offset = Offset;
68 return IL;
69 }
70 static InitLink Base(unsigned Offset) {
71 InitLink IL{K_Base};
72 IL.Offset = Offset;
73 return IL;
74 }
75 static InitLink Temp(unsigned Offset) {
76 InitLink IL{K_Temp};
77 IL.Offset = Offset;
78 return IL;
79 }
80 static InitLink Decl(const ValueDecl *D) {
81 InitLink IL{K_Decl};
82 IL.D = D;
83 return IL;
84 }
85 static InitLink Elem(unsigned Index) {
86 InitLink IL{K_Elem};
87 IL.Offset = Index;
88 return IL;
89 }
90
91 InitLink(uint8_t Kind) : Kind(Kind) {}
92 template <class Emitter>
93 bool emit(Compiler<Emitter> *Ctx, const Expr *E) const;
94
95 uint32_t Kind;
96 union {
97 unsigned Offset;
98 const ValueDecl *D;
99 };
100};
101
102/// State encapsulating if a the variable creation has been successful,
103/// unsuccessful, or no variable has been created at all.
104struct VarCreationState {
105 std::optional<bool> S = std::nullopt;
106 VarCreationState() = default;
107 VarCreationState(bool b) : S(b) {}
108 static VarCreationState NotCreated() { return VarCreationState(); }
109
110 operator bool() const { return S && *S; }
111 bool notCreated() const { return !S; }
112};
113
114enum class ScopeKind { Block, FullExpression, Call };
115
116/// Compilation context for expressions.
117template <class Emitter>
118class Compiler final : public ConstStmtVisitor<Compiler<Emitter>, bool>,
119 public Emitter {
120protected:
121 // Aliases for types defined in the emitter.
122 using LabelTy = typename Emitter::LabelTy;
123 using AddrTy = typename Emitter::AddrTy;
124 using OptLabelTy = UnsignedOrNone;
125 using CaseMap = llvm::DenseMap<const SwitchCase *, LabelTy>;
126
127 struct LabelInfo {
128 const Stmt *Name;
129 const VariableScope<Emitter> *BreakOrContinueScope;
130 OptLabelTy BreakLabel;
131 OptLabelTy ContinueLabel;
132 OptLabelTy DefaultLabel;
133 LabelInfo(const Stmt *Name, OptLabelTy BreakLabel, OptLabelTy ContinueLabel,
134 OptLabelTy DefaultLabel,
135 const VariableScope<Emitter> *BreakOrContinueScope)
136 : Name(Name), BreakOrContinueScope(BreakOrContinueScope),
137 BreakLabel(BreakLabel), ContinueLabel(ContinueLabel),
138 DefaultLabel(DefaultLabel) {}
139 };
140
141 /// Current compilation context.
142 Context &Ctx;
143 /// Program to link to.
144 Program &P;
145
146public:
147 /// Initializes the compiler and the backend emitter.
148 template <typename... Tys>
149 Compiler(Context &Ctx, Program &P, Tys &&...Args)
150 : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}
151
152 // Expressions.
153 bool VisitCastExpr(const CastExpr *E);
154 bool VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *E);
155 bool VisitIntegerLiteral(const IntegerLiteral *E);
156 bool VisitFloatingLiteral(const FloatingLiteral *E);
157 bool VisitImaginaryLiteral(const ImaginaryLiteral *E);
158 bool VisitFixedPointLiteral(const FixedPointLiteral *E);
159 bool VisitParenExpr(const ParenExpr *E);
160 bool VisitBinaryOperator(const BinaryOperator *E);
161 bool VisitLogicalBinOp(const BinaryOperator *E);
162 bool VisitPointerArithBinOp(const BinaryOperator *E);
163 bool VisitComplexBinOp(const BinaryOperator *E);
164 bool VisitVectorBinOp(const BinaryOperator *E);
165 bool VisitFixedPointBinOp(const BinaryOperator *E);
166 bool VisitFixedPointUnaryOperator(const UnaryOperator *E);
167 bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
168 bool VisitCallExpr(const CallExpr *E);
169 bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinID);
170 bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E);
171 bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E);
172 bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E);
173 bool VisitGNUNullExpr(const GNUNullExpr *E);
174 bool VisitCXXThisExpr(const CXXThisExpr *E);
175 bool VisitUnaryOperator(const UnaryOperator *E);
176 bool VisitVectorUnaryOperator(const UnaryOperator *E);
177 bool VisitComplexUnaryOperator(const UnaryOperator *E);
178 bool VisitDeclRefExpr(const DeclRefExpr *E);
179 bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E);
180 bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);
181 bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
182 bool VisitInitListExpr(const InitListExpr *E);
183 bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E);
184 bool VisitConstantExpr(const ConstantExpr *E);
185 bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
186 bool VisitMemberExpr(const MemberExpr *E);
187 bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E);
188 bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E);
189 bool VisitOpaqueValueExpr(const OpaqueValueExpr *E);
190 bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E);
191 bool VisitStringLiteral(const StringLiteral *E);
192 bool VisitObjCStringLiteral(const ObjCStringLiteral *E);
193 bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
194 bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);
195 bool VisitCharacterLiteral(const CharacterLiteral *E);
196 bool VisitCompoundAssignOperator(const CompoundAssignOperator *E);
197 bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E);
198 bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E);
199 bool VisitExprWithCleanups(const ExprWithCleanups *E);
200 bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
201 bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E);
202 bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
203 bool VisitTypeTraitExpr(const TypeTraitExpr *E);
204 bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E);
205 bool VisitLambdaExpr(const LambdaExpr *E);
206 bool VisitPredefinedExpr(const PredefinedExpr *E);
207 bool VisitCXXThrowExpr(const CXXThrowExpr *E);
208 bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E);
209 bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E);
210 bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
211 bool VisitCXXConstructExpr(const CXXConstructExpr *E);
212 bool VisitSourceLocExpr(const SourceLocExpr *E);
213 bool VisitOffsetOfExpr(const OffsetOfExpr *E);
214 bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E);
215 bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
216 bool VisitGenericSelectionExpr(const GenericSelectionExpr *E);
217 bool VisitChooseExpr(const ChooseExpr *E);
218 bool VisitEmbedExpr(const EmbedExpr *E);
219 bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E);
220 bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E);
221 bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E);
222 bool VisitCXXUuidofExpr(const CXXUuidofExpr *E);
223 bool VisitRequiresExpr(const RequiresExpr *E);
224 bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E);
225 bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E);
226 bool VisitPseudoObjectExpr(const PseudoObjectExpr *E);
227 bool VisitPackIndexingExpr(const PackIndexingExpr *E);
228 bool VisitRecoveryExpr(const RecoveryExpr *E);
229 bool VisitAddrLabelExpr(const AddrLabelExpr *E);
230 bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
231 bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
232 bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E);
233 bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E);
234 bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E);
235 bool VisitStmtExpr(const StmtExpr *E);
236 bool VisitCXXNewExpr(const CXXNewExpr *E);
237 bool VisitCXXDeleteExpr(const CXXDeleteExpr *E);
238 bool VisitBlockExpr(const BlockExpr *E);
239 bool VisitCXXTypeidExpr(const CXXTypeidExpr *E);
240 bool VisitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E);
241 bool VisitObjCArrayLiteral(const ObjCArrayLiteral *E);
242 bool VisitCXXReflectExpr(const CXXReflectExpr *E);
243 bool VisitDesignatedInitUpdateExpr(const DesignatedInitUpdateExpr *E);
244
245 // Statements.
246 bool visitCompoundStmt(const CompoundStmt *S);
247 bool visitDeclStmt(const DeclStmt *DS, bool EvaluateConditionDecl = false);
248 bool visitReturnStmt(const ReturnStmt *RS);
249 bool visitIfStmt(const IfStmt *IS);
250 bool visitWhileStmt(const WhileStmt *S);
251 bool visitDoStmt(const DoStmt *S);
252 bool visitForStmt(const ForStmt *S);
253 bool visitCXXForRangeStmt(const CXXForRangeStmt *S);
254 bool visitBreakStmt(const BreakStmt *S);
255 bool visitContinueStmt(const ContinueStmt *S);
256 bool visitSwitchStmt(const SwitchStmt *S);
257 bool visitCaseStmt(const CaseStmt *S);
258 bool visitDefaultStmt(const DefaultStmt *S);
259 bool visitAttributedStmt(const AttributedStmt *S);
260 bool visitCXXTryStmt(const CXXTryStmt *S);
261 bool
262 visitCXXExpansionStmtInstantiation(const CXXExpansionStmtInstantiation *S);
263
264 bool registerRedecl(const VarDecl *VD, const APValue &V);
265
266protected:
267 bool visitStmt(const Stmt *S);
268 bool visitExpr(const Expr *E, bool DestroyToplevelScope) override;
269 bool visitLValueExpr(const Expr *E, bool DestroyToplevelScope) override;
270 bool visitFunc(const FunctionDecl *F) override;
271
272 bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init,
273 bool ConstantContext) override;
274 bool visitDtorCall(const VarDecl *VD, const APValue &Value) override;
275 bool visitWithSubstitutions(const FunctionDecl *Callee,
276 ArrayRef<const Expr *> Args, const Expr *This,
277 const Expr *Condition) override;
278
279protected:
280 /// Emits scope cleanup instructions.
281 bool emitCleanup();
282
283 /// Returns a record type from a record or pointer type.
284 const RecordType *getRecordTy(QualType Ty);
285
286 /// Returns a record from a record or pointer type.
287 Record *getRecord(QualType Ty);
288 Record *getRecord(const RecordDecl *RD);
289
290 /// Returns a function for the given FunctionDecl.
291 /// If the function does not exist yet, it is compiled.
292 const Function *getFunction(const FunctionDecl *FD);
293
294 OptPrimType classify(const Expr *E) const { return Ctx.classify(E); }
295 OptPrimType classify(QualType Ty) const { return Ctx.classify(T: Ty); }
296 bool canClassify(const Expr *E) const { return Ctx.canClassify(E); }
297 bool canClassify(QualType T) const { return Ctx.canClassify(T); }
298
299 /// Classifies a known primitive type.
300 PrimType classifyPrim(QualType Ty) const {
301 if (auto T = classify(Ty)) {
302 return *T;
303 }
304 llvm_unreachable("not a primitive type");
305 }
306 /// Classifies a known primitive expression.
307 PrimType classifyPrim(const Expr *E) const {
308 if (auto T = classify(E))
309 return *T;
310 llvm_unreachable("not a primitive type");
311 }
312
313 /// Evaluates an expression and places the result on the stack. If the
314 /// expression is of composite type, a local variable will be created
315 /// and a pointer to said variable will be placed on the stack.
316 bool visit(const Expr *E) override;
317 /// Compiles an initializer. This is like visit() but it will never
318 /// create a variable and instead rely on a variable already having
319 /// been created. visitInitializer() then relies on a pointer to this
320 /// variable being on top of the stack.
321 bool visitInitializer(const Expr *E);
322 /// Similar, but will also pop the pointer.
323 bool visitInitializerPop(const Expr *E);
324 bool visitAsLValue(const Expr *E);
325 /// Evaluates an expression for side effects and discards the result.
326 bool discard(const Expr *E);
327 /// Just pass evaluation on to \p E. This leaves all the parsing flags
328 /// intact.
329 bool delegate(const Expr *E);
330 /// Creates and initializes a variable from the given decl.
331 VarCreationState visitVarDecl(const VarDecl *VD, const Expr *Init,
332 bool Toplevel = false);
333 VarCreationState visitDecl(const VarDecl *VD);
334 /// Visit an APValue.
335 bool visitAPValue(const APValue &Val, PrimType ValType, SourceInfo Info);
336 bool visitAPValueInitializer(const APValue &Val, SourceInfo Info, QualType T,
337 bool IsCompleteClass = true);
338 /// Visit the given decl as if we have a reference to it.
339 bool visitDeclRef(const ValueDecl *D, const Expr *E);
340
341 /// Visits an expression and converts it to a boolean.
342 bool visitBool(const Expr *E);
343
344 bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *ArrayFiller,
345 const Expr *E);
346 bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init,
347 OptPrimType InitT);
348 bool visitCallArgs(ArrayRef<const Expr *> Args, const FunctionDecl *FuncDecl,
349 bool Activate, bool IsOperatorCall);
350
351 /// Creates a local primitive value.
352 unsigned allocateLocalPrimitive(DeclOrExpr Decl, PrimType Ty, bool IsConst,
353 bool IsVolatile = false,
354 ScopeKind SC = ScopeKind::Block);
355
356 /// Allocates a space storing a local given its type.
357 UnsignedOrNone allocateLocal(DeclOrExpr Decl, QualType Ty = QualType(),
358 ScopeKind = ScopeKind::Block);
359 UnsignedOrNone allocateTemporary(const Expr *E);
360
361private:
362 friend class VariableScope<Emitter>;
363 friend class LocalScope<Emitter>;
364 friend class DestructorScope<Emitter>;
365 friend class DeclScope<Emitter>;
366 friend class InitLinkScope<Emitter>;
367 friend class InitStackScope<Emitter>;
368 friend class OptionScope<Emitter>;
369 friend class ArrayIndexScope<Emitter>;
370 friend class SourceLocScope<Emitter>;
371 friend struct InitLink;
372 friend class LoopScope<Emitter>;
373 friend class LabelScope<Emitter>;
374 friend class SwitchScope<Emitter>;
375 friend class StmtExprScope<Emitter>;
376 friend class LocOverrideScope<Emitter>;
377
378 /// Emits a zero initializer.
379 bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);
380 bool visitZeroRecordInitializer(const Record *R, const Expr *E,
381 bool IsCompleteClass = true);
382 bool visitZeroArrayInitializer(QualType T, const Expr *E);
383 bool visitAssignment(const Expr *LHS, const Expr *RHS, const Expr *E);
384
385 /// Emits an APSInt constant.
386 bool emitConst(const llvm::APSInt &Value, PrimType Ty, SourceInfo Info);
387 bool emitConst(const llvm::APInt &Value, PrimType Ty, SourceInfo Info);
388 bool emitConst(const llvm::APSInt &Value, const Expr *E);
389 bool emitConst(const llvm::APInt &Value, const Expr *E) {
390 return emitConst(Value, classifyPrim(E), E);
391 }
392
393 /// Emits an integer constant.
394 template <typename T> bool emitConst(T Value, PrimType Ty, SourceInfo Info);
395 template <typename T> bool emitConst(T Value, const Expr *E);
396 bool emitBool(bool V, const Expr *E) override {
397 return this->emitConst(V, E);
398 }
399
400 llvm::RoundingMode getRoundingMode(const Expr *E) const {
401 FPOptions FPO = E->getFPFeaturesInEffect(LO: Ctx.getLangOpts());
402
403 if (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic)
404 return llvm::RoundingMode::NearestTiesToEven;
405
406 return FPO.getRoundingMode();
407 }
408
409 uint32_t getFPOptions(const Expr *E) const {
410 return E->getFPFeaturesInEffect(LO: Ctx.getLangOpts()).getAsOpaqueInt();
411 }
412
413 bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E);
414 bool emitIntegralCast(PrimType FromT, PrimType ToT, QualType ToQT,
415 const Expr *E);
416 PrimType classifyComplexElementType(QualType T) const {
417 assert(T->isAnyComplexType());
418
419 QualType ElemType = T->getAs<ComplexType>()->getElementType();
420
421 return *this->classify(ElemType);
422 }
423
424 PrimType classifyVectorElementType(QualType T) const {
425 assert(T->isVectorType());
426 return *this->classify(T->getAs<VectorType>()->getElementType());
427 }
428
429 PrimType classifyMatrixElementType(QualType T) const {
430 assert(T->isMatrixType());
431 return *this->classify(T->getAs<MatrixType>()->getElementType());
432 }
433
434 bool emitComplexReal(const Expr *SubExpr);
435 bool emitComplexBoolCast(const Expr *E);
436 bool emitComplexComparison(const Expr *LHS, const Expr *RHS,
437 const BinaryOperator *E);
438 bool emitRecordDestructionPop(const Record *R, SourceInfo Loc);
439 bool emitDestructionPop(const Descriptor *Desc, SourceInfo Loc);
440 bool emitDummyPtr(DeclOrExpr D, const Expr *E, bool CU = false);
441 bool emitFloat(const APFloat &F, SourceInfo Info);
442 unsigned collectBaseOffset(const QualType BaseType,
443 const QualType DerivedType);
444 bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
445 bool emitBuiltinBitCast(const CastExpr *E);
446
447 bool emitHLSLAggregateSplat(PrimType SrcT, unsigned SrcOffset,
448 QualType DestType, const Expr *E);
449 bool emitVectorConversion(const Expr *Src, const Expr *E);
450
451 /// A scalar element extracted during HLSL aggregate flattening.
452 struct HLSLFlatElement {
453 unsigned LocalOffset;
454 PrimType Type;
455 };
456 unsigned countHLSLFlatElements(QualType Ty);
457 bool emitHLSLFlattenAggregate(QualType SrcType, unsigned SrcPtrOffset,
458 SmallVectorImpl<HLSLFlatElement> &Elements,
459 unsigned MaxElements, const Expr *E);
460 bool emitHLSLConstructAggregate(QualType DestType,
461 ArrayRef<HLSLFlatElement> Elements,
462 unsigned &ElemIdx, const Expr *E);
463 bool emitHLSLConstructAggregate(QualType DestType,
464 ArrayRef<HLSLFlatElement> Elements,
465 const Expr *E) {
466 unsigned ElemIdx = 0;
467 return emitHLSLConstructAggregate(DestType, Elements, ElemIdx, E);
468 }
469
470 bool compileConstructor(const CXXConstructorDecl *Ctor);
471 bool compileDestructor(const CXXDestructorDecl *Dtor);
472 bool compileUnionAssignmentOperator(const CXXMethodDecl *MD);
473
474 bool checkLiteralType(const Expr *E);
475 bool maybeEmitDeferredVarInit(const VarDecl *VD);
476
477 bool refersToUnion(const Expr *E);
478
479protected:
480 /// Variable to storage mapping.
481 llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
482
483 /// OpaqueValueExpr to location mapping.
484 llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs;
485
486 /// Current scope.
487 VariableScope<Emitter> *VarScope = nullptr;
488
489 /// Current argument index. Needed to emit ArrayInitIndexExpr.
490 std::optional<uint64_t> ArrayIndex;
491
492 /// DefaultInit- or DefaultArgExpr, needed for SourceLocExpr.
493 const Expr *SourceLocDefaultExpr = nullptr;
494
495 /// Flag indicating if return value is to be discarded.
496 bool DiscardResult = false;
497
498 bool SwitchInStmtExpr = false;
499 bool InStmtExpr = false;
500 bool ToLValue = false;
501
502 bool VariablesAreConstexprUnknown = false;
503
504 /// Flag inidicating if we're initializing an already created
505 /// variable. This is set in visitInitializer().
506 bool Initializing = false;
507 const VarDecl *InitializingDecl = nullptr;
508
509 llvm::SmallVector<InitLink> InitStack;
510 bool InitStackActive = false;
511
512 /// Type of the expression returned by the function.
513 OptPrimType ReturnType;
514
515 /// Switch case mapping.
516 CaseMap CaseLabels;
517 /// Stack of label information for loops and switch statements.
518 llvm::SmallVector<LabelInfo> LabelInfoStack;
519
520 const FunctionDecl *CompilingFunction = nullptr;
521};
522
523extern template class Compiler<ByteCodeEmitter>;
524extern template class Compiler<EvalEmitter>;
525
526} // namespace interp
527} // namespace clang
528
529#endif
530