forked from emscripten-core/emscripten
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibrary_int53.js
144 lines (132 loc) · 5.71 KB
/
library_int53.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* @license
* Copyright 2020 The Emscripten Authors
* SPDX-License-Identifier: MIT
*/
mergeInto(LibraryManager.library, {
#if ASSERTIONS
$writeI53ToI64__deps: ['$readI53FromI64', '$readI53FromU64'
#if MINIMAL_RUNTIME
, '$warnOnce'
#endif
],
#endif
// Writes the given JavaScript Number to the WebAssembly heap as a 64-bit integer variable.
// If the given number is not in the range [-2^53, 2^53] (inclusive), then an unexpectedly
// rounded or incorrect number can be written to the heap. ("garbage in, garbage out")
// Note that unlike the most other function variants in this library, there is no separate
// function $writeI53ToU64(): the implementation would be identical, and it is up to the
// C/C++ side code to interpret the resulting number as signed or unsigned as is desirable.
$writeI53ToI64: function(ptr, num) {
HEAPU32[ptr>>2] = num;
HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
#if ASSERTIONS
var deserialized = (num >= 0) ? readI53FromU64(ptr) : readI53FromI64(ptr);
if (deserialized != num) warnOnce('writeI53ToI64() out of range: serialized JS Number ' + num + ' to Wasm heap as bytes lo=0x' + HEAPU32[ptr>>2].toString(16) + ', hi=0x' + HEAPU32[ptr+4>>2].toString(16) + ', which deserializes back to ' + deserialized + ' instead!');
#endif
},
// Same as writeI53ToI64, but if the double precision number does not fit within the
// 64-bit number, the number is clamped to range [-2^63, 2^63-1].
$writeI53ToI64Clamped: function(ptr, num) {
if (num > 0x7FFFFFFFFFFFFFFF) {
HEAPU32[ptr>>2] = 0xFFFFFFFF;
HEAPU32[ptr+4>>2] = 0x7FFFFFFF;
} else if (num < -0x8000000000000000) {
HEAPU32[ptr>>2] = 0;
HEAPU32[ptr+4>>2] = 0x80000000;
} else {
HEAPU32[ptr>>2] = num;
HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
}
},
// Like writeI53ToI64, but throws if the passed number is out of range of int64.
$writeI53ToI64Signaling: function(ptr, num) {
if (num > 0x7FFFFFFFFFFFFFFF || num < -0x8000000000000000) {
#if ASSERTIONS
throw 'RangeError in writeI53ToI64Signaling(): input value ' + num + ' is out of range of int64';
#else
throw 'RangeError:' + num;
#endif
}
HEAPU32[ptr>>2] = num;
HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
},
// Uint64 variant of writeI53ToI64Clamped. Writes the Number to a Uint64 variable on
// the heap, clamping out of range values to range [0, 2^64-1].
$writeI53ToU64Clamped: function(ptr, num) {
if (num > 0xFFFFFFFFFFFFFFFF) HEAPU32[ptr>>2] = HEAPU32[ptr+4>>2] = 0xFFFFFFFF;
else if (num < 0) HEAPU32[ptr>>2] = HEAPU32[ptr+4>>2] = 0;
else {
HEAPU32[ptr>>2] = num;
HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
}
},
// Like writeI53ToI64, but throws if the passed number is out of range of uint64.
$writeI53ToU64Signaling: function(ptr, num) {
if (num < 0 || num > 0xFFFFFFFFFFFFFFFF) {
#if ASSERTIONS
throw 'RangeError in writeI53ToU64Signaling(): input value ' + num + ' is out of range of uint64';
#else
throw 'RangeError:'+num;
#endif
}
HEAPU32[ptr>>2] = num;
HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
},
// Reads a 64-bit signed integer from the WebAssembly heap and
// converts it to a JavaScript Number, which can represent 53 integer bits precisely.
// TODO: Add $readI53FromI64Signaling() variant.
$readI53FromI64: function(ptr) {
return HEAPU32[ptr>>2] + HEAP32[ptr+4>>2] * 4294967296;
},
// Reads a 64-bit unsigned integer from the WebAssembly heap and
// converts it to a JavaScript Number, which can represent 53 integer bits precisely.
// TODO: Add $readI53FromU64Signaling() variant.
$readI53FromU64: function(ptr) {
return HEAPU32[ptr>>2] + HEAPU32[ptr+4>>2] * 4294967296;
},
// Converts the given signed 32-bit low-high pair to a JavaScript Number that
// can represent 53 bits of precision.
$convertI32PairToI53: function(lo, hi) {
#if ASSERTIONS
// This function should not be getting called with too large unsigned numbers
// in high part (if hi >= 0x7FFFFFFFF, one should have been calling
// convertU32PairToI53())
assert(hi === (hi|0));
#endif
return (lo >>> 0) + hi * 4294967296;
},
// Converts the given signed 32-bit low-high pair to a JavaScript Number that can
// represent 53 bits of precision. Returns a NaN if the number exceeds the safe
// integer range representable by a Number (x > 9007199254740992 || x < -9007199254740992)
$convertI32PairToI53Checked: function(lo, hi) {
#if ASSERTIONS
assert(lo == (lo >>> 0) || lo == (lo|0)); // lo should either be a i32 or a u32
assert(hi === (hi|0)); // hi should be a i32
#endif
return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN;
},
// Converts the given unsigned 32-bit low-high pair to a JavaScript Number that can
// represent 53 bits of precision.
// TODO: Add $convertU32PairToI53Checked() variant.
$convertU32PairToI53: function(lo, hi) {
return (lo >>> 0) + (hi >>> 0) * 4294967296;
},
#if WASM_BIGINT
$MAX_INT53: '{{{ Math.pow(2, 53) }}}',
$MIN_INT53: '-{{{ Math.pow(2, 53) }}}',
// Counvert a bigint value (usually coming from Wasm->JS call) into an int53
// JS Number. This is used when we have an incoming i64 that we know is a
// pointer or size_t and is expected to be withing the int53 range.
// Returns NaN if the incoming bigint is outside the range.
$bigintToI53Checked__deps: ['$MAX_INT53', '$MIN_INT53'],
$bigintToI53Checked: function(num) {
return (num < MIN_INT53 || num > MAX_INT53) ? NaN : Number(num);
},
#endif
});
#if WASM_BIGINT
global.i53ConversionDeps = ['$bigintToI53Checked'];
#else
global.i53ConversionDeps = ['$convertI32PairToI53Checked'];
#endif