选项 -mcmodel=medium,-mlarge-data-threshold=n
说明
此选项使能了32bit之外的动态取址操作。在使用-mcmodel=medium时,对于符号size大于aarch64_data_threshold的符号使用通过mov序列来获取PC值的offset,再与PC值相加的方式实现64bit的相对PC寻址,在地址无关选项打开时,可以实现64bit相对PC寻址,获取GOT表入口,并且通过mov序列+LDR方式获取符号。
注:aarch64_data_threshold默认值为2^16 = 65536,用户可以使用-mlarge-data-threshold=n选项指定大符号的阈值为n。
举例
如下图1,假设foovar的符号距离寻址指令的距离大于4GB,-mcmodel=small使用ADRP+ADD指令进行符号拿取,而foovar在链接时计算距离的方式是.bss+size方式,在链接时会报relocation truncated to fit错误。在此使用图2中的mov序列+PC寻址方式可将寻址范围扩大至64位,解决由于地址溢出导致的报错。
使用方法
用例:hello.f90
编译命令:
1 | gfortran -mcmodel=medium hello.f90 -o hello.out -mlarge-data-threshold=1 |
hello.f90用例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | program main common/baz/a,b,c real a,b,c b = 0.0 call foo() print*, b end subroutine foo() common/baz/a,b,c real a,b,c integer, parameter :: nx = 1024 integer, parameter :: ny = 1024 integer, parameter :: nz = 1024 integer, parameter :: nf = 1 real :: bar(nf,nx*ny*nz) real :: bar1(nf,nx*ny*nz) !real, allocatable,dimension(:,:) :: bar !allocate(bar(nf,nx*ny*nz)) bar = 1.0 b = bar(1,320*138*420) b = bar1(1,321*138*420) return end |
结果
此例中有size=1024*1024*1024的大符号bar1,其阈值大于-mlarge-data-threshold=1选项指定的阈值,因此实现了64bit的相对PC寻址。
如下图所示,如果不加-mcmodel=medium,bar1符号就无法寻址,会报错。
提示
在GCC for openEuler使用过程中,若出现以下错误,可以尝试添加编译选项-mcmodel=medium -mlarge-data-threshold=1解决。
父主题: 静态编译优化