Question

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.

Was it helpful?

Solution

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:

  1. The value of a no returning non-void function is undefined as far as the standard is concerned.
  2. There's no risk of suppressing (new) diagnostic warnings there was no intention to suppress in the first place.

OTHER TIPS

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top