LLVM language 参考手册(译)(3)

可见性模式(Visibility Styles

全部全局变量和函数具备如下的可见性模式之一:html

default” - Default style
在那些使用ELF object file格式的平台( targets),默承认见性意味着声明对于其余模块是可见的,而且在可共享库,意味着这个声明的实体是可被覆盖的。在 Darwin平台,默承认见性意味着声明对于其余模块是可见的。默承认见性与在这种语言中的 “external linkage” 是一致的。
hidden” - Hidden style
一个对象的带有hidden可见性的两个声明,若是它们是处于一个相同的可共享单元( shared object),那么它们会被引用到一个相同的对象。一般来讲,hidden可见性代表符号不会被放置到动态符号表,因此其余模块(可执行程序 或 共享库)不能够直接引用这个符号
protected” - Protected style
在ELF中,protected 可见性代表符号会被放置到动态符号表,但在特定模块中的这些引用会绑定到一个本地的符号。因此这个符号不能被其余模块重写。

DLL存储类别(DLL Storage Classes

全部全局变量,函数,别名(Aliases)能够拥有下面的DLL存储类别之一:python

dllimport
dllimport” 会致使编译器经过一个指向到 被DLL导出的指针 的全局指针,来引用一个函数或变量。在微软windows平台,这个指针名的格式为  __imp_ 接上引用的函数或变量的名称(__imp_函数名)。
dllexport
dllexport” 会致使编译器提供一个指向 一个在DLL中的指针 的全局变量,因此它能够被引用到带有 dllimport 属性的实体。在微软windows平台,这个指针名的格式为  __imp_ 接上引用的函数或变量的名称(__imp_函数名)。为了使编译器,汇编器和连接器知道某个符号是被外部引用而且防止这个符号被删除,所以这个存储类别为了定义一个dll接口而存在的。

具名类型(Named Types

LLVM IR容许你为明确类型标识其名称的别名。这使得阅读IR更加得容易且使IR更加紧凑(condensed )(实际上这与递归类型有关)。一个名字标识的例子以下:windows

%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。这是一个重要的设计点且将不会被改变。函数

全局变量(Global Variables

全局变量在编译期定义存储分配范围而不是运行期。优化

全局变量定义必须被初始化,被放置在一个显式的section中,且有一个可选的显式对齐标识。spa

全局变量在其余的编译单元也能够被声明,但在这种状况下它们没有初始化式(initializer)。线程

一个变量可能被定义为thread_local,,这意味着这个变量不会被其余线程所共享(每个线程会拥有这个变量的一份单独的拷贝)。设计

不是全部平台都支持thread-local变量。可选地,一个TLS模型能够标识:指针

localdynamic

标识仅用于当前可共享库的变量

initialexec

标识在模块中不会被动态加载的变量

localexec

标识在可执行程序中定义且只在可执行程序中使用的变量

这种模型与ELF TLS模型是一致的;详见ELF Handling For Thread-Local Storage。若是指定的模型不被支持或者有一个更合适的模型可供选择,平台可能会选择一个不一样TLS模型。
一个变量可能被定义为一个全局常量,代表其内容从不会被修改(使其可以更好地被优化,容许这个全局数据被放置到可执行程序的只读section)。注意,须要在运行期被初始化的变量不能被标识为 constant,由于初始化时有一个到这个变量的存储操做。
LLVM容许明确全局变量的声明被标识为constant,计时这个全局变量的最终定义不是constant。这种能力可使程序得到些微的优化,但这要求这个语言定义保证基于“constantness”的优化对于不包含这个定义的编译单元是有效的。
做为SSA值,全局变量定义为指针值,其做用域是程序中的全部基本块。全局变量永远定义为一个其content所对应的类型的指针由于他们描述一个存储范围,全部这些LLVM中的存储对象被经过这个指针访问。
全局变量能够被  unnamed_addr 标识,代表它的地址是没有意义的,仅仅是指向其内容。一个常量被这样标识能够被合并到其余拥有相同初始化式的常量。注意,一个地址有意义的常量能够被合并到一个 unnamed_addr 常量,且合并结果变为一个地址有意义的常量。
一个全局变量可能被声明驻留在一个平台指定的编号地址空间。对于支持编号地址空间的平台,地址空间会影响优化被怎么处理及使用什么指令来访问变量。默认的地址空间是0。地址空间限定符必须放在其余任何属性前。
LLVM容许一个明确的section用于指定全局变量。若是目标平台支持它,他会发散全局变量到这个指定section。

默认下,全局初始化式经过假设被定义在模块中的全局变量是在全局初始化式以前他们的初始值是不会被修改的。对于可能从外部被访问的变量,包括带有“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
相关文章
相关标签/搜索