[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 { dependencies {
compileOnly(kotlinStdlib()) compileOnly(kotlinStdlib())
api(project(":native:swift:sir"))
testApi(platform(libs.junit.bom)) testApi(platform(libs.junit.bom))
testRuntimeOnly(libs.junit.jupiter.engine) testRuntimeOnly(libs.junit.jupiter.engine)
testImplementation(libs.junit.jupiter.api) testImplementation(libs.junit.jupiter.api)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.sir.bridge 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.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
@@ -12,36 +13,14 @@ import org.jetbrains.kotlin.sir.bridge.impl.KotlinBridgePrinter
/** /**
* Description of a Kotlin function for which we are creating the bridge. * Description of a Kotlin function for which we are creating the bridge.
* *
* TODO: Replace with SIR once KT-63266 is merged. * @param function SIR function we are generating bridge for
*
* @param fqName Fully qualified name of the function we are bridging.
* @param bridgeName C name of the bridge * @param bridgeName C name of the bridge
*/ */
class BridgeRequest( class BridgeRequest(
val fqName: List<String>, val function: SirFunction,
val bridgeName: String, val bridgeName: String,
val parameters: List<Parameter>, val fqName: List<String>,
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. * A C-like wrapper around some Kotlin function.
@@ -5,16 +5,19 @@
package org.jetbrains.kotlin.sir.bridge.impl 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.bridge.*
import org.jetbrains.kotlin.sir.util.SirSwiftModule
private const val exportAnnotationFqName = "kotlin.native.internal.ExportForCppRuntime" private const val exportAnnotationFqName = "kotlin.native.internal.ExportForCppRuntime"
private const val stdintHeader = "stdint.h" private const val stdintHeader = "stdint.h"
internal class BridgeGeneratorImpl : BridgeGenerator { internal class BridgeGeneratorImpl : BridgeGenerator {
override fun generate(request: BridgeRequest): FunctionBridge { override fun generate(request: BridgeRequest): FunctionBridge {
val (kotlinReturnType, cReturnType) = bridgeType(request.function.returnType)
val (kotlinReturnType, cReturnType) = bridgeType(request.returnType) val parameterBridges = request.function.parameters.map { bridgeParameter(it) }
val parameterBridges = request.parameters.map { bridgeParameter(it) }
val cDeclaration = createCDeclaration(request.bridgeName, cReturnType, parameterBridges.map { it.c }) val cDeclaration = createCDeclaration(request.bridgeName, cReturnType, parameterBridges.map { it.c })
val kotlinBridge = createKotlinBridge(request.bridgeName, request.fqName, kotlinReturnType, parameterBridges.map { it.kotlin }) val kotlinBridge = createKotlinBridge(request.bridgeName, request.fqName, kotlinReturnType, parameterBridges.map { it.kotlin })
@@ -29,7 +32,7 @@ private fun createKotlinBridge(
bridgeName: String, bridgeName: String,
functionFqName: List<String>, functionFqName: List<String>,
returnType: KotlinType, returnType: KotlinType,
parameterBridges: List<KotlinBridgeParameter> parameterBridges: List<KotlinBridgeParameter>,
): List<String> { ): List<String> {
val declaration = createKotlinDeclarationSignature(bridgeName, returnType, parameterBridges) val declaration = createKotlinDeclarationSignature(bridgeName, returnType, parameterBridges)
val annotation = "@${exportAnnotationFqName.substringAfterLast('.')}(\"${bridgeName}\")" 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> { private fun bridgeType(type: SirType): Pair<KotlinType, CType> {
return when (type) { require(type is SirNominalType)
BridgeRequest.Type.Boolean -> (KotlinType.Boolean to CType.Bool) return when (type.type) {
SirSwiftModule.bool -> (KotlinType.Boolean to CType.Bool)
BridgeRequest.Type.Byte -> (KotlinType.Byte to CType.Int8) SirSwiftModule.int8 -> (KotlinType.Byte to CType.Int8)
BridgeRequest.Type.Int -> (KotlinType.Int to CType.Int32) SirSwiftModule.int32 -> (KotlinType.Int to CType.Int32)
BridgeRequest.Type.Long -> (KotlinType.Long to CType.Int64) SirSwiftModule.int64 -> (KotlinType.Long to CType.Int64)
BridgeRequest.Type.Short -> (KotlinType.Short to CType.Int16) SirSwiftModule.int16 -> (KotlinType.Short to CType.Int16)
BridgeRequest.Type.UByte -> (KotlinType.UByte to CType.UInt8) SirSwiftModule.uint8 -> (KotlinType.UByte to CType.UInt8)
BridgeRequest.Type.UInt -> (KotlinType.UInt to CType.UInt32) SirSwiftModule.uint32 -> (KotlinType.UInt to CType.UInt32)
BridgeRequest.Type.ULong -> (KotlinType.ULong to CType.UInt64) SirSwiftModule.uint64 -> (KotlinType.ULong to CType.UInt64)
BridgeRequest.Type.UShort -> (KotlinType.UShort to CType.UInt16) SirSwiftModule.uint16 -> (KotlinType.UShort to CType.UInt16)
else -> error("Unsupported type: ${type.type}")
} }
} }
private fun bridgeParameter(request: BridgeRequest.Parameter): BridgeParameter { private fun bridgeParameter(parameter: SirParameter): BridgeParameter {
val bridgeParameterName = createBridgeParameterName(request.name) val bridgeParameterName = parameter.argumentName?.let(::createBridgeParameterName) ?: ""
val (kotlinType, cType) = bridgeType(request.type) val (kotlinType, cType) = bridgeType(parameter.type)
return BridgeParameter( return BridgeParameter(
KotlinBridgeParameter(bridgeParameterName, kotlinType), KotlinBridgeParameter(bridgeParameterName, kotlinType),
CBridgeParameter(bridgeParameterName, cType) CBridgeParameter(bridgeParameterName, cType)
@@ -6,6 +6,11 @@
package org.jetbrains.kotlin.sir.bridge package org.jetbrains.kotlin.sir.bridge
import com.intellij.testFramework.TestDataFile 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.services.JUnit5Assertions
import org.jetbrains.kotlin.test.util.KtTestUtil import org.jetbrains.kotlin.test.util.KtTestUtil
import java.io.File import java.io.File
@@ -46,22 +51,22 @@ private fun parseRequestsFromTestDir(testDir: File): List<BridgeRequest> =
?.sortedBy { it.bridgeName } ?.sortedBy { it.bridgeName }
?: emptyList() ?: emptyList()
private fun parseType(typeName: String): BridgeRequest.Type { private fun parseType(typeName: String): SirType {
return when (typeName.lowercase()) { return when (typeName.lowercase()) {
"boolean" -> BridgeRequest.Type.Boolean "boolean" -> SirSwiftModule.bool
"byte" -> BridgeRequest.Type.Byte "byte" -> SirSwiftModule.int8
"short" -> BridgeRequest.Type.Short "short" -> SirSwiftModule.int16
"int" -> BridgeRequest.Type.Int "int" -> SirSwiftModule.int32
"long" -> BridgeRequest.Type.Long "long" -> SirSwiftModule.int64
"ubyte" -> BridgeRequest.Type.UByte "ubyte" -> SirSwiftModule.uint8
"ushort" -> BridgeRequest.Type.UShort "ushort" -> SirSwiftModule.uint16
"uint" -> BridgeRequest.Type.UInt "uint" -> SirSwiftModule.uint32
"ulong" -> BridgeRequest.Type.ULong "ulong" -> SirSwiftModule.uint64
else -> error("Unknown type: $typeName") else -> error("Unknown type: $typeName")
} }.let { SirNominalType(it) }
} }
private fun readRequestFromFile(file: File): BridgeRequest { private fun readRequestFromFile(file: File): BridgeRequest {
@@ -75,11 +80,16 @@ private fun readRequestFromFile(file: File): BridgeRequest {
parametersString.isNullOrEmpty() -> emptyList() parametersString.isNullOrEmpty() -> emptyList()
else -> parametersString.split(Regex("\\s+")) else -> parametersString.split(Regex("\\s+"))
}.map { }.map {
BridgeRequest.Parameter( SirParameter(
name = it.substringBefore(':'), argumentName = it.substringBefore(':'),
type = parseType(it.substringAfter(':')) 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 { override val declarations: List<SirDeclaration> by lazy {
listOf( listOf(
bool, bool,
int8, int8,
int16, int16,
int32, int32,
int64, int64,
uint8,
uint16,
uint32,
uint64,
double, double,
float, float,
) )
} }
val bool = primitive("Bool") val bool = primitive("Bool")
val int8 = primitive("Int8") val int8 = primitive("Int8")
val int16 = primitive("Int16") val int16 = primitive("Int16")
val int32 = primitive("Int32") val int32 = primitive("Int32")
val int64 = primitive("Int64") 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 double = primitive("Double")
val float = primitive("Float") val float = primitive("Float")