diff options
Diffstat (limited to 'src/wasm-s-parser.h')
-rw-r--r-- | src/wasm-s-parser.h | 69 |
1 files changed, 62 insertions, 7 deletions
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 750d485fb..b70f70b4e 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -367,13 +367,15 @@ private: if (id == START) return parseStart(curr); if (id == FUNC) return parseFunction(curr); if (id == MEMORY) return parseMemory(curr); + if (id == DATA) return parseData(curr); if (id == EXPORT) return parseExport(curr); if (id == IMPORT) return; // already done if (id == GLOBAL) return parseGlobal(curr); if (id == TABLE) return parseTable(curr); + if (id == ELEM) return parseElem(curr); if (id == TYPE) return; // already done std::cerr << "bad module element " << id.str << '\n'; - throw ParseException("unknown module element"); + throw ParseException("unknown module element", curr.line, curr.col); } // function parsing state @@ -1321,19 +1323,40 @@ private: } while (i < s.size()) { Element& curr = *s[i]; - assert(curr[0]->str() == SEGMENT); - const char *input = curr[2]->c_str(); + size_t j = 1; + Address offsetValue; + if (curr[0]->str() == DATA) { + offsetValue = 0; + } else { + offsetValue = atoi(curr[j++]->c_str()); + } + const char *input = curr[j]->c_str(); + auto* offset = allocator.alloc<Const>(); + offset->type = i32; + offset->value = Literal(int32_t(offsetValue)); if (auto size = strlen(input)) { std::vector<char> data; stringToBinary(input, size, data); - wasm.memory.segments.emplace_back(atoi(curr[1]->c_str()), data.data(), data.size()); + wasm.memory.segments.emplace_back(offset, data.data(), data.size()); } else { - wasm.memory.segments.emplace_back(atoi(curr[1]->c_str()), "", 0); + wasm.memory.segments.emplace_back(offset, "", 0); } i++; } } + void parseData(Element& s) { + auto* offset = parseExpression(s[1]); + const char *input = s[2]->c_str(); + if (auto size = strlen(input)) { + std::vector<char> data; + stringToBinary(input, size, data); + wasm.memory.segments.emplace_back(offset, data.data(), data.size()); + } else { + wasm.memory.segments.emplace_back(offset, "", 0); + } + } + void parseExport(Element& s) { if (!s[2]->dollared() && !std::isdigit(s[2]->str()[0])) { assert(s[2]->str() == MEMORY); @@ -1402,9 +1425,41 @@ private: } void parseTable(Element& s) { - for (size_t i = 1; i < s.size(); i++) { - wasm.table.names.push_back(getFunctionName(*s[i])); + if (s.size() == 1) return; // empty table in old notation + if (!s[1]->dollared()) { + if (s[1]->str() == ANYFUNC) { + // (table type (elem ..)) + parseElem(*s[2]); + wasm.table.initial = wasm.table.max = wasm.table.segments[0].data.size(); + return; + } + // first element isn't dollared, and isn't anyfunc. this could be old syntax for (table 0 1) which means function 0 and 1, or it could be (table initial max? type), look for type + if (s[s.size() - 1]->str() == ANYFUNC) { + // (table initial max? type) + wasm.table.initial = atoi(s[1]->c_str()); + wasm.table.max = atoi(s[2]->c_str()); + return; + } + } + // old notation (table func1 func2 ..) + parseElem(s); + wasm.table.initial = wasm.table.max = wasm.table.segments[0].data.size(); + } + + void parseElem(Element& s) { + Index i = 1; + Expression* offset; + if (s[i]->isList()) { + // there is an init expression + offset = parseExpression(s[i++]); + } else { + offset = allocator.alloc<Const>()->set(Literal(int32_t(0))); + } + Table::Segment segment(offset); + for (; i < s.size(); i++) { + segment.data.push_back(getFunctionName(*s[i])); } + wasm.table.segments.push_back(segment); } void parseType(Element& s) { |