comp.lang.ada
 help / color / mirror / Atom feed
From: NCOHEN@IBM.COM ("Norman H. Cohen")
Subject: aliases/function return values
Date: 30 Aug 90 13:29:18 GMT	[thread overview]
Message-ID: <9008301534.AA11465@ajpo.sei.cmu.edu> (raw)

Jerry Callen presents a program that fails if the statement

   return Global;

is implemented by returning a REFERENCE to Global, rather than a COPY of
Global, to the caller.  He then writes:

 >I would LIKE to think that objects may be returned by reference;
 >otherwise potentially large objects would have to be copied.
 >I would call the program above erroneous, since it is dependent upon
 >the mechanism used for parameter passing and value return.

David Rosenfeld, referring to a compiler that "returns by reference,"
responds:

 >It's a compiler bug, but a useful one, and there are no ACVC's which
 >test for it; so it's probably best to assume that the program
 >is erroneous.

Hold on there!  It is not up to the programmer or the implementer to
decide what will be considered erroneous.  Dependence on the PARAMETER-
passing mechanism is erroneous because the reference manual explicitly
states (6.2(7)):  "For a parameter whose type is an array, record, or
task type, an implementation may likewise achieve the above effects by
copy, as for scalar types....  Alternatively, an implementation may
achieve these effects by reference....  The execution of a program is
erroneous if its effect depends on which mechanism is selected by the
implementation."

No such choice is given for passing function results back to the caller.
Indeed, RM 5.8(6) specifically states, "For the execution of a return
statement, the expression (if any) is first evaluated," and 5.8(5)
states, "The value of the expression determines the result returned by
the function."

The offenses constituting erroneous execution are specifically
enumerated in the RM (with a few more added by AIs).  Dependence on
the result-passing mechanism is not such an offense.

Switching my perspective from language legalities to implementation
practicalities, the implementation approach suggested by Callen will
very rarely be useful.  Most of the time, the expression in a return
statement does not name a global variable, but a variable local to the
function body, or some expression such as a catenation or aggregate.
A reference to a local variable is a pointer into the stack frame that is
about to disappear.  Indeed, in a context like

   if Array_Func_1(X) = Array_Func_2(X) then ...

the stack frame will likely be overwritten by the second function call
before the value of the first function call is dereferenced.

When the function result subtype is CONSTRAINED, the caller can determine
an appropriate destination for the function result and pass a pointer to
that destination into the function body.  The return statement is then
implemented by copying the result value into the specified destination.
In a context like

   A := Array_Func(X);

the caller can pass the address of A, so that both the return and the
assignment statement are achieved with one copy of the array value.  In
a context like

   Proc(Array_Func(X));

the caller can pass an address in the stack frame it is setting up for
the call on Proc, or the address of a temporary whose address will be
placed in that stack frame.

Usually, the only useful context for a call on a function with an
UNCONSTRAINED array result is as a parameter to some outer subprogram
call--as in

   Text_IO.Put(Text_IO.Name(Input_File));

--or as the initial value of an allocator--as in

   String_Pointer := new String'(Text_IO.Name(Input_File));

--or as PART of the initial value for an allocator for some record type
with discriminants--as in

   String_List :=
      new List_Node_Type'
         (Size => Name_Length,
          Text => Text_IO.Name(Input_File),
          Link => String_List);

In the first case, the implementation can allocate temporary space at the
other end of storage, construct the result value there (entailing a copy
of each array component value), and return a pointer into that space for
the caller to use in passing the array by reference to the outer
subprogram call.  (It is essential that the caller free the allocated
space at the end of the outer call, to prevent storage leaks.)  In the
second case, the implementation can proceed as above, but allocating
space for the function result directly in the collection for the
corresponding access type, so that a pointer to the allocated space can
be used directly as the value of the allocator.  The third case is more
complicated.  The most reasonable approach is probably for the function
to yield a pointer as in the first case and for evaluation
of the record aggregate to perform the check that the array pointed to
satisfies the index constraint for the corresponding array component,
then copy the array yet again, then free the temporary copy constructed
by the function.  The extra copy can be avoided by passing the address
and index constraint of the record component, which is allocated on the
basis of discriminant values before the function is called, and
proceeding as in the constrained case; however, potential benefits may be
outweighed by the cost and complexity of adding an extra implicit
parameter to functions with unconstrained array-type results, indicating
which return method to use for a given call.

Callen bemoans the fact that potentially large objects have to be
copied, but returning an array as a function result is inherently a
potentially expensive operation, especially if the result subtype is
unconstrained.  Fortunately, clever compilation can keep the cost
reasonable in most cases, while preserving the semantics required by the
reference manual.

Norman H. Cohen

             reply	other threads:[~1990-08-30 13:29 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1990-08-30 13:29 "Norman H. Cohen" [this message]
  -- strict thread matches above, loose matches on Subject: below --
1990-08-28 15:14 aliases/function return values Jerry Callen
1990-08-29 15:12 ` davidr
1990-09-07 19:00   ` Robert I. Eachus
1990-09-07 20:42     ` Michael Feldman
1990-08-31  0:47 ` Charles H. Sampson
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox