[clang] [clang][bytecode][NFC] Move Scope classes to source file (PR #207647)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 5 20:58:59 PDT 2026
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/207647
None
>From 6574bf6b4548bcb616ff9762bfab17f1cc79d551 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 6 Jul 2026 05:24:17 +0200
Subject: [PATCH] asdf
---
clang/lib/AST/ByteCode/Compiler.cpp | 234 ++++++++++++++++++++++++++++
clang/lib/AST/ByteCode/Compiler.h | 234 ----------------------------
2 files changed, 234 insertions(+), 234 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 090bbf4596413..662944a9bd2ca 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -37,6 +37,240 @@ static std::optional<bool> getBoolValue(const Expr *E) {
return std::nullopt;
}
+/// Scope chain managing the variable lifetimes.
+template <class Emitter> class VariableScope {
+public:
+ VariableScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block)
+ : Ctx(Ctx), Parent(Ctx->VarScope), Kind(Kind) {
+ if (Parent)
+ this->LocalsAlwaysEnabled = Parent->LocalsAlwaysEnabled;
+ Ctx->VarScope = this;
+ }
+
+ virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
+
+ virtual void addLocal(Scope::Local Local) {
+ llvm_unreachable("Shouldn't be called");
+ }
+ /// Like addExtended, but adds to the nearest scope of the given kind.
+ void addForScopeKind(const Scope::Local &Local, ScopeKind Kind) {
+ VariableScope *P = this;
+ while (P) {
+ // We found the right scope kind.
+ if (P->Kind == Kind) {
+ P->addLocal(Local);
+ return;
+ }
+ // If we reached the root scope and we're looking for a Block scope,
+ // attach it to the root instead of the current scope.
+ if (!P->Parent && Kind == ScopeKind::Block) {
+ P->addLocal(Local);
+ return;
+ }
+ P = P->Parent;
+ if (!P)
+ break;
+ }
+
+ // Add to this scope.
+ this->addLocal(Local);
+ }
+
+ virtual bool emitDestructors(const Expr *E = nullptr) { return true; }
+ virtual bool destroyLocals(const Expr *E = nullptr) { return true; }
+ virtual void forceInit() {}
+ VariableScope *getParent() const { return Parent; }
+ ScopeKind getKind() const { return Kind; }
+
+ /// Whether locals added to this scope are enabled by default.
+ /// This is almost always true, except for the two branches
+ /// of a conditional operator.
+ bool LocalsAlwaysEnabled = true;
+
+protected:
+ /// Compiler instance.
+ Compiler<Emitter> *Ctx;
+ /// Link to the parent scope.
+ VariableScope *Parent;
+ ScopeKind Kind;
+};
+
+/// Generic scope for local variables.
+template <class Emitter> class LocalScope : public VariableScope<Emitter> {
+public:
+ LocalScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block)
+ : VariableScope<Emitter>(Ctx, Kind) {}
+
+ /// Emit a Destroy op for this scope.
+ ~LocalScope() override {
+ if (!Idx)
+ return;
+ this->Ctx->emitDestroy(*Idx, SourceInfo{});
+ removeStoredOpaqueValues();
+ }
+ /// Explicit destruction of local variables.
+ bool destroyLocals(const Expr *E = nullptr) override {
+ if (!Idx)
+ return true;
+
+ // NB: We are *not* resetting Idx here as to allow multiple
+ // calls to destroyLocals().
+ bool Success = this->emitDestructors(E);
+ this->Ctx->emitDestroy(*Idx, E);
+ return Success;
+ }
+
+ void addLocal(Scope::Local Local) override {
+ if (!Idx) {
+ Idx = static_cast<unsigned>(this->Ctx->Descriptors.size());
+ this->Ctx->Descriptors.emplace_back();
+ this->Ctx->emitInitScope(*Idx, {});
+ }
+
+ Local.EnabledByDefault = this->LocalsAlwaysEnabled;
+ this->Ctx->Descriptors[*Idx].emplace_back(Local);
+ }
+
+ /// Force-initialize this scope. Usually, scopes are lazily initialized when
+ /// the first local variable is created, but in scenarios with conditonal
+ /// operators, we need to ensure scope is initialized just in case one of the
+ /// arms will create a local and the other won't. In such a case, the
+ /// InitScope() op would be part of the arm that created the local.
+ void forceInit() override {
+ if (!Idx) {
+ Idx = static_cast<unsigned>(this->Ctx->Descriptors.size());
+ this->Ctx->Descriptors.emplace_back();
+ this->Ctx->emitInitScope(*Idx, {});
+ }
+ }
+
+ bool emitDestructors(const Expr *E = nullptr) override {
+ if (!Idx)
+ return true;
+
+ // Emit destructor calls for local variables of record
+ // type with a destructor.
+ for (Scope::Local &Local : llvm::reverse(this->Ctx->Descriptors[*Idx])) {
+ if (Local.Desc->hasTrivialDtor())
+ continue;
+
+ if (!Local.EnabledByDefault) {
+ typename Emitter::LabelTy EndLabel = this->Ctx->getLabel();
+ if (!this->Ctx->emitGetLocalEnabled(Local.Offset, E))
+ return false;
+ if (!this->Ctx->jumpFalse(EndLabel, E))
+ return false;
+
+ if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
+ return false;
+
+ if (!this->Ctx->emitDestructionPop(Local.Desc, Local.Desc->getLoc()))
+ return false;
+
+ this->Ctx->fallthrough(EndLabel);
+ this->Ctx->emitLabel(EndLabel);
+ } else {
+ if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
+ return false;
+ if (!this->Ctx->emitDestructionPop(Local.Desc, Local.Desc->getLoc()))
+ return false;
+ }
+
+ removeIfStoredOpaqueValue(Local);
+ }
+ return true;
+ }
+
+ void removeStoredOpaqueValues() {
+ if (!Idx)
+ return;
+
+ for (const Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
+ removeIfStoredOpaqueValue(Local);
+ }
+ }
+
+ void removeIfStoredOpaqueValue(const Scope::Local &Local) {
+ if (const auto *OVE =
+ llvm::dyn_cast_if_present<OpaqueValueExpr>(Local.Desc->asExpr())) {
+ if (auto It = this->Ctx->OpaqueExprs.find(OVE);
+ It != this->Ctx->OpaqueExprs.end())
+ this->Ctx->OpaqueExprs.erase(It);
+ };
+ }
+
+ /// Index of the scope in the chain.
+ UnsignedOrNone Idx = std::nullopt;
+};
+
+template <class Emitter> class ArrayIndexScope final {
+public:
+ ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
+ OldArrayIndex = Ctx->ArrayIndex;
+ Ctx->ArrayIndex = Index;
+ }
+
+ ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }
+
+private:
+ Compiler<Emitter> *Ctx;
+ std::optional<uint64_t> OldArrayIndex;
+};
+
+template <class Emitter> class SourceLocScope final {
+public:
+ SourceLocScope(Compiler<Emitter> *Ctx, const Expr *DefaultExpr) : Ctx(Ctx) {
+ assert(DefaultExpr);
+ // We only switch if the current SourceLocDefaultExpr is null.
+ if (!Ctx->SourceLocDefaultExpr) {
+ Enabled = true;
+ Ctx->SourceLocDefaultExpr = DefaultExpr;
+ }
+ }
+
+ ~SourceLocScope() {
+ if (Enabled)
+ Ctx->SourceLocDefaultExpr = nullptr;
+ }
+
+private:
+ Compiler<Emitter> *Ctx;
+ bool Enabled = false;
+};
+
+template <class Emitter> class InitLinkScope final {
+public:
+ InitLinkScope(Compiler<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) {
+ Ctx->InitStack.push_back(std::move(Link));
+ }
+
+ ~InitLinkScope() { this->Ctx->InitStack.pop_back(); }
+
+public:
+ Compiler<Emitter> *Ctx;
+};
+
+template <class Emitter> class InitStackScope final {
+public:
+ InitStackScope(Compiler<Emitter> *Ctx, bool Active)
+ : Ctx(Ctx), OldValue(Ctx->InitStackActive), Active(Active) {
+ Ctx->InitStackActive = Active;
+ if (Active)
+ Ctx->InitStack.push_back(InitLink::DIE());
+ }
+
+ ~InitStackScope() {
+ this->Ctx->InitStackActive = OldValue;
+ if (Active)
+ Ctx->InitStack.pop_back();
+ }
+
+private:
+ Compiler<Emitter> *Ctx;
+ bool OldValue;
+ bool Active;
+};
+
/// Scope used to handle temporaries in toplevel variable declarations.
template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
public:
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 0a2e75887711d..a93fdd20b712f 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -509,240 +509,6 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
extern template class Compiler<ByteCodeEmitter>;
extern template class Compiler<EvalEmitter>;
-/// Scope chain managing the variable lifetimes.
-template <class Emitter> class VariableScope {
-public:
- VariableScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block)
- : Ctx(Ctx), Parent(Ctx->VarScope), Kind(Kind) {
- if (Parent)
- this->LocalsAlwaysEnabled = Parent->LocalsAlwaysEnabled;
- Ctx->VarScope = this;
- }
-
- virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
-
- virtual void addLocal(Scope::Local Local) {
- llvm_unreachable("Shouldn't be called");
- }
- /// Like addExtended, but adds to the nearest scope of the given kind.
- void addForScopeKind(const Scope::Local &Local, ScopeKind Kind) {
- VariableScope *P = this;
- while (P) {
- // We found the right scope kind.
- if (P->Kind == Kind) {
- P->addLocal(Local);
- return;
- }
- // If we reached the root scope and we're looking for a Block scope,
- // attach it to the root instead of the current scope.
- if (!P->Parent && Kind == ScopeKind::Block) {
- P->addLocal(Local);
- return;
- }
- P = P->Parent;
- if (!P)
- break;
- }
-
- // Add to this scope.
- this->addLocal(Local);
- }
-
- virtual bool emitDestructors(const Expr *E = nullptr) { return true; }
- virtual bool destroyLocals(const Expr *E = nullptr) { return true; }
- virtual void forceInit() {}
- VariableScope *getParent() const { return Parent; }
- ScopeKind getKind() const { return Kind; }
-
- /// Whether locals added to this scope are enabled by default.
- /// This is almost always true, except for the two branches
- /// of a conditional operator.
- bool LocalsAlwaysEnabled = true;
-
-protected:
- /// Compiler instance.
- Compiler<Emitter> *Ctx;
- /// Link to the parent scope.
- VariableScope *Parent;
- ScopeKind Kind;
-};
-
-/// Generic scope for local variables.
-template <class Emitter> class LocalScope : public VariableScope<Emitter> {
-public:
- LocalScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block)
- : VariableScope<Emitter>(Ctx, Kind) {}
-
- /// Emit a Destroy op for this scope.
- ~LocalScope() override {
- if (!Idx)
- return;
- this->Ctx->emitDestroy(*Idx, SourceInfo{});
- removeStoredOpaqueValues();
- }
- /// Explicit destruction of local variables.
- bool destroyLocals(const Expr *E = nullptr) override {
- if (!Idx)
- return true;
-
- // NB: We are *not* resetting Idx here as to allow multiple
- // calls to destroyLocals().
- bool Success = this->emitDestructors(E);
- this->Ctx->emitDestroy(*Idx, E);
- return Success;
- }
-
- void addLocal(Scope::Local Local) override {
- if (!Idx) {
- Idx = static_cast<unsigned>(this->Ctx->Descriptors.size());
- this->Ctx->Descriptors.emplace_back();
- this->Ctx->emitInitScope(*Idx, {});
- }
-
- Local.EnabledByDefault = this->LocalsAlwaysEnabled;
- this->Ctx->Descriptors[*Idx].emplace_back(Local);
- }
-
- /// Force-initialize this scope. Usually, scopes are lazily initialized when
- /// the first local variable is created, but in scenarios with conditonal
- /// operators, we need to ensure scope is initialized just in case one of the
- /// arms will create a local and the other won't. In such a case, the
- /// InitScope() op would be part of the arm that created the local.
- void forceInit() override {
- if (!Idx) {
- Idx = static_cast<unsigned>(this->Ctx->Descriptors.size());
- this->Ctx->Descriptors.emplace_back();
- this->Ctx->emitInitScope(*Idx, {});
- }
- }
-
- bool emitDestructors(const Expr *E = nullptr) override {
- if (!Idx)
- return true;
-
- // Emit destructor calls for local variables of record
- // type with a destructor.
- for (Scope::Local &Local : llvm::reverse(this->Ctx->Descriptors[*Idx])) {
- if (Local.Desc->hasTrivialDtor())
- continue;
-
- if (!Local.EnabledByDefault) {
- typename Emitter::LabelTy EndLabel = this->Ctx->getLabel();
- if (!this->Ctx->emitGetLocalEnabled(Local.Offset, E))
- return false;
- if (!this->Ctx->jumpFalse(EndLabel, E))
- return false;
-
- if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
- return false;
-
- if (!this->Ctx->emitDestructionPop(Local.Desc, Local.Desc->getLoc()))
- return false;
-
- this->Ctx->fallthrough(EndLabel);
- this->Ctx->emitLabel(EndLabel);
- } else {
- if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
- return false;
- if (!this->Ctx->emitDestructionPop(Local.Desc, Local.Desc->getLoc()))
- return false;
- }
-
- removeIfStoredOpaqueValue(Local);
- }
- return true;
- }
-
- void removeStoredOpaqueValues() {
- if (!Idx)
- return;
-
- for (const Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
- removeIfStoredOpaqueValue(Local);
- }
- }
-
- void removeIfStoredOpaqueValue(const Scope::Local &Local) {
- if (const auto *OVE =
- llvm::dyn_cast_if_present<OpaqueValueExpr>(Local.Desc->asExpr())) {
- if (auto It = this->Ctx->OpaqueExprs.find(OVE);
- It != this->Ctx->OpaqueExprs.end())
- this->Ctx->OpaqueExprs.erase(It);
- };
- }
-
- /// Index of the scope in the chain.
- UnsignedOrNone Idx = std::nullopt;
-};
-
-template <class Emitter> class ArrayIndexScope final {
-public:
- ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
- OldArrayIndex = Ctx->ArrayIndex;
- Ctx->ArrayIndex = Index;
- }
-
- ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }
-
-private:
- Compiler<Emitter> *Ctx;
- std::optional<uint64_t> OldArrayIndex;
-};
-
-template <class Emitter> class SourceLocScope final {
-public:
- SourceLocScope(Compiler<Emitter> *Ctx, const Expr *DefaultExpr) : Ctx(Ctx) {
- assert(DefaultExpr);
- // We only switch if the current SourceLocDefaultExpr is null.
- if (!Ctx->SourceLocDefaultExpr) {
- Enabled = true;
- Ctx->SourceLocDefaultExpr = DefaultExpr;
- }
- }
-
- ~SourceLocScope() {
- if (Enabled)
- Ctx->SourceLocDefaultExpr = nullptr;
- }
-
-private:
- Compiler<Emitter> *Ctx;
- bool Enabled = false;
-};
-
-template <class Emitter> class InitLinkScope final {
-public:
- InitLinkScope(Compiler<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) {
- Ctx->InitStack.push_back(std::move(Link));
- }
-
- ~InitLinkScope() { this->Ctx->InitStack.pop_back(); }
-
-public:
- Compiler<Emitter> *Ctx;
-};
-
-template <class Emitter> class InitStackScope final {
-public:
- InitStackScope(Compiler<Emitter> *Ctx, bool Active)
- : Ctx(Ctx), OldValue(Ctx->InitStackActive), Active(Active) {
- Ctx->InitStackActive = Active;
- if (Active)
- Ctx->InitStack.push_back(InitLink::DIE());
- }
-
- ~InitStackScope() {
- this->Ctx->InitStackActive = OldValue;
- if (Active)
- Ctx->InitStack.pop_back();
- }
-
-private:
- Compiler<Emitter> *Ctx;
- bool OldValue;
- bool Active;
-};
-
} // namespace interp
} // namespace clang
More information about the cfe-commits
mailing list