我想使用 gcc 编译一个程序,并针对 ARM 处理器进行链接时间优化。当我在没有 LTO 的情况下编译时,系统会被编译。当我启用 LTO 时
(使用 -flto),我收到以下汇编错误:
错误:无效的文字常量:池需要更近
环顾网络,我发现这与我系统中的常量有关,这些常量被放置在一个名为 .rodata 的特殊部分中,它被称为常量池,位于我系统中的 .text 部分之后。看起来,当使用 LTO 进行编译时,由于内联和其他优化,该 .rodata 部分距离指令太远,因此不再可能对常量进行寻址。是否可以将常量放在使用它们的函数之后?或者是否可以使用另一种寻址模式,以便仍然可以对 .rodata 部分进行寻址?谢谢。
这是汇编器消息,而不是链接器消息,因此这发生在生成节之前。
汇编器有一条伪指令用于将常量加载到寄存器中:
ldr r0, =0x12345678
这被扩展为
ldr r0, [constant_12345678, r15]
...
bx lr
constant_12345678:
dw 0x12345678
常量池通常位于返回指令之后。通过函数内联,函数可能会变得足够长,以至于返回指令太远;不幸的是,编译器不知道内存地址之间的距离,并且汇编器除了“流不会超出返回指令之外,不知道控制流,因此在这里发出常量池是安全的”。
不幸的是,目前还没有好的解决方案。
你可以尝试一个asm
块包含
b 1f
.ltorg
1:
这将在此时强制发出常量池,但代价是额外的分支指令。
如果常量池为空,可能可以指示汇编器省略分支,但我目前无法测试这一点,因此这可能无效:
.if (2f - 1f)
.b 2f
.endif
1:
.ltorg
2:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)