CIRCT  20.0.0git
CheckRecursiveInstantiation.cpp
Go to the documentation of this file.
1 //===- CheckRecursiveInstantiation.cpp - Check recurisve instantiation ----===//
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 
11 #include "mlir/Pass/Pass.h"
12 #include "llvm/ADT/SCCIterator.h"
13 
14 namespace circt {
15 namespace firrtl {
16 #define GEN_PASS_DEF_CHECKRECURSIVEINSTANTIATION
17 #include "circt/Dialect/FIRRTL/Passes.h.inc"
18 } // namespace firrtl
19 } // namespace circt
20 
21 using namespace circt;
22 using namespace firrtl;
23 
24 static void printPath(InstanceGraph &instanceGraph,
25  ArrayRef<InstanceGraphNode *> nodes) {
26  assert(nodes.size() > 0 && "an scc should have at least one node");
27  auto diag =
28  emitError(nodes.front()->getModule().getLoc(), "recursive instantiation");
29  llvm::SmallPtrSet<InstanceGraphNode *, 8> scc(nodes.begin(), nodes.end());
30  for (auto *node : nodes) {
31  for (auto *record : *node) {
32  auto *target = record->getTarget();
33  if (!scc.contains(target))
34  continue;
35  auto &note = diag.attachNote(record->getInstance().getLoc());
36  note << record->getParent()->getModule().getModuleName();
37  note << " instantiates "
38  << record->getTarget()->getModule().getModuleName() << " here";
39  }
40  }
41 }
42 
43 namespace {
44 class CheckRecursiveInstantiationPass
45  : public impl::CheckRecursiveInstantiationBase<
46  CheckRecursiveInstantiationPass> {
47 public:
48  void runOnOperation() override {
49  auto &instanceGraph = getAnalysis<InstanceGraph>();
50  for (auto it = llvm::scc_begin(&instanceGraph),
51  end = llvm::scc_end(&instanceGraph);
52  it != end; ++it) {
53  if (it.hasCycle()) {
54  printPath(instanceGraph, *it);
55  signalPassFailure();
56  }
57  }
58  markAllAnalysesPreserved();
59  }
60 };
61 } // namespace
62 
63 std::unique_ptr<mlir::Pass> circt::firrtl::createCheckRecursiveInstantiation() {
64  return std::make_unique<CheckRecursiveInstantiationPass>();
65 }
assert(baseType &&"element must be base type")
static void printPath(InstanceGraph &instanceGraph, ArrayRef< InstanceGraphNode * > nodes)
This graph tracks modules and where they are instantiated.
std::unique_ptr< mlir::Pass > createCheckRecursiveInstantiation()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21