@@ -26,7 +26,11 @@ namespace clang::CIRGen {
2626
2727CIRGenFunction::CIRGenFunction (CIRGenModule &cgm, CIRGenBuilderTy &builder,
2828 bool suppressNewContext)
29- : CIRGenTypeCache(cgm), cgm{cgm}, builder(builder) {}
29+ : CIRGenTypeCache(cgm), cgm{cgm}, builder(builder) {
30+ ehStack.setCGF (this );
31+ currentCleanupStackDepth = 0 ;
32+ assert (ehStack.getStackDepth () == 0 );
33+ }
3034
3135CIRGenFunction::~CIRGenFunction () {}
3236
@@ -227,6 +231,14 @@ void CIRGenFunction::LexicalScope::cleanup() {
227231 CIRGenBuilderTy &builder = cgf.builder ;
228232 LexicalScope *localScope = cgf.curLexScope ;
229233
234+ auto applyCleanup = [&]() {
235+ if (performCleanup) {
236+ // ApplyDebugLocation
237+ assert (!cir::MissingFeatures::generateDebugInfo ());
238+ forceCleanup ();
239+ }
240+ };
241+
230242 if (returnBlock != nullptr ) {
231243 // Write out the return block, which loads the value from `__retval` and
232244 // issues the `cir.return`.
@@ -235,46 +247,93 @@ void CIRGenFunction::LexicalScope::cleanup() {
235247 (void )emitReturn (*returnLoc);
236248 }
237249
238- mlir::Block *curBlock = builder.getBlock ();
239- if (isGlobalInit () && !curBlock)
240- return ;
241- if (curBlock->mightHaveTerminator () && curBlock->getTerminator ())
242- return ;
243-
244- // Get rid of any empty block at the end of the scope.
245- bool entryBlock = builder.getInsertionBlock ()->isEntryBlock ();
246- if (!entryBlock && curBlock->empty ()) {
247- curBlock->erase ();
248- if (returnBlock != nullptr && returnBlock->getUses ().empty ())
249- returnBlock->erase ();
250- return ;
251- }
252-
253- // Reached the end of the scope.
254- {
250+ auto insertCleanupAndLeave = [&](mlir::Block *insPt) {
255251 mlir::OpBuilder::InsertionGuard guard (builder);
256- builder.setInsertionPointToEnd (curBlock);
252+ builder.setInsertionPointToEnd (insPt);
253+
254+ // If we still don't have a cleanup block, it means that `applyCleanup`
255+ // below might be able to get us one.
256+ mlir::Block *cleanupBlock = localScope->getCleanupBlock (builder);
257+
258+ // Leverage and defers to RunCleanupsScope's dtor and scope handling.
259+ applyCleanup ();
260+
261+ // If we now have one after `applyCleanup`, hook it up properly.
262+ if (!cleanupBlock && localScope->getCleanupBlock (builder)) {
263+ cleanupBlock = localScope->getCleanupBlock (builder);
264+ builder.create <cir::BrOp>(insPt->back ().getLoc (), cleanupBlock);
265+ if (!cleanupBlock->mightHaveTerminator ()) {
266+ mlir::OpBuilder::InsertionGuard guard (builder);
267+ builder.setInsertionPointToEnd (cleanupBlock);
268+ builder.create <cir::YieldOp>(localScope->endLoc );
269+ }
270+ }
257271
258272 if (localScope->depth == 0 ) {
259273 // Reached the end of the function.
260274 if (returnBlock != nullptr ) {
261- if (returnBlock->getUses ().empty ())
275+ if (returnBlock->getUses ().empty ()) {
262276 returnBlock->erase ();
263- else {
277+ } else {
278+ // Thread return block via cleanup block.
279+ if (cleanupBlock) {
280+ for (mlir::BlockOperand &blockUse : returnBlock->getUses ()) {
281+ cir::BrOp brOp = mlir::cast<cir::BrOp>(blockUse.getOwner ());
282+ brOp.setSuccessor (cleanupBlock);
283+ }
284+ }
285+
264286 builder.create <cir::BrOp>(*returnLoc, returnBlock);
265287 return ;
266288 }
267289 }
268290 emitImplicitReturn ();
269291 return ;
270292 }
271- // Reached the end of a non-function scope. Some scopes, such as those
272- // used with the ?: operator, can return a value.
273- if (!localScope->isTernary () && !curBlock->mightHaveTerminator ()) {
293+
294+ // End of any local scope != function
295+ // Ternary ops have to deal with matching arms for yielding types
296+ // and do return a value, it must do its own cir.yield insertion.
297+ if (!localScope->isTernary () && !insPt->mightHaveTerminator ()) {
274298 !retVal ? builder.create <cir::YieldOp>(localScope->endLoc )
275299 : builder.create <cir::YieldOp>(localScope->endLoc , retVal);
276300 }
301+ };
302+
303+ // If a cleanup block has been created at some point, branch to it
304+ // and set the insertion point to continue at the cleanup block.
305+ // Terminators are then inserted either in the cleanup block or
306+ // inline in this current block.
307+ mlir::Block *cleanupBlock = localScope->getCleanupBlock (builder);
308+ if (cleanupBlock)
309+ insertCleanupAndLeave (cleanupBlock);
310+
311+ // Now deal with any pending block wrap up like implicit end of
312+ // scope.
313+
314+ mlir::Block *curBlock = builder.getBlock ();
315+ if (isGlobalInit () && !curBlock)
316+ return ;
317+ if (curBlock->mightHaveTerminator () && curBlock->getTerminator ())
318+ return ;
319+
320+ // Get rid of any empty block at the end of the scope.
321+ bool entryBlock = builder.getInsertionBlock ()->isEntryBlock ();
322+ if (!entryBlock && curBlock->empty ()) {
323+ curBlock->erase ();
324+ if (returnBlock != nullptr && returnBlock->getUses ().empty ())
325+ returnBlock->erase ();
326+ return ;
277327 }
328+
329+ // If there's a cleanup block, branch to it, nothing else to do.
330+ if (cleanupBlock) {
331+ builder.create <cir::BrOp>(curBlock->back ().getLoc (), cleanupBlock);
332+ return ;
333+ }
334+
335+ // No pre-existent cleanup block, emit cleanup code and yield/return.
336+ insertCleanupAndLeave (curBlock);
278337}
279338
280339cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn (mlir::Location loc) {
@@ -408,7 +467,19 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType,
408467 }
409468}
410469
411- void CIRGenFunction::finishFunction (SourceLocation endLoc) {}
470+ void CIRGenFunction::finishFunction (SourceLocation endLoc) {
471+ // Pop any cleanups that might have been associated with the
472+ // parameters. Do this in whatever block we're currently in; it's
473+ // important to do this before we enter the return block or return
474+ // edges will be *really* confused.
475+ // TODO(cir): Use prologueCleanupDepth here.
476+ bool hasCleanups = ehStack.getStackDepth () != currentCleanupStackDepth;
477+ if (hasCleanups) {
478+ assert (!cir::MissingFeatures::generateDebugInfo ());
479+ // FIXME(cir): should we clearInsertionPoint? breaks many testcases
480+ popCleanupBlocks (currentCleanupStackDepth);
481+ }
482+ }
412483
413484mlir::LogicalResult CIRGenFunction::emitFunctionBody (const clang::Stmt *body) {
414485 auto result = mlir::LogicalResult::success ();
0 commit comments