Skip to content

dart:ffi Uint64 load/store values which cannot be represented in Dart int #35757

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
dcharkes opened this issue Jan 25, 2019 · 3 comments
Closed
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-ffi

Comments

@dcharkes
Copy link
Contributor

Dart ints are signed 64 bit ints, so they cannot hold the values [2 ^ 63, ..., 2 ^ 64 - 1].

We have three options:

  • Keep Uint64 and interpret the bits as Int64 in Dart.
  • Keep Uint64, but throw an error if we load a value that we cannot represent in Dart.
  • remove Uint64, and write Int64 in signatures.

Interpret bits differently in Dart

Pointer<Uint64> p = allocate();
p.store(0x7FFFFFFFFFFFFFFF); // 2 ^ 63 - 1
Expect.equals(0x7FFFFFFFFFFFFFFF, p.load<int>());
p.store(-0x8000000000000000); // -2 ^ 63 interpreted as 2 ^ 63
Expect.equals(-0x8000000000000000, p.load<int>());
p.store(-1); // -1 interpreted as 2 ^ 64 - 1
Expect.equals(-1, p.load<int>());
ffi.free(p);

Pro: we can represent the C signatures
Con: interpreting bits differently on load/store can be confusing

Throw an error on loading

Pointer<Int64> p = allocate();
p.store(-1);
Expect.equals(-1, p.load<int>());
Pointer<Uint64> p2 = p.cast(); // bits for -1 are now 2 ^ 64 - 1
Expect.throws(() => p2.load<int>());
ffi.free(p);

Pro: explicit that bits are interpreted differently
Con: verbose

Drop Uint64 and use Int64

typedef NativeFunc = Int64 Function(Int64); // for some Uint64 Function(Uint64) in C
int Function(int) f = somePointer.asFunction();
int result = f(-1); // will be interpreted as 2 ^ 64 - 1 by C
Expect.equals(-1, result); // C returing 2 ^ 64 - 1 shows up as -1 in Dart

Con: interpreting bits differently can be confusing
Con 2: signatures of C function in Dart does not correspond to signature in h file

@lrhn
Copy link
Member

lrhn commented Jan 25, 2019

The Uint64List returns int values for the same bit pattern, so you would not be alone in choosing that approach. (And their documentation is not up-to-date, it still talks about truncating integers to 64 bits.)

Arguably, we could also just remove the Uint64List (it doesn't exist when compiled to JS anyway).

The Dart VM integer literals are designed so that you can write:

int bignum = 0xFFFFFFFFFFFFFFFF;  // 16 F's.

even on the VM (a hex literal that is in the range 2^63..2^64-1). The result is -1. This is intended to allow you to write 64-bit bit patterns independently of their interpretation as numbers. So, at some level, we are aware that a signed 64-bit value can be used to contain an unsigned value.

@dcharkes dcharkes changed the title Uint64 load/store values which cannot be represented in Dart int dart:ffi Uint64 load/store values which cannot be represented in Dart int Jan 25, 2019
@kevmoo kevmoo added the area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. label Jan 25, 2019
@dcharkes
Copy link
Contributor Author

looping in @sjindel-google

Interesting:

Expect.equals(0xFFFFFFFFFFFFFFFF, -1);  // true

So, at some level, we are aware that a signed 64-bit value can be used to contain an unsigned value.

Okay, that corresponds to our first option.

@dcharkes
Copy link
Contributor Author

dcharkes commented Feb 7, 2019

First option it is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-ffi
Projects
None yet
Development

No branches or pull requests

3 participants