Abstract
不是鲸书。
arvcc
想尝试设计一套针对优化和程序分析的框架。 通常做程序分析有两条路子,一条是针对程序分析的专用分析器,单独作为一套框架使用;另一条是作为编译器的优化趟来实现, 想到哪里写到哪里。
针对常规的编译流程Source
——IR
——CodeGen
,我目前还是倾向于Clang
的设计,先打算研究其架构并简化出来一套适合的东西。其次要继续读static analysis
方向的论文,复现其算法和原理。
我准备在arvcc仓库里面实现新设计的编译框架,最近的工作主要是将Clang
里面的架构简化出来然后加以利用。
Option
llvm
中所有的工具都会使用到选项options
:
1 | '-emit-llvm', '-S' and'test.cpp' are all options |
所以option
是一个根类,各个工具也有自己的选项子类比如Driver
下面可以有自己的DriverOption
。这些XXXOption
都是各个工具*.td/*.def文件
自定义,然后通过TableGen
自动生成的。
arvcc
聚焦了很少的功能,所以我打算将各自Option
直接集成到不同工具目录下,比如Driver
的话,就直接定义在DriverOption.h
中,其中DriverOption
类继承自Option
类。
Driver
工业级编译器需要考虑很多兼容性功能和用户接口,从而有了Driver
的概念。还有很多性能上的trade-off
从而用很多LLVM
自定义的数据结构。故其具体实现上也及其复杂繁琐。
Clang
本质是一个Driver
,而-cc1
才是编译器前端。在命令行中敲下clang a.cpp
之后,编译器默认会自带很多编译选项-###
,其中就有-cc1
来进入编译器前端。
Type
Clang
通过定义各个DriverOptions
的类型来映射整个编译流程,甚至精确到了选择指定的工具,编译步骤和输出格式。
开发环境
记录自己机器上和开发有关的些许细节。
brew
brew
是用的最多的,我机器上存在多个版本的软件比如python/llvm/node...
,PATH里都是以brew
版本为准(因为时间原因,可能brew
自己构建其他软件的依赖也选择了不同的版本,可以使用brew search xxx
来查看)。下面列出项目相关:
llvm+clang:
构建于brew info llvm
,目前-v = 13.0.1
$CC/CXX
用于cmake
的默认编译器-LDFLAGS/CPPFLAGS
用于cmake
编译器编译选项
NeoVim:
构建于brew info NeoVim
,目前版本-v = 0.6.1
,依赖检查: checkhealth
Voltron:
构建依赖brew info python 3.10
ccls:
构建依赖brew info llvm
lsp
今年正式从Vim+YCM
转到了NeoVim+LSP
。language server protocol
降低了由M
家IDE厂商分别为N
门语言做插件的复杂度。由language server
(针对语言)和language client
(针对IDE/Editor)两部分构成。我的配置是server:ccls
+client:coc.vim
.
目前仅仅使用其completion
和go to def/ref
功能。
ccls
-DCMAKE_PREFIX_PATH
选项很重要,这是因为它将clang/llvm
的头文件include paths
和库resourceDir
硬编码到ccls
中以便索引。
include paths: clang -v -fsyntax-only -x c++ /dev/null
resourceDir: clang -print-resource-dir
ccls
使用.ccls/ compile_command.json
来索引文件:
1 | % cmake -H. -BDebug -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=YES |
coc.vim
想要加其他语言的插件:CocConfig
。
有些硬编码的字符可以直接使用grep
来过滤文本文件内容,fzf/find
来查找指定目录下的文件。
1 | grep -r "ccc_print_phases" llvm-src/clang/ # 目录查找 |
lldb
我用voltron
做调试器前端,功能很全就是需要在自启动窗口。。有点麻烦
1 | $ voltron view register |