I am by no means an expert on the GCC's interior, but I will do it. Unfortunately, most of the information about allocating and distinguishing GCC registers seems to be out of date (links to files like local-alloc.c that no longer exist).
I am looking at gcc-4.5-20110825 source code.
The GNU C Compiler Internals mentions that the initial function code is generated by expand_function_start in gcc/function.c . To process the parameters, we find the following:
4462 /* Initialize rtx for parameters and local variables. 4463 In some cases this requires emitting insns. */ 4464 assign_parms (subr);
In assign_parms code that processes where each argument is stored is as follows:
3207 if (assign_parm_setup_block_p (&data)) 3208 assign_parm_setup_block (&all, parm, &data); 3209 else if (data.passed_pointer || use_register_for_decl (parm)) 3210 assign_parm_setup_reg (&all, parm, &data); 3211 else 3212 assign_parm_setup_stack (&all, parm, &data);
assign_parm_setup_block_p handles aggregated data types and is not applicable in this case, and since the data is not passed as a pointer GCC checks use_register_for_decl .
Here's the relevant part:
1972 if (optimize) 1973 return true; 1974 1975 if (!DECL_REGISTER (decl)) 1976 return false;
DECL_REGISTER checks if a variable with the register keyword has been specified. And now we have our answer: most parameters live on the stack when optimization is not turned on, and then assign_parm_setup_stack processed. The route received through the source code before it ends, spilling the value, is a bit more complicated for the pointer arguments, but can be traced in the same file if you are interested.
Why does GCC distinguish between all arguments and local variables with optimizations disabled? To help debugging. Consider this simple function:
1 extern int bar(int); 2 int foo(int a) { 3 int b = bar(a | 1); 4 b += 42; 5 return b; 6 }
Compiled with gcc -O1 -c , this creates the following on my machine:
0: 48 83 ec 08 sub $0x8,%rsp 4: 83 cf 01 or $0x1,%edi 7: e8 00 00 00 00 callq c <foo+0xc> c: 83 c0 2a add $0x2a,%eax f: 48 83 c4 08 add $0x8,%rsp 13: c3 retq
Well, if only you break line 5 and try to print the value of a, you get
(gdb) print a $1 = <value optimized out>
As an argument, it is overwritten because it is not used after the call to bar .