[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4688: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3823)
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4690: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3823)
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4691: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3823)
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4692: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3823)
Parallella Community • View topic - The stack

The stack

Discussion about Parallella (and Epiphany) Software Development

Moderators: amylaar, jeremybennett, simoncook

The stack

Postby Hoernchen » Sun Mar 24, 2013 8:38 pm

Hoernchen
 
Posts: 41
Joined: Mon Dec 17, 2012 3:22 am

Re: The stack

Postby amylaar » Mon Mar 25, 2013 7:53 pm

The epiphany architecture uses a flags register which, for reasons of scheduling, we want to expose to the compiler.
Register allocation in GCC generally assumes that whenever a register needs to be spilled, we can allocate a stack slot for it, and insert loads / stores, including
the necessary address arithmetic, wherever needed.
Because reg+offset addressing has a limited offset range, and the add instruction clobbers the flags register, it was not easy to make sure we can always do the
necessary address arithmetic for reloads without clobbering a live value in the flags register.
Therefore, the top of the stack is reserved as temporary storage where the flags can be stored. In the vast majority of cases, we don't have to actually resort
to use that space, but we only know that after register allocation - which includes assigning stack slots.


In your example code, the parameter 'd' straddles the boundary between parameters passed in registers and parameters passed on the stack. In this case,
gcc pretends the part passed in registers has also been pushed to the stack, and arranges for this part to be written to the stack in the prologue. For this
purpose, the area is rounded up to be a multiple of STACK_BOUNDARY bits, i.e. instead of writing just the 4 bytes of d passed in registers, 8 bytes
passed in registers are written. The code for this is in function.c:assign_parm_find_entry_rtl .
amylaar
 
Posts: 31
Joined: Thu Jan 10, 2013 3:06 pm

Re: The stack

Postby Hoernchen » Tue Mar 26, 2013 12:00 am

Ah yes, the flags thing makes sense.
The complex thing..I don't really see why you'd split it in the first place, only to reassemble it afterwards? I'd expect that it would be passed like a double (on the stack) or a struct{float, float} (also on the stack) which would require only one dword load in the best case.
This should be also added to the sdk reference.
Hoernchen
 
Posts: 41
Joined: Mon Dec 17, 2012 3:22 am

Re: The stack

Postby amylaar » Tue Mar 26, 2013 11:47 pm

This is related to the handling of variadic (stdarg.h) functions. There are basically three main ways these can be handled in an ABI supported by GCC:

1) Pass all arguments in a strict order on the stack, or in registers and on the stack, where the registers correspond to some space on the stack that is written
to in the implementation of the variadic function. This allows a very simple implementation of va_arg that just advances a pointer into the argument area
on the stack by the size of the argument. The downsize is that when an argument is larger than the alignment unit of arguments on the stack, it might end
up straddling the boundary between the argument passing in registers and on the stack, and as you have seen, GCC is not good at handling this partial
argument passing, in terms of number of instructions used.

2) Have arguments that don't fit entirely in registers passed entirely on the stack. This also mixes well with ABIs that use different kinds of registers for
different types of arguments - e.g. if the target processor has specific registers for floating point values. The downside is that the implementation
of va_arg is more complicated. That means a little bit more code size / cycles in variadic functions, but mostly just compiler / runtime implementation.

3) Use different argument passing for variadic functions that for non-variadic functions, typically like 1) - preferrably without registers - for variadic functions, and
like 2) for non-variadic functions. The downside is that there's still code out in the wild that doesn't have proper prototypes for variadic functions in scope
for all calls. This might be code that pre-dates the ANSI/ISO C standards, or where the programmer ignored or was ignorant of these standards for one
reason or another. Such code will not work for a target that uses such an ABI when the variadic/non-variadic argument passing differes for an affected call.
amylaar
 
Posts: 31
Joined: Thu Jan 10, 2013 3:06 pm


Return to Programming Q & A

Who is online

Users browsing this forum: No registered users and 10 guests

cron