Variables allocated on stack

M

Markus Wichmann

So how do you call Pascal, Fortran, (or C++) etc from C on your platform? Do
you not need to tell it that that imported function is in a different
language?

Not here. Well, there's two possibilities: For one, my C compiler has a
nonstandard way of declaring a function with another calling convention,
for two my Pascal compiler has a de-facto standard way (i.e. Borland
does it the same way. ISO Pascal is next to unusable) of declaring a
function with another calling convention. OK, that is, my Pascal
compiler_s_. For Freepascal, I can either append "cdecl;" to a function
declaration/definition, or compile it with the commandline switch
"-Cccdecl", which I can also set in the config file, and for GNU Pascal,
cdecl is already the standard.
The platform interface should be language-independent. This is where a
binary interface becomes useful. (C has done a good job here in past, in
defining such interfaces, but there is often confusion; is 'long' 32-bits or
64-bits for example? gcc for Windows says 32, gcc for Linux says 64.)

The binary interface is necessary when multiple compilers come into
play. Those may even be two C compilers, or a C compiler and an
assembler. (As is needed for writing a C standard library, because most
OSes cannot call a C-style main function, so you need a wrapper to get
from the OS-specific entry point to main(). You also need assembly for
other stuff in there.)

Also (I cannot resist):

$ uname -m -o
x86_64 GNU/Linux
$ cat test.c
#include <stdio.h>

int main()
{
printf("%d\n", sizeof(long));
return 0;
}
$ gcc test.c && ./a.out
8
$ gcc -m32 test.c && ./a.out
4

The ABI also defines much of the stuff the C standard deliberately
excludes, like padding rules of structures (arrays in structures are
only padded as much as the array type is big, i.e. a "char a[3];"
receives no padding at all on AMD64/SysV)
But should a complex, register-based interface (I believe this might be for
x86-64) be also used as the standard when one C function calls another C
function in the same application?

The register-based interface of AMD64 is really not that much harder to
use than the register preservance rules of i386 were. You know, when a
function could only use three registers before having to set up a stack
frame. With AMD64 you could reserve the whole first register bank to
parameter passing and still have 8 registers left to do all of your
calculations. The result is that the calculations stay in the processor
without having to use the memory, which is nowadays a severe speedup.

CYA,
Markus
 
A

André Gillibert

Markus Wichmann said:
Yeah, that's right!

Only... every function not defined "static" may be called "from the
outside". Every call to a function only declared (and not qualified
"static") but not defined may be to a foreign function.

Plus, when a "static" function pointer is passed around, either the
function must get the standard calling convention or a stub must be
written.

Or, an implementation that wants a non-standard calling convention may
use a non-standard keyword to differentiate internal functions that
must be called with the new calling convention from exported functions.
 
N

Nick Keighley

[...] Having implemented linux's calling
conventions where you have nothing less than 7 registers that
can receive parameters

I can'tbelieve Linux specifies there are 7 registers. How would it run
on a processor that didn't have 7 registers?
[...] those calls with embedded cals in the arguments
evaluation are a plain nightmare...

<snip>
 
J

jacob navia

Le 27/11/11 11:31, Nick Keighley a écrit :
[...] Having implemented linux's calling
conventions where you have nothing less than 7 registers that
can receive parameters

I can'tbelieve Linux specifies there are 7 registers. How would it run
on a processor that didn't have 7 registers?

I do not think it would run in a processor with less than 7 registers

:)

The 8086 already had 8 more than 30 years ago... But in your fantasy
world maybe, anything is possible there.

Most of linux users and software runs in the x86. Yes, there
is a power pc version (32 registers) and there is an ARM version
(16 registers) and there could be other versions that I do not
know about.
 
A

André Gillibert

Nick Keighley said:
[...] Having implemented linux's calling
conventions where you have nothing less than 7 registers that
can receive parameters

I can'tbelieve Linux specifies there are 7 registers. How would it run
on a processor that didn't have 7 registers?
[...] those calls with embedded cals in the arguments
evaluation are a plain nightmare...

Linux calling convention depends on the architecture. I guess Mr navia
is refering to the x86_64 calling convention.
 
J

jacob navia

Le 27/11/11 13:44, André Gillibert a écrit :
Nick Keighley said:
[...] Having implemented linux's calling
conventions where you have nothing less than 7 registers that
can receive parameters

I can'tbelieve Linux specifies there are 7 registers. How would it run
on a processor that didn't have 7 registers?
[...] those calls with embedded cals in the arguments
evaluation are a plain nightmare...

Linux calling convention depends on the architecture. I guess Mr navia
is refering to the x86_64 calling convention.
In the Power PC you use register windows, and as far as I remember
there are more than 7 rfegisters in a window.

Now, it could be that in the ARM the situation is completely different
I do not know. Those are marginal "markets" for linux, (unless you
consider Android as linux) most users are in the main x86 distribution.
 
A

André Gillibert

jacob navia said:
Le 27/11/11 13:44, André Gillibert a écrit :
Nick Keighley said:
<snip>

[...] Having implemented linux's calling
conventions where you have nothing less than 7 registers that
can receive parameters

I can'tbelieve Linux specifies there are 7 registers. How would it run
on a processor that didn't have 7 registers?

[...] those calls with embedded cals in the arguments
evaluation are a plain nightmare...

Linux calling convention depends on the architecture. I guess Mr navia
is refering to the x86_64 calling convention.
In the Power PC you use register windows, and as far as I remember
there are more than 7 rfegisters in a window.

Now, it could be that in the ARM the situation is completely different
I do not know. Those are marginal "markets" for linux, (unless you
consider Android as linux) most users are in the main x86 distribution.

Are we talking of the same thing?
As far as I know, the C calling convention for Linux on i386, as used
in CCC, TCC and intel C compiler for user space function calls, put
function arguments on the stack pointed by ESP.

If you are refering to the system calling convention, that programs use
to enter kernel mode, this is a different thing, and, in my opinion,
not relevant to the original topic.
 
J

jacob navia

Le 27/11/11 17:34, André Gillibert a écrit :
Are we talking of the same thing?
As far as I know, the C calling convention for Linux on i386, as used
in CCC, TCC and intel C compiler for user space function calls, put
function arguments on the stack pointed by ESP.

Sorry, I forgot to specify 64 bit linux. Obviously under 32 bits
the machine can't access all the extended registers (R8 to R15)
so the conventions are very similar to windows 32 bits, as you
say, using the stack.

Since 32 bit linux is quite dated, I just didn't think that it was
necessary to specify that.

Sorry.
 
I

Ian Collins

Le 27/11/11 17:34, André Gillibert a écrit :

Sorry, I forgot to specify 64 bit linux. Obviously under 32 bits
the machine can't access all the extended registers (R8 to R15)
so the conventions are very similar to windows 32 bits, as you
say, using the stack.

Since 32 bit linux is quite dated, I just didn't think that it was
necessary to specify that.

Far from dated. Most targets for embedded Linux are 32 bit (ARM, PPC).
 
S

Seebs

Surely compiler writers can do what they like - within their own
implementation? Calling conventions are only important when calling foreign
and OS functions, and being called from outside.

The thing is, if you are producing functions with external linkage, you had
BETTER be writing them in the ABI-standard way, because your users are going
to expect to be able to call those functions from other stuff -- other
compilers, other languages, etcetera.

A whole lot of C functions end up with external linkage, at which point it
is almost always the case that Bad Things will happen if they don't comply
with the ABI. (In particular: Even if a given function is definitely never
called by anything but your compiler's output, it has to have the same calling
sequence as other functions with the same prototype, some of which will
probably be in a library that is called from another language or the output
of another compiler.)

-s
 
K

Keith Thompson

Markus Wichmann said:
$ uname -m -o
x86_64 GNU/Linux
$ cat test.c
#include <stdio.h>

int main()
{
printf("%d\n", sizeof(long));
return 0;
}
$ gcc test.c && ./a.out
8
$ gcc -m32 test.c && ./a.out
4
[...]

That could have failed, since "%d" expects an int argument but you
passed it a size_t.

printf("%d\n", (int)sizeof(long));

(And "int main()" should be "int main(void)".)
 
G

gwowen

Far from dated.  Most targets for embedded Linux are 32 bit (ARM, PPC).

Ian, its *Jacob*. He doesn't acknowledge the existence of any sort of
embedded development except as a tiny niche market inhabited almost
entirely by Windows-hating by Luddites.
 
N

Noob

Bogdan said:
I had during an interview this question: which variables are
allocated on the stack in a function ? I am unsure how the output
variable is handled. Is this one too allocated on the stack and popped
when the function exists ?
Here is an example:

char* some_function(char c)
{
char *out = malloc(10);
return out;
}

Well, obviously, "c" is in r4, while "out" is in r0.

Wait, what platform did you have in mind?
 
J

jacob navia

Le 29/11/11 10:11, gwowen a écrit :
Ian, its *Jacob*. He doesn't acknowledge the existence of any sort of
embedded development except as a tiny niche market inhabited almost
entirely by Windows-hating by Luddites.

lcc-win has been ported to several 16 bits DSPs.

You are just insulting me because it is fun for you, like many
people here.
 
M

Markus Wichmann

Markus Wichmann said:
$ uname -m -o
x86_64 GNU/Linux
$ cat test.c
#include <stdio.h>

int main()
{
printf("%d\n", sizeof(long));
return 0;
}
$ gcc test.c && ./a.out
8
$ gcc -m32 test.c && ./a.out
4
[...]

That could have failed, since "%d" expects an int argument but you
passed it a size_t.

Oh, my bad. "%zd" it is, then. Unless, of course, I'm compiling with
MinGW or MSVC, then it is "%d" with a cast. Or "%ld", it doesn't matter,
I'd need to cast anyway. (Both MinGW and MSVC use the outdated
msvcrt.dll and crtdll.dll, both of which don't provide a C99 compatible
printf(). Microsoft officially stated to stop caring about their C
compiler and library in 1998. Ah, portability is but a dream!)
printf("%d\n", (int)sizeof(long));

(And "int main()" should be "int main(void)".)

OK, that's just a nitpick. The semantic difference between both of them
is that in the first case, the compiler doesn't complain if the caller
of main() passes additional arguments. In both cases the compiler
doesn't even get to see the caller, the only one who does that is the
linker.

CYA,
Markus
 
K

Keith Thompson

Markus Wichmann said:
Markus Wichmann said:
$ uname -m -o
x86_64 GNU/Linux
$ cat test.c
#include <stdio.h>

int main()
{
printf("%d\n", sizeof(long));
return 0;
}
$ gcc test.c && ./a.out
8
$ gcc -m32 test.c && ./a.out
4
[...]

That could have failed, since "%d" expects an int argument but you
passed it a size_t.

Oh, my bad. "%zd" it is, then.

No, "%zu", since size_t is an unsigned type.

[...]
OK, that's just a nitpick. The semantic difference between both of them
is that in the first case, the compiler doesn't complain if the caller
of main() passes additional arguments. In both cases the compiler
doesn't even get to see the caller, the only one who does that is the
linker.

I've argued that a program using "int main()", as opposed to "int
main(void)", has undefined behavior, since "int main()" is not one of
the forms permitted by C99 5.1.2.2.1 (nor is it quite equivalent to
either of them).

And it's legal to call main recursively.
 
Q

Quentin Pope

What needs to be retained is that C implies (because it accepts
recursive functions) a stack like organization of the activation frames
of each function.

Sorry, but this is extremely misleading. C can and does run on
implementations with no stack. Although the C standard states in general
terms that "recursion function calls shall be permitted", the
"environmental limits" section places no constraints whatsoever on the
depth of recursion that a C implementation is required to support. So it
is perfectly acceptable to store the current hierarchy of function calls
in a fixed length list buffer, with NO notion of a stack growing and
shrinking.
 
J

jacob navia

Le 02/12/11 23:33, Quentin Pope a écrit :
Sorry, but this is extremely misleading. C can and does run on
implementations with no stack. Although the C standard states in general
terms that "recursion function calls shall be permitted", the
"environmental limits" section places no constraints whatsoever on the
depth of recursion that a C implementation is required to support. So it
is perfectly acceptable to store the current hierarchy of function calls
in a fixed length list buffer, with NO notion of a stack growing and
shrinking.

Sure, and that is not a stack huh???

I did not mention any machine stack but just a "stack like organization"
and your trolling has nothing to do with what I wrote.
 
M

Malcolm McLean

Sorry, but this is extremely misleading. C can and does run on
implementations with no stack.
I had such an implementation. int was eight bits, double 24 bits, of
which 7 were exponent. Recursion was not supported. There was no
malloc. Essentially every variable had an invisible "static"
qualifier. It wasn't conforming, but it was clearly C.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
474,082
Messages
2,570,589
Members
47,211
Latest member
Shamestone

Latest Threads

Top