Skip to content

[ffi] isLeaf changes the value returned by calling lookupFunction. #52696

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

Closed
modulovalue opened this issue Jun 13, 2023 · 2 comments
Closed

[ffi] isLeaf changes the value returned by calling lookupFunction. #52696

modulovalue opened this issue Jun 13, 2023 · 2 comments

Comments

@modulovalue
Copy link
Contributor

modulovalue commented Jun 13, 2023

For context see: #52692

@dcharkes setting isLeaf to true improves the performance by almost 50%. However, calling the result of lookupFunction appears to return a different value when isLeaf is set to true. Is that expected?

.p2align 2
.global _popcount
_popcount:
    // TODO
    mov x0, x1
    ret
 * Writing file to: /Users/modulovalue/Desktop/hello_assembly/hello_assembly/bin/popcount/output/hello_dylib.s'
 * Running command: 'as -arch arm64 /Users/modulovalue/Desktop/hello_assembly/hello_assembly/bin/popcount/output/hello_dylib.s -o /Users/modulovalue/Desktop/hello_assembly/hello_assembly/bin/popcount/output/hello_dylib.o'
 * Running command: 'clang -current_version 1.0 -compatibility_version 1.0 -dynamiclib -o /Users/modulovalue/Desktop/hello_assembly/hello_assembly/bin/popcount/output/hello_dylib.dylib /Users/modulovalue/Desktop/hello_assembly/hello_assembly/bin/popcount/output/hello_dylib.o'
void run(
  final DynamicLibrary dylib,
) {
  final popcount_leaf =
      dylib.lookupFunction<Uint32 Function(Uint32), int Function(int)>(
    'popcount',
    isLeaf: true,
  );
  final popcount_notleaf =
      dylib.lookupFunction<Uint32 Function(Uint32), int Function(int)>(
    'popcount',
    isLeaf: false,
  );
  print(popcount_notleaf(100000));
  print(popcount_leaf   (100000));
}

outputs:

100000
43032064

on: Dart SDK version: 3.1.0-163.1.beta (beta) (Wed Jun 7 05:06:41 2023 -0700) on "macos_arm64"

@modulovalue modulovalue changed the title [ffi] isLeaf changes the value returned by lookupFunction. [ffi] isLeaf changes the value returned by calling lookupFunction. Jun 13, 2023
@dcharkes
Copy link
Contributor

However, calling the result of lookupFunction appears to return a different value when isLeaf is set to true. Is that expected?

Your function signature takes one integer and returns one integer.

The calling convention in C on MacOS is to pass the argument in x0 and return the value in x0.

R0, R1, R2, R3, R4, R5, R6, R7,

static constexpr Register kReturnReg = R0;

Therefore, x1 is undefined.

You can explore calling conventions with

R0, R1, R2, R3, R4, R5, R6, R7,

The fact that it works without isLeaf is likely due to somehow the x1 register also being populated with the first argument (maybe the Dart compiler shuffles some values around right before the FFI call).

If you're going to write assembly by hand, it needs to follow the C ABI.

Nit: you're using int32_t while using x registers, w registers are 32 bits wide. So your move is copying the upper 4 bytes as well.

@mraleph mraleph closed this as completed Jun 13, 2023
@modulovalue
Copy link
Contributor Author

So everything that violates the established calling conventions is undefined behavior and not a bug, got it. Thank you for your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants