我有一些使用此功能的gcc交叉编译器翻译的PowerPC汇编代码:
uint32_t fill_cache(void)
{
__asm__ ("addi 3, 0, 0\n"); /* R3 = 0 */
/* More asm here modifying R3 and filling the cache lines. */
}
,在PowerPC EABI下,返回R3中计算的值。编译时我得到了
foo.c:105: warning: control reaches end of non-void function
有没有办法教gcc实际返回值?或者有没有办法抑制警告(不删除-Wall或添加-Wno- *)?我想非常有选择地仅针对此功能禁止此警告,以便尽可能保持一般警告级别。
不能使此函数返回void,因为调用者需要计算值。
答案 0 :(得分:13)
解决方案1 :使用diagnostic pragmas,您可以在本地禁止某些诊断检查。在非void函数中抱怨没有返回的特定选项(也由 -Wall 暗示)是 -Wreturn-type 。因此,禁止警告的具体代码是:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
/* Your code here */
#pragma GCC diagnostic pop
您可以通过使用 -fdiagnostics-show-option 进行编译来找出导致警告的选项。它只会将选项附加到警告消息中。
解决方案2:定义register variable并将其放入所需的寄存器中。请参考inline assembler template中的变量,并生成代码:
uint32_t fill_cache(void)
{
register uint32_t cacheVal __asm__ ("r3");
__asm__ __volatile__ ("addi %0, 0, 0" : "=r" (cacheVal));
/* More code here */
return cacheVal;
}
volatile 修饰符用于确保指令不被删除或以其他方式受到优化策略的不利影响。
溶液2是优选的,至少有两个原因:
答案 1 :(得分:1)
函数可以声明为naked
,在这种情况下编译器不会生成prolog& epilog并假设程序员保留所有必要的寄存器并在返回之前将输出值放入正确的寄存器中。
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. */
}
有点晚了但也许有人会介入这个:)
PS:据我所知,__asm__
以及__volatile__
是std=c89
语法。实际上__asm__
和{}之间没有区别。 GNU GCC中的asm
。但现代的方法是无足轻重的风格:asm volatile
。