From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,984d3d7860d7c8c X-Google-Attributes: gid103376,public Path: controlnews3.google.com!news2.google.com!fu-berlin.de!uni-berlin.de!not-for-mail From: "Nick Roberts" Newsgroups: comp.lang.ada Subject: Re: Where are returned values stored? Date: Sun, 30 May 2004 22:17:17 +0100 Message-ID: <2hv1auFhi91aU1@uni-berlin.de> References: <75s9b0pgo91ctvlm5op2rcql82t9ip4me2@4ax.com> <1dptc.49822$tb4.1731604@news20.bellglobal.com> X-Trace: news.uni-berlin.de xBMBBO6ybCYwxH6S05dUGgE0dQMXy9vl7DUs/hqRoG5unI16U= X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1409 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1409 Xref: controlnews3.google.com comp.lang.ada:940 Date: 2004-05-30T22:17:17+01:00 List-Id: "Warren W. Gay VE3WWG" wrote in message news:1dptc.49822$tb4.1731604@news20.bellglobal.com... > If you're worried about the inefficiency of copying data around, > then I would suggest that the above advice is good. Leave that > up to the compiler/machine team. > > If you really must know more than that, then you'll need to look > at the assembler output, but maybe the following explanation > might save you from bothering/worrying about it: > > Conceptually, there is _no_ reason a compiler _must_ copy a > return value. Consider a function like: > > function Foo return String is > I : Integer := 23; > S : String(1..3) := "Bar"; > X : Natural := 0; > begin > ... > return S; > end; > > To return S, all the compiler needs to do is to extend the > caller's stack frame to claim all the storage up to and > including S (I and S assuming sequential assignment), at > the point when Foo returns (return effectively does > reclaim the storage used for X however). > > Then the calling code can reference S as if it were a > local variable. The space used for I is > wasted at this point, but temporarily, who cares? > > Once the compiler knows that the caller's use of the returned > value S is no longer required, the stack frame can be shrunk > back to the original size that it had prior to calling Foo. > > Is this done? Is it done by GNAT? I have no idea, but I > suspect that this is done in some places, some of the time, > by some compilers. Perhaps, someone in this group > can confirm/debunk this idea. I don't think any compiler does quite as you suggest, Warren, but many do something similar: they allocate two stacks to each task, usually called the 'primary' and 'secondary' stacks; the primary stack is used as the normal stack, and the secondary is used exclusively for returning indefinite function results. In the common case of all the return statements in a function being of the form 'return S' (as above), S will be allocated on the secondary stack. When Foo returns, its stack frame (containing I and X plus some other stuff) is deallocated (from the primary stack), but the calling code can access the result (S) on the secondary stack. When the calling code has finished with S, it deallocates it (from the secondary stack). In the general case (return statements returning expressions), an anonymous intermediate variable is used instead of S, and it is this anonymous variable that is allocated on the secondary stack. You can see that this works fine for recursive functions, although a rewriting (so it is no longer recursive) of a recursive function that returns an indefinite type may produce a much more memory-efficient algorithm. The only problem is that you have two stacks per task. That can add up to a lot of stacks for some programs! One optimisation is to determine if a task will never call a function that needs a secondary stack, and eliminate the (allocation of) the secondary stack for such tasks; if my memory serves me, I think I've heard of an Ada compiler that does this optimisation. I think all those compilers which don't use a secondary stack use the heap (or some storage pool) instead. -- Nick Roberts