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/Common/type-kinds.h"
12#include "flang/Evaluate/common.h"
13#include "flang/Evaluate/type.h"
14
15namespace Fortran::evaluate {
16
17Rounding TargetCharacteristics::defaultRounding;
18
19TargetCharacteristics::TargetCharacteristics() {
20 auto enableCategoryKinds{[this](TypeCategory category) {
21 for (int kind{1}; kind <= maxKind; ++kind) {
22 if (CanSupportType(category, kind)) {
23 auto byteSize{
24 static_cast<std::size_t>(common::TypeSizeInBytes(category, kind))};
25 std::size_t align{byteSize};
26 if (category == TypeCategory::Complex) {
27 align /= 2;
28 }
29 EnableType(category, kind, byteSize, align);
30 }
31 }
32 }};
33 enableCategoryKinds(TypeCategory::Integer);
34 enableCategoryKinds(TypeCategory::Real);
35 enableCategoryKinds(TypeCategory::Complex);
36 enableCategoryKinds(TypeCategory::Character);
37 enableCategoryKinds(TypeCategory::Logical);
38 enableCategoryKinds(TypeCategory::Unsigned);
39
40 isBigEndian_ = !isHostLittleEndian;
41
42 areSubnormalsFlushedToZero_ = false;
43}
44
45bool TargetCharacteristics::CanSupportType(
46 TypeCategory category, std::int64_t kind) {
47 return common::IsValidKindOfIntrinsicType(category, kind);
48}
49
50bool TargetCharacteristics::EnableType(common::TypeCategory category,
51 std::int64_t kind, std::size_t byteSize, std::size_t align) {
52 if (CanSupportType(category, kind)) {
53 byteSize_[static_cast<int>(category)][kind] = byteSize;
54 align_[static_cast<int>(category)][kind] = align;
55 maxByteSize_ = std::max(maxByteSize_, byteSize);
56 maxAlignment_ = std::max(maxAlignment_, align);
57 return true;
58 } else {
59 return false;
60 }
61}
62
63void TargetCharacteristics::DisableType(
64 common::TypeCategory category, std::int64_t kind) {
65 if (kind > 0 && kind <= maxKind) {
66 align_[static_cast<int>(category)][kind] = 0;
67 }
68}
69
70std::size_t TargetCharacteristics::GetByteSize(
71 common::TypeCategory category, std::int64_t kind) const {
72 if (kind > 0 && kind <= maxKind) {
73 return byteSize_[static_cast<int>(category)][kind];
74 } else {
75 return 0;
76 }
77}
78
79std::size_t TargetCharacteristics::GetAlignment(
80 common::TypeCategory category, std::int64_t kind) const {
81 if (kind > 0 && kind <= maxKind) {
82 return align_[static_cast<int>(category)][kind];
83 } else {
84 return 0;
85 }
86}
87
88bool TargetCharacteristics::IsTypeEnabled(
89 common::TypeCategory category, std::int64_t kind) const {
90 return GetAlignment(category, kind) > 0;
91}
92
93void TargetCharacteristics::set_isBigEndian(bool isBig) {
94 isBigEndian_ = isBig;
95}
96
97void TargetCharacteristics::set_isPPC(bool isPowerPC) { isPPC_ = isPowerPC; }
98void TargetCharacteristics::set_isSPARC(bool isSPARC) { isSPARC_ = isSPARC; }
99
100void TargetCharacteristics::set_areSubnormalsFlushedToZero(bool yes) {
101 areSubnormalsFlushedToZero_ = yes;
102}
103
104// Check if a given real kind has flushing control.
105bool TargetCharacteristics::hasSubnormalFlushingControl(int kind) const {
106 CHECK(kind > 0 && kind <= maxKind);
107 CHECK(CanSupportType(TypeCategory::Real, kind));
108 return hasSubnormalFlushingControl_[kind];
109}
110
111// Check if any or all real kinds have flushing control.
112bool TargetCharacteristics::hasSubnormalFlushingControl(bool any) const {
113 for (int kind{1}; kind <= maxKind; ++kind) {
114 if (CanSupportType(TypeCategory::Real, kind) &&
115 hasSubnormalFlushingControl_[kind] == any) {
116 return any;
117 }
118 }
119 return !any;
120}
121
122void TargetCharacteristics::set_hasSubnormalFlushingControl(
123 int kind, bool yes) {
124 CHECK(kind > 0 && kind <= maxKind);
125 hasSubnormalFlushingControl_[kind] = yes;
126}
127
128// Check if a given real kind has (nonstandard) ieee_denorm exception control.
129bool TargetCharacteristics::hasSubnormalExceptionSupport(int kind) const {
130 CHECK(kind > 0 && kind <= maxKind);
131 CHECK(CanSupportType(TypeCategory::Real, kind));
132 return hasSubnormalExceptionSupport_[kind];
133}
134
135// Check if all real kinds have support for the ieee_denorm exception.
136bool TargetCharacteristics::hasSubnormalExceptionSupport() const {
137 for (int kind{1}; kind <= maxKind; ++kind) {
138 if (CanSupportType(TypeCategory::Real, kind) &&
139 !hasSubnormalExceptionSupport_[kind]) {
140 return false;
141 }
142 }
143 return true;
144}
145
146void TargetCharacteristics::set_hasSubnormalExceptionSupport(
147 int kind, bool yes) {
148 CHECK(kind > 0 && kind <= maxKind);
149 hasSubnormalExceptionSupport_[kind] = yes;
150}
151
152void TargetCharacteristics::set_roundingMode(Rounding rounding) {
153 roundingMode_ = rounding;
154}
155
156// SELECTED_INT_KIND() -- F'2018 16.9.169
157// and SELECTED_UNSIGNED_KIND() extension (same results)
158class SelectedIntKindVisitor {
159public:
160 SelectedIntKindVisitor(
161 const TargetCharacteristics &targetCharacteristics, std::int64_t p)
162 : targetCharacteristics_{targetCharacteristics}, precision_{p} {}
163 using Result = std::optional<int>;
164 using Types = IntegerTypes;
165 template <typename T> Result Test() const {
166 if (Scalar<T>::RANGE >= precision_ &&
167 targetCharacteristics_.IsTypeEnabled(T::category, T::kind)) {
168 return T::kind;
169 } else {
170 return std::nullopt;
171 }
172 }
173
174private:
175 const TargetCharacteristics &targetCharacteristics_;
176 std::int64_t precision_;
177};
178
179int TargetCharacteristics::SelectedIntKind(std::int64_t precision) const {
180 if (auto kind{
181 common::SearchTypes(SelectedIntKindVisitor{*this, precision})}) {
182 return *kind;
183 } else {
184 return -1;
185 }
186}
187
188// SELECTED_LOGICAL_KIND() -- F'2023 16.9.182
189class SelectedLogicalKindVisitor {
190public:
191 SelectedLogicalKindVisitor(
192 const TargetCharacteristics &targetCharacteristics, std::int64_t bits)
193 : targetCharacteristics_{targetCharacteristics}, bits_{bits} {}
194 using Result = std::optional<int>;
195 using Types = LogicalTypes;
196 template <typename T> Result Test() const {
197 if (Scalar<T>::bits >= bits_ &&
198 targetCharacteristics_.IsTypeEnabled(T::category, T::kind)) {
199 return T::kind;
200 } else {
201 return std::nullopt;
202 }
203 }
204
205private:
206 const TargetCharacteristics &targetCharacteristics_;
207 std::int64_t bits_;
208};
209
210int TargetCharacteristics::SelectedLogicalKind(std::int64_t bits) const {
211 if (auto kind{common::SearchTypes(SelectedLogicalKindVisitor{*this, bits})}) {
212 return *kind;
213 } else {
214 return -1;
215 }
216}
217
218// SELECTED_REAL_KIND() -- F'2018 16.9.170
219class SelectedRealKindVisitor {
220public:
221 SelectedRealKindVisitor(const TargetCharacteristics &targetCharacteristics,
222 std::int64_t p, std::int64_t r)
223 : targetCharacteristics_{targetCharacteristics}, precision_{p}, range_{
224 r} {}
225 using Result = std::optional<int>;
226 using Types = RealTypes;
227 template <typename T> Result Test() const {
228 if (Scalar<T>::PRECISION >= precision_ && Scalar<T>::RANGE >= range_ &&
229 targetCharacteristics_.IsTypeEnabled(T::category, T::kind)) {
230 return {T::kind};
231 } else {
232 return std::nullopt;
233 }
234 }
235
236private:
237 const TargetCharacteristics &targetCharacteristics_;
238 std::int64_t precision_, range_;
239};
240
241int TargetCharacteristics::SelectedRealKind(
242 std::int64_t precision, std::int64_t range, std::int64_t radix) const {
243 if (radix != 2) {
244 return -5;
245 }
246 if (auto kind{common::SearchTypes(
247 SelectedRealKindVisitor{*this, precision, range})}) {
248 return *kind;
249 }
250 // No kind has both sufficient precision and sufficient range.
251 // The negative return value encodes whether any kinds exist that
252 // could satisfy either constraint independently.
253 bool pOK{common::SearchTypes(SelectedRealKindVisitor{*this, precision, 0})};
254 bool rOK{common::SearchTypes(SelectedRealKindVisitor{*this, 0, range})};
255 if (pOK) {
256 if (rOK) {
257 return -4;
258 } else {
259 return -2;
260 }
261 } else {
262 if (rOK) {
263 return -1;
264 } else {
265 return -3;
266 }
267 }
268}
269
270} // namespace Fortran::evaluate
271

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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