diff options
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenFunction.cpp')
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 36 | 
1 files changed, 24 insertions, 12 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 71ff20a..5d5209b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -242,12 +242,19 @@ void CIRGenFunction::LexicalScope::cleanup() {      }    }; -  if (returnBlock != nullptr) { -    // Write out the return block, which loads the value from `__retval` and -    // issues the `cir.return`. +  // Cleanup are done right before codegen resumes a scope. This is where +  // objects are destroyed. Process all return blocks. +  // TODO(cir): Handle returning from a switch statement through a cleanup +  // block. We can't simply jump to the cleanup block, because the cleanup block +  // is not part of the case region. Either reemit all cleanups in the return +  // block or wait for MLIR structured control flow to support early exits. +  llvm::SmallVector<mlir::Block *> retBlocks; +  for (mlir::Block *retBlock : localScope->getRetBlocks()) {      mlir::OpBuilder::InsertionGuard guard(builder); -    builder.setInsertionPointToEnd(returnBlock); -    (void)emitReturn(*returnLoc); +    builder.setInsertionPointToEnd(retBlock); +    retBlocks.push_back(retBlock); +    mlir::Location retLoc = localScope->getRetLoc(retBlock); +    emitReturn(retLoc);    }    auto insertCleanupAndLeave = [&](mlir::Block *insPt) { @@ -274,19 +281,22 @@ void CIRGenFunction::LexicalScope::cleanup() {      if (localScope->depth == 0) {        // Reached the end of the function. -      if (returnBlock != nullptr) { -        if (returnBlock->getUses().empty()) { -          returnBlock->erase(); +      // Special handling only for single return block case +      if (localScope->getRetBlocks().size() == 1) { +        mlir::Block *retBlock = localScope->getRetBlocks()[0]; +        mlir::Location retLoc = localScope->getRetLoc(retBlock); +        if (retBlock->getUses().empty()) { +          retBlock->erase();          } else {            // Thread return block via cleanup block.            if (cleanupBlock) { -            for (mlir::BlockOperand &blockUse : returnBlock->getUses()) { +            for (mlir::BlockOperand &blockUse : retBlock->getUses()) {                cir::BrOp brOp = mlir::cast<cir::BrOp>(blockUse.getOwner());                brOp.setSuccessor(cleanupBlock);              }            } -          cir::BrOp::create(builder, *returnLoc, returnBlock); +          cir::BrOp::create(builder, retLoc, retBlock);            return;          }        } @@ -324,8 +334,10 @@ void CIRGenFunction::LexicalScope::cleanup() {    bool entryBlock = builder.getInsertionBlock()->isEntryBlock();    if (!entryBlock && curBlock->empty()) {      curBlock->erase(); -    if (returnBlock != nullptr && returnBlock->getUses().empty()) -      returnBlock->erase(); +    for (mlir::Block *retBlock : retBlocks) { +      if (retBlock->getUses().empty()) +        retBlock->erase(); +    }      return;    }  | 
