From 2bd1fb61d58c819980f57c33b1de54f7795a5a9b Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 19 Dec 2024 13:38:20 -0800 Subject: [PATCH] Enable BigInt for binaryen.js We previously had a build option for enabling BigInt support when compiling with Emscripten, but the test suite did not actually pass with it enabled. The problem was that the binaryen.js glue code assumed that C API functions that took i64 parameters would be transformed to take a pair of i32 parameters instead, but this assumption was incorrect when BigInt support was enabled. Emscripten has now enabled BigInt by default, so update binaryen.js to use BigInt as well. Fix the JS API glue code to pass i64s as BigInts rather than pairs of numbers and fix the tests accordingly. Also fix some other small problems with the tests that only show up in debug builds. Resolves #7163. --- CHANGELOG.md | 3 ++ CMakeLists.txt | 17 ++------ src/js/binaryen.js-post.js | 8 ++-- test/binaryen.js/kitchen-sink.js | 62 +++++++++++++-------------- test/binaryen.js/validation_errors.js | 4 +- 5 files changed, 43 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6685533bd3b..466abf7c7a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ full changeset diff at the end of each section. Current Trunk ------------- + - Binaryen.js now builds with BigInt support. The i64.const and f64.const_bits + functions now take BigInt parameters rather than pairs of numbers. + v121 ---- diff --git a/CMakeLists.txt b/CMakeLists.txt index d02096fa06e..095ff439d65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -326,20 +326,9 @@ else() endif() if(EMSCRIPTEN) - # Note: to debug with DWARF you will usually want to enable BIGINT support, as - # that helps avoid running Binaryen on the wasm after link. Binaryen's DWARF - # rewriting has known limitations, so avoiding it during link is recommended - # where possible (like local debugging). - # - # Note that this is debug info for Binaryen itself, that is, when you are - # debugging Binaryen source code. This flag has no impact on what Binaryen - # does when run on wasm files. - option(ENABLE_BIGINT "Enable wasm BigInt support" OFF) - if(ENABLE_BIGINT) - add_link_flag("-sWASM_BIGINT") - else() - add_link_flag("-sWASM_BIGINT=0") - endif() + # This is now on by default in Emscripten, but set it explicitly to continue + # building correctly on older Emscriptens. + add_link_flag("-sWASM_BIGINT") if("${CMAKE_BUILD_TYPE}" MATCHES "Release") # Extra check that cmake has set -O3 in its release flags. diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index c8d8e31ba58..b5c9bd1463a 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -1049,10 +1049,10 @@ function wrapModule(module, self = {}) { 'store32'(offset, align, ptr, value, name) { return Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['i64'], strToStack(name)); }, - 'const'(x, y) { + 'const'(x) { return preserveStack(() => { const tempLiteral = stackAlloc(sizeOfLiteral); - Module['_BinaryenLiteralInt64'](tempLiteral, x, y); + Module['_BinaryenLiteralInt64'](tempLiteral, BigInt(x)); return Module['_BinaryenConst'](module, tempLiteral); }); }, @@ -1438,10 +1438,10 @@ function wrapModule(module, self = {}) { return Module['_BinaryenConst'](module, tempLiteral); }); }, - 'const_bits'(x, y) { + 'const_bits'(x) { return preserveStack(() => { const tempLiteral = stackAlloc(sizeOfLiteral); - Module['_BinaryenLiteralFloat64Bits'](tempLiteral, x, y); + Module['_BinaryenLiteralFloat64Bits'](tempLiteral, BigInt(x)); return Module['_BinaryenConst'](module, tempLiteral); }); }, diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index acef392c377..525debfab59 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -24,8 +24,8 @@ function makeFloat32(x) { return module.f32.const(x); } -function makeInt64(l, h) { - return module.i64.const(l, h); +function makeInt64(x) { + return module.i64.const(x); } function makeFloat64(x) { @@ -214,7 +214,7 @@ function test_core() { constF32 = module.f32.const(3.14), constF64 = module.f64.const(2.1828), constF32Bits = module.f32.const_bits(0xffff1234), - constF64Bits = module.f64.const_bits(0x5678abcd, 0xffff1234); + constF64Bits = module.f64.const_bits(0xffff12345678ABCDn) var iIfF = binaryen.createType([binaryen.i32, binaryen.i64, binaryen.f32, binaryen.f64]) @@ -229,7 +229,7 @@ function test_core() { var valueList = [ // Unary module.i32.clz(module.i32.const(-10)), - module.i64.ctz(module.i64.const(-22, -1)), + module.i64.ctz(module.i64.const(295147905179352825834n)), module.i32.popcnt(module.i32.const(-10)), module.f32.neg(module.f32.const(-33.612)), module.f64.abs(module.f64.const(-9005.841)), @@ -241,7 +241,7 @@ function test_core() { module.i32.eqz(module.i32.const(-10)), module.i64.extend_s(module.i32.const(-10)), module.i64.extend_u(module.i32.const(-10)), - module.i32.wrap(module.i64.const(-22, -1)), + module.i32.wrap(module.i64.const(295147905179352825834n)), module.i32.trunc_s.f32(module.f32.const(-33.612)), module.i64.trunc_s.f32(module.f32.const(-33.612)), module.i32.trunc_u.f32(module.f32.const(-33.612)), @@ -264,18 +264,18 @@ function test_core() { module.f64.convert_s.i32(module.i32.const(-10)), module.f32.convert_u.i32(module.i32.const(-10)), module.f64.convert_u.i32(module.i32.const(-10)), - module.f32.convert_s.i64(module.i64.const(-22, -1)), - module.f64.convert_s.i64(module.i64.const(-22, -1)), - module.f32.convert_u.i64(module.i64.const(-22, -1)), - module.f64.convert_u.i64(module.i64.const(-22, -1)), + module.f32.convert_s.i64(module.i64.const(295147905179352825834n)), + module.f64.convert_s.i64(module.i64.const(295147905179352825834n)), + module.f32.convert_u.i64(module.i64.const(295147905179352825834n)), + module.f64.convert_u.i64(module.i64.const(295147905179352825834n)), module.f64.promote(module.f32.const(-33.612)), module.f32.demote(module.f64.const(-9005.841)), module.f32.reinterpret(module.i32.const(-10)), - module.f64.reinterpret(module.i64.const(-22, -1)), + module.f64.reinterpret(module.i64.const(295147905179352825834n)), module.i8x16.splat(module.i32.const(42)), module.i16x8.splat(module.i32.const(42)), module.i32x4.splat(module.i32.const(42)), - module.i64x2.splat(module.i64.const(123, 456)), + module.i64x2.splat(module.i64.const(1958505087099n)), module.f32x4.splat(module.f32.const(42.0)), module.f64x2.splat(module.f64.const(42.0)), module.v128.not(module.v128.const(v128_bytes)), @@ -333,17 +333,17 @@ function test_core() { module.i32.add(module.i32.const(-10), module.i32.const(-11)), module.f64.sub(module.f64.const(-9005.841), module.f64.const(-9007.333)), module.i32.div_s(module.i32.const(-10), module.i32.const(-11)), - module.i64.div_u(module.i64.const(-22, 0), module.i64.const(-23, 0)), - module.i64.rem_s(module.i64.const(-22, 0), module.i64.const(-23, 0)), + module.i64.div_u(module.i64.const(4294967274n), module.i64.const(4294967273n)), + module.i64.rem_s(module.i64.const(4294967274n), module.i64.const(4294967273n)), module.i32.rem_u(module.i32.const(-10), module.i32.const(-11)), module.i32.and(module.i32.const(-10), module.i32.const(-11)), - module.i64.or(module.i64.const(-22, 0), module.i64.const(-23, 0)), + module.i64.or(module.i64.const(4294967274n), module.i64.const(4294967273n)), module.i32.xor(module.i32.const(-10), module.i32.const(-11)), - module.i64.shl(module.i64.const(-22, 0), module.i64.const(-23, 0)), - module.i64.shr_u(module.i64.const(-22, 0), module.i64.const(-23, 0)), + module.i64.shl(module.i64.const(4294967274n), module.i64.const(4294967273n)), + module.i64.shr_u(module.i64.const(4294967274n), module.i64.const(4294967273n)), module.i32.shr_s(module.i32.const(-10), module.i32.const(-11)), module.i32.rotl(module.i32.const(-10), module.i32.const(-11)), - module.i64.rotr(module.i64.const(-22, 0), module.i64.const(-23, 0)), + module.i64.rotr(module.i64.const(4294967274n), module.i64.const(4294967273n)), module.f32.div(module.f32.const(-33.612), module.f32.const(-62.5)), module.f64.copysign(module.f64.const(-9005.841), module.f64.const(-9007.333)), module.f32.min(module.f32.const(-33.612), module.f32.const(-62.5)), @@ -351,13 +351,13 @@ function test_core() { module.i32.eq(module.i32.const(-10), module.i32.const(-11)), module.f32.ne(module.f32.const(-33.612), module.f32.const(-62.5)), module.i32.lt_s(module.i32.const(-10), module.i32.const(-11)), - module.i64.lt_u(module.i64.const(-22, 0), module.i64.const(-23, 0)), - module.i64.le_s(module.i64.const(-22, 0), module.i64.const(-23, 0)), + module.i64.lt_u(module.i64.const(4294967274n), module.i64.const(4294967273n)), + module.i64.le_s(module.i64.const(4294967274n), module.i64.const(4294967273n)), module.i32.le_u(module.i32.const(-10), module.i32.const(-11)), - module.i64.gt_s(module.i64.const(-22, 0), module.i64.const(-23, 0)), + module.i64.gt_s(module.i64.const(4294967274n), module.i64.const(4294967273n)), module.i32.gt_u(module.i32.const(-10), module.i32.const(-11)), module.i32.ge_s(module.i32.const(-10), module.i32.const(-11)), - module.i64.ge_u(module.i64.const(-22, 0), module.i64.const(-23, 0)), + module.i64.ge_u(module.i64.const(4294967274n), module.i64.const(4294967273n)), module.f32.lt(module.f32.const(-33.612), module.f32.const(-62.5)), module.f64.le(module.f64.const(-9005.841), module.f64.const(-9007.333)), module.f64.gt(module.f64.const(-9005.841), module.f64.const(-9007.333)), @@ -502,7 +502,7 @@ function test_core() { module.i16x8.replace_lane(module.v128.const(v128_bytes), 1, module.i32.const(42)), module.i8x16.replace_lane(module.v128.const(v128_bytes), 1, module.i32.const(42)), module.i32x4.replace_lane(module.v128.const(v128_bytes), 1, module.i32.const(42)), - module.i64x2.replace_lane(module.v128.const(v128_bytes), 1, module.i64.const(42, 43)), + module.i64x2.replace_lane(module.v128.const(v128_bytes), 1, module.i64.const(184683593770n)), module.f32x4.replace_lane(module.v128.const(v128_bytes), 1, module.f32.const(42)), module.f64x2.replace_lane(module.v128.const(v128_bytes), 1, module.f64.const(42)), // SIMD shift @@ -569,7 +569,7 @@ function test_core() { module.switch([ "the-value" ], "the-value", temp8, temp9), module.switch([ "the-nothing" ], "the-nothing", makeInt32(2)), module.i32.eqz( // check the output type of the call node - module.call("kitchen()sinker", [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], binaryen.i32) + module.call("kitchen()sinker", [ makeInt32(13), makeInt64(37), makeFloat32(1.3), makeFloat64(3.7) ], binaryen.i32) ), module.i32.eqz( // check the output type of the call node module.i32.trunc_s.f32( @@ -577,7 +577,7 @@ function test_core() { ) ), module.i32.eqz( // check the output type of the call node - module.call_indirect("t0", makeInt32(2449), [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], iIfF, binaryen.i32) + module.call_indirect("t0", makeInt32(2449), [ makeInt32(13), makeInt64(37), makeFloat32(1.3), makeFloat64(3.7) ], iIfF, binaryen.i32) ), module.drop(module.local.get(0, binaryen.i32)), module.local.set(0, makeInt32(101)), @@ -591,8 +591,8 @@ function test_core() { module.select(temp10, temp11, temp12), module.return(makeInt32(1337)), // Tail Call - module.return_call("kitchen()sinker", [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], binaryen.i32), - module.return_call_indirect("t0", makeInt32(2449), [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], iIfF, binaryen.i32), + module.return_call("kitchen()sinker", [ makeInt32(13), makeInt64(37), makeFloat32(1.3), makeFloat64(3.7) ], binaryen.i32), + module.return_call_indirect("t0", makeInt32(2449), [ makeInt32(13), makeInt64(37), makeFloat32(1.3), makeFloat64(3.7) ], iIfF, binaryen.i32), // Reference types module.ref.is_null(module.ref.null(binaryen.externref)), @@ -636,11 +636,11 @@ function test_core() { // Tuples module.tuple.make( - [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ] + [ makeInt32(13), makeInt64(37), makeFloat32(1.3), makeFloat64(3.7) ] ), module.tuple.extract( module.tuple.make( - [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ] + [ makeInt32(13), makeInt64(37), makeFloat32(1.3), makeFloat64(3.7) ] ), 2 ), @@ -695,11 +695,11 @@ function test_core() { } console.log("getExpressionInfo(i32.const)=" + JSON.stringify(binaryen.getExpressionInfo(module.i32.const(5)))); - console.log("getExpressionInfo(i64.const)=" + JSON.stringify(binaryen.getExpressionInfo(module.i64.const(6, 7)))); + console.log("getExpressionInfo(i64.const)=" + JSON.stringify(binaryen.getExpressionInfo(module.i64.const(30064771078n)))); console.log("getExpressionInfo(f32.const)=" + JSON.stringify(binaryen.getExpressionInfo(module.f32.const(8.5)))); console.log("getExpressionInfo(f64.const)=" + JSON.stringify(binaryen.getExpressionInfo(module.f64.const(9.5)))); var elements = binaryen.getExpressionInfo( - module.tuple.make([ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ]) + module.tuple.make([ makeInt32(13), makeInt64(37), makeFloat32(1.3), makeFloat64(3.7) ]) ).operands; for (var i = 0; i < elements.length; i++) { console.log("getExpressionInfo(tuple[" + i + "])=" + JSON.stringify(binaryen.getExpressionInfo(elements[i]))); @@ -1018,7 +1018,7 @@ function test_nonvalid() { module = new binaryen.Module(); var func = module.addFunction("func", binaryen.none, binaryen.none, [ binaryen.i32 ], - module.local.set(0, makeInt64(1234, 0)) // wrong type! + module.local.set(0, makeInt64(1234)) // wrong type! ); console.log(module.emitText()); diff --git a/test/binaryen.js/validation_errors.js b/test/binaryen.js/validation_errors.js index 57e37d8ba32..b7ee5d00ea8 100644 --- a/test/binaryen.js/validation_errors.js +++ b/test/binaryen.js/validation_errors.js @@ -7,7 +7,7 @@ ) ]) ); - mod.addExport("test", func); + mod.addExport("test", "test"); console.log(mod.validate()) })(); @@ -20,6 +20,6 @@ ) ]) ); - mod.addFunctionExport("test", "test", func); + mod.addFunctionExport("test", "test"); console.log(mod.validate()) })();