Skip to content

Commit 54c8a25

Browse files
committed
[JExtract] Import Data
1 parent 4b96ba4 commit 54c8a25

File tree

10 files changed

+406
-8
lines changed

10 files changed

+406
-8
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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
import org.swift.swiftkit.SwiftArena;
2222
import org.swift.swiftkit.SwiftKit;
2323

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

2630
public static void main(String[] args) {
@@ -77,6 +81,22 @@ static void examples() {
7781
});
7882
}
7983

84+
// Example of using 'Data'.
85+
try (var arena = SwiftArena.ofConfined()) {
86+
var origBytes = arena.allocateFrom("foobar");
87+
var origDat = Data.init(origBytes, origBytes.byteSize(), arena);
88+
89+
// var origBytes = arena.allocate(ValueLayout.JAVA_INT, arry.length);
90+
// origBytes.copyFrom(MemorySegment.ofArray(arry));
91+
// var dat = MySwiftLibrary.globalReceiveReturnData(origDat, arena);
92+
// dat.withUnsafeBytes((retBytes) -> {
93+
// SwiftKit.trace("retBytes=" + retBytes.toArray(ValueLayout.JAVA_INT)[1]);
94+
// SwiftKit.trace("foobar");
95+
// });
96+
//SwiftKit.trace(origDat);
97+
}
98+
99+
80100
System.out.println("DONE.");
81101
}
82102

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
@@ -764,7 +773,7 @@ extension LoweredFunctionSignature {
764773
}
765774

766775
enum LoweringError: Error {
767-
case inoutNotSupported(SwiftType)
768-
case unhandledType(SwiftType)
769-
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)
770779
}

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ extension FFMSwift2JavaGenerator {
353353
conversion: .call(.placeholder, function: "SwiftKit.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: 13 additions & 0 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 {

Sources/JExtractSwiftLib/Swift2JavaTranslator.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ extension Swift2JavaTranslator {
9999
log.trace("Analyzing \(input.filePath)")
100100
visitor.visit(sourceFile: input.syntax)
101101
}
102+
103+
// If any API uses 'Foundation.Data', import 'Data' as if it's declared in
104+
// this module.
105+
if let dataDecl = self.symbolTable[.data] {
106+
if self.isUsing(dataDecl) {
107+
visitor.visit(nominalDecl: dataDecl.syntax!.asNominal!, in: nil)
108+
}
109+
}
102110
}
103111

104112
package func prepareForTranslation() {
@@ -108,6 +116,53 @@ extension Swift2JavaTranslator {
108116
log: self.log
109117
)
110118
}
119+
120+
// Check if any of the imported decls uses the specified nominal declaration.
121+
func isUsing(_ decl: SwiftNominalTypeDeclaration) -> Bool {
122+
func check(_ type: SwiftType) -> Bool {
123+
switch type {
124+
case .nominal(let nominal):
125+
return nominal.nominalTypeDecl == decl
126+
case .optional(let ty):
127+
return check(ty)
128+
case .tuple(let tuple):
129+
return tuple.contains(where: check)
130+
case .function(let fn):
131+
return check(fn.resultType) || fn.parameters.contains(where: { check($0.type) })
132+
case .metatype(let ty):
133+
return check(ty)
134+
}
135+
}
136+
137+
func check(_ fn: ImportedFunc) -> Bool {
138+
if check(fn.functionSignature.result.type) {
139+
return true
140+
}
141+
if fn.functionSignature.parameters.contains(where: { check($0.type) }) {
142+
return true
143+
}
144+
return false
145+
}
146+
147+
if self.importedGlobalFuncs.contains(where: check) {
148+
return true
149+
}
150+
if self.importedGlobalVariables.contains(where: check) {
151+
return true
152+
}
153+
for importedType in self.importedTypes.values {
154+
if importedType.initializers.contains(where: check) {
155+
return true
156+
}
157+
if importedType.methods.contains(where: check) {
158+
return true
159+
}
160+
if importedGlobalVariables.contains(where: check) {
161+
return true
162+
}
163+
}
164+
return false
165+
}
111166
}
112167

113168
// ==== ----------------------------------------------------------------------------------------------------------------

Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,18 @@ private let swiftSourceFile: SourceFileSyntax = """
7676
public struct UnsafeBufferPointer<Element> {}
7777
public struct UnsafeMutableBufferPointer<Element> {}
7878
79-
public struct Void {} // FIXME: Support 'typealias Void = ()'
79+
// FIXME: Support 'typealias Void = ()'
80+
public struct Void {}
8081
8182
public struct String {
8283
public init(cString: UnsafePointer<Int8>)
83-
public func withCString(body: (UnsafePointer<Int8>) -> Void)
84+
public func withCString(_ body: (UnsafePointer<Int8>) -> Void)
8485
}
8586
"""
8687

8788
private let foundationSourceFile: SourceFileSyntax = """
8889
public struct Data {
8990
public init(bytes: UnsafeRawPointer, count: Int)
90-
public func withUnsafeBytes(body: (UnsafeRawBufferPointer) -> Void)
91+
public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
9192
}
9293
"""

Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ extension SwiftSymbolTable {
131131

132132
let (module, name) = knownType.moduleAndName
133133
guard let moduleTable = importedModules[module] else {
134-
fatalError("module \(module) is not known")
134+
return nil
135135
}
136136

137137
let found = moduleTable.lookupTopLevelNominalType(name)

0 commit comments

Comments
 (0)