[KT-63275] Generate wrapper bodies in the SwiftExportExtension

This commit is contained in:
Sergey Bogolepov
2024-01-12 13:42:55 +02:00
committed by Space Team
parent cb19e291a3
commit 591e98a947
6 changed files with 55 additions and 33 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.sir.bridge
import org.jetbrains.kotlin.sir.SirFunction
import org.jetbrains.kotlin.sir.SirFunctionBody
import org.jetbrains.kotlin.sir.bridge.impl.BridgeGeneratorImpl
import org.jetbrains.kotlin.sir.bridge.impl.CBridgePrinter
import org.jetbrains.kotlin.sir.bridge.impl.KotlinBridgePrinter
@@ -22,6 +23,21 @@ public class BridgeRequest(
public val fqName: List<String>,
)
/**
* Generates the body of a function from a given request.
*
* @param request the BridgeRequest object that contains information about the function and the bridge
* @return the generated SirFunctionBody object representing the body of the function
*/
public fun createFunctionBodyFromRequest(request: BridgeRequest): SirFunctionBody {
val callee = request.bridgeName
val calleeArguments = request.function.parameters.map { it.argumentName }
val callSite = "$callee(${calleeArguments.joinToString(separator = ", ")})"
return SirFunctionBody(
listOf("return $callSite")
)
}
/**
* A C-like wrapper around some Kotlin function.
* Abstracts away all nuances of Kotlin compiler ABI, making it possible
@@ -14,12 +14,9 @@ import org.jetbrains.kotlin.fir.extensions.FirAnalysisHandlerExtension
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.sir.*
import org.jetbrains.kotlin.sir.analysisapi.SirGenerator
import org.jetbrains.kotlin.sir.bridge.BridgeRequest
import org.jetbrains.kotlin.sir.bridge.createBridgeGenerator
import org.jetbrains.kotlin.sir.bridge.createCBridgePrinter
import org.jetbrains.kotlin.sir.bridge.createKotlinBridgePrinter
import org.jetbrains.kotlin.sir.bridge.*
import org.jetbrains.kotlin.sir.builder.buildModule
import org.jetbrains.kotlin.sir.visitors.SirVisitor
import org.jetbrains.kotlin.sir.visitors.SirVisitorVoid
import org.jetbrains.sir.passes.SirInflatePackagesPass
import org.jetbrains.sir.passes.SirModulePass
import org.jetbrains.sir.passes.SirPass
@@ -37,12 +34,17 @@ class SwiftExportExtension(
}
override fun doAnalysis(configuration: CompilerConfiguration): Boolean {
buildSwiftModule(configuration)
val module = buildSwiftModule(configuration)
.transformToSwift()
.dumpResultToFiles()
val bridgeRequests = module.createFunctionBridges()
module.dumpResultToFiles(bridgeRequests)
return true
}
private fun SirModule.createFunctionBridges(): List<BridgeRequest> {
return BridgeGenerationPass.run(this)
}
@OptIn(KtAnalysisApiInternals::class)
private fun buildSwiftModule(configuration: CompilerConfiguration): SirModule {
val standaloneAnalysisAPISession =
@@ -74,14 +76,14 @@ class SwiftExportExtension(
}
}
private fun SirModule.dumpResultToFiles() {
private fun SirModule.dumpResultToFiles(requests: List<BridgeRequest>) {
val destinationPath = destination.absolutePath
val cHeaderFile = File("${destinationPath}/${outputFileName}.h")
val ktBridgeFile = File("${destinationPath}/${outputFileName}.kt")
val swiftFile = File("${destinationPath}/${outputFileName}.swift")
val bridges = generateBridgeSources()
val bridges = generateBridgeSources(requests)
val swiftSrc = generateSwiftSrc()
dumpTextAtFile(bridges.ktSrc, ktBridgeFile)
@@ -93,8 +95,7 @@ class SwiftExportExtension(
return SirAsSwiftSourcesPrinter().print(this)
}
private fun SirModule.generateBridgeSources(): BridgeSources {
val requests = BridgeRequestsBuilder.build(this)
private fun generateBridgeSources(requests: List<BridgeRequest>): BridgeSources {
val generator = createBridgeGenerator()
val kotlinBridgePrinter = createKotlinBridgePrinter()
@@ -149,27 +150,30 @@ class SwiftExportExtension(
}
}
private object BridgeRequestsBuilder : SirVisitor<Unit, MutableList<BridgeRequest>>() {
fun build(from: SirModule): List<BridgeRequest> {
val result = mutableListOf<BridgeRequest>()
from.accept(this, result)
return result
private object BridgeGenerationPass : SirPass<SirElement, Nothing?, List<BridgeRequest>> {
override fun run(element: SirElement, data: Nothing?): List<BridgeRequest> {
val requests = mutableListOf<BridgeRequest>()
element.accept(Visitor(requests))
return requests.toList()
}
override fun visitFunction(function: SirFunction, data: MutableList<BridgeRequest>) {
val fqName = (function.origin as? SirKotlinOrigin.Function)?.fqName ?: return
private class Visitor(val requests: MutableList<BridgeRequest>) : SirVisitorVoid() {
data.add(
BridgeRequest(
override fun visitElement(element: SirElement) {
element.acceptChildren(this)
}
override fun visitFunction(function: SirFunction) {
val fqName = (function.origin as? SirKotlinOrigin.Function)?.fqName
?: return
val bridgeRequest = BridgeRequest(
function,
fqName.joinToString("_"),
fqName
)
)
}
override fun visitElement(element: SirElement, data: MutableList<BridgeRequest>) {
element.acceptChildren(this, data)
requests += bridgeRequest
function.body = createFunctionBodyFromRequest(bridgeRequest)
}
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
#include <stdint.h>
int32_t namespace1_main_foobar();
int32_t namespace1_main_foobar(int32_t param);
int32_t namespace1_foo();
+2 -2
View File
@@ -1,8 +1,8 @@
import kotlin.native.internal.ExportedBridge
@ExportedBridge("namespace1_main_foobar")
public fun namespace1_main_foobar(): Int {
val result = namespace1.main.foobar()
public fun namespace1_main_foobar(param: Int): Int {
val result = namespace1.main.foobar(param)
return result
}
+6 -4
View File
@@ -1,16 +1,18 @@
enum namespace1 {
enum main {
public func foobar() -> Swift.Int32 {
fatalError()
public func foobar(
param: Swift.Int32
) -> Swift.Int32 {
return namespace1_main_foobar(param)
}
}
public func foo() -> Swift.Int32 {
fatalError()
return namespace1_foo()
}
}
enum namespace2 {
public func bar() -> Swift.Int32 {
fatalError()
return namespace2_bar()
}
}
+1 -1
View File
@@ -13,4 +13,4 @@ package namespace1.main
import namespace1
import namespace2
fun foobar(): Int = foo() + bar()
fun foobar(param: Int): Int = foo() + bar() + param