I have some PowerPC assembly code translated with a gcc cross compiler with this function:
uint32_t fill_cache(void)
{
__asm__ ("addi 3, 0, 0\n"); /* R3 = 0 */
/* More asm here modifying R3 and filling the cache lines. */
}
which, under the PowerPC EABI, returns the value computed in R3. When compiling I get
foo.c:105: warning: control reaches end of non-void function
Is there a way to teach gcc that a value is actually returned? Or is there a way to suppress the warning (without removing -Wall or adding -Wno-*)? I would like to very selectively suppress this warning for only this function in order to leave the general warning level as high as possible.
It is not an option to make this function return void since the value computed is required by the caller.
Solution 1: with diagnostic pragmas you can locally suppress certain diagnostic checks. The specific option (which also is implied by -Wall) that complains for no return in a non-void function is -Wreturn-type. So the specific code to suppress the warning is:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
/* Your code here */
#pragma GCC diagnostic pop
You can find out which option is causing the warning by compiling with -fdiagnostics-show-option. It will simply append the option to the warning message.
Solution 2: define a register variable and put it in the desired register. Refer to the variable in an inline assembler template, with the resulting code:
uint32_t fill_cache(void)
{
register uint32_t cacheVal __asm__ ("r3");
__asm__ __volatile__ ("addi %0, 0, 0" : "=r" (cacheVal));
/* More code here */
return cacheVal;
}
The volatile modifier is to ensure that the instruction is not removed or in some other way affected undesirably by the optimization strategy.
Solution 2 is preferred for at least two reasons:
Function could be declared as naked
, in this case compiler would not generate prolog & epilog and would assume that programmer preserves all necessary registers and puts output value into correct register(s) before return.
uint32_t fill_cache(void) __attribute__((naked)); // Declaration
// attribute should be specified in declaration not in implementation
uint32_t fill_cache(void)
{
__asm__ ("addi 3, 0, 0\n"); /* R3 = 0 */
/* More asm here modifying R3 and filling the cache lines. */
}
A bit late but maybe someone will step in this as well :)
PS: For my best knowledge __asm__
as well as __volatile__
are std=c89
syntax. Practically there is not difference between __asm__
& asm
in GNU GCC. But the modern approach is underscoreless style: asm volatile
.
asm_language
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With