| 772 | } |
| 773 | |
| 774 | void ParseContext::parse_memorysection() { |
| 775 | tok_.expect(TokenType::LParen); |
| 776 | tok_.expect_keyword("memory"); |
| 777 | index_t mem_idx = mem_map_.records.size(); |
| 778 | // optional Id |
| 779 | if (tok_.peek().type == TokenType::Id) { |
| 780 | std::string id = tok_.consume().text; |
| 781 | if (mem_map_.id_map.contains(id)) |
| 782 | throw Exception::Parse("duplicated memory id '" + id + "'", tok_.location()); |
| 783 | mem_map_.id_map[id] = mem_idx; |
| 784 | } |
| 785 | // exportabbr* |
| 786 | while (tok_.peek().type == TokenType::LParen && |
| 787 | tok_.peek2().type == TokenType::Keyword && tok_.peek2().text == "export") { |
| 788 | WasmExport& exp = module_.exports.emplace_back(); |
| 789 | exp.name = parse_exportabbr(); |
| 790 | exp.index = mem_idx; |
| 791 | exp.desc = WasmExport::DescType::mem; |
| 792 | } |
| 793 | // import or inline |
| 794 | if (tok_.peek().type == TokenType::LParen && |
| 795 | tok_.peek2().type == TokenType::Keyword && tok_.peek2().text == "import") { |
| 796 | mem_map_.records.emplace_back(IndexSpace::Type::Import); |
| 797 | auto [imod, iname] = parse_importabbr(); |
| 798 | WasmImport& imp = module_.imports.emplace_back(); |
| 799 | imp.desc = parse_memtype(); |
| 800 | imp.module = imod; imp.name = iname; |
| 801 | } else if (tok_.peek().type == TokenType::LParen && |
| 802 | tok_.peek2().type == TokenType::Keyword && tok_.peek2().text == "data") { |
| 803 | // Inline data: '(' 'data' String* ')' |
| 804 | mem_map_.records.emplace_back(IndexSpace::Type::Normal); |
| 805 | MemType& mem = module_.mems.emplace_back(); |
| 806 | tok_.consume(); tok_.consume(); // '(' 'data' |
| 807 | WasmData& data = module_.datas.emplace_back(); |
| 808 | data.mode = WasmData::DataMode{ |
| 809 | .type = WasmData::DataMode::Mode::active, |
| 810 | .memidx = mem_idx, |
| 811 | .offset = Instr::I64_const() |
| 812 | }; |
| 813 | while (tok_.peek().type == TokenType::String) { |
| 814 | std::string bytes = parse_string_to_bytes(tok_.consume().text); |
| 815 | size_t orig = data.init.size(); |
| 816 | data.init.resize(orig + bytes.size()); |
| 817 | std::memcpy(data.init.data() + orig, bytes.data(), bytes.size()); |
| 818 | } |
| 819 | tok_.expect(TokenType::RParen); // close data |
| 820 | offset_t pages = (offset_t)((data.init.size() + page_size - 1) / page_size); |
| 821 | mem.min = pages; mem.max = pages; |
| 822 | } else { |
| 823 | mem_map_.records.emplace_back(IndexSpace::Type::Normal); |
| 824 | MemType& mem = module_.mems.emplace_back(); |
| 825 | mem = parse_memtype(); |
| 826 | } |
| 827 | tok_.expect(TokenType::RParen); |
| 828 | } |
| 829 | |
| 830 | void ParseContext::parse_globalsection() { |
| 831 | tok_.expect(TokenType::LParen); |