brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.2 KiB · 9db7b01 Raw
575 lines · cpp
1//===- TestAttributes.cpp - MLIR Test Dialect Attributes --------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains attributes defined by the TestDialect for testing various10// features of MLIR.11//12//===----------------------------------------------------------------------===//13 14#include "TestAttributes.h"15#include "TestDialect.h"16#include "TestTypes.h"17#include "mlir/IR/Attributes.h"18#include "mlir/IR/Builders.h"19#include "mlir/IR/DialectImplementation.h"20#include "mlir/IR/ExtensibleDialect.h"21#include "mlir/IR/OpImplementation.h"22#include "mlir/IR/Types.h"23#include "llvm/ADT/APFloat.h"24#include "llvm/ADT/Hashing.h"25#include "llvm/ADT/StringExtras.h"26#include "llvm/ADT/TypeSwitch.h"27#include "llvm/ADT/bit.h"28#include "llvm/Support/ErrorHandling.h"29#include "llvm/Support/raw_ostream.h"30 31using namespace mlir;32using namespace test;33 34//===----------------------------------------------------------------------===//35// CompoundAAttr36//===----------------------------------------------------------------------===//37 38Attribute CompoundAAttr::parse(AsmParser &parser, Type type) {39  int widthOfSomething;40  Type oneType;41  SmallVector<int, 4> arrayOfInts;42  if (parser.parseLess() || parser.parseInteger(widthOfSomething) ||43      parser.parseComma() || parser.parseType(oneType) || parser.parseComma() ||44      parser.parseLSquare())45    return Attribute();46 47  int intVal;48  while (!*parser.parseOptionalInteger(intVal)) {49    arrayOfInts.push_back(intVal);50    if (parser.parseOptionalComma())51      break;52  }53 54  if (parser.parseRSquare() || parser.parseGreater())55    return Attribute();56  return get(parser.getContext(), widthOfSomething, oneType, arrayOfInts);57}58 59void CompoundAAttr::print(AsmPrinter &printer) const {60  printer << "<" << getWidthOfSomething() << ", " << getOneType() << ", [";61  llvm::interleaveComma(getArrayOfInts(), printer);62  printer << "]>";63}64 65//===----------------------------------------------------------------------===//66// CompoundAAttr67//===----------------------------------------------------------------------===//68 69Attribute TestDecimalShapeAttr::parse(AsmParser &parser, Type type) {70  if (parser.parseLess()) {71    return Attribute();72  }73  SmallVector<int64_t> shape;74  if (parser.parseOptionalGreater()) {75    auto parseDecimal = [&]() {76      shape.emplace_back();77      auto parseResult = parser.parseOptionalDecimalInteger(shape.back());78      if (!parseResult.has_value() || failed(*parseResult)) {79        parser.emitError(parser.getCurrentLocation()) << "expected an integer";80        return failure();81      }82      return success();83    };84    if (failed(parseDecimal())) {85      return Attribute();86    }87    while (failed(parser.parseOptionalGreater())) {88      if (failed(parser.parseXInDimensionList()) || failed(parseDecimal())) {89        return Attribute();90      }91    }92  }93  return get(parser.getContext(), shape);94}95 96void TestDecimalShapeAttr::print(AsmPrinter &printer) const {97  printer << "<";98  llvm::interleave(getShape(), printer, "x");99  printer << ">";100}101 102Attribute TestI64ElementsAttr::parse(AsmParser &parser, Type type) {103  SmallVector<uint64_t> elements;104  if (parser.parseLess() || parser.parseLSquare())105    return Attribute();106  uint64_t intVal;107  while (succeeded(*parser.parseOptionalInteger(intVal))) {108    elements.push_back(intVal);109    if (parser.parseOptionalComma())110      break;111  }112 113  if (parser.parseRSquare() || parser.parseGreater())114    return Attribute();115  return parser.getChecked<TestI64ElementsAttr>(116      parser.getContext(), llvm::cast<ShapedType>(type), elements);117}118 119void TestI64ElementsAttr::print(AsmPrinter &printer) const {120  printer << "<[";121  llvm::interleaveComma(getElements(), printer);122  printer << "]>";123}124 125LogicalResult126TestI64ElementsAttr::verify(function_ref<InFlightDiagnostic()> emitError,127                            ShapedType type, ArrayRef<uint64_t> elements) {128  if (type.getNumElements() != static_cast<int64_t>(elements.size())) {129    return emitError()130           << "number of elements does not match the provided shape type, got: "131           << elements.size() << ", but expected: " << type.getNumElements();132  }133  if (type.getRank() != 1 || !type.getElementType().isSignlessInteger(64))134    return emitError() << "expected single rank 64-bit shape type, but got: "135                       << type;136  return success();137}138 139LogicalResult TestAttrWithFormatAttr::verify(140    function_ref<InFlightDiagnostic()> emitError, int64_t one, std::string two,141    IntegerAttr three, ArrayRef<int> four, uint64_t five, ArrayRef<int> six,142    ArrayRef<AttrWithTypeBuilderAttr> arrayOfAttrs) {143  if (four.size() != static_cast<unsigned>(one))144    return emitError() << "expected 'one' to equal 'four.size()'";145  return success();146}147 148//===----------------------------------------------------------------------===//149// Utility Functions for Generated Attributes150//===----------------------------------------------------------------------===//151 152static FailureOr<SmallVector<int>> parseIntArray(AsmParser &parser) {153  SmallVector<int> ints;154  if (parser.parseLSquare() || parser.parseCommaSeparatedList([&]() {155        ints.push_back(0);156        return parser.parseInteger(ints.back());157      }) ||158      parser.parseRSquare())159    return failure();160  return ints;161}162 163static void printIntArray(AsmPrinter &printer, ArrayRef<int> ints) {164  printer << '[';165  llvm::interleaveComma(ints, printer);166  printer << ']';167}168 169//===----------------------------------------------------------------------===//170// TestSubElementsAccessAttr171//===----------------------------------------------------------------------===//172 173Attribute TestSubElementsAccessAttr::parse(::mlir::AsmParser &parser,174                                           ::mlir::Type type) {175  Attribute first, second, third;176  if (parser.parseLess() || parser.parseAttribute(first) ||177      parser.parseComma() || parser.parseAttribute(second) ||178      parser.parseComma() || parser.parseAttribute(third) ||179      parser.parseGreater()) {180    return {};181  }182  return get(parser.getContext(), first, second, third);183}184 185void TestSubElementsAccessAttr::print(::mlir::AsmPrinter &printer) const {186  printer << "<" << getFirst() << ", " << getSecond() << ", " << getThird()187          << ">";188}189 190//===----------------------------------------------------------------------===//191// TestExtern1DI64ElementsAttr192//===----------------------------------------------------------------------===//193 194ArrayRef<uint64_t> TestExtern1DI64ElementsAttr::getElements() const {195  if (auto *blob = getHandle().getBlob())196    return blob->getDataAs<uint64_t>();197  return {};198}199 200//===----------------------------------------------------------------------===//201// TestCustomAnchorAttr202//===----------------------------------------------------------------------===//203 204static ParseResult parseTrueFalse(AsmParser &p, std::optional<int> &result) {205  bool b;206  if (p.parseInteger(b))207    return failure();208  result = b;209  return success();210}211 212static void printTrueFalse(AsmPrinter &p, std::optional<int> result) {213  p << (*result ? "true" : "false");214}215 216//===----------------------------------------------------------------------===//217// TestCopyCountAttr Implementation218//===----------------------------------------------------------------------===//219 220LogicalResult TestCopyCountAttr::verify(221    llvm::function_ref<::mlir::InFlightDiagnostic()> /*emitError*/,222    CopyCount /*copy_count*/) {223  return success();224}225 226//===----------------------------------------------------------------------===//227// CopyCountAttr Implementation228//===----------------------------------------------------------------------===//229 230CopyCount::CopyCount(const CopyCount &rhs) : value(rhs.value) {231  CopyCount::counter++;232}233 234CopyCount &CopyCount::operator=(const CopyCount &rhs) {235  CopyCount::counter++;236  value = rhs.value;237  return *this;238}239 240int CopyCount::counter;241 242static bool operator==(const test::CopyCount &lhs, const test::CopyCount &rhs) {243  return lhs.value == rhs.value;244}245 246llvm::raw_ostream &test::operator<<(llvm::raw_ostream &os,247                                    const test::CopyCount &value) {248  return os << value.value;249}250 251template <>252struct mlir::FieldParser<test::CopyCount> {253  static FailureOr<test::CopyCount> parse(AsmParser &parser) {254    std::string value;255    if (parser.parseKeyword(value))256      return failure();257    return test::CopyCount(value);258  }259};260namespace test {261llvm::hash_code hash_value(const test::CopyCount &copyCount) {262  return llvm::hash_value(copyCount.value);263}264} // namespace test265 266//===----------------------------------------------------------------------===//267// TestConditionalAliasAttr268//===----------------------------------------------------------------------===//269 270/// Attempt to parse the conditionally-aliased string attribute as a keyword or271/// string, else try to parse an alias.272static ParseResult parseConditionalAlias(AsmParser &p, StringAttr &value) {273  std::string str;274  if (succeeded(p.parseOptionalKeywordOrString(&str))) {275    value = StringAttr::get(p.getContext(), str);276    return success();277  }278  return p.parseAttribute(value);279}280 281/// Print the string attribute as an alias if it has one, otherwise print it as282/// a keyword if possible.283static void printConditionalAlias(AsmPrinter &p, StringAttr value) {284  if (succeeded(p.printAlias(value)))285    return;286  p.printKeywordOrString(value);287}288 289//===----------------------------------------------------------------------===//290// Custom Float Attribute291//===----------------------------------------------------------------------===//292 293static void printCustomFloatAttr(AsmPrinter &p, StringAttr typeStrAttr,294                                 APFloat value) {295  p << typeStrAttr << " : " << value;296}297 298static ParseResult parseCustomFloatAttr(AsmParser &p, StringAttr &typeStrAttr,299                                        FailureOr<APFloat> &value) {300 301  std::string str;302  if (p.parseString(&str))303    return failure();304 305  typeStrAttr = StringAttr::get(p.getContext(), str);306 307  if (p.parseColon())308    return failure();309 310  const llvm::fltSemantics *semantics;311  if (str == "float")312    semantics = &llvm::APFloat::IEEEsingle();313  else if (str == "double")314    semantics = &llvm::APFloat::IEEEdouble();315  else if (str == "fp80")316    semantics = &llvm::APFloat::x87DoubleExtended();317  else318    return p.emitError(p.getCurrentLocation(), "unknown float type, expected "319                                               "'float', 'double' or 'fp80'");320 321  APFloat parsedValue(0.0);322  if (p.parseFloat(*semantics, parsedValue))323    return failure();324 325  value.emplace(parsedValue);326  return success();327}328 329//===----------------------------------------------------------------------===//330// TestCustomStructAttr331//===----------------------------------------------------------------------===//332 333static void printCustomStructAttr(AsmPrinter &p, int64_t value) {334  if (ShapedType::isDynamic(value)) {335    p << "?";336  } else {337    p.printStrippedAttrOrType(value);338  }339}340 341static ParseResult parseCustomStructAttr(AsmParser &p, int64_t &value) {342  if (succeeded(p.parseOptionalQuestion())) {343    value = ShapedType::kDynamic;344    return success();345  }346  return p.parseInteger(value);347}348 349static void printCustomOptStructFieldAttr(AsmPrinter &p, ArrayAttr attr) {350  if (attr && attr.size() == 1 && isa<IntegerAttr>(attr[0])) {351    p << cast<IntegerAttr>(attr[0]).getInt();352  } else {353    p.printStrippedAttrOrType(attr);354  }355}356 357static ParseResult parseCustomOptStructFieldAttr(AsmParser &p,358                                                 ArrayAttr &attr) {359  int64_t value;360  OptionalParseResult result = p.parseOptionalInteger(value);361  if (result.has_value()) {362    if (failed(result.value()))363      return failure();364    attr = ArrayAttr::get(365        p.getContext(),366        {IntegerAttr::get(IntegerType::get(p.getContext(), 64), value)});367    return success();368  }369  return p.parseAttribute(attr);370}371 372//===----------------------------------------------------------------------===//373// TestOpAsmAttrInterfaceAttr374//===----------------------------------------------------------------------===//375 376::mlir::OpAsmDialectInterface::AliasResult377TestOpAsmAttrInterfaceAttr::getAlias(::llvm::raw_ostream &os) const {378  os << "op_asm_attr_interface_";379  os << getValue().getValue();380  return ::mlir::OpAsmDialectInterface::AliasResult::FinalAlias;381}382 383//===----------------------------------------------------------------------===//384// TestConstMemorySpaceAttr385//===----------------------------------------------------------------------===//386 387bool TestConstMemorySpaceAttr::isValidLoad(388    Type type, mlir::ptr::AtomicOrdering ordering,389    std::optional<int64_t> alignment, const ::mlir::DataLayout *dataLayout,390    function_ref<InFlightDiagnostic()> emitError) const {391  return true;392}393 394bool TestConstMemorySpaceAttr::isValidStore(395    Type type, mlir::ptr::AtomicOrdering ordering,396    std::optional<int64_t> alignment, const ::mlir::DataLayout *dataLayout,397    function_ref<InFlightDiagnostic()> emitError) const {398  if (emitError)399    emitError() << "memory space is read-only";400  return false;401}402 403bool TestConstMemorySpaceAttr::isValidAtomicOp(404    mlir::ptr::AtomicBinOp binOp, Type type, mlir::ptr::AtomicOrdering ordering,405    std::optional<int64_t> alignment, const ::mlir::DataLayout *dataLayout,406    function_ref<InFlightDiagnostic()> emitError) const {407  if (emitError)408    emitError() << "memory space is read-only";409  return false;410}411 412bool TestConstMemorySpaceAttr::isValidAtomicXchg(413    Type type, mlir::ptr::AtomicOrdering successOrdering,414    mlir::ptr::AtomicOrdering failureOrdering, std::optional<int64_t> alignment,415    const ::mlir::DataLayout *dataLayout,416    function_ref<InFlightDiagnostic()> emitError) const {417  if (emitError)418    emitError() << "memory space is read-only";419  return false;420}421 422bool TestConstMemorySpaceAttr::isValidAddrSpaceCast(423    Type tgt, Type src, function_ref<InFlightDiagnostic()> emitError) const {424  if (emitError)425    emitError() << "memory space doesn't allow addrspace casts";426  return false;427}428 429bool TestConstMemorySpaceAttr::isValidPtrIntCast(430    Type intLikeTy, Type ptrLikeTy,431    function_ref<InFlightDiagnostic()> emitError) const {432  if (emitError)433    emitError() << "memory space doesn't allow int-ptr casts";434  return false;435}436 437//===----------------------------------------------------------------------===//438// Tablegen Generated Definitions439//===----------------------------------------------------------------------===//440 441#include "TestAttrInterfaces.cpp.inc"442#include "TestOpEnums.cpp.inc"443#define GET_ATTRDEF_CLASSES444#include "TestAttrDefs.cpp.inc"445 446//===----------------------------------------------------------------------===//447// Dynamic Attributes448//===----------------------------------------------------------------------===//449 450/// Define a singleton dynamic attribute.451static std::unique_ptr<DynamicAttrDefinition>452getDynamicSingletonAttr(TestDialect *testDialect) {453  return DynamicAttrDefinition::get(454      "dynamic_singleton", testDialect,455      [](function_ref<InFlightDiagnostic()> emitError,456         ArrayRef<Attribute> args) {457        if (!args.empty()) {458          emitError() << "expected 0 attribute arguments, but had "459                      << args.size();460          return failure();461        }462        return success();463      });464}465 466/// Define a dynamic attribute representing a pair or attributes.467static std::unique_ptr<DynamicAttrDefinition>468getDynamicPairAttr(TestDialect *testDialect) {469  return DynamicAttrDefinition::get(470      "dynamic_pair", testDialect,471      [](function_ref<InFlightDiagnostic()> emitError,472         ArrayRef<Attribute> args) {473        if (args.size() != 2) {474          emitError() << "expected 2 attribute arguments, but had "475                      << args.size();476          return failure();477        }478        return success();479      });480}481 482static std::unique_ptr<DynamicAttrDefinition>483getDynamicCustomAssemblyFormatAttr(TestDialect *testDialect) {484  auto verifier = [](function_ref<InFlightDiagnostic()> emitError,485                     ArrayRef<Attribute> args) {486    if (args.size() != 2) {487      emitError() << "expected 2 attribute arguments, but had " << args.size();488      return failure();489    }490    return success();491  };492 493  auto parser = [](AsmParser &parser,494                   llvm::SmallVectorImpl<Attribute> &parsedParams) {495    Attribute leftAttr, rightAttr;496    if (parser.parseLess() || parser.parseAttribute(leftAttr) ||497        parser.parseColon() || parser.parseAttribute(rightAttr) ||498        parser.parseGreater())499      return failure();500    parsedParams.push_back(leftAttr);501    parsedParams.push_back(rightAttr);502    return success();503  };504 505  auto printer = [](AsmPrinter &printer, ArrayRef<Attribute> params) {506    printer << "<" << params[0] << ":" << params[1] << ">";507  };508 509  return DynamicAttrDefinition::get("dynamic_custom_assembly_format",510                                    testDialect, std::move(verifier),511                                    std::move(parser), std::move(printer));512}513 514//===----------------------------------------------------------------------===//515// SlashAttr516//===----------------------------------------------------------------------===//517 518Attribute SlashAttr::parse(AsmParser &parser, Type type) {519  int lhs, rhs;520 521  if (parser.parseLess() || parser.parseInteger(lhs) || parser.parseSlash() ||522      parser.parseInteger(rhs) || parser.parseGreater())523    return Attribute();524 525  return SlashAttr::get(parser.getContext(), lhs, rhs);526}527 528void SlashAttr::print(AsmPrinter &printer) const {529  printer << "<" << getLhs() << " / " << getRhs() << ">";530}531 532//===----------------------------------------------------------------------===//533// TestCustomStorageCtorAttr534//===----------------------------------------------------------------------===//535 536test::detail::TestCustomStorageCtorAttrAttrStorage *537test::detail::TestCustomStorageCtorAttrAttrStorage::construct(538    mlir::StorageUniquer::StorageAllocator &, std::tuple<int> &&) {539  // Note: this tests linker error ("undefined symbol"), the actual540  // implementation is not important.541  return nullptr;542}543 544//===----------------------------------------------------------------------===//545// TestTensorEncodingAttr546//===----------------------------------------------------------------------===//547 548::llvm::LogicalResult TestTensorEncodingAttr::verifyEncoding(549    mlir::ArrayRef<int64_t> shape, mlir::Type elementType,550    llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) const {551  return mlir::success();552}553 554//===----------------------------------------------------------------------===//555// TestMemRefLayoutAttr556//===----------------------------------------------------------------------===//557 558mlir::AffineMap TestMemRefLayoutAttr::getAffineMap() const {559  return mlir::AffineMap::getMultiDimIdentityMap(1, getContext());560}561 562//===----------------------------------------------------------------------===//563// TestDialect564//===----------------------------------------------------------------------===//565 566void TestDialect::registerAttributes() {567  addAttributes<568#define GET_ATTRDEF_LIST569#include "TestAttrDefs.cpp.inc"570      >();571  registerDynamicAttr(getDynamicSingletonAttr(this));572  registerDynamicAttr(getDynamicPairAttr(this));573  registerDynamicAttr(getDynamicCustomAssemblyFormatAttr(this));574}575