236
|
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
|
|
14 namespace Fortran::evaluate {
|
|
15
|
|
16 Rounding TargetCharacteristics::defaultRounding;
|
|
17
|
|
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;
|
|
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
|
|
53 bool TargetCharacteristics::CanSupportType(
|
|
54 TypeCategory category, std::int64_t kind) {
|
|
55 return IsValidKindOfIntrinsicType(category, kind);
|
|
56 }
|
|
57
|
|
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;
|
|
68 }
|
|
69 }
|
|
70
|
|
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;
|
|
75 }
|
|
76 }
|
|
77
|
|
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;
|
|
84 }
|
|
85 }
|
|
86
|
|
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;
|
|
93 }
|
|
94 }
|
|
95
|
|
96 bool TargetCharacteristics::IsTypeEnabled(
|
|
97 common::TypeCategory category, std::int64_t kind) const {
|
|
98 return GetAlignment(category, kind) > 0;
|
|
99 }
|
|
100
|
|
101 void TargetCharacteristics::set_isBigEndian(bool isBig) {
|
|
102 isBigEndian_ = isBig;
|
|
103 }
|
|
104
|
|
105 void TargetCharacteristics::set_areSubnormalsFlushedToZero(bool yes) {
|
|
106 areSubnormalsFlushedToZero_ = yes;
|
|
107 }
|
|
108
|
|
109 void TargetCharacteristics::set_roundingMode(Rounding rounding) {
|
|
110 roundingMode_ = rounding;
|
|
111 }
|
|
112
|
|
113 // SELECTED_INT_KIND() -- F'2018 16.9.169
|
|
114 class SelectedIntKindVisitor {
|
|
115 public:
|
|
116 SelectedIntKindVisitor(
|
|
117 const TargetCharacteristics &targetCharacteristics, std::int64_t p)
|
|
118 : targetCharacteristics_{targetCharacteristics}, precision_{p} {}
|
|
119 using Result = std::optional<int>;
|
|
120 using Types = IntegerTypes;
|
|
121 template <typename T> Result Test() const {
|
|
122 if (Scalar<T>::RANGE >= precision_ &&
|
|
123 targetCharacteristics_.IsTypeEnabled(T::category, T::kind)) {
|
|
124 return T::kind;
|
|
125 } else {
|
|
126 return std::nullopt;
|
|
127 }
|
|
128 }
|
|
129
|
|
130 private:
|
|
131 const TargetCharacteristics &targetCharacteristics_;
|
|
132 std::int64_t precision_;
|
|
133 };
|
|
134
|
|
135 int TargetCharacteristics::SelectedIntKind(std::int64_t precision) const {
|
|
136 if (auto kind{
|
|
137 common::SearchTypes(SelectedIntKindVisitor{*this, precision})}) {
|
|
138 return *kind;
|
|
139 } else {
|
|
140 return -1;
|
|
141 }
|
|
142 }
|
|
143
|
|
144 // SELECTED_REAL_KIND() -- F'2018 16.9.170
|
|
145 class SelectedRealKindVisitor {
|
|
146 public:
|
|
147 SelectedRealKindVisitor(const TargetCharacteristics &targetCharacteristics,
|
|
148 std::int64_t p, std::int64_t r)
|
|
149 : targetCharacteristics_{targetCharacteristics}, precision_{p}, range_{
|
|
150 r} {}
|
|
151 using Result = std::optional<int>;
|
|
152 using Types = RealTypes;
|
|
153 template <typename T> Result Test() const {
|
|
154 if (Scalar<T>::PRECISION >= precision_ && Scalar<T>::RANGE >= range_ &&
|
|
155 targetCharacteristics_.IsTypeEnabled(T::category, T::kind)) {
|
|
156 return {T::kind};
|
|
157 } else {
|
|
158 return std::nullopt;
|
|
159 }
|
|
160 }
|
|
161
|
|
162 private:
|
|
163 const TargetCharacteristics &targetCharacteristics_;
|
|
164 std::int64_t precision_, range_;
|
|
165 };
|
|
166
|
|
167 int TargetCharacteristics::SelectedRealKind(
|
|
168 std::int64_t precision, std::int64_t range, std::int64_t radix) const {
|
|
169 if (radix != 2) {
|
|
170 return -5;
|
|
171 }
|
|
172 if (auto kind{common::SearchTypes(
|
|
173 SelectedRealKindVisitor{*this, precision, range})}) {
|
|
174 return *kind;
|
|
175 }
|
|
176 // No kind has both sufficient precision and sufficient range.
|
|
177 // The negative return value encodes whether any kinds exist that
|
|
178 // could satisfy either constraint independently.
|
|
179 bool pOK{common::SearchTypes(SelectedRealKindVisitor{*this, precision, 0})};
|
|
180 bool rOK{common::SearchTypes(SelectedRealKindVisitor{*this, 0, range})};
|
|
181 if (pOK) {
|
|
182 if (rOK) {
|
|
183 return -4;
|
|
184 } else {
|
|
185 return -2;
|
|
186 }
|
|
187 } else {
|
|
188 if (rOK) {
|
|
189 return -1;
|
|
190 } else {
|
|
191 return -3;
|
|
192 }
|
|
193 }
|
|
194 }
|
|
195
|
|
196 } // namespace Fortran::evaluate
|