技术导读——☆☆☆LLVM源码导览
我们这里只讲 llvm 子目录,其他的 module 暂时不讲。
本笔记记录于我接触 LLVM 20 个月左右,已经对源码构成和编码风格有了大致的了解。为了进一步解读 LLVM 的实际代码构成,方便综合性分析性能缺陷,同时为了在遇到性能缺陷时第一时间给出 LLVM 中的可能存在的问题。
本文用例是 LLVM 官方 19.1.0.
导览
首先可以简要 ls 看一下一级文件夹的组成部分:
benchmarks cmake-build-debug CMakeLists.txt docs lib projects resources tools
bindings CMakeCache.txt configure examples LICENSE.TXT README.txt runtimes unittests
cmake CMakeFiles CREDITS.TXT include Maintainers.md RELEASE_TESTERS.TXT test utils
其中首先需要关注的是 lib 和 include 文件夹;其次需要关注 tools, unittests, utils, runtimes 文件夹。其中:
- lib : LLVM 的核心代码库都放在这个目录下,包括各种编译器中间表示(IR)、优化、代码生成、后端实现等模块。可以认为 lib 是 LLVM “引擎”的实现所在,很多关键算法和数据结构均在此处实现。
include :与 lib 配套,include 文件夹存放的是 LLVM 的公共头文件(API 接口声明、数据结构定义等)。当外部代码或 LLVM 内部模块需要使用某个功能时,通常会包含这里的头文件。lib 和 include 合起来构成了 LLVM 的核心库及其接口。
tools :这个目录包含了 LLVM 自身提供的一系列工具,例如编译器前端 Clang(尽管 Clang 可能在 projects 或独立仓库中)、调试器、汇编工具、静态分析工具等。==这是 LLVM 工具链的实现的地方==。
- unittests :单元测试代码放在这个目录中,用于对 LLVM 各个模块进行功能验证。单元测试帮助确保代码在修改后仍能保持正确性,并且对日常开发和持续集成非常重要。
- utils :包含一些辅助工具和脚本,这些工具可能是构建、测试、代码格式化、自动化任务的支持程序。它们在 ==LLVM 的开发过程中提供了很多便利==,帮助维护代码质量和开发效率。
- runtimes :存放的是与 LLVM 运行时相关的代码和库,例如编译器运行时库(compiler-rt)、各种运行时支持模块。这些运行时库通常被生成的代码调用,用于支持例如内置函数、数学库替换等功能。
llvm/lib
初学者往往认为 LLVM 的工程非常庞大,无从下手,但是参考附录 A 的统计数据,C++文件仅有 2000 余个,完全可以归类和进行大体分析。我们首先按照重要性给这些二级目录分一下类:
- ★★★★★:==IR==、==CodeGen==、MC、==Target==、==TableGen==、==LTO==、Support、Option、Passes、Object、Bitcode、Bitstream、==Transforms==、TargetParser、==ExecutionEngine==等模块构成了 LLVM 的核心体系,直接影响编译器的整体功能与性能。
- ★★★★☆:FrontEnd、IRPrinter、IRReader、DebugInfo、CodeGenTypes、MCA、ProfileData、XRay 等在关键流程中发挥重要作用,但作为辅助工具或细化功能可略逊于核心模块。
- ★★★☆☆:Analysis、AsmParser、BinaryFormat、Debuginfod、Demangle、DWARFLinker、DWP、Fuzzer、FuzzMutate、LineEditor、ObjectYAML、InterfaceStub、SandboxIR、Telemetry、TextAPI、ToolDrivers、Testing、WindowsDriver、WindowsManifest 等则主要属于辅助、扩展或测试支持功能,对核心编译流程影响较小。
下面是对上述归类的一览表:
文件夹 | 重要性评分 | 说明 |
---|---|---|
Analysis | ★★★★★ | 提供静态分析支持,辅助优化和验证,但不直接参与核心代码生成。 |
AsmParser | ★★★☆☆ | 汇编解析工具,对处理汇编代码有用,属于辅助功能。 |
BinaryFormat | ★★★☆☆ | 负责处理二进制格式,支持性功能较强。 |
Bitcode | ★★☆☆☆ | LLVM IR 的二进制序列化格式,是跨平台传递 IR 的核心。 |
Bitstream | ★★★☆☆ | 处理 Bitcode 的读写与序列化,为核心底层支持。 |
CGData | ★★★☆☆ | 为代码生成提供数据结构支持,属于后端的重要辅助模块。 |
CodeGen | ★★★★★ | 后端代码生成的核心模块,直接影响机器代码输出。 |
CodeGenTypes | ★★★★☆ | 定义和管理代码生成时的数据类型,支撑后端生成。 |
DebugInfo | ★★★★☆ | 提供调试信息支持,对调试和诊断至关重要。 |
Debuginfod | ★★☆☆☆ | 专用于调试信息分发,属于扩展支持功能。 |
Demangle | ★★★☆☆ | 用于符号解码,方便调试信息展示,不影响编译核心。 |
DWARFLinker | ★★☆☆☆ | 针对 DWARF 调试信息链接,主要服务于调试支持。 |
DWP | ★★☆☆☆ | DWARF 信息打包工具,属于调试辅助工具。 |
Fuzzer | ★★☆☆☆ | ==面向安全和==测试的工具,不属于常规编译流程。 |
FuzzMutate | ★★☆☆☆ | ==用于模糊测试的辅助工具。== |
LineEditor | ★★☆☆☆ | 文本编辑辅助工具,对核心流程无直接影响。 |
Object | ★★★★★ | 处理目标文件和二进制对象,核心于目标代码的组织与操作。 |
ObjectYAML | ★★☆☆☆ | 提供 YAML 格式支持,主要用于辅助性展示。 |
Frontend | ★★★★★ | 前端解析和初步转换模块,是整个编译流程的入口。 |
ExecutionEngine | ★★★★★ | 支持 JIT 编译与运行时执行,关系到程序执行。 |
InterfaceStub | ★★☆☆☆ | 提供接口占位支持,辅助性较强。 |
IR | ★★★★★ | LLVM 中间表示的核心,整个编译优化的基础。 |
IRPrinter | ★★★★☆ | 将 IR 转为可读格式,调试和验证时非常重要。 |
IRReader | ★★★★☆ | 从文本或其他格式读取 IR,核心 I/O 功能。 |
TableGen | ★★★★★ | 自动生成大量描述代码,是自动化配置 Target 等模块的关键工具。 |
LTO | ★★★★★ | 链接时优化模块,实现全程序优化,至关重要。 |
MC | ★★★★★ | 负责机器码相关处理,生成目标代码的关键环节。 |
MCA | ★★★★☆ | Machine Code Analyzer,用于性能调优和分析。 |
Option | ★★★★★ | 命令行选项解析库,为整个编译器提供基础支持。 |
Passes | ★★★★★ | 包含各种优化 Pass,对整个编译优化流程核心。 |
ProfileData | ★★★★☆ | 收集和管理性能数据,对反馈和调优非常关键。 |
SandboxIR | ★★☆☆☆ | 用于实验和测试 IR 转换,不属于生产核心。 |
Support | ★★★★★ | 提供通用工具和基础库,贯穿各模块,极为重要。 |
Target | ★★★★★ | 定义目标平台,后端代码生成的基础。 |
TargetParser | ★★★★★ | 解析目标描述,对生成目标代码起关键作用。 |
Transforms | ★★★★★ | 执行 IR 转换和优化,编译优化核心。 |
Telemetry | ★★☆☆☆ | 数据上报与监控,辅助于系统运行统计。 |
TextAPI | ★★☆☆☆ | 文本处理接口,属于辅助性工具。 |
ToolDrivers | ★★☆☆☆ | 提供工具驱动支持,辅助功能。 |
Testing | ★★★☆☆ | 测试框架,确保各模块正确性,但不直接影响产品编译。 |
XRay | ★★★★☆ | 内置的跟踪与性能分析工具,对调试性能非常有帮助。 |
WindowsDriver | ★★☆☆☆ | 针对 Windows 平台的专用支持,不是跨平台核心。 |
WindowsManifest | ★★☆☆☆ | 针对 Windows 的配置文件,辅助于平台适配。 |
附录 A-代码统计
❯ cloc .
72785 text files.
72220 unique files.
7063 files ignored.
github.com/AlDanial/cloc v 1.90 T=42.02 s (1566.0 files/s, 520304.0 lines/s)
---------------------------------------------------------------------------------------
Language files blank comment code
---------------------------------------------------------------------------------------
LLVM IR 38638 724163 8547726 3521229
C++ 4102 353147 401906 2152276
JSON 2862 1 0 1085693
YAML 5216 77069 70500 998111
Assembly 8673 582930 1381465 847763
C/C++ Header 3191 110011 183250 418580
reStructuredText 1180 46066 54138 98981
CMake 1062 9137 7298 45198
Python 328 7319 10706 29648
Windows Module Definition 100 2405 202 19681
C 109 2647 3136 16357
Markdown 34 2806 0 8722
SVG 8 0 0 7804
OCaml 38 1446 2385 5073
Bourne Shell 26 477 614 3966
Pascal 19 1262 5852 2602
XML 34 51 44 2261
HTML 18 209 1 1890
Windows Resource File 110 131 37 1116
CSS 5 114 45 850
Perl 5 120 146 657
DOS Batch 2 77 45 582
vim script 12 61 76 404
Jupyter Notebook 3 0 2434 319
Lisp 4 47 92 239
Bourne Again Shell 2 20 92 166
TypeScript 2 13 3 78
make 1 17 5 74
Objective-C 6 34 209 69
Dockerfile 3 14 54 51
INI 7 10 0 42
TOML 2 3 0 22
Swift 2 6 0 17
NAnt script 1 0 0 13
CSV 2 0 0 6
OpenCL 1 0 0 6
Logos 2 4 0 2
---------------------------------------------------------------------------------------
SUM: 65810 1921817 10672461 9270548
---------------------------------------------------------------------------------------
❯ cloc lib
4647 text files.
4647 unique files.
557 files ignored.
github.com/AlDanial/cloc v 1.90 T=3.31 s (1235.4 files/s, 786675.1 lines/s)
---------------------------------------------------------------------------------------
Language files blank comment code
---------------------------------------------------------------------------------------
C++ 2870 284487 347766 1742709
C/C++ Header 915 25575 31342 113928
Assembly 12 125 118 26285
C 16 931 1407 9056
CMake 230 789 98 6566
Windows Module Definition 22 200 0 3824
Pascal 13 1116 5256 1734
Python 6 99 107 391
Markdown 5 161 0 389
YAML 1 0 0 2
---------------------------------------------------------------------------------------
SUM: 4090 313483 386094 1904884
---------------------------------------------------------------------------------------
评论