diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -33,8 +33,6 @@ "FIR dialect type">; // Fortran intrinsic types -def fir_CharacterType : Type()">, - "FIR character type">; def fir_ComplexType : Type()">, "FIR complex type">; def fir_IntegerType : Type()">, @@ -84,10 +82,6 @@ def AnyReferenceLike : TypeConstraint, "any reference">; -// CHARACTER type descriptor. A pair of a data reference and a LEN value. -def fir_BoxCharType : Type()">, - "box character type">; - // PROCEDURE POINTER descriptor. A pair that can capture a host closure. def fir_BoxProcType : Type()">, "box procedure type">; diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h --- a/flang/include/flang/Optimizer/Dialect/FIRType.h +++ b/flang/include/flang/Optimizer/Dialect/FIRType.h @@ -42,9 +42,7 @@ using KindTy = unsigned; namespace detail { -struct BoxCharTypeStorage; struct BoxProcTypeStorage; -struct CharacterTypeStorage; struct ComplexTypeStorage; struct HeapTypeStorage; struct IntegerTypeStorage; @@ -98,37 +96,6 @@ // Intrinsic types -/// Model of the Fortran CHARACTER intrinsic type, including the KIND type -/// parameter. The model optionally includes a LEN type parameter. A -/// CharacterType is thus the type of both a single character value and a -/// character with a LEN parameter. -class CharacterType - : public mlir::Type::TypeBase { -public: - using Base::Base; - using LenType = std::int64_t; - - static CharacterType get(mlir::MLIRContext *ctxt, KindTy kind, LenType len); - /// Return unknown length CHARACTER type. - static CharacterType getUnknownLen(mlir::MLIRContext *ctxt, KindTy kind) { - return get(ctxt, kind, unknownLen()); - } - /// Return length 1 CHARACTER type. - static CharacterType getSingleton(mlir::MLIRContext *ctxt, KindTy kind) { - return get(ctxt, kind, singleton()); - } - KindTy getFKind() const; - - /// CHARACTER is a singleton and has a LEN of 1. - static constexpr LenType singleton() { return 1; } - /// CHARACTER has an unknown LEN property. - static constexpr LenType unknownLen() { return -1; } - - /// Access to a CHARACTER's LEN property. Defaults to 1. - LenType getLen() const; -}; - /// Model of a Fortran COMPLEX intrinsic type, including the KIND type /// parameter. COMPLEX is a floating point type with a real and imaginary /// member. @@ -176,17 +143,6 @@ // FIR support types -/// The type of a pair that describes a CHARACTER variable. Specifically, a -/// CHARACTER consists of a reference to a buffer (the string value) and a LEN -/// type parameter (the runtime length of the buffer). -class BoxCharType : public mlir::Type::TypeBase { -public: - using Base::Base; - static BoxCharType get(mlir::MLIRContext *ctxt, KindTy kind); - CharacterType getEleTy() const; -}; - /// The type of a pair that describes a PROCEDURE reference. Pointers to /// internal procedures must carry an additional reference to the host's /// variables that are referenced. diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td --- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td +++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td @@ -115,4 +115,64 @@ }]; } +def fir_CharacterType : FIR_Type<"Character", "char"> { + let summary = "FIR character type"; + + let description = [{ + Model of the Fortran CHARACTER intrinsic type, including the KIND type + parameter. The model optionally includes a LEN type parameter. A + CharacterType is thus the type of both a single character value and a + character with a LEN parameter. + }]; + + let parameters = (ins "KindTy":$FKind, "CharacterType::LenType":$len); + + let extraClassDeclaration = [{ + using KindTy = unsigned; + using LenType = std::int64_t; + + // Return unknown length CHARACTER type. + static CharacterType getUnknownLen(mlir::MLIRContext *ctxt, KindTy kind) { + return get(ctxt, kind, unknownLen()); + } + + // Return length 1 CHARACTER type. + static CharacterType getSingleton(mlir::MLIRContext *ctxt, KindTy kind) { + return get(ctxt, kind, singleton()); + } + + // CHARACTER is a singleton and has a LEN of 1. + static constexpr LenType singleton() { return 1; } + // CHARACTER has an unknown LEN property. + static constexpr LenType unknownLen() { return -1; } + }]; +} + +def fir_BoxCharType : FIR_Type<"BoxChar", "boxchar"> { + let summary = "CHARACTER type descriptor."; + + let description = [{ + The type of a pair that describes a CHARACTER variable. Specifically, a + CHARACTER consists of a reference to a buffer (the string value) and a LEN + type parameter (the runtime length of the buffer). + }]; + + let parameters = (ins "KindTy":$kind); + + let printer = [{ + $_printer << "boxchar<" << getImpl()->kind << ">"; + }]; + + let genAccessors = 1; + + let extraClassDeclaration = [{ + using KindTy = unsigned; + + // a !fir.boxchar always wraps a !fir.char + CharacterType getElementType(mlir::MLIRContext *context) const; + + CharacterType getEleTy() const; + }]; +} + #endif // FIR_DIALECT_FIR_TYPES diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -58,37 +58,11 @@ return TYPE::get(ty); } -// `boxchar` `<` kind `>` -BoxCharType parseBoxChar(mlir::DialectAsmParser &parser) { - return parseKindSingleton(parser); -} - // `boxproc` `<` return-type `>` BoxProcType parseBoxProc(mlir::DialectAsmParser &parser, mlir::Location loc) { return parseTypeSingleton(parser, loc); } -// `char` `<` kind [`,` `len`] `>` -CharacterType parseCharacter(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 CharacterType::get(parser.getBuilder().getContext(), kind, len); -} - // `complex` `<` kind `>` fir::ComplexType parseComplex(mlir::DialectAsmParser &parser) { return parseKindSingleton(parser); @@ -325,17 +299,20 @@ if (mlir::failed(parser.parseKeyword(&typeNameLit))) return {}; + // 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 parseBoxChar(parser); + return generatedTypeParser(dialect->getContext(), parser, typeNameLit); if (typeNameLit == "boxproc") return parseBoxProc(parser, loc); if (typeNameLit == "char") - return parseCharacter(parser); + return generatedTypeParser(dialect->getContext(), parser, typeNameLit); if (typeNameLit == "complex") return parseComplex(parser); if (typeNameLit == "field") @@ -378,39 +355,6 @@ // Type storage classes -/// `CHARACTER` storage -struct CharacterTypeStorage : public mlir::TypeStorage { - using KeyTy = std::tuple; - - static unsigned hashKey(const KeyTy &key) { - auto hashVal = llvm::hash_combine(std::get<0>(key)); - return llvm::hash_combine(hashVal, llvm::hash_combine(std::get<1>(key))); - } - - bool operator==(const KeyTy &key) const { - return key == KeyTy{getFKind(), getLen()}; - } - - static CharacterTypeStorage *construct(mlir::TypeStorageAllocator &allocator, - const KeyTy &key) { - auto *storage = allocator.allocate(); - return new (storage) - CharacterTypeStorage{std::get<0>(key), std::get<1>(key)}; - } - - KindTy getFKind() const { return kind; } - CharacterType::LenType getLen() const { return len; } - -protected: - KindTy kind; - CharacterType::LenType len; - -private: - CharacterTypeStorage() = delete; - explicit CharacterTypeStorage(KindTy kind, CharacterType::LenType len) - : kind{kind}, len{len} {} -}; - struct SliceTypeStorage : public mlir::TypeStorage { using KeyTy = unsigned; @@ -549,35 +493,6 @@ explicit RealTypeStorage(KindTy kind) : kind{kind} {} }; -/// Boxed CHARACTER object type -struct BoxCharTypeStorage : 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 BoxCharTypeStorage *construct(mlir::TypeStorageAllocator &allocator, - KindTy kind) { - auto *storage = allocator.allocate(); - return new (storage) BoxCharTypeStorage{kind}; - } - - KindTy getFKind() const { return kind; } - - // a !fir.boxchar always wraps a !fir.char - CharacterType getElementType(mlir::MLIRContext *ctxt) const { - return CharacterType::getUnknownLen(ctxt, getFKind()); - } - -protected: - KindTy kind; - -private: - BoxCharTypeStorage() = delete; - explicit BoxCharTypeStorage(KindTy kind) : kind{kind} {} -}; - /// Boxed PROCEDURE POINTER object type struct BoxProcTypeStorage : public mlir::TypeStorage { using KeyTy = mlir::Type; @@ -872,19 +787,6 @@ } // namespace fir -// CHARACTER - -CharacterType fir::CharacterType::get(mlir::MLIRContext *ctxt, KindTy kind, - CharacterType::LenType len) { - return Base::get(ctxt, kind, len); -} - -KindTy fir::CharacterType::getFKind() const { return getImpl()->getFKind(); } - -CharacterType::LenType fir::CharacterType::getLen() const { - return getImpl()->getLen(); -} - // Len LenType fir::LenType::get(mlir::MLIRContext *ctxt) { @@ -934,16 +836,6 @@ return mlir::success(); } -// BoxChar - -BoxCharType fir::BoxCharType::get(mlir::MLIRContext *ctxt, KindTy kind) { - return Base::get(ctxt, kind); -} - -CharacterType fir::BoxCharType::getEleTy() const { - return getImpl()->getElementType(getContext()); -} - // BoxProc BoxProcType fir::BoxProcType::get(mlir::Type elementType) { @@ -1240,31 +1132,12 @@ void fir::printFirType(FIROpsDialect *, mlir::Type ty, mlir::DialectAsmPrinter &p) { auto &os = p.getStream(); - if (auto type = ty.dyn_cast()) { - os << "boxchar<" << type.getEleTy().cast().getFKind() - << '>'; - return; - } if (auto type = ty.dyn_cast()) { os << "boxproc<"; p.printType(type.getEleTy()); os << '>'; return; } - if (auto chTy = ty.dyn_cast()) { - // Fortran intrinsic type CHARACTER - os << "char<" << chTy.getFKind(); - auto len = chTy.getLen(); - if (len != fir::CharacterType::singleton()) { - os << ','; - if (len == fir::CharacterType::unknownLen()) - os << '?'; - else - os << len; - } - os << '>'; - return; - } if (auto type = ty.dyn_cast()) { // Fortran intrinsic type COMPLEX os << "complex<" << type.getFKind() << '>'; @@ -1387,15 +1260,13 @@ return false; } -namespace fir { - //===----------------------------------------------------------------------===// // BoxType //===----------------------------------------------------------------------===// // `box` `<` type (',' affine-map)? `>` -mlir::Type BoxType::parse(mlir::MLIRContext *context, - mlir::DialectAsmParser &parser) { +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"); @@ -1416,7 +1287,7 @@ return get(ofTy, map); } -void BoxType::print(::mlir::DialectAsmPrinter &printer) const { +void fir::BoxType::print(::mlir::DialectAsmPrinter &printer) const { printer << "box<"; printer.printType(getEleTy()); if (auto map = getLayoutMap()) { @@ -1426,4 +1297,65 @@ printer << '>'; } -} // namespace fir +//===----------------------------------------------------------------------===// +// BoxCharType +//===----------------------------------------------------------------------===// + +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); +} + +CharacterType +fir::BoxCharType::getElementType(mlir::MLIRContext *context) const { + return CharacterType::getUnknownLen(context, getKind()); +} + +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 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(); + } + } + if (parser.parseGreater()) + return Type(); + return get(context, kind, len); +} + +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 << '>'; +}