1 //===-- lib/Semantics/target.cpp ------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "flang/Evaluate/target.h"
10 #include "flang/Common/template.h"
11 #include "flang/Evaluate/common.h"
12 #include "flang/Evaluate/type.h"
14 namespace Fortran::evaluate
{
16 Rounding
TargetCharacteristics::defaultRounding
;
18 TargetCharacteristics::TargetCharacteristics() {
19 auto enableCategoryKinds
{[this](TypeCategory category
) {
20 for (int kind
{0}; kind
< maxKind
; ++kind
) {
21 if (CanSupportType(category
, kind
)) {
22 auto byteSize
{static_cast<std::size_t>(kind
)};
23 if (category
== TypeCategory::Real
||
24 category
== TypeCategory::Complex
) {
26 // non-IEEE 16-bit format (truncated 32-bit)
28 } else if (kind
== 10) {
30 // Follow gcc precedent for "long double"
34 std::size_t align
{byteSize
};
35 if (category
== TypeCategory::Complex
) {
36 byteSize
= 2 * byteSize
;
38 EnableType(category
, kind
, byteSize
, align
);
42 enableCategoryKinds(TypeCategory::Integer
);
43 enableCategoryKinds(TypeCategory::Real
);
44 enableCategoryKinds(TypeCategory::Complex
);
45 enableCategoryKinds(TypeCategory::Character
);
46 enableCategoryKinds(TypeCategory::Logical
);
48 isBigEndian_
= !isHostLittleEndian
;
50 areSubnormalsFlushedToZero_
= false;
53 bool TargetCharacteristics::CanSupportType(
54 TypeCategory category
, std::int64_t kind
) {
55 return IsValidKindOfIntrinsicType(category
, kind
);
58 bool TargetCharacteristics::EnableType(common::TypeCategory category
,
59 std::int64_t kind
, std::size_t byteSize
, std::size_t align
) {
60 if (CanSupportType(category
, kind
)) {
61 byteSize_
[static_cast<int>(category
)][kind
] = byteSize
;
62 align_
[static_cast<int>(category
)][kind
] = align
;
63 maxByteSize_
= std::max(maxByteSize_
, byteSize
);
64 maxAlignment_
= std::max(maxAlignment_
, align
);
71 void TargetCharacteristics::DisableType(
72 common::TypeCategory category
, std::int64_t kind
) {
73 if (kind
>= 0 && kind
< maxKind
) {
74 align_
[static_cast<int>(category
)][kind
] = 0;
78 std::size_t TargetCharacteristics::GetByteSize(
79 common::TypeCategory category
, std::int64_t kind
) const {
80 if (kind
>= 0 && kind
< maxKind
) {
81 return byteSize_
[static_cast<int>(category
)][kind
];
87 std::size_t TargetCharacteristics::GetAlignment(
88 common::TypeCategory category
, std::int64_t kind
) const {
89 if (kind
>= 0 && kind
< maxKind
) {
90 return align_
[static_cast<int>(category
)][kind
];
96 bool TargetCharacteristics::IsTypeEnabled(
97 common::TypeCategory category
, std::int64_t kind
) const {
98 return GetAlignment(category
, kind
) > 0;
101 void TargetCharacteristics::set_isBigEndian(bool isBig
) {
102 isBigEndian_
= isBig
;
105 void TargetCharacteristics::set_isPPC(bool isPowerPC
) { isPPC_
= isPowerPC
; }
107 void TargetCharacteristics::set_areSubnormalsFlushedToZero(bool yes
) {
108 areSubnormalsFlushedToZero_
= yes
;
111 void TargetCharacteristics::set_roundingMode(Rounding rounding
) {
112 roundingMode_
= rounding
;
115 // SELECTED_INT_KIND() -- F'2018 16.9.169
116 class SelectedIntKindVisitor
{
118 SelectedIntKindVisitor(
119 const TargetCharacteristics
&targetCharacteristics
, std::int64_t p
)
120 : targetCharacteristics_
{targetCharacteristics
}, precision_
{p
} {}
121 using Result
= std::optional
<int>;
122 using Types
= IntegerTypes
;
123 template <typename T
> Result
Test() const {
124 if (Scalar
<T
>::RANGE
>= precision_
&&
125 targetCharacteristics_
.IsTypeEnabled(T::category
, T::kind
)) {
133 const TargetCharacteristics
&targetCharacteristics_
;
134 std::int64_t precision_
;
137 int TargetCharacteristics::SelectedIntKind(std::int64_t precision
) const {
139 common::SearchTypes(SelectedIntKindVisitor
{*this, precision
})}) {
146 // SELECTED_LOGICAL_KIND() -- F'2023 16.9.182
147 class SelectedLogicalKindVisitor
{
149 SelectedLogicalKindVisitor(
150 const TargetCharacteristics
&targetCharacteristics
, std::int64_t bits
)
151 : targetCharacteristics_
{targetCharacteristics
}, bits_
{bits
} {}
152 using Result
= std::optional
<int>;
153 using Types
= LogicalTypes
;
154 template <typename T
> Result
Test() const {
155 if (Scalar
<T
>::bits
>= bits_
&&
156 targetCharacteristics_
.IsTypeEnabled(T::category
, T::kind
)) {
164 const TargetCharacteristics
&targetCharacteristics_
;
168 int TargetCharacteristics::SelectedLogicalKind(std::int64_t bits
) const {
169 if (auto kind
{common::SearchTypes(SelectedLogicalKindVisitor
{*this, bits
})}) {
176 // SELECTED_REAL_KIND() -- F'2018 16.9.170
177 class SelectedRealKindVisitor
{
179 SelectedRealKindVisitor(const TargetCharacteristics
&targetCharacteristics
,
180 std::int64_t p
, std::int64_t r
)
181 : targetCharacteristics_
{targetCharacteristics
}, precision_
{p
}, range_
{
183 using Result
= std::optional
<int>;
184 using Types
= RealTypes
;
185 template <typename T
> Result
Test() const {
186 if (Scalar
<T
>::PRECISION
>= precision_
&& Scalar
<T
>::RANGE
>= range_
&&
187 targetCharacteristics_
.IsTypeEnabled(T::category
, T::kind
)) {
195 const TargetCharacteristics
&targetCharacteristics_
;
196 std::int64_t precision_
, range_
;
199 int TargetCharacteristics::SelectedRealKind(
200 std::int64_t precision
, std::int64_t range
, std::int64_t radix
) const {
204 if (auto kind
{common::SearchTypes(
205 SelectedRealKindVisitor
{*this, precision
, range
})}) {
208 // No kind has both sufficient precision and sufficient range.
209 // The negative return value encodes whether any kinds exist that
210 // could satisfy either constraint independently.
211 bool pOK
{common::SearchTypes(SelectedRealKindVisitor
{*this, precision
, 0})};
212 bool rOK
{common::SearchTypes(SelectedRealKindVisitor
{*this, 0, range
})};
228 } // namespace Fortran::evaluate