From bf110a08e4e717961d811170a49a72212fbf0b96 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 13:46:27 -0700 Subject: support not exporting memory in binaries --- src/wasm-binary.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 8fed9f6d9..ed9b733d0 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -518,7 +518,7 @@ public: auto start = startSection(BinaryConsts::Section::Memory); o << U32LEB(wasm->memory.initial) << U32LEB(wasm->memory.max) - << int8_t(1); // export memory + << int8_t(wasm->memory.exportName.is()); // export memory finishSection(start); } @@ -1343,7 +1343,10 @@ public: if (debug) std::cerr << "== readMemory" << std::endl; wasm.memory.initial = getU32LEB(); wasm.memory.max = getU32LEB(); - verifyInt8(1); // export memory + auto exportMemory = getInt8(); + if (exportMemory) { + wasm.memory.exportName = Name("memory"); + } } void readSignatures() { -- cgit v1.2.3 From d0aa7bd92d4ccd0148c082fb4df5c0d21aba88ba Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 14:54:28 -0700 Subject: function ending fixes --- src/wasm-binary.h | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index ed9b733d0..1cb2046e3 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -230,7 +230,6 @@ namespace Section { auto DataSegments = "data"; auto FunctionTable = "table"; auto Names = "name"; - auto End = "end"; auto Start = "start"; }; @@ -476,7 +475,6 @@ public: writeDataSegments(); writeFunctionTable(); writeNames(); - writeEnd(); finishUp(); } @@ -644,7 +642,6 @@ public: if (numLocalsByType[f64]) o << U32LEB(numLocalsByType[f64]) << binaryWasmType(f64); depth = 0; recurse(function->body); - o << int8_t(BinaryConsts::End); assert(depth == 0); size_t size = o.size() - start; assert(size <= std::numeric_limits::max()); @@ -732,11 +729,6 @@ public: finishSection(start); } - void writeEnd() { - auto start = startSection(BinaryConsts::Section::End); - finishSection(start); - } - // helpers void writeInlineString(const char* name) { @@ -862,13 +854,13 @@ public: } o << U32LEB(getBreakIndex(curr->default_)); recurse(curr->condition); - o << int8_t(BinaryConsts::End); + o << int8_t(BinaryConsts::End); // XXX if (curr->value) { recurse(curr->value); } else { visitNop(nullptr); } - o << int8_t(BinaryConsts::End); + o << int8_t(BinaryConsts::End); // XXX } void visitCall(Call *curr) { if (debug) std::cerr << "zz node: Call" << std::endl; @@ -1178,10 +1170,10 @@ public: else if (match(BinaryConsts::Section::DataSegments)) readDataSegments(); else if (match(BinaryConsts::Section::FunctionTable)) readFunctionTable(); else if (match(BinaryConsts::Section::Names)) readNames(); - else if (match(BinaryConsts::Section::End)) { - if (debug) std::cerr << "== readEnd" << std::endl; - break; - } else { + else { + std::cerr << "unfamiliar section: "; + for (size_t i = 0; i < nameSize; i++) std::cerr << input[pos + i]; + std::cerr << std::endl; abort(); } assert(pos == before + sectionSize); @@ -1417,6 +1409,7 @@ public: std::vector functions; // we store functions here before wasm.addFunction after we know their names std::map> functionCalls; // at index i we have all calls to i Function* currFunction = nullptr; + size_t endOfFunction; void readFunctions() { if (debug) std::cerr << "== readFunctions" << std::endl; @@ -1424,7 +1417,8 @@ public: for (size_t i = 0; i < total; i++) { if (debug) std::cerr << "read one at " << pos << std::endl; size_t size = getU32LEB(); - assert(size > 0); // we could also check it matches the seen size + assert(size > 0); + endOfFunction = pos + size; auto type = functionTypes[i]; if (debug) std::cerr << "reading" << i << std::endl; size_t nextVar = 0; @@ -1467,6 +1461,7 @@ public: assert(depth == 0); assert(breakStack.empty()); assert(expressionStack.empty()); + assert(pos == endOfFunction); } currFunction = nullptr; functions.push_back(func); @@ -1493,7 +1488,7 @@ public: std::vector expressionStack; - BinaryConsts::ASTNodes processExpressions() { // until an end or else marker + BinaryConsts::ASTNodes processExpressions() { // until an end or else marker, or the end of the function while (1) { Expression* curr; auto ret = readExpression(curr); @@ -1582,6 +1577,10 @@ public: int depth; // only for debugging BinaryConsts::ASTNodes readExpression(Expression*& curr) { + if (pos == endOfFunction) { + curr = nullptr; + return BinaryConsts::End; + } if (debug) std::cerr << "zz recurse into " << ++depth << " at " << pos << std::endl; uint8_t code = getInt8(); if (debug) std::cerr << "readExpression seeing " << (int)code << std::endl; -- cgit v1.2.3 From fab4db7cd141388b9fdf5c0632f50912fff38891 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 15:05:47 -0700 Subject: name unnamed functions in binaries --- src/wasm-binary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 1cb2046e3..2a49f4ffd 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1440,7 +1440,7 @@ public: } } auto func = Builder(wasm).makeFunction( - Name("TODO"), + Name::fromInt(i), std::move(params), type->result, std::move(vars) -- cgit v1.2.3 From a90070a487d232555831959d78e1c47e9274c97d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 15:09:29 -0700 Subject: update eqz opcodes --- src/wasm-binary.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 2a49f4ffd..50fcc6238 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -269,8 +269,7 @@ enum ASTNodes { I32Clz = 0x57, I32Ctz = 0x58, I32Popcnt = 0x59, - I32EqZ = 0xc0, // XXX - BoolNot = 0x5a, + I32EqZ = 0x5a, I64Add = 0x5b, I64Sub = 0x5c, I64Mul = 0x5d, @@ -297,7 +296,7 @@ enum ASTNodes { I64Clz = 0x72, I64Ctz = 0x73, I64Popcnt = 0x74, - I64EqZ = 0xc1, // XXX + I64EqZ = 0xba, F32Add = 0x75, F32Sub = 0x76, F32Mul = 0x77, -- cgit v1.2.3 From e9ba8d7dfe1754cb48b1efeb6eb9572bd6388a4e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 15:53:16 -0700 Subject: fix a reinterpret opcode --- bin/wasm.js | 2 +- src/wasm-binary.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/bin/wasm.js b/bin/wasm.js index 8d844b38a..ea50d9dde 100644 --- a/bin/wasm.js +++ b/bin/wasm.js @@ -38646,7 +38646,7 @@ function __ZN4wasm17WasmBinaryBuilder14maybeVisitImplEPNS_5UnaryEh(i4, i3, i2) { i5 = 49; break; } - case 254: + case 180: { HEAP32[i3 + 8 >> 2] = 25; HEAP32[i3 + 4 >> 2] = 3; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 50fcc6238..8e9faa15a 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -361,12 +361,12 @@ enum ASTNodes { F64UConvertI64 = 0xb1, F64ConvertF32 = 0xb2, F64ReinterpretI64 = 0xb3, + I32ReinterpretF32 = 0xb4, I64ReinterpretF64 = 0xb5, I32RotR = 0xb6, I32RotL = 0xb7, I64RotR = 0xb8, I64RotL = 0xb9, - I32ReinterpretF32 = 0xfe, // XXX not in v8 spec doc I32LoadMem8S = 0x20, I32LoadMem8U = 0x21, -- cgit v1.2.3 From 10766f949b05379f543ed1f2f4e148fdc9e9ea96 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 16:06:47 -0700 Subject: update br_table in binary format --- src/wasm-binary.h | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 8e9faa15a..fad98386d 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -847,19 +847,17 @@ public: } void visitSwitch(Switch *curr) { if (debug) std::cerr << "zz node: Switch" << std::endl; - o << int8_t(BinaryConsts::TableSwitch) << U32LEB(curr->targets.size()); - for (auto target : curr->targets) { - o << U32LEB(getBreakIndex(target)); - } - o << U32LEB(getBreakIndex(curr->default_)); - recurse(curr->condition); - o << int8_t(BinaryConsts::End); // XXX if (curr->value) { recurse(curr->value); } else { visitNop(nullptr); } - o << int8_t(BinaryConsts::End); // XXX + recurse(curr->condition); + o << int8_t(BinaryConsts::TableSwitch) << U32LEB(curr->targets.size()); + for (auto target : curr->targets) { + o << U32LEB(getBreakIndex(target)); + } + o << U32LEB(getBreakIndex(curr->default_)); } void visitCall(Call *curr) { if (debug) std::cerr << "zz node: Call" << std::endl; @@ -1714,16 +1712,13 @@ public: } void visitSwitch(Switch *curr) { if (debug) std::cerr << "zz node: Switch" << std::endl; + curr->condition = popExpression(); + curr->value = popExpression(); auto numTargets = getU32LEB(); for (size_t i = 0; i < numTargets; i++) { curr->targets.push_back(getBreakName(getU32LEB())); } curr->default_ = getBreakName(getU32LEB()); - processExpressions(); - curr->condition = popExpression(); - processExpressions(); - curr->value = popExpression(); - if (curr->value->is()) curr->value = nullptr; } void visitCall(Call *curr) { if (debug) std::cerr << "zz node: Call" << std::endl; -- cgit v1.2.3 From a7ddd9614b4a7b567258eb018d5e7827d3f48cba Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 16:32:47 -0700 Subject: if condition is popped from before, not pre-order inline --- src/wasm-binary.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index fad98386d..12ea039ac 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -803,8 +803,8 @@ public: } void visitIf(If *curr) { if (debug) std::cerr << "zz node: If" << std::endl; - o << int8_t(BinaryConsts::If); recurse(curr->condition); + o << int8_t(BinaryConsts::If); recurse(curr->ifTrue); // TODO: emit block contents directly, if block with no name if (curr->ifFalse) { o << int8_t(BinaryConsts::Else); @@ -1670,12 +1670,12 @@ public: } void visitIf(If *curr) { if (debug) std::cerr << "zz node: If" << std::endl; + curr->condition = popExpression(); size_t start = expressionStack.size(); auto next = processExpressions(); size_t end = expressionStack.size(); - assert(end - start == 2); + assert(end - start == 1); curr->ifTrue = popExpression(); - curr->condition = popExpression(); if (next == BinaryConsts::Else) { size_t start = expressionStack.size(); processExpressions(); -- cgit v1.2.3 From 66412d32a863fff2308ffc349eeca7f6ffbc2a31 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 17:13:32 -0700 Subject: fix loop binary parsing --- CMakeLists.txt | 3 ++- src/wasm-binary.h | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index 5440db9ab..2f40fa3d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,7 +63,8 @@ ELSE() ADD_COMPILE_FLAG("-O0") ADD_COMPILE_FLAG("-g3") ELSE() - ADD_COMPILE_FLAG("-O2") + ADD_COMPILE_FLAG("-O0") + ADD_COMPILE_FLAG("-g3") ADD_DEFINITIONS("-UNDEBUG") # Keep asserts. ENDIF() ENDIF() diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 12ea039ac..9a911b07d 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -815,7 +815,7 @@ public: void visitLoop(Loop *curr) { if (debug) std::cerr << "zz node: Loop" << std::endl; // TODO: optimize, as we usually have a block as our singleton child - o << int8_t(BinaryConsts::Loop) << int8_t(1); + o << int8_t(BinaryConsts::Loop); breakStack.push_back(curr->out); breakStack.push_back(curr->in); recurse(curr->body); @@ -1668,6 +1668,23 @@ public: breakStack.pop_back(); } } + + Expression* getMaybeBlock() { + auto start = expressionStack.size(); + processExpressions(); + size_t end = expressionStack.size(); + if (end - start == 1) { + return popExpression(); + } else { + auto* body = allocator.alloc(); + for (size_t i = start; i < end; i++) { + body->list.push_back(expressionStack[i]); + } + expressionStack.resize(start); + return body; + } + } + void visitIf(If *curr) { if (debug) std::cerr << "zz node: If" << std::endl; curr->condition = popExpression(); @@ -1687,13 +1704,11 @@ public: } void visitLoop(Loop *curr) { if (debug) std::cerr << "zz node: Loop" << std::endl; - verifyInt8(1); // size TODO: generalize curr->out = getNextLabel(); curr->in = getNextLabel(); breakStack.push_back(curr->out); breakStack.push_back(curr->in); - processExpressions(); - curr->body = popExpression(); + curr->body = getMaybeBlock(); breakStack.pop_back(); breakStack.pop_back(); curr->finalize(); -- cgit v1.2.3 From 51283a2da84f8cbd606b64a1883777a4a3a6aff0 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 17:32:49 -0700 Subject: fix if and else bodies, which can be lists --- src/wasm-binary.h | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 9a911b07d..3e4002c0e 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1485,11 +1485,16 @@ public: std::vector expressionStack; - BinaryConsts::ASTNodes processExpressions() { // until an end or else marker, or the end of the function + BinaryConsts::ASTNodes lastSeparator = BinaryConsts::End; + + void processExpressions() { // until an end or else marker, or the end of the function while (1) { Expression* curr; auto ret = readExpression(curr); - if (!curr) return ret; + if (!curr) { + lastSeparator = ret; + return; + } expressionStack.push_back(curr); } } @@ -1688,19 +1693,12 @@ public: void visitIf(If *curr) { if (debug) std::cerr << "zz node: If" << std::endl; curr->condition = popExpression(); - size_t start = expressionStack.size(); - auto next = processExpressions(); - size_t end = expressionStack.size(); - assert(end - start == 1); - curr->ifTrue = popExpression(); - if (next == BinaryConsts::Else) { - size_t start = expressionStack.size(); - processExpressions(); - size_t end = expressionStack.size(); - assert(end - start == 1); - curr->ifFalse = popExpression(); + curr->ifTrue = getMaybeBlock(); + if (lastSeparator == BinaryConsts::Else) { + curr->ifFalse = getMaybeBlock(); curr->finalize(); } + assert(lastSeparator == BinaryConsts::End); } void visitLoop(Loop *curr) { if (debug) std::cerr << "zz node: Loop" << std::endl; -- cgit v1.2.3 From 89292a31f04882a51338e6c1b98532de2d4ad750 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 18:24:51 -0700 Subject: ifs in the binary format always have a break scope --- src/wasm-binary.h | 35 +++++++++++++++++++++++------------ test/unit.wast.fromBinary | 36 ++++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 24 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 3e4002c0e..3c2833069 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -805,10 +805,14 @@ public: if (debug) std::cerr << "zz node: If" << std::endl; recurse(curr->condition); o << int8_t(BinaryConsts::If); - recurse(curr->ifTrue); // TODO: emit block contents directly, if block with no name + breakStack.push_back(IMPOSSIBLE_CONTINUE); // the binary format requires this; we have a block if we need one; TODO: optimize + recurse(curr->ifTrue); // TODO: emit block contents directly, if possible + breakStack.pop_back(); if (curr->ifFalse) { o << int8_t(BinaryConsts::Else); + breakStack.push_back(IMPOSSIBLE_CONTINUE); // TODO ditto recurse(curr->ifFalse); + breakStack.pop_back(); } o << int8_t(BinaryConsts::End); } @@ -1678,24 +1682,31 @@ public: auto start = expressionStack.size(); processExpressions(); size_t end = expressionStack.size(); - if (end - start == 1) { - return popExpression(); - } else { - auto* body = allocator.alloc(); - for (size_t i = start; i < end; i++) { - body->list.push_back(expressionStack[i]); - } - expressionStack.resize(start); - return body; + // TODO: optimize case of 1 expression and 0 breaks in this scope + auto* block = allocator.alloc(); + for (size_t i = start; i < end; i++) { + block->list.push_back(expressionStack[i]); } + block->finalize(); + expressionStack.resize(start); + return block; + } + + Expression* getBlock() { + Name label = getNextLabel(); + breakStack.push_back(label); + auto* block = getMaybeBlock()->cast(); // TODO: when getMaybeBlock is optimized, blockify only when needed + breakStack.pop_back(); + block->name = label; + return block; } void visitIf(If *curr) { if (debug) std::cerr << "zz node: If" << std::endl; curr->condition = popExpression(); - curr->ifTrue = getMaybeBlock(); + curr->ifTrue = getBlock(); if (lastSeparator == BinaryConsts::Else) { - curr->ifFalse = getMaybeBlock(); + curr->ifFalse = getBlock(); curr->finalize(); } assert(lastSeparator == BinaryConsts::End); diff --git a/test/unit.wast.fromBinary b/test/unit.wast.fromBinary index e99eb1309..e80ba999e 100644 --- a/test/unit.wast.fromBinary +++ b/test/unit.wast.fromBinary @@ -68,8 +68,10 @@ ) (i32.const 0) ) - (br $label$0 - (f64.const -3.4) + (block $label$1 + (br $label$0 + (f64.const -3.4) + ) ) ) (if @@ -79,8 +81,10 @@ ) (f64.const 0) ) - (br $label$0 - (f64.const 5.6) + (block $label$2 + (br $label$0 + (f64.const 5.6) + ) ) ) (f64.const 1.2) @@ -96,8 +100,10 @@ (get_local $var$0) (f64.const 0) ) - (br $label$0 - (f64.const 1.2) + (block $label$1 + (br $label$0 + (f64.const 1.2) + ) ) ) (if @@ -105,8 +111,10 @@ (get_local $var$4) (f64.const 0) ) - (br $label$0 - (f64.const -3.4) + (block $label$2 + (br $label$0 + (f64.const -3.4) + ) ) ) (if @@ -114,8 +122,10 @@ (get_local $var$2) (i32.const 0) ) - (br $label$0 - (f64.const 5.6) + (block $label$3 + (br $label$0 + (f64.const 5.6) + ) ) ) (if @@ -123,8 +133,10 @@ (get_local $var$0) (get_local $var$1) ) - (br $label$0 - (get_local $var$0) + (block $label$4 + (br $label$0 + (get_local $var$0) + ) ) ) (get_local $var$1) -- cgit v1.2.3 From c24d8add1582e6c9caa6c8951d7bcc5c3d64b8c9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Apr 2016 18:37:48 -0700 Subject: function toplevels is a list --- src/wasm-binary.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 3c2833069..01ccfdd3c 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1456,9 +1456,7 @@ public: assert(breakStack.empty()); assert(expressionStack.empty()); depth = 0; - processExpressions(); - assert(expressionStack.size() == 1); - func->body = popExpression(); + func->body = getMaybeBlock(); assert(depth == 0); assert(breakStack.empty()); assert(expressionStack.empty()); @@ -1682,7 +1680,9 @@ public: auto start = expressionStack.size(); processExpressions(); size_t end = expressionStack.size(); - // TODO: optimize case of 1 expression and 0 breaks in this scope + if (start - end == 1) { + return popExpression(); + } auto* block = allocator.alloc(); for (size_t i = start; i < end; i++) { block->list.push_back(expressionStack[i]); @@ -1695,9 +1695,9 @@ public: Expression* getBlock() { Name label = getNextLabel(); breakStack.push_back(label); - auto* block = getMaybeBlock()->cast(); // TODO: when getMaybeBlock is optimized, blockify only when needed + auto* block = Builder(wasm).blockify(getMaybeBlock()); breakStack.pop_back(); - block->name = label; + block->cast()->name = label; return block; } -- cgit v1.2.3