[clang] [CIR] Introduce more cleanup infrastructure (PR #152589)
Morris Hafner via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 11 07:43:13 PDT 2025
================
@@ -70,45 +70,89 @@ void EHScopeStack::deallocate(size_t size) {
}
void *EHScopeStack::pushCleanup(CleanupKind kind, size_t size) {
- char *buffer = allocate(size);
+ char *buffer = allocate(EHCleanupScope::getSizeForCleanupSize(size));
- // When the full implementation is upstreamed, this will allocate
- // extra memory for and construct a wrapper object that is used to
- // manage the cleanup generation.
- assert(!cir::MissingFeatures::ehCleanupScope());
+ EHCleanupScope *scope = new (buffer) EHCleanupScope(size);
- return buffer;
+ return scope->getCleanupBuffer();
}
-static mlir::Block *getCurCleanupBlock(CIRGenFunction &cgf) {
- mlir::OpBuilder::InsertionGuard guard(cgf.getBuilder());
- mlir::Block *cleanup =
- cgf.curLexScope->getOrCreateCleanupBlock(cgf.getBuilder());
- return cleanup;
+void EHScopeStack::popCleanup() {
+ assert(!empty() && "popping exception stack when not empty");
+
+ assert(isa<EHCleanupScope>(*begin()));
+ EHCleanupScope &cleanup = cast<EHCleanupScope>(*begin());
+ deallocate(cleanup.getAllocatedSize());
+
+ // Destroy the cleanup.
+ cleanup.destroy();
+
+ assert(!cir::MissingFeatures::ehCleanupBranchFixups());
+}
+
+static void emitCleanup(CIRGenFunction &cgf, EHScopeStack::Cleanup *cleanup) {
+ // Ask the cleanup to emit itself.
+ assert(cgf.haveInsertPoint() && "expected insertion point");
+ assert(!cir::MissingFeatures::ehCleanupFlags());
+ cleanup->emit(cgf);
+ assert(cgf.haveInsertPoint() && "cleanup ended with no insertion point?");
}
/// Pops a cleanup block. If the block includes a normal cleanup, the
/// current insertion point is threaded through the cleanup, as are
/// any branch fixups on the cleanup.
void CIRGenFunction::popCleanupBlock() {
assert(!ehStack.empty() && "cleanup stack is empty!");
+ assert(isa<EHCleanupScope>(*ehStack.begin()) && "top not a cleanup!");
+ EHCleanupScope &scope = cast<EHCleanupScope>(*ehStack.begin());
- // The memory for the cleanup continues to be owned by the EHScopeStack
- // allocator, so we just destroy the object rather than attempting to
- // free it.
- EHScopeStack::Cleanup &cleanup = *ehStack.begin();
+ // Remember activation information.
+ bool isActive = scope.isActive();
- // The eventual implementation here will use the EHCleanupScope helper class.
- assert(!cir::MissingFeatures::ehCleanupScope());
+ assert(!cir::MissingFeatures::ehCleanupBranchFixups());
- mlir::OpBuilder::InsertionGuard guard(builder);
+ // - whether there's a fallthrough
+ mlir::Block *fallthroughSource = builder.getInsertionBlock();
+ bool hasFallthrough = fallthroughSource != nullptr && isActive;
+
+ bool requiresNormalCleanup = scope.isNormalCleanup() && hasFallthrough;
+
+ // If we don't need the cleanup at all, we're done.
+ assert(!cir::MissingFeatures::ehCleanupScopeRequiresEHCleanup());
+ if (!requiresNormalCleanup) {
+ ehStack.popCleanup();
+ return;
+ }
+
+ // Copy the cleanup emission data out. This uses either a stack
+ // array or malloc'd memory, depending on the size, which is
+ // behavior that SmallVector would provide, if we could use it
+ // here. Unfortunately, if you ask for a SmallVector<char>, the
+ // alignment isn't sufficient.
----------------
mmha wrote:
We need to do an [aligned operator new](https://en.cppreference.com/w/cpp/memory/new/align_val_t.html) below now that we can use C++17.
But isn't it easier to create a `SmallVector<EHScopeStack::Cleanup>` and cast `vector.data()` to `char *` than the other way around? This way we get our alignment requrement satisfied, too.
https://github.com/llvm/llvm-project/pull/152589
More information about the cfe-commits
mailing list