[Hexagon] Use llvm::children (NFC)
[llvm-project.git] / flang / lib / Evaluate / target.cpp
blob1e2cf6b0d298d4dda6f8fb66c0fe2eb5133f7c3b
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 //===----------------------------------------------------------------------===//
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) {
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;
34 std::size_t align{byteSize};
35 if (category == TypeCategory::Complex) {
36 byteSize = 2 * byteSize;
38 EnableType(category, kind, byteSize, align);
41 }};
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);
65 return true;
66 } else {
67 return false;
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];
82 } else {
83 return 0;
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];
91 } else {
92 return 0;
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 {
117 public:
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;
132 private:
133 const TargetCharacteristics &targetCharacteristics_;
134 std::int64_t precision_;
137 int 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;
146 // SELECTED_LOGICAL_KIND() -- F'2023 16.9.182
147 class SelectedLogicalKindVisitor {
148 public:
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;
163 private:
164 const TargetCharacteristics &targetCharacteristics_;
165 std::int64_t bits_;
168 int TargetCharacteristics::SelectedLogicalKind(std::int64_t bits) const {
169 if (auto kind{common::SearchTypes(SelectedLogicalKindVisitor{*this, bits})}) {
170 return *kind;
171 } else {
172 return -1;
176 // SELECTED_REAL_KIND() -- F'2018 16.9.170
177 class SelectedRealKindVisitor {
178 public:
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;
194 private:
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 {
201 if (radix != 2) {
202 return -5;
204 if (auto kind{common::SearchTypes(
205 SelectedRealKindVisitor{*this, precision, range})}) {
206 return *kind;
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;
219 } else {
220 if (rOK) {
221 return -1;
222 } else {
223 return -3;
228 } // namespace Fortran::evaluate