f



x86-64 and calling conventions

Well, I have my own compiler, however, I don't as of yet target x86-64.

one of the main reasons:
the calling conventions used in Linux and friends are, scary...


Short Description:
arguments are passed in registers, meanwhile, others may be left on the
stack, and there is no particular relation between the registers and the
stack layout.

Beyond Just Putting A Big Damper On The Compiler Machinery, It Leaves Many
Ugly Questions:
how does one effectively deal with varargs? (of all things, the convention
still uses regs even for passing varargs...).

it seems almost like one will have to dump all of the registers into a kind
of a context, and keep note of particular counts (GPR pos, XMM pos, stack
pos).

how does one do things like hidden argument injection? (useful for many
tasks, such as closures).
.....


Or, in general, there are all sorts of ugly questions wrt the topic of
actually working with the args list in a first-class manner (beyond just the
task of having to get the compiler to work with all this to begin with).


I am left considering the idea of abandoning this convention for internal
usage, and instead using a different default calling convention. probably,
name mangling would be used to distinguish them, and interface stubs would
be generated to handle external calls.

sadly, this would lead to a big issue, which is that there would be a kind
of a "wall" between the two worlds. firstly, interface stubs would be
needed, and secondly, that function pointers could not be safely passed
across this wall (limiting the usage of callbacks, ...).

more-so, these stubs could potentially be limited in terms of what they can
pass along (functions passing raw structs or similar stack-disordering
features may not be wrapable).

so, such a wall could be very problematic (especially in a mixed-compiler
codebase).


now, what kind of convention would I be imagining:
well, basically, it would be a hybrid of the existing conventions, and the
good old 32-bit x86 convention.

in particular, arguments would be passed on the stack (in good old linear
right-to-left ordering).


now, beyond this wall, there is also a possible risk of a performance impact
(both with calls, and in general).

it is also possible I could just "bear with it", and possibly use
stack-flattening/unflattening hacks mostly as a means of dealing with edge
cases.


alternatively, I could use a variant of the MS convention by default (even
on Linux), which is basically about the same (it being fairly simple to dump
arguments to the shadow space, or retrieve them from there).

the task of defeating the "wall" would then be a task for later...


any suggestions?
[My suggestion is that if you want people to use the compiler, use the same
calling sequence as everyone else.  The code to deal with varargs is ugly,
but I would be surprised if it were very long. -John]
0
cr88192355 (1928)
5/11/2008 11:44:42 PM
comp.compilers 3310 articles. 1 followers. Post Follow

16 Replies
2223 Views

Similar Articles

[PageSpeed] 19

"cr88192" <cr88192@hotmail.com> wrote in message
> Well, I have my own compiler, however, I don't as of yet target x86-64.
>
> one of the main reasons:
> the calling conventions used in Linux and friends are, scary...
>
>
> Short Description:
> arguments are passed in registers, meanwhile, others may be left on the
> stack, and there is no particular relation between the registers and the
> stack layout.
>
> Beyond Just Putting A Big Damper On The Compiler Machinery, It Leaves Many
> Ugly Questions:
> how does one effectively deal with varargs? (of all things, the convention
> still uses regs even for passing varargs...).

<snip>

> alternatively, I could use a variant of the MS convention by default
> (even on Linux), which is basically about the same (it being fairly
> simple to dump arguments to the shadow space, or retrieve them from
> there).
>
> the task of defeating the "wall" would then be a task for later...
>
> any suggestions?
> [My suggestion is that if you want people to use the compiler, use
> the same calling sequence as everyone else.  The code to deal with
> varargs is ugly, but I would be surprised if it were very
> long. -John]


Yes, this is probably what I will have to do.
the convention is a little bit of a horror, but I guess it has to be lived
with...


after all, it is probably my due punishment for writing yet another C
compiler.  it will also be the cost for trying to add an x86-64
target.

well, I do JIT and I focus on somewhat different goals than those of
LLVM and similar.  probably a good enough justification.

all just the fiddling of some lowly hobbyist anyways...


general context:

the compiler exists as 2 major parts:
an upper compiler, which does parsing and a lot of the higher-level
transformations;
the lower compiler, which takes the RPN-based output of the upper compiler,
and compiles it into assembly code.

the JIT is simply an integrated assembler and linker (I use an
NASM-like syntax, and it can also dynamically load COFF, ELF, GNU-AR
libs, ... and can export COFF).

Win32 is my primary target, with Linux (x86 and x86-64) as secondary
targets. Win64 may also be a target at some point.

the primary use at present is as a scripting VM. technically, pretty damn
overkill, but this is the price I pay to not have to endlessly deal with
stupid FFI issues. now I just deal with code-generation issues...


later on, I may also incorporate a Java frontend as well (currentlly, I only
have a C frontend).

it is my eventual hope to use it for implementing something much closer to
the high-level scripting languages I have usually implemented in the past,
yet while hopefully still being solidly attached to C-land...

a nearer term goal is to add both lexical closures and eval as C extensions
(note: I already have garbage collection, dynamic types, geometric vectors
and quaternions, ... as compiler extensions).

note, on x86 maintaining the integrity of the calling convention and proper
threading has been an invariant goal (it not being acceptable for features
either to break the calling convention or violate threading).


my previous lower compiler was based on a stack machine, which later ended
up using register allocation and similar more as a means of optimization;
basically the lower compiler is an elaborate mass of fixed logic trees.

later on, I had started a rewrite (highly delayed due to getting backlogged
with homework and similar...).
I started building from the bottom up, targetting both x86 and x86-64 at the
same time, and reusing some of the codegen machinery from the previous lower
compiler.


what I have now is basically a bunch of register allocation machinery, code
for performing various operations on registers, and code for performing
low-level memory operations.

however, I started to get a little stalled as to which direction I would go.
I am thinking of adding an intermediate representation basically consisting
of a kind of value flow graph.

this would imply a new upper end of the lower compiler, basically converting
from RPN into the graph representation (and also handling most of the
typesystem machinery and similar), possibly doing some fiddling, and then
flattening it back out in the process of converting it into assembly code
(the big hassle here being that registers have to be allocated in effective
reverse order...).


all of this will be because I don't really think it is possible to target
x86-64 with a big mass of fixed-logic being driven by the RPN-based input
(this works for x86, but doesn't really look like it will work for x86-64, a
graph being necessary just to generate working code it seems...).


but, I don't know if there is much point in all this, or if I am headed in a
good direction.

general opinions?...


or such...
0
cr88192
5/12/2008 10:10:59 AM
On 12 May, 00:44, "cr88192" <cr88...@hotmail.com> wrote:
> Well, I have my own compiler, however, I don't as of yet target x86-64.
>
> one of the main reasons:
> the calling conventions used in Linux and friends are, scary...

I'm working on a language where the call conventions are to be filled-
in after compilation. Each function is to compile to also use virtual
registers rather than real ones. Then only when one function calls
another do we set up the registers for both functions, the calling
conventions to pass data between them, and decide which regs to either
spill or save.

I should say this is work in progress. I'm not sure how well it will
work but expect that for small called functions there may be useful
gains. Oh, yes, the decision as to whether to inline small functions
will happen at the same time (based on optimisation speed/space
goals).

Not sure if that's any help. If it works it would illustrate that
subroutine and OS calling conventions can be plugged in after and are
distinct from code generation. OS calls are just function calls where
the callee's needs have already been decided - stack for Windows, regs
for Linux etc.

--
James
[How do you plan to handle function pointers? -John]
0
James
5/12/2008 11:12:03 AM
On May 12, 12:44 am, "cr88192" <cr88...@hotmail.com> wrote:
> Well, I have my own compiler, however, I don't as of yet target x86-64.
>
> one of the main reasons:
> the calling conventions used in Linux and friends are, scary...
>
> Short Description:
> arguments are passed in registers, meanwhile, others may be left on the
> stack, and there is no particular relation between the registers and the
> stack layout.

Ouch. This is hideous. Since I didn't know what you were talking
about, but is in the process of writing a compiler in Ruby (currently
targeting 386, but I want to add x86_64 later) I did a search and came
up with this: http://www.x86-64.org/documentation/abi-0.99.pdf

I can see why you consider it scary. My compiler is taking a lot of
ideas from Ruby, and that includes being able to take all arguments as
an array, which is trivial on 32 bit x86, but a real pain here..

There are a number of callee saved registers, so you can do some forms
of extension of the calling convention without losing the ability for
your code to call out to C without interface stubs, but you'd lose the
ability for C to call back in, of course (I made that sacrifice in my
compiler for varargs, where I pass the count of varargs provided in a
register, in which case you'll need a wrapper to safely call it from
C, but if my code calls varargs C functions, the value of that
register will just be ignored).

Apart from that, I'd strongly suggest you stick with the calling
convention, even though it's painful. To handle higher order argument
lists you could always synthesize an anonymous conversion function if
needed, to turn it into an array or iterate over the arguments.

As for "hidden arguments", presumably they won't be hidden to the C
code anyway, or the values would be lost when crossing the barrier, so
there I'd consider just treating them as normal arguments with respect
to the calling convention and just hiding them to the users of your
language.

There's in practice nothing outright stopping you from defining your
function signatures in a way which will force all the arguments onto
the stack and still comply with this calling convention, either, as
far as I can see, but it'd result in function signatures that would be
extremely inconvenient to work with on the C side, and you'd still
have a problem calling C code unless your compiler explicitly knows
when it needs to resort to the C calling convention.

I'd bite the bullet...

Vidar
0
Vidar
5/12/2008 12:48:02 PM
On May 11, 5:44 pm, "cr88192" <cr88...@hotmail.com> wrote:
> now, what kind of convention would I be imagining:
> well, basically, it would be a hybrid of the existing conventions, and the
> good old 32-bit x86 convention.
>
> in particular, arguments would be passed on the stack (in good old linear
> right-to-left ordering).

That's kind of what I did in the Flaming Thunder compiler (which
supports the x86 and x86-64 versions of FreeBSD, Linux, Mac OS X and
Windows).

Some differences:

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.

When I need to access a system service, I translate my stack layout to
the Windows/Mac/Linux/FreeBSD/32/64 layout, then call the system.
0
Dave
5/13/2008 3:10:58 AM
"Dave Parker" <daveparker@flamingthunder.com> wrote in message
> On May 11, 5:44 pm, "cr88192" <cr88...@hotmail.com> wrote:
>> now, what kind of convention would I be imagining:
>> well, basically, it would be a hybrid of the existing conventions, and
>> the
>> good old 32-bit x86 convention.
>>
>> in particular, arguments would be passed on the stack (in good old linear
>> right-to-left ordering).
>
> That's kind of what I did in the Flaming Thunder compiler (which
> supports the x86 and x86-64 versions of FreeBSD, Linux, Mac OS X and
> Windows).
>
> Some differences:
>
> 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.
>
> When I need to access a system service, I translate my stack layout to
> the Windows/Mac/Linux/FreeBSD/32/64 layout, then call the system.

yes, though possible, there is a biggie issue with this: it would be
rather painful in the case of mixed-compiler codebases.

Also, in my case for the time being I am limited to right-to-left
ordering, since that is what I am getting out of the upper compiler
(for x86, I more or less layed out all of the logic in a fixed
ordering, namely that of execution on x86, however this ordering does
not work so well for x86-64...).

Recently, I had started beating together code for internally using
SSA, but this does not look like it will be so easy. SSA seems, rather
awkward... a big issue is that one ends up with a graph, and rather
than being driven either imperatively, or simply by unwinding a tree,
requires (as it was turning out in my case at least) identifying
top-level expressions and stepping along the graph doing register
allocation and such.

Just as of writing this, I have had an interesting idea: it could be
possible to abandon my current RPN based representation, and
reimplement a lot of the machinery from the RPNIL compiler into a
modified form of the existing upper compiler.

The result would be replacing the big mass of fixed-form code
(basically, a structure driven purely by a central switch statement
and a big mass of function calls), with likely a much bigger mass of
XML processing (the current upper compiler being structured around
processing DOM trees).

This would likely imply adding another XML-based stage (likely,
working out all of the type mechanics, ...), the output of which would
then be converted directly to SSA.

A slight modification of this idea would be to use the DOM trees to
directly drive the low-level code generation (XML could likely serve a
similar role to what I am imagining with SSA, albeit there is little
to stop SSA from being represented is XML as well). in this case,
register allocation and codegen would be driven directly by the
process of flattening out these trees.

Never Mind that all this would imply discarding and rewriting almost
everything located between the parser and the low level code
generation (even as such, it could be less work than SSA+reworking the
RPN compiler to target SSA).

Another possible advantage is that, for the implied notable loss of
abstraction, it could make the whole compiler core a lot more open and
flexible (thus easing the addition of new features and possible non-C
languages).

In all this, pretty much everything above low-level code generation,
would become a big mass of transforms applied to globs of XML (I will
just have to deal some with the awkwardness and verbosity of XML
processing... XSLT almost looks tempting...).

possible layout:
parser (intact);
expression reduction, inlining, ... (heavily modified);
expression type propagation and decomposition (new);
tree flattening, register allocation (new, directly-drives next down);
low-level code generation (intact);
assembler, ...



more in general:

I tend to use my compiler right along with gcc, using gcc more as a
static compiler, and mine more as a dynamic compiler.

reasons:
though some code is likely to be highly volatile, other code is likely to be
mostly static;
compiling C code, especially large amounts of it, also tends not to be a
super fast process (sadly, my compiler is not the fastest option WRT
compiling speed...);
likewise, though there are many cases where my compiler does well, at
present gcc generally does better (in terms of general performance and
non-buggy output).

Thus It Is Effective To Compile Parts Of The App Statically, And Other
Parts Dynamically.  some parts are linked into the executable, and
other parts are static libraries (however, at present, the entire
library tends to be linked in, wheras later it may be better to
demand-link missing symbols).

Later plans may involve caching and demand compilation (we have the
source, and automatically recompile those parts that have changed).

or such...
0
cr88192
5/13/2008 7:51:07 AM
"Vidar Hokstad" <vidar.hokstad@gmail.com> wrote in message
> On May 12, 12:44 am, "cr88192" <cr88...@hotmail.com> wrote:
>> Well, I have my own compiler, however, I don't as of yet target x86-64.
>>
>> one of the main reasons:
>> the calling conventions used in Linux and friends are, scary...
>>
>> Short Description:
>> arguments are passed in registers, meanwhile, others may be left on the
>> stack, and there is no particular relation between the registers and the
>> stack layout.
>
> Ouch. This is hideous. Since I didn't know what you were talking
> about, but is in the process of writing a compiler in Ruby (currently
> targeting 386, but I want to add x86_64 later) I did a search and came
> up with this: http://www.x86-64.org/documentation/abi-0.99.pdf
>
> I can see why you consider it scary. My compiler is taking a lot of
> ideas from Ruby, and that includes being able to take all arguments as
> an array, which is trivial on 32 bit x86, but a real pain here..

yeah.


> There are a number of callee saved registers, so you can do some forms
> of extension of the calling convention without losing the ability for
> your code to call out to C without interface stubs, but you'd lose the
> ability for C to call back in, of course (I made that sacrifice in my
> compiler for varargs, where I pass the count of varargs provided in a
> register, in which case you'll need a wrapper to safely call it from
> C, but if my code calls varargs C functions, the value of that
> register will just be ignored).
>

my compiler is for C...

the ability to make calls need to be bidirectional...


> Apart from that, I'd strongly suggest you stick with the calling
> convention, even though it's painful. To handle higher order argument
> lists you could always synthesize an anonymous conversion function if
> needed, to turn it into an array or iterate over the arguments.
>
> As for "hidden arguments", presumably they won't be hidden to the C
> code anyway, or the values would be lost when crossing the barrier, so
> there I'd consider just treating them as normal arguments with respect
> to the calling convention and just hiding them to the users of your
> language.

my language is C...

Actually, the hidden arguments are more within the compiler-generated
function body. it itself is wrapped by another automatically generated
wrapper (which has the same interface as the original function).

The added argument would basically be a context representing the
closures' environment...


> There's in practice nothing outright stopping you from defining your
> function signatures in a way which will force all the arguments onto
> the stack and still comply with this calling convention, either, as
> far as I can see, but it'd result in function signatures that would be
> extremely inconvenient to work with on the C side, and you'd still
> have a problem calling C code unless your compiler explicitly knows
> when it needs to resort to the C calling convention.

well, this wont work in my case.


> I'd bite the bullet...

will probably have to.
0
cr88192
5/13/2008 8:19:29 AM
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.

-- glen
0
glen
5/13/2008 9:28:57 AM
On 12 May, 12:12, James Harris <james.harri...@googlemail.com> wrote:
> I'm working on a language where the call conventions are to be filled-
> in after compilation. Each function is to compile to also use virtual
> registers rather than real ones. Then only when one function calls
> another do we set up the registers for both functions, the calling
> conventions to pass data between them, and decide which regs to either
> spill or save. ...

> [How do you plan to handle function pointers? -John]

You mean how to call routines which are dynamically chosen? I'm not
sure I'll have function pointers as such but maybe first class
functions having the same issue. If the caller does not know which
function it will call at the time of compilation perhaps the caller
could fall back to saving all in-use registers and using a generic
method to pass parameters

1. on the stack,
2. in registers,
3. in a block of memory.

Of course, any function which could potentially be called dynamically
would need to use the matching mechanism to retrieve its parameter
values. Things get more interesting if a function could be called
either statically or dynamically. In that case it may need to support
more than one method of parameter passing. Options here? 1. Header and
footer glue code - possibly the more complex of the two glue code
sequences calls the simpler or both types of glue code call the
function proper, 2. Duplicate functions - especially if the function
is short its code could be duplicated between suitable headers and
footers.

Does that sound like it would work? Maybe you meant something entirely
different!

By the way, the idea of duplicating code is intended to be quite
widespread in order to achieve speed. Two cases where that may apply:

First, when the number of iterations is small some iterable constructs
may be implementable more efficiently than in a loop. As an example,
the IBM 360 instruction set includes an insert characters under mask
instruction which can load bytes into a register. It may be the
fastest (and shortest) way to pick up unaligned bytes from memory
where the number of bytes is three or fewer. For higher numbers a loop
may be more appropriate.

Second, where parameters have default values execution may be faster
to execute if there is a copy of the code which uses the defaults.
After all, constants provide ways to optimise that are not possible
when variables are used. There would also need to be a piece of code
emitted for the more general case.

--
James
[Are you considering cache behavior?  If you duplicate a lot of code,
it becomes less likely that it'll fit in the cache. -John]

0
James
5/14/2008 10:38:42 AM
On May 13, 4:10 am, Dave Parker <davepar...@flamingthunder.com> wrote:
>  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.

The evaluation order and the calling convention don't need to be tied
together, though. Gcc on i386 for example subtracts the required
number of words from %esp and then copy the arguments into place via
indexed indirect mov's. No idea if that is slower or faster than
push'ing stuff onto the stack instead, but the version of gcc I've
used "gcc -S" on will use the mov approach even if all arguments are
constants.

Vidar

0
Vidar
5/14/2008 3:20:27 PM
On 14 May, 11:38, James Harris <james.harri...@googlemail.com> wrote:
....

> By the way, the idea of duplicating code is intended to be quite
> widespread in order to achieve speed.


> [Are you considering cache behavior?  If you duplicate a lot of code,
> it becomes less likely that it'll fit in the cache. -John]

Well, I'm aware of the issue but I don't have a general formula as yet
to know when to generate alternate copies of code and when not to do
so. Things I can say:

1. This is a code generation issue. The viability of using alternate
copies depends in large part on the target CPU. As such the IR is to
have only the simple loop code.
2. As long as the same alternative of the function code is called
repeatedly in an inner loop the benefits of code cacheing should still
apply. The natural extension of calling the same variant each time is
inlined code which will be appropriate in some cases.

Is it worth it? Although I cannot quantify the gains yet it is easy to
demonstrate cases where loops with few iterations are faster encoded
with non-loop instruction sequences. This applies even including a
test and branch (which is not needed if the iteration count is
constant or predictable). If the test and branch is needed viability
depends on correct branch prediction. In terms of ease of use I want
the programmer who uses the language to be able to code simple loops
without having to think about special per-CPU cases to gain speed, and
to be able to leave efficient code generation to the compiler.

The main intended benefit is the source code can be written
independently of word length and will thus scale to arbitrary-length
data (i.e. it can be more general) without sacrificing performance in
the smaller cases.

Don't code generators do this kind of thing as a matter of course?
--
James
[Yes, loop unrolling and software pipelining are well known
optimizations. -John]

0
James
5/14/2008 6:37:05 PM
"Vidar Hokstad" <vidar.hokstad@gmail.com> wrote in message
> On May 13, 4:10 am, Dave Parker <davepar...@flamingthunder.com> wrote:
>>  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.
>
> The evaluation order and the calling convention don't need to be tied
> together, though. Gcc on i386 for example subtracts the required
> number of words from %esp and then copy the arguments into place via
> indexed indirect mov's. No idea if that is slower or faster than
> push'ing stuff onto the stack instead, but the version of gcc I've
> used "gcc -S" on will use the mov approach even if all arguments are
> constants.

on x86, sub+mov's is actually a little faster I think.

The reason is, I think push gets decomposed into a mov and a sub
internally.  more so, since esp gets modified, no other instructions
can use it until the next clock (or such...).

Meanwhile, several parallel mov's can be pipelined, which is faster.

In my case, I have usually tended to use a hybrid approach...
0
cr88192
5/14/2008 8:46:20 PM
"glen herrmannsfeldt" <gah@ugcs.caltech.edu> 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
or:
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.
0
cr88192
5/14/2008 9:44:35 PM
On May 12, 11:10 am, "cr88192" <cr88...@hotmail.com> wrote:
> "cr88192" <cr88...@hotmail.com> wrote in message

> a nearer term goal is to add both lexical closures and eval as C extensions
> (note: I already have garbage collection, dynamic types, geometric vectors
> and quaternions, ... as compiler extensions).

Dynamic types in C? How would that work from a programmer viewpoint?

--
Bartc
0
Bart
5/15/2008 2:22:59 AM
"Bart" <bc@freeuk.com> wrote
> On May 12, 11:10 am, "cr88192" <cr88...@hotmail.com> wrote:
>> "cr88192" <cr88...@hotmail.com> wrote in message
>
>> a nearer term goal is to add both lexical closures and eval as C
>> extensions
>> (note: I already have garbage collection, dynamic types, geometric
>> vectors
>> and quaternions, ... as compiler extensions).
>
> Dynamic types in C? How would that work from a programmer viewpoint?

Should have been worded 'language extensions', as technically only the
geometric vectors and quats are true compiler extensions (dynamic typing and
garbage collection being, simply, runtime extensions...).

It Works About Like This:
A single type that can hold other objects of the same type, which just
happens to be any number of other types...

At Present, They Exist Mostly As A Library Feature (Still Fairly Usable
Though), Where Functions Respond To Whatever They Are Given And Respond In
Some Way That Is Reasonable For The Types They Are Given.

the main detractor though is that in currently lacking specialized compiler
functionality, they are not as nice as they could be (for example, the don't
automatically wrap or unwrap types, lack builtin operators, ...).

however, the API is not all that bad, since I made most of the operation
names fairly short (such as 'dyadd', 'dysub', ...). this also allows the
system to remain usable from gcc-compiled code...

note that naturally the dynamic and static typesystems would be
non-orthogonal, so it is neither reasonable to expect malloc'ed memory to
behave as a dynamic type, nor to meaningfully expect to get a pointer to
part of a dynamic object (or, at least, when they do, they are outside of
dynamic-typing land...).


geometric vectors and quaternions, however, are compiler extensions (and
this is one place my compiler can somewhat outperform GCC, where my compiler
tends to fall behind some on scalar intensive tasks, ...).

there was just more compelling reason to add vectors than to fully integrate
the dynamic types (note that API and funky code is added, so that, like
dynamic types, a partial version is still available within GCC as well,
albeit lacking the specialized operators and thus requiring use of
functions...).
0
cr88192
5/15/2008 5:44:11 AM
glen herrmannsfeldt wrote:
> 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.

This is the case for 32-bit PowerPC.

Bolek

0
Boleslaw
5/23/2008 4:05:14 PM
Boleslaw Ciesielski wrote:
(I wrote)

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

> This is the case for 32-bit PowerPC.

It seems the one I was remembering is SPARC.  The LCC book, "A
Retargetable C compiler: Design and Implementation," describes code
generators for MIPS R3000, SPARC, and x86.

For SPARC, the first 24 bytes of arguments go in registers, even if a
double is split in half.  Stack space is allocated for them, and also
16 words to store other registers if the register stack overflows.
Floating point values are passed in i registers, so have to be stored
anyway before they can be loaded into floating point registers.  It
would have seemed more convenient to pass floating point values in
floating point registers, but that may not be compatible with C,
especially in the case of varargs.

-- glen

0
glen
5/29/2008 9:56:05 PM
Reply:

Similar Artilces:

misc, OT: C compiler, x86-64 or not x86-64...
well, I have my C compiler, for now, for the most part, it is working (and being used in my projects for its amazing scripting powers). but, now, there is a new mystery: do for now, I count my blessings, and just continue using it for plain x86, or partly branch my lower compiler and make an x86-64 version as well?... before, I had thought, well, x86-64 would very likely require nearly completely rewriting my lower compiler. now, maybe, maybe not (could be able to get by just with minor modifications...). me now thinking, as it is structured, it would be less work than it would have be...

What is the different between c++ call convention and c call convention?
What is the different between c++ call convention and c call convention?Can some give some examples? On Thu, 6 Dec 2007 19:25:57 -0800 (PST), dolphin <jdxyw2004@gmail.com> wrote in comp.lang.c++: > What is the different between c++ call convention and c call > convention?Can some give some examples? Neither C nor C++ define a "calling convention". Particular compilers provide their own "calling conventions", generally based on the underlying processor architecture and usually also on the operating system that the code will run under. If you are interested i...

[9fans] Plan9 Calling Convention (x86)
Hi, I'm in the process of porting dyncall (http://dyncall.org) to Plan9, and I was wondering if there are any documents about the calling convention used by Plan9 - specifically for x86, for starters. I was unable to find any at the time of writing, and well, hoped that it would be similar to the SystemV calling convention(s) used by the *BSDs or Linux, etc., but that doesn't seem to be the case. The only information I found so far, is, that most of the compiled Plan9 functions don't seem to have any prologue/epilogue, however, this assumption might be wrong (maybe I did...

New Intel compilers for x86-64
Intel's compiler suite now has support available for x64 systems. It also looks like Intel is playing nice for right now, and not doing anything to prevent their code from working on AMD systems. Versions available for Linux and Windows, even though Windows for x64 isn't due out till 2005. http://news.zdnet.com/2100-9584_22-5393204.html?tag=default Yousuf Khan -- Humans: contact me at ykhan at rogers dot com Spambots: just reply to this email address ;-) "Yousuf Khan" <bbbl67@ezrs.com> wrote : > Intel's compiler suite now has support available for...

High calling overhead when calling compiled functions from C++ application (V4.0 Compiler)
Hi, I have just started using V4.0 of the compiler and am doing some performance testing. I am interested particularly in calling Matlab functions from a C++ program. From my initial tests, I am concerned about the cost of invoking a function. Calling a compiled version of the the following minimal function: function [ out ] = return_input( in ) out = in; ....from a C++ application takes an average of 15 ms per call (averaged over 1000 calls). As a comparison from Matlab console, it takes 6 microseconds (1/2500 of the time). tic; for ( i=1:1000000 ) return_input( 99.9 ); end toc; El...

bind calls fails when compiled in OBJECT_MODE=64
Hi , I have a simple program here which binds to a socket. This program works fine in my AIX box when compiled in 32-bit mode. If I set 'OBJECT_MODE=64', then compile, bind call fails with errno : 68. (EADDRNOTAVAIL 68 /* Can't assign requested address */) $ cc -o test_bind test_bind.c $ ./test_bind IP: 130.35.138.14 $ file test_bind test_bind: executable (RISC System/6000) or object module not stripped $ ldd test_bind test_bind needs: /usr/lib/libc.a(shr.o) /unix /usr/lib/libcrypt.a(shr.o) $ export OBJECT_MODE=64 $ cc -o test_bind test_bind.c ...

64 bit Fortran compiler test suite .... or how to develop 64 bit compiler test suite?
hello Everybody Hi, I have just ported My Fortran 90 Compiler on IBM AIX-5.3.0.0. Now teh compiler is able to generate 64 bit binaries. And i have also enhanced my FORTRAN compiler to support integer up to 8 bytes(INTEGER*8 or INTEGER(KIND=8). But I don't have test cases how to do proper testing. Actually i am confused about what the meaning of testing 64 bit compiler???? I did not get any free test suit for tesing 64 bit compiler...... I am having FCVS. But it does not cover 64 bit test suite. Can any one tell me from where i acn get 64 bit FORTRAN compiler Test suit????? Or wh...

By default, which calling convention C55 compiler is using?
Which one? c55_std? c55_compat? c55_new? TIA. ...

Compiling with 64-bit libcrypt on Solaris x86
I am running Solaris 10 x86 10/08 on an X2200M2 using Sun Studio 12 C compiler. I am compiling a 64-bit shared library and need to use the 64-bit libcrypt library. When I compile in 32-bit mode, I use the "-l crypt" option on my compile command. This same option for a 64-bit mode compilation gives me the error: ld: fatal: library -lcrypt: not found I noticed the following symlinks under the /usr/lib directory: /usr/lib/libcrypt.so -> libcrypt_d.so /usr/lib/libcrypt_d.so -> ./libcrypt_d.so.1 The corresponding symlinks are not under /usr/lib/amd64. I have been able to get ...

"C" calling convention on x86
Good day, in attempting to call externally compiled "C" code from asm, I've been trying to understand the "C" calling convention on x86. Below is what I think to be the way it all works. If anybody could confirm/deny/correct this I'd be most grateful. The 'C' calling convention on a x86: ==================================== - args are pushed right to left - caller must free args Arguments: ---------- - 1, 2 or 4 byte integers pushed onto stack as single DWORDs - 8 byte integers are pushed onto stack as two DWORDs, the most significant DWORD is ...

calling convention used by the avr-gcc compiler
Hi there, I want to know about the calling convention used by the avr-gcc compiler. Can anyone please refer any document or manual where I can look for the calling convention ? Thank you, Prinyanka ...

Disassembler for x86/x86-64
Hello everybody, I would like to announce the release of the 4th (Alpha-release) of the development series of releases of udis86/64 - a binary file disassembler for the x86/x86-64 architectures. Udis86 is a binary file disassembler for the x86 and x86-64 (AMD64) architectures, capable of disassembling 16/32/64 bit binary files to AT&T or Intel assembly language syntax. It also supports all MMX, SSE, FPU(x87), AMD 3Dnow! instructions. It focuses on providing the basic disassembler functionality in executable format as well as through a static library libudis86.a for use as the core of obj...

Summer of Code project (x86 calling conventions, SBCL)
One of the Summer of Code projects I proposed to the lispNYC which ended up not being funded was to investigate the effect of calling conventions on the x86 platform; my original proposal is still viewable at [1]. Since some of the work in that proposal has now been done, a report is due; this is probably the best place for it. Juho Snellman performed some investigations on code related to but separate from that which SBCL produces, and reported what he measured on his blog [2]; the executive summary is that, yes, the calling convention potentially makes a significant difference in performan...

calling convention adopted by the gcc compiler for the C programs
Hi there, I want to learn about the calling convention that is adopted by the gcc compiler for C programs ? I need to learn about it immidiately for finding out the parameters passed to registers when a function call is made and print out the values of the parameters. Can anyone give me some pointers or refer to some book that would be helpful ? I tried searching at google but did not find any useful papers or reference. Thank you, Priyanka priyanka wrote: > Hi there, > > I want to learn about the calling convention that is adopted by the gcc > compiler for C programs ? I need...

Web resources about - x86-64 and calling conventions - comp.compilers

Berne Convention for the Protection of Literary and Artistic Works - Wikipedia, the free encyclopedia ...
The Berne Convention requires its signatories to recognize the copyright of works of authors from other signatory countries (known as members ...

15th annual Northwest aerospace convention to draw 500, focus on new tech
February’s Pacific Northwest aerospace convention, now in its 15th year, has become the largest of its type on the West Coast, and is attracting ...

Will The GOP National Convention In Cleveland Turn Into A Gun Battle?
... whether Herr or Cruz it's going to kill them down-ticket. And they know it. Ryan sees this as part of the rationale for the brokered convention ...

Trump, Cruz Battle Heads To Myrtle Beach For Breitbart News-Sponsored Tea Party Convention
Trump, Cruz Battle Heads To Myrtle Beach For Breitbart News-Sponsored Tea Party Convention

On the List - Sherlock Seattle Convention, Children’s Film Fest, Tiny House Village housewarming
You can do good and meet the neighbors this week at events on and around Capitol Hill. Saturday, bring goods to donate, meet the new residents ...

30 years of the Cubs Convention's greatest hits
Chicago Tribune 30 years of the Cubs Convention's greatest hits Chicago Tribune Paul Sullivan has chronicled the conventions for the Tribune ...

Texas governor joins Marco Rubio in call for new constitutional convention
CNN Texas governor joins Marco Rubio in call for new constitutional convention CNN (CNN) Texas Gov. Greg Abbott on Friday revealed his plans ...

The New Phase In The Convention Of States Propaganda Campaign Is Making The Idea Seem Mainstream
The proposal to hold a "convention of States" to amend the U.S. Constitution is a favorite on the right, but most political observers continue ...

Judge Napolitano: Iran Violated Geneva Conventions By Broadcasting The American Sailors Held Captive
Judge Napolitano: Iran Violated Geneva Conventions By Broadcasting The American Sailors Held Captive

Republicans prepare for (cough, Trump) the possibility (Trump) of a contested convention
I'll believe it when I see it . Several top Republicans tell The Associated Press the party has started preparing for a contested convention ...

Resources last updated: 1/24/2016 9:03:03 AM