comp.lang.ada
 help / color / mirror / Atom feed
* 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 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 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-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-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
                   ` (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  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  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-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  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: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  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-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 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 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 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  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 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-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-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-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-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 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-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

* 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-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-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-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

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