菜单

架构概述

相关源文件

本文档提供了 Kotlin 编译器架构的高级概述,描述了其主要组件以及从源代码到目标平台的编译流程。它概述了关键的转换阶段、核心系统以及它们如何交互以生成各种平台的最终输出。

有关构建编译器的具体详细信息,请参阅 构建和贡献。有关特定编译器组件的详细信息,请参阅 编译器前端中间端后端测试基础架构 的专用页面。

编译器流程概述

高级编译流程

来源:compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ResolutionStages.kt compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/FunctionInlining.kt

编译器由三个主要处理阶段组成

  1. 前端:解析源代码并构建程序结构接口 (PSI) 树。现代前端使用 FIR(前端 IR)进行分析,而旧版 K1 前端则维护以兼容。

  2. 中间端:将 FIR 转换为 IR(中间表示),执行如函数内联和类型检查等优化。

  3. 后端:目标特定代码生成器,将 IR 转换为相应的输出格式(JVM 字节码、JavaScript、原生代码或 WebAssembly)。

整个流程由语言版本设置控制,这些设置决定了启用或禁用的语言功能和 API 兼容性。

前端:FIR 系统

来源:compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ResolutionStages.kt compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirCallResolver.kt compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt

前端 IR (FIR) 系统通过多个阶段处理 Kotlin 源代码

  1. 生成原始 FIR:将 PSI(程序结构接口)树转换为初始 FIR 结构。

  2. 隐式类型处理:分析并填充隐式类型。

  3. 主体解析:包含两个主要部分

    • 声明解析器:解析声明引用和签名
    • 表达式解析器:处理表达式解析,包括调用
  4. 调用解析:执行重载解析和类型参数推断。

  5. 诊断检查:运行检查器以识别和报告代码中的错误。

  6. FIR 到 IR 转换:将完全解析的 FIR 转换为 IR 格式以供中间端使用。

整个过程由语言版本设置控制,这些设置决定了哪些语言功能被启用或禁用。

中间端:IR 系统和内联

来源:compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/FunctionInlining.kt37-134 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt35-59 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt37-72

IR(中间表示)系统是 Kotlin 编译器的中间端。关键组件包括

  1. IR 树:Kotlin 代码的语言中立表示,从 FIR 生成。

  2. IR Lowerings(IR 降级):用于简化或优化 IR 的转换,包括

    • 函数内联:用函数体替换函数调用
    • 类型运算符降级:将类型操作转换为运行时调用
    • 默认参数降级:处理默认参数值
  3. 函数内联过程:

  4. IR 序列化:将 IR 编码以存储在 KLIB 格式中,从而支持增量编译和跨模块内联。

  5. 代码生成:后端特定的进程,将 IR 转换为目标代码。

原生后端降级阶段

来源:kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/NativeLoweringPhases.kt60-118 kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/NativeLoweringPhases.kt339-374 kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeInlineFunctionResolver.kt31-90

原生后端应用一系列降级转换到 IR 树,将其转换为适合原生代码生成的表示。该过程包括

  1. 初始验证:在开始转换之前验证 IR 是否格式正确。

  2. 初级降级:

    • 升级可调用引用:将可调用引用转换为更高效的形式
    • 数组构造函数降级:处理数组创建
    • Lateinit 降级:实现 lateinit 属性的运行时检查
    • 共享变量降级:处理在 lambda 中捕获的变量
    • 提取局部类:处理内联 lambda 中的局部类
  3. 内联过程:

    • 内联私有函数:第一个阶段,仅内联私有函数
    • 合成访问器生成:为私有成员创建访问器
    • 内联所有函数:第二个阶段,内联剩余的内联函数
  4. 后内联降级:

    • 移除 Expect 声明:处理多平台 expect/actual 声明
    • Contracts DSL 移除:移除 contract DSL 调用
    • 字符串连接:优化字符串连接操作
    • 枚举构造函数/类:转换枚举类
    • 协程降级:转换挂起函数和协程
    • 类型运算符降级:处理类型检查和转换
    • 桥接构建:为继承创建桥接方法
    • 自动装箱:处理原始类型的装箱/拆箱
  5. 最终验证和代码生成:验证降级后的 IR 并生成原生代码。

NativeInlineFunctionResolver 用于从外部模块解析和反序列化用于内联的函数。

语言版本设置

语言版本设置控制着给定语言版本可用功能的范围以及编译器的行为。该系统对于管理兼容性和支持增量语言演进至关重要。

来源:compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt15-542

语言版本设置系统的关键方面

  1. 语言特性:每个特性都在LanguageFeature枚举中定义,compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt20-483 包含属性:

    • sinceVersion:特性引入的 Kotlin 版本
    • sinceApiVersion:API 版本要求
    • kind:特性的类型(BUG_FIX、UNSTABLE_FEATURE、OTHER 等)
    • behaviorAfterSinceVersion:特性引入后是否可以禁用
  2. 特性状态:

    • ENABLED:特性完全启用
    • ENABLED_WITH_WARNING:特性已启用但会产生警告
    • DISABLED:特性不可用
  3. 渐进模式:某些特性可以使用 -progressive 编译器标志自动启用,从而允许提前采用即将推出的特性。

  4. 在编译器管道中的使用:

    • 前端使用语言设置来确定哪些结构是有效的
    • 中端根据启用的特性应用不同的转换
    • 后端根据语言版本设置生成不同的代码

该系统允许语言平稳演进并保持向后兼容性,并为实验性特性和弃用周期提供机制。

测试基础设施

来源:compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KaFirDiagnosticImpl.kt analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KaFirDiagnosticImpl.kt

Kotlin 编译器拥有全面的测试基础架构,用于验证编译的各个方面。

  1. 诊断测试:验证编译器是否正确报告错误和警告。

  2. 黑盒测试:通过执行编译后的代码来验证代码生成。

    • 特定于平台的变体:JVM、JS、Native 和 WebAssembly
    • 测试编译和运行时行为
  3. 内联测试:专门测试函数内联机制,确保它

    • 正确地用函数体替换函数调用
    • 妥善处理 lambda 参数和捕获
    • 转换后保留语义

测试系统结合使用测试数据文件(包含 Kotlin 源代码)、测试生成器和测试运行器来自动验证编译器行为。

Gradle 构建系统

来源:compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt

Kotlin 编译器通过 Kotlin Gradle 插件 (KGP) 系统与 Gradle 集成,该系统

  1. 提供特定于平台的插件:

    • Kotlin JVM 插件:将 Kotlin 编译为 JVM 字节码
    • Kotlin JS 插件:将 Kotlin 编译为 JavaScript
    • Kotlin Multiplatform 插件:处理多平台项目
    • Kotlin Native 插件:将 Kotlin 编译为原生二进制文件
  2. 定义 Gradle 任务:

    • KotlinCompile:用于 JVM 编译
    • KotlinJsCompile:用于 JavaScript 编译
    • KotlinNativeLink:用于原生二进制文件链接
  3. 管理配置:

    • 根据 Gradle 属性配置编译器选项
    • 处理依赖项管理
    • 设置编译器插件

该构建系统旨在支持多个平台,同时通过 Gradle 提供一致的接口。

关键系统关系和接口

Kotlin 编译器的主要组件通过定义明确的接口进行交互

组件输入输出关键接口
前端 (FIR)源文件FIR 树FirDeclarationsResolveTransformerFirCallResolver
中端 (IR)FIR 树IR 树Fir2IrConverterFunctionInlining
后端IR 树目标代码特定于后端的降低操作
语言设置配置功能状态LanguageVersionSettingsLanguageFeature
诊断错误/警告用户消息FirErrorsFirDiagnosticsDefaultMessages

设计遵循明确的关注点分离

  1. 前端:专注于语法和语义分析。
  2. 中端:处理与语言无关的优化和转换。
  3. 后端:负责特定于目标的代码生成。
  4. 通用基础设施:提供语言版本控制和诊断报告等实用程序。

这种架构使得在共享大量代码分析和转换逻辑的同时支持多个目标平台成为可能。

来源:compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/FunctionInlining.kt compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt