diff options
author | Daniel Wirtz <dcode@dcode.io> | 2019-03-13 16:58:45 +0100 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2019-03-13 08:58:45 -0700 |
commit | 65446aeade5b5a1acab6ae2a605ae1702251fda2 (patch) | |
tree | 5f6fe5423bfa98248f2d64b21ea9b142ce2bd45c | |
parent | f0ec4b02fb797387040c65d63f690b3856b1183e (diff) | |
download | binaryen-65446aeade5b5a1acab6ae2a605ae1702251fda2.tar.gz binaryen-65446aeade5b5a1acab6ae2a605ae1702251fda2.tar.bz2 binaryen-65446aeade5b5a1acab6ae2a605ae1702251fda2.zip |
Add BinaryenConstGetValueV128 to C/JS-API (#1931)
This PR adds
void BinaryenConstGetValueV128(BinaryenExpressionRef expr, uint8_t* out);
to the C-API and uses it in Binaryen.getExpressionInfo in the JS-API.
-rwxr-xr-x | build-js.sh | 1 | ||||
-rw-r--r-- | src/binaryen-c.cpp | 17 | ||||
-rw-r--r-- | src/binaryen-c.h | 1 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 95 | ||||
-rw-r--r-- | test/binaryen.js/simd.js | 5 | ||||
-rw-r--r-- | test/binaryen.js/simd.js.txt | 1 |
6 files changed, 87 insertions, 33 deletions
diff --git a/build-js.sh b/build-js.sh index 06141dea2..896d1736d 100755 --- a/build-js.sh +++ b/build-js.sh @@ -635,6 +635,7 @@ export_function "_BinaryenConstGetValueI64Low" export_function "_BinaryenConstGetValueI64High" export_function "_BinaryenConstGetValueF32" export_function "_BinaryenConstGetValueF64" +export_function "_BinaryenConstGetValueV128" # 'Unary' expression operations export_function "_BinaryenUnaryGetOp" diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index c554b0a23..71cd92da4 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -1616,6 +1616,15 @@ double BinaryenConstGetValueF64(BinaryenExpressionRef expr) { assert(expression->is<Const>()); return static_cast<Const*>(expression)->value.getf64(); } +void BinaryenConstGetValueV128(BinaryenExpressionRef expr, uint8_t* out) { + if (tracing) { + std::cout << " BinaryenConstGetValueV128(expressions[" << expressions[expr] << "], " << out << ");\n"; + } + + auto* expression = (Expression*)expr; + assert(expression->is<Const>()); + memcpy(out, static_cast<Const*>(expression)->value.getv128().data(), 16); +} // Unary BinaryenOp BinaryenUnaryGetOp(BinaryenExpressionRef expr) { if (tracing) { @@ -1945,7 +1954,7 @@ BinaryenExpressionRef BinaryenSIMDShuffleGetRight(BinaryenExpressionRef expr) { } void BinaryenSIMDShuffleGetMask(BinaryenExpressionRef expr, uint8_t *mask) { if (tracing) { - std::cout << " BinaryenSIMDShuffleGetMask(expressions[" << expressions[expr] << "]);\n"; + std::cout << " BinaryenSIMDShuffleGetMask(expressions[" << expressions[expr] << "], " << mask << ");\n"; } auto* expression = (Expression*)expr; @@ -3067,6 +3076,12 @@ size_t BinaryenSizeofLiteral(void) { return sizeof(Literal); } +// Returns the size of an allocate and write result object. +EMSCRIPTEN_KEEPALIVE +size_t BinaryenSizeofAllocateAndWriteResult(void) { + return sizeof(BinaryenModuleAllocateAndWriteResult); +} + #endif } // extern "C" diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 5355ceeeb..787bfb242 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -618,6 +618,7 @@ int32_t BinaryenConstGetValueI64Low(BinaryenExpressionRef expr); int32_t BinaryenConstGetValueI64High(BinaryenExpressionRef expr); float BinaryenConstGetValueF32(BinaryenExpressionRef expr); double BinaryenConstGetValueF64(BinaryenExpressionRef expr); +void BinaryenConstGetValueV128(BinaryenExpressionRef expr, uint8_t* out); BinaryenOp BinaryenUnaryGetOp(BinaryenExpressionRef expr); BinaryenExpressionRef BinaryenUnaryGetValue(BinaryenExpressionRef expr); diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 1eef5757e..aee41255c 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -365,6 +365,13 @@ Module['ConvertUVecI32x4ToVecF32x4'] = Module['_BinaryenConvertUVecI32x4ToVecF32 Module['ConvertSVecI64x2ToVecF64x2'] = Module['_BinaryenConvertSVecI64x2ToVecF64x2'](); Module['ConvertUVecI64x2ToVecF64x2'] = Module['_BinaryenConvertUVecI64x2ToVecF64x2'](); +// The size of a single literal in memory as used in Const creation, +// which is a little different: we don't want users to need to make +// their own Literals, as the C API handles them by value, which means +// we would leak them. Instead, Const creation is fused together with +// an intermediate stack allocation of this size to pass the value. +var sizeOfLiteral = _BinaryenSizeofLiteral(); + // 'Module' interface Module['Module'] = function(module) { assert(!module); // guard against incorrect old API usage @@ -482,13 +489,6 @@ function wrapModule(module, self) { } } - // The Const creation API is a little different: we don't want users to - // need to make their own Literals, as the C API handles them by value, - // which means we would leak them. Instead, this is the only API that - // accepts Literals, so fuse it with Literal creation - var temp = _malloc(Module['_BinaryenSizeofLiteral']()); // a single literal in memory. the LLVM C ABI - // makes us pass pointers to this. - self['i32'] = { 'load': function(offset, align, ptr) { return Module['_BinaryenLoad'](module, 4, true, offset, align, Module['i32'], ptr); @@ -515,8 +515,11 @@ function wrapModule(module, self) { return Module['_BinaryenStore'](module, 2, offset, align, ptr, value, Module['i32']); }, 'const': function(x) { - Module['_BinaryenLiteralInt32'](temp, x); - return Module['_BinaryenConst'](module, temp); + return preserveStack(function() { + var tempLiteral = stackAlloc(sizeOfLiteral); + Module['_BinaryenLiteralInt32'](tempLiteral, x); + return Module['_BinaryenConst'](module, tempLiteral); + }); }, 'clz': function(value) { return Module['_BinaryenUnary'](module, Module['ClzInt32'], value); @@ -778,8 +781,11 @@ function wrapModule(module, self) { return Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['i64']); }, 'const': function(x, y) { - Module['_BinaryenLiteralInt64'](temp, x, y); - return Module['_BinaryenConst'](module, temp); + return preserveStack(function() { + var tempLiteral = stackAlloc(sizeOfLiteral); + Module['_BinaryenLiteralInt64'](tempLiteral, x, y); + return Module['_BinaryenConst'](module, tempLiteral); + }); }, 'clz': function(value) { return Module['_BinaryenUnary'](module, Module['ClzInt64'], value); @@ -1049,12 +1055,18 @@ function wrapModule(module, self) { return Module['_BinaryenStore'](module, 4, offset, align, ptr, value, Module['f32']); }, 'const': function(x) { - Module['_BinaryenLiteralFloat32'](temp, x); - return Module['_BinaryenConst'](module, temp); + return preserveStack(function() { + var tempLiteral = stackAlloc(sizeOfLiteral); + Module['_BinaryenLiteralFloat32'](tempLiteral, x); + return Module['_BinaryenConst'](module, tempLiteral); + }); }, 'const_bits': function(x) { - Module['_BinaryenLiteralFloat32Bits'](temp, x); - return Module['_BinaryenConst'](module, temp); + return preserveStack(function() { + var tempLiteral = stackAlloc(sizeOfLiteral); + Module['_BinaryenLiteralFloat32Bits'](tempLiteral, x); + return Module['_BinaryenConst'](module, tempLiteral); + }); }, 'neg': function(value) { return Module['_BinaryenUnary'](module, Module['NegFloat32'], value); @@ -1148,12 +1160,18 @@ function wrapModule(module, self) { return Module['_BinaryenStore'](module, 8, offset, align, ptr, value, Module['f64']); }, 'const': function(x) { - Module['_BinaryenLiteralFloat64'](temp, x); - return Module['_BinaryenConst'](module, temp); + return preserveStack(function() { + var tempLiteral = stackAlloc(sizeOfLiteral); + Module['_BinaryenLiteralFloat64'](tempLiteral, x); + return Module['_BinaryenConst'](module, tempLiteral); + }); }, 'const_bits': function(x, y) { - Module['_BinaryenLiteralFloat64Bits'](temp, x, y); - return Module['_BinaryenConst'](module, temp); + return preserveStack(function() { + var tempLiteral = stackAlloc(sizeOfLiteral); + Module['_BinaryenLiteralFloat64Bits'](tempLiteral, x, y); + return Module['_BinaryenConst'](module, tempLiteral); + }); }, 'neg': function(value) { return Module['_BinaryenUnary'](module, Module['NegFloat64'], value); @@ -1248,8 +1266,9 @@ function wrapModule(module, self) { }, 'const': function(i8s) { return preserveStack(function() { - Module['_BinaryenLiteralVec128'](temp, i8sToStack(i8s)); - return Module['_BinaryenConst'](module, temp); + var tempLiteral = stackAlloc(sizeOfLiteral); + Module['_BinaryenLiteralVec128'](tempLiteral, i8sToStack(i8s)); + return Module['_BinaryenConst'](module, tempLiteral); }); }, 'not': function(value) { @@ -1729,7 +1748,7 @@ function wrapModule(module, self) { }); }; self['removeFunctionType'] = function(name) { - return preserveStack(function () { + return preserveStack(function() { return Module['_BinaryenRemoveFunctionType'](module, strToStack(name)); }); }; @@ -1754,7 +1773,7 @@ function wrapModule(module, self) { }); } self['removeGlobal'] = function(name) { - return preserveStack(function () { + return preserveStack(function() { return Module['_BinaryenRemoveGlobal'](module, strToStack(name)); }); } @@ -1900,10 +1919,11 @@ function wrapModule(module, self) { }; self['emitBinary'] = function(sourceMapUrl) { return preserveStack(function() { - Module['_BinaryenModuleAllocateAndWrite'](temp, module, strToStack(sourceMapUrl)); - var binaryPtr = HEAPU32[ temp >>> 2 ]; - var binaryBytes = HEAPU32[(temp >>> 2) + 1]; - var sourceMapPtr = HEAPU32[(temp >>> 2) + 2]; + var tempBuffer = stackAlloc(_BinaryenSizeofAllocateAndWriteResult()); + Module['_BinaryenModuleAllocateAndWrite'](tempBuffer, module, strToStack(sourceMapUrl)); + var binaryPtr = HEAPU32[ tempBuffer >>> 2 ]; + var binaryBytes = HEAPU32[(tempBuffer >>> 2) + 1]; + var sourceMapPtr = HEAPU32[(tempBuffer >>> 2) + 2]; try { var buffer = new Uint8Array(binaryBytes); buffer.set(HEAPU8.subarray(binaryPtr, binaryPtr + binaryBytes)); @@ -2090,7 +2110,18 @@ Module['getExpressionInfo'] = function(expr) { case Module['i32']: value = Module['_BinaryenConstGetValueI32'](expr); break; case Module['i64']: value = { 'low': Module['_BinaryenConstGetValueI64Low'](expr), 'high': Module['_BinaryenConstGetValueI64High'](expr) }; break; case Module['f32']: value = Module['_BinaryenConstGetValueF32'](expr); break; - case Module['f64']: value = Module['_BinaryenConstGetValueF64'](expr); break; + case Module['f64']: value = Module['_BinaryenConstGetValueF64'](expr); break; + case Module['v128']: { + preserveStack(function() { + var tempBuffer = stackAlloc(16); + Module['_BinaryenConstGetValueV128'](expr, tempBuffer); + value = new Array(16); + for (var i = 0 ; i < 16; i++) { + value[i] = HEAPU8[tempBuffer + i]; + } + }); + break; + } default: throw Error('unexpected type: ' + type); } return { @@ -2203,11 +2234,11 @@ Module['getExpressionInfo'] = function(expr) { }; case Module['SIMDShuffleId']: return preserveStack(function() { - var ret = stackAlloc(16); - Module['_BinaryenSIMDShuffleGetMask'](expr, ret); - var mask = []; + var tempBuffer = stackAlloc(16); + Module['_BinaryenSIMDShuffleGetMask'](expr, tempBuffer); + var mask = new Array(16); for (var i = 0 ; i < 16; i++) { - mask[i] = HEAP8[ret + i]; + mask[i] = HEAPU8[tempBuffer + i]; } return { 'id': id, diff --git a/test/binaryen.js/simd.js b/test/binaryen.js/simd.js new file mode 100644 index 000000000..a6055a267 --- /dev/null +++ b/test/binaryen.js/simd.js @@ -0,0 +1,5 @@ +var module = new Binaryen.Module(); + +var expr = module.v128.const([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); +var info = Binaryen.getExpressionInfo(expr); +console.log("v128.const i8x16 0x" + info.value.map(b => b.toString(16)).join(" 0x")); diff --git a/test/binaryen.js/simd.js.txt b/test/binaryen.js/simd.js.txt new file mode 100644 index 000000000..d4facdde5 --- /dev/null +++ b/test/binaryen.js/simd.js.txt @@ -0,0 +1 @@ +v128.const i8x16 0x1 0x0 0x0 0x0 0x2 0x0 0x0 0x0 0x3 0x0 0x0 0x0 0x4 0x0 0x0 0x0 |