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/DenseMap.h"
13 #include "llvm/ADT/SCCIterator.h"
14 
15 namespace circt {
16 namespace firrtl {
17 #define GEN_PASS_DEF_CHECKRECURSIVEINSTANTIATION
18 #include "circt/Dialect/FIRRTL/Passes.h.inc"
19 } // namespace firrtl
20 } // namespace circt
21 
22 using namespace circt;
23 using namespace firrtl;
24 
25 static void printPath(InstanceGraph &instanceGraph,
26  ArrayRef<InstanceGraphNode *> nodes) {
27  assert(nodes.size() > 0 && "an scc should have at least one node");
28  auto diag =
29  emitError(nodes.front()->getModule().getLoc(), "recursive instantiation");
30  llvm::SmallPtrSet<InstanceGraphNode *, 8> scc(nodes.begin(), nodes.end());
31  for (auto *node : nodes) {
32  for (auto *record : *node) {
33  auto *target = record->getTarget();
34  if (!scc.contains(target))
35  continue;
36  auto &note = diag.attachNote(record->getInstance().getLoc());
37  note << record->getParent()->getModule().getModuleName();
38  note << " instantiates "
39  << record->getTarget()->getModule().getModuleName() << " here";
40  }
41  }
42 }
43 
44 namespace {
45 class CheckRecursiveInstantiationPass
46  : public impl::CheckRecursiveInstantiationBase<
47  CheckRecursiveInstantiationPass> {
48 public:
49  void runOnOperation() override {
50  auto &instanceGraph = getAnalysis<InstanceGraph>();
51  for (auto it = llvm::scc_begin(&instanceGraph),
52  end = llvm::scc_end(&instanceGraph);
53  it != end; ++it) {
54  if (it.hasCycle()) {
55  printPath(instanceGraph, *it);
56  signalPassFailure();
57  }
58  }
59  markAllAnalysesPreserved();
60  }
61 };
62 } // namespace
63 
64 std::unique_ptr<mlir::Pass> circt::firrtl::createCheckRecursiveInstantiation() {
65  return std::make_unique<CheckRecursiveInstantiationPass>();
66 }
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