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中引入目标特异性。