Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vm/ffi] Explore using FfiNative for static linking #49418

Open
Tracked by #50565
dcharkes opened this issue Jul 7, 2022 · 9 comments
Open
Tracked by #50565

[vm/ffi] Explore using FfiNative for static linking #49418

dcharkes opened this issue Jul 7, 2022 · 9 comments
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi

Comments

@dcharkes
Copy link
Contributor

dcharkes commented Jul 7, 2022

Given a dart file

@FfiNative<Int64 Function(Int64, Int64)>("FfiNative_Sum", isLeaf:true)
external int sum(int a, int b);

main(){
  print(sum(40, 2));
}

And a C file:

#include <stdint.h>

uint64_t FfiNative_Sum(uint64_t a, uint64_t b) { return a + b; }

It should be possible to compile this to a pc relative call if we use the native linker.

  1. Compile the dart program to a (a) an assembly file with a call FfiNative_Sum or (b) to an ELF file with relocation records (a static library in ELF format rather than a dynamic library in ELF format).
  2. Compile the C program to a relocatable file (static library or object file).
  3. Link them together with the native linker to a dynamic library in ELF format.
  4. Run with dartaotruntime passing in the dynamic library or appending it.

There is a huge design space.

For example we should add asset tags to disambiguate native symbols.
And we could use the same syntax for dynamic linking using these assets.
I will not write these up here, but wanted to have a bug to point to.

@dcharkes dcharkes added area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi labels Jul 7, 2022
copybara-service bot pushed a commit that referenced this issue Jul 15, 2022
We don't check undefined symbols in our assembly snapshots. We
currently never emit undefined symbols, because Dart code only refers
to Dart code statically.

When adding static linking, we would like to have the option to have
PC relative calls to native libraries provided as relocatable files
(object files or static libraries).

Not checking would compile the symbols to dynamic linker, but we don't
support that `dart compile exe` at the moment. So we should add this
sanity check.

Also: Removes unused imports in relevant test.

Bug: #49418
Change-Id: I10701b82a1e8a06ce41271bd9183064addfb88f4
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-nnbd-mac-release-arm64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-debug-x64c-try,vm-kernel-precomp-mac-product-x64-try,vm-kernel-precomp-dwarf-linux-product-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/251261
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Jonas Termansen <sortie@google.com>
@safasofuoglu
Copy link

Would this enable LTO inlining of FfiNative_Sum?

@dcharkes
Copy link
Contributor Author

Would this enable LTO inlining of FfiNative_Sum?

I believe so.

@mraleph
Copy link
Member

mraleph commented Oct 20, 2022

Unfortunately, LTO inlining requires some interoperability between compilers (e.g. either us using the same IR as C/C++ compiler or us implementing C/C++ compiler on top of our IR). Currently we have no concrete plans for going that route.

The best we will get here is a direct (e.g. PC-relative) call from Dart function to C function, but not the inlining of C function into the Dart function.

If you have some C code that is so small that it hugely benefits from inlining into its Dart caller then probably that C code should be written in Dart if possible. Though, I can understand situations where callee is extremely low level (e.g. a snippet of assembly code). I have been dreaming about adding inline assembly to dart:ffi - but that's a very speculative and probably far out, given our current priorities.

@dcharkes
Copy link
Contributor Author

Unfortunately, LTO inlining requires some interoperability between compilers (e.g. either us using the same IR as C/C++ compiler or us implementing C/C++ compiler on top of our IR).

Today I learned, with LTO a higher level representation (LLVM bitcode) is put in object files, not ELF:

(I assumed LTO works on regular ELF object files and static libraries. ELF object files and static libraries only contain symbols and machine code, not a higher level representation. In which case LTO would need to prove to itself which registers are preserved to enable inlining.)

@modulovalue
Copy link
Contributor

FYI: A week ago, at WWDC23, Apple introduced the concept of mergeable libraries that, they claim, combine the best parts of static and dynamic libraries. The main selling point appears to be improved build times. (Maybe there's something there that could be used for inspiration to e.g. minimize the impact of static linking on e.g. hot reload.)

@dcharkes
Copy link
Contributor Author

FYI: A week ago, at WWDC23, Apple introduced the concept of mergeable libraries that, they claim, combine the best parts of static and dynamic libraries. The main selling point appears to be improved build times. (Maybe there's something there that could be used for inspiration to e.g. minimize the impact of static linking on e.g. hot reload.)

I believe we will solve this with #50565 already. If your build.dart can both do static and dynamic libraries, the embedder (dart standalone or Flutter) can decide per command to have prefer-dynamic or prefer-static. In debug mode it can then use dylibs to support hot reload, and when making a release build for the app it could use static linking.

That being said, maybe mergable libraries will be a 3rd type link mode for assets, that build.dart could produce and that can be consumed both as dynamic library and static library.

https://github.com/dart-lang/native/blob/2de88135e25577d851c95b04af0ceb74b706f285/pkgs/native_assets_cli/lib/src/model/link_mode.dart#L10

@dxvid-pts
Copy link

If we know which functions are called in the native library, couldn't this also enable three-shaking of the native library? E.g if it is a huge library like OpenSSL but the user only calls one function of it, we could strip the rest to make binary size smaller. This would be amazing!

@dcharkes
Copy link
Contributor Author

If we know which functions are called in the native library, couldn't this also enable three-shaking of the native library? E.g if it is a huge library like OpenSSL but the user only calls one function of it, we could strip the rest to make binary size smaller. This would be amazing!

That's precisely the point! :)

copybara-service bot pushed a commit that referenced this issue Apr 12, 2024
Test the assembly snapshot flow with native assets.
This is a prerequisite for using the native linker in follow up CLs.

TEST=tests/ffi/native_assets/asset_relative_test.dart

Bug: #49418
Change-Id: Ib14c3e1edb652ac0eefeefd0b46fa0dd69c7fa67
Cq-Include-Trybots: dart/try:vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-aot-mac-release-arm64-try,vm-aot-mac-release-x64-try,vm-aot-obfuscate-linux-release-x64-try,vm-aot-optimization-level-linux-release-x64-try,vm-aot-win-debug-arm64-try,vm-aot-win-debug-x64-try,vm-aot-win-debug-x64c-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/362501
Reviewed-by: Tess Strickland <sstrickl@google.com>
@medz
Copy link

medz commented Dec 2, 2024

I think the most confusing point is that I use C to write a call to a function in a static library. Then I can find all the functions of this static library from Dart FFI, otherwise I can't get any.

For the problem of finding the functions exposed by the .a static library, I now write a C file that does nothing but forward parameters to the functions of the static library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi
Projects
None yet
Development

No branches or pull requests

6 participants