[Swift Export] Update sir-compiler-bridge to use SIR

Now that SIR has finally landed in the repository, we can remove
unnecessary entities from the bridge generator.
This commit is contained in:
Sergey Bogolepov
2023-11-24 14:16:11 +01:00
committed by Space Team
parent a040954f68
commit 5eeb82bb6f
5 changed files with 69 additions and 58 deletions
@@ -7,6 +7,8 @@ description = "SIR to Kotlin bindings generator"
dependencies {
compileOnly(kotlinStdlib())
api(project(":native:swift:sir"))
testApi(platform(libs.junit.bom))
testRuntimeOnly(libs.junit.jupiter.engine)
testImplementation(libs.junit.jupiter.api)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.sir.bridge
import org.jetbrains.kotlin.sir.SirFunction
import org.jetbrains.kotlin.sir.bridge.impl.BridgeGeneratorImpl
import org.jetbrains.kotlin.sir.bridge.impl.CBridgePrinter
import org.jetbrains.kotlin.sir.bridge.impl.KotlinBridgePrinter
@@ -12,36 +13,14 @@ 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 function SIR function we are generating bridge for
* @param bridgeName C name of the bridge
*/
class BridgeRequest(
val fqName: List<String>,
val function: SirFunction,
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
}
}
val fqName: List<String>,
)
/**
* A C-like wrapper around some Kotlin function.
@@ -5,16 +5,19 @@
package org.jetbrains.kotlin.sir.bridge.impl
import org.jetbrains.kotlin.sir.SirNominalType
import org.jetbrains.kotlin.sir.SirParameter
import org.jetbrains.kotlin.sir.SirType
import org.jetbrains.kotlin.sir.bridge.*
import org.jetbrains.kotlin.sir.util.SirSwiftModule
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 (kotlinReturnType, cReturnType) = bridgeType(request.function.returnType)
val parameterBridges = request.function.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 })
@@ -29,7 +32,7 @@ private fun createKotlinBridge(
bridgeName: String,
functionFqName: List<String>,
returnType: KotlinType,
parameterBridges: List<KotlinBridgeParameter>
parameterBridges: List<KotlinBridgeParameter>,
): List<String> {
val declaration = createKotlinDeclarationSignature(bridgeName, returnType, parameterBridges)
val annotation = "@${exportAnnotationFqName.substringAfterLast('.')}(\"${bridgeName}\")"
@@ -65,25 +68,28 @@ private fun createCDeclaration(bridgeName: String, returnType: CType, parameters
}
private fun bridgeType(type: BridgeRequest.Type): Pair<KotlinType, CType> {
return when (type) {
BridgeRequest.Type.Boolean -> (KotlinType.Boolean to CType.Bool)
private fun bridgeType(type: SirType): Pair<KotlinType, CType> {
require(type is SirNominalType)
return when (type.type) {
SirSwiftModule.bool -> (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)
SirSwiftModule.int8 -> (KotlinType.Byte to CType.Int8)
SirSwiftModule.int32 -> (KotlinType.Int to CType.Int32)
SirSwiftModule.int64 -> (KotlinType.Long to CType.Int64)
SirSwiftModule.int16 -> (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)
SirSwiftModule.uint8 -> (KotlinType.UByte to CType.UInt8)
SirSwiftModule.uint32 -> (KotlinType.UInt to CType.UInt32)
SirSwiftModule.uint64 -> (KotlinType.ULong to CType.UInt64)
SirSwiftModule.uint16 -> (KotlinType.UShort to CType.UInt16)
else -> error("Unsupported type: ${type.type}")
}
}
private fun bridgeParameter(request: BridgeRequest.Parameter): BridgeParameter {
val bridgeParameterName = createBridgeParameterName(request.name)
val (kotlinType, cType) = bridgeType(request.type)
private fun bridgeParameter(parameter: SirParameter): BridgeParameter {
val bridgeParameterName = parameter.argumentName?.let(::createBridgeParameterName) ?: ""
val (kotlinType, cType) = bridgeType(parameter.type)
return BridgeParameter(
KotlinBridgeParameter(bridgeParameterName, kotlinType),
CBridgeParameter(bridgeParameterName, cType)
@@ -6,6 +6,11 @@
package org.jetbrains.kotlin.sir.bridge
import com.intellij.testFramework.TestDataFile
import org.jetbrains.kotlin.sir.SirNominalType
import org.jetbrains.kotlin.sir.SirParameter
import org.jetbrains.kotlin.sir.SirType
import org.jetbrains.kotlin.sir.builder.buildFunction
import org.jetbrains.kotlin.sir.util.SirSwiftModule
import org.jetbrains.kotlin.test.services.JUnit5Assertions
import org.jetbrains.kotlin.test.util.KtTestUtil
import java.io.File
@@ -46,22 +51,22 @@ private fun parseRequestsFromTestDir(testDir: File): List<BridgeRequest> =
?.sortedBy { it.bridgeName }
?: emptyList()
private fun parseType(typeName: String): BridgeRequest.Type {
private fun parseType(typeName: String): SirType {
return when (typeName.lowercase()) {
"boolean" -> BridgeRequest.Type.Boolean
"boolean" -> SirSwiftModule.bool
"byte" -> BridgeRequest.Type.Byte
"short" -> BridgeRequest.Type.Short
"int" -> BridgeRequest.Type.Int
"long" -> BridgeRequest.Type.Long
"byte" -> SirSwiftModule.int8
"short" -> SirSwiftModule.int16
"int" -> SirSwiftModule.int32
"long" -> SirSwiftModule.int64
"ubyte" -> BridgeRequest.Type.UByte
"ushort" -> BridgeRequest.Type.UShort
"uint" -> BridgeRequest.Type.UInt
"ulong" -> BridgeRequest.Type.ULong
"ubyte" -> SirSwiftModule.uint8
"ushort" -> SirSwiftModule.uint16
"uint" -> SirSwiftModule.uint32
"ulong" -> SirSwiftModule.uint64
else -> error("Unknown type: $typeName")
}
}.let { SirNominalType(it) }
}
private fun readRequestFromFile(file: File): BridgeRequest {
@@ -75,11 +80,16 @@ private fun readRequestFromFile(file: File): BridgeRequest {
parametersString.isNullOrEmpty() -> emptyList()
else -> parametersString.split(Regex("\\s+"))
}.map {
BridgeRequest.Parameter(
name = it.substringBefore(':'),
SirParameter(
argumentName = it.substringBefore(':'),
type = parseType(it.substringAfter(':'))
)
}
}
return BridgeRequest(fqName, bridgeName, parameters, returnType)
val function = buildFunction {
this.name = fqName.last()
this.returnType = returnType
this.parameters += parameters
}
return BridgeRequest(function, bridgeName, fqName)
}
@@ -21,20 +21,34 @@ object SirSwiftModule : SirModule() {
override val declarations: List<SirDeclaration> by lazy {
listOf(
bool,
int8,
int16,
int32,
int64,
uint8,
uint16,
uint32,
uint64,
double,
float,
)
}
val bool = primitive("Bool")
val int8 = primitive("Int8")
val int16 = primitive("Int16")
val int32 = primitive("Int32")
val int64 = primitive("Int64")
val uint8 = primitive("UInt8")
val uint16 = primitive("UInt16")
val uint32 = primitive("UInt32")
val uint64 = primitive("UInt64")
val double = primitive("Double")
val float = primitive("Float")