LLVM学习笔记

LLVM是一款比较新的编译器工具。网上对LLVM使用的相关文档比较少,大部分都是官方给的例子。翻译过后晦涩难懂。在次,写一篇心得,也是为了课程任务,也是为了自己的一个学习总结,总结一下LLVM的学习过程,以及LLVM的万花筒实例。

首先和大家说一说LLVM是干什么的。LLVM是一个编译器。一个帮助你更简单写编译器的一个框架。在LLVM中有很多文件,这些文件我们都看不懂,也不用管,需要什么,找什么就可以。我们需要看的就是里面的万花筒的例子,在Examples文件里面的。

这个万花筒实现了一个简单的函数式语言,前面几个例子都不是完整的,从第四个开始,你可以用例子将他的语言完整的运行起来。

估计很多初学者和我一样,看着这个LLVM有点摸不到头脑,不知道如何去做,没关系,继续向下看,下面帮大家梳理的一下LLVM框架,通过例子,帮大家更好的理解。

在开始之前,我想先请大家想一想,一个完整的编译器都需要什么?词法分析,语法分析,语义分析,中间代码生成。(语法制导和优化在LLVM中几乎已经被做了,初学者也不用管他)

  1. 词法分析。在这部,你肯定要把一个一个的词读出来,看看是否和你规定的语言一样。(比如说,C语言,整数声明是 int a,你写一个in a 肯定是错的)在这里,你就要读取字符,和你自己规定的对比一下,看看是否是正确的。
  2. 语法分析,当你分析出输入的东西是你规定的时候,就要考虑语法的正确性,还是C语言的例子(int , 要求后边是一个变量的名字,你肯定不可以写int 3 ,这种就是错误的。)在这一步,你可以给所有的类型标记为1,所有字母标记为2,所有数字标记为3.当年你识别到 1(类型标记)之后,你应该继续识别到2才正确,3不可以在1 的后面。(例子可能不是那么严谨,但是对于理解来说是没问题的)
  3. 语义分析,基本上就是检测一些函数调用啥的合不合理。
  4. 中间代码生成LLVM都帮你做了,我们几乎不需要做啥,只需要你遵守LLVM的接口,用他的一些类,就可以了。

万花筒是LLVM里面提供的一个实例,完成了一个比较简单地语言。通过学习这个语言,可以增强对LLVM的理解。首先说一下LLVM安装。首先下载LLVM以及Clang,将LLVM转化成VS2017可执行版。在这里不再赘述,网上有很多安装教程。

首先生成一下解决方案。大概半个多小时吧。LLVM是真的大。话不多说,直接点开Example文件。里面的Kaleidoscope便是LLVM自带的简单语言的例子。

Kaleidoscope2

万花筒一里面几乎什么都没有。我们直接从第二个开始看起。第二个主要完成的是词法分析和语法分析。我们从main函数开始看起。

Main函数中主要包含3部分。符号优先级设定(那几个BinopPrecedence),getNextToken函数,MainLoop函数。关于符号的优先级,我们先不去管他,我们先开一下getToken函数。

返回的是一个CurTok值,好吧,我们进到里面继续看。(这个CurTok其实就是我说的那个1 2 3 的标记)

在gettok函数里,可以看到,首先使用一个while循环去除输入的空格和换行。然后分析是否是字母。当后面的字符是数字和字母的时候,将其加到IndentifierStr上。最后分析这个串是不是def 以及extern。其实这一步就是保存声明的变量或者函数名的关键字的。将以字母为首,后面是字母和数字的一个串提取,保存到一起。生成一个identifier,再与已有的关键字对比,检查是否是关键字。

继续向下看,是一个isdigit函数,是一个检查是否是数字的函数,后面还有小数点检查。检查当前输入是否是一个数字串。如果是数字,将其保存到NumVal并返回Tok_number代表当前输入是数字。

下面则是继续判断,如果不是字母,也不是数字,是不是终结符号或者“#”号。“#”在这里表示注释,他读取完当前这一行。大概就是这样一个内容。我们可以知道,这部分应该就是一个简单的词法分析。分析当前输入部分的类型,来返回不同的值,赋给Curtok这个静态变量。

我们继续看main函数。Main函数下面的是MainLoop函数。在MainLoop中使用到了词法分析中的CurTok,通过不同的CurTok进入不同的函数。当识别到eof时直接return,代表已经结束,函数返回。在为“;’”时,继续读取下一个关键字。当读到def时,代表读取到声明函数名字,下面要开始函数定义。关于extern函数拓展我们先不管他。先去def声明后看一看,看看是如何讲函数定义的。

继续进入ParseDefinition函数中。

在这个函数中,可以看到我们想要的东西。他生命的一个Proto的一个结构体。调用了ParsePrototype函数。我们先看看这个声明的PrototypeAST结构体中。

这个结构体,声明的一个名字,一个参数数组,就是一个用来存函数名字和参数的。那么ParseExpression函数就应该是读取函数的名字和参数名字的。我们进去确认一下。

如图所示,在这个函数中,首先判断CurTok是否为identifier,既当前字符串是否是一个以字母开头的字符串。如果是。将这个值赋给FnName即函数名字。后又判断函数名后是否是含有括号,如果没括号,报错,当有括号的时候,声明参数名的Vevtor容器,一个while循环,将所有参数如Vector。在这里,我们会有疑问,为什么没有参数类型。后来发现,这里面只有一个double类型,没有其他类型,所以默认类型为double,再添加其他类型时,应在这个while循环中添加一个参数的类型变量。之后识别“)”返回一个函数体。该函数结束,与我们预想的一样。
继续回到刚才的函数,下面判断返回函数是否为0.不是0。继续分析。又来了个ExprAST这个结构体。让我们再进去看看这个是什么。

这是个虚类,让我们看看他的实体类。

有一个NumberExprAST类,这个只有一个Val,应该是一个存数字的类。

还有变量类,放变量名字。还有一个二元表达式类。一个符号Op,还有左右节点也是ExprAST。

韩包含一个CallExprAST,这个就是一个调用类。返回上一步,这个ExprAST里面有数字,有变量,有二元表达式,有调用。我们进入函数看一下。

是一个LHS,二元表达式形式。再进入ParseExpression函数中

到这里,又是一连串。让我们想一想,定义一个函数,最开始是定义他的名字,然后又读取了他的形参。下一步是干什么?应该是函数的定义,函数里面的操作。他上面还有一个二元表达式,应该就是把操作串起来,串成一个二元表达式。最后把这个整体串起来的保存起来,就是一个完整的函数体。我们首先看这里面的switch。他有字母,数字,左括号三个种类。让我们先看看。字母的函数ParseIdentifierExpr。

如果后面没有做括号,返回变量名。想想也对,正常也不应该有括号,不就是一个变量名吗,也就是声明了一个变量呗。返回了一个variableExprAST,构成了之前函数的那部左子树,他返回了一个0,LHS。让我们再进入ParseBinOpRHS函数中看一看。

这里又是一片东西,慢慢看一看,首先是GetTOkPRecedence函数,点进去看一下。

这里面用上了BinopPrecedence函数,这个就是在Main函数里面声明的那个符号的优先级。在这个函数中,获取了优先级,别进行返回。可以看到,如果当前优先级,小于ExprPrec的有限级,返回左节点。否则继续运行。在下面有继续读取,读取右子树,重复了左边的内容,后又进行比较,最后生成了一个LHS总节点。此时,一个函数体就构成了。回到Function函数里面,直接return0;函数畸形返回,函数构造完成。

我们再重新回到MainLoop中来,看看HandleTolLevelExpression()函数。看看这个函数中的内容。

和解析函数体如此的相似,继续进入函数ParseTopLevelRxpr。

在这里面也调用了ParseExpression函数。在这里,官方教程说是调用函数,不过我看和声明函数差不多,看了好半天也没看明白,先不管他。

总结:在万花筒二中,实现了词法分析和语法分析,解析了一个函数,还用了大量的结构体,包括数字,变量等。代码比较易懂,在这里面学到了很多东西,加深了对编译器的理解。也增加了自己对代码结构的了解。提升了自己的代码能力。

Kaleidoscope3

看完了2,继续看三,LLVM IR生成。代码生成应该就是中间代码生成了吧,生成中间代码。最后再使用。LLVM在这里真的很强大,他给了你一个类似固定的模板,你把你的东西,放到它里面,然后他就给你生成了中间代码,你就可以实现跨平台的跑代码。(猜测,没有实践)。
我们来看看IR是如何生成的。

首先,它添加了好多codegen方法。
下面有这些codegen的方法定义。

首先是NumberExprAST,它使用了ConstantFP,后面还有APFloat,应该是吧Val转化了一种形式,存在ConstantFP里面。

关于变量的。通过变量名找变量值,并返回,使用了一个map容器。

在这里就清晰的很多,首先将左右节点都进行codegen,最后返回的不就是数字吗,就是那个变量或数字。也可能是表达式,不过最后返回的应该都是个结果。下面是看符号。加号就在Builder中调用加法函数,不同的符号调用不同的形式。

还有一个调用函数。这个函数从THeModel里面获取函数名,存到了一个Function类里面,这个类是LLVM自带的类,大概就是存函数的、下面还有args应该是形参、下面又进行了形参的构造,最后创建了一个调用,放到builder里面。应该是形参赋值后调用的作用。

函数体的codegen,这个没有什么东西,就是使用了一个Creat函数创建了一个函数。

最后又有个function的构造,这里面有BasicBlock,还有函数体的构造,函数的构造,这个应该是将函数名与函数体和在一个,构造一个完整的函数。

总结:在IR生成这部分,将我们的东西换成了LLVM的东西,相当于一个桥梁,使用了ConstantFP存数值,Function类存函数起了一个过渡的作用。

Kaleidoscope4

网上的中文教程就到了第四节,在四里面,函数就可以调用了,添加了JIT支持,我还没时间理解这个JIT支持是什么意思,知道这个位置的效果,函数可以调用了,可以有结果了。快到期末考试了,也没时间继续往下看了。

就是将TheModule函数添加到JIT里面。

并且在里一个地方使用find来达到函数调用的目的。

LLVM编译器Kaleidoscope(万花筒)入门教学相关推荐

  1. 基于LLVM编译器的IDA自动结构体分析插件

    引用 这篇文章旨在介绍一款对基于LLVM的retdec开源反编译器工具进行二次开发的IDA自动结构体识别插件实现原理分析 文章目录 引用 简介 源码分析 LLVM编译器简介 Retdec源码分析 Kl ...

  2. 1.偏头痛杨的Java入门教学系列之认识Java篇

    转载自:偏头痛杨的Java入门教学系列 地址:https://blog.csdn.net/piantoutongyang/article/details/70138697 前戏 今天我们主要来介绍一下 ...

  3. 三段式LLVM编译器

    三段式LLVM编译器 目录 概述 LLVM技术生态之编译器 一.传统编译器的设计 二.传统编译器模式的实现 三.LLVM的三段式实现 四.LLVM's Code Representation:LLVM ...

  4. LLVM编译器基础架构与DragonEgg示例

    LLVM编译器基础架构与DragonEgg示例 LLVM 概述 LLVM 项目是模块化和可重用的编译器和工具链技术的集合.LLVM 与传统的虚拟机几乎没有关系."LLVM"这个名字 ...

  5. LLVM 编译器和工具链技术

    LLVM 编译器和工具链技术 LLVM概述 LLVM项目是模块化和可重用的编译器和工具链技术的集合.尽管名称如此,LLVM与传统虚拟机几乎没有关系.LLVM本身不是首字母缩略词,项目的全名. LLVM ...

  6. Windows Azure Marketplace入门教学-利用TabLeau Public构建可视化DataMarket应用

    公告    :本博客为微软云计算中文博客  的镜像博客.   部分文章因为博客兼容性问题  ,会影响阅读体验  .如遇此情况,请访问  原博客    . 在上一篇教学Windows Azure Mar ...

  7. c语言作业ppt模板,C语言入门教学PPT模板

    目前要说发展前景最好的行业,那么就必然是互联网行业了,大部分行业现在都离不开计算机,也就是说学好计算机,走到哪里都不怕,特别是程序员,那么C语言就是首先需要接触的.本模板是由西西为大家整理的C语言入门 ...

  8. PHP on Windows Azure 入门教学系列(2) ——利用SQL Azure做一个简单的访问计数器...

    公告:本博客为微软云计算中文博客的镜像博客.部分文章因为博客兼容性问题,会影响阅读体验.如遇此情况,请访问原博客. 本文是PHP on Windows Azure 入门教学系列第二篇文章.请上一篇文章 ...

  9. linux入门 适合初学者_【推荐】适合初学者临摹的国画|国画基础入门教学视频教程!...

    原标题:[推荐]适合初学者临摹的国画|国画基础入门教学视频教程! 适合初学者临摹的国画|国画基础入门教学视频教程!适合初学者临摹的国画|国画基础入门教学视频教程! 关注公众号:每日学绘画,回复关键词[ ...

最新文章

  1. 自然语言处理NLP之语义相似度、语言模型、doc2vec
  2. Overload 和Override 的区别
  3. 【SDL】 如何在RedHat6.5中搭建SDL开发环境
  4. 四叶草社交平台——十天冲刺(10)
  5. BIO与NIO、AIO的区别
  6. java 不写this_还没弄明白Java中的this关键字吗,那来看这篇就够了!
  7. 《你必须知道的.NET》第五章读书笔记
  8. AI 监控之风刮到美国高校!学生浏览网页都能被追踪到
  9. [转]C#综合揭秘——细说进程、应用程序域与上下文之间的关系
  10. Android使用PDFviewer渲染PDF文件
  11. Linux学习笔记——网络组成
  12. 键 -- 主键、候选键、可选键
  13. JSON Views 基本用法
  14. cookie 、localStorage 和 sessionStorage 区别
  15. 若依源码分析(14)——数据监控
  16. 通过电脑重置解决小米笔记本巨卡无比的问题
  17. 在Centos7上安装Docker
  18. C++ -- STL文件解析
  19. 怎么批量修改照片的分辨率?照片dpi怎么调?
  20. Week2 Assignment - Princeton-Algorithms-PartI

热门文章

  1. 婚礼上新郎经典发言稿!搞笑!
  2. C#批量更改控件显示名称(举例中英文语言切换)
  3. mysql安装与修改初始密码
  4. 2020ICPC济南站 铸铜记
  5. vue的点击事件作防抖
  6. 使用adb命令将手机上的文件传输至电脑
  7. 在小程序授权公众号,获取公众号的code(前端)
  8. echarts中画布的清空
  9. 嘉霖浦厨卫荣膺美国缪斯设计大奖
  10. 大话西游手游服务器维护要多久,大话西游手游2019年12月12日维护公告