| /** |
| * @license |
| * Copyright 2010 The Emscripten Authors |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| // 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) { |
| 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) { |
| 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 stripCorrections(param) { |
| 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 = ';') { |
| 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); |
| } |