| //===- TestPrintNesting.cpp - Passes to illustrate the IR nesting ---------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "mlir/IR/BuiltinOps.h" |
| #include "mlir/Pass/Pass.h" |
| |
| using namespace mlir; |
| |
| namespace { |
| /// This pass illustrates the IR nesting through printing. |
| struct TestPrintNestingPass |
| : public PassWrapper<TestPrintNestingPass, OperationPass<>> { |
| StringRef getArgument() const final { return "test-print-nesting"; } |
| StringRef getDescription() const final { return "Test various printing."; } |
| // Entry point for the pass. |
| void runOnOperation() override { |
| Operation *op = getOperation(); |
| resetIndent(); |
| printOperation(op); |
| } |
| |
| /// The three methods below are mutually recursive and follow the nesting of |
| /// the IR: operation->region->block->operation->... |
| |
| void printOperation(Operation *op) { |
| // Print the operation itself and some of its properties |
| printIndent() << "visiting op: '" << op->getName() << "' with " |
| << op->getNumOperands() << " operands and " |
| << op->getNumResults() << " results\n"; |
| // Print the operation attributes |
| if (!op->getAttrs().empty()) { |
| printIndent() << op->getAttrs().size() << " attributes:\n"; |
| for (NamedAttribute attr : op->getAttrs()) |
| printIndent() << " - '" << attr.getName().getValue() << "' : '" |
| << attr.getValue() << "'\n"; |
| } |
| |
| // Recurse into each of the regions attached to the operation. |
| printIndent() << " " << op->getNumRegions() << " nested regions:\n"; |
| auto indent = pushIndent(); |
| for (Region ®ion : op->getRegions()) |
| printRegion(region); |
| } |
| |
| void printRegion(Region ®ion) { |
| // A region does not hold anything by itself other than a list of blocks. |
| printIndent() << "Region with " << region.getBlocks().size() |
| << " blocks:\n"; |
| auto indent = pushIndent(); |
| for (Block &block : region.getBlocks()) |
| printBlock(block); |
| } |
| |
| void printBlock(Block &block) { |
| // Print the block intrinsics properties (basically: argument list) |
| printIndent() |
| << "Block with " << block.getNumArguments() << " arguments, " |
| << block.getNumSuccessors() |
| << " successors, and " |
| // Note, this `.size()` is traversing a linked-list and is O(n). |
| << block.getOperations().size() << " operations\n"; |
| |
| // Block main role is to hold a list of Operations: let's recurse. |
| auto indent = pushIndent(); |
| for (Operation &op : block.getOperations()) |
| printOperation(&op); |
| } |
| |
| /// Manages the indentation as we traverse the IR nesting. |
| int indent; |
| struct IdentRAII { |
| int &indent; |
| IdentRAII(int &indent) : indent(indent) {} |
| ~IdentRAII() { --indent; } |
| }; |
| void resetIndent() { indent = 0; } |
| IdentRAII pushIndent() { return IdentRAII(++indent); } |
| |
| llvm::raw_ostream &printIndent() { |
| for (int i = 0; i < indent; ++i) |
| llvm::outs() << " "; |
| return llvm::outs(); |
| } |
| }; |
| } // namespace |
| |
| namespace mlir { |
| void registerTestPrintNestingPass() { |
| PassRegistration<TestPrintNestingPass>(); |
| } |
| } // namespace mlir |