LLVM程序模块,可以指定目标特定数据布局字符串,该字符串指定数据如何布置在内存中。数据布局的语法很简单:
target datalayout = "layout specification" |
该布局规范包括规范用减号字符分隔(“-”)的列表中。每个规范都以字母开头,并可能在字母后包含其他信息以定义数据布局的某些方面。接受的规格如下:
E
:
指定目标以big-endian格式显示数据。也就是说,最重要的位具有最低的地址位置。e
:
指定目标以little-endian形式显示数据。也就是说,具有最低重要性的位具有最低的地址位置。S<size>
:
指定堆栈的自然对齐位数。堆栈变量的对齐提升仅限于自然堆栈对齐,以避免动态堆栈重新对齐。堆栈对齐必须是8位的倍数。如果省略,则自然堆栈对齐默认为“未指定”,这不会阻止任何对齐升级。P<address space>
:
指定对应于程序内存的地址空间。哈佛(Harvard)体系结构可以使用它来指定LLVM应该在哪些空间放置诸如函数之类的东西。如果省略,程序存储器空间默认为默认地址空间0,这对应于具有相同空间中的代码和数据的冯诺依曼体系结构。A<address space>
:
指定由’alloca
‘创建的对象的地址空间。默认为默认地址空间0。p[n]:<size>:<abi>:<pref>:<idx>
:
这将指定大小的指针和它的<abi>
和<pref>
错误的地址的空间对齐n。第四个参数<idx>
是用于地址计算的索引大小。如果未指定,则默认索引大小等于指针大小。所有尺寸都是位。地址空间n是可选的,如果未指定,则表示默认地址空间0.值n必须在[1,2^23)
范围内。i<size>:<abi>:<pref>
:
这指定了给定<size>
位的整数类型的对齐方式。值<size>
必须在[1,2^23)
范围内。v<size>:<abi>:<pref>
:
这指定了给定<size>
位的向量类型的对齐方式。f<size>:<abi>:<pref>
:
这指定了给定<size>
位的浮点类型的对齐方式。只有目标支持的<size>
值才有效。所有目标都支持32(浮动)和64(双)。一些目标也支持80或128(不同长度的双重版本)。a:<abi>:<pref>
: 这指定了聚合类型对象的对齐方式。F<type><abi>
:这指定了函数指针的对齐方式。<type>
的选项是:i
:函数指针的对齐与函数的对齐无关,是的倍数。 n
:函数指针的对齐是函数指定的显式对齐的倍数,是的倍数。
m:<mangling>
:
如果存在,则指定llvm名称在输出中被损坏。以mangling转义字符作为前缀的符号\01
直接传递给汇编器而不使用转义字符。mangling风格选项是e
:ELF mangling:专用符号获取.L
前缀。m
:Mips mangling:私有符号获取$
前缀。o
:Mach-O修改:专用符号获取L
前缀。其他符号会得到一个_
前缀。x
:Windows x86 COFF mangling:私有符号获取通常的前缀。普通的C符号会得到一个_
前缀。带有__stdcall
,__fastcall
,和__vectorcall
的函数具有附加的自定义修剪(mangling),@N
其中N是用于传递参数的字节数。以?
开头的C++符号不会以任何方式的变形(mangling)。w
:Windows COFF mangling:类似于x
,除了普通的C符号不接受_
前缀。
n<size1>:<size2>:<size3>...
:
这为位目标CPU指定了一组本地整数宽度。例如,它可能包含32位PowerPC的n32,对于PowerPC 64是n32:64
或对于X86-64是n8:16:32:64
。这组元素被认为可以有效地支持大多数一般的算术运算。ni:<address space0>:<address space1>:<address space2>...
:
这指定具有指定地址空间的指针类型作为非整体指针类型。该0
地址空间不能被指定为非积分(non-integral)。
在每个采用的<abi>:<pref>
规范上,指定<pref>
对齐是可选的。如果省略,则前面的内容也应该省略,并且<pref>
等于<abi>
。
在为给定目标构建数据布局时,LLVM从默认的一组规范开始,然后(可能)由datalayout
关键字中的规范覆盖。默认规格在此列表中给出:
E
– 大端p:64:64:64
– 与64位对齐的64位指针。p[n]:64:64:64
– 其他地址空间被假定为与默认地址空间相同。S0
– 自然堆栈对齐未指定i1:8:8
– i1是8位(字节)对齐i8:8:8
– i8是8位(字节)对齐i16:16:16
– i16是16位对齐的i32:32:32
– i32是32位对齐的i64:32:64
– i64具有32位的ABI对齐,但优选对齐64位f16:16:16
– 一半是16位对齐的f32:32:32
– 浮点数是32位对齐的f64:64:64
– 双是64位对齐f128:128:128
– 四位是128位对齐v64:64:64
– 64位向量是64位对齐的v128:128:128
– 128位向量是128位对齐的a:0:64
– 聚合是64位对齐
当LLVM确定给定类型的对齐时,它使用以下规则:
- 如果所寻找的类型与其中一个规格完全匹配,则使用该规格。
- 如果未找到匹配项,并且所查找的类型是整数类型,则使用大于所查找类型的位宽的最小整数类型。如果没有任何规格大于位宽,则使用最大的整数类型。例如,给定上面的默认规格,
i7
类型将使用i8
(次大)的对齐,而i65
和i256
将使用i64
(最大指定)的对齐。 - 如果找不到匹配,并且所寻找的类型是矢量类型,那么将使用小于所寻找的矢量类型的最大矢量类型作为回退。发生这种情况是因为
<128 x double>
可以用64 <2 x double>
来实现,例如。
数据布局字符串的功能可能不是您所期望的。值得注意的是,这不是来自代码生成器应该使用的对齐前端(frontend)的规范。
相反,如果指定,则需要目标数据布局来匹配最终代码生成器所期望的内容。这个字符串被中级优化器用来改进代码,这只有在它与最终的代码生成器使用的匹配时才有效。没有办法生成IR,这并不会将这个特定于目标的细节嵌入到IR中。如果您未指定字符串,则将使用默认规格来生成数据布局,并且优化阶段将相应地运行,并针对这些默认规格向IR中引入目标特异性。