[flang-commits] [flang] baa12dd - [flang] Add the conversions for types.

Eric Schweitz via flang-commits flang-commits at lists.llvm.org
Thu Jun 4 12:55:05 PDT 2020


Author: Eric Schweitz
Date: 2020-06-04T12:54:50-07:00
New Revision: baa12ddb6fa6840c1125f0aa11cd0e05fe82385d

URL: https://github.com/llvm/llvm-project/commit/baa12ddb6fa6840c1125f0aa11cd0e05fe82385d
DIFF: https://github.com/llvm/llvm-project/commit/baa12ddb6fa6840c1125f0aa11cd0e05fe82385d.diff

LOG: [flang] Add the conversions for types.

Part of lowering is to convert the front-end types to their FIR dialect representations.  These conversions are done by here in the ConvertType module.

proactively update the code to conform better with LLVM coding conventions

Differential Revision: https://reviews.llvm.org/D81034

Added: 
    flang/include/flang/Lower/ConvertType.h
    flang/lib/Lower/ConvertType.cpp

Modified: 
    flang/lib/Lower/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Lower/ConvertType.h b/flang/include/flang/Lower/ConvertType.h
new file mode 100644
index 000000000000..f4046efba112
--- /dev/null
+++ b/flang/include/flang/Lower/ConvertType.h
@@ -0,0 +1,131 @@
+//===-- Lower/ConvertType.h -- lowering of types ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//----------------------------------------------------------------------------//
+///
+/// Conversion of front-end TYPE, KIND, ATTRIBUTE (TKA) information to FIR/MLIR.
+/// This is meant to be the single point of truth (SPOT) for all type
+/// conversions when lowering to FIR.  This implements all lowering of parse
+/// tree TKA to the FIR type system. If one is converting front-end types and
+/// not using one of the routines provided here, it's being done wrong.
+///
+/// [Coding style](https://llvm.org/docs/CodingStandards.html)
+///
+//----------------------------------------------------------------------------//
+
+#ifndef FORTRAN_LOWER_CONVERT_TYPE_H
+#define FORTRAN_LOWER_CONVERT_TYPE_H
+
+#include "flang/Common/Fortran.h"
+#include "mlir/IR/Types.h"
+
+namespace mlir {
+class Location;
+class MLIRContext;
+class Type;
+} // namespace mlir
+
+namespace Fortran {
+namespace common {
+class IntrinsicTypeDefaultKinds;
+template <typename>
+class Reference;
+} // namespace common
+
+namespace evaluate {
+struct DataRef;
+template <typename>
+class Designator;
+template <typename>
+class Expr;
+template <common::TypeCategory>
+struct SomeKind;
+struct SomeType;
+template <common::TypeCategory, int>
+class Type;
+} // namespace evaluate
+
+namespace parser {
+class CharBlock;
+class CookedSource;
+} // namespace parser
+
+namespace semantics {
+class Symbol;
+} // namespace semantics
+
+namespace lower {
+namespace pft {
+struct Variable;
+}
+
+using SomeExpr = evaluate::Expr<evaluate::SomeType>;
+using SymbolRef = common::Reference<const semantics::Symbol>;
+
+/// Get a FIR type based on a category and kind.
+mlir::Type getFIRType(mlir::MLIRContext *ctxt,
+                      common::IntrinsicTypeDefaultKinds const &defaults,
+                      common::TypeCategory tc, int kind);
+
+/// Get a FIR type based on a category.
+mlir::Type getFIRType(mlir::MLIRContext *ctxt,
+                      common::IntrinsicTypeDefaultKinds const &defaults,
+                      common::TypeCategory tc);
+
+/// Translate a Fortran::evaluate::DataRef to an mlir::Type.
+mlir::Type
+translateDataRefToFIRType(mlir::MLIRContext *ctxt,
+                          common::IntrinsicTypeDefaultKinds const &defaults,
+                          const evaluate::DataRef &dataRef);
+
+/// Translate a Fortran::evaluate::Designator<> to an mlir::Type.
+template <common::TypeCategory TC, int KIND>
+inline mlir::Type translateDesignatorToFIRType(
+    mlir::MLIRContext *ctxt, common::IntrinsicTypeDefaultKinds const &defaults,
+    const evaluate::Designator<evaluate::Type<TC, KIND>> &) {
+  return getFIRType(ctxt, defaults, TC, KIND);
+}
+
+/// Translate a Fortran::evaluate::Designator<> to an mlir::Type.
+template <common::TypeCategory TC>
+inline mlir::Type translateDesignatorToFIRType(
+    mlir::MLIRContext *ctxt, common::IntrinsicTypeDefaultKinds const &defaults,
+    const evaluate::Designator<evaluate::SomeKind<TC>> &) {
+  return getFIRType(ctxt, defaults, TC);
+}
+
+/// Translate a SomeExpr to an mlir::Type.
+mlir::Type
+translateSomeExprToFIRType(mlir::MLIRContext *ctxt,
+                           common::IntrinsicTypeDefaultKinds const &defaults,
+                           const SomeExpr *expr);
+
+/// Translate a Fortran::semantics::Symbol to an mlir::Type.
+mlir::Type
+translateSymbolToFIRType(mlir::MLIRContext *ctxt,
+                         common::IntrinsicTypeDefaultKinds const &defaults,
+                         const SymbolRef symbol);
+
+/// Translate a Fortran::lower::pft::Variable to an mlir::Type.
+mlir::Type
+translateVariableToFIRType(mlir::MLIRContext *ctxt,
+                           common::IntrinsicTypeDefaultKinds const &defaults,
+                           const pft::Variable &variable);
+
+/// Translate a REAL of KIND to the mlir::Type.
+mlir::Type convertReal(mlir::MLIRContext *ctxt, int KIND);
+
+// Given a ReferenceType of a base type, returns the ReferenceType to
+// the SequenceType of this base type.
+// The created SequenceType has one dimension of unknown extent.
+// This is useful to do pointer arithmetic using fir::CoordinateOp that requires
+// a memory reference to a sequence type.
+mlir::Type getSequenceRefType(mlir::Type referenceType);
+
+} // namespace lower
+} // namespace Fortran
+
+#endif // FORTRAN_LOWER_CONVERT_TYPE_H

diff  --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt
index 9e1dbc782db6..4473a13e986b 100644
--- a/flang/lib/Lower/CMakeLists.txt
+++ b/flang/lib/Lower/CMakeLists.txt
@@ -1,5 +1,6 @@
 
 add_flang_library(FortranLower
+  ConvertType.cpp
   OpenMP.cpp
   PFTBuilder.cpp
 

diff  --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp
new file mode 100644
index 000000000000..54792a51b4eb
--- /dev/null
+++ b/flang/lib/Lower/ConvertType.cpp
@@ -0,0 +1,532 @@
+//===-- ConvertType.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Lower/ConvertType.h"
+#include "flang/Lower/PFTBuilder.h"
+#include "flang/Lower/Utils.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Semantics/tools.h"
+#include "flang/Semantics/type.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/StandardTypes.h"
+
+#undef QUOTE
+#undef TODO
+#define QUOTE(X) #X
+#define TODO(S)                                                                \
+  {                                                                            \
+    emitError(__FILE__ ":" QUOTE(__LINE__) ": type lowering of " S             \
+                                           " not implemented");                \
+    exit(1);                                                                   \
+  }
+
+template <typename A>
+bool isConstant(const Fortran::evaluate::Expr<A> &e) {
+  return Fortran::evaluate::IsConstantExpr(Fortran::lower::SomeExpr{e});
+}
+
+template <typename A>
+int64_t toConstant(const Fortran::evaluate::Expr<A> &e) {
+  auto opt = Fortran::evaluate::ToInt64(e);
+  assert(opt.has_value() && "expression didn't resolve to a constant");
+  return opt.value();
+}
+
+// one argument template, must be specialized
+template <Fortran::common::TypeCategory TC>
+mlir::Type genFIRType(mlir::MLIRContext *, int) {
+  return {};
+}
+
+// two argument template
+template <Fortran::common::TypeCategory TC, int KIND>
+mlir::Type genFIRType(mlir::MLIRContext *context) {
+  if constexpr (TC == Fortran::common::TypeCategory::Integer) {
+    auto bits{Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer,
+                                      KIND>::Scalar::bits};
+    return mlir::IntegerType::get(bits, context);
+  } else if constexpr (TC == Fortran::common::TypeCategory::Logical ||
+                       TC == Fortran::common::TypeCategory::Character ||
+                       TC == Fortran::common::TypeCategory::Complex) {
+    return genFIRType<TC>(context, KIND);
+  } else {
+    return {};
+  }
+}
+
+template <>
+mlir::Type
+genFIRType<Fortran::common::TypeCategory::Real, 2>(mlir::MLIRContext *context) {
+  return mlir::FloatType::getF16(context);
+}
+
+template <>
+mlir::Type
+genFIRType<Fortran::common::TypeCategory::Real, 3>(mlir::MLIRContext *context) {
+  return mlir::FloatType::getBF16(context);
+}
+
+template <>
+mlir::Type
+genFIRType<Fortran::common::TypeCategory::Real, 4>(mlir::MLIRContext *context) {
+  return mlir::FloatType::getF32(context);
+}
+
+template <>
+mlir::Type
+genFIRType<Fortran::common::TypeCategory::Real, 8>(mlir::MLIRContext *context) {
+  return mlir::FloatType::getF64(context);
+}
+
+template <>
+mlir::Type genFIRType<Fortran::common::TypeCategory::Real, 10>(
+    mlir::MLIRContext *context) {
+  return fir::RealType::get(context, 10);
+}
+
+template <>
+mlir::Type genFIRType<Fortran::common::TypeCategory::Real, 16>(
+    mlir::MLIRContext *context) {
+  return fir::RealType::get(context, 16);
+}
+
+template <>
+mlir::Type
+genFIRType<Fortran::common::TypeCategory::Real>(mlir::MLIRContext *context,
+                                                int kind) {
+  if (Fortran::evaluate::IsValidKindOfIntrinsicType(
+          Fortran::common::TypeCategory::Real, kind)) {
+    switch (kind) {
+    case 2:
+      return genFIRType<Fortran::common::TypeCategory::Real, 2>(context);
+    case 3:
+      return genFIRType<Fortran::common::TypeCategory::Real, 3>(context);
+    case 4:
+      return genFIRType<Fortran::common::TypeCategory::Real, 4>(context);
+    case 8:
+      return genFIRType<Fortran::common::TypeCategory::Real, 8>(context);
+    case 10:
+      return genFIRType<Fortran::common::TypeCategory::Real, 10>(context);
+    case 16:
+      return genFIRType<Fortran::common::TypeCategory::Real, 16>(context);
+    }
+  }
+  llvm_unreachable("REAL type translation not implemented");
+}
+
+template <>
+mlir::Type
+genFIRType<Fortran::common::TypeCategory::Integer>(mlir::MLIRContext *context,
+                                                   int kind) {
+  if (Fortran::evaluate::IsValidKindOfIntrinsicType(
+          Fortran::common::TypeCategory::Integer, kind)) {
+    switch (kind) {
+    case 1:
+      return genFIRType<Fortran::common::TypeCategory::Integer, 1>(context);
+    case 2:
+      return genFIRType<Fortran::common::TypeCategory::Integer, 2>(context);
+    case 4:
+      return genFIRType<Fortran::common::TypeCategory::Integer, 4>(context);
+    case 8:
+      return genFIRType<Fortran::common::TypeCategory::Integer, 8>(context);
+    case 16:
+      return genFIRType<Fortran::common::TypeCategory::Integer, 16>(context);
+    }
+  }
+  llvm_unreachable("INTEGER type translation not implemented");
+}
+
+template <>
+mlir::Type
+genFIRType<Fortran::common::TypeCategory::Logical>(mlir::MLIRContext *context,
+                                                   int KIND) {
+  if (Fortran::evaluate::IsValidKindOfIntrinsicType(
+          Fortran::common::TypeCategory::Logical, KIND))
+    return fir::LogicalType::get(context, KIND);
+  return {};
+}
+
+template <>
+mlir::Type
+genFIRType<Fortran::common::TypeCategory::Character>(mlir::MLIRContext *context,
+                                                     int KIND) {
+  if (Fortran::evaluate::IsValidKindOfIntrinsicType(
+          Fortran::common::TypeCategory::Character, KIND))
+    return fir::CharacterType::get(context, KIND);
+  return {};
+}
+
+template <>
+mlir::Type
+genFIRType<Fortran::common::TypeCategory::Complex>(mlir::MLIRContext *context,
+                                                   int KIND) {
+  if (Fortran::evaluate::IsValidKindOfIntrinsicType(
+          Fortran::common::TypeCategory::Complex, KIND))
+    return fir::CplxType::get(context, KIND);
+  return {};
+}
+
+namespace {
+
+/// Discover the type of an Fortran::evaluate::Expr<T> and convert it to an
+/// mlir::Type. The type returned may be an MLIR standard or FIR type.
+class TypeBuilder {
+public:
+  
+  /// Constructor.
+  explicit TypeBuilder(
+      mlir::MLIRContext *context,
+      const Fortran::common::IntrinsicTypeDefaultKinds &defaults)
+      : context{context}, defaults{defaults} {}
+
+  
+  //===--------------------------------------------------------------------===//
+  // Generate type entry points
+  //===--------------------------------------------------------------------===//
+  
+  template <template <typename> typename A, Fortran::common::TypeCategory TC>
+  mlir::Type gen(const A<Fortran::evaluate::SomeKind<TC>> &) {
+    return genFIRType<TC>(context, defaultKind<TC>());
+  }
+
+  template <template <typename> typename A, Fortran::common::TypeCategory TC,
+            int KIND>
+  mlir::Type gen(const A<Fortran::evaluate::Type<TC, KIND>> &) {
+    return genFIRType<TC, KIND>(context);
+  }
+
+  // breaks the conflict between A<Type<TC,KIND>> and Expr<B> deduction
+  template <Fortran::common::TypeCategory TC, int KIND>
+  mlir::Type
+  gen(const Fortran::evaluate::Expr<Fortran::evaluate::Type<TC, KIND>> &) {
+    return genFIRType<TC, KIND>(context);
+  }
+
+  // breaks the conflict between A<SomeKind<TC>> and Expr<B> deduction
+  template <Fortran::common::TypeCategory TC>
+  mlir::Type
+  gen(const Fortran::evaluate::Expr<Fortran::evaluate::SomeKind<TC>> &expr) {
+    return genVariant(expr);
+  }
+
+  template <typename A>
+  mlir::Type gen(const Fortran::evaluate::Expr<A> &expr) {
+    return genVariant(expr);
+  }
+
+  mlir::Type gen(const Fortran::evaluate::DataRef &dref) {
+    return genVariant(dref);
+  }
+
+  mlir::Type gen(const Fortran::lower::pft::Variable &var) {
+    return genSymbolHelper(var.getSymbol(), var.isHeapAlloc(), var.isPointer());
+  }
+
+  /// Type consing from a symbol. A symbol's type must be created from the type
+  /// discovered by the front-end at runtime.
+  mlir::Type gen(Fortran::semantics::SymbolRef symbol) {
+    return genSymbolHelper(symbol);
+  }
+
+  // non-template, category is runtime values, kind is defaulted
+  mlir::Type genFIRTy(Fortran::common::TypeCategory tc) {
+    return genFIRTy(tc, defaultKind(tc));
+  }
+
+  // non-template, arguments are runtime values
+  mlir::Type genFIRTy(Fortran::common::TypeCategory tc, int kind) {
+    switch (tc) {
+    case Fortran::common::TypeCategory::Real:
+      return genFIRType<Fortran::common::TypeCategory::Real>(context, kind);
+    case Fortran::common::TypeCategory::Integer:
+      return genFIRType<Fortran::common::TypeCategory::Integer>(context, kind);
+    case Fortran::common::TypeCategory::Complex:
+      return genFIRType<Fortran::common::TypeCategory::Complex>(context, kind);
+    case Fortran::common::TypeCategory::Logical:
+      return genFIRType<Fortran::common::TypeCategory::Logical>(context, kind);
+    case Fortran::common::TypeCategory::Character:
+      return genFIRType<Fortran::common::TypeCategory::Character>(context,
+                                                                  kind);
+    default:
+      break;
+    }
+    llvm_unreachable("unhandled type category");
+  }
+
+private:
+  //===--------------------------------------------------------------------===//
+  // Generate type helpers
+  //===--------------------------------------------------------------------===//
+  
+  mlir::Type gen(const Fortran::evaluate::ImpliedDoIndex &) {
+    return genFIRType<Fortran::common::TypeCategory::Integer>(
+        context, defaultKind<Fortran::common::TypeCategory::Integer>());
+  }
+
+  template <int KIND>
+  mlir::Type gen(const Fortran::evaluate::TypeParamInquiry<KIND> &) {
+    return genFIRType<Fortran::common::TypeCategory::Integer, KIND>(context);
+  }
+
+  template <typename A>
+  mlir::Type gen(const Fortran::evaluate::Relational<A> &) {
+    return genFIRType<Fortran::common::TypeCategory::Logical, 1>(context);
+  }
+
+  // some sequence of `n` bytes
+  mlir::Type gen(const Fortran::evaluate::StaticDataObject::Pointer &ptr) {
+    mlir::Type byteTy{mlir::IntegerType::get(8, context)};
+    return fir::SequenceType::get(trivialShape(ptr->itemBytes()), byteTy);
+  }
+
+  mlir::Type gen(const Fortran::evaluate::Substring &ss) {
+    return genVariant(ss.GetBaseObject());
+  }
+
+  mlir::Type gen(const Fortran::evaluate::NullPointer &) {
+    return genTypelessPtr();
+  }
+  mlir::Type gen(const Fortran::evaluate::ProcedureRef &) {
+    return genTypelessPtr();
+  }
+  mlir::Type gen(const Fortran::evaluate::ProcedureDesignator &) {
+    return genTypelessPtr();
+  }
+  mlir::Type gen(const Fortran::evaluate::BOZLiteralConstant &) {
+    return genTypelessPtr();
+  }
+  mlir::Type gen(const Fortran::evaluate::ArrayRef &) { TODO("array ref"); }
+  mlir::Type gen(const Fortran::evaluate::CoarrayRef &) { TODO("coarray ref"); }
+  mlir::Type gen(const Fortran::evaluate::Component &) { TODO("component"); }
+  mlir::Type gen(const Fortran::evaluate::ComplexPart &) {
+    TODO("complex part");
+  }
+  mlir::Type gen(const Fortran::evaluate::DescriptorInquiry &) {
+    TODO("descriptor inquiry");
+  }
+  mlir::Type gen(const Fortran::evaluate::StructureConstructor &) {
+    TODO("structure constructor");
+  }
+
+  fir::SequenceType::Shape genSeqShape(Fortran::semantics::SymbolRef symbol) {
+    assert(symbol->IsObjectArray() && "unexpected symbol type");
+    fir::SequenceType::Shape bounds;
+    return seqShapeHelper(symbol, bounds);
+  }
+
+  fir::SequenceType::Shape genSeqShape(Fortran::semantics::SymbolRef symbol,
+                                       fir::SequenceType::Extent charLen) {
+    assert(symbol->IsObjectArray() && "unexpected symbol type");
+    fir::SequenceType::Shape bounds;
+    bounds.push_back(charLen);
+    return seqShapeHelper(symbol, bounds);
+  }
+
+  mlir::Type genSymbolHelper(const Fortran::semantics::Symbol &symbol,
+                             bool isAlloc = false, bool isPtr = false) {
+    mlir::Type ty;
+    if (auto *type{symbol.GetType()}) {
+      if (auto *tySpec{type->AsIntrinsic()}) {
+        int kind = toConstant(tySpec->kind());
+        switch (tySpec->category()) {
+        case Fortran::common::TypeCategory::Integer:
+          ty =
+              genFIRType<Fortran::common::TypeCategory::Integer>(context, kind);
+          break;
+        case Fortran::common::TypeCategory::Real:
+          ty = genFIRType<Fortran::common::TypeCategory::Real>(context, kind);
+          break;
+        case Fortran::common::TypeCategory::Complex:
+          ty =
+              genFIRType<Fortran::common::TypeCategory::Complex>(context, kind);
+          break;
+        case Fortran::common::TypeCategory::Character:
+          ty = genFIRType<Fortran::common::TypeCategory::Character>(context,
+                                                                    kind);
+          break;
+        case Fortran::common::TypeCategory::Logical:
+          ty =
+              genFIRType<Fortran::common::TypeCategory::Logical>(context, kind);
+          break;
+        default:
+          emitError("symbol has unknown intrinsic type");
+          return {};
+        }
+      } else if (auto *tySpec = type->AsDerived()) {
+        std::vector<std::pair<std::string, mlir::Type>> ps;
+        std::vector<std::pair<std::string, mlir::Type>> cs;
+        auto &symbol = tySpec->typeSymbol();
+        // FIXME: don't want to recurse forever here, but this won't happen
+        // since we don't know the components at this time
+        auto rec = fir::RecordType::get(context, toStringRef(symbol.name()));
+        auto &details = symbol.get<Fortran::semantics::DerivedTypeDetails>();
+        for (auto &param : details.paramDecls()) {
+          auto &p{*param};
+          ps.push_back(std::pair{p.name().ToString(), gen(p)});
+        }
+        emitError("the front-end returns symbols of derived type that have "
+                  "components that are simple names and not symbols, so cannot "
+                  "construct the type '" +
+                  toStringRef(symbol.name()) + "'");
+        rec.finalize(ps, cs);
+        ty = rec;
+      } else {
+        emitError("symbol's type must have a type spec");
+        return {};
+      }
+    } else {
+      emitError("symbol must have a type");
+      return {};
+    }
+    if (symbol.IsObjectArray()) {
+      if (symbol.GetType()->category() ==
+          Fortran::semantics::DeclTypeSpec::Character) {
+        auto charLen = fir::SequenceType::getUnknownExtent();
+        const auto &lenParam = symbol.GetType()->characterTypeSpec().length();
+        if (auto expr = lenParam.GetExplicit()) {
+          auto len = Fortran::evaluate::AsGenericExpr(std::move(*expr));
+          auto asInt = Fortran::evaluate::ToInt64(len);
+          if (asInt)
+            charLen = *asInt;
+        }
+        return fir::SequenceType::get(genSeqShape(symbol, charLen), ty);
+      }
+      return fir::SequenceType::get(genSeqShape(symbol), ty);
+    }
+    if (isPtr || Fortran::semantics::IsPointer(symbol))
+      ty = fir::PointerType::get(ty);
+    else if (isAlloc || Fortran::semantics::IsAllocatable(symbol))
+      ty = fir::HeapType::get(ty);
+    return ty;
+  }
+
+  //===--------------------------------------------------------------------===//
+  // Other helper functions
+  //===--------------------------------------------------------------------===//
+
+  fir::SequenceType::Shape trivialShape(int size) {
+    fir::SequenceType::Shape bounds;
+    bounds.emplace_back(size);
+    return bounds;
+  }
+
+  mlir::Type mkVoid() { return mlir::TupleType::get(context); }
+  mlir::Type genTypelessPtr() { return fir::ReferenceType::get(mkVoid()); }
+
+  template <typename A>
+  mlir::Type genVariant(const A &variant) {
+    return std::visit([&](const auto &x) { return gen(x); }, variant.u);
+  }
+
+  template <Fortran::common::TypeCategory TC>
+  int defaultKind() {
+    return defaultKind(TC);
+  }
+  int defaultKind(Fortran::common::TypeCategory TC) {
+    return defaults.GetDefaultKind(TC);
+  }
+
+  fir::SequenceType::Shape seqShapeHelper(Fortran::semantics::SymbolRef symbol,
+                                          fir::SequenceType::Shape &bounds) {
+    auto &details = symbol->get<Fortran::semantics::ObjectEntityDetails>();
+    const auto size = details.shape().size();
+    for (auto &ss : details.shape()) {
+      auto lb = ss.lbound();
+      auto ub = ss.ubound();
+      if (lb.isAssumed() && ub.isAssumed() && size == 1)
+        return {};
+      if (lb.isExplicit() && ub.isExplicit()) {
+        auto &lbv = lb.GetExplicit();
+        auto &ubv = ub.GetExplicit();
+        if (lbv.has_value() && ubv.has_value() && isConstant(lbv.value()) &&
+            isConstant(ubv.value())) {
+          bounds.emplace_back(toConstant(ubv.value()) -
+                              toConstant(lbv.value()) + 1);
+        } else {
+          bounds.emplace_back(fir::SequenceType::getUnknownExtent());
+        }
+      } else {
+        bounds.emplace_back(fir::SequenceType::getUnknownExtent());
+      }
+    }
+    return bounds;
+  }
+
+  //===--------------------------------------------------------------------===//
+  // Emit errors and warnings.
+  //===--------------------------------------------------------------------===//
+
+  mlir::InFlightDiagnostic emitError(const llvm::Twine &message) {
+    return mlir::emitError(mlir::UnknownLoc::get(context), message);
+  }
+
+  mlir::InFlightDiagnostic emitWarning(const llvm::Twine &message) {
+    return mlir::emitWarning(mlir::UnknownLoc::get(context), message);
+  }
+
+  //===--------------------------------------------------------------------===//
+
+  mlir::MLIRContext *context;
+  const Fortran::common::IntrinsicTypeDefaultKinds &defaults;
+};
+
+} // namespace
+
+mlir::Type Fortran::lower::getFIRType(
+    mlir::MLIRContext *context,
+    const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
+    Fortran::common::TypeCategory tc, int kind) {
+  return TypeBuilder{context, defaults}.genFIRTy(tc, kind);
+}
+
+mlir::Type Fortran::lower::getFIRType(
+    mlir::MLIRContext *context,
+    const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
+    Fortran::common::TypeCategory tc) {
+  return TypeBuilder{context, defaults}.genFIRTy(tc);
+}
+
+mlir::Type Fortran::lower::translateDataRefToFIRType(
+    mlir::MLIRContext *context,
+    const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
+    const Fortran::evaluate::DataRef &dataRef) {
+  return TypeBuilder{context, defaults}.gen(dataRef);
+}
+
+mlir::Type Fortran::lower::translateSomeExprToFIRType(
+    mlir::MLIRContext *context,
+    const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
+    const SomeExpr *expr) {
+  return TypeBuilder{context, defaults}.gen(*expr);
+}
+
+mlir::Type Fortran::lower::translateSymbolToFIRType(
+    mlir::MLIRContext *context,
+    const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
+    const SymbolRef symbol) {
+  return TypeBuilder{context, defaults}.gen(symbol);
+}
+
+mlir::Type Fortran::lower::translateVariableToFIRType(
+    mlir::MLIRContext *context,
+    const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
+    const Fortran::lower::pft::Variable &var) {
+  return TypeBuilder{context, defaults}.gen(var);
+}
+
+mlir::Type Fortran::lower::convertReal(mlir::MLIRContext *context, int kind) {
+  return genFIRType<Fortran::common::TypeCategory::Real>(context, kind);
+}
+
+mlir::Type Fortran::lower::getSequenceRefType(mlir::Type refType) {
+  auto type{refType.dyn_cast<fir::ReferenceType>()};
+  assert(type && "expected a reference type");
+  auto elementType{type.getEleTy()};
+  fir::SequenceType::Shape shape{fir::SequenceType::getUnknownExtent()};
+  return fir::ReferenceType::get(fir::SequenceType::get(shape, elementType));
+}


        


More information about the flang-commits mailing list