LLVM笔记1

这篇具有很好参考价值的文章主要介绍了LLVM笔记1。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考:https://www.bilibili.com/video/BV1D84y1y73v/?share_source=copy_web&vd_source=fc187607fc6ec6bbd2c74a3d0d7484cf


LLVM升级:
https://blog.csdn.net/weixin_51760563/article/details/127810160
https://zhuanlan.zhihu.com/p/614675827

升级cmake:
https://zhuanlan.zhihu.com/p/519732843

零、入门名词解释

1. Compiler & Interpreter

将程序从高级语言翻译到机器语言,得到一个可运行的文件。
LLVM笔记1,Linux,笔记
LLVM笔记1,Linux,笔记

2. AOT静态编译和JIT动态解释的编译方式

LLVM笔记1,Linux,笔记

3. Pass

对源程序的一次完整扫描或处理。从高级语言到低级语言或者IR会经过几次Pass。比如下图第一个Pass是词法分析、语法分析、语义分析(图片里中间代码生成拼错了)。
LLVM笔记1,Linux,笔记

4. Intermediate Representations中间表达

可以是数据结构或者定义好的代码,能让编译器或者虚拟机表达源码就行。

5. 编译器基本构成

  • 前端:词法语法分析,将源代码转化为抽象语法树。
  • 优化:对前端得到的IR优化,使得更高效。
  • 后端:将优化的IR转化为针对各自平台的机器代码。比如X86、ARM、GPU上执行的机器码是不同的。
    LLVM笔记1,Linux,笔记

一、GCC编译流程

  • 预处理(前端):读入源代码,响应预处理指令和替换宏定义,删除程序中的注释和多余空白符。会把引用的头文件和自己写的hello.c文件都放在hello.i文件中。
  • 编译(优化):语法分析和词法分析,以及大量优化。hello.s中都是汇编指令。
  • 汇编(后端):则是将汇编指令转为机器语言。
  • 链接(后端):链接程序用到的目标文件、各种依赖的库文件,生成可执行文件,以二进制形式存储在磁盘中。
    LLVM笔记1,Linux,笔记

二、LLVM编译技术

1. LLVM设计架构

利用IR做中转,将前端和优化和后端分离开。不同于GCC的前后端没有解耦,LLVM增加一种新的语言时只用实现一个新的编译前端,优化和后端都能复用。

clang -E -c hello.c -o hello.i
clang -emit-llvm hello.c -S -o hello.ll #这里是导出为IR模式
llc hello.ll -o hello.s #这里导出的是汇编语言了
clang hello.s -o hello #这里得到可执行的二进制文件

LLVM笔记1,Linux,笔记

LLVM笔记1,Linux,笔记
LLVM笔记1,Linux,笔记

2. LLVM IR

2.1 IR语法

;表示注释
@全局变量开头
%局部变量开头
alloca在函数栈中分配内存
store写入
load读取
i32 32位4字节
align字节对齐(计算机中内存大小的基本单位是字节(byte),理论上来讲,可以从任意地址访问某种基本数据类型,但是实际上,计算机并非逐字节大小读写内存,而是以2,4,或8的 倍数的字节块来读写内存,如此一来就会对基本数据类型的合法地址作出一些限制,即它的地址必须是2,4或8的倍数。那么就要求各种数据类型按照一定的规则在空间上排列,这就是对齐。)
LLVM笔记1,Linux,笔记

  • IR假设寄存器数量无限。
  • 指令都是三地址形式,操作码OP 第一操作数地址A1 第二操作数地址A2 结果地址A3
  • 不使用固定的命名寄存器,都是用%字符命名临时寄存器。

2.2 IR三种表达形式

这三种中间格式是完全等价的:

  • 在内存中的编译中间语言(无法通过文件的形式得到的指令类等)
  • 在硬盘上存储的二进制中间语言( 格式为.bc )
  • 人类可读的代码语言(格式为.Il )

2.3 IR内存模型

如果在编译器的优化层对LLVM的IR进行操作,写一个定制的优化pass,就需要了解LLVM IR内存模型。

● LLVM IR文件的基本单位称为module;
● 一个module中可以拥有多个顶层实体,比如function和global variable;
● 一个function define中至少有一个basicblock(就是花括号);
● 每个basicblock中有若干instruction ,并且都以terminator instruction(写作ret,就是return的意思)结尾。

void test( int a, int b){
	int c=a*b + 100;
}
1 ; Function Attrs: noinline nounwind optnone ssp uwtable
2 define void @test(i32, i32) #2 { ;有个全局函数@test (a,b)
3 %3 = alloca 132,align 4 ;局部变量C
4 %4 = alloca i32,align 4 ;局部变量d
5 %5 = alloca i32, align 4 ;局部变量e
6 store i32 %0, i32*%3,align 4 ;%0赋值给3C=a
7 store i32%1,i32*%4,align 4 ;%1赋值给%4d=b
8 %6=load i32, i32*%3, align 4 ;读取%3 ,赋值给%6就是函数参数a
9 %7=load i32, i32* %4 , align 4 ;读取%4 ,赋值给%7就是函数参数b
10 %8=mul nsw i32%6, %7 ;a*b
11 %9=add nsw i32%8, 100 ;a*b+100
12 store i32%9, i32*%5, align 4 ;参数%9赋值给%5 e ===>就是转换前函数写的int c变量
ret void

3. LLVM前端

3.1 词法分析

前端的第一个步骤处理源代码的文本输入,将语言结构分解为一组单词和标记,去除注释、空白、制表符等。每个单词或者标记必须属于语言子集,语言的保留字被变换为编译器内部表示

3.2 语法分析

分组标记以形成表达式、语句、函数体等。检查-组标记是否有意义 ,考虑代码物理布局,未分析代码的意思,就像英语中的语法分析,不关心你说了什么,只考虑句子是否正确,并输出语法树( AST )。
LLVM笔记1,Linux,笔记

3.3 语义分析

借助符号表检验代码没有违背语言类型系统。符号表存储标识符和其各自的类型之间的映射,以及其它内容。类型检查的一-种直觉的方法是,在解析之后,遍历AST的同时从符号表收集关于类型的信息。

4. LLVM优化

4.1 发现Pass

优化通常由分析Pass和转换Pass组成:

  • 分析Pass :负责发掘性质和优化机会;
  • 转换Pass :生成必需的数据结构,后续为后者所用;

4.2 Pass依赖

在转换Pass和分析Pass之间,有两种主要的依赖类型:

  • 显式依赖:转换Pass需要一种分析,则Pass管理器自动地安排它所依赖的分析Pass在它之前运行;
DominatorTree &DT = getAnalysis<DominatorTree>(Func);
  • 隐式依赖:转换或者分析Pass要求IR代码运用特定表达式。需要手动地以正确的顺序把这个Pass加到Pass队列中,通过命令行工具( clang或者opt )或者Pass管理器。

4.3 Pass API

Pass类是实现优化的主要资源。然而,我们从不直接使用它,而是通过清楚的子类使用它。当实现一个Pass时,你应该选择适合你的Pass的最佳粒度,适合此粒度的最佳子类,例如基于函数、模块、循环、强联通区域,等等。常见的这些子类如下:
● ModulePass (一个模块)
● FunctionPass(一个函数)
● BasicBlockPass (某几条指令)

5. LLVM后端

也是由多个Pass链接,分为必要Pass和非必要Pass,下面介绍一些必要Pass

5.1 指令选择

  • 内存中LLVM IR变换为目标特定SelectionDAG节点;
  • DAG有向无环图,IR变成图后表示单一的一个计算节点,图的节点是具体执行的指令,边是数据流依赖关系。。每个DAG能够表示单一基本块的计算。

5.2 指令调度

第1次指令调度( Instruction Scheduling ) ,也称为前寄存器分配(RA)调度。
●对指令排序,同时尝试发现尽可能多的指令层次的并行;
●然后指令被变换为MachineInstr三地址表示。

5.3 寄存器分配

LLVM IR寄存器集是无限的,这个性质一直保持着,直到寄存器分配( Register Allocation )
●寄存器分配将无限的虚拟寄存器引用转换为有限的目标特定的寄存器集;
●寄存器不够时挤出( spill )到内存。

5.4 指令调度

第2次指令调度,也称为后寄存器分配(RA)调度。
●此时可获得真实的寄存器信息,某些类型寄存器存在延迟,它们可被用以改进指令顺序。

5.5 代码输出

  • 代码输出阶段将指令从MachineInstr表示变换为MCInst实例;
  • 新的表示更适合汇编器和链接器,可以输出汇编代码或者输出二进制块特定目标代码格式。

发展

XLA (加速线性代数)是一种针对特定领域的线性代数编译器。

Julia面向科学计算的高性能动态编程语言,使用LLVM JIT编译。LLVM JIT编译器通常不断地分析正在执行的代码,并且识别代码的一部分 ,使得从编译中获得的性能加速超过编译该代码的性能开销。文章来源地址https://www.toymoban.com/news/detail-626350.html

到了这里,关于LLVM笔记1的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • LLVM安装教程

    llvm下载页面:https://releases.llvm.org/download.html 方法一:从官网上下载预编译好的包 在Ubuntu 20.04安装LLVM 13.0.0 sudo mkdir -p /usr/local cd /usr/local sudo wget https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-linux-gnu-ubuntu-20.04.tar.xz sudo tar xvf clang+llvm-13.0.0-x86_64-linux-g

    2024年02月15日
    浏览(36)
  • LLVM代码内容

    LLVM库包含所有LLVM顶层项目,可以分为以下几类: • LLVM核心库和附加内容 • 编译器和工具 • 运行时库         LLVM是一个编译器框架。LLVM作为编译器框架,是需要各种功能模块支撑起来的。可以将clang和lld都看做是LLVM的组成部分。框架的意思是,你可以基于LLVM提供的功能

    2024年01月20日
    浏览(36)
  • LLVM编译

    欢迎到我的博客来阅读这篇文章: https://qiu-weidong.github.io/2022/05/01/llvm/build/ 安装Visual Studio 首先需要下载 Visual Studio Installer 的安装程序 VisualStudioSetup.exe ,下载链接: https://visualstudio.microsoft.com/zh-hans/downloads/。选择社区版,点击 免费下载 。 下载后,双击运行 VisualStudioSetup.exe 。

    2024年02月07日
    浏览(34)
  • PWN学习之LLVM入门

    ①找到runOnFunction函数时如何重写的,一般来说runOnFunction都会在函数表最下面,找PASS注册的名称,一般会在README文件中给出,若是没有给出,可通过对__cxa_atexit函数\\\"交叉引用\\\"来定位: ②通过逆向,找到函数名及参数,编写基本exp ③找到漏洞,写利用exp.c,其中的pwn的目标是

    2024年02月05日
    浏览(26)
  • 2401llvm,clang的libtooling

    LibTooling 是个支持基于 Clang 编写 独立工具 的库. 在此,为 LLVM 安装 Clang 工具 用 LibTooling 构建的工具(如 Clang 插件)通过代码运行 FrontendActions . 这里演示运行 Clang 的快速检查 一堆代码语法 的 SyntaxOnlyAction 的不同方法. 如果想对,如对 ClangAST 的某些部分 单元测试 的 代码 运行 F

    2024年01月23日
    浏览(41)
  • LLVM(5)ORC实例分析

    总结 因为API茫茫多,逻辑上的一些概念需要搞清,编码时会容易很多。 JIT的运行实体使用LLVMOrcCreateLLJIT可以创建出来,逻辑上的JIT实例。 JIT实例需要加入运行库(依赖库)和用户定义的context(运行内容)才能运行,LLVMOrcLLJITAddLLVMIRModule函数负责将运行库和ctx加入JIT实例。

    2024年02月07日
    浏览(79)
  • clang+llvm多进程gdb调试

    在学习新增llvm的优化pass时,需要跟踪clang及llvm的调用栈。然而llvm通过 posix_spawn() 创建了新进程,这使得gdb调试必须有一定的技巧了。 以下命令通过clang调用新增优化pass(指令替换),将simple.c文件中的sum函数替换掉: 单步调试的命令为: 实际上,在我的ubuntu下clang指向cl

    2024年02月05日
    浏览(39)
  • Mac 上编译 LLVM 7.x

    Mac 上编译 LLVM 7.x 如果您想在搭载 M1 芯片的 Mac 上编译 LLVM 7.x,可以按照以下步骤进行操作。请注意,LLVM 的版本和编译过程可能随时间变化,因此确保查看 LLVM 的官方文档以获取最新的信息。 安装开发工具和依赖项: 在 M1 Mac 上编译 LLVM,首先需要安装一些开发工具和依赖项

    2024年02月05日
    浏览(30)
  • 深度学习AI编译器-LLVM简介

    LLVM的命名最早来源于底层语言虚拟机(Low Level Virtual Machine)的缩写。它是一个用于建立编译器的基础框架,以C++编写。创建此工程的目的是对于任意的编程语言,利用该基础框架,构建一个包括编译时、链接时、执行时等的语言执行器。目前官方的LLVM只支持处理C/C++,Obje

    2024年02月06日
    浏览(43)
  • openharmony 编译LLVM编译器基础架构

    third_party_llvm-project: 管理员 liwentao_uiw dhy308 huanghuijin (1) 缺少依赖,一次安装好几个依赖 (2) case in的语法识别不了 实际上case in是没有问题的,主要是结尾需要改成Unix结尾

    2024年01月19日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包