[clang][bytecode] Add Descriptor::hasTrivialDtor() (#146286)

We sometimes used to have a long list of 

```
  GetLocalPtr
  PopPtr
  [...]
```

ops at the end of scopes, because we first got a pointer to a local
variable and only then did we figure out that we didn't actually want to
call the destructor for it. Add a new function that allows us to just
ask the `Descriptor` whether we need to call its destructor.
This commit is contained in:
Timm Baeder 2025-06-30 16:59:57 +02:00 committed by GitHub
parent 53102a395f
commit 00cdaa5c39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 27 additions and 9 deletions

View File

@ -574,17 +574,17 @@ public:
// Emit destructor calls for local variables of record // Emit destructor calls for local variables of record
// type with a destructor. // type with a destructor.
for (Scope::Local &Local : llvm::reverse(this->Ctx->Descriptors[*Idx])) { for (Scope::Local &Local : llvm::reverse(this->Ctx->Descriptors[*Idx])) {
if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) { if (Local.Desc->hasTrivialDtor())
if (!this->Ctx->emitGetPtrLocal(Local.Offset, E)) continue;
return false; if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
return false;
if (!this->Ctx->emitDestruction(Local.Desc, Local.Desc->getLoc())) if (!this->Ctx->emitDestruction(Local.Desc, Local.Desc->getLoc()))
return false; return false;
if (!this->Ctx->emitPopPtr(E)) if (!this->Ctx->emitPopPtr(E))
return false; return false;
removeIfStoredOpaqueValue(Local); removeIfStoredOpaqueValue(Local);
}
} }
return true; return true;
} }

View File

@ -502,6 +502,21 @@ SourceInfo Descriptor::getLoc() const {
llvm_unreachable("Invalid descriptor type"); llvm_unreachable("Invalid descriptor type");
} }
bool Descriptor::hasTrivialDtor() const {
if (isPrimitive() || isPrimitiveArray() || isDummy())
return true;
if (isRecord()) {
assert(ElemRecord);
const CXXDestructorDecl *Dtor = ElemRecord->getDestructor();
return !Dtor || Dtor->isTrivial();
}
// Composite arrays.
assert(ElemDesc);
return ElemDesc->hasTrivialDtor();
}
bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); } bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); }
InitMap::InitMap(unsigned N) InitMap::InitMap(unsigned N)

View File

@ -281,6 +281,9 @@ public:
/// Checks if this is a dummy descriptor. /// Checks if this is a dummy descriptor.
bool isDummy() const { return IsDummy; } bool isDummy() const { return IsDummy; }
/// Whether variables of this descriptor need their destructor called or not.
bool hasTrivialDtor() const;
void dump() const; void dump() const;
void dump(llvm::raw_ostream &OS) const; void dump(llvm::raw_ostream &OS) const;
void dumpFull(unsigned Offset = 0, unsigned Indent = 0) const; void dumpFull(unsigned Offset = 0, unsigned Indent = 0) const;