13#ifndef CIRCT_DIALECT_FIRRTL_FIRRTLINTRINSICS_H
14#define CIRCT_DIALECT_FIRRTL_FIRRTLINTRINSICS_H
18#include "mlir/IR/Diagnostics.h"
19#include "mlir/Transforms/DialectConversion.h"
27 GenericIntrinsicOp
op;
31 InFlightDiagnostic
emitError() {
return op.emitError(
op.getIntrinsic()); }
37 ParseResult
hasNInputs(
unsigned n,
unsigned c = 0);
42 if (n >=
op.getNumOperands())
43 return emitError() <<
" missing input " << n;
44 if (!std::invoke(std::forward<C>(call),
op.getOperand(n).getType()))
45 return emitError() <<
" input " << n <<
" " << msg;
51 return checkInputType(n,
"not of correct type", std::forward<C>(call));
61 auto baseType = dyn_cast<FIRRTLBaseType>(ty);
62 return baseType && baseType.isResetType();
68 return checkInputType(n,
"not size " + Twine(size), [size](
auto ty) {
69 auto t = dyn_cast<T>(ty);
70 return t && t.getWidth() == size;
78 ParseResult
hasNParam(
unsigned n,
unsigned c = 0);
80 ParseResult
namedParam(StringRef paramName,
bool optional =
false);
82 ParseResult
namedIntParam(StringRef paramName,
bool optional =
false);
85 for (
auto param :
op.getParameters().getAsRange<ParamDeclAttr>())
86 if (param.getName().getValue() == name)
97 return cast<T>(p.getValue());
105 if (
op.getNumResults() == 0)
110 if (
op.getNumResults() != 0)
111 return emitError() <<
" should not have outputs";
115 template <
typename T>
119 if (!isa<T>(
op.getResult().getType()))
120 return emitError() <<
" output not of correct type";
124 template <
typename T>
128 if (cast<T>(
op.getResult().getType()).getWidth() != size)
129 return emitError() <<
" output not size " << size;
138 return dyn_cast_or_null<mlir::TypedValue<BundleType>>(
op.getResult());
143 template <
typename C>
148 return emitError() <<
" missing output bundle";
149 auto ty = b.getType();
150 if (n >= ty.getNumElements())
151 return emitError() <<
" missing output element " << n;
152 auto elementName = ty.getElementName(n);
153 if (elementName != name)
154 return emitError() <<
" output element " << n <<
" is named "
155 << elementName <<
" not " << name;
156 if (!std::invoke(std::forward<C>(call),
157 ty.getElementTypePreservingConst(n)))
158 return emitError() <<
" output element " << n <<
" " << msg;
162 template <
typename C>
165 std::forward<C>(call));
172 template <
typename T>
177 template <
typename T>
181 auto t = dyn_cast<T>(ty);
182 return t && t.getWidth() == size;
204 llvm::report_fatal_error(
205 "check() or checkAndConvert() must be implemented");
211 PatternRewriter &rewriter) {
212 llvm::report_fatal_error(
213 "convert() or checkAndConvert() must be implemented");
222 GenericIntrinsicOpAdaptor adaptor,
223 PatternRewriter &rewriter) {
226 convert(gi, adaptor, rewriter);
231template <
typename OpTy>
237 PatternRewriter &rewriter)
final {
239 rewriter.replaceOpWithNewOp<OpTy>(gi.op, gi.op.getResultTypes(),
240 adaptor.getOperands());
248 llvm::DenseMap<StringAttr, std::unique_ptr<IntrinsicConverter>>;
261 template <
typename T,
typename... Args>
267 FailureOr<size_t>
lower(FModuleOp mod,
bool allowUnknownIntrinsics =
false);
270 template <
typename T>
271 typename std::enable_if_t<std::is_base_of_v<IntrinsicConverter, T>>
273 auto nameAttr = StringAttr::get(
context, name);
275 "duplicate conversion for intrinsic");
276 conversions.try_emplace(nameAttr, std::make_unique<T>());
290 :
public mlir::DialectInterfaceCollection<
291 IntrinsicLoweringDialectInterface> {
assert(baseType &&"element must be base type")
false return failure()
Parse an optional keyword or string and set instance into 'result'.
Base class for Intrinsic Converters.
virtual bool check(GenericIntrinsic gi)
Checks whether the intrinsic is well-formed.
virtual ~IntrinsicConverter()=default
virtual void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor, PatternRewriter &rewriter)
Transform the intrinsic to its implementation.
virtual LogicalResult checkAndConvert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor, PatternRewriter &rewriter)
Perform both check and convert, defaults to using check() and convert().
Lowering helper which collects all intrinsic converters.
FailureOr< size_t > lower(FModuleOp mod, bool allowUnknownIntrinsics=false)
Lowers all intrinsics in a module. Returns number converted or failure.
IntrinsicLowerings(MLIRContext *context)
std::enable_if_t< std::is_base_of_v< IntrinsicConverter, T > > addConverter(StringRef name)
llvm::DenseMap< StringAttr, std::unique_ptr< IntrinsicConverter > > ConversionMapTy
void add(Args... args)
Registers a converter to one or more intrinsic names.
MLIRContext * context
Reference to the MLIR context.
ConversionMapTy conversions
Mapping from intrinsic names to converters.
void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor, PatternRewriter &rewriter) final
Transform the intrinsic to its implementation.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
IntrinsicLoweringDialectInterface(Dialect *dialect)
void populateIntrinsicLowerings(IntrinsicLowerings &lowerings) const override
Helper class for checking and extracting information from the generic instrinsic op.
ParseResult sizedInput(unsigned n, int32_t size)
mlir::TypedValue< BundleType > getOutputBundle()
T getParamValue(StringRef name)
Get parameter value by name, if present, as requested type.
ParseResult typedOutput()
ParseResult hasResetInput(unsigned n)
ParseResult checkInputType(unsigned n, const Twine &msg, C &&call)
GenericIntrinsic(GenericIntrinsicOp op)
ParseResult typedInput(unsigned n)
ParseResult hasNOutputElements(unsigned n)
InFlightDiagnostic emitError()
ParseResult checkOutputElement(unsigned n, StringRef name, C &&call)
ParseResult namedIntParam(StringRef paramName, bool optional=false)
ParamDeclAttr getParamByName(StringRef name)
ParseResult checkOutputElement(unsigned n, StringRef name, const Twine &msg, C &&call)
ParseResult namedParam(StringRef paramName, bool optional=false)
ParseResult sizedOutput(int32_t size)
ParseResult sizedOutputElement(unsigned n, StringRef name, int32_t size)
ParseResult hasNParam(unsigned n, unsigned c=0)
ParseResult hasOutputElement(unsigned n, StringRef name)
ParseResult hasNInputs(unsigned n, unsigned c=0)
ParseResult typedOutputElement(unsigned n, StringRef name)
ParseResult hasNoOutput()
ParseResult checkInputType(unsigned n, C &&call)
IntrinsicLoweringDialectInterface(Dialect *dialect)
virtual void populateIntrinsicLowerings(IntrinsicLowerings &lowerings) const =0
void populateIntrinsicLowerings(IntrinsicLowerings &lowerings) const