Re: x86-64 and calling conventions

"cr88192" <>
Thu, 15 May 2008 07:44:35 +1000

          From comp.compilers

Related articles
[6 earlier articles]
Re: x86-64 and calling conventions (cr88192) (2008-05-13)
Re: x86-64 and calling conventions (glen herrmannsfeldt) (2008-05-13)
Re: x86-64 and calling conventions (James Harris) (2008-05-14)
Re: x86-64 and calling conventions (Vidar Hokstad) (2008-05-14)
Re: x86-64 and calling conventions (James Harris) (2008-05-14)
Re: x86-64 and calling conventions (cr88192) (2008-05-15)
Re: x86-64 and calling conventions (cr88192) (2008-05-15)
Re: x86-64 and calling conventions (Bart) (2008-05-14)
Re: x86-64 and calling conventions (cr88192) (2008-05-15)
Re: x86-64 and calling conventions (Boleslaw Ciesielski) (2008-05-23)
Re: x86-64 and calling conventions (glen herrmannsfeldt) (2008-05-29)
| List of all articles for this month |

From: "cr88192" <>
Newsgroups: comp.compilers
Date: Thu, 15 May 2008 07:44:35 +1000
Organization: Saipan Datacom
References: 08-05-031 08-05-043 08-05-048
Keywords: design, storage
Posted-Date: 14 May 2008 22:41:22 EDT

"glen herrmannsfeldt" <> wrote in message
> Dave Parker wrote:
> (snip)
>> The calling convention is left-to-right (since I was making my own
>> calling convention, I figured I might as well fix the old right-to-
>> left holdover and use the stack the way the stack should be used ---
>> left-to-right). Left-to-right means the arguments are evaluated in
>> the order that users expect them to be. If the function is vararg,
>> then I push the argument count on the stack last.
> That doesn't sound very convenient. I have known for a while now that
> ANSI C requires varargs routines to be declared as such so that a
> different calling convention could be used.
> So far, I haven't known any that actually did that, though.
> If you always push the length, one could use it to find the address of
> the first argument, and then subsequent arguments.
> As far as passing arguments in registers, there is at least one
> convention (possibly SPARC, but I am not sure now) where some are
> passed in registers, but stack space is still reserved for them. The
> called routine can then store them into the stack. As some number of
> words are kept in the registers, in some cases a double variable will
> be half in a register and half on the stack. Storing to the stack is
> a convenient way to get the two back together again.

the AMD64/SysV/... convention is IMO one of the most awkward I am
aware of... not only does it pass things in registers, but: no space
is left on the stack, and the relative 'order' of the GPRs, XMM regs,
and stack, are not kept in sync.

the MS convention is a little nicer, as at least it leaves space on
the stack and uses a fixed ordering, even if it is theoretically a
little less efficient with registers.

had I been designing a similar calling convention, likely it would
have been a tradeoff...

6 args in regs, likely:
rsi, rdi, r8, r9, r10, r11
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5.

rbx, rbp, r12-r15 are callee preserve
xmm10-xmm15 are callee preserve

like MS, args are in a fixed relative ordering, so: a value is either
in a given GPR, a given XMM reg, or on the stack; stack space is
preserved for each arg, and is an appropriate size for the type;
arguments are not decomposed, so a struct is either in an XMM reg
(<=16 bytes), or in a pointer.

this would at least make it a little simpler to dump args to the
stack, and fetch them from the stack (albeit we still need to know
which is which...), and would not have much of a performance impact
(actually it could help I think).

in some cases (particularly varargs), all arguments would be on the stack.

a much simpler convention would be to always pass args on the stack
(as in x86 cdecl), but this would hurt performance some...

sadly, knowing either the exact args count (varargs), or which arg is
where, can't be done without a performance impact.

In One Of My Earlier Compiler Versions (x86), I had, however, used ebx
for marking the end of the args list. this was also because, at the
time, my compiler was much less refined so I used ebx also as the
means of cleaning up the stack (later on, the compiler kept track of
this itself, so using ebx was no longer needed...).

similar "could" be employed, at a small cost, in the case of varargs.

Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.