[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 package org.jetbrains.kotlin.sir.bridge
import org.jetbrains.kotlin.sir.SirFunction 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.BridgeGeneratorImpl
import org.jetbrains.kotlin.sir.bridge.impl.CBridgePrinter import org.jetbrains.kotlin.sir.bridge.impl.CBridgePrinter
import org.jetbrains.kotlin.sir.bridge.impl.KotlinBridgePrinter import org.jetbrains.kotlin.sir.bridge.impl.KotlinBridgePrinter
@@ -22,6 +23,21 @@ public class BridgeRequest(
public val fqName: List<String>, 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. * A C-like wrapper around some Kotlin function.
* Abstracts away all nuances of Kotlin compiler ABI, making it possible * 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.psi.KtFile
import org.jetbrains.kotlin.sir.* import org.jetbrains.kotlin.sir.*
import org.jetbrains.kotlin.sir.analysisapi.SirGenerator import org.jetbrains.kotlin.sir.analysisapi.SirGenerator
import org.jetbrains.kotlin.sir.bridge.BridgeRequest import org.jetbrains.kotlin.sir.bridge.*
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.builder.buildModule 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.SirInflatePackagesPass
import org.jetbrains.sir.passes.SirModulePass import org.jetbrains.sir.passes.SirModulePass
import org.jetbrains.sir.passes.SirPass import org.jetbrains.sir.passes.SirPass
@@ -37,12 +34,17 @@ class SwiftExportExtension(
} }
override fun doAnalysis(configuration: CompilerConfiguration): Boolean { override fun doAnalysis(configuration: CompilerConfiguration): Boolean {
buildSwiftModule(configuration) val module = buildSwiftModule(configuration)
.transformToSwift() .transformToSwift()
.dumpResultToFiles() val bridgeRequests = module.createFunctionBridges()
module.dumpResultToFiles(bridgeRequests)
return true return true
} }
private fun SirModule.createFunctionBridges(): List<BridgeRequest> {
return BridgeGenerationPass.run(this)
}
@OptIn(KtAnalysisApiInternals::class) @OptIn(KtAnalysisApiInternals::class)
private fun buildSwiftModule(configuration: CompilerConfiguration): SirModule { private fun buildSwiftModule(configuration: CompilerConfiguration): SirModule {
val standaloneAnalysisAPISession = val standaloneAnalysisAPISession =
@@ -74,14 +76,14 @@ class SwiftExportExtension(
} }
} }
private fun SirModule.dumpResultToFiles() { private fun SirModule.dumpResultToFiles(requests: List<BridgeRequest>) {
val destinationPath = destination.absolutePath val destinationPath = destination.absolutePath
val cHeaderFile = File("${destinationPath}/${outputFileName}.h") val cHeaderFile = File("${destinationPath}/${outputFileName}.h")
val ktBridgeFile = File("${destinationPath}/${outputFileName}.kt") val ktBridgeFile = File("${destinationPath}/${outputFileName}.kt")
val swiftFile = File("${destinationPath}/${outputFileName}.swift") val swiftFile = File("${destinationPath}/${outputFileName}.swift")
val bridges = generateBridgeSources() val bridges = generateBridgeSources(requests)
val swiftSrc = generateSwiftSrc() val swiftSrc = generateSwiftSrc()
dumpTextAtFile(bridges.ktSrc, ktBridgeFile) dumpTextAtFile(bridges.ktSrc, ktBridgeFile)
@@ -93,8 +95,7 @@ class SwiftExportExtension(
return SirAsSwiftSourcesPrinter().print(this) return SirAsSwiftSourcesPrinter().print(this)
} }
private fun SirModule.generateBridgeSources(): BridgeSources { private fun generateBridgeSources(requests: List<BridgeRequest>): BridgeSources {
val requests = BridgeRequestsBuilder.build(this)
val generator = createBridgeGenerator() val generator = createBridgeGenerator()
val kotlinBridgePrinter = createKotlinBridgePrinter() val kotlinBridgePrinter = createKotlinBridgePrinter()
@@ -149,27 +150,30 @@ class SwiftExportExtension(
} }
} }
private object BridgeRequestsBuilder : SirVisitor<Unit, MutableList<BridgeRequest>>() { private object BridgeGenerationPass : SirPass<SirElement, Nothing?, List<BridgeRequest>> {
fun build(from: SirModule): List<BridgeRequest> { override fun run(element: SirElement, data: Nothing?): List<BridgeRequest> {
val result = mutableListOf<BridgeRequest>() val requests = mutableListOf<BridgeRequest>()
from.accept(this, result) element.accept(Visitor(requests))
return result return requests.toList()
} }
override fun visitFunction(function: SirFunction, data: MutableList<BridgeRequest>) { private class Visitor(val requests: MutableList<BridgeRequest>) : SirVisitorVoid() {
val fqName = (function.origin as? SirKotlinOrigin.Function)?.fqName ?: return
data.add( override fun visitElement(element: SirElement) {
BridgeRequest( element.acceptChildren(this)
}
override fun visitFunction(function: SirFunction) {
val fqName = (function.origin as? SirKotlinOrigin.Function)?.fqName
?: return
val bridgeRequest = BridgeRequest(
function, function,
fqName.joinToString("_"), fqName.joinToString("_"),
fqName fqName
) )
) requests += bridgeRequest
} function.body = createFunctionBodyFromRequest(bridgeRequest)
}
override fun visitElement(element: SirElement, data: MutableList<BridgeRequest>) {
element.acceptChildren(this, data)
} }
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
#include <stdint.h> #include <stdint.h>
int32_t namespace1_main_foobar(); int32_t namespace1_main_foobar(int32_t param);
int32_t namespace1_foo(); int32_t namespace1_foo();
+2 -2
View File
@@ -1,8 +1,8 @@
import kotlin.native.internal.ExportedBridge import kotlin.native.internal.ExportedBridge
@ExportedBridge("namespace1_main_foobar") @ExportedBridge("namespace1_main_foobar")
public fun namespace1_main_foobar(): Int { public fun namespace1_main_foobar(param: Int): Int {
val result = namespace1.main.foobar() val result = namespace1.main.foobar(param)
return result return result
} }
+6 -4
View File
@@ -1,16 +1,18 @@
enum namespace1 { enum namespace1 {
enum main { enum main {
public func foobar() -> Swift.Int32 { public func foobar(
fatalError() param: Swift.Int32
) -> Swift.Int32 {
return namespace1_main_foobar(param)
} }
} }
public func foo() -> Swift.Int32 { public func foo() -> Swift.Int32 {
fatalError() return namespace1_foo()
} }
} }
enum namespace2 { enum namespace2 {
public func bar() -> Swift.Int32 { public func bar() -> Swift.Int32 {
fatalError() return namespace2_bar()
} }
} }
+1 -1
View File
@@ -13,4 +13,4 @@ package namespace1.main
import namespace1 import namespace1
import namespace2 import namespace2
fun foobar(): Int = foo() + bar() fun foobar(param: Int): Int = foo() + bar() + param