23#include <mlir/IR/Builders.h>
24#include <mlir/IR/BuiltinTypes.h>
25#include <mlir/IR/DialectImplementation.h>
26#include <mlir/Transforms/DialectConversion.h>
28#include <llvm/ADT/DenseMap.h>
29#include <llvm/ADT/TypeSwitch.h>
34#define GET_TYPEDEF_CLASSES
49class V1StructNameTypeConverter :
public TypeConverter {
50 const DenseMap<SymbolRefAttr, SymbolRefAttr> &fqnMap;
53 explicit V1StructNameTypeConverter(
const DenseMap<SymbolRefAttr, SymbolRefAttr> &renamingMap)
54 : fqnMap(renamingMap) {
56 addConversion([](Type t) {
return t; });
59 auto it = fqnMap.find(t.getNameRef());
60 SymbolRefAttr newRef = (it != fqnMap.end()) ? it->second : t.getNameRef();
61 bool changed = (newRef != t.getNameRef());
62 ArrayAttr params = t.getParams();
64 SmallVector<Attribute> updated;
65 bool paramsChanged =
false;
66 for (Attribute a : params) {
67 if (
auto ta = dyn_cast<TypeAttr>(a)) {
68 Type inner = convertType(ta.getValue());
69 updated.push_back(TypeAttr::get(inner));
70 paramsChanged |= (inner != ta.getValue());
76 params = ArrayAttr::get(t.getContext(), updated);
87class V1CallOpPattern :
public OpConversionPattern<CallOp> {
88 const DenseMap<SymbolRefAttr, SymbolRefAttr> &fqnMap;
92 TypeConverter &converter, MLIRContext *ctx,
93 const DenseMap<SymbolRefAttr, SymbolRefAttr> &renamingMap
95 : OpConversionPattern<CallOp>(converter, ctx), fqnMap(renamingMap) {}
97 LogicalResult matchAndRewrite(
98 CallOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
100 SmallVector<Type> newResultTypes;
101 if (failed(getTypeConverter()->convertTypes(op.getResultTypes(), newResultTypes))) {
102 return op->emitError(
"Could not convert Op result types.");
106 SmallVector<FlatSymbolRefAttr> calleePieces =
getPieces(calleeAttr);
107 for (
auto &[oldFQN, newFQN] : fqnMap) {
108 SmallVector<FlatSymbolRefAttr> oldPieces =
getPieces(oldFQN);
109 if (calleePieces.size() > oldPieces.size() &&
111 calleePieces.begin(), calleePieces.begin() + (ptrdiff_t)oldPieces.size(),
114 SmallVector<FlatSymbolRefAttr> newPieces =
getPieces(newFQN);
115 newPieces.append(calleePieces.begin() + (ptrdiff_t)oldPieces.size(), calleePieces.end());
121 rewriter, op, newResultTypes, calleeAttr, adaptor.
getMapOperands(),
136LogicalResult migrateToV2(Operation *rootOp) {
141 llvm::DenseMap<SymbolRefAttr, SymbolRefAttr> oldToNewFQN;
144 rootOp->walk<WalkOrder::PreOrder>([&oldToNewFQN](
StructDefOp structOp) -> WalkResult {
145 Attribute constParamsAttr = structOp->getAttr(llzk::kV1ConstParamsAttr);
146 if (!constParamsAttr) {
147 return WalkResult::advance();
149 structOp->removeAttr(llzk::kV1ConstParamsAttr);
153 OpBuilder builder(structOp);
158 Block &templateBody = templateOp.getBodyRegion().emplaceBlock();
159 OpBuilder templateBuilder = OpBuilder::atBlockBegin(&templateBody);
160 auto constParams = llvm::cast<ArrayAttr>(constParamsAttr);
161 for (
auto paramRef : constParams.getAsRange<FlatSymbolRefAttr>()) {
163 structOp.getLoc(), paramRef.getValue(),
169 SymbolRefAttr oldFQN = structOp.getFullyQualifiedName();
172 structOp->moveBefore(&templateBody, templateBody.end());
176 oldToNewFQN[oldFQN] =
appendLeaf(oldFQN, structOp.getSymNameAttr());
179 return WalkResult::skip();
183 if (oldToNewFQN.empty()) {
189 MLIRContext *ctx = rootOp->getContext();
190 V1StructNameTypeConverter tyConv(oldToNewFQN);
191 ConversionTarget target(*ctx);
192 target.markUnknownOpDynamicallyLegal([&tyConv](Operation *op) {
199 patterns.add<V1CallOpPattern>(tyConv, ctx, oldToNewFQN);
200 return applyPartialConversion(rootOp, target, std::move(patterns));
219 assert(requested < current &&
"pre-condition");
221 if (failed(migrateToV2(rootOp))) {
232auto llzk::component::StructDialect::initialize() ->
void {
240 #define GET_TYPEDEF_LIST
244 addInterfaces<StructDialectBytecodeInterface>();
Reusable MLIR dialect conversion functions for LLZK StructType replacement.
static StructType get(::mlir::SymbolRefAttr structName)
::mlir::SymbolRefAttr getCalleeAttr()
::mlir::OperandRangeRange getMapOperands()
::mlir::DenseI32ArrayAttr getNumDimsPerMapAttr()
OpClass replaceOpWithNewOp(Rewriter &rewriter, mlir::Operation *op, Args &&...args)
Wrapper for PatternRewriter::replaceOpWithNewOp() that automatically copies discardable attributes (i...
SymbolRefAttr appendLeaf(SymbolRefAttr orig, FlatSymbolRefAttr newLeaf)
mlir::RewritePatternSet newGeneralRewritePatternSet(mlir::TypeConverter &tyConv, mlir::MLIRContext *ctx, mlir::ConversionTarget &target)
Return a new RewritePatternSet covering all LLZK op types that may contain a StructType.
mlir::SymbolRefAttr asSymbolRefAttr(mlir::StringAttr root, mlir::SymbolRefAttr tail)
Build a SymbolRefAttr that prepends tail with root, i.e., root::tail.
llvm::SmallVector< FlatSymbolRefAttr > getPieces(SymbolRefAttr ref)
bool defaultLegalityCheck(const mlir::TypeConverter &tyConv, mlir::Operation *op)
Check whether an op is legal with respect to the given type converter, including TypeAttr attributes ...
LLZKDialectBytecodeInterface(mlir::Dialect *dia)
Implement version upgrade for StructDialect.
LLZKDialectBytecodeInterface(mlir::Dialect *dia)
LogicalResult upgradeFromVersion(mlir::Operation *rootOp, const LLZKDialectVersion ¤t, const LLZKDialectVersion &requested) const override