本文基于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形式的,所以会验证格式错误

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对象被重命名以防止名字冲突
  • 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字节大小
    • Opaque Structure
      • 没有结构体,类似C中的结构体类型前向声明

        • %X = type opaque
        • %52 = type opaque

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`
      
  • 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
  • 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指令集入门相关推荐

  1. LLVM框架/LLVM编译流程/Clang前端/LLVM IR/LLVM应用与实践-李明杰-专题视频课程

    LLVM框架/LLVM编译流程/Clang前端/LLVM IR/LLVM应用与实践-3人已学习 课程介绍         LLVM并非仅仅是一款编译器这么简单.利用LLVM,我们可以进行各种疯狂的操作 ...

  2. LLVM IR入门指南(4)——类型系统

    我们知道,汇编语言是弱类型的,我们操作汇编语言的时候,实际上考虑的是一些二进制串.但是,LLVM IR却是强类型的,在LLVM IR中所有变量都必须有类型.这是因为,我们在使用高级语言编程的时候,往往 ...

  3. 简单了解LLVM IR基本语法

    可以转载,请注明出处! 以下内容是参照官方文档,对一些代码样例做出的解释,想要彻底掌握IR的语法规则,还是需要仔细熟读IR的官方文档.这里只是对IR的入门介绍,等上道之后,建议再去看官方文档,因为工作 ...

  4. LLVM每日谈之四十五 LLVM IR TUTORIAL

    今年的LLVM欧洲开发者会议上,在Tutorials环节,Vince Bridgers (Intel Corporation), Felipe de Azevedo Piovezan (Intel C ...

  5. 修改的LLVM IR基本指令

    SysY2022语言定义中不包含无符号整数.结构体.移位操作,整数和浮点数均为32位,比赛测试样例不包含错误.鉴于SysY2022语言的特点,为了IR的简洁,对LLVM IR进行筛选和修改得到如下指令 ...

  6. LLVM IR 理解

    LLVM IR 理解 LLVM IR表示 LLVM IR有三个不同的形式: 内存中编译中间语言(IR) 保存在硬盘上的 bitcode(.bc 文件,适合快速被一个 JIT 编译器加载) 一个可读性的 ...

  7. 使用clang将C/C++代码编译成LLVM的中间代码(LLVM ir bitcode),并反汇编LLVM bitcode

    test.c文件内容如下: #include<stdio.h> int main(void){printf("hello world!\n");return 0; } ...

  8. 手写token解析器、语法解析器、LLVM IR生成器(GO语言)

    最近开始尝试用go写点东西,正好在看LLVM的资料,就写了点相关的内容 - 前端解析器+中间代码生成(本地代码的汇编.执行则靠LLVM工具链完成) https://github.com/daibinh ...

  9. 【从零开始学深度学习编译器】十五,MLIR Toy Tutorials学习笔记之Lowering到LLVM IR

    0x0. 前言 在上一节中,我们将Toy Dialect的部分Operation Lowering到Affine Dialect,MemRef Dialect和Standard Dialect,而to ...

  10. LLVM IR 语法

    译者序     目前几乎没有关于LLVM IR(中间语言)的中文资料,因此本人在看英文手册的同时尝试翻译.限于水平和时间,本文只翻译了一小部分英文手册,如果发现理解有冲突之处,请以原文为准.     ...

最新文章

  1. ASP.NET2.0中的ClientScriptManager 类用法—如何添加客户端事件
  2. c++中vector的用法详解
  3. Redis入门与数据类型介绍
  4. TP返回原生SQL语句:fetchSql
  5. linux启动xorg进程,Linux 黑话解释:Xorg,X11,Wayland,什么是显示服务器
  6. DiscoveryService.getRemoteAdvertisements是否会获得本地通告?
  7. idea搭建maven项目关于数据库连接jar包版本问题解决方案
  8. css3 弹性盒模型 变化
  9. 介绍几种jquery ui使用方法
  10. QT从字体名获取字库文件路径(从宋体获取到simsun.ttc)
  11. 浅析JVM中常见的垃圾收集算法
  12. Java机器人解密游戏_解谜类游戏 篇十:在机器人的世界中,那些隐藏在谜题之下的眼泪...
  13. DotNetTools Workflow教程
  14. 华钜同创:亚马逊滞销产品快速清仓的方法!
  15. ip代理软件的原理到底是什么?适用场景有哪些?
  16. 关于cgi的初步认识推荐两篇博文
  17. 在linux用utorrent下载文件,utorrent在ubuntu上怎么使用
  18. deeplinux 热点_deepin使用笔记,安装steam客户端
  19. 10月24日 化装晚会
  20. 搭建网站?(手把手教你)

热门文章

  1. 删库跑路技巧 删库跑路命令
  2. 工作-safari时间格式
  3. 统计学③——总体与样本的差异在哪里
  4. Python—猫眼电影票房爬虫实战 轻松弄懂字体反爬!
  5. 苹果鼠标右键怎么按_iPadOS 13.4 鼠标体验如何?附使用指南
  6. 12 | 腾讯云代码分析快速部署
  7. 联想计算机e480,【晒单】联想ThinkPad E480外观性能屌炸天
  8. 计算机远程操作之后怎么保护,电脑远程控制怎么操作 两种方法介绍
  9. oracle的alter table,Oracle ALTER TABLE语句
  10. Ubuntu 12.04设置豆沙绿