Skip to content

Commit e3d6a3a

Browse files
authored
[flang][runtime] Support non contiguous array in Finalize/Initialize (#67295)
Finalize/Initialize may be called on non contiguous arrays when dealing with INTENT(OUT) dummies or non contiguous LHS. Update the related element access to use indices instead of assuming contiguity and manually computing the byte offset. Also, the descriptor passed to parent type final routines should be set to the parent type, otherwise descriptor.IsContiguous() may wrongfully return true when finalizing parent components. Create a pointer to the parent component when recursing in Finalize.
1 parent 6f4ed39 commit e3d6a3a

File tree

2 files changed

+56
-34
lines changed

2 files changed

+56
-34
lines changed

flang/include/flang/Runtime/descriptor.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,13 @@ class Descriptor {
250250
return OffsetElement<A>(SubscriptsToByteOffset(subscript));
251251
}
252252

253+
template <typename A>
254+
RT_API_ATTRS A *ElementComponent(
255+
const SubscriptValue subscript[], std::size_t componentOffset) const {
256+
return OffsetElement<A>(
257+
SubscriptsToByteOffset(subscript) + componentOffset);
258+
}
259+
253260
template <typename A>
254261
RT_API_ATTRS A *ZeroBasedIndexedElement(std::size_t n) const {
255262
SubscriptValue at[maxRank];

flang/runtime/derived.cpp

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,20 @@ int Initialize(const Descriptor &instance, const typeInfo::DerivedType &derived,
1919
Terminator &terminator, bool hasStat, const Descriptor *errMsg) {
2020
const Descriptor &componentDesc{derived.component()};
2121
std::size_t elements{instance.Elements()};
22-
std::size_t byteStride{instance.ElementBytes()};
2322
int stat{StatOk};
2423
// Initialize data components in each element; the per-element iterations
2524
// constitute the inner loops, not the outer ones
2625
std::size_t myComponents{componentDesc.Elements()};
2726
for (std::size_t k{0}; k < myComponents; ++k) {
2827
const auto &comp{
2928
*componentDesc.ZeroBasedIndexedElement<typeInfo::Component>(k)};
29+
SubscriptValue at[maxRank];
30+
instance.GetLowerBounds(at);
3031
if (comp.genre() == typeInfo::Component::Genre::Allocatable ||
3132
comp.genre() == typeInfo::Component::Genre::Automatic) {
32-
for (std::size_t j{0}; j < elements; ++j) {
33-
Descriptor &allocDesc{*instance.OffsetElement<Descriptor>(
34-
j * byteStride + comp.offset())};
33+
for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
34+
Descriptor &allocDesc{
35+
*instance.ElementComponent<Descriptor>(at, comp.offset())};
3536
comp.EstablishDescriptor(allocDesc, instance, terminator);
3637
allocDesc.raw().attribute = CFI_attribute_allocatable;
3738
if (comp.genre() == typeInfo::Component::Genre::Automatic) {
@@ -55,17 +56,17 @@ int Initialize(const Descriptor &instance, const typeInfo::DerivedType &derived,
5556
// Explicit initialization of data pointers and
5657
// non-allocatable non-automatic components
5758
std::size_t bytes{comp.SizeInBytes(instance)};
58-
for (std::size_t j{0}; j < elements; ++j) {
59-
char *ptr{instance.ZeroBasedIndexedElement<char>(j) + comp.offset()};
59+
for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
60+
char *ptr{instance.ElementComponent<char>(at, comp.offset())};
6061
std::memcpy(ptr, init, bytes);
6162
}
6263
} else if (comp.genre() == typeInfo::Component::Genre::Pointer) {
6364
// Data pointers without explicit initialization are established
6465
// so that they are valid right-hand side targets of pointer
6566
// assignment statements.
66-
for (std::size_t j{0}; j < elements; ++j) {
67-
Descriptor &ptrDesc{*instance.OffsetElement<Descriptor>(
68-
j * byteStride + comp.offset())};
67+
for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
68+
Descriptor &ptrDesc{
69+
*instance.ElementComponent<Descriptor>(at, comp.offset())};
6970
comp.EstablishDescriptor(ptrDesc, instance, terminator);
7071
ptrDesc.raw().attribute = CFI_attribute_pointer;
7172
}
@@ -85,10 +86,10 @@ int Initialize(const Descriptor &instance, const typeInfo::DerivedType &derived,
8586
StaticDescriptor<maxRank, true, 0> staticDescriptor;
8687
Descriptor &compDesc{staticDescriptor.descriptor()};
8788
const typeInfo::DerivedType &compType{*comp.derivedType()};
88-
for (std::size_t j{0}; j < elements; ++j) {
89+
for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
8990
compDesc.Establish(compType,
90-
instance.OffsetElement<char>(j * byteStride + comp.offset()),
91-
comp.rank(), extent);
91+
instance.ElementComponent<char>(at, comp.offset()), comp.rank(),
92+
extent);
9293
stat = Initialize(compDesc, compType, terminator, hasStat, errMsg);
9394
if (stat != StatOk) {
9495
break;
@@ -102,9 +103,11 @@ int Initialize(const Descriptor &instance, const typeInfo::DerivedType &derived,
102103
for (std::size_t k{0}; k < myProcPtrs; ++k) {
103104
const auto &comp{
104105
*procPtrDesc.ZeroBasedIndexedElement<typeInfo::ProcPtrComponent>(k)};
105-
for (std::size_t j{0}; j < elements; ++j) {
106-
auto &pptr{*instance.OffsetElement<typeInfo::ProcedurePointer>(
107-
j * byteStride + comp.offset)};
106+
SubscriptValue at[maxRank];
107+
instance.GetLowerBounds(at);
108+
for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
109+
auto &pptr{*instance.ElementComponent<typeInfo::ProcedurePointer>(
110+
at, comp.offset)};
108111
pptr = comp.procInitialization;
109112
}
110113
}
@@ -129,24 +132,26 @@ static void CallFinalSubroutine(const Descriptor &descriptor,
129132
const typeInfo::DerivedType &derived, Terminator *terminator) {
130133
if (const auto *special{FindFinal(derived, descriptor.rank())}) {
131134
if (special->which() == typeInfo::SpecialBinding::Which::ElementalFinal) {
132-
std::size_t byteStride{descriptor.ElementBytes()};
133135
std::size_t elements{descriptor.Elements()};
136+
SubscriptValue at[maxRank];
137+
descriptor.GetLowerBounds(at);
134138
if (special->IsArgDescriptor(0)) {
135139
StaticDescriptor<maxRank, true, 8 /*?*/> statDesc;
136140
Descriptor &elemDesc{statDesc.descriptor()};
137141
elemDesc = descriptor;
138142
elemDesc.raw().attribute = CFI_attribute_pointer;
139143
elemDesc.raw().rank = 0;
140144
auto *p{special->GetProc<void (*)(const Descriptor &)>()};
141-
for (std::size_t j{0}; j < elements; ++j) {
142-
elemDesc.set_base_addr(
143-
descriptor.OffsetElement<char>(j * byteStride));
145+
for (std::size_t j{0}; j++ < elements;
146+
descriptor.IncrementSubscripts(at)) {
147+
elemDesc.set_base_addr(descriptor.Element<char>(at));
144148
p(elemDesc);
145149
}
146150
} else {
147151
auto *p{special->GetProc<void (*)(char *)>()};
148-
for (std::size_t j{0}; j < elements; ++j) {
149-
p(descriptor.OffsetElement<char>(j * byteStride));
152+
for (std::size_t j{0}; j++ < elements;
153+
descriptor.IncrementSubscripts(at)) {
154+
p(descriptor.Element<char>(at));
150155
}
151156
}
152157
} else {
@@ -202,20 +207,22 @@ void Finalize(const Descriptor &descriptor,
202207
const Descriptor &componentDesc{derived.component()};
203208
std::size_t myComponents{componentDesc.Elements()};
204209
std::size_t elements{descriptor.Elements()};
205-
std::size_t byteStride{descriptor.ElementBytes()};
206210
for (auto k{recurse ? std::size_t{1}
207211
/* skip first component, it's the parent */
208212
: 0};
209213
k < myComponents; ++k) {
210214
const auto &comp{
211215
*componentDesc.ZeroBasedIndexedElement<typeInfo::Component>(k)};
216+
SubscriptValue at[maxRank];
217+
descriptor.GetLowerBounds(at);
212218
if (comp.genre() == typeInfo::Component::Genre::Allocatable &&
213219
comp.category() == TypeCategory::Derived) {
214220
// Component may be polymorphic or unlimited polymorphic. Need to use the
215221
// dynamic type to check whether finalization is needed.
216-
for (std::size_t j{0}; j < elements; ++j) {
217-
const Descriptor &compDesc{*descriptor.OffsetElement<Descriptor>(
218-
j * byteStride + comp.offset())};
222+
for (std::size_t j{0}; j++ < elements;
223+
descriptor.IncrementSubscripts(at)) {
224+
const Descriptor &compDesc{
225+
*descriptor.ElementComponent<Descriptor>(at, comp.offset())};
219226
if (compDesc.IsAllocated()) {
220227
if (const DescriptorAddendum * addendum{compDesc.Addendum()}) {
221228
if (const typeInfo::DerivedType *
@@ -231,9 +238,10 @@ void Finalize(const Descriptor &descriptor,
231238
comp.genre() == typeInfo::Component::Genre::Automatic) {
232239
if (const typeInfo::DerivedType * compType{comp.derivedType()}) {
233240
if (!compType->noFinalizationNeeded()) {
234-
for (std::size_t j{0}; j < elements; ++j) {
235-
const Descriptor &compDesc{*descriptor.OffsetElement<Descriptor>(
236-
j * byteStride + comp.offset())};
241+
for (std::size_t j{0}; j++ < elements;
242+
descriptor.IncrementSubscripts(at)) {
243+
const Descriptor &compDesc{
244+
*descriptor.ElementComponent<Descriptor>(at, comp.offset())};
237245
if (compDesc.IsAllocated()) {
238246
Finalize(compDesc, *compType, terminator);
239247
}
@@ -253,16 +261,23 @@ void Finalize(const Descriptor &descriptor,
253261
StaticDescriptor<maxRank, true, 0> staticDescriptor;
254262
Descriptor &compDesc{staticDescriptor.descriptor()};
255263
const typeInfo::DerivedType &compType{*comp.derivedType()};
256-
for (std::size_t j{0}; j < elements; ++j) {
264+
for (std::size_t j{0}; j++ < elements;
265+
descriptor.IncrementSubscripts(at)) {
257266
compDesc.Establish(compType,
258-
descriptor.OffsetElement<char>(j * byteStride + comp.offset()),
259-
comp.rank(), extent);
267+
descriptor.ElementComponent<char>(at, comp.offset()), comp.rank(),
268+
extent);
260269
Finalize(compDesc, compType, terminator);
261270
}
262271
}
263272
}
264273
if (recurse) {
265-
Finalize(descriptor, *parentType, terminator);
274+
StaticDescriptor<maxRank, true, 8 /*?*/> statDesc;
275+
Descriptor &tmpDesc{statDesc.descriptor()};
276+
tmpDesc = descriptor;
277+
tmpDesc.raw().attribute = CFI_attribute_pointer;
278+
tmpDesc.Addendum()->set_derivedType(parentType);
279+
tmpDesc.raw().elem_len = parentType->sizeInBytes();
280+
Finalize(tmpDesc, *parentType, terminator);
266281
}
267282
}
268283

@@ -289,8 +304,8 @@ void Destroy(const Descriptor &descriptor, bool finalize,
289304
if (comp.genre() == typeInfo::Component::Genre::Allocatable ||
290305
comp.genre() == typeInfo::Component::Genre::Automatic) {
291306
for (std::size_t j{0}; j < elements; ++j) {
292-
Descriptor *d{reinterpret_cast<Descriptor *>(
293-
descriptor.Element<char>(at) + comp.offset())};
307+
Descriptor *d{
308+
descriptor.ElementComponent<Descriptor>(at, comp.offset())};
294309
d->Deallocate();
295310
descriptor.IncrementSubscripts(at);
296311
}

0 commit comments

Comments
 (0)