[学习cpu0](二) Cpu0后端初始化

前言

该笔记学习自台湾的陳鍾樞编写的《Tutorial: Creating an LLVM Backend for the Cpu0 Architecture》,书中讲解地非常细致,没有涉及很复杂的功能,可以作为入门材料。同时参考了github上基于llvm8.09.0复现的版本,我基于9.0学习的代码也同步在gitee.

1. Tablegen描述文件

共五个td:

  • Cpu0.td 包含了其他几个td文件,同时定义了一个基于Target类的子类Cpu0;
def Cpu0 : Target {
 // def Cpu0InstrInfo : InstrInfo as before.
 let InstructionSet = Cpu0InstrInfo;
}

  • Cpu0InstrInfo.td & Cpu0InstrFormats.td
    一些 SDNode 节点的定义,比如 Cpu0Ret,还有操作数类型定义,比如 simm16,还有最多的是指令的定义,这些指令,同样会做不同的 class,最后基于这些 class 来定义具体的指令模式。值得留意的是,其中会有一个参数叫 pseudo,默认是 0,这个参数指明要定义的指令是否是一个伪指令,在 build 编译器之后,会发现生成了一个 Cpu0GenMCPseudoLowering.inc 文件,目前这个文件里还没啥实质的东西,因为我们还没涉及到伪指令。
  • Cpu0RegisterInfo.td
    定义了所有的寄存器和寄存器集合(RegisterClass)
  • Cpu0Schedule.td
    定义了一些调度方式,它们基于一个类 InstrItinClass,通常简写叫 IIC,这些调度信息会在其他位置被用到

注意,目前,我们还没有完整的把这些 .td 文件写完,为了能尽快看到一个能编译通过的版本,我们只搭框架。在后续的几章中,这些文件的内容还会被反复修改。

2. 目标注册

这部分会修改一些公共代码,把要编写的 Cpu0 注册到 LLVM 架构中,让 LLVM 知道新增了一个后端。

  • 在 Cpu0 的路径下,先创建一个 Cpu0.h 的文件,做了一些包含操作。然后创建 Cpu0TargetMachine.cpp 文件和对应头文件,里边只写了一个 LLVMInitializeCpu0Target() 的函数,并且暂时没有内容,目前还是只搭框架。
  • 创建一个子目录 lib/Target/Cpu0/TargetInfo/,在这个路径下新建 Cpu0TargetInfo.cpp,这个文件中,我们调用了 RegisterTarget 接口来注册我们的目标,需要做两次注册,分别完成 cpu0 和 cpu0el 的注册。
  • 还需要创建一个子目录 lib/Target/Cpu0/MCTargetDesc/,在这个路径下新建 MCTargetDesc.cpp 文件和其对应的头文件,这里写了一个 LLVMInitializeCpu0TargetMC() 的函数,也暂时留空。

放这两个额外的子目录,在其他后端中也同样这么做,究其原因,是每个后端都会提供多个库,我们的 Cpu0/ 路径下会生成一个叫 libLLVMCpu0CodeGen.a 的库,而这两个子目录会生成 libLLVMCpu0Desc.a 和 libLLVMCpu0Info.a 这两个库,关于库的生成控制是在 CMakeLists.txt 中完成的。
以上工作做完之后,还需要对公共代码进行修改。

需要修改的文件有:

  • lib/Object/ELF.cpp
  • lib/Support/Triple.cpp
  • include/llvm/ADT/Triple.cpp
  • include/llvm/BinaryFormat/ELF.h
  • include/llvm/Object/ELFObjectFile.h
  • 新增一个文件:include/llvm/BinaryFormat/ELFRelocs/Cpu0.def

可以暂时不管它们是做什么用的,先按着其他后端的位置,把Cpu0 后端补上去就可以了
每个目录下都需要包含一个CMakeLists和一个LLVMBuild.txt,前者是cmake执行时需要查找的,后者是llvm构建时辅助的描述文件。所以需要添加的目录有:

  • lib/Target/Cpu0/
  • lib/Target/Cpu0/TargetInfo
  • lib/Target/Cpu0/MCTargetDesc
  • 修改lib/Target/LLVMBuild.txt
    lib/Target/LLVMBuild.txt

3. 编译测试

编译命令:

cmake -G Ninja -DCMAKE_BUILD_TYPE="Debug" \
	  -DBUILD_SHARED_LIBS=True -DLLVM_USE_SPLIT_DWARF=True \
	      -DLLVM_OPTIMIZED_TABLEGEN=True -DLLVM_BUILD_TESTS=False \
	      -DLLVM_ENABLE_PROJECTS=lld -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ \
	       ../llvm
ninja -j64  (或者 cmake --build .)

先不install, 占空间
测试1:

build/bin/llc --version

llc --version图示
测试2:
源文件ch1.c

int main(){
  return 0;
}

cpu0后端没有自己的ABI, 使用Mips的ABI,

build/bin/clang -target mips-unknown-linux-gnu -c ch1.c -emit-llvm -o ch1.bc
build/bin/llc -march=cpu0 -relocation-model=pic -filetype=asm ch1.bc -o ch1.s

assertion
一个 assert 阻止了异常操作。这里报错是正常的,毕竟后端啥都没做呢,没那么轻松就能生成汇编,看到这个提示,这一章的验证就结束了。在下一章会解决这个问题,并能正常输出简单程序的汇编文件。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值