全局变量区的内存分配是在编译时期而不是运行时。
必须初始化全局变量定义。
可以声明其他转换单元中的全局变量,在这种情况下,它们没有初始化器。
全局变量可以选择指定链接类型(linkage type)。
全局变量的定义或声明都放置在明确段,并且可能指定了可选的对齐方式。如果全局变量声明的显式或推断段信息与定义不匹配,其结果是未定义的。
一个表示全局常量(constant
)的变量意味着该变量的内容不会被修改(比较好的实现是将这种全局数据放进可执行文件的只读段)。请注意,需要运行时初始化的变量不能标记为常量,因为这种变量有存储。
LLVM明确允许将全局变量的声明标记为常量,即使最后这个全局变量没有定义。此功能可用于稍微更好地优化程序,但要求语言定义保证基于“恒定性”的优化对不包括定义的翻译单元有效。
作为SSA值,全局变量在程序中所有基本块中都定义了指针值(即它们主导)。全局变量总是定义一个指向其"内容"类型的指针,因为该指针描述了一块内存区域,LLVM中的所有内存对象都是通过指针访问的。
全局变量可以用unname_addr
标记,这表示地址不重要,只需要内容。标记为这样的常量,如果它们具有相同的初始化器,则可以与其他常量合并。一个地址重要的常量可以和一个unname_addr
常量进行合并,合并的结果就是得到一个地址重要的常量。
如果给定一个local_unnamed_addr
属性,那么就知道这个地址对于当前块来讲不重要。
全局变量可以被声明为驻留在目标特定的编号地址空间中。对于支持它们的目标,地址空间可能会影响执行优化的方式 和/或 使用哪些目标指令访问这个全局变量。默认地址空间为零。地址空间限定符必须在任何其他属性之前。
LLVM允许为全局指定明确段。如果目标支持,将会把全局指定到这个段。此外,如果目标具有相应的必要支持,还可以将全局可以放置在命令中。
外部申明可以指定明确段。段信息会保留在LLVM IR中,以便目标使用。将段信息附加到外部声明是一个断言,这个断言的定义位于指定的段。如果这个断言的定义位于不同的段,这种行为的结果是未定义的。
默认情况下,全局初始化器的优化是建立在假设模块中定义的全局变量在全局初始化器启动之前不会修改的基础上。即使对于可能从模块外部访问的变量,包括那些具有外部链接或出现在@llvm.use或dllexported变量中的变量,也是如此。此假设可以通过将变量标记为externally_initialized
来抑制。
可以为全局指定显式对齐,全局对齐必须是2的幂。如果不存在,或者如果对齐设置为零,则全局的对齐将由目标设置为它感觉方便的任何内容。如果指定了显式对齐,则全局将强制具有该对齐。如果全局具有分配的段,则不允许目标和优化器过度对齐全局。在这种情况下,可以观察到额外的对齐:例如,代码可以假设全局被密集地包装在其段中,并尝试将其作为数组迭代,对齐填充将破坏此迭代。最大对齐方式为1 << 29。
对于全局变量声明,以及可能在链接时替换的定义,LLVM不对变量的分配大小进行假设,只是它们可能不重叠。全局变量声明或可替换定义的对齐方式不得大于其解析到的定义的对齐方式。
全局变量也可以拥有一个DLL storage class,一个可选的runtime preemption specifier,一个可选的global attributes和一个可选的附加的metadata列表。
变量和别名可以拥有一个Thread Local Storage Model。
Scalable vectors不能是一个全局变量或者一个数组的成员,因为它的尺寸在编译时期未知。在结构体中允许它们,以促进内部函数返回多个值。包含可扩展向量的结构体不能用在load,stores,allocas,或者 GEPs。
语法:
@<GlobalVarName> = [Linkage] [PreemptionSpecifier] [Visibility]
[DLLStorageClass] [ThreadLocal]
[(unnamed_addr|local_unnamed_addr)] [AddrSpace]
[ExternallyInitialized]
<global | constant> <Type> [<InitializerConstant>]
[, section "name"] [, comdat [($name)]]
[, align <Alignment>] (, !name !N)*
举个例子,下面定义了一个在编码地址空间中的全局变量,且带有一个初始化器,一个段,和一个对其方式:
@G = addrspace(5) constant float 1.0, section "foo", align 4
举个例子,一个全局变量的声明:
@G = external global i32
举个例子,定义一个initialexec
TLS模式下的线程本地全局变量:
@G = thread_local(initialexec) global i32 0, align 4