summaryrefslogtreecommitdiff
path: root/src/wasm-s-parser.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm-s-parser.h')
-rw-r--r--src/wasm-s-parser.h69
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) {