如何告诉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两个内联汇编标签之间的所有内容都应该保持完整"没有重新订购?我的实施取决于此。
答案 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