================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits