所有全局变量和函数具有以下的可见性模式之一:
所有全局变量,函数,别名(Aliases)可以拥有下面的DLL存储类别之一:
LLVM IR允许你为明确类型标识其名称的别名。这使得阅读IR更加得容易且使IR更加紧凑(condensed )(实际上这与递归类型有关)。一个名字标识的例子如下:
%mytype = type { %mytype*, i32 }
你可以给定对除了“void”任何类型一个名称。类型名的别名可以被使用到任何期望 “%mytype”语法的地方。
注意,这些类型名是构造类型指明的名称的别名,因此你可以对同一个类型标识多个名字。这通常会在dumping out一个 .ll文件的时候导致行为混乱。由于LLVM IR使用构造类型,所以这个名称不是这个类型的一部分。当print out LLVM IR,printer会挑选一个名称替代来同一类型的所有名称(the printer will pick one name to render all types of a particular shape. 。。。为相同形状着色,囧)。这意味着如果你有最终具有相同LLVM 类型的两个不同的源类型在一段代码中,那么dumper会打印the “wrong” 或 unexpected type。这是一个重要的设计点且将不会被改变。
全局变量在编译期定义存储分配范围而不是运行期。
全局变量定义必须被初始化,被放置在一个显式的section中,且有一个可选的显式对齐标识。
全局变量在其他的编译单元也可以被声明,但在这种情况下它们没有初始化式(initializer)。
一个变量可能被定义为thread_local,,这意味着这个变量不会被其他线程所共享(每一个线程会拥有这个变量的一份单独的拷贝)。
不是所有平台都支持thread-local变量。可选地,一个TLS模型可以标识:
localdynamic
标识仅用于当前可共享库的变量
initialexec
标识在模块中不会被动态加载的变量
localexec
标识在可执行程序中定义且只在可执行程序中使用的变量
默认下,全局初始化式通过假设被定义在模块中的全局变量是在全局初始化式之前他们的初始值是不会被修改的。对于可能从外部被访问的变量,包括带有“external”链接标识的全局变量 或者 出现在@llvm.used 或者 dll导出的变量,这种猜想也是正确的。这种猜想会被带有"externally_initialized"的变量抑制。
一个显式对齐可能被标识于一个全局变量,这个显示对齐一定是2的次幂。如果对齐属性标识不存在,或者对齐属性被设置为0,那么这个全局变量的对齐属性将会被根据目标平台需求设置。如果一个显式的对齐属性被标识,这个全局变量被迫完全按照这个对齐属性对齐。如果这个全局变量有一个被分配到的section,目标平台和优化器不会允许over-align这个全局变量。在这种情况下,额外的对齐是显而易见的:例如,代码可能猜想全局变量被集中放置到他们的section中并尝试以数组形式遍历他们,但对齐填充会打破这个遍历过程。
全局变量同样可以拥有一个DLL存储类别
语法:
[@<GlobalVarName> =] [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal]
[AddrSpace] [unnamed_addr] [ExternallyInitialized]
<global | constant> <Type>
[, section "name"] [, align <Alignment>]
例如,下面定义了一个存储在编号地址带有一个初始化式,section和对齐属性的全局常量。
@G = addrspace(5) constant float 1.0, section "foo", align 4
下面是一个只声明全局变量的例子
@G = external global i32
下面是一个定义了thread-local的带有initialexec TLS模型的全局变量
@G = thread_local(initialexec) global i32 0, align 4