Author: Timm Baeder Date: 2025-12-05T10:22:37+01:00 New Revision: 5b2eb0dcb717c7218f691e2a10f76b60ed039ecd
URL: https://github.com/llvm/llvm-project/commit/5b2eb0dcb717c7218f691e2a10f76b60ed039ecd DIFF: https://github.com/llvm/llvm-project/commit/5b2eb0dcb717c7218f691e2a10f76b60ed039ecd.diff LOG: [clang][bytecode][NFC] Add FullExpression scopes (#170705) And use them instead of the extending decl. This is close to what the current interpreter is doing. This is NFC right now but fixes a problem I encountered while looking into the expansion statement stuff. Added: Modified: clang/lib/AST/ByteCode/Compiler.cpp clang/lib/AST/ByteCode/Compiler.h Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 58e84ef70abb7..14b6bb7bf61d5 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -40,7 +40,7 @@ static std::optional<bool> getBoolValue(const Expr *E) { template <class Emitter> class DeclScope final : public LocalScope<Emitter> { public: DeclScope(Compiler<Emitter> *Ctx, const ValueDecl *VD) - : LocalScope<Emitter>(Ctx, VD), Scope(Ctx->P), + : LocalScope<Emitter>(Ctx), Scope(Ctx->P), OldInitializingDecl(Ctx->InitializingDecl) { Ctx->InitializingDecl = VD; Ctx->InitStack.push_back(InitLink::Decl(VD)); @@ -2137,8 +2137,7 @@ bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args, } UnsignedOrNone LocalIndex = - allocateLocal(std::move(Source), Arg->getType(), - /*ExtendingDecl=*/nullptr, ScopeKind::Call); + allocateLocal(std::move(Source), Arg->getType(), ScopeKind::Call); if (!LocalIndex) return false; @@ -2451,7 +2450,7 @@ bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { // and the RHS is our SubExpr. for (size_t I = 0; I != Size; ++I) { ArrayIndexScope<Emitter> IndexScope(this, I); - LocalScope<Emitter> BS(this); + LocalScope<Emitter> BS(this, ScopeKind::FullExpression); if (!this->visitArrayElemInit(I, SubExpr, SubExprT)) return false; @@ -2903,7 +2902,7 @@ bool Compiler<Emitter>::VisitCompoundAssignOperator( template <class Emitter> bool Compiler<Emitter>::VisitExprWithCleanups(const ExprWithCleanups *E) { - LocalScope<Emitter> ES(this); + LocalScope<Emitter> ES(this, ScopeKind::FullExpression); const Expr *SubExpr = E->getSubExpr(); return this->delegate(SubExpr) && ES.destroyLocals(E); @@ -2926,9 +2925,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr( // When we're initializing a global variable *or* the storage duration of // the temporary is explicitly static, create a global variable. OptPrimType SubExprT = classify(SubExpr); - bool IsStatic = E->getStorageDuration() == SD_Static; - if (IsStatic) { - + if (E->getStorageDuration() == SD_Static) { UnsignedOrNone GlobalIndex = P.createGlobal(E); if (!GlobalIndex) return false; @@ -2955,12 +2952,16 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr( return this->emitInitGlobalTempComp(TempDecl, E); } + ScopeKind VarScope = E->getStorageDuration() == SD_FullExpression + ? ScopeKind::FullExpression + : ScopeKind::Block; + // For everyhing else, use local variables. if (SubExprT) { bool IsConst = SubExpr->getType().isConstQualified(); bool IsVolatile = SubExpr->getType().isVolatileQualified(); - unsigned LocalIndex = allocateLocalPrimitive( - E, *SubExprT, IsConst, IsVolatile, E->getExtendingDecl()); + unsigned LocalIndex = + allocateLocalPrimitive(E, *SubExprT, IsConst, IsVolatile, VarScope); if (!this->VarScope->LocalsAlwaysEnabled && !this->emitEnableLocal(LocalIndex, E)) return false; @@ -2975,9 +2976,10 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr( if (!this->checkLiteralType(SubExpr)) return false; + const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments(); if (UnsignedOrNone LocalIndex = - allocateLocal(E, Inner->getType(), E->getExtendingDecl())) { + allocateLocal(E, Inner->getType(), VarScope)) { InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex)); if (!this->VarScope->LocalsAlwaysEnabled && @@ -4269,7 +4271,8 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) { // Create local variable to hold the return value. if (!E->isGLValue() && !canClassify(E->getType())) { - UnsignedOrNone LocalIndex = allocateLocal(stripDerivedToBaseCasts(E)); + UnsignedOrNone LocalIndex = allocateLocal( + stripDerivedToBaseCasts(E), QualType(), ScopeKind::FullExpression); if (!LocalIndex) return false; @@ -4626,9 +4629,11 @@ bool Compiler<Emitter>::emitConst(const APSInt &Value, const Expr *E) { } template <class Emitter> -unsigned Compiler<Emitter>::allocateLocalPrimitive( - DeclTy &&Src, PrimType Ty, bool IsConst, bool IsVolatile, - const ValueDecl *ExtendingDecl, ScopeKind SC, bool IsConstexprUnknown) { +unsigned Compiler<Emitter>::allocateLocalPrimitive(DeclTy &&Src, PrimType Ty, + bool IsConst, + bool IsVolatile, + ScopeKind SC, + bool IsConstexprUnknown) { // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g. // (int){12} in C. Consider using Expr::isTemporaryObject() instead // or isa<MaterializeTemporaryExpr>(). @@ -4639,16 +4644,12 @@ unsigned Compiler<Emitter>::allocateLocalPrimitive( Scope::Local Local = this->createLocal(D); if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) Locals.insert({VD, Local}); - if (ExtendingDecl) - VarScope->addExtended(Local, ExtendingDecl); - else - VarScope->addForScopeKind(Local, SC); + VarScope->addForScopeKind(Local, SC); return Local.Offset; } template <class Emitter> UnsignedOrNone Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty, - const ValueDecl *ExtendingDecl, ScopeKind SC, bool IsConstexprUnknown) { const ValueDecl *Key = nullptr; @@ -4676,10 +4677,7 @@ UnsignedOrNone Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty, Scope::Local Local = this->createLocal(D); if (Key) Locals.insert({Key, Local}); - if (ExtendingDecl) - VarScope->addExtended(Local, ExtendingDecl); - else - VarScope->addForScopeKind(Local, SC); + VarScope->addForScopeKind(Local, SC); return Local.Offset; } @@ -4731,7 +4729,7 @@ const Function *Compiler<Emitter>::getFunction(const FunctionDecl *FD) { template <class Emitter> bool Compiler<Emitter>::visitExpr(const Expr *E, bool DestroyToplevelScope) { - LocalScope<Emitter> RootScope(this); + LocalScope<Emitter> RootScope(this, ScopeKind::FullExpression); // If we won't destroy the toplevel scope, check for memory leaks first. if (!DestroyToplevelScope) { @@ -4825,7 +4823,7 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD, const Expr *Init, LS.destroyLocals() && this->emitCheckAllocations(VD); } - LocalScope<Emitter> VDScope(this, VD); + LocalScope<Emitter> VDScope(this); if (!this->visitVarDecl(VD, Init, /*Toplevel=*/true)) return false; @@ -4936,7 +4934,7 @@ Compiler<Emitter>::visitVarDecl(const VarDecl *VD, const Expr *Init, if (VarT) { unsigned Offset = this->allocateLocalPrimitive( VD, *VarT, VD->getType().isConstQualified(), - VD->getType().isVolatileQualified(), nullptr, ScopeKind::Block, + VD->getType().isVolatileQualified(), ScopeKind::Block, IsConstexprUnknown); if (!Init) @@ -4956,7 +4954,7 @@ Compiler<Emitter>::visitVarDecl(const VarDecl *VD, const Expr *Init, } // Local composite variables. if (UnsignedOrNone Offset = this->allocateLocal( - VD, VD->getType(), nullptr, ScopeKind::Block, IsConstexprUnknown)) { + VD, VD->getType(), ScopeKind::Block, IsConstexprUnknown)) { if (!Init) return true; @@ -5671,19 +5669,24 @@ bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) { } template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) { + LocalScope<Emitter> IfScope(this); + auto visitChildStmt = [&](const Stmt *S) -> bool { LocalScope<Emitter> SScope(this); if (!visitStmt(S)) return false; return SScope.destroyLocals(); }; - if (auto *CondInit = IS->getInit()) + + if (auto *CondInit = IS->getInit()) { if (!visitStmt(CondInit)) return false; + } - if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt()) + if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt()) { if (!visitDeclStmt(CondDecl)) return false; + } // Save ourselves compiling some code and the jumps, etc. if the condition is // stataically known to be either true or false. We could look at more cases @@ -5707,8 +5710,11 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) { if (!this->emitInv(IS)) return false; } else { + LocalScope<Emitter> CondScope(this, ScopeKind::FullExpression); if (!this->visitBool(IS->getCond())) return false; + if (!CondScope.destroyLocals()) + return false; } if (!this->maybeEmitDeferredVarInit(IS->getConditionVariable())) @@ -5736,6 +5742,9 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) { this->emitLabel(LabelEnd); } + if (!IfScope.destroyLocals()) + return false; + return true; } @@ -6333,7 +6342,7 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) { InitLinkScope<Emitter> InitScope(this, InitLink::This()); for (const auto *Init : Ctor->inits()) { // Scope needed for the initializers. - LocalScope<Emitter> Scope(this); + LocalScope<Emitter> Scope(this, ScopeKind::FullExpression); const Expr *InitExpr = Init->getInit(); if (const FieldDecl *Member = Init->getMember()) { diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 54d39bbc25952..c641af52c2811 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -104,7 +104,7 @@ struct VarCreationState { bool notCreated() const { return !S; } }; -enum class ScopeKind { Call, Block }; +enum class ScopeKind { Block, FullExpression, Call }; /// Compilation context for expressions. template <class Emitter> @@ -330,13 +330,11 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>, /// Creates a local primitive value. unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst, bool IsVolatile = false, - const ValueDecl *ExtendingDecl = nullptr, ScopeKind SC = ScopeKind::Block, bool IsConstexprUnknown = false); /// Allocates a space storing a local given its type. UnsignedOrNone allocateLocal(DeclTy &&Decl, QualType Ty = QualType(), - const ValueDecl *ExtendingDecl = nullptr, ScopeKind = ScopeKind::Block, bool IsConstexprUnknown = false); UnsignedOrNone allocateTemporary(const Expr *E); @@ -476,9 +474,8 @@ extern template class Compiler<EvalEmitter>; /// Scope chain managing the variable lifetimes. template <class Emitter> class VariableScope { public: - VariableScope(Compiler<Emitter> *Ctx, const ValueDecl *VD, - ScopeKind Kind = ScopeKind::Block) - : Ctx(Ctx), Parent(Ctx->VarScope), ValDecl(VD), Kind(Kind) { + VariableScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block) + : Ctx(Ctx), Parent(Ctx->VarScope), Kind(Kind) { if (Parent) this->LocalsAlwaysEnabled = Parent->LocalsAlwaysEnabled; Ctx->VarScope = this; @@ -489,28 +486,6 @@ template <class Emitter> class VariableScope { virtual void addLocal(Scope::Local Local) { llvm_unreachable("Shouldn't be called"); } - - void addExtended(const Scope::Local &Local, const ValueDecl *ExtendingDecl) { - // Walk up the chain of scopes until we find the one for ExtendingDecl. - // If there is no such scope, attach it to the parent one. - VariableScope *P = this; - while (P) { - if (P->ValDecl == ExtendingDecl) { - P->addLocal(Local); - return; - } - P = P->Parent; - if (!P) - break; - } - - // Use the parent scope. - if (this->Parent) - this->Parent->addLocal(Local); - else - this->addLocal(Local); - } - /// Like addExtended, but adds to the nearest scope of the given kind. void addForScopeKind(const Scope::Local &Local, ScopeKind Kind) { VariableScope *P = this; @@ -523,6 +498,7 @@ template <class Emitter> class VariableScope { if (!P) break; } + // Add to this scope. this->addLocal(Local); } @@ -542,7 +518,6 @@ template <class Emitter> class VariableScope { Compiler<Emitter> *Ctx; /// Link to the parent scope. VariableScope *Parent; - const ValueDecl *ValDecl = nullptr; ScopeKind Kind; }; @@ -550,9 +525,7 @@ template <class Emitter> class VariableScope { template <class Emitter> class LocalScope : public VariableScope<Emitter> { public: LocalScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block) - : VariableScope<Emitter>(Ctx, nullptr, Kind) {} - LocalScope(Compiler<Emitter> *Ctx, const ValueDecl *VD) - : VariableScope<Emitter>(Ctx, VD) {} + : VariableScope<Emitter>(Ctx, Kind) {} /// Emit a Destroy op for this scope. ~LocalScope() override { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
