F2003 Finalization -- progress and problems
Daniel Kraft
d@domob.eu
Tue Jun 10 18:48:00 GMT 2008
Tobias Burnus wrote:
>> After finishing the code, I want to write some little documentation
>> about how finalization works and is implemented if you want so in the
>> future everyone has it easier to work on it (now that I still know how
>> it works...), if you point me where to write this.
> GREAT idea! I think gfc-internals.texi is the best place, see:
> http://gcc.gnu.org/onlinedocs/gfc-internals/
> (An alternative would be the Wiki, but I think gfc-internals.texi is
> better.)
I also like the TexInfo better, so we've agreed here ;) But this will
have to wait until the code is ready for check-in I think, then we can
discuss this again.
>> c) what exactly does that "specification expression in scoping unit"
>> mean? But otherwise, this sounds similar to b).
>
> "If a specification expression in a scoping unit references a function,
> the result is finalized before execution of the first executable
> statement in the scoping unit."
>
> "7.1.6 Specification expression"
> "R729 specification-expr is scalar-int-expr"
> "C710 (R729) The scalar-int-expr shall be a restricted expression."
> "A *restricted expression* is an expression [...], and where any final
> subroutine that is invoked is *pure*."
But then nothing needs to be finalized if the result has to be
integer... Or did I miss something?
>> b) results of functions and structure-constructors after they have been
>> used: I'm not sure how this could be done in resolution-phase (without
>> "rewriting" the code and introducing temporaries), but maybe in trans
>> this will be easier. Any ideas and tipps?
> I don't quite understand what with "after they have been used" is meant
> - nor can I find it in the standard. (Currently, I have no opinion
> whether on should use trans*.c or resolve*.c.)
In the subsection "When finalization occurs":
...
"If an executable construct references a function, the result is
finalized after execution of the innermost executable construct
containing the reference.
"If an executable construct references a structure constructor, the
entity created by the structure constructor is finalized after execution
of the innermost executable construct containing the reference."
My problem here is that if we have something like:
x = foobar (funct (x)),
where funct returns a finalizable entity. Then we need to generate code
like that:
temp = funct (x)
x = foobar (temp)
finalize (temp)
If I did understand the code correctly. Are such nested constructs
flattened in trans like the above or is this passed down like it is to
the middle-end and converted there? In the latter case, we would need
to split it and introduce temporaries manually during either resolution
or trans to handle the finalization (in that case when both are equally
possible, I'd prefer resolution as working on the gfortran-trees is
probably easier as more information is available). Or do you have
better ideas?
I think it should not be too hard to do those splitting of expressions,
although it surely makes the code uglier, but I don't see any other way
to handle the finalization-requirements of the standard.
>> e) intrinsic assignment: for ordinary assignments this is handled
> What do you mean by ordinary assignments? If you mean a simple
Right, I mean assignment not in WHERE/FORALL; I believe somewhere in the
code this is called "resolve_ordinary_assignment" ;)
> type(t) :: x, y
> y = x
>
> then this is an intrinsic assignment unless you have "assignment(=)"
> anywhere. Using
>
> interface assignment(=)
> subroutine assign_t(x,y)
>
> the finalization happens automatically as the LHS argument matches a
> INTENT(OUT) in assign_t.
Ah, yes! But I have to make sure the LHS is not finalized twice in this
case; the old patch *should* already handle this, but at the moment
there's no test for this. That will be changed of course.
>> WHERE (arr == 2)
>> arr = 5
>> END WHERE
>>
>> Should this finalize the whole masked arr at once or each element before
>> it is overwritten? Can there be a similar unclarity for FORALL?
> I really dislike WHERE as it is (at least to me) a bit intransparent
> what happens there. Maybe something to ask at lang.comp.fortran.
I myself don't have much experience with WHERE, only looked at it
briefly once. From a programmer's point of view, it sounds nice to me
(or, better, like a neat feature that let's you express some thing in an
elegant way; but it might be something that's never really needed
anyway, I don't know). But I believe this will be some mess implementing...
> I read this as follows, but now guarantees that I interpret the standard
> correctly.
>
> {
> tmp = function(array)
> finalize(array(mask))
> array(mask) = tmp(mask)
> }
That makes sense, so finalizing the masked array.
> FORALL: I have not yet fully understand how this should be handled, but
> note:
>
> "C738 (R756) Any procedure referenced in a forall-body-construct,
> including one referenced by a defined operation, assignment, or
> *finalization*, shall be a *pure* procedure."
>
> And for PURE procedures:
>
> "C1273 Any procedure referenced *in a pure subprogram*, including one
> referenced via a defined operation, assignment, or *finalization*, shall
> be *pure*."
Do you mean I have to check on finalization if the only calls are pure
procedures and output an error otherwise? Hm... It gets even nicer...
>> I was more thinking about the expression "x + foobar (x)" in itself
>> rather than the I/O; that's because foobar (x) changes the value of x
>> and I wanted to know whether it was defined or not if the first x had
>> the earlier or later value.
>
> In other words: The program is invalid and the compiler can do anything.
> (The saying goes this includes starting WW3.)
Thanks, that's what I was looking for.
>>> + TYPE(yes_t), ALLOCATABLE :: alloc_vector(:)
>>> + ! alloc_vector is deallocated automatically here
>>> + ! XXX: Or not?
>>
>> BTW, I was a bit surprised when I first read about this nice feature
>> of automatic deallocation (and automatic allocation the like)--Fortran
>> isn't C++ :D
> That is one of the nice features of Fortran: With allocatable, one
> cannot have loose memory. If one tries to allocate an already allocated
> variable, one gets an error; and when the variable goes out of scope, it
> is automatically deallocated.
This is implemented now, I did this other than everything else so far in
trans as I believe this automatic deallocation is added there.
How about ALLOCATABLE components? I saw in the code there that all
those are recursively deallocated during deallocation of an entity. So
this means we have to finalize those, too, before they get deallocated,
right? But maybe this isn't much effort now I've already some
experience (and code) for doing the finalization in trans.
The problem with this is just that I need the original gfc_expr for
this, as I have to have access to the derived-type structure and similar
for access to the finalizer-procedures and the like. And this lets me
reuse the existing finalization-code :D
Cheers,
Daniel
--
Done: Bar-Sam-Val-Wiz, Dwa-Elf-Hum-Orc, Cha-Law, Fem-Mal
Underway: Ran-Gno-Neu-Fem
To go: Arc-Cav-Hea-Kni-Mon-Pri-Rog-Tou
More information about the Fortran
mailing list