| 239 | // ── Control instructions ────────────────────────────────────────────────────── |
| 240 | |
| 241 | WasmInstr ParseContext::parse_controlinstr(const std::string& name) { |
| 242 | if (name == "unreachable") return Instr::Unreachable(); |
| 243 | if (name == "nop") return Instr::Nop(); |
| 244 | if (name == "return") return Instr::Return(); |
| 245 | if (name == "br") return Instr::Br(parse_labelidx()); |
| 246 | if (name == "br_if") return Instr::Br_if(parse_labelidx()); |
| 247 | if (name == "br_table") { |
| 248 | Instr::Br_table instr; |
| 249 | while (tok_.peek().type == TokenType::Integer || tok_.peek().type == TokenType::Id) |
| 250 | instr.indices.push_back(parse_labelidx()); |
| 251 | return instr; |
| 252 | } |
| 253 | if (name == "call") return Instr::Call(parse_funcidx()); |
| 254 | if (name == "call_ref") return Instr::Call_ref(parse_typeidx()); |
| 255 | if (name == "return_call") return Instr::Return_call(parse_funcidx()); |
| 256 | if (name == "return_call_ref") return Instr::Return_call_ref(parse_typeidx()); |
| 257 | if (name == "throw") return Instr::Throw(parse_tagidx()); |
| 258 | if (name == "throw_ref") return Instr::Throw_ref(); |
| 259 | if (name == "return_call_indirect") { |
| 260 | index_t tableidx = 0; |
| 261 | if ((tok_.peek().type == TokenType::Integer || tok_.peek().type == TokenType::Id) |
| 262 | && !is_typeuse_start()) |
| 263 | tableidx = parse_tableidx(); |
| 264 | return Instr::Return_call_indirect(tableidx, parse_typeuse()); |
| 265 | } |
| 266 | // call_indirect: tableidx? typeuse |
| 267 | index_t tableidx = 0; |
| 268 | if ((tok_.peek().type == TokenType::Integer || tok_.peek().type == TokenType::Id) |
| 269 | && !is_typeuse_start()) { |
| 270 | tableidx = parse_tableidx(); |
| 271 | } |
| 272 | index_t typeidx = parse_typeuse(); |
| 273 | return Instr::Call_indirect(tableidx, typeidx); |
| 274 | } |
| 275 | |
| 276 | // ── Reference instructions ──────────────────────────────────────────────────── |
| 277 |
nothing calls this directly
no test coverage detected