#8 llvm & complier & cpp
敲!compiler?!
LLVM之父Chris Lattner :现在是编译器的黄金时代(hhh 其实所有技术现在都处于黄金时代)
背景介绍
例行公事,还是得先要介绍一下编译器(complier)是干嘛的。但是当我在b站上看到一个比较厉害的up主上传的非常友好的编译体系科普视频,我决定偷偷懒就不在这里给大伙做介绍了(因为他实在讲的太好了捏 图文并茂),上链接
编译体系漫游
看完上述科普向视频,大概能对编译器是干嘛、编译的流程、现在市面上有哪些编译器(编译器框架)有一个大概的了解(emmm 好像没介绍msvc 不对 是msbc 那玩意太蠢了 谁用谁知道)
学习编译原理最好的方式就是自己写一个编译器,不然学习再多的理论也是徒劳,因为困难往往隐藏在实现的细节当中。
但是从0实现一个完整的编译器是一个十分困难且工作量巨大的工程(特别是在你想要实现一个有一定优化和拓展性的编译器)。好在现在llvm提供了一套框架,我们只需要分析我们所需要实现语言上的特性,在llvm的规则下编译对应的词法、语法、语义分析等,将我们需要实现语言的源代码转换成llvm框架下的虚拟指令形式(有点像做映射?),我们不需要去关注怎么编写编译器的优化,因为llvm框架自己能对llvm虚拟指令进行非常非常多的优化,我们也不需要做我们实现语言跟各种各样平台的汇编的映射,因为llvm框本身架能对llvm虚拟指令与各种各样的平台的汇编作转换。
2023年了,不基于llvm开发编译器都是耍流氓,我说的~~(暴论~~
还有要注意的一点是,就算你对编译器好不感兴趣。这里仍然也有很多你学习llvm工具链的理由,比如它提供了非常多分析你程序的工具(比如分许你编写的程序的性能瓶颈、找出你程序中可能存在的内存泄露
我在这里只介绍了llvm对于传统编译器的意义(比如咱们的c/c++
的编译器),但是在很多深度学习框架的底层也是跑的mlir/llvm
(毕竟深度学习的代码也需要编译是不是。但是这些就需要更进一步的探索了。
实现计算器捏
好。说了这么多,也该说说这道招新题的事情了,一般来说大家编译器入门的第一个小项目都会是做一个支持四则运算的计算器,注意是编译器不是解释器,咱们写的计算器应该是可以双击运行的程序,而不是依托于一些其他的平台(例如jvm)。
至于招新题目是什么。emm 你猜对了 我们这次的主要内容就是使用llvm来做一个支持四则运算的计算器
但是如果直接让你去学习llvm的框架(对于没有基础的童鞋来说这是十分困难的。毕竟你甚至现在不知道该如何编译llvm-project。所以捏,我们的想法是提供一个利用llvm编写的计算器的源代码,你要做的是学习这个计算器的源代码、在这个基础上做一些拓展(例如支持括号来提升运算的优先级/当除数为0的时候崩溃。。。)
不过这一切有一个前提,就是你得先把llvm-project
下载下来并且使用(你心想这还不简单,百度搜索llvm,立即下载x64平台,双击执行不就行了么)呃 可能跟你想的有一点偏差,毕竟其实有很多的东西可以在命令行(或者只能在命令行)下使用 可以想一下自己最初使用git
一般来说我们要使用命令行工具有两种方式(在类unix环境下哈,不要跟我说windows的事情!!顺带一提做这个题目之前有一个类unix系统是最基本的条件,你可以选择linux常见发行版或者macos,虚拟机、wsl、双系统都可以,我是不会去介绍windows下的方法的)
这两种方式分别是通过包管理器(apt/yum/pacman/brew…这个一般是与平台相关的)下载软件和源码编译安装(一个常见的方式是 git clone … && cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --buid build --parallel 4 && cmake --build build --target install)。
如果你是一位green hand
,我会非常推荐你使用包管理器来安装任何命令行程序(或者一些有图形化界面的程序),这样会省去非常多不必要的麻烦,毕竟完整编译安装llvm少则半小时,多则两小时(期间还可能会有各种各样的报错)。当然编译安装也有编译安装的好处,就是你可以自由的选择你需要的模块来编译,并且可以编译debug
模式来进入程序内部调试程序(不过千万不要以debug模式来编译安装llvm,因为他可能会吃掉你电脑的30G硬盘空间)
下面我就以通过ubuntu
下的apt
安装 llvm-12 来给大家做一个例子( llvm有很多个版本 我们这里采用的是比较新的llvm12 千万不要安装错版本了)
sudo apt-get install llvm-12
# 等待安装完成后执行下面这条命令 这种命令一般可以用来检验你是否安装好了一个程序
# 安装后你可以阅读一下由 apt 产生的日志(就是你安装过程中打印在终端上的文本) 里面可能会有一些有用的信息 例如如何初始化或者启动你刚刚下载程序 如果将apt下载的程序添加到环境变量等等
# which opt
opt --version
好 到目前为止你应该已经安装好了llvm-12
了,剩下的就是开始下载我们的计算器了。
# 如果你比较了解git的使用也许会发现这个招新题有一个的小彩蛋
git clone https://github.com/GithubXxz/llvm-calc.git --depth=1
cd llvm-calc
# 构建这个项目 请注意路径是否正确
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
build/src/calc "with a : 3 + 2 + a" | llc -filetype=obj -relocation-model=pic -o exp.o
clang++ -o exp exp.o rtcalc.cpp
./exp
你可以输入一个数字然后回车,看一下输出是否符合预期,你也可以测试一些其他的表达式。
非常建议你写一个shell脚本来完成上述的构建命令
测试了一下基本的加减法功能,剩下的就是阅读源代码,通过debug搞清楚程序执行的流程(词法分析/语法分析/语义分析/代码生成)。对了,这期间可能会用到一个叫做访问者模式的设计模式访问者模式,可以以这篇文章作为一个切入点。
剩下的时间就是在给定的框架对它进行拓展,实现一些新的功能了。
前置内容:
参阅
了解一些llvm的基础知识(SSA/LLVM IR表示)
- 搞清楚构建命令(clang++、llc)是干嘛用的 为什么要通过这些命令来构建一个可执行程序
要求实现:
(可能需要重新定义输出计算结果的触发点,分隔符是完全可以自己来定义的哦)
# 例如
with a : int b : b = a + 3 : with m : a = b + a * 10 - m
- 实现浮点数的计算和存储(可能需要将with改成withint和withfloat和运算时可能需要对整数类型的提升来进行和浮点数的运算)
- 发挥你的想象力实现任何计算器可以实现的功能(这很重要
学有余力可以了解一下antlr的使用,来帮助自己更加便捷地构建一个功能强大计算器
My First Language Frontend with LLVM
好吧,对于大多数童鞋来说,写一个计算器~~(写计算器真没意思,我要看血流成河)~~完全不能满足大家对于一门编程语言的想象(计算器和c语言这样的编程语言也差的太远了)。
8说了 直接上正菜
Kaleidoscope: Implementing a Language with LLVM
这是llvm官方提供的使用llvm构建一门叫做Kaleidoscope
的语言的教程。冲他就完事了
真正有想法要做这道题目的童鞋,可以参照计算器那一节的cmake写法和一些常见的语句的构建(加减乘除和跳转语句什么的构造都是大差不差的),基本都是互通的。有什么问题或者需要什么支持 也欢迎来找我讨论。
要求实现:
- 构建一门属于你自己的编程语言(其中滋味只有自己写过编译器的人才知道捏
参考资料:
提交内容
- 编写好markdown文档并且附上你的github项目地址(或者dockerhub项目地址)
- markdown文档中包含做项目的学习过程和学习/编码的心得体会
- 详尽的项目部署运行方式