brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.0 KiB · a1a16e5 Raw
305 lines · cpp
1//===-- FIRAttr.cpp -------------------------------------------------------===//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// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/10//11//===----------------------------------------------------------------------===//12 13#include "flang/Optimizer/Dialect/FIRAttr.h"14#include "flang/Optimizer/Dialect/FIRDialect.h"15#include "flang/Optimizer/Dialect/Support/KindMapping.h"16#include "mlir/IR/AttributeSupport.h"17#include "mlir/IR/Builders.h"18#include "mlir/IR/BuiltinTypes.h"19#include "mlir/IR/DialectImplementation.h"20#include "llvm/ADT/SmallString.h"21#include "llvm/ADT/StringExtras.h"22#include "llvm/ADT/TypeSwitch.h"23 24#include "flang/Optimizer/Dialect/FIREnumAttr.cpp.inc"25#define GET_ATTRDEF_CLASSES26#include "flang/Optimizer/Dialect/FIRAttr.cpp.inc"27 28using namespace fir;29 30namespace fir::detail {31 32struct RealAttributeStorage : public mlir::AttributeStorage {33  using KeyTy = std::pair<int, llvm::APFloat>;34 35  RealAttributeStorage(int kind, const llvm::APFloat &value)36      : kind(kind), value(value) {}37  RealAttributeStorage(const KeyTy &key)38      : RealAttributeStorage(key.first, key.second) {}39 40  static unsigned hashKey(const KeyTy &key) { return llvm::hash_value(key); }41 42  bool operator==(const KeyTy &key) const {43    return key.first == kind &&44           key.second.compare(value) == llvm::APFloatBase::cmpEqual;45  }46 47  static RealAttributeStorage *48  construct(mlir::AttributeStorageAllocator &allocator, const KeyTy &key) {49    return new (allocator.allocate<RealAttributeStorage>())50        RealAttributeStorage(key);51  }52 53  KindTy getFKind() const { return kind; }54  llvm::APFloat getValue() const { return value; }55 56private:57  int kind;58  llvm::APFloat value;59};60 61/// An attribute representing a reference to a type.62struct TypeAttributeStorage : public mlir::AttributeStorage {63  using KeyTy = mlir::Type;64 65  TypeAttributeStorage(mlir::Type value) : value(value) {66    assert(value && "must not be of Type null");67  }68 69  /// Key equality function.70  bool operator==(const KeyTy &key) const { return key == value; }71 72  /// Construct a new storage instance.73  static TypeAttributeStorage *74  construct(mlir::AttributeStorageAllocator &allocator, KeyTy key) {75    return new (allocator.allocate<TypeAttributeStorage>())76        TypeAttributeStorage(key);77  }78 79  mlir::Type getType() const { return value; }80 81private:82  mlir::Type value;83};84} // namespace fir::detail85 86//===----------------------------------------------------------------------===//87// Attributes for SELECT TYPE88//===----------------------------------------------------------------------===//89 90ExactTypeAttr fir::ExactTypeAttr::get(mlir::Type value) {91  return Base::get(value.getContext(), value);92}93 94mlir::Type fir::ExactTypeAttr::getType() const { return getImpl()->getType(); }95 96SubclassAttr fir::SubclassAttr::get(mlir::Type value) {97  return Base::get(value.getContext(), value);98}99 100mlir::Type fir::SubclassAttr::getType() const { return getImpl()->getType(); }101 102//===----------------------------------------------------------------------===//103// Attributes for SELECT CASE104//===----------------------------------------------------------------------===//105 106using AttributeUniquer = mlir::detail::AttributeUniquer;107 108ClosedIntervalAttr fir::ClosedIntervalAttr::get(mlir::MLIRContext *ctxt) {109  return AttributeUniquer::get<ClosedIntervalAttr>(ctxt);110}111 112UpperBoundAttr fir::UpperBoundAttr::get(mlir::MLIRContext *ctxt) {113  return AttributeUniquer::get<UpperBoundAttr>(ctxt);114}115 116LowerBoundAttr fir::LowerBoundAttr::get(mlir::MLIRContext *ctxt) {117  return AttributeUniquer::get<LowerBoundAttr>(ctxt);118}119 120PointIntervalAttr fir::PointIntervalAttr::get(mlir::MLIRContext *ctxt) {121  return AttributeUniquer::get<PointIntervalAttr>(ctxt);122}123 124//===----------------------------------------------------------------------===//125// RealAttr126//===----------------------------------------------------------------------===//127 128RealAttr fir::RealAttr::get(mlir::MLIRContext *ctxt,129                            const RealAttr::ValueType &key) {130  return Base::get(ctxt, key);131}132 133KindTy fir::RealAttr::getFKind() const { return getImpl()->getFKind(); }134 135llvm::APFloat fir::RealAttr::getValue() const { return getImpl()->getValue(); }136 137//===----------------------------------------------------------------------===//138// FIR attribute parsing139//===----------------------------------------------------------------------===//140 141static mlir::Attribute parseFirRealAttr(FIROpsDialect *dialect,142                                        mlir::DialectAsmParser &parser,143                                        mlir::Type type) {144  int kind = 0;145  if (parser.parseLess() || parser.parseInteger(kind) || parser.parseComma()) {146    parser.emitError(parser.getNameLoc(), "expected '<' kind ','");147    return {};148  }149  KindMapping kindMap(dialect->getContext());150  llvm::APFloat value(0.);151  if (parser.parseOptionalKeyword("i")) {152    // `i` not present, so literal float must be present153    double dontCare;154    if (parser.parseFloat(dontCare) || parser.parseGreater()) {155      parser.emitError(parser.getNameLoc(), "expected real constant '>'");156      return {};157    }158    auto fltStr = parser.getFullSymbolSpec()159                      .drop_until([](char c) { return c == ','; })160                      .drop_front()161                      .drop_while([](char c) { return c == ' ' || c == '\t'; })162                      .take_until([](char c) {163                        return c == '>' || c == ' ' || c == '\t';164                      });165    value = llvm::APFloat(kindMap.getFloatSemantics(kind), fltStr);166  } else {167    // `i` is present, so literal bitstring (hex) must be present168    llvm::StringRef hex;169    if (parser.parseKeyword(&hex) || parser.parseGreater()) {170      parser.emitError(parser.getNameLoc(), "expected real constant '>'");171      return {};172    }173    const llvm::fltSemantics &sem = kindMap.getFloatSemantics(kind);174    unsigned int numBits = llvm::APFloat::semanticsSizeInBits(sem);175    auto bits = llvm::APInt(numBits, hex.drop_front(), 16);176    value = llvm::APFloat(sem, bits);177  }178  return RealAttr::get(dialect->getContext(), {kind, value});179}180 181mlir::Attribute fir::FortranVariableFlagsAttr::parse(mlir::AsmParser &parser,182                                                     mlir::Type type) {183  if (mlir::failed(parser.parseLess()))184    return {};185 186  fir::FortranVariableFlagsEnum flags = {};187  if (mlir::failed(parser.parseOptionalGreater())) {188    auto parseFlags = [&]() -> mlir::ParseResult {189      llvm::StringRef elemName;190      if (mlir::failed(parser.parseKeyword(&elemName)))191        return mlir::failure();192 193      auto elem = fir::symbolizeFortranVariableFlagsEnum(elemName);194      if (!elem)195        return parser.emitError(parser.getNameLoc(),196                                "Unknown fortran variable attribute: ")197               << elemName;198 199      flags = flags | *elem;200      return mlir::success();201    };202    if (mlir::failed(parser.parseCommaSeparatedList(parseFlags)) ||203        parser.parseGreater())204      return {};205  }206 207  return FortranVariableFlagsAttr::get(parser.getContext(), flags);208}209 210mlir::Attribute fir::parseFirAttribute(FIROpsDialect *dialect,211                                       mlir::DialectAsmParser &parser,212                                       mlir::Type type) {213  auto loc = parser.getNameLoc();214  llvm::StringRef attrName;215  mlir::Attribute attr;216  mlir::OptionalParseResult result =217      generatedAttributeParser(parser, &attrName, type, attr);218  if (result.has_value())219    return attr;220  if (attrName.empty())221    return {}; // error reported by generatedAttributeParser222 223  if (attrName == ExactTypeAttr::getAttrName()) {224    mlir::Type type;225    if (parser.parseLess() || parser.parseType(type) || parser.parseGreater()) {226      parser.emitError(loc, "expected a type");227      return {};228    }229    return ExactTypeAttr::get(type);230  }231  if (attrName == SubclassAttr::getAttrName()) {232    mlir::Type type;233    if (parser.parseLess() || parser.parseType(type) || parser.parseGreater()) {234      parser.emitError(loc, "expected a subtype");235      return {};236    }237    return SubclassAttr::get(type);238  }239  if (attrName == PointIntervalAttr::getAttrName())240    return PointIntervalAttr::get(dialect->getContext());241  if (attrName == LowerBoundAttr::getAttrName())242    return LowerBoundAttr::get(dialect->getContext());243  if (attrName == UpperBoundAttr::getAttrName())244    return UpperBoundAttr::get(dialect->getContext());245  if (attrName == ClosedIntervalAttr::getAttrName())246    return ClosedIntervalAttr::get(dialect->getContext());247  if (attrName == RealAttr::getAttrName())248    return parseFirRealAttr(dialect, parser, type);249 250  parser.emitError(loc, "unknown FIR attribute: ") << attrName;251  return {};252}253 254//===----------------------------------------------------------------------===//255// FIR attribute pretty printer256//===----------------------------------------------------------------------===//257 258void fir::FortranVariableFlagsAttr::print(mlir::AsmPrinter &printer) const {259  printer << "<";260  printer << fir::stringifyFortranVariableFlagsEnum(this->getFlags());261  printer << ">";262}263 264void fir::printFirAttribute(FIROpsDialect *dialect, mlir::Attribute attr,265                            mlir::DialectAsmPrinter &p) {266  auto &os = p.getStream();267  if (auto exact = mlir::dyn_cast<fir::ExactTypeAttr>(attr)) {268    os << fir::ExactTypeAttr::getAttrName() << '<';269    p.printType(exact.getType());270    os << '>';271  } else if (auto sub = mlir::dyn_cast<fir::SubclassAttr>(attr)) {272    os << fir::SubclassAttr::getAttrName() << '<';273    p.printType(sub.getType());274    os << '>';275  } else if (mlir::dyn_cast_or_null<fir::PointIntervalAttr>(attr)) {276    os << fir::PointIntervalAttr::getAttrName();277  } else if (mlir::dyn_cast_or_null<fir::ClosedIntervalAttr>(attr)) {278    os << fir::ClosedIntervalAttr::getAttrName();279  } else if (mlir::dyn_cast_or_null<fir::LowerBoundAttr>(attr)) {280    os << fir::LowerBoundAttr::getAttrName();281  } else if (mlir::dyn_cast_or_null<fir::UpperBoundAttr>(attr)) {282    os << fir::UpperBoundAttr::getAttrName();283  } else if (auto a = mlir::dyn_cast_or_null<fir::RealAttr>(attr)) {284    os << fir::RealAttr::getAttrName() << '<' << a.getFKind() << ", i x";285    llvm::SmallString<40> ss;286    a.getValue().bitcastToAPInt().toStringUnsigned(ss, 16);287    os << ss << '>';288  } else if (mlir::failed(generatedAttributePrinter(attr, p))) {289    // don't know how to print the attribute, so use a default290    os << "<(unknown attribute)>";291  }292}293 294//===----------------------------------------------------------------------===//295// FIROpsDialect296//===----------------------------------------------------------------------===//297 298void FIROpsDialect::registerAttributes() {299  addAttributes<ClosedIntervalAttr, ExactTypeAttr, LowerBoundAttr,300                PointIntervalAttr, RealAttr, SubclassAttr, UpperBoundAttr,301#define GET_ATTRDEF_LIST302#include "flang/Optimizer/Dialect/FIRAttr.cpp.inc"303                >();304}305