本文档描述了 Kotlin WebAssembly (Wasm) 后端,该后端能够将 Kotlin 代码编译为 WebAssembly。Wasm 后端将 Kotlin IR (中间表示) 转换为 WebAssembly IR,然后再转换为二进制或文本格式。本页重点介绍后端本身的实现细节,而不是如何作为开发者使用 Kotlin/Wasm。
WebAssembly 后端作为 Kotlin 编译器后端基础设施的一部分实现,将 Kotlin IR 转换为 WebAssembly 模块。它包含代码生成、序列化和优化组件。
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compilerWithIC.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleFragmentGenerator.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt
WebAssembly 后端遵循以下主要步骤将 Kotlin IR 转换为 WebAssembly
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleFragmentGenerator.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt
这是表示已编译的 WebAssembly 模块片段的核心数据结构。它包含生成 WebAssembly 代码所需的所有必要信息。
DeclarationGenerator 负责将 Kotlin IR 声明(类、函数、属性)转换为 WebAssembly 声明。
主要职责
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt
BodyGenerator 将 Kotlin IR 函数体转换为 WebAssembly 指令。它处理各种 Kotlin 结构,例如
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt
WasmModuleMetadataCache 维护编译期间所需的 Kotlin 类和接口信息
WasmFunctionCodegenContext 跟踪与正在编译的特定函数相关的信息
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContext.kt
WebAssembly 后端包含序列化组件,用于在内存表示和二进制/文本格式之间进行转换。
WasmSerializer 将 WebAssembly IR 转换为二进制格式,它实现了一种复杂的引用表方法来处理共享对象。
主要功能
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/serialization/WasmSerializer.kt
WasmDeserializer 从二进制格式中重建 WebAssembly IR。它是序列化器的精确反操作。
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/serialization/WasmDeserializer.kt
序列化过程遵循以下顺序
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/serialization/WasmSerializer.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/serialization/WasmDeserializer.kt
最终的 WebAssembly 模块包含几个关键部分
| 章节 | 目的 |
|---|---|
| 类型 | 函数、结构和数组类型声明 |
| 导入 | 从 JS 导入的外部函数、内存和标签 |
| 功能 | 函数声明 |
| 表格 | 函数表(用于动态分派) |
| 内存 | 线性内存声明 |
| 全局 | 全局变量声明 |
| 导出 | 暴露给宿主环境的项 |
| 代码 | 包含 WebAssembly 指令的函数实现 |
| 数据 | 静态数据段 |
来源: wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt97-198
WebAssembly 后端支持 JavaScript 互操作性,这对于 Web 应用程序至关重要。
对于外部 JavaScript 函数,后端会创建适当的包装器和适配器
后端会创建专门的适配器来处理 Kotlin 和 JavaScript 之间的类型转换
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/JsInteropFunctionsLowering.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/ComplexExternalDeclarationsToTopLevelFunctionsLowering.kt
后端支持使用 @JsExport 注解导出 Kotlin 函数到 JavaScript。这会在 WebAssembly 模块中创建适当的导出声明。
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/JsInteropFunctionsLowering.kt
生成最终的 WebAssembly 模块时,后端会执行几项重要任务
主初始化函数在正确初始化模块方面起着关键作用
_initialize():
1. Call kotlin.Unit_getInstance()
2. Call _fieldInitialize() to initialize all global fields
3. Call main function wrappers (if present)
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt140-222 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt477-458
WebAssembly 后端支持两种基于 WebAssembly 异常处理提案的异常处理方法
try_table 和 catch 块try/catch 机制异常处理适应目标 WebAssembly 环境的功能
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt190-432
WebAssembly 后端实现了垃圾回收(Dead Code Elimination, DCE)以通过移除未使用的代码来减小生成模块的大小
DCE 通过消除运行时不需要的代码,显著减小了二进制文件的大小。
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/Dce.kt
WebAssembly 后端通过 IC (Incremental Compilation) 基础设施支持增量编译
这使得在开发过程中只重新编译更改的文件变得高效。
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compilerWithIC.kt24-60 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ic/IrFactoryImplForWasmIC.kt
WebAssembly 后端应用了若干专门的 lowering 来适配 Kotlin IR 到 WebAssembly。
| Lowering | 目的 |
|---|---|
ComplexExternalDeclarationsToTopLevelFunctionsLowering | 将外部声明转换为顶层函数 |
JsInteropFunctionsLowering | 为 JS 互操作创建适配器 |
WasmTypeOperatorLowering | 处理类型操作,如 instanceof |
BuiltInsLowering | 将内建函数替换为 WebAssembly 等效项 |
UnitToVoidLowering | 在适当的情况下将 Unit 返回类型转换为 void |
来源: compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/ComplexExternalDeclarationsToTopLevelFunctionsLowering.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/JsInteropFunctionsLowering.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/UnitToVoidLowering.kt
Kotlin WebAssembly 后端是一个复杂的编译器组件,它使 Kotlin 代码能够在 WebAssembly 目标上运行。它负责从 Kotlin IR 到 WebAssembly 模块的完整编译管线,并提供对 JavaScript 互操作、异常处理和优化的专门支持。
该后端在设计上考虑了模块化,将声明生成、体生成和序列化等关注点分离开来。这种架构有利于随着 WebAssembly 的发展来维护和扩展后端。