11#include "mlir/Pass/Pass.h"
20#include "mlir/Transforms/DialectConversion.h"
24#define GEN_PASS_DEF_KANAGAWACONTAINERIZE
25#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
30using namespace kanagawa;
35 OutlineContainerPattern(MLIRContext *context,
Namespace &ns)
41 matchAndRewrite(ContainerOp op, OpAdaptor adaptor,
42 ConversionPatternRewriter &rewriter)
const override {
46 dyn_cast_or_null<ClassOp>(op.getOperation()->getParentOp());
47 assert(parentClass &&
"This pattern should never be called on a container"
48 "that is not nested within a class.");
49 auto design = parentClass.getParentOp<DesignOp>();
50 assert(design &&
"Parent class should be nested within a design.");
52 rewriter.setInsertionPoint(parentClass);
53 StringAttr newContainerName = rewriter.getStringAttr(
54 ns.
newName(parentClass.getInnerNameAttr().strref() +
"_" +
55 op.getInnerNameAttr().strref()));
56 auto newContainer = rewriter.create<ContainerOp>(
57 op.getLoc(), newContainerName,
false);
59 rewriter.mergeBlocks(op.getBodyBlock(), newContainer.getBodyBlock(), {});
62 rewriter.setInsertionPoint(op);
63 rewriter.create<ContainerInstanceOp>(
64 parentClass.getLoc(), hw::InnerSymAttr::get(newContainerName),
65 newContainer.getInnerRef());
77 matchAndRewrite(ClassOp op, OpAdaptor adaptor,
78 ConversionPatternRewriter &rewriter)
const override {
81 rewriter.create<ContainerOp>(op.getLoc(), op.getInnerSymAttr(),
82 false, op.getNameAttr());
83 rewriter.mergeBlocks(op.getBodyBlock(), newContainer.getBodyBlock(), {});
89struct InstanceToContainerInstancePattern
94 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
95 ConversionPatternRewriter &rewriter)
const override {
97 rewriter.replaceOpWithNewOp<ContainerInstanceOp>(op, op.getInnerSym(),
98 op.getTargetNameAttr());
104struct ContainerizePass
105 :
public circt::kanagawa::impl::KanagawaContainerizeBase<ContainerizePass> {
106 void runOnOperation()
override;
110 LogicalResult outlineContainers();
113 LogicalResult containerizeClasses();
117LogicalResult ContainerizePass::outlineContainers() {
118 auto *context = &getContext();
119 ConversionTarget target(*context);
120 target.addLegalDialect<KanagawaDialect>();
121 target.addDynamicallyLegalOp<ContainerOp>(
122 [&](
auto *op) {
return !isa<kanagawa::ClassOp>(op->getParentOp()); });
123 RewritePatternSet
patterns(context);
137 patterns.insert<OutlineContainerPattern>(context, ns);
138 return applyPartialConversion(getOperation(), target, std::move(
patterns));
141LogicalResult ContainerizePass::containerizeClasses() {
142 auto *context = &getContext();
143 ConversionTarget target(*context);
144 target.addLegalDialect<KanagawaDialect>();
145 target.addIllegalOp<ClassOp, InstanceOp>();
146 RewritePatternSet
patterns(context);
147 patterns.insert<ClassToContainerPattern, InstanceToContainerInstancePattern>(
149 return applyPartialConversion(getOperation(), target, std::move(
patterns));
152void ContainerizePass::runOnOperation() {
153 if (failed(outlineContainers()) || failed(containerizeClasses()))
158 return std::make_unique<ContainerizePass>();
assert(baseType &&"element must be base type")
A namespace that is used to store existing names and generate new names in some scope within the IR.
void add(mlir::ModuleOp module)
StringRef newName(const Twine &name)
Return a unique name, derived from the input name, and add the new name to the internal namespace.
void addDefinitions(mlir::Operation *top)
Populate the symbol cache with all symbol-defining operations within the 'top' operation.
Default symbol cache implementation; stores associations between names (StringAttr's) to mlir::Operat...
void addDefinition(mlir::Attribute key, mlir::Operation *op) override
In the building phase, add symbols.
The target of an inner symbol, the entity the symbol is a handle for.
static RetTy walkSymbols(Operation *op, FuncTy &&callback)
Walk the given IST operation and invoke the callback for all encountered inner symbols.
std::unique_ptr< mlir::Pass > createContainerizePass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.