[flang-commits] [flang] 841f699 - [flang][fir][NFC] Move remaining types to TableGen type definition
via flang-commits
flang-commits at lists.llvm.org
Wed Feb 24 17:23:40 PST 2021
Author: Valentin Clement
Date: 2021-02-24T20:23:31-05:00
New Revision: 841f6995cd33b8891655b2aeb78deca548362c23
URL: https://github.com/llvm/llvm-project/commit/841f6995cd33b8891655b2aeb78deca548362c23
DIFF: https://github.com/llvm/llvm-project/commit/841f6995cd33b8891655b2aeb78deca548362c23.diff
LOG: [flang][fir][NFC] Move remaining types to TableGen type definition
Move the remaing of FIR types to TableGen type definition. This follow suggestion in D96422.
Reviewed By: schweitz, jeanPerier, rriddle
Differential Revision: https://reviews.llvm.org/D96987
Added:
Modified:
flang/include/flang/Optimizer/Dialect/FIROps.td
flang/include/flang/Optimizer/Dialect/FIRType.h
flang/include/flang/Optimizer/Dialect/FIRTypes.td
flang/lib/Optimizer/Dialect/FIRType.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index 40f0bb8e9d8e..fed8b8d770fa 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -22,94 +22,6 @@ include "mlir/Interfaces/SideEffectInterfaces.td"
include "flang/Optimizer/Dialect/FIRTypes.td"
-// Types and predicates
-
-def fir_Type : Type<CPred<"fir::isa_fir_or_std_type($_self)">,
- "FIR dialect type">;
-
-// Fortran intrinsic types
-def fir_IntegerType : Type<CPred<"$_self.isa<fir::IntegerType>()">,
- "FIR integer type">;
-def fir_LogicalType : Type<CPred<"$_self.isa<fir::LogicalType>()">,
- "FIR logical type">;
-def fir_RealType : Type<CPred<"$_self.isa<fir::RealType>()">,
- "FIR real type">;
-def fir_VectorType : Type<CPred<"$_self.isa<fir::VectorType>()">,
- "FIR vector type">;
-
-// Generalized FIR and standard dialect types representing intrinsic types
-def AnyIntegerLike : TypeConstraint<Or<[SignlessIntegerLike.predicate,
- fir_IntegerType.predicate]>, "any integer">;
-def AnyLogicalLike : TypeConstraint<Or<[BoolLike.predicate,
- fir_LogicalType.predicate]>, "any logical">;
-def AnyRealLike : TypeConstraint<Or<[FloatLike.predicate,
- fir_RealType.predicate]>, "any real">;
-def AnyIntegerType : Type<AnyIntegerLike.predicate, "any integer">;
-
-// Fortran derived (user defined) type
-def fir_RecordType : Type<CPred<"$_self.isa<fir::RecordType>()">,
- "FIR derived type">;
-
-// Fortran array attribute
-def fir_SequenceType : Type<CPred<"$_self.isa<fir::SequenceType>()">,
- "array type">;
-
-// Composable types
-def AnyCompositeLike : TypeConstraint<Or<[fir_RecordType.predicate,
- fir_SequenceType.predicate, fir_ComplexType.predicate,
- fir_VectorType.predicate, IsTupleTypePred]>, "any composite">;
-
-// Reference to an entity type
-def fir_ReferenceType : Type<CPred<"$_self.isa<fir::ReferenceType>()">,
- "reference type">;
-
-// Reference to an ALLOCATABLE attribute type
-def fir_HeapType : Type<CPred<"$_self.isa<fir::HeapType>()">,
- "allocatable type">;
-
-// Reference to a POINTER attribute type
-def fir_PointerType : Type<CPred<"$_self.isa<fir::PointerType>()">,
- "pointer type">;
-
-// Reference types
-def AnyReferenceLike : TypeConstraint<Or<[fir_ReferenceType.predicate,
- fir_HeapType.predicate, fir_PointerType.predicate]>, "any reference">;
-
-def AnyBoxLike : TypeConstraint<Or<[fir_BoxType.predicate,
- fir_BoxCharType.predicate, fir_BoxProcType.predicate]>, "any box">;
-
-def AnyRefOrBox : TypeConstraint<Or<[fir_ReferenceType.predicate,
- fir_HeapType.predicate, fir_PointerType.predicate, fir_BoxType.predicate]>,
- "any reference or box">;
-
-def AnyShapeLike : TypeConstraint<Or<[fir_ShapeType.predicate,
- fir_ShapeShiftType.predicate]>, "any legal shape type">;
-def AnyShapeType : Type<AnyShapeLike.predicate, "any legal shape type">;
-def fir_SliceType : Type<CPred<"$_self.isa<fir::SliceType>()">, "slice type">;
-
-def AnyEmboxLike : TypeConstraint<Or<[AnySignlessInteger.predicate,
- Index.predicate, fir_IntegerType.predicate]>,
- "any legal embox argument type">;
-def AnyEmboxArg : Type<AnyEmboxLike.predicate, "embox argument type">;
-
-// A type descriptor's type
-def fir_TypeDescType : Type<CPred<"$_self.isa<fir::TypeDescType>()">,
- "type desc type">;
-
-// A LEN parameter (in a RecordType) argument's type
-def fir_LenType : Type<CPred<"$_self.isa<fir::LenType>()">,
- "LEN parameter type">;
-
-def AnyComponentLike : TypeConstraint<Or<[AnySignlessInteger.predicate,
- Index.predicate, fir_IntegerType.predicate, fir_FieldType.predicate]>,
- "any coordinate index">;
-def AnyComponentType : Type<AnyComponentLike.predicate, "coordinate type">;
-
-def AnyCoordinateLike : TypeConstraint<Or<[AnySignlessInteger.predicate,
- Index.predicate, fir_IntegerType.predicate, fir_FieldType.predicate,
- fir_LenType.predicate]>, "any coordinate index">;
-def AnyCoordinateType : Type<AnyCoordinateLike.predicate, "coordinate type">;
-
// Base class for FIR operations.
// All operations automatically get a prefix of "fir.".
class fir_Op<string mnemonic, list<OpTrait> traits>
@@ -2251,7 +2163,7 @@ def fir_StringLitOp : fir_Op<"string_lit", [NoSideEffect]> {
if (!(type.isa<fir::CharacterType>() || type.isa<mlir::IntegerType>()))
return parser.emitError(parser.getCurrentLocation(),
"must have character type");
- type = fir::SequenceType::get({sz.getInt()}, type);
+ type = fir::SequenceType::get(type.getContext(), {sz.getInt()}, type, {});
if (!type || parser.addTypesToList(type, result.types))
return mlir::failure();
return mlir::success();
diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index e8972cfdb5e9..2477b07d1d08 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -41,18 +41,7 @@ class FIROpsDialect;
using KindTy = unsigned;
namespace detail {
-struct HeapTypeStorage;
-struct IntegerTypeStorage;
-struct LenTypeStorage;
-struct LogicalTypeStorage;
-struct PointerTypeStorage;
-struct RealTypeStorage;
struct RecordTypeStorage;
-struct ReferenceTypeStorage;
-struct SequenceTypeStorage;
-struct SliceTypeStorage;
-struct TypeDescTypeStorage;
-struct VectorTypeStorage;
} // namespace detail
// These isa_ routines follow the precedent of llvm::isa_or_null<>
@@ -91,213 +80,6 @@ bool isa_aggregate(mlir::Type t);
/// not a memory reference type, then returns a null `Type`.
mlir::Type dyn_cast_ptrEleTy(mlir::Type t);
-// Intrinsic types
-
-/// Model of a Fortran INTEGER intrinsic type, including the KIND type
-/// parameter.
-class IntegerType : public mlir::Type::TypeBase<fir::IntegerType, mlir::Type,
- detail::IntegerTypeStorage> {
-public:
- using Base::Base;
- static fir::IntegerType get(mlir::MLIRContext *ctxt, KindTy kind);
- KindTy getFKind() const;
-};
-
-/// Model of a Fortran LOGICAL intrinsic type, including the KIND type
-/// parameter.
-class LogicalType : public mlir::Type::TypeBase<LogicalType, mlir::Type,
- detail::LogicalTypeStorage> {
-public:
- using Base::Base;
- static LogicalType get(mlir::MLIRContext *ctxt, KindTy kind);
- KindTy getFKind() const;
-};
-
-/// Model of a Fortran REAL (and DOUBLE PRECISION) intrinsic type, including the
-/// KIND type parameter.
-class RealType : public mlir::Type::TypeBase<RealType, mlir::Type,
- detail::RealTypeStorage> {
-public:
- using Base::Base;
- static RealType get(mlir::MLIRContext *ctxt, KindTy kind);
- KindTy getFKind() const;
-};
-
-// FIR support types
-
-/// Type of a vector that represents an array slice operation on an array.
-/// Fortran slices are triples of lower bound, upper bound, and stride. The rank
-/// of a SliceType must be at least 1.
-class SliceType : public mlir::Type::TypeBase<SliceType, mlir::Type,
- detail::SliceTypeStorage> {
-public:
- using Base::Base;
- static SliceType get(mlir::MLIRContext *ctx, unsigned rank);
- unsigned getRank() const;
-};
-
-/// The type of a heap pointer. Fortran entities with the ALLOCATABLE attribute
-/// may be allocated on the heap at runtime. These pointers are explicitly
-/// distinguished to disallow the composition of multiple levels of
-/// indirection. For example, an ALLOCATABLE POINTER is invalid.
-class HeapType : public mlir::Type::TypeBase<HeapType, mlir::Type,
- detail::HeapTypeStorage> {
-public:
- using Base::Base;
- static HeapType get(mlir::Type elementType);
-
- mlir::Type getEleTy() const;
-
- static mlir::LogicalResult
- verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- mlir::Type eleTy);
-};
-
-/// The type of a LEN parameter name. Implementations may defer the layout of a
-/// Fortran derived type until runtime. This implies that the runtime must be
-/// able to determine the offset of LEN type parameters related to an entity.
-class LenType
- : public mlir::Type::TypeBase<LenType, mlir::Type, detail::LenTypeStorage> {
-public:
- using Base::Base;
- static LenType get(mlir::MLIRContext *ctxt);
-};
-
-/// The type of entities with the POINTER attribute. These pointers are
-/// explicitly distinguished to disallow the composition of multiple levels of
-/// indirection. For example, an ALLOCATABLE POINTER is invalid.
-class PointerType : public mlir::Type::TypeBase<PointerType, mlir::Type,
- detail::PointerTypeStorage> {
-public:
- using Base::Base;
- static PointerType get(mlir::Type elementType);
-
- mlir::Type getEleTy() const;
-
- static mlir::LogicalResult
- verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- mlir::Type eleTy);
-};
-
-/// The type of a reference to an entity in memory.
-class ReferenceType
- : public mlir::Type::TypeBase<ReferenceType, mlir::Type,
- detail::ReferenceTypeStorage> {
-public:
- using Base::Base;
- static ReferenceType get(mlir::Type elementType);
-
- mlir::Type getEleTy() const;
-
- static mlir::LogicalResult
- verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- mlir::Type eleTy);
-};
-
-/// A sequence type is a multi-dimensional array of values. The sequence type
-/// may have an unknown number of dimensions or the extent of dimensions may be
-/// unknown. A sequence type models a Fortran array entity, giving it a type in
-/// FIR. A sequence type is assumed to be stored in a column-major order, which
-///
diff ers from LLVM IR and other dialects of MLIR.
-class SequenceType : public mlir::Type::TypeBase<SequenceType, mlir::Type,
- detail::SequenceTypeStorage> {
-public:
- using Base::Base;
- using Extent = int64_t;
- using Shape = llvm::SmallVector<Extent, 8>;
-
- /// Return a sequence type with the specified shape and element type
- static SequenceType get(const Shape &shape, mlir::Type elementType,
- mlir::AffineMapAttr map = {});
-
- /// The element type of this sequence
- mlir::Type getEleTy() const;
-
- /// The shape of the sequence. If the sequence has an unknown shape, the shape
- /// returned will be empty.
- Shape getShape() const;
-
- mlir::AffineMapAttr getLayoutMap() const;
-
- /// The number of dimensions of the sequence
- unsigned getDimension() const { return getShape().size(); }
-
- /// Number of rows of constant extent
- unsigned getConstantRows() const;
-
- /// Is the shape of the sequence constant?
- bool hasConstantShape() const { return getConstantRows() == getDimension(); }
-
- /// Does the sequence have unknown shape? (`array<* x T>`)
- bool hasUnknownShape() const { return getShape().empty(); }
-
- /// Is the interior of the sequence constant? Check if the array is
- /// one of constant shape (`array<C...xCxT>`), unknown shape
- /// (`array<*xT>`), or rows with shape and ending with column(s) of
- /// unknown extent (`array<C...xCx?...x?xT>`).
- bool hasConstantInterior() const;
-
- /// The value `-1` represents an unknown extent for a dimension
- static constexpr Extent getUnknownExtent() { return -1; }
-
- static mlir::LogicalResult
- verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- const Shape &shape, mlir::Type eleTy, mlir::AffineMapAttr map);
-};
-
-bool operator==(const SequenceType::Shape &, const SequenceType::Shape &);
-llvm::hash_code hash_value(const SequenceType::Extent &);
-llvm::hash_code hash_value(const SequenceType::Shape &);
-
-/// The type of a type descriptor object. The runtime may generate type
-/// descriptor objects to determine the type of an entity at runtime, etc.
-class TypeDescType : public mlir::Type::TypeBase<TypeDescType, mlir::Type,
- detail::TypeDescTypeStorage> {
-public:
- using Base::Base;
- static TypeDescType get(mlir::Type ofType);
- mlir::Type getOfTy() const;
-
- static mlir::LogicalResult
- verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- mlir::Type ofType);
-};
-
-// Derived types
-
-/// Model of Fortran's derived type, TYPE. The name of the TYPE includes any
-/// KIND type parameters. The record includes runtime slots for LEN type
-/// parameters and for data components.
-class RecordType : public mlir::Type::TypeBase<RecordType, mlir::Type,
- detail::RecordTypeStorage> {
-public:
- using Base::Base;
- using TypePair = std::pair<std::string, mlir::Type>;
- using TypeList = std::vector<TypePair>;
-
- llvm::StringRef getName();
- TypeList getTypeList();
- TypeList getLenParamList();
-
- mlir::Type getType(llvm::StringRef ident);
- mlir::Type getType(unsigned index) {
- assert(index < getNumFields());
- return getTypeList()[index].second;
- }
- unsigned getNumFields() { return getTypeList().size(); }
- unsigned getNumLenParams() { return getLenParamList().size(); }
-
- static RecordType get(mlir::MLIRContext *ctxt, llvm::StringRef name);
- void finalize(llvm::ArrayRef<TypePair> lenPList,
- llvm::ArrayRef<TypePair> typeList);
-
- detail::RecordTypeStorage const *uniqueKey() const;
-
- static mlir::LogicalResult
- verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- llvm::StringRef name);
-};
-
/// Is `t` a FIR Real or MLIR Float type?
inline bool isa_real(mlir::Type t) {
return t.isa<fir::RealType>() || t.isa<mlir::FloatType>();
@@ -309,26 +91,6 @@ inline bool isa_integer(mlir::Type t) {
t.isa<fir::IntegerType>();
}
-/// Replacement for the builtin vector type.
-/// The FIR vector type is always rank one. It's size is always a constant.
-/// A vector's element type must be real or integer.
-class VectorType : public mlir::Type::TypeBase<fir::VectorType, mlir::Type,
- detail::VectorTypeStorage> {
-public:
- using Base::Base;
-
- static fir::VectorType get(uint64_t len, mlir::Type eleTy);
- mlir::Type getEleTy() const;
- uint64_t getLen() const;
-
- static mlir::LogicalResult
- verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError, uint64_t len,
- mlir::Type eleTy);
- static bool isValidElementType(mlir::Type t) {
- return isa_real(t) || isa_integer(t);
- }
-};
-
mlir::Type parseFirType(FIROpsDialect *, mlir::DialectAsmParser &parser);
void printFirType(FIROpsDialect *, mlir::Type ty, mlir::DialectAsmPrinter &p);
@@ -353,6 +115,14 @@ inline bool isa_char_string(mlir::Type t) {
/// of unknown rank or type.
bool isa_unknown_size_box(mlir::Type t);
+#ifndef NDEBUG
+// !fir.ptr<X> and !fir.heap<X> where X is !fir.ptr, !fir.heap, or !fir.ref
+// is undefined and disallowed.
+inline bool singleIndirectionLevel(mlir::Type ty) {
+ return !fir::isa_ref_type(ty);
+}
+#endif
+
} // namespace fir
#endif // OPTIMIZER_DIALECT_FIRTYPE_H
diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
index 07c2c58c7c16..a5bbbbdc0798 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
@@ -23,6 +23,9 @@ class FIR_Type<string name, string typeMnemonic> : TypeDef<fir_Dialect, name> {
let mnemonic = typeMnemonic;
}
+def fir_Type : Type<CPred<"fir::isa_fir_or_std_type($_self)">,
+ "FIR dialect type">;
+
def fir_BoxCharType : FIR_Type<"BoxChar", "boxchar"> {
let summary = "CHARACTER type descriptor.";
@@ -34,10 +37,6 @@ def fir_BoxCharType : FIR_Type<"BoxChar", "boxchar"> {
let parameters = (ins "KindTy":$kind);
- let printer = [{
- $_printer << "boxchar<" << getImpl()->kind << ">";
- }];
-
let genAccessors = 1;
let extraClassDeclaration = [{
@@ -61,13 +60,6 @@ def fir_BoxProcType : FIR_Type<"BoxProc", "boxproc"> {
let parameters = (ins "mlir::Type":$eleTy);
- let printer = [{
- $_printer << "boxproc<";
- $_printer.printType(getEleTy());
- $_printer << '>';
- }];
-
- let genAccessors = 1;
let genVerifyDecl = 1;
}
@@ -82,15 +74,21 @@ def fir_BoxType : FIR_Type<"Box", "box"> {
let parameters = (ins "mlir::Type":$eleTy, "mlir::AffineMapAttr":$map);
+ let skipDefaultBuilders = 1;
+
+ let builders = [
+ TypeBuilderWithInferredContext<(ins
+ "mlir::Type":$eleTy,
+ CArg<"mlir::AffineMapAttr", "{}">:$map), [{
+ return Base::get(eleTy.getContext(), eleTy, map);
+ }]>,
+ ];
+
let extraClassDeclaration = [{
mlir::Type getElementType() const { return getEleTy(); }
mlir::AffineMapAttr getLayoutMap() const { return getMap(); }
- static BoxType get(mlir::Type eleTy, mlir::AffineMapAttr map = {}) {
- return get(eleTy.getContext(), eleTy, map);
- }
}];
- let genAccessors = 1;
let genVerifyDecl = 1;
}
@@ -138,12 +136,6 @@ def fir_ComplexType : FIR_Type<"Complex", "complex"> {
let parameters = (ins "KindTy":$fKind);
- let printer = [{
- $_printer << "complex<" << getFKind() << '>';
- }];
-
- let genAccessors = 1;
-
let extraClassDeclaration = [{
using KindTy = unsigned;
@@ -159,14 +151,176 @@ def fir_FieldType : FIR_Type<"Field", "field"> {
derived type until runtime. This implies that the runtime must be able to
determine the offset of fields within the entity.
}];
+}
+
+def fir_HeapType : FIR_Type<"Heap", "heap"> {
+ let summary = "Reference to an ALLOCATABLE attribute type";
+
+ let description = [{
+ The type of a heap pointer. Fortran entities with the ALLOCATABLE attribute
+ may be allocated on the heap at runtime. These pointers are explicitly
+ distinguished to disallow the composition of multiple levels of
+ indirection. For example, an ALLOCATABLE POINTER is invalid.
+ }];
+
+ let parameters = (ins "mlir::Type":$eleTy);
+
+ let genVerifyDecl = 1;
+
+ let skipDefaultBuilders = 1;
+
+ let builders = [
+ TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
+ assert(singleIndirectionLevel(elementType) && "invalid element type");
+ return Base::get(elementType.getContext(), elementType);
+ }]>,
+ ];
+}
+
+def fir_IntegerType : FIR_Type<"Integer", "int"> {
+ let summary = "FIR integer type";
+
+ let description = [{
+ Model of a Fortran INTEGER intrinsic type, including the KIND type
+ parameter.
+ }];
+
+ let parameters = (ins "KindTy":$fKind);
+
+ let extraClassDeclaration = [{
+ using KindTy = unsigned;
+ }];
+}
+
+def fir_LenType : FIR_Type<"Len", "len"> {
+ let summary = "A LEN parameter (in a RecordType) argument's type";
+
+ let description = [{
+ The type of a LEN parameter name. Implementations may defer the layout of a
+ Fortran derived type until runtime. This implies that the runtime must be
+ able to determine the offset of LEN type parameters related to an entity.
+ }];
+}
+
+def fir_LogicalType : FIR_Type<"Logical", "logical"> {
+ let summary = "FIR logical type";
+
+ let description = [{
+ Model of a Fortran LOGICAL intrinsic type, including the KIND type
+ parameter.
+ }];
+
+ let parameters = (ins "KindTy":$fKind);
+
+ let extraClassDeclaration = [{
+ using KindTy = unsigned;
+ }];
+}
+
+def fir_PointerType : FIR_Type<"Pointer", "ptr"> {
+ let summary = "Reference to a POINTER attribute type";
+
+ let description = [{
+ The type of entities with the POINTER attribute. These pointers are
+ explicitly distinguished to disallow the composition of multiple levels of
+ indirection. For example, an ALLOCATABLE POINTER is invalid.
+ }];
+
+ let parameters = (ins "mlir::Type":$eleTy);
+
+ let genVerifyDecl = 1;
+
+ let skipDefaultBuilders = 1;
+
+ let builders = [
+ TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
+ assert(singleIndirectionLevel(elementType) && "invalid element type");
+ return Base::get(elementType.getContext(), elementType);
+ }]>,
+ ];
+
+ let extraClassDeclaration = [{
+ mlir::Type getElementType() const { return getEleTy(); }
+ }];
+}
+
+def fir_RealType : FIR_Type<"Real", "real"> {
+ let summary = "FIR real type";
+
+ let description = [{
+ Model of a Fortran REAL (and DOUBLE PRECISION) intrinsic type, including the
+ KIND type parameter.
+ }];
+
+ let parameters = (ins "KindTy":$fKind);
+
+ let extraClassDeclaration = [{
+ using KindTy = unsigned;
+ }];
+
+ let genVerifyDecl = 1;
+}
+
+def fir_RecordType : FIR_Type<"Record", "type"> {
+ let summary = "FIR derived type";
+
+ let description = [{
+ Model of Fortran's derived type, TYPE. The name of the TYPE includes any
+ KIND type parameters. The record includes runtime slots for LEN type
+ parameters and for data components.
+ }];
+
+ let parameters = (ins StringRefParameter<"name">:$name);
+
+ let genVerifyDecl = 1;
+ let genStorageClass = 0;
- let printer = [{
- $_printer << "field";
+ let extraClassDeclaration = [{
+ using TypePair = std::pair<std::string, mlir::Type>;
+ using TypeList = std::vector<TypePair>;
+ TypeList getTypeList() const;
+ TypeList getLenParamList() const;
+
+ mlir::Type getType(llvm::StringRef ident);
+ // Returns the index of the field \p ident in the type list.
+ // Returns maximum unsigned if ident is not a field of this RecordType.
+ unsigned getFieldIndex(llvm::StringRef ident);
+ mlir::Type getType(unsigned index) {
+ assert(index < getNumFields());
+ return getTypeList()[index].second;
+ }
+ unsigned getNumFields() { return getTypeList().size(); }
+ unsigned getNumLenParams() { return getLenParamList().size(); }
+
+ void finalize(llvm::ArrayRef<TypePair> lenPList,
+ llvm::ArrayRef<TypePair> typeList);
+
+ detail::RecordTypeStorage const *uniqueKey() const;
}];
+}
- let parser = [{
- return get(context);
+def fir_ReferenceType : FIR_Type<"Reference", "ref"> {
+ let summary = "Reference to an entity type";
+
+ let description = [{
+ The type of a reference to an entity in memory.
}];
+
+ let parameters = (ins "mlir::Type":$eleTy);
+
+ let skipDefaultBuilders = 1;
+
+ let builders = [
+ TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
+ return Base::get(elementType.getContext(), elementType);
+ }]>,
+ ];
+
+ let extraClassDeclaration = [{
+ mlir::Type getElementType() const { return getEleTy(); }
+ }];
+
+ let genVerifyDecl = 1;
}
def fir_ShapeType : FIR_Type<"Shape", "shape"> {
@@ -179,18 +333,6 @@ def fir_ShapeType : FIR_Type<"Shape", "shape"> {
}];
let parameters = (ins "unsigned":$rank);
-
- let printer = [{
- $_printer << "shape<" << getImpl()->rank << ">";
- }];
-
- let parser = [{
- int rank;
- if ($_parser.parseLess() || $_parser.parseInteger(rank) ||
- $_parser.parseGreater())
- return Type();
- return get(context, rank);
- }];
}
def fir_ShapeShiftType : FIR_Type<"ShapeShift", "shapeshift"> {
@@ -204,18 +346,6 @@ def fir_ShapeShiftType : FIR_Type<"ShapeShift", "shapeshift"> {
}];
let parameters = (ins "unsigned":$rank);
-
- let printer = [{
- $_printer << "shapeshift<" << getImpl()->rank << ">";
- }];
-
- let parser = [{
- int rank;
- if ($_parser.parseLess() || $_parser.parseInteger(rank) ||
- $_parser.parseGreater())
- return Type();
- return get(context, rank);
- }];
}
def fir_ShiftType : FIR_Type<"Shift", "shift"> {
@@ -229,17 +359,189 @@ def fir_ShiftType : FIR_Type<"Shift", "shift"> {
let parameters = (ins "unsigned":$rank);
- let printer = [{
- $_printer << "shift<" << getImpl()->rank << ">";
+ let extraClassDeclaration = [{
+ using KindTy = unsigned;
+
+ // a !fir.boxchar<k> always wraps a !fir.char<k, ?>
+ CharacterType getElementType(mlir::MLIRContext *context) const;
+
+ CharacterType getEleTy() const;
+ }];
+}
+
+def fir_SequenceType : FIR_Type<"Sequence", "array"> {
+ let summary = "FIR array type";
+
+ let description = [{
+ A sequence type is a multi-dimensional array of values. The sequence type
+ may have an unknown number of dimensions or the extent of dimensions may be
+ unknown. A sequence type models a Fortran array entity, giving it a type in
+ FIR. A sequence type is assumed to be stored in a column-major order, which
+
diff ers from LLVM IR and other dialects of MLIR.
+ }];
+
+ let parameters = (ins
+ ArrayRefParameter<"int64_t", "Sequence shape">:$shape,
+ "mlir::Type":$eleTy,
+ "mlir::AffineMapAttr":$layoutMap
+ );
+
+ let genVerifyDecl = 1;
+
+ let builders = [
+ TypeBuilderWithInferredContext<(ins
+ "llvm::ArrayRef<int64_t>":$shape,
+ "mlir::Type":$eleTy), [{
+ return get(eleTy.getContext(), shape, eleTy, {});
+ }]>,
+ ];
+
+ let extraClassDeclaration = [{
+ using Extent = int64_t;
+ using Shape = llvm::SmallVector<Extent, 8>;
+ using ShapeRef = llvm::ArrayRef<int64_t>;
+ unsigned getConstantRows() const;
+
+ // The number of dimensions of the sequence
+ unsigned getDimension() const { return getShape().size(); }
+
+ // Is the interior of the sequence constant? Check if the array is
+ // one of constant shape (`array<C...xCxT>`), unknown shape
+ // (`array<*xT>`), or rows with shape and ending with column(s) of
+ // unknown extent (`array<C...xCx?...x?xT>`).
+ bool hasConstantInterior() const;
+
+ // Is the shape of the sequence constant?
+ bool hasConstantShape() const { return getConstantRows() == getDimension(); }
+
+ // Does the sequence have unknown shape? (`array<* x T>`)
+ bool hasUnknownShape() const { return getShape().empty(); }
+
+ // The value `-1` represents an unknown extent for a dimension
+ static constexpr Extent getUnknownExtent() { return -1; }
+ }];
+}
+
+def fir_SliceType : FIR_Type<"Slice", "slice"> {
+ let summary = "FIR slice";
+
+ let description = [{
+ Type of a vector that represents an array slice operation on an array.
+ Fortran slices are triples of lower bound, upper bound, and stride. The rank
+ of a SliceType must be at least 1.
+ }];
+
+ let parameters = (ins "unsigned":$rank);
+}
+
+def fir_TypeDescType : FIR_Type<"TypeDesc", "tdesc"> {
+ let summary = "FIR Type descriptor type";
+
+ let description = [{
+ The type of a type descriptor object. The runtime may generate type
+ descriptor objects to determine the type of an entity at runtime, etc.
}];
- let parser = [{
- int rank;
- if ($_parser.parseLess() || $_parser.parseInteger(rank) ||
- $_parser.parseGreater())
- return Type();
- return get(context, rank);
+ let parameters = (ins "mlir::Type":$ofTy);
+
+ let genVerifyDecl = 1;
+
+ let skipDefaultBuilders = 1;
+
+ let builders = [
+ TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
+ return Base::get(elementType.getContext(), elementType);
+ }]>,
+ ];
+}
+
+def fir_VectorType : FIR_Type<"Vector", "vector"> {
+ let summary = "FIR vector type";
+
+ let description = [{
+ Replacement for the builtin vector type.
+ The FIR vector type is always rank one. It's size is always a constant.
+ A vector's element type must be real or integer.
}];
+
+ let parameters = (ins "uint64_t":$len, "mlir::Type":$eleTy);
+
+ let genVerifyDecl = 1;
+
+ let extraClassDeclaration = [{
+ static bool isValidElementType(mlir::Type t);
+ }];
+
+ let skipDefaultBuilders = 1;
+
+ let builders = [
+ TypeBuilderWithInferredContext<(ins
+ "uint64_t":$len,
+ "mlir::Type":$eleTy), [{
+ return Base::get(eleTy.getContext(), len, eleTy);
+ }]>,
+ ];
}
+def fir_VoidType : FIR_Type<"Void", "void"> {
+ let genStorageClass = 0;
+}
+
+// Generalized FIR and standard dialect types representing intrinsic types
+def AnyIntegerLike : TypeConstraint<Or<[SignlessIntegerLike.predicate,
+ AnySignedInteger.predicate, fir_IntegerType.predicate]>, "any integer">;
+def AnyLogicalLike : TypeConstraint<Or<[BoolLike.predicate,
+ fir_LogicalType.predicate]>, "any logical">;
+def AnyRealLike : TypeConstraint<Or<[FloatLike.predicate,
+ fir_RealType.predicate]>, "any real">;
+def AnyIntegerType : Type<AnyIntegerLike.predicate, "any integer">;
+
+// Composable types
+def AnyCompositeLike : TypeConstraint<Or<[fir_RecordType.predicate,
+ fir_SequenceType.predicate, fir_ComplexType.predicate,
+ fir_VectorType.predicate, IsTupleTypePred, fir_CharacterType.predicate]>,
+ "any composite">;
+
+// Reference types
+def AnyReferenceLike : TypeConstraint<Or<[fir_ReferenceType.predicate,
+ fir_HeapType.predicate, fir_PointerType.predicate]>, "any reference">;
+
+def AnyBoxLike : TypeConstraint<Or<[fir_BoxType.predicate,
+ fir_BoxCharType.predicate, fir_BoxProcType.predicate]>, "any box">;
+
+def AnyRefOrBoxLike : TypeConstraint<Or<[AnyReferenceLike.predicate,
+ AnyBoxLike.predicate]>,
+ "any reference or box like">;
+def AnyRefOrBox : TypeConstraint<Or<[fir_ReferenceType.predicate,
+ fir_HeapType.predicate, fir_PointerType.predicate, fir_BoxType.predicate]>,
+ "any reference or box">;
+
+def AnyShapeLike : TypeConstraint<Or<[fir_ShapeType.predicate,
+ fir_ShapeShiftType.predicate]>, "any legal shape type">;
+def AnyShapeType : Type<AnyShapeLike.predicate, "any legal shape type">;
+def AnyShapeOrShiftLike : TypeConstraint<Or<[fir_ShapeType.predicate,
+ fir_ShapeShiftType.predicate, fir_ShiftType.predicate]>,
+ "any legal shape or shift type">;
+def AnyShapeOrShiftType : Type<AnyShapeOrShiftLike.predicate,
+ "any legal shape or shift type">;
+
+def AnyEmboxLike : TypeConstraint<Or<[AnySignlessInteger.predicate,
+ Index.predicate, fir_IntegerType.predicate]>,
+ "any legal embox argument type">;
+def AnyEmboxArg : Type<AnyEmboxLike.predicate, "embox argument type">;
+
+def AnyComponentLike : TypeConstraint<Or<[AnySignlessInteger.predicate,
+ Index.predicate, fir_IntegerType.predicate, fir_FieldType.predicate]>,
+ "any coordinate index">;
+def AnyComponentType : Type<AnyComponentLike.predicate, "coordinate type">;
+
+def AnyCoordinateLike : TypeConstraint<Or<[AnySignlessInteger.predicate,
+ Index.predicate, fir_IntegerType.predicate, fir_FieldType.predicate,
+ fir_LenType.predicate]>, "any coordinate index">;
+def AnyCoordinateType : Type<AnyCoordinateLike.predicate, "coordinate type">;
+
+// The legal types of global symbols
+def AnyAddressableLike : TypeConstraint<Or<[fir_ReferenceType.predicate,
+ FunctionType.predicate]>, "any addressable">;
+
#endif // FIR_DIALECT_FIR_TYPES
diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index ecfc597d820a..4cbdf15f38d6 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -49,7 +49,7 @@ TYPE parseRankSingleton(mlir::DialectAsmParser &parser) {
}
template <typename TYPE>
-TYPE parseTypeSingleton(mlir::DialectAsmParser &parser, mlir::Location) {
+TYPE parseTypeSingleton(mlir::DialectAsmParser &parser) {
mlir::Type ty;
if (parser.parseLess() || parser.parseType(ty) || parser.parseGreater()) {
parser.emitError(parser.getCurrentLocation(), "type expected");
@@ -58,101 +58,6 @@ TYPE parseTypeSingleton(mlir::DialectAsmParser &parser, mlir::Location) {
return TYPE::get(ty);
}
-// `slice` `<` rank `>`
-SliceType parseSlice(mlir::DialectAsmParser &parser) {
- return parseRankSingleton<SliceType>(parser);
-}
-
-// `heap` `<` type `>`
-HeapType parseHeap(mlir::DialectAsmParser &parser, mlir::Location loc) {
- return parseTypeSingleton<HeapType>(parser, loc);
-}
-
-// `int` `<` kind `>`
-fir::IntegerType parseInteger(mlir::DialectAsmParser &parser) {
- return parseKindSingleton<fir::IntegerType>(parser);
-}
-
-// `len`
-LenType parseLen(mlir::DialectAsmParser &parser) {
- return LenType::get(parser.getBuilder().getContext());
-}
-
-// `logical` `<` kind `>`
-LogicalType parseLogical(mlir::DialectAsmParser &parser) {
- return parseKindSingleton<LogicalType>(parser);
-}
-
-// `ptr` `<` type `>`
-PointerType parsePointer(mlir::DialectAsmParser &parser, mlir::Location loc) {
- return parseTypeSingleton<PointerType>(parser, loc);
-}
-
-// `real` `<` kind `>`
-RealType parseReal(mlir::DialectAsmParser &parser) {
- return parseKindSingleton<RealType>(parser);
-}
-
-// `ref` `<` type `>`
-ReferenceType parseReference(mlir::DialectAsmParser &parser,
- mlir::Location loc) {
- return parseTypeSingleton<ReferenceType>(parser, loc);
-}
-
-// `tdesc` `<` type `>`
-TypeDescType parseTypeDesc(mlir::DialectAsmParser &parser, mlir::Location loc) {
- return parseTypeSingleton<TypeDescType>(parser, loc);
-}
-
-// `vector` `<` len `:` type `>`
-fir::VectorType parseVector(mlir::DialectAsmParser &parser,
- mlir::Location loc) {
- int64_t len = 0;
- mlir::Type eleTy;
- if (parser.parseLess() || parser.parseInteger(len) || parser.parseColon() ||
- parser.parseType(eleTy) || parser.parseGreater()) {
- parser.emitError(parser.getNameLoc(), "invalid vector type");
- return {};
- }
- return fir::VectorType::get(len, eleTy);
-}
-
-// `void`
-mlir::Type parseVoid(mlir::DialectAsmParser &parser) {
- return parser.getBuilder().getNoneType();
-}
-
-// `array` `<` `*` | bounds (`x` bounds)* `:` type (',' affine-map)? `>`
-// bounds ::= `?` | int-lit
-SequenceType parseSequence(mlir::DialectAsmParser &parser, mlir::Location) {
- if (parser.parseLess()) {
- parser.emitError(parser.getNameLoc(), "expecting '<'");
- return {};
- }
- SequenceType::Shape shape;
- if (parser.parseOptionalStar()) {
- if (parser.parseDimensionList(shape, /*allowDynamic=*/true)) {
- parser.emitError(parser.getNameLoc(), "invalid shape");
- return {};
- }
- } else if (parser.parseColon()) {
- parser.emitError(parser.getNameLoc(), "expected ':'");
- return {};
- }
- mlir::Type eleTy;
- if (parser.parseType(eleTy) || parser.parseGreater()) {
- parser.emitError(parser.getNameLoc(), "expecting element type");
- return {};
- }
- mlir::AffineMapAttr map;
- if (!parser.parseOptionalComma())
- if (parser.parseAttribute(map)) {
- parser.emitError(parser.getNameLoc(), "expecting affine map");
- return {};
- }
- return SequenceType::get(shape, eleTy, map);
-}
-
/// Is `ty` a standard or FIR integer type?
static bool isaIntegerType(mlir::Type ty) {
// TODO: why aren't we using isa_integer? investigatation required.
@@ -206,79 +111,6 @@ RecordType verifyDerived(mlir::DialectAsmParser &parser, RecordType derivedTy,
return derivedTy;
}
-// Fortran derived type
-// `type` `<` name
-// (`(` id `:` type (`,` id `:` type)* `)`)?
-// (`{` id `:` type (`,` id `:` type)* `}`)? '>'
-RecordType parseDerived(mlir::DialectAsmParser &parser, mlir::Location) {
- llvm::StringRef name;
- if (parser.parseLess() || parser.parseKeyword(&name)) {
- parser.emitError(parser.getNameLoc(),
- "expected a identifier as name of derived type");
- return {};
- }
- RecordType result = RecordType::get(parser.getBuilder().getContext(), name);
-
- RecordType::TypeList lenParamList;
- if (!parser.parseOptionalLParen()) {
- while (true) {
- llvm::StringRef lenparam;
- mlir::Type intTy;
- if (parser.parseKeyword(&lenparam) || parser.parseColon() ||
- parser.parseType(intTy)) {
- parser.emitError(parser.getNameLoc(), "expected LEN parameter list");
- return {};
- }
- lenParamList.emplace_back(lenparam, intTy);
- if (parser.parseOptionalComma())
- break;
- }
- if (parser.parseRParen()) {
- parser.emitError(parser.getNameLoc(), "expected ')'");
- return {};
- }
- }
-
- RecordType::TypeList typeList;
- if (!parser.parseOptionalLBrace()) {
- while (true) {
- llvm::StringRef field;
- mlir::Type fldTy;
- if (parser.parseKeyword(&field) || parser.parseColon() ||
- parser.parseType(fldTy)) {
- parser.emitError(parser.getNameLoc(), "expected field type list");
- return {};
- }
- typeList.emplace_back(field, fldTy);
- if (parser.parseOptionalComma())
- break;
- }
- if (parser.parseRBrace()) {
- parser.emitError(parser.getNameLoc(), "expected '}'");
- return {};
- }
- }
-
- if (parser.parseGreater()) {
- parser.emitError(parser.getNameLoc(), "expected '>' in type type");
- return {};
- }
-
- if (lenParamList.empty() && typeList.empty())
- return result;
-
- result.finalize(lenParamList, typeList);
- return verifyDerived(parser, result, lenParamList, typeList);
-}
-
-#ifndef NDEBUG
-// !fir.ptr<X> and !fir.heap<X> where X is !fir.ptr, !fir.heap, or !fir.ref
-// is undefined and disallowed.
-inline bool singleIndirectionLevel(mlir::Type ty) {
- return !fir::isa_ref_type(ty);
-}
-#endif
-
} // namespace
// Implementation of the thin interface from dialect to type parser
@@ -287,57 +119,9 @@ mlir::Type fir::parseFirType(FIROpsDialect *dialect,
mlir::DialectAsmParser &parser) {
llvm::StringRef typeNameLit;
if (mlir::failed(parser.parseKeyword(&typeNameLit)))
- return {};
+ return mlir::Type();
- // TODO all TYPE::parse can be move to generatedTypeParser when all types
- // have been moved
-
- auto loc = parser.getEncodedSourceLoc(parser.getNameLoc());
- if (typeNameLit == "array")
- return parseSequence(parser, loc);
- if (typeNameLit == "box")
- return generatedTypeParser(dialect->getContext(), parser, typeNameLit);
- if (typeNameLit == "boxchar")
- return generatedTypeParser(dialect->getContext(), parser, typeNameLit);
- if (typeNameLit == "boxproc")
- return generatedTypeParser(dialect->getContext(), parser, typeNameLit);
- if (typeNameLit == "char")
- return generatedTypeParser(dialect->getContext(), parser, typeNameLit);
- if (typeNameLit == "complex")
- return generatedTypeParser(dialect->getContext(), parser, typeNameLit);
- if (typeNameLit == "field")
- return generatedTypeParser(dialect->getContext(), parser, typeNameLit);
- if (typeNameLit == "heap")
- return parseHeap(parser, loc);
- if (typeNameLit == "int")
- return parseInteger(parser);
- if (typeNameLit == "len")
- return parseLen(parser);
- if (typeNameLit == "logical")
- return parseLogical(parser);
- if (typeNameLit == "ptr")
- return parsePointer(parser, loc);
- if (typeNameLit == "real")
- return parseReal(parser);
- if (typeNameLit == "ref")
- return parseReference(parser, loc);
- if (typeNameLit == "shape")
- return generatedTypeParser(dialect->getContext(), parser, typeNameLit);
- if (typeNameLit == "shapeshift")
- return generatedTypeParser(dialect->getContext(), parser, typeNameLit);
- if (typeNameLit == "slice")
- return parseSlice(parser);
- if (typeNameLit == "tdesc")
- return parseTypeDesc(parser, loc);
- if (typeNameLit == "type")
- return parseDerived(parser, loc);
- if (typeNameLit == "void")
- return parseVoid(parser);
- if (typeNameLit == "vector")
- return parseVector(parser, loc);
-
- parser.emitError(parser.getNameLoc(), "unknown FIR type " + typeNameLit);
- return {};
+ return generatedTypeParser(dialect->getContext(), parser, typeNameLit);
}
namespace fir {
@@ -345,234 +129,6 @@ namespace detail {
// Type storage classes
-struct SliceTypeStorage : public mlir::TypeStorage {
- using KeyTy = unsigned;
-
- static unsigned hashKey(const KeyTy &key) { return llvm::hash_combine(key); }
-
- bool operator==(const KeyTy &key) const { return key == getRank(); }
-
- static SliceTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- unsigned rank) {
- auto *storage = allocator.allocate<SliceTypeStorage>();
- return new (storage) SliceTypeStorage{rank};
- }
-
- unsigned getRank() const { return rank; }
-
-protected:
- unsigned rank;
-
-private:
- SliceTypeStorage() = delete;
- explicit SliceTypeStorage(unsigned rank) : rank{rank} {}
-};
-
-/// The type of a derived type LEN parameter reference
-struct LenTypeStorage : public mlir::TypeStorage {
- using KeyTy = KindTy;
-
- static unsigned hashKey(const KeyTy &) { return llvm::hash_combine(0); }
-
- bool operator==(const KeyTy &) const { return true; }
-
- static LenTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- KindTy) {
- auto *storage = allocator.allocate<LenTypeStorage>();
- return new (storage) LenTypeStorage{0};
- }
-
-private:
- LenTypeStorage() = delete;
- explicit LenTypeStorage(KindTy) {}
-};
-
-/// `LOGICAL` storage
-struct LogicalTypeStorage : public mlir::TypeStorage {
- using KeyTy = KindTy;
-
- static unsigned hashKey(const KeyTy &key) { return llvm::hash_combine(key); }
-
- bool operator==(const KeyTy &key) const { return key == getFKind(); }
-
- static LogicalTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- KindTy kind) {
- auto *storage = allocator.allocate<LogicalTypeStorage>();
- return new (storage) LogicalTypeStorage{kind};
- }
-
- KindTy getFKind() const { return kind; }
-
-protected:
- KindTy kind;
-
-private:
- LogicalTypeStorage() = delete;
- explicit LogicalTypeStorage(KindTy kind) : kind{kind} {}
-};
-
-/// `INTEGER` storage
-struct IntegerTypeStorage : public mlir::TypeStorage {
- using KeyTy = KindTy;
-
- static unsigned hashKey(const KeyTy &key) { return llvm::hash_combine(key); }
-
- bool operator==(const KeyTy &key) const { return key == getFKind(); }
-
- static IntegerTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- KindTy kind) {
- auto *storage = allocator.allocate<IntegerTypeStorage>();
- return new (storage) IntegerTypeStorage{kind};
- }
-
- KindTy getFKind() const { return kind; }
-
-protected:
- KindTy kind;
-
-private:
- IntegerTypeStorage() = delete;
- explicit IntegerTypeStorage(KindTy kind) : kind{kind} {}
-};
-
-/// `REAL` storage (for reals of unsupported sizes)
-struct RealTypeStorage : public mlir::TypeStorage {
- using KeyTy = KindTy;
-
- static unsigned hashKey(const KeyTy &key) { return llvm::hash_combine(key); }
-
- bool operator==(const KeyTy &key) const { return key == getFKind(); }
-
- static RealTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- KindTy kind) {
- auto *storage = allocator.allocate<RealTypeStorage>();
- return new (storage) RealTypeStorage{kind};
- }
-
- KindTy getFKind() const { return kind; }
-
-protected:
- KindTy kind;
-
-private:
- RealTypeStorage() = delete;
- explicit RealTypeStorage(KindTy kind) : kind{kind} {}
-};
-
-/// Pointer-like object storage
-struct ReferenceTypeStorage : public mlir::TypeStorage {
- using KeyTy = mlir::Type;
-
- static unsigned hashKey(const KeyTy &key) { return llvm::hash_combine(key); }
-
- bool operator==(const KeyTy &key) const { return key == getElementType(); }
-
- static ReferenceTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- mlir::Type eleTy) {
- assert(eleTy && "element type is null");
- auto *storage = allocator.allocate<ReferenceTypeStorage>();
- return new (storage) ReferenceTypeStorage{eleTy};
- }
-
- mlir::Type getElementType() const { return eleTy; }
-
-protected:
- mlir::Type eleTy;
-
-private:
- ReferenceTypeStorage() = delete;
- explicit ReferenceTypeStorage(mlir::Type eleTy) : eleTy{eleTy} {}
-};
-
-/// Pointer object storage
-struct PointerTypeStorage : public mlir::TypeStorage {
- using KeyTy = mlir::Type;
-
- static unsigned hashKey(const KeyTy &key) { return llvm::hash_combine(key); }
-
- bool operator==(const KeyTy &key) const { return key == getElementType(); }
-
- static PointerTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- mlir::Type eleTy) {
- assert(eleTy && "element type is null");
- auto *storage = allocator.allocate<PointerTypeStorage>();
- return new (storage) PointerTypeStorage{eleTy};
- }
-
- mlir::Type getElementType() const { return eleTy; }
-
-protected:
- mlir::Type eleTy;
-
-private:
- PointerTypeStorage() = delete;
- explicit PointerTypeStorage(mlir::Type eleTy) : eleTy{eleTy} {}
-};
-
-/// Heap memory reference object storage
-struct HeapTypeStorage : public mlir::TypeStorage {
- using KeyTy = mlir::Type;
-
- static unsigned hashKey(const KeyTy &key) { return llvm::hash_combine(key); }
-
- bool operator==(const KeyTy &key) const { return key == getElementType(); }
-
- static HeapTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- mlir::Type eleTy) {
- assert(eleTy && "element type is null");
- auto *storage = allocator.allocate<HeapTypeStorage>();
- return new (storage) HeapTypeStorage{eleTy};
- }
-
- mlir::Type getElementType() const { return eleTy; }
-
-protected:
- mlir::Type eleTy;
-
-private:
- HeapTypeStorage() = delete;
- explicit HeapTypeStorage(mlir::Type eleTy) : eleTy{eleTy} {}
-};
-
-/// Sequence-like object storage
-struct SequenceTypeStorage : public mlir::TypeStorage {
- using KeyTy =
- std::tuple<SequenceType::Shape, mlir::Type, mlir::AffineMapAttr>;
-
- static unsigned hashKey(const KeyTy &key) {
- auto shapeHash = hash_value(std::get<SequenceType::Shape>(key));
- shapeHash = llvm::hash_combine(shapeHash, std::get<mlir::Type>(key));
- return llvm::hash_combine(shapeHash, std::get<mlir::AffineMapAttr>(key));
- }
-
- bool operator==(const KeyTy &key) const {
- return key == KeyTy{getShape(), getElementType(), getLayoutMap()};
- }
-
- static SequenceTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- const KeyTy &key) {
- auto *storage = allocator.allocate<SequenceTypeStorage>();
- return new (storage) SequenceTypeStorage{
- std::get<SequenceType::Shape>(key), std::get<mlir::Type>(key),
- std::get<mlir::AffineMapAttr>(key)};
- }
-
- SequenceType::Shape getShape() const { return shape; }
- mlir::Type getElementType() const { return eleTy; }
- mlir::AffineMapAttr getLayoutMap() const { return map; }
-
-protected:
- SequenceType::Shape shape;
- mlir::Type eleTy;
- mlir::AffineMapAttr map;
-
-private:
- SequenceTypeStorage() = delete;
- explicit SequenceTypeStorage(const SequenceType::Shape &shape,
- mlir::Type eleTy, mlir::AffineMapAttr map)
- : shape{shape}, eleTy{eleTy}, map{map} {}
-};
-
/// Derived type storage
struct RecordTypeStorage : public mlir::TypeStorage {
using KeyTy = llvm::StringRef;
@@ -620,78 +176,20 @@ struct RecordTypeStorage : public mlir::TypeStorage {
: name{name}, finalized{false} {}
};
-/// Type descriptor type storage
-struct TypeDescTypeStorage : public mlir::TypeStorage {
- using KeyTy = mlir::Type;
-
- static unsigned hashKey(const KeyTy &key) { return llvm::hash_combine(key); }
-
- bool operator==(const KeyTy &key) const { return key == getOfType(); }
+} // namespace detail
- static TypeDescTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- mlir::Type ofTy) {
- assert(ofTy && "descriptor type is null");
- auto *storage = allocator.allocate<TypeDescTypeStorage>();
- return new (storage) TypeDescTypeStorage{ofTy};
- }
+template <typename A, typename B>
+bool inbounds(A v, B lb, B ub) {
+ return v >= lb && v < ub;
+}
- // The type described by this type descriptor instance
- mlir::Type getOfType() const { return ofTy; }
+bool isa_fir_type(mlir::Type t) {
+ return llvm::isa<FIROpsDialect>(t.getDialect());
+}
-protected:
- mlir::Type ofTy;
-
-private:
- TypeDescTypeStorage() = delete;
- explicit TypeDescTypeStorage(mlir::Type ofTy) : ofTy{ofTy} {}
-};
-
-/// Vector type storage
-struct VectorTypeStorage : public mlir::TypeStorage {
- using KeyTy = std::tuple<uint64_t, mlir::Type>;
-
- static unsigned hashKey(const KeyTy &key) {
- return llvm::hash_combine(std::get<uint64_t>(key),
- std::get<mlir::Type>(key));
- }
-
- bool operator==(const KeyTy &key) const {
- return key == KeyTy{getLen(), getEleTy()};
- }
-
- static VectorTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
- const KeyTy &key) {
- auto *storage = allocator.allocate<VectorTypeStorage>();
- return new (storage)
- VectorTypeStorage{std::get<uint64_t>(key), std::get<mlir::Type>(key)};
- }
-
- uint64_t getLen() const { return len; }
- mlir::Type getEleTy() const { return eleTy; }
-
-protected:
- uint64_t len;
- mlir::Type eleTy;
-
-private:
- VectorTypeStorage() = delete;
- explicit VectorTypeStorage(uint64_t len, mlir::Type eleTy)
- : len{len}, eleTy{eleTy} {}
-};
-
-} // namespace detail
-
-template <typename A, typename B> bool inbounds(A v, B lb, B ub) {
- return v >= lb && v < ub;
-}
-
-bool isa_fir_type(mlir::Type t) {
- return llvm::isa<FIROpsDialect>(t.getDialect());
-}
-
-bool isa_std_type(mlir::Type t) {
- return t.getDialect().getNamespace().empty();
-}
+bool isa_std_type(mlir::Type t) {
+ return t.getDialect().getNamespace().empty();
+}
bool isa_fir_or_std_type(mlir::Type t) {
if (auto funcType = t.dyn_cast<mlir::FunctionType>())
@@ -727,101 +225,212 @@ mlir::Type dyn_cast_ptrEleTy(mlir::Type t) {
} // namespace fir
-// Len
+namespace {
+
+static llvm::SmallPtrSet<detail::RecordTypeStorage const *, 4>
+ recordTypeVisited;
+
+} // namespace
+
+void fir::verifyIntegralType(mlir::Type type) {
+ if (isaIntegerType(type) || type.isa<mlir::IndexType>())
+ return;
+ llvm::report_fatal_error("expected integral type");
+}
+
+void fir::printFirType(FIROpsDialect *, mlir::Type ty,
+ mlir::DialectAsmPrinter &p) {
+ if (mlir::failed(generatedTypePrinter(ty, p)))
+ llvm::report_fatal_error("unknown type to print");
+}
-LenType fir::LenType::get(mlir::MLIRContext *ctxt) {
- return Base::get(ctxt, 0);
+bool fir::isa_unknown_size_box(mlir::Type t) {
+ if (auto boxTy = t.dyn_cast<fir::BoxType>()) {
+ auto eleTy = boxTy.getEleTy();
+ if (auto actualEleTy = fir::dyn_cast_ptrEleTy(eleTy))
+ eleTy = actualEleTy;
+ if (eleTy.isa<mlir::NoneType>())
+ return true;
+ if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
+ if (seqTy.hasUnknownShape())
+ return true;
+ }
+ return false;
}
-// LOGICAL
+//===----------------------------------------------------------------------===//
+// BoxProcType
+//===----------------------------------------------------------------------===//
-LogicalType fir::LogicalType::get(mlir::MLIRContext *ctxt, KindTy kind) {
- return Base::get(ctxt, kind);
+// `boxproc` `<` return-type `>`
+mlir::Type BoxProcType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ mlir::Type ty;
+ if (parser.parseLess() || parser.parseType(ty) || parser.parseGreater()) {
+ parser.emitError(parser.getCurrentLocation(), "type expected");
+ return {};
+ }
+ return get(context, ty);
}
-KindTy fir::LogicalType::getFKind() const { return getImpl()->getFKind(); }
+void fir::BoxProcType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getEleTy() << '>';
+}
-// INTEGER
+mlir::LogicalResult
+BoxProcType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
+ mlir::Type eleTy) {
+ if (eleTy.isa<mlir::FunctionType>())
+ return mlir::success();
+ if (auto refTy = eleTy.dyn_cast<ReferenceType>())
+ if (refTy.isa<mlir::FunctionType>())
+ return mlir::success();
+ return emitError() << "invalid type for boxproc" << eleTy << '\n';
+}
-fir::IntegerType fir::IntegerType::get(mlir::MLIRContext *ctxt, KindTy kind) {
- return Base::get(ctxt, kind);
+static bool canBePointerOrHeapElementType(mlir::Type eleTy) {
+ return eleTy.isa<BoxType, BoxCharType, BoxProcType, ShapeType, ShapeShiftType,
+ SliceType, FieldType, LenType, HeapType, PointerType,
+ ReferenceType, TypeDescType>();
}
-KindTy fir::IntegerType::getFKind() const { return getImpl()->getFKind(); }
+//===----------------------------------------------------------------------===//
+// BoxType
+//===----------------------------------------------------------------------===//
-// REAL
+// `box` `<` type (',' affine-map)? `>`
+mlir::Type fir::BoxType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ mlir::Type ofTy;
+ if (parser.parseLess() || parser.parseType(ofTy)) {
+ parser.emitError(parser.getCurrentLocation(), "expected type parameter");
+ return {};
+ }
-RealType fir::RealType::get(mlir::MLIRContext *ctxt, KindTy kind) {
- return Base::get(ctxt, kind);
+ mlir::AffineMapAttr map;
+ if (!parser.parseOptionalComma()) {
+ if (parser.parseAttribute(map)) {
+ parser.emitError(parser.getCurrentLocation(), "expected affine map");
+ return {};
+ }
+ }
+ if (parser.parseGreater()) {
+ return {};
+ }
+ return get(ofTy, map);
}
-KindTy fir::RealType::getFKind() const { return getImpl()->getFKind(); }
+void fir::BoxType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getEleTy();
+ if (auto map = getLayoutMap()) {
+ printer << ", " << map;
+ }
+ printer << '>';
+}
mlir::LogicalResult
-fir::BoxType::verify(llvm::function_ref<mlir::InFlightDiagnostic()>,
+fir::BoxType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
mlir::Type eleTy, mlir::AffineMapAttr map) {
// TODO
return mlir::success();
}
-// Reference<T>
+//===----------------------------------------------------------------------===//
+// BoxCharType
+//===----------------------------------------------------------------------===//
-ReferenceType fir::ReferenceType::get(mlir::Type elementType) {
- return Base::get(elementType.getContext(), elementType);
+mlir::Type fir::BoxCharType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ int kind = 0;
+ if (parser.parseLess() || parser.parseInteger(kind) ||
+ parser.parseGreater()) {
+ parser.emitError(parser.getCurrentLocation(), "kind value expected");
+ return {};
+ }
+ return get(context, kind);
}
-mlir::Type fir::ReferenceType::getEleTy() const {
- return getImpl()->getElementType();
+void fir::BoxCharType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getKind() << ">";
}
-mlir::LogicalResult fir::ReferenceType::verify(
- llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- mlir::Type eleTy) {
- if (eleTy.isa<ShapeType>() || eleTy.isa<ShapeShiftType>() ||
- eleTy.isa<SliceType>() || eleTy.isa<FieldType>() ||
- eleTy.isa<LenType>() || eleTy.isa<ReferenceType>() ||
- eleTy.isa<TypeDescType>())
- return emitError() << "cannot build a reference to type: " << eleTy << '\n';
- return mlir::success();
+CharacterType
+fir::BoxCharType::getElementType(mlir::MLIRContext *context) const {
+ return CharacterType::getUnknownLen(context, getKind());
}
-// Pointer<T>
+CharacterType fir::BoxCharType::getEleTy() const {
+ return getElementType(getContext());
+}
+
+//===----------------------------------------------------------------------===//
+// CharacterType
+//===----------------------------------------------------------------------===//
+
+// `char` `<` kind [`,` `len`] `>`
+mlir::Type fir::CharacterType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ int kind = 0;
+ if (parser.parseLess() || parser.parseInteger(kind)) {
+ parser.emitError(parser.getCurrentLocation(), "kind value expected");
+ return {};
+ }
+ CharacterType::LenType len = 1;
+ if (mlir::succeeded(parser.parseOptionalComma())) {
+ if (mlir::succeeded(parser.parseOptionalQuestion())) {
+ len = fir::CharacterType::unknownLen();
+ } else if (!mlir::succeeded(parser.parseInteger(len))) {
+ parser.emitError(parser.getCurrentLocation(), "len value expected");
+ return {};
+ }
+ }
+ if (parser.parseGreater())
+ return {};
+ return get(context, kind, len);
+}
-PointerType fir::PointerType::get(mlir::Type elementType) {
- assert(singleIndirectionLevel(elementType) && "invalid element type");
- return Base::get(elementType.getContext(), elementType);
+void fir::CharacterType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getFKind();
+ auto len = getLen();
+ if (len != fir::CharacterType::singleton()) {
+ printer << ',';
+ if (len == fir::CharacterType::unknownLen())
+ printer << '?';
+ else
+ printer << len;
+ }
+ printer << '>';
}
-mlir::Type fir::PointerType::getEleTy() const {
- return getImpl()->getElementType();
+//===----------------------------------------------------------------------===//
+// ComplexType
+//===----------------------------------------------------------------------===//
+
+mlir::Type fir::ComplexType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseKindSingleton<fir::ComplexType>(parser);
}
-static bool canBePointerOrHeapElementType(mlir::Type eleTy) {
- return eleTy.isa<BoxType>() || eleTy.isa<BoxCharType>() ||
- eleTy.isa<BoxProcType>() || eleTy.isa<ShapeType>() ||
- eleTy.isa<ShapeShiftType>() || eleTy.isa<SliceType>() ||
- eleTy.isa<FieldType>() || eleTy.isa<LenType>() ||
- eleTy.isa<HeapType>() || eleTy.isa<PointerType>() ||
- eleTy.isa<ReferenceType>() || eleTy.isa<TypeDescType>();
+void fir::ComplexType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getFKind() << '>';
}
-mlir::LogicalResult fir::PointerType::verify(
- llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- mlir::Type eleTy) {
- if (canBePointerOrHeapElementType(eleTy))
- return emitError() << "cannot build a pointer to type: " << eleTy << '\n';
- return mlir::success();
+mlir::Type fir::ComplexType::getElementType() const {
+ return fir::RealType::get(getContext(), getFKind());
}
-// Heap<T>
+//===----------------------------------------------------------------------===//
+// HeapType
+//===----------------------------------------------------------------------===//
-HeapType fir::HeapType::get(mlir::Type elementType) {
- assert(singleIndirectionLevel(elementType) && "invalid element type");
- return Base::get(elementType.getContext(), elementType);
+// `heap` `<` type `>`
+mlir::Type fir::HeapType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseTypeSingleton<HeapType>(parser);
}
-mlir::Type fir::HeapType::getEleTy() const {
- return getImpl()->getElementType();
+void fir::HeapType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getEleTy() << '>';
}
mlir::LogicalResult
@@ -833,121 +442,190 @@ fir::HeapType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
return mlir::success();
}
-// Sequence<T>
+//===----------------------------------------------------------------------===//
+// IntegerType
+//===----------------------------------------------------------------------===//
-SequenceType fir::SequenceType::get(const Shape &shape, mlir::Type elementType,
- mlir::AffineMapAttr map) {
- auto *ctxt = elementType.getContext();
- return Base::get(ctxt, shape, elementType, map);
+// `int` `<` kind `>`
+mlir::Type fir::IntegerType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseKindSingleton<fir::IntegerType>(parser);
}
-mlir::Type fir::SequenceType::getEleTy() const {
- return getImpl()->getElementType();
+void fir::IntegerType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getFKind() << '>';
}
-mlir::AffineMapAttr fir::SequenceType::getLayoutMap() const {
- return getImpl()->getLayoutMap();
-}
+//===----------------------------------------------------------------------===//
+// LogicalType
+//===----------------------------------------------------------------------===//
-SequenceType::Shape fir::SequenceType::getShape() const {
- return getImpl()->getShape();
+// `logical` `<` kind `>`
+mlir::Type fir::LogicalType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseKindSingleton<fir::LogicalType>(parser);
}
-unsigned fir::SequenceType::getConstantRows() const {
- auto shape = getShape();
- unsigned count = 0;
- for (auto d : shape) {
- if (d < 0)
- break;
- ++count;
- }
- return count;
+void fir::LogicalType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getFKind() << '>';
}
-// This test helps us determine if we can degenerate an array to a
-// pointer to some interior section (possibly a single element) of the
-// sequence. This is used to determine if we can lower to the LLVM IR.
-bool fir::SequenceType::hasConstantInterior() const {
- if (hasUnknownShape())
- return true;
- auto rows = getConstantRows();
- auto dim = getDimension();
- if (rows == dim)
- return true;
- auto shape = getShape();
- for (unsigned i{rows}, size{dim}; i < size; ++i)
- if (shape[i] != getUnknownExtent())
- return false;
- return true;
-}
+//===----------------------------------------------------------------------===//
+// PointerType
+//===----------------------------------------------------------------------===//
-mlir::LogicalResult fir::SequenceType::verify(
- llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- const SequenceType::Shape &shape, mlir::Type eleTy,
- mlir::AffineMapAttr map) {
- // DIMENSION attribute can only be applied to an intrinsic or record type
- if (eleTy.isa<BoxType>() || eleTy.isa<BoxCharType>() ||
- eleTy.isa<BoxProcType>() || eleTy.isa<ShapeType>() ||
- eleTy.isa<ShapeShiftType>() || eleTy.isa<SliceType>() ||
- eleTy.isa<FieldType>() || eleTy.isa<LenType>() || eleTy.isa<HeapType>() ||
- eleTy.isa<PointerType>() || eleTy.isa<ReferenceType>() ||
- eleTy.isa<TypeDescType>() || eleTy.isa<fir::VectorType>() ||
- eleTy.isa<SequenceType>())
- return emitError() << "cannot build an array of this element type: "
- << eleTy << '\n';
- return mlir::success();
+// `ptr` `<` type `>`
+mlir::Type fir::PointerType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseTypeSingleton<fir::PointerType>(parser);
}
-// compare if two shapes are equivalent
-bool fir::operator==(const SequenceType::Shape &sh_1,
- const SequenceType::Shape &sh_2) {
- if (sh_1.size() != sh_2.size())
- return false;
- auto e = sh_1.size();
- for (decltype(e) i = 0; i != e; ++i)
- if (sh_1[i] != sh_2[i])
- return false;
- return true;
+void fir::PointerType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getEleTy() << '>';
}
-// compute the hash of a Shape
-llvm::hash_code fir::hash_value(const SequenceType::Shape &sh) {
- if (sh.size()) {
- return llvm::hash_combine_range(sh.begin(), sh.end());
- }
- return llvm::hash_combine(0);
+mlir::LogicalResult fir::PointerType::verify(
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
+ mlir::Type eleTy) {
+ if (canBePointerOrHeapElementType(eleTy))
+ return emitError() << "cannot build a pointer to type: " << eleTy << '\n';
+ return mlir::success();
}
-// Slice
+//===----------------------------------------------------------------------===//
+// RealType
+//===----------------------------------------------------------------------===//
-SliceType fir::SliceType::get(mlir::MLIRContext *ctxt, unsigned rank) {
- return Base::get(ctxt, rank);
+// `real` `<` kind `>`
+mlir::Type fir::RealType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseKindSingleton<fir::RealType>(parser);
}
-unsigned fir::SliceType::getRank() const { return getImpl()->getRank(); }
-
-/// RecordType
-///
-/// This type captures a Fortran "derived type"
-
-RecordType fir::RecordType::get(mlir::MLIRContext *ctxt, llvm::StringRef name) {
- return Base::get(ctxt, name);
+void fir::RealType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getFKind() << '>';
}
-void fir::RecordType::finalize(llvm::ArrayRef<TypePair> lenPList,
- llvm::ArrayRef<TypePair> typeList) {
- getImpl()->finalize(lenPList, typeList);
+mlir::LogicalResult
+fir::RealType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
+ KindTy fKind) {
+ // TODO
+ return mlir::success();
}
-llvm::StringRef fir::RecordType::getName() { return getImpl()->getName(); }
-
-RecordType::TypeList fir::RecordType::getTypeList() {
- return getImpl()->getTypeList();
-}
+//===----------------------------------------------------------------------===//
+// RecordType
+//===----------------------------------------------------------------------===//
-RecordType::TypeList fir::RecordType::getLenParamList() {
- return getImpl()->getLenParamList();
-}
+// Fortran derived type
+// `type` `<` name
+// (`(` id `:` type (`,` id `:` type)* `)`)?
+// (`{` id `:` type (`,` id `:` type)* `}`)? '>'
+mlir::Type fir::RecordType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ llvm::StringRef name;
+ if (parser.parseLess() || parser.parseKeyword(&name)) {
+ parser.emitError(parser.getNameLoc(),
+ "expected a identifier as name of derived type");
+ return {};
+ }
+ RecordType result = RecordType::get(parser.getBuilder().getContext(), name);
+
+ RecordType::TypeList lenParamList;
+ if (!parser.parseOptionalLParen()) {
+ while (true) {
+ llvm::StringRef lenparam;
+ mlir::Type intTy;
+ if (parser.parseKeyword(&lenparam) || parser.parseColon() ||
+ parser.parseType(intTy)) {
+ parser.emitError(parser.getNameLoc(), "expected LEN parameter list");
+ return {};
+ }
+ lenParamList.emplace_back(lenparam, intTy);
+ if (parser.parseOptionalComma())
+ break;
+ }
+ if (parser.parseRParen()) {
+ parser.emitError(parser.getNameLoc(), "expected ')'");
+ return {};
+ }
+ }
+
+ RecordType::TypeList typeList;
+ if (!parser.parseOptionalLBrace()) {
+ while (true) {
+ llvm::StringRef field;
+ mlir::Type fldTy;
+ if (parser.parseKeyword(&field) || parser.parseColon() ||
+ parser.parseType(fldTy)) {
+ parser.emitError(parser.getNameLoc(), "expected field type list");
+ return {};
+ }
+ typeList.emplace_back(field, fldTy);
+ if (parser.parseOptionalComma())
+ break;
+ }
+ if (parser.parseRBrace()) {
+ parser.emitError(parser.getNameLoc(), "expected '}'");
+ return {};
+ }
+ }
+
+ if (parser.parseGreater()) {
+ parser.emitError(parser.getNameLoc(), "expected '>' in type type");
+ return {};
+ }
+
+ if (lenParamList.empty() && typeList.empty())
+ return result;
+
+ result.finalize(lenParamList, typeList);
+ return verifyDerived(parser, result, lenParamList, typeList);
+}
+
+void fir::RecordType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getName();
+ if (!recordTypeVisited.count(uniqueKey())) {
+ recordTypeVisited.insert(uniqueKey());
+ if (getLenParamList().size()) {
+ char ch = '(';
+ for (auto p : getLenParamList()) {
+ printer << ch << p.first << ':';
+ p.second.print(printer.getStream());
+ ch = ',';
+ }
+ printer << ')';
+ }
+ if (getTypeList().size()) {
+ char ch = '{';
+ for (auto p : getTypeList()) {
+ printer << ch << p.first << ':';
+ p.second.print(printer.getStream());
+ ch = ',';
+ }
+ printer << '}';
+ }
+ recordTypeVisited.erase(uniqueKey());
+ }
+ printer << '>';
+}
+
+void fir::RecordType::finalize(llvm::ArrayRef<TypePair> lenPList,
+ llvm::ArrayRef<TypePair> typeList) {
+ getImpl()->finalize(lenPList, typeList);
+}
+
+llvm::StringRef fir::RecordType::getName() const {
+ return getImpl()->getName();
+}
+
+RecordType::TypeList fir::RecordType::getTypeList() const {
+ return getImpl()->getTypeList();
+}
+
+RecordType::TypeList fir::RecordType::getLenParamList() const {
+ return getImpl()->getLenParamList();
+}
detail::RecordTypeStorage const *fir::RecordType::uniqueKey() const {
return getImpl();
@@ -968,327 +646,242 @@ mlir::Type fir::RecordType::getType(llvm::StringRef ident) {
return {};
}
+unsigned fir::RecordType::getFieldIndex(llvm::StringRef ident) {
+ for (auto f : llvm::enumerate(getTypeList()))
+ if (ident == f.value().first)
+ return f.index();
+ return std::numeric_limits<unsigned>::max();
+}
+
//===----------------------------------------------------------------------===//
-// Type descriptor type
+// ReferenceType
//===----------------------------------------------------------------------===//
-TypeDescType fir::TypeDescType::get(mlir::Type ofType) {
- assert(!ofType.isa<ReferenceType>());
- return Base::get(ofType.getContext(), ofType);
+// `ref` `<` type `>`
+mlir::Type fir::ReferenceType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseTypeSingleton<fir::ReferenceType>(parser);
}
-mlir::Type fir::TypeDescType::getOfTy() const { return getImpl()->getOfType(); }
+void fir::ReferenceType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getEleTy() << '>';
+}
-mlir::LogicalResult fir::TypeDescType::verify(
+mlir::LogicalResult fir::ReferenceType::verify(
llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
mlir::Type eleTy) {
- if (eleTy.isa<BoxType>() || eleTy.isa<BoxCharType>() ||
- eleTy.isa<BoxProcType>() || eleTy.isa<ShapeType>() ||
- eleTy.isa<ShapeShiftType>() || eleTy.isa<SliceType>() ||
- eleTy.isa<FieldType>() || eleTy.isa<LenType>() ||
- eleTy.isa<ReferenceType>() || eleTy.isa<TypeDescType>())
- return emitError() << "cannot build a type descriptor of type: " << eleTy
- << '\n';
+ if (eleTy.isa<ShapeType, ShapeShiftType, SliceType, FieldType, LenType,
+ ReferenceType, TypeDescType>())
+ return emitError() << "cannot build a reference to type: " << eleTy << '\n';
return mlir::success();
}
//===----------------------------------------------------------------------===//
-// Vector type
+// SequenceType
//===----------------------------------------------------------------------===//
-fir::VectorType fir::VectorType::get(uint64_t len, mlir::Type eleTy) {
- return Base::get(eleTy.getContext(), len, eleTy);
+// `array` `<` `*` | bounds (`x` bounds)* `:` type (',' affine-map)? `>`
+// bounds ::= `?` | int-lit
+mlir::Type fir::SequenceType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ if (parser.parseLess()) {
+ parser.emitError(parser.getNameLoc(), "expecting '<'");
+ return {};
+ }
+ SequenceType::Shape shape;
+ if (parser.parseOptionalStar()) {
+ if (parser.parseDimensionList(shape, /*allowDynamic=*/true)) {
+ parser.emitError(parser.getNameLoc(), "invalid shape");
+ return {};
+ }
+ } else if (parser.parseColon()) {
+ parser.emitError(parser.getNameLoc(), "expected ':'");
+ return {};
+ }
+ mlir::Type eleTy;
+ if (parser.parseType(eleTy) || parser.parseGreater()) {
+ parser.emitError(parser.getNameLoc(), "expecting element type");
+ return {};
+ }
+ mlir::AffineMapAttr map;
+ if (!parser.parseOptionalComma())
+ if (parser.parseAttribute(map)) {
+ parser.emitError(parser.getNameLoc(), "expecting affine map");
+ return {};
+ }
+ return SequenceType::get(context, shape, eleTy, map);
}
-mlir::Type fir::VectorType::getEleTy() const { return getImpl()->getEleTy(); }
-
-uint64_t fir::VectorType::getLen() const { return getImpl()->getLen(); }
+void fir::SequenceType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic();
+ auto shape = getShape();
+ if (shape.size()) {
+ printer << '<';
+ for (const auto &b : shape) {
+ if (b >= 0)
+ printer << b << 'x';
+ else
+ printer << "?x";
+ }
+ } else {
+ printer << "<*:";
+ }
+ printer << getEleTy();
+ if (auto map = getLayoutMap()) {
+ printer << ", ";
+ map.print(printer.getStream());
+ }
+ printer << '>';
+}
-mlir::LogicalResult fir::VectorType::verify(
- llvm::function_ref<mlir::InFlightDiagnostic()> emitError, uint64_t len,
- mlir::Type eleTy) {
- if (!(fir::isa_real(eleTy) || fir::isa_integer(eleTy)))
- return emitError() << "cannot build a vector of type " << eleTy << '\n';
- return mlir::success();
+unsigned fir::SequenceType::getConstantRows() const {
+ auto shape = getShape();
+ unsigned count = 0;
+ for (auto d : shape) {
+ if (d < 0)
+ break;
+ ++count;
+ }
+ return count;
}
-namespace {
+// This test helps us determine if we can degenerate an array to a
+// pointer to some interior section (possibly a single element) of the
+// sequence. This is used to determine if we can lower to the LLVM IR.
+bool fir::SequenceType::hasConstantInterior() const {
+ if (hasUnknownShape())
+ return true;
+ auto rows = getConstantRows();
+ auto dim = getDimension();
+ if (rows == dim)
+ return true;
+ auto shape = getShape();
+ for (unsigned i = rows, size = dim; i < size; ++i)
+ if (shape[i] != getUnknownExtent())
+ return false;
+ return true;
+}
-void printBounds(llvm::raw_ostream &os, const SequenceType::Shape &bounds) {
- os << '<';
- for (auto &b : bounds) {
- if (b >= 0)
- os << b << 'x';
- else
- os << "?x";
- }
+mlir::LogicalResult fir::SequenceType::verify(
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
+ llvm::ArrayRef<int64_t> shape, mlir::Type eleTy,
+ mlir::AffineMapAttr layoutMap) {
+ // DIMENSION attribute can only be applied to an intrinsic or record type
+ if (eleTy.isa<BoxType, BoxCharType, BoxProcType, ShapeType, ShapeShiftType,
+ ShiftType, SliceType, FieldType, LenType, HeapType, PointerType,
+ ReferenceType, TypeDescType, fir::VectorType, SequenceType>())
+ return emitError() << "cannot build an array of this element type: "
+ << eleTy << '\n';
+ return mlir::success();
}
-llvm::SmallPtrSet<detail::RecordTypeStorage const *, 4> recordTypeVisited;
+//===----------------------------------------------------------------------===//
+// ShapeType
+//===----------------------------------------------------------------------===//
-} // namespace
+mlir::Type fir::ShapeType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseRankSingleton<fir::ShapeType>(parser);
+}
-void fir::verifyIntegralType(mlir::Type type) {
- if (isaIntegerType(type) || type.isa<mlir::IndexType>())
- return;
- llvm::report_fatal_error("expected integral type");
+void fir::ShapeType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getImpl()->rank << ">";
}
-void fir::printFirType(FIROpsDialect *, mlir::Type ty,
- mlir::DialectAsmPrinter &p) {
- auto &os = p.getStream();
- if (auto type = ty.dyn_cast<RecordType>()) {
- // Fortran derived type
- os << "type<" << type.getName();
- if (!recordTypeVisited.count(type.uniqueKey())) {
- recordTypeVisited.insert(type.uniqueKey());
- if (type.getLenParamList().size()) {
- char ch = '(';
- for (auto p : type.getLenParamList()) {
- os << ch << p.first << ':';
- p.second.print(os);
- ch = ',';
- }
- os << ')';
- }
- if (type.getTypeList().size()) {
- char ch = '{';
- for (auto p : type.getTypeList()) {
- os << ch << p.first << ':';
- p.second.print(os);
- ch = ',';
- }
- os << '}';
- }
- recordTypeVisited.erase(type.uniqueKey());
- }
- os << '>';
- return;
- }
- if (auto type = ty.dyn_cast<SliceType>()) {
- os << "slice<" << type.getRank() << '>';
- return;
- }
- if (auto type = ty.dyn_cast<HeapType>()) {
- os << "heap<";
- p.printType(type.getEleTy());
- os << '>';
- return;
- }
- if (auto type = ty.dyn_cast<fir::IntegerType>()) {
- // Fortran intrinsic type INTEGER
- os << "int<" << type.getFKind() << '>';
- return;
- }
- if (auto type = ty.dyn_cast<LenType>()) {
- os << "len";
- return;
- }
- if (auto type = ty.dyn_cast<LogicalType>()) {
- // Fortran intrinsic type LOGICAL
- os << "logical<" << type.getFKind() << '>';
- return;
- }
- if (auto type = ty.dyn_cast<PointerType>()) {
- os << "ptr<";
- p.printType(type.getEleTy());
- os << '>';
- return;
- }
- if (auto type = ty.dyn_cast<fir::RealType>()) {
- // Fortran intrinsic types REAL and DOUBLE PRECISION
- os << "real<" << type.getFKind() << '>';
- return;
- }
- if (auto type = ty.dyn_cast<ReferenceType>()) {
- os << "ref<";
- p.printType(type.getEleTy());
- os << '>';
- return;
- }
- if (auto type = ty.dyn_cast<SequenceType>()) {
- os << "array";
- auto shape = type.getShape();
- if (shape.size()) {
- printBounds(os, shape);
- } else {
- os << "<*:";
- }
- p.printType(ty.cast<SequenceType>().getEleTy());
- if (auto map = type.getLayoutMap()) {
- os << ", ";
- map.print(os);
- }
- os << '>';
- return;
- }
- if (auto type = ty.dyn_cast<TypeDescType>()) {
- os << "tdesc<";
- p.printType(type.getOfTy());
- os << '>';
- return;
- }
- if (auto type = ty.dyn_cast<fir::VectorType>()) {
- os << "vector<" << type.getLen() << ':';
- p.printType(type.getEleTy());
- os << '>';
- return;
- }
+//===----------------------------------------------------------------------===//
+// ShapeShiftType
+//===----------------------------------------------------------------------===//
- if (mlir::succeeded(generatedTypePrinter(ty, p))) {
- return;
- }
+mlir::Type fir::ShapeShiftType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseRankSingleton<fir::ShapeShiftType>(parser);
}
-bool fir::isa_unknown_size_box(mlir::Type t) {
- if (auto boxTy = t.dyn_cast<fir::BoxType>()) {
- auto eleTy = boxTy.getEleTy();
- if (auto actualEleTy = fir::dyn_cast_ptrEleTy(eleTy))
- eleTy = actualEleTy;
- if (eleTy.isa<mlir::NoneType>())
- return true;
- if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
- if (seqTy.hasUnknownShape())
- return true;
- }
- return false;
+void fir::ShapeShiftType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getRank() << ">";
}
//===----------------------------------------------------------------------===//
-// BoxProcType
+// ShiftType
//===----------------------------------------------------------------------===//
-// `boxproc` `<` return-type `>`
-mlir::Type BoxProcType::parse(mlir::MLIRContext *context,
- mlir::DialectAsmParser &parser) {
- mlir::Type ty;
- if (parser.parseLess() || parser.parseType(ty) || parser.parseGreater()) {
- parser.emitError(parser.getCurrentLocation(), "type expected");
- return Type();
- }
- return get(context, ty);
+mlir::Type fir::ShiftType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseRankSingleton<fir::ShiftType>(parser);
}
-mlir::LogicalResult
-BoxProcType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- mlir::Type eleTy) {
- if (eleTy.isa<mlir::FunctionType>())
- return mlir::success();
- if (auto refTy = eleTy.dyn_cast<ReferenceType>())
- if (refTy.isa<mlir::FunctionType>())
- return mlir::success();
- return emitError() << "invalid type for boxproc" << eleTy << '\n';
+void fir::ShiftType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getRank() << ">";
}
//===----------------------------------------------------------------------===//
-// BoxType
+// SliceType
//===----------------------------------------------------------------------===//
-// `box` `<` type (',' affine-map)? `>`
-mlir::Type fir::BoxType::parse(mlir::MLIRContext *context,
- mlir::DialectAsmParser &parser) {
- mlir::Type ofTy;
- if (parser.parseLess() || parser.parseType(ofTy)) {
- parser.emitError(parser.getCurrentLocation(), "expected type parameter");
- return Type();
- }
-
- mlir::AffineMapAttr map;
- if (!parser.parseOptionalComma()) {
- if (parser.parseAttribute(map)) {
- parser.emitError(parser.getCurrentLocation(), "expected affine map");
- return Type();
- }
- }
- if (parser.parseGreater()) {
- parser.emitError(parser.getCurrentLocation(), "expected '>'");
- return Type();
- }
- return get(ofTy, map);
+// `slice` `<` rank `>`
+mlir::Type fir::SliceType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseRankSingleton<fir::SliceType>(parser);
}
-void fir::BoxType::print(::mlir::DialectAsmPrinter &printer) const {
- printer << "box<";
- printer.printType(getEleTy());
- if (auto map = getLayoutMap()) {
- printer << ", ";
- printer.printAttribute(map);
- }
- printer << '>';
+void fir::SliceType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getRank() << '>';
}
//===----------------------------------------------------------------------===//
-// BoxCharType
+// TypeDescType
//===----------------------------------------------------------------------===//
-mlir::Type fir::BoxCharType::parse(mlir::MLIRContext *context,
- mlir::DialectAsmParser &parser) {
- int kind = 0;
- if (parser.parseLess() || parser.parseInteger(kind) ||
- parser.parseGreater()) {
- parser.emitError(parser.getCurrentLocation(), "kind value expected");
- return Type();
- }
- return get(context, kind);
+// `tdesc` `<` type `>`
+mlir::Type fir::TypeDescType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ return parseTypeSingleton<fir::TypeDescType>(parser);
}
-CharacterType
-fir::BoxCharType::getElementType(mlir::MLIRContext *context) const {
- return CharacterType::getUnknownLen(context, getKind());
+void fir::TypeDescType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getOfTy() << '>';
}
-CharacterType fir::BoxCharType::getEleTy() const {
- return getElementType(getContext());
+mlir::LogicalResult fir::TypeDescType::verify(
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
+ mlir::Type eleTy) {
+ if (eleTy.isa<BoxType, BoxCharType, BoxProcType, ShapeType, ShapeShiftType,
+ ShiftType, SliceType, FieldType, LenType, ReferenceType,
+ TypeDescType>())
+ return emitError() << "cannot build a type descriptor of type: " << eleTy
+ << '\n';
+ return mlir::success();
}
//===----------------------------------------------------------------------===//
-// CharacterType
+// VectorType
//===----------------------------------------------------------------------===//
-// `char` `<` kind [`,` `len`] `>`
-mlir::Type fir::CharacterType::parse(mlir::MLIRContext *context,
- mlir::DialectAsmParser &parser) {
- int kind = 0;
- if (parser.parseLess() || parser.parseInteger(kind)) {
- parser.emitError(parser.getCurrentLocation(), "kind value expected");
- return Type();
- }
- CharacterType::LenType len = 1;
- if (mlir::succeeded(parser.parseOptionalComma())) {
- if (mlir::succeeded(parser.parseOptionalQuestion())) {
- len = fir::CharacterType::unknownLen();
- } else if (!mlir::succeeded(parser.parseInteger(len))) {
- parser.emitError(parser.getCurrentLocation(), "len value expected");
- return Type();
- }
+// `vector` `<` len `:` type `>`
+mlir::Type fir::VectorType::parse(mlir::MLIRContext *context,
+ mlir::DialectAsmParser &parser) {
+ int64_t len = 0;
+ mlir::Type eleTy;
+ if (parser.parseLess() || parser.parseInteger(len) || parser.parseColon() ||
+ parser.parseType(eleTy) || parser.parseGreater()) {
+ parser.emitError(parser.getNameLoc(), "invalid vector type");
+ return {};
}
- if (parser.parseGreater())
- return Type();
- return get(context, kind, len);
+ return fir::VectorType::get(len, eleTy);
}
-void fir::CharacterType::print(::mlir::DialectAsmPrinter &printer) const {
- printer << "char<" << getFKind();
- auto len = getLen();
- if (len != fir::CharacterType::singleton()) {
- printer << ',';
- if (len == fir::CharacterType::unknownLen())
- printer << '?';
- else
- printer << len;
- }
- printer << '>';
+void fir::VectorType::print(mlir::DialectAsmPrinter &printer) const {
+ printer << getMnemonic() << "<" << getLen() << ':' << getEleTy() << '>';
}
-//===----------------------------------------------------------------------===//
-// ComplexType
-//===----------------------------------------------------------------------===//
-
-mlir::Type fir::ComplexType::parse(mlir::MLIRContext *context,
- mlir::DialectAsmParser &parser) {
- return parseKindSingleton<fir::ComplexType>(parser);
+mlir::LogicalResult fir::VectorType::verify(
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError, uint64_t len,
+ mlir::Type eleTy) {
+ if (!(fir::isa_real(eleTy) || fir::isa_integer(eleTy)))
+ return emitError() << "cannot build a vector of type " << eleTy << '\n';
+ return mlir::success();
}
-mlir::Type fir::ComplexType::getElementType() const {
- return fir::RealType::get(getContext(), getFKind());
+bool fir::VectorType::isValidElementType(mlir::Type t) {
+ return isa_real(t) || isa_integer(t);
}
More information about the flang-commits
mailing list