summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-02-16 11:34:32 -0800
committerGitHub <noreply@github.com>2017-02-16 11:34:32 -0800
commit97077693a6458d51bd5b3dc85187d5a4bd16c3ee (patch)
tree1a35a1fa4a3fb0741826bfd81ecc692a8d3a9eb7
parent08345e231133cd44b956f11a68f72a5c7b5fd1d9 (diff)
downloadbinaryen-97077693a6458d51bd5b3dc85187d5a4bd16c3ee.tar.gz
binaryen-97077693a6458d51bd5b3dc85187d5a4bd16c3ee.tar.bz2
binaryen-97077693a6458d51bd5b3dc85187d5a4bd16c3ee.zip
Optimize precise mode integer ops (#907)
* improve precise integer operations: call into a wasm function to do the possibly-trapping div/rem, which handles the corner cases, instead of an ffi. also fix a bug in the existing parallel 64-bit code for this * remove no longer needed wasm.js-post.js file (it moved into emscripten repo)
-rw-r--r--src/asm2wasm.h115
-rw-r--r--src/js/wasm.js-post.js351
-rw-r--r--test/debugInfo.fromasm12
-rw-r--r--test/debugInfo.fromasm.no-opts14
-rw-r--r--test/emcc_O2_hello_world.fromasm13
-rw-r--r--test/emcc_O2_hello_world.fromasm.no-opts15
-rw-r--r--test/emcc_hello_world.fromasm59
-rw-r--r--test/emcc_hello_world.fromasm.no-opts67
-rw-r--r--test/memorygrowth.fromasm13
-rw-r--r--test/memorygrowth.fromasm.no-opts15
-rw-r--r--test/unit.fromasm12
-rw-r--r--test/unit.fromasm.no-opts14
-rw-r--r--test/wasm-only.fromasm19
-rw-r--r--test/wasm-only.fromasm.no-opts19
14 files changed, 323 insertions, 415 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 32b6af5b0..c25855712 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -613,8 +613,63 @@ private:
return ret;
}
+ Expression* makePotentiallyTrappingI32Binary(BinaryOp op, Expression* left, Expression* right) {
+ if (imprecise) return builder.makeBinary(op, left, right);
+ // we are precise, and the wasm operation might trap if done over 0, so generate a safe call
+ auto *call = allocator.alloc<Call>();
+ switch (op) {
+ case BinaryOp::RemSInt32: call->target = I32S_REM; break;
+ case BinaryOp::RemUInt32: call->target = I32U_REM; break;
+ case BinaryOp::DivSInt32: call->target = I32S_DIV; break;
+ case BinaryOp::DivUInt32: call->target = I32U_DIV; break;
+ default: WASM_UNREACHABLE();
+ }
+ call->operands.push_back(left);
+ call->operands.push_back(right);
+ call->type = i32;
+ static std::set<Name> addedFunctions;
+ if (addedFunctions.count(call->target) == 0) {
+ Expression* result = builder.makeBinary(op,
+ builder.makeGetLocal(0, i32),
+ builder.makeGetLocal(1, i32)
+ );
+ if (op == DivSInt32) {
+ // guard against signed division overflow
+ result = builder.makeIf(
+ builder.makeBinary(AndInt32,
+ builder.makeBinary(EqInt32,
+ builder.makeGetLocal(0, i32),
+ builder.makeConst(Literal(std::numeric_limits<int32_t>::min()))
+ ),
+ builder.makeBinary(EqInt32,
+ builder.makeGetLocal(1, i32),
+ builder.makeConst(Literal(int32_t(-1)))
+ )
+ ),
+ builder.makeConst(Literal(int32_t(0))),
+ result
+ );
+ }
+ addedFunctions.insert(call->target);
+ auto func = new Function;
+ func->name = call->target;
+ func->params.push_back(i32);
+ func->params.push_back(i32);
+ func->result = i32;
+ func->body = builder.makeIf(
+ builder.makeUnary(EqZInt32,
+ builder.makeGetLocal(1, i32)
+ ),
+ builder.makeConst(Literal(int32_t(0))),
+ result
+ );
+ wasm.addFunction(func);
+ }
+ return call;
+ }
+
// Some binary opts might trap, so emit them safely if we are precise
- Expression* makeDangerousI64Binary(BinaryOp op, Expression* left, Expression* right) {
+ Expression* makePotentiallyTrappingI64Binary(BinaryOp op, Expression* left, Expression* right) {
if (imprecise) return builder.makeBinary(op, left, right);
// we are precise, and the wasm operation might trap if done over 0, so generate a safe call
auto *call = allocator.alloc<Call>();
@@ -630,6 +685,27 @@ private:
call->type = i64;
static std::set<Name> addedFunctions;
if (addedFunctions.count(call->target) == 0) {
+ Expression* result = builder.makeBinary(op,
+ builder.makeGetLocal(0, i64),
+ builder.makeGetLocal(1, i64)
+ );
+ if (op == DivSInt64) {
+ // guard against signed division overflow
+ result = builder.makeIf(
+ builder.makeBinary(AndInt32,
+ builder.makeBinary(EqInt64,
+ builder.makeGetLocal(0, i64),
+ builder.makeConst(Literal(std::numeric_limits<int64_t>::min()))
+ ),
+ builder.makeBinary(EqInt64,
+ builder.makeGetLocal(1, i64),
+ builder.makeConst(Literal(int64_t(-1)))
+ )
+ ),
+ builder.makeConst(Literal(int64_t(0))),
+ result
+ );
+ }
addedFunctions.insert(call->target);
auto func = new Function;
func->name = call->target;
@@ -641,10 +717,7 @@ private:
builder.makeGetLocal(1, i64)
),
builder.makeConst(Literal(int64_t(0))),
- builder.makeBinary(op,
- builder.makeGetLocal(0, i64),
- builder.makeGetLocal(1, i64)
- )
+ result
);
wasm.addFunction(func);
}
@@ -1511,29 +1584,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
} else if (!imprecise && (ret->op == BinaryOp::RemSInt32 || ret->op == BinaryOp::RemUInt32 ||
ret->op == BinaryOp::DivSInt32 || ret->op == BinaryOp::DivUInt32)) {
// we are precise, and the wasm operation might trap if done over 0, so generate a safe call
- CallImport *call = allocator.alloc<CallImport>();
- switch (ret->op) {
- case BinaryOp::RemSInt32: call->target = I32S_REM; break;
- case BinaryOp::RemUInt32: call->target = I32U_REM; break;
- case BinaryOp::DivSInt32: call->target = I32S_DIV; break;
- case BinaryOp::DivUInt32: call->target = I32U_DIV; break;
- default: WASM_UNREACHABLE();
- }
- call->operands.push_back(ret->left);
- call->operands.push_back(ret->right);
- call->type = i32;
- static std::set<Name> addedImport;
- if (addedImport.count(call->target) == 0) {
- addedImport.insert(call->target);
- auto import = new Import;
- import->name = call->target;
- import->module = ASM2WASM;
- import->base = call->target;
- import->functionType = ensureFunctionType("iii", &wasm);
- import->kind = ExternalKind::Function;
- wasm.addImport(import);
- }
- return call;
+ return makePotentiallyTrappingI32Binary(ret->op, ret->left, ret->right);
}
return ret;
} else if (what == SUB) {
@@ -1856,10 +1907,10 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
if (name == I64_ADD) return builder.makeBinary(BinaryOp::AddInt64, left, right);
if (name == I64_SUB) return builder.makeBinary(BinaryOp::SubInt64, left, right);
if (name == I64_MUL) return builder.makeBinary(BinaryOp::MulInt64, left, right);
- if (name == I64_UDIV) return makeDangerousI64Binary(BinaryOp::DivUInt64, left, right);
- if (name == I64_SDIV) return makeDangerousI64Binary(BinaryOp::DivSInt64, left, right);
- if (name == I64_UREM) return makeDangerousI64Binary(BinaryOp::RemUInt64, left, right);
- if (name == I64_SREM) return makeDangerousI64Binary(BinaryOp::RemSInt64, left, right);
+ if (name == I64_UDIV) return makePotentiallyTrappingI64Binary(BinaryOp::DivUInt64, left, right);
+ if (name == I64_SDIV) return makePotentiallyTrappingI64Binary(BinaryOp::DivSInt64, left, right);
+ if (name == I64_UREM) return makePotentiallyTrappingI64Binary(BinaryOp::RemUInt64, left, right);
+ if (name == I64_SREM) return makePotentiallyTrappingI64Binary(BinaryOp::RemSInt64, left, right);
if (name == I64_AND) return builder.makeBinary(BinaryOp::AndInt64, left, right);
if (name == I64_OR) return builder.makeBinary(BinaryOp::OrInt64, left, right);
if (name == I64_XOR) return builder.makeBinary(BinaryOp::XorInt64, left, right);
diff --git a/src/js/wasm.js-post.js b/src/js/wasm.js-post.js
deleted file mode 100644
index e7a10f49a..000000000
--- a/src/js/wasm.js-post.js
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright 2015 WebAssembly Community Group participants
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-function integrateWasmJS(Module) {
- // wasm.js has several methods for creating the compiled code module here:
- // * 'native-wasm' : use native WebAssembly support in the browser
- // * 'interpret-s-expr': load s-expression code from a .wast and interpret
- // * 'interpret-binary': load binary wasm and interpret
- // * 'interpret-asm2wasm': load asm.js code, translate to wasm, and interpret
- // * 'asmjs': no wasm, just load the asm.js code and use that (good for testing)
- // The method can be set at compile time (BINARYEN_METHOD), or runtime by setting Module['wasmJSMethod'].
- // The method can be a comma-separated list, in which case, we will try the
- // options one by one. Some of them can fail gracefully, and then we can try
- // the next.
-
- // inputs
-
- var method = Module['wasmJSMethod'] || {{{ wasmJSMethod }}} || 'native-wasm'; // by default, use native support
- Module['wasmJSMethod'] = method;
-
- var wasmTextFile = Module['wasmTextFile'] || {{{ wasmTextFile }}};
- var wasmBinaryFile = Module['wasmBinaryFile'] || {{{ wasmBinaryFile }}};
- var asmjsCodeFile = Module['asmjsCodeFile'] || {{{ asmjsCodeFile }}};
-
- // utilities
-
- var wasmPageSize = 64*1024;
-
- var asm2wasmImports = { // special asm2wasm imports
- "f64-rem": function(x, y) {
- return x % y;
- },
- "f64-to-int": function(x) {
- return x | 0;
- },
- "i32s-div": function(x, y) {
- return ((x | 0) / (y | 0)) | 0;
- },
- "i32u-div": function(x, y) {
- return ((x >>> 0) / (y >>> 0)) >>> 0;
- },
- "i32s-rem": function(x, y) {
- return ((x | 0) % (y | 0)) | 0;
- },
- "i32u-rem": function(x, y) {
- return ((x >>> 0) % (y >>> 0)) >>> 0;
- },
- "debugger": function() {
- debugger;
- },
- };
-
- var info = {
- 'global': null,
- 'env': null,
- 'asm2wasm': asm2wasmImports,
- 'parent': Module // Module inside wasm-js.cpp refers to wasm-js.cpp; this allows access to the outside program.
- };
-
- var exports = null;
-
- function lookupImport(mod, base) {
- var lookup = info;
- if (mod.indexOf('.') < 0) {
- lookup = (lookup || {})[mod];
- } else {
- var parts = mod.split('.');
- lookup = (lookup || {})[parts[0]];
- lookup = (lookup || {})[parts[1]];
- }
- if (base) {
- lookup = (lookup || {})[base];
- }
- if (lookup === undefined) {
- abort('bad lookupImport to (' + mod + ').' + base);
- }
- return lookup;
- }
-
- function mergeMemory(newBuffer) {
- // The wasm instance creates its memory. But static init code might have written to
- // buffer already, including the mem init file, and we must copy it over in a proper merge.
- // TODO: avoid this copy, by avoiding such static init writes
- // TODO: in shorter term, just copy up to the last static init write
- var oldBuffer = Module['buffer'];
- if (newBuffer.byteLength < oldBuffer.byteLength) {
- Module['printErr']('the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here');
- }
- var oldView = new Int8Array(oldBuffer);
- var newView = new Int8Array(newBuffer);
-
- // If we have a mem init file, do not trample it
- if (!memoryInitializer) {
- oldView.set(newView.subarray(Module['STATIC_BASE'], Module['STATIC_BASE'] + Module['STATIC_BUMP']), Module['STATIC_BASE']);
- }
-
- newView.set(oldView);
- updateGlobalBuffer(newBuffer);
- updateGlobalBufferViews();
- }
-
- var WasmTypes = {
- none: 0,
- i32: 1,
- i64: 2,
- f32: 3,
- f64: 4
- };
-
- function fixImports(imports) {
- if (!{{{ WASM_BACKEND }}}) return imports;
- var ret = {};
- for (var i in imports) {
- var fixed = i;
- if (fixed[0] == '_') fixed = fixed.substr(1);
- ret[fixed] = imports[i];
- }
- return ret;
- }
-
- function getBinary() {
- var binary;
- if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
- binary = Module['wasmBinary'];
- assert(binary, "on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)");
- binary = new Uint8Array(binary);
- } else {
- binary = Module['readBinary'](wasmBinaryFile);
- }
- return binary;
- }
-
- // do-method functions
-
- function doJustAsm(global, env, providedBuffer) {
- // if no Module.asm, or it's the method handler helper (see below), then apply
- // the asmjs
- if (typeof Module['asm'] !== 'function' || Module['asm'] === methodHandler) {
- if (!Module['asmPreload']) {
- // you can load the .asm.js file before this, to avoid this sync xhr and eval
- eval(Module['read'](asmjsCodeFile)); // set Module.asm
- } else {
- Module['asm'] = Module['asmPreload'];
- }
- }
- if (typeof Module['asm'] !== 'function') {
- Module['printErr']('asm evalling did not set the module properly');
- return false;
- }
- return Module['asm'](global, env, providedBuffer);
- }
-
- function doNativeWasm(global, env, providedBuffer) {
- if (typeof WebAssembly !== 'object') {
- Module['printErr']('no native wasm support detected');
- return false;
- }
- // prepare memory import
- if (!(Module['wasmMemory'] instanceof WebAssembly.Memory)) {
- Module['printErr']('no native wasm Memory in use');
- return false;
- }
- env['memory'] = Module['wasmMemory'];
- // Load the wasm module and create an instance of using native support in the JS engine.
- info['global'] = {
- 'NaN': NaN,
- 'Infinity': Infinity
- };
- info['global.Math'] = global.Math;
- info['env'] = env;
- var instance;
- try {
- instance = new WebAssembly.Instance(new WebAssembly.Module(getBinary()), info)
- } catch (e) {
- Module['printErr']('failed to compile wasm module: ' + e);
- if (e.toString().indexOf('imported Memory with incompatible size') >= 0) {
- Module['printErr']('Memory size incompatibility issues may be due to changing TOTAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set TOTAL_MEMORY at runtime to something smaller than it was at compile time).');
- }
- return false;
- }
- exports = instance.exports;
- if (exports.memory) mergeMemory(exports.memory);
-
- Module["usingWasm"] = true;
-
- return exports;
- }
-
- function doWasmPolyfill(global, env, providedBuffer, method) {
- if (typeof WasmJS !== 'function') {
- Module['printErr']('WasmJS not detected - polyfill not bundled?');
- return false;
- }
-
- // Use wasm.js to polyfill and execute code in a wasm interpreter.
- var wasmJS = WasmJS({});
-
- // XXX don't be confused. Module here is in the outside program. wasmJS is the inner wasm-js.cpp.
- wasmJS['outside'] = Module; // Inside wasm-js.cpp, Module['outside'] reaches the outside module.
-
- // Information for the instance of the module.
- wasmJS['info'] = info;
-
- wasmJS['lookupImport'] = lookupImport;
-
- assert(providedBuffer === Module['buffer']); // we should not even need to pass it as a 3rd arg for wasm, but that's the asm.js way.
-
- info.global = global;
- info.env = env;
-
- // polyfill interpreter expects an ArrayBuffer
- assert(providedBuffer === Module['buffer']);
- env['memory'] = providedBuffer;
- assert(env['memory'] instanceof ArrayBuffer);
-
- wasmJS['providedTotalMemory'] = Module['buffer'].byteLength;
-
- // Prepare to generate wasm, using either asm2wasm or s-exprs
- var code;
- if (method === 'interpret-binary') {
- code = getBinary();
- } else {
- code = Module['read'](method == 'interpret-asm2wasm' ? asmjsCodeFile : wasmTextFile);
- }
- var temp;
- if (method == 'interpret-asm2wasm') {
- temp = wasmJS['_malloc'](code.length + 1);
- wasmJS['writeAsciiToMemory'](code, temp);
- wasmJS['_load_asm2wasm'](temp);
- } else if (method === 'interpret-s-expr') {
- temp = wasmJS['_malloc'](code.length + 1);
- wasmJS['writeAsciiToMemory'](code, temp);
- wasmJS['_load_s_expr2wasm'](temp);
- } else if (method === 'interpret-binary') {
- temp = wasmJS['_malloc'](code.length);
- wasmJS['HEAPU8'].set(code, temp);
- wasmJS['_load_binary2wasm'](temp, code.length);
- } else {
- throw 'what? ' + method;
- }
- wasmJS['_free'](temp);
-
- wasmJS['_instantiate'](temp);
-
- if (Module['newBuffer']) {
- mergeMemory(Module['newBuffer']);
- Module['newBuffer'] = null;
- }
-
- exports = wasmJS['asmExports'];
-
- return exports;
- }
-
- // We may have a preloaded value in Module.asm, save it
- Module['asmPreload'] = Module['asm'];
-
- // Memory growth integration code
- Module['reallocBuffer'] = function(size) {
- size = Math.ceil(size / wasmPageSize) * wasmPageSize; // round up to wasm page size
- var old = Module['buffer'];
- var result = exports['__growWasmMemory'](size / wasmPageSize); // tiny wasm method that just does grow_memory
- if (Module["usingWasm"]) {
- if (result !== (-1 | 0)) {
- // success in native wasm memory growth, get the buffer from the memory
- return Module['buffer'] = Module['wasmMemory'].buffer;
- } else {
- return null;
- }
- } else {
- // in interpreter, we replace Module.buffer if we allocate
- return Module['buffer'] !== old ? Module['buffer'] : null; // if it was reallocated, it changed
- }
- };
-
- // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate
- // the wasm module at that time, and it receives imports and provides exports and so forth, the app
- // doesn't need to care that it is wasm or olyfilled wasm or asm.js.
-
- Module['asm'] = function(global, env, providedBuffer) {
- global = fixImports(global);
- env = fixImports(env);
-
- // import table
- if (!env['table']) {
- var TABLE_SIZE = Module['wasmTableSize'];
- if (TABLE_SIZE === undefined) TABLE_SIZE = 1024; // works in binaryen interpreter at least
- var MAX_TABLE_SIZE = Module['wasmMaxTableSize'];
- if (typeof WebAssembly === 'object' && typeof WebAssembly.Table === 'function') {
- if (MAX_TABLE_SIZE !== undefined) {
- env['table'] = new WebAssembly.Table({ initial: TABLE_SIZE, maximum: MAX_TABLE_SIZE, element: 'anyfunc' });
- } else {
- env['table'] = new WebAssembly.Table({ initial: TABLE_SIZE, element: 'anyfunc' });
- }
- } else {
- env['table'] = new Array(TABLE_SIZE); // works in binaryen interpreter at least
- }
- Module['wasmTable'] = env['table'];
- }
-
- if (!env['memoryBase']) {
- env['memoryBase'] = Module['STATIC_BASE']; // tell the memory segments where to place themselves
- }
- if (!env['tableBase']) {
- env['tableBase'] = 0; // table starts at 0 by default, in dynamic linking this will change
- }
-
- // try the methods. each should return the exports if it succeeded
-
- var exports;
- var methods = method.split(',');
-
- for (var i = 0; i < methods.length; i++) {
- var curr = methods[i];
-
- Module['printErr']('trying binaryen method: ' + curr);
-
- if (curr === 'native-wasm') {
- if (exports = doNativeWasm(global, env, providedBuffer)) break;
- } else if (curr === 'asmjs') {
- if (exports = doJustAsm(global, env, providedBuffer)) break;
- } else if (curr === 'interpret-asm2wasm' || curr === 'interpret-s-expr' || curr === 'interpret-binary') {
- if (exports = doWasmPolyfill(global, env, providedBuffer, curr)) break;
- } else {
- throw 'bad method: ' + curr;
- }
- }
-
- if (!exports) throw 'no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods';
-
- Module['printErr']('binaryen method succeeded.');
-
- return exports;
- };
-
- var methodHandler = Module['asm']; // note our method handler, as we may modify Module['asm'] later
-}
-
diff --git a/test/debugInfo.fromasm b/test/debugInfo.fromasm
index f073f66a1..f19f244f5 100644
--- a/test/debugInfo.fromasm
+++ b/test/debugInfo.fromasm
@@ -1,7 +1,5 @@
(module
- (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$vii (func (param i32 i32)))
- (import "asm2wasm" "i32s-rem" (func $i32s-rem (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
@@ -25,6 +23,16 @@
(i32.const 1)
)
)
+ (func $i32s-rem (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (get_local $1)
+ (i32.rem_s
+ (get_local $0)
+ (get_local $1)
+ )
+ (i32.const 0)
+ )
+ )
(func $opts (param $0 i32) (param $1 i32) (result i32)
;; even-opted.cpp:2
(set_local $1
diff --git a/test/debugInfo.fromasm.no-opts b/test/debugInfo.fromasm.no-opts
index 0e450a5ab..af52ca902 100644
--- a/test/debugInfo.fromasm.no-opts
+++ b/test/debugInfo.fromasm.no-opts
@@ -1,7 +1,5 @@
(module
- (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$vii (func (param i32 i32)))
- (import "asm2wasm" "i32s-rem" (func $i32s-rem (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
@@ -45,6 +43,18 @@
)
)
)
+ (func $i32s-rem (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (i32.eqz
+ (get_local $1)
+ )
+ (i32.const 0)
+ (i32.rem_s
+ (get_local $0)
+ (get_local $1)
+ )
+ )
+ )
(func $opts (param $x i32) (param $y i32) (result i32)
;; even-opted.cpp:1
(set_local $x
diff --git a/test/emcc_O2_hello_world.fromasm b/test/emcc_O2_hello_world.fromasm
index 1cc6427ef..40f7d3585 100644
--- a/test/emcc_O2_hello_world.fromasm
+++ b/test/emcc_O2_hello_world.fromasm
@@ -1,9 +1,9 @@
(module
(type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
- (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$v (func))
(type $FUNCSIG$vii (func (param i32 i32)))
(import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32))
@@ -23,7 +23,6 @@
(import "env" "___unlock" (func $___unlock (param i32)))
(import "env" "___syscall140" (func $___syscall140 (param i32 i32) (result i32)))
(import "env" "___syscall146" (func $___syscall146 (param i32 i32) (result i32)))
- (import "asm2wasm" "i32u-div" (func $i32u-div (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 18 18 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
@@ -9450,6 +9449,16 @@
)
)
)
+ (func $i32u-div (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (get_local $1)
+ (i32.div_u
+ (get_local $0)
+ (get_local $1)
+ )
+ (i32.const 0)
+ )
+ )
(func $_fwrite (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32)
(local $4 i32)
(local $5 i32)
diff --git a/test/emcc_O2_hello_world.fromasm.no-opts b/test/emcc_O2_hello_world.fromasm.no-opts
index 80801ea2d..e5c2052a6 100644
--- a/test/emcc_O2_hello_world.fromasm.no-opts
+++ b/test/emcc_O2_hello_world.fromasm.no-opts
@@ -1,9 +1,9 @@
(module
(type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
- (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$v (func))
(type $FUNCSIG$vii (func (param i32 i32)))
(import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32))
@@ -27,7 +27,6 @@
(import "env" "___unlock" (func $___unlock (param i32)))
(import "env" "___syscall140" (func $___syscall140 (param i32 i32) (result i32)))
(import "env" "___syscall146" (func $___syscall146 (param i32 i32) (result i32)))
- (import "asm2wasm" "i32u-div" (func $i32u-div (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 18 18 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
@@ -11347,6 +11346,18 @@
(get_local $i4)
)
)
+ (func $i32u-div (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (i32.eqz
+ (get_local $1)
+ )
+ (i32.const 0)
+ (i32.div_u
+ (get_local $0)
+ (get_local $1)
+ )
+ )
+ )
(func $_fwrite (param $i1 i32) (param $i2 i32) (param $i3 i32) (param $i4 i32) (result i32)
(local $i5 i32)
(local $i6 i32)
diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm
index 7dbe75147..87cf3f385 100644
--- a/test/emcc_hello_world.fromasm
+++ b/test/emcc_hello_world.fromasm
@@ -1,11 +1,11 @@
(module
(type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
(type $FUNCSIG$id (func (param f64) (result i32)))
- (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$v (func))
(type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$vii (func (param i32 i32)))
(import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32))
(import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32))
@@ -29,10 +29,6 @@
(import "env" "_sysconf" (func $_sysconf (param i32) (result i32)))
(import "env" "___syscall146" (func $___syscall146 (param i32 i32) (result i32)))
(import "asm2wasm" "f64-to-int" (func $f64-to-int (param f64) (result i32)))
- (import "asm2wasm" "i32s-div" (func $i32s-div (param i32 i32) (result i32)))
- (import "asm2wasm" "i32s-rem" (func $i32s-rem (param i32 i32) (result i32)))
- (import "asm2wasm" "i32u-rem" (func $i32u-rem (param i32 i32) (result i32)))
- (import "asm2wasm" "i32u-div" (func $i32u-div (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 18 18 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
@@ -2234,6 +2230,59 @@
)
)
)
+ (func $i32s-div (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (get_local $1)
+ (if i32
+ (i32.and
+ (i32.eq
+ (get_local $0)
+ (i32.const -2147483648)
+ )
+ (i32.eq
+ (get_local $1)
+ (i32.const -1)
+ )
+ )
+ (i32.const 0)
+ (i32.div_s
+ (get_local $0)
+ (get_local $1)
+ )
+ )
+ (i32.const 0)
+ )
+ )
+ (func $i32s-rem (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (get_local $1)
+ (i32.rem_s
+ (get_local $0)
+ (get_local $1)
+ )
+ (i32.const 0)
+ )
+ )
+ (func $i32u-rem (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (get_local $1)
+ (i32.rem_u
+ (get_local $0)
+ (get_local $1)
+ )
+ (i32.const 0)
+ )
+ )
+ (func $i32u-div (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (get_local $1)
+ (i32.div_u
+ (get_local $0)
+ (get_local $1)
+ )
+ (i32.const 0)
+ )
+ )
(func $_printf_core (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32)
(local $5 i32)
(local $6 i32)
diff --git a/test/emcc_hello_world.fromasm.no-opts b/test/emcc_hello_world.fromasm.no-opts
index 10cae59e8..1b51d826c 100644
--- a/test/emcc_hello_world.fromasm.no-opts
+++ b/test/emcc_hello_world.fromasm.no-opts
@@ -1,11 +1,11 @@
(module
(type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
(type $FUNCSIG$id (func (param f64) (result i32)))
- (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$v (func))
(type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$vii (func (param i32 i32)))
(import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32))
(import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32))
@@ -33,10 +33,6 @@
(import "env" "_sysconf" (func $_sysconf (param i32) (result i32)))
(import "env" "___syscall146" (func $___syscall146 (param i32 i32) (result i32)))
(import "asm2wasm" "f64-to-int" (func $f64-to-int (param f64) (result i32)))
- (import "asm2wasm" "i32s-div" (func $i32s-div (param i32 i32) (result i32)))
- (import "asm2wasm" "i32s-rem" (func $i32s-rem (param i32 i32) (result i32)))
- (import "asm2wasm" "i32u-rem" (func $i32u-rem (param i32 i32) (result i32)))
- (import "asm2wasm" "i32u-div" (func $i32u-div (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 18 18 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
@@ -4638,6 +4634,67 @@
)
(return)
)
+ (func $i32s-div (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (i32.eqz
+ (get_local $1)
+ )
+ (i32.const 0)
+ (if i32
+ (i32.and
+ (i32.eq
+ (get_local $0)
+ (i32.const -2147483648)
+ )
+ (i32.eq
+ (get_local $1)
+ (i32.const -1)
+ )
+ )
+ (i32.const 0)
+ (i32.div_s
+ (get_local $0)
+ (get_local $1)
+ )
+ )
+ )
+ )
+ (func $i32s-rem (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (i32.eqz
+ (get_local $1)
+ )
+ (i32.const 0)
+ (i32.rem_s
+ (get_local $0)
+ (get_local $1)
+ )
+ )
+ )
+ (func $i32u-rem (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (i32.eqz
+ (get_local $1)
+ )
+ (i32.const 0)
+ (i32.rem_u
+ (get_local $0)
+ (get_local $1)
+ )
+ )
+ )
+ (func $i32u-div (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (i32.eqz
+ (get_local $1)
+ )
+ (i32.const 0)
+ (i32.div_u
+ (get_local $0)
+ (get_local $1)
+ )
+ )
+ )
(func $_printf_core (param $$f i32) (param $$fmt i32) (param $$ap i32) (param $$nl_arg i32) (param $$nl_type i32) (result i32)
(local $$$ i32)
(local $$$$i i32)
diff --git a/test/memorygrowth.fromasm b/test/memorygrowth.fromasm
index e33525578..b06a13f64 100644
--- a/test/memorygrowth.fromasm
+++ b/test/memorygrowth.fromasm
@@ -1,10 +1,10 @@
(module
(type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
- (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$v (func))
(type $FUNCSIG$vii (func (param i32 i32)))
+ (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(import "env" "STACKTOP" (global $r$asm2wasm$import i32))
(import "env" "STACK_MAX" (global $s$asm2wasm$import i32))
(import "env" "abort" (func $ja (param i32)))
@@ -19,7 +19,6 @@
(import "env" "___syscall54" (func $wa (param i32 i32) (result i32)))
(import "env" "___unlock" (func $xa (param i32)))
(import "env" "___syscall146" (func $ya (param i32 i32) (result i32)))
- (import "asm2wasm" "i32u-div" (func $i32u-div (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256))
(import "env" "table" (table 8 8 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
@@ -9442,6 +9441,16 @@
)
)
)
+ (func $i32u-div (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (get_local $1)
+ (i32.div_u
+ (get_local $0)
+ (get_local $1)
+ )
+ (i32.const 0)
+ )
+ )
(func $bb (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32)
(local $4 i32)
(local $5 i32)
diff --git a/test/memorygrowth.fromasm.no-opts b/test/memorygrowth.fromasm.no-opts
index a27f419ae..c9569d0bd 100644
--- a/test/memorygrowth.fromasm.no-opts
+++ b/test/memorygrowth.fromasm.no-opts
@@ -1,10 +1,10 @@
(module
(type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
- (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$v (func))
(type $FUNCSIG$vii (func (param i32 i32)))
+ (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(import "env" "STACKTOP" (global $r$asm2wasm$import i32))
(import "env" "STACK_MAX" (global $s$asm2wasm$import i32))
(import "env" "tempDoublePtr" (global $t$asm2wasm$import i32))
@@ -23,7 +23,6 @@
(import "env" "___syscall54" (func $wa (param i32 i32) (result i32)))
(import "env" "___unlock" (func $xa (param i32)))
(import "env" "___syscall146" (func $ya (param i32 i32) (result i32)))
- (import "asm2wasm" "i32u-div" (func $i32u-div (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256))
(import "env" "table" (table 8 8 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
@@ -11306,6 +11305,18 @@
(get_local $d)
)
)
+ (func $i32u-div (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (i32.eqz
+ (get_local $1)
+ )
+ (i32.const 0)
+ (i32.div_u
+ (get_local $0)
+ (get_local $1)
+ )
+ )
+ )
(func $bb (param $a i32) (param $b i32) (param $c i32) (param $d i32) (result i32)
(local $e i32)
(local $f i32)
diff --git a/test/unit.fromasm b/test/unit.fromasm
index 4f7b2c6a9..bbce09412 100644
--- a/test/unit.fromasm
+++ b/test/unit.fromasm
@@ -1,7 +1,6 @@
(module
(type $FUNCSIG$id (func (param f64) (result i32)))
(type $FUNCSIG$ddd (func (param f64 f64) (result f64)))
- (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$vf (func (param f32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$v (func))
@@ -17,7 +16,6 @@
(import "env" "return_int" (func $return_int (result i32)))
(import "asm2wasm" "f64-to-int" (func $f64-to-int (param f64) (result i32)))
(import "asm2wasm" "f64-rem" (func $f64-rem (param f64 f64) (result f64)))
- (import "asm2wasm" "i32u-div" (func $i32u-div (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 24 24 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
@@ -252,6 +250,16 @@
(f64.const 1.2)
)
)
+ (func $i32u-div (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (get_local $1)
+ (i32.div_u
+ (get_local $0)
+ (get_local $1)
+ )
+ (i32.const 0)
+ )
+ )
(func $big_uint_div_u (result i32)
(call $i32u-div
(i32.const -1)
diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts
index 29fede80c..d18dfd77e 100644
--- a/test/unit.fromasm.no-opts
+++ b/test/unit.fromasm.no-opts
@@ -1,7 +1,6 @@
(module
(type $FUNCSIG$id (func (param f64) (result i32)))
(type $FUNCSIG$ddd (func (param f64 f64) (result f64)))
- (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$vf (func (param f32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$v (func))
@@ -21,7 +20,6 @@
(import "env" "return_int" (func $return_int (result i32)))
(import "asm2wasm" "f64-to-int" (func $f64-to-int (param f64) (result i32)))
(import "asm2wasm" "f64-rem" (func $f64-rem (param f64 f64) (result f64)))
- (import "asm2wasm" "i32u-div" (func $i32u-div (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 24 24 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
@@ -379,6 +377,18 @@
)
)
)
+ (func $i32u-div (param $0 i32) (param $1 i32) (result i32)
+ (if i32
+ (i32.eqz
+ (get_local $1)
+ )
+ (i32.const 0)
+ (i32.div_u
+ (get_local $0)
+ (get_local $1)
+ )
+ )
+ )
(func $big_uint_div_u (result i32)
(local $x i32)
(set_local $x
diff --git a/test/wasm-only.fromasm b/test/wasm-only.fromasm
index 1a50a4385..dbb67e746 100644
--- a/test/wasm-only.fromasm
+++ b/test/wasm-only.fromasm
@@ -148,9 +148,22 @@
(get_local $1)
)
(i64.const 0)
- (i64.div_s
- (get_local $0)
- (get_local $1)
+ (if i64
+ (i32.and
+ (i64.eq
+ (get_local $0)
+ (i64.const -9223372036854775808)
+ )
+ (i64.eq
+ (get_local $1)
+ (i64.const -1)
+ )
+ )
+ (i64.const 0)
+ (i64.div_s
+ (get_local $0)
+ (get_local $1)
+ )
)
)
)
diff --git a/test/wasm-only.fromasm.no-opts b/test/wasm-only.fromasm.no-opts
index eae9c4597..ae1fa211b 100644
--- a/test/wasm-only.fromasm.no-opts
+++ b/test/wasm-only.fromasm.no-opts
@@ -296,9 +296,22 @@
(get_local $1)
)
(i64.const 0)
- (i64.div_s
- (get_local $0)
- (get_local $1)
+ (if i64
+ (i32.and
+ (i64.eq
+ (get_local $0)
+ (i64.const -9223372036854775808)
+ )
+ (i64.eq
+ (get_local $1)
+ (i64.const -1)
+ )
+ )
+ (i64.const 0)
+ (i64.div_s
+ (get_local $0)
+ (get_local $1)
+ )
)
)
)