Skip to content

Commit 4b96ba4

Browse files
committed
[JExtract] Prepare Foundation Data
1 parent e887a9f commit 4b96ba4

18 files changed

+479
-466
lines changed

Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ enum CDeclToCLoweringError: Error {
102102
case invalidFunctionConvention(SwiftFunctionType)
103103
}
104104

105-
extension SwiftStandardLibraryTypeKind {
105+
extension SwiftKnownTypeDeclKind {
106106
/// Determine the primitive C type that corresponds to this C standard
107107
/// library type, if there is one.
108108
var primitiveCType: CType? {
@@ -125,7 +125,7 @@ extension SwiftStandardLibraryTypeKind {
125125
.qualified(const: true, volatile: false, type: .void)
126126
)
127127
case .void: .void
128-
case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string:
128+
case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .data:
129129
nil
130130
}
131131
}

Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ extension FFMSwift2JavaGenerator {
2929
enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) },
3030
symbolTable: symbolTable
3131
)
32-
return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature)
32+
return try CdeclLowering(symbolTable: symbolTable).lowerFunctionSignature(signature)
3333
}
3434

3535
/// Lower the given initializer to a C-compatible entrypoint,
@@ -46,7 +46,7 @@ extension FFMSwift2JavaGenerator {
4646
symbolTable: symbolTable
4747
)
4848

49-
return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature)
49+
return try CdeclLowering(symbolTable: symbolTable).lowerFunctionSignature(signature)
5050
}
5151

5252
/// Lower the given variable decl to a C-compatible entrypoint,
@@ -69,16 +69,16 @@ extension FFMSwift2JavaGenerator {
6969
enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) },
7070
symbolTable: symbolTable
7171
)
72-
return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature)
72+
return try CdeclLowering(symbolTable: symbolTable).lowerFunctionSignature(signature)
7373
}
7474
}
7575

7676
/// Responsible for lowering Swift API to C API.
7777
struct CdeclLowering {
7878
var knownTypes: SwiftKnownTypes
7979

80-
init(swiftStdlibTypes: SwiftStandardLibraryTypeDecls) {
81-
self.knownTypes = SwiftKnownTypes(decls: swiftStdlibTypes)
80+
init(symbolTable: SwiftSymbolTable) {
81+
self.knownTypes = SwiftKnownTypes(symbolTable: symbolTable)
8282
}
8383

8484
/// Lower the given Swift function signature to a Swift @_cdecl function signature,
@@ -663,8 +663,7 @@ extension LoweredFunctionSignature {
663663
package func cdeclThunk(
664664
cName: String,
665665
swiftAPIName: String,
666-
as apiKind: SwiftAPIKind,
667-
stdlibTypes: SwiftStandardLibraryTypeDecls
666+
as apiKind: SwiftAPIKind
668667
) -> FunctionDeclSyntax {
669668

670669
let cdeclParams = allLoweredParameters.map(\.description).joined(separator: ", ")

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extension FFMSwift2JavaGenerator {
2424

2525
let translated: TranslatedFunctionDecl?
2626
do {
27-
let translation = JavaTranslation(swiftStdlibTypes: self.swiftStdlibTypes)
27+
let translation = JavaTranslation(symbolTable: self.symbolTable)
2828
translated = try translation.translate(decl)
2929
} catch {
3030
self.log.info("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)")
@@ -113,12 +113,12 @@ extension FFMSwift2JavaGenerator {
113113
}
114114

115115
struct JavaTranslation {
116-
var swiftStdlibTypes: SwiftStandardLibraryTypeDecls
116+
var symbolTable: SwiftSymbolTable
117117

118118
func translate(
119119
_ decl: ImportedFunc
120120
) throws -> TranslatedFunctionDecl {
121-
let lowering = CdeclLowering(swiftStdlibTypes: self.swiftStdlibTypes)
121+
let lowering = CdeclLowering(symbolTable: symbolTable)
122122
let loweredSignature = try lowering.lowerFunctionSignature(decl.functionSignature)
123123

124124
// Name.

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,7 @@ struct SwiftThunkTranslator {
196196
let thunkFunc = translated.loweredSignature.cdeclThunk(
197197
cName: thunkName,
198198
swiftAPIName: decl.name,
199-
as: decl.apiKind,
200-
stdlibTypes: st.swiftStdlibTypes
199+
as: decl.apiKind
201200
)
202201
return [DeclSyntax(thunkFunc)]
203202
}

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator {
2424
let javaPackage: String
2525
let swiftOutputDirectory: String
2626
let javaOutputDirectory: String
27-
let swiftStdlibTypes: SwiftStandardLibraryTypeDecls
2827
let symbolTable: SwiftSymbolTable
2928

3029
var javaPackagePath: String {
@@ -53,7 +52,6 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator {
5352
self.swiftOutputDirectory = swiftOutputDirectory
5453
self.javaOutputDirectory = javaOutputDirectory
5554
self.symbolTable = translator.symbolTable
56-
self.swiftStdlibTypes = translator.swiftStdlibTypeDecls
5755

5856
// If we are forced to write empty files, construct the expected outputs
5957
if translator.config.writeEmptyFiles ?? false {

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ extension JNISwift2JavaGenerator {
6767
switch swiftType {
6868
case .nominal(let nominalType):
6969
if let knownType = nominalType.nominalTypeDecl.knownStandardLibraryType {
70-
guard let javaType = translate(standardLibraryType: knownType) else {
70+
guard let javaType = translate(knownType: knownType) else {
7171
fatalError("unsupported known type: \(knownType)")
7272
}
7373
return javaType
@@ -83,8 +83,8 @@ extension JNISwift2JavaGenerator {
8383
}
8484
}
8585

86-
func translate(standardLibraryType: SwiftStandardLibraryTypeKind) -> JavaType? {
87-
switch standardLibraryType {
86+
func translate(knownType: SwiftKnownTypeDeclKind) -> JavaType? {
87+
switch knownType {
8888
case .bool: .boolean
8989
case .int8: .byte
9090
case .uint16: .char
@@ -101,6 +101,8 @@ extension JNISwift2JavaGenerator {
101101
.unsafeRawBufferPointer, .unsafeMutableRawBufferPointer,
102102
.unsafeBufferPointer, .unsafeMutableBufferPointer:
103103
nil
104+
case .data:
105+
fatalError("unimplemented")
104106
}
105107
}
106108
}

Sources/JExtractSwiftLib/Swift2JavaTranslator.swift

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ public final class Swift2JavaTranslator {
2727

2828
let config: Configuration
2929

30+
/// The name of the Swift module being translated.
31+
let swiftModuleName: String
32+
3033
// ==== Input
3134

3235
struct Input {
@@ -46,14 +49,7 @@ public final class Swift2JavaTranslator {
4649
/// type representation.
4750
package var importedTypes: [String: ImportedNominalType] = [:]
4851

49-
package var swiftStdlibTypeDecls: SwiftStandardLibraryTypeDecls
50-
51-
package let symbolTable: SwiftSymbolTable
52-
53-
/// The name of the Swift module being translated.
54-
var swiftModuleName: String {
55-
symbolTable.moduleName
56-
}
52+
package var symbolTable: SwiftSymbolTable! = nil
5753

5854
public init(
5955
config: Configuration
@@ -62,12 +58,7 @@ public final class Swift2JavaTranslator {
6258
fatalError("Missing 'swiftModule' name.") // FIXME: can we make it required in config? but we shared config for many cases
6359
}
6460
self.config = config
65-
self.symbolTable = SwiftSymbolTable(parsedModuleName: swiftModule)
66-
67-
// Create a mock of the Swift standard library.
68-
var parsedSwiftModule = SwiftParsedModuleSymbolTable(moduleName: "Swift")
69-
self.swiftStdlibTypeDecls = SwiftStandardLibraryTypeDecls(into: &parsedSwiftModule)
70-
self.symbolTable.importedModules.append(parsedSwiftModule.symbolTable)
61+
self.swiftModuleName = swiftModule
7162
}
7263
}
7364

@@ -111,8 +102,11 @@ extension Swift2JavaTranslator {
111102
}
112103

113104
package func prepareForTranslation() {
114-
/// Setup the symbol table.
115-
symbolTable.setup(inputs.map({ $0.syntax }))
105+
self.symbolTable = SwiftSymbolTable.setup(
106+
moduleName: self.swiftModuleName,
107+
inputs.map({ $0.syntax }),
108+
log: self.log
109+
)
116110
}
117111
}
118112

@@ -146,10 +140,10 @@ extension Swift2JavaTranslator {
146140
}
147141

148142
// Whether to import this extension?
149-
guard let nominalNode = symbolTable.parsedModule.nominalTypeSyntaxNodes[swiftNominalDecl] else {
143+
guard swiftNominalDecl.moduleName == self.swiftModuleName else {
150144
return nil
151145
}
152-
guard nominalNode.shouldImport(log: log) else {
146+
guard swiftNominalDecl.syntax!.shouldImport(log: log) else {
153147
return nil
154148
}
155149

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import SwiftSyntax
16+
17+
/// Scan importing modules.
18+
func importingModuleNames(sourceFile: SourceFileSyntax) -> [String] {
19+
var importingModuleNames: [String] = []
20+
for item in sourceFile.statements {
21+
if let importDecl = item.item.as(ImportDeclSyntax.self) {
22+
guard let moduleName = importDecl.path.first?.name.text else {
23+
continue
24+
}
25+
importingModuleNames.append(moduleName)
26+
}
27+
}
28+
return importingModuleNames
29+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import SwiftSyntax
16+
import SwiftSyntaxBuilder
17+
18+
enum SwiftKnownModule: String {
19+
case swift = "Swift"
20+
case foundation = "Foundation"
21+
22+
var name: String {
23+
return self.rawValue
24+
}
25+
26+
var symbolTable: SwiftModuleSymbolTable {
27+
return switch self {
28+
case .swift: swiftSymbolTable
29+
case .foundation: foundationSymbolTable
30+
}
31+
}
32+
33+
var sourceFile: SourceFileSyntax {
34+
return switch self {
35+
case .swift: swiftSourceFile
36+
case .foundation: foundationSourceFile
37+
}
38+
}
39+
}
40+
41+
private var swiftSymbolTable: SwiftModuleSymbolTable {
42+
var builder = SwiftParsedModuleSymbolTableBuilder(moduleName: "Swift", importedModules: [:])
43+
builder.handle(sourceFile: swiftSourceFile)
44+
return builder.finalize()
45+
}
46+
47+
private var foundationSymbolTable: SwiftModuleSymbolTable {
48+
var builder = SwiftParsedModuleSymbolTableBuilder(moduleName: "Foundation", importedModules: ["Swift": swiftSymbolTable])
49+
builder.handle(sourceFile: foundationSourceFile)
50+
return builder.finalize()
51+
}
52+
53+
private let swiftSourceFile: SourceFileSyntax = """
54+
public struct Bool {}
55+
public struct Int {}
56+
public struct UInt {}
57+
public struct Int8 {}
58+
public struct UInt8 {}
59+
public struct Int16 {}
60+
public struct UInt16 {}
61+
public struct Int32 {}
62+
public struct UInt32 {}
63+
public struct Int64 {}
64+
public struct UInt64 {}
65+
public struct Float {}
66+
public struct Double {}
67+
68+
public struct UnsafeRawPointer {}
69+
public struct UnsafeMutableRawPointer {}
70+
public struct UnsafeRawBufferPointer {}
71+
public struct UnsafeMutableRawBufferPointer {}
72+
73+
public struct UnsafePointer<Pointee> {}
74+
public struct UnsafeMutablePointer<Pointee> {}
75+
76+
public struct UnsafeBufferPointer<Element> {}
77+
public struct UnsafeMutableBufferPointer<Element> {}
78+
79+
public struct Void {} // FIXME: Support 'typealias Void = ()'
80+
81+
public struct String {
82+
public init(cString: UnsafePointer<Int8>)
83+
public func withCString(body: (UnsafePointer<Int8>) -> Void)
84+
}
85+
"""
86+
87+
private let foundationSourceFile: SourceFileSyntax = """
88+
public struct Data {
89+
public init(bytes: UnsafeRawPointer, count: Int)
90+
public func withUnsafeBytes(body: (UnsafeRawBufferPointer) -> Void)
91+
}
92+
"""
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import SwiftSyntax
16+
17+
enum SwiftKnownTypeDeclKind: String, Hashable {
18+
case bool = "Swift.Bool"
19+
case int = "Swift.Int"
20+
case uint = "Swift.UInt"
21+
case int8 = "Swift.Int8"
22+
case uint8 = "Swift.UInt8"
23+
case int16 = "Swift.Int16"
24+
case uint16 = "Swift.UInt16"
25+
case int32 = "Swift.Int32"
26+
case uint32 = "Swift.UInt32"
27+
case int64 = "Swift.Int64"
28+
case uint64 = "Swift.UInt64"
29+
case float = "Swift.Float"
30+
case double = "Swift.Double"
31+
case unsafeRawPointer = "Swift.UnsafeRawPointer"
32+
case unsafeMutableRawPointer = "Swift.UnsafeMutableRawPointer"
33+
case unsafeRawBufferPointer = "Swift.UnsafeRawBufferPointer"
34+
case unsafeMutableRawBufferPointer = "Swift.UnsafeMutableRawBufferPointer"
35+
case unsafePointer = "Swift.UnsafePointer"
36+
case unsafeMutablePointer = "Swift.UnsafeMutablePointer"
37+
case unsafeBufferPointer = "Swift.UnsafeBufferPointer"
38+
case unsafeMutableBufferPointer = "Swift.UnsafeMutableBufferPointer"
39+
case void = "Swift.Void"
40+
case string = "Swift.String"
41+
42+
case data = "Foundation.Data"
43+
44+
var moduleAndName: (module: String, name: String) {
45+
let qualified = self.rawValue
46+
let period = qualified.firstIndex(of: ".")!
47+
return (
48+
module: String(qualified[..<period]),
49+
name: String(qualified[qualified.index(after: period)...])
50+
)
51+
}
52+
53+
var isPointer: Bool {
54+
switch self {
55+
case .unsafePointer, .unsafeMutablePointer, .unsafeRawPointer, .unsafeMutableRawPointer:
56+
return true
57+
default:
58+
return false
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)