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