diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/asm2wasm-main.cpp | 8 | ||||
-rw-r--r-- | src/asm2wasm.h | 67 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 4 |
3 files changed, 44 insertions, 35 deletions
diff --git a/src/asm2wasm-main.cpp b/src/asm2wasm-main.cpp index 73f6853d8..cbcb3b547 100644 --- a/src/asm2wasm-main.cpp +++ b/src/asm2wasm-main.cpp @@ -29,6 +29,8 @@ using namespace cashew; using namespace wasm; int main(int argc, const char *argv[]) { + bool imprecise = false; + Options options("asm2wasm", "Translate asm.js files to .wast files"); options .add("--output", "-o", "Output file (stdout if not specified)", @@ -45,6 +47,10 @@ int main(int argc, const char *argv[]) { [](Options *o, const std::string &argument) { o->extra["total memory"] = argument; }) + .add("--imprecise", "-i", "Imprecise optimizations", Options::Arguments::Zero, + [&imprecise](Options *o, const std::string &) { + imprecise = true; + }) .add_positional("INFILE", Options::Arguments::One, [](Options *o, const std::string &argument) { o->extra["infile"] = argument; @@ -81,7 +87,7 @@ int main(int argc, const char *argv[]) { if (options.debug) std::cerr << "wasming..." << std::endl; AllocatingModule wasm; wasm.memory.initial = wasm.memory.max = totalMemory / Memory::kPageSize; - Asm2WasmBuilder asm2wasm(wasm, pre.memoryGrowth, options.debug); + Asm2WasmBuilder asm2wasm(wasm, pre.memoryGrowth, options.debug, imprecise); asm2wasm.processAsm(asmjs); if (options.debug) std::cerr << "optimizing..." << std::endl; diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 2d024665e..bf59d08ad 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -151,6 +151,7 @@ class Asm2WasmBuilder { bool memoryGrowth; bool debug; + bool imprecise; public: std::map<IString, MappedGlobal> mappedGlobals; @@ -254,13 +255,14 @@ private: } public: - Asm2WasmBuilder(AllocatingModule& wasm, bool memoryGrowth, bool debug) + Asm2WasmBuilder(AllocatingModule& wasm, bool memoryGrowth, bool debug, bool imprecise) : wasm(wasm), allocator(wasm.allocator), nextGlobal(8), maxGlobal(1000), memoryGrowth(memoryGrowth), - debug(debug) {} + debug(debug), + imprecise(imprecise) {} void processAsm(Ref ast); void optimize(); @@ -1009,37 +1011,38 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { } else if (ast[1] == B_NOT) { // ~, might be ~~ as a coercion or just a not if (ast[2][0] == UNARY_PREFIX && ast[2][1] == B_NOT) { -#if 0 - auto ret = allocator.alloc<Unary>(); - ret->op = TruncSFloat64; // equivalent to U, except for error handling, which asm.js doesn't have anyhow - ret->value = process(ast[2][2]); - ret->type = WasmType::i32; - return ret; -#endif - // WebAssembly traps on float-to-int overflows, but asm.js wouldn't, so we must emulate that - CallImport *ret = allocator.alloc<CallImport>(); - ret->target = F64_TO_INT; - auto input = process(ast[2][2]); - if (input->type == f32) { - auto conv = allocator.alloc<Unary>(); - conv->op = PromoteFloat32; - conv->value = input; - conv->type = WasmType::f64; - input = conv; - } - ret->operands.push_back(input); - ret->type = i32; - static bool addedImport = false; - if (!addedImport) { - addedImport = true; - auto import = allocator.alloc<Import>(); // f64-to-int = asm2wasm.f64-to-int; - import->name = F64_TO_INT; - import->module = ASM2WASM; - import->base = F64_TO_INT; - import->type = ensureFunctionType("id", &wasm, allocator); - wasm.addImport(import); + if (imprecise) { + auto ret = allocator.alloc<Unary>(); + ret->value = process(ast[2][2]); + ret->op = ret->value->type == f64 ? TruncSFloat64 : TruncSFloat32; // imprecise, because this wasm thing might trap, while asm.js never would + ret->type = WasmType::i32; + return ret; + } else { + // WebAssembly traps on float-to-int overflows, but asm.js wouldn't, so we must emulate that + CallImport *ret = allocator.alloc<CallImport>(); + ret->target = F64_TO_INT; + auto input = process(ast[2][2]); + if (input->type == f32) { + auto conv = allocator.alloc<Unary>(); + conv->op = PromoteFloat32; + conv->value = input; + conv->type = WasmType::f64; + input = conv; + } + ret->operands.push_back(input); + ret->type = i32; + static bool addedImport = false; + if (!addedImport) { + addedImport = true; + auto import = allocator.alloc<Import>(); // f64-to-int = asm2wasm.f64-to-int; + import->name = F64_TO_INT; + import->module = ASM2WASM; + import->base = F64_TO_INT; + import->type = ensureFunctionType("id", &wasm, allocator); + wasm.addImport(import); + } + return ret; } - return ret; } // no bitwise unary not, so do xor with -1 auto ret = allocator.alloc<Binary>(); diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index eca91fc82..e9ced6b6f 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -631,7 +631,7 @@ private: return Literal(int32_t(val)); } else { int64_t converted = val; - if ((val >= 1 && converted <= 0) || val < (double)LLONG_MIN) trap("i32.truncSFloat overflow"); + if ((val >= 1 && converted <= 0) || val < (double)LLONG_MIN) trap("i64.truncSFloat overflow"); return Literal(converted); } } @@ -640,7 +640,7 @@ private: double val = value.getFloat(); if (isnan(val)) trap("truncUFloat of nan"); if (curr->type == i32) { - if (val > (double)std::numeric_limits<uint32_t>::max() || val <= (double)-1) trap("i64.truncUFloat overflow"); + if (val > (double)std::numeric_limits<uint32_t>::max() || val <= (double)-1) trap("i32.truncUFloat overflow"); return Literal(uint32_t(val)); } else { uint64_t converted = val; |