www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - D calling convention

reply Christian Kamm <kamm-incasoftware removethis.de> writes:
Tomas has done a lot of work on D ABI compatibility for LDC during the last
weeks. He's come quite far: except for the passing of some parameters in
EAX, things seem to work fine.

One point we couldn't understand though, is the reversal of parameters when
calling some D functions: Parameters are usually passed right-to-left,
except for nonvariadic D functions, where the order changes to
left-to-right. 

What is the reason for it?


If this was not so, and D functions would always pass parameters
right-to-left, it'd be very easy to call a member or nested function given
the type and address only: the context would just always go first in the
parameter list (and hence be passed last, possibly in EAX). As it is, you
have to put the context in as the last argument - except for variadics,
where it can go first again.

As a somewhat related, but separate issue, this would open the door to real
easy pointer-to-members. Given

class C {
  void foo(int i) { ... }
}

you could have

typeof(C.foo) == void function(C, int) 

and

auto memberfn = &C.foo;
memberfn(new C, 42);

would work too.
Oct 28 2008
next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Tue, Oct 28, 2008 at 12:28 PM, Christian Kamm
<kamm-incasoftware removethis.de> wrote:
 Tomas has done a lot of work on D ABI compatibility for LDC during the last
 weeks. He's come quite far: except for the passing of some parameters in
 EAX, things seem to work fine.

 One point we couldn't understand though, is the reversal of parameters when
 calling some D functions: Parameters are usually passed right-to-left,
 except for nonvariadic D functions, where the order changes to
 left-to-right.

 What is the reason for it?


 If this was not so, and D functions would always pass parameters
 right-to-left, it'd be very easy to call a member or nested function given
 the type and address only: the context would just always go first in the
 parameter list (and hence be passed last, possibly in EAX). As it is, you
 have to put the context in as the last argument - except for variadics,
 where it can go first again.

 As a somewhat related, but separate issue, this would open the door to real
 easy pointer-to-members. Given

 class C {
  void foo(int i) { ... }
 }

 you could have

 typeof(C.foo) == void function(C, int)

 and

 auto memberfn = &C.foo;
 memberfn(new C, 42);

 would work too.

All of these things would make me happy. :)
Oct 28 2008
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Christian Kamm wrote:
 One point we couldn't understand though, is the reversal of parameters when
 calling some D functions: Parameters are usually passed right-to-left,
 except for nonvariadic D functions, where the order changes to
 left-to-right. 
 
 What is the reason for it?

The reason is because I'd eventually like to specify the order of evaluation of function arguments as being left to right. So, for normal D functions, this makes for optimal code generation. The only time monkey business would have to happen would be to support the C calling convention or the variadic one.
Oct 28 2008
next sibling parent Tomas Lindquist Olsen <tomas famolsen.dk> writes:
Walter Bright wrote:
 Christian Kamm wrote:
 One point we couldn't understand though, is the reversal of parameters 
 when
 calling some D functions: Parameters are usually passed right-to-left,
 except for nonvariadic D functions, where the order changes to
 left-to-right.
 What is the reason for it?

The reason is because I'd eventually like to specify the order of evaluation of function arguments as being left to right. So, for normal D functions, this makes for optimal code generation. The only time monkey business would have to happen would be to support the C calling convention or the variadic one.

What do you think of the "proposal"?, I think it could be quite valuable and the current setup makes has some odd behaviour. Take the TypeInfo_Struct.xopCmp for example. Here a member function pointer is assigned to a static function pointer, the result being that you have to call it with parameters reversed for things to work as you expect, but only when x86 ABI is in effect.
Oct 28 2008
prev sibling next sibling parent reply Jason House <jason.james.house gmail.com> writes:
Walter Bright Wrote:

 Christian Kamm wrote:
 One point we couldn't understand though, is the reversal of parameters when
 calling some D functions: Parameters are usually passed right-to-left,
 except for nonvariadic D functions, where the order changes to
 left-to-right. 
 
 What is the reason for it?

The reason is because I'd eventually like to specify the order of evaluation of function arguments as being left to right. So, for normal D functions, this makes for optimal code generation. The only time monkey business would have to happen would be to support the C calling convention or the variadic one.

It's sounding like right-to-left makes more sense than left-to-right. As an English speaker, left-to-right seems more natural, but I see no reason to require it. Beyond that, do we really want to require an evaluation order of arguments? I'd much prefer for the compiler to work its optimization magic than have a set order anyway.
Oct 28 2008
parent Walter Bright <newshound1 digitalmars.com> writes:
Jason House wrote:
 It's sounding like right-to-left makes more sense than left-to-right.
 As an English speaker, left-to-right seems more natural, but I see no
 reason to require it.  Beyond that, do we really want to require an
 evaluation order of arguments?  I'd much prefer for the compiler to
 work its optimization magic than have a set order anyway.

People intuitively expect expressions to be evaluated left-to-right, and that applies to function arguments, too. Eliminating implementation defined behavior makes the source code much more portable. There is no way to reliably detect inadvertent order-of-evaluation dependencies.
Oct 28 2008
prev sibling parent reply Christian Kamm <kamm-incasoftware removethis.de> writes:
 Christian Kamm wrote:
 One point we couldn't understand though, is the reversal of parameters
 when calling some D functions: Parameters are usually passed
 right-to-left, except for nonvariadic D functions, where the order
 changes to left-to-right.
 
 What is the reason for it?


Walter Bright wrote:
 The reason is because I'd eventually like to specify the order of
 evaluation of function arguments as being left to right. So, for normal
 D functions, this makes for optimal code generation. The only time
 monkey business would have to happen would be to support the C calling
 convention or the variadic one.

What about generally passing left-to-right for D functions then? If foo(a1,...,an) was passed as (this), a1, ..., an, (_arguments), (hidden) with the first parameter in EAX if possible, we'd have the neatness of "member function pointers have context as first arg" and the possibility of specifying left-to-right evaluation order easily. We'd lose the ability to pass hidden in EAX though.
Oct 28 2008
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Christian Kamm wrote:
 with the first parameter in EAX if possible, we'd have the neatness
 of "member function pointers have context as first arg" and the possibility
 of specifying left-to-right evaluation order easily. We'd lose the ability
 to pass hidden in EAX though.

EAX always gets the last argument evaluated, because evaluating an expression often naturally winds up in EAX.
Oct 29 2008
parent reply Christian Kamm <kamm.without this.incasoftware.de> writes:
Walter Bright Wrote:
 EAX always gets the last argument evaluated, because evaluating an 
 expression often naturally winds up in EAX.

Ah, right. I didn't think of that. Do I understand correctly that in order to get the 'context as the first arg' behavior, we'd have to drop either EAX or left-to-right passing? Maybe it's not worth it then.
Oct 29 2008
parent Walter Bright <newshound1 digitalmars.com> writes:
Christian Kamm wrote:
 Do I understand correctly that in order to get the 'context as the
 first arg' behavior, we'd have to drop either EAX or left-to-right
 passing? Maybe it's not worth it then.

I don't think it's worth it. Passing it in EAX is a big performance win.
Oct 29 2008
prev sibling parent reply "Lionello Lunesu" <lionello lunesu.remove.com> writes:
 As a somewhat related, but separate issue, this would open the door to 
 real
 easy pointer-to-members. Given

 class C {
  void foo(int i) { ... }
 }

 you could have

 typeof(C.foo) == void function(C, int)

 and

 auto memberfn = &C.foo;
 memberfn(new C, 42);

 would work too.

Is it possible to solve this problem and also solve the problem mentioned in the thread "implicitly convert function pointers to delegates"? Or are these two mutually exclusive? L.
Oct 28 2008
parent reply Christian Kamm <kamm-incasoftware removethis.de> writes:
 Is it possible to solve this problem and also solve the problem mentioned
 in the thread "implicitly convert function pointers to delegates"? Or are
 these two mutually exclusive?

The two things are separate. Delegates are functions that have the context argument bound. This is about the passing order of arguments.
Oct 28 2008
parent reply "Lionello Lunesu" <lionello lunesu.remove.com> writes:
"Christian Kamm" <kamm-incasoftware removethis.de> wrote in message 
news:ge9044$1l0d$1 digitalmars.com...
 Is it possible to solve this problem and also solve the problem mentioned
 in the thread "implicitly convert function pointers to delegates"? Or are
 these two mutually exclusive?

The two things are separate. Delegates are functions that have the context argument bound. This is about the passing order of arguments.

But it matters how delegates pass the context pointer. In order to call functions using a delegate, the functions should silently ignore the context pointer. Which means they should never expect any argument to be passed in that register, or accept an argument on the stack that can be ignore (last one?).. I don't know the details, but I think these two issue are very closely related. L.
Oct 29 2008
parent Tomas Lindquist Olsen <tomas famolsen.dk> writes:
Lionello Lunesu wrote:
 
 "Christian Kamm" <kamm-incasoftware removethis.de> wrote in message 
 news:ge9044$1l0d$1 digitalmars.com...
 Is it possible to solve this problem and also solve the problem 
 mentioned
 in the thread "implicitly convert function pointers to delegates"? Or 
 are
 these two mutually exclusive?

The two things are separate. Delegates are functions that have the context argument bound. This is about the passing order of arguments.

But it matters how delegates pass the context pointer. In order to call functions using a delegate, the functions should silently ignore the context pointer. Which means they should never expect any argument to be passed in that register, or accept an argument on the stack that can be ignore (last one?).. I don't know the details, but I think these two issue are very closely related. L.

As I see it there are really 3 different scenarios we'd (do we?) like to support: 1) converting a function pointer to a delegate 2) converting a member function pointer to a function pointer 3) converting a delegate to a function pointer 1) seems to be easiest by having the compiler generate a small wrapper that takes care of the differences in number of arguments. 2) would be easy to solve given the stuff mentioned in this thread 3) isn't really hard to solve either, at least in terms of LDC (thus LLVM), you'd just generate a trampoline.
Oct 29 2008