5

我有一些 PowerPC 汇编代码用 gcc 交叉编译器和这个函数翻译:

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。

4

2 回答 2

14

解决方案 1:使用诊断编译指示,您可以在本地抑制某些诊断检查。抱怨在非空函数中没有返回的特定选项(也由-Wall暗示)是-Wreturn-type。所以抑制警告的具体代码是:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
/* Your code here */
#pragma GCC diagnostic pop

您可以通过使用-fdiagnostics-show-option进行编译来找出导致警告的选项。它只会将选项附加到警告消息中。

解决方案2:定义一个寄存器变量并将其放入所需的寄存器中。参考内联汇编器模板中的变量,并使用生成的代码:

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. 就标准而言,不返回非 void 函数的值是未定义的。
  2. 没有压制(新)诊断警告的风险,因为一开始就没有压制的意图。
于 2013-04-10T15:02:27.463 回答
2

函数可以声明为naked,在这种情况下,编译器不会生成序言和结语,并会假定程序员保留所有必要的寄存器并将输出值放入正确的寄存器中,然后再返回。

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__也是如此。实际上,GNU GCC 中的&std=c89之间没有区别。但现代的做法是没有下划线的风格:.__asm__asmasm volatile

asm_language

于 2017-03-06T23:49:22.160 回答