From 227f4e473b39d28f749f4252a0a922517d3a4938 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 14:44:04 -0700 Subject: refactor an LEB128 placeholder method --- src/wasm-binary.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 4b7e1a2a4..f36dcb897 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -432,11 +432,16 @@ public: o << int32_t(10); // version number } - int32_t startSection(const char* name) { - // emit 5 bytes of 0, which we'll fill with LEB later + int32_t writeLEB128Placeholder() { int32_t ret = o.size(); o << int32_t(0); o << int8_t(0); + return ret; + } + + int32_t startSection(const char* name) { + // emit 5 bytes of 0, which we'll fill with LEB later + auto ret = writeLEB128Placeholder(); writeInlineString(name); return ret; } -- cgit v1.2.3 From 8c47cbf61b8751e0f82d002bea57e24f3461458f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 14:53:36 -0700 Subject: backpatching LEB128 always fills all 5 bytes --- src/wasm-binary.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index f36dcb897..37f2d459b 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -158,9 +158,9 @@ public: (*this)[i+2] = x & 0xff; x >>= 8; (*this)[i+3] = x & 0xff; } - void writeAt(size_t i, LEB128 x, size_t minimum = 0) { - if (debug) std::cerr << "backpatchLEB128: " << x.value << " (at " << i << "), minimum " << minimum << std::endl; - x.writeAt(this, i, minimum); + void writeAt(size_t i, LEB128 x) { + if (debug) std::cerr << "backpatchLEB128: " << x.value << " (at " << i << ")" << std::endl; + x.writeAt(this, i, 5); // fill all 5 bytes, we have to do this when backpatching } template @@ -448,7 +448,7 @@ public: void finishSection(int32_t start) { int32_t size = o.size() - start - 5; // section size does not include the 5 bytes of the size field itself - o.writeAt(start, LEB128(size), 5); + o.writeAt(start, LEB128(size)); } void writeStart() { -- cgit v1.2.3 From 0c73e0b7462fa353a7865768375694f48e937aea Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 15:38:22 -0700 Subject: stop assuming we know function names as we decode the binary --- src/wasm-binary.h | 121 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 50 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 37f2d459b..870f5832d 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1061,10 +1061,11 @@ class WasmBinaryBuilder { std::vector& input; bool debug; - size_t pos; + size_t pos = 0; + int32_t startIndex = -1; public: - WasmBinaryBuilder(AllocatingModule& wasm, std::vector& input, bool debug) : wasm(wasm), allocator(wasm.allocator), input(input), debug(debug), pos(0) {} + WasmBinaryBuilder(AllocatingModule& wasm, std::vector& input, bool debug) : wasm(wasm), allocator(wasm.allocator), input(input), debug(debug) {} void read() { @@ -1224,7 +1225,7 @@ public: void readStart() { if (debug) std::cerr << "== readStart" << std::endl; - wasm.start = wasm.functions[getLEB128()]->name; + startIndex = getLEB128(); } void readMemory() { @@ -1289,6 +1290,11 @@ public: return cashew::IString(("label$" + std::to_string(nextLabel++)).c_str(), false); } + // We read functions before we know their names, so we need to backpatch the names later + + 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 + void readFunctions() { if (debug) std::cerr << "== readFunctions" << std::endl; size_t total = getLEB128(); @@ -1327,15 +1333,39 @@ public: addLocals(f64); } size_t size = getInt32(); // XXX int32, diverge from v8 format, to get more code to compile - // we can't read the function yet - it might call other functions that are defined later, - // and we do depend on the function type. - functions.emplace_back(func, pos, size); - pos += size; - func->body = nullptr; // will be filled later. but we do have the name and the type already. - wasm.addFunction(func); + assert(size > 0); // we could also check it matches the see in the next {} + { + // process the function body + if (debug) std::cerr << "processing function: " << i << std::endl; + nextLabel = 0; + // prepare locals + mappedLocals.clear(); + localTypes.clear(); + for (size_t i = 0; i < func->params.size(); i++) { + mappedLocals.push_back(func->params[i].name); + localTypes[func->params[i].name] = func->params[i].type; + } + for (size_t i = 0; i < func->locals.size(); i++) { + mappedLocals.push_back(func->locals[i].name); + localTypes[func->locals[i].name] = func->locals[i].type; + } + // process body + assert(breakStack.empty()); + assert(expressionStack.empty()); + depth = 0; + processExpressions(); + assert(expressionStack.size() == 1); + func->body = popExpression(); + assert(depth == 0); + assert(breakStack.empty()); + assert(expressionStack.empty()); + } + functions.push_back(func); } } + std::map exportIndexes; + void readExports() { if (debug) std::cerr << "== readExports" << std::endl; size_t num = getLEB128(); @@ -1344,22 +1374,12 @@ public: if (debug) std::cerr << "read one" << std::endl; auto curr = allocator.alloc(); auto index = getLEB128(); - assert(index < wasm.functions.size()); - curr->value = wasm.functions[index]->name; - assert(curr->value.is()); + assert(index < functionTypes.size()); curr->name = getInlineString(); - wasm.addExport(curr); + exportIndexes[curr] = index; } } - struct FunctionData { - Function* func; - size_t pos, size; - FunctionData(Function* func, size_t pos, size_t size) : func(func), pos(pos), size(size) {} - }; - - std::vector functions; - std::vector mappedLocals; // index => local name std::map localTypes; // TODO: optimize @@ -1385,32 +1405,31 @@ public: void processFunctions() { for (auto& func : functions) { - Function* curr = func.func; - if (debug) std::cerr << "processing function: " << curr->name << std::endl; - pos = func.pos; - nextLabel = 0; - // prepare locals - mappedLocals.clear(); - localTypes.clear(); - for (size_t i = 0; i < curr->params.size(); i++) { - mappedLocals.push_back(curr->params[i].name); - localTypes[curr->params[i].name] = curr->params[i].type; - } - for (size_t i = 0; i < curr->locals.size(); i++) { - mappedLocals.push_back(curr->locals[i].name); - localTypes[curr->locals[i].name] = curr->locals[i].type; + wasm.addFunction(func); + } + // now that we have names for each function, apply things + + if (startIndex >= 0) { + wasm.start = wasm.functions[startIndex]->name; + } + + for (auto& iter : exportIndexes) { + Export* curr = iter.first; + curr->value = wasm.functions[iter.second]->name; + wasm.addExport(curr); + } + + for (auto& iter : functionCalls) { + size_t index = iter.first; + auto& calls = iter.second; + for (auto* call : calls) { + call->target = wasm.functions[index]->name; } - // process body - assert(breakStack.empty()); - assert(expressionStack.empty()); - depth = 0; - processExpressions(); - assert(expressionStack.size() == 1); - curr->body = popExpression(); - assert(depth == 0); - assert(breakStack.empty()); - assert(expressionStack.empty()); - assert(pos == func.pos + func.size); + } + + for (size_t index : functionTable) { + assert(index < wasm.functions.size()); + wasm.table.names.push_back(wasm.functions[index]->name); } } @@ -1431,13 +1450,14 @@ public: } } + std::vector functionTable; + void readFunctionTable() { if (debug) std::cerr << "== readFunctionTable" << std::endl; auto num = getLEB128(); for (size_t i = 0; i < num; i++) { auto index = getLEB128(); - assert(index < wasm.functions.size()); - wasm.table.names.push_back(wasm.functions[index]->name); + functionTable.push_back(index); } } @@ -1588,14 +1608,15 @@ public: } void visitCall(Call *curr) { if (debug) std::cerr << "zz node: Call" << std::endl; - curr->target = wasm.functions[getLEB128()]->name; - auto type = wasm.functionTypesMap[wasm.functionsMap[curr->target]->type]; + auto index = getLEB128(); + auto type = functionTypes[index]; auto num = type->params.size(); curr->operands.resize(num); for (size_t i = 0; i < num; i++) { curr->operands[num - i - 1] = popExpression(); } curr->type = type->result; + functionCalls[index].push_back(curr); } void visitCallImport(CallImport *curr) { if (debug) std::cerr << "zz node: CallImport" << std::endl; -- cgit v1.2.3 From cec883550664a64b9f6a425dd68a3caf529fa306 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 16:00:10 -0700 Subject: use names section for function names --- src/wasm-binary.h | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 870f5832d..d1dd038c6 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -180,6 +180,7 @@ namespace Section { auto ExportTable = "export_table"; auto DataSegments = "data_segments"; auto FunctionTable = "function_table"; + auto Names = "names"; auto End = "end"; auto Start = "start_function"; }; @@ -422,6 +423,7 @@ public: writeExports(); writeDataSegments(); writeFunctionTable(); + writeNames(); writeEnd(); finishUp(); } @@ -568,15 +570,11 @@ public: for (size_t i = 0; i < total; i++) { if (debug) std::cerr << "write one at" << o.size() << std::endl; Function* function = wasm->functions[i]; - Name name, type; - name = function->name; - type = function->type; mappedLocals.clear(); numLocalsByType.clear(); - if (debug) std::cerr << "writing" << name << std::endl; + if (debug) std::cerr << "writing" << function->name << std::endl; o << int8_t(BinaryConsts::Named | (BinaryConsts::Locals * (function && function->locals.size() > 0))); - emitString(name.str); mapLocals(function); if (function->locals.size() > 0) { o << uint16_t(numLocalsByType[i32]) @@ -654,6 +652,18 @@ public: finishSection(start); } + void writeNames() { + if (wasm->functions.size() == 0) return; + if (debug) std::cerr << "== writeNames" << std::endl; + auto start = startSection(BinaryConsts::Section::Names); + o << LEB128(wasm->functions.size()); + for (auto* curr : wasm->functions) { + writeInlineString(curr->name.str); + o << LEB128(0); // TODO: locals + } + finishSection(start); + } + void writeEnd() { auto start = startSection(BinaryConsts::Section::End); finishSection(start); @@ -1095,6 +1105,7 @@ public: else if (match(BinaryConsts::Section::ExportTable)) readExports(); 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; @@ -1305,10 +1316,8 @@ public: bool named = data & BinaryConsts::Named; assert(named); bool locals = data & BinaryConsts::Locals; - Name name = getString(); - if (debug) std::cerr << "reading" << name << std::endl; + if (debug) std::cerr << "reading" << i << std::endl; auto func = allocator.alloc(); - func->name = name; func->type = type->name; func->result = type->result; size_t nextVar = 0; @@ -1461,6 +1470,16 @@ public: } } + void readNames() { + if (debug) std::cerr << "== readNames" << std::endl; + auto num = getLEB128(); + for (size_t i = 0; i < num; i++) { + functions[i]->name = getInlineString(); + auto numLocals = getLEB128(); + assert(numLocals == 0); // TODO + } + } + // AST reading int depth; // only for debugging -- cgit v1.2.3 From fcc348ac052f213d7b57d27f82a743fbc932ef45 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 16:05:08 -0700 Subject: use function body sizes like in the spec --- src/wasm-binary.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index d1dd038c6..1d51fba57 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -569,6 +569,8 @@ public: o << LEB128(total); for (size_t i = 0; i < total; i++) { if (debug) std::cerr << "write one at" << o.size() << std::endl; + size_t sizePos = writeLEB128Placeholder(); + size_t start = o.size(); Function* function = wasm->functions[i]; mappedLocals.clear(); numLocalsByType.clear(); @@ -582,9 +584,6 @@ public: << uint16_t(numLocalsByType[f32]) << uint16_t(numLocalsByType[f64]); } - size_t sizePos = o.size(); - o << (uint32_t)0; // placeholder, we fill in the size later when we have it // XXX int32, diverge from v8 format, to get more code to compile - size_t start = o.size(); depth = 0; recurse(function->body); o << int8_t(BinaryConsts::EndMarker); @@ -592,7 +591,7 @@ public: size_t size = o.size() - start; assert(size <= std::numeric_limits::max()); if (debug) std::cerr << "body size: " << size << ", writing at " << sizePos << ", next starts at " << o.size() << std::endl; - o.writeAt(sizePos, uint32_t(size)); // XXX int32, diverge from v8 format, to get more code to compile + o.writeAt(sizePos, LEB128(size)); } finishSection(start); } @@ -1311,6 +1310,8 @@ public: size_t total = getLEB128(); for (size_t i = 0; i < total; i++) { if (debug) std::cerr << "read one at " << pos << std::endl; + size_t size = getLEB128(); + assert(size > 0); // we could also check it matches the seen size auto data = getInt8(); auto type = functionTypes[i]; bool named = data & BinaryConsts::Named; @@ -1341,8 +1342,6 @@ public: addLocals(f32); addLocals(f64); } - size_t size = getInt32(); // XXX int32, diverge from v8 format, to get more code to compile - assert(size > 0); // we could also check it matches the see in the next {} { // process the function body if (debug) std::cerr << "processing function: " << i << std::endl; -- cgit v1.2.3 From fbd820246f8e721aab2e6696d22dacdf3271e6ae Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 16:18:03 -0700 Subject: write function locals per the spec --- src/wasm-binary.h | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 1d51fba57..7a801920e 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -575,15 +575,17 @@ public: mappedLocals.clear(); numLocalsByType.clear(); if (debug) std::cerr << "writing" << function->name << std::endl; - o << int8_t(BinaryConsts::Named | - (BinaryConsts::Locals * (function && function->locals.size() > 0))); mapLocals(function); - if (function->locals.size() > 0) { - o << uint16_t(numLocalsByType[i32]) - << uint16_t(numLocalsByType[i64]) - << uint16_t(numLocalsByType[f32]) - << uint16_t(numLocalsByType[f64]); - } + o << LEB128( + (numLocalsByType[i32] ? 1 : 0) + + (numLocalsByType[i64] ? 1 : 0) + + (numLocalsByType[f32] ? 1 : 0) + + (numLocalsByType[f64] ? 1 : 0) + ); + if (numLocalsByType[i32]) o << LEB128(numLocalsByType[i32]) << binaryWasmType(i32); + if (numLocalsByType[i64]) o << LEB128(numLocalsByType[i64]) << binaryWasmType(i64); + if (numLocalsByType[f32]) o << LEB128(numLocalsByType[f32]) << binaryWasmType(f32); + if (numLocalsByType[f64]) o << LEB128(numLocalsByType[f64]) << binaryWasmType(f64); depth = 0; recurse(function->body); o << int8_t(BinaryConsts::EndMarker); @@ -1312,11 +1314,7 @@ public: if (debug) std::cerr << "read one at " << pos << std::endl; size_t size = getLEB128(); assert(size > 0); // we could also check it matches the seen size - auto data = getInt8(); auto type = functionTypes[i]; - bool named = data & BinaryConsts::Named; - assert(named); - bool locals = data & BinaryConsts::Locals; if (debug) std::cerr << "reading" << i << std::endl; auto func = allocator.alloc(); func->type = type->name; @@ -1329,18 +1327,14 @@ public: for (size_t j = 0; j < type->params.size(); j++) { func->params.emplace_back(addVar(), type->params[j]); } - if (locals) { - auto addLocals = [&](WasmType type) { - int16_t num = getInt16(); - while (num > 0) { - func->locals.emplace_back(addVar(), type); - num--; - } - }; - addLocals(i32); - addLocals(i64); - addLocals(f32); - addLocals(f64); + size_t numLocalTypes = getLEB128(); + for (size_t t = 0; t < numLocalTypes; t++) { + auto num = getLEB128(); + auto type = getWasmType(); + while (num > 0) { + func->locals.emplace_back(addVar(), type); + num--; + } } { // process the function body -- cgit v1.2.3 From 9c374b6a2368ef5cb0c102e3e2f164410289f454 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 16:52:20 -0700 Subject: use leb128 in breaks --- bin/wasm.js | 60 +++++++++++++++++++++++++++---------------------------- src/wasm-binary.h | 4 ++-- 2 files changed, 32 insertions(+), 32 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/bin/wasm.js b/bin/wasm.js index 60a91b2d6..724d85352 100644 --- a/bin/wasm.js +++ b/bin/wasm.js @@ -63029,6 +63029,36 @@ function __ZNSt3__114__num_put_base14__format_floatEPcPKcj(i1, i3, i2) { return i5 | 0; } +function __ZN4wasm17WasmBinaryBuilder10visitBreakEPNS_5BreakEh(i4, i3, i2) { + i4 = i4 | 0; + i3 = i3 | 0; + i2 = i2 | 0; + var i1 = 0, i5 = 0, i6 = 0, i7 = 0; + i5 = STACKTOP; + STACKTOP = STACKTOP + 16 | 0; + i1 = i5; + if (HEAP8[i4 + 12 >> 0] | 0) { + i6 = __ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc(43944, 18680) | 0; + i7 = __ZNKSt3__18ios_base6getlocEv(i6 + (HEAP32[(HEAP32[i6 >> 2] | 0) + -12 >> 2] | 0) | 0) | 0; + HEAP32[i1 >> 2] = i7; + i7 = __ZNKSt3__16locale9use_facetERNS0_2idE(i1, 44820) | 0; + i7 = FUNCTION_TABLE_iii[HEAP32[(HEAP32[i7 >> 2] | 0) + 28 >> 2] & 31](i7, 10) | 0; + __ZNSt3__16localeD2Ev(i1); + __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE3putEc(i6, i7) | 0; + __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5flushEv(i6) | 0; + } + i7 = __ZN4wasm17WasmBinaryBuilder12getBreakNameEi(i4, __ZN4wasm17WasmBinaryBuilder9getLEB128Ev(i4) | 0) | 0; + HEAP32[i3 + 8 >> 2] = i7; + if (i2 << 24 >> 24 == 7) { + i7 = __ZN4wasm17WasmBinaryBuilder13popExpressionEv(i4) | 0; + HEAP32[i3 + 16 >> 2] = i7; + } + i7 = __ZN4wasm17WasmBinaryBuilder13popExpressionEv(i4) | 0; + HEAP32[i3 + 12 >> 2] = i7; + STACKTOP = i5; + return; +} + function __ZNSt3__16vectorIN4wasm8NameTypeENS_9allocatorIS2_EEE24__emplace_back_slow_pathIJNS1_4NameERNS1_8WasmTypeEEEEvDpOT_(i8, i5, i6) { i8 = i8 | 0; i5 = i5 | 0; @@ -63059,36 +63089,6 @@ function __ZNSt3__16vectorIN4wasm8NameTypeENS_9allocatorIS2_EEE24__emplace_back_ return; } -function __ZN4wasm17WasmBinaryBuilder10visitBreakEPNS_5BreakEh(i4, i3, i2) { - i4 = i4 | 0; - i3 = i3 | 0; - i2 = i2 | 0; - var i1 = 0, i5 = 0, i6 = 0, i7 = 0; - i5 = STACKTOP; - STACKTOP = STACKTOP + 16 | 0; - i1 = i5; - if (HEAP8[i4 + 12 >> 0] | 0) { - i6 = __ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc(43944, 18680) | 0; - i7 = __ZNKSt3__18ios_base6getlocEv(i6 + (HEAP32[(HEAP32[i6 >> 2] | 0) + -12 >> 2] | 0) | 0) | 0; - HEAP32[i1 >> 2] = i7; - i7 = __ZNKSt3__16locale9use_facetERNS0_2idE(i1, 44820) | 0; - i7 = FUNCTION_TABLE_iii[HEAP32[(HEAP32[i7 >> 2] | 0) + 28 >> 2] & 31](i7, 10) | 0; - __ZNSt3__16localeD2Ev(i1); - __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE3putEc(i6, i7) | 0; - __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5flushEv(i6) | 0; - } - i7 = __ZN4wasm17WasmBinaryBuilder12getBreakNameEi(i4, __ZN4wasm17WasmBinaryBuilder8getInt32Ev(i4) | 0) | 0; - HEAP32[i3 + 8 >> 2] = i7; - if (i2 << 24 >> 24 == 7) { - i7 = __ZN4wasm17WasmBinaryBuilder13popExpressionEv(i4) | 0; - HEAP32[i3 + 16 >> 2] = i7; - } - i7 = __ZN4wasm17WasmBinaryBuilder13popExpressionEv(i4) | 0; - HEAP32[i3 + 12 >> 2] = i7; - STACKTOP = i5; - return; -} - function __ZNSt3__113unordered_mapIN6cashew7IStringEN7AsmData5LocalENS_4hashIS2_EENS_8equal_toIS2_EENS_9allocatorINS_4pairIKS2_S4_EEEEEixERSB_(i5, i4) { i5 = i5 | 0; i4 = i4 | 0; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 7a801920e..5dd363b9d 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -781,7 +781,7 @@ public: } if (curr->condition) recurse(curr->condition); o << int8_t(curr->condition ? BinaryConsts::BrIf : BinaryConsts::Br) - << int32_t(getBreakIndex(curr->name)); + << LEB128(getBreakIndex(curr->name)); } void visitSwitch(Switch *curr) { if (debug) std::cerr << "zz node: Switch" << std::endl; @@ -1599,7 +1599,7 @@ public: void visitBreak(Break *curr, uint8_t code) { if (debug) std::cerr << "zz node: Break" << std::endl; - curr->name = getBreakName(getInt32()); + curr->name = getBreakName(getLEB128()); if (code == BinaryConsts::BrIf) curr->condition = popExpression(); curr->value = popExpression(); } -- cgit v1.2.3 From 1574710289a5ff49f983d96fd9782800d8d87c00 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 17:01:03 -0700 Subject: update switch encoding --- src/wasm-binary.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 5dd363b9d..1e6c48c3b 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -785,17 +785,19 @@ public: } void visitSwitch(Switch *curr) { if (debug) std::cerr << "zz node: Switch" << std::endl; - o << int8_t(BinaryConsts::TableSwitch) << int16_t(curr->targets.size() + 1) << int8_t(curr->value != nullptr); + o << int8_t(BinaryConsts::TableSwitch) << LEB128(curr->targets.size()); for (auto target : curr->targets) { - o << (int32_t)getBreakIndex(target); + o << LEB128(getBreakIndex(target)); } - o << (int32_t)getBreakIndex(curr->default_); + o << LEB128(getBreakIndex(curr->default_)); recurse(curr->condition); o << int8_t(BinaryConsts::EndMarker); if (curr->value) { recurse(curr->value); - o << int8_t(BinaryConsts::EndMarker); + } else { + visitNop(nullptr); } + o << int8_t(BinaryConsts::EndMarker); } void visitCall(Call *curr) { if (debug) std::cerr << "zz node: Call" << std::endl; @@ -1605,18 +1607,16 @@ public: } void visitSwitch(Switch *curr) { if (debug) std::cerr << "zz node: Switch" << std::endl; - auto numTargets = getInt16(); - auto hasValue = getInt8(); - for (auto i = 0; i < numTargets - 1; i++) { - curr->targets.push_back(getBreakName(getInt32())); + auto numTargets = getLEB128(); + for (size_t i = 0; i < numTargets; i++) { + curr->targets.push_back(getBreakName(getLEB128())); } - curr->default_ = getBreakName(getInt32()); + curr->default_ = getBreakName(getLEB128()); processExpressions(); curr->condition = popExpression(); - if (hasValue) { - processExpressions(); - curr->value = 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 31e92024ae8859c9387dbdcda1dfebb888f82510 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 17:20:15 -0700 Subject: add a 64-bit LEB --- src/wasm-binary.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 1e6c48c3b..da397399f 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -30,14 +30,15 @@ namespace wasm { -struct LEB128 { - uint32_t value; +template +struct LEB { + T value; - LEB128() {} - LEB128(uint32_t value) : value(value) {} + LEB() {} + LEB(T value) : value(value) {} void write(std::vector* out) { - uint32_t temp = value; + T temp = value; do { uint8_t byte = temp & 127; temp >>= 7; @@ -49,7 +50,7 @@ struct LEB128 { } void writeAt(std::vector* out, size_t at, size_t minimum = 0) { - uint32_t temp = value; + T temp = value; size_t offset = 0; bool more; do { @@ -66,16 +67,19 @@ struct LEB128 { void read(std::function get) { value = 0; - uint32_t shift = 0; + T shift = 0; while (1) { uint8_t byte = get(); - value |= ((byte & 127) << shift); + value |= ((T(byte & 127)) << shift); if (!(byte & 128)) break; shift += 7; } } }; +typedef LEB LEB128; +typedef LEB LEB256; + // // We mostly stream into a buffer as we create the binary format, however, // sometimes we need to backtrack and write to a location behind us - wasm -- cgit v1.2.3 From b0e342231cab63668a98c8b1caac700e4a1cb0fc Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 17:23:55 -0700 Subject: update const to binary spec --- src/wasm-binary.h | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index da397399f..3985bae04 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -127,6 +127,11 @@ public: x.write(this); return *this; } + BufferWithRandomAccess& operator<<(LEB256 x) { + if (debug) std::cerr << "writeLEB256: " << x.value << " (at " << size() << ")" << std::endl; + x.write(this); + return *this; + } BufferWithRandomAccess& operator<<(uint8_t x) { return *this << (int8_t)x; @@ -347,7 +352,6 @@ enum ASTNodes { F32StoreMem = 0x35, F64StoreMem = 0x36, - I8Const = 0x09, I32Const = 0x0a, I64Const = 0x0b, F64Const = 0x0c, @@ -904,16 +908,11 @@ public: if (debug) std::cerr << "zz node: Const" << curr << " : " << curr->type << std::endl; switch (curr->type) { case i32: { - uint32_t value = curr->value.geti32(); - if (value <= 255) { - o << int8_t(BinaryConsts::I8Const) << uint8_t(value); - break; - } - o << int8_t(BinaryConsts::I32Const) << value; + o << int8_t(BinaryConsts::I32Const) << LEB128(curr->value.geti32()); break; } case i64: { - o << int8_t(BinaryConsts::I64Const) << curr->value.geti64(); + o << int8_t(BinaryConsts::I64Const) << LEB256(curr->value.geti64()); break; } case f32: { @@ -1173,6 +1172,15 @@ public: if (debug) std::cerr << "getLEB128: " << ret.value << " ==>" << std::endl; return ret.value; } + uint64_t getLEB256() { + if (debug) std::cerr << "<==" << std::endl; + LEB256 ret; + ret.read([&]() { + return getInt8(); + }); + if (debug) std::cerr << "getLEB256: " << ret.value << " ==>" << std::endl; + return ret.value; + } WasmType getWasmType() { int8_t type = getInt8(); switch (type) { @@ -1727,9 +1735,8 @@ public: } bool maybeVisitImpl(Const *curr, uint8_t code) { switch (code) { - case BinaryConsts::I8Const: curr->value = Literal(int32_t(getInt8())); break; - case BinaryConsts::I32Const: curr->value = Literal(getInt32()); break; - case BinaryConsts::I64Const: curr->value = Literal(getInt64()); break; + case BinaryConsts::I32Const: curr->value = Literal(getLEB128()); break; + case BinaryConsts::I64Const: curr->value = Literal(getLEB256()); break; case BinaryConsts::F32Const: curr->value = Literal(getFloat32()); break; case BinaryConsts::F64Const: curr->value = Literal(getFloat64()); break; default: return false; -- cgit v1.2.3 From 2467f6f72ecdd1e3f5353abecc67e8e8241f93e6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 16 Mar 2016 17:51:29 -0700 Subject: update memory access in binary format --- src/wasm-binary.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 3985bae04..3ce76e247 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -840,9 +840,8 @@ public: } void emitMemoryAccess(size_t alignment, size_t bytes, uint32_t offset) { - o << int8_t( ((alignment == bytes || alignment == 0) ? BinaryConsts::NaturalAlignment : BinaryConsts::Alignment) | - (offset ? BinaryConsts::Offset : 0) ); - if (offset) o << LEB128(offset); + o << LEB128(Log2(alignment ? alignment : bytes)); + o << LEB128(offset); } void visitLoad(Load *curr) { @@ -1682,13 +1681,8 @@ public: } void readMemoryAccess(uint32_t& alignment, size_t bytes, uint32_t& offset) { - auto value = getInt8(); - alignment = value & BinaryConsts::Alignment ? 1 : bytes; - if (value & BinaryConsts::Offset) { - offset = getLEB128(); - } else { - offset = 0; - } + alignment = Pow2(getLEB128()); + offset = getLEB128(); } bool maybeVisitImpl(Load *curr, uint8_t code) { -- cgit v1.2.3