forked from OSchip/llvm-project
[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
This commit is contained in:
parent
c19fae507e
commit
baa12ddb6f
|
@ -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
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
add_flang_library(FortranLower
|
||||
ConvertType.cpp
|
||||
OpenMP.cpp
|
||||
PFTBuilder.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 ¶m : 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));
|
||||
}
|
Loading…
Reference in New Issue