[Swift Export] KT-63516
Add a sir-compiler-bridge module that adds Kotlin and C bridges for SIR. As SIR is still WIP, the module accepts `BridgeRequest` instances instead of SIR elements.
This commit is contained in:
committed by
Space Team
parent
7c15e3f229
commit
fe9ab0a1fc
@@ -10,6 +10,7 @@ sourceSets {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testApi(projectTests(":native:swift:sir-analysis-api"))
|
testApi(projectTests(":native:swift:sir-analysis-api"))
|
||||||
|
testApi(projectTests(":native:swift:sir-compiler-bridge"))
|
||||||
testImplementation(projectTests(":generators:test-generator"))
|
testImplementation(projectTests(":generators:test-generator"))
|
||||||
|
|
||||||
testRuntimeOnly(projectTests(":analysis:analysis-test-framework"))
|
testRuntimeOnly(projectTests(":analysis:analysis-test-framework"))
|
||||||
|
|||||||
+11
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.generators.tests.native.swift.sir.analysis.api
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5
|
import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5
|
||||||
import org.jetbrains.kotlin.sir.analysisapi.AbstractKotlinSirContextTest
|
import org.jetbrains.kotlin.sir.analysisapi.AbstractKotlinSirContextTest
|
||||||
|
import org.jetbrains.kotlin.sir.bridge.AbstractKotlinSirBridgeTest
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
@@ -22,5 +23,15 @@ fun main() {
|
|||||||
model("", pattern = "^([^_](.+)).kt$", recursive = false)
|
model("", pattern = "^([^_](.+)).kt$", recursive = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testGroup(
|
||||||
|
"native/swift/sir-compiler-bridge/tests-gen/",
|
||||||
|
"native/swift/sir-compiler-bridge/testData"
|
||||||
|
) {
|
||||||
|
testClass<AbstractKotlinSirBridgeTest>(
|
||||||
|
suiteTestClassName = "SirCompilerBridgeTestGenerated"
|
||||||
|
) {
|
||||||
|
model("", extension = null, recursive = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Swift IR to Kotlin compiler bridges
|
||||||
|
|
||||||
|
This module is responsible for the generation of "glue" code between Swift Export and Kotlin compiler.
|
||||||
|
|
||||||
|
Swift does not "know" how to call Kotlin directly. But it has a C/C++/Objective-C interop, and we can leverage it for Swift Export.
|
||||||
|
|
||||||
|
We do the following:
|
||||||
|
1. Generate a Kotlin wrapper around the original Kotlin function with a primitive C-like ABI.
|
||||||
|
2. Generate a C header with C declarations of these wrappers.
|
||||||
|
3. Call these C functions from Swift functions.
|
||||||
|
|
||||||
|
That's it! This approach also has the following advantages:
|
||||||
|
1. All nuances of Kotlin compiler and Kotlin/Native runtime are hidden behind wrappers with a simple ABI.
|
||||||
|
So Swift Export (mostly) does not need to care about how Kotlin/Native works under the hood.
|
||||||
|
2. The contract between Swift Export and Kotlin compiler is well-defined in the form of a set of compiler intrinsics.
|
||||||
|
|
||||||
|
For the sake of simplicity, Kotlin wrappers are generated as Kotlin sources,
|
||||||
|
but later we can switch to direct generation of Kotlin Backend IR.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
description = "SIR to Kotlin bindings generator"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly(kotlinStdlib())
|
||||||
|
|
||||||
|
testApi(platform(libs.junit.bom))
|
||||||
|
testRuntimeOnly(libs.junit.jupiter.engine)
|
||||||
|
testImplementation(libs.junit.jupiter.api)
|
||||||
|
|
||||||
|
testImplementation(projectTests(":compiler:tests-common"))
|
||||||
|
testImplementation(projectTests(":compiler:tests-common-new"))
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
"main" { projectDefault() }
|
||||||
|
"test" {
|
||||||
|
projectDefault()
|
||||||
|
generatedTestDir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
projectTest(jUnitMode = JUnitMode.JUnit5) {
|
||||||
|
workingDir = rootDir
|
||||||
|
useJUnitPlatform { }
|
||||||
|
}
|
||||||
|
|
||||||
|
testsJar()
|
||||||
+108
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.sir.bridge
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.sir.bridge.impl.BridgeGeneratorImpl
|
||||||
|
import org.jetbrains.kotlin.sir.bridge.impl.CBridgePrinter
|
||||||
|
import org.jetbrains.kotlin.sir.bridge.impl.KotlinBridgePrinter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of a Kotlin function for which we are creating the bridge.
|
||||||
|
*
|
||||||
|
* TODO: Replace with SIR once KT-63266 is merged.
|
||||||
|
*
|
||||||
|
* @param fqName Fully qualified name of the function we are bridging.
|
||||||
|
* @param bridgeName C name of the bridge
|
||||||
|
*/
|
||||||
|
class BridgeRequest(
|
||||||
|
val fqName: List<String>,
|
||||||
|
val bridgeName: String,
|
||||||
|
val parameters: List<Parameter>,
|
||||||
|
val returnType: Type,
|
||||||
|
) {
|
||||||
|
class Parameter(
|
||||||
|
val name: String,
|
||||||
|
val type: Type,
|
||||||
|
)
|
||||||
|
|
||||||
|
sealed interface Type {
|
||||||
|
data object Boolean : Type
|
||||||
|
|
||||||
|
data object Byte : Type
|
||||||
|
data object Short : Type
|
||||||
|
data object Int : Type
|
||||||
|
data object Long : Type
|
||||||
|
|
||||||
|
data object UByte : Type
|
||||||
|
data object UShort : Type
|
||||||
|
data object UInt : Type
|
||||||
|
data object ULong : Type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A C-like wrapper around some Kotlin function.
|
||||||
|
* Abstracts away all nuances of Kotlin compiler ABI, making it possible
|
||||||
|
* to call Kotlin code from other environments.
|
||||||
|
*/
|
||||||
|
class FunctionBridge(
|
||||||
|
val kotlinFunctionBridge: KotlinFunctionBridge,
|
||||||
|
val cDeclarationBridge: CFunctionBridge,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C part of [FunctionBridgeImpl].
|
||||||
|
*
|
||||||
|
* @param lines with function declaration.
|
||||||
|
* @param headerDependencies required headers.
|
||||||
|
*/
|
||||||
|
class CFunctionBridge(
|
||||||
|
val lines: List<String>,
|
||||||
|
val headerDependencies: List<String>,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kotlin part of [FunctionBridgeImpl].
|
||||||
|
*
|
||||||
|
* @param lines definition of Kotlin bridge.
|
||||||
|
* @param packageDependencies required packages to make sources compile.
|
||||||
|
*/
|
||||||
|
class KotlinFunctionBridge(
|
||||||
|
val lines: List<String>,
|
||||||
|
val packageDependencies: List<String>,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates [FunctionBridge] that binds SIR function to its Kotlin origin.
|
||||||
|
*/
|
||||||
|
interface BridgeGenerator {
|
||||||
|
fun generate(request: BridgeRequest): FunctionBridge
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A common interface for classes that serialize [FunctionBridge] in some form.
|
||||||
|
*/
|
||||||
|
interface BridgePrinter {
|
||||||
|
/**
|
||||||
|
* Populate printer with an additional [bridge].
|
||||||
|
*/
|
||||||
|
fun add(bridge: FunctionBridge)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outputs the aggregated result.
|
||||||
|
*/
|
||||||
|
fun print(): Sequence<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createBridgeGenerator(): BridgeGenerator =
|
||||||
|
BridgeGeneratorImpl()
|
||||||
|
|
||||||
|
fun createCBridgePrinter(): BridgePrinter =
|
||||||
|
CBridgePrinter()
|
||||||
|
|
||||||
|
fun createKotlinBridgePrinter(): BridgePrinter =
|
||||||
|
KotlinBridgePrinter()
|
||||||
|
|
||||||
+140
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.sir.bridge.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.sir.bridge.*
|
||||||
|
|
||||||
|
private const val exportAnnotationFqName = "kotlin.native.internal.ExportForCppRuntime"
|
||||||
|
private const val stdintHeader = "stdint.h"
|
||||||
|
|
||||||
|
internal class BridgeGeneratorImpl : BridgeGenerator {
|
||||||
|
override fun generate(request: BridgeRequest): FunctionBridge {
|
||||||
|
|
||||||
|
val (kotlinReturnType, cReturnType) = bridgeType(request.returnType)
|
||||||
|
val parameterBridges = request.parameters.map { bridgeParameter(it) }
|
||||||
|
|
||||||
|
val cDeclaration = createCDeclaration(request.bridgeName, cReturnType, parameterBridges.map { it.c })
|
||||||
|
val kotlinBridge = createKotlinBridge(request.bridgeName, request.fqName, kotlinReturnType, parameterBridges.map { it.kotlin })
|
||||||
|
return FunctionBridge(
|
||||||
|
KotlinFunctionBridge(kotlinBridge, listOf(exportAnnotationFqName)),
|
||||||
|
CFunctionBridge(cDeclaration, listOf(stdintHeader))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createKotlinBridge(
|
||||||
|
bridgeName: String,
|
||||||
|
functionFqName: List<String>,
|
||||||
|
returnType: KotlinType,
|
||||||
|
parameterBridges: List<KotlinBridgeParameter>
|
||||||
|
): List<String> {
|
||||||
|
val declaration = createKotlinDeclarationSignature(bridgeName, returnType, parameterBridges)
|
||||||
|
val annotation = "@${exportAnnotationFqName.substringAfterLast('.')}(\"${bridgeName}\")"
|
||||||
|
val resultName = "result"
|
||||||
|
val callSite = createCallSite(functionFqName, parameterBridges.map { it.name }, resultName)
|
||||||
|
return """
|
||||||
|
$annotation
|
||||||
|
$declaration {
|
||||||
|
$callSite
|
||||||
|
return $resultName
|
||||||
|
}
|
||||||
|
""".trimIndent().lines()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCallSite(functionFqName: List<String>, parameterNames: List<String>, resultName: String): String {
|
||||||
|
val functionCall = "${functionFqName.joinToString(separator = ".")}(${parameterNames.joinToString(", ")})"
|
||||||
|
return "val $resultName = $functionCall"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createKotlinDeclarationSignature(bridgeName: String, returnType: KotlinType, parameters: List<KotlinBridgeParameter>): String {
|
||||||
|
return "public fun $bridgeName(${
|
||||||
|
parameters.joinToString(
|
||||||
|
separator = ", ",
|
||||||
|
transform = { "${it.name}: ${it.type.repr}" }
|
||||||
|
)
|
||||||
|
}): ${returnType.repr}"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCDeclaration(bridgeName: String, returnType: CType, parameters: List<CBridgeParameter>): List<String> {
|
||||||
|
val cParameters = parameters.joinToString(separator = ", ", transform = { "${it.type.repr} ${it.name}" })
|
||||||
|
val declaration = "${returnType.repr} $bridgeName($cParameters);"
|
||||||
|
return listOf(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun bridgeType(type: BridgeRequest.Type): Pair<KotlinType, CType> {
|
||||||
|
return when (type) {
|
||||||
|
BridgeRequest.Type.Boolean -> (KotlinType.Boolean to CType.Bool)
|
||||||
|
|
||||||
|
BridgeRequest.Type.Byte -> (KotlinType.Byte to CType.Int8)
|
||||||
|
BridgeRequest.Type.Int -> (KotlinType.Int to CType.Int32)
|
||||||
|
BridgeRequest.Type.Long -> (KotlinType.Long to CType.Int64)
|
||||||
|
BridgeRequest.Type.Short -> (KotlinType.Short to CType.Int16)
|
||||||
|
|
||||||
|
BridgeRequest.Type.UByte -> (KotlinType.UByte to CType.UInt8)
|
||||||
|
BridgeRequest.Type.UInt -> (KotlinType.UInt to CType.UInt32)
|
||||||
|
BridgeRequest.Type.ULong -> (KotlinType.ULong to CType.UInt64)
|
||||||
|
BridgeRequest.Type.UShort -> (KotlinType.UShort to CType.UInt16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bridgeParameter(request: BridgeRequest.Parameter): BridgeParameter {
|
||||||
|
val bridgeParameterName = createBridgeParameterName(request.name)
|
||||||
|
val (kotlinType, cType) = bridgeType(request.type)
|
||||||
|
return BridgeParameter(
|
||||||
|
KotlinBridgeParameter(bridgeParameterName, kotlinType),
|
||||||
|
CBridgeParameter(bridgeParameterName, cType)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createBridgeParameterName(kotlinName: String): String {
|
||||||
|
// TODO: Post-process because C has stricter naming conventions.
|
||||||
|
return kotlinName
|
||||||
|
}
|
||||||
|
|
||||||
|
internal data class BridgeParameter(
|
||||||
|
val kotlin: KotlinBridgeParameter,
|
||||||
|
val c: CBridgeParameter,
|
||||||
|
)
|
||||||
|
|
||||||
|
internal data class CBridgeParameter(
|
||||||
|
val name: String,
|
||||||
|
val type: CType,
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class CType(val repr: String) {
|
||||||
|
Bool("_Bool"),
|
||||||
|
|
||||||
|
Int8("int8_t"),
|
||||||
|
Int16("int16_t"),
|
||||||
|
Int32("int32_t"),
|
||||||
|
Int64("int64_t"),
|
||||||
|
|
||||||
|
UInt8("uint8_t"),
|
||||||
|
UInt16("uint16_t"),
|
||||||
|
UInt32("uint32_t"),
|
||||||
|
UInt64("uint64_t"),
|
||||||
|
}
|
||||||
|
|
||||||
|
internal data class KotlinBridgeParameter(
|
||||||
|
val name: String,
|
||||||
|
val type: KotlinType,
|
||||||
|
)
|
||||||
|
|
||||||
|
internal enum class KotlinType(val repr: String) {
|
||||||
|
Boolean("Boolean"),
|
||||||
|
|
||||||
|
Byte("Byte"),
|
||||||
|
Short("Short"),
|
||||||
|
Int("Int"),
|
||||||
|
Long("Long"),
|
||||||
|
|
||||||
|
UByte("UByte"),
|
||||||
|
UShort("UShort"),
|
||||||
|
UInt("UInt"),
|
||||||
|
ULong("ULong"),
|
||||||
|
}
|
||||||
|
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.sir.bridge.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.sir.bridge.BridgePrinter
|
||||||
|
import org.jetbrains.kotlin.sir.bridge.FunctionBridge
|
||||||
|
|
||||||
|
internal class CBridgePrinter : BridgePrinter {
|
||||||
|
|
||||||
|
private val includes = mutableSetOf<String>()
|
||||||
|
|
||||||
|
private val functions = mutableListOf<List<String>>()
|
||||||
|
|
||||||
|
override fun add(bridge: FunctionBridge) {
|
||||||
|
functions += bridge.cDeclarationBridge.lines
|
||||||
|
includes += bridge.cDeclarationBridge.headerDependencies
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun print(): Sequence<String> = sequence {
|
||||||
|
if (includes.isNotEmpty()) {
|
||||||
|
includes.forEach {
|
||||||
|
yield("#include <$it>")
|
||||||
|
}
|
||||||
|
yield("")
|
||||||
|
}
|
||||||
|
functions.forEach { functionLines ->
|
||||||
|
yieldAll(functionLines)
|
||||||
|
yield("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.sir.bridge.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.sir.bridge.BridgePrinter
|
||||||
|
import org.jetbrains.kotlin.sir.bridge.FunctionBridge
|
||||||
|
|
||||||
|
internal class KotlinBridgePrinter : BridgePrinter {
|
||||||
|
|
||||||
|
private val imports = mutableSetOf<String>()
|
||||||
|
private val functions = mutableListOf<List<String>>()
|
||||||
|
|
||||||
|
override fun add(bridge: FunctionBridge) {
|
||||||
|
functions += bridge.kotlinFunctionBridge.lines
|
||||||
|
imports += bridge.kotlinFunctionBridge.packageDependencies
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun print(): Sequence<String> = sequence {
|
||||||
|
if (imports.isNotEmpty()) {
|
||||||
|
imports.forEach {
|
||||||
|
yield("import $it")
|
||||||
|
}
|
||||||
|
yield("")
|
||||||
|
}
|
||||||
|
functions.forEach { functionLines ->
|
||||||
|
yieldAll(functionLines)
|
||||||
|
yield("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.sir.bridge
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataFile
|
||||||
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
abstract class AbstractKotlinSirBridgeTest {
|
||||||
|
protected fun runTest(@TestDataFile testPath: String) {
|
||||||
|
val testPathFull = File(KtTestUtil.getHomeDirectory()).resolve(testPath)
|
||||||
|
val expectedKotlinSrc = testPathFull.resolve("expected.kt")
|
||||||
|
val expectedCHeader = testPathFull.resolve("expected.h")
|
||||||
|
|
||||||
|
val requests = parseRequestsFromTestDir(testPathFull)
|
||||||
|
|
||||||
|
val generator = createBridgeGenerator()
|
||||||
|
val kotlinBridgePrinter = createKotlinBridgePrinter()
|
||||||
|
val cBridgePrinter = createCBridgePrinter()
|
||||||
|
|
||||||
|
requests.forEach { request ->
|
||||||
|
val bridge = generator.generate(request)
|
||||||
|
kotlinBridgePrinter.add(bridge)
|
||||||
|
cBridgePrinter.add(bridge)
|
||||||
|
}
|
||||||
|
|
||||||
|
val actualKotlinSrc = kotlinBridgePrinter.print().joinToString(separator = lineSeparator)
|
||||||
|
val actualHeader = cBridgePrinter.print().joinToString(separator = lineSeparator)
|
||||||
|
|
||||||
|
JUnit5Assertions.assertEqualsToFile(expectedCHeader, actualHeader)
|
||||||
|
JUnit5Assertions.assertEqualsToFile(expectedKotlinSrc, actualKotlinSrc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val lineSeparator: String = System.getProperty("line.separator")
|
||||||
|
|
||||||
|
private fun parseRequestsFromTestDir(testDir: File): List<BridgeRequest> =
|
||||||
|
testDir.listFiles()
|
||||||
|
?.filter { it.extension == "properties" && it.name.startsWith("request") }
|
||||||
|
?.map { readRequestFromFile(it) }
|
||||||
|
?.sortedBy { it.bridgeName }
|
||||||
|
?: emptyList()
|
||||||
|
|
||||||
|
private fun parseType(typeName: String): BridgeRequest.Type {
|
||||||
|
return when (typeName.lowercase()) {
|
||||||
|
"boolean" -> BridgeRequest.Type.Boolean
|
||||||
|
|
||||||
|
"byte" -> BridgeRequest.Type.Byte
|
||||||
|
"short" -> BridgeRequest.Type.Short
|
||||||
|
"int" -> BridgeRequest.Type.Int
|
||||||
|
"long" -> BridgeRequest.Type.Long
|
||||||
|
|
||||||
|
"ubyte" -> BridgeRequest.Type.UByte
|
||||||
|
"ushort" -> BridgeRequest.Type.UShort
|
||||||
|
"uint" -> BridgeRequest.Type.UInt
|
||||||
|
"ulong" -> BridgeRequest.Type.ULong
|
||||||
|
|
||||||
|
else -> error("Unknown type: $typeName")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun readRequestFromFile(file: File): BridgeRequest {
|
||||||
|
val properties = Properties()
|
||||||
|
file.bufferedReader().use(properties::load)
|
||||||
|
val fqName = properties.getProperty("fqName").split('.')
|
||||||
|
val bridgeName = properties.getProperty("bridgeName")
|
||||||
|
val returnType = parseType(properties.getProperty("returnType"))
|
||||||
|
val parameters = properties.getProperty("parameters").let { parametersString ->
|
||||||
|
when {
|
||||||
|
parametersString.isNullOrEmpty() -> emptyList()
|
||||||
|
else -> parametersString.split(Regex("\\s+"))
|
||||||
|
}.map {
|
||||||
|
BridgeRequest.Parameter(
|
||||||
|
name = it.substringBefore(':'),
|
||||||
|
type = parseType(it.substringAfter(':'))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BridgeRequest(fqName, bridgeName, parameters, returnType)
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int32_t a_b_bar_bridge(int32_t param1, int64_t param2);
|
||||||
|
|
||||||
|
_Bool a_b_foo_bridge(int32_t param1, int64_t param2);
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import kotlin.native.internal.ExportForCppRuntime
|
||||||
|
|
||||||
|
@ExportForCppRuntime("a_b_bar_bridge")
|
||||||
|
public fun a_b_bar_bridge(param1: Int, param2: Long): Int {
|
||||||
|
val result = a.b.bar(param1, param2)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime("a_b_foo_bridge")
|
||||||
|
public fun a_b_foo_bridge(param1: Int, param2: Long): Boolean {
|
||||||
|
val result = a.b.foo(param1, param2)
|
||||||
|
return result
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fqName=a.b.foo
|
||||||
|
bridgeName=a_b_foo_bridge
|
||||||
|
parameters=param1:int param2:long
|
||||||
|
returnType=boolean
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fqName=a.b.bar
|
||||||
|
bridgeName=a_b_bar_bridge
|
||||||
|
parameters=param1:int param2:long
|
||||||
|
returnType=int
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int32_t a(int8_t p0, int16_t p1, int32_t p2, int64_t p3);
|
||||||
|
|
||||||
|
uint32_t b(uint8_t p0, uint16_t p1, uint32_t p2, uint64_t p3);
|
||||||
|
|
||||||
|
_Bool c(_Bool p0);
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import kotlin.native.internal.ExportForCppRuntime
|
||||||
|
|
||||||
|
@ExportForCppRuntime("a")
|
||||||
|
public fun a(p0: Byte, p1: Short, p2: Int, p3: Long): Int {
|
||||||
|
val result = pkg.a(p0, p1, p2, p3)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime("b")
|
||||||
|
public fun b(p0: UByte, p1: UShort, p2: UInt, p3: ULong): UInt {
|
||||||
|
val result = pkg.b(p0, p1, p2, p3)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime("c")
|
||||||
|
public fun c(p0: Boolean): Boolean {
|
||||||
|
val result = pkg.c(p0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fqName=pkg.a
|
||||||
|
bridgeName=a
|
||||||
|
returnType=int
|
||||||
|
parameters=p0:byte p1:short p2:int p3:long
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fqName=pkg.b
|
||||||
|
bridgeName=b
|
||||||
|
returnType=uint
|
||||||
|
parameters=p0:ubyte p1:ushort p2:uint p3:ulong
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fqName=pkg.c
|
||||||
|
bridgeName=c
|
||||||
|
returnType=boolean
|
||||||
|
parameters=p0:boolean
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
_Bool a_bridge();
|
||||||
|
|
||||||
|
int16_t b_bridge();
|
||||||
|
|
||||||
|
int32_t c_bridge();
|
||||||
|
|
||||||
|
int64_t d_bridge();
|
||||||
|
|
||||||
|
int8_t e_bridge();
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import kotlin.native.internal.ExportForCppRuntime
|
||||||
|
|
||||||
|
@ExportForCppRuntime("a_bridge")
|
||||||
|
public fun a_bridge(): Boolean {
|
||||||
|
val result = a()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime("b_bridge")
|
||||||
|
public fun b_bridge(): Short {
|
||||||
|
val result = b()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime("c_bridge")
|
||||||
|
public fun c_bridge(): Int {
|
||||||
|
val result = c()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime("d_bridge")
|
||||||
|
public fun d_bridge(): Long {
|
||||||
|
val result = d()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime("e_bridge")
|
||||||
|
public fun e_bridge(): Byte {
|
||||||
|
val result = e()
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fqName=a
|
||||||
|
bridgeName=a_bridge
|
||||||
|
returnType=boolean
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fqName=b
|
||||||
|
bridgeName=b_bridge
|
||||||
|
returnType=short
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fqName=c
|
||||||
|
bridgeName=c_bridge
|
||||||
|
returnType=int
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fqName=d
|
||||||
|
bridgeName=d_bridge
|
||||||
|
returnType=long
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fqName=e
|
||||||
|
bridgeName=e_bridge
|
||||||
|
returnType=byte
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int32_t a_b_foo_bridge(int32_t param1, int64_t param2);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import kotlin.native.internal.ExportForCppRuntime
|
||||||
|
|
||||||
|
@ExportForCppRuntime("a_b_foo_bridge")
|
||||||
|
public fun a_b_foo_bridge(param1: Int, param2: Long): Int {
|
||||||
|
val result = a.b.foo(param1, param2)
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fqName=a.b.foo
|
||||||
|
bridgeName=a_b_foo_bridge
|
||||||
|
parameters=param1:int param2:long
|
||||||
|
returnType=int
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint16_t b_bridge();
|
||||||
|
|
||||||
|
uint32_t c_bridge();
|
||||||
|
|
||||||
|
uint64_t d_bridge();
|
||||||
|
|
||||||
|
uint8_t e_bridge();
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import kotlin.native.internal.ExportForCppRuntime
|
||||||
|
|
||||||
|
@ExportForCppRuntime("b_bridge")
|
||||||
|
public fun b_bridge(): UShort {
|
||||||
|
val result = b()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime("c_bridge")
|
||||||
|
public fun c_bridge(): UInt {
|
||||||
|
val result = c()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime("d_bridge")
|
||||||
|
public fun d_bridge(): ULong {
|
||||||
|
val result = d()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime("e_bridge")
|
||||||
|
public fun e_bridge(): UByte {
|
||||||
|
val result = e()
|
||||||
|
return result
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fqName=b
|
||||||
|
bridgeName=b_bridge
|
||||||
|
returnType=ushort
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fqName=c
|
||||||
|
bridgeName=c_bridge
|
||||||
|
returnType=uint
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fqName=d
|
||||||
|
bridgeName=d_bridge
|
||||||
|
returnType=ulong
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fqName=e
|
||||||
|
bridgeName=e_bridge
|
||||||
|
returnType=ubyte
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.sir.bridge;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.native.swift.sir.analysis.api.GenerateSirAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("native/swift/sir-compiler-bridge/testData")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class SirCompilerBridgeTestGenerated extends AbstractKotlinSirBridgeTest {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInTestData() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/swift/sir-compiler-bridge/testData"), Pattern.compile("^([^\\.]+)$"), null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multiple_requests")
|
||||||
|
public void testMultiple_requests() throws Exception {
|
||||||
|
runTest("native/swift/sir-compiler-bridge/testData/multiple_requests/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smoke0")
|
||||||
|
public void testSmoke0() throws Exception {
|
||||||
|
runTest("native/swift/sir-compiler-bridge/testData/smoke0/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("primitive_types")
|
||||||
|
public void testPrimitive_types() throws Exception {
|
||||||
|
runTest("native/swift/sir-compiler-bridge/testData/primitive_types/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("unsigned_primitive_types")
|
||||||
|
public void testUnsigned_primitive_types() throws Exception {
|
||||||
|
runTest("native/swift/sir-compiler-bridge/testData/unsigned_primitive_types/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("primitive_parameters")
|
||||||
|
public void testPrimitive_parameters() throws Exception {
|
||||||
|
runTest("native/swift/sir-compiler-bridge/testData/primitive_parameters/");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -401,6 +401,7 @@ include ":plugins:compose-compiler-plugin:compiler",
|
|||||||
include ":native:swift:sir",
|
include ":native:swift:sir",
|
||||||
":native:swift:sir-passes",
|
":native:swift:sir-passes",
|
||||||
":native:swift:sir-analysis-api",
|
":native:swift:sir-analysis-api",
|
||||||
|
":native:swift:sir-compiler-bridge",
|
||||||
":generators:sir-analysis-api-generator"
|
":generators:sir-analysis-api-generator"
|
||||||
|
|
||||||
void intellij(String imlPath) {
|
void intellij(String imlPath) {
|
||||||
|
|||||||
Reference in New Issue
Block a user