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>
126 if (failed(typedOutput<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>
263 (addConverter<T>(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")
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.
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)
A dialect interface to provide lowering conversions.
IntrinsicLoweringDialectInterface(Dialect *dialect)
virtual void populateIntrinsicLowerings(IntrinsicLowerings &lowerings) const =0
void populateIntrinsicLowerings(IntrinsicLowerings &lowerings) const