LLVM IR / LLVM指令集入门
本文基于LLVM 12官方文档的
LLVM Language Reference Manual
。以学习笔记为主。所以本文会摘录一些常见/常用的指令。对于一些更加深层次的指令属性/特性,待我对LLVM有更深的理解再单独写文章记录。
1. LLVM IR简介
LLVM IR可以理解为LLVM平台的汇编语言,所以官方也是以语言参考手册(Language Reference Manual)的形式给出LLVM IR的文档说明。既然是汇编语言,那么就和传统的CUP类似,有特定的汇编指令集。但是它又与传统的特定平台相关的指令集(x86, ARM, RISC-V等)不一样,它定位为平台无关的汇编语言。也就是说,LLVM IR是一种相对于CUP指令集高级,但是又是一种低级的代码中间表示(比抽象语法树等高级表示更加低级)。
1. 1 LLVM IR的基本特点
为:
SSA
。在指令集层面,以SSA的形式表示。指令集中存在Phi指令。类型安全
。它在指令集层面,是有类型的,也就是说指令是需要有特定的类型作为约束的。低级操作
。指令集相对比较底层。灵活
。能够很利索地表示“所有”的高级语言。也叫Universal IR。- 它是
LLVM编译各个阶段通用的IR
。
1.2 LLVM IR的表示形式
:
存在形式
内存
。基于LLVM开发需要用到许多的类。include "llvm/IR/XX"
磁盘(二进制)
。一般以.bc
的形式存在。方便JIT编译器快速加载。磁盘(文本)
。可读的汇编语言表示,一般以.ll
的形式存在,本文研究的就是这种形式的LLVM IR
特点
- 轻量
- 低级
- 富有表达性
- 有类型的。利于指针分析
- 可扩展性的
良好的格式
- LLVM提供了验证格式正确性的Verification Pass。它不仅仅是语法上的格式验证,还从语义上进行验证。比如说
%x = add i32 1, %x在语法上符合,但是它并不是SSA形式的,所以会验证格式错误
- LLVM提供了验证格式正确性的Verification Pass。它不仅仅是语法上的格式验证,还从语义上进行验证。比如说
1.3 LLVM IR中的标识符(Identifier)
LLVM IR中有两种标识符类型
:
全局标识
。以@开头的- 函数
- 全局变量
局部标识
。以%开头- 寄存器名
- 类型名
LLVM IR中有3种标识符格式
:
有名字的值(Named Values)
- 格式:[%@][-azA-Z.][−a−zA−Z._][-a-zA-Z.][−a−zA−Z._0-9]*
- 例如
- %foo
- @DivisionByZero
- %a.really.long.identifier
无名字的值(Unnamed Values)
- 格式:用无符号数值作为它们的前缀
- 例如
- %12
- @2
- %44
常量(后文再讲)
2. LLVM整体结构
官方文档罗列得非常多,这里暂时只列出几个我觉得比较重要的
。
2.1 Module
LLVM程序是由若干个Module组成。而Module中由如下三个部分组成:
函数
全局变量
符号表项
其中函数/全局变量都可以认为是全局值(即全局函数和全局变量);
而全局值能够用一个指向内存位置的指针标识。其中
- 全局变量通过指向char数组的指针标识。
- 函数通过指向函数的指针标识。
全局值都有链接类型
。链接,即它们可能会结合LLVM Linker,合并每个Module的函数/全局变量定义。并resolve前向声明,合并符号表项
。
2.2 链接类型
全局值(全局变量/函数)会有一种如下的链接类型(这里只简单了解2中类型):
private
- 只能在当前module被访问
链接private全局值到另外一个模块中,可能会导致此private对象被重命名以防止名字冲突
- 只能在当前module被访问
internal
- 类似private,全局值在object file中被当成一个local符号
- 与C语言中的static关键字相关
- available_externally
- linkonce
- weak
- common
- appending
- extern_weak
- linkonce_odr,
- weak_odr
- external
- extern_weak
2.2 调用惯例
LLVM支持如下几种调用模式。(这里只简单了解,后续深入再添加)
ccc
The C calling convention
支持变长参数的函数调用,容忍一些函数声明和实现的不匹配(C里面也是这样)fastcc
coldcc
cc 10
cc 11
webkit_jscc
anyregcc
preserve_mostcc
preserve_allcc
cxx_fast_tlscc
swiftcc
tailcc
cfguard_checkcc
cc <n>
更多可能会在未来添加
…
3.类型系统
类型系统是LLVM IR中最重要的特性之一。它带来好处:
有类型让许多优化能够直接在IR上进行(一般的三地址码不行,它没类型)
强类型使得LLVM IR更加可读
3.1 Void类型
void就是通常编程语言中的void,空。
3.2 Function类型
函数类型,它的表示成:
<return type> (<parameter list>)
例如:
i32 (i32)
: 它表示的函数为:i32类型作为函数入参,i32类型作为函数返回值float (i16, i32 *) *
: 它表示指向函数的指针,此函数以i16,i32指针类型作为入参类型,float作为返回值类型。i32 (i8*, ...)
: 变长参数的函数,固定长度的入参为i8类型,返回值为i32类型{i32, i32} (i32)
: i32,i32为结构体的前两个字段类型,此结构体类型作为函数的返回值类型,函数入参为i32类型。
3.3 First Class类型
First Class表示一大类的类型。包括:
Single Value
Label
Token
Metadata
Aggregate
3.3.1 Single Value Type
Integer(整数)
- 表示为: iN, 其中N正整数,如i8,i32
Float-Point(浮点)
- half
- bfloat
- float
- double
- fp128
- x86_fp80
- ppc_fp128
x86_mmx
Pointer(指针类型)
- 表示形式为:
<type> *
- 表示形式为:
Vector(向量)
Fiexed-length vector(定长向量)
:< <# elements> x <elementtype> >
Scalable vector(变长向量)
:< vscale x <# elements> x <elementtype> >
- <vscale x 4 x i32>
Label
Token
Metadata
Aggregate(聚合类型)
Array(数组)
:- 表示: [<# elements> x ]
Structure(结构体)
- Identified normal struct type
%T1 = type { \<type list\> }
{ i32, i32, i32}
: 4字节三元组{ float, i32 (i32) * }
: 第一个元素float,第二个元素函数指针,函数为4字节入参,返回4字节类型
- Identified packed struct type
%T2 = type <{ \<type list\> }>
<{ i8, i32 }>
: 只知道5字节大小
- Identified normal struct type
Opaque Structure
- 没有结构体,类似C中的结构体类型前向声明
- %X = type opaque
- %52 = type opaque
- 没有结构体,类似C中的结构体类型前向声明
4. 常量
- 简单常量
- 布尔常量:i1类型,’true’ 或者 ’false’
- 整数常量: 4
- 浮点常量: 123.421, 1.23421e+2,
- Null指针常量: ‘null’
- Token常量: ‘none’等
- 复杂常量
- 结构体常量:{ i32 4, float 17.0, i32* @G }
- 数组常量:[ i32 42, i32 11, i32 74 ]
- 向量常量:< i32 42, i32 11, i32 74, i32 100 >
- Zero初始化:'zeroinitializer’能够用来初始化任何类型为零值
- Metadata node:!{!0, !{!2, !0}, !“test”}, !{!0, i32 0, i8* @global, i64 (i64)* @function, !“str”}
- 全局变量和函数的地址
- 全局变量和函数的地址隐式地为链接时常量
- 这些常量当它们的标识被使用时,会被显示地引用,并且是指针类型
- Undefined值
- Poison值
- Well-Defined值
- 基本块的地址
- DSO Local Equivalent
- 常量表达式
5. 指令集
指令集分为如下几大类,这里会挑一些指令列举,随着后续对指令更加深入,再对指令的具体内容进行补充。
- 终止指令
- 单目运算
- 二元运算
- 二元位运算
- 向量操作
- 聚合操作
- 访问/操作内存
- 强转操作
- 其它操作
5.1 终止指令
ret
- ret <type> <value>
- ret void
- value必须是first-class类型
- 例子
- ret i32 5 ; Return an integer value of 5
- ret void ; Return from a void function
- ret { i32, i8 } { i32 4, i8 2 } ; Return a struct of values 4 and 2
br
- br i1 , label , label
- br label ; Unconditional branch
- 例子
Test: %cond = icmp eq i32 %a, %b br i1 %cond, label %IfEqual, label %IfUnequal IfEqual:ret i32 1 IfUnequal:ret i32 0
switch
- switch , label [ , label … ]
- 例子
; Emulate a conditional br instruction %Val = zext i1 %value to i32 switch i32 %Val, label %truedest [ i32 0, label %falsedest ]; Emulate an unconditional br instruction switch i32 0, label %dest [ ]; Implement a jump table: switch i32 %val, label %otherwise [ i32 0, label %onzeroi32 1, label %ononei32 2, label %ontwo ]
indirectbr
- indirectbr <somety>* <address>, [ label <dest1>, label <dest2>, … ]
invoke
- <result> = invoke [cconv] [ret attrs] [addrspace(<num>)] | (<function args>) [fn attrs]
[operand bundles] to label <normal label> unwind label <exception label> - 说明
- normal label对应于ret
- exception label对应于resume或者其它异常处理机制
- 这个指令对高级语言的catch实现很重要
- 例子
%retval = invoke i32 @Test(i32 15) to label %Continueunwind label %TestCleanup ; i32:retval set %retval = invoke coldcc i32 %Testfnptr(i32 15) to label %Continueunwind label %TestCleanup ; i32:retval set`
- <result> = invoke [cconv] [ret attrs] [addrspace(<num>)] | (<function args>) [fn attrs]
callbr
- <result> = callbr [cconv] [ret attrs] [addrspace(<num>)] <ty>|<fnty> <fnptrval>(<function args>) [fn attrs] [operand bundles] to label <fallthrough label> [indirect labels]
resume
- resume <type> <value>
catchswitch
- <resultval> = catchswitch within <parent> [ label <handler1>, label <handler2>, … ] unwind to caller
- <resultval> = catchswitch within <parent> [ label <handler1>, label <handler2>, … ] unwind label <default>
catchret
- catchret from <token> to label <normal>
cleanupret
- cleanupret from <value> unwind label <continue>
- cleanupret from <value> unwind to caller
unreachable
5.2 单目运算
fneg
- <result> = fneg [fast-math flags]* <ty> <op1> ; yields ty:result
- 浮点数或者浮点向量的负
5.3 二元运算
add
- <result> = add <ty> <op1>, <op2> ; yields ty:result
- <result> = add nuw <ty> <op1>, <op2> ; yields ty:result
- <result> = add nsw <ty> <op1>, <op2> ; yields ty:result
- <result> = add nuw nsw <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用到整数或者整数向量,两个操作数都必须是相同类型
- nuw
- No Unsigned Wrap
- nsw
- No Signed Wrap
- 如果无符号/有符号溢出,nuw/nsw设置,得到poison value
fadd
- <result> = fadd [fast-math flags]* <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用相等类型的浮点/浮点向量上
sub
- <result> = sub
<ty
><op1
>,<op2
> ; yields ty:result - <result> = sub nuw
<ty
><op1
>,<op2
> ; yields ty:result - <result> = sub nsw
<ty
><op1
>,<op2
> ; yields ty:result - <result> = sub nuw nsw
<ty
><op1
>,<op2
> ; yields ty:result - 约束
- 作用到整数或者整数向量,两个操作数都必须是相同类型
- nuw
- No Unsigned Wrap
- nsw
- No Signed Wrap
- 如果无符号/有符号溢出,nuw/nsw设置,得到poison value
- <result> = sub
fsub
- <result> = fsub [fast-math flags]* <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用相等类型的浮点/浮点向量上
mul
- <result> = mul <ty> <op1>, <op2> ; yields ty:result
- <result> = mul nuw <ty> , <op2> ; yields ty:result
- <result> = mul nsw <ty> <op1>, <op2> ; yields ty:result
- <result> = mul nuw nsw <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用到整数或者整数向量,两个操作数都必须是相同类型
- nuw
- No Unsigned Wrap
- nsw
- No Signed Wrap
- 如果无符号/有符号溢出,nuw/nsw设置,得到poison value
fmul
- <result> = fmul [fast-math flags]* <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用相等类型的浮点/浮点向量上
udiv
- <result> = udiv <ty> <op1>, <op2> ; yields ty:result
- <result> = udiv exact <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用到整数或者整数向量,两个操作数都必须是相同类型
- 无符号整数相除
- 除0行为未知
- 使用exact时,如果((%op1 udiv exact %op2) mul %op2) != %op1, 则udiv exact得到的结果为poison value
sdiv
- <result> = sdiv <ty> <op1>, <op2> ; yields ty:result
- <result> = sdiv exact <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用到整数或者整数向量,两个操作数都必须是相同类型
- 有符号整数相除
- 除0行为未知
- 溢出行为未知
- 如果exact使用,结果被舍入,则结果为poison value
fdiv
- <result> = fdiv [fast-math flags]* <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用相等类型的浮点/浮点向量上
urem
- <result> = urem <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用到整数或者整数向量,两个操作数都必须是相同类型
- 无符号整数除法的余数
- op2为0,行为未知
- 例如
= urem i32 4, %var ; yields i32:result = 4 % %var
srem
- <result> = srem <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用到整数或者整数向量,两个操作数都必须是相同类型
- 有符号整数除法的余数
- 结果要么为0,要么与op1有相同的符号
- op2为0,行为未知
- 溢出行为未知
frem
- <result> = frem [fast-math flags]* <ty> <op1>, <op2> ; yields ty:result
- 约束
- 作用相等类型的浮点/浮点向量上
- 与被除数相同符号
5.4 二元位运算
shl
- <result> = shl <ty> <op1>, <op2> ; yields ty:result
- <result> = shl nuw <ty> <op1>, <op2> ; yields ty:result
- <result> = shl nsw <ty> <op1>, <op2> ; yields ty:result
- <result> = shl nuw nsw <ty> <op1>, <op2> ; yields ty:result
- 说明
- op1左移特定数量的位(op2为无符号)
- 结果为(op1 * 2^(op2) ) % 2^n
lshr
- <result> = lshr <ty> <op1>, <op2> ; yields ty:result
- <result> = lshr exact <ty> <op1>, <op2> ; yields ty:result
- 说明
- 逻辑右移
ashr
- <result> = ashr <ty> <op1>, <op2> ; yields ty:result
- <result> = ashr exact <ty> <op1>, <op2> ; yields ty:result
- 说明
- 算数右移
and
- <result> = and <ty> <op1>, <op2> ; yields ty:result
or
- <result> = or <ty> <op1>, <op2> ; yields ty:result
xor
- <result> = xor <ty> <op1>, <op2> ; yields ty:result
5.5 向量操作
extractelement
- <result> = extractelement <n x <ty>> <val>, <ty2> <idx> ; yields <ty>
- <result> = extractelement <vscale x n x <ty>> <val>, <ty2> <idx> ; yields <ty>
- 例子
- <result> = extractelement <4 x i32> %vec, i32 0 ; yields i32
insertelement
- <result> = insertelement <n x <ty>> <val>, <ty> <elt>, <ty2> <idx> ; yields <n x <ty>>
- <result> = insertelement <vscale x n x <ty>> <val>, <ty> <elt>, <ty2> <idx> ; yields <vscale x n x <ty>>
- 例子
- <result> = insertelement <4 x i32> %vec, i32 1, i32 0 ; yields <4 x i32>
shufflevector
- <result> = shufflevector <n x <ty>> <v1>, <n x <ty>> <v2>, <m x i32> <mask> ; yields <m x <ty>>
- <result> = shufflevector <vscale x n x <ty>> <v1>, <vscale x n x <ty>> v2, <vscale x m x i32> <mask> ; yields <vscale x m x <ty>>
- 例子
- <result> = shufflevector <4 x i32> %v1, <4 x i32> %v2, <4 x i32> <i32 0, i32 4, i32 1, i32 5> ; yields <4 x i32>
- <result> = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> ; yields <4 x i32> - Identity shuffle.
- <result> = shufflevector <8 x i32> %v1, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> ; yields <4 x i32>
- <result> = shufflevector <4 x i32> %v1, <4 x i32> %v2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7 > ; yields <8 x i32>
5.6 访问/操作内存
alloca
- <result> = alloca [inalloca] <type> [, <ty> <NumElements>] [, align <alignment>] [, addrspace(<num>)] ; yields type addrspace(num)*:result
- 说明
- 在当前正执行函数的栈帧分配内存,当函数返回到调用点时自动释放此内存。对象分配内存空间会根据datalayout的指示来
- 例子
- %ptr = alloca i32 ; yields i32*:ptr
- %ptr = alloca i32, i32 4 ; yields i32*:ptr
- %ptr = alloca i32, i32 4, align 1024 ; yields i32*:ptr
- %ptr = alloca i32, align 1024 ; yields i32*:ptr
load
- <result> = load [volatile] <ty>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<nontemp_node>][, !invariant.load !<empty_node>][, !invariant.group !<empty_node>][, !nonnull !<empty_node>][, !dereferenceable !<deref_bytes_node>][, !dereferenceable_or_null !<deref_bytes_node>][, !align !<align_node>][, !noundef !<empty_node>]
- <result> = load atomic [volatile] <ty>, <ty>* <pointer> [syncscope("<target-scope>")] <ordering>, align <alignment> [, !invariant.group !<empty_node>]
!<nontemp_node> = !{ i32 1 }
!<empty_node> = !{}
!<deref_bytes_node> = !{ i64 <dereferenceable_bytes> }
!<align_node> = !{ i64 <value_alignment> } - 说明
- 指定从哪个内存地址加载;指定的类型必须是已知first class类型(不包含opaque structural type)
- 例子
- %ptr = alloca i32 ; yields i32*:ptr
- store i32 3, i32* %ptr ; yields void
- %val = load i32, i32* %ptr ; yields i32:val = i32 3
store
- store [volatile] <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<nontemp_node>][, !invariant.group !<empty_node>] ; yields void
- store atomic [volatile] <ty> <value>, <ty>* <pointer> [syncscope("<target-scope>")] <ordering>, align <alignment> [, !invariant.group !<empty_node>] ; yields void
!<nontemp_node> = !{ i32 1 }
!<empty_node> = !{} - 说明
- 被用来写内存
- 类型必须是的first-class类型
- 例子
- %ptr = alloca i32 ; yields i32*:ptr
- store i32 3, i32* %ptr ; yields void
- %val = load i32, i32* %ptr ; yields i32:val = i32 3
fence
- 用于实现happens-before
cmpxchg
- 用于自动修改内存(比较,然后修改)。
atomicrmw
- 用于自动修改内存
getelementptr
- <result> = getelementptr <ty>, * {, [inrange] <ty> <idx>}*
- <result> = getelementptr inbounds <ty>, <ty>* <ptrval>{, [inrange] <ty> <idx>}*
- <result> = getelementptr <ty>, <ptr vector> <ptrval>, [inrange] <vector index type> <idx>
- 说明
- 获取aggregate数据结构的子元素的地址;它只执行地址计算不访问内存
- 例子
struct RT {char A;int B[10][20];char C; }; struct ST {int X;double Y;struct RT Z; }; int *foo(struct ST *s) {return &s[1].Z.B[5][13]; }
%struct.RT = type { i8, [10 x [20 x i32]], i8 }%struct.ST = type { i32, double, %struct.RT }define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {entry:%arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13ret i32* %arrayidx}
5.6 强转操作
trunc ... to
zext ... to
- <result> = zext <ty> <value> to <ty2> ; yields ty2
- 约束
- 两个ty必须是整数,或者相同数量的整数向量
- value的位数要比ty2类型的位数小
- 例子
- %X = zext i32 257 to i64 ; yields i64:257
- %Y = zext i1 true to i32 ; yields i32:1
- %Z = zext <2 x i16> <i16 8, i16 7> to <2 x i32> ; yields <i32 8, i32 7>
sext ... to
fptrunc ... to
fpext ... to
fptoui ... to
fptosi ... to
uitofp ... to
sitofp ... to
ptrtoint ... to
inttoptr ... to
bitcast ... to
addrspacecast ... to
5.7 其它操作
icmp
- <result> = icmp <cond> <ty> <op1>, <op2> ; yields i1 or <N x i1>:result
- <cond>
- eq: equal
- ne: not equal
- ugt: unsigned greater than
- uge: unsigned greater or equal
- ult: unsigned less than
- ule: unsigned less or equal
- sgt: signed greater than
- sge: signed greater or equal
- slt: signed less than
- sle: signed less or equal
- 说明
- 返回布尔值或者布尔值的向量
- op1和op2必须是integer/pointer或者interger vector
- 例子
- <result> = icmp eq i32 4, 5 ; yields: result=false
- <result> = icmp ne float* %X, %X ; yields: result=false
- <result> = icmp ult i16 4, 5 ; yields: result=true
- <result> = icmp sgt i16 4, 5 ; yields: result=false
- <result> = icmp ule i16 -4, 5 ; yields: result=false
- <result> = icmp sge i16 4, 5 ; yields: result=false
fcmp
- <result> = fcmp [fast-math flags]* <cond> <ty> <op1>, <op2> ; yields i1 or <N x i1>:result
- <cond>
- false: no comparison, always returns false
- oeq: ordered and equal
- ogt: ordered and greater than
- oge: ordered and greater than or equal
- olt: ordered and less than
- ole: ordered and less than or equal
- one: ordered and not equal
- ord: ordered (no nans)
- ueq: unordered or equal
- ugt: unordered or greater than
- uge: unordered or greater than or equal
- ult: unordered or less than
- ule: unordered or less than or equal
- une: unordered or not equal
- uno: unordered (either nans)
- true: no comparison, always returns true
- 例子
- <result> = fcmp oeq float 4.0, 5.0 ; yields: result=false
- <result> = fcmp one float 4.0, 5.0 ; yields: result=true
- <result> = fcmp olt float 4.0, 5.0 ; yields: result=true
- <result> = fcmp ueq double 1.0, 2.0 ; yields: result=false
phi
- <result> = phi [fast-math-flags] <ty> [ <val0>, <label0>], …
- 说明
- 每个val对应一个label;
- 每个label对应一个basic block,此bb到phi节点的incoming value就是val
select
freeze
call
va_arg
landingpad
catchpad
cleanuppad
LLVM IR / LLVM指令集入门相关推荐
- LLVM框架/LLVM编译流程/Clang前端/LLVM IR/LLVM应用与实践-李明杰-专题视频课程
LLVM框架/LLVM编译流程/Clang前端/LLVM IR/LLVM应用与实践-3人已学习 课程介绍 LLVM并非仅仅是一款编译器这么简单.利用LLVM,我们可以进行各种疯狂的操作 ...
- LLVM IR入门指南(4)——类型系统
我们知道,汇编语言是弱类型的,我们操作汇编语言的时候,实际上考虑的是一些二进制串.但是,LLVM IR却是强类型的,在LLVM IR中所有变量都必须有类型.这是因为,我们在使用高级语言编程的时候,往往 ...
- 简单了解LLVM IR基本语法
可以转载,请注明出处! 以下内容是参照官方文档,对一些代码样例做出的解释,想要彻底掌握IR的语法规则,还是需要仔细熟读IR的官方文档.这里只是对IR的入门介绍,等上道之后,建议再去看官方文档,因为工作 ...
- LLVM每日谈之四十五 LLVM IR TUTORIAL
今年的LLVM欧洲开发者会议上,在Tutorials环节,Vince Bridgers (Intel Corporation), Felipe de Azevedo Piovezan (Intel C ...
- 修改的LLVM IR基本指令
SysY2022语言定义中不包含无符号整数.结构体.移位操作,整数和浮点数均为32位,比赛测试样例不包含错误.鉴于SysY2022语言的特点,为了IR的简洁,对LLVM IR进行筛选和修改得到如下指令 ...
- LLVM IR 理解
LLVM IR 理解 LLVM IR表示 LLVM IR有三个不同的形式: 内存中编译中间语言(IR) 保存在硬盘上的 bitcode(.bc 文件,适合快速被一个 JIT 编译器加载) 一个可读性的 ...
- 使用clang将C/C++代码编译成LLVM的中间代码(LLVM ir bitcode),并反汇编LLVM bitcode
test.c文件内容如下: #include<stdio.h> int main(void){printf("hello world!\n");return 0; } ...
- 手写token解析器、语法解析器、LLVM IR生成器(GO语言)
最近开始尝试用go写点东西,正好在看LLVM的资料,就写了点相关的内容 - 前端解析器+中间代码生成(本地代码的汇编.执行则靠LLVM工具链完成) https://github.com/daibinh ...
- 【从零开始学深度学习编译器】十五,MLIR Toy Tutorials学习笔记之Lowering到LLVM IR
0x0. 前言 在上一节中,我们将Toy Dialect的部分Operation Lowering到Affine Dialect,MemRef Dialect和Standard Dialect,而to ...
- LLVM IR 语法
译者序 目前几乎没有关于LLVM IR(中间语言)的中文资料,因此本人在看英文手册的同时尝试翻译.限于水平和时间,本文只翻译了一小部分英文手册,如果发现理解有冲突之处,请以原文为准. ...
最新文章
- ASP.NET2.0中的ClientScriptManager 类用法—如何添加客户端事件
- c++中vector的用法详解
- Redis入门与数据类型介绍
- TP返回原生SQL语句:fetchSql
- linux启动xorg进程,Linux 黑话解释:Xorg,X11,Wayland,什么是显示服务器
- DiscoveryService.getRemoteAdvertisements是否会获得本地通告?
- idea搭建maven项目关于数据库连接jar包版本问题解决方案
- css3 弹性盒模型 变化
- 介绍几种jquery ui使用方法
- QT从字体名获取字库文件路径(从宋体获取到simsun.ttc)
- 浅析JVM中常见的垃圾收集算法
- Java机器人解密游戏_解谜类游戏 篇十:在机器人的世界中,那些隐藏在谜题之下的眼泪...
- DotNetTools Workflow教程
- 华钜同创:亚马逊滞销产品快速清仓的方法!
- ip代理软件的原理到底是什么?适用场景有哪些?
- 关于cgi的初步认识推荐两篇博文
- 在linux用utorrent下载文件,utorrent在ubuntu上怎么使用
- deeplinux 热点_deepin使用笔记,安装steam客户端
- 10月24日 化装晚会
- 搭建网站?(手把手教你)