1//===-- lib/Semantics/target.cpp ------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "flang/Evaluate/target.h"
10#include "flang/Common/template.h"
11#include "flang/Evaluate/common.h"
12#include "flang/Evaluate/type.h"
13
14namespace Fortran::evaluate {
15
16Rounding TargetCharacteristics::defaultRounding;
17
18TargetCharacteristics::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) {
25 if (kind == 3) {
26 // non-IEEE 16-bit format (truncated 32-bit)
27 byteSize = 2;
28 } else if (kind == 10) {
29 // x87 floating-point
30 // Follow gcc precedent for "long double"
31 byteSize = 16;
32 }
33 }
34 std::size_t align{byteSize};
35 if (category == TypeCategory::Complex) {
36 byteSize = 2 * byteSize;
37 }
38 EnableType(category, kind, byteSize, align);
39 }
40 }
41 }};
42 enableCategoryKinds(TypeCategory::Integer);
43 enableCategoryKinds(TypeCategory::Real);
44 enableCategoryKinds(TypeCategory::Complex);
45 enableCategoryKinds(TypeCategory::Character);
46 enableCategoryKinds(TypeCategory::Logical);
47
48 isBigEndian_ = !isHostLittleEndian;
49
50 areSubnormalsFlushedToZero_ = false;
51}
52
53bool TargetCharacteristics::CanSupportType(
54 TypeCategory category, std::int64_t kind) {
55 return IsValidKindOfIntrinsicType(category, kind);
56}
57
58bool 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);
65 return true;
66 } else {
67 return false;
68 }
69}
70
71void TargetCharacteristics::DisableType(
72 common::TypeCategory category, std::int64_t kind) {
73 if (kind >= 0 && kind < maxKind) {
74 align_[static_cast<int>(category)][kind] = 0;
75 }
76}
77
78std::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];
82 } else {
83 return 0;
84 }
85}
86
87std::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];
91 } else {
92 return 0;
93 }
94}
95
96bool TargetCharacteristics::IsTypeEnabled(
97 common::TypeCategory category, std::int64_t kind) const {
98 return GetAlignment(category, kind) > 0;
99}
100
101void TargetCharacteristics::set_isBigEndian(bool isBig) {
102 isBigEndian_ = isBig;
103}
104
105void TargetCharacteristics::set_isPPC(bool isPowerPC) { isPPC_ = isPowerPC; }
106
107void TargetCharacteristics::set_areSubnormalsFlushedToZero(bool yes) {
108 areSubnormalsFlushedToZero_ = yes;
109}
110
111void TargetCharacteristics::set_roundingMode(Rounding rounding) {
112 roundingMode_ = rounding;
113}
114
115// SELECTED_INT_KIND() -- F'2018 16.9.169
116class SelectedIntKindVisitor {
117public:
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)) {
126 return T::kind;
127 } else {
128 return std::nullopt;
129 }
130 }
131
132private:
133 const TargetCharacteristics &targetCharacteristics_;
134 std::int64_t precision_;
135};
136
137int TargetCharacteristics::SelectedIntKind(std::int64_t precision) const {
138 if (auto kind{
139 common::SearchTypes(SelectedIntKindVisitor{*this, precision})}) {
140 return *kind;
141 } else {
142 return -1;
143 }
144}
145
146// SELECTED_LOGICAL_KIND() -- F'2023 16.9.182
147class SelectedLogicalKindVisitor {
148public:
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)) {
157 return T::kind;
158 } else {
159 return std::nullopt;
160 }
161 }
162
163private:
164 const TargetCharacteristics &targetCharacteristics_;
165 std::int64_t bits_;
166};
167
168int TargetCharacteristics::SelectedLogicalKind(std::int64_t bits) const {
169 if (auto kind{common::SearchTypes(SelectedLogicalKindVisitor{*this, bits})}) {
170 return *kind;
171 } else {
172 return -1;
173 }
174}
175
176// SELECTED_REAL_KIND() -- F'2018 16.9.170
177class SelectedRealKindVisitor {
178public:
179 SelectedRealKindVisitor(const TargetCharacteristics &targetCharacteristics,
180 std::int64_t p, std::int64_t r)
181 : targetCharacteristics_{targetCharacteristics}, precision_{p}, range_{
182 r} {}
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)) {
188 return {T::kind};
189 } else {
190 return std::nullopt;
191 }
192 }
193
194private:
195 const TargetCharacteristics &targetCharacteristics_;
196 std::int64_t precision_, range_;
197};
198
199int TargetCharacteristics::SelectedRealKind(
200 std::int64_t precision, std::int64_t range, std::int64_t radix) const {
201 if (radix != 2) {
202 return -5;
203 }
204 if (auto kind{common::SearchTypes(
205 SelectedRealKindVisitor{*this, precision, range})}) {
206 return *kind;
207 }
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})};
213 if (pOK) {
214 if (rOK) {
215 return -4;
216 } else {
217 return -2;
218 }
219 } else {
220 if (rOK) {
221 return -1;
222 } else {
223 return -3;
224 }
225 }
226}
227
228} // namespace Fortran::evaluate
229

source code of flang/lib/Evaluate/target.cpp