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;
202 PatternRewriter &rewriter) = 0;
205 template <
typename OpTy>
211 PatternRewriter &rewriter)
final {
213 rewriter.replaceOpWithNewOp<OpTy>(gi.op, gi.op.getResultTypes(),
214 adaptor.getOperands());
222 llvm::DenseMap<StringAttr, std::unique_ptr<IntrinsicConverter>>;
235 template <
typename T,
typename... Args>
237 (addConverter<T>(args), ...);
241 FailureOr<size_t>
lower(FModuleOp mod,
bool allowUnknownIntrinsics =
false);
244 template <
typename T>
245 typename std::enable_if_t<std::is_base_of_v<IntrinsicConverter, T>>
249 "duplicate conversion for intrinsic");
250 conversions.try_emplace(nameAttr, std::make_unique<T>());
264 :
public mlir::DialectInterfaceCollection<
265 IntrinsicLoweringDialectInterface> {
assert(baseType &&"element must be base type")
Base class for Intrinsic Converters.
virtual ~IntrinsicConverter()=default
virtual void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor, PatternRewriter &rewriter)=0
Transform the intrinsic to its implementation.
virtual bool check(GenericIntrinsic gi)=0
Checks whether the intrinsic is well-formed.
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)
llvm::DenseMap< StringAttr, std::unique_ptr< IntrinsicConverter > > ConversionMapTy
std::enable_if_t< std::is_base_of_v< IntrinsicConverter, T > > addConverter(StringRef name)
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.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
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