LLVM IR 全局变量

在LLVM程序中:

  • 全局变量是在编译期定义存储分配范围而不是运行期。
  • 全局变量定义必须被初始化。
  • 全局变量也可以在其他编译单元中声明,这种情况下,它们没有初始化程序。

无论是全局变量定义还是声明都可以有一个显式的部分放在里面,并且可以有一个可选的显式对齐。如果变量声明的显式或推断区段信息与其定义之间存在不匹配,则结果行为未定义。

一个变量可以被定义为一个全局constant,它表示变量的内容永远不会被修改(开启更好的优化,允许全局数据被放置在可执行文件的只读部分等)。请注意,需要运行时初始化的变量不能标记constant,因为变量在存储区中。

LLVM明确允许将全局变量的声明标记为常量,即使全局变量的定义中没有指定。此功能可用于对程序进行稍微更好的优化,但需要语言定义以保证于“constantness”的优化对于在定义中不包含constant的编译单元有效。

作为SSA(静态单赋值)值,全局变量定义了程序中所有基本块的范围内的指针值(即它们是可控的)。全局变量总是定义一个指向其“内容”类型的指针,因为它们描述了一个内存区域,并且LLVM中的所有内存对象都是通过指针访问的。

全局变量可以用unnamed_addr来标记,表示地址不重要,只有内容。如果它们具有相同的初始化程序,标记为unnamed_addr的常量可以与其他常量合并。请注意,一个具有显着地址的常量可以与一个unnamed_addr常量合并,结果是一个地址明确的(significant)常量。

如果给出local_unnamed_addr属性,则这个属性的地址在模块内是不明确的。

全局变量可能被声明为驻留在特定目标机的编号地址空间中。对于支持它们的目标机,地址空间可能会影响优化的执行方式,可能也会影响使用什么目标机指令访问变量。默认地址空间为零。地址空间限定符必须在任何其他属性之前。

LLVM允许为全局指定显式部分(section)。如果目标机支持它,它会将globals发送到指定的section。此外,如果目标机有必要的支持,全局变量可以放在一个comdat中。

外部声明可能有明确的section指定。对于使用此信息的目标机器,section信息保留在LLVM IR中。将section信息附加到外部声明是一个断言,其定义位于指定的section。如果定义位于不同的section,则行为是未定义的。

默认情况下,全局初始化器通过假设在全局初始化器开始之前在模块内定义的全局变量未从其初始值修改而得到优化。即使对于可能从模块外部访问的变量(包括具有外部链接的或者出现在@llvm.useddllexported中的变量)也是如此。这个假设可以通过将变量标记为externally_initialized来消除。

可以为全局变量指定明确的对齐方式,它必须是2的幂。如果不存在,或者如果对齐方式设置为零,则全局对齐由目标机器设置为任何方便的方式。如果指定了明确的对齐,则全局被强制完全按照指定的对齐方式。如果全局变量具有分配的section,则不允许目标机和优化器过度对齐(over-align)全局变量。在这种情况下,额外的对齐方式可以被观察到:例如,代码可以假定全局变量被密集包装在它们的section中,并尝试将它们作为数组进行迭代,对齐填充将会破坏这个迭代。最大对齐是1 << 29.

全局变量还可以具有DLL存储类,可选的运行时抢占说明符,可选的全局属性和可选的附加元数据列表。

变量和别名可以有一个线程本地存储模型

Syntax:

@<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)*

例如,下面在带有初始值设定项,节(section)和对齐的编号地址空间中定义全局变量:

@G = addrspace(5) constant float 1.0, section "foo", align 4

以下示例仅声明一个全局变量

@G = external global i32

以下示例使用initialexecTLS模型定义了一个thread-local全局变量:

@G = thread_local(initialexec) global i32 0, align 4