183ef862fSRiver Riddle //===- TestAttributes.cpp - MLIR Test Dialect Attributes --------*- C++ -*-===// 283ef862fSRiver Riddle // 383ef862fSRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 483ef862fSRiver Riddle // See https://llvm.org/LICENSE.txt for license information. 583ef862fSRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 683ef862fSRiver Riddle // 783ef862fSRiver Riddle //===----------------------------------------------------------------------===// 883ef862fSRiver Riddle // 983ef862fSRiver Riddle // This file contains attributes defined by the TestDialect for testing various 1083ef862fSRiver Riddle // features of MLIR. 1183ef862fSRiver Riddle // 1283ef862fSRiver Riddle //===----------------------------------------------------------------------===// 1383ef862fSRiver Riddle 1483ef862fSRiver Riddle #include "TestAttributes.h" 1583ef862fSRiver Riddle #include "TestDialect.h" 16*690dc4efSquartersdg #include "TestTypes.h" 17*690dc4efSquartersdg #include "mlir/IR/Attributes.h" 1883ef862fSRiver Riddle #include "mlir/IR/Builders.h" 1983ef862fSRiver Riddle #include "mlir/IR/DialectImplementation.h" 209e0b5533SMathieu Fehr #include "mlir/IR/ExtensibleDialect.h" 21*690dc4efSquartersdg #include "mlir/IR/OpImplementation.h" 2283ef862fSRiver Riddle #include "mlir/IR/Types.h" 231e3c630fSorbiri #include "llvm/ADT/APFloat.h" 2483ef862fSRiver Riddle #include "llvm/ADT/Hashing.h" 25e95e94adSJeff Niu #include "llvm/ADT/StringExtras.h" 2683ef862fSRiver Riddle #include "llvm/ADT/TypeSwitch.h" 279a2fdc36SJeff Niu #include "llvm/ADT/bit.h" 289e0b5533SMathieu Fehr #include "llvm/Support/ErrorHandling.h" 295fc28e7aSMehdi Amini #include "llvm/Support/raw_ostream.h" 3083ef862fSRiver Riddle 3183ef862fSRiver Riddle using namespace mlir; 327776b19eSStephen Neuendorffer using namespace test; 3383ef862fSRiver Riddle 341447ec51SRiver Riddle //===----------------------------------------------------------------------===// 351447ec51SRiver Riddle // CompoundAAttr 361447ec51SRiver Riddle //===----------------------------------------------------------------------===// 371447ec51SRiver Riddle 38f97e72aaSMehdi Amini Attribute CompoundAAttr::parse(AsmParser &parser, Type type) { 3983ef862fSRiver Riddle int widthOfSomething; 4083ef862fSRiver Riddle Type oneType; 4183ef862fSRiver Riddle SmallVector<int, 4> arrayOfInts; 4283ef862fSRiver Riddle if (parser.parseLess() || parser.parseInteger(widthOfSomething) || 4383ef862fSRiver Riddle parser.parseComma() || parser.parseType(oneType) || parser.parseComma() || 4483ef862fSRiver Riddle parser.parseLSquare()) 4583ef862fSRiver Riddle return Attribute(); 4683ef862fSRiver Riddle 4783ef862fSRiver Riddle int intVal; 4883ef862fSRiver Riddle while (!*parser.parseOptionalInteger(intVal)) { 4983ef862fSRiver Riddle arrayOfInts.push_back(intVal); 5083ef862fSRiver Riddle if (parser.parseOptionalComma()) 5183ef862fSRiver Riddle break; 5283ef862fSRiver Riddle } 5383ef862fSRiver Riddle 5483ef862fSRiver Riddle if (parser.parseRSquare() || parser.parseGreater()) 5583ef862fSRiver Riddle return Attribute(); 56fb093c83SChris Lattner return get(parser.getContext(), widthOfSomething, oneType, arrayOfInts); 5783ef862fSRiver Riddle } 5883ef862fSRiver Riddle 59f97e72aaSMehdi Amini void CompoundAAttr::print(AsmPrinter &printer) const { 60f30a8a6fSMehdi Amini printer << "<" << getWidthOfSomething() << ", " << getOneType() << ", ["; 6183ef862fSRiver Riddle llvm::interleaveComma(getArrayOfInts(), printer); 6283ef862fSRiver Riddle printer << "]>"; 6383ef862fSRiver Riddle } 6483ef862fSRiver Riddle 6583ef862fSRiver Riddle //===----------------------------------------------------------------------===// 66d80d3a35SRiver Riddle // CompoundAAttr 67d80d3a35SRiver Riddle //===----------------------------------------------------------------------===// 68d80d3a35SRiver Riddle 69*690dc4efSquartersdg Attribute TestDecimalShapeAttr::parse(AsmParser &parser, Type type) { 70*690dc4efSquartersdg if (parser.parseLess()){ 71*690dc4efSquartersdg return Attribute(); 72*690dc4efSquartersdg } 73*690dc4efSquartersdg SmallVector<int64_t> shape; 74*690dc4efSquartersdg if (parser.parseOptionalGreater()) { 75*690dc4efSquartersdg auto parseDecimal = [&]() { 76*690dc4efSquartersdg shape.emplace_back(); 77*690dc4efSquartersdg auto parseResult = parser.parseOptionalDecimalInteger(shape.back()); 78*690dc4efSquartersdg if (!parseResult.has_value() || failed(*parseResult)) { 79*690dc4efSquartersdg parser.emitError(parser.getCurrentLocation()) << "expected an integer"; 80*690dc4efSquartersdg return failure(); 81*690dc4efSquartersdg } 82*690dc4efSquartersdg return success(); 83*690dc4efSquartersdg }; 84*690dc4efSquartersdg if (failed(parseDecimal())) { 85*690dc4efSquartersdg return Attribute(); 86*690dc4efSquartersdg } 87*690dc4efSquartersdg while (failed(parser.parseOptionalGreater())) { 88*690dc4efSquartersdg if (failed(parser.parseXInDimensionList()) || failed(parseDecimal())) { 89*690dc4efSquartersdg return Attribute(); 90*690dc4efSquartersdg } 91*690dc4efSquartersdg } 92*690dc4efSquartersdg } 93*690dc4efSquartersdg return get(parser.getContext(), shape); 94*690dc4efSquartersdg } 95*690dc4efSquartersdg 96*690dc4efSquartersdg void TestDecimalShapeAttr::print(AsmPrinter &printer) const { 97*690dc4efSquartersdg printer << "<"; 98*690dc4efSquartersdg llvm::interleave(getShape(), printer, "x"); 99*690dc4efSquartersdg printer << ">"; 100*690dc4efSquartersdg } 101*690dc4efSquartersdg 102f97e72aaSMehdi Amini Attribute TestI64ElementsAttr::parse(AsmParser &parser, Type type) { 103d80d3a35SRiver Riddle SmallVector<uint64_t> elements; 104d80d3a35SRiver Riddle if (parser.parseLess() || parser.parseLSquare()) 105d80d3a35SRiver Riddle return Attribute(); 106d80d3a35SRiver Riddle uint64_t intVal; 107d80d3a35SRiver Riddle while (succeeded(*parser.parseOptionalInteger(intVal))) { 108d80d3a35SRiver Riddle elements.push_back(intVal); 109d80d3a35SRiver Riddle if (parser.parseOptionalComma()) 110d80d3a35SRiver Riddle break; 111d80d3a35SRiver Riddle } 112d80d3a35SRiver Riddle 113d80d3a35SRiver Riddle if (parser.parseRSquare() || parser.parseGreater()) 114d80d3a35SRiver Riddle return Attribute(); 115d80d3a35SRiver Riddle return parser.getChecked<TestI64ElementsAttr>( 116c1fa60b4STres Popp parser.getContext(), llvm::cast<ShapedType>(type), elements); 117d80d3a35SRiver Riddle } 118d80d3a35SRiver Riddle 119f97e72aaSMehdi Amini void TestI64ElementsAttr::print(AsmPrinter &printer) const { 120f30a8a6fSMehdi Amini printer << "<["; 121d80d3a35SRiver Riddle llvm::interleaveComma(getElements(), printer); 122bc6b5be6SMatteo Franciolini printer << "]>"; 123d80d3a35SRiver Riddle } 124d80d3a35SRiver Riddle 125d80d3a35SRiver Riddle LogicalResult 126d80d3a35SRiver Riddle TestI64ElementsAttr::verify(function_ref<InFlightDiagnostic()> emitError, 127d80d3a35SRiver Riddle ShapedType type, ArrayRef<uint64_t> elements) { 128d80d3a35SRiver Riddle if (type.getNumElements() != static_cast<int64_t>(elements.size())) { 129d80d3a35SRiver Riddle return emitError() 130d80d3a35SRiver Riddle << "number of elements does not match the provided shape type, got: " 131d80d3a35SRiver Riddle << elements.size() << ", but expected: " << type.getNumElements(); 132d80d3a35SRiver Riddle } 133d80d3a35SRiver Riddle if (type.getRank() != 1 || !type.getElementType().isSignlessInteger(64)) 134d80d3a35SRiver Riddle return emitError() << "expected single rank 64-bit shape type, but got: " 135d80d3a35SRiver Riddle << type; 136d80d3a35SRiver Riddle return success(); 137d80d3a35SRiver Riddle } 138d80d3a35SRiver Riddle 139a71bc5f5Srkayaith LogicalResult TestAttrWithFormatAttr::verify( 140a71bc5f5Srkayaith function_ref<InFlightDiagnostic()> emitError, int64_t one, std::string two, 141a71bc5f5Srkayaith IntegerAttr three, ArrayRef<int> four, uint64_t five, ArrayRef<int> six, 142e1795322SJeff Niu ArrayRef<AttrWithTypeBuilderAttr> arrayOfAttrs) { 1439a2fdc36SJeff Niu if (four.size() != static_cast<unsigned>(one)) 1449a2fdc36SJeff Niu return emitError() << "expected 'one' to equal 'four.size()'"; 1459a2fdc36SJeff Niu return success(); 1469a2fdc36SJeff Niu } 1479a2fdc36SJeff Niu 1489a2fdc36SJeff Niu //===----------------------------------------------------------------------===// 1499a2fdc36SJeff Niu // Utility Functions for Generated Attributes 1509a2fdc36SJeff Niu //===----------------------------------------------------------------------===// 1519a2fdc36SJeff Niu 152f97e72aaSMehdi Amini static FailureOr<SmallVector<int>> parseIntArray(AsmParser &parser) { 1539a2fdc36SJeff Niu SmallVector<int> ints; 1549a2fdc36SJeff Niu if (parser.parseLSquare() || parser.parseCommaSeparatedList([&]() { 1559a2fdc36SJeff Niu ints.push_back(0); 1569a2fdc36SJeff Niu return parser.parseInteger(ints.back()); 1579a2fdc36SJeff Niu }) || 1589a2fdc36SJeff Niu parser.parseRSquare()) 1599a2fdc36SJeff Niu return failure(); 1609a2fdc36SJeff Niu return ints; 1619a2fdc36SJeff Niu } 1629a2fdc36SJeff Niu 163f97e72aaSMehdi Amini static void printIntArray(AsmPrinter &printer, ArrayRef<int> ints) { 1649a2fdc36SJeff Niu printer << '['; 1659a2fdc36SJeff Niu llvm::interleaveComma(ints, printer); 1669a2fdc36SJeff Niu printer << ']'; 1679a2fdc36SJeff Niu } 1689a2fdc36SJeff Niu 169d80d3a35SRiver Riddle //===----------------------------------------------------------------------===// 17010a80c44SMarkus Böck // TestSubElementsAccessAttr 17110a80c44SMarkus Böck //===----------------------------------------------------------------------===// 17210a80c44SMarkus Böck 173f97e72aaSMehdi Amini Attribute TestSubElementsAccessAttr::parse(::mlir::AsmParser &parser, 17410a80c44SMarkus Böck ::mlir::Type type) { 17510a80c44SMarkus Böck Attribute first, second, third; 17610a80c44SMarkus Böck if (parser.parseLess() || parser.parseAttribute(first) || 17710a80c44SMarkus Böck parser.parseComma() || parser.parseAttribute(second) || 17810a80c44SMarkus Böck parser.parseComma() || parser.parseAttribute(third) || 17910a80c44SMarkus Böck parser.parseGreater()) { 18010a80c44SMarkus Böck return {}; 18110a80c44SMarkus Böck } 18210a80c44SMarkus Böck return get(parser.getContext(), first, second, third); 18310a80c44SMarkus Böck } 18410a80c44SMarkus Böck 185f97e72aaSMehdi Amini void TestSubElementsAccessAttr::print(::mlir::AsmPrinter &printer) const { 186f30a8a6fSMehdi Amini printer << "<" << getFirst() << ", " << getSecond() << ", " << getThird() 187f30a8a6fSMehdi Amini << ">"; 18810a80c44SMarkus Böck } 18910a80c44SMarkus Böck 19010a80c44SMarkus Böck //===----------------------------------------------------------------------===// 191ea488bd6SRiver Riddle // TestExtern1DI64ElementsAttr 192ea488bd6SRiver Riddle //===----------------------------------------------------------------------===// 193ea488bd6SRiver Riddle 194ea488bd6SRiver Riddle ArrayRef<uint64_t> TestExtern1DI64ElementsAttr::getElements() const { 1955f58e14bSRiver Riddle if (auto *blob = getHandle().getBlob()) 1965f58e14bSRiver Riddle return blob->getDataAs<uint64_t>(); 1971a36588eSKazu Hirata return std::nullopt; 198ea488bd6SRiver Riddle } 199ea488bd6SRiver Riddle 200ea488bd6SRiver Riddle //===----------------------------------------------------------------------===// 201e936c3bbSJeff Niu // TestCustomAnchorAttr 202e936c3bbSJeff Niu //===----------------------------------------------------------------------===// 203e936c3bbSJeff Niu 204715b0258SMarkus Böck static ParseResult parseTrueFalse(AsmParser &p, std::optional<int> &result) { 205e936c3bbSJeff Niu bool b; 206e936c3bbSJeff Niu if (p.parseInteger(b)) 207e936c3bbSJeff Niu return failure(); 208715b0258SMarkus Böck result = b; 209e936c3bbSJeff Niu return success(); 210e936c3bbSJeff Niu } 211e936c3bbSJeff Niu 212e8bcc37fSRamkumar Ramachandra static void printTrueFalse(AsmPrinter &p, std::optional<int> result) { 213e936c3bbSJeff Niu p << (*result ? "true" : "false"); 214e936c3bbSJeff Niu } 215e936c3bbSJeff Niu 216e936c3bbSJeff Niu //===----------------------------------------------------------------------===// 2175fc28e7aSMehdi Amini // CopyCountAttr Implementation 2185fc28e7aSMehdi Amini //===----------------------------------------------------------------------===// 2195fc28e7aSMehdi Amini 2205fc28e7aSMehdi Amini CopyCount::CopyCount(const CopyCount &rhs) : value(rhs.value) { 2215fc28e7aSMehdi Amini CopyCount::counter++; 2225fc28e7aSMehdi Amini } 2235fc28e7aSMehdi Amini 2245fc28e7aSMehdi Amini CopyCount &CopyCount::operator=(const CopyCount &rhs) { 2255fc28e7aSMehdi Amini CopyCount::counter++; 2265fc28e7aSMehdi Amini value = rhs.value; 2275fc28e7aSMehdi Amini return *this; 2285fc28e7aSMehdi Amini } 2295fc28e7aSMehdi Amini 2305fc28e7aSMehdi Amini int CopyCount::counter; 2315fc28e7aSMehdi Amini 2325fc28e7aSMehdi Amini static bool operator==(const test::CopyCount &lhs, const test::CopyCount &rhs) { 2335fc28e7aSMehdi Amini return lhs.value == rhs.value; 2345fc28e7aSMehdi Amini } 2355fc28e7aSMehdi Amini 2365fc28e7aSMehdi Amini llvm::raw_ostream &test::operator<<(llvm::raw_ostream &os, 2375fc28e7aSMehdi Amini const test::CopyCount &value) { 2385fc28e7aSMehdi Amini return os << value.value; 2395fc28e7aSMehdi Amini } 2405fc28e7aSMehdi Amini 2415fc28e7aSMehdi Amini template <> 2425fc28e7aSMehdi Amini struct mlir::FieldParser<test::CopyCount> { 2435fc28e7aSMehdi Amini static FailureOr<test::CopyCount> parse(AsmParser &parser) { 2445fc28e7aSMehdi Amini std::string value; 2455fc28e7aSMehdi Amini if (parser.parseKeyword(value)) 2465fc28e7aSMehdi Amini return failure(); 2475fc28e7aSMehdi Amini return test::CopyCount(value); 2485fc28e7aSMehdi Amini } 2495fc28e7aSMehdi Amini }; 2505fc28e7aSMehdi Amini namespace test { 2515fc28e7aSMehdi Amini llvm::hash_code hash_value(const test::CopyCount ©Count) { 2525fc28e7aSMehdi Amini return llvm::hash_value(copyCount.value); 2535fc28e7aSMehdi Amini } 2545fc28e7aSMehdi Amini } // namespace test 255df1e01b3SJeff Niu 256df1e01b3SJeff Niu //===----------------------------------------------------------------------===// 257df1e01b3SJeff Niu // TestConditionalAliasAttr 258df1e01b3SJeff Niu //===----------------------------------------------------------------------===// 259df1e01b3SJeff Niu 260df1e01b3SJeff Niu /// Attempt to parse the conditionally-aliased string attribute as a keyword or 261df1e01b3SJeff Niu /// string, else try to parse an alias. 262df1e01b3SJeff Niu static ParseResult parseConditionalAlias(AsmParser &p, StringAttr &value) { 263df1e01b3SJeff Niu std::string str; 264df1e01b3SJeff Niu if (succeeded(p.parseOptionalKeywordOrString(&str))) { 265df1e01b3SJeff Niu value = StringAttr::get(p.getContext(), str); 266df1e01b3SJeff Niu return success(); 267df1e01b3SJeff Niu } 268df1e01b3SJeff Niu return p.parseAttribute(value); 269df1e01b3SJeff Niu } 270df1e01b3SJeff Niu 271df1e01b3SJeff Niu /// Print the string attribute as an alias if it has one, otherwise print it as 272df1e01b3SJeff Niu /// a keyword if possible. 273df1e01b3SJeff Niu static void printConditionalAlias(AsmPrinter &p, StringAttr value) { 274df1e01b3SJeff Niu if (succeeded(p.printAlias(value))) 275df1e01b3SJeff Niu return; 276df1e01b3SJeff Niu p.printKeywordOrString(value); 277df1e01b3SJeff Niu } 278df1e01b3SJeff Niu 2795fc28e7aSMehdi Amini //===----------------------------------------------------------------------===// 2801e3c630fSorbiri // Custom Float Attribute 2811e3c630fSorbiri //===----------------------------------------------------------------------===// 2821e3c630fSorbiri 2831e3c630fSorbiri static void printCustomFloatAttr(AsmPrinter &p, StringAttr typeStrAttr, 2841e3c630fSorbiri APFloat value) { 2851e3c630fSorbiri p << typeStrAttr << " : " << value; 2861e3c630fSorbiri } 2871e3c630fSorbiri 2881e3c630fSorbiri static ParseResult parseCustomFloatAttr(AsmParser &p, StringAttr &typeStrAttr, 2891e3c630fSorbiri FailureOr<APFloat> &value) { 2901e3c630fSorbiri 2911e3c630fSorbiri std::string str; 2921e3c630fSorbiri if (p.parseString(&str)) 2931e3c630fSorbiri return failure(); 2941e3c630fSorbiri 2951e3c630fSorbiri typeStrAttr = StringAttr::get(p.getContext(), str); 2961e3c630fSorbiri 2971e3c630fSorbiri if (p.parseColon()) 2981e3c630fSorbiri return failure(); 2991e3c630fSorbiri 3001e3c630fSorbiri const llvm::fltSemantics *semantics; 3011e3c630fSorbiri if (str == "float") 3021e3c630fSorbiri semantics = &llvm::APFloat::IEEEsingle(); 3031e3c630fSorbiri else if (str == "double") 3041e3c630fSorbiri semantics = &llvm::APFloat::IEEEdouble(); 3051e3c630fSorbiri else if (str == "fp80") 3061e3c630fSorbiri semantics = &llvm::APFloat::x87DoubleExtended(); 3071e3c630fSorbiri else 3081e3c630fSorbiri return p.emitError(p.getCurrentLocation(), "unknown float type, expected " 3091e3c630fSorbiri "'float', 'double' or 'fp80'"); 3101e3c630fSorbiri 3111e3c630fSorbiri APFloat parsedValue(0.0); 3121e3c630fSorbiri if (p.parseFloat(*semantics, parsedValue)) 3131e3c630fSorbiri return failure(); 3141e3c630fSorbiri 3151e3c630fSorbiri value.emplace(parsedValue); 3161e3c630fSorbiri return success(); 3171e3c630fSorbiri } 3181e3c630fSorbiri 3191e3c630fSorbiri //===----------------------------------------------------------------------===// 32083ef862fSRiver Riddle // Tablegen Generated Definitions 32183ef862fSRiver Riddle //===----------------------------------------------------------------------===// 32283ef862fSRiver Riddle 3239b2a1bcfSAlex Zinenko #include "TestAttrInterfaces.cpp.inc" 324e95e94adSJeff Niu #include "TestOpEnums.cpp.inc" 32583ef862fSRiver Riddle #define GET_ATTRDEF_CLASSES 32683ef862fSRiver Riddle #include "TestAttrDefs.cpp.inc" 32783ef862fSRiver Riddle 32883ef862fSRiver Riddle //===----------------------------------------------------------------------===// 3299e0b5533SMathieu Fehr // Dynamic Attributes 3309e0b5533SMathieu Fehr //===----------------------------------------------------------------------===// 3319e0b5533SMathieu Fehr 3329e0b5533SMathieu Fehr /// Define a singleton dynamic attribute. 3339e0b5533SMathieu Fehr static std::unique_ptr<DynamicAttrDefinition> 3349e0b5533SMathieu Fehr getDynamicSingletonAttr(TestDialect *testDialect) { 3359e0b5533SMathieu Fehr return DynamicAttrDefinition::get( 3369e0b5533SMathieu Fehr "dynamic_singleton", testDialect, 3379e0b5533SMathieu Fehr [](function_ref<InFlightDiagnostic()> emitError, 3389e0b5533SMathieu Fehr ArrayRef<Attribute> args) { 3399e0b5533SMathieu Fehr if (!args.empty()) { 3409e0b5533SMathieu Fehr emitError() << "expected 0 attribute arguments, but had " 3419e0b5533SMathieu Fehr << args.size(); 3429e0b5533SMathieu Fehr return failure(); 3439e0b5533SMathieu Fehr } 3449e0b5533SMathieu Fehr return success(); 3459e0b5533SMathieu Fehr }); 3469e0b5533SMathieu Fehr } 3479e0b5533SMathieu Fehr 3489e0b5533SMathieu Fehr /// Define a dynamic attribute representing a pair or attributes. 3499e0b5533SMathieu Fehr static std::unique_ptr<DynamicAttrDefinition> 3509e0b5533SMathieu Fehr getDynamicPairAttr(TestDialect *testDialect) { 3519e0b5533SMathieu Fehr return DynamicAttrDefinition::get( 3529e0b5533SMathieu Fehr "dynamic_pair", testDialect, 3539e0b5533SMathieu Fehr [](function_ref<InFlightDiagnostic()> emitError, 3549e0b5533SMathieu Fehr ArrayRef<Attribute> args) { 3559e0b5533SMathieu Fehr if (args.size() != 2) { 3569e0b5533SMathieu Fehr emitError() << "expected 2 attribute arguments, but had " 3579e0b5533SMathieu Fehr << args.size(); 3589e0b5533SMathieu Fehr return failure(); 3599e0b5533SMathieu Fehr } 3609e0b5533SMathieu Fehr return success(); 3619e0b5533SMathieu Fehr }); 3629e0b5533SMathieu Fehr } 3639e0b5533SMathieu Fehr 3649e0b5533SMathieu Fehr static std::unique_ptr<DynamicAttrDefinition> 3659e0b5533SMathieu Fehr getDynamicCustomAssemblyFormatAttr(TestDialect *testDialect) { 3669e0b5533SMathieu Fehr auto verifier = [](function_ref<InFlightDiagnostic()> emitError, 3679e0b5533SMathieu Fehr ArrayRef<Attribute> args) { 3689e0b5533SMathieu Fehr if (args.size() != 2) { 3699e0b5533SMathieu Fehr emitError() << "expected 2 attribute arguments, but had " << args.size(); 3709e0b5533SMathieu Fehr return failure(); 3719e0b5533SMathieu Fehr } 3729e0b5533SMathieu Fehr return success(); 3739e0b5533SMathieu Fehr }; 3749e0b5533SMathieu Fehr 3759e0b5533SMathieu Fehr auto parser = [](AsmParser &parser, 3769e0b5533SMathieu Fehr llvm::SmallVectorImpl<Attribute> &parsedParams) { 3779e0b5533SMathieu Fehr Attribute leftAttr, rightAttr; 3789e0b5533SMathieu Fehr if (parser.parseLess() || parser.parseAttribute(leftAttr) || 3799e0b5533SMathieu Fehr parser.parseColon() || parser.parseAttribute(rightAttr) || 3809e0b5533SMathieu Fehr parser.parseGreater()) 3819e0b5533SMathieu Fehr return failure(); 3829e0b5533SMathieu Fehr parsedParams.push_back(leftAttr); 3839e0b5533SMathieu Fehr parsedParams.push_back(rightAttr); 3849e0b5533SMathieu Fehr return success(); 3859e0b5533SMathieu Fehr }; 3869e0b5533SMathieu Fehr 3879e0b5533SMathieu Fehr auto printer = [](AsmPrinter &printer, ArrayRef<Attribute> params) { 3889e0b5533SMathieu Fehr printer << "<" << params[0] << ":" << params[1] << ">"; 3899e0b5533SMathieu Fehr }; 3909e0b5533SMathieu Fehr 3919e0b5533SMathieu Fehr return DynamicAttrDefinition::get("dynamic_custom_assembly_format", 3929e0b5533SMathieu Fehr testDialect, std::move(verifier), 3939e0b5533SMathieu Fehr std::move(parser), std::move(printer)); 3949e0b5533SMathieu Fehr } 3959e0b5533SMathieu Fehr 3969e0b5533SMathieu Fehr //===----------------------------------------------------------------------===// 39783ef862fSRiver Riddle // TestDialect 39883ef862fSRiver Riddle //===----------------------------------------------------------------------===// 39983ef862fSRiver Riddle 40031bb8efdSRiver Riddle void TestDialect::registerAttributes() { 40131bb8efdSRiver Riddle addAttributes< 40231bb8efdSRiver Riddle #define GET_ATTRDEF_LIST 40331bb8efdSRiver Riddle #include "TestAttrDefs.cpp.inc" 40431bb8efdSRiver Riddle >(); 4059e0b5533SMathieu Fehr registerDynamicAttr(getDynamicSingletonAttr(this)); 4069e0b5533SMathieu Fehr registerDynamicAttr(getDynamicPairAttr(this)); 4079e0b5533SMathieu Fehr registerDynamicAttr(getDynamicCustomAssemblyFormatAttr(this)); 40831bb8efdSRiver Riddle } 409