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 "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 VariableScope; 34 template <class Emitter> class DeclScope; 35 template <class Emitter> class InitLinkScope; 36 template <class Emitter> class InitStackScope; 37 template <class Emitter> class OptionScope; 38 template <class Emitter> class ArrayIndexScope; 39 template <class Emitter> class SourceLocScope; 40 template <class Emitter> class LoopScope; 41 template <class Emitter> class LabelScope; 42 template <class Emitter> class SwitchScope; 43 template <class Emitter> class StmtExprScope; 44 45 template <class Emitter> class Compiler; 46 struct InitLink { 47 public: 48 enum { 49 K_This = 0, 50 K_Field = 1, 51 K_Temp = 2, 52 K_Decl = 3, 53 K_Elem = 5, 54 K_RVO = 6, 55 K_InitList = 7 56 }; 57 ThisInitLink58 static InitLink This() { return InitLink{K_This}; } InitListInitLink59 static InitLink InitList() { return InitLink{K_InitList}; } RVOInitLink60 static InitLink RVO() { return InitLink{K_RVO}; } FieldInitLink61 static InitLink Field(unsigned Offset) { 62 InitLink IL{K_Field}; 63 IL.Offset = Offset; 64 return IL; 65 } TempInitLink66 static InitLink Temp(unsigned Offset) { 67 InitLink IL{K_Temp}; 68 IL.Offset = Offset; 69 return IL; 70 } DeclInitLink71 static InitLink Decl(const ValueDecl *D) { 72 InitLink IL{K_Decl}; 73 IL.D = D; 74 return IL; 75 } ElemInitLink76 static InitLink Elem(unsigned Index) { 77 InitLink IL{K_Elem}; 78 IL.Offset = Index; 79 return IL; 80 } 81 InitLinkInitLink82 InitLink(uint8_t Kind) : Kind(Kind) {} 83 template <class Emitter> 84 bool emit(Compiler<Emitter> *Ctx, const Expr *E) const; 85 86 uint32_t Kind; 87 union { 88 unsigned Offset; 89 const ValueDecl *D; 90 }; 91 }; 92 93 /// State encapsulating if a the variable creation has been successful, 94 /// unsuccessful, or no variable has been created at all. 95 struct VarCreationState { 96 std::optional<bool> S = std::nullopt; 97 VarCreationState() = default; VarCreationStateVarCreationState98 VarCreationState(bool b) : S(b) {} NotCreatedVarCreationState99 static VarCreationState NotCreated() { return VarCreationState(); } 100 101 operator bool() const { return S && *S; } notCreatedVarCreationState102 bool notCreated() const { return !S; } 103 }; 104 105 enum class ScopeKind { Call, Block }; 106 107 /// Compilation context for expressions. 108 template <class Emitter> 109 class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>, 110 public Emitter { 111 protected: 112 // Aliases for types defined in the emitter. 113 using LabelTy = typename Emitter::LabelTy; 114 using AddrTy = typename Emitter::AddrTy; 115 using OptLabelTy = std::optional<LabelTy>; 116 using CaseMap = llvm::DenseMap<const SwitchCase *, LabelTy>; 117 118 /// Current compilation context. 119 Context &Ctx; 120 /// Program to link to. 121 Program &P; 122 123 public: 124 /// Initializes the compiler and the backend emitter. 125 template <typename... Tys> Compiler(Context & Ctx,Program & P,Tys &&...Args)126 Compiler(Context &Ctx, Program &P, Tys &&...Args) 127 : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {} 128 129 // Expressions. 130 bool VisitCastExpr(const CastExpr *E); 131 bool VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *E); 132 bool VisitIntegerLiteral(const IntegerLiteral *E); 133 bool VisitFloatingLiteral(const FloatingLiteral *E); 134 bool VisitImaginaryLiteral(const ImaginaryLiteral *E); 135 bool VisitFixedPointLiteral(const FixedPointLiteral *E); 136 bool VisitParenExpr(const ParenExpr *E); 137 bool VisitBinaryOperator(const BinaryOperator *E); 138 bool VisitLogicalBinOp(const BinaryOperator *E); 139 bool VisitPointerArithBinOp(const BinaryOperator *E); 140 bool VisitComplexBinOp(const BinaryOperator *E); 141 bool VisitVectorBinOp(const BinaryOperator *E); 142 bool VisitFixedPointBinOp(const BinaryOperator *E); 143 bool VisitFixedPointUnaryOperator(const UnaryOperator *E); 144 bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E); 145 bool VisitCallExpr(const CallExpr *E); 146 bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinID); 147 bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E); 148 bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E); 149 bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E); 150 bool VisitGNUNullExpr(const GNUNullExpr *E); 151 bool VisitCXXThisExpr(const CXXThisExpr *E); 152 bool VisitUnaryOperator(const UnaryOperator *E); 153 bool VisitVectorUnaryOperator(const UnaryOperator *E); 154 bool VisitComplexUnaryOperator(const UnaryOperator *E); 155 bool VisitDeclRefExpr(const DeclRefExpr *E); 156 bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E); 157 bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E); 158 bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); 159 bool VisitInitListExpr(const InitListExpr *E); 160 bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E); 161 bool VisitConstantExpr(const ConstantExpr *E); 162 bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); 163 bool VisitMemberExpr(const MemberExpr *E); 164 bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E); 165 bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E); 166 bool VisitOpaqueValueExpr(const OpaqueValueExpr *E); 167 bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E); 168 bool VisitStringLiteral(const StringLiteral *E); 169 bool VisitObjCStringLiteral(const ObjCStringLiteral *E); 170 bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E); 171 bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E); 172 bool VisitCharacterLiteral(const CharacterLiteral *E); 173 bool VisitCompoundAssignOperator(const CompoundAssignOperator *E); 174 bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E); 175 bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E); 176 bool VisitExprWithCleanups(const ExprWithCleanups *E); 177 bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); 178 bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E); 179 bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); 180 bool VisitTypeTraitExpr(const TypeTraitExpr *E); 181 bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E); 182 bool VisitLambdaExpr(const LambdaExpr *E); 183 bool VisitPredefinedExpr(const PredefinedExpr *E); 184 bool VisitCXXThrowExpr(const CXXThrowExpr *E); 185 bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E); 186 bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E); 187 bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); 188 bool VisitCXXConstructExpr(const CXXConstructExpr *E); 189 bool VisitSourceLocExpr(const SourceLocExpr *E); 190 bool VisitOffsetOfExpr(const OffsetOfExpr *E); 191 bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E); 192 bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); 193 bool VisitGenericSelectionExpr(const GenericSelectionExpr *E); 194 bool VisitChooseExpr(const ChooseExpr *E); 195 bool VisitEmbedExpr(const EmbedExpr *E); 196 bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E); 197 bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); 198 bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E); 199 bool VisitCXXUuidofExpr(const CXXUuidofExpr *E); 200 bool VisitRequiresExpr(const RequiresExpr *E); 201 bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E); 202 bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E); 203 bool VisitPseudoObjectExpr(const PseudoObjectExpr *E); 204 bool VisitPackIndexingExpr(const PackIndexingExpr *E); 205 bool VisitRecoveryExpr(const RecoveryExpr *E); 206 bool VisitAddrLabelExpr(const AddrLabelExpr *E); 207 bool VisitConvertVectorExpr(const ConvertVectorExpr *E); 208 bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E); 209 bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E); 210 bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E); 211 bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); 212 bool VisitStmtExpr(const StmtExpr *E); 213 bool VisitCXXNewExpr(const CXXNewExpr *E); 214 bool VisitCXXDeleteExpr(const CXXDeleteExpr *E); 215 bool VisitBlockExpr(const BlockExpr *E); 216 bool VisitCXXTypeidExpr(const CXXTypeidExpr *E); 217 218 // Statements. 219 bool visitCompoundStmt(const CompoundStmt *S); 220 bool visitDeclStmt(const DeclStmt *DS, bool EvaluateConditionDecl = false); 221 bool visitReturnStmt(const ReturnStmt *RS); 222 bool visitIfStmt(const IfStmt *IS); 223 bool visitWhileStmt(const WhileStmt *S); 224 bool visitDoStmt(const DoStmt *S); 225 bool visitForStmt(const ForStmt *S); 226 bool visitCXXForRangeStmt(const CXXForRangeStmt *S); 227 bool visitBreakStmt(const BreakStmt *S); 228 bool visitContinueStmt(const ContinueStmt *S); 229 bool visitSwitchStmt(const SwitchStmt *S); 230 bool visitCaseStmt(const CaseStmt *S); 231 bool visitDefaultStmt(const DefaultStmt *S); 232 bool visitAttributedStmt(const AttributedStmt *S); 233 bool visitCXXTryStmt(const CXXTryStmt *S); 234 235 protected: 236 bool visitStmt(const Stmt *S); 237 bool visitExpr(const Expr *E, bool DestroyToplevelScope) override; 238 bool visitFunc(const FunctionDecl *F) override; 239 240 bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) override; 241 242 protected: 243 /// Emits scope cleanup instructions. 244 void emitCleanup(); 245 246 /// Returns a record type from a record or pointer type. 247 const RecordType *getRecordTy(QualType Ty); 248 249 /// Returns a record from a record or pointer type. 250 Record *getRecord(QualType Ty); 251 Record *getRecord(const RecordDecl *RD); 252 253 /// Returns a function for the given FunctionDecl. 254 /// If the function does not exist yet, it is compiled. 255 const Function *getFunction(const FunctionDecl *FD); 256 classify(const Expr * E)257 std::optional<PrimType> classify(const Expr *E) const { 258 return Ctx.classify(E); 259 } classify(QualType Ty)260 std::optional<PrimType> classify(QualType Ty) const { 261 return Ctx.classify(Ty); 262 } 263 264 /// Classifies a known primitive type. classifyPrim(QualType Ty)265 PrimType classifyPrim(QualType Ty) const { 266 if (auto T = classify(Ty)) { 267 return *T; 268 } 269 llvm_unreachable("not a primitive type"); 270 } 271 /// Classifies a known primitive expression. classifyPrim(const Expr * E)272 PrimType classifyPrim(const Expr *E) const { 273 if (auto T = classify(E)) 274 return *T; 275 llvm_unreachable("not a primitive type"); 276 } 277 278 /// Evaluates an expression and places the result on the stack. If the 279 /// expression is of composite type, a local variable will be created 280 /// and a pointer to said variable will be placed on the stack. 281 bool visit(const Expr *E) override; 282 /// Compiles an initializer. This is like visit() but it will never 283 /// create a variable and instead rely on a variable already having 284 /// been created. visitInitializer() then relies on a pointer to this 285 /// variable being on top of the stack. 286 bool visitInitializer(const Expr *E); 287 /// Evaluates an expression for side effects and discards the result. 288 bool discard(const Expr *E); 289 /// Just pass evaluation on to \p E. This leaves all the parsing flags 290 /// intact. 291 bool delegate(const Expr *E); 292 /// Creates and initializes a variable from the given decl. 293 VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false, 294 bool IsConstexprUnknown = false); 295 VarCreationState visitDecl(const VarDecl *VD, 296 bool IsConstexprUnknown = false); 297 /// Visit an APValue. 298 bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E); 299 bool visitAPValueInitializer(const APValue &Val, const Expr *E, QualType T); 300 /// Visit the given decl as if we have a reference to it. 301 bool visitDeclRef(const ValueDecl *D, const Expr *E); 302 303 /// Visits an expression and converts it to a boolean. 304 bool visitBool(const Expr *E); 305 306 bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *ArrayFiller, 307 const Expr *E); 308 bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init, 309 std::optional<PrimType> InitT); 310 bool visitCallArgs(ArrayRef<const Expr *> Args, const FunctionDecl *FuncDecl); 311 312 /// Creates a local primitive value. 313 unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst, 314 const ValueDecl *ExtendingDecl = nullptr, 315 ScopeKind SC = ScopeKind::Block, 316 bool IsConstexprUnknown = false); 317 318 /// Allocates a space storing a local given its type. 319 std::optional<unsigned> 320 allocateLocal(DeclTy &&Decl, QualType Ty = QualType(), 321 const ValueDecl *ExtendingDecl = nullptr, 322 ScopeKind = ScopeKind::Block, bool IsConstexprUnknown = false); 323 std::optional<unsigned> allocateTemporary(const Expr *E); 324 325 private: 326 friend class VariableScope<Emitter>; 327 friend class LocalScope<Emitter>; 328 friend class DestructorScope<Emitter>; 329 friend class DeclScope<Emitter>; 330 friend class InitLinkScope<Emitter>; 331 friend class InitStackScope<Emitter>; 332 friend class OptionScope<Emitter>; 333 friend class ArrayIndexScope<Emitter>; 334 friend class SourceLocScope<Emitter>; 335 friend struct InitLink; 336 friend class LoopScope<Emitter>; 337 friend class LabelScope<Emitter>; 338 friend class SwitchScope<Emitter>; 339 friend class StmtExprScope<Emitter>; 340 341 /// Emits a zero initializer. 342 bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E); 343 bool visitZeroRecordInitializer(const Record *R, const Expr *E); 344 bool visitZeroArrayInitializer(QualType T, const Expr *E); 345 346 /// Emits an APSInt constant. 347 bool emitConst(const llvm::APSInt &Value, PrimType Ty, const Expr *E); 348 bool emitConst(const llvm::APSInt &Value, const Expr *E); emitConst(const llvm::APInt & Value,const Expr * E)349 bool emitConst(const llvm::APInt &Value, const Expr *E) { 350 return emitConst(static_cast<llvm::APSInt>(Value), E); 351 } 352 353 /// Emits an integer constant. 354 template <typename T> bool emitConst(T Value, PrimType Ty, const Expr *E); 355 template <typename T> bool emitConst(T Value, const Expr *E); emitBool(bool V,const Expr * E)356 bool emitBool(bool V, const Expr *E) override { 357 return this->emitConst(V, E); 358 } 359 getRoundingMode(const Expr * E)360 llvm::RoundingMode getRoundingMode(const Expr *E) const { 361 FPOptions FPO = E->getFPFeaturesInEffect(Ctx.getLangOpts()); 362 363 if (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) 364 return llvm::RoundingMode::NearestTiesToEven; 365 366 return FPO.getRoundingMode(); 367 } 368 getFPOptions(const Expr * E)369 uint32_t getFPOptions(const Expr *E) const { 370 return E->getFPFeaturesInEffect(Ctx.getLangOpts()).getAsOpaqueInt(); 371 } 372 373 bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E); classifyComplexElementType(QualType T)374 PrimType classifyComplexElementType(QualType T) const { 375 assert(T->isAnyComplexType()); 376 377 QualType ElemType = T->getAs<ComplexType>()->getElementType(); 378 379 return *this->classify(ElemType); 380 } 381 classifyVectorElementType(QualType T)382 PrimType classifyVectorElementType(QualType T) const { 383 assert(T->isVectorType()); 384 return *this->classify(T->getAs<VectorType>()->getElementType()); 385 } 386 387 bool emitComplexReal(const Expr *SubExpr); 388 bool emitComplexBoolCast(const Expr *E); 389 bool emitComplexComparison(const Expr *LHS, const Expr *RHS, 390 const BinaryOperator *E); 391 bool emitRecordDestruction(const Record *R, SourceInfo Loc); 392 bool emitDestruction(const Descriptor *Desc, SourceInfo Loc); 393 bool emitDummyPtr(const DeclTy &D, const Expr *E); 394 bool emitFloat(const APFloat &F, const Expr *E); 395 unsigned collectBaseOffset(const QualType BaseType, 396 const QualType DerivedType); 397 bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD); 398 bool emitBuiltinBitCast(const CastExpr *E); 399 bool compileConstructor(const CXXConstructorDecl *Ctor); 400 bool compileDestructor(const CXXDestructorDecl *Dtor); 401 bool compileUnionAssignmentOperator(const CXXMethodDecl *MD); 402 403 bool checkLiteralType(const Expr *E); 404 bool maybeEmitDeferredVarInit(const VarDecl *VD); 405 406 protected: 407 /// Variable to storage mapping. 408 llvm::DenseMap<const ValueDecl *, Scope::Local> Locals; 409 410 /// OpaqueValueExpr to location mapping. 411 llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs; 412 413 /// Current scope. 414 VariableScope<Emitter> *VarScope = nullptr; 415 416 /// Current argument index. Needed to emit ArrayInitIndexExpr. 417 std::optional<uint64_t> ArrayIndex; 418 419 /// DefaultInit- or DefaultArgExpr, needed for SourceLocExpr. 420 const Expr *SourceLocDefaultExpr = nullptr; 421 422 /// Flag indicating if return value is to be discarded. 423 bool DiscardResult = false; 424 425 bool InStmtExpr = false; 426 427 /// Flag inidicating if we're initializing an already created 428 /// variable. This is set in visitInitializer(). 429 bool Initializing = false; 430 const ValueDecl *InitializingDecl = nullptr; 431 432 llvm::SmallVector<InitLink> InitStack; 433 bool InitStackActive = false; 434 435 /// Type of the expression returned by the function. 436 std::optional<PrimType> ReturnType; 437 438 /// Switch case mapping. 439 CaseMap CaseLabels; 440 441 /// Scope to cleanup until when we see a break statement. 442 VariableScope<Emitter> *BreakVarScope = nullptr; 443 /// Point to break to. 444 OptLabelTy BreakLabel; 445 /// Scope to cleanup until when we see a continue statement. 446 VariableScope<Emitter> *ContinueVarScope = nullptr; 447 /// Point to continue to. 448 OptLabelTy ContinueLabel; 449 /// Default case label. 450 OptLabelTy DefaultLabel; 451 452 const FunctionDecl *CompilingFunction = nullptr; 453 }; 454 455 extern template class Compiler<ByteCodeEmitter>; 456 extern template class Compiler<EvalEmitter>; 457 458 /// Scope chain managing the variable lifetimes. 459 template <class Emitter> class VariableScope { 460 public: 461 VariableScope(Compiler<Emitter> *Ctx, const ValueDecl *VD, 462 ScopeKind Kind = ScopeKind::Block) Ctx(Ctx)463 : Ctx(Ctx), Parent(Ctx->VarScope), ValDecl(VD), Kind(Kind) { 464 Ctx->VarScope = this; 465 } 466 ~VariableScope()467 virtual ~VariableScope() { Ctx->VarScope = this->Parent; } 468 addLocal(const Scope::Local & Local)469 virtual void addLocal(const Scope::Local &Local) { 470 llvm_unreachable("Shouldn't be called"); 471 } 472 addExtended(const Scope::Local & Local,const ValueDecl * ExtendingDecl)473 void addExtended(const Scope::Local &Local, const ValueDecl *ExtendingDecl) { 474 // Walk up the chain of scopes until we find the one for ExtendingDecl. 475 // If there is no such scope, attach it to the parent one. 476 VariableScope *P = this; 477 while (P) { 478 if (P->ValDecl == ExtendingDecl) { 479 P->addLocal(Local); 480 return; 481 } 482 P = P->Parent; 483 if (!P) 484 break; 485 } 486 487 // Use the parent scope. 488 if (this->Parent) 489 this->Parent->addLocal(Local); 490 else 491 this->addLocal(Local); 492 } 493 494 /// Like addExtended, but adds to the nearest scope of the given kind. addForScopeKind(const Scope::Local & Local,ScopeKind Kind)495 void addForScopeKind(const Scope::Local &Local, ScopeKind Kind) { 496 VariableScope *P = this; 497 while (P) { 498 if (P->Kind == Kind) { 499 P->addLocal(Local); 500 return; 501 } 502 P = P->Parent; 503 if (!P) 504 break; 505 } 506 507 // Add to this scope. 508 this->addLocal(Local); 509 } 510 emitDestruction()511 virtual void emitDestruction() {} 512 virtual bool emitDestructors(const Expr *E = nullptr) { return true; } 513 virtual bool destroyLocals(const Expr *E = nullptr) { return true; } getParent()514 VariableScope *getParent() const { return Parent; } getKind()515 ScopeKind getKind() const { return Kind; } 516 517 protected: 518 /// Compiler instance. 519 Compiler<Emitter> *Ctx; 520 /// Link to the parent scope. 521 VariableScope *Parent; 522 const ValueDecl *ValDecl = nullptr; 523 ScopeKind Kind; 524 }; 525 526 /// Generic scope for local variables. 527 template <class Emitter> class LocalScope : public VariableScope<Emitter> { 528 public: 529 LocalScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block) 530 : VariableScope<Emitter>(Ctx, nullptr, Kind) {} LocalScope(Compiler<Emitter> * Ctx,const ValueDecl * VD)531 LocalScope(Compiler<Emitter> *Ctx, const ValueDecl *VD) 532 : VariableScope<Emitter>(Ctx, VD) {} 533 534 /// Emit a Destroy op for this scope. ~LocalScope()535 ~LocalScope() override { 536 if (!Idx) 537 return; 538 this->Ctx->emitDestroy(*Idx, SourceInfo{}); 539 removeStoredOpaqueValues(); 540 } 541 542 /// Overriden to support explicit destruction. emitDestruction()543 void emitDestruction() override { 544 if (!Idx) 545 return; 546 547 this->emitDestructors(); 548 this->Ctx->emitDestroy(*Idx, SourceInfo{}); 549 } 550 551 /// Explicit destruction of local variables. 552 bool destroyLocals(const Expr *E = nullptr) override { 553 if (!Idx) 554 return true; 555 556 // NB: We are *not* resetting Idx here as to allow multiple 557 // calls to destroyLocals(). 558 bool Success = this->emitDestructors(E); 559 this->Ctx->emitDestroy(*Idx, E); 560 return Success; 561 } 562 addLocal(const Scope::Local & Local)563 void addLocal(const Scope::Local &Local) override { 564 if (!Idx) { 565 Idx = this->Ctx->Descriptors.size(); 566 this->Ctx->Descriptors.emplace_back(); 567 this->Ctx->emitInitScope(*Idx, {}); 568 } 569 570 this->Ctx->Descriptors[*Idx].emplace_back(Local); 571 } 572 573 bool emitDestructors(const Expr *E = nullptr) override { 574 if (!Idx) 575 return true; 576 // Emit destructor calls for local variables of record 577 // type with a destructor. 578 for (Scope::Local &Local : llvm::reverse(this->Ctx->Descriptors[*Idx])) { 579 if (Local.Desc->hasTrivialDtor()) 580 continue; 581 if (!this->Ctx->emitGetPtrLocal(Local.Offset, E)) 582 return false; 583 584 if (!this->Ctx->emitDestruction(Local.Desc, Local.Desc->getLoc())) 585 return false; 586 587 if (!this->Ctx->emitPopPtr(E)) 588 return false; 589 removeIfStoredOpaqueValue(Local); 590 } 591 return true; 592 } 593 removeStoredOpaqueValues()594 void removeStoredOpaqueValues() { 595 if (!Idx) 596 return; 597 598 for (const Scope::Local &Local : this->Ctx->Descriptors[*Idx]) { 599 removeIfStoredOpaqueValue(Local); 600 } 601 } 602 removeIfStoredOpaqueValue(const Scope::Local & Local)603 void removeIfStoredOpaqueValue(const Scope::Local &Local) { 604 if (const auto *OVE = 605 llvm::dyn_cast_if_present<OpaqueValueExpr>(Local.Desc->asExpr())) { 606 if (auto It = this->Ctx->OpaqueExprs.find(OVE); 607 It != this->Ctx->OpaqueExprs.end()) 608 this->Ctx->OpaqueExprs.erase(It); 609 }; 610 } 611 612 /// Index of the scope in the chain. 613 std::optional<unsigned> Idx; 614 }; 615 616 /// Scope for storage declared in a compound statement. 617 // FIXME: Remove? 618 template <class Emitter> class BlockScope final : public LocalScope<Emitter> { 619 public: 620 BlockScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block) 621 : LocalScope<Emitter>(Ctx, Kind) {} 622 }; 623 624 template <class Emitter> class ArrayIndexScope final { 625 public: ArrayIndexScope(Compiler<Emitter> * Ctx,uint64_t Index)626 ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) { 627 OldArrayIndex = Ctx->ArrayIndex; 628 Ctx->ArrayIndex = Index; 629 } 630 ~ArrayIndexScope()631 ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; } 632 633 private: 634 Compiler<Emitter> *Ctx; 635 std::optional<uint64_t> OldArrayIndex; 636 }; 637 638 template <class Emitter> class SourceLocScope final { 639 public: SourceLocScope(Compiler<Emitter> * Ctx,const Expr * DefaultExpr)640 SourceLocScope(Compiler<Emitter> *Ctx, const Expr *DefaultExpr) : Ctx(Ctx) { 641 assert(DefaultExpr); 642 // We only switch if the current SourceLocDefaultExpr is null. 643 if (!Ctx->SourceLocDefaultExpr) { 644 Enabled = true; 645 Ctx->SourceLocDefaultExpr = DefaultExpr; 646 } 647 } 648 ~SourceLocScope()649 ~SourceLocScope() { 650 if (Enabled) 651 Ctx->SourceLocDefaultExpr = nullptr; 652 } 653 654 private: 655 Compiler<Emitter> *Ctx; 656 bool Enabled = false; 657 }; 658 659 template <class Emitter> class InitLinkScope final { 660 public: InitLinkScope(Compiler<Emitter> * Ctx,InitLink && Link)661 InitLinkScope(Compiler<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) { 662 Ctx->InitStack.push_back(std::move(Link)); 663 } 664 ~InitLinkScope()665 ~InitLinkScope() { this->Ctx->InitStack.pop_back(); } 666 667 private: 668 Compiler<Emitter> *Ctx; 669 }; 670 671 template <class Emitter> class InitStackScope final { 672 public: InitStackScope(Compiler<Emitter> * Ctx,bool Active)673 InitStackScope(Compiler<Emitter> *Ctx, bool Active) 674 : Ctx(Ctx), OldValue(Ctx->InitStackActive) { 675 Ctx->InitStackActive = Active; 676 } 677 ~InitStackScope()678 ~InitStackScope() { this->Ctx->InitStackActive = OldValue; } 679 680 private: 681 Compiler<Emitter> *Ctx; 682 bool OldValue; 683 }; 684 685 } // namespace interp 686 } // namespace clang 687 688 #endif 689