LLVM学习笔记⑤

全局变量
①全局变量定义在编译时而不是运行时分配的内存区域。
②全局变量必须被初始化
③全局变量也可以在其他编译单元中声明,这样的话就没有初始化程序了。
④全局变量可以指定一个连接类型(前面有说到)
无论是全局变量定义还是声明,都可以放一个显式的section在里面,并且可以指定可选的显式对齐。如果变量声明的显式或推断部分信息与其定义之间不匹配,则产生的行为是未定义的。
一个变量可以被定义为一个全局constant,它表示变量的内容永远不会被修改(开启更好的优化,允许全局数据被放置在可执行文件的只读部分等)。请注意,需要运行时初始化的变量不能标记constant,因为变量在存储区中。
LLVM显式地允许将全局变量的声明标记为常量,即使全局变量的最终定义不是常量。这个功能可以用来稍微更好地优化程序,但是需要语言定义来保证基于“constantness”的优化对于不包含该定义的翻译单元是有效的。
作为SSA值,全局变量定义的指针值在程序中所有基本块的作用域内(即它们占主导地位)。全局变量总是定义一个指向其“content”类型的指针,因为它们描述了一个内存区域,而LLVM中的所有内存对象都是通过指针访问的。
全局变量可以用unnamed_addr来标记,表示地址不重要,只有内容重要。如果它们具有相同的初始化程序,标记为unnamed_addr的常量可以与其他常量合并。请注意,一个具有显着地址的常量可以与一个unnamed_addr常量合并,结果是一个地址明确的(significant)常量。
如果给定了local_unnamed_addr属性,则知道该地址在模块中不重要。
全局变量可以声明为驻留在特定于目标的编号地址空间中。对于支持它们的目标,地址空间可能会影响如何执行优化和/或使用什么目标指令来访问变量。默认地址空间为零。地址空间限定符必须在任何其他属性之前。
LLVM允许显式地为全局变量指定section。如果目标支持它,它将向指定的section出globals。此外,如果目标有必要的支持,全局变量可以放在comdat(后续有涉及到)中。
外部声明可以有明确指定的section。对于使用该信息的目标,section信息将保留在LLVM IR中。将section信息附加到外部声明是一个断言,其定义位于指定的section中。如果定义位于不同的section,则该行为是未定义的。
默认情况下,全局初始化器通过假设全局初始化器启动之前在模块内定义的全局变量未被其初始值修改而得到优化(原文:By default, global initializers are optimized by assuming that global variables defined within the module are not modified from their initial values before the start of the global initializer.)。甚至对于可能从模块外部访问的变量(包括具有外部链接的或者出现在@llvm.used或dllexported中的变量)也是如此。这个假设可以通过将变量标记为externally_initialized来消除。
可以为全局变量指定显式对齐,全局变量必须是2的幂。如果不存在,或者对齐设置为0,则目标将全局对齐设置为它认为方便的任何位置。如果指定了显式对齐,则全局函数将被强制使用该对齐。如果全局变量有一个指定的section,则不允许目标和优化器对全局变量过度对齐。在这种情况下,额外的对齐是可以观察到的:例如,代码可以假设全局变量密集地封装在它们的section中,并尝试将它们作为一个数组进行迭代,对齐填充将打断这个迭代。最大对齐是1 << 32。
全局变量还可以有一个DLL存储类、一个可选的运行时抢占说明符、一个可选的全局属性和一个可选的附加元数据列表。
变量和别名可以有一个线程本地存储模型。
可伸缩向量不能是全局变量或数组成员,因为在编译时它们的大小未知。它们允许在结构中使用,以便于内部函数返回多个值。包含可伸缩向量的结构不能在负载、存储、分配或GEP中使用。

语法:
@ = [Linkage] [PreemptionSpecifier] [Visibility]
                   [DLLStorageClass] [ThreadLocal]
                   [(unnamed_addr|local_unnamed_addr)] [AddrSpace]
                   [ExternallyInitialized]
                     []
                   [, section "name"] [, comdat [($name)]]
                   [, align ] (, !name !N)*

例子1:
下面的代码是带有编号的地址空间中用初始化器,section,对齐方式定义的一个全局变量:

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

例子2:仅声明一个全局变量

@G = external global i32

例子3:使用initialexecTLS模型定义的一个thread-local全局变量

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

你可能感兴趣的:(LLVM,llvm)