用LLVM写一个芯片编译器(二)——从无到有需要写什么东西
绪论经过了上一章对编译基础知识的讲解,我们已经明白了编译器的基本步骤。如果以前对编译没概念建议简单先看看。 那么当我们自己做了一个芯片,如何利用LLVM从无到有的写我们自己的编译器呢? 从本章开始我们回答这个问题。 由于LLVM是个开源框架,我们没必要从头来搞。我们只需要搞定需要在LLVM的框架下添加什么东西即可。 本章先看个整体。
第一章 你需要添加的文件类型LLVM基于C++写的,所以,首先,你肯定要添加一堆的.cpp和.h文件。 其次,为了进一步提高编码效率,LLVM其实提供了一套target definition接口(td文件,td的名字就这么来的)。 你写td文件,LLVM里有个组件叫tablegen, tablegen读取你写的td文件自动帮你转成对应的cpp文件,避免所有的cpp都要你自己写。 大致的原理是这样的:
重要的事说1.5遍。。看到这个点,你只需要明白,你得写两种文件。 td文件:与架构组件相关的内容,例如寄存器什么的,会用td写。语法是新的,但是不多。照猫画虎就能凑出来。 cpp.h文件:其他控制性的、调用性的, 不好用td自动生产的,就直接写cpp。(所以C++不熟阅读或者写代码有苦难,找一本C++ PREMIER先学学 Orz)。
用LLVM写一个芯片编译器(二)——从无到有需要写什么东西
第二章 从文件角度先看个整体完成一个简单的后端你需要添加多少文件? 这一章我们先看一看,做一个最简单的编译器你需要添加什么东西。我们先看个整体,里面有什么。 此处给我们的后端起个名字叫SmallBird。刚起这个名字的时候其实是有麻雀虽小五脏俱全的意思,但是后来写着写着看到这个名字,满脑子都想的是鸟的自由,看来最近感觉不自由Orz。SmallBird能够较为明显的区分我们写的东西和LLVM自带的东西。
用LLVM写一个芯片编译器(二)——从无到有需要写什么东西
上面就是一个简单的LLVM后端你需要写的所有文件。不要看到这个地方就被劝退了,其实有些文件内容不多的,一共也就几千行代码。 下面一张表列出了按功能分类的各个文件是干嘛用的。这个代码施工完毕后会挂github, 此处我们主要看看你要写几个方面的内容。
用LLVM写一个芯片编译器(二)——从无到有需要写什么东西
划重点,一共六个方面需要写! - 芯片总体的架构
- 寄存器的描述
- 指令相关的描述
- 堆栈的管理
- 函数的管理
- 汇编和其他输出的管理
上面实现了最基本的功能,运用熟练以后还可以自己添加其他功能。这个地方你不需要搞清楚每个文件具体是干什么的,后续返回来看就能明白,我们会逐章来细讲。 第三章 从类继承与派生角度看个整体上面以文件角度看可能对于熟悉C++的你来讲还不够脉络清晰,我们换个角度看世界。 既然以类角度看,那我们就需要来个抓手。在我们编译器中,这个抓手其实是SmallBirdSubTarget类。
用LLVM写一个芯片编译器(二)——从无到有需要写什么东西
有了这个类,大部分的资源你都能通过指针访问到。同时,其他类也通过指向Subtarget的指针获得了访问其他信息的接口。 总而言之,subtarget类是一个接口类。实现了资源的互通调用。这样其他类的关系就有了联络。一般来讲,你写的代码先要找到subtarget的指针,然后通过subtarget访问其他。 td文件通过tablegen生成对应的xxgeninfo类,然后通过派生合入我们自己写的类。然后subtarget通过指针访问之。
划重点: - Subtarget类是接口类,四通八达
- td文件通过tablegen生产类,然后通过派生合入我们写的类
第四章 总结本篇文章实际上是解决LLVM如何用起来这个问题的开始。我觉得开源项目要想玩的快,一定是要先看森林后看树叶的。否则很容易陷入开源代码的汪洋大海中毫无方向。本篇文章我们从两个角度介绍了宏观的看看我们最后完成的目标,属于介绍LLVM的森林。从下一章开始,我们逐个方向介绍如何一步步撺起来我们的编译器。
|