Search code examples
rusttypesarbitrary-precision

Copy a u128 into [u64;2]


How can a u128 be converted to an array of u64s. While passing a u128 to an API which takes arbitrary precision int, the API takes 3 parameters

LLVMValueRef LLVMConstIntOfArbitraryPrecision   (
  LLVMTypeRef IntTy,
  unsigned  NumWords,
  const uint64_t Words[] 
)

The first two parameters are known (IntTy = LLVMInt128Type, and NumWords = 2). The third parameter needs an array of uint64_ts. The provided u128 needs to be converted to an array of u64. From the rust doc it seems u128 can be converted to an array of bytes e.g.

let buff: [u8; 16] = u128_val.to_ne_bytes();
let Words: [u64; 2] = ?? // What to do here?

How can buff be converted to an array of Words? Also, how to deal with endianness. For simplicity, the code generator and the API will run on the machine with same endianness.


Solution

  • I would just made it by hand, this avoid any unsafe and is straight forward and care about endianness:

    pub fn foo(a: u128) -> [u64; 2] {
        [(a >> 64) as u64, a as u64]
    }
    

    This translate to:

    playground::foo:
        movq    %rdi, %rax
        movq    %rdx, (%rdi)
        movq    %rsi, 8(%rdi)
        retq