IR(中间表示)是 Kotlin 编译器管道中的一个关键组件,它作为前端(解析和分析)与后端(代码生成)之间的通用代码表示。本页面将介绍 IR 的结构和目的、如何对其应用转换,以及它如何实现 Kotlin 的跨平台编译。
IR 位于 Kotlin 编译器的中间阶段,在前端从源代码生成结构化表示之后,但在特定于后端的代码生成之前。有关前端 IR (FIR) 的信息,请参阅页面 FIR (前端 IR)。
IR 以树状结构表示 Kotlin 代码,该结构在保留所有必要代码生成信息的同时,抽象化了源代码的语法。
来源:compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/FunctionInlining.kt19-33 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrInlineUtils.kt8-13
声明:定义程序结构(类、函数、属性)
IrClass:表示类、接口、对象、枚举类IrFunction:所有类函数声明的基类IrProperty:具有关联的 getter/setter 的属性IrVariable:局部变量表达式:表示产生值的计算
IrCall:函数调用IrGetValue/IrSetValue:变量访问/赋值IrReturn:return 语句IrWhen:条件表达式符号:充当声明的引用
IrClassSymbol:类引用IrFunctionSymbol:函数引用类型:指定表达式产生的值的种类
IrSimpleType:常规类型(类、接口)IrDynamicType:动态类型(主要用于 JavaScript)签名:声明的唯一标识符
IdSignature:用于跨模块链接和序列化来源:compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DeclarationTable.kt12-59 compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/signature/IdSignatureComputers.kt22-59
IR 创建后,它会经历许多称为“下推”(lowerings)的转换,这些转换会修改 IR 树,逐步为代码生成做好准备。
来源:kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/NativeLoweringPhases.kt149-176 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt747-779 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt149-186
最重要的转换之一是函数内联,它在适当转换后用函数体替换对内联函数的调用。这分为两个阶段:
来源:compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/FunctionInlining.kt37-134 compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/InlineFunctionResolver.kt27-74 compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/CommonInlineCallableReferenceToLambdaPhase.kt7-14
IR 阶段的函数内联支持多项重要功能:
来源:compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/InlineCallableReferenceToLambda.kt36-98 kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeIrInliner.kt12-18
除了函数内联,IR 还经历许多其他转换:
IR 可以被序列化以支持增量编译、多模块项目和库分发。
来源:compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt114-205 compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/serializeModuleIntoKlib.kt1-40
来源:compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrSerializationSettings.kt36-46 compiler/ir/serialization.common/src/KotlinIr.proto1-2
当消费序列化的 IR 时
对于内联函数,存在特殊的反序列化器,可以在需要内联时按需加载函数体。
来源:compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt1-6 compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt1-35 compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/NonLinkingIrInlineFunctionDeserializer.kt24-35
IR 通过提供可独立于平台转换的通用表示,实现了 Kotlin 的多平台能力
来源:compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt80-109 native/native.tests/tests/org/jetbrains/kotlin/konan/test/NativeKlibSerializerFacade.kt40-61
每个后端(JVM、JS、Native、WebAssembly)都有处理平台特定要求的特定 IR 降低阶段,但它们都从相同的通用 IR 结构开始。
来源:kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirNativeSerializer.kt1-5 js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt77-109 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt34-61
函数内联是 IR 阶段最复杂的转换之一。该过程包括
来源:compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/FunctionInlining.kt136-201 compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/FunctionInlining.kt37-61
函数内联分两个阶段进行,以正确处理依赖关系
来源:compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/CommonLoweringPhases.kt54-63 compiler/ir/ir.inline/src/org/jetbrains/kotlin/ir/inline/CommonLoweringPhases.kt103-140
虽然 IR 主要用于编译,但也支持工具
IR 结构保留了足够多的关于原始源代码的信息,可以支持这些功能,同时仍然是一个可优化的中间表示。
IR 是 Kotlin 编译器的骨干,它实现了
它的设计允许 Kotlin 在所有目标平台保持相同的语言语义,同时仍然为每个平台生成最佳代码。
来源:compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrInlineUtils.kt25-64