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.h61
1 files changed, 47 insertions, 14 deletions
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index cfabbf52d..db57dda9f 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -699,22 +699,55 @@ private:
}
Expression* makeBlock(Element& s) {
- auto ret = allocator.alloc<Block>();
- size_t i = 1;
- if (i >= s.size()) return ret; // empty block
- if (s[i]->isStr()) {
- ret->name = s[i]->str();
- i++;
- } else {
- ret->name = getPrefixedName("block");
+ // special-case Block, because Block nesting (in their first element) can be incredibly deep
+ auto curr = allocator.alloc<Block>();
+ auto* sp = &s;
+ std::vector<std::pair<Element*, Block*>> stack;
+ while (1) {
+ stack.emplace_back(sp, curr);
+ auto& s = *sp;
+ size_t i = 1;
+ if (i < s.size() && s[i]->isStr()) {
+ curr->name = s[i]->str();
+ i++;
+ } else {
+ curr->name = getPrefixedName("block");
+ }
+ labelStack.push_back(curr->name);
+ if (i >= s.size()) break; // labeled empty block
+ auto& first = *s[i];
+ if (first[0]->str() == BLOCK) {
+ // recurse
+ curr = allocator.alloc<Block>();
+ sp = &first;
+ continue;
+ }
+ break;
}
- labelStack.push_back(ret->name);
- for (; i < s.size(); i++) {
- ret->list.push_back(parseExpression(s[i]));
+ // we now have a stack of Blocks, with their labels, but no contents yet
+ for (int t = int(stack.size()) - 1; t >= 0; t--) {
+ auto* sp = stack[t].first;
+ auto* curr = stack[t].second;
+ auto& s = *sp;
+ size_t i = 1;
+ if (i < s.size()) {
+ if (s[i]->isStr()) {
+ i++;
+ }
+ if (t < int(stack.size()) - 1) {
+ // first child is one of our recursions
+ curr->list.push_back(stack[t + 1].second);
+ i++;
+ }
+ for (; i < s.size(); i++) {
+ curr->list.push_back(parseExpression(s[i]));
+ }
+ }
+ assert(labelStack.back() == curr->name);
+ labelStack.pop_back();
+ curr->finalize();
}
- labelStack.pop_back();
- ret->finalize();
- return ret;
+ return stack[0].second;
}
// Similar to block, but the label is handled by the enclosing if (since there might not be a then or else, ick)