@@ -620,6 +620,23 @@ fn instruction(
620
620
)
621
621
}
622
622
623
+ fn int128_to_int64x2 ( val : & str ) -> ( String , String ) {
624
+ // we don't need to perform any conversion here, because the JS
625
+ // WebAssembly API will automatically convert the bigints to 64 bits
626
+ // for us. This even allows us to ignore signedness.
627
+ let low = val. to_owned ( ) ;
628
+ let high = format ! ( "{val} >> BigInt(64)" ) ;
629
+ ( low, high)
630
+ }
631
+ fn int64x2_to_int128 ( low : String , high : String , signed : bool ) -> String {
632
+ let low = format ! ( "BigInt.asUintN(64, {low})" ) ;
633
+ if signed {
634
+ format ! ( "({low} | ({high} << BigInt(64)))" )
635
+ } else {
636
+ format ! ( "({low} | (BigInt.asUintN(64, {high}) << BigInt(64)))" )
637
+ }
638
+ }
639
+
623
640
match instr {
624
641
Instruction :: ArgGet ( n) => {
625
642
let arg = js. arg ( * n) . to_string ( ) ;
@@ -712,6 +729,36 @@ fn instruction(
712
729
}
713
730
}
714
731
732
+ Instruction :: Int128ToWasm => {
733
+ let val = js. pop ( ) ;
734
+ js. assert_bigint ( & val) ;
735
+ let ( low, high) = int128_to_int64x2 ( & val) ;
736
+ js. push ( low) ;
737
+ js. push ( high) ;
738
+ }
739
+ Instruction :: WasmToInt128 { signed } => {
740
+ let high = js. pop ( ) ;
741
+ let low = js. pop ( ) ;
742
+ js. push ( int64x2_to_int128 ( low, high, * signed) ) ;
743
+ }
744
+
745
+ Instruction :: OptionInt128ToWasm => {
746
+ let val = js. pop ( ) ;
747
+ js. cx . expose_is_like_none ( ) ;
748
+ js. assert_optional_bigint ( & val) ;
749
+ let ( low, high) = int128_to_int64x2 ( & val) ;
750
+ js. push ( format ! ( "!isLikeNone({val})" ) ) ;
751
+ js. push ( format ! ( "isLikeNone({val}) ? BigInt(0) : {low}" ) ) ;
752
+ js. push ( format ! ( "isLikeNone({val}) ? BigInt(0) : {high}" ) ) ;
753
+ }
754
+ Instruction :: OptionWasmToInt128 { signed } => {
755
+ let high = js. pop ( ) ;
756
+ let low = js. pop ( ) ;
757
+ let present = js. pop ( ) ;
758
+ let val = int64x2_to_int128 ( low, high, * signed) ;
759
+ js. push ( format ! ( "{present} === 0 ? undefined : {val}" ) ) ;
760
+ }
761
+
715
762
Instruction :: WasmToStringEnum { name } => {
716
763
let index = js. pop ( ) ;
717
764
js. cx . expose_string_enum ( name) ;
@@ -983,6 +1030,8 @@ fn instruction(
983
1030
js. push ( format ! (
984
1031
"isLikeNone({val}) ? {zero} : {val}" ,
985
1032
zero = if * ty == ValType :: I64 {
1033
+ // We can't use bigint literals for now. See:
1034
+ // https://github.com/rustwasm/wasm-bindgen/issues/4246
986
1035
"BigInt(0)"
987
1036
} else {
988
1037
"0"
@@ -1500,7 +1549,11 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String, refs: Option<&mut HashSet<TsRe
1500
1549
| AdapterType :: F32
1501
1550
| AdapterType :: F64
1502
1551
| AdapterType :: NonNull => dst. push_str ( "number" ) ,
1503
- AdapterType :: I64 | AdapterType :: S64 | AdapterType :: U64 => dst. push_str ( "bigint" ) ,
1552
+ AdapterType :: I64
1553
+ | AdapterType :: S64
1554
+ | AdapterType :: U64
1555
+ | AdapterType :: S128
1556
+ | AdapterType :: U128 => dst. push_str ( "bigint" ) ,
1504
1557
AdapterType :: String => dst. push_str ( "string" ) ,
1505
1558
AdapterType :: Externref => dst. push_str ( "any" ) ,
1506
1559
AdapterType :: Bool => dst. push_str ( "boolean" ) ,
0 commit comments