| 652 | } |
| 653 | |
| 654 | void ParseContext::parse_funcsection() { |
| 655 | tok_.expect(TokenType::LParen); |
| 656 | tok_.expect_keyword("func"); |
| 657 | index_t func_idx = func_map_.records.size(); |
| 658 | // optional Id |
| 659 | if (tok_.peek().type == TokenType::Id) { |
| 660 | std::string id = tok_.consume().text; |
| 661 | if (func_map_.id_map.contains(id)) |
| 662 | throw Exception::Parse("duplicated func id '" + id + "'", tok_.location()); |
| 663 | func_map_.id_map[id] = func_idx; |
| 664 | } |
| 665 | // exportabbr* |
| 666 | while (tok_.peek().type == TokenType::LParen && |
| 667 | tok_.peek2().type == TokenType::Keyword && tok_.peek2().text == "export") { |
| 668 | WasmExport& exp = module_.exports.emplace_back(); |
| 669 | exp.name = parse_exportabbr(); |
| 670 | exp.index = func_idx; |
| 671 | exp.desc = WasmExport::DescType::func; |
| 672 | } |
| 673 | // import or body |
| 674 | if (tok_.peek().type == TokenType::LParen && |
| 675 | tok_.peek2().type == TokenType::Keyword && tok_.peek2().text == "import") { |
| 676 | func_map_.records.emplace_back(IndexSpace::Type::Import); |
| 677 | auto [imod, iname] = parse_importabbr(); |
| 678 | WasmImport& imp = module_.imports.emplace_back(); |
| 679 | imp.desc = parse_typeuse(); |
| 680 | imp.module = imod; imp.name = iname; |
| 681 | } else { |
| 682 | func_map_.records.emplace_back(IndexSpace::Type::Normal); |
| 683 | WasmFunc& func = module_.funcs.emplace_back(); |
| 684 | func.typeidx = parse_typeuse(); |
| 685 | // set local_map from param ids |
| 686 | local_map_ = types_[func.typeidx].second; |
| 687 | // locals |
| 688 | while (tok_.peek().type == TokenType::LParen && |
| 689 | tok_.peek2().type == TokenType::Keyword && tok_.peek2().text == "local") { |
| 690 | auto [id, types] = parse_local(); |
| 691 | if (!id.empty()) { |
| 692 | local_map_[id] = func.locals.size(); |
| 693 | } |
| 694 | func.locals.insert(func.locals.end(), types.begin(), types.end()); |
| 695 | } |
| 696 | // instructions |
| 697 | while (tok_.peek().type != TokenType::RParen && !tok_.at_eof()) { |
| 698 | auto instrs = parse_instr(); |
| 699 | func.body.insert(func.body.end(), instrs.begin(), instrs.end()); |
| 700 | } |
| 701 | func.body.emplace_back(Instr::End()); |
| 702 | local_map_.clear(); |
| 703 | label_map_.clear(); |
| 704 | } |
| 705 | tok_.expect(TokenType::RParen); |
| 706 | } |
| 707 | |
| 708 | void ParseContext::parse_tablesection() { |
| 709 | tok_.expect(TokenType::LParen); |