-
Notifications
You must be signed in to change notification settings - Fork 3.3k
/
parseTools_legacy.mjs
152 lines (137 loc) · 4.59 KB
/
parseTools_legacy.mjs
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
145
146
147
148
149
150
151
152
/**
* @license
* Copyright 2010 The Emscripten Authors
* SPDX-License-Identifier: MIT
*/
import {warn, addToCompileTimeContext} from './utility.mjs';
import {ATMAINS, POINTER_SIZE, runIfMainThread} from './parseTools.mjs';
// Takes a pair of return values, stashes one in tempRet0 and returns the other.
// Should probably be renamed to `makeReturn64` but keeping this old name in
// case external JS library code uses this name.
function makeStructuralReturn(values) {
warn('use of legacy parseTools function: makeStructuralReturn');
assert(values.length == 2);
return 'setTempRet0(' + values[1] + '); return ' + asmCoercion(values[0], 'i32');
}
// Replaced (at least internally) with receiveI64ParamAsI53 that does
// bounds checking.
function receiveI64ParamAsDouble(name) {
warn('use of legacy parseTools function: receiveI64ParamAsDouble');
if (WASM_BIGINT) {
// Just convert the bigint into a double.
return `${name} = Number(${name});`;
}
// Combine the i32 params. Use an unsigned operator on low and shift high by
// 32 bits.
return `var ${name} = ${name}_high * 0x100000000 + (${name}_low >>> 0);`;
}
function receiveI64ParamAsI32s(name) {
warn('use of legacy parseTools function: receiveI64ParamAsI32s');
if (WASM_BIGINT) {
return `var ${name}_low = Number(${name} & 0xffffffffn) | 0, ${name}_high = Number(${name} >> 32n) | 0;`;
}
return '';
}
function stripCorrections(param) {
warn('use of legacy parseTools function: stripCorrections');
let m;
while (true) {
if ((m = /^\((.*)\)$/.exec(param))) {
param = m[1];
continue;
}
if ((m = /^\(([$_\w]+)\)&\d+$/.exec(param))) {
param = m[1];
continue;
}
if ((m = /^\(([$_\w()]+)\)\|0$/.exec(param))) {
param = m[1];
continue;
}
if ((m = /^\(([$_\w()]+)\)\>>>0$/.exec(param))) {
param = m[1];
continue;
}
if ((m = /CHECK_OVERFLOW\(([^,)]*),.*/.exec(param))) {
param = m[1];
continue;
}
break;
}
return param;
}
const UNROLL_LOOP_MAX = 8;
function makeCopyValues(dest, src, num, type, modifier, align, sep = ';') {
warn('use of legacy parseTools function: makeCopyValues');
assert(typeof align === 'undefined');
function unroll(type, num, jump = 1) {
const setValues = range(num).map((i) =>
makeSetValue(dest, i * jump, makeGetValue(src, i * jump, type), type),
);
return setValues.join(sep);
}
// If we don't know how to handle this at compile-time, or handling it is best
// done in a large amount of code, call memcpy
if (!isNumber(num)) num = stripCorrections(num);
if (!isNumber(align)) align = stripCorrections(align);
if (!isNumber(num) || parseInt(num) / align >= UNROLL_LOOP_MAX) {
return '(_memcpy(' + dest + ', ' + src + ', ' + num + ')|0)';
}
num = parseInt(num);
// remove corrections, since we will be correcting after we add anyhow,
dest = stripCorrections(dest);
src = stripCorrections(src);
// and in the heap assignment expression
const ret = [];
[4, 2, 1].forEach((possibleAlign) => {
if (num == 0) return;
if (align >= possibleAlign) {
ret.push(unroll('i' + possibleAlign * 8, Math.floor(num / possibleAlign), possibleAlign));
src = getFastValue(src, '+', Math.floor(num / possibleAlign) * possibleAlign);
dest = getFastValue(dest, '+', Math.floor(num / possibleAlign) * possibleAlign);
num %= possibleAlign;
}
});
return ret.join(sep);
}
function makeMalloc(source, param) {
warn('use of legacy parseTools function: makeMalloc');
return `_malloc(${param})`;
}
function getNativeFieldSize(type) {
warn('use of legacy parseTools function: getNativeFieldSize');
return Math.max(getNativeTypeSize(type), POINTER_SIZE);
}
const Runtime = {
getNativeFieldSize,
POINTER_SIZE,
QUANTUM_SIZE: POINTER_SIZE,
};
function addAtMain(code) {
warn('use of legacy parseTools function: addAtMain');
assert(HAS_MAIN, 'addAtMain called but program has no main function');
ATMAINS.push(code);
}
function ensureValidFFIType(type) {
return type === 'float' ? 'double' : type; // ffi does not tolerate float XXX
}
// FFI return values must arrive as doubles, and we can force them to floats afterwards
function asmFFICoercion(value, type) {
value = asmCoercion(value, ensureValidFFIType(type));
if (type === 'float') value = asmCoercion(value, 'float');
return value;
}
// Legacy name for runIfMainThread.
const runOnMainThread = runIfMainThread;
addToCompileTimeContext({
ATMAINS,
Runtime,
addAtMain,
asmFFICoercion,
makeCopyValues,
makeMalloc,
makeStructuralReturn,
receiveI64ParamAsDouble,
receiveI64ParamAsI32s,
runOnMainThread,
});