Proof-of-concept port of Swift for Android

android

(Geordie J) #1

Hi, maybe one of the Apple devs can help out with this quick Q:

To interface with the JNI, we’d presumably need to call swift functions from our compiled swift binaries from C (or directly from Java, the result being the same). Is there a way to demangle certain symbols in the output binary to this effect, or is there another / a better way to access Swift functions from C?

Thanks

···

----

For anyone else following along, there is some discussion here:


.. which I guess we’d probably be better off keeping on this mailing list instead.


(Douglas Gregor) #2

Others can probably give a more detailed response, but...

There’s a Swift demangler in Swift’s “Basic” library (lib/Basic/Demangle.cpp), along with a standalone tool (swift-demangle) you can experiment with. The information in the mangled name should be complete enough to call, but you’ll need to match Swift’s calling convention.

If it’s just a specific set of Swift functions you want to call from C, you can use the @_silgen_name attribute to override the mangled name, and/or make them @convention(c) to use the C calling convention.

  - Doug

···

On Dec 11, 2015, at 4:33 AM, Geordie Jay via swift-dev <swift-dev@swift.org> wrote:

Hi, maybe one of the Apple devs can help out with this quick Q:

To interface with the JNI, we’d presumably need to call swift functions from our compiled swift binaries from C (or directly from Java, the result being the same). Is there a way to demangle certain symbols in the output binary to this effect, or is there another / a better way to access Swift functions from C?


(Slava Pestov) #3

Hi, maybe one of the Apple devs can help out with this quick Q:

To interface with the JNI, we’d presumably need to call swift functions from our compiled swift binaries from C (or directly from Java, the result being the same). Is there a way to demangle certain symbols in the output binary to this effect, or is there another / a better way to access Swift functions from C?

Joe Groff has a proof-of-concept implementation of a @cdecl attribute for exporting functions to C in the cdecl-attribute branch on GitHub.

Slava

···

On Dec 11, 2015, at 4:33 AM, Geordie Jay via swift-dev <swift-dev@swift.org> wrote:

Thanks

----

For anyone else following along, there is some discussion here:
https://www.reddit.com/r/swift/comments/3w0xrd/im_patching_the_opensource_swift_compiler_to/
.. which I guess we’d probably be better off keeping on this mailing list instead.
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


(Joe Groff) #4

@_silgen_name isn't the right answer here, since the convention will be wrong, and it won't interact properly with Clang imports and exports. Like Slava said, you want something like the '@_cdecl' attribute he proposed and I half-implemented.

-Joe

···

On Dec 11, 2015, at 7:13 AM, Douglas Gregor via swift-dev <swift-dev@swift.org> wrote:

On Dec 11, 2015, at 4:33 AM, Geordie Jay via swift-dev <swift-dev@swift.org> wrote:

Hi, maybe one of the Apple devs can help out with this quick Q:

To interface with the JNI, we’d presumably need to call swift functions from our compiled swift binaries from C (or directly from Java, the result being the same). Is there a way to demangle certain symbols in the output binary to this effect, or is there another / a better way to access Swift functions from C?

Others can probably give a more detailed response, but...

There’s a Swift demangler in Swift’s “Basic” library (lib/Basic/Demangle.cpp), along with a standalone tool (swift-demangle) you can experiment with. The information in the mangled name should be complete enough to call, but you’ll need to match Swift’s calling convention.

If it’s just a specific set of Swift functions you want to call from C, you can use the @_silgen_name attribute to override the mangled name, and/or make them @convention(c) to use the C calling convention.


(Geordie J) #5

Hi Joe,

I was just commenting on your @_cdecl commit on GitHub but I’ll keep the discussion here.

I was wondering what it is about your implementation that makes it rely on ObjC interop, as you noted. And whether this dependency can be removed for a quick and dirty proof of concept, or whether it’s something more fundamental than that?

In this (admittedly very simple) example, the author just calls the mangled name from C and appears to get away with it:

http://romain.goyet.com/articles/running_swift_code_on_android/

Makes me wonder whether the @_silgen_name approach wouldn’t suffice after all for a proof of concept?

Best regards,

Geordie

(Joe: apologies for the double up, I’m evidently terrible at mailing lists and hit reply instead of reply all!)

···

On Fri, Dec 11, 2015 at 5:53 PM, Joe Groff <jgroff@apple.com> wrote:

On Dec 11, 2015, at 7:13 AM, Douglas Gregor via swift-dev <swift-dev@swift.org> wrote:

On Dec 11, 2015, at 4:33 AM, Geordie Jay via swift-dev <swift-dev@swift.org> wrote:

Hi, maybe one of the Apple devs can help out with this quick Q:

To interface with the JNI, we’d presumably need to call swift functions from our compiled swift binaries from C (or directly from Java, the result being the same). Is there a way to demangle certain symbols in the output binary to this effect, or is there another / a better way to access Swift functions from C?

Others can probably give a more detailed response, but...

There’s a Swift demangler in Swift’s “Basic” library (lib/Basic/Demangle.cpp), along with a standalone tool (swift-demangle) you can experiment with. The information in the mangled name should be complete enough to call, but you’ll need to match Swift’s calling convention.

If it’s just a specific set of Swift functions you want to call from C, you can use the @_silgen_name attribute to override the mangled name, and/or make them @convention(c) to use the C calling convention.

@_silgen_name isn't the right answer here, since the convention will be wrong, and it won't interact properly with Clang imports and exports. Like Slava said, you want something like the '@_cdecl' attribute he proposed and I half-implemented.
-Joe


(Joe Groff) #6

Hi Joe,
I was just commenting on your @_cdecl commit on GitHub but I’ll keep the discussion here.

I was wondering what it is about your implementation that makes it rely on ObjC interop, as you noted. And whether this dependency can be removed for a quick and dirty proof of concept, or whether it’s something more fundamental than that?

It's mostly because that's how the parameter type validation logic I borrowed from @objc works, and I didn't have time to change it. The code for @cdecl has to be refined to support a "C-only" model, or maybe just only require ObjCInterop and 'import Foundation' when ObjC-specific constructs are used.

In this (admittedly very simple) example, the author just calls the mangled name from C and appears to get away with it:
http://romain.goyet.com/articles/running_swift_code_on_android/

Makes me wonder whether the @_silgen_name approach wouldn’t suffice after all for a proof of concept?

They're getting lucky. Swift function ABIs happen to coincide with C function ABIs in some cases, but this can't be relied on, and will probably break soon when we switch over the Swift-specific calling convention in LLVM.

-Joe

···

On Dec 11, 2015, at 9:03 AM, Geordie Jay <geojay@gmail.com> wrote:

Best regards,
Geordie

(Joe: apologies for the double up, I’m evidently terrible at mailing lists and hit reply instead of reply all!)

On Fri, Dec 11, 2015 at 5:53 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

> On Dec 11, 2015, at 7:13 AM, Douglas Gregor via swift-dev <swift-dev@swift.org> wrote:
>
>
>> On Dec 11, 2015, at 4:33 AM, Geordie Jay via swift-dev <swift-dev@swift.org> wrote:
>>
>> Hi, maybe one of the Apple devs can help out with this quick Q:
>>
>> To interface with the JNI, we’d presumably need to call swift functions from our compiled swift binaries from C (or directly from Java, the result being the same). Is there a way to demangle certain symbols in the output binary to this effect, or is there another / a better way to access Swift functions from C?
>
> Others can probably give a more detailed response, but...
>
> There’s a Swift demangler in Swift’s “Basic” library (lib/Basic/Demangle.cpp), along with a standalone tool (swift-demangle) you can experiment with. The information in the mangled name should be complete enough to call, but you’ll need to match Swift’s calling convention.
>
> If it’s just a specific set of Swift functions you want to call from C, you can use the @_silgen_name attribute to override the mangled name, and/or make them @convention(c) to use the C calling convention.

@_silgen_name isn't the right answer here, since the convention will be wrong, and it won't interact properly with Clang imports and exports. Like Slava said, you want something like the '@_cdecl' attribute he proposed and I half-implemented.

-Joe


(Geordie J) #7

Hi Joe,
I was just commenting on your @_cdecl commit on GitHub but I’ll keep the discussion here.

I was wondering what it is about your implementation that makes it rely on ObjC interop, as you noted. And whether this dependency can be removed for a quick and dirty proof of concept, or whether it’s something more fundamental than that?

It's mostly because that's how the parameter type validation logic I borrowed from @objc works, and I didn't have time to change it. The code for @cdecl has to be refined to support a "C-only" model, or maybe just only require ObjCInterop and 'import Foundation' when ObjC-specific constructs are used.

I’d like to have a look at making a simple C-only model of this. Compiler hacking is new to me though so I’ll be stabbing in the dark for a while. Can you elaborate as to whether you're referring to the block starting at line 4108 in 'lib/Sema/TypeCheckDecl.cpp’, or something else? Presumably there are already relevant type-checking routines for Swift's @convention_c functions, no?

In this (admittedly very simple) example, the author just calls the mangled name from C and appears to get away with it:
http://romain.goyet.com/articles/running_swift_code_on_android/

Makes me wonder whether the @_silgen_name approach wouldn’t suffice after all for a proof of concept?

They're getting lucky. Swift function ABIs happen to coincide with C function ABIs in some cases, but this can't be relied on, and will probably break soon when we switch over the Swift-specific calling convention in LLVM.

Are we talking about safety / type checking? I mean about validating that we’re not asking for e.g. a Swift Struct in our @_cdecl function? Or is there something else at play? The goal of Swift is obviously to be safe, but since I’m so new to this, what I’d like to see first is something that ‘works' at all, and continue on the safe side after that. I’m just after a proof of concept for now.

···

On Dec 11, 2015, at 9:03 AM, Geordie Jay <geojay@gmail.com <mailto:geojay@gmail.com>> wrote:

I’m sorry about repeatedly starting new threads, I can’t figure out what the mailing list system expects of me. Even if I click reply from the web archive, which fills in the to/reply-to and subject (complete with RE: RE: etc.), it still starts a new thread. I haven’t felt this technically incompetent since the early 90s :slight_smile:


(Joe Groff) #8

Hi Joe,
I was just commenting on your @_cdecl commit on GitHub but I’ll keep the discussion here.

I was wondering what it is about your implementation that makes it rely on ObjC interop, as you noted. And whether this dependency can be removed for a quick and dirty proof of concept, or whether it’s something more fundamental than that?

It's mostly because that's how the parameter type validation logic I borrowed from @objc works, and I didn't have time to change it. The code for @cdecl has to be refined to support a "C-only" model, or maybe just only require ObjCInterop and 'import Foundation' when ObjC-specific constructs are used.

I’d like to have a look at making a simple C-only model of this. Compiler hacking is new to me though so I’ll be stabbing in the dark for a while. Can you elaborate as to whether you're referring to the block starting at line 4108 in 'lib/Sema/TypeCheckDecl.cpp’, or something else? Presumably there are already relevant type-checking routines for Swift's @convention_c functions, no?

The checking code is in the "isRepresentableInObjC" family of functions around there, yeah. @convention(c) didn't need to distinguish C from ObjC on Darwin platforms, since ObjC and Foundation are always available there, so we didn't bother trying to separate them. You could probably get started by just disabling the checks for Foundation and ObjC interop altogether and avoiding touching any class, block, or CF types (which probably is easy on Android).

In this (admittedly very simple) example, the author just calls the mangled name from C and appears to get away with it:
http://romain.goyet.com/articles/running_swift_code_on_android/

Makes me wonder whether the @_silgen_name approach wouldn’t suffice after all for a proof of concept?

They're getting lucky. Swift function ABIs happen to coincide with C function ABIs in some cases, but this can't be relied on, and will probably break soon when we switch over the Swift-specific calling convention in LLVM.

Are we talking about safety / type checking? I mean about validating that we’re not asking for e.g. a Swift Struct in our @_cdecl function? Or is there something else at play? The goal of Swift is obviously to be safe, but since I’m so new to this, what I’d like to see first is something that ‘works' at all, and continue on the safe side after that. I’m just after a proof of concept for now.

I'm talking about linkage safety. If swiftc exports a swift function with a certain symbol name, and C code links against it, we don't want to guarantee they'll use the same calling convention, unless the function is explicitly exported with an attribute saying it uses the C calling convention.

-Joe

···

On Dec 11, 2015, at 11:41 AM, Geordie Jay <geojay@gmail.com> wrote:

On Dec 11, 2015, at 9:03 AM, Geordie Jay <geojay@gmail.com <mailto:geojay@gmail.com>> wrote: