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