LLVM IR 标识符有两种基本类型:
- 全局标识符(函数,全局变量)以’@’字符开头。
- 本地标识符(寄存器名称,类型)以’%’字符开头。
标识符有三种不同的格式,分别用于不同的目的:
- 命名值表示为带有前缀的字符串。例如%foo,@DivisionByZero,%a.really.long.identifier。使用的实际正则表达式是’
[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*’。名称中需要其他字符的标识符可以用引号括起来。可以使用十六进制字符的ASCII代码”\xx”在哪里转义特殊字符xx。通过这种方式,任何字符都可以在名称值中使用,甚至可以引用自己。该”\01″前缀可以在全局值可用于压制截断。 - 未命名的值表示为带有前缀的无符号数值。例如%12,@2,%44。
- 常量,将在后面的关于常量的部分进行描述。
LLVM要求值以一个前缀开始有两个原因:
- 编译器不需要担心值的名称会和保留字(reserved words)冲突,保留字(reserved word)集可以在未来扩展的时候不会出现惩罚(penalty,不会发生冲突)。
- 非命名的identifier允许编译器快速找出一个临时变量且不会造成符号表冲突。
LLVM中的保留字与其他语言的保留字非常相似。有相应的关键字对应着不同的操作码有(add
, bitcast
, ret
, etc…),原始类型名(void
, i32
,etc…)和其他。这些保留字不会与变量名冲突,因为他们之中没有一个是以前缀(%
or @
)开头的。
这里有一个表示用8乘上一个整型变量%x
的LLVM代码例子:
#The easy way:
%result = mul i32 %X, 8
#在强度折减后:
%result = shl i32 %X, 3
#And the hard way:
%0 = add i32 %X, %X ; yields {i32}:%0
%1 = add i32 %0, %0 ; yields {i32}:%1
%result = add i32 %1, %1
用8乘上%x
的最后的方式说明了LLVM的几个重要的词法特点:
- 注解是以
;
分隔且直到当前行的结尾 - 当计算的结果不能被赋值的一个具名值的时候,非命名临时变量被创建
- 非具名临时变量是按顺序编号的(使用一个递增计数器,从0开始)。注意整个基本块都被包含在这种编号方法中。例如,如果一个基本块的入口没有被给予一个标签名,那么它就会获得一个编号0。
它也表明了一个在这个文档我们应该遵循的约定。当演示指令的时候,我们应该使一个定义了被创建的值的类型和名称的注释紧跟这条指令后面。