| 881 | } |
| 882 | |
| 883 | void ParseContext::parse_elemsection() { |
| 884 | tok_.expect(TokenType::LParen); |
| 885 | tok_.expect_keyword("elem"); |
| 886 | index_t elem_idx = module_.elems.size(); |
| 887 | // optional Id |
| 888 | if (tok_.peek().type == TokenType::Id) { |
| 889 | std::string id = tok_.consume().text; |
| 890 | if (elem_map_.contains(id)) |
| 891 | throw Exception::Parse("duplicated elem id '" + id + "'", tok_.location()); |
| 892 | elem_map_[id] = elem_idx; |
| 893 | } |
| 894 | |
| 895 | WasmElem& elem = module_.elems.emplace_back(); |
| 896 | |
| 897 | // Detect form: |
| 898 | // 1. Active with offset: tableuse? '(' ('offset'|) constexpr ')' ... |
| 899 | // 2. declare elemlist |
| 900 | // 3. passive elemlist |
| 901 | // 4. Active with just funcidx* (legacy): '(' 'offset'? constexpr ')' funcidx* |
| 902 | |
| 903 | // Check for '(' 'table' ... ')' tableuse |
| 904 | if (tok_.peek().type == TokenType::LParen && |
| 905 | tok_.peek2().type == TokenType::Keyword && tok_.peek2().text == "table") { |
| 906 | // tableuse |
| 907 | tok_.consume(); tok_.consume(); // '(' 'table' |
| 908 | elem.mode.tableidx = parse_tableidx(); |
| 909 | tok_.expect(TokenType::RParen); |
| 910 | } |
| 911 | |
| 912 | // Check for '(' ('offset'|constexpr-keyword) ... ')' — active |
| 913 | if (tok_.peek().type == TokenType::LParen && |
| 914 | tok_.peek2().type == TokenType::Keyword && |
| 915 | (tok_.peek2().text == "offset" || |
| 916 | tok_.peek2().text == "i32.const" || tok_.peek2().text == "i64.const" || |
| 917 | tok_.peek2().text == "f32.const" || tok_.peek2().text == "f64.const" || |
| 918 | tok_.peek2().text == "ref.null" || tok_.peek2().text == "ref.func" || |
| 919 | tok_.peek2().text == "global.get")) { |
| 920 | elem.mode.type = WasmElem::ElemMode::Mode::active; |
| 921 | tok_.consume(); // '(' |
| 922 | if (tok_.peek_keyword("offset")) tok_.consume(); // 'offset' |
| 923 | elem.mode.offset = parse_constexpr(); |
| 924 | tok_.expect(TokenType::RParen); |
| 925 | if (!elem.mode.tableidx.has_value()) elem.mode.tableidx = 0; |
| 926 | // funcidx* (legacy form) |
| 927 | if (tok_.peek().type == TokenType::Integer || tok_.peek().type == TokenType::Id) { |
| 928 | elem.type = RefType::funcref; |
| 929 | while (tok_.peek().type == TokenType::Integer || tok_.peek().type == TokenType::Id) { |
| 930 | elem.elemlist.push_back(ConstInstr{Instr::Ref_func(parse_funcidx())}); |
| 931 | } |
| 932 | tok_.expect(TokenType::RParen); |
| 933 | return; |
| 934 | } |
| 935 | } else if (tok_.peek_keyword("declare")) { |
| 936 | tok_.consume(); |
| 937 | elem.mode.type = WasmElem::ElemMode::Mode::declarative; |
| 938 | } else { |
| 939 | elem.mode.type = WasmElem::ElemMode::Mode::passive; |
| 940 | } |
nothing calls this directly
no test coverage detected