| 58 | // ── Block instructions (non-folded form) ───────────────────────────────────── |
| 59 | |
| 60 | std::vector<WasmInstr> ParseContext::parse_blockinstr(const std::string& kw) { |
| 61 | tok_.consume(); // consume 'block'/'loop'/'if'/'try_table' |
| 62 | |
| 63 | // Increment block level FIRST, then register the label at that level |
| 64 | block_level_ += 1; |
| 65 | std::string label = parse_label(); |
| 66 | |
| 67 | std::optional<index_t> type; |
| 68 | if (is_typeuse_start()) type = parse_typeuse(); |
| 69 | |
| 70 | // try_table: parse catch entries before body |
| 71 | if (kw == "try_table") { |
| 72 | Instr::Try_table tt; |
| 73 | tt.type = type; |
| 74 | while (tok_.peek().type == TokenType::LParen) { |
| 75 | const Token& peek2 = tok_.peek2(); |
| 76 | if (peek2.type != TokenType::Keyword) break; |
| 77 | const std::string& ck = peek2.text; |
| 78 | if (ck != "catch" && ck != "catch_ref" && ck != "catch_all" && ck != "catch_all_ref") |
| 79 | break; |
| 80 | tok_.consume(); // '(' |
| 81 | tok_.consume(); // catch keyword |
| 82 | Instr::TryCatchEntry entry; |
| 83 | if (ck == "catch") entry.kind = Instr::TryCatchEntry::Catch; |
| 84 | else if (ck == "catch_ref") entry.kind = Instr::TryCatchEntry::CatchRef; |
| 85 | else if (ck == "catch_all") entry.kind = Instr::TryCatchEntry::CatchAll; |
| 86 | else entry.kind = Instr::TryCatchEntry::CatchAllRef; |
| 87 | if (entry.kind == Instr::TryCatchEntry::Catch || entry.kind == Instr::TryCatchEntry::CatchRef) |
| 88 | entry.tag_idx = parse_tagidx(); |
| 89 | else |
| 90 | entry.tag_idx = 0; |
| 91 | entry.label_idx = parse_labelidx(); |
| 92 | tok_.expect(TokenType::RParen); |
| 93 | tt.catches.push_back(entry); |
| 94 | } |
| 95 | std::vector<WasmInstr> instrs; |
| 96 | instrs.emplace_back(tt); |
| 97 | while (!tok_.at_eof() && !tok_.peek_keyword("end")) { |
| 98 | auto new_instrs = parse_instr(); |
| 99 | instrs.insert(instrs.end(), new_instrs.begin(), new_instrs.end()); |
| 100 | } |
| 101 | block_level_ -= 1; |
| 102 | tok_.expect_keyword("end"); |
| 103 | if (tok_.peek().type == TokenType::Id) { |
| 104 | Token closing = tok_.consume(); |
| 105 | if (!label.empty() && closing.text != label) |
| 106 | throw Exception::Parse("id '" + closing.text + "' does not match block label", |
| 107 | {closing.line, closing.column}); |
| 108 | } |
| 109 | instrs.emplace_back(Instr::End()); |
| 110 | return instrs; |
| 111 | } |
| 112 | |
| 113 | std::vector<WasmInstr> instrs; |
| 114 | if (kw == "if") instrs.emplace_back(Instr::If(type)); |
| 115 | else if (kw == "block") instrs.emplace_back(Instr::Block(type)); |
| 116 | else instrs.emplace_back(Instr::Loop(type)); |
| 117 |
nothing calls this directly
no test coverage detected