1//===- TestPrintNesting.cpp - Passes to illustrate the IR nesting ---------===//
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/IR/BuiltinOps.h"
10#include "mlir/Pass/Pass.h"
11
12using namespace mlir;
13
14namespace {
15/// This pass illustrates the IR nesting through printing.
16struct TestPrintNestingPass
17 : public PassWrapper<TestPrintNestingPass, OperationPass<>> {
18 MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestPrintNestingPass)
19
20 StringRef getArgument() const final { return "test-print-nesting"; }
21 StringRef getDescription() const final { return "Test various printing."; }
22 // Entry point for the pass.
23 void runOnOperation() override {
24 Operation *op = getOperation();
25 resetIndent();
26 printOperation(op);
27 }
28
29 /// The three methods below are mutually recursive and follow the nesting of
30 /// the IR: operation->region->block->operation->...
31
32 void printOperation(Operation *op) {
33 // Print the operation itself and some of its properties
34 printIndent() << "visiting op: '" << op->getName() << "' with "
35 << op->getNumOperands() << " operands and "
36 << op->getNumResults() << " results\n";
37 // Print the operation attributes
38 if (!op->getAttrs().empty()) {
39 printIndent() << op->getAttrs().size() << " attributes:\n";
40 for (NamedAttribute attr : op->getAttrs())
41 printIndent() << " - '" << attr.getName().getValue() << "' : '"
42 << attr.getValue() << "'\n";
43 }
44
45 // Recurse into each of the regions attached to the operation.
46 printIndent() << " " << op->getNumRegions() << " nested regions:\n";
47 auto indent = pushIndent();
48 for (Region &region : op->getRegions())
49 printRegion(region);
50 }
51
52 void printRegion(Region &region) {
53 // A region does not hold anything by itself other than a list of blocks.
54 printIndent() << "Region with " << region.getBlocks().size()
55 << " blocks:\n";
56 auto indent = pushIndent();
57 for (Block &block : region.getBlocks())
58 printBlock(block);
59 }
60
61 void printBlock(Block &block) {
62 // Print the block intrinsics properties (basically: argument list)
63 printIndent()
64 << "Block with " << block.getNumArguments() << " arguments, "
65 << block.getNumSuccessors()
66 << " successors, and "
67 // Note, this `.size()` is traversing a linked-list and is O(n).
68 << block.getOperations().size() << " operations\n";
69
70 // Block main role is to hold a list of Operations: let's recurse.
71 auto indent = pushIndent();
72 for (Operation &op : block.getOperations())
73 printOperation(op: &op);
74 }
75
76 /// Manages the indentation as we traverse the IR nesting.
77 int indent;
78 struct IdentRAII {
79 int &indent;
80 IdentRAII(int &indent) : indent(indent) {}
81 ~IdentRAII() { --indent; }
82 };
83 void resetIndent() { indent = 0; }
84 IdentRAII pushIndent() { return IdentRAII(++indent); }
85
86 llvm::raw_ostream &printIndent() {
87 for (int i = 0; i < indent; ++i)
88 llvm::outs() << " ";
89 return llvm::outs();
90 }
91};
92} // namespace
93
94namespace mlir {
95void registerTestPrintNestingPass() {
96 PassRegistration<TestPrintNestingPass>();
97}
98} // namespace mlir
99

source code of mlir/test/lib/IR/TestPrintNesting.cpp