1 //===- ControlFlowInterfaces.cpp - ControlFlow Interfaces -----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "mlir/Interfaces/ControlFlowInterfaces.h"
10 #include "mlir/IR/StandardTypes.h"
11 
12 using namespace mlir;
13 
14 //===----------------------------------------------------------------------===//
15 // ControlFlowInterfaces
16 //===----------------------------------------------------------------------===//
17 
18 #include "mlir/Interfaces/ControlFlowInterfaces.cpp.inc"
19 
20 //===----------------------------------------------------------------------===//
21 // BranchOpInterface
22 //===----------------------------------------------------------------------===//
23 
24 /// Returns the `BlockArgument` corresponding to operand `operandIndex` in some
25 /// successor if 'operandIndex' is within the range of 'operands', or None if
26 /// `operandIndex` isn't a successor operand index.
27 Optional<BlockArgument> mlir::detail::getBranchSuccessorArgument(
28     Optional<OperandRange> operands, unsigned operandIndex, Block *successor) {
29   // Check that the operands are valid.
30   if (!operands || operands->empty())
31     return llvm::None;
32 
33   // Check to ensure that this operand is within the range.
34   unsigned operandsStart = operands->getBeginOperandIndex();
35   if (operandIndex < operandsStart ||
36       operandIndex >= (operandsStart + operands->size()))
37     return llvm::None;
38 
39   // Index the successor.
40   unsigned argIndex = operandIndex - operandsStart;
41   return successor->getArgument(argIndex);
42 }
43 
44 /// Verify that the given operands match those of the given successor block.
45 LogicalResult
46 mlir::detail::verifyBranchSuccessorOperands(Operation *op, unsigned succNo,
47                                             Optional<OperandRange> operands) {
48   if (!operands)
49     return success();
50 
51   // Check the count.
52   unsigned operandCount = operands->size();
53   Block *destBB = op->getSuccessor(succNo);
54   if (operandCount != destBB->getNumArguments())
55     return op->emitError() << "branch has " << operandCount
56                            << " operands for successor #" << succNo
57                            << ", but target block has "
58                            << destBB->getNumArguments();
59 
60   // Check the types.
61   auto operandIt = operands->begin();
62   for (unsigned i = 0; i != operandCount; ++i, ++operandIt) {
63     if ((*operandIt).getType() != destBB->getArgument(i).getType())
64       return op->emitError() << "type mismatch for bb argument #" << i
65                              << " of successor #" << succNo;
66   }
67   return success();
68 }
69