17#include <mlir/IR/Builders.h>
18#include <mlir/IR/BuiltinAttributes.h>
19#include <mlir/IR/Diagnostics.h>
20#include <mlir/IR/OpImplementation.h>
21#include <mlir/IR/OperationSupport.h>
22#include <mlir/Support/LLVM.h>
24#include <llvm/ADT/STLExtras.h>
25#include <llvm/ADT/SmallString.h>
26#include <llvm/ADT/SmallVectorExtras.h>
27#include <llvm/ADT/StringSet.h>
28#include <llvm/ADT/TypeSwitch.h>
29#include <llvm/Support/Debug.h>
46static void buildCommon(
47 OpBuilder &builder, OperationState &state, PodType result,
InitializedRecords initialValues
49 SmallVector<Value, 4> values;
50 SmallVector<StringRef, 4>
names;
52 for (
const auto &record : initialValues) {
53 names.push_back(record.name);
54 values.push_back(record.value);
58 state.addTypes(result);
59 state.addOperands(values);
65 OpBuilder &builder, OperationState &state, PodType result, ArrayRef<ValueRange> mapOperands,
68 buildCommon(builder, state, result, initialValues);
73 OpBuilder &builder, OperationState &state, PodType result,
InitializedRecords initialValues
75 buildCommon(builder, state, result, initialValues);
87static void collectMapAttrs(Type type, SmallVector<AffineMapAttr> &mapAttrs) {
89 llvm::TypeSwitch<Type, void>(type)
92 collectMapAttrs(record.getType(), mapAttrs);
95 .Case([&mapAttrs](array::ArrayType t) {
96 for (
auto a : t.getDimensionSizes()) {
97 if (
auto m = llvm::dyn_cast<AffineMapAttr>(a)) {
98 mapAttrs.push_back(m);
102 .Case([&mapAttrs](component::StructType t) {
103 if (ArrayAttr params = t.getParams()) {
104 for (
auto param : params) {
105 if (
auto m = llvm::dyn_cast<AffineMapAttr>(param)) {
106 mapAttrs.push_back(m);
110 }).Default([](Type) {});
121static LogicalResult verifyInitialValues(
122 ValueRange values, ArrayRef<Attribute>
names,
PodType retTy,
123 llvm::function_ref<InFlightDiagnostic()> emitError
126 if (
names.size() != values.size()) {
127 emitError() <<
"number of initialized records and initial values does not match ("
128 <<
names.size() <<
" != " << values.size() <<
")";
132 llvm::StringMap<Type> records = retTy.getRecordMap();
133 llvm::StringSet<> seenNames;
134 for (
auto [nameAttr, value] : llvm::zip_equal(
names, values)) {
135 auto name = llvm::cast<StringAttr>(nameAttr).getValue();
136 if (seenNames.contains(name)) {
137 emitError() <<
"found duplicated record name '" << name <<
'\'';
140 seenNames.insert(name);
142 if (!records.contains(name)) {
143 emitError() <<
"record '" << name <<
"' is not part of the struct";
148 auto valueTy = value.getType();
149 auto recordTy = records.at(name);
150 if (valueTy != recordTy) {
151 auto err = emitError();
152 err <<
"record '" << name <<
"' expected type " << recordTy <<
" but got " << valueTy;
155 <<
"types " << valueTy <<
" and " << recordTy
156 <<
" can be unified. Perhaps you can add a 'poly.unifiable_cast' operation?";
162 return failure(failed);
165static LogicalResult verifyAffineMapOperands(
NewPodOp *op, Type retTy) {
166 SmallVector<AffineMapAttr> mapAttrs;
167 collectMapAttrs(retTy, mapAttrs);
169 op->getMapOperands(), op->getNumDimsPerMap(), mapAttrs, *op
177 failed = failed || mlir::failed(x); \
181 auto retTy = llvm::dyn_cast<PodType>(
getResult().getType());
187 return this->emitError();
190 check(verifyAffineMapOperands(
this, retTy));
192 return failure(failed);
201 if (failed(parser.parseSymbolName(name))) {
205 if (parser.parseEqual()) {
208 return parser.parseOperand(operand);
221 SmallVector<Attribute> initializedRecords;
224 llvm::StringMap<UnresolvedOp> initialValuesOperands;
225 auto parseElementFn = [&parser, &initializedRecords, &initialValuesOperands] {
231 initializedRecords.push_back(name);
232 initialValuesOperands.insert({name.getValue(), operand});
235 auto initialValuesLoc = parser.getCurrentLocation();
236 if (parser.parseCommaSeparatedList(AsmParser::Delimiter::OptionalBraces, parseElementFn)) {
239 SmallVector<int32_t> mapOperandsGroupSizes;
240 SmallVector<UnresolvedOp> allMapOperands;
241 Type indexTy = parser.getBuilder().getIndexType();
242 bool colonAlreadyParsed =
true;
243 auto mapOperandsLoc = parser.getCurrentLocation();
246 if (failed(parser.parseOptionalColon())) {
247 colonAlreadyParsed =
false;
248 SmallVector<SmallVector<UnresolvedOp>> mapOperands {};
253 mapOperandsGroupSizes.reserve(mapOperands.size());
254 for (
const auto &subRange : mapOperands) {
255 allMapOperands.append(subRange.begin(), subRange.end());
260 if (!colonAlreadyParsed && parser.parseColon()) {
265 if (parser.parseCustomTypeWithFallback(resultType)) {
270 for (
auto attr : initializedRecords) {
271 auto name = llvm::cast<StringAttr>(attr);
272 auto lookup = resultType.
getRecord(name.getValue(), [&parser, initialValuesLoc] {
273 return parser.emitError(initialValuesLoc);
275 if (failed(lookup)) {
278 const auto &operand = initialValuesOperands.at(name.getValue());
279 if (failed(parser.resolveOperands({operand}, *lookup, initialValuesLoc, result.operands))) {
283 props.operandSegmentSizes = {
287 props.mapOpGroupSizes = parser.getBuilder().getDenseI32ArrayAttr(mapOperandsGroupSizes);
288 props.initializedRecords = parser.getBuilder().getArrayAttr(initializedRecords);
289 result.addTypes({resultType});
291 if (failed(parser.resolveOperands(allMapOperands, indexTy, mapOperandsLoc, result.operands))) {
295 auto loc = parser.getCurrentLocation();
296 if (parser.parseOptionalAttrDict(result.attributes)) {
300 return parser.emitError(loc) <<
'\'' << result.name.getStringRef() <<
"' op ";
310 auto &os = printer.getStream();
312 if (!initializedRecords.empty()) {
314 llvm::interleaveComma(initializedRecords, os, [&os, &printer](
auto record) {
315 printer.printSymbolName(record.name);
317 printer.printOperand(record.value);
326 if (
auto validType = llvm::dyn_cast<PodType>(type)) {
327 printer.printStrippedAttrOrType(validType);
329 printer.printType(type);
332 printer.printOptionalAttrDict(
334 {
"initializedRecords",
"mapOpGroupSizes",
"numDimsPerMap",
"operandSegmentSizes"}
339 return llvm::map_to_vector(
341 auto [value, name] = pair;
342 return RecordValue {.name = llvm::cast<StringAttr>(name).getValue(), .value = value};
352 auto podTy = llvm::dyn_cast<PodType>(
getPodRef().getType());
354 return emitError() <<
"reference operand expected a plain-old-data struct but got "
358 auto lookup = podTy.getRecord(
getRecordName(), [
this]() {
return this->emitError(); });
359 if (failed(lookup)) {
364 return emitError() <<
"operation result type and type of record do not match ("
365 <<
getResult().getType() <<
" != " << *lookup <<
")";
376 auto podTy = llvm::dyn_cast<PodType>(
getPodRef().getType());
378 return emitError() <<
"reference operand expected a plain-old-data struct but got "
382 auto lookup = podTy.getRecord(
getRecordName(), [
this]() {
return this->emitError(); });
383 if (failed(lookup)) {
387 if (
getValue().getType() != *lookup) {
388 return emitError() <<
"type of source value and type of record do not match ("
389 <<
getValue().getType() <<
" != " << *lookup <<
")";
400 return parser.parseCustomAttributeWithFallback(name);
404 printer.printSymbolName(name.getValue());
within a display generated by the Derivative if and wherever such third party notices normally appear The contents of the NOTICE file are for informational purposes only and do not modify the License You may add Your own attribution notices within Derivative Works that You alongside or as an addendum to the NOTICE text from the provided that such additional attribution notices cannot be construed as modifying the License You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for or distribution of Your or for any such Derivative Works as a provided Your and distribution of the Work otherwise complies with the conditions stated in this License Submission of Contributions Unless You explicitly state any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this without any additional terms or conditions Notwithstanding the nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions Trademarks This License does not grant permission to use the trade names
void print(::mlir::OpAsmPrinter &p)
::mlir::Operation::operand_range getInitialValues()
::mlir::OperandRangeRange getMapOperands()
::mlir::SmallVector<::llzk::pod::RecordValue > getInitializedRecordValues()
static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::llzk::pod::InitializedRecords initialValues={})
::mlir::DenseI32ArrayAttr getNumDimsPerMapAttr()
::mlir::TypedValue<::llzk::pod::PodType > getResult()
void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn)
FoldAdaptor::Properties Properties
::llvm::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> emitError)
::llvm::LogicalResult verify()
::mlir::ArrayAttr getInitializedRecords()
::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result)
::llvm::FailureOr<::mlir::Type > getRecord(::llvm::StringRef name, ::llvm::function_ref<::mlir::InFlightDiagnostic()>) const
Searches a record by name.
::llvm::ArrayRef<::llzk::pod::RecordAttr > getRecords() const
::llvm::StringRef getRecordName()
::mlir::TypedValue<::mlir::Type > getResult()
::llvm::LogicalResult verify()
::mlir::TypedValue<::llzk::pod::PodType > getPodRef()
::llvm::LogicalResult verify()
::mlir::TypedValue<::mlir::Type > getValue()
::mlir::TypedValue<::llzk::pod::PodType > getPodRef()
::llvm::StringRef getRecordName()
OpClass::Properties & buildInstantiationAttrs(mlir::OpBuilder &odsBuilder, mlir::OperationState &odsState, mlir::ArrayRef< mlir::ValueRange > mapOperands, mlir::DenseI32ArrayAttr numDimsPerMap, int32_t firstSegmentSize=0)
Utility for build() functions that initializes the operandSegmentSizes, mapOpGroupSizes,...
LogicalResult verifyAffineMapInstantiations(OperandRangeRange mapOps, ArrayRef< int32_t > numDimsPerMap, ArrayRef< AffineMapAttr > mapAttrs, Operation *origin)
OpClass::Properties & buildInstantiationAttrsEmpty(mlir::OpBuilder &odsBuilder, mlir::OperationState &odsState, int32_t firstSegmentSize=0)
Utility for build() functions that initializes the operandSegmentSizes, mapOpGroupSizes,...
mlir::ArrayRef< RecordValue > InitializedRecords
OpAsmParser::UnresolvedOperand UnresolvedOp
ParseResult parseRecordName(AsmParser &parser, FlatSymbolRefAttr &name)
ParseResult parseRecordInitialization(OpAsmParser &parser, StringAttr &name, UnresolvedOp &operand)
void printRecordName(AsmPrinter &printer, Operation *, FlatSymbolRefAttr name)
constexpr T checkedCast(U u) noexcept
void printMultiDimAndSymbolList(mlir::OpAsmPrinter &printer, mlir::Operation *op, mlir::OperandRangeRange multiMapOperands, mlir::DenseI32ArrayAttr numDimsPerMap)
bool typesUnify(Type lhs, Type rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
mlir::ParseResult parseMultiDimAndSymbolList(mlir::OpAsmParser &parser, mlir::SmallVector< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &multiMapOperands, mlir::DenseI32ArrayAttr &numDimsPerMap)
void setInitializedRecords(const ::mlir::ArrayAttr &propValue)