// A ragged array header block.
// The header block is used to create the "array of arrays" ragged data
-// structure. It contains a boolean value to indicate if the header points to
+// structure. It contains a pair in `flags` to indicate if the header points to
// an array of headers (isIndirection) or data elements and the rank of the
-// pointed-to array in an integer value. The rank is the length of the extents
-// vector accessed through `extentPointer`. The `bufferPointer` is overloaded
+// pointed-to array. The rank is the length of the extents vector accessed
+// through `extentPointer`. The `bufferPointer` is overloaded
// and is null, points to an array of headers (isIndirection), or data.
// By default, a header is set to zero, which is its unused state.
// The layout of a ragged buffer header is mirrored in the compiler.
struct RaggedArrayHeader {
- bool indirection{false};
- std::uint8_t rank;
- void *bufferPointer{nullptr};
- std::int64_t *extentPointer{nullptr};
-
- bool isIndirection() { return indirection; }
- std::uint8_t getRank() { return rank; }
+ std::uint64_t flags;
+ void *bufferPointer;
+ std::int64_t *extentPointer;
};
RaggedArrayHeader *RaggedArrayAllocate(
mlir::TupleType
fir::factory::getRaggedArrayHeaderType(fir::FirOpBuilder &builder) {
- mlir::IntegerType i1Ty = builder.getIntegerType(1);
- mlir::IntegerType i8Ty = builder.getIntegerType(8);
mlir::IntegerType i64Ty = builder.getIntegerType(64);
auto arrTy = fir::SequenceType::get(builder.getIntegerType(8), 1);
auto buffTy = fir::HeapType::get(arrTy);
auto extTy = fir::SequenceType::get(i64Ty, 1);
auto shTy = fir::HeapType::get(extTy);
- return mlir::TupleType::get(builder.getContext(), {i1Ty, i8Ty, buffTy, shTy});
+ return mlir::TupleType::get(builder.getContext(), {i64Ty, buffTy, shTy});
}
auto extentTy = fir::SequenceType::get(shape, i64Ty);
auto refTy = fir::ReferenceType::get(i64Ty);
// Position of the bufferPointer in the header struct.
- auto two = builder.createIntegerConstant(loc, i32Ty, 2);
+ auto one = builder.createIntegerConstant(loc, i32Ty, 1);
auto eleTy = fir::unwrapSequenceType(fir::unwrapRefType(header.getType()));
auto ptrTy = builder.getRefType(eleTy.cast<mlir::TupleType>().getType(1));
- auto ptr = builder.create<fir::CoordinateOp>(loc, ptrTy, header, two);
+ auto ptr = builder.create<fir::CoordinateOp>(loc, ptrTy, header, one);
auto heap = builder.create<fir::LoadOp>(loc, ptr);
auto cmp = builder.genIsNull(loc, heap);
builder.genIfThen(loc, cmp)
namespace Fortran::runtime {
+inline bool isIndirection(const RaggedArrayHeader *const header) {
+ return header->flags & 1;
+}
+
+inline std::size_t rank(const RaggedArrayHeader *const header) {
+ return header->flags >> 1;
+}
+
RaggedArrayHeader *RaggedArrayAllocate(RaggedArrayHeader *header, bool isHeader,
std::int64_t rank, std::int64_t elementSize, std::int64_t *extentVector) {
if (header && rank) {
return nullptr;
}
}
- header->indirection = isHeader;
- header->rank = rank;
+ header->flags = (rank << 1) | isHeader;
header->extentPointer = extentVector;
if (isHeader) {
- header->bufferPointer = std::malloc(sizeof(RaggedArrayHeader) * size);
+ header->bufferPointer = std::calloc(sizeof(RaggedArrayHeader), size);
} else {
header->bufferPointer =
static_cast<void *>(std::calloc(elementSize, size));
// Deallocate a ragged array from the heap.
void RaggedArrayDeallocate(RaggedArrayHeader *raggedArrayHeader) {
if (raggedArrayHeader) {
- if (std::size_t end{raggedArrayHeader->getRank()}) {
- if (raggedArrayHeader->isIndirection()) {
+ if (std::size_t end{rank(raggedArrayHeader)}) {
+ if (isIndirection(raggedArrayHeader)) {
std::size_t linearExtent{1u};
for (std::size_t counter{0u}; counter < end && linearExtent > 0;
++counter) {
}
std::free(raggedArrayHeader->bufferPointer);
std::free(raggedArrayHeader->extentPointer);
- raggedArrayHeader->indirection = false;
- raggedArrayHeader->rank = 0u;
+ raggedArrayHeader->flags = 0u;
}
}
}
EXPECT_EQ(extents, ret->extentPointer);
EXPECT_EQ(10, ret->extentPointer[0]);
EXPECT_EQ(100, ret->extentPointer[1]);
- EXPECT_EQ(rank, ret->getRank());
- EXPECT_FALSE(ret->isIndirection());
+ EXPECT_EQ(rank, ret->flags >> 1);
+ EXPECT_FALSE(ret->flags & 1);
_FortranARaggedArrayDeallocate(ret);
- EXPECT_EQ(0u, ret->getRank());
- EXPECT_FALSE(ret->isIndirection());
+ EXPECT_EQ(0u, ret->flags);
}