Skip to content

Commit 8fc045e

Browse files
authored
[flang][runtime] Accept 128-bit integer SHIFT values in CSHIFT/EOSHIFT (#75246)
It would surprise me if this case ever arose outside a couple of tests in llvm-test-suite/Fortran/gfortran/regression (namely cshift_large_1.f90 and eoshift_large_1.f90), but now at least those tests will pass.
1 parent befdfae commit 8fc045e

File tree

2 files changed

+48
-14
lines changed

2 files changed

+48
-14
lines changed

flang/runtime/tools.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,31 @@ static inline RT_API_ATTRS std::int64_t GetInt64(
9494
}
9595
}
9696

97+
static inline RT_API_ATTRS std::optional<std::int64_t> GetInt64Safe(
98+
const char *p, std::size_t bytes, Terminator &terminator) {
99+
switch (bytes) {
100+
case 1:
101+
return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 1> *>(p);
102+
case 2:
103+
return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 2> *>(p);
104+
case 4:
105+
return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 4> *>(p);
106+
case 8:
107+
return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 8> *>(p);
108+
case 16: {
109+
using Int128 = CppTypeFor<TypeCategory::Integer, 16>;
110+
auto n{*reinterpret_cast<const Int128 *>(p)};
111+
std::int64_t result = n;
112+
if (result == n) {
113+
return result;
114+
}
115+
return std::nullopt;
116+
}
117+
default:
118+
terminator.Crash("GetInt64Safe: no case for %zd bytes", bytes);
119+
}
120+
}
121+
97122
template <typename INT>
98123
inline RT_API_ATTRS bool SetInteger(INT &x, int kind, std::int64_t value) {
99124
switch (kind) {

flang/runtime/transformational.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@ class ShiftControl {
5252
}
5353
}
5454
}
55+
} else if (auto count{GetInt64Safe(
56+
shift_.OffsetElement<char>(), shiftElemLen_, terminator_)}) {
57+
shiftCount_ = *count;
5558
} else {
56-
shiftCount_ =
57-
GetInt64(shift_.OffsetElement<char>(), shiftElemLen_, terminator_);
59+
terminator_.Crash("%s: SHIFT= value exceeds 64 bits", which);
5860
}
5961
}
6062
RT_API_ATTRS SubscriptValue GetShift(const SubscriptValue resultAt[]) const {
@@ -67,8 +69,10 @@ class ShiftControl {
6769
++k;
6870
}
6971
}
70-
return GetInt64(
71-
shift_.Element<char>(shiftAt), shiftElemLen_, terminator_);
72+
auto count{GetInt64Safe(
73+
shift_.Element<char>(shiftAt), shiftElemLen_, terminator_)};
74+
RUNTIME_CHECK(terminator_, count.has_value());
75+
return *count;
7276
} else {
7377
return shiftCount_; // invariant count extracted in Init()
7478
}
@@ -719,12 +723,15 @@ void RTDEF(Reshape)(Descriptor &result, const Descriptor &source,
719723
std::size_t resultElements{1};
720724
SubscriptValue shapeSubscript{shape.GetDimension(0).LowerBound()};
721725
for (int j{0}; j < resultRank; ++j, ++shapeSubscript) {
722-
resultExtent[j] = GetInt64(
723-
shape.Element<char>(&shapeSubscript), shapeElementBytes, terminator);
724-
if (resultExtent[j] < 0) {
726+
auto extent{GetInt64Safe(
727+
shape.Element<char>(&shapeSubscript), shapeElementBytes, terminator)};
728+
if (!extent) {
729+
terminator.Crash("RESHAPE: value of SHAPE(%d) exceeds 64 bits", j + 1);
730+
} else if (*extent < 0) {
725731
terminator.Crash("RESHAPE: bad value for SHAPE(%d)=%jd", j + 1,
726-
static_cast<std::intmax_t>(resultExtent[j]));
732+
static_cast<std::intmax_t>(*extent));
727733
}
734+
resultExtent[j] = *extent;
728735
resultElements *= resultExtent[j];
729736
}
730737

@@ -762,14 +769,16 @@ void RTDEF(Reshape)(Descriptor &result, const Descriptor &source,
762769
SubscriptValue orderSubscript{order->GetDimension(0).LowerBound()};
763770
std::size_t orderElementBytes{order->ElementBytes()};
764771
for (SubscriptValue j{0}; j < resultRank; ++j, ++orderSubscript) {
765-
auto k{GetInt64(order->Element<char>(&orderSubscript), orderElementBytes,
766-
terminator)};
767-
if (k < 1 || k > resultRank || ((values >> k) & 1)) {
772+
auto k{GetInt64Safe(order->Element<char>(&orderSubscript),
773+
orderElementBytes, terminator)};
774+
if (!k) {
775+
terminator.Crash("RESHAPE: ORDER element value exceeds 64 bits");
776+
} else if (*k < 1 || *k > resultRank || ((values >> *k) & 1)) {
768777
terminator.Crash("RESHAPE: bad value for ORDER element (%jd)",
769-
static_cast<std::intmax_t>(k));
778+
static_cast<std::intmax_t>(*k));
770779
}
771-
values |= std::uint64_t{1} << k;
772-
dimOrder[j] = k - 1;
780+
values |= std::uint64_t{1} << *k;
781+
dimOrder[j] = *k - 1;
773782
}
774783
} else {
775784
for (int j{0}; j < resultRank; ++j) {

0 commit comments

Comments
 (0)