-
Notifications
You must be signed in to change notification settings - Fork 167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to handle deallocatable function return values #494
Comments
There are two cases:
|
Another open question is exactly how the ASR should look like for |
Should |
What about DerivedTypes (struct)? Those can have allocatable components, but the derived type itself can live on a stack. The components however must be deallocated when the derived type goes out of scope. So it seems we need to call a "Destructor" on all variables that go out of scope. Integers/Real obviously do not need it, but derived types, lists, etc. need it. As well as user classes with a finalizer / destructor. |
We can have a Destructor (or Destruct) ASR node, and it would call a "destructor" for all the variables (so list would free its elements, a derived type would deallocate all its components). |
I would say the answer is that ASR could allow both, that is, if ImplicitDeallocate or Destructor does not need to be called (such as for an integer, non-allocatable return value), then one can either do directly |
By this you mean deep copy the data from |
Yes, deep copy. Note however, that the transformation |
I see. Here's my opinion,
|
Yes, deallocation should only happen at all exit points of the functions, so at the end of a function and before every return. We don't have exceptions in ASR, so that's currently the only way the function can exit. Our ASR optimizers can do all kinds of optimizations, similar to the LLVM's mem2reg pass. The main question really is, what is required of the frontend to do, and what the "canonical" ASR way should be (checked by verify). It should not require any complicated rewriting by the frontend, just enough to get "canonical", and ASR should be explicit about the deallocation, so that it's easy to generate code from it. |
For this I would suggest the following,
|
This naturally leads to: https://gitlab.com/lfortran/lfortran/-/issues/693 |
Makes sense to me. ASR pass can do everything that you mentioned in the above Gitlab issue. We should do this one by one. |
An example:
Here, we need to deallocate the temporary result of the function
g()
.One general way is to assign the result of a function to a temporary variable first (either always do it, or only when the result is allocatable, or possibly an array). Like this:
It's a question whether we should do this for all functions all the time, or only for functions that return allocatable arrays/lists.
For arrays, this approach also allows to write an ASR transformation that transforms functions into subroutines:
Which makes it easy on the LLVM backend to implement.
The text was updated successfully, but these errors were encountered: