1 //===-- runtime/tools.cpp -------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 #include "terminator.h"
16 namespace Fortran::runtime
{
18 RT_OFFLOAD_API_GROUP_BEGIN
20 RT_API_ATTRS
std::size_t TrimTrailingSpaces(const char *s
, std::size_t n
) {
21 while (n
> 0 && s
[n
- 1] == ' ') {
27 RT_API_ATTRS OwningPtr
<char> SaveDefaultCharacter(
28 const char *s
, std::size_t length
, const Terminator
&terminator
) {
30 auto *p
{static_cast<char *>(AllocateMemoryOrCrash(terminator
, length
+ 1))};
31 std::memcpy(p
, s
, length
);
33 return OwningPtr
<char>{p
};
35 return OwningPtr
<char>{};
39 static RT_API_ATTRS
bool CaseInsensitiveMatch(
40 const char *value
, std::size_t length
, const char *possibility
) {
41 for (; length
-- > 0; ++possibility
) {
43 if (ch
>= 'a' && ch
<= 'z') {
46 if (*possibility
!= ch
) {
47 if (*possibility
!= '\0' || ch
!= ' ') {
50 // Ignore trailing blanks (12.5.6.2 p1)
51 while (length
-- > 0) {
52 if (*value
++ != ' ') {
59 return *possibility
== '\0';
62 RT_API_ATTRS
int IdentifyValue(
63 const char *value
, std::size_t length
, const char *possibilities
[]) {
65 for (int j
{0}; possibilities
[j
]; ++j
) {
66 if (CaseInsensitiveMatch(value
, length
, possibilities
[j
])) {
74 RT_API_ATTRS
void ToFortranDefaultCharacter(
75 char *to
, std::size_t toLength
, const char *from
) {
76 std::size_t len
{Fortran::runtime::strlen(from
)};
78 std::memcpy(to
, from
, len
);
79 std::memset(to
+ len
, ' ', toLength
- len
);
81 std::memcpy(to
, from
, toLength
);
85 RT_API_ATTRS
void CheckConformability(const Descriptor
&to
, const Descriptor
&x
,
86 Terminator
&terminator
, const char *funcName
, const char *toName
,
89 return; // scalar conforms with anything
92 if (x
.rank() != rank
) {
94 "Incompatible array arguments to %s: %s has rank %d but %s has rank %d",
95 funcName
, toName
, rank
, xName
, x
.rank());
97 for (int j
{0}; j
< rank
; ++j
) {
98 auto toExtent
{static_cast<std::int64_t>(to
.GetDimension(j
).Extent())};
99 auto xExtent
{static_cast<std::int64_t>(x
.GetDimension(j
).Extent())};
100 if (xExtent
!= toExtent
) {
101 terminator
.Crash("Incompatible array arguments to %s: dimension %d of "
102 "%s has extent %" PRId64
" but %s has extent %" PRId64
,
103 funcName
, j
+ 1, toName
, toExtent
, xName
, xExtent
);
109 RT_API_ATTRS
void CheckIntegerKind(
110 Terminator
&terminator
, int kind
, const char *intrinsic
) {
111 if (kind
< 1 || kind
> 16 || (kind
& (kind
- 1)) != 0) {
112 terminator
.Crash("not yet implemented: INTEGER(KIND=%d) in %s intrinsic",
117 RT_API_ATTRS
void ShallowCopyDiscontiguousToDiscontiguous(
118 const Descriptor
&to
, const Descriptor
&from
) {
119 SubscriptValue toAt
[maxRank
], fromAt
[maxRank
];
120 to
.GetLowerBounds(toAt
);
121 from
.GetLowerBounds(fromAt
);
122 std::size_t elementBytes
{to
.ElementBytes()};
123 for (std::size_t n
{to
.Elements()}; n
-- > 0;
124 to
.IncrementSubscripts(toAt
), from
.IncrementSubscripts(fromAt
)) {
126 to
.Element
<char>(toAt
), from
.Element
<char>(fromAt
), elementBytes
);
130 RT_API_ATTRS
void ShallowCopyDiscontiguousToContiguous(
131 const Descriptor
&to
, const Descriptor
&from
) {
132 char *toAt
{to
.OffsetElement()};
133 SubscriptValue fromAt
[maxRank
];
134 from
.GetLowerBounds(fromAt
);
135 std::size_t elementBytes
{to
.ElementBytes()};
136 for (std::size_t n
{to
.Elements()}; n
-- > 0;
137 toAt
+= elementBytes
, from
.IncrementSubscripts(fromAt
)) {
138 std::memcpy(toAt
, from
.Element
<char>(fromAt
), elementBytes
);
142 RT_API_ATTRS
void ShallowCopyContiguousToDiscontiguous(
143 const Descriptor
&to
, const Descriptor
&from
) {
144 SubscriptValue toAt
[maxRank
];
145 to
.GetLowerBounds(toAt
);
146 char *fromAt
{from
.OffsetElement()};
147 std::size_t elementBytes
{to
.ElementBytes()};
148 for (std::size_t n
{to
.Elements()}; n
-- > 0;
149 to
.IncrementSubscripts(toAt
), fromAt
+= elementBytes
) {
150 std::memcpy(to
.Element
<char>(toAt
), fromAt
, elementBytes
);
154 RT_API_ATTRS
void ShallowCopy(const Descriptor
&to
, const Descriptor
&from
,
155 bool toIsContiguous
, bool fromIsContiguous
) {
156 if (toIsContiguous
) {
157 if (fromIsContiguous
) {
158 std::memcpy(to
.OffsetElement(), from
.OffsetElement(),
159 to
.Elements() * to
.ElementBytes());
161 ShallowCopyDiscontiguousToContiguous(to
, from
);
164 if (fromIsContiguous
) {
165 ShallowCopyContiguousToDiscontiguous(to
, from
);
167 ShallowCopyDiscontiguousToDiscontiguous(to
, from
);
172 RT_API_ATTRS
void ShallowCopy(const Descriptor
&to
, const Descriptor
&from
) {
173 ShallowCopy(to
, from
, to
.IsContiguous(), from
.IsContiguous());
176 RT_OFFLOAD_API_GROUP_END
177 } // namespace Fortran::runtime