Skip to content

Commit 33959da

Browse files
committed
[flang] Restructure runtime to avoid recursion
Recursion, both direct and indirect, prevents accurate stack size calculation at link time for GPU device code. Restructure these recursive (often mutually so) routines in the Fortran runtime with new implementations based on an iterative work queue with suspendable/resumable work tickets: Assign, Initialize, initializeClone, Finalize, and Destroy. Default derived type I/O is also recursive, but already disabled. It can be added to this new framework later if the overall approach succeeds. Note that derived type FINAL subroutine calls, defined assignments, and defined I/O procedures all perform callbacks into user code, which may well reenter the runtime library. This kind of recursion is not handled by this change, although it may be possible to do so in the future using thread-local work queues. (Relanding this patch after reverting initial attempt due to some test failures that needed some time to analyze and fix.) Fixes #142481.
1 parent 52a6492 commit 33959da

32 files changed

+2350
-1172
lines changed

flang-rt/include/flang-rt/runtime/environment.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ struct ExecutionEnvironment {
6464
bool defaultUTF8{false}; // DEFAULT_UTF8
6565
bool checkPointerDeallocation{true}; // FORT_CHECK_POINTER_DEALLOCATION
6666

67+
enum InternalDebugging { WorkQueue = 1 };
68+
int internalDebugging{0}; // FLANG_RT_DEBUG
69+
6770
// CUDA related variables
6871
std::size_t cudaStackLimit{0}; // ACC_OFFLOAD_STACK_SIZE
6972
bool cudaDeviceIsManaged{false}; // NV_CUDAFOR_DEVICE_IS_MANAGED

flang-rt/include/flang-rt/runtime/stat.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class Terminator;
2424
enum Stat {
2525
StatOk = 0, // required to be zero by Fortran
2626

27-
// Interoperable STAT= codes
27+
// Interoperable STAT= codes (>= 11)
2828
StatBaseNull = CFI_ERROR_BASE_ADDR_NULL,
2929
StatBaseNotNull = CFI_ERROR_BASE_ADDR_NOT_NULL,
3030
StatInvalidElemLen = CFI_INVALID_ELEM_LEN,
@@ -36,7 +36,7 @@ enum Stat {
3636
StatMemAllocation = CFI_ERROR_MEM_ALLOCATION,
3737
StatOutOfBounds = CFI_ERROR_OUT_OF_BOUNDS,
3838

39-
// Standard STAT= values
39+
// Standard STAT= values (>= 101)
4040
StatFailedImage = FORTRAN_RUNTIME_STAT_FAILED_IMAGE,
4141
StatLocked = FORTRAN_RUNTIME_STAT_LOCKED,
4242
StatLockedOtherImage = FORTRAN_RUNTIME_STAT_LOCKED_OTHER_IMAGE,
@@ -49,10 +49,14 @@ enum Stat {
4949
// Additional "processor-defined" STAT= values
5050
StatInvalidArgumentNumber = FORTRAN_RUNTIME_STAT_INVALID_ARG_NUMBER,
5151
StatMissingArgument = FORTRAN_RUNTIME_STAT_MISSING_ARG,
52-
StatValueTooShort = FORTRAN_RUNTIME_STAT_VALUE_TOO_SHORT,
52+
StatValueTooShort = FORTRAN_RUNTIME_STAT_VALUE_TOO_SHORT, // -1
5353
StatMoveAllocSameAllocatable =
5454
FORTRAN_RUNTIME_STAT_MOVE_ALLOC_SAME_ALLOCATABLE,
5555
StatBadPointerDeallocation = FORTRAN_RUNTIME_STAT_BAD_POINTER_DEALLOCATION,
56+
57+
// Dummy status for work queue continuation, declared here to perhaps
58+
// avoid collisions
59+
StatContinue = 201
5660
};
5761

5862
RT_API_ATTRS const char *StatErrorString(int);

flang-rt/include/flang-rt/runtime/type-info.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,17 @@ class SpecialBinding {
154154
RT_API_ATTRS bool IsArgDescriptor(int zeroBasedArg) const {
155155
return (isArgDescriptorSet_ >> zeroBasedArg) & 1;
156156
}
157-
RT_API_ATTRS bool isTypeBound() const { return isTypeBound_; }
157+
RT_API_ATTRS bool IsTypeBound() const { return isTypeBound_ != 0; }
158158
RT_API_ATTRS bool IsArgContiguous(int zeroBasedArg) const {
159159
return (isArgContiguousSet_ >> zeroBasedArg) & 1;
160160
}
161-
template <typename PROC> RT_API_ATTRS PROC GetProc() const {
162-
return reinterpret_cast<PROC>(proc_);
161+
template <typename PROC>
162+
RT_API_ATTRS PROC GetProc(const Binding *bindings = nullptr) const {
163+
if (bindings && isTypeBound_ > 0) {
164+
return reinterpret_cast<PROC>(bindings[isTypeBound_ - 1].proc);
165+
} else {
166+
return reinterpret_cast<PROC>(proc_);
167+
}
163168
}
164169

165170
FILE *Dump(FILE *) const;
@@ -193,6 +198,8 @@ class SpecialBinding {
193198
// When false, the defined I/O subroutine must have been
194199
// called via a generic interface, not a generic TBP.
195200
std::uint8_t isArgDescriptorSet_{0};
201+
// When a special binding is type-bound, this is its binding's index (plus 1,
202+
// so that 0 signifies that it's not type-bound).
196203
std::uint8_t isTypeBound_{0};
197204
// True when a FINAL subroutine has a dummy argument that is an array that
198205
// is CONTIGUOUS or neither assumed-rank nor assumed-shape.
@@ -240,6 +247,7 @@ class DerivedType {
240247
RT_API_ATTRS bool noFinalizationNeeded() const {
241248
return noFinalizationNeeded_;
242249
}
250+
RT_API_ATTRS bool noDefinedAssignment() const { return noDefinedAssignment_; }
243251

244252
RT_API_ATTRS std::size_t LenParameters() const {
245253
return lenParameterKind().Elements();
@@ -322,6 +330,7 @@ class DerivedType {
322330
bool noInitializationNeeded_{false};
323331
bool noDestructionNeeded_{false};
324332
bool noFinalizationNeeded_{false};
333+
bool noDefinedAssignment_{false};
325334
};
326335

327336
} // namespace Fortran::runtime::typeInfo

0 commit comments

Comments
 (0)