Skip to content

[JExtract] Introduce SwiftKnownTypes #271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ enum CDeclToCLoweringError: Error {
case invalidFunctionConvention(SwiftFunctionType)
}

extension KnownStandardLibraryType {
extension SwiftStandardLibraryTypeKind {
/// Determine the primitive C type that corresponds to this C standard
/// library type, if there is one.
var primitiveCType: CType? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ extension FFMSwift2JavaGenerator {

/// Responsible for lowering Swift API to C API.
struct CdeclLowering {
var swiftStdlibTypes: SwiftStandardLibraryTypes
var knownTypes: SwiftKnownTypes

init(swiftStdlibTypes: SwiftStandardLibraryTypeDecls) {
self.knownTypes = SwiftKnownTypes(decls: swiftStdlibTypes)
}

/// Lower the given Swift function signature to a Swift @_cdecl function signature,
/// which is C compatible, and the corresponding Java method signature.
Expand Down Expand Up @@ -149,11 +153,7 @@ struct CdeclLowering {
SwiftParameter(
convention: .byValue,
parameterName: parameterName,
type: .nominal(
SwiftNominalType(
nominalTypeDecl: swiftStdlibTypes[.unsafeRawPointer]
)
)
type: knownTypes.unsafeRawPointer
)
],
conversion: .unsafeCastPointer(.placeholder, swiftType: instanceType)
Expand All @@ -173,10 +173,14 @@ struct CdeclLowering {
// Typed pointers are mapped down to their raw forms in cdecl entry
// points. These can be passed through directly.
let isMutable = knownType == .unsafeMutablePointer
let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer]
let paramType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal))
return LoweredParameter(
cdeclParameters: [SwiftParameter(convention: .byValue, parameterName: parameterName, type: paramType)],
cdeclParameters: [
SwiftParameter(
convention: .byValue,
parameterName: parameterName,
type: isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer
)
],
conversion: .typedPointer(.placeholder, swiftType: genericArgs[0])
)

Expand All @@ -186,17 +190,15 @@ struct CdeclLowering {
}
// Typed pointers are lowered to (raw-pointer, count) pair.
let isMutable = knownType == .unsafeMutableBufferPointer
let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer]

return LoweredParameter(
cdeclParameters: [
SwiftParameter(
convention: .byValue, parameterName: "\(parameterName)_pointer",
type: .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal))
type: isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer
),
SwiftParameter(
convention: .byValue, parameterName: "\(parameterName)_count",
type: .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int]))
type: knownTypes.int
),
], conversion: .initialize(
type,
Expand All @@ -221,12 +223,7 @@ struct CdeclLowering {
SwiftParameter(
convention: .byValue,
parameterName: parameterName,
type: .nominal(SwiftNominalType(
nominalTypeDecl: swiftStdlibTypes.unsafePointerDecl,
genericArguments: [
.nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int8]))
]
))
type: knownTypes.unsafePointer(knownTypes.int8)
)
],
conversion: .initialize(type, arguments: [
Expand All @@ -243,15 +240,12 @@ struct CdeclLowering {

// Arbitrary nominal types are passed-in as an pointer.
let isMutable = (convention == .inout)
let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer]
let parameterType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal))

return LoweredParameter(
cdeclParameters: [
SwiftParameter(
convention: .byValue,
parameterName: parameterName,
type: parameterType
type: isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer
),
],
conversion: .pointee(.typedPointer(.placeholder, swiftType: type))
Expand Down Expand Up @@ -352,12 +346,10 @@ struct CdeclLowering {
switch type {
case .metatype:
// 'unsafeBitcast(<result>, to: UnsafeRawPointer.self)' as 'UnsafeRawPointer'

let resultType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.unsafeRawPointer]))
return LoweredResult(
cdeclResultType: resultType,
cdeclResultType: knownTypes.unsafeRawPointer,
cdeclOutParameters: [],
conversion: .unsafeCastPointer(.placeholder, swiftType: resultType)
conversion: .unsafeCastPointer(.placeholder, swiftType: knownTypes.unsafeRawPointer)
)

case .nominal(let nominal):
Expand All @@ -367,8 +359,7 @@ struct CdeclLowering {
case .unsafePointer, .unsafeMutablePointer:
// Typed pointers are lowered to corresponding raw forms.
let isMutable = knownType == .unsafeMutablePointer
let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer]
let resultType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal))
let resultType: SwiftType = isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer
return LoweredResult(
cdeclResultType: resultType,
cdeclOutParameters: [],
Expand All @@ -378,11 +369,10 @@ struct CdeclLowering {
case .unsafeBufferPointer, .unsafeMutableBufferPointer:
// Typed pointers are lowered to (raw-pointer, count) pair.
let isMutable = knownType == .unsafeMutableBufferPointer
let rawPointerType = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer]
return try lowerResult(
.tuple([
.nominal(SwiftNominalType(nominalTypeDecl: rawPointerType)),
.nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int]))
isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer,
knownTypes.int
]),
outParameterName: outParameterName
)
Expand All @@ -407,7 +397,7 @@ struct CdeclLowering {
SwiftParameter(
convention: .byValue,
parameterName: outParameterName,
type: .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.unsafeMutableRawPointer]))
type: knownTypes.unsafeMutableRawPointer
)
],
conversion: .populatePointer(name: outParameterName, assumingType: type, to: .placeholder)
Expand All @@ -431,10 +421,7 @@ struct CdeclLowering {
let parameter = SwiftParameter(
convention: .byValue,
parameterName: parameterName,
type: .nominal(SwiftNominalType(
nominalTypeDecl: swiftStdlibTypes.unsafeMutablePointerDecl,
genericArguments: [lowered.cdeclResultType]
))
type: knownTypes.unsafeMutablePointer(lowered.cdeclResultType)
)
parameters.append(parameter)
conversions.append(.populatePointer(
Expand Down Expand Up @@ -551,7 +538,7 @@ extension LoweredFunctionSignature {
cName: String,
swiftAPIName: String,
as apiKind: SwiftAPIKind,
stdlibTypes: SwiftStandardLibraryTypes
stdlibTypes: SwiftStandardLibraryTypeDecls
) -> FunctionDeclSyntax {

let cdeclParams = allLoweredParameters.map(\.description).joined(separator: ", ")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ extension TranslatedFunctionSignature {
}

struct JavaTranslation {
var swiftStdlibTypes: SwiftStandardLibraryTypes
var swiftStdlibTypes: SwiftStandardLibraryTypeDecls

func translate(
_ decl: ImportedFunc
Expand Down
4 changes: 2 additions & 2 deletions Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator {
let javaPackage: String
let swiftOutputDirectory: String
let javaOutputDirectory: String
let swiftStdlibTypes: SwiftStandardLibraryTypes
let swiftStdlibTypes: SwiftStandardLibraryTypeDecls
let symbolTable: SwiftSymbolTable

var javaPackagePath: String {
Expand All @@ -49,7 +49,7 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator {
self.swiftOutputDirectory = swiftOutputDirectory
self.javaOutputDirectory = javaOutputDirectory
self.symbolTable = translator.symbolTable
self.swiftStdlibTypes = translator.swiftStdlibTypes
self.swiftStdlibTypes = translator.swiftStdlibTypeDecls
}

func generate() throws {
Expand Down
4 changes: 2 additions & 2 deletions Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public final class Swift2JavaTranslator {
/// type representation.
package var importedTypes: [String: ImportedNominalType] = [:]

package var swiftStdlibTypes: SwiftStandardLibraryTypes
package var swiftStdlibTypeDecls: SwiftStandardLibraryTypeDecls

package let symbolTable: SwiftSymbolTable

Expand All @@ -59,7 +59,7 @@ public final class Swift2JavaTranslator {

// Create a mock of the Swift standard library.
var parsedSwiftModule = SwiftParsedModuleSymbolTable(moduleName: "Swift")
self.swiftStdlibTypes = SwiftStandardLibraryTypes(into: &parsedSwiftModule)
self.swiftStdlibTypeDecls = SwiftStandardLibraryTypeDecls(into: &parsedSwiftModule)
self.symbolTable.importedModules.append(parsedSwiftModule.symbolTable)
}
}
Expand Down
73 changes: 73 additions & 0 deletions Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

struct SwiftKnownTypes {
private let decls: SwiftStandardLibraryTypeDecls

init(decls: SwiftStandardLibraryTypeDecls) {
self.decls = decls
}

var bool: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.bool])) }
var int: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.int])) }
var uint: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.uint])) }
var int8: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.int8])) }
var uint8: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.uint8])) }
var int16: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.int16])) }
var uint16: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.uint16])) }
var int32: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.int32])) }
var uint32: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.uint32])) }
var int64: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.int64])) }
var uint64: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.uint64])) }
var float: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.float])) }
var double: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.double])) }
var unsafeRawPointer: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.unsafeRawPointer])) }
var unsafeMutableRawPointer: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.unsafeMutableRawPointer])) }

func unsafePointer(_ pointeeType: SwiftType) -> SwiftType {
.nominal(
SwiftNominalType(
nominalTypeDecl: decls.unsafePointerDecl,
genericArguments: [pointeeType]
)
)
}

func unsafeMutablePointer(_ pointeeType: SwiftType) -> SwiftType {
.nominal(
SwiftNominalType(
nominalTypeDecl: decls.unsafeMutablePointerDecl,
genericArguments: [pointeeType]
)
)
}

func unsafeBufferPointer(_ elementType: SwiftType) -> SwiftType {
.nominal(
SwiftNominalType(
nominalTypeDecl: decls.unsafeBufferPointerDecl,
genericArguments: [elementType]
)
)
}

func unsafeMutableBufferPointer(_ elementType: SwiftType) -> SwiftType {
.nominal(
SwiftNominalType(
nominalTypeDecl: decls.unsafeMutableBufferPointerDecl,
genericArguments: [elementType]
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ package class SwiftNominalTypeDeclaration {

/// Identify this nominal declaration as one of the known standard library
/// types, like 'Swift.Int[.
lazy var knownStandardLibraryType: KnownStandardLibraryType? = {
lazy var knownStandardLibraryType: SwiftStandardLibraryTypeKind? = {
self.computeKnownStandardLibraryType()
}()

Expand Down Expand Up @@ -80,12 +80,12 @@ package class SwiftNominalTypeDeclaration {

/// Determine the known standard library type for this nominal type
/// declaration.
private func computeKnownStandardLibraryType() -> KnownStandardLibraryType? {
private func computeKnownStandardLibraryType() -> SwiftStandardLibraryTypeKind? {
if parent != nil || moduleName != "Swift" {
return nil
}

return KnownStandardLibraryType(typeNameInSwiftModule: name)
return SwiftStandardLibraryTypeKind(typeNameInSwiftModule: name)
}

package var qualifiedName: String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import SwiftSyntax

enum KnownStandardLibraryType: String, Hashable, CaseIterable {
enum SwiftStandardLibraryTypeKind: String, Hashable, CaseIterable {
case bool = "Bool"
case int = "Int"
case uint = "UInt"
Expand Down Expand Up @@ -60,7 +60,7 @@ enum KnownStandardLibraryType: String, Hashable, CaseIterable {

/// Captures many types from the Swift standard library in their most basic
/// forms, so that the translator can reason about them in source code.
public struct SwiftStandardLibraryTypes {
public struct SwiftStandardLibraryTypeDecls {
// Swift.UnsafePointer<Element>
let unsafePointerDecl: SwiftNominalTypeDeclaration

Expand All @@ -74,16 +74,16 @@ public struct SwiftStandardLibraryTypes {
let unsafeMutableBufferPointerDecl: SwiftNominalTypeDeclaration

/// Mapping from known standard library types to their nominal type declaration.
let knownTypeToNominal: [KnownStandardLibraryType: SwiftNominalTypeDeclaration]
let knownTypeToNominal: [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration]

/// Mapping from nominal type declarations to known types.
let nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: KnownStandardLibraryType]
let nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind]

private static func recordKnownType(
_ type: KnownStandardLibraryType,
_ type: SwiftStandardLibraryTypeKind,
_ syntax: NominalTypeDeclSyntaxNode,
knownTypeToNominal: inout [KnownStandardLibraryType: SwiftNominalTypeDeclaration],
nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: KnownStandardLibraryType],
knownTypeToNominal: inout [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration],
nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind],
parsedModule: inout SwiftParsedModuleSymbolTable
) {
let nominalDecl = parsedModule.addNominalTypeDeclaration(syntax, parent: nil)
Expand All @@ -92,9 +92,9 @@ public struct SwiftStandardLibraryTypes {
}

private static func recordKnownNonGenericStruct(
_ type: KnownStandardLibraryType,
knownTypeToNominal: inout [KnownStandardLibraryType: SwiftNominalTypeDeclaration],
nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: KnownStandardLibraryType],
_ type: SwiftStandardLibraryTypeKind,
knownTypeToNominal: inout [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration],
nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind],
parsedModule: inout SwiftParsedModuleSymbolTable
) {
recordKnownType(
Expand Down Expand Up @@ -155,11 +155,11 @@ public struct SwiftStandardLibraryTypes {
parent: nil
)

var knownTypeToNominal: [KnownStandardLibraryType: SwiftNominalTypeDeclaration] = [:]
var nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: KnownStandardLibraryType] = [:]
var knownTypeToNominal: [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration] = [:]
var nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind] = [:]

// Handle all of the non-generic types at once.
for knownType in KnownStandardLibraryType.allCases {
for knownType in SwiftStandardLibraryTypeKind.allCases {
guard !knownType.isGeneric else {
continue
}
Expand All @@ -176,11 +176,11 @@ public struct SwiftStandardLibraryTypes {
self.nominalTypeDeclToKnownType = nominalTypeDeclToKnownType
}

subscript(knownType: KnownStandardLibraryType) -> SwiftNominalTypeDeclaration {
subscript(knownType: SwiftStandardLibraryTypeKind) -> SwiftNominalTypeDeclaration {
knownTypeToNominal[knownType]!
}

subscript(nominalType: SwiftNominalTypeDeclaration) -> KnownStandardLibraryType? {
subscript(nominalType: SwiftNominalTypeDeclaration) -> SwiftStandardLibraryTypeKind? {
nominalTypeDeclToKnownType[nominalType]
}
}
Loading