annotate flang/lib/Evaluate/target.cpp @ 248:cfe92afade2b

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 16 Aug 2023 18:23:14 +0900
parents c4bab56944e8
children 1f2b6ac9f198
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
236
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
1 //===-- lib/Semantics/target.cpp ------------------------------------------===//
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
2 //
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
6 //
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
8
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
9 #include "flang/Evaluate/target.h"
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
10 #include "flang/Common/template.h"
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
11 #include "flang/Evaluate/common.h"
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
12 #include "flang/Evaluate/type.h"
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
13
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
14 namespace Fortran::evaluate {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
15
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
16 Rounding TargetCharacteristics::defaultRounding;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
17
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
18 TargetCharacteristics::TargetCharacteristics() {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
19 auto enableCategoryKinds{[this](TypeCategory category) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
20 for (int kind{0}; kind < maxKind; ++kind) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
21 if (CanSupportType(category, kind)) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
22 auto byteSize{static_cast<std::size_t>(kind)};
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
23 if (category == TypeCategory::Real ||
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
24 category == TypeCategory::Complex) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
25 if (kind == 3) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
26 // non-IEEE 16-bit format (truncated 32-bit)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
27 byteSize = 2;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
28 } else if (kind == 10) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
29 // x87 floating-point
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
30 // Follow gcc precedent for "long double"
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
31 byteSize = 16;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
32 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
33 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
34 std::size_t align{byteSize};
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
35 if (category == TypeCategory::Complex) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
36 byteSize = 2 * byteSize;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
37 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
38 EnableType(category, kind, byteSize, align);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
39 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
40 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
41 }};
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
42 enableCategoryKinds(TypeCategory::Integer);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
43 enableCategoryKinds(TypeCategory::Real);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
44 enableCategoryKinds(TypeCategory::Complex);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
45 enableCategoryKinds(TypeCategory::Character);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
46 enableCategoryKinds(TypeCategory::Logical);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
47
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
48 isBigEndian_ = !isHostLittleEndian;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
49
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
50 areSubnormalsFlushedToZero_ = false;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
51 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
52
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
53 bool TargetCharacteristics::CanSupportType(
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
54 TypeCategory category, std::int64_t kind) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
55 return IsValidKindOfIntrinsicType(category, kind);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
56 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
57
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
58 bool TargetCharacteristics::EnableType(common::TypeCategory category,
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
59 std::int64_t kind, std::size_t byteSize, std::size_t align) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
60 if (CanSupportType(category, kind)) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
61 byteSize_[static_cast<int>(category)][kind] = byteSize;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
62 align_[static_cast<int>(category)][kind] = align;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
63 maxByteSize_ = std::max(maxByteSize_, byteSize);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
64 maxAlignment_ = std::max(maxAlignment_, align);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
65 return true;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
66 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
67 return false;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
68 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
69 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
70
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
71 void TargetCharacteristics::DisableType(
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
72 common::TypeCategory category, std::int64_t kind) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
73 if (kind >= 0 && kind < maxKind) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
74 align_[static_cast<int>(category)][kind] = 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
75 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
76 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
77
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
78 std::size_t TargetCharacteristics::GetByteSize(
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
79 common::TypeCategory category, std::int64_t kind) const {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
80 if (kind >= 0 && kind < maxKind) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
81 return byteSize_[static_cast<int>(category)][kind];
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
82 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
83 return 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
84 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
85 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
86
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
87 std::size_t TargetCharacteristics::GetAlignment(
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
88 common::TypeCategory category, std::int64_t kind) const {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
89 if (kind >= 0 && kind < maxKind) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
90 return align_[static_cast<int>(category)][kind];
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
91 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
92 return 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
93 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
94 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
95
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
96 bool TargetCharacteristics::IsTypeEnabled(
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
97 common::TypeCategory category, std::int64_t kind) const {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
98 return GetAlignment(category, kind) > 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
99 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
100
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
101 void TargetCharacteristics::set_isBigEndian(bool isBig) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
102 isBigEndian_ = isBig;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
103 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
104
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
105 void TargetCharacteristics::set_areSubnormalsFlushedToZero(bool yes) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
106 areSubnormalsFlushedToZero_ = yes;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
107 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
108
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
109 void TargetCharacteristics::set_roundingMode(Rounding rounding) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
110 roundingMode_ = rounding;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
111 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
112
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
113 // SELECTED_INT_KIND() -- F'2018 16.9.169
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
114 class SelectedIntKindVisitor {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
115 public:
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
116 SelectedIntKindVisitor(
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
117 const TargetCharacteristics &targetCharacteristics, std::int64_t p)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
118 : targetCharacteristics_{targetCharacteristics}, precision_{p} {}
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
119 using Result = std::optional<int>;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
120 using Types = IntegerTypes;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
121 template <typename T> Result Test() const {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
122 if (Scalar<T>::RANGE >= precision_ &&
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
123 targetCharacteristics_.IsTypeEnabled(T::category, T::kind)) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
124 return T::kind;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
125 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
126 return std::nullopt;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
127 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
128 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
129
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
130 private:
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
131 const TargetCharacteristics &targetCharacteristics_;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
132 std::int64_t precision_;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
133 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
134
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
135 int TargetCharacteristics::SelectedIntKind(std::int64_t precision) const {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
136 if (auto kind{
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
137 common::SearchTypes(SelectedIntKindVisitor{*this, precision})}) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
138 return *kind;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
139 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
140 return -1;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
141 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
142 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
143
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
144 // SELECTED_REAL_KIND() -- F'2018 16.9.170
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
145 class SelectedRealKindVisitor {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
146 public:
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
147 SelectedRealKindVisitor(const TargetCharacteristics &targetCharacteristics,
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
148 std::int64_t p, std::int64_t r)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
149 : targetCharacteristics_{targetCharacteristics}, precision_{p}, range_{
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
150 r} {}
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
151 using Result = std::optional<int>;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
152 using Types = RealTypes;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
153 template <typename T> Result Test() const {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
154 if (Scalar<T>::PRECISION >= precision_ && Scalar<T>::RANGE >= range_ &&
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
155 targetCharacteristics_.IsTypeEnabled(T::category, T::kind)) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
156 return {T::kind};
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
157 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
158 return std::nullopt;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
159 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
160 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
161
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
162 private:
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
163 const TargetCharacteristics &targetCharacteristics_;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
164 std::int64_t precision_, range_;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
165 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
166
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
167 int TargetCharacteristics::SelectedRealKind(
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
168 std::int64_t precision, std::int64_t range, std::int64_t radix) const {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
169 if (radix != 2) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
170 return -5;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
171 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
172 if (auto kind{common::SearchTypes(
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
173 SelectedRealKindVisitor{*this, precision, range})}) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
174 return *kind;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
175 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
176 // No kind has both sufficient precision and sufficient range.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
177 // The negative return value encodes whether any kinds exist that
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
178 // could satisfy either constraint independently.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
179 bool pOK{common::SearchTypes(SelectedRealKindVisitor{*this, precision, 0})};
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
180 bool rOK{common::SearchTypes(SelectedRealKindVisitor{*this, 0, range})};
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
181 if (pOK) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
182 if (rOK) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
183 return -4;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
184 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
185 return -2;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
186 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
187 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
188 if (rOK) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
189 return -1;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
190 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
191 return -3;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
192 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
193 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
194 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
195
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
196 } // namespace Fortran::evaluate