1 //===-- runtime/ragged.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 //===----------------------------------------------------------------------===//
9 #include "flang/Runtime/ragged.h"
13 namespace Fortran::runtime
{
15 inline RT_API_ATTRS
bool isIndirection(const RaggedArrayHeader
*const header
) {
16 return header
->flags
& 1;
19 inline RT_API_ATTRS
std::size_t rank(const RaggedArrayHeader
*const header
) {
20 return header
->flags
>> 1;
23 RT_API_ATTRS RaggedArrayHeader
*RaggedArrayAllocate(RaggedArrayHeader
*header
,
24 bool isHeader
, std::int64_t rank
, std::int64_t elementSize
,
25 std::int64_t *extentVector
) {
28 for (std::int64_t counter
{0}; counter
< rank
; ++counter
) {
29 size
*= extentVector
[counter
];
34 header
->flags
= (rank
<< 1) | isHeader
;
35 header
->extentPointer
= extentVector
;
37 elementSize
= sizeof(RaggedArrayHeader
);
39 Terminator terminator
{__FILE__
, __LINE__
};
40 std::size_t bytes
{static_cast<std::size_t>(elementSize
* size
)};
41 header
->bufferPointer
= AllocateMemoryOrCrash(terminator
, bytes
);
42 if (header
->bufferPointer
) {
43 std::memset(header
->bufferPointer
, 0, bytes
);
51 // Deallocate a ragged array from the heap.
52 RT_API_ATTRS
void RaggedArrayDeallocate(RaggedArrayHeader
*raggedArrayHeader
) {
53 if (raggedArrayHeader
) {
54 if (std::size_t end
{rank(raggedArrayHeader
)}) {
55 if (isIndirection(raggedArrayHeader
)) {
56 std::size_t linearExtent
{1u};
57 for (std::size_t counter
{0u}; counter
< end
&& linearExtent
> 0;
59 linearExtent
*= raggedArrayHeader
->extentPointer
[counter
];
61 for (std::size_t counter
{0u}; counter
< linearExtent
; ++counter
) {
62 RaggedArrayDeallocate(&static_cast<RaggedArrayHeader
*>(
63 raggedArrayHeader
->bufferPointer
)[counter
]);
66 std::free(raggedArrayHeader
->bufferPointer
);
67 std::free(raggedArrayHeader
->extentPointer
);
68 raggedArrayHeader
->flags
= 0u;
74 void *RTDEF(RaggedArrayAllocate
)(void *header
, bool isHeader
, std::int64_t rank
,
75 std::int64_t elementSize
, std::int64_t *extentVector
) {
76 auto *result
= RaggedArrayAllocate(static_cast<RaggedArrayHeader
*>(header
),
77 isHeader
, rank
, elementSize
, extentVector
);
78 return static_cast<void *>(result
);
81 void RTDEF(RaggedArrayDeallocate
)(void *raggedArrayHeader
) {
82 RaggedArrayDeallocate(static_cast<RaggedArrayHeader
*>(raggedArrayHeader
));
85 } // namespace Fortran::runtime