diff --git a/src/growableHeap.js b/src/growableHeap.js index 6169ab5909ef6..099df836d0768 100644 --- a/src/growableHeap.js +++ b/src/growableHeap.js @@ -42,6 +42,18 @@ function GROWABLE_HEAP_U32() { } return HEAPU32; } +function GROWABLE_HEAP_I64() { + if (wasmMemory.buffer != HEAP8.buffer) { + updateMemoryViews(); + } + return HEAP64; +} +function GROWABLE_HEAP_U64() { + if (wasmMemory.buffer != HEAP8.buffer) { + updateMemoryViews(); + } + return HEAPU64; +} function GROWABLE_HEAP_F32() { if (wasmMemory.buffer != HEAP8.buffer) { updateMemoryViews(); diff --git a/src/lib/liblittle_endian_heap.js b/src/lib/liblittle_endian_heap.js index 571cea68f462d..1f97eb6530010 100644 --- a/src/lib/liblittle_endian_heap.js +++ b/src/lib/liblittle_endian_heap.js @@ -11,6 +11,12 @@ var LibraryLittleEndianHeap = { $LE_HEAP_STORE_I32: (byteOffset, value) => HEAP_DATA_VIEW.setInt32(byteOffset, value, true), + $LE_HEAP_STORE_U64: (byteOffset, value) => + HEAP_DATA_VIEW.setBigUint64(byteOffset, value, true), + + $LE_HEAP_STORE_I64: (byteOffset, value) => + HEAP_DATA_VIEW.setBigInt64(byteOffset, value, true), + $LE_HEAP_STORE_F32: (byteOffset, value) => HEAP_DATA_VIEW.setFloat32(byteOffset, value, true), @@ -29,6 +35,12 @@ var LibraryLittleEndianHeap = { $LE_HEAP_LOAD_I32: (byteOffset) => HEAP_DATA_VIEW.getInt32(byteOffset, true), + $LE_HEAP_LOAD_U64: (byteOffset) => + HEAP_DATA_VIEW.getBigUint64(byteOffset, true), + + $LE_HEAP_LOAD_I64: (byteOffset) => + HEAP_DATA_VIEW.getBigInt64(byteOffset, true), + $LE_HEAP_LOAD_F32: (byteOffset) => HEAP_DATA_VIEW.getFloat32(byteOffset, true), diff --git a/src/modules.mjs b/src/modules.mjs index b03cdfe9008d9..cd5ef5fc51694 100644 --- a/src/modules.mjs +++ b/src/modules.mjs @@ -462,6 +462,8 @@ function exportRuntimeSymbols() { 'GROWABLE_HEAP_U16', 'GROWABLE_HEAP_I32', 'GROWABLE_HEAP_U32', + 'GROWABLE_HEAP_I64', + 'GROWABLE_HEAP_U64', 'GROWABLE_HEAP_F32', 'GROWABLE_HEAP_F64', ); diff --git a/src/runtime_asan.js b/src/runtime_asan.js index babc684d04ffc..dd32df2aab2b7 100644 --- a/src/runtime_asan.js +++ b/src/runtime_asan.js @@ -43,6 +43,16 @@ function _asan_js_load_4u(ptr) { return HEAPU32[ptr]; } /** @suppress{duplicate} */ +function _asan_js_load_8(ptr) { + if (runtimeInitialized) return __asan_c_load_8(ptr); + return HEAP64[ptr]; +} +/** @suppress{duplicate} */ +function _asan_js_load_8u(ptr) { + if (runtimeInitialized) return BigInt.asUintN(64, __asan_c_load_8u(ptr)); + return HEAPU64[ptr]; +} +/** @suppress{duplicate} */ function _asan_js_load_f(ptr) { if (runtimeInitialized) return __asan_c_load_f(ptr); return HEAPF32[ptr]; @@ -84,6 +94,19 @@ function _asan_js_store_4u(ptr, val) { return HEAPU32[ptr] = val; } /** @suppress{duplicate} */ +function _asan_js_store_8(ptr, val) { + if (runtimeInitialized) return __asan_c_store_8(ptr, val); + return HEAP64[ptr] = val; +} +/** @suppress{duplicate} */ +function _asan_js_store_8u(ptr, val) { + if (runtimeInitialized) { + __asan_c_store_8u(ptr, val); + return val; + } + return HEAPU64[ptr] = val; +} +/** @suppress{duplicate} */ function _asan_js_store_f(ptr, val) { if (runtimeInitialized) return __asan_c_store_f(ptr, val); return HEAPF32[ptr] = val; diff --git a/system/lib/asan_js.c b/system/lib/asan_js.c index 58e4e97dc24cd..a349270479ea6 100644 --- a/system/lib/asan_js.c +++ b/system/lib/asan_js.c @@ -45,6 +45,14 @@ uint32_t _asan_c_load_4u(uintptr_t shifted) { uint32_t* ptr = (uint32_t*)(shifted << 2); return *ptr; } +int64_t _asan_c_load_8(uintptr_t shifted) { + int64_t* ptr = (int64_t*)(shifted << 3); + return *ptr; +} +uint64_t _asan_c_load_8u(uintptr_t shifted) { + uint64_t* ptr = (uint64_t*)(shifted << 3); + return *ptr; +} float _asan_c_load_f(uintptr_t shifted) { float* ptr = (float*)(shifted << 2); return *ptr; @@ -79,6 +87,14 @@ uint32_t _asan_c_store_4u(uintptr_t shifted, uint32_t val) { uint32_t* ptr = (uint32_t*)(shifted << 2); return *ptr = val; } +int64_t _asan_c_store_8(uintptr_t shifted, int64_t val) { + int64_t* ptr = (int64_t*)(shifted << 3); + return *ptr = val; +} +uint64_t _asan_c_store_8u(uintptr_t shifted, uint64_t val) { + uint64_t* ptr = (uint64_t*)(shifted << 3); + return *ptr = val; +} float _asan_c_store_f(uintptr_t shifted, float val) { float* ptr = (float*)(shifted << 2); return *ptr = val; diff --git a/test/js_optimizer/asanify-output.js b/test/js_optimizer/asanify-output.js index 099b88c616f25..6308bf7e8afc8 100644 --- a/test/js_optimizer/asanify-output.js +++ b/test/js_optimizer/asanify-output.js @@ -14,6 +14,10 @@ _asan_js_store_f(x, 7); _asan_js_store_d(x, 8); +_asan_js_store_8(x, 9n); + +_asan_js_store_8u(x, 10n); + a1 = _asan_js_load_1(x); a2 = _asan_js_load_2(x); @@ -30,6 +34,10 @@ a7 = _asan_js_load_f(x); a8 = _asan_js_load_d(x); +a9 = _asan_js_load_8(x); + +a10 = _asan_js_load_8u(x); + foo = _asan_js_store_1u(1337, 42); _asan_js_load_2(bar(_asan_js_load_d(5))); diff --git a/test/js_optimizer/asanify.js b/test/js_optimizer/asanify.js index 6d8ff13cddb89..bba03a1d5da90 100644 --- a/test/js_optimizer/asanify.js +++ b/test/js_optimizer/asanify.js @@ -7,6 +7,8 @@ HEAPU16[x] = 5; HEAPU32[x] = 6; HEAPF32[x] = 7; HEAPF64[x] = 8; +HEAP64[x] = 9n; +HEAPU64[x] = 10n; // loads a1 = HEAP8[x]; @@ -17,6 +19,8 @@ a5 = HEAPU16[x]; a6 = HEAPU32[x]; a7 = HEAPF32[x]; a8 = HEAPF64[x]; +a9 = HEAP64[x]; +a10 = HEAPU64[x]; // store return value foo = HEAPU8[1337] = 42; diff --git a/test/js_optimizer/growableHeap-output.js b/test/js_optimizer/growableHeap-output.js index 8ad2f21f2afec..0e70a486b170c 100644 --- a/test/js_optimizer/growableHeap-output.js +++ b/test/js_optimizer/growableHeap-output.js @@ -3,6 +3,7 @@ function f() { GROWABLE_HEAP_I32()[$0 >> 2] = $2 + 1; $9 = GROWABLE_HEAP_U8()[$2 >> 0] | 0; +GROWABLE_HEAP_F64()[x >> 3]; + GROWABLE_HEAP_I64()[x >> 3] = GROWABLE_HEAP_I64()[y >> 3]; } function libraryFunc(ptr, val) { diff --git a/test/js_optimizer/growableHeap.js b/test/js_optimizer/growableHeap.js index e7b92ec8e8a9e..c14766733c7bd 100644 --- a/test/js_optimizer/growableHeap.js +++ b/test/js_optimizer/growableHeap.js @@ -3,6 +3,7 @@ function f() { HEAP32[$0 >> 2] = $2 + 1; $9 = HEAPU8[$2 >> 0] | 0; +HEAPF64[x >> 3]; + HEAP64[x >> 3] = HEAP64[y >> 3]; } function libraryFunc(ptr, val) { diff --git a/test/js_optimizer/safeHeap-output.js b/test/js_optimizer/safeHeap-output.js index e6e06c7740e50..cc7bfddca7e77 100644 --- a/test/js_optimizer/safeHeap-output.js +++ b/test/js_optimizer/safeHeap-output.js @@ -14,6 +14,10 @@ SAFE_HEAP_STORE_D(x * 4, 7, 4); SAFE_HEAP_STORE_D(x * 8, 8, 8); +SAFE_HEAP_STORE(x * 8, 9n, 8); + +SAFE_HEAP_STORE(x * 8, 10n, 8); + a1 = SAFE_HEAP_LOAD(x, 1, 0); a2 = SAFE_HEAP_LOAD(x * 2, 2, 0); @@ -30,6 +34,10 @@ a7 = SAFE_HEAP_LOAD_D(x * 4, 4, 0); a8 = SAFE_HEAP_LOAD_D(x * 8, 8, 0); +a9 = SAFE_HEAP_LOAD(x * 8, 8, 0); + +a10 = SAFE_HEAP_LOAD(x * 8, 8, 1); + foo = SAFE_HEAP_STORE(1337, 42, 1); SAFE_HEAP_LOAD(bar(SAFE_HEAP_LOAD_D(5 * 8, 8, 0)) * 2, 2, 0); diff --git a/test/js_optimizer/safeHeap.js b/test/js_optimizer/safeHeap.js index 8f5e567101257..0f6a88b108b06 100644 --- a/test/js_optimizer/safeHeap.js +++ b/test/js_optimizer/safeHeap.js @@ -7,6 +7,8 @@ HEAPU16[x] = 5; HEAPU32[x] = 6; HEAPF32[x] = 7; HEAPF64[x] = 8; +HEAP64[x] = 9n; +HEAPU64[x] = 10n; // loads a1 = HEAP8[x]; @@ -17,6 +19,8 @@ a5 = HEAPU16[x]; a6 = HEAPU32[x]; a7 = HEAPF32[x]; a8 = HEAPF64[x]; +a9 = HEAP64[x]; +a10 = HEAPU64[x]; // store return value foo = HEAPU8[1337] = 42; diff --git a/test/js_optimizer/unsignPointers-output.js b/test/js_optimizer/unsignPointers-output.js index 69f9beaa63506..3a87c8980708c 100644 --- a/test/js_optimizer/unsignPointers-output.js +++ b/test/js_optimizer/unsignPointers-output.js @@ -27,13 +27,16 @@ HEAPU8.subarray(x >>> 0); HEAPU8.subarray(x >>> 0, y >>> 0); +// something completely different process.versions.node; -// something completely different insideCall(HEAP32[x >>> 2]); heap[x >>> 0]; HEAP[x >>> 0]; +// but not this HeAp[x]; + +HEAP64[x >>> 3] = HEAPU64[y >>> 0]; diff --git a/test/js_optimizer/unsignPointers.js b/test/js_optimizer/unsignPointers.js index 93159f496571e..7494d3c94d59c 100644 --- a/test/js_optimizer/unsignPointers.js +++ b/test/js_optimizer/unsignPointers.js @@ -30,7 +30,8 @@ HEAPU8.subarray(x); HEAPU8.subarray(x, y); -process.versions.node; // something completely different +// something completely different +process.versions.node; insideCall(HEAP32[x >> 2]); @@ -38,4 +39,7 @@ heap[x]; HEAP[x]; -HeAp[x]; // but not this +// but not this +HeAp[x]; + +HEAP64[x >> 3] = HEAPU64[y]; diff --git a/tools/acorn-optimizer.mjs b/tools/acorn-optimizer.mjs index 50e5cb9de3d17..379412e20349f 100755 --- a/tools/acorn-optimizer.mjs +++ b/tools/acorn-optimizer.mjs @@ -1114,6 +1114,8 @@ function isEmscriptenHEAP(name) { case 'HEAPU16': case 'HEAP32': case 'HEAPU32': + case 'HEAP64': + case 'HEAPU64': case 'HEAPF32': case 'HEAPF64': { return true; @@ -1182,6 +1184,16 @@ function littleEndianHeap(ast) { makeCallExpression(node, 'LE_HEAP_STORE_U32', [multiply(idx, 4), value]); break; } + case 'HEAP64': { + // change "name[idx] = value" to "LE_HEAP_STORE_I64(idx*8, value)" + makeCallExpression(node, 'LE_HEAP_STORE_I64', [multiply(idx, 8), value]); + break; + } + case 'HEAPU64': { + // change "name[idx] = value" to "LE_HEAP_STORE_U64(idx*8, value)" + makeCallExpression(node, 'LE_HEAP_STORE_U64', [multiply(idx, 8), value]); + break; + } case 'HEAPF32': { // change "name[idx] = value" to "LE_HEAP_STORE_F32(idx*4, value)" makeCallExpression(node, 'LE_HEAP_STORE_F32', [multiply(idx, 4), value]); @@ -1250,6 +1262,16 @@ function littleEndianHeap(ast) { makeCallExpression(node, 'LE_HEAP_LOAD_U32', [multiply(idx, 4)]); break; } + case 'HEAP64': { + // change "name[idx]" to "LE_HEAP_LOAD_I64(idx*8)" + makeCallExpression(node, 'LE_HEAP_LOAD_I64', [multiply(idx, 8)]); + break; + } + case 'HEAPU64': { + // change "name[idx]" to "LE_HEAP_LOAD_U64(idx*8)" + makeCallExpression(node, 'LE_HEAP_LOAD_U64', [multiply(idx, 8)]); + break; + } case 'HEAPF32': { // change "name[idx]" to "LE_HEAP_LOAD_F32(idx*4)" makeCallExpression(node, 'LE_HEAP_LOAD_F32', [multiply(idx, 4)]); @@ -1328,6 +1350,14 @@ function growableHeap(ast) { makeCallExpression(node, 'GROWABLE_HEAP_U32', []); break; } + case 'HEAP64': { + makeCallExpression(node, 'GROWABLE_HEAP_I64', []); + break; + } + case 'HEAPU64': { + makeCallExpression(node, 'GROWABLE_HEAP_U64', []); + break; + } case 'HEAPF32': { makeCallExpression(node, 'GROWABLE_HEAP_F32', []); break; @@ -1470,6 +1500,14 @@ function asanify(ast) { makeCallExpression(node, '_asan_js_store_4u', [ptr, value]); break; } + case 'HEAP64': { + makeCallExpression(node, '_asan_js_store_8', [ptr, value]); + break; + } + case 'HEAPU64': { + makeCallExpression(node, '_asan_js_store_8u', [ptr, value]); + break; + } case 'HEAPF32': { makeCallExpression(node, '_asan_js_store_f', [ptr, value]); break; @@ -1515,6 +1553,14 @@ function asanify(ast) { makeCallExpression(node, '_asan_js_load_4u', [ptr]); break; } + case 'HEAP64': { + makeCallExpression(node, '_asan_js_load_8', [ptr]); + break; + } + case 'HEAPU64': { + makeCallExpression(node, '_asan_js_load_8u', [ptr]); + break; + } case 'HEAPF32': { makeCallExpression(node, '_asan_js_load_f', [ptr]); break; @@ -1585,6 +1631,15 @@ function safeHeap(ast) { ]); break; } + case 'HEAP64': + case 'HEAPU64': { + makeCallExpression(node, 'SAFE_HEAP_STORE', [ + multiply(ptr, 8), + value, + createLiteral(8), + ]); + break; + } case 'HEAPF32': { makeCallExpression(node, 'SAFE_HEAP_STORE_D', [ multiply(ptr, 4), @@ -1654,6 +1709,22 @@ function safeHeap(ast) { ]); break; } + case 'HEAP64': { + makeCallExpression(node, 'SAFE_HEAP_LOAD', [ + multiply(ptr, 8), + createLiteral(8), + createLiteral(0), + ]); + break; + } + case 'HEAPU64': { + makeCallExpression(node, 'SAFE_HEAP_LOAD', [ + multiply(ptr, 8), + createLiteral(8), + createLiteral(1), + ]); + break; + } case 'HEAPF32': { makeCallExpression(node, 'SAFE_HEAP_LOAD_D', [ multiply(ptr, 4), diff --git a/tools/emscripten.py b/tools/emscripten.py index b3c2801f2370a..b1660fd6b0e75 100644 --- a/tools/emscripten.py +++ b/tools/emscripten.py @@ -44,10 +44,12 @@ '_asan_c_load_1', '_asan_c_load_1u', '_asan_c_load_2', '_asan_c_load_2u', '_asan_c_load_4', '_asan_c_load_4u', + '_asan_c_load_8', '_asan_c_load_8u', '_asan_c_load_f', '_asan_c_load_d', '_asan_c_store_1', '_asan_c_store_1u', '_asan_c_store_2', '_asan_c_store_2u', '_asan_c_store_4', '_asan_c_store_4u', + '_asan_c_store_8', '_asan_c_store_8u', '_asan_c_store_f', '_asan_c_store_d', ]