如何告诉GCC编译器应该生成串行代码,即没有跳转

时间:2017-05-11 05:56:54

标签: c gcc llvm llvm-gcc

  

如何告诉GCC编译器应该生成串行代码,即没有跳转。

我正在开发一个将内联汇编嵌入C源代码(或LLVM IR)的项目。

我的实现依赖于内联汇编之间的代码,该代码将按原样写入可执行文件。

更正式地说,假设我有源代码(C或LLVM IR):

.label_start: (inserted as inline assembly)
inline_assembly0
source_code0
source_code1
inline_assembly1
...
.label_end: (inserted as inline assembly)
...

现在,这不应该编译为:

.jmp_target:
source_code1
inline_assembly1
...
.label_end: (inserted as inline assembly)
...

.label_start: (inserted as inline assembly)
inline_assembly0
source_code0
jmp jmp_target

即。代码应保留在标签之间,而不会跳转重新排序.label_start.label_end

有没有办法告诉GCC两个内联汇编标签之间的所有内容都应该保持完整"没有重新订购?我的实施取决于此。

2 个答案:

答案 0 :(得分:4)

如果我理解你的问题,那么GCC manual会对此有一些说明(强调添加)。

  

请注意,编译器甚至可以相对于其他代码移动易失性asm指令,包括跨跳转指令。例如,在许多目标上有一个系统寄存器,用于控制浮点运算的舍入模式。使用易失性asm进行设置(如以下PowerPC示例中所示)无法可靠地运行。

asm volatile("mtfsf 255, %0" : : "f" (fpenv));
sum = x + y;
     

编译器可以在易失性asm之前移回加法。 要使其按预期工作,请通过引用后续代码中的变量asm添加人工依赖关系,例如:

asm volatile("mtfsf 255,%1" : "=X" (sum) : "f" (fpenv));
sum = x + y;

基本上,您需要“虚拟使用”来防止重新排序。

我们也在Mono中使用这种东西来扩展低级GC代码中引用的活跃性,确保在GC中断例程时不会过早释放它:

static inline void dummy_use (void *v)
    __asm__ volatile ("" : "=r"(v) : "r"(v));
}

答案 1 :(得分:1)

尝试禁用优化,gcc -O0 source.c