仓颉 LLVM 测试体系完全指南:lit 与 FileCheck 如何保障 CJ Pass 质量

📅 发布时间:2026/10/9 10:01:53
仓颉 LLVM 测试体系完全指南:lit 与 FileCheck 如何保障 CJ Pass 质量
仓颉 LLVM 测试体系完全指南lit 与 FileCheck 如何保障 CJ Pass 质量【免费下载链接】llvm-projectLLVM 项目是一个模块化、可复用的编译器及工具链技术的集合。此fork用于添加仓颉编译器的功能并支持仓颉编译器项目。项目地址: https://gitcode.com/Cangjie/llvm-project仓颉 LLVM 测试体系基于 LLVM 项目成熟的 lit FileCheck 测试框架为本仓颉编译器 fork 中新增的 CJ 系列优化 Pass 提供自动化的正确性验证每提交一次代码llvm/test/Transforms/ 下的测试就会驱动opt执行 Pass再用 FileCheck 逐行比对 IR 输出确保 CJ Pass 行为稳定可控。本文带你快速理解这套测试体系的构成与原理。为什么 CJ Pass 需要专门的测试体系CJ PassCangjie Pass是仓颉编译器 fork 在标准 LLVM 之上新增的一系列 IR 优化 Pass源码集中在 llvm/lib/Transforms/Scalar/ 与 llvm/lib/Transforms/IPO/ 目录下例如Pass源码位置作用CJBarrierOptCJBarrierOpt.cpp内存屏障优化CJSimpleOptCJSimpleOpt.cpp通用简单指令优化CJStringPoolMergeCJStringPoolMerge.cpp字符串池合并CJDevirtualOptCJDevirtualOpt.cpp去虚函数调用优化CJPartialEscapeAnalysisCJPartialEscapeAnalysis.cpp部分逃逸分析编译器 Pass 的输入输出是复杂的中间表示IR一次错误的变换可能悄悄破坏程序语义。因此仓颉 LLVM 测试体系借鉴 LLVM 的做法用可复现的 IR 输入 期望的输出片段把每个 Pass 的行为钉死。下图展示了编译器工具链的整体流程Pass 正是作用在 IR 变换这一环节lit自动化测试执行器llvm/test/lit.cfg.py 是 LLVM 测试套件的总配置文件它告诉 litLLVM Integrated Tester识别哪些后缀是测试文件默认包含.ll、.c、.s、.mir、.yaml等见 lit.cfg.py 中的config.suffixes准备运行环境把构建出的opt、FileCheck等工具加入 PATH解析每个测试头部的RUN行按指令执行并收集结果。CJ Pass 的测试目录与 Pass 一一对应例如 llvm/test/Transforms/CJBarrierOpt/、llvm/test/Transforms/CJInlineCache/ 等共 17 个 CJ 相关测试目录。运行方式通常是lit llvm/test/Transforms/CJBarrierOpt # 只跑某个 Pass 的测试 lit llvm/test/Transforms -v # 带详细输出调试 小技巧lit 支持按路径筛选测试新增 CJ Pass 时先跑旧测试确认全绿再补充新测试可显著降低误判成本。FileCheck逐行验证编译器输出FileCheck 是 lit 测试体系中的判卷老师。它不关心完整的输出只检查期望的模式是否按顺序出现。以最典型的 vcall.ll 为例它测试内联缓存 Pass 能否把虚调用改写为直接调用; RUN: opt -S --iv-call-inline-cache-enabletrue -passescj-runtime-lowering \ ; --cj-ic-input-file%S/inputfile/VCallProfileOutput.txt %s | FileCheck %sRUN 行把opt的执行结果通过管道交给 FileCheck。随后测试文件里散布着一组CHECK断言vcall.ll; CHECK: %2 call i8* CJ_MCC_GetObjClass(i8 addrspace(1)* %a) ; CHECK: br i1 %4, label %if.true.call_direct, label %if.false.call_virtual ; CHECK: if.true.call_direct:这 3 行断言的含义是变换后的 IR 中必须依次出现获取对象类 → 条件分支 → 直接调用块。任何一个模式缺失或顺序错乱测试即失败。这种片段式检查非常灵活既避免了维护整份期望 IR 的繁琐又能精确定位是哪一步变换出了问题。下图示意了 Pass 变换 IR 指令的典型场景LLVM 中 load/store 向量操作的位宽匹配过程FileCheck 验证的正是这类变换结果是否符合预期编写 CJ Pass 测试三步走结合 CJInlineCache 等现有测试可以为新 Pass 编写测试准备输入 IR在测试目录中创建.ll文件写出最小可复现的输入 IR可加%S/inputfile/存放辅助数据文件如上例中的 profile 文件编写 RUN 行指定opt的 Pass 参数末尾接| FileCheck %s补充 CHECK 断言先真实运行一次拿到输出再把关键片段固化为CHECK行——注意断言要少而准只锁定 Pass 的核心行为避免测试过度脆弱。此外测试头部的注释还能声明平台限制如XFAIL: *标记已知失败保证同一套测试在不同环境下的可解释性。性能维度不止正确还要够快除了正确性测试体系还需关注 Pass 的性能回归。LLVM 提供了 locstats 工具统计各 Pass 耗时并用 llvm/tools/locstats/ 生成对比图帮助开发者发现这次提交让某个 Pass 变慢了相关组件与延伸阅读本 fork 的仓颉适配不止于优化 Pass调试器一侧也有对应架构如表达式解析器支持 Clang 与 Cangjie关键路径速查表内容路径lit 总配置llvm/test/lit.cfg.pyCJ Pass 源码llvm/lib/Transforms/Scalar/CJ Pass 测试llvm/test/Transforms/内联缓存测试样例vcall.ll屏障优化测试样例CJBarrierOpt总结仓颉 LLVM 测试体系 lit负责跑 FileCheck负责判 与 Pass 一一对应的测试目录负责覆盖。理解了这三者的分工你既能读懂现有 CJ 测试也能为自己新写的 CJ Pass 快速补上可靠的质量护栏。【免费下载链接】llvm-projectLLVM 项目是一个模块化、可复用的编译器及工具链技术的集合。此fork用于添加仓颉编译器的功能并支持仓颉编译器项目。项目地址: https://gitcode.com/Cangjie/llvm-project创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考