diff --git a/flang-rt/lib/runtime/descriptor.cpp b/flang-rt/lib/runtime/descriptor.cpp index a1f4b044bddd7..495e25e96aded 100644 --- a/flang-rt/lib/runtime/descriptor.cpp +++ b/flang-rt/lib/runtime/descriptor.cpp @@ -13,8 +13,8 @@ #include "flang-rt/runtime/derived.h" #include "flang-rt/runtime/stat.h" #include "flang-rt/runtime/terminator.h" -#include "flang-rt/runtime/tools.h" #include "flang-rt/runtime/type-info.h" +#include "flang/Common/type-kinds.h" #include #include #include @@ -61,18 +61,11 @@ RT_API_ATTRS void Descriptor::Establish(TypeCode t, std::size_t elementBytes, } } -namespace { -template struct TypeSizeGetter { - constexpr RT_API_ATTRS std::size_t operator()() const { - CppTypeFor arr[2]; - return sizeof arr / 2; - } -}; -} // namespace - RT_API_ATTRS std::size_t Descriptor::BytesFor(TypeCategory category, int kind) { Terminator terminator{__FILE__, __LINE__}; - return ApplyType(category, kind, terminator); + int bytes{common::TypeSizeInBytes(category, kind)}; + RUNTIME_CHECK(terminator, bytes > 0); + return bytes; } RT_API_ATTRS void Descriptor::Establish(TypeCategory c, int kind, void *p, diff --git a/flang/include/flang/Common/Fortran-consts.h b/flang/include/flang/Common/Fortran-consts.h index 3ce5b6ac7b686..74ef1c85d2c86 100644 --- a/flang/include/flang/Common/Fortran-consts.h +++ b/flang/include/flang/Common/Fortran-consts.h @@ -9,7 +9,7 @@ #ifndef FORTRAN_COMMON_FORTRAN_CONSTS_H_ #define FORTRAN_COMMON_FORTRAN_CONSTS_H_ -#include "enum-set.h" +#include "enum-class.h" #include namespace Fortran::common { diff --git a/flang/include/flang/Common/real.h b/flang/include/flang/Common/real.h index b47ba46581db6..785cde3236bf4 100644 --- a/flang/include/flang/Common/real.h +++ b/flang/include/flang/Common/real.h @@ -13,7 +13,6 @@ // The various representations are distinguished by their binary precisions // (number of explicit significand bits and any implicit MSB in the fraction). -#include "api-attrs.h" #include namespace Fortran::common { diff --git a/flang/include/flang/Common/type-kinds.h b/flang/include/flang/Common/type-kinds.h new file mode 100644 index 0000000000000..4e5c4f69fcc67 --- /dev/null +++ b/flang/include/flang/Common/type-kinds.h @@ -0,0 +1,63 @@ +//===-- include/flang/Common/type-kinds.h -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_COMMON_TYPE_KINDS_H_ +#define FORTRAN_COMMON_TYPE_KINDS_H_ + +#include "Fortran-consts.h" +#include "real.h" +#include + +namespace Fortran::common { + +static constexpr int maxKind{16}; + +// A predicate that is true when a kind value is a kind that could possibly +// be supported for an intrinsic type category on some target instruction +// set architecture. +static constexpr bool IsValidKindOfIntrinsicType( + TypeCategory category, std::int64_t kind) { + switch (category) { + case TypeCategory::Integer: + case TypeCategory::Unsigned: + return kind == 1 || kind == 2 || kind == 4 || kind == 8 || kind == 16; + case TypeCategory::Real: + case TypeCategory::Complex: + return kind == 2 || kind == 3 || kind == 4 || kind == 8 || kind == 10 || + kind == 16; + case TypeCategory::Character: + return kind == 1 || kind == 2 || kind == 4; + case TypeCategory::Logical: + return kind == 1 || kind == 2 || kind == 4 || kind == 8; + default: + return false; + } +} + +static constexpr int TypeSizeInBytes(TypeCategory category, std::int64_t kind) { + if (IsValidKindOfIntrinsicType(category, kind)) { + if (category == TypeCategory::Real || category == TypeCategory::Complex) { + int precision{PrecisionOfRealKind(kind)}; + int bits{BitsForBinaryPrecision(precision)}; + if (bits == 80) { // x87 is stored in 16-byte containers + bits = 128; + } + if (category == TypeCategory::Complex) { + bits *= 2; + } + return bits >> 3; + } else { + return kind; + } + } else { + return -1; + } +} + +} // namespace Fortran::common +#endif // FORTRAN_COMMON_TYPE_KINDS_H_ diff --git a/flang/include/flang/Evaluate/target.h b/flang/include/flang/Evaluate/target.h index 7b1593ca270db..cc6172b492b3c 100644 --- a/flang/include/flang/Evaluate/target.h +++ b/flang/include/flang/Evaluate/target.h @@ -15,6 +15,7 @@ #include "flang/Common/enum-class.h" #include "flang/Common/enum-set.h" #include "flang/Common/target-rounding.h" +#include "flang/Common/type-kinds.h" #include "flang/Evaluate/common.h" #include "flang/Support/Fortran.h" #include @@ -131,7 +132,7 @@ class TargetCharacteristics { const IeeeFeatures &ieeeFeatures() const { return ieeeFeatures_; } private: - static constexpr int maxKind{16}; + static constexpr int maxKind{common::maxKind}; std::uint8_t byteSize_[common::TypeCategory_enumSize][maxKind + 1]{}; std::uint8_t align_[common::TypeCategory_enumSize][maxKind + 1]{}; bool isBigEndian_{false}; diff --git a/flang/include/flang/Evaluate/type.h b/flang/include/flang/Evaluate/type.h index cfb162f040e8a..f3bba7790e1a2 100644 --- a/flang/include/flang/Evaluate/type.h +++ b/flang/include/flang/Evaluate/type.h @@ -25,6 +25,7 @@ #include "flang/Common/idioms.h" #include "flang/Common/real.h" #include "flang/Common/template.h" +#include "flang/Common/type-kinds.h" #include "flang/Support/Fortran-features.h" #include "flang/Support/Fortran.h" #include @@ -62,28 +63,6 @@ using LogicalResult = Type; using LargestReal = Type; using Ascii = Type; -// A predicate that is true when a kind value is a kind that could possibly -// be supported for an intrinsic type category on some target instruction -// set architecture. -static constexpr bool IsValidKindOfIntrinsicType( - TypeCategory category, std::int64_t kind) { - switch (category) { - case TypeCategory::Integer: - case TypeCategory::Unsigned: - return kind == 1 || kind == 2 || kind == 4 || kind == 8 || kind == 16; - case TypeCategory::Real: - case TypeCategory::Complex: - return kind == 2 || kind == 3 || kind == 4 || kind == 8 || kind == 10 || - kind == 16; - case TypeCategory::Character: - return kind == 1 || kind == 2 || kind == 4; - case TypeCategory::Logical: - return kind == 1 || kind == 2 || kind == 4 || kind == 8; - default: - return false; - } -} - // DynamicType is meant to be suitable for use as the result type for // GetType() functions and member functions; consequently, it must be // capable of being used in a constexpr context. So it does *not* @@ -95,7 +74,7 @@ static constexpr bool IsValidKindOfIntrinsicType( class DynamicType { public: constexpr DynamicType(TypeCategory cat, int k) : category_{cat}, kind_{k} { - CHECK(IsValidKindOfIntrinsicType(category_, kind_)); + CHECK(common::IsValidKindOfIntrinsicType(category_, kind_)); } DynamicType(int charKind, const semantics::ParamValue &len); // When a known length is presented, resolve it to its effective @@ -103,7 +82,7 @@ class DynamicType { constexpr DynamicType(int k, std::int64_t len) : category_{TypeCategory::Character}, kind_{k}, knownLength_{ len >= 0 ? len : 0} { - CHECK(IsValidKindOfIntrinsicType(category_, kind_)); + CHECK(common::IsValidKindOfIntrinsicType(category_, kind_)); } explicit constexpr DynamicType( const semantics::DerivedTypeSpec &dt, bool poly = false) @@ -360,7 +339,7 @@ using IndirectSubscriptIntegerExpr = // category that could possibly be supported on any target. template using CategoryKindTuple = - std::conditional_t>, std::tuple<>>; template diff --git a/flang/lib/Evaluate/target.cpp b/flang/lib/Evaluate/target.cpp index ba768f38c0ba4..c443278148304 100644 --- a/flang/lib/Evaluate/target.cpp +++ b/flang/lib/Evaluate/target.cpp @@ -8,6 +8,7 @@ #include "flang/Evaluate/target.h" #include "flang/Common/template.h" +#include "flang/Common/type-kinds.h" #include "flang/Evaluate/common.h" #include "flang/Evaluate/type.h" @@ -19,21 +20,11 @@ TargetCharacteristics::TargetCharacteristics() { auto enableCategoryKinds{[this](TypeCategory category) { for (int kind{1}; kind <= maxKind; ++kind) { if (CanSupportType(category, kind)) { - auto byteSize{static_cast(kind)}; - if (category == TypeCategory::Real || - category == TypeCategory::Complex) { - if (kind == 3) { - // non-IEEE 16-bit format (truncated 32-bit) - byteSize = 2; - } else if (kind == 10) { - // x87 floating-point - // Follow gcc precedent for "long double" - byteSize = 16; - } - } + auto byteSize{ + static_cast(common::TypeSizeInBytes(category, kind))}; std::size_t align{byteSize}; if (category == TypeCategory::Complex) { - byteSize = 2 * byteSize; + align /= 2; } EnableType(category, kind, byteSize, align); } @@ -53,7 +44,7 @@ TargetCharacteristics::TargetCharacteristics() { bool TargetCharacteristics::CanSupportType( TypeCategory category, std::int64_t kind) { - return IsValidKindOfIntrinsicType(category, kind); + return common::IsValidKindOfIntrinsicType(category, kind); } bool TargetCharacteristics::EnableType(common::TypeCategory category, diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index fcd6860917247..702711e3cff53 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -8,6 +8,7 @@ #include "flang/Evaluate/tools.h" #include "flang/Common/idioms.h" +#include "flang/Common/type-kinds.h" #include "flang/Evaluate/characteristics.h" #include "flang/Evaluate/traverse.h" #include "flang/Parser/message.h" @@ -1349,7 +1350,7 @@ template static std::optional> DataConstantConversionHelper( FoldingContext &context, const DynamicType &toType, const Expr &expr) { - if (!IsValidKindOfIntrinsicType(FROM, toType.kind())) { + if (!common::IsValidKindOfIntrinsicType(FROM, toType.kind())) { return std::nullopt; } DynamicType sizedType{FROM, toType.kind()}; diff --git a/flang/lib/Evaluate/type.cpp b/flang/lib/Evaluate/type.cpp index c8f75f91ed9c6..5b5f3c2cd0cf0 100644 --- a/flang/lib/Evaluate/type.cpp +++ b/flang/lib/Evaluate/type.cpp @@ -8,6 +8,7 @@ #include "flang/Evaluate/type.h" #include "flang/Common/idioms.h" +#include "flang/Common/type-kinds.h" #include "flang/Evaluate/expression.h" #include "flang/Evaluate/fold.h" #include "flang/Evaluate/target.h" @@ -118,7 +119,7 @@ namespace Fortran::evaluate { DynamicType::DynamicType(int k, const semantics::ParamValue &pv) : category_{TypeCategory::Character}, kind_{k} { - CHECK(IsValidKindOfIntrinsicType(category_, kind_)); + CHECK(common::IsValidKindOfIntrinsicType(category_, kind_)); if (auto n{ToInt64(pv.GetExplicit())}) { knownLength_ = *n > 0 ? *n : 0; } else { @@ -660,7 +661,7 @@ std::optional DynamicType::From( if (const auto *intrinsic{type.AsIntrinsic()}) { if (auto kind{ToInt64(intrinsic->kind())}) { TypeCategory category{intrinsic->category()}; - if (IsValidKindOfIntrinsicType(category, *kind)) { + if (common::IsValidKindOfIntrinsicType(category, *kind)) { if (category == TypeCategory::Character) { const auto &charType{type.characterTypeSpec()}; return DynamicType{static_cast(*kind), charType.length()}; diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp index 2fab520e6c475..d45f9e7c0bf1b 100644 --- a/flang/lib/Lower/ConvertType.cpp +++ b/flang/lib/Lower/ConvertType.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "flang/Lower/ConvertType.h" +#include "flang/Common/type-kinds.h" #include "flang/Lower/AbstractConverter.h" #include "flang/Lower/CallInterface.h" #include "flang/Lower/ConvertVariable.h" @@ -32,7 +33,7 @@ using Fortran::common::VectorElementCategory; //===--------------------------------------------------------------------===// static mlir::Type genRealType(mlir::MLIRContext *context, int kind) { - if (Fortran::evaluate::IsValidKindOfIntrinsicType( + if (Fortran::common::IsValidKindOfIntrinsicType( Fortran::common::TypeCategory::Real, kind)) { switch (kind) { case 2: @@ -59,7 +60,7 @@ int getIntegerBits() { } static mlir::Type genIntegerType(mlir::MLIRContext *context, int kind, bool isUnsigned = false) { - if (Fortran::evaluate::IsValidKindOfIntrinsicType( + if (Fortran::common::IsValidKindOfIntrinsicType( Fortran::common::TypeCategory::Integer, kind)) { mlir::IntegerType::SignednessSemantics signedness = (isUnsigned ? mlir::IntegerType::SignednessSemantics::Unsigned @@ -82,7 +83,7 @@ static mlir::Type genIntegerType(mlir::MLIRContext *context, int kind, } static mlir::Type genLogicalType(mlir::MLIRContext *context, int KIND) { - if (Fortran::evaluate::IsValidKindOfIntrinsicType( + if (Fortran::common::IsValidKindOfIntrinsicType( Fortran::common::TypeCategory::Logical, KIND)) return fir::LogicalType::get(context, KIND); return {}; @@ -91,7 +92,7 @@ static mlir::Type genLogicalType(mlir::MLIRContext *context, int KIND) { static mlir::Type genCharacterType( mlir::MLIRContext *context, int KIND, Fortran::lower::LenParameterTy len = fir::CharacterType::unknownLen()) { - if (Fortran::evaluate::IsValidKindOfIntrinsicType( + if (Fortran::common::IsValidKindOfIntrinsicType( Fortran::common::TypeCategory::Character, KIND)) return fir::CharacterType::get(context, KIND, len); return {}; diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index f2b9702d7c5a0..e139bda7e4950 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -12,6 +12,7 @@ #include "resolve-names-utils.h" #include "resolve-names.h" #include "flang/Common/idioms.h" +#include "flang/Common/type-kinds.h" #include "flang/Evaluate/common.h" #include "flang/Evaluate/fold.h" #include "flang/Evaluate/tools.h" @@ -1058,7 +1059,8 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) { if (const semantics::IntrinsicTypeSpec * intrinType{typeSpec->AsIntrinsic()}) { if (auto k{ToInt64(Fold(semantics::KindExpr{intrinType->kind()}))}; - k && IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) { + k && + common::IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) { kind = *k; } } diff --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp index c5a75c4d619c5..964a37e1c822b 100644 --- a/flang/lib/Semantics/type.cpp +++ b/flang/lib/Semantics/type.cpp @@ -9,6 +9,7 @@ #include "flang/Semantics/type.h" #include "check-declarations.h" #include "compute-offsets.h" +#include "flang/Common/type-kinds.h" #include "flang/Evaluate/fold.h" #include "flang/Evaluate/tools.h" #include "flang/Evaluate/type.h" @@ -125,7 +126,7 @@ void DerivedTypeSpec::EvaluateParameters(SemanticsContext &context) { auto restorer{foldingContext.WithPDTInstance(*this)}; auto folded{Fold(foldingContext, KindExpr{intrinType->kind()})}; if (auto k{evaluate::ToInt64(folded)}; k && - evaluate::IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) { + common::IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) { parameterKind = static_cast(*k); } else { messages.Say(