From 673689ee3d4022e21a5be5e08c31fcc30bdca1ec Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Fri, 13 Jun 2025 15:53:06 -0700 Subject: [PATCH] [JExtract] Introduce SwiftKnownTypes to construct stdlib types easily. Rename `SwiftStandardLibraryTypes` to `SwiftStandardLibraryTypeDecls` Rename `KnownStandardLibraryType` to `SwiftStandardLibraryTypeKind` --- .../FFM/CDeclLowering/CRepresentation.swift | 2 +- ...Swift2JavaGenerator+FunctionLowering.swift | 63 +++++++--------- ...MSwift2JavaGenerator+JavaTranslation.swift | 2 +- .../FFM/FFMSwift2JavaGenerator.swift | 4 +- .../Swift2JavaTranslator.swift | 4 +- .../SwiftTypes/SwiftKnownTypes.swift | 73 +++++++++++++++++++ .../SwiftNominalTypeDeclaration.swift | 6 +- ...ft => SwiftStandardLibraryTypeDecls.swift} | 30 ++++---- .../Asserts/LoweringAssertions.swift | 4 +- 9 files changed, 124 insertions(+), 64 deletions(-) create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift rename Sources/JExtractSwiftLib/SwiftTypes/{SwiftStandardLibraryTypes.swift => SwiftStandardLibraryTypeDecls.swift} (85%) diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift index e1a69d12..c52bf7db 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift @@ -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? { diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 02501dc5..061dc997 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -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. @@ -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) @@ -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]) ) @@ -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, @@ -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: [ @@ -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)) @@ -352,12 +346,10 @@ struct CdeclLowering { switch type { case .metatype: // 'unsafeBitcast(, 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): @@ -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: [], @@ -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 ) @@ -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) @@ -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( @@ -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: ", ") diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index c7e2338d..47616030 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -144,7 +144,7 @@ extension TranslatedFunctionSignature { } struct JavaTranslation { - var swiftStdlibTypes: SwiftStandardLibraryTypes + var swiftStdlibTypes: SwiftStandardLibraryTypeDecls func translate( _ decl: ImportedFunc diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 7cd0075b..036ee31e 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -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 { @@ -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 { diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index ace5f444..857a053a 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -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 @@ -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) } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift new file mode 100644 index 00000000..eaae18cd --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift @@ -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] + ) + ) + } +} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift index c8330126..29a287fe 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -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() }() @@ -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 { diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypes.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift similarity index 85% rename from Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypes.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift index 4b07c575..51e1adcf 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypes.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift @@ -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" @@ -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 let unsafePointerDecl: SwiftNominalTypeDeclaration @@ -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) @@ -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( @@ -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 } @@ -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] } } diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index 5dd28cc8..f017bc49 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -73,7 +73,7 @@ func assertLoweredFunction( cName: "c_\(swiftFunctionName)", swiftAPIName: swiftFunctionName, as: apiKind, - stdlibTypes: translator.swiftStdlibTypes + stdlibTypes: translator.swiftStdlibTypeDecls ) #expect( @@ -141,7 +141,7 @@ func assertLoweredVariableAccessor( cName: "c_\(swiftVariableName)", swiftAPIName: swiftVariableName, as: isSet ? .setter : .getter, - stdlibTypes: translator.swiftStdlibTypes + stdlibTypes: translator.swiftStdlibTypeDecls ) #expect(