brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.1 KiB · 64ac970 Raw
528 lines · cpp
1//===- CIRAttrs.cpp - MLIR CIR Attributes ---------------------------------===//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 defines the attributes in the CIR dialect.10//11//===----------------------------------------------------------------------===//12 13#include "clang/CIR/Dialect/IR/CIRDialect.h"14 15#include "mlir/IR/DialectImplementation.h"16#include "llvm/ADT/TypeSwitch.h"17 18//===-----------------------------------------------------------------===//19// RecordMembers20//===-----------------------------------------------------------------===//21 22static void printRecordMembers(mlir::AsmPrinter &p, mlir::ArrayAttr members);23static mlir::ParseResult parseRecordMembers(mlir::AsmParser &parser,24                                            mlir::ArrayAttr &members);25 26//===-----------------------------------------------------------------===//27// IntLiteral28//===-----------------------------------------------------------------===//29 30static void printIntLiteral(mlir::AsmPrinter &p, llvm::APInt value,31                            cir::IntTypeInterface ty);32static mlir::ParseResult parseIntLiteral(mlir::AsmParser &parser,33                                         llvm::APInt &value,34                                         cir::IntTypeInterface ty);35//===-----------------------------------------------------------------===//36// FloatLiteral37//===-----------------------------------------------------------------===//38 39static void printFloatLiteral(mlir::AsmPrinter &p, llvm::APFloat value,40                              mlir::Type ty);41static mlir::ParseResult42parseFloatLiteral(mlir::AsmParser &parser,43                  mlir::FailureOr<llvm::APFloat> &value,44                  cir::FPTypeInterface fpType);45 46//===----------------------------------------------------------------------===//47// AddressSpaceAttr48//===----------------------------------------------------------------------===//49 50mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p,51                                          cir::TargetAddressSpaceAttr &attr);52 53void printTargetAddressSpace(mlir::AsmPrinter &p,54                             cir::TargetAddressSpaceAttr attr);55 56static mlir::ParseResult parseConstPtr(mlir::AsmParser &parser,57                                       mlir::IntegerAttr &value);58 59static void printConstPtr(mlir::AsmPrinter &p, mlir::IntegerAttr value);60 61#define GET_ATTRDEF_CLASSES62#include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc"63 64using namespace mlir;65using namespace cir;66 67//===----------------------------------------------------------------------===//68// General CIR parsing / printing69//===----------------------------------------------------------------------===//70 71Attribute CIRDialect::parseAttribute(DialectAsmParser &parser,72                                     Type type) const {73  llvm::SMLoc typeLoc = parser.getCurrentLocation();74  llvm::StringRef mnemonic;75  Attribute genAttr;76  OptionalParseResult parseResult =77      generatedAttributeParser(parser, &mnemonic, type, genAttr);78  if (parseResult.has_value())79    return genAttr;80  parser.emitError(typeLoc, "unknown attribute in CIR dialect");81  return Attribute();82}83 84void CIRDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const {85  if (failed(generatedAttributePrinter(attr, os)))86    llvm_unreachable("unexpected CIR type kind");87}88 89static void printRecordMembers(mlir::AsmPrinter &printer,90                               mlir::ArrayAttr members) {91  printer << '{';92  llvm::interleaveComma(members, printer);93  printer << '}';94}95 96static ParseResult parseRecordMembers(mlir::AsmParser &parser,97                                      mlir::ArrayAttr &members) {98  llvm::SmallVector<mlir::Attribute, 4> elts;99 100  auto delimiter = AsmParser::Delimiter::Braces;101  auto result = parser.parseCommaSeparatedList(delimiter, [&]() {102    mlir::TypedAttr attr;103    if (parser.parseAttribute(attr).failed())104      return mlir::failure();105    elts.push_back(attr);106    return mlir::success();107  });108 109  if (result.failed())110    return mlir::failure();111 112  members = mlir::ArrayAttr::get(parser.getContext(), elts);113  return mlir::success();114}115 116//===----------------------------------------------------------------------===//117// ConstRecordAttr definitions118//===----------------------------------------------------------------------===//119 120LogicalResult121ConstRecordAttr::verify(function_ref<InFlightDiagnostic()> emitError,122                        mlir::Type type, ArrayAttr members) {123  auto sTy = mlir::dyn_cast_if_present<cir::RecordType>(type);124  if (!sTy)125    return emitError() << "expected !cir.record type";126 127  if (sTy.getMembers().size() != members.size())128    return emitError() << "number of elements must match";129 130  unsigned attrIdx = 0;131  for (auto &member : sTy.getMembers()) {132    auto m = mlir::cast<mlir::TypedAttr>(members[attrIdx]);133    if (member != m.getType())134      return emitError() << "element at index " << attrIdx << " has type "135                         << m.getType()136                         << " but the expected type for this element is "137                         << member;138    attrIdx++;139  }140 141  return success();142}143 144//===----------------------------------------------------------------------===//145// OptInfoAttr definitions146//===----------------------------------------------------------------------===//147 148LogicalResult OptInfoAttr::verify(function_ref<InFlightDiagnostic()> emitError,149                                  unsigned level, unsigned size) {150  if (level > 3)151    return emitError()152           << "optimization level must be between 0 and 3 inclusive";153  if (size > 2)154    return emitError()155           << "size optimization level must be between 0 and 2 inclusive";156  return success();157}158 159//===----------------------------------------------------------------------===//160// ConstPtrAttr definitions161//===----------------------------------------------------------------------===//162 163// TODO(CIR): Consider encoding the null value differently and use conditional164// assembly format instead of custom parsing/printing.165static ParseResult parseConstPtr(AsmParser &parser, mlir::IntegerAttr &value) {166 167  if (parser.parseOptionalKeyword("null").succeeded()) {168    value = parser.getBuilder().getI64IntegerAttr(0);169    return success();170  }171 172  return parser.parseAttribute(value);173}174 175static void printConstPtr(AsmPrinter &p, mlir::IntegerAttr value) {176  if (!value.getInt())177    p << "null";178  else179    p << value;180}181 182//===----------------------------------------------------------------------===//183// IntAttr definitions184//===----------------------------------------------------------------------===//185 186template <typename IntT>187static bool isTooLargeForType(const mlir::APInt &value, IntT expectedValue) {188  if constexpr (std::is_signed_v<IntT>) {189    return value.getSExtValue() != expectedValue;190  } else {191    return value.getZExtValue() != expectedValue;192  }193}194 195template <typename IntT>196static mlir::ParseResult parseIntLiteralImpl(mlir::AsmParser &p,197                                             llvm::APInt &value,198                                             cir::IntTypeInterface ty) {199  IntT ivalue;200  const bool isSigned = ty.isSigned();201  if (p.parseInteger(ivalue))202    return p.emitError(p.getCurrentLocation(), "expected integer value");203 204  value = mlir::APInt(ty.getWidth(), ivalue, isSigned, /*implicitTrunc=*/true);205  if (isTooLargeForType(value, ivalue))206    return p.emitError(p.getCurrentLocation(),207                       "integer value too large for the given type");208 209  return success();210}211 212mlir::ParseResult parseIntLiteral(mlir::AsmParser &parser, llvm::APInt &value,213                                  cir::IntTypeInterface ty) {214  if (ty.isSigned())215    return parseIntLiteralImpl<int64_t>(parser, value, ty);216  return parseIntLiteralImpl<uint64_t>(parser, value, ty);217}218 219void printIntLiteral(mlir::AsmPrinter &p, llvm::APInt value,220                     cir::IntTypeInterface ty) {221  if (ty.isSigned())222    p << value.getSExtValue();223  else224    p << value.getZExtValue();225}226 227LogicalResult IntAttr::verify(function_ref<InFlightDiagnostic()> emitError,228                              cir::IntTypeInterface type, llvm::APInt value) {229  if (value.getBitWidth() != type.getWidth())230    return emitError() << "type and value bitwidth mismatch: "231                       << type.getWidth() << " != " << value.getBitWidth();232  return success();233}234 235//===----------------------------------------------------------------------===//236// FPAttr definitions237//===----------------------------------------------------------------------===//238 239static void printFloatLiteral(AsmPrinter &p, APFloat value, Type ty) {240  p << value;241}242 243static ParseResult parseFloatLiteral(AsmParser &parser,244                                     FailureOr<APFloat> &value,245                                     cir::FPTypeInterface fpType) {246 247  APFloat parsedValue(0.0);248  if (parser.parseFloat(fpType.getFloatSemantics(), parsedValue))249    return failure();250 251  value.emplace(parsedValue);252  return success();253}254 255FPAttr FPAttr::getZero(Type type) {256  return get(type,257             APFloat::getZero(258                 mlir::cast<cir::FPTypeInterface>(type).getFloatSemantics()));259}260 261LogicalResult FPAttr::verify(function_ref<InFlightDiagnostic()> emitError,262                             cir::FPTypeInterface fpType, APFloat value) {263  if (APFloat::SemanticsToEnum(fpType.getFloatSemantics()) !=264      APFloat::SemanticsToEnum(value.getSemantics()))265    return emitError() << "floating-point semantics mismatch";266 267  return success();268}269 270//===----------------------------------------------------------------------===//271// ConstComplexAttr definitions272//===----------------------------------------------------------------------===//273 274LogicalResult275ConstComplexAttr::verify(function_ref<InFlightDiagnostic()> emitError,276                         cir::ComplexType type, mlir::TypedAttr real,277                         mlir::TypedAttr imag) {278  mlir::Type elemType = type.getElementType();279  if (real.getType() != elemType)280    return emitError()281           << "type of the real part does not match the complex type";282 283  if (imag.getType() != elemType)284    return emitError()285           << "type of the imaginary part does not match the complex type";286 287  return success();288}289 290//===----------------------------------------------------------------------===//291// CIR ConstArrayAttr292//===----------------------------------------------------------------------===//293 294LogicalResult295ConstArrayAttr::verify(function_ref<InFlightDiagnostic()> emitError, Type type,296                       Attribute elts, int trailingZerosNum) {297 298  if (!(mlir::isa<ArrayAttr, StringAttr>(elts)))299    return emitError() << "constant array expects ArrayAttr or StringAttr";300 301  if (auto strAttr = mlir::dyn_cast<StringAttr>(elts)) {302    const auto arrayTy = mlir::cast<ArrayType>(type);303    const auto intTy = mlir::dyn_cast<IntType>(arrayTy.getElementType());304 305    // TODO: add CIR type for char.306    if (!intTy || intTy.getWidth() != 8)307      return emitError()308             << "constant array element for string literals expects "309                "!cir.int<u, 8> element type";310    return success();311  }312 313  assert(mlir::isa<ArrayAttr>(elts));314  const auto arrayAttr = mlir::cast<mlir::ArrayAttr>(elts);315  const auto arrayTy = mlir::cast<ArrayType>(type);316 317  // Make sure both number of elements and subelement types match type.318  if (arrayTy.getSize() != arrayAttr.size() + trailingZerosNum)319    return emitError() << "constant array size should match type size";320  return success();321}322 323Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {324  mlir::FailureOr<Type> resultTy;325  mlir::FailureOr<Attribute> resultVal;326 327  // Parse literal '<'328  if (parser.parseLess())329    return {};330 331  // Parse variable 'value'332  resultVal = FieldParser<Attribute>::parse(parser);333  if (failed(resultVal)) {334    parser.emitError(335        parser.getCurrentLocation(),336        "failed to parse ConstArrayAttr parameter 'value' which is "337        "to be a `Attribute`");338    return {};339  }340 341  // ArrayAttrrs have per-element type, not the type of the array...342  if (mlir::isa<ArrayAttr>(*resultVal)) {343    // Array has implicit type: infer from const array type.344    if (parser.parseOptionalColon().failed()) {345      resultTy = type;346    } else { // Array has explicit type: parse it.347      resultTy = FieldParser<Type>::parse(parser);348      if (failed(resultTy)) {349        parser.emitError(350            parser.getCurrentLocation(),351            "failed to parse ConstArrayAttr parameter 'type' which is "352            "to be a `::mlir::Type`");353        return {};354      }355    }356  } else {357    auto ta = mlir::cast<TypedAttr>(*resultVal);358    resultTy = ta.getType();359    if (mlir::isa<mlir::NoneType>(*resultTy)) {360      parser.emitError(parser.getCurrentLocation(),361                       "expected type declaration for string literal");362      return {};363    }364  }365 366  unsigned zeros = 0;367  if (parser.parseOptionalComma().succeeded()) {368    if (parser.parseOptionalKeyword("trailing_zeros").succeeded()) {369      unsigned typeSize =370          mlir::cast<cir::ArrayType>(resultTy.value()).getSize();371      mlir::Attribute elts = resultVal.value();372      if (auto str = mlir::dyn_cast<mlir::StringAttr>(elts))373        zeros = typeSize - str.size();374      else375        zeros = typeSize - mlir::cast<mlir::ArrayAttr>(elts).size();376    } else {377      return {};378    }379  }380 381  // Parse literal '>'382  if (parser.parseGreater())383    return {};384 385  return parser.getChecked<ConstArrayAttr>(386      parser.getCurrentLocation(), parser.getContext(), resultTy.value(),387      resultVal.value(), zeros);388}389 390void ConstArrayAttr::print(AsmPrinter &printer) const {391  printer << "<";392  printer.printStrippedAttrOrType(getElts());393  if (getTrailingZerosNum())394    printer << ", trailing_zeros";395  printer << ">";396}397 398//===----------------------------------------------------------------------===//399// CIR ConstVectorAttr400//===----------------------------------------------------------------------===//401 402LogicalResult403cir::ConstVectorAttr::verify(function_ref<InFlightDiagnostic()> emitError,404                             Type type, ArrayAttr elts) {405 406  if (!mlir::isa<cir::VectorType>(type))407    return emitError() << "type of cir::ConstVectorAttr is not a "408                          "cir::VectorType: "409                       << type;410 411  const auto vecType = mlir::cast<cir::VectorType>(type);412 413  if (vecType.getSize() != elts.size())414    return emitError()415           << "number of constant elements should match vector size";416 417  // Check if the types of the elements match418  LogicalResult elementTypeCheck = success();419  elts.walkImmediateSubElements(420      [&](Attribute element) {421        if (elementTypeCheck.failed()) {422          // An earlier element didn't match423          return;424        }425        auto typedElement = mlir::dyn_cast<TypedAttr>(element);426        if (!typedElement ||427            typedElement.getType() != vecType.getElementType()) {428          elementTypeCheck = failure();429          emitError() << "constant type should match vector element type";430        }431      },432      [&](Type) {});433 434  return elementTypeCheck;435}436 437//===----------------------------------------------------------------------===//438// CIR VTableAttr439//===----------------------------------------------------------------------===//440 441LogicalResult cir::VTableAttr::verify(442    llvm::function_ref<mlir::InFlightDiagnostic()> emitError, mlir::Type type,443    mlir::ArrayAttr data) {444  auto sTy = mlir::dyn_cast_if_present<cir::RecordType>(type);445  if (!sTy)446    return emitError() << "expected !cir.record type result";447  if (sTy.getMembers().empty() || data.empty())448    return emitError() << "expected record type with one or more subtype";449 450  if (cir::ConstRecordAttr::verify(emitError, type, data).failed())451    return failure();452 453  for (const auto &element : data.getAsRange<mlir::Attribute>()) {454    const auto &constArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(element);455    if (!constArrayAttr)456      return emitError() << "expected constant array subtype";457 458    LogicalResult eltTypeCheck = success();459    auto arrayElts = mlir::cast<ArrayAttr>(constArrayAttr.getElts());460    arrayElts.walkImmediateSubElements(461        [&](mlir::Attribute attr) {462          if (mlir::isa<ConstPtrAttr, GlobalViewAttr>(attr))463            return;464 465          eltTypeCheck = emitError()466                         << "expected GlobalViewAttr or ConstPtrAttr";467        },468        [&](mlir::Type type) {});469    if (eltTypeCheck.failed())470      return eltTypeCheck;471  }472  return success();473}474 475//===----------------------------------------------------------------------===//476// DynamicCastInfoAtttr definitions477//===----------------------------------------------------------------------===//478 479std::string DynamicCastInfoAttr::getAlias() const {480  // The alias looks like: `dyn_cast_info_<src>_<dest>`481 482  std::string alias = "dyn_cast_info_";483 484  alias.append(getSrcRtti().getSymbol().getValue());485  alias.push_back('_');486  alias.append(getDestRtti().getSymbol().getValue());487 488  return alias;489}490 491LogicalResult DynamicCastInfoAttr::verify(492    function_ref<InFlightDiagnostic()> emitError, cir::GlobalViewAttr srcRtti,493    cir::GlobalViewAttr destRtti, mlir::FlatSymbolRefAttr runtimeFunc,494    mlir::FlatSymbolRefAttr badCastFunc, cir::IntAttr offsetHint) {495  auto isRttiPtr = [](mlir::Type ty) {496    // RTTI pointers are !cir.ptr<!u8i>.497 498    auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty);499    if (!ptrTy)500      return false;501 502    auto pointeeIntTy = mlir::dyn_cast<cir::IntType>(ptrTy.getPointee());503    if (!pointeeIntTy)504      return false;505 506    return pointeeIntTy.isUnsigned() && pointeeIntTy.getWidth() == 8;507  };508 509  if (!isRttiPtr(srcRtti.getType()))510    return emitError() << "srcRtti must be an RTTI pointer";511 512  if (!isRttiPtr(destRtti.getType()))513    return emitError() << "destRtti must be an RTTI pointer";514 515  return success();516}517 518//===----------------------------------------------------------------------===//519// CIR Dialect520//===----------------------------------------------------------------------===//521 522void CIRDialect::registerAttributes() {523  addAttributes<524#define GET_ATTRDEF_LIST525#include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc"526      >();527}528