* Pass by reference @ 2004-04-08 14:52 Dan McLeran 2004-04-08 18:21 ` Martin Krischik ` (4 more replies) 0 siblings, 5 replies; 35+ messages in thread From: Dan McLeran @ 2004-04-08 14:52 UTC (permalink / raw) I am investigating using Ada for a project at work and I have a question I hope someone can answer. If I am interpreting the RM section 6.2 correctly, an array of elementary types does not meet the criteria of a by-reference type. But, when looking at the disassembly, it seems that passing an array of elementary types to a function as an in-mode parameter is passing by reference. Does this mean that an array of elementary types is an unspecfied type? A 2nd part to my question is: Does Ada automatically pass tagged types by reference no matter what mode the parameter is specfied (in, in out, or out)? The language RM 6.2 seems to suggest this is so. If so, does this mean that there is no way to pass a tagged type by value? I believe C# works this way without programmer intervention. I am using Aonix's ObjectAda V7.2.2, by the way. I have not tried GNAT for comparison. Thanks, Dan McLeran ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-08 14:52 Pass by reference Dan McLeran @ 2004-04-08 18:21 ` Martin Krischik 2004-04-09 12:53 ` Dan McLeran 2004-04-08 19:04 ` Jim Rogers ` (3 subsequent siblings) 4 siblings, 1 reply; 35+ messages in thread From: Martin Krischik @ 2004-04-08 18:21 UTC (permalink / raw) Dan McLeran wrote: > I am investigating using Ada for a project at work and I have a > question I hope someone can answer. If I am interpreting the RM > section 6.2 correctly, an array of elementary types does not meet the > criteria of a by-reference type. But, when looking at the disassembly, > it seems that passing an array of elementary types to a function as an > in-mode parameter is passing by reference. Does this mean that an > array of elementary types is an unspecfied type? Good Ada compiler will do what is best. So "array (1 .. 2) of Character" is likely to be passed by value while "array (1 .. 10_000) of Integer" is probably passed by reference. And some Ada compilers might even use pass by register. This might sound strange to a C, C++ or C# programmer. Like giving up control. There are things humans can do better then computers but there are also things computers can do better then humans - and counting is is among those. The compiler knows much better how many registers are available, how large the type is, how long it takes to copy and so on. You say what you need (in, out, in out) and the compiler will choose the optimal way to fullfill you which. > A 2nd part to my question is: Does Ada automatically pass tagged types > by reference no matter what mode the parameter is specfied (in, in > out, or out)? The language RM 6.2 seems to suggest this is so. If so, > does this mean that there is no way to pass a tagged type by value? I > believe C# works this way without programmer intervention. They are in deed allways passed by reference. That's done to enable dispaching. Rermember: all native procedures of a tagged type are "virtual". Two ways around that behavior: 1st: for any tagged type X there is indefinite type X'Class. X'Class is an indefinite but untagged type so RM 6.2 does not apply here. 2nt: RM 6.2 does not apply to a non native procedure. That is a procedure in another package. With Regards Martin -- mailto://krischik@users.sourceforge.net http://www.ada.krischik.com ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-08 18:21 ` Martin Krischik @ 2004-04-09 12:53 ` Dan McLeran 2004-04-13 12:42 ` Martin Krischik 0 siblings, 1 reply; 35+ messages in thread From: Dan McLeran @ 2004-04-09 12:53 UTC (permalink / raw) > Good Ada compiler will do what is best. So "array (1 .. 2) of Character" is > likely to be passed by value while "array (1 .. 10_000) of Integer" is > probably passed by reference. And some Ada compilers might even use pass by > register. Not sure what you mean by 'pass by register'. Maybe each value of a 2-element array are loaded into registers and then read by the calling function? > > This might sound strange to a C, C++ or C# programmer. Like giving up > control. There are things humans can do better then computers but there are > also things computers can do better then humans - and counting is is among > those. The compiler knows much better how many registers are available, how > large the type is, how long it takes to copy and so on. It's not too foreign of idea to me because I use a C++ library to do essentially the same thing. The Boost Call Traits Library is a template library that chooses the optimal parameter passing convention based on type. Since the C++ project I have been working on makes heavy use of templates, I am used to leaving it up to someone/something else to choose the best calling convention. > > You say what you need (in, out, in out) and the compiler will choose the > optimal way to fullfill you which. This is what I want to solidify in my brain. Alot of people posting replies seem to say that the compiler has more freedom than the RM specifies. If most Ada compilers are conforming, I would assume that the compiler only has freedom for unspecified types. By-reference and by-values types must be passed as stated in RM 6.2. > > > A 2nd part to my question is: Does Ada automatically pass tagged types > > by reference no matter what mode the parameter is specfied (in, in > > out, or out)? The language RM 6.2 seems to suggest this is so. If so, > > does this mean that there is no way to pass a tagged type by value? I > > believe C# works this way without programmer intervention. > > They are in deed allways passed by reference. That's done to enable > dispaching. Rermember: all native procedures of a tagged type are "virtual". > > Two ways around that behavior: > > 1st: for any tagged type X there is indefinite type X'Class. X'Class is an > indefinite but untagged type so RM 6.2 does not apply here. > > 2nt: RM 6.2 does not apply to a non native procedure. That is a procedure > in another package. > > With Regards > > Martin ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 12:53 ` Dan McLeran @ 2004-04-13 12:42 ` Martin Krischik 0 siblings, 0 replies; 35+ messages in thread From: Martin Krischik @ 2004-04-13 12:42 UTC (permalink / raw) Dan McLeran wrote: >> Good Ada compiler will do what is best. So "array (1 .. 2) of Character" >> is likely to be passed by value while "array (1 .. 10_000) of Integer" is >> probably passed by reference. And some Ada compilers might even use pass >> by register. > > Not sure what you mean by 'pass by register'. Maybe each value of a > 2-element array are loaded into registers and then read by the calling > function? Well on a 32bit CPU any data with 'Size <= 32 can be passed by register. But this is purly academic since AFAIK the standart x86 compiler won't do pass by register anyway. >> You say what you need (in, out, in out) and the compiler will choose the >> optimal way to fullfill you which. > > This is what I want to solidify in my brain. Alot of people posting > replies seem to say that the compiler has more freedom than the RM > specifies. If most Ada compilers are conforming, I would assume that > the compiler only has freedom for unspecified types. By-reference and > by-values types must be passed as stated in RM 6.2. True, however there is a reason why By-reference are By-reference. They yould not be anything else - otherwise dispaching would not work. With Regards Martin -- mailto://krischik@users.sourceforge.net http://www.ada.krischik.com ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-08 14:52 Pass by reference Dan McLeran 2004-04-08 18:21 ` Martin Krischik @ 2004-04-08 19:04 ` Jim Rogers 2004-04-09 3:24 ` Dan McLeran 2004-04-09 0:01 ` Stephen Leake ` (2 subsequent siblings) 4 siblings, 1 reply; 35+ messages in thread From: Jim Rogers @ 2004-04-08 19:04 UTC (permalink / raw) dan.r.mcleran@seagate.com (Dan McLeran) wrote in message news:<19b0e504.0404080652.4eab9f80@posting.google.com>... > I am investigating using Ada for a project at work and I have a > question I hope someone can answer. If I am interpreting the RM > section 6.2 correctly, an array of elementary types does not meet the > criteria of a by-reference type. But, when looking at the disassembly, > it seems that passing an array of elementary types to a function as an > in-mode parameter is passing by reference. Does this mean that an > array of elementary types is an unspecfied type? Ada provides some guidance to the compiler, but the general idea is that the compiler is free to choose the most efficient parameter passing mechanism for each instance. If you specify an parameter (of any type) as an IN parameter you will not be able to modify the array within the subprogram, no matter how the compiler chooses to pass the parameter. If you specify a parameter of any type as an OUT or IN OUT parameter you will be able to modify its value within the procedure. This is true even if the parameter is passed by value. > > A 2nd part to my question is: Does Ada automatically pass tagged types > by reference no matter what mode the parameter is specfied (in, in > out, or out)? The language RM 6.2 seems to suggest this is so. If so, > does this mean that there is no way to pass a tagged type by value? I > believe C# works this way without programmer intervention. Tagged types are typically passed by reference no matter what the parameter mode. Why do you want to specify by value if you can specify IN mode? Do you want to be able to modify the value locally in the subprogram? In Ada you do that by copying the IN value to a local variable in the subprogram. In this manner you are forcing the creation of a local copy of the value, no matter how it was passed. The Ada approach is most efficient if you only want to read, but not write to, the IN parameter. It eliminates an unnecessary copy. If you do want to read and locally modify the parameter Ada forces you to explicitly make the copy implicitly made by C#, making your code no less efficient than C# in that case. Jim Rogers ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-08 19:04 ` Jim Rogers @ 2004-04-09 3:24 ` Dan McLeran 0 siblings, 0 replies; 35+ messages in thread From: Dan McLeran @ 2004-04-09 3:24 UTC (permalink / raw) Jim, Thanks for the response. I am quite new to Ada and am trying to get my head around all of the details. You wrote: >Ada provides some guidance to the compiler, but the general idea >is that the compiler is free to choose the most efficient parameter >passing mechanism for each instance. The Language RM reads more strictly than that. When I read section 6.2: "A type is a by-copy type if it is an elementary type, or if it is a descendant of a private type whose full type is a by-copy type. A parameter of a by-copy type is passed by copy." The RM also states: "A parameter of a by-reference type is passed by reference." No ambiguity is implied here. I assume that a conforming compiler does not get to decide which way to go. Anyone else care to comment? There is one statement that leads me to believe that the answer to the by-copy or by-reference question may be ambiguous. The RM states: "For parameters of other types, it is unspecified whether the parameter is passed by copy or by reference. " It seems that an array of elementary types does not fit in with either the by-copy types or by-reference types. In this case, it seems to be up to the compiler implementation. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-08 14:52 Pass by reference Dan McLeran 2004-04-08 18:21 ` Martin Krischik 2004-04-08 19:04 ` Jim Rogers @ 2004-04-09 0:01 ` Stephen Leake 2004-04-09 12:38 ` Dan McLeran ` (2 more replies) 2004-04-09 1:15 ` Jeffrey Carter 2004-04-09 4:03 ` Steve 4 siblings, 3 replies; 35+ messages in thread From: Stephen Leake @ 2004-04-09 0:01 UTC (permalink / raw) To: comp.lang.ada dan.r.mcleran@seagate.com (Dan McLeran) writes: > I am investigating using Ada for a project at work Excellent choice :). > and I have a question I hope someone can answer. If I am > interpreting the RM section 6.2 correctly, an array of elementary > types does not meet the criteria of a by-reference type. A 'by-reference type' is simply one that is always passed by reference, never by copy. > But, when looking at the disassembly, it seems that passing an array > of elementary types to a function as an in-mode parameter is passing > by reference. Does this mean that an array of elementary types is an > unspecfied type? The compiler is always free to choose either copy or reference for passing parameters. I'm not clear what you mean by "unspecified type". Hmm, perhaps you are refering to 6.2(11): For parameters of other types, it is unspecified whether the parameter is passed by copy or by reference. Yes, an array of elementary types is an "other type" in this sense; it may be passed either by reference or copy. The compiler will choose whichever mechanism it feels is "best". > A 2nd part to my question is: Does Ada automatically pass tagged types > by reference no matter what mode the parameter is specfied (in, in > out, or out)? The language RM 6.2 seems to suggest this is so. Yes. > If so, does this mean that there is no way to pass a tagged type by > value? Yes. > I believe C# works this way without programmer intervention. Don't know. > I am using Aonix's ObjectAda V7.2.2, by the way. I have not tried > GNAT for comparison. Ok. A couple of larger questions; Why do you care whether a type is passed by copy or reference? If you are worried about time or space efficiency, specify the appropriate option to the compiler, and forget about it, until measurements of your final application show a problem. Why would you want to pass a tagged type by copy? You might want to read the Ada Rationale, and the annotated Ada Reference manual, on this topic. See http://www.adaic.com/standards/ada95.html -- -- Stephe ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 0:01 ` Stephen Leake @ 2004-04-09 12:38 ` Dan McLeran 2004-04-09 13:03 ` Dmitry A. Kazakov 2004-04-10 1:42 ` Stephen Leake 2004-04-09 12:44 ` Dan McLeran 2004-04-09 14:44 ` Simon Wright 2 siblings, 2 replies; 35+ messages in thread From: Dan McLeran @ 2004-04-09 12:38 UTC (permalink / raw) > A couple of larger questions; > > Why do you care whether a type is passed by copy or reference? I'm just trying to get more familiar with the language. I've done mostly C++ programming for the past several years and am looking at alternatives. > > If you are worried about time or space efficiency, specify the > appropriate option to the compiler, and forget about it, until > measurements of your final application show a problem. I'm not worried about it. I just want to understand all the details because I'll probably have to explain it to others. > > Why would you want to pass a tagged type by copy? I don't necessarily want to. I actually would never do this in C++, unless the class was something very small and intended to be passed by value: struct Silly { int i; }; I'm just trying to solidify the Ada language rules in my brain. > > You might want to read the Ada Rationale, and the annotated Ada > Reference manual, on this topic. See > http://www.adaic.com/standards/ada95.html Thanks for the link. I can use all the help I can get. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 12:38 ` Dan McLeran @ 2004-04-09 13:03 ` Dmitry A. Kazakov 2004-04-09 19:09 ` Dan McLeran 2004-04-11 12:43 ` Florian Weimer 2004-04-10 1:42 ` Stephen Leake 1 sibling, 2 replies; 35+ messages in thread From: Dmitry A. Kazakov @ 2004-04-09 13:03 UTC (permalink / raw) Dan McLeran wrote: > Stephen Leake wrote: >> Why would you want to pass a tagged type by copy? Because that could be a handle requiring Initialize/Adjust/Finalize. To be honest, forcing tagged types to be by-reference was probably a mistake. > I don't necessarily want to. I actually would never do this in C++, > unless the class was something very small and intended to be passed by > value: > > struct Silly > { > int i; > }; This need not to be tagged, because there is no dispatching subroutines here. A rough C++ equivalent of a tagged type is a class with virtual functions. -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 13:03 ` Dmitry A. Kazakov @ 2004-04-09 19:09 ` Dan McLeran 2004-04-10 10:49 ` Dmitry A. Kazakov 2004-04-11 12:43 ` Florian Weimer 1 sibling, 1 reply; 35+ messages in thread From: Dan McLeran @ 2004-04-09 19:09 UTC (permalink / raw) > This need not to be tagged, because there is no dispatching subroutines > here. A rough C++ equivalent of a tagged type is a class with virtual > functions. Quite right. This is a better example: struct Silly { virtual int Get() { return i; } private: int i; }; ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 19:09 ` Dan McLeran @ 2004-04-10 10:49 ` Dmitry A. Kazakov 0 siblings, 0 replies; 35+ messages in thread From: Dmitry A. Kazakov @ 2004-04-10 10:49 UTC (permalink / raw) Dan McLeran wrote: >> This need not to be tagged, because there is no dispatching subroutines >> here. A rough C++ equivalent of a tagged type is a class with virtual >> functions. > > Quite right. This is a better example: > > struct Silly > { > virtual int Get() > { > return i; > } > private: > int i; > }; You have to add a friend function, because in C++ Silly will be passed to Get() by reference as in Ada: type Silly is tagged private; function Get (Object : Silly) return Integer; private type Silly is tagged record I : Integer; end record; So the difference between C++ and Ada is rather marginal here. But as I said, I think it would be better to leave the choice to the compiler (in the case of non-limited tagged types.) -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 13:03 ` Dmitry A. Kazakov 2004-04-09 19:09 ` Dan McLeran @ 2004-04-11 12:43 ` Florian Weimer 2004-04-12 10:29 ` Dmitry A. Kazakov 1 sibling, 1 reply; 35+ messages in thread From: Florian Weimer @ 2004-04-11 12:43 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: > Because that could be a handle requiring Initialize/Adjust/Finalize. To be > honest, forcing tagged types to be by-reference was probably a mistake. It's hard to envision another efficient way of implementing dispatching calls. -- Current mail filters: many dial-up/DSL/cable modem hosts, and the following domains: postino.it, tiscali.co.uk, tiscali.cz, tiscali.it, voila.fr. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-11 12:43 ` Florian Weimer @ 2004-04-12 10:29 ` Dmitry A. Kazakov 2004-04-12 12:29 ` Samuel Tardieu 0 siblings, 1 reply; 35+ messages in thread From: Dmitry A. Kazakov @ 2004-04-12 10:29 UTC (permalink / raw) Florian Weimer wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: > >> Because that could be a handle requiring Initialize/Adjust/Finalize. To >> be honest, forcing tagged types to be by-reference was probably a >> mistake. > > It's hard to envision another efficient way of implementing > dispatching calls. Why? Dispatching does not depend on the way an object is passed. For example, let you have a by-copy T and Foo (Object : in out T); is a primitive operaton: X : T'Class; Foo (X); -- Selects Foo according the type tag in X -- Copies the T part of X (calls Adjust) -- Calls the selected Foo with the copy -- Finalizes the T part of X (calls Finalize) -- Copies possibly modified T back into X (calls Adjust) -- Finalizes the copy (calls Finalize) When T is in a register it might be more efficient than by-reference. But let the compiler decide it knows better. -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-12 10:29 ` Dmitry A. Kazakov @ 2004-04-12 12:29 ` Samuel Tardieu 2004-04-13 8:46 ` Dmitry A. Kazakov 0 siblings, 1 reply; 35+ messages in thread From: Samuel Tardieu @ 2004-04-12 12:29 UTC (permalink / raw) >>>>> "Dmitry" == Dmitry A Kazakov <mailbox@dmitry-kazakov.de> writes: Dmitry> When T is in a register it might be more efficient than Dmitry> by-reference. But let the compiler decide it knows better. If T is an object, its tag alone (likely to be an address in many implementations) will already take the whole space in the register. Sam -- Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/sam ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-12 12:29 ` Samuel Tardieu @ 2004-04-13 8:46 ` Dmitry A. Kazakov 0 siblings, 0 replies; 35+ messages in thread From: Dmitry A. Kazakov @ 2004-04-13 8:46 UTC (permalink / raw) Samuel Tardieu wrote: >>>>>> "Dmitry" == Dmitry A Kazakov <mailbox@dmitry-kazakov.de> writes: > > Dmitry> When T is in a register it might be more efficient than > Dmitry> by-reference. But let the compiler decide it knows better. > > If T is an object, its tag alone (likely to be an address in many > implementations) will already take the whole space in the register. The beauty of Ada's OO concept is that T need not to have any tag, as opposed to T'Class. With by-reference parameter passing it is almost no matter, but for by-copy one it makes much sense to keep T and T'Tag separate. For example, one could have Boolean and Boolean'Class. -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 12:38 ` Dan McLeran 2004-04-09 13:03 ` Dmitry A. Kazakov @ 2004-04-10 1:42 ` Stephen Leake 2004-04-10 16:05 ` chris 1 sibling, 1 reply; 35+ messages in thread From: Stephen Leake @ 2004-04-10 1:42 UTC (permalink / raw) To: comp.lang.ada dan.r.mcleran@seagate.com (Dan McLeran) writes: > > A couple of larger questions; > > > > Why do you care whether a type is passed by copy or reference? > > I'm just trying to get more familiar with the language. I've done > mostly C++ programming for the past several years and am looking at > alternatives. Ok. I also recommend "Ada as a Second Language", by Norm Cohen. A very thorough Language Lawyer book, with excellent discussion of all of this sort of thing. -- -- Stephe ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-10 1:42 ` Stephen Leake @ 2004-04-10 16:05 ` chris 0 siblings, 0 replies; 35+ messages in thread From: chris @ 2004-04-10 16:05 UTC (permalink / raw) Stephen Leake wrote: > > Ok. I also recommend "Ada as a Second Language", by Norm Cohen. A very > thorough Language Lawyer book, with excellent discussion of all of > this sort of thing. I second that. It's a very good book, well worth having if you're going to use Ada. Chris ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 0:01 ` Stephen Leake 2004-04-09 12:38 ` Dan McLeran @ 2004-04-09 12:44 ` Dan McLeran 2004-04-09 22:44 ` Randy Brukardt 2004-04-09 14:44 ` Simon Wright 2 siblings, 1 reply; 35+ messages in thread From: Dan McLeran @ 2004-04-09 12:44 UTC (permalink / raw) > > > I am investigating using Ada for a project at work > > Excellent choice :). > > > and I have a question I hope someone can answer. If I am > > interpreting the RM section 6.2 correctly, an array of elementary > > types does not meet the criteria of a by-reference type. > > A 'by-reference type' is simply one that is always passed by > reference, never by copy. That's what I thought. > > > But, when looking at the disassembly, it seems that passing an array > > of elementary types to a function as an in-mode parameter is passing > > by reference. Does this mean that an array of elementary types is an > > unspecfied type? > > The compiler is always free to choose either copy or reference for > passing parameters. This statement seems to contradict the RM and what you've said above. The way I read the RM, a by-reference type is passed by reference. No choice. A by-value type is passed by value. Again, no choice. The RM seems to indicate that the only time a compiler is free to choose is for the 'unspecified' types. > > I'm not clear what you mean by "unspecified type". Hmm, perhaps you > are refering to 6.2(11): > > For parameters of other types, it is unspecified whether the > parameter is passed by copy or by reference. Exactly. > > Yes, an array of elementary types is an "other type" in this sense; it > may be passed either by reference or copy. The compiler will choose > whichever mechanism it feels is "best". That's what I assumed when reading the RM. I'll play around with small arrays and see if the compiler decides by-value is better. > > > A 2nd part to my question is: Does Ada automatically pass tagged types > > by reference no matter what mode the parameter is specfied (in, in > > out, or out)? The language RM 6.2 seems to suggest this is so. > > Yes. > > > If so, does this mean that there is no way to pass a tagged type by > > value? > > Yes. > > > I believe C# works this way without programmer intervention. > > Don't know. > A couple of larger questions; > > Why do you care whether a type is passed by copy or reference? > > If you are worried about time or space efficiency, specify the > appropriate option to the compiler, and forget about it, until > measurements of your final application show a problem. > > Why would you want to pass a tagged type by copy? > > You might want to read the Ada Rationale, and the annotated Ada > Reference manual, on this topic. See > http://www.adaic.com/standards/ada95.html ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 12:44 ` Dan McLeran @ 2004-04-09 22:44 ` Randy Brukardt 0 siblings, 0 replies; 35+ messages in thread From: Randy Brukardt @ 2004-04-09 22:44 UTC (permalink / raw) "Dan McLeran" <dan.r.mcleran@seagate.com> wrote in message news:19b0e504.0404090444.376ab672@posting.google.com... > > The compiler is always free to choose either copy or reference for > > passing parameters. > > This statement seems to contradict the RM and what you've said above. > The way I read the RM, a by-reference type is passed by reference. No > choice. A by-value type is passed by value. Again, no choice. The RM > seems to indicate that the only time a compiler is free to choose is > for the 'unspecified' types. That's not quite true. The important thing is that the passing has the semantics of by-reference or by-copy, not necessarily that that is used. For instance, we've worked on targets where the standard calling convention did not support copy back. In order to implement 'in out' parameters of elementary types on those targets, we do the parameter passing by-reference, and make a copy at the call-site to insure the by-copy semantics. (We also use a similar trick for passing large [>32 bit] elementary objects.) Randy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 0:01 ` Stephen Leake 2004-04-09 12:38 ` Dan McLeran 2004-04-09 12:44 ` Dan McLeran @ 2004-04-09 14:44 ` Simon Wright 2 siblings, 0 replies; 35+ messages in thread From: Simon Wright @ 2004-04-09 14:44 UTC (permalink / raw) Stephen Leake <stephen_leake@acm.org> writes: > The compiler is always free to choose either copy or reference for > passing parameters. No, 6.2(10) -- Simon Wright 100% Ada, no bugs. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-08 14:52 Pass by reference Dan McLeran ` (2 preceding siblings ...) 2004-04-09 0:01 ` Stephen Leake @ 2004-04-09 1:15 ` Jeffrey Carter 2004-04-09 1:28 ` Pat Rogers 2004-04-09 12:57 ` Dan McLeran 2004-04-09 4:03 ` Steve 4 siblings, 2 replies; 35+ messages in thread From: Jeffrey Carter @ 2004-04-09 1:15 UTC (permalink / raw) Dan McLeran wrote: > I am investigating using Ada for a project at work and I have a > question I hope someone can answer. If I am interpreting the RM > section 6.2 correctly, an array of elementary types does not meet the > criteria of a by-reference type. But, when looking at the disassembly, > it seems that passing an array of elementary types to a function as an > in-mode parameter is passing by reference. Does this mean that an > array of elementary types is an unspecfied type? > > A 2nd part to my question is: Does Ada automatically pass tagged types > by reference no matter what mode the parameter is specfied (in, in > out, or out)? The language RM 6.2 seems to suggest this is so. If so, > does this mean that there is no way to pass a tagged type by value? I > believe C# works this way without programmer intervention. The Ada rules, simple version, for parameter passing mechanisms, are: Elementary types are always passed by copy. Tagged and private types are always passed by reference. Other types have the mechanism chosen by the compiler. The parameter mode (in, in out, and out) is completely unrelated to the parameter passing mechanism. Generally, compilers do a good job of choosing the mechanism for "other types". It might be informative to check the mechanism used for type T is array (1 .. Integer'Size) of Boolean; pragma Pack (T); -- Jeff Carter "Sons of a silly person." Monty Python & the Holy Grail 02 ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 1:15 ` Jeffrey Carter @ 2004-04-09 1:28 ` Pat Rogers 2004-04-10 1:05 ` Jeffrey Carter 2004-04-09 12:57 ` Dan McLeran 1 sibling, 1 reply; 35+ messages in thread From: Pat Rogers @ 2004-04-09 1:28 UTC (permalink / raw) > The Ada rules, simple version, for parameter passing mechanisms, are: > > Elementary types are always passed by copy. > > Tagged and private types are always passed by reference. You meant "limited" rather than "private" in the above, I'm sure. > > Other types have the mechanism chosen by the compiler. > > The parameter mode (in, in out, and out) is completely unrelated to > the parameter passing mechanism. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 1:28 ` Pat Rogers @ 2004-04-10 1:05 ` Jeffrey Carter 0 siblings, 0 replies; 35+ messages in thread From: Jeffrey Carter @ 2004-04-10 1:05 UTC (permalink / raw) Pat Rogers wrote: >>The Ada rules, simple version, for parameter passing mechanisms, > > are: > >>Elementary types are always passed by copy. >> >>Tagged and private types are always passed by reference. > > > You meant "limited" rather than "private" in the above, I'm sure. Yes, of course. Sorry. -- Jeff Carter "I'm a kike, a yid, a heebie, a hook nose! I'm Kosher, Mum! I'm a Red Sea pedestrian, and proud of it!" Monty Python's Life of Brian 77 ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 1:15 ` Jeffrey Carter 2004-04-09 1:28 ` Pat Rogers @ 2004-04-09 12:57 ` Dan McLeran 2004-04-10 1:16 ` Jeffrey Carter 1 sibling, 1 reply; 35+ messages in thread From: Dan McLeran @ 2004-04-09 12:57 UTC (permalink / raw) > The Ada rules, simple version, for parameter passing mechanisms, are: > > Elementary types are always passed by copy. > > Tagged and private types are always passed by reference. > > Other types have the mechanism chosen by the compiler. That's what I thought. The RM is actually very clear about this, but it seems that alot of people assume compilers have more leeway. Alot of the answers indicate that people think the compiler is always free to choose the best convention. I don't believe this is true. A conforming compiler should do exactly what the RM says, which is what your short-version says. > The parameter mode (in, in out, and out) is completely unrelated to the > parameter passing mechanism. > > Generally, compilers do a good job of choosing the mechanism for "other > types". It might be informative to check the mechanism used for > > type T is array (1 .. Integer'Size) of Boolean; > pragma Pack (T); I'll check it out, Thanks. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 12:57 ` Dan McLeran @ 2004-04-10 1:16 ` Jeffrey Carter 0 siblings, 0 replies; 35+ messages in thread From: Jeffrey Carter @ 2004-04-10 1:16 UTC (permalink / raw) Dan McLeran wrote: >>The Ada rules, simple version, for parameter passing mechanisms, are: >> >>Elementary types are always passed by copy. >> >>Tagged and private types are always passed by reference. >> >>Other types have the mechanism chosen by the compiler. > > That's what I thought. The RM is actually very clear about this, but > it seems that alot of people assume compilers have more leeway. Alot > of the answers indicate that people think the compiler is always free > to choose the best convention. I don't believe this is true. A > conforming compiler should do exactly what the RM says, which is what > your short-version says. Except for my mistake in writing "private" instead of "limited". The 2 are unrelated. I suspect the discrepency we're seeing between the ARM and the responses here are more due to the use of informal language than to significant misunderstandings of the ARM. However, the best rule is that you shouldn't care about the parameter passing mechanism [unless it gets you in trouble]. -- Jeff Carter "I'm a kike, a yid, a heebie, a hook nose! I'm Kosher, Mum! I'm a Red Sea pedestrian, and proud of it!" Monty Python's Life of Brian 77 ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-08 14:52 Pass by reference Dan McLeran ` (3 preceding siblings ...) 2004-04-09 1:15 ` Jeffrey Carter @ 2004-04-09 4:03 ` Steve 2004-04-09 14:50 ` Simon Wright 2004-04-11 12:45 ` Florian Weimer 4 siblings, 2 replies; 35+ messages in thread From: Steve @ 2004-04-09 4:03 UTC (permalink / raw) I am only aware of one (obscure) case in Ada where passing by reference versus passing by value makes a difference. It has come up on this newsgroup before. If you pass the same value to a procedure as both an "in" and an "in out" parameter, changes to the "in out" version may or may not effect the value of the "in" mode value depending on the compilers choice of whether to pass by reference or by value. Here is a small program that illustrates the case: with Ada.Text_Io; with Ada.Integer_Text_Io; procedure By_Ref_Vs_By_Value is package Text_Io renames Ada.Text_IO; package Integer_Text_Io renames Ada.Integer_Text_Io; type int_array_type is array( 1 .. 10 ) of integer; procedure Show_Both( a : Integer; b : in out integer ) is begin Text_Io.Put( "Initial a" ); Integer_Text_Io.Put( a ); Text_Io.New_Line; b := b + 1; Text_Io.Put( "Final a" ); Integer_Text_Io.Put( a ); Text_Io.New_Line; end Show_Both; procedure Show_Both( a : int_array_type; b : in out int_array_type ) is begin Text_Io.Put( "Initial a" ); Integer_Text_Io.Put( a(1) ); Text_Io.New_Line; b(1) := b(1) + 1; Text_Io.Put( "Final a" ); Integer_Text_Io.Put( a(1) ); Text_Io.New_Line; end Show_Both; int_value : Integer := 0; int_array_value : int_array_type := ( others => 0 ); begin Show_Both( int_value, int_value ); Show_Both( int_array_value, int_array_value ); end By_Ref_Vs_By_Value; BTW: I have never experienced this in practice. In Ada I have found that if you just let the compiler to its thing, it is generally the right thing. Steve (The Duck) "Dan McLeran" <dan.r.mcleran@seagate.com> wrote in message news:19b0e504.0404080652.4eab9f80@posting.google.com... > I am investigating using Ada for a project at work and I have a > question I hope someone can answer. If I am interpreting the RM > section 6.2 correctly, an array of elementary types does not meet the > criteria of a by-reference type. But, when looking at the disassembly, > it seems that passing an array of elementary types to a function as an > in-mode parameter is passing by reference. Does this mean that an > array of elementary types is an unspecfied type? > > A 2nd part to my question is: Does Ada automatically pass tagged types > by reference no matter what mode the parameter is specfied (in, in > out, or out)? The language RM 6.2 seems to suggest this is so. If so, > does this mean that there is no way to pass a tagged type by value? I > believe C# works this way without programmer intervention. > > I am using Aonix's ObjectAda V7.2.2, by the way. I have not tried GNAT > for comparison. > > Thanks, > > Dan McLeran ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 4:03 ` Steve @ 2004-04-09 14:50 ` Simon Wright 2004-04-09 17:12 ` Pat Rogers 2004-04-11 12:45 ` Florian Weimer 1 sibling, 1 reply; 35+ messages in thread From: Simon Wright @ 2004-04-09 14:50 UTC (permalink / raw) "Steve" <nospam_steved94@comcast.net> writes: > I am only aware of one (obscure) case in Ada where passing by > reference versus passing by value makes a difference. It has come > up on this newsgroup before. I had (in the full view) type Socket is record Handle : Interfaces.C.int; end record; and, on failure, my Read operation woudl close() the Handle in its "in out" Socket parameter, set it to -1, and raise an exception. But the actual Socket didn't get altered, because it wasn't by-reference. So I had to make it a tagged type (couldn't be limited, for some reason I forget now). -- Simon Wright 100% Ada, no bugs. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 14:50 ` Simon Wright @ 2004-04-09 17:12 ` Pat Rogers 2004-04-09 19:33 ` Vinzent 'Gadget' Hoefler 0 siblings, 1 reply; 35+ messages in thread From: Pat Rogers @ 2004-04-09 17:12 UTC (permalink / raw) > So I had to make it a tagged type (couldn't be limited, for some > reason I forget now). If you made the type volatile that would also force by-reference. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 17:12 ` Pat Rogers @ 2004-04-09 19:33 ` Vinzent 'Gadget' Hoefler 2004-04-10 6:33 ` Simon Wright 0 siblings, 1 reply; 35+ messages in thread From: Vinzent 'Gadget' Hoefler @ 2004-04-09 19:33 UTC (permalink / raw) Pat Rogers wrote: >If you made the type volatile that would also force by-reference. Are you sure? I'm just looking at the assembly ouput of GNAT for a procedure that takes a volatile type (memory mapped register) and it does't seem so. Even worse, it optimizes the sequence of assignment which I need for this register. If you have any idea how can I avoid using access types to make it right, I'd be glad to hear it. Here's the procedure: | -- Write ------------------------------------------------------------ | -- writes a timer value (low byte/high byte in succession) to the -- | -- memory mapped timer port given by its access -- | --------------------------------------------------------------------- | procedure Write (Timer_Reg : in out Registers.Reg_8; | Value : in i8254_Timer) is | Internal_Value : Interfaces.Unsigned_16 := To_U16 (Value); | begin | Timer_Reg := Lo_Byte (Internal_Value); | Timer_Reg := Hi_Byte (Internal_Value); | end Write; the assembly output is: |_timer__write: | pushl %ebp | movl %esp,%ebp | movl 12(%ebp),%eax | movl %eax,%edx | cmpl $65536,%eax | jne L21 | xorl %edx,%edx |L21: | movl %edx,%eax | movl %ebp,%esp | shrw $8,%ax | popl %ebp | ret which is not what it should be. If I change it back to use access types: | procedure Write (Timer_Reg : in Registers.Reg_8_Access; | Value : in i8254_Timer) is | Internal_Value : Interfaces.Unsigned_16 := To_U16 (Value); | begin | Timer_Reg.all := Lo_Byte (Internal_Value); | Timer_Reg.all := Hi_Byte (Internal_Value); | end Write; everything is fine: |_timer__write: | pushl %ebp | movl %esp,%ebp | movl 12(%ebp),%eax | movl 8(%ebp),%ecx | movl %eax,%edx | cmpl $65536,%eax | jne L21 | xorl %edx,%edx |L21: | movl %edx,%eax | movb %dl,(%ecx) | shrw $8,%ax | movl %ebp,%esp | movb %al,(%ecx) | popl %ebp | ret Vinzent. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 19:33 ` Vinzent 'Gadget' Hoefler @ 2004-04-10 6:33 ` Simon Wright 2004-04-13 10:26 ` Vinzent 'Gadget' Hoefler 0 siblings, 1 reply; 35+ messages in thread From: Simon Wright @ 2004-04-10 6:33 UTC (permalink / raw) Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes: > Pat Rogers wrote: > > >If you made the type volatile that would also force by-reference. C.6(18): If a type is atomic or volatile and it is not a by-copy type, then the type is defined to be a by-reference type. If any subcomponent of a type is atomic or volatile, then the type is defined to be a by-reference type. > Are you sure? I'm just looking at the assembly ouput of GNAT for a > procedure that takes a volatile type (memory mapped register) and it > does't seem so. Even worse, it optimizes the sequence of assignment > which I need for this register. If you have any idea how can I avoid > using access types to make it right, I'd be glad to hear it. I think you need to use inline assembler to be sure. And to be really sure you may need to use Volatile => True on the call, I had to (this was GNAT/PowerPC, by the way). -- Simon Wright 100% Ada, no bugs. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-10 6:33 ` Simon Wright @ 2004-04-13 10:26 ` Vinzent 'Gadget' Hoefler 2004-04-14 17:27 ` Simon Wright 0 siblings, 1 reply; 35+ messages in thread From: Vinzent 'Gadget' Hoefler @ 2004-04-13 10:26 UTC (permalink / raw) Simon Wright wrote: >Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes: > >> Pat Rogers wrote: >> >> >If you made the type volatile that would also force by-reference. > >C.6(18): If a type is atomic or volatile and it is not a by-copy type, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Yes, but if I understand that part correctly, this is the point. The register-type is just a simple Integer-type: |package Registers is | | type Reg_8 is mod 2**8; | type Reg_8_Access is access Reg_8; | [...] | |private | | pragma Volatile (Reg_8); | [...] |end Registers; So although it is declared Volatile it is a by-copy type. Too bad. >> Are you sure? I'm just looking at the assembly ouput of GNAT for a >> procedure that takes a volatile type (memory mapped register) and it >> does't seem so. Even worse, it optimizes the sequence of assignment >> which I need for this register. If you have any idea how can I avoid >> using access types to make it right, I'd be glad to hear it. > >I think you need to use inline assembler to be sure. You must be kidding me, I'm just getting away from using assembler. :) The old system was a 16-bit-CPU programmed entirely in assembly language, now I am having MaRTE and Ada and you say, I should use inline assembler instead? ;-) Well, there is no general problem in here for me, but even with inline assembler the fact remains that the procedure would need the _address_ of the register, and *not* its contents. So using inline assembler wouldn't help in avoiding access types and if it doesn't, I won't need it, because in that case the compiler generated code is just fine. >And to be really sure you may need to use Volatile => True on the >call, I had to (this was GNAT/PowerPC, by the way). I'm not sure if I understand... can I actually apply that pragma to a call? Or am I missing something else? Vinzent. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-13 10:26 ` Vinzent 'Gadget' Hoefler @ 2004-04-14 17:27 ` Simon Wright 2004-04-15 9:43 ` Vinzent 'Gadget' Hoefler 0 siblings, 1 reply; 35+ messages in thread From: Simon Wright @ 2004-04-14 17:27 UTC (permalink / raw) Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes: > Simon Wright wrote: > > >Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes: > > > >> Pat Rogers wrote: > >> > >> >If you made the type volatile that would also force by-reference. > > > >C.6(18): If a type is atomic or volatile and it is not a by-copy type, > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > Yes, but if I understand that part correctly, this is the point. The > register-type is just a simple Integer-type: Sorry, that's what _I_ was trying to say too! > >> Are you sure? I'm just looking at the assembly ouput of GNAT for a > >> procedure that takes a volatile type (memory mapped register) and it > >> does't seem so. Even worse, it optimizes the sequence of assignment > >> which I need for this register. If you have any idea how can I avoid > >> using access types to make it right, I'd be glad to hear it. > > > >I think you need to use inline assembler to be sure. > > You must be kidding me, I'm just getting away from using assembler. :) > The old system was a 16-bit-CPU programmed entirely in assembly > language, now I am having MaRTE and Ada and you say, I should use > inline assembler instead? ;-) > > Well, there is no general problem in here for me, but even with inline > assembler the fact remains that the procedure would need the _address_ > of the register, and *not* its contents. So using inline assembler > wouldn't help in avoiding access types and if it doesn't, I won't need > it, because in that case the compiler generated code is just fine. > > >And to be really sure you may need to use Volatile => True on the > >call, I had to (this was GNAT/PowerPC, by the way). > > I'm not sure if I understand... can I actually apply that pragma to > a call? Or am I missing something else? I was talking about your "optimizes the sequence of assignment which I need for this register" problem. I don't know whether it's available in GCC C inline assembler, but for GNAT, System.Machine_Code.Asm looks like procedure Asm ( Template : String; Outputs : Asm_Output_Operand_List; Inputs : Asm_Input_Operand_List; Clobber : String := ""; Volatile : Boolean := False); (plus other variants). From http://gcc.gnu.org/onlinedocs/gnat_ug_unx/The-Volatile-Parameter.html#The%20Volatile%20Parameter Compiler optimizations in the presence of Inline Assembler may sometimes have unwanted effects. For example, when an Asm invocation with an input variable is inside a loop, the compiler might move the loading of the input variable outside the loop, regarding it as a one-time initialization. If this effect is not desired, you can disable such optimizations by setting the Volatile parameter to True; for example: Asm ("movl %0, %%ebx" & LF & HT & "movl %%ebx, %1", Inputs => Unsigned_32'Asm_Input ("g", Var_In), Outputs => Unsigned_32'Asm_Output ("=g", Var_Out), Clobber => "ebx", Volatile => True); I'm not 100% sure on this, but this code with Interfaces; with System.Machine_Code; with System.Storage_Elements; procedure Access_Memory_Mapped_Register is R : Interfaces.Unsigned_32; for R'Address use System.Storage_Elements.To_Address (16#ffff0000#); begin System.Machine_Code.Asm ("movl #01000000, %0", Outputs => Interfaces.Unsigned_32'Asm_Output ("=m", R), Volatile => True); System.Machine_Code.Asm ("movl #00000000, %0", Outputs => Interfaces.Unsigned_32'Asm_Output ("=m", R), Volatile => True); end Access_Memory_Mapped_Register; generates this i86 assembler .file "vinzent.adb" .version "01.01" gcc2_compiled.: .section .rodata .LC0: .string "vinzent.adb" .text .align 4 .globl _ada_access_memory_mapped_register .type _ada_access_memory_mapped_register,@function _ada_access_memory_mapped_register: pushl %ebp movl %esp,%ebp #APP movl #01000000, -65536 movl #00000000, -65536 #NO_APP movl %ebp,%esp popl %ebp ret .Lfe1: .size _ada_access_memory_mapped_register,.Lfe1-_ada_access_memory_mapped_register .ident "GCC: (GNU) 2.8.1" which looks good .. no 'Access anywhere .. -- Simon Wright 100% Ada, no bugs. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-14 17:27 ` Simon Wright @ 2004-04-15 9:43 ` Vinzent 'Gadget' Hoefler 2004-04-17 7:59 ` Simon Wright 0 siblings, 1 reply; 35+ messages in thread From: Vinzent 'Gadget' Hoefler @ 2004-04-15 9:43 UTC (permalink / raw) Simon Wright wrote: >Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes: > >> Simon Wright wrote: >> >> >Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes: >> > >> >> Pat Rogers wrote: >> >> >> >> >If you made the type volatile that would also force by-reference. >> > >> >C.6(18): If a type is atomic or volatile and it is not a by-copy type, >> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >> >> Yes, but if I understand that part correctly, this is the point. The >> register-type is just a simple Integer-type: > >Sorry, that's what _I_ was trying to say too! Ok. Got it. :) [...] >> >I think you need to use inline assembler to be sure. >> [...] >> >> >And to be really sure you may need to use Volatile => True on the >> >call, I had to (this was GNAT/PowerPC, by the way). >> >> I'm not sure if I understand... can I actually apply that pragma to >> a call? Or am I missing something else? > >I was talking about your "optimizes the sequence of assignment which I >need for this register" problem. Oh. Well, from what I was trying to understand by looking at the ASM-output I figured the volatile-"property" of the type just got lost, *because* it was passed by copy. >I don't know whether it's available in GCC C inline assembler, but for >GNAT, System.Machine_Code.Asm looks like > > procedure Asm ( > Template : String; > Outputs : Asm_Output_Operand_List; > Inputs : Asm_Input_Operand_List; > Clobber : String := ""; > Volatile : Boolean := False); > >(plus other variants). Duh. _Now_ I understand. I've never looked at System.Machine_Code. (IMO inline assembler can considered to be evil in most cases). >I'm not 100% sure on this, but this code > > with Interfaces; > with System.Machine_Code; > with System.Storage_Elements; > > procedure Access_Memory_Mapped_Register is [...] > #APP > movl #01000000, -65536 > movl #00000000, -65536 > #NO_APP (Despite the fact that this code is not valid, i386 can't load two constants in one instruction, your intention is clear and would work). >which looks good .. no 'Access anywhere .. Yes. Probably I wasn't expressing myself too clear, so I'm trying to switch to verbose mode. :) Firstly, if I assign the values to the variable directly the compiled code is just perfect. No problem here, no inline-assembler needed. Ada behaves as I expect it to. Fine. But what I am trying to do is to abstract away some (nasty) behaviour of the registers (yes, there is more than one, in fact: up to twenty-four): If I write a new timer value I have to write two byte values (low-, high-byte) in succession instead of just assigning the (16-bit) value directly (the 8254 timer only has an 8-bit-data-port). To make this part a little bit more safe (if you forget to write a value then - *poof* - everything will screw up) I declared the "Timer.Write"-procedure that should take one of the memory-mapped-registers and the value-to-be-written as parameters and do the nasty stuff with converting the value and extracting high- and low-byte at this only one place. Probably a neat idea, but now RM C.6(18) strikes back and passes the _value_ at the memory address of the register to the procedure (by-copy) instead of the _address_ of the register (by-reference), I assign the stuff inside the procedure (means: the compiler is perfectly allowed to optimize anything away, because it is just working with a local copy and can't "return" more than 8 bits anyway) and get the result back that would then be written to the register. Well, this might be perfectly justified by the mentioned paragraph of the RM - but is just plain wrong for the real world. Switching to inline assembler wouldn't help here either, because *at this point* it is already too late, all I'd get as input would be the value of the register, not the register (read: pointer to) "itself". That's why I declared the procedure to take an access parameter instead of "in out" and now everything is working fine as expected. It is just the fact that I now use access types in the interface (IMO: unnecessarily from the point of logic) that bugs me a little bit. Eventually I should try to switch to use limited types instead to circumvent this problem? Vinzent. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-15 9:43 ` Vinzent 'Gadget' Hoefler @ 2004-04-17 7:59 ` Simon Wright 0 siblings, 0 replies; 35+ messages in thread From: Simon Wright @ 2004-04-17 7:59 UTC (permalink / raw) Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes: > Simon Wright wrote: > >I'm not 100% sure on this, but this code > > > > with Interfaces; > > with System.Machine_Code; > > with System.Storage_Elements; > > > > procedure Access_Memory_Mapped_Register is > [...] > > #APP > > movl #01000000, -65536 > > movl #00000000, -65536 > > #NO_APP > > (Despite the fact that this code is not valid, i386 can't load two > constants in one instruction, your intention is clear and would > work). Yes, more work needed (and next time, Simon, go the whole way and don't just stop with a -S compilation). I too will only use asm when it's _necessary_, so it's a new learning experience each time ... > That's why I declared the procedure to take an access parameter > instead of "in out" and now everything is working fine as > expected. It is just the fact that I now use access types in the > interface (IMO: unnecessarily from the point of logic) that bugs me > a little bit. Another possibility would be to pass System.Address. On the whole, access is a lot safer I would have thought -- especially if you can encapsulate this low-level stuff (including the calls to your wrapper procedure) to a restricted area of the code. > Eventually I should try to switch to use limited types instead to > circumvent this problem? I had a play with this, and for GNAT 3.15p (and 3.16a1, 5.02a) this package Wrapper is type Register is limited private; procedure Write (Value : Interfaces.Unsigned_16; To : in out Register); private type Actual_Register is mod 256; for Actual_Register'Size use 8; pragma Volatile (Actual_Register); type Register is limited record Actual : Actual_Register; end record; for Register'Size use 8; end Wrapper; used pass-by-reference. The asm for 5.02a (-gnatp -O2) is .type access_memory_mapped_register__wrapper__write.0,@function access_memory_mapped_register__wrapper__write.0: .LFB1: pushl %ebp .LCFI0: movl %esp, %ebp .LCFI1: subl $4, %esp .LCFI2: movzwl 8(%ebp), %eax movl 12(%ebp), %edx movb %al, (%edx) shrl $8, %eax movb %al, (%edx) movl %ebp, %esp popl %ebp ret which looks as though it at least stands a chance; I don't understand the 3.15p code, .type access_memory_mapped_register__wrapper__write.0,@function access_memory_mapped_register__wrapper__write.0: pushl %ebp movl %esp,%ebp subl $4,%esp movl %ecx,-4(%ebp) movl 12(%ebp),%edx movzbw 9(%ebp),%ax movb %al,(%edx) movl %ebp,%esp popl %ebp ret -- Simon Wright 100% Ada, no bugs. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Pass by reference 2004-04-09 4:03 ` Steve 2004-04-09 14:50 ` Simon Wright @ 2004-04-11 12:45 ` Florian Weimer 1 sibling, 0 replies; 35+ messages in thread From: Florian Weimer @ 2004-04-11 12:45 UTC (permalink / raw) "Steve" <nospam_steved94@comcast.net> writes: > I am only aware of one (obscure) case in Ada where passing by reference > versus passing by value makes a difference. Another (not-so-obscure) case are exceptions. Pass-by-copy parameters retain their values if the subprogram raises an exception. -- Current mail filters: many dial-up/DSL/cable modem hosts, and the following domains: postino.it, tiscali.co.uk, tiscali.cz, tiscali.it, voila.fr. ^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2004-04-17 7:59 UTC | newest] Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-04-08 14:52 Pass by reference Dan McLeran 2004-04-08 18:21 ` Martin Krischik 2004-04-09 12:53 ` Dan McLeran 2004-04-13 12:42 ` Martin Krischik 2004-04-08 19:04 ` Jim Rogers 2004-04-09 3:24 ` Dan McLeran 2004-04-09 0:01 ` Stephen Leake 2004-04-09 12:38 ` Dan McLeran 2004-04-09 13:03 ` Dmitry A. Kazakov 2004-04-09 19:09 ` Dan McLeran 2004-04-10 10:49 ` Dmitry A. Kazakov 2004-04-11 12:43 ` Florian Weimer 2004-04-12 10:29 ` Dmitry A. Kazakov 2004-04-12 12:29 ` Samuel Tardieu 2004-04-13 8:46 ` Dmitry A. Kazakov 2004-04-10 1:42 ` Stephen Leake 2004-04-10 16:05 ` chris 2004-04-09 12:44 ` Dan McLeran 2004-04-09 22:44 ` Randy Brukardt 2004-04-09 14:44 ` Simon Wright 2004-04-09 1:15 ` Jeffrey Carter 2004-04-09 1:28 ` Pat Rogers 2004-04-10 1:05 ` Jeffrey Carter 2004-04-09 12:57 ` Dan McLeran 2004-04-10 1:16 ` Jeffrey Carter 2004-04-09 4:03 ` Steve 2004-04-09 14:50 ` Simon Wright 2004-04-09 17:12 ` Pat Rogers 2004-04-09 19:33 ` Vinzent 'Gadget' Hoefler 2004-04-10 6:33 ` Simon Wright 2004-04-13 10:26 ` Vinzent 'Gadget' Hoefler 2004-04-14 17:27 ` Simon Wright 2004-04-15 9:43 ` Vinzent 'Gadget' Hoefler 2004-04-17 7:59 ` Simon Wright 2004-04-11 12:45 ` Florian Weimer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox