@@ -528,6 +528,34 @@ cir::TryOp CIRGenFunction::LexicalScope::getClosestTryParent() {
528528 return nullptr ;
529529}
530530
531+ void CIRGenFunction::resolveBlockAddresses () {
532+
533+ for (auto &blockAddress : CGM.unresolvedBlockAddressToLabel ) {
534+ cir::LabelOp labelOp =
535+ CGM.lookupBlockAddressInfo (blockAddress.getBlockAddrInfo ());
536+ assert (labelOp && " expected cir.labelOp to already be emitted" );
537+ CGM.updateResolvedBlockAddress (blockAddress, labelOp);
538+ }
539+ CGM.unresolvedBlockAddressToLabel .clear ();
540+ }
541+
542+ void CIRGenFunction::finishIndirectBranch () {
543+ if (!indirectGotoBlock)
544+ return ;
545+ llvm::SmallVector<mlir::Block *> succesors;
546+ llvm::SmallVector<mlir::ValueRange> rangeOperands;
547+ mlir::OpBuilder::InsertionGuard guard (builder);
548+ builder.setInsertionPointToEnd (indirectGotoBlock);
549+ for (auto &[blockAdd, labelOp] : CGM.blockAddressToLabel ) {
550+ succesors.push_back (labelOp->getBlock ());
551+ rangeOperands.push_back (labelOp->getBlock ()->getArguments ());
552+ }
553+ cir::IndirectBrOp::create (builder, builder.getUnknownLoc (),
554+ indirectGotoBlock->getArgument (0 ), false ,
555+ rangeOperands, succesors);
556+ CGM.blockAddressToLabel .clear ();
557+ }
558+
531559void CIRGenFunction::finishFunction (SourceLocation endLoc) {
532560 // CIRGen doesn't use a BreakContinueStack or evaluates OnlySimpleReturnStmts.
533561
@@ -584,15 +612,23 @@ void CIRGenFunction::finishFunction(SourceLocation endLoc) {
584612
585613 // If someone did an indirect goto, emit the indirect goto block at the end of
586614 // the function.
587- assert (!cir::MissingFeatures::indirectBranch () && " NYI" );
588615
616+ // Resolve block address-to-label mappings, then emit the indirect branch
617+ // with the corresponding targets.
618+ resolveBlockAddresses ();
619+ finishIndirectBranch ();
589620 // If some of our locals escaped, insert a call to llvm.localescape in the
590621 // entry block.
591622 assert (!cir::MissingFeatures::escapedLocals () && " NYI" );
592623
593- // If someone took the address of a label but never did an indirect goto, we
594- // made a zero entry PHI node, which is illegal, zap it now.
595- assert (!cir::MissingFeatures::indirectBranch () && " NYI" );
624+ // If a label address was taken but no indirect goto was used, we can't remove
625+ // the block argument here. Instead, we mark the 'indirectbr' op
626+ // as poison so that the cleanup can be deferred to lowering, since the
627+ // verifier doesn't allow the 'indirectbr' target address to be null.
628+ if (indirectGotoBlock && indirectGotoBlock->hasNoPredecessors ()) {
629+ auto indrBr = cast<cir::IndirectBrOp>(indirectGotoBlock->front ());
630+ indrBr.setPoison (true );
631+ }
596632
597633 // CIRGen doesn't need to emit EHResumeBlock, TerminateLandingPad,
598634 // TerminateHandler, UnreachableBlock, TerminateFunclets, NormalCleanupDest
@@ -1965,6 +2001,17 @@ CIRGenFunction::emitArrayLength(const clang::ArrayType *origArrayType,
19652001 return numElements;
19662002}
19672003
2004+ mlir::Block *CIRGenFunction::getIndirectGotoBlock (cir::BlockAddressOp op) {
2005+ // If we already made the indirect branch for indirect goto, return its block.
2006+ if (indirectGotoBlock)
2007+ return indirectGotoBlock;
2008+
2009+ mlir::OpBuilder::InsertionGuard guard (builder);
2010+ indirectGotoBlock = builder.createBlock (builder.getBlock ()->getParent (), {},
2011+ {op.getType ()}, {op.getLoc ()});
2012+ return indirectGotoBlock;
2013+ }
2014+
19682015mlir::Value CIRGenFunction::emitAlignmentAssumption (
19692016 mlir::Value ptrValue, QualType ty, SourceLocation loc,
19702017 SourceLocation assumptionLoc, mlir::IntegerAttr alignment,
0 commit comments