十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Mojo 编译器(KGEN)文档导航、工具链与编译管线完全指南

Mojo 编译器(KGEN)文档导航、工具链与编译管线完全指南 Mojo 编译器KGEN文档导航、工具链与编译管线完全指南【免费下载链接】mojoThe Modular Platform (includes MAX Mojo)项目地址: https://gitcode.com/GitHub_Trending/mo/mojo本篇指南以 Mojo/docs/compiler/README.md 为总入口系统梳理 Mojo 编译器的文档体系、命令行工具链mojo、kgen、kgen-opt、kgen-translate、库产物CompilerRT.a以及从源码解析到 LLVM 机器码的六阶段编译管线。读完本文你将能够在开源仓库中构建 Mojo 编译器、用kgen-translate查看解析后的 LIT IR、用kgen-opt调试单个 pass并理解 KGEN、LIT、POP、HLCF 等核心 dialect 在整个编译流程中的角色。KGEN 是什么Kernel Generator文档开头明确给出一个关键提示KGEN 代表 kernel generator内核生成器在 Mojo 的代码库中看到 KGEN 时可以将其理解为 Mojo 本身。整个 Mojo 编译器就是围绕 KGEN 这一代号构建的Mojo/lib/下存放编译器库的 C 源码Mojo/tools/下存放命令行可执行程序CLIMojo/test/下存放以 Mojo 源码程序形式编写的编译器测试。Mojo 编译器有一个与大多数传统编译器截然不同的核心设计它完全构建在 MLIRMulti-Level Intermediate Representation之上。传统编译器通常走 AST → IR → 机器码 的独立阶段而 Mojo 使用 MLIR 的 dialect 机制在不同抽象层次上表示代码所有阶段都在同一个框架内完成。这一点在 MojoCompilerWalkthrough.md 中有完整阐述也是理解下文所有工具和 pass 的基础。文档地图从入口到深处的五类文档Mojo/docs/compiler/目录是 Mojo 编译器文档的一站式入口其下的文档按读者经验层次组织目录定位适用读者docs/manual/入门文档假设读者没有 Mojo 编译器知识编译器团队新人、做临时贡献的开发者docs/overviews/子系统与横切行为概览对编译器较熟悉的开发者docs/arcana/深入细微行为的细节文档包含调试编译器的关键线索尝试调试编译器的开发者docs/attic/记录早期思路与行为的旧文档做代码考古code archeology时偶尔查阅顶层文档如MojoCompilerWalkthrough.md、WorkingInOSRepo.md、DesignOverview.md等所有开发者其中 manual/README.md 是编译器开发手册进一步指向PassesAndIR.mdpass 与中间表示、Terminology.md编译器内部术语、CommonTypesAndTools.md通用类型与工具、MojoIRCPPCorrespondence.mdMojo ↔ IR ↔ C 对应关系、ParserDebugging.md与PostParserDebugging.md调试技巧等专题文档。与文档平行的还有三个源码目录构成文档-源码对照关系Mojo/lib/— 编译器库的 C 源码包括 parser、passes、MLIR dialects 及相关工具如 debuggerMojo/tools/— 命令行接口可执行程序CLI的 C 源码包括mojo、kgen、kgen-opt、kgen-translate等Mojo/test/— 以 Mojo 源程序形式编写的编译器测试覆盖语言特性、mojoCLI 及相关工具测试工具与约定见 testing.md编译产物公开工具、内部工具与运行时库命令行工具一览README.md的 Artifacts 一节将工具划分为公开public与内部internal两类公开工具随mojo包发布内部工具仅在仓库内可用。工具可见性功能输入 → 输出mojo公开Mojo 编译器主可执行程序.mojo→ 可执行文件、.a、.dylibkgen内部完整编译器驱动解析 Mojo或读取 MLIR、运行 KGEN 管线、产出构建产物可输出不同层次的 IR 或最终产物.mojo、.mlir→.mlir、.mlirbc、.ll、.s、.o、.so、C 头文件或程序输出kgen-opt内部对 KGEN IR 运行指定的优化 pass.mlir→.mlirkgen-translate内部仅前端不运行编译管线-import-mojo解析并做类型检查 Mojo 源码、输出litdialect 的 MLIR-mlir-to-llvmir将已 lower 的 MLIR 翻译为文本 LLVM IR.mojo、.mlir→.mlir、.llkgen-translate在文档中被定位为观察解析器产出的最佳工具先用它查看 parser 生成的 LIT IR再把输出管道给kgen-opt以研究单个 pass 的行为。这一用法可以在源码中得到印证——kgen-translate.cpp 中通过mlir::TranslateToMLIRRegistration(import-mojo, ...)注册了-import-mojo选项内部调用LIT::importMojoFile并通过mlir::TranslateFromMLIRRegistration(mlir-to-llvmir, ...)注册了-mlir-to-llvmir选项内部调用mlir::translateModuleToLLVMIR。运行时库CompilerRT.aCompilerRT.a是链接进每个编译出的 Mojo 程序的运行时库为 Mojo 标准库提供底层设施。它属于编译产物中的库Libraries类别。README.md中还以 TODO 形式记录了一个已知的未完成事项Mojo 编译器会产出被 Graph Compiler 消费的 dialect 库使 Graph Compiler 了解 Mojo 编译器使用的 dialects——这说明编译产物与上层生态Graph Compiler之间存在预期的接口设计。在开源仓库中构建与使用 Mojo 编译器WorkingInOSRepo.md专门处理一个常见困惑目录中的多数文档假设你在 Modular monorepo 中工作而在开源仓库中部分命令需要调整。以下是在本仓库中实际可用的工作流。Bazel 构建配置构建 Mojo 编译器时需要给bazel加上--configbuild-mojo标志。为避免每个命令都重复输入可以把它写入local.bazelrcbuild --configbuild-mojoBazel 别名许多编译器文档使用简写别名本仓库的bazelw脚本见仓库根目录 bazelw是对 bazel 的封装。三个常用别名及对应命令如下REPO_PATH指本地仓库根目录别名命令bbREPO_PATH/bazelw buildbrREPO_PATH/bazelw runbtREPO_PATH/bazelw test典型命令构建 Mojo 编译器与标准库./bazelw build --configbuild-mojo //Mojo:mojo用本地构建的编译器运行单个 Mojo 文件./bazelw run --configbuild-mojo //Mojo:mojo -- run main.mojo构建并运行标准库测试./bazelw test --configbuild-mojo //Mojo/stdlib/...若已将构建配置写入local.bazelrc并定义了别名上述三条命令可简化为bb //Mojo:mojo br //Mojo:mojo -- run main.mojo bt //Mojo/stdlib/...使用低层工具时需添加标准库搜索路径kgen、kgen-translate等低层工具在开源仓库中运行时需要加-I Mojo/stdlib标志来包含 Mojo 标准库。例如文档中生成litdialect 的原始命令是br //Mojo/tools/kgen-translate -- -import-mojo main.mojo开源仓库的等价写法为./bazelw run //Mojo/tools/kgen-translate -- -import-mojo -I Mojo/stdlib main.mojo注意此命令本身不会构建标准库需要先按上文说明完成构建。此外仓库中Mojo/test/mojo-integration/目录下的大量测试文件如builtin_function_folder.mojo等都包含import-mojo的 FileCheck 指令是观察该工具实际用法的现成范例。开源仓库中不支持的工作流文档特别提醒两个在开源仓库中不工作的 monorepo 工作流start-modular.shmonorepo 环境设置脚本开源仓库没有对应物//:install构建并安装的目标会创建有状态开发环境并把构建产物安装进PATH开源仓库中可以从构建输出目录bazel-bin手动拷贝产物到PATH中的目录但每次重新构建编译器后需要手动更新另一个重要限制是不能用本地构建的编译器构建任何 MAX 目标此时应使用预构建编译器--configprebuilt-mojo对标准库的改动在提交 PR 前也应使用预构建编译器测试。高层走读六阶段编译管线文档的 High-Level Walkthrough 一节指向 MojoCompilerWalkthrough.md该文档面向刚接触 KGEN/Mojo 代码库的编译器工程师用六个阶段完整描述了从 Mojo 源码到机器码的旅程。以下按该文档的架构图浓缩各阶段要点。阶段 1解析与类型检查关键洞察Mojo 没有传统意义上的 AST。parser 直接向litdialect 发射 MLIR 操作lit就是源码级 IR。实现位于 Mojo/lib/MojoParser/如Lexer.cpp、IREmitter.cpp、DeclResolver.cpp、CallEmission.cpp等。Mojo 采用惰性三阶段解析来处理前向引用Phase 1a 名称解析只注册声明名跳过内容、Phase 1b 签名解析解析参数与返回类型正文仍跳过、Phase 1c 正文解析只对嵌套声明做名称解析。这样struct Foo[T: Stringable]之类的类型可以在定义完成前就被def bar(x: Foo[Int])引用。阶段 2语义检查与 LIT Loweringlitdialect 紧密反映 Mojo 语义关键操作包括lit.fn函数定义、lit.call函数调用、lit.ref.store/lit.ref.load引用存取、lit.struct.decl/lit.trait.decl结构体/特质定义等关键类型包括!lit.refT, origin带生命周期跟踪的引用类型与!lit.generatorsig带元数据的生成器类型。实现位于 Mojo/lib/LowerLIT/主要 pass 有三个LowerSemanticCF将语义级控制流如lit.returnlower 为终结符并诊断不可达代码CheckLifetimes借用检查器插入析构调用、拒绝 use-after-free、对引用执行借用检查LowerLIT将 LIT dialect 转换为 KGEN dialect如lit.fn→kgen.generator、lit.ref→!kgen.pointer阶段 3预展开优化在 elaboration 之前对 KGEN IR 运行若干优化。其动机很直接更少、更小、更简单的生成器generator实例化更快对 elaborator 缓存更友好。关键 pass 包括SROA、Mem2Reg、Canonicalizer、InlineParametric只内联nodebug函数与小函数、SCCP、ApplyInliner处理apply操作符内联等。文档特别提醒预展开阶段过度内联会增加 elaborator 压力并降低缓存粒度。这里需要区分文档中的两个关键概念generator 指带有编译期参数的参数化模板既包括函数生成器kgen.generator也包括结构体生成器kgen.struct.generator经过 elaboration 后它们分别变为具体化的kgen.func与kgen.struct.instance。这与 C 模板 vs 实例化后的模板类似但不要与 Python 基于 yield 的生成器混淆——两者毫无关系。kgen.generator与kgen.struct.generator都实现GeneratorOpInterface这使得 elaboration 对所有生成器是统一的。阶段 4展开单态化展开Elaboration类似 C 的模板实例化但更强大实现位于 Mojo/lib/Elaborator/Elaborator.cpp、IREvaluator.cpp以及较新的ParametricElaborator.cpp、ParametricIREvaluator.cpp。它完成三件事参数替换将泛型参数替换为具体值编译期求值求值参数表达式约束检查验证静态断言elaborator 会构建一张展开图其中ParamNode表示一次生成器实例化生成器引用 输入参数值ImplNode与ParamNode一一对应、包含正在展开的具体函数。展开是并行的独立的生成器实例化并发处理求值同步点强制串行化。编译期代码求值由 Mojo/lib/Interpreter/ 中的解释器完成函数被编译为FunctionIRBytecode以提高求值效率解释器维护模拟内存模型虚拟地址空间来支持加载/存储if/for/while/函数调用均可在编译期工作它不需要真正的 JIT因此可在禁止 JIT 的环境中运行。阶段 5展开后的 Lowering 与优化展开产出具体函数kgen.func后本阶段先做lowering passes必须先于优化运行因为它们影响函数签名与调用点LowerArgConventionslower KGEN 参数传递约定如byref_result、byref_error、packsLowerCallingConventions将高层 KGEN 类型pack、variant、nonelower 为具体表示随后运行优化 passesSROA、Mem2Reg、Canonicalizer、SCCP、AutomaticInline带启发式的激进内联、LoopUnrolling、DeadArgumentElimination等。阶段 6Lowering 到 LLVM实现位于 Mojo/lib/KGENToLLVM/ 与 Mojo/lib/Compiler/ObjectCompiler/KGENToLLVMPipeline.cpp。核心类型映射如下KGEN/POP 类型LLVM 类型!kgen.scalarf32f32!kgen.simd4, f324 x f32!kgen.pointerTptr不透明指针LLVM 15!pop.array4, T[4 x T]结构体类型LLVM 结构体类型之后依次是 MLIR-to-LLVM 翻译LLVM dialect → LLVM IR、LLVM 优化管线、目标相关机器码生成。编译管线中的 dialect 层次文档的 Dialects Reference 总结了各阶段 dialect 的分布源码级LowerLIT 之前 lit kgen pop hlcf 预展开LowerLIT 之后 kgen参数化生成器无 lit ops pop hlcf 展开后 kgen仅具体 op无生成器 pop hlcf 目标级LowerToLLVM 之后llvm其他 dialect 全部被 lower 掉其中popParametric Operations提供常见 LLVM 指令的参数化版本pop.add、pop.load、pop.store、pop.simd.splat等hlcfHigh-Level Control Flow表示结构化控制流hlcf.if、hlcf.for、hlcf.loop、hlcf.break等co协程、debuginfo调试信息、interp解释器操作与数据在阶段 6 lower 到 LLVM。上游/第三方 dialectindex、llvm、nvvm、rocdl可能出现在流程的任何位置。编译器开发者的调试与测试工具箱打印 pass 前后的 IR# 在每个 pass 之前打印 IR kgen --mlir-print-ir-before-all -elaborate main.mojo # 在每个 pass 之后打印 IR kgen --mlir-print-ir-after-all -elaborate main.mojo # 在特定 pass 后打印 IR适合输出较大时 kgen --mlir-print-ir-afterlower-lit main.mojo 21 | less # 调试特定子系统需要 debug 构建 kgen -debug-onlyelaborator -elaborate main.mojo # 把 IR dump 到文件便于检查 kgen --mlir-print-ir-after-all -elaborate main.mojo 2 ir-dump.mlir查看所有运行的 passkgen --mlir-print-ir-before-all -elaborate main.mojo 21 | grep IR Dump Before运行测试编译器测试位于 Mojo/test/使用 LLVM 的 lit 测试框架与 FileCheck 断言# 运行全部 Mojo 测试 bt //Mojo/test/... # 运行特定测试文件 bt //Mojo/test/mojo-integration:my_test.mojo测试文件通过 FileCheck 指令验证输出例如# RUN: kgen-translate -import-mojo %s | FileCheck %s def foo(): pass # CHECK: lit.fn foo()源码快速参考目录内容Mojo/lib/MojoParser/解析器与类型检查器Mojo/lib/LITDialect/LIT dialect 实现Mojo/lib/KGENDialect/KGEN dialect 实现Mojo/lib/POPDialect/POP dialect 实现Mojo/lib/HLCFDialect/HLCF dialect 实现Mojo/lib/Elaborator/展开/单态化Mojo/lib/Interpreter/编译期解释器字节码、内存模型Mojo/lib/LowerLIT/LIT lowering passesMojo/lib/KGENToLLVM/LLVM lowering passesMojo/lib/Transforms/优化 passesMojo/tools/mojo/Precompile/precompile 命令实现Support/lib/DebugInfoDialect/调试信息 dialect 实现Mojo/test/编译器测试lit FileCheck进一步阅读本指南只是入口。深入的方向包括MojoCompilerWalkthrough.md完整的六阶段编译管线、Mojo 包与预编译文件.mojoc、参数化调试信息debuginfodialect与 key passes 汇总manual/编译器开发手册从零开始修改 Mojo 编译器overviews/子系统与横切行为概览如并行展开、包格式、LazyParsing、解释器WorkingInOSRepo.md开源仓库中的 Bazel 工作流本文第 5 节即其要点DesignOverview.md编译器设计总览【免费下载链接】mojoThe Modular Platform (includes MAX Mojo)项目地址: https://gitcode.com/GitHub_Trending/mo/mojo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表