From 555e671b6e9d04ab9f40959fcbdc291b47305b63 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sat, 5 Apr 2025 13:13:59 +0500 Subject: [PATCH 01/29] Add br_on_*, struct.* and array.* functions to Binaryen.js --- src/js/binaryen.js-post.js | 91 +++++++++++++++++++++++++++++++++++--- test/binaryen.js/gc.js | 5 +++ test/binaryen.js/gc.txt | 0 3 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 test/binaryen.js/gc.js create mode 100644 test/binaryen.js/gc.txt diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 6d886d26b1d..d8bd05a8270 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -2333,6 +2333,12 @@ function wrapModule(module, self = {}) { }, 'eq'(left, right) { return Module['_BinaryenRefEq'](module, left, right); + }, + 'test'(value, castType) { + return Module['_BinaryenRefTest'](module, value, castType); + }, + 'cast'(value, castType) { + return Module['_BinaryenRefCast'](module, value, castType); } }; @@ -2387,15 +2393,86 @@ function wrapModule(module, self = {}) { } }; - // TODO: any.convert_extern - // TODO: extern.convert_any - // TODO: ref.test - // TODO: ref.cast - // TODO: br_on_* - // TODO: struct.* - // TODO: array.* + self['any'] = { + 'convert_extern'() { + return Module['_BinaryenRefAsAnyConvertExtern'](); + } + }; + + self['extern'] = { + 'convert_any'() { + return Module['_BinaryenRefAsExternConvertAny'](); + } + }; + + self['br_on_null'] = function(name, value, castType) { + return Module['_BinaryenBrOn'](module, Module['BrOnNull'], strToStack(name), value, castType); + }; + + self['br_on_non_null'] = function(name, value, castType) { + return Module['_BinaryenBrOn'](module, Module['BrOnNonNull'], strToStack(name), value, castType); + }; + + self['br_on_cast'] = function(name, value, castType) { + return Module['_BinaryenBrOn'](module, Module['BrOnCast'], strToStack(name), value, castType); + }; + + self['br_on_cast_fail'] = function(name, value, castType) { + return Module['_BinaryenBrOn'](module, Module['BrOnCastFail'], strToStack(name), value, castType); + }; + + self['struct'] = { + 'new'(operands, type) { + return Module['_BinaryenStructNew'](module, i32sToStack(operands), operands.length, type); + }, + 'new_default'(type) { + // Passing in null for |operands| (and 0 for |numOperands|) implies this is + // struct.new_default. + return Module['_BinaryenStructNew'](module, 0, 0, type); + }, + 'get'(index, ref, type, isSigned) { + return Module['_BinaryenStructGet'](module, index, ref, type, isSigned); + }, + 'set'(index, ref, value) { + return Module['_BinaryenStructSet'](module, index, ref, value); + } + }; + + self['array'] = { + 'new'(type, size, init) { + return Module['_BinaryenArrayNew'](module, type, size, init); + }, + 'new_default'(type, size) { + return Module['_BinaryenArrayNew'](module, type, size, 0); + }, + 'new_fixed'(type, values) { + return Module['_BinaryenArrayNewFixed'](module, type, i32sToStack(values), values.length); + }, + 'new_data'(type, name, offset, size) { + return Module['_BinaryenArrayNewData'](module, type, strToStack(name), offset, size); + }, + // TODO: array.new_elem + 'get'(ref, index, type, isSigned) { + return Module['_BinaryenArrayGet'](module, ref, index, type, isSigned); + }, + 'set'(ref, index, value) { + return Module['_BinaryenArraySet'](module, ref, index, value); + }, + 'len'(ref) { + return Module['_BinaryenArrayLen'](module, ref); + }, + // TODO: array.fill + 'copy'(destRef, destIndex, srcRef, srcIndex, length) { + return Module['_BinaryenArrayCopy'](destRef, destIndex, srcRef, srcIndex, length); + }, + // TODO: array.init_data + // TODO: array.init_elem + }; + // TODO: string.* + // TODO: API for creating and modifying GC types + // 'Module' operations self['addFunction'] = function(name, params, results, varTypes, body) { return preserveStack(() => diff --git a/test/binaryen.js/gc.js b/test/binaryen.js/gc.js new file mode 100644 index 00000000000..3720e7cfc4d --- /dev/null +++ b/test/binaryen.js/gc.js @@ -0,0 +1,5 @@ +var module = new binaryen.Module(); + +// TODO + +console.log(module.emitText()); diff --git a/test/binaryen.js/gc.txt b/test/binaryen.js/gc.txt new file mode 100644 index 00000000000..e69de29bb2d From fcb5ac7f2e9bcef09c6267652c68a575395f3555 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sat, 5 Apr 2025 23:14:44 +0500 Subject: [PATCH 02/29] Add TypeBuilder API --- src/js/binaryen.js-post.js | 72 ++++++++++++++++++++++++++++++++++++-- test/binaryen.js/gc.js | 15 +++++++- test/binaryen.js/gc.js.txt | 3 ++ test/binaryen.js/gc.txt | 0 4 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 test/binaryen.js/gc.js.txt delete mode 100644 test/binaryen.js/gc.txt diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index d8bd05a8270..bfb69201eda 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -46,6 +46,13 @@ function initializeConstants() { Module[entry[0]] = Module['_BinaryenType' + entry[1]](); }); + [ ['notPacked', 'NotPacked'], + ['i8', 'Int8'], + ['i16', 'Int16'] + ].forEach(entry => { + Module[entry[0]] = Module['_BinaryenPackedType' + entry[1]](); + }); + // Expression ids Module['ExpressionIds'] = {}; [ 'Invalid', @@ -2471,8 +2478,6 @@ function wrapModule(module, self = {}) { // TODO: string.* - // TODO: API for creating and modifying GC types - // 'Module' operations self['addFunction'] = function(name, params, results, varTypes, body) { return preserveStack(() => @@ -2801,6 +2806,69 @@ function wrapModule(module, self = {}) { } Module['wrapModule'] = wrapModule; +// 'TypeBuilder' interface +/** @constructor */ +Module['TypeBuilder'] = function(size) { + const builder = Module['_TypeBuilderCreate'](size); + this['ptr'] = builder; + + this['grow'] = function(count) { + Module['_TypeBuilderGrow'](builder, count); + }; + this['getSize'] = function() { + return Module['_TypeBuilderGetSize'](builder); + }; + this['setSignatureType'] = function(index, paramTypes, resultTypes) { + Module['_TypeBuilderSetSignatureType'](builder, index, paramTypes, resultTypes); + }; + this['setStructType'] = function(index, fields) { + preserveStack(() => { + const numFields = fields.length; + const types = new Array(numFields); + const packedTypes = new Array(numFields); + const mutables = new Array(numFields); + for (let i = 0; i < numFields; i++) { + const { type, packedType, mutable } = fields[i]; + types[i] = type; + packedTypes[i] = packedType ?? Module['notPacked']; + mutables[i] = mutable; + } + Module['_TypeBuilderSetStructType'](builder, + index, + i32sToStack(types), i32sToStack(packedTypes), + i8sToStack(mutables) + ); + }); + }; + this['setArrayType'] = function(index, elementType, elementPackedType, elementMutable) { + Module['_TypeBuilderSetArrayType'](builder, + index, elementType, elementPackedType, elementMutable + ); + }; + this['buildAndDispose'] = function() { + return preserveStack(() => { + const numTypes = this['getSize'](); + const array = stackAlloc(numTypes << 2); + Module['_TypeBuilderBuildAndDispose'](builder, array, 0, 0); // TODO: Handle errors + const types = new Array(numTypes); + for (let i = 0; i < numTypes; i++) { + types[i] = HEAPU32[(array >>> 2) + i]; + } + return types; + }); + }; +} + +// Gets the type from a heap type generated by TypeBuilder +Module['getTypeFromHeapType'] = function(heapType, nullable) { + return Module['_BinaryenTypeFromHeapType'](heapType, nullable); +}; + +// Gets the heap type of a type +Module['getHeapType'] = function(type) { + return Module['_BinaryenTypeGetHeapType'](type); +}; + // 'Relooper' interface /** @constructor */ Module['Relooper'] = function(module) { diff --git a/test/binaryen.js/gc.js b/test/binaryen.js/gc.js index 3720e7cfc4d..acba77a68b2 100644 --- a/test/binaryen.js/gc.js +++ b/test/binaryen.js/gc.js @@ -1,5 +1,18 @@ var module = new binaryen.Module(); -// TODO +var builder = new binaryen.TypeBuilder(1); +builder.setArrayType(0, binaryen.i32); +var [arrayHeapType] = builder.buildAndDispose(); + +var arrayType = binaryen.getTypeFromHeapType(arrayHeapType); + +module.addGlobal("global-array", + arrayType, + true, + module.array.new_default( + binaryen.getHeapType(arrayType), + module.i32.const(4) + ) +); console.log(module.emitText()); diff --git a/test/binaryen.js/gc.js.txt b/test/binaryen.js/gc.js.txt new file mode 100644 index 00000000000..fdfb985f6f6 --- /dev/null +++ b/test/binaryen.js/gc.js.txt @@ -0,0 +1,3 @@ +(module +) + diff --git a/test/binaryen.js/gc.txt b/test/binaryen.js/gc.txt deleted file mode 100644 index e69de29bb2d..00000000000 From 49cddc85cd656135bbaa239a9f7317602072e1a5 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sun, 6 Apr 2025 00:26:34 +0500 Subject: [PATCH 03/29] Complete TypeBuilder API & add misc functions + basic tests --- src/js/binaryen.js-post.js | 30 +++++++++++++++ test/binaryen.js/gc.js | 76 ++++++++++++++++++++++++++++++++------ 2 files changed, 95 insertions(+), 11 deletions(-) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index bfb69201eda..896f022221f 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -2685,6 +2685,16 @@ function wrapModule(module, self = {}) { self['setFeatures'] = function(features) { Module['_BinaryenModuleSetFeatures'](module, features); }; + self['setTypeName'] = function(heapType, name) { + return preserveStack(() => + Module['_BinaryenModuleSetTypeName'](module, heapType, strToStack(name)) + ); + }; + self['setFieldName'] = function(heapType, index, name) { + return preserveStack(() => + Module['_BinaryenModuleSetFieldName'](module, heapType, index, strToStack(name)) + ); + }; self['addCustomSection'] = function(name, contents) { return preserveStack(() => Module['_BinaryenAddCustomSection'](module, strToStack(name), i8sToStack(contents), contents.length) @@ -2845,6 +2855,26 @@ Module['TypeBuilder'] = function(size) { index, elementType, elementPackedType, elementMutable ); }; + this['getTempHeapType'] = function(index) { + return Module['_TypeBuilderGetTempHeapType'](builder, index); + }; + this['getTempTupleType'] = function(types) { + return preserveStack(() => { + return Module['_TypeBuilderGetTempTupleType'](builder, i32sToStack(types), types.length); + }); + }; + this['getTempRefType'] = function(heapType, nullable) { + return Module['_TypeBuilderGetTempRefType'](builder, heapType, nullable); + }; + this['setSubType'] = function(index, superType) { + Module['_TypeBuilderSetSubType'](builder, index, superType); + }; + this['setOpen'] = function(index) { + Module['_TypeBuilderSetOpen'](builder, index); + }; + this['createRecGroup'] = function(index, length) { + Module['_TypeBuilderCreateRecGroup'](builder, index, length); + }; this['buildAndDispose'] = function() { return preserveStack(() => { const numTypes = this['getSize'](); diff --git a/test/binaryen.js/gc.js b/test/binaryen.js/gc.js index acba77a68b2..a01ffaafdcc 100644 --- a/test/binaryen.js/gc.js +++ b/test/binaryen.js/gc.js @@ -1,18 +1,72 @@ -var module = new binaryen.Module(); - var builder = new binaryen.TypeBuilder(1); -builder.setArrayType(0, binaryen.i32); -var [arrayHeapType] = builder.buildAndDispose(); +builder.setSignatureType(0, binaryen.i32, binaryen.notPacked, true); +builder.setStructType(1, binaryen.i32, binaryen.notPacked, true); +builder.setArrayType(2, binaryen.i32, binaryen.notPacked, true); +var [ + signatureHeapType, + structHeapType, + arrayHeapType +] = builder.buildAndDispose(); +var signatureType = binaryen.getTypeFromHeapType(signatureHeapType); +var structType = binaryen.getTypeFromHeapType(structHeapType); var arrayType = binaryen.getTypeFromHeapType(arrayHeapType); -module.addGlobal("global-array", - arrayType, - true, - module.array.new_default( - binaryen.getHeapType(arrayType), - module.i32.const(4) - ) +var module = new binaryen.Module(); +module.setFeatures(binaryen.Features.ReferenceTypes | binaryen.Features.GC); + +module.setMemory(1, -1, null, [ + { offset: 0, data: [4, 3, 2, 1] } +]); + +module.addGlobal("global-array.new", + arrayType, + true, + module.array.new( + binaryen.getHeapType(arrayType), + module.i32.const(4), + module.i32.const(123) + ) +); + +module.addGlobal("global-array.new_default", + arrayType, + true, + module.array.new_default( + binaryen.getHeapType(arrayType), + module.i32.const(4) + ) +); + +module.addGlobal("global-array.new_fixed", + arrayType, + true, + module.array.new_fixed( + binaryen.getHeapType(arrayType), + [ + module.i32.const(1), + module.i32.const(2), + module.i32.const(3), + module.i32.const(4) + ] + ) +); + +module.addGlobal("global-array.new_data", + arrayType, + true, + module.array.new_data( + binaryen.getHeapType(arrayType), + "0", + module.i32.const(0), + module.i32.const(4) + ) +); + +module.addFunction("main", binaryen.none, binaryen.none, [], + module.block(null, [ + // ... + ], binaryen.none) ); console.log(module.emitText()); From 25e93944754de1c85b93663c6ec3731553bab3fd Mon Sep 17 00:00:00 2001 From: GulgDev Date: Tue, 8 Apr 2025 12:18:33 +0500 Subject: [PATCH 04/29] Update tests & fix GC API --- src/js/binaryen.js-post.js | 15 ++++--- test/binaryen.js/gc.js | 86 ++++++++++++++++++++++++++++++-------- test/binaryen.js/gc.js.txt | 61 +++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 24 deletions(-) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 896f022221f..4bf8ecf2bc4 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -2470,7 +2470,7 @@ function wrapModule(module, self = {}) { }, // TODO: array.fill 'copy'(destRef, destIndex, srcRef, srcIndex, length) { - return Module['_BinaryenArrayCopy'](destRef, destIndex, srcRef, srcIndex, length); + return Module['_BinaryenArrayCopy'](module, destRef, destIndex, srcRef, srcIndex, length); }, // TODO: array.init_data // TODO: array.init_elem @@ -2831,22 +2831,24 @@ Module['TypeBuilder'] = function(size) { this['setSignatureType'] = function(index, paramTypes, resultTypes) { Module['_TypeBuilderSetSignatureType'](builder, index, paramTypes, resultTypes); }; - this['setStructType'] = function(index, fields) { + this['setStructType'] = function(index, fields = []) { + // fields are assumed to be { type: type ref, packedType: type ref, mutable: bool } preserveStack(() => { const numFields = fields.length; const types = new Array(numFields); const packedTypes = new Array(numFields); const mutables = new Array(numFields); for (let i = 0; i < numFields; i++) { - const { type, packedType, mutable } = fields[i]; + const { ['type']: type, ['packedType']: packedType, ['mutable']: mutable } = fields[i]; types[i] = type; - packedTypes[i] = packedType ?? Module['notPacked']; + packedTypes[i] = packedType; mutables[i] = mutable; } Module['_TypeBuilderSetStructType'](builder, index, i32sToStack(types), i32sToStack(packedTypes), - i8sToStack(mutables) + i8sToStack(mutables), + numFields ); }); }; @@ -2879,7 +2881,8 @@ Module['TypeBuilder'] = function(size) { return preserveStack(() => { const numTypes = this['getSize'](); const array = stackAlloc(numTypes << 2); - Module['_TypeBuilderBuildAndDispose'](builder, array, 0, 0); // TODO: Handle errors + if (!Module['_TypeBuilderBuildAndDispose'](builder, array, 0, 0)) + throw new TypeError('TypeBuilder.buildAndDispose failed'); const types = new Array(numTypes); for (let i = 0; i < numTypes; i++) { types[i] = HEAPU32[(array >>> 2) + i]; diff --git a/test/binaryen.js/gc.js b/test/binaryen.js/gc.js index a01ffaafdcc..d69e2e1a279 100644 --- a/test/binaryen.js/gc.js +++ b/test/binaryen.js/gc.js @@ -1,6 +1,9 @@ -var builder = new binaryen.TypeBuilder(1); -builder.setSignatureType(0, binaryen.i32, binaryen.notPacked, true); -builder.setStructType(1, binaryen.i32, binaryen.notPacked, true); +var builder = new binaryen.TypeBuilder(3); +builder.setSignatureType(0, binaryen.createType([binaryen.i32]), binaryen.none); +builder.setStructType(1, [ + { type: binaryen.i32, packedType: binaryen.notPacked, mutable: true }, + { type: binaryen.f64, packedType: binaryen.notPacked, mutable: true } +]); builder.setArrayType(2, binaryen.i32, binaryen.notPacked, true); var [ signatureHeapType, @@ -13,12 +16,32 @@ var structType = binaryen.getTypeFromHeapType(structHeapType); var arrayType = binaryen.getTypeFromHeapType(arrayHeapType); var module = new binaryen.Module(); -module.setFeatures(binaryen.Features.ReferenceTypes | binaryen.Features.GC); +module.setFeatures(binaryen.Features.ReferenceTypes | binaryen.Features.BulkMemory | binaryen.Features.GC); module.setMemory(1, -1, null, [ - { offset: 0, data: [4, 3, 2, 1] } + { offset: module.i32.const(0), data: [4, 3, 2, 1] } ]); +module.addGlobal("global-struct.new", + structType, + true, + module.struct.new( + [ + module.i32.const(123), + module.f64.const(123.456) + ], + binaryen.getHeapType(structType) + ) +); + +module.addGlobal("global-struct.new_default", + structType, + true, + module.struct.new_default( + binaryen.getHeapType(structType) + ) +); + module.addGlobal("global-array.new", arrayType, true, @@ -52,21 +75,48 @@ module.addGlobal("global-array.new_fixed", ) ); -module.addGlobal("global-array.new_data", - arrayType, - true, - module.array.new_data( - binaryen.getHeapType(arrayType), - "0", - module.i32.const(0), - module.i32.const(4) - ) -); - -module.addFunction("main", binaryen.none, binaryen.none, [], +module.addFunction("main", binaryen.none, binaryen.none, [binaryen.i32, binaryen.f64], module.block(null, [ - // ... + module.global.set("global-array.new_default", + module.array.new_data( + binaryen.getHeapType(arrayType), + "0", + module.i32.const(0), + module.i32.const(4) + ) + ), + + module.array.copy( + module.global.get("global-array.new_fixed", arrayType), + module.i32.const(0), + module.global.get("global-array.new_default", arrayType), + module.i32.const(0), + module.array.len( + module.global.get("global-array.new_default", arrayType) + ) + ), + module.array.set( + module.global.get("global-array.new", arrayType), + module.i32.const(2), + module.array.get( + module.global.get("global-array.new_default", arrayType), + module.i32.const(0), + binaryen.i32, + false + ) + ), + + module.local.set(0, module.struct.get(0, module.global.get("global-struct.new", structType), false)), + module.struct.set( + 1, + module.global.get("global-struct.new_default", structType), + module.f64.convert_u.i32( + module.local.get(0, binaryen.i32) + ) + ) ], binaryen.none) ); +assert(module.validate()); + console.log(module.emitText()); diff --git a/test/binaryen.js/gc.js.txt b/test/binaryen.js/gc.js.txt index fdfb985f6f6..42dd68b6e3c 100644 --- a/test/binaryen.js/gc.js.txt +++ b/test/binaryen.js/gc.js.txt @@ -1,3 +1,64 @@ (module + (type $0 (array (mut i32))) + (type $1 (struct (field (mut i32)) (field (mut f64)))) + (type $2 (func)) + (global $global-struct.new (mut (ref $1)) (struct.new $1 + (i32.const 123) + (f64.const 123.456) + )) + (global $global-struct.new_default (mut (ref $1)) (struct.new_default $1)) + (global $global-array.new (mut (ref $0)) (array.new $0 + (i32.const 123) + (i32.const 4) + )) + (global $global-array.new_default (mut (ref $0)) (array.new_default $0 + (i32.const 4) + )) + (global $global-array.new_fixed (mut (ref $0)) (array.new_fixed $0 4 + (i32.const 1) + (i32.const 2) + (i32.const 3) + (i32.const 4) + )) + (memory $0 1) + (data $0 (i32.const 0) "\04\03\02\01") + (func $main (type $2) + (local $0 i32) + (local $1 f64) + (global.set $global-array.new_default + (array.new_data $0 $0 + (i32.const 0) + (i32.const 4) + ) + ) + (array.copy $0 $0 + (global.get $global-array.new_fixed) + (i32.const 0) + (global.get $global-array.new_default) + (i32.const 0) + (array.len + (global.get $global-array.new_default) + ) + ) + (array.set $0 + (global.get $global-array.new) + (i32.const 2) + (array.get $0 + (global.get $global-array.new_default) + (i32.const 0) + ) + ) + (local.set $0 + (struct.get $1 0 + (global.get $global-struct.new) + ) + ) + (struct.set $1 1 + (global.get $global-struct.new_default) + (f64.convert_i32_u + (local.get $0) + ) + ) + ) ) From a9cd17483b7471933bc873d6f6e182294bbf6046 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Wed, 9 Apr 2025 08:33:56 +0500 Subject: [PATCH 05/29] Wrap stack-allocating functions in preserveStack --- src/js/binaryen.js-post.js | 377 +++++++++++++++++++++---------------- 1 file changed, 219 insertions(+), 158 deletions(-) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 4bf8ecf2bc4..efc517dfbd7 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -712,54 +712,54 @@ function wrapModule(module, self = {}) { self['global'] = { 'get'(name, type) { - return Module['_BinaryenGlobalGet'](module, strToStack(name), type); + return preserveStack(() => Module['_BinaryenGlobalGet'](module, strToStack(name), type)); }, 'set'(name, value) { - return Module['_BinaryenGlobalSet'](module, strToStack(name), value); + return preserveStack(() => Module['_BinaryenGlobalSet'](module, strToStack(name), value)); } } self['table'] = { 'get'(name, index, type) { - return Module['_BinaryenTableGet'](module, strToStack(name), index, type); + return preserveStack(() => Module['_BinaryenTableGet'](module, strToStack(name), index, type)); }, 'set'(name, index, value) { - return Module['_BinaryenTableSet'](module, strToStack(name), index, value); + return preserveStack(() => Module['_BinaryenTableSet'](module, strToStack(name), index, value)); }, 'size'(name) { - return Module['_BinaryenTableSize'](module, strToStack(name)); + return preserveStack(() => Module['_BinaryenTableSize'](module, strToStack(name))); }, 'grow'(name, value, delta) { - return Module['_BinaryenTableGrow'](module, strToStack(name), value, delta); + return preserveStack(() => Module['_BinaryenTableGrow'](module, strToStack(name), value, delta)); } } self['memory'] = { // memory64 defaults to undefined/false. 'size'(name, memory64) { - return Module['_BinaryenMemorySize'](module, strToStack(name), memory64); + return preserveStack(() => Module['_BinaryenMemorySize'](module, strToStack(name), memory64)); }, 'grow'(value, name, memory64) { - return Module['_BinaryenMemoryGrow'](module, value, strToStack(name), memory64); + return preserveStack(() => Module['_BinaryenMemoryGrow'](module, value, strToStack(name), memory64)); }, 'init'(segment, dest, offset, size, name) { return preserveStack(() => Module['_BinaryenMemoryInit'](module, strToStack(segment), dest, offset, size, strToStack(name))); }, 'copy'(dest, source, size, destMemory, sourceMemory) { - return Module['_BinaryenMemoryCopy'](module, dest, source, size, strToStack(destMemory), strToStack(sourceMemory)); + return preserveStack(() => Module['_BinaryenMemoryCopy'](module, dest, source, size, strToStack(destMemory), strToStack(sourceMemory))); }, 'fill'(dest, value, size, name) { - return Module['_BinaryenMemoryFill'](module, dest, value, size, strToStack(name)); + return preserveStack(() => Module['_BinaryenMemoryFill'](module, dest, value, size, strToStack(name))); }, 'atomic': { 'notify'(ptr, notifyCount, name) { - return Module['_BinaryenAtomicNotify'](module, ptr, notifyCount, strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicNotify'](module, ptr, notifyCount, strToStack(name))); }, 'wait32'(ptr, expected, timeout, name) { - return Module['_BinaryenAtomicWait'](module, ptr, expected, timeout, Module['i32'], strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicWait'](module, ptr, expected, timeout, Module['i32'], strToStack(name))); }, 'wait64'(ptr, expected, timeout, name) { - return Module['_BinaryenAtomicWait'](module, ptr, expected, timeout, Module['i64'], strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicWait'](module, ptr, expected, timeout, Module['i64'], strToStack(name))); } } } @@ -772,28 +772,28 @@ function wrapModule(module, self = {}) { self['i32'] = { 'load'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 4, true, offset, align, Module['i32'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 4, true, offset, align, Module['i32'], ptr, strToStack(name))); }, 'load8_s'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 1, true, offset, align, Module['i32'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 1, true, offset, align, Module['i32'], ptr, strToStack(name))); }, 'load8_u'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 1, false, offset, align, Module['i32'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 1, false, offset, align, Module['i32'], ptr, strToStack(name))); }, 'load16_s'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 2, true, offset, align, Module['i32'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 2, true, offset, align, Module['i32'], ptr, strToStack(name))); }, 'load16_u'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 2, false, offset, align, Module['i32'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 2, false, offset, align, Module['i32'], ptr, strToStack(name))); }, 'store'(offset, align, ptr, value, name) { - return Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['i32'], strToStack(name))); }, 'store8'(offset, align, ptr, value, name) { - return Module['_BinaryenStore'](module, 1, offset, align, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => Module['_BinaryenStore'](module, 1, offset, align, ptr, value, Module['i32'], strToStack(name))); }, 'store16'(offset, align, ptr, value, name) { - return Module['_BinaryenStore'](module, 2, offset, align, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => Module['_BinaryenStore'](module, 2, offset, align, ptr, value, Module['i32'], strToStack(name))); }, 'const'(x) { return preserveStack(() => { @@ -935,90 +935,111 @@ function wrapModule(module, self = {}) { }, 'atomic': { 'load'(offset, ptr, name) { - return Module['_BinaryenAtomicLoad'](module, 4, offset, Module['i32'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 4, offset, Module['i32'], ptr, strToStack(name))); }, 'load8_u'(offset, ptr, name) { - return Module['_BinaryenAtomicLoad'](module, 1, offset, Module['i32'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 1, offset, Module['i32'], ptr, strToStack(name))); }, 'load16_u'(offset, ptr, name) { - return Module['_BinaryenAtomicLoad'](module, 2, offset, Module['i32'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 2, offset, Module['i32'], ptr, strToStack(name))); }, 'store'(offset, ptr, value, name) { - return Module['_BinaryenAtomicStore'](module, 4, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 4, offset, ptr, value, Module['i32'], strToStack(name))); }, 'store8'(offset, ptr, value, name) { - return Module['_BinaryenAtomicStore'](module, 1, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 1, offset, ptr, value, Module['i32'], strToStack(name))); }, 'store16'(offset, ptr, value, name) { - return Module['_BinaryenAtomicStore'](module, 2, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 2, offset, ptr, value, Module['i32'], strToStack(name))); }, 'rmw': { 'add'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 4, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 4, offset, ptr, value, Module['i32'], strToStack(name))); }, 'sub'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 4, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 4, offset, ptr, value, Module['i32'], strToStack(name))); }, 'and'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 4, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 4, offset, ptr, value, Module['i32'], strToStack(name))); }, 'or'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 4, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 4, offset, ptr, value, Module['i32'], strToStack(name))); }, 'xor'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 4, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 4, offset, ptr, value, Module['i32'], strToStack(name))); }, 'xchg'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 4, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 4, offset, ptr, value, Module['i32'], strToStack(name))); }, 'cmpxchg'(offset, ptr, expected, replacement, name) { - return Module['_BinaryenAtomicCmpxchg'](module, 4, offset, ptr, expected, replacement, Module['i32'], strToStack(name)) + return preserveStack(() => + Module['_BinaryenAtomicCmpxchg'](module, 4, offset, ptr, expected, replacement, Module['i32'], strToStack(name))); }, }, 'rmw8_u': { 'add'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 1, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 1, offset, ptr, value, Module['i32'], strToStack(name))); }, 'sub'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 1, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 1, offset, ptr, value, Module['i32'], strToStack(name))); }, 'and'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 1, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 1, offset, ptr, value, Module['i32'], strToStack(name))); }, 'or'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 1, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 1, offset, ptr, value, Module['i32'], strToStack(name))); }, 'xor'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 1, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 1, offset, ptr, value, Module['i32'], strToStack(name))); }, 'xchg'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 1, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 1, offset, ptr, value, Module['i32'], strToStack(name))); }, 'cmpxchg'(offset, ptr, expected, replacement, name) { - return Module['_BinaryenAtomicCmpxchg'](module, 1, offset, ptr, expected, replacement, Module['i32'], strToStack(name)) + return preserveStack(() => + Module['_BinaryenAtomicCmpxchg'](module, 1, offset, ptr, expected, replacement, Module['i32'], strToStack(name))); }, }, 'rmw16_u': { 'add'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 2, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 2, offset, ptr, value, Module['i32'], strToStack(name))); }, 'sub'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 2, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 2, offset, ptr, value, Module['i32'], strToStack(name))); }, 'and'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 2, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 2, offset, ptr, value, Module['i32'], strToStack(name))); }, 'or'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 2, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 2, offset, ptr, value, Module['i32'], strToStack(name))); }, 'xor'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 2, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 2, offset, ptr, value, Module['i32'], strToStack(name))); }, 'xchg'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 2, offset, ptr, value, Module['i32'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 2, offset, ptr, value, Module['i32'], strToStack(name))); }, 'cmpxchg'(offset, ptr, expected, replacement, name) { - return Module['_BinaryenAtomicCmpxchg'](module, 2, offset, ptr, expected, replacement, Module['i32'], strToStack(name)) + return preserveStack(() => + Module['_BinaryenAtomicCmpxchg'](module, 2, offset, ptr, expected, replacement, Module['i32'], strToStack(name))); }, }, }, @@ -1029,37 +1050,37 @@ function wrapModule(module, self = {}) { self['i64'] = { 'load'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 8, true, offset, align, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 8, true, offset, align, Module['i64'], ptr, strToStack(name))); }, 'load8_s'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 1, true, offset, align, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 1, true, offset, align, Module['i64'], ptr, strToStack(name))); }, 'load8_u'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 1, false, offset, align, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 1, false, offset, align, Module['i64'], ptr, strToStack(name))); }, 'load16_s'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 2, true, offset, align, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 2, true, offset, align, Module['i64'], ptr, strToStack(name))); }, 'load16_u'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 2, false, offset, align, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 2, false, offset, align, Module['i64'], ptr, strToStack(name))); }, 'load32_s'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 4, true, offset, align, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 4, true, offset, align, Module['i64'], ptr, strToStack(name))); }, 'load32_u'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 4, false, offset, align, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 4, false, offset, align, Module['i64'], ptr, strToStack(name))); }, 'store'(offset, align, ptr, value, name) { - return Module['_BinaryenStore'](module, 8, offset, align, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => Module['_BinaryenStore'](module, 8, offset, align, ptr, value, Module['i64'], strToStack(name))); }, 'store8'(offset, align, ptr, value, name) { - return Module['_BinaryenStore'](module, 1, offset, align, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => Module['_BinaryenStore'](module, 1, offset, align, ptr, value, Module['i64'], strToStack(name))); }, 'store16'(offset, align, ptr, value, name) { - return Module['_BinaryenStore'](module, 2, offset, align, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => Module['_BinaryenStore'](module, 2, offset, align, ptr, value, Module['i64'], strToStack(name))); }, 'store32'(offset, align, ptr, value, name) { - return Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['i64'], strToStack(name))); }, 'const'(x, y) { return preserveStack(() => { @@ -1207,119 +1228,147 @@ function wrapModule(module, self = {}) { }, 'atomic': { 'load'(offset, ptr, name) { - return Module['_BinaryenAtomicLoad'](module, 8, offset, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 8, offset, Module['i64'], ptr, strToStack(name))); }, 'load8_u'(offset, ptr, name) { - return Module['_BinaryenAtomicLoad'](module, 1, offset, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 1, offset, Module['i64'], ptr, strToStack(name))); }, 'load16_u'(offset, ptr, name) { - return Module['_BinaryenAtomicLoad'](module, 2, offset, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 2, offset, Module['i64'], ptr, strToStack(name))); }, 'load32_u'(offset, ptr, name) { - return Module['_BinaryenAtomicLoad'](module, 4, offset, Module['i64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 4, offset, Module['i64'], ptr, strToStack(name))); }, 'store'(offset, ptr, value, name) { - return Module['_BinaryenAtomicStore'](module, 8, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 8, offset, ptr, value, Module['i64'], strToStack(name))); }, 'store8'(offset, ptr, value, name) { - return Module['_BinaryenAtomicStore'](module, 1, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 1, offset, ptr, value, Module['i64'], strToStack(name))); }, 'store16'(offset, ptr, value, name) { - return Module['_BinaryenAtomicStore'](module, 2, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 2, offset, ptr, value, Module['i64'], strToStack(name))); }, 'store32'(offset, ptr, value, name) { - return Module['_BinaryenAtomicStore'](module, 4, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 4, offset, ptr, value, Module['i64'], strToStack(name))); }, 'rmw': { 'add'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 8, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 8, offset, ptr, value, Module['i64'], strToStack(name))); }, 'sub'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 8, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 8, offset, ptr, value, Module['i64'], strToStack(name))); }, 'and'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 8, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 8, offset, ptr, value, Module['i64'], strToStack(name))); }, 'or'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 8, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 8, offset, ptr, value, Module['i64'], strToStack(name))); }, 'xor'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 8, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 8, offset, ptr, value, Module['i64'], strToStack(name))); }, 'xchg'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 8, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 8, offset, ptr, value, Module['i64'], strToStack(name))); }, 'cmpxchg'(offset, ptr, expected, replacement, name) { - return Module['_BinaryenAtomicCmpxchg'](module, 8, offset, ptr, expected, replacement, Module['i64'], strToStack(name)) + return preserveStack(() => + Module['_BinaryenAtomicCmpxchg'](module, 8, offset, ptr, expected, replacement, Module['i64'], strToStack(name))); }, }, 'rmw8_u': { 'add'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 1, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 1, offset, ptr, value, Module['i64'], strToStack(name))); }, 'sub'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 1, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 1, offset, ptr, value, Module['i64'], strToStack(name))); }, 'and'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 1, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 1, offset, ptr, value, Module['i64'], strToStack(name))); }, 'or'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 1, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 1, offset, ptr, value, Module['i64'], strToStack(name))); }, 'xor'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 1, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 1, offset, ptr, value, Module['i64'], strToStack(name))); }, 'xchg'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 1, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 1, offset, ptr, value, Module['i64'], strToStack(name))); }, 'cmpxchg'(offset, ptr, expected, replacement, name) { - return Module['_BinaryenAtomicCmpxchg'](module, 1, offset, ptr, expected, replacement, Module['i64'], strToStack(name)) + return preserveStack(() => + Module['_BinaryenAtomicCmpxchg'](module, 1, offset, ptr, expected, replacement, Module['i64'], strToStack(name))); }, }, 'rmw16_u': { 'add'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 2, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 2, offset, ptr, value, Module['i64'], strToStack(name))); }, 'sub'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 2, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 2, offset, ptr, value, Module['i64'], strToStack(name))); }, 'and'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 2, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 2, offset, ptr, value, Module['i64'], strToStack(name))); }, 'or'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 2, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 2, offset, ptr, value, Module['i64'], strToStack(name))); }, 'xor'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 2, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 2, offset, ptr, value, Module['i64'], strToStack(name))); }, 'xchg'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 2, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 2, offset, ptr, value, Module['i64'], strToStack(name))); }, 'cmpxchg'(offset, ptr, expected, replacement, name) { - return Module['_BinaryenAtomicCmpxchg'](module, 2, offset, ptr, expected, replacement, Module['i64'], strToStack(name)) + return preserveStack(() => + Module['_BinaryenAtomicCmpxchg'](module, 2, offset, ptr, expected, replacement, Module['i64'], strToStack(name))); }, }, 'rmw32_u': { 'add'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 4, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 4, offset, ptr, value, Module['i64'], strToStack(name))); }, 'sub'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 4, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 4, offset, ptr, value, Module['i64'], strToStack(name))); }, 'and'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 4, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 4, offset, ptr, value, Module['i64'], strToStack(name))); }, 'or'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 4, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 4, offset, ptr, value, Module['i64'], strToStack(name))); }, 'xor'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 4, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 4, offset, ptr, value, Module['i64'], strToStack(name))); }, 'xchg'(offset, ptr, value, name) { - return Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 4, offset, ptr, value, Module['i64'], strToStack(name)); + return preserveStack(() => + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 4, offset, ptr, value, Module['i64'], strToStack(name))); }, 'cmpxchg'(offset, ptr, expected, replacement, name) { - return Module['_BinaryenAtomicCmpxchg'](module, 4, offset, ptr, expected, replacement, Module['i64'], strToStack(name)) + return preserveStack(() => + Module['_BinaryenAtomicCmpxchg'](module, 4, offset, ptr, expected, replacement, Module['i64'], strToStack(name))); }, }, }, @@ -1330,10 +1379,10 @@ function wrapModule(module, self = {}) { self['f32'] = { 'load'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 4, true, offset, align, Module['f32'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 4, true, offset, align, Module['f32'], ptr, strToStack(name))); }, 'store'(offset, align, ptr, value, name) { - return Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['f32'], strToStack(name)); + return preserveStack(() => Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['f32'], strToStack(name))); }, 'const'(x) { return preserveStack(() => { @@ -1438,10 +1487,10 @@ function wrapModule(module, self = {}) { self['f64'] = { 'load'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 8, true, offset, align, Module['f64'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 8, true, offset, align, Module['f64'], ptr, strToStack(name))); }, 'store'(offset, align, ptr, value, name) { - return Module['_BinaryenStore'](module, 8, offset, align, ptr, value, Module['f64'], strToStack(name)); + return preserveStack(() => Module['_BinaryenStore'](module, 8, offset, align, ptr, value, Module['f64'], strToStack(name))); }, 'const'(x) { return preserveStack(() => { @@ -1546,70 +1595,78 @@ function wrapModule(module, self = {}) { self['v128'] = { 'load'(offset, align, ptr, name) { - return Module['_BinaryenLoad'](module, 16, false, offset, align, Module['v128'], ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenLoad'](module, 16, false, offset, align, Module['v128'], ptr, strToStack(name))); }, 'load8_splat'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load8SplatVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load8SplatVec128'], offset, align, ptr, strToStack(name))); }, 'load16_splat'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load16SplatVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load16SplatVec128'], offset, align, ptr, strToStack(name))); }, 'load32_splat'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load32SplatVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load32SplatVec128'], offset, align, ptr, strToStack(name))); }, 'load64_splat'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load64SplatVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load64SplatVec128'], offset, align, ptr, strToStack(name))); }, 'load8x8_s'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load8x8SVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load8x8SVec128'], offset, align, ptr, strToStack(name))); }, 'load8x8_u'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load8x8UVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load8x8UVec128'], offset, align, ptr, strToStack(name))); }, 'load16x4_s'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load16x4SVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load16x4SVec128'], offset, align, ptr, strToStack(name))); }, 'load16x4_u'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load16x4UVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load16x4UVec128'], offset, align, ptr, strToStack(name))); }, 'load32x2_s'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load32x2SVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load32x2SVec128'], offset, align, ptr, strToStack(name))); }, 'load32x2_u'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load32x2UVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load32x2UVec128'], offset, align, ptr, strToStack(name))); }, 'load32_zero'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load32ZeroVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load32ZeroVec128'], offset, align, ptr, strToStack(name))); }, 'load64_zero'(offset, align, ptr, name) { - return Module['_BinaryenSIMDLoad'](module, Module['Load64ZeroVec128'], offset, align, ptr, strToStack(name)); + return preserveStack(() => Module['_BinaryenSIMDLoad'](module, Module['Load64ZeroVec128'], offset, align, ptr, strToStack(name))); }, 'load8_lane'(offset, align, index, ptr, vec, name) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load8LaneVec128'], offset, align, index, ptr, vec, strToStack(name)); + return preserveStack(() => + Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load8LaneVec128'], offset, align, index, ptr, vec, strToStack(name))); }, 'load16_lane'(offset, align, index, ptr, vec, name) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load16LaneVec128'], offset, align, index, ptr, vec, strToStack(name)); + return preserveStack(() => + Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load16LaneVec128'], offset, align, index, ptr, vec, strToStack(name))); }, 'load32_lane'(offset, align, index, ptr, vec, name) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load32LaneVec128'], offset, align, index, ptr, vec, strToStack(name)); + return preserveStack(() => + Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load32LaneVec128'], offset, align, index, ptr, vec, strToStack(name))); }, 'load64_lane'(offset, align, index, ptr, vec, name) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load64LaneVec128'], offset, align, index, ptr, vec, strToStack(name)); + return preserveStack(() => + Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load64LaneVec128'], offset, align, index, ptr, vec, strToStack(name))); }, 'store8_lane'(offset, align, index, ptr, vec, name) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store8LaneVec128'], offset, align, index, ptr, vec, strToStack(name)); + return preserveStack(() => + Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store8LaneVec128'], offset, align, index, ptr, vec, strToStack(name))); }, 'store16_lane'(offset, align, index, ptr, vec, name) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store16LaneVec128'], offset, align, index, ptr, vec, strToStack(name)); + return preserveStack(() => + Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store16LaneVec128'], offset, align, index, ptr, vec, strToStack(name))); }, 'store32_lane'(offset, align, index, ptr, vec, name) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store32LaneVec128'], offset, align, index, ptr, vec, strToStack(name)); + return preserveStack(() => + Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store32LaneVec128'], offset, align, index, ptr, vec, strToStack(name))); }, 'store64_lane'(offset, align, index, ptr, vec, name) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store64LaneVec128'], offset, align, index, ptr, vec, strToStack(name)); + return preserveStack(() => + Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store64LaneVec128'], offset, align, index, ptr, vec, strToStack(name))); }, 'store'(offset, align, ptr, value, name) { - return Module['_BinaryenStore'](module, 16, offset, align, ptr, value, Module['v128'], strToStack(name)); + return preserveStack(() => Module['_BinaryenStore'](module, 16, offset, align, ptr, value, Module['v128'], strToStack(name))); }, 'const'(i8s) { return preserveStack(() => { @@ -2379,7 +2436,7 @@ function wrapModule(module, self = {}) { return preserveStack(() => Module['_BinaryenThrow'](module, strToStack(tag), i32sToStack(operands), operands.length)); }; self['rethrow'] = function(target) { - return Module['_BinaryenRethrow'](module, strToStack(target)); + return preserveStack(() => Module['_BinaryenRethrow'](module, strToStack(target))); }; self['tuple'] = { @@ -2413,24 +2470,24 @@ function wrapModule(module, self = {}) { }; self['br_on_null'] = function(name, value, castType) { - return Module['_BinaryenBrOn'](module, Module['BrOnNull'], strToStack(name), value, castType); + return preserveStack(() => Module['_BinaryenBrOn'](module, Module['BrOnNull'], strToStack(name), value, castType)); }; self['br_on_non_null'] = function(name, value, castType) { - return Module['_BinaryenBrOn'](module, Module['BrOnNonNull'], strToStack(name), value, castType); + return preserveStack(() => Module['_BinaryenBrOn'](module, Module['BrOnNonNull'], strToStack(name), value, castType)); }; self['br_on_cast'] = function(name, value, castType) { - return Module['_BinaryenBrOn'](module, Module['BrOnCast'], strToStack(name), value, castType); + return preserveStack(() => Module['_BinaryenBrOn'](module, Module['BrOnCast'], strToStack(name), value, castType)); }; self['br_on_cast_fail'] = function(name, value, castType) { - return Module['_BinaryenBrOn'](module, Module['BrOnCastFail'], strToStack(name), value, castType); + return preserveStack(() => Module['_BinaryenBrOn'](module, Module['BrOnCastFail'], strToStack(name), value, castType)); }; self['struct'] = { 'new'(operands, type) { - return Module['_BinaryenStructNew'](module, i32sToStack(operands), operands.length, type); + return preserveStack(() => Module['_BinaryenStructNew'](module, i32sToStack(operands), operands.length, type)); }, 'new_default'(type) { // Passing in null for |operands| (and 0 for |numOperands|) implies this is @@ -2453,10 +2510,10 @@ function wrapModule(module, self = {}) { return Module['_BinaryenArrayNew'](module, type, size, 0); }, 'new_fixed'(type, values) { - return Module['_BinaryenArrayNewFixed'](module, type, i32sToStack(values), values.length); + return preserveStack(() => Module['_BinaryenArrayNewFixed'](module, type, i32sToStack(values), values.length)); }, 'new_data'(type, name, offset, size) { - return Module['_BinaryenArrayNewData'](module, type, strToStack(name), offset, size); + return preserveStack(() => Module['_BinaryenArrayNewData'](module, type, strToStack(name), offset, size)); }, // TODO: array.new_elem 'get'(ref, index, type, isSigned) { @@ -2638,40 +2695,44 @@ function wrapModule(module, self = {}) { return Boolean(Module['_BinaryenHasMemory'](module)); }; self['getMemoryInfo'] = function(name) { - var memoryInfo = { - 'module': UTF8ToString(Module['_BinaryenMemoryImportGetModule'](module, strToStack(name))), - 'base': UTF8ToString(Module['_BinaryenMemoryImportGetBase'](module, strToStack(name))), - 'initial': Module['_BinaryenMemoryGetInitial'](module, strToStack(name)), - 'shared': Boolean(Module['_BinaryenMemoryIsShared'](module, strToStack(name))), - 'is64': Boolean(Module['_BinaryenMemoryIs64'](module, strToStack(name))), - }; - if (Module['_BinaryenMemoryHasMax'](module, strToStack(name))) { - memoryInfo['max'] = Module['_BinaryenMemoryGetMax'](module, strToStack(name)); - } - return memoryInfo; + return preserveStack(() => { + var memoryInfo = { + 'module': UTF8ToString(Module['_BinaryenMemoryImportGetModule'](module, strToStack(name))), + 'base': UTF8ToString(Module['_BinaryenMemoryImportGetBase'](module, strToStack(name))), + 'initial': Module['_BinaryenMemoryGetInitial'](module, strToStack(name)), + 'shared': Boolean(Module['_BinaryenMemoryIsShared'](module, strToStack(name))), + 'is64': Boolean(Module['_BinaryenMemoryIs64'](module, strToStack(name))), + }; + if (Module['_BinaryenMemoryHasMax'](module, strToStack(name))) { + memoryInfo['max'] = Module['_BinaryenMemoryGetMax'](module, strToStack(name)); + } + return memoryInfo; + }); }; self['getNumMemorySegments'] = function() { return Module['_BinaryenGetNumMemorySegments'](module); }; self['getMemorySegmentInfo'] = function(name) { - const passive = Boolean(Module['_BinaryenGetMemorySegmentPassive'](module, strToStack(name))); - let offset = null; - if (!passive) { - offset = Module['_BinaryenGetMemorySegmentByteOffset'](module, strToStack(name)); - } - return { - 'offset': offset, - 'data': (function(){ - const size = Module['_BinaryenGetMemorySegmentByteLength'](module, strToStack(name)); - const ptr = _malloc(size); - Module['_BinaryenCopyMemorySegmentData'](module, strToStack(name), ptr); - const res = new Uint8Array(size); - res.set(HEAP8.subarray(ptr, ptr + size)); - _free(ptr); - return res.buffer; - })(), - 'passive': passive - }; + return preserveStack(() => { + const passive = Boolean(Module['_BinaryenGetMemorySegmentPassive'](module, strToStack(name))); + let offset = null; + if (!passive) { + offset = Module['_BinaryenGetMemorySegmentByteOffset'](module, strToStack(name)); + } + return { + 'offset': offset, + 'data': (function(){ + const size = Module['_BinaryenGetMemorySegmentByteLength'](module, strToStack(name)); + const ptr = _malloc(size); + Module['_BinaryenCopyMemorySegmentData'](module, strToStack(name), ptr); + const res = new Uint8Array(size); + res.set(HEAP8.subarray(ptr, ptr + size)); + _free(ptr); + return res.buffer; + })(), + 'passive': passive + }; + }); }; self['setStart'] = function(start) { return Module['_BinaryenSetStart'](module, start); From ad972e4a0bbdda08f0d1fa918f4c00ba5fc0a0c6 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Wed, 9 Apr 2025 08:54:53 +0500 Subject: [PATCH 06/29] Add array.fill & array.init_(data,elem) C API + tests --- src/binaryen-c.cpp | 42 ++++++++++++++++++++++++++++- src/binaryen-c.h | 27 ++++++++++++++++++- test/example/c-api-kitchen-sink.c | 17 ++++++++++++ test/example/c-api-kitchen-sink.txt | 18 +++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 8e8c295f2ca..04648d81a71 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -1796,7 +1796,16 @@ BinaryenExpressionRef BinaryenArrayNewData(BinaryenModuleRef module, .makeArrayNewData( HeapType(type), name, (Expression*)offset, (Expression*)size)); } - +BinaryenExpressionRef BinaryenArrayNewElem(BinaryenModuleRef module, + BinaryenHeapType type, + const char* name, + BinaryenExpressionRef offset, + BinaryenExpressionRef size) { + return static_cast( + Builder(*(Module*)module) + .makeArrayNewElem( + HeapType(type), name, (Expression*)offset, (Expression*)size)); +} BinaryenExpressionRef BinaryenArrayNewFixed(BinaryenModuleRef module, BinaryenHeapType type, BinaryenExpressionRef* values, @@ -1843,6 +1852,37 @@ BinaryenExpressionRef BinaryenArrayCopy(BinaryenModuleRef module, (Expression*)srcIndex, (Expression*)length)); } +BinaryenExpressionRef BinaryenArrayFill(BinaryenModuleRef module, + BinaryenExpressionRef ref, + BinaryenExpressionRef index, + BinaryenExpressionRef value, + BinaryenExpressionRef size) { + return static_cast(Builder(*(Module*)module) + .makeArrayFill((Expression*)ref, + (Expression*)index, + (Expression*)value, + (Expression*)size)); +} +BinaryenExpressionRef BinaryenArrayInitData(BinaryenModuleRef module, + const char* name, + BinaryenExpressionRef ref, + BinaryenExpressionRef index, + BinaryenExpressionRef offset, + BinaryenExpressionRef size) { + return static_cast( + Builder(*(Module*)module) + .makeArrayInitData(name, (Expression*)ref, (Expression*)index, (Expression*)offset, (Expression*)size)); +} +BinaryenExpressionRef BinaryenArrayInitElem(BinaryenModuleRef module, + const char* seg, + BinaryenExpressionRef ref, + BinaryenExpressionRef index, + BinaryenExpressionRef offset, + BinaryenExpressionRef size) { + return static_cast( + Builder(*(Module*)module) + .makeArrayInitElem(seg, (Expression*)ref, (Expression*)index, (Expression*)offset, (Expression*)size)); +} BinaryenExpressionRef BinaryenStringNew(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef ptr, diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 65a2f12f451..07c35439be3 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -1050,7 +1050,6 @@ BINARYEN_API BinaryenExpressionRef BinaryenArrayNew(BinaryenModuleRef module, BinaryenHeapType type, BinaryenExpressionRef size, BinaryenExpressionRef init); - BINARYEN_API BinaryenExpressionRef BinaryenArrayNewData(BinaryenModuleRef module, BinaryenHeapType type, @@ -1058,6 +1057,12 @@ BinaryenArrayNewData(BinaryenModuleRef module, BinaryenExpressionRef offset, BinaryenExpressionRef size); BINARYEN_API BinaryenExpressionRef +BinaryenArrayNewElem(BinaryenModuleRef module, + BinaryenHeapType type, + const char* seg, + BinaryenExpressionRef offset, + BinaryenExpressionRef size); +BINARYEN_API BinaryenExpressionRef BinaryenArrayNewFixed(BinaryenModuleRef module, BinaryenHeapType type, BinaryenExpressionRef* values, @@ -1082,11 +1087,31 @@ BinaryenArrayCopy(BinaryenModuleRef module, BinaryenExpressionRef srcIndex, BinaryenExpressionRef length); BINARYEN_API BinaryenExpressionRef +BinaryenArrayFill(BinaryenModuleRef module, + BinaryenExpressionRef ref, + BinaryenExpressionRef index, + BinaryenExpressionRef value, + BinaryenExpressionRef size); +BINARYEN_API BinaryenExpressionRef BinaryenStringNew(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef ref, BinaryenExpressionRef start, BinaryenExpressionRef end); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayInitData(BinaryenModuleRef module, + const char* name, + BinaryenExpressionRef ref, + BinaryenExpressionRef index, + BinaryenExpressionRef offset, + BinaryenExpressionRef size); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayInitElem(BinaryenModuleRef module, + const char* seg, + BinaryenExpressionRef ref, + BinaryenExpressionRef index, + BinaryenExpressionRef offset, + BinaryenExpressionRef size); BINARYEN_API BinaryenExpressionRef BinaryenStringConst(BinaryenModuleRef module, const char* name); BINARYEN_API BinaryenExpressionRef BinaryenStringMeasure( diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index c97de45a366..7d19ebb4a10 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -1170,12 +1170,29 @@ void test_core() { makeInt32(module, 42)), BinaryenArrayLen(module, BinaryenGlobalGet(module, "i8Array-global", i8Array)), + BinaryenArrayFill(module, + BinaryenGlobalGet(module, "i8Array-global", i8Array), + makeInt32(module, 0), + makeInt32(module, 1), + makeInt32(module, 2)), BinaryenArrayCopy(module, BinaryenGlobalGet(module, "i8Array-global", i8Array), makeInt32(module, 0), BinaryenGlobalGet(module, "i8Array-global", i8Array), makeInt32(module, 1), makeInt32(module, 2)), + BinaryenArrayInitData(module, + "0", + BinaryenGlobalGet(module, "i8Array-global", i8Array), + makeInt32(module, 0), + makeInt32(module, 1), + makeInt32(module, 2)), + BinaryenArrayInitElem(module, + "0", + BinaryenGlobalGet(module, "i8Array-global", i8Array), + makeInt32(module, 0), + makeInt32(module, 1), + makeInt32(module, 2)), // Strings BinaryenStringNew(module, BinaryenStringNewLossyUTF8Array(), diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 78f1c73552f..d1dad3d82ca 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -2327,6 +2327,12 @@ BinaryenFeatureAll: 4194303 (global.get $i8Array-global) ) ) + (array.fill $0 + (global.get $i8Array-global) + (i32.const 0) + (i32.const 1) + (i32.const 2) + ) (array.copy $0 $0 (global.get $i8Array-global) (i32.const 0) @@ -2334,6 +2340,18 @@ BinaryenFeatureAll: 4194303 (i32.const 1) (i32.const 2) ) + (array.init_data $0 $0 + (global.get $i8Array-global) + (i32.const 0) + (i32.const 1) + (i32.const 2) + ) + (array.init_elem $0 $0 + (global.get $i8Array-global) + (i32.const 0) + (i32.const 1) + (i32.const 2) + ) (drop (string.new_lossy_utf8_array (global.get $i8Array-global) From bb58e9d69d7911ca64dd6ada0e722d9ac52ffb2a Mon Sep 17 00:00:00 2001 From: GulgDev Date: Wed, 9 Apr 2025 08:58:36 +0500 Subject: [PATCH 07/29] Fix formatting --- src/binaryen-c.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 04648d81a71..d875986e4bd 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -1869,9 +1869,12 @@ BinaryenExpressionRef BinaryenArrayInitData(BinaryenModuleRef module, BinaryenExpressionRef index, BinaryenExpressionRef offset, BinaryenExpressionRef size) { - return static_cast( - Builder(*(Module*)module) - .makeArrayInitData(name, (Expression*)ref, (Expression*)index, (Expression*)offset, (Expression*)size)); + return static_cast(Builder(*(Module*)module) + .makeArrayInitData(name, + (Expression*)ref, + (Expression*)index, + (Expression*)offset, + (Expression*)size)); } BinaryenExpressionRef BinaryenArrayInitElem(BinaryenModuleRef module, const char* seg, @@ -1879,9 +1882,12 @@ BinaryenExpressionRef BinaryenArrayInitElem(BinaryenModuleRef module, BinaryenExpressionRef index, BinaryenExpressionRef offset, BinaryenExpressionRef size) { - return static_cast( - Builder(*(Module*)module) - .makeArrayInitElem(seg, (Expression*)ref, (Expression*)index, (Expression*)offset, (Expression*)size)); + return static_cast(Builder(*(Module*)module) + .makeArrayInitElem(seg, + (Expression*)ref, + (Expression*)index, + (Expression*)offset, + (Expression*)size)); } BinaryenExpressionRef BinaryenStringNew(BinaryenModuleRef module, BinaryenOp op, From eb0c88f9924f620d1fd2e1b5dbd2e6aeecddbc3c Mon Sep 17 00:00:00 2001 From: GulgDev Date: Wed, 9 Apr 2025 09:40:51 +0500 Subject: [PATCH 08/29] Fix array.init_elem test --- test/example/c-api-kitchen-sink.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 7d19ebb4a10..4997649760a 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -518,13 +518,16 @@ void test_core() { BinaryenType v128 = BinaryenTypeVec128(); BinaryenType i8Array; BinaryenType i16Array; + BinaryenType kitchenSinkerArray; BinaryenType i32Struct; { - TypeBuilderRef tb = TypeBuilderCreate(3); + TypeBuilderRef tb = TypeBuilderCreate(4); TypeBuilderSetArrayType( tb, 0, BinaryenTypeInt32(), BinaryenPackedTypeInt8(), true); TypeBuilderSetArrayType( tb, 1, BinaryenTypeInt32(), BinaryenPackedTypeInt16(), true); + TypeBuilderSetArrayType( + tb, 2, kitchenSinkerRefType, BinaryenPackedTypeNotPacked(), true); TypeBuilderSetStructType( tb, 2, @@ -1189,7 +1192,7 @@ void test_core() { makeInt32(module, 2)), BinaryenArrayInitElem(module, "0", - BinaryenGlobalGet(module, "i8Array-global", i8Array), + BinaryenGlobalGet(module, "kitchenSinkerArray-global", kitchenSinkerArray), makeInt32(module, 0), makeInt32(module, 1), makeInt32(module, 2)), @@ -1319,6 +1322,13 @@ void test_core() { true, BinaryenArrayNew( module, BinaryenTypeGetHeapType(i16Array), makeInt32(module, 0), 0)); + BinaryenAddGlobal( + module, + "kitchenSinkerArray-global", + kitchenSinkerArray, + true, + BinaryenArrayNew( + module, BinaryenTypeGetHeapType(kitchenSinkerArray), makeInt32(module, 0), BinaryenRefNull(module, kitchenSinkerRefType))); BinaryenAddGlobal( module, "i32Struct-global", From 9ebe7f1aab1854c55d3f009972b8c3c6cbeb8afa Mon Sep 17 00:00:00 2001 From: GulgDev Date: Wed, 9 Apr 2025 13:22:06 +0500 Subject: [PATCH 09/29] Fix formatting --- test/example/c-api-kitchen-sink.c | 10 +++++++--- test/example/c-api-kitchen-sink.txt | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 4997649760a..8f7e866920f 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -1192,7 +1192,9 @@ void test_core() { makeInt32(module, 2)), BinaryenArrayInitElem(module, "0", - BinaryenGlobalGet(module, "kitchenSinkerArray-global", kitchenSinkerArray), + BinaryenGlobalGet(module, + "kitchenSinkerArray-global", + kitchenSinkerArray), makeInt32(module, 0), makeInt32(module, 1), makeInt32(module, 2)), @@ -1327,8 +1329,10 @@ void test_core() { "kitchenSinkerArray-global", kitchenSinkerArray, true, - BinaryenArrayNew( - module, BinaryenTypeGetHeapType(kitchenSinkerArray), makeInt32(module, 0), BinaryenRefNull(module, kitchenSinkerRefType))); + BinaryenArrayNew(module, + BinaryenTypeGetHeapType(kitchenSinkerArray), + makeInt32(module, 0), + BinaryenRefNull(module, kitchenSinkerRefType))); BinaryenAddGlobal( module, "i32Struct-global", diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index d1dad3d82ca..177b63e3039 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -2347,7 +2347,7 @@ BinaryenFeatureAll: 4194303 (i32.const 2) ) (array.init_elem $0 $0 - (global.get $i8Array-global) + (global.get $kitchenSinkerArray-global) (i32.const 0) (i32.const 1) (i32.const 2) From 3d57cadaded7126d7aea515997c538ec9279224b Mon Sep 17 00:00:00 2001 From: GulgDev Date: Wed, 9 Apr 2025 14:05:48 +0500 Subject: [PATCH 10/29] Fix kitchen sink test --- test/example/c-api-kitchen-sink.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 8f7e866920f..80f52828d61 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -530,7 +530,7 @@ void test_core() { tb, 2, kitchenSinkerRefType, BinaryenPackedTypeNotPacked(), true); TypeBuilderSetStructType( tb, - 2, + 3, (BinaryenType[]){BinaryenTypeInt32()}, (BinaryenPackedType[]){BinaryenPackedTypeNotPacked()}, (bool[]){true}, @@ -539,7 +539,8 @@ void test_core() { TypeBuilderBuildAndDispose(tb, (BinaryenHeapType*)&builtHeapTypes, 0, 0); i8Array = BinaryenTypeFromHeapType(builtHeapTypes[0], true); i16Array = BinaryenTypeFromHeapType(builtHeapTypes[1], true); - i32Struct = BinaryenTypeFromHeapType(builtHeapTypes[2], true); + kitchenSinkerArray = BinaryenTypeFromHeapType(builtHeapTypes[2], true); + i32Struct = BinaryenTypeFromHeapType(builtHeapTypes[3], true); } // Memory. Add it before creating any memory-using instructions. From 919dbb21f274ae1a052396fcc66dee0c001da351 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Thu, 10 Apr 2025 10:31:33 +0500 Subject: [PATCH 11/29] Fix null ref in kitchen sink test --- test/example/c-api-kitchen-sink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 80f52828d61..a4c3455f53b 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -1333,7 +1333,7 @@ void test_core() { BinaryenArrayNew(module, BinaryenTypeGetHeapType(kitchenSinkerArray), makeInt32(module, 0), - BinaryenRefNull(module, kitchenSinkerRefType))); + BinaryenRefNull(module, BinaryenTypeNullFuncref()))); BinaryenAddGlobal( module, "i32Struct-global", From 4c56fee1bf059153e061311b09077f5e34b35be9 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Thu, 10 Apr 2025 11:08:50 +0500 Subject: [PATCH 12/29] Replace table type --- test/example/c-api-kitchen-sink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index a4c3455f53b..a6a265a3ba4 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -1359,7 +1359,7 @@ void test_core() { // Function table. One per module const char* funcNames[] = {BinaryenFunctionGetName(sinker)}; - BinaryenAddTable(module, "0", 1, 1, BinaryenTypeFuncref()); + BinaryenAddTable(module, "0", 1, 1, kitchenSinkerRefType); BinaryenAddActiveElementSegment( module, "0", From 618592f276f48bc53938bf6fc10ea632ca39958e Mon Sep 17 00:00:00 2001 From: GulgDev Date: Thu, 10 Apr 2025 11:55:38 +0500 Subject: [PATCH 13/29] Fix array types in test --- test/example/c-api-kitchen-sink.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index a6a265a3ba4..40b9e3a0d53 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -518,7 +518,7 @@ void test_core() { BinaryenType v128 = BinaryenTypeVec128(); BinaryenType i8Array; BinaryenType i16Array; - BinaryenType kitchenSinkerArray; + BinaryenType funcArray; BinaryenType i32Struct; { TypeBuilderRef tb = TypeBuilderCreate(4); @@ -527,7 +527,7 @@ void test_core() { TypeBuilderSetArrayType( tb, 1, BinaryenTypeInt32(), BinaryenPackedTypeInt16(), true); TypeBuilderSetArrayType( - tb, 2, kitchenSinkerRefType, BinaryenPackedTypeNotPacked(), true); + tb, 2, BinaryenTypeFuncref(), BinaryenPackedTypeNotPacked(), true); TypeBuilderSetStructType( tb, 3, @@ -539,7 +539,7 @@ void test_core() { TypeBuilderBuildAndDispose(tb, (BinaryenHeapType*)&builtHeapTypes, 0, 0); i8Array = BinaryenTypeFromHeapType(builtHeapTypes[0], true); i16Array = BinaryenTypeFromHeapType(builtHeapTypes[1], true); - kitchenSinkerArray = BinaryenTypeFromHeapType(builtHeapTypes[2], true); + funcArray = BinaryenTypeFromHeapType(builtHeapTypes[2], true); i32Struct = BinaryenTypeFromHeapType(builtHeapTypes[3], true); } @@ -1194,8 +1194,8 @@ void test_core() { BinaryenArrayInitElem(module, "0", BinaryenGlobalGet(module, - "kitchenSinkerArray-global", - kitchenSinkerArray), + "funcArray-global", + funcArray), makeInt32(module, 0), makeInt32(module, 1), makeInt32(module, 2)), @@ -1327,11 +1327,11 @@ void test_core() { module, BinaryenTypeGetHeapType(i16Array), makeInt32(module, 0), 0)); BinaryenAddGlobal( module, - "kitchenSinkerArray-global", - kitchenSinkerArray, + "funcArray-global", + funcArray, true, BinaryenArrayNew(module, - BinaryenTypeGetHeapType(kitchenSinkerArray), + BinaryenTypeGetHeapType(funcArray), makeInt32(module, 0), BinaryenRefNull(module, BinaryenTypeNullFuncref()))); BinaryenAddGlobal( @@ -1359,7 +1359,7 @@ void test_core() { // Function table. One per module const char* funcNames[] = {BinaryenFunctionGetName(sinker)}; - BinaryenAddTable(module, "0", 1, 1, kitchenSinkerRefType); + BinaryenAddTable(module, "0", 1, 1, BinaryenTypeFuncref()); BinaryenAddActiveElementSegment( module, "0", From de0d9561f50bc525c06a687f03b7970aa836669d Mon Sep 17 00:00:00 2001 From: GulgDev Date: Thu, 10 Apr 2025 12:28:13 +0500 Subject: [PATCH 14/29] Fix formatting & update test results --- test/example/c-api-kitchen-sink.c | 15 +++++++-------- test/example/c-api-kitchen-sink.txt | 25 +++++++++++++++---------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 40b9e3a0d53..190e07f261d 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -1191,14 +1191,13 @@ void test_core() { makeInt32(module, 0), makeInt32(module, 1), makeInt32(module, 2)), - BinaryenArrayInitElem(module, - "0", - BinaryenGlobalGet(module, - "funcArray-global", - funcArray), - makeInt32(module, 0), - makeInt32(module, 1), - makeInt32(module, 2)), + BinaryenArrayInitElem( + module, + "0", + BinaryenGlobalGet(module, "funcArray-global", funcArray), + makeInt32(module, 0), + makeInt32(module, 1), + makeInt32(module, 2)), // Strings BinaryenStringNew(module, BinaryenStringNewLossyUTF8Array(), diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 177b63e3039..1961547c5a1 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -67,17 +67,22 @@ BinaryenFeatureAll: 4194303 (type $0 (array (mut i8))) (type $1 (struct (field (mut i32)))) (type $2 (func (param i32 i64 f32 f64) (result i32))) - (type $3 (array (mut i16))) - (type $4 (func (param i32))) - (type $5 (func (param i32 f64) (result f32))) - (type $6 (func)) - (import "module" "base" (func $an-imported (type $5) (param i32 f64) (result f32))) + (type $3 (array (mut funcref))) + (type $4 (array (mut i16))) + (type $5 (func (param i32))) + (type $6 (func (param i32 f64) (result f32))) + (type $7 (func)) + (import "module" "base" (func $an-imported (type $6) (param i32 f64) (result f32))) (global $a-global i32 (i32.const 7)) (global $a-mutable-global (mut f32) (f32.const 7.5)) (global $i8Array-global (mut (ref null $0)) (array.new_default $0 (i32.const 0) )) - (global $i16Array-global (mut (ref null $3)) (array.new_default $3 + (global $i16Array-global (mut (ref null $4)) (array.new_default $4 + (i32.const 0) + )) + (global $funcArray-global (mut (ref null $3)) (array.new $3 + (ref.null nofunc) (i32.const 0) )) (global $i32Struct-global (mut (ref null $1)) (struct.new_default $1)) @@ -91,7 +96,7 @@ BinaryenFeatureAll: 4194303 (table $0 1 1 funcref) (elem $0 (table $0) (i32.const 0) func $"kitchen()sinker") (elem $passive func $"kitchen()sinker") - (tag $a-tag (type $4) (param i32)) + (tag $a-tag (type $5) (param i32)) (export "mem" (memory $0)) (export "kitchen_sinker" (func $"kitchen()sinker")) (start $starter) @@ -2346,8 +2351,8 @@ BinaryenFeatureAll: 4194303 (i32.const 1) (i32.const 2) ) - (array.init_elem $0 $0 - (global.get $kitchenSinkerArray-global) + (array.init_elem $3 $0 + (global.get $funcArray-global) (i32.const 0) (i32.const 1) (i32.const 2) @@ -2437,7 +2442,7 @@ BinaryenFeatureAll: 4194303 (i32.const 42) ) ) - (func $starter (type $6) + (func $starter (type $7) (nop) ) ) From ef5ed0f4578ba4f821ee4725555599f66eaf26aa Mon Sep 17 00:00:00 2001 From: GulgDev Date: Thu, 10 Apr 2025 13:05:28 +0500 Subject: [PATCH 15/29] Fix UB in test --- test/example/c-api-kitchen-sink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 190e07f261d..85937929d7e 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -535,7 +535,7 @@ void test_core() { (BinaryenPackedType[]){BinaryenPackedTypeNotPacked()}, (bool[]){true}, 1); - BinaryenHeapType builtHeapTypes[3]; + BinaryenHeapType builtHeapTypes[4]; TypeBuilderBuildAndDispose(tb, (BinaryenHeapType*)&builtHeapTypes, 0, 0); i8Array = BinaryenTypeFromHeapType(builtHeapTypes[0], true); i16Array = BinaryenTypeFromHeapType(builtHeapTypes[1], true); From 5143ebad4033d65d0eeae04f0b19b43c1425921e Mon Sep 17 00:00:00 2001 From: GulgDev Date: Fri, 11 Apr 2025 13:41:06 +0500 Subject: [PATCH 16/29] Update Binaryen.js API & tests (array.new_elem, array.init_data, array.init_elem) --- src/js/binaryen.js-post.js | 19 +++- test/binaryen.js/gc.js | 202 +++++++++++++++++++++++-------------- test/binaryen.js/gc.js.txt | 79 +++++++-------- 3 files changed, 180 insertions(+), 120 deletions(-) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index efc517dfbd7..ae4b6fe9fcd 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -40,6 +40,9 @@ function initializeConstants() { ['i31ref', 'I31ref'], ['structref', 'Structref'], ['stringref', 'Stringref'], + ['nullref', 'Nullref'], + ['nullexternref', 'NullExternref'], + ['nullfuncref', 'NullFuncref'], ['unreachable', 'Unreachable'], ['auto', 'Auto'] ].forEach(entry => { @@ -2515,7 +2518,9 @@ function wrapModule(module, self = {}) { 'new_data'(type, name, offset, size) { return preserveStack(() => Module['_BinaryenArrayNewData'](module, type, strToStack(name), offset, size)); }, - // TODO: array.new_elem + 'new_elem'(type, name, offset, size) { + return preserveStack(() => Module['_BinaryenArrayNewElem'](module, type, strToStack(name), offset, size)); + }, 'get'(ref, index, type, isSigned) { return Module['_BinaryenArrayGet'](module, ref, index, type, isSigned); }, @@ -2525,12 +2530,18 @@ function wrapModule(module, self = {}) { 'len'(ref) { return Module['_BinaryenArrayLen'](module, ref); }, - // TODO: array.fill + 'fill'(ref, index, value, size) { + return Module['_BinaryenArrayFill'](module, ref, index, value, size); + }, 'copy'(destRef, destIndex, srcRef, srcIndex, length) { return Module['_BinaryenArrayCopy'](module, destRef, destIndex, srcRef, srcIndex, length); }, - // TODO: array.init_data - // TODO: array.init_elem + 'init_data'(name, ref, index, offset, size) { + return preserveStack(() => Module['_BinaryenArrayInitData'](module, strToStack(name), ref, index, offset, size)); + }, + 'init_elem'(name, ref, index, offset, size) { + return preserveStack(() => Module['_BinaryenArrayInitElem'](module, strToStack(name), ref, index, offset, size)); + } }; // TODO: string.* diff --git a/test/binaryen.js/gc.js b/test/binaryen.js/gc.js index d69e2e1a279..0f12184b4c4 100644 --- a/test/binaryen.js/gc.js +++ b/test/binaryen.js/gc.js @@ -1,40 +1,41 @@ -var builder = new binaryen.TypeBuilder(3); +var builder = new binaryen.TypeBuilder(4); builder.setSignatureType(0, binaryen.createType([binaryen.i32]), binaryen.none); builder.setStructType(1, [ - { type: binaryen.i32, packedType: binaryen.notPacked, mutable: true }, + { type: binaryen.i32, packedType: binaryen.i16, mutable: true }, { type: binaryen.f64, packedType: binaryen.notPacked, mutable: true } ]); -builder.setArrayType(2, binaryen.i32, binaryen.notPacked, true); +builder.setArrayType(2, binaryen.i32, binaryen.i8, true); +builder.setArrayType(3, binaryen.funcref, binaryen.notPacked, true); var [ signatureHeapType, structHeapType, - arrayHeapType + arrayHeapType, + funcArrayHeapType ] = builder.buildAndDispose(); -var signatureType = binaryen.getTypeFromHeapType(signatureHeapType); -var structType = binaryen.getTypeFromHeapType(structHeapType); -var arrayType = binaryen.getTypeFromHeapType(arrayHeapType); +var signatureType = binaryen.getTypeFromHeapType(signatureHeapType, true); +var structType = binaryen.getTypeFromHeapType(structHeapType, true); +var arrayType = binaryen.getTypeFromHeapType(arrayHeapType, true); +var funcArrayType = binaryen.getTypeFromHeapType(funcArrayHeapType, true); var module = new binaryen.Module(); module.setFeatures(binaryen.Features.ReferenceTypes | binaryen.Features.BulkMemory | binaryen.Features.GC); +module.addFunction("add", binaryen.createType([binaryen.i32, binaryen.i32]), binaryen.i32, [], + module.i32.add( + module.local.get("0", binaryen.i32), + module.local.get("1", binaryen.i32) + ) +); + module.setMemory(1, -1, null, [ { offset: module.i32.const(0), data: [4, 3, 2, 1] } ]); -module.addGlobal("global-struct.new", - structType, - true, - module.struct.new( - [ - module.i32.const(123), - module.f64.const(123.456) - ], - binaryen.getHeapType(structType) - ) -); +module.addTable("0", 1, -1); +module.addActiveElementSegment("0", "0", ["add"]); -module.addGlobal("global-struct.new_default", +module.addGlobal("struct-global", structType, true, module.struct.new_default( @@ -42,79 +43,134 @@ module.addGlobal("global-struct.new_default", ) ); -module.addGlobal("global-array.new", +module.addGlobal("array-global", arrayType, true, - module.array.new( + module.array.new_default( binaryen.getHeapType(arrayType), - module.i32.const(4), - module.i32.const(123) + module.i32.const(4) ) ); -module.addGlobal("global-array.new_default", - arrayType, +module.addGlobal("funcArray-global", + funcArrayType, true, module.array.new_default( - binaryen.getHeapType(arrayType), + binaryen.getHeapType(funcArrayType), module.i32.const(4) ) ); -module.addGlobal("global-array.new_fixed", - arrayType, - true, +var valueList = [ + // ref + + // struct + module.struct.new( + [ + module.i32.const(1), + module.f64.const(2.3) + ], + binaryen.getHeapType(structType) + ), + module.struct.new_default( + binaryen.getHeapType(structType) + ), + module.struct.get( + 0, + module.global.get("struct-global", structType), + binaryen.i32, + true + ), + module.struct.set( + 1, + module.global.get("struct-global", structType), + module.f64.const(1.23) + ), + + // array + module.array.new( + binaryen.getHeapType(arrayType), + module.i32.const(1), + module.i32.const(0) + ), + module.array.new_default( + binaryen.getHeapType(arrayType), + module.i32.const(1) + ), module.array.new_fixed( binaryen.getHeapType(arrayType), [ module.i32.const(1), module.i32.const(2), - module.i32.const(3), - module.i32.const(4) + module.i32.const(3) ] + ), + module.array.new_data( + binaryen.getHeapType(arrayType), + "0", + module.i32.const(0), + module.i32.const(4) + ), + module.array.new_elem( + binaryen.getHeapType(funcArrayType), + "0", + module.i32.const(0), + module.i32.const(1) + ), + module.array.get( + module.global.get("array-global", arrayType), + module.i32.const(0), + binaryen.i32, + true + ), + module.array.set( + module.global.get("array-global", arrayType), + module.i32.const(1), + module.i32.const(2) + ), + module.array.len( + module.global.get("array-global", arrayType) + ), + module.array.fill( + module.global.get("array-global", arrayType), + module.i32.const(0), + module.i32.const(1), + module.i32.const(2) + ), + module.array.copy( + module.global.get("array-global", arrayType), + module.i32.const(0), + module.global.get("array-global", arrayType), + module.i32.const(1), + module.i32.const(2) + ), + module.array.init_data( + "0", + module.global.get("array-global", arrayType), + module.i32.const(0), + module.i32.const(1), + module.i32.const(2) + ), + module.array.init_elem( + "0", + module.global.get("funcArray-global", funcArrayType), + module.i32.const(0), + module.i32.const(1), + module.i32.const(2) + ) +]; +module.addFunction("main", binaryen.none, binaryen.none, [], + module.block( + null, + valueList.map(value => { + var type = binaryen.getExpressionType(value); + if (type === binaryen.none || type === binaryen.unreachable) + return value; + else + return module.drop(value); + }), + binaryen.none ) -); - -module.addFunction("main", binaryen.none, binaryen.none, [binaryen.i32, binaryen.f64], - module.block(null, [ - module.global.set("global-array.new_default", - module.array.new_data( - binaryen.getHeapType(arrayType), - "0", - module.i32.const(0), - module.i32.const(4) - ) - ), - - module.array.copy( - module.global.get("global-array.new_fixed", arrayType), - module.i32.const(0), - module.global.get("global-array.new_default", arrayType), - module.i32.const(0), - module.array.len( - module.global.get("global-array.new_default", arrayType) - ) - ), - module.array.set( - module.global.get("global-array.new", arrayType), - module.i32.const(2), - module.array.get( - module.global.get("global-array.new_default", arrayType), - module.i32.const(0), - binaryen.i32, - false - ) - ), - - module.local.set(0, module.struct.get(0, module.global.get("global-struct.new", structType), false)), - module.struct.set( - 1, - module.global.get("global-struct.new_default", structType), - module.f64.convert_u.i32( - module.local.get(0, binaryen.i32) - ) - ) - ], binaryen.none) ); assert(module.validate()); diff --git a/test/binaryen.js/gc.js.txt b/test/binaryen.js/gc.js.txt index 42dd68b6e3c..70a0dd1058c 100644 --- a/test/binaryen.js/gc.js.txt +++ b/test/binaryen.js/gc.js.txt @@ -1,62 +1,55 @@ (module - (type $0 (array (mut i32))) - (type $1 (struct (field (mut i32)) (field (mut f64)))) + (type $0 (struct (field (mut i16)) (field (mut f64)))) + (type $1 (array (mut i8))) (type $2 (func)) - (global $global-struct.new (mut (ref $1)) (struct.new $1 - (i32.const 123) - (f64.const 123.456) - )) - (global $global-struct.new_default (mut (ref $1)) (struct.new_default $1)) - (global $global-array.new (mut (ref $0)) (array.new $0 - (i32.const 123) - (i32.const 4) - )) - (global $global-array.new_default (mut (ref $0)) (array.new_default $0 - (i32.const 4) - )) - (global $global-array.new_fixed (mut (ref $0)) (array.new_fixed $0 4 - (i32.const 1) - (i32.const 2) - (i32.const 3) + (global $struct-global (mut (ref $0)) (struct.new_default $0)) + (global $array-global (mut (ref $1)) (array.new_default $1 (i32.const 4) )) (memory $0 1) (data $0 (i32.const 0) "\04\03\02\01") + (table $0 1 funcref) (func $main (type $2) - (local $0 i32) - (local $1 f64) - (global.set $global-array.new_default - (array.new_data $0 $0 - (i32.const 0) - (i32.const 4) + (drop + (struct.new $0 + (i32.const 1) + (f64.const 2.3) ) ) - (array.copy $0 $0 - (global.get $global-array.new_fixed) - (i32.const 0) - (global.get $global-array.new_default) - (i32.const 0) - (array.len - (global.get $global-array.new_default) + (drop + (struct.new_default $0) + ) + (drop + (struct.get_s $0 0 + (global.get $struct-global) ) ) - (array.set $0 - (global.get $global-array.new) - (i32.const 2) - (array.get $0 - (global.get $global-array.new_default) + (struct.set $0 1 + (global.get $struct-global) + (f64.const 1.23) + ) + (drop + (array.new $1 (i32.const 0) + (i32.const 1) + ) + ) + (drop + (array.new_default $1 + (i32.const 1) ) ) - (local.set $0 - (struct.get $1 0 - (global.get $global-struct.new) + (drop + (array.new_fixed $1 3 + (i32.const 1) + (i32.const 2) + (i32.const 3) ) ) - (struct.set $1 1 - (global.get $global-struct.new_default) - (f64.convert_i32_u - (local.get $0) + (drop + (array.new_data $1 $0 + (i32.const 0) + (i32.const 4) ) ) ) From 889b941982e6d88ca34ec9ae3c8627755d6855f0 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Fri, 11 Apr 2025 13:41:59 +0500 Subject: [PATCH 17/29] Fix expected test results for GC --- test/binaryen.js/gc.js.txt | 87 ++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 14 deletions(-) diff --git a/test/binaryen.js/gc.js.txt b/test/binaryen.js/gc.js.txt index 70a0dd1058c..7b557c7c743 100644 --- a/test/binaryen.js/gc.js.txt +++ b/test/binaryen.js/gc.js.txt @@ -1,57 +1,116 @@ (module - (type $0 (struct (field (mut i16)) (field (mut f64)))) - (type $1 (array (mut i8))) - (type $2 (func)) - (global $struct-global (mut (ref $0)) (struct.new_default $0)) - (global $array-global (mut (ref $1)) (array.new_default $1 + (type $0 (array (mut i8))) + (type $1 (struct (field (mut i16)) (field (mut f64)))) + (type $2 (array (mut funcref))) + (type $3 (func (param i32 i32) (result i32))) + (type $4 (func)) + (global $struct-global (mut (ref null $1)) (struct.new_default $1)) + (global $array-global (mut (ref null $0)) (array.new_default $0 + (i32.const 4) + )) + (global $funcArray-global (mut (ref null $2)) (array.new_default $2 (i32.const 4) )) (memory $0 1) (data $0 (i32.const 0) "\04\03\02\01") (table $0 1 funcref) - (func $main (type $2) + (elem $0 (i32.const 0) $add) + (func $add (type $3) (param $0 i32) (param $1 i32) (result i32) + (i32.add + (local.get $0) + (local.get $1) + ) + ) + (func $main (type $4) (drop - (struct.new $0 + (struct.new $1 (i32.const 1) (f64.const 2.3) ) ) (drop - (struct.new_default $0) + (struct.new_default $1) ) (drop - (struct.get_s $0 0 + (struct.get_s $1 0 (global.get $struct-global) ) ) - (struct.set $0 1 + (struct.set $1 1 (global.get $struct-global) (f64.const 1.23) ) (drop - (array.new $1 + (array.new $0 (i32.const 0) (i32.const 1) ) ) (drop - (array.new_default $1 + (array.new_default $0 (i32.const 1) ) ) (drop - (array.new_fixed $1 3 + (array.new_fixed $0 3 (i32.const 1) (i32.const 2) (i32.const 3) ) ) (drop - (array.new_data $1 $0 + (array.new_data $0 $0 (i32.const 0) (i32.const 4) ) ) + (drop + (array.new_elem $2 $0 + (i32.const 0) + (i32.const 1) + ) + ) + (drop + (array.get_s $0 + (global.get $array-global) + (i32.const 0) + ) + ) + (array.set $0 + (global.get $array-global) + (i32.const 1) + (i32.const 2) + ) + (drop + (array.len + (global.get $array-global) + ) + ) + (array.fill $0 + (global.get $array-global) + (i32.const 0) + (i32.const 1) + (i32.const 2) + ) + (array.copy $0 $0 + (global.get $array-global) + (i32.const 0) + (global.get $array-global) + (i32.const 1) + (i32.const 2) + ) + (array.init_data $0 $0 + (global.get $array-global) + (i32.const 0) + (i32.const 1) + (i32.const 2) + ) + (array.init_elem $2 $0 + (global.get $funcArray-global) + (i32.const 0) + (i32.const 1) + (i32.const 2) + ) ) ) From 8e82b0b76c984e7698844a8884272cd801323d8d Mon Sep 17 00:00:00 2001 From: GulgDev Date: Fri, 11 Apr 2025 20:57:31 +0500 Subject: [PATCH 18/29] Add expression wrappers for `RefTest`, `RefCast` and `BrOn` --- src/js/binaryen.js-post.js | 62 ++++++++++++++++-- test/binaryen.js/expressions.js | 97 +++++++++++++++++++++++++++++ test/binaryen.js/expressions.js.txt | 15 +++++ 3 files changed, 170 insertions(+), 4 deletions(-) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index ae4b6fe9fcd..ead1b6abeb2 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -2472,12 +2472,12 @@ function wrapModule(module, self = {}) { } }; - self['br_on_null'] = function(name, value, castType) { - return preserveStack(() => Module['_BinaryenBrOn'](module, Module['BrOnNull'], strToStack(name), value, castType)); + self['br_on_null'] = function(name, value) { + return preserveStack(() => Module['_BinaryenBrOn'](module, Module['BrOnNull'], strToStack(name), value, Module['unreachable'])); }; - self['br_on_non_null'] = function(name, value, castType) { - return preserveStack(() => Module['_BinaryenBrOn'](module, Module['BrOnNonNull'], strToStack(name), value, castType)); + self['br_on_non_null'] = function(name, value) { + return preserveStack(() => Module['_BinaryenBrOn'](module, Module['BrOnNonNull'], strToStack(name), value, Module['unreachable'])); }; self['br_on_cast'] = function(name, value, castType) { @@ -4943,6 +4943,60 @@ Module['RefEq'] = makeExpressionWrapper({ } }); +Module['RefTest'] = makeExpressionWrapper({ + 'getRef'(expr) { + return Module['_BinaryenRefTestGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenRefTestSetRef'](expr, ref); + }, + 'getCastType'(expr) { + return Module['_BinaryenRefTestGetCastType'](expr); + }, + 'setCastType'(expr, castType) { + Module['_BinaryenRefTestSetCastType'](expr, castType); + } +}); + +Module['RefCast'] = makeExpressionWrapper({ + 'getRef'(expr) { + return Module['_BinaryenRefCastGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenRefCastSetRef'](expr, ref); + } +}); + +// TODO: any.convert_extern +// TODO: extern.convert_any + +Module['BrOn'] = makeExpressionWrapper({ + 'getOp'(expr) { + return Module['_BinaryenBrOnGetOp'](expr); + }, + 'setOp'(expr, op) { + Module['_BinaryenBrOnSetOp'](expr, op); + }, + 'getName'(expr) { + return UTF8ToString(Module['_BinaryenBrOnGetName'](expr)); + }, + 'setName'(expr, name) { + preserveStack(() => Module['_BinaryenBrOnSetName'](expr, strToStack(name))); + }, + 'getRef'(expr) { + return Module['_BinaryenBrOnGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenBrOnSetRef'](expr, ref); + }, + 'getCastType'(expr) { + return Module['_BinaryenBrOnGetCastType'](expr); + }, + 'setCastType'(expr, castType) { + Module['_BinaryenBrOnSetCastType'](expr, castType); + } +}); + Module['Try'] = makeExpressionWrapper({ 'getName'(expr) { const name = Module['_BinaryenTryGetName'](expr); diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js index 0d1c9669084..a5eec8491c0 100644 --- a/test/binaryen.js/expressions.js +++ b/test/binaryen.js/expressions.js @@ -1531,6 +1531,103 @@ console.log("# RefEq"); module.dispose(); })(); +console.log("# RefTest"); +(function testRefTest() { + const module = new binaryen.Module(); + + var ref = module.local.get(0, binaryen.anyref); + var castType = binaryen.anyref; + const theRefTest = binaryen.RefTest(module.ref.test(ref, castType)); + assert(theRefTest instanceof binaryen.RefTest); + assert(theRefTest instanceof binaryen.Expression); + assert(theRefTest.ref === ref); + assert(theRefTest.castType === castType); + assert(theRefTest.type === binaryen.i32); + + theRefTest.ref = ref = module.local.get(2, binaryen.externref); + assert(theRefTest.ref === ref); + theRefTest.castType = castType = binaryen.externref; + assert(theRefTest.castType === castType); + theRefTest.type = binaryen.f64; + theRefTest.finalize(); + assert(theRefTest.type === binaryen.i32); + + console.log(theRefTest.toText()); + assert( + theRefTest.toText() + == + "(ref.test externref\n (local.get $2)\n)\n" + ); + + module.dispose(); +})(); + +console.log("# RefCast"); +(function testRefCast() { + const module = new binaryen.Module(); + + var ref = module.local.get(0, binaryen.anyref); + var type = binaryen.anyref; + const theRefCast = binaryen.RefCast(module.ref.cast(ref, type)); + assert(theRefCast instanceof binaryen.RefCast); + assert(theRefCast instanceof binaryen.Expression); + assert(theRefCast.ref === ref); + assert(theRefCast.type === type); + + theRefCast.ref = ref = module.local.get(2, binaryen.externref); + assert(theRefCast.ref === ref); + theRefCast.type = type = binaryen.externref; + theRefCast.finalize(); + assert(theRefCast.type === type); + + console.log(theRefCast.toText()); + assert( + theRefCast.toText() + == + "(ref.cast externref\n (local.get $2)\n)\n" + ); + + module.dispose(); +})(); + +console.log("# BrOn"); +(function testBrOn() { + const module = new binaryen.Module(); + + var name = "br"; + var ref = module.local.get(0, binaryen.externref); + var op = binaryen.Operations.BrOnNull; + var castType = binaryen.unreachable; + const theBrOn = binaryen.BrOn(module.br_on_null(name, ref)); + assert(theBrOn instanceof binaryen.BrOn); + assert(theBrOn instanceof binaryen.Expression); + assert(theBrOn.name === name); + assert(theBrOn.ref === ref); + assert(theBrOn.op === op); + assert(theBrOn.castType === castType); + + // TODO: What should theBrOn.type be equal to? + + theBrOn.name = name = "br2"; + assert(theBrOn.name === name); + theBrOn.ref = ref = module.local.get(1, binaryen.anyref); + assert(theBrOn.ref === ref); + theBrOn.op = op = binaryen.Operations.BrOnCast; + assert(theBrOn.op === op); + theBrOn.castType = castType = binaryen.i31ref; + assert(theBrOn.castType === castType); + theBrOn.finalize(); + + console.log(theBrOn.toText()); + assert( + theBrOn.toText() + == + "(br_on_cast $br2 anyref i31ref\n (local.get $1)\n)\n" + ); + + module.dispose(); +})(); + console.log("# Try"); (function testTry() { const module = new binaryen.Module(); diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt index 5d6c37c6bc6..990234195e1 100644 --- a/test/binaryen.js/expressions.js.txt +++ b/test/binaryen.js/expressions.js.txt @@ -239,6 +239,21 @@ (local.get $3) ) +# RefTest +(ref.test externref + (local.get $2) +) + +# RefCast +(ref.cast externref + (local.get $2) +) + +# BrOn +(br_on_cast $br2 anyref i31ref + (local.get $1) +) + # Try (try (result i32) (do From 1fa3a2f301b6005993b4d6cd4ac580a8a9fc04c1 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Fri, 11 Apr 2025 23:02:27 +0500 Subject: [PATCH 19/29] Add expression wrappers for struct instructions --- src/js/binaryen.js-post.js | 76 ++++++++++++++ test/binaryen.js/expressions.js | 154 ++++++++++++++++++++++++++++ test/binaryen.js/expressions.js.txt | 17 +++ 3 files changed, 247 insertions(+) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index ead1b6abeb2..512dacf9409 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -4997,6 +4997,82 @@ Module['BrOn'] = makeExpressionWrapper({ } }); +Module['StructNew'] = makeExpressionWrapper({ + 'getNumOperands'(expr) { + return Module['_BinaryenStructNewGetNumOperands'](expr); + }, + 'getOperands'(expr) { + return getAllNested(expr, Module['_BinaryenStructNewGetNumOperands'], Module['_BinaryenStructNewGetOperandAt']); + }, + 'setOperands'(expr, operands) { + setAllNested( + expr, + operands, + Module['_BinaryenStructNewGetNumOperands'], + Module['_BinaryenStructNewSetOperandAt'], + Module['_BinaryenStructNewAppendOperand'], + Module['_BinaryenStructNewRemoveOperandAt'] + ); + }, + 'getOperandAt'(expr, index) { + return Module['_BinaryenStructNewGetOperandAt'](expr, index); + }, + 'setOperandAt'(expr, index, operandExpr) { + Module['_BinaryenStructNewSetOperandAt'](expr, index, operandExpr); + }, + 'appendOperand'(expr, operandExpr) { + return Module['_BinaryenStructNewAppendOperand'](expr, operandExpr); + }, + 'insertOperandAt'(expr, index, operandExpr) { + Module['_BinaryenStructNewInsertOperandAt'](expr, index, operandExpr); + }, + 'removeOperandAt'(expr, index) { + return Module['_BinaryenStructNewRemoveOperandAt'](expr, index); + } +}); + +Module['StructGet'] = makeExpressionWrapper({ + 'getIndex'(expr) { + return Module['_BinaryenStructGetGetIndex'](expr); + }, + 'setIndex'(expr, index) { + Module['_BinaryenStructGetSetIndex'](expr, index); + }, + 'getRef'(expr) { + return Module['_BinaryenStructGetGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenStructGetSetRef'](expr, ref); + }, + 'getSigned'(expr) { + return Boolean(Module['_BinaryenStructGetIsSigned'](expr)); + }, + 'setSigned'(expr, signed) { + Module['_BinaryenStructGetSetSigned'](expr, signed); + } +}); + +Module['StructSet'] = makeExpressionWrapper({ + 'getIndex'(expr) { + return Module['_BinaryenStructSetGetIndex'](expr); + }, + 'setIndex'(expr, index) { + Module['_BinaryenStructSetSetIndex'](expr, index); + }, + 'getRef'(expr) { + return Module['_BinaryenStructSetGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenStructSetSetRef'](expr, ref); + }, + 'getValue'(expr) { + return Module['_BinaryenStructSetGetValue'](expr); + }, + 'setValue'(expr, value) { + Module['_BinaryenStructSetSetValue'](expr, value); + } +}); + Module['Try'] = makeExpressionWrapper({ 'getName'(expr) { const name = Module['_BinaryenTryGetName'](expr); diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js index a5eec8491c0..0e5ea49f9bf 100644 --- a/test/binaryen.js/expressions.js +++ b/test/binaryen.js/expressions.js @@ -1628,6 +1628,160 @@ console.log("# BrOn"); module.dispose(); })(); +console.log("# StructNew"); +(function testStructNew() { + const builder = new binaryen.TypeBuilder(2); + builder.setStructType(0, [ + { type: binaryen.i32, packedType: binaryen.notPacked, mutable: true }, + ]); + builder.setStructType(1, [ + { type: binaryen.i32, packedType: binaryen.i16, mutable: true }, + { type: binaryen.i64, packedType: binaryen.notPacked, mutable: true } + ]); + var [ + struct0Type, + struct1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var operands = [ + module.i32.const(1), + module.i32.const(2) + ]; + var type = struct0Type; + const theStructNew = binaryen.StructNew(module.struct.new(operands, type)); + assert(theStructNew instanceof binaryen.StructNew); + assert(theStructNew instanceof binaryen.Expression); + assertDeepEqual(theStructNew.operands, operands); + assertDeepEqual(theStructNew.getOperands(), operands); + assert(theStructNew.type === type); + + theStructNew.operands = operands = [ + module.i32.const(3), // set + module.i32.const(4), // set + module.i32.const(5) // append + ]; + assertDeepEqual(theStructNew.operands, operands); + operands = [ + module.i32.const(6) // set + // remove + // remove + ]; + theStructNew.setOperands(operands); + assertDeepEqual(theStructNew.operands, operands); + theStructNew.insertOperandAt(0, module.i32.const(7)); + theStructNew.type = type = struct1Type; + theStructNew.finalize(); + assert(theStructNew.type === type); + + console.log(theStructNew.toText()); + assert( + theStructNew.toText() + == + "(struct.new $struct.0\n (i32.const 7)\n (i32.const 6)\n)\n" + ); + + module.dispose(); +})(); + +console.log("# StructGet"); +(function testStructGet() { + const builder = new binaryen.TypeBuilder(2); + builder.setStructType(0, [ + { type: binaryen.i32, packedType: binaryen.notPacked, mutable: true }, + ]); + builder.setStructType(1, [ + { type: binaryen.i32, packedType: binaryen.i16, mutable: true }, + { type: binaryen.i64, packedType: binaryen.notPacked, mutable: true } + ]); + var [ + struct0Type, + struct1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var index = 0; + var ref = module.local.get(0, struct0Type); + var type = binaryen.i32; + var signed = false; + const theStructGet = binaryen.StructGet(module.struct.get(index, ref, type, signed)); + assert(theStructGet instanceof binaryen.StructGet); + assert(theStructGet instanceof binaryen.Expression); + assert(theStructGet.index === index); + assert(theStructGet.ref === ref); + assert(theStructGet.signed === signed); + assert(theStructGet.type === type); + + theStructGet.index = index = 1; + assert(theStructGet.index === index); + theStructGet.ref = ref = module.local.get(1, struct1Type); + assert(theStructGet.ref === ref); + theStructGet.signed = signed = true; + assert(theStructGet.signed === signed); + theStructGet.type = type = binaryen.i64; + theStructGet.finalize(); + assert(theStructGet.type === type); + + console.log(theStructGet.toText()); + assert( + theStructGet.toText() + == + "(struct.get $struct.0 1\n (local.get $1)\n)\n" + ); + + module.dispose(); +})(); + +console.log("# StructSet"); +(function testStructSet() { + const builder = new binaryen.TypeBuilder(2); + builder.setStructType(0, [ + { type: binaryen.i32, packedType: binaryen.notPacked, mutable: true }, + ]); + builder.setStructType(1, [ + { type: binaryen.i32, packedType: binaryen.i16, mutable: true }, + { type: binaryen.i64, packedType: binaryen.notPacked, mutable: true } + ]); + var [ + struct0Type, + struct1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var index = 0; + var ref = module.local.get(0, struct0Type); + var value = module.local.get(1, binaryen.i32); + const theStructSet = binaryen.StructSet(module.struct.set(index, ref, value)); + assert(theStructSet instanceof binaryen.StructSet); + assert(theStructSet instanceof binaryen.Expression); + assert(theStructSet.index === index); + assert(theStructSet.ref === ref); + assert(theStructSet.value === value); + assert(theStructSet.type === binaryen.none); + + theStructSet.index = index = 1; + assert(theStructSet.index === index); + theStructSet.ref = ref = module.local.get(2, struct1Type); + assert(theStructSet.ref === ref); + theStructSet.value = value = module.local.get(3, binaryen.i64); + assert(theStructSet.value === value); + theStructSet.type = binaryen.f64; + theStructSet.finalize(); + assert(theStructSet.type === binaryen.none); + + console.log(theStructSet.toText()); + assert( + theStructSet.toText() + == + "(struct.set $struct.0 1\n (local.get $2)\n (local.get $3)\n)\n" + ); + + module.dispose(); +})(); + console.log("# Try"); (function testTry() { const module = new binaryen.Module(); diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt index 990234195e1..ae3164a41f6 100644 --- a/test/binaryen.js/expressions.js.txt +++ b/test/binaryen.js/expressions.js.txt @@ -254,6 +254,23 @@ (local.get $1) ) +# StructNew +(struct.new $struct.0 + (i32.const 7) + (i32.const 6) +) + +# StructGet +(struct.get $struct.0 1 + (local.get $1) +) + +# StructSet +(struct.set $struct.0 1 + (local.get $2) + (local.get $3) +) + # Try (try (result i32) (do From 9250d829881b511799c3179b251e2a3be171f3dc Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sat, 12 Apr 2025 01:16:51 +0500 Subject: [PATCH 20/29] Add expression wrappers for `ArrayNew`, `ArrayNewFixed`, `ArrayGet`, `ArraySet`, `ArrayLen`, `ArrayCopy` --- src/binaryen-c.h | 9 +++ src/js/binaryen.js-post.js | 143 +++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 07c35439be3..a582d06567f 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -2469,6 +2469,9 @@ BinaryenArrayNewFixedInsertValueAt(BinaryenExpressionRef expr, BINARYEN_API BinaryenExpressionRef BinaryenArrayNewFixedRemoveValueAt( BinaryenExpressionRef expr, BinaryenIndex index); +// TODO: ArrayNewData +// TODO: ArrayNewElem + // ArrayGet BINARYEN_API BinaryenExpressionRef @@ -2505,6 +2508,8 @@ BinaryenArrayLenGetRef(BinaryenExpressionRef expr); BINARYEN_API void BinaryenArrayLenSetRef(BinaryenExpressionRef expr, BinaryenExpressionRef refExpr); +// TODO: ArrayFill + // ArrayCopy BINARYEN_API BinaryenExpressionRef @@ -2531,6 +2536,10 @@ BinaryenArrayCopyGetLength(BinaryenExpressionRef expr); BINARYEN_API void BinaryenArrayCopySetLength(BinaryenExpressionRef expr, BinaryenExpressionRef lengthExpr); +// TODO: ArrayInitData + +// TODO: ArrayInitElem + // StringNew BINARYEN_API BinaryenOp BinaryenStringNewGetOp(BinaryenExpressionRef expr); diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 512dacf9409..88cd9dbbe74 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -5073,6 +5073,149 @@ Module['StructSet'] = makeExpressionWrapper({ } }); +// TODO: Tests in expressions.js + +Module['ArrayNew'] = makeExpressionWrapper({ + 'getInit'(expr) { + return Module['_BinaryenArrayNewGetInit'](expr); + }, + 'setInit'(expr, init) { + Module['_BinaryenArrayNewSetInit'](expr, init); + }, + 'getSize'(expr) { + return Module['_BinaryenArrayNewGetSize'](expr); + }, + 'setSize'(expr, size) { + Module['_BinaryenArrayNewSetSize'](expr, size); + } +}); + +Module['ArrayNewFixed'] = makeExpressionWrapper({ + 'getNumValues'(expr) { + return Module['_BinaryenArrayNewFixedGetNumValues'](expr); + }, + 'getValues'(expr) { + return getAllNested(expr, + Module['_BinaryenArrayNewFixedGetNumValues'], + Module['_BinaryenArrayNewFixedGetValueAt']); + }, + 'setValues'(expr, values) { + setAllNested( + expr, + values, + Module['_BinaryenArrayNewFixedGetNumValues'], + Module['_BinaryenArrayNewFixedSetValueAt'], + Module['_BinaryenArrayNewFixedAppendValue'], + Module['_BinaryenArrayNewFixedRemoveValueAt'] + ); + }, + 'getValueAt'(expr, index) { + return Module['_BinaryenArrayNewFixedGetValueAt'](expr, index); + }, + 'setValueAt'(expr, index, valueExpr) { + Module['_BinaryenArrayNewFixedSetValueAt'](expr, index, valueExpr); + }, + 'appendValue'(expr, valueExpr) { + return Module['_BinaryenArrayNewFixedAppendValue'](expr, valueExpr); + }, + 'insertValueAt'(expr, index, valueExpr) { + Module['_BinaryenArrayNewFixedInsertValueAt'](expr, index, valueExpr); + }, + 'removeValueAt'(expr, index) { + return Module['_BinaryenArrayNewFixedRemoveValueAt'](expr, index); + } +}); + +Module['ArrayGet'] = makeExpressionWrapper({ + 'getRef'(expr) { + return Module['_BinaryenArrayGetGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenArrayGetSetRef'](expr, ref); + }, + 'getIndex'(expr) { + return Module['_BinaryenArrayGetGetIndex'](expr); + }, + 'setIndex'(expr, index) { + Module['_BinaryenArrayGetSetIndex'](expr, index); + }, + 'getSigned'(expr) { + return Boolean(Module['_BinaryenArrayGetIsSigned'](expr)); + }, + 'setSigned'(expr, signed) { + Module['_BinaryenArrayGetSetSigned'](expr, signed); + } +}); + +Module['ArraySet'] = makeExpressionWrapper({ + 'getRef'(expr) { + return Module['_BinaryenArraySetGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenArraySetSetRef'](expr, ref); + }, + 'getIndex'(expr) { + return Module['_BinaryenArraySetGetIndex'](expr); + }, + 'setIndex'(expr, index) { + Module['_BinaryenArraySetSetIndex'](expr, index); + }, + 'getValue'(expr) { + return Module['_BinaryenArraySetGetValue'](expr); + }, + 'setValue'(expr, value) { + Module['_BinaryenArraySetSetValue'](expr, value); + } +}); + +Module['ArrayLen'] = makeExpressionWrapper({ + 'getRef'(expr) { + return Module['_BinaryenArrayLenGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenArrayLenSetRef'](expr, ref); + } +}); + +// TODO: ArrayFill + +Module['ArrayCopy'] = makeExpressionWrapper({ + 'getDestRef'(expr) { + return Module['_BinaryenArrayCopyGetDestRef'](expr); + }, + 'setDestRef'(expr, ref) { + Module['_BinaryenArrayCopySetDestRef'](expr, ref); + }, + 'getDestIndex'(expr) { + return Module['_BinaryenArrayCopyGetDestIndex'](expr); + }, + 'setDestIndex'(expr, index) { + Module['_BinaryenArrayCopySetDestIndex'](expr, index); + }, + 'getSrcRef'(expr) { + return Module['_BinaryenArrayCopyGetSrcRef'](expr); + }, + 'setSrcRef'(expr, ref) { + Module['_BinaryenArrayCopySetSrcRef'](expr, ref); + }, + 'getSrcIndex'(expr) { + return Module['_BinaryenArrayCopyGetSrcIndex'](expr); + }, + 'setSrcIndex'(expr, index) { + Module['_BinaryenArrayCopySetSrcIndex'](expr, index); + }, + 'getLength'(expr) { + return Module['_BinaryenArrayCopyGetLength'](expr); + }, + 'setLength'(expr, length) { + Module['_BinaryenArrayCopySetLength'](expr, length); + } +}); + +// TODO: ArrayInitData + +// TODO: ArrayInitElem + Module['Try'] = makeExpressionWrapper({ 'getName'(expr) { const name = Module['_BinaryenTryGetName'](expr); From 39f0487c0308d2e261e3e33cc30f1e4a61e7c935 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sat, 12 Apr 2025 14:15:46 +0500 Subject: [PATCH 21/29] Add wrappers for `ArrayNewData` and `ArrayNewElem` --- src/binaryen-c.cpp | 70 ++++++++++++++++++++++++++++++++++++++ src/binaryen-c.h | 31 +++++++++++++++-- src/js/binaryen.js-post.js | 42 +++++++++++++++++++++++ 3 files changed, 141 insertions(+), 2 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index d875986e4bd..1dd48369dd2 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -4322,6 +4322,76 @@ BinaryenArrayNewFixedRemoveValueAt(BinaryenExpressionRef expr, assert(expression->is()); return static_cast(expression)->values.removeAt(index); } +// ArrayNewData +const char* BinaryenArrayNewDataGetSegment(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->segment.str.data(); +} +void BinaryenArrayNewDataSetSegment(BinaryenExpressionRef expr, + const char* segment) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->segment = Name(segment); +} +BinaryenExpressionRef +BinaryenArrayNewDataGetOffset(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->offset; +} +void BinaryenArrayNewDataSetOffset(BinaryenExpressionRef expr, + BinaryenExpressionRef offset) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->offset = offset; +} +BinaryenExpressionRef BinaryenArrayNewDataGetSize(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->size; +} +void BinaryenArrayNewDataSetSize(BinaryenExpressionRef expr, + BinaryenExpressionRef size) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->size = size; +} +// ArrayNewElem +const char* BinaryenArrayNewElemGetSegment(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->segment.str.data(); +} +void BinaryenArrayNewElemSetSegment(BinaryenExpressionRef expr, + const char* segment) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->segment = Name(segment); +} +BinaryenExpressionRef +BinaryenArrayNewElemGetOffset(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->offset; +} +void BinaryenArrayNewElemSetOffset(BinaryenExpressionRef expr, + BinaryenExpressionRef offset) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->offset = offset; +} +BinaryenExpressionRef BinaryenArrayNewElemGetSize(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->size; +} +void BinaryenArrayNewElemSetSize(BinaryenExpressionRef expr, + BinaryenExpressionRef size) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->size = size; +} // ArrayGet BinaryenExpressionRef BinaryenArrayGetGetRef(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; diff --git a/src/binaryen-c.h b/src/binaryen-c.h index a582d06567f..62cb97f48f8 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -2469,8 +2469,35 @@ BinaryenArrayNewFixedInsertValueAt(BinaryenExpressionRef expr, BINARYEN_API BinaryenExpressionRef BinaryenArrayNewFixedRemoveValueAt( BinaryenExpressionRef expr, BinaryenIndex index); -// TODO: ArrayNewData -// TODO: ArrayNewElem +// ArrayNewData + +BINARYEN_API const char* +BinaryenArrayNewDataGetSegment(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayNewDataSetSegment(BinaryenExpressionRef expr, + const char* segment); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayNewDataGetOffset(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayNewDataSetOffset(BinaryenExpressionRef expr, + BinaryenExpressionRef offset); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayNewDataGetSize(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayNewDataSetSize(BinaryenExpressionRef expr, + BinaryenExpressionRef size); + +// ArrayNewElem + +BINARYEN_API const char* +BinaryenArrayNewElemGetSegment(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayNewElemSetSegment(BinaryenExpressionRef expr, + const char* segment); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayNewElemGetOffset(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayNewElemSetOffset(BinaryenExpressionRef expr, + BinaryenExpressionRef offset); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayNewElemGetSize(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayNewElemSetSize(BinaryenExpressionRef expr, + BinaryenExpressionRef size); // ArrayGet diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 88cd9dbbe74..edcf2e73d7e 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -5126,6 +5126,48 @@ Module['ArrayNewFixed'] = makeExpressionWrapper({ } }); +Module['ArrayNewData'] = makeExpressionWrapper({ + 'getSegment'(expr) { + return UTF8ToString(Module['_BinaryenArrayNewDataGetSegment'](expr)); + }, + 'setSegment'(expr, segment) { + preserveStack(() => Module['_BinaryenArrayNewDataSetSegment'](expr, strToStack(segment))); + }, + 'getOffset'(expr) { + return Module['_BinaryenArrayNewDataGetOffset'](expr); + }, + 'setOffset'(expr, offset) { + Module['_BinaryenArrayNewDataSetOffset'](expr, offset); + }, + 'getSize'(expr) { + return Module['_BinaryenArrayNewDataGetSize'](expr); + }, + 'setSize'(expr, size) { + Module['_BinaryenArrayNewDataSetSize'](expr, size); + } +}); + +Module['ArrayNewElem'] = makeExpressionWrapper({ + 'getSegment'(expr) { + return UTF8ToString(Module['_BinaryenArrayNewElemGetSegment'](expr)); + }, + 'setSegment'(expr, segment) { + preserveStack(() => Module['_BinaryenArrayNewElemSetSegment'](expr, strToStack(segment))); + }, + 'getOffset'(expr) { + return Module['_BinaryenArrayNewElemGetOffset'](expr); + }, + 'setOffset'(expr, offset) { + Module['_BinaryenArrayNewElemSetOffset'](expr, offset); + }, + 'getSize'(expr) { + return Module['_BinaryenArrayNewElemGetSize'](expr); + }, + 'setSize'(expr, size) { + Module['_BinaryenArrayNewElemSetSize'](expr, size); + } +}); + Module['ArrayGet'] = makeExpressionWrapper({ 'getRef'(expr) { return Module['_BinaryenArrayGetGetRef'](expr); From ddc6343dc86bcab046fc571695318768b3d68fb5 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sat, 12 Apr 2025 14:33:09 +0500 Subject: [PATCH 22/29] Add test for `ArrayNew` and missing expression ids --- src/js/binaryen.js-post.js | 7 +++-- test/binaryen.js/expressions.js | 40 +++++++++++++++++++++++++++++ test/binaryen.js/expressions.js.txt | 6 +++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index edcf2e73d7e..73ba2356a3d 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -123,10 +123,15 @@ function initializeConstants() { 'StructSet', 'ArrayNew', 'ArrayNewFixed', + 'ArrayNewData', + 'ArrayNewElem', 'ArrayGet', 'ArraySet', 'ArrayLen', + 'ArrayFill', 'ArrayCopy', + 'ArrayInitData', + 'ArrayInitElem', 'RefAs', 'StringNew', 'StringConst', @@ -5073,8 +5078,6 @@ Module['StructSet'] = makeExpressionWrapper({ } }); -// TODO: Tests in expressions.js - Module['ArrayNew'] = makeExpressionWrapper({ 'getInit'(expr) { return Module['_BinaryenArrayNewGetInit'](expr); diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js index 0e5ea49f9bf..61f79232214 100644 --- a/test/binaryen.js/expressions.js +++ b/test/binaryen.js/expressions.js @@ -1782,6 +1782,46 @@ console.log("# StructSet"); module.dispose(); })(); +console.log("# ArrayNew"); +(function testArrayNew() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i32, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var type = array0Type; + var size = module.i32.const(2); + var init = module.i32.const(1); + const theArrayNew = binaryen.ArrayNew(module.array.new(type, size, init)); + assert(theArrayNew instanceof binaryen.ArrayNew); + assert(theArrayNew instanceof binaryen.Expression); + assert(theArrayNew.size === size); + assert(theArrayNew.init === init); + assert(theArrayNew.type === type); + + theArrayNew.size = size = module.i32.const(4); + assert(theArrayNew.size === size); + theArrayNew.init = init = module.i32.const(3); + assert(theArrayNew.init === init); + theArrayNew.type = type = array1Type; + theArrayNew.finalize(); + assert(theArrayNew.type === type); + + console.log(theArrayNew.toText()); + assert( + theArrayNew.toText() + == + "(array.new $array.0\n (i32.const 3)\n (i32.const 4)\n)\n" + ); + + module.dispose(); +})(); + console.log("# Try"); (function testTry() { const module = new binaryen.Module(); diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt index ae3164a41f6..6b749f0c25d 100644 --- a/test/binaryen.js/expressions.js.txt +++ b/test/binaryen.js/expressions.js.txt @@ -271,6 +271,12 @@ (local.get $3) ) +# ArrayNew +(array.new $array.0 + (i32.const 3) + (i32.const 4) +) + # Try (try (result i32) (do From 1bf64dcae71dde548734567ee303772af5a5d098 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sat, 12 Apr 2025 16:43:49 +0500 Subject: [PATCH 23/29] Add test cases for `ArrayNewFixed`, `ArrayNewData` and `ArrayNewElem` --- test/binaryen.js/expressions.js | 140 ++++++++++++++++++++++++++++ test/binaryen.js/expressions.js.txt | 18 ++++ 2 files changed, 158 insertions(+) diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js index 61f79232214..aaa69ef7bac 100644 --- a/test/binaryen.js/expressions.js +++ b/test/binaryen.js/expressions.js @@ -1822,6 +1822,146 @@ console.log("# ArrayNew"); module.dispose(); })(); +console.log("# ArrayNewFixed"); +(function testArrayNewFixed() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i32, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var type = array0Type; + var values = [ + module.i32.const(1), + module.i32.const(2) + ]; + const theArrayNewFixed = binaryen.ArrayNewFixed(module.array.new_fixed(type, values)); + assert(theArrayNewFixed instanceof binaryen.ArrayNewFixed); + assert(theArrayNewFixed instanceof binaryen.Expression); + assertDeepEqual(theArrayNewFixed.values, values); + assertDeepEqual(theArrayNewFixed.getValues(), values); + assert(theArrayNewFixed.type === type); + + theArrayNewFixed.values = values = [ + module.i32.const(3), // set + module.i32.const(4), // set + module.i32.const(5) // append + ]; + assertDeepEqual(theArrayNewFixed.values, values); + values = [ + module.i32.const(6) // set + // remove + // remove + ]; + theArrayNewFixed.setValues(values); + assertDeepEqual(theArrayNewFixed.values, values); + theArrayNewFixed.insertValueAt(0, module.i32.const(7)); + theArrayNewFixed.type = type = array1Type; + theArrayNewFixed.finalize(); + assert(theArrayNewFixed.type === type); + + console.log(theArrayNewFixed.toText()); + assert( + theArrayNewFixed.toText() + == + "(array.new_fixed $array.0 2\n (i32.const 7)\n (i32.const 6)\n)\n" + ); + + module.dispose(); +})(); + +console.log("# ArrayNewData"); +(function testArrayNewData() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i32, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var type = array0Type; + var segment = "0"; + var offset = module.i32.const(1); + var size = module.i32.const(2); + const theArrayNewData = binaryen.ArrayNewData(module.array.new_data(type, segment, offset, size)); + assert(theArrayNewData instanceof binaryen.ArrayNewData); + assert(theArrayNewData instanceof binaryen.Expression); + assert(theArrayNewData.segment === segment); + assert(theArrayNewData.offset === offset); + assert(theArrayNewData.size === size); + assert(theArrayNewData.type === type); + + theArrayNewData.segment = segment = "3"; + assert(theArrayNewData.segment === segment); + theArrayNewData.offset = offset = module.i32.const(4); + assert(theArrayNewData.offset === offset); + theArrayNewData.size = size = module.i32.const(5); + assert(theArrayNewData.size === size); + theArrayNewData.type = type = array1Type; + theArrayNewData.finalize(); + assert(theArrayNewData.type === type); + + console.log(theArrayNewData.toText()); + assert( + theArrayNewData.toText() + == + "(array.new_data $array.0 $3\n (i32.const 4)\n (i32.const 5)\n)\n" + ); + + module.dispose(); +})(); + +console.log("# ArrayNewElem"); +(function testArrayNewElem() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i32, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var type = array0Type; + var segment = "0"; + var offset = module.i32.const(1); + var size = module.i32.const(2); + const theArrayNewElem = binaryen.ArrayNewElem(module.array.new_elem(type, segment, offset, size)); + assert(theArrayNewElem instanceof binaryen.ArrayNewElem); + assert(theArrayNewElem instanceof binaryen.Expression); + assert(theArrayNewElem.segment === segment); + assert(theArrayNewElem.offset === offset); + assert(theArrayNewElem.size === size); + assert(theArrayNewElem.type === type); + + theArrayNewElem.segment = segment = "3"; + assert(theArrayNewElem.segment === segment); + theArrayNewElem.offset = offset = module.i32.const(4); + assert(theArrayNewElem.offset === offset); + theArrayNewElem.size = size = module.i32.const(5); + assert(theArrayNewElem.size === size); + theArrayNewElem.type = type = array1Type; + theArrayNewElem.finalize(); + assert(theArrayNewElem.type === type); + + console.log(theArrayNewElem.toText()); + assert( + theArrayNewElem.toText() + == + "(array.new_elem $array.0 $3\n (i32.const 4)\n (i32.const 5)\n)\n" + ); + + module.dispose(); +})(); + console.log("# Try"); (function testTry() { const module = new binaryen.Module(); diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt index 6b749f0c25d..b49beb02f87 100644 --- a/test/binaryen.js/expressions.js.txt +++ b/test/binaryen.js/expressions.js.txt @@ -277,6 +277,24 @@ (i32.const 4) ) +# ArrayNewFixed +(array.new_fixed $array.0 2 + (i32.const 7) + (i32.const 6) +) + +# ArrayNewData +(array.new_data $array.0 $3 + (i32.const 4) + (i32.const 5) +) + +# ArrayNewElem +(array.new_elem $array.0 $3 + (i32.const 4) + (i32.const 5) +) + # Try (try (result i32) (do From fd75d9bf7b2458f4d4028aa8456100e48ae037c4 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sat, 12 Apr 2025 18:23:21 +0500 Subject: [PATCH 24/29] Add test cases for `ArrayGet`, `ArraySet` and `ArrayLen` --- test/binaryen.js/expressions.js | 122 ++++++++++++++++++++++++++++ test/binaryen.js/expressions.js.txt | 18 ++++ 2 files changed, 140 insertions(+) diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js index aaa69ef7bac..f4319d0877a 100644 --- a/test/binaryen.js/expressions.js +++ b/test/binaryen.js/expressions.js @@ -1962,6 +1962,128 @@ console.log("# ArrayNewElem"); module.dispose(); })(); +console.log("# ArrayGet"); +(function testArrayGet() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i64, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var ref = module.local.get(0, array0Type); + var index = module.i32.const(0); + var type = binaryen.i32; + var signed = false; + const theArrayGet = binaryen.ArrayGet(module.array.get(ref, index, type, signed)); + assert(theArrayGet instanceof binaryen.ArrayGet); + assert(theArrayGet instanceof binaryen.Expression); + assert(theArrayGet.ref === ref); + assert(theArrayGet.index === index); + assert(theArrayGet.signed === signed); + assert(theArrayGet.type === type); + + theArrayGet.ref = ref = module.local.get(1, array1Type); + assert(theArrayGet.ref === ref); + theArrayGet.index = index = module.i32.const(1); + assert(theArrayGet.index === index); + theArrayGet.signed = signed = true; + assert(theArrayGet.signed === signed); + theArrayGet.type = type = binaryen.i64; + theArrayGet.finalize(); + assert(theArrayGet.type === type); + + console.log(theArrayGet.toText()); + assert( + theArrayGet.toText() + == + "(array.get $array.0\n (local.get $1)\n (i32.const 1)\n)\n" + ); + + module.dispose(); +})(); + +console.log("# ArraySet"); +(function testArraySet() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i64, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var ref = module.local.get(0, array0Type); + var index = module.i32.const(0); + var value = module.local.get(1, binaryen.i32); + const theArraySet = binaryen.ArraySet(module.array.set(ref, index, value)); + assert(theArraySet instanceof binaryen.ArraySet); + assert(theArraySet instanceof binaryen.Expression); + assert(theArraySet.ref === ref); + assert(theArraySet.index === index); + assert(theArraySet.value === value); + assert(theArraySet.type === binaryen.none); + + theArraySet.ref = ref = module.local.get(2, array1Type); + assert(theArraySet.ref === ref); + theArraySet.index = index = module.i32.const(1); + assert(theArraySet.index === index); + theArraySet.value = value = module.local.get(3, binaryen.i64); + assert(theArraySet.value === value); + theArraySet.type = binaryen.i64; + theArraySet.finalize(); + assert(theArraySet.type === binaryen.none); + + console.log(theArraySet.toText()); + assert( + theArraySet.toText() + == + "(array.set $array.0\n (local.get $2)\n (i32.const 1)\n (local.get $3)\n)\n" + ); + + module.dispose(); +})(); + +console.log("# ArrayLen"); +(function testArrayLen() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i64, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var ref = module.local.get(0, array0Type); + const theArrayLen = binaryen.ArrayLen(module.array.len(ref)); + assert(theArrayLen instanceof binaryen.ArrayLen); + assert(theArrayLen instanceof binaryen.Expression); + assert(theArrayLen.ref === ref); + assert(theArrayLen.type === binaryen.i32); + + theArrayLen.ref = ref = module.local.get(1, array1Type); + assert(theArrayLen.ref === ref); + theArrayLen.type = binaryen.i64; + theArrayLen.finalize(); + assert(theArrayLen.type === binaryen.i32); + + console.log(theArrayLen.toText()); + assert( + theArrayLen.toText() + == + "(array.len\n (local.get $1)\n)\n" + ); + + module.dispose(); +})(); + console.log("# Try"); (function testTry() { const module = new binaryen.Module(); diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt index b49beb02f87..35637f7acaa 100644 --- a/test/binaryen.js/expressions.js.txt +++ b/test/binaryen.js/expressions.js.txt @@ -295,6 +295,24 @@ (i32.const 5) ) +# ArrayGet +(array.get $array.0 + (local.get $1) + (i32.const 1) +) + +# ArraySet +(array.set $array.0 + (local.get $2) + (i32.const 1) + (local.get $3) +) + +# ArrayLen +(array.len + (local.get $1) +) + # Try (try (result i32) (do From 0915f8427f2a68e7d4cbba3257b260174e700107 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sat, 12 Apr 2025 18:59:46 +0500 Subject: [PATCH 25/29] Add `ArrayFill` wrapper & tests --- src/binaryen-c.cpp | 49 +++++++++++++++++++++++++++++ src/binaryen-c.h | 19 ++++++++++- src/js/binaryen.js-post.js | 27 +++++++++++++++- test/binaryen.js/expressions.js | 47 +++++++++++++++++++++++++++ test/binaryen.js/expressions.js.txt | 8 +++++ 5 files changed, 148 insertions(+), 2 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 1dd48369dd2..95e5d0eb0a8 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -4477,6 +4477,55 @@ void BinaryenArrayLenSetRef(BinaryenExpressionRef expr, assert(refExpr); static_cast(expression)->ref = (Expression*)refExpr; } +// ArrayFill +BinaryenExpressionRef BinaryenArrayFillGetRef(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->ref; +} +void BinaryenArrayFillSetRef(BinaryenExpressionRef expr, + BinaryenExpressionRef refExpr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + assert(refExpr); + static_cast(expression)->ref = (Expression*)refExpr; +} +BinaryenExpressionRef BinaryenArrayFillGetIndex(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->index; +} +void BinaryenArrayFillSetIndex(BinaryenExpressionRef expr, + BinaryenExpressionRef indexExpr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + assert(indexExpr); + static_cast(expression)->index = (Expression*)indexExpr; +} +BinaryenExpressionRef BinaryenArrayFillGetValue(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->value; +} +void BinaryenArrayFillSetValue(BinaryenExpressionRef expr, + BinaryenExpressionRef valueExpr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + assert(valueExpr); + static_cast(expression)->value = (Expression*)valueExpr; +} +BinaryenExpressionRef BinaryenArrayFillGetSize(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->size; +} +void BinaryenArrayFillSetSize(BinaryenExpressionRef expr, + BinaryenExpressionRef sizeExpr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + assert(sizeExpr); + static_cast(expression)->size = (Expression*)sizeExpr; +} // ArrayCopy BinaryenExpressionRef BinaryenArrayCopyGetDestRef(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 62cb97f48f8..f0a25d51f8e 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -2535,7 +2535,24 @@ BinaryenArrayLenGetRef(BinaryenExpressionRef expr); BINARYEN_API void BinaryenArrayLenSetRef(BinaryenExpressionRef expr, BinaryenExpressionRef refExpr); -// TODO: ArrayFill +// ArrayFill + +BINARYEN_API BinaryenExpressionRef +BinaryenArrayFillGetRef(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayFillSetRef(BinaryenExpressionRef expr, + BinaryenExpressionRef refExpr); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayFillGetIndex(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayFillSetIndex(BinaryenExpressionRef expr, + BinaryenExpressionRef indexExpr); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayFillGetValue(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayFillSetValue(BinaryenExpressionRef expr, + BinaryenExpressionRef valueExpr); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayFillGetSize(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayFillSetSize(BinaryenExpressionRef expr, + BinaryenExpressionRef sizeExpr); // ArrayCopy diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 73ba2356a3d..79e3eaa3162 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -5222,7 +5222,32 @@ Module['ArrayLen'] = makeExpressionWrapper({ } }); -// TODO: ArrayFill +Module['ArrayFill'] = makeExpressionWrapper({ + 'getRef'(expr) { + return Module['_BinaryenArrayFillGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenArrayFillSetRef'](expr, ref); + }, + 'getIndex'(expr) { + return Module['_BinaryenArrayFillGetIndex'](expr); + }, + 'setIndex'(expr, index) { + Module['_BinaryenArrayFillSetIndex'](expr, index); + }, + 'getValue'(expr) { + return Module['_BinaryenArrayFillGetValue'](expr); + }, + 'setValue'(expr, value) { + Module['_BinaryenArrayFillSetValue'](expr, value); + }, + 'getSize'(expr) { + return Module['_BinaryenArrayFillGetSize'](expr); + }, + 'setSize'(expr, size) { + Module['_BinaryenArrayFillSetSize'](expr, size); + } +}); Module['ArrayCopy'] = makeExpressionWrapper({ 'getDestRef'(expr) { diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js index f4319d0877a..463a9f72d8d 100644 --- a/test/binaryen.js/expressions.js +++ b/test/binaryen.js/expressions.js @@ -2084,6 +2084,53 @@ console.log("# ArrayLen"); module.dispose(); })(); +console.log("# ArrayFill"); +(function testArrayFill() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i64, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var ref = module.local.get(0, array0Type); + var index = module.i32.const(0); + var value = module.local.get(1, binaryen.i32); + var size = module.i32.const(1); + const theArrayFill = binaryen.ArrayFill(module.array.fill(ref, index, value, size)); + assert(theArrayFill instanceof binaryen.ArrayFill); + assert(theArrayFill instanceof binaryen.Expression); + assert(theArrayFill.ref === ref); + assert(theArrayFill.index === index); + assert(theArrayFill.value === value); + assert(theArrayFill.size === size); + assert(theArrayFill.type === binaryen.none); + + theArrayFill.ref = ref = module.local.get(2, array1Type); + assert(theArrayFill.ref === ref); + theArrayFill.index = index = module.i32.const(2); + assert(theArrayFill.index === index); + theArrayFill.value = value = module.local.get(3, binaryen.i64); + assert(theArrayFill.value = value); + theArrayFill.size = size = module.i32.const(3); + assert(theArrayFill.size === size); + theArrayFill.type = binaryen.i64; + theArrayFill.finalize(); + assert(theArrayFill.type === binaryen.none); + + console.log(theArrayFill.toText()); + assert( + theArrayFill.toText() + == + "(array.fill $array.0\n (local.get $2)\n (i32.const 2)\n (local.get $3)\n (i32.const 3)\n)\n" + ); + + module.dispose(); +})(); + console.log("# Try"); (function testTry() { const module = new binaryen.Module(); diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt index 35637f7acaa..1137b9a62f9 100644 --- a/test/binaryen.js/expressions.js.txt +++ b/test/binaryen.js/expressions.js.txt @@ -313,6 +313,14 @@ (local.get $1) ) +# ArrayFill +(array.fill $array.0 + (local.get $2) + (i32.const 2) + (local.get $3) + (i32.const 3) +) + # Try (try (result i32) (do From 5b5084e693a7213d57a6ca2db551bd7412a23a05 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sat, 12 Apr 2025 23:57:18 +0500 Subject: [PATCH 26/29] Add `ArrayCopy` wrapper tests --- test/binaryen.js/expressions.js | 51 +++++++++++++++++++++++++++++ test/binaryen.js/expressions.js.txt | 9 +++++ 2 files changed, 60 insertions(+) diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js index 463a9f72d8d..84b651e3b03 100644 --- a/test/binaryen.js/expressions.js +++ b/test/binaryen.js/expressions.js @@ -2131,6 +2131,57 @@ console.log("# ArrayFill"); module.dispose(); })(); +console.log("# ArrayCopy"); +(function testArrayCopy() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i64, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var destRef = module.local.get(0, array0Type); + var destIndex = module.i32.const(0); + var srcRef = module.local.get(1, array0Type); + var srcIndex = module.i32.const(1); + var length = module.i32.const(1); + const theArrayCopy = binaryen.ArrayCopy(module.array.copy(destRef, destIndex, srcRef, srcIndex, length)); + assert(theArrayCopy instanceof binaryen.ArrayCopy); + assert(theArrayCopy instanceof binaryen.Expression); + assert(theArrayCopy.destRef === destRef); + assert(theArrayCopy.destIndex === destIndex); + assert(theArrayCopy.srcRef === srcRef); + assert(theArrayCopy.srcIndex === srcIndex); + assert(theArrayCopy.length === length); + assert(theArrayCopy.type === binaryen.none); + + theArrayCopy.destRef = destRef = module.local.get(2, array1Type); + assert(theArrayCopy.destRef === destRef); + theArrayCopy.destIndex = destIndex = module.i32.const(2); + assert(theArrayCopy.destIndex === destIndex); + theArrayCopy.srcRef = srcRef = module.local.get(3, array1Type); + assert(theArrayCopy.srcRef === srcRef); + theArrayCopy.srcIndex = srcIndex = module.i32.const(3); + assert(theArrayCopy.srcIndex === srcIndex); + theArrayCopy.length = length = module.i32.const(2); + assert(theArrayCopy.length === length); + theArrayCopy.type = binaryen.i64; + theArrayCopy.finalize(); + assert(theArrayCopy.type === binaryen.none); + + console.log(theArrayCopy.toText()); + assert( + theArrayCopy.toText() + == + "(array.copy $array.0 $array.0\n (local.get $2)\n (i32.const 2)\n (local.get $3)\n (i32.const 3)\n (i32.const 2)\n)\n" + ); + + module.dispose(); +})(); + console.log("# Try"); (function testTry() { const module = new binaryen.Module(); diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt index 1137b9a62f9..6dfbcfc987c 100644 --- a/test/binaryen.js/expressions.js.txt +++ b/test/binaryen.js/expressions.js.txt @@ -321,6 +321,15 @@ (i32.const 3) ) +# ArrayCopy +(array.copy $array.0 $array.0 + (local.get $2) + (i32.const 2) + (local.get $3) + (i32.const 3) + (i32.const 2) +) + # Try (try (result i32) (do From 49f8ad75c83d719370f0c4a4761bc60ab46d8bb0 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sun, 13 Apr 2025 00:22:28 +0500 Subject: [PATCH 27/29] Add `ArrayInitData` and `ArrayInitElem` wrappers & tests --- src/binaryen-c.cpp | 116 ++++++++++++++++++++++++++++ src/binaryen-c.h | 46 ++++++++++- src/js/binaryen.js-post.js | 66 +++++++++++++++- test/binaryen.js/expressions.js | 102 ++++++++++++++++++++++++ test/binaryen.js/expressions.js.txt | 16 ++++ 5 files changed, 342 insertions(+), 4 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 95e5d0eb0a8..18378fe8e02 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -4588,6 +4588,122 @@ void BinaryenArrayCopySetLength(BinaryenExpressionRef expr, assert(lengthExpr); static_cast(expression)->length = (Expression*)lengthExpr; } +// ArrayInitData +const char* BinaryenArrayInitDataGetSegment(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->segment.str.data(); +} +void BinaryenArrayInitDataSetSegment(BinaryenExpressionRef expr, + const char* segment) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->segment = Name(segment); +} +BinaryenExpressionRef BinaryenArrayInitDataGetRef(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->ref; +} +void BinaryenArrayInitDataSetRef(BinaryenExpressionRef expr, + BinaryenExpressionRef ref) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->ref = ref; +} +BinaryenExpressionRef +BinaryenArrayInitDataGetIndex(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->index; +} +void BinaryenArrayInitDataSetIndex(BinaryenExpressionRef expr, + BinaryenExpressionRef index) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->index = index; +} +BinaryenExpressionRef +BinaryenArrayInitDataGetOffset(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->offset; +} +void BinaryenArrayInitDataSetOffset(BinaryenExpressionRef expr, + BinaryenExpressionRef offset) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->offset = offset; +} +BinaryenExpressionRef BinaryenArrayInitDataGetSize(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->size; +} +void BinaryenArrayInitDataSetSize(BinaryenExpressionRef expr, + BinaryenExpressionRef size) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->size = size; +} +// ArrayInitElem +const char* BinaryenArrayInitElemGetSegment(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->segment.str.data(); +} +void BinaryenArrayInitElemSetSegment(BinaryenExpressionRef expr, + const char* segment) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->segment = Name(segment); +} +BinaryenExpressionRef BinaryenArrayInitElemGetRef(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->ref; +} +void BinaryenArrayInitElemSetRef(BinaryenExpressionRef expr, + BinaryenExpressionRef ref) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->ref = ref; +} +BinaryenExpressionRef +BinaryenArrayInitElemGetIndex(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->index; +} +void BinaryenArrayInitElemSetIndex(BinaryenExpressionRef expr, + BinaryenExpressionRef index) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->index = index; +} +BinaryenExpressionRef +BinaryenArrayInitElemGetOffset(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->offset; +} +void BinaryenArrayInitElemSetOffset(BinaryenExpressionRef expr, + BinaryenExpressionRef offset) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->offset = offset; +} +BinaryenExpressionRef BinaryenArrayInitElemGetSize(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->size; +} +void BinaryenArrayInitElemSetSize(BinaryenExpressionRef expr, + BinaryenExpressionRef size) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->size = size; +} // StringNew BinaryenOp BinaryenStringNewGetOp(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; diff --git a/src/binaryen-c.h b/src/binaryen-c.h index f0a25d51f8e..67948d8b79c 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -2580,9 +2580,51 @@ BinaryenArrayCopyGetLength(BinaryenExpressionRef expr); BINARYEN_API void BinaryenArrayCopySetLength(BinaryenExpressionRef expr, BinaryenExpressionRef lengthExpr); -// TODO: ArrayInitData +// ArrayInitData -// TODO: ArrayInitElem +BINARYEN_API const char* +BinaryenArrayInitDataGetSegment(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayInitDataSetSegment(BinaryenExpressionRef expr, + const char* segment); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayInitDataGetRef(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayInitDataSetRef(BinaryenExpressionRef expr, + BinaryenExpressionRef ref); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayInitDataGetIndex(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayInitDataSetIndex(BinaryenExpressionRef expr, + BinaryenExpressionRef index); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayInitDataGetOffset(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayInitDataSetOffset(BinaryenExpressionRef expr, + BinaryenExpressionRef offset); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayInitDataGetSize(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayInitDataSetSize(BinaryenExpressionRef expr, + BinaryenExpressionRef size); + +// ArrayInitElem + +BINARYEN_API const char* +BinaryenArrayInitElemGetSegment(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayInitElemSetSegment(BinaryenExpressionRef expr, + const char* segment); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayInitElemGetRef(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayInitElemSetRef(BinaryenExpressionRef expr, + BinaryenExpressionRef ref); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayInitElemGetIndex(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayInitElemSetIndex(BinaryenExpressionRef expr, + BinaryenExpressionRef index); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayInitElemGetOffset(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayInitElemSetOffset(BinaryenExpressionRef expr, + BinaryenExpressionRef offset); +BINARYEN_API BinaryenExpressionRef +BinaryenArrayInitElemGetSize(BinaryenExpressionRef expr); +BINARYEN_API void BinaryenArrayInitElemSetSize(BinaryenExpressionRef expr, + BinaryenExpressionRef size); // StringNew diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 79e3eaa3162..ee5f216e04d 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -5282,9 +5282,71 @@ Module['ArrayCopy'] = makeExpressionWrapper({ } }); -// TODO: ArrayInitData +Module['ArrayInitData'] = makeExpressionWrapper({ + 'getSegment'(expr) { + return UTF8ToString(Module['_BinaryenArrayInitDataGetSegment'](expr)); + }, + 'setSegment'(expr, segment) { + preserveStack(() => Module['_BinaryenArrayInitDataSetSegment'](expr, strToStack(segment))); + }, + 'getRef'(expr) { + return Module['_BinaryenArrayInitDataGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenArrayInitDataSetRef'](expr, ref); + }, + 'getIndex'(expr) { + return Module['_BinaryenArrayInitDataGetIndex'](expr); + }, + 'setIndex'(expr, index) { + Module['_BinaryenArrayInitDataSetIndex'](expr, index); + }, + 'getOffset'(expr) { + return Module['_BinaryenArrayInitDataGetOffset'](expr); + }, + 'setOffset'(expr, offset) { + Module['_BinaryenArrayInitDataSetOffset'](expr, offset); + }, + 'getSize'(expr) { + return Module['_BinaryenArrayInitDataGetSize'](expr); + }, + 'setSize'(expr, size) { + Module['_BinaryenArrayInitDataSetSize'](expr, size); + } +}); -// TODO: ArrayInitElem +Module['ArrayInitElem'] = makeExpressionWrapper({ + 'getSegment'(expr) { + return UTF8ToString(Module['_BinaryenArrayInitElemGetSegment'](expr)); + }, + 'setSegment'(expr, segment) { + preserveStack(() => Module['_BinaryenArrayInitElemSetSegment'](expr, strToStack(segment))); + }, + 'getRef'(expr) { + return Module['_BinaryenArrayInitElemGetRef'](expr); + }, + 'setRef'(expr, ref) { + Module['_BinaryenArrayInitElemSetRef'](expr, ref); + }, + 'getIndex'(expr) { + return Module['_BinaryenArrayInitElemGetIndex'](expr); + }, + 'setIndex'(expr, index) { + Module['_BinaryenArrayInitElemSetIndex'](expr, index); + }, + 'getOffset'(expr) { + return Module['_BinaryenArrayInitElemGetOffset'](expr); + }, + 'setOffset'(expr, offset) { + Module['_BinaryenArrayInitElemSetOffset'](expr, offset); + }, + 'getSize'(expr) { + return Module['_BinaryenArrayInitElemGetSize'](expr); + }, + 'setSize'(expr, size) { + Module['_BinaryenArrayInitElemSetSize'](expr, size); + } +}); Module['Try'] = makeExpressionWrapper({ 'getName'(expr) { diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js index 84b651e3b03..544f2b97806 100644 --- a/test/binaryen.js/expressions.js +++ b/test/binaryen.js/expressions.js @@ -2182,6 +2182,108 @@ console.log("# ArrayCopy"); module.dispose(); })(); +console.log("# ArrayInitData"); +(function testArrayInitData() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i32, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var segment = "0"; + var ref = module.local.get(0, array0Type); + var index = module.i32.const(0); + var offset = module.i32.const(1); + var size = module.i32.const(2); + const theArrayInitData = binaryen.ArrayInitData(module.array.init_data(segment, ref, index, offset, size)); + assert(theArrayInitData instanceof binaryen.ArrayInitData); + assert(theArrayInitData instanceof binaryen.Expression); + assert(theArrayInitData.segment === segment); + assert(theArrayInitData.ref === ref); + assert(theArrayInitData.index === index); + assert(theArrayInitData.offset === offset); + assert(theArrayInitData.size === size); + assert(theArrayInitData.type === binaryen.none); + + theArrayInitData.segment = segment = "1"; + assert(theArrayInitData.segment === segment); + theArrayInitData.ref = ref = module.local.get(1, array1Type); + assert(theArrayInitData.ref === ref); + theArrayInitData.index = index = module.i32.const(3); + assert(theArrayInitData.index === index); + theArrayInitData.offset = offset = module.i32.const(4); + assert(theArrayInitData.offset === offset); + theArrayInitData.size = size = module.i32.const(5); + assert(theArrayInitData.size === size); + theArrayInitData.type = binaryen.i64; + theArrayInitData.finalize(); + assert(theArrayInitData.type === binaryen.none); + + console.log(theArrayInitData.toText()); + assert( + theArrayInitData.toText() + == + "(array.init_data $array.0 $1\n (local.get $1)\n (i32.const 3)\n (i32.const 4)\n (i32.const 5)\n)\n" + ); + + module.dispose(); +})(); + +console.log("# ArrayInitElem"); +(function testArrayInitElem() { + const builder = new binaryen.TypeBuilder(2); + builder.setArrayType(0, binaryen.i32, binaryen.i16, true); + builder.setArrayType(1, binaryen.i32, binaryen.notPacked, true); + var [ + array0Type, + array1Type + ] = builder.buildAndDispose(); + + const module = new binaryen.Module(); + + var segment = "0"; + var ref = module.local.get(0, array0Type); + var index = module.i32.const(0); + var offset = module.i32.const(1); + var size = module.i32.const(2); + const theArrayInitElem = binaryen.ArrayInitElem(module.array.init_elem(segment, ref, index, offset, size)); + assert(theArrayInitElem instanceof binaryen.ArrayInitElem); + assert(theArrayInitElem instanceof binaryen.Expression); + assert(theArrayInitElem.segment === segment); + assert(theArrayInitElem.ref === ref); + assert(theArrayInitElem.index === index); + assert(theArrayInitElem.offset === offset); + assert(theArrayInitElem.size === size); + assert(theArrayInitElem.type === binaryen.none); + + theArrayInitElem.segment = segment = "1"; + assert(theArrayInitElem.segment === segment); + theArrayInitElem.ref = ref = module.local.get(1, array1Type); + assert(theArrayInitElem.ref === ref); + theArrayInitElem.index = index = module.i32.const(3); + assert(theArrayInitElem.index === index); + theArrayInitElem.offset = offset = module.i32.const(4); + assert(theArrayInitElem.offset === offset); + theArrayInitElem.size = size = module.i32.const(5); + assert(theArrayInitElem.size === size); + theArrayInitElem.type = binaryen.i64; + theArrayInitElem.finalize(); + assert(theArrayInitElem.type === binaryen.none); + + console.log(theArrayInitElem.toText()); + assert( + theArrayInitElem.toText() + == + "(array.init_elem $array.0 $1\n (local.get $1)\n (i32.const 3)\n (i32.const 4)\n (i32.const 5)\n)\n" + ); + + module.dispose(); +})(); + console.log("# Try"); (function testTry() { const module = new binaryen.Module(); diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt index 6dfbcfc987c..47d7cf43fb4 100644 --- a/test/binaryen.js/expressions.js.txt +++ b/test/binaryen.js/expressions.js.txt @@ -330,6 +330,22 @@ (i32.const 2) ) +# ArrayInitData +(array.init_data $array.0 $1 + (local.get $1) + (i32.const 3) + (i32.const 4) + (i32.const 5) +) + +# ArrayInitElem +(array.init_elem $array.0 $1 + (local.get $1) + (i32.const 3) + (i32.const 4) + (i32.const 5) +) + # Try (try (result i32) (do From 3353cb237d726eddf34838ed623a942032f15574 Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sun, 13 Apr 2025 12:36:55 +0500 Subject: [PATCH 28/29] Rename `getSigned` to `isSigned` --- src/js/binaryen.js-post.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index ee5f216e04d..e38a1823696 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -5049,7 +5049,7 @@ Module['StructGet'] = makeExpressionWrapper({ 'setRef'(expr, ref) { Module['_BinaryenStructGetSetRef'](expr, ref); }, - 'getSigned'(expr) { + 'isSigned'(expr) { return Boolean(Module['_BinaryenStructGetIsSigned'](expr)); }, 'setSigned'(expr, signed) { @@ -5184,7 +5184,7 @@ Module['ArrayGet'] = makeExpressionWrapper({ 'setIndex'(expr, index) { Module['_BinaryenArrayGetSetIndex'](expr, index); }, - 'getSigned'(expr) { + 'isSigned'(expr) { return Boolean(Module['_BinaryenArrayGetIsSigned'](expr)); }, 'setSigned'(expr, signed) { From 00fe5707ea365b73d60f158edbc388662f49dd5b Mon Sep 17 00:00:00 2001 From: GulgDev Date: Sun, 13 Apr 2025 12:44:05 +0500 Subject: [PATCH 29/29] Add a TODO for GC instructions in `getExpressionInfo` --- src/js/binaryen.js-post.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index e38a1823696..5521cc6cca8 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -3058,7 +3058,7 @@ Module['getExpressionType'] = function(expr) { Module['getExpressionInfo'] = function(expr) { const id = Module['_BinaryenExpressionGetId'](expr); const type = Module['_BinaryenExpressionGetType'](expr); - switch (id) { + switch (id) { // TODO: GC instructions case Module['BlockId']: return { 'id': id,