Skip to content

Commit c2f683e

Browse files
committed
[JExtract] Import 'Foundation.Data' if used
* Introduce `KnownSwiftModules` to represent `Swift` and `Foundation` modules. * `SwiftSymbolTable.setup()` is now a factory method to create `SwiftSymbolTable`. It scans the source file for module dependency. If `import Foundation` is found, add `Foundation` from the `KnownSwiftModules` (Just `Data` for now) * In `Swift2JavaTranslator` import `Data` APIs if any of the imported APIs use `Data` * `Data` has limited hardcoded APIs `init(bytes:count:)`, `getter:count`, and `withUnsafeBytes(_:)`. * Add `import Foundation` in Swift thunk if any of the the original source files import it
1 parent d969933 commit c2f683e

23 files changed

+936
-470
lines changed

Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
100100
outputSwiftDirectory.appending(path: "\(sourceModule.name)Module+SwiftJava.swift")
101101
]
102102

103+
// If the module uses 'Data' type, the thunk file is emitted as if 'Data' is declared
104+
// in that module. Declare the thunk file as the output.
105+
// FIXME: Make this conditional.
106+
outputSwiftFiles += [
107+
outputSwiftDirectory.appending(path: "Data+SwiftJava.swift")
108+
]
109+
103110
return [
104111
.buildCommand(
105112
displayName: "Generate Java wrappers for Swift types",

Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import Glibc
2323
import Darwin.C
2424
#endif
2525

26+
import Foundation
27+
2628
public func helloWorld() {
2729
p("\(#function)")
2830
}
@@ -53,6 +55,10 @@ public func globalReceiveRawBuffer(buf: UnsafeRawBufferPointer) -> Int {
5355

5456
public var globalBuffer: UnsafeRawBufferPointer = UnsafeRawBufferPointer(UnsafeMutableRawBufferPointer.allocate(byteCount: 124, alignment: 1))
5557

58+
public func globalReceiveReturnData(data: Data) -> Data {
59+
return Data(data)
60+
}
61+
5662
public func withBuffer(body: (UnsafeRawBufferPointer) -> Void) {
5763
body(globalBuffer)
5864
}

Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
import org.swift.swiftkit.ffm.AllocatingSwiftArena;
2323
import org.swift.swiftkit.ffm.SwiftRuntime;
2424

25+
import java.lang.foreign.MemoryLayout;
26+
import java.lang.foreign.MemorySegment;
27+
import java.lang.foreign.ValueLayout;
28+
2529
public class HelloJava2Swift {
2630

2731
public static void main(String[] args) {
@@ -78,6 +82,20 @@ static void examples() {
7882
});
7983
}
8084

85+
// Example of using 'Data'.
86+
try (var arena = AllocatingSwiftArena.ofConfined()) {
87+
var origBytes = arena.allocateFrom("foobar");
88+
var origDat = Data.init(origBytes, origBytes.byteSize(), arena);
89+
SwiftRuntime.trace("origDat.count = " + origDat.getCount());
90+
91+
var retDat = MySwiftLibrary.globalReceiveReturnData(origDat, arena);
92+
retDat.withUnsafeBytes((retBytes) -> {
93+
var str = retBytes.getString(0);
94+
SwiftRuntime.trace("retStr=" + str);
95+
});
96+
}
97+
98+
8199
System.out.println("DONE.");
82100
}
83101

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: 18 additions & 10 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,
@@ -266,6 +266,9 @@ struct CdeclLowering {
266266
)
267267
}
268268

269+
case .data:
270+
break
271+
269272
default:
270273
// Unreachable? Should be handled by `CType(cdeclType:)` lowering above.
271274
throw LoweringError.unhandledType(type)
@@ -407,6 +410,9 @@ struct CdeclLowering {
407410
])
408411
)
409412

413+
case .data:
414+
break
415+
410416
default:
411417
throw LoweringError.unhandledType(type)
412418
}
@@ -509,6 +515,9 @@ struct CdeclLowering {
509515
// Returning string is not supported at this point.
510516
throw LoweringError.unhandledType(type)
511517

518+
case .data:
519+
break
520+
512521
default:
513522
// Unreachable? Should be handled by `CType(cdeclType:)` lowering above.
514523
throw LoweringError.unhandledType(type)
@@ -663,8 +672,7 @@ extension LoweredFunctionSignature {
663672
package func cdeclThunk(
664673
cName: String,
665674
swiftAPIName: String,
666-
as apiKind: SwiftAPIKind,
667-
stdlibTypes: SwiftStandardLibraryTypeDecls
675+
as apiKind: SwiftAPIKind
668676
) -> FunctionDeclSyntax {
669677

670678
let cdeclParams = allLoweredParameters.map(\.description).joined(separator: ", ")
@@ -765,7 +773,7 @@ extension LoweredFunctionSignature {
765773
}
766774

767775
enum LoweringError: Error {
768-
case inoutNotSupported(SwiftType)
769-
case unhandledType(SwiftType)
770-
case effectNotSupported(SwiftEffectSpecifier)
776+
case inoutNotSupported(SwiftType, file: String = #file, line: Int = #line)
777+
case unhandledType(SwiftType, file: String = #file, line: Int = #line)
778+
case effectNotSupported(SwiftEffectSpecifier, file: String = #file, line: Int = #line)
771779
}

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift

Lines changed: 10 additions & 4 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.
@@ -353,6 +353,9 @@ extension FFMSwift2JavaGenerator {
353353
conversion: .call(.placeholder, function: "SwiftRuntime.toCString", withArena: true)
354354
)
355355

356+
case .data:
357+
break
358+
356359
default:
357360
throw JavaTranslationError.unhandledType(swiftType)
358361
}
@@ -438,6 +441,9 @@ extension FFMSwift2JavaGenerator {
438441
)
439442
)
440443

444+
case .data:
445+
break
446+
441447
case .unsafePointer, .unsafeMutablePointer:
442448
// FIXME: Implement
443449
throw JavaTranslationError.unhandledType(swiftType)
@@ -629,6 +635,6 @@ extension CType {
629635
}
630636

631637
enum JavaTranslationError: Error {
632-
case inoutNotSupported(SwiftType)
638+
case inoutNotSupported(SwiftType, file: String = #file, line: Int = #line)
633639
case unhandledType(SwiftType, file: String = #file, line: Int = #line)
634640
}

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ extension FFMSwift2JavaGenerator {
8787
8888
""")
8989

90+
printSwiftThunkImports(&printer)
91+
9092
for thunk in stt.renderGlobalThunks() {
9193
printer.print(thunk)
9294
printer.println()
@@ -114,11 +116,22 @@ extension FFMSwift2JavaGenerator {
114116
"""
115117
)
116118

119+
printSwiftThunkImports(&printer)
120+
117121
for thunk in stt.renderThunks(forType: ty) {
118122
printer.print("\(thunk)")
119123
printer.print("")
120124
}
121125
}
126+
127+
func printSwiftThunkImports(_ printer: inout CodePrinter) {
128+
for module in self.symbolTable.importedModules.keys.sorted() {
129+
guard module != "Swift" else {
130+
continue
131+
}
132+
printer.print("import \(module)")
133+
}
134+
}
122135
}
123136

124137
struct SwiftThunkTranslator {
@@ -196,8 +209,7 @@ struct SwiftThunkTranslator {
196209
let thunkFunc = translated.loweredSignature.cdeclThunk(
197210
cName: thunkName,
198211
swiftAPIName: decl.name,
199-
as: decl.apiKind,
200-
stdlibTypes: st.swiftStdlibTypes
212+
as: decl.apiKind
201213
)
202214
return [DeclSyntax(thunkFunc)]
203215
}

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift

Lines changed: 3 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 {
@@ -65,6 +63,9 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator {
6563
return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift"))
6664
})
6765
self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift")
66+
67+
// FIXME: Can we avoid this?
68+
self.expectedOutputSwiftFiles.insert("Data+SwiftJava.swift")
6869
} else {
6970
self.expectedOutputSwiftFiles = []
7071
}

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/JNI/JNISwift2JavaGenerator.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator {
5858
return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift"))
5959
})
6060
self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift")
61+
62+
// FIXME: Can we avoid this?
63+
self.expectedOutputSwiftFiles.insert("Data+SwiftJava.swift")
6164
} else {
6265
self.expectedOutputSwiftFiles = []
6366
}

0 commit comments

Comments
 (0)