SPARC架构下GCC编译Ada代码:如何让常量从内存加载而非内联
针对你在SPARC架构嵌入式系统中遇到的问题——Ada常量被GCC内联到.text段指令里没法修改,但又不想放到.data段(避免双副本),我整理了几个精准适配需求的方案:
1. 用Volatile编译指示强制内存存储
给常量加上pragma Volatile,相当于告诉编译器:“这个值可能会被外部偷偷修改,别偷懒把它直接嵌到指令里,每次都得从内存读”。这样编译器就会把常量存在内存里,而不是内联成立即数。
示例代码:
pragma Volatile (cHello); cHello : CONSTANT INTEGER_16 := 16#FFFE#;
2. 把常量塞进代码段(.text)的自定义区域
用pragma Linker_Section把常量指定到.text段的一个子区域,这样它会和代码一起加载到RAM里,解锁代码RAM后就能修改,还不会跑到.data段产生双副本。
示例代码:
-- 把常量放到.text下的可修改常量子段 pragma Linker_Section (cHello, ".text.modifiable_consts"); cHello : CONSTANT INTEGER_16 := 16#FFFE#;
之后需要在链接脚本里给这个段分配可写的RAM地址(如果你的系统是从ROM加载到RAM运行的话),比如:
.text.modifiable_consts : { *(.text.modifiable_consts) } > RAM AT> ROM
或者直接用GCC选项指定地址:-Wl,--section-start=.text.modifiable_consts=0x你的RAM地址
3. 针对性关闭优化阻止内联
如果是全局优化导致常量被内联,你可以只在常量附近临时关闭优化,或者用GCC选项禁止常量传播:
局部优化控制(推荐,不影响其他代码)
在常量声明前后临时关掉优化,用完再开:
pragma Optimize (Off); cHello : CONSTANT INTEGER_16 := 16#FFFE#; pragma Optimize (On);
全局编译选项
添加-fno-const-prop选项,禁止编译器做常量传播优化,这样所有常量都会保留内存存储,不会被内联。如果想保留其他优化,可以这么写:-O2 -fno-const-prop
4. SPARC专属:用-mno-const-data把常量全塞.text里
SPARC的GCC有个专门的选项-mno-const-data,会把原本要放到只读数据段(.rodata)的常量全移到.text段里。这样你的常量就和代码一起在代码RAM里,解锁后就能改,完美避开.data段的双副本问题。
编译时直接加这个选项就行:
gcc -c -msparc -mno-const-data your_ada_code.adb
验证小技巧
编译完看生成的汇编代码,如果看到是用ldhw这类指令从内存加载常量,而不是set直接把立即数塞进寄存器,就说明成功了!
内容的提问来源于stack exchange,提问作者zephyr0110

