Calling convention refers to how arguments, return values are passed between caller and callee; how a call stack (if it exists) is constructed, how a return address is saved and retrieved; how local variables are assigned memory and how they are accessed. In short - it refers to prologue and epilogue of a function. Below presentation shows how a call stack changes during a function call.
Monday, December 27, 2010
Friday, December 24, 2010
Simple parameter passing with gcc
# simple.c
int foo(int a, int b) { return a+b; }
int main() { return foo(10, 20);}
Compile with -fdump-tree-all and -fdump-rtl-all. Analyze the expand and global register allocation passes. For a target like AVR, below snapshot shows expand pass for the foo(10,20) code:
Note that r24 and r22 are chosen to pass the arguments 10 and 20 respectively. Also, arguments are passed from left to right. How the register selection is controlled in gcc?
Target hooks - FUNCTION_ARG and FUNCTION_ARG_ADVANCE decide which register to be used for each argument. So a back-end developer decides the argument register selection algorithm. It is also partially dependent on macros CALL_USED_REGISTERS, ARG_POINTER_REGNUM and wholly dependent on CUMULATIVE_ARGS structure. In this particular case, register r25-r8 are used for passing arguments in descending order. Since an integer in AVR is 2bytes while each register is byte sized, to pass a single argument two registers are used. Also only even-numbered registers are chosen, which means even for char, even number registers are chosen.
The other interesting aspect is register chosen to store return value. Following rtl patterns can be seen:
//return value for foo
(insn 16 24 21 5 simple.c:3 (set (reg/i:HI 24 r24)
(reg:HI 44 [ <result> ])) -1 (nil))
// return value for main()
(insn 14 22 19 5 simple.c:8 (set (reg/i:HI 24 r24)
(reg:HI 42 [ <result> ])) -1 (nil))
How the register selection is controlled here? Target hook FUNCTION_VALUE_REGNO_P decides which register to hold the function value which is nothing but return value in the most of the cases (except when register windows exist). In the context of AVR, r24 is used as return register. (Click on source code hyperlinks. Version: GCC 4.6 trunk)
#define FUNCTION_VALUE_REGNO_P(N) ((int) (N) == RET_REGISTER)
/* Returns register number for function return value.*/
int avr_ret_register (void) { return 24; }
int foo(int a, int b) { return a+b; }
int main() { return foo(10, 20);}
Compile with -fdump-tree-all and -fdump-rtl-all. Analyze the expand and global register allocation passes. For a target like AVR, below snapshot shows expand pass for the foo(10,20) code:
Note that r24 and r22 are chosen to pass the arguments 10 and 20 respectively. Also, arguments are passed from left to right. How the register selection is controlled in gcc?
Target hooks - FUNCTION_ARG and FUNCTION_ARG_ADVANCE decide which register to be used for each argument. So a back-end developer decides the argument register selection algorithm. It is also partially dependent on macros CALL_USED_REGISTERS, ARG_POINTER_REGNUM and wholly dependent on CUMULATIVE_ARGS structure. In this particular case, register r25-r8 are used for passing arguments in descending order. Since an integer in AVR is 2bytes while each register is byte sized, to pass a single argument two registers are used. Also only even-numbered registers are chosen, which means even for char, even number registers are chosen.
The other interesting aspect is register chosen to store return value. Following rtl patterns can be seen:
//return value for foo
(insn 16 24 21 5 simple.c:3 (set (reg/i:HI 24 r24)
(reg:HI 44 [ <result> ])) -1 (nil))
// return value for main()
(insn 14 22 19 5 simple.c:8 (set (reg/i:HI 24 r24)
(reg:HI 42 [ <result> ])) -1 (nil))
How the register selection is controlled here? Target hook FUNCTION_VALUE_REGNO_P decides which register to hold the function value which is nothing but return value in the most of the cases (except when register windows exist). In the context of AVR, r24 is used as return register. (Click on source code hyperlinks. Version: GCC 4.6 trunk)
#define FUNCTION_VALUE_REGNO_P(N) ((int) (N) == RET_REGISTER)
/* Returns register number for function return value.*/
int avr_ret_register (void) { return 24; }
Subscribe to:
Comments (Atom)
