忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT 视频 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
楼主: 蔡万钊

一步步实现QBASIC编译器 [复制链接]

论坛徽章:
0
发表于 2012-11-20 17:06 |显示全部楼层
回复 1# 蔡万钊


    小弟也在学习编译器 跪求一个用c实现的LR语法分析器

论坛徽章:
2
摩羯座
日期:2013-10-10 14:29:04天蝎座
日期:2014-01-03 09:14:49
发表于 2012-11-20 17:24 |显示全部楼层
回复 2# 蔡万钊

稍微指出一下啊,呵呵,flex官方网页上是这么描述的:

Flex is a free (but non-GNU) implementation of the original Unix lex program.

我查了下源码,使用的不是GPL。


   

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:11数据库技术版块每日发帖之星
日期:2015-08-30 06:20:00
发表于 2012-11-20 21:47 |显示全部楼层
EricFisher 发表于 2012-11-20 17:24
回复 2# 蔡万钊

稍微指出一下啊,呵呵,flex官方网页上是这么描述的:


好, 谢谢! 我都没怎么关注 flex 到底是不是 gnu 的, 呵呵. 马上修改

论坛徽章:
0
发表于 2012-11-20 21:51 |显示全部楼层
支持 蔡蔡 ! 加油!

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:11数据库技术版块每日发帖之星
日期:2015-08-30 06:20:00
发表于 2012-11-20 21:52 |显示全部楼层
EricFisher 发表于 2012-11-20 17:24
回复 2# 蔡万钊

稍微指出一下啊,呵呵,flex官方网页上是这么描述的:



www.gnu.org/software/flex/

确实是 gnu 出品. 我没说是什么协议的, 我只说是  gnu 出品的, 呵呵. 不用改正了.

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:11数据库技术版块每日发帖之星
日期:2015-08-30 06:20:00
发表于 2012-11-20 21:58 |显示全部楼层
wgm001 发表于 2012-11-20 21:51
支持 蔡蔡 ! 加油!



ya ~~~ 那是

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:11数据库技术版块每日发帖之星
日期:2015-08-30 06:20:00
发表于 2012-11-21 00:25 |显示全部楼层

调用树

调用树

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:11数据库技术版块每日发帖之星
日期:2015-08-30 06:20:00
发表于 2012-11-21 21:23 |显示全部楼层
第三步骤 - 中间代码生成


llvm 是一个完善的编译器框架, 但这并不意味着, 你写了语法解析后就没事情做了

从 AST 生成 llvm 能使用的中间过程依然是一个充满挑战性的工作. llvm 是一个中间化的汇编语言, 意味着, 事实上你的代码生成器是在生成 llvm 汇编语言 , 所以依然是一个完备的编译器. 你如果觉得乐意, 完全可以不生成 llvm 汇编代码, 直接生成具体机器平台的汇编语言. llvm 的汇编语言依然是一个比较底层的语言. 和一般的汇编器不一样的是, llvm 的汇编器能对这个汇编语言进行 "优化" . 而其他平台的汇编器则需要编译器自己生成优化的结果. 注意, llvm 执行的优化是比较底层的, 专注于机器平台的, 比如 乘法指令转 SSE 指令, 指令重排序这样的优化. 语言层面的,如常量折叠, 死代码清除, 尾递归优化等 , 依然需要编译器作者进行优化. 所以千万不要认为有了 llvm 写编译器就是非常简单的事情了.

llvm 的好处就是可以专注于语言层面的实现和优化, 而具体机器指令层面的优化交给 llvm 来做, 分工协作.


生成 llvm 的代码有两种形式:

第一种是手动生成. 适用于实现编译器所使用的语言没有 llvm 可用的库的时候使用. 编译器生成文本格式的 llvm 汇编代码然后调用 llvm 汇编器生成本机代码.

第二种是使用 llvm 的 C++ 库.  llvm 提供了比较丰富的 类库用来简化 llvm 代码的生成.  我的QBASIC编译器就采用这种形式.


生成  llvm 代码的步骤非常简单, 为每个语法树节点调用 codegen 虚函数即可. 因为是虚函数, 所以调用基类的 codegen 会自动调用对应类的 codegen .


我在这里举一个加法表达式的 codegen


  1. llvm::Value * AddExprAST::Codegen( BasicBlocks * inserpoint)
  2. {
  3.     IRBuilder<>   builder(insertpoint); // 一个 LLVM 辅助库, 用来生成 llvm 代码

  4.     /// 因为加法这样的表达式是递归定义的, 所以 ...

  5.     LHS =  this->leftnode->Codegen(insertpoint); // 就像这里, 递归调用子节点, 获得的就是子节点生成的加法指令的结果的 llvm 寄存器的引用.
  6.     RHS = this->rightnode->Codegen(insertpoint);

  7. //  生成 llvm 加法指令. 并返回保存加法结果的寄存器的引用.
  8.     return     builder.CreateAdd( LHS, RHS); // 返回结果是 llvm::Value *  , 也就是一个 寄存器的引用.
  9. }


复制代码
注意 llvm 的 builder 构造一个加法(减乘除等都一样的啦) , 会生成(一系列, 有可能是一系列)的寄存器操作, 然后是加法指令, 然后是返回该加法指令的结果寄存器的引用

如果后续使用到了这个引用, 就告诉 llvm 的代码生成器, 要安排好这个寄存器的使用, 重新进入下一次运算操作哦 ~

llvm 实际上就是一个 寄存器分配器. 如果可用的寄存器不足, llvm 会自动生成压栈指令, 将一些暂时用不到的数据移出寄存器.

所以, 可以把 llvm 看成有无限个寄存器的机器. 这样像例子代码中的递归调用, 层层返回指令结果寄存器引用, 是可以的. llvm 生成机器代码的时候自动安排好寄存器的使用.







论坛徽章:
16
处女座
日期:2016-04-18 14:00:45牛市纪念徽章
日期:2015-07-07 14:25:2615-16赛季CBA联赛之北京
日期:2016-06-03 17:11:5815-16赛季CBA联赛之天津
日期:2016-12-12 10:44:2315-16赛季CBA联赛之佛山
日期:2017-02-20 18:21:13
发表于 2012-11-22 18:48 |显示全部楼层
挖 牛人啊, 我倒是想参考你的设计做一个 javascript 编译器了

论坛徽章:
0
发表于 2012-11-23 11:51 |显示全部楼层
回复 19# evaspring


    我发现好多人都想做js的编译。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

【有奖调查】AI时代如何迎接未知挑战?

人工智能一直在医疗行业扮演着重要角色,最早的专家系统和后来的基因诊断都是人工智能技术在医疗的行业探索。近年来,随着深度学习等技术的进步,人工智能在医疗行业的应用领域不断扩展,医学影像智能诊断、语音电子病历、癌症智能诊断等均已逐渐成为热门发展方向。
而作为人工智能重要推动力的深度学习技术的快速发展却亟需认知系统的强力支撑。
----------------------------------------
活动时间:2017年5月15日-6月5日

调查入口>>
  

北京皓辰网域网络信息技术有限公司. 版权所有 京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:1101082001
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP