From 0b8c66a19e87c6b5de6539fc742c351c754b4771 Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Wed, 11 Mar 2026 15:05:52 -0400 Subject: [PATCH 01/16] fix: symbol name for combined z3 model --- headers/wasm/smt_solver.hpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/headers/wasm/smt_solver.hpp b/headers/wasm/smt_solver.hpp index 562eeecb..7faaf83a 100644 --- a/headers/wasm/smt_solver.hpp +++ b/headers/wasm/smt_solver.hpp @@ -59,7 +59,18 @@ compose_query_results(const std::vector &results) { } } ImmNumMapBox combined_map_box(combined_map); - return QueryResult{combined_map_box, combined_model}; + + z3::solver solver(global_z3_ctx()); + + // build a combined z3 model + for (const auto &[id, num] : combined_map) { + // TODO: fix symbol name for other types + solver.add( + global_z3_ctx().bv_const(("s_int" + std::to_string(id)).c_str(), 32) == + global_z3_ctx().bv_val(num.value, 32)); + } + solver.check(); + return QueryResult{combined_map_box, solver.get_model()}; } // VectorGroupResult groups a vector. key is the vector index, and value is the From c103f855d825280ece5a99d58a4ffcd5cbd59abf Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Wed, 11 Mar 2026 15:11:11 -0400 Subject: [PATCH 02/16] compute composed model by z3::model directly --- headers/wasm/smt_solver.hpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/headers/wasm/smt_solver.hpp b/headers/wasm/smt_solver.hpp index 7faaf83a..562eeecb 100644 --- a/headers/wasm/smt_solver.hpp +++ b/headers/wasm/smt_solver.hpp @@ -59,18 +59,7 @@ compose_query_results(const std::vector &results) { } } ImmNumMapBox combined_map_box(combined_map); - - z3::solver solver(global_z3_ctx()); - - // build a combined z3 model - for (const auto &[id, num] : combined_map) { - // TODO: fix symbol name for other types - solver.add( - global_z3_ctx().bv_const(("s_int" + std::to_string(id)).c_str(), 32) == - global_z3_ctx().bv_val(num.value, 32)); - } - solver.check(); - return QueryResult{combined_map_box, solver.get_model()}; + return QueryResult{combined_map_box, combined_model}; } // VectorGroupResult groups a vector. key is the vector index, and value is the From e3a2f080831b4cf4acdef0e4c369bef447a544fb Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Thu, 12 Mar 2026 00:14:23 -0400 Subject: [PATCH 03/16] move antlr interp files to .antlr folder so we can debug them in vscode --- grammar/gen-wat-parser.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/grammar/gen-wat-parser.sh b/grammar/gen-wat-parser.sh index a67e72a0..19923715 100755 --- a/grammar/gen-wat-parser.sh +++ b/grammar/gen-wat-parser.sh @@ -19,4 +19,6 @@ do rm $file done -rm *.tokens *.interp +mkdir -p "$(dirname "$0")/.antlr" +mv *.tokens *.interp .antlr/ + From 97e90637c7c980bc0da065a0c06d3bc8de44affc Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Thu, 12 Mar 2026 00:14:53 -0400 Subject: [PATCH 04/16] fix load syntax --- grammar/WatParser.g4 | 4 +- src/main/java/wasm/WatParser.java | 2218 ++++++++++++++--------------- src/main/scala/wasm/Parser.scala | 26 +- 3 files changed, 1113 insertions(+), 1135 deletions(-) diff --git a/grammar/WatParser.g4 b/grammar/WatParser.g4 index 5e3a5b02..d6274275 100644 --- a/grammar/WatParser.g4 +++ b/grammar/WatParser.g4 @@ -196,11 +196,11 @@ offsetEq : OFFSET_EQ NAT ; alignEq: ALIGN_EQ NAT ; load - : numType LOAD (MEM_SIZE UNDERSCORE SIGN_POSTFIX)? + : numType LOAD ; store - : numType STORE (MEM_SIZE)? + : numType STORE ; selectInstr diff --git a/src/main/java/wasm/WatParser.java b/src/main/java/wasm/WatParser.java index 1c36b848..73f3f523 100644 --- a/src/main/java/wasm/WatParser.java +++ b/src/main/java/wasm/WatParser.java @@ -2277,9 +2277,6 @@ public NumTypeContext numType() { return getRuleContext(NumTypeContext.class,0); } public TerminalNode LOAD() { return getToken(WatParser.LOAD, 0); } - public TerminalNode MEM_SIZE() { return getToken(WatParser.MEM_SIZE, 0); } - public TerminalNode UNDERSCORE() { return getToken(WatParser.UNDERSCORE, 0); } - public TerminalNode SIGN_POSTFIX() { return getToken(WatParser.SIGN_POSTFIX, 0); } public LoadContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2302,7 +2299,6 @@ public T accept(ParseTreeVisitor visitor) { public final LoadContext load() throws RecognitionException { LoadContext _localctx = new LoadContext(_ctx, getState()); enterRule(_localctx, 50, RULE_load); - int _la; try { enterOuterAlt(_localctx, 1); { @@ -2310,20 +2306,6 @@ public final LoadContext load() throws RecognitionException { numType(); setState(380); match(LOAD); - setState(384); - _errHandler.sync(this); - _la = _input.LA(1); - if (_la==MEM_SIZE) { - { - setState(381); - match(MEM_SIZE); - setState(382); - match(UNDERSCORE); - setState(383); - match(SIGN_POSTFIX); - } - } - } } catch (RecognitionException re) { @@ -2343,7 +2325,6 @@ public NumTypeContext numType() { return getRuleContext(NumTypeContext.class,0); } public TerminalNode STORE() { return getToken(WatParser.STORE, 0); } - public TerminalNode MEM_SIZE() { return getToken(WatParser.MEM_SIZE, 0); } public StoreContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2366,24 +2347,13 @@ public T accept(ParseTreeVisitor visitor) { public final StoreContext store() throws RecognitionException { StoreContext _localctx = new StoreContext(_ctx, getState()); enterRule(_localctx, 52, RULE_store); - int _la; try { enterOuterAlt(_localctx, 1); { - setState(386); + setState(382); numType(); - setState(387); + setState(383); match(STORE); - setState(389); - _errHandler.sync(this); - _la = _input.LA(1); - if (_la==MEM_SIZE) { - { - setState(388); - match(MEM_SIZE); - } - } - } } catch (RecognitionException re) { @@ -2425,7 +2395,7 @@ public final SelectInstrContext selectInstr() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(391); + setState(385); match(SELECT); } } @@ -2474,44 +2444,44 @@ public final CallIndirectInstrContext callIndirectInstr() throws RecognitionExce enterRule(_localctx, 56, RULE_callIndirectInstr); int _la; try { - setState(403); + setState(397); _errHandler.sync(this); switch (_input.LA(1)) { case CALL_INDIRECT: enterOuterAlt(_localctx, 1); { - setState(393); + setState(387); match(CALL_INDIRECT); - setState(395); + setState(389); _errHandler.sync(this); _la = _input.LA(1); if (_la==NAT || _la==VAR) { { - setState(394); + setState(388); idx(); } } - setState(397); + setState(391); typeUse(); } break; case RETURN_CALL_INDIRECT: enterOuterAlt(_localctx, 2); { - setState(398); + setState(392); match(RETURN_CALL_INDIRECT); - setState(400); + setState(394); _errHandler.sync(this); _la = _input.LA(1); if (_la==NAT || _la==VAR) { { - setState(399); + setState(393); idx(); } } - setState(402); + setState(396); typeUse(); } break; @@ -2581,69 +2551,69 @@ public final CallInstrParamsContext callInstrParams() throws RecognitionExceptio int _alt; enterOuterAlt(_localctx, 1); { - setState(416); + setState(410); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,26,_ctx); + _alt = getInterpreter().adaptivePredict(_input,24,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(405); + setState(399); match(LPAR); - setState(406); + setState(400); match(PARAM); - setState(410); + setState(404); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 3202L) != 0) || _la==V128) { { { - setState(407); + setState(401); valType(); } } - setState(412); + setState(406); _errHandler.sync(this); _la = _input.LA(1); } - setState(413); + setState(407); match(RPAR); } } } - setState(418); + setState(412); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,26,_ctx); + _alt = getInterpreter().adaptivePredict(_input,24,_ctx); } - setState(430); + setState(424); _errHandler.sync(this); _la = _input.LA(1); while (_la==LPAR) { { { - setState(419); + setState(413); match(LPAR); - setState(420); + setState(414); match(RESULT); - setState(424); + setState(418); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 3202L) != 0) || _la==V128) { { { - setState(421); + setState(415); valType(); } } - setState(426); + setState(420); _errHandler.sync(this); _la = _input.LA(1); } - setState(427); + setState(421); match(RPAR); } } - setState(432); + setState(426); _errHandler.sync(this); _la = _input.LA(1); } @@ -2710,41 +2680,41 @@ public final CallInstrParamsInstrContext callInstrParamsInstr() throws Recogniti int _alt; enterOuterAlt(_localctx, 1); { - setState(444); + setState(438); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,30,_ctx); + _alt = getInterpreter().adaptivePredict(_input,28,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(433); + setState(427); match(LPAR); - setState(434); + setState(428); match(PARAM); - setState(438); + setState(432); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 3202L) != 0) || _la==V128) { { { - setState(435); + setState(429); valType(); } } - setState(440); + setState(434); _errHandler.sync(this); _la = _input.LA(1); } - setState(441); + setState(435); match(RPAR); } } } - setState(446); + setState(440); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,30,_ctx); + _alt = getInterpreter().adaptivePredict(_input,28,_ctx); } - setState(447); + setState(441); callInstrResultsInstr(); } } @@ -2809,41 +2779,41 @@ public final CallInstrResultsInstrContext callInstrResultsInstr() throws Recogni int _alt; enterOuterAlt(_localctx, 1); { - setState(460); + setState(454); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,32,_ctx); + _alt = getInterpreter().adaptivePredict(_input,30,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(449); + setState(443); match(LPAR); - setState(450); + setState(444); match(RESULT); - setState(454); + setState(448); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 3202L) != 0) || _la==V128) { { { - setState(451); + setState(445); valType(); } } - setState(456); + setState(450); _errHandler.sync(this); _la = _input.LA(1); } - setState(457); + setState(451); match(RPAR); } } } - setState(462); + setState(456); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,32,_ctx); + _alt = getInterpreter().adaptivePredict(_input,30,_ctx); } - setState(463); + setState(457); instr(); } } @@ -2906,34 +2876,34 @@ public final BlockInstrContext blockInstr() throws RecognitionException { enterRule(_localctx, 64, RULE_blockInstr); int _la; try { - setState(505); + setState(499); _errHandler.sync(this); switch (_input.LA(1)) { case BLOCK: enterOuterAlt(_localctx, 1); { - setState(465); + setState(459); match(BLOCK); - setState(467); + setState(461); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(466); + setState(460); bindVar(); } } - setState(469); + setState(463); block(); - setState(470); + setState(464); match(END); - setState(472); + setState(466); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(471); + setState(465); bindVar(); } } @@ -2943,28 +2913,28 @@ public final BlockInstrContext blockInstr() throws RecognitionException { case LOOP: enterOuterAlt(_localctx, 2); { - setState(474); + setState(468); match(LOOP); - setState(476); + setState(470); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(475); + setState(469); bindVar(); } } - setState(478); + setState(472); block(); - setState(479); + setState(473); match(END); - setState(481); + setState(475); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(480); + setState(474); bindVar(); } } @@ -2974,50 +2944,50 @@ public final BlockInstrContext blockInstr() throws RecognitionException { case IF: enterOuterAlt(_localctx, 3); { - setState(483); + setState(477); match(IF); - setState(485); + setState(479); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(484); + setState(478); bindVar(); } } - setState(487); + setState(481); block(); - setState(493); + setState(487); _errHandler.sync(this); _la = _input.LA(1); if (_la==ELSE) { { - setState(488); + setState(482); match(ELSE); - setState(490); + setState(484); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(489); + setState(483); bindVar(); } } - setState(492); + setState(486); instrList(); } } - setState(495); + setState(489); match(END); - setState(497); + setState(491); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(496); + setState(490); bindVar(); } } @@ -3027,15 +2997,15 @@ public final BlockInstrContext blockInstr() throws RecognitionException { case TRY: enterOuterAlt(_localctx, 4); { - setState(499); + setState(493); match(TRY); - setState(500); + setState(494); block(); - setState(501); + setState(495); match(CATCH); - setState(502); + setState(496); block(); - setState(503); + setState(497); match(END); } break; @@ -3091,24 +3061,24 @@ public final BlockTypeContext blockType() throws RecognitionException { BlockTypeContext _localctx = new BlockTypeContext(_ctx, getState()); enterRule(_localctx, 66, RULE_blockType); try { - setState(518); + setState(512); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,43,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,41,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(512); + setState(506); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,42,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) { case 1: { - setState(507); + setState(501); match(LPAR); - setState(508); + setState(502); match(RESULT); - setState(509); + setState(503); valType(); - setState(510); + setState(504); match(RPAR); } break; @@ -3118,16 +3088,16 @@ public final BlockTypeContext blockType() throws RecognitionException { case 2: enterOuterAlt(_localctx, 2); { - setState(514); + setState(508); typeUse(); - setState(515); + setState(509); funcType(); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(517); + setState(511); funcType(); } break; @@ -3177,9 +3147,9 @@ public final BlockContext block() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(520); + setState(514); blockType(); - setState(521); + setState(515); instrList(); } } @@ -3226,11 +3196,11 @@ public final FoldedInstrContext foldedInstr() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(523); + setState(517); match(LPAR); - setState(524); + setState(518); expr(); - setState(525); + setState(519); match(RPAR); } } @@ -3317,139 +3287,139 @@ public final ExprContext expr() throws RecognitionException { int _la; try { int _alt; - setState(569); + setState(563); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,50,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,48,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(527); + setState(521); plainInstr(); - setState(531); + setState(525); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,44,_ctx); + _alt = getInterpreter().adaptivePredict(_input,42,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(528); + setState(522); expr(); } } } - setState(533); + setState(527); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,44,_ctx); + _alt = getInterpreter().adaptivePredict(_input,42,_ctx); } } break; case 2: enterOuterAlt(_localctx, 2); { - setState(534); + setState(528); match(CALL_INDIRECT); - setState(535); + setState(529); callExprType(); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(536); + setState(530); match(RETURN_CALL_INDIRECT); - setState(537); + setState(531); callExprType(); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(538); + setState(532); match(BLOCK); - setState(540); + setState(534); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(539); + setState(533); bindVar(); } } - setState(542); + setState(536); block(); } break; case 5: enterOuterAlt(_localctx, 5); { - setState(543); + setState(537); match(LOOP); - setState(545); + setState(539); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(544); + setState(538); bindVar(); } } - setState(547); + setState(541); block(); } break; case 6: enterOuterAlt(_localctx, 6); { - setState(548); + setState(542); match(IF); - setState(550); + setState(544); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(549); + setState(543); bindVar(); } } - setState(552); + setState(546); blockType(); - setState(556); + setState(550); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,48,_ctx); + _alt = getInterpreter().adaptivePredict(_input,46,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(553); + setState(547); foldedInstr(); } } } - setState(558); + setState(552); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,48,_ctx); + _alt = getInterpreter().adaptivePredict(_input,46,_ctx); } - setState(559); + setState(553); match(LPAR); - setState(560); + setState(554); match(THEN); - setState(561); + setState(555); instrList(); - setState(567); + setState(561); _errHandler.sync(this); _la = _input.LA(1); if (_la==LPAR) { { - setState(562); + setState(556); match(LPAR); - setState(563); + setState(557); match(ELSE); - setState(564); + setState(558); instrList(); - setState(565); + setState(559); match(RPAR); } } @@ -3502,17 +3472,17 @@ public final CallExprTypeContext callExprType() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(572); + setState(566); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,49,_ctx) ) { case 1: { - setState(571); + setState(565); typeUse(); } break; } - setState(574); + setState(568); callExprParams(); } } @@ -3577,41 +3547,41 @@ public final CallExprParamsContext callExprParams() throws RecognitionException int _alt; enterOuterAlt(_localctx, 1); { - setState(587); + setState(581); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,53,_ctx); + _alt = getInterpreter().adaptivePredict(_input,51,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(576); + setState(570); match(LPAR); - setState(577); + setState(571); match(PARAM); - setState(581); + setState(575); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 3202L) != 0) || _la==V128) { { { - setState(578); + setState(572); valType(); } } - setState(583); + setState(577); _errHandler.sync(this); _la = _input.LA(1); } - setState(584); + setState(578); match(RPAR); } } } - setState(589); + setState(583); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,53,_ctx); + _alt = getInterpreter().adaptivePredict(_input,51,_ctx); } - setState(590); + setState(584); callExprResults(); } } @@ -3679,53 +3649,53 @@ public final CallExprResultsContext callExprResults() throws RecognitionExceptio int _alt; enterOuterAlt(_localctx, 1); { - setState(603); + setState(597); _errHandler.sync(this); _la = _input.LA(1); while (_la==LPAR) { { { - setState(592); + setState(586); match(LPAR); - setState(593); + setState(587); match(RESULT); - setState(597); + setState(591); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 3202L) != 0) || _la==V128) { { { - setState(594); + setState(588); valType(); } } - setState(599); + setState(593); _errHandler.sync(this); _la = _input.LA(1); } - setState(600); + setState(594); match(RPAR); } } - setState(605); + setState(599); _errHandler.sync(this); _la = _input.LA(1); } - setState(609); + setState(603); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,56,_ctx); + _alt = getInterpreter().adaptivePredict(_input,54,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(606); + setState(600); expr(); } } } - setState(611); + setState(605); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,56,_ctx); + _alt = getInterpreter().adaptivePredict(_input,54,_ctx); } } } @@ -3777,28 +3747,28 @@ public final InstrListContext instrList() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(615); + setState(609); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,57,_ctx); + _alt = getInterpreter().adaptivePredict(_input,55,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(612); + setState(606); instr(); } } } - setState(617); + setState(611); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,57,_ctx); + _alt = getInterpreter().adaptivePredict(_input,55,_ctx); } - setState(619); + setState(613); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,58,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,56,_ctx) ) { case 1: { - setState(618); + setState(612); callIndirectInstr(); } break; @@ -3846,7 +3816,7 @@ public final ConstExprContext constExpr() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(621); + setState(615); instrList(); } } @@ -3898,23 +3868,23 @@ public final FunctionContext function() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(623); + setState(617); match(LPAR); - setState(624); + setState(618); match(FUNC); - setState(626); + setState(620); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(625); + setState(619); bindVar(); } } - setState(628); + setState(622); funcFields(); - setState(629); + setState(623); match(RPAR); } } @@ -3972,51 +3942,51 @@ public final FuncFieldsContext funcFields() throws RecognitionException { FuncFieldsContext _localctx = new FuncFieldsContext(_ctx, getState()); enterRule(_localctx, 86, RULE_funcFields); try { - setState(644); + setState(638); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,62,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,60,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(632); + setState(626); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,60,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,58,_ctx) ) { case 1: { - setState(631); + setState(625); typeUse(); } break; } - setState(634); + setState(628); funcFieldsBody(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(635); + setState(629); inlineImport(); - setState(637); + setState(631); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,61,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,59,_ctx) ) { case 1: { - setState(636); + setState(630); typeUse(); } break; } - setState(639); + setState(633); funcType(); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(641); + setState(635); inlineExport(); - setState(642); + setState(636); funcFields(); } break; @@ -4066,9 +4036,9 @@ public final FuncFieldsBodyContext funcFieldsBody() throws RecognitionException try { enterOuterAlt(_localctx, 1); { - setState(646); + setState(640); funcType(); - setState(647); + setState(641); funcBody(); } } @@ -4139,18 +4109,18 @@ public final FuncBodyContext funcBody() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(665); + setState(659); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,65,_ctx); + _alt = getInterpreter().adaptivePredict(_input,63,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(649); + setState(643); match(LPAR); - setState(650); + setState(644); match(LOCAL); - setState(660); + setState(654); _errHandler.sync(this); switch (_input.LA(1)) { case LPAR: @@ -4160,17 +4130,17 @@ public final FuncBodyContext funcBody() throws RecognitionException { case EXTERNREF: case V128: { - setState(654); + setState(648); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 3202L) != 0) || _la==V128) { { { - setState(651); + setState(645); valType(); } } - setState(656); + setState(650); _errHandler.sync(this); _la = _input.LA(1); } @@ -4178,25 +4148,25 @@ public final FuncBodyContext funcBody() throws RecognitionException { break; case VAR: { - setState(657); + setState(651); bindVar(); - setState(658); + setState(652); valType(); } break; default: throw new NoViableAltException(this); } - setState(662); + setState(656); match(RPAR); } } } - setState(667); + setState(661); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,65,_ctx); + _alt = getInterpreter().adaptivePredict(_input,63,_ctx); } - setState(668); + setState(662); instrList(); } } @@ -4245,19 +4215,19 @@ public final OffsetContext offset() throws RecognitionException { OffsetContext _localctx = new OffsetContext(_ctx, getState()); enterRule(_localctx, 92, RULE_offset); try { - setState(676); + setState(670); _errHandler.sync(this); switch (_input.LA(1)) { case LPAR: enterOuterAlt(_localctx, 1); { - setState(670); + setState(664); match(LPAR); - setState(671); + setState(665); match(OFFSET); - setState(672); + setState(666); constExpr(); - setState(673); + setState(667); match(RPAR); } break; @@ -4308,7 +4278,7 @@ public final OffsetContext offset() throws RecognitionException { case CONVERT: enterOuterAlt(_localctx, 2); { - setState(675); + setState(669); expr(); } break; @@ -4374,33 +4344,33 @@ public final ElemContext elem() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(678); + setState(672); match(LPAR); - setState(679); + setState(673); match(ELEM); - setState(680); + setState(674); match(LPAR); - setState(681); + setState(675); instr(); - setState(682); + setState(676); match(RPAR); - setState(683); + setState(677); match(FUNC); - setState(687); + setState(681); _errHandler.sync(this); _la = _input.LA(1); while (_la==NAT || _la==VAR) { { { - setState(684); + setState(678); idx(); } } - setState(689); + setState(683); _errHandler.sync(this); _la = _input.LA(1); } - setState(690); + setState(684); match(RPAR); } } @@ -4452,23 +4422,23 @@ public final TableContext table() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(692); + setState(686); match(LPAR); - setState(693); + setState(687); match(TABLE); - setState(695); + setState(689); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(694); + setState(688); bindVar(); } } - setState(697); + setState(691); tableField(); - setState(698); + setState(692); match(RPAR); } } @@ -4533,58 +4503,58 @@ public final TableFieldContext tableField() throws RecognitionException { enterRule(_localctx, 98, RULE_tableField); int _la; try { - setState(718); + setState(712); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,70,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,68,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(700); + setState(694); tableType(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(701); + setState(695); inlineImport(); - setState(702); + setState(696); tableType(); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(704); + setState(698); inlineExport(); - setState(705); + setState(699); tableField(); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(707); + setState(701); refType(); - setState(708); + setState(702); match(LPAR); - setState(709); + setState(703); match(ELEM); - setState(713); + setState(707); _errHandler.sync(this); _la = _input.LA(1); while (_la==NAT || _la==VAR) { { { - setState(710); + setState(704); idx(); } } - setState(715); + setState(709); _errHandler.sync(this); _la = _input.LA(1); } - setState(716); + setState(710); match(RPAR); } break; @@ -4649,84 +4619,84 @@ public final DataContext data() throws RecognitionException { enterRule(_localctx, 100, RULE_data); int _la; try { - setState(750); + setState(744); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,75,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,73,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(720); + setState(714); match(LPAR); - setState(721); + setState(715); match(DATA); - setState(723); + setState(717); _errHandler.sync(this); _la = _input.LA(1); if (_la==NAT || _la==VAR) { { - setState(722); + setState(716); idx(); } } - setState(725); + setState(719); match(LPAR); - setState(726); + setState(720); instr(); - setState(727); + setState(721); match(RPAR); - setState(731); + setState(725); _errHandler.sync(this); _la = _input.LA(1); while (_la==STRING_) { { { - setState(728); + setState(722); match(STRING_); } } - setState(733); + setState(727); _errHandler.sync(this); _la = _input.LA(1); } - setState(734); + setState(728); match(RPAR); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(736); + setState(730); match(LPAR); - setState(737); + setState(731); match(DATA); - setState(739); + setState(733); _errHandler.sync(this); _la = _input.LA(1); if (_la==NAT || _la==VAR) { { - setState(738); + setState(732); idx(); } } - setState(741); + setState(735); offset(); - setState(745); + setState(739); _errHandler.sync(this); _la = _input.LA(1); while (_la==STRING_) { { { - setState(742); + setState(736); match(STRING_); } } - setState(747); + setState(741); _errHandler.sync(this); _la = _input.LA(1); } - setState(748); + setState(742); match(RPAR); } break; @@ -4780,23 +4750,23 @@ public final MemoryContext memory() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(752); + setState(746); match(LPAR); - setState(753); + setState(747); match(MEMORY); - setState(755); + setState(749); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(754); + setState(748); bindVar(); } } - setState(757); + setState(751); memoryField(); - setState(758); + setState(752); match(RPAR); } } @@ -4856,56 +4826,56 @@ public final MemoryFieldContext memoryField() throws RecognitionException { enterRule(_localctx, 104, RULE_memoryField); int _la; try { - setState(776); + setState(770); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,78,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,76,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(760); + setState(754); memoryType(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(761); + setState(755); inlineImport(); - setState(762); + setState(756); memoryType(); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(764); + setState(758); inlineExport(); - setState(765); + setState(759); memoryField(); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(767); + setState(761); match(LPAR); - setState(768); + setState(762); match(DATA); - setState(772); + setState(766); _errHandler.sync(this); _la = _input.LA(1); while (_la==STRING_) { { { - setState(769); + setState(763); match(STRING_); } } - setState(774); + setState(768); _errHandler.sync(this); _la = _input.LA(1); } - setState(775); + setState(769); match(RPAR); } break; @@ -4959,23 +4929,23 @@ public final GlobalContext global() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(778); + setState(772); match(LPAR); - setState(779); + setState(773); match(GLOBAL); - setState(781); + setState(775); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(780); + setState(774); bindVar(); } } - setState(783); + setState(777); globalField(); - setState(784); + setState(778); match(RPAR); } } @@ -5030,33 +5000,33 @@ public final GlobalFieldContext globalField() throws RecognitionException { GlobalFieldContext _localctx = new GlobalFieldContext(_ctx, getState()); enterRule(_localctx, 108, RULE_globalField); try { - setState(795); + setState(789); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,80,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,78,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(786); + setState(780); globalType(); - setState(787); + setState(781); constExpr(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(789); + setState(783); inlineImport(); - setState(790); + setState(784); globalType(); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(792); + setState(786); inlineExport(); - setState(793); + setState(787); globalField(); } break; @@ -5123,121 +5093,121 @@ public final ImportDescContext importDesc() throws RecognitionException { enterRule(_localctx, 110, RULE_importDesc); int _la; try { - setState(837); + setState(831); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,86,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,84,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(797); + setState(791); match(LPAR); - setState(798); + setState(792); match(FUNC); - setState(800); + setState(794); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(799); + setState(793); bindVar(); } } - setState(802); + setState(796); typeUse(); - setState(803); + setState(797); match(RPAR); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(805); + setState(799); match(LPAR); - setState(806); + setState(800); match(FUNC); - setState(808); + setState(802); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(807); + setState(801); bindVar(); } } - setState(810); + setState(804); funcType(); - setState(811); + setState(805); match(RPAR); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(813); + setState(807); match(LPAR); - setState(814); + setState(808); match(TABLE); - setState(816); + setState(810); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(815); + setState(809); bindVar(); } } - setState(818); + setState(812); tableType(); - setState(819); + setState(813); match(RPAR); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(821); + setState(815); match(LPAR); - setState(822); + setState(816); match(MEMORY); - setState(824); + setState(818); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(823); + setState(817); bindVar(); } } - setState(826); + setState(820); memoryType(); - setState(827); + setState(821); match(RPAR); } break; case 5: enterOuterAlt(_localctx, 5); { - setState(829); + setState(823); match(LPAR); - setState(830); + setState(824); match(GLOBAL); - setState(832); + setState(826); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(831); + setState(825); bindVar(); } } - setState(834); + setState(828); globalType(); - setState(835); + setState(829); match(RPAR); } break; @@ -5293,17 +5263,17 @@ public final SimportContext simport() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(839); + setState(833); match(LPAR); - setState(840); + setState(834); match(IMPORT); - setState(841); + setState(835); name(); - setState(842); + setState(836); name(); - setState(843); + setState(837); importDesc(); - setState(844); + setState(838); match(RPAR); } } @@ -5354,15 +5324,15 @@ public final InlineImportContext inlineImport() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(846); + setState(840); match(LPAR); - setState(847); + setState(841); match(IMPORT); - setState(848); + setState(842); name(); - setState(849); + setState(843); name(); - setState(850); + setState(844); match(RPAR); } } @@ -5411,58 +5381,58 @@ public final ExportDescContext exportDesc() throws RecognitionException { ExportDescContext _localctx = new ExportDescContext(_ctx, getState()); enterRule(_localctx, 116, RULE_exportDesc); try { - setState(872); + setState(866); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,87,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,85,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(852); + setState(846); match(LPAR); - setState(853); + setState(847); match(FUNC); - setState(854); + setState(848); idx(); - setState(855); + setState(849); match(RPAR); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(857); + setState(851); match(LPAR); - setState(858); + setState(852); match(TABLE); - setState(859); + setState(853); idx(); - setState(860); + setState(854); match(RPAR); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(862); + setState(856); match(LPAR); - setState(863); + setState(857); match(MEMORY); - setState(864); + setState(858); idx(); - setState(865); + setState(859); match(RPAR); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(867); + setState(861); match(LPAR); - setState(868); + setState(862); match(GLOBAL); - setState(869); + setState(863); idx(); - setState(870); + setState(864); match(RPAR); } break; @@ -5515,15 +5485,15 @@ public final Export_Context export_() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(874); + setState(868); match(LPAR); - setState(875); + setState(869); match(EXPORT); - setState(876); + setState(870); name(); - setState(877); + setState(871); exportDesc(); - setState(878); + setState(872); match(RPAR); } } @@ -5571,13 +5541,13 @@ public final InlineExportContext inlineExport() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(880); + setState(874); match(LPAR); - setState(881); + setState(875); match(EXPORT); - setState(882); + setState(876); name(); - setState(883); + setState(877); match(RPAR); } } @@ -5632,25 +5602,25 @@ public final TagContext tag() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(885); + setState(879); match(LPAR); - setState(886); + setState(880); match(TAG); - setState(888); + setState(882); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(887); + setState(881); bindVar(); } } - setState(890); + setState(884); typeUse(); - setState(891); + setState(885); funcType(); - setState(892); + setState(886); match(RPAR); } } @@ -5702,23 +5672,23 @@ public final TypeDefContext typeDef() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(894); + setState(888); match(LPAR); - setState(895); + setState(889); match(TYPE); - setState(897); + setState(891); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(896); + setState(890); bindVar(); } } - setState(899); + setState(893); defType(); - setState(900); + setState(894); match(RPAR); } } @@ -5766,13 +5736,13 @@ public final Start_Context start_() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(902); + setState(896); match(LPAR); - setState(903); + setState(897); match(START_); - setState(904); + setState(898); idx(); - setState(905); + setState(899); match(RPAR); } } @@ -5845,83 +5815,83 @@ public final ModuleFieldContext moduleField() throws RecognitionException { ModuleFieldContext _localctx = new ModuleFieldContext(_ctx, getState()); enterRule(_localctx, 128, RULE_moduleField); try { - setState(918); + setState(912); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,90,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,88,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(907); + setState(901); typeDef(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(908); + setState(902); global(); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(909); + setState(903); table(); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(910); + setState(904); memory(); } break; case 5: enterOuterAlt(_localctx, 5); { - setState(911); + setState(905); function(); } break; case 6: enterOuterAlt(_localctx, 6); { - setState(912); + setState(906); elem(); } break; case 7: enterOuterAlt(_localctx, 7); { - setState(913); + setState(907); data(); } break; case 8: enterOuterAlt(_localctx, 8); { - setState(914); + setState(908); start_(); } break; case 9: enterOuterAlt(_localctx, 9); { - setState(915); + setState(909); simport(); } break; case 10: enterOuterAlt(_localctx, 10); { - setState(916); + setState(910); export_(); } break; case 11: enterOuterAlt(_localctx, 11); { - setState(917); + setState(911); tag(); } break; @@ -5976,35 +5946,35 @@ public final Module_Context module_() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(920); + setState(914); match(LPAR); - setState(921); + setState(915); match(MODULE); - setState(923); + setState(917); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(922); + setState(916); match(VAR); } } - setState(928); + setState(922); _errHandler.sync(this); _la = _input.LA(1); while (_la==LPAR) { { { - setState(925); + setState(919); moduleField(); } } - setState(930); + setState(924); _errHandler.sync(this); _la = _input.LA(1); } - setState(931); + setState(925); match(RPAR); } } @@ -6059,34 +6029,34 @@ public final ScriptModuleContext scriptModule() throws RecognitionException { enterRule(_localctx, 132, RULE_scriptModule); int _la; try { - setState(961); + setState(955); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,97,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,95,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(933); + setState(927); module_(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(934); + setState(928); match(LPAR); - setState(935); + setState(929); match(MODULE); - setState(937); + setState(931); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(936); + setState(930); match(VAR); } } - setState(939); + setState(933); _la = _input.LA(1); if ( !(_la==BIN || _la==QUOTE) ) { _errHandler.recoverInline(this); @@ -6096,60 +6066,60 @@ public final ScriptModuleContext scriptModule() throws RecognitionException { _errHandler.reportMatch(this); consume(); } - setState(943); + setState(937); _errHandler.sync(this); _la = _input.LA(1); while (_la==STRING_) { { { - setState(940); + setState(934); match(STRING_); } } - setState(945); + setState(939); _errHandler.sync(this); _la = _input.LA(1); } - setState(946); + setState(940); match(RPAR); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(947); + setState(941); match(LPAR); - setState(948); + setState(942); match(MODULE); - setState(949); + setState(943); match(DEFINITION); - setState(951); + setState(945); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(950); + setState(944); match(VAR); } } - setState(953); + setState(947); match(BIN); - setState(957); + setState(951); _errHandler.sync(this); _la = _input.LA(1); while (_la==STRING_) { { { - setState(954); + setState(948); match(STRING_); } } - setState(959); + setState(953); _errHandler.sync(this); _la = _input.LA(1); } - setState(960); + setState(954); match(RPAR); } break; @@ -6203,54 +6173,54 @@ public final Action_Context action_() throws RecognitionException { enterRule(_localctx, 134, RULE_action_); int _la; try { - setState(980); + setState(974); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,100,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,98,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(963); + setState(957); match(LPAR); - setState(964); + setState(958); match(INVOKE); - setState(966); + setState(960); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(965); + setState(959); match(VAR); } } - setState(968); + setState(962); name(); - setState(969); + setState(963); constList(); - setState(970); + setState(964); match(RPAR); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(972); + setState(966); match(LPAR); - setState(973); + setState(967); match(GET); - setState(975); + setState(969); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(974); + setState(968); match(VAR); } } - setState(977); + setState(971); name(); - setState(978); + setState(972); match(RPAR); } break; @@ -6312,137 +6282,137 @@ public final AssertionContext assertion() throws RecognitionException { AssertionContext _localctx = new AssertionContext(_ctx, getState()); enterRule(_localctx, 136, RULE_assertion); try { - setState(1034); + setState(1028); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,101,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,99,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(982); + setState(976); match(LPAR); - setState(983); + setState(977); match(ASSERT_MALFORMED); - setState(984); + setState(978); scriptModule(); - setState(985); + setState(979); match(STRING_); - setState(986); + setState(980); match(RPAR); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(988); + setState(982); match(LPAR); - setState(989); + setState(983); match(ASSERT_INVALID); - setState(990); + setState(984); scriptModule(); - setState(991); + setState(985); match(STRING_); - setState(992); + setState(986); match(RPAR); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(994); + setState(988); match(LPAR); - setState(995); + setState(989); match(ASSERT_UNLINKABLE); - setState(996); + setState(990); scriptModule(); - setState(997); + setState(991); match(STRING_); - setState(998); + setState(992); match(RPAR); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(1000); + setState(994); match(LPAR); - setState(1001); + setState(995); match(ASSERT_TRAP); - setState(1002); + setState(996); scriptModule(); - setState(1003); + setState(997); match(STRING_); - setState(1004); + setState(998); match(RPAR); } break; case 5: enterOuterAlt(_localctx, 5); { - setState(1006); + setState(1000); match(LPAR); - setState(1007); + setState(1001); match(ASSERT_RETURN); - setState(1008); + setState(1002); action_(); - setState(1009); + setState(1003); constList(); - setState(1010); + setState(1004); match(RPAR); } break; case 6: enterOuterAlt(_localctx, 6); { - setState(1012); + setState(1006); match(LPAR); - setState(1013); + setState(1007); match(ASSERT_RETURN_CANONICAL_NAN); - setState(1014); + setState(1008); action_(); - setState(1015); + setState(1009); match(RPAR); } break; case 7: enterOuterAlt(_localctx, 7); { - setState(1017); + setState(1011); match(LPAR); - setState(1018); + setState(1012); match(ASSERT_RETURN_ARITHMETIC_NAN); - setState(1019); + setState(1013); action_(); - setState(1020); + setState(1014); match(RPAR); } break; case 8: enterOuterAlt(_localctx, 8); { - setState(1022); + setState(1016); match(LPAR); - setState(1023); + setState(1017); match(ASSERT_TRAP); - setState(1024); + setState(1018); action_(); - setState(1025); + setState(1019); match(STRING_); - setState(1026); + setState(1020); match(RPAR); } break; case 9: enterOuterAlt(_localctx, 9); { - setState(1028); + setState(1022); match(LPAR); - setState(1029); + setState(1023); match(ASSERT_EXHAUSTION); - setState(1030); + setState(1024); action_(); - setState(1031); + setState(1025); match(STRING_); - setState(1032); + setState(1026); match(RPAR); } break; @@ -6507,64 +6477,64 @@ public final CmdContext cmd() throws RecognitionException { enterRule(_localctx, 138, RULE_cmd); int _la; try { - setState(1049); + setState(1043); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,103,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,101,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(1036); + setState(1030); action_(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(1037); + setState(1031); assertion(); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(1038); + setState(1032); scriptModule(); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(1039); + setState(1033); match(LPAR); - setState(1040); + setState(1034); match(REGISTER); - setState(1041); + setState(1035); name(); - setState(1043); + setState(1037); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(1042); + setState(1036); match(VAR); } } - setState(1045); + setState(1039); match(RPAR); } break; case 5: enterOuterAlt(_localctx, 5); { - setState(1047); + setState(1041); meta(); } break; case 6: enterOuterAlt(_localctx, 6); { - setState(1048); + setState(1042); instance(); } break; @@ -6617,33 +6587,33 @@ public final InstanceContext instance() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(1051); + setState(1045); match(LPAR); - setState(1052); + setState(1046); match(MODULE); - setState(1053); + setState(1047); match(INSTANCE); - setState(1055); + setState(1049); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,104,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,102,_ctx) ) { case 1: { - setState(1054); + setState(1048); match(VAR); } break; } - setState(1058); + setState(1052); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(1057); + setState(1051); match(VAR); } } - setState(1060); + setState(1054); match(RPAR); } } @@ -6697,108 +6667,108 @@ public final MetaContext meta() throws RecognitionException { enterRule(_localctx, 142, RULE_meta); int _la; try { - setState(1094); + setState(1088); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,111,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,109,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(1062); + setState(1056); match(LPAR); - setState(1063); + setState(1057); match(SCRIPT); - setState(1065); + setState(1059); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(1064); + setState(1058); match(VAR); } } - setState(1070); + setState(1064); _errHandler.sync(this); _la = _input.LA(1); while (_la==LPAR) { { { - setState(1067); + setState(1061); cmd(); } } - setState(1072); + setState(1066); _errHandler.sync(this); _la = _input.LA(1); } - setState(1073); + setState(1067); match(RPAR); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(1074); + setState(1068); match(LPAR); - setState(1075); + setState(1069); match(INPUT); - setState(1077); + setState(1071); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(1076); + setState(1070); match(VAR); } } - setState(1079); + setState(1073); match(STRING_); - setState(1080); + setState(1074); match(RPAR); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(1081); + setState(1075); match(LPAR); - setState(1082); + setState(1076); match(OUTPUT); - setState(1084); + setState(1078); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(1083); + setState(1077); match(VAR); } } - setState(1086); + setState(1080); match(STRING_); - setState(1087); + setState(1081); match(RPAR); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(1088); + setState(1082); match(LPAR); - setState(1089); + setState(1083); match(OUTPUT); - setState(1091); + setState(1085); _errHandler.sync(this); _la = _input.LA(1); if (_la==VAR) { { - setState(1090); + setState(1084); match(VAR); } } - setState(1093); + setState(1087); match(RPAR); } break; @@ -6848,13 +6818,13 @@ public final WconstContext wconst() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(1096); + setState(1090); match(LPAR); - setState(1097); + setState(1091); match(CONST); - setState(1098); + setState(1092); literal(); - setState(1099); + setState(1093); match(RPAR); } } @@ -6903,17 +6873,17 @@ public final ConstListContext constList() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(1104); + setState(1098); _errHandler.sync(this); _la = _input.LA(1); while (_la==LPAR) { { { - setState(1101); + setState(1095); wconst(); } } - setState(1106); + setState(1100); _errHandler.sync(this); _la = _input.LA(1); } @@ -6969,48 +6939,48 @@ public final ScriptContext script() throws RecognitionException { enterRule(_localctx, 148, RULE_script); int _la; try { - setState(1121); + setState(1115); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,115,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,113,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(1110); + setState(1104); _errHandler.sync(this); _la = _input.LA(1); while (_la==LPAR) { { { - setState(1107); + setState(1101); cmd(); } } - setState(1112); + setState(1106); _errHandler.sync(this); _la = _input.LA(1); } - setState(1113); + setState(1107); match(EOF); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(1115); + setState(1109); _errHandler.sync(this); _la = _input.LA(1); do { { { - setState(1114); + setState(1108); moduleField(); } } - setState(1117); + setState(1111); _errHandler.sync(this); _la = _input.LA(1); } while ( _la==LPAR ); - setState(1119); + setState(1113); match(EOF); } break; @@ -7063,36 +7033,36 @@ public final ModuleContext module() throws RecognitionException { enterRule(_localctx, 150, RULE_module); int _la; try { - setState(1133); + setState(1127); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,117,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,115,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(1123); + setState(1117); module_(); - setState(1124); + setState(1118); match(EOF); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(1129); + setState(1123); _errHandler.sync(this); _la = _input.LA(1); while (_la==LPAR) { { { - setState(1126); + setState(1120); moduleField(); } } - setState(1131); + setState(1125); _errHandler.sync(this); _la = _input.LA(1); } - setState(1132); + setState(1126); match(EOF); } break; @@ -7110,7 +7080,7 @@ public final ModuleContext module() throws RecognitionException { } public static final String _serializedATN = - "\u0004\u0001\u00ab\u0470\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001"+ + "\u0004\u0001\u00ab\u046a\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001"+ "\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004"+ "\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007"+ "\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b\u0007\u000b"+ @@ -7164,92 +7134,91 @@ public final ModuleContext module() throws RecognitionException { "\u0015\u0001\u0015\u0001\u0015\u0005\u0015\u016b\b\u0015\n\u0015\f\u0015"+ "\u016e\t\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016"+ "\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018"+ - "\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019"+ - "\u0003\u0019\u0181\b\u0019\u0001\u001a\u0001\u001a\u0001\u001a\u0003\u001a"+ - "\u0186\b\u001a\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0003\u001c"+ - "\u018c\b\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0003\u001c\u0191\b"+ - "\u001c\u0001\u001c\u0003\u001c\u0194\b\u001c\u0001\u001d\u0001\u001d\u0001"+ - "\u001d\u0005\u001d\u0199\b\u001d\n\u001d\f\u001d\u019c\t\u001d\u0001\u001d"+ - "\u0005\u001d\u019f\b\u001d\n\u001d\f\u001d\u01a2\t\u001d\u0001\u001d\u0001"+ - "\u001d\u0001\u001d\u0005\u001d\u01a7\b\u001d\n\u001d\f\u001d\u01aa\t\u001d"+ - "\u0001\u001d\u0005\u001d\u01ad\b\u001d\n\u001d\f\u001d\u01b0\t\u001d\u0001"+ - "\u001e\u0001\u001e\u0001\u001e\u0005\u001e\u01b5\b\u001e\n\u001e\f\u001e"+ - "\u01b8\t\u001e\u0001\u001e\u0005\u001e\u01bb\b\u001e\n\u001e\f\u001e\u01be"+ + "\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a"+ + "\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0003\u001c"+ + "\u0186\b\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0003\u001c\u018b\b"+ + "\u001c\u0001\u001c\u0003\u001c\u018e\b\u001c\u0001\u001d\u0001\u001d\u0001"+ + "\u001d\u0005\u001d\u0193\b\u001d\n\u001d\f\u001d\u0196\t\u001d\u0001\u001d"+ + "\u0005\u001d\u0199\b\u001d\n\u001d\f\u001d\u019c\t\u001d\u0001\u001d\u0001"+ + "\u001d\u0001\u001d\u0005\u001d\u01a1\b\u001d\n\u001d\f\u001d\u01a4\t\u001d"+ + "\u0001\u001d\u0005\u001d\u01a7\b\u001d\n\u001d\f\u001d\u01aa\t\u001d\u0001"+ + "\u001e\u0001\u001e\u0001\u001e\u0005\u001e\u01af\b\u001e\n\u001e\f\u001e"+ + "\u01b2\t\u001e\u0001\u001e\u0005\u001e\u01b5\b\u001e\n\u001e\f\u001e\u01b8"+ "\t\u001e\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0001\u001f\u0005"+ - "\u001f\u01c5\b\u001f\n\u001f\f\u001f\u01c8\t\u001f\u0001\u001f\u0005\u001f"+ - "\u01cb\b\u001f\n\u001f\f\u001f\u01ce\t\u001f\u0001\u001f\u0001\u001f\u0001"+ - " \u0001 \u0003 \u01d4\b \u0001 \u0001 \u0001 \u0003 \u01d9\b \u0001 \u0001"+ - " \u0003 \u01dd\b \u0001 \u0001 \u0001 \u0003 \u01e2\b \u0001 \u0001 \u0003"+ - " \u01e6\b \u0001 \u0001 \u0001 \u0003 \u01eb\b \u0001 \u0003 \u01ee\b"+ - " \u0001 \u0001 \u0003 \u01f2\b \u0001 \u0001 \u0001 \u0001 \u0001 \u0001"+ - " \u0003 \u01fa\b \u0001!\u0001!\u0001!\u0001!\u0001!\u0003!\u0201\b!\u0001"+ - "!\u0001!\u0001!\u0001!\u0003!\u0207\b!\u0001\"\u0001\"\u0001\"\u0001#"+ - "\u0001#\u0001#\u0001#\u0001$\u0001$\u0005$\u0212\b$\n$\f$\u0215\t$\u0001"+ - "$\u0001$\u0001$\u0001$\u0001$\u0001$\u0003$\u021d\b$\u0001$\u0001$\u0001"+ - "$\u0003$\u0222\b$\u0001$\u0001$\u0001$\u0003$\u0227\b$\u0001$\u0001$\u0005"+ - "$\u022b\b$\n$\f$\u022e\t$\u0001$\u0001$\u0001$\u0001$\u0001$\u0001$\u0001"+ - "$\u0001$\u0003$\u0238\b$\u0003$\u023a\b$\u0001%\u0003%\u023d\b%\u0001"+ - "%\u0001%\u0001&\u0001&\u0001&\u0005&\u0244\b&\n&\f&\u0247\t&\u0001&\u0005"+ - "&\u024a\b&\n&\f&\u024d\t&\u0001&\u0001&\u0001\'\u0001\'\u0001\'\u0005"+ - "\'\u0254\b\'\n\'\f\'\u0257\t\'\u0001\'\u0005\'\u025a\b\'\n\'\f\'\u025d"+ - "\t\'\u0001\'\u0005\'\u0260\b\'\n\'\f\'\u0263\t\'\u0001(\u0005(\u0266\b"+ - "(\n(\f(\u0269\t(\u0001(\u0003(\u026c\b(\u0001)\u0001)\u0001*\u0001*\u0001"+ - "*\u0003*\u0273\b*\u0001*\u0001*\u0001*\u0001+\u0003+\u0279\b+\u0001+\u0001"+ - "+\u0001+\u0003+\u027e\b+\u0001+\u0001+\u0001+\u0001+\u0001+\u0003+\u0285"+ - "\b+\u0001,\u0001,\u0001,\u0001-\u0001-\u0001-\u0005-\u028d\b-\n-\f-\u0290"+ - "\t-\u0001-\u0001-\u0001-\u0003-\u0295\b-\u0001-\u0005-\u0298\b-\n-\f-"+ - "\u029b\t-\u0001-\u0001-\u0001.\u0001.\u0001.\u0001.\u0001.\u0001.\u0003"+ - ".\u02a5\b.\u0001/\u0001/\u0001/\u0001/\u0001/\u0001/\u0001/\u0005/\u02ae"+ - "\b/\n/\f/\u02b1\t/\u0001/\u0001/\u00010\u00010\u00010\u00030\u02b8\b0"+ + "\u001f\u01bf\b\u001f\n\u001f\f\u001f\u01c2\t\u001f\u0001\u001f\u0005\u001f"+ + "\u01c5\b\u001f\n\u001f\f\u001f\u01c8\t\u001f\u0001\u001f\u0001\u001f\u0001"+ + " \u0001 \u0003 \u01ce\b \u0001 \u0001 \u0001 \u0003 \u01d3\b \u0001 \u0001"+ + " \u0003 \u01d7\b \u0001 \u0001 \u0001 \u0003 \u01dc\b \u0001 \u0001 \u0003"+ + " \u01e0\b \u0001 \u0001 \u0001 \u0003 \u01e5\b \u0001 \u0003 \u01e8\b"+ + " \u0001 \u0001 \u0003 \u01ec\b \u0001 \u0001 \u0001 \u0001 \u0001 \u0001"+ + " \u0003 \u01f4\b \u0001!\u0001!\u0001!\u0001!\u0001!\u0003!\u01fb\b!\u0001"+ + "!\u0001!\u0001!\u0001!\u0003!\u0201\b!\u0001\"\u0001\"\u0001\"\u0001#"+ + "\u0001#\u0001#\u0001#\u0001$\u0001$\u0005$\u020c\b$\n$\f$\u020f\t$\u0001"+ + "$\u0001$\u0001$\u0001$\u0001$\u0001$\u0003$\u0217\b$\u0001$\u0001$\u0001"+ + "$\u0003$\u021c\b$\u0001$\u0001$\u0001$\u0003$\u0221\b$\u0001$\u0001$\u0005"+ + "$\u0225\b$\n$\f$\u0228\t$\u0001$\u0001$\u0001$\u0001$\u0001$\u0001$\u0001"+ + "$\u0001$\u0003$\u0232\b$\u0003$\u0234\b$\u0001%\u0003%\u0237\b%\u0001"+ + "%\u0001%\u0001&\u0001&\u0001&\u0005&\u023e\b&\n&\f&\u0241\t&\u0001&\u0005"+ + "&\u0244\b&\n&\f&\u0247\t&\u0001&\u0001&\u0001\'\u0001\'\u0001\'\u0005"+ + "\'\u024e\b\'\n\'\f\'\u0251\t\'\u0001\'\u0005\'\u0254\b\'\n\'\f\'\u0257"+ + "\t\'\u0001\'\u0005\'\u025a\b\'\n\'\f\'\u025d\t\'\u0001(\u0005(\u0260\b"+ + "(\n(\f(\u0263\t(\u0001(\u0003(\u0266\b(\u0001)\u0001)\u0001*\u0001*\u0001"+ + "*\u0003*\u026d\b*\u0001*\u0001*\u0001*\u0001+\u0003+\u0273\b+\u0001+\u0001"+ + "+\u0001+\u0003+\u0278\b+\u0001+\u0001+\u0001+\u0001+\u0001+\u0003+\u027f"+ + "\b+\u0001,\u0001,\u0001,\u0001-\u0001-\u0001-\u0005-\u0287\b-\n-\f-\u028a"+ + "\t-\u0001-\u0001-\u0001-\u0003-\u028f\b-\u0001-\u0005-\u0292\b-\n-\f-"+ + "\u0295\t-\u0001-\u0001-\u0001.\u0001.\u0001.\u0001.\u0001.\u0001.\u0003"+ + ".\u029f\b.\u0001/\u0001/\u0001/\u0001/\u0001/\u0001/\u0001/\u0005/\u02a8"+ + "\b/\n/\f/\u02ab\t/\u0001/\u0001/\u00010\u00010\u00010\u00030\u02b2\b0"+ "\u00010\u00010\u00010\u00011\u00011\u00011\u00011\u00011\u00011\u0001"+ - "1\u00011\u00011\u00011\u00011\u00051\u02c8\b1\n1\f1\u02cb\t1\u00011\u0001"+ - "1\u00031\u02cf\b1\u00012\u00012\u00012\u00032\u02d4\b2\u00012\u00012\u0001"+ - "2\u00012\u00052\u02da\b2\n2\f2\u02dd\t2\u00012\u00012\u00012\u00012\u0001"+ - "2\u00032\u02e4\b2\u00012\u00012\u00052\u02e8\b2\n2\f2\u02eb\t2\u00012"+ - "\u00012\u00032\u02ef\b2\u00013\u00013\u00013\u00033\u02f4\b3\u00013\u0001"+ + "1\u00011\u00011\u00011\u00011\u00051\u02c2\b1\n1\f1\u02c5\t1\u00011\u0001"+ + "1\u00031\u02c9\b1\u00012\u00012\u00012\u00032\u02ce\b2\u00012\u00012\u0001"+ + "2\u00012\u00052\u02d4\b2\n2\f2\u02d7\t2\u00012\u00012\u00012\u00012\u0001"+ + "2\u00032\u02de\b2\u00012\u00012\u00052\u02e2\b2\n2\f2\u02e5\t2\u00012"+ + "\u00012\u00032\u02e9\b2\u00013\u00013\u00013\u00033\u02ee\b3\u00013\u0001"+ "3\u00013\u00014\u00014\u00014\u00014\u00014\u00014\u00014\u00014\u0001"+ - "4\u00014\u00054\u0303\b4\n4\f4\u0306\t4\u00014\u00034\u0309\b4\u00015"+ - "\u00015\u00015\u00035\u030e\b5\u00015\u00015\u00015\u00016\u00016\u0001"+ - "6\u00016\u00016\u00016\u00016\u00016\u00016\u00036\u031c\b6\u00017\u0001"+ - "7\u00017\u00037\u0321\b7\u00017\u00017\u00017\u00017\u00017\u00017\u0003"+ - "7\u0329\b7\u00017\u00017\u00017\u00017\u00017\u00017\u00037\u0331\b7\u0001"+ - "7\u00017\u00017\u00017\u00017\u00017\u00037\u0339\b7\u00017\u00017\u0001"+ - "7\u00017\u00017\u00017\u00037\u0341\b7\u00017\u00017\u00017\u00037\u0346"+ + "4\u00014\u00054\u02fd\b4\n4\f4\u0300\t4\u00014\u00034\u0303\b4\u00015"+ + "\u00015\u00015\u00035\u0308\b5\u00015\u00015\u00015\u00016\u00016\u0001"+ + "6\u00016\u00016\u00016\u00016\u00016\u00016\u00036\u0316\b6\u00017\u0001"+ + "7\u00017\u00037\u031b\b7\u00017\u00017\u00017\u00017\u00017\u00017\u0003"+ + "7\u0323\b7\u00017\u00017\u00017\u00017\u00017\u00017\u00037\u032b\b7\u0001"+ + "7\u00017\u00017\u00017\u00017\u00017\u00037\u0333\b7\u00017\u00017\u0001"+ + "7\u00017\u00017\u00017\u00037\u033b\b7\u00017\u00017\u00017\u00037\u0340"+ "\b7\u00018\u00018\u00018\u00018\u00018\u00018\u00018\u00019\u00019\u0001"+ "9\u00019\u00019\u00019\u0001:\u0001:\u0001:\u0001:\u0001:\u0001:\u0001"+ ":\u0001:\u0001:\u0001:\u0001:\u0001:\u0001:\u0001:\u0001:\u0001:\u0001"+ - ":\u0001:\u0001:\u0001:\u0003:\u0369\b:\u0001;\u0001;\u0001;\u0001;\u0001"+ + ":\u0001:\u0001:\u0001:\u0003:\u0363\b:\u0001;\u0001;\u0001;\u0001;\u0001"+ ";\u0001;\u0001<\u0001<\u0001<\u0001<\u0001<\u0001=\u0001=\u0001=\u0003"+ - "=\u0379\b=\u0001=\u0001=\u0001=\u0001=\u0001>\u0001>\u0001>\u0003>\u0382"+ + "=\u0373\b=\u0001=\u0001=\u0001=\u0001=\u0001>\u0001>\u0001>\u0003>\u037c"+ "\b>\u0001>\u0001>\u0001>\u0001?\u0001?\u0001?\u0001?\u0001?\u0001@\u0001"+ "@\u0001@\u0001@\u0001@\u0001@\u0001@\u0001@\u0001@\u0001@\u0001@\u0003"+ - "@\u0397\b@\u0001A\u0001A\u0001A\u0003A\u039c\bA\u0001A\u0005A\u039f\b"+ - "A\nA\fA\u03a2\tA\u0001A\u0001A\u0001B\u0001B\u0001B\u0001B\u0003B\u03aa"+ - "\bB\u0001B\u0001B\u0005B\u03ae\bB\nB\fB\u03b1\tB\u0001B\u0001B\u0001B"+ - "\u0001B\u0001B\u0003B\u03b8\bB\u0001B\u0001B\u0005B\u03bc\bB\nB\fB\u03bf"+ - "\tB\u0001B\u0003B\u03c2\bB\u0001C\u0001C\u0001C\u0003C\u03c7\bC\u0001"+ - "C\u0001C\u0001C\u0001C\u0001C\u0001C\u0001C\u0003C\u03d0\bC\u0001C\u0001"+ - "C\u0001C\u0003C\u03d5\bC\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001"+ + "@\u0391\b@\u0001A\u0001A\u0001A\u0003A\u0396\bA\u0001A\u0005A\u0399\b"+ + "A\nA\fA\u039c\tA\u0001A\u0001A\u0001B\u0001B\u0001B\u0001B\u0003B\u03a4"+ + "\bB\u0001B\u0001B\u0005B\u03a8\bB\nB\fB\u03ab\tB\u0001B\u0001B\u0001B"+ + "\u0001B\u0001B\u0003B\u03b2\bB\u0001B\u0001B\u0005B\u03b6\bB\nB\fB\u03b9"+ + "\tB\u0001B\u0003B\u03bc\bB\u0001C\u0001C\u0001C\u0003C\u03c1\bC\u0001"+ + "C\u0001C\u0001C\u0001C\u0001C\u0001C\u0001C\u0003C\u03ca\bC\u0001C\u0001"+ + "C\u0001C\u0003C\u03cf\bC\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001"+ "D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001"+ "D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001"+ "D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001"+ "D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001D\u0001"+ - "D\u0001D\u0001D\u0001D\u0001D\u0001D\u0003D\u040b\bD\u0001E\u0001E\u0001"+ - "E\u0001E\u0001E\u0001E\u0001E\u0003E\u0414\bE\u0001E\u0001E\u0001E\u0001"+ - "E\u0003E\u041a\bE\u0001F\u0001F\u0001F\u0001F\u0003F\u0420\bF\u0001F\u0003"+ - "F\u0423\bF\u0001F\u0001F\u0001G\u0001G\u0001G\u0003G\u042a\bG\u0001G\u0005"+ - "G\u042d\bG\nG\fG\u0430\tG\u0001G\u0001G\u0001G\u0001G\u0003G\u0436\bG"+ - "\u0001G\u0001G\u0001G\u0001G\u0001G\u0003G\u043d\bG\u0001G\u0001G\u0001"+ - "G\u0001G\u0001G\u0003G\u0444\bG\u0001G\u0003G\u0447\bG\u0001H\u0001H\u0001"+ - "H\u0001H\u0001H\u0001I\u0005I\u044f\bI\nI\fI\u0452\tI\u0001J\u0005J\u0455"+ - "\bJ\nJ\fJ\u0458\tJ\u0001J\u0001J\u0004J\u045c\bJ\u000bJ\fJ\u045d\u0001"+ - "J\u0001J\u0003J\u0462\bJ\u0001K\u0001K\u0001K\u0001K\u0005K\u0468\bK\n"+ - "K\fK\u046b\tK\u0001K\u0003K\u046e\bK\u0001K\u0000\u0000L\u0000\u0002\u0004"+ + "D\u0001D\u0001D\u0001D\u0001D\u0001D\u0003D\u0405\bD\u0001E\u0001E\u0001"+ + "E\u0001E\u0001E\u0001E\u0001E\u0003E\u040e\bE\u0001E\u0001E\u0001E\u0001"+ + "E\u0003E\u0414\bE\u0001F\u0001F\u0001F\u0001F\u0003F\u041a\bF\u0001F\u0003"+ + "F\u041d\bF\u0001F\u0001F\u0001G\u0001G\u0001G\u0003G\u0424\bG\u0001G\u0005"+ + "G\u0427\bG\nG\fG\u042a\tG\u0001G\u0001G\u0001G\u0001G\u0003G\u0430\bG"+ + "\u0001G\u0001G\u0001G\u0001G\u0001G\u0003G\u0437\bG\u0001G\u0001G\u0001"+ + "G\u0001G\u0001G\u0003G\u043e\bG\u0001G\u0003G\u0441\bG\u0001H\u0001H\u0001"+ + "H\u0001H\u0001H\u0001I\u0005I\u0449\bI\nI\fI\u044c\tI\u0001J\u0005J\u044f"+ + "\bJ\nJ\fJ\u0452\tJ\u0001J\u0001J\u0004J\u0456\bJ\u000bJ\fJ\u0457\u0001"+ + "J\u0001J\u0003J\u045c\bJ\u0001K\u0001K\u0001K\u0001K\u0005K\u0462\bK\n"+ + "K\fK\u0465\tK\u0001K\u0003K\u0468\bK\u0001K\u0000\u0000L\u0000\u0002\u0004"+ "\u0006\b\n\f\u000e\u0010\u0012\u0014\u0016\u0018\u001a\u001c\u001e \""+ "$&(*,.02468:<>@BDFHJLNPRTVXZ\\^`bdfhjlnprtvxz|~\u0080\u0082\u0084\u0086"+ "\u0088\u008a\u008c\u008e\u0090\u0092\u0094\u0096\u0000\u0004\u0001\u0000"+ "\u0004\u0005\u0001\u0000\u0003\u0005\u0002\u0000\u0003\u0003\u00a8\u00a8"+ - "\u0001\u0000\u0096\u0097\u04f1\u0000\u0098\u0001\u0000\u0000\u0000\u0002"+ + "\u0001\u0000\u0096\u0097\u04e9\u0000\u0098\u0001\u0000\u0000\u0000\u0002"+ "\u009a\u0001\u0000\u0000\u0000\u0004\u009c\u0001\u0000\u0000\u0000\u0006"+ "\u00ab\u0001\u0000\u0000\u0000\b\u00ad\u0001\u0000\u0000\u0000\n\u00b2"+ "\u0001\u0000\u0000\u0000\f\u00b7\u0001\u0000\u0000\u0000\u000e\u00bf\u0001"+ @@ -7261,29 +7230,29 @@ public final ModuleContext module() throws RecognitionException { "\u0000\u0000$\u010b\u0001\u0000\u0000\u0000&\u010d\u0001\u0000\u0000\u0000"+ "(\u0165\u0001\u0000\u0000\u0000*\u0167\u0001\u0000\u0000\u0000,\u016f"+ "\u0001\u0000\u0000\u0000.\u0175\u0001\u0000\u0000\u00000\u0178\u0001\u0000"+ - "\u0000\u00002\u017b\u0001\u0000\u0000\u00004\u0182\u0001\u0000\u0000\u0000"+ - "6\u0187\u0001\u0000\u0000\u00008\u0193\u0001\u0000\u0000\u0000:\u01a0"+ - "\u0001\u0000\u0000\u0000<\u01bc\u0001\u0000\u0000\u0000>\u01cc\u0001\u0000"+ - "\u0000\u0000@\u01f9\u0001\u0000\u0000\u0000B\u0206\u0001\u0000\u0000\u0000"+ - "D\u0208\u0001\u0000\u0000\u0000F\u020b\u0001\u0000\u0000\u0000H\u0239"+ - "\u0001\u0000\u0000\u0000J\u023c\u0001\u0000\u0000\u0000L\u024b\u0001\u0000"+ - "\u0000\u0000N\u025b\u0001\u0000\u0000\u0000P\u0267\u0001\u0000\u0000\u0000"+ - "R\u026d\u0001\u0000\u0000\u0000T\u026f\u0001\u0000\u0000\u0000V\u0284"+ - "\u0001\u0000\u0000\u0000X\u0286\u0001\u0000\u0000\u0000Z\u0299\u0001\u0000"+ - "\u0000\u0000\\\u02a4\u0001\u0000\u0000\u0000^\u02a6\u0001\u0000\u0000"+ - "\u0000`\u02b4\u0001\u0000\u0000\u0000b\u02ce\u0001\u0000\u0000\u0000d"+ - "\u02ee\u0001\u0000\u0000\u0000f\u02f0\u0001\u0000\u0000\u0000h\u0308\u0001"+ - "\u0000\u0000\u0000j\u030a\u0001\u0000\u0000\u0000l\u031b\u0001\u0000\u0000"+ - "\u0000n\u0345\u0001\u0000\u0000\u0000p\u0347\u0001\u0000\u0000\u0000r"+ - "\u034e\u0001\u0000\u0000\u0000t\u0368\u0001\u0000\u0000\u0000v\u036a\u0001"+ - "\u0000\u0000\u0000x\u0370\u0001\u0000\u0000\u0000z\u0375\u0001\u0000\u0000"+ - "\u0000|\u037e\u0001\u0000\u0000\u0000~\u0386\u0001\u0000\u0000\u0000\u0080"+ - "\u0396\u0001\u0000\u0000\u0000\u0082\u0398\u0001\u0000\u0000\u0000\u0084"+ - "\u03c1\u0001\u0000\u0000\u0000\u0086\u03d4\u0001\u0000\u0000\u0000\u0088"+ - "\u040a\u0001\u0000\u0000\u0000\u008a\u0419\u0001\u0000\u0000\u0000\u008c"+ - "\u041b\u0001\u0000\u0000\u0000\u008e\u0446\u0001\u0000\u0000\u0000\u0090"+ - "\u0448\u0001\u0000\u0000\u0000\u0092\u0450\u0001\u0000\u0000\u0000\u0094"+ - "\u0461\u0001\u0000\u0000\u0000\u0096\u046d\u0001\u0000\u0000\u0000\u0098"+ + "\u0000\u00002\u017b\u0001\u0000\u0000\u00004\u017e\u0001\u0000\u0000\u0000"+ + "6\u0181\u0001\u0000\u0000\u00008\u018d\u0001\u0000\u0000\u0000:\u019a"+ + "\u0001\u0000\u0000\u0000<\u01b6\u0001\u0000\u0000\u0000>\u01c6\u0001\u0000"+ + "\u0000\u0000@\u01f3\u0001\u0000\u0000\u0000B\u0200\u0001\u0000\u0000\u0000"+ + "D\u0202\u0001\u0000\u0000\u0000F\u0205\u0001\u0000\u0000\u0000H\u0233"+ + "\u0001\u0000\u0000\u0000J\u0236\u0001\u0000\u0000\u0000L\u0245\u0001\u0000"+ + "\u0000\u0000N\u0255\u0001\u0000\u0000\u0000P\u0261\u0001\u0000\u0000\u0000"+ + "R\u0267\u0001\u0000\u0000\u0000T\u0269\u0001\u0000\u0000\u0000V\u027e"+ + "\u0001\u0000\u0000\u0000X\u0280\u0001\u0000\u0000\u0000Z\u0293\u0001\u0000"+ + "\u0000\u0000\\\u029e\u0001\u0000\u0000\u0000^\u02a0\u0001\u0000\u0000"+ + "\u0000`\u02ae\u0001\u0000\u0000\u0000b\u02c8\u0001\u0000\u0000\u0000d"+ + "\u02e8\u0001\u0000\u0000\u0000f\u02ea\u0001\u0000\u0000\u0000h\u0302\u0001"+ + "\u0000\u0000\u0000j\u0304\u0001\u0000\u0000\u0000l\u0315\u0001\u0000\u0000"+ + "\u0000n\u033f\u0001\u0000\u0000\u0000p\u0341\u0001\u0000\u0000\u0000r"+ + "\u0348\u0001\u0000\u0000\u0000t\u0362\u0001\u0000\u0000\u0000v\u0364\u0001"+ + "\u0000\u0000\u0000x\u036a\u0001\u0000\u0000\u0000z\u036f\u0001\u0000\u0000"+ + "\u0000|\u0378\u0001\u0000\u0000\u0000~\u0380\u0001\u0000\u0000\u0000\u0080"+ + "\u0390\u0001\u0000\u0000\u0000\u0082\u0392\u0001\u0000\u0000\u0000\u0084"+ + "\u03bb\u0001\u0000\u0000\u0000\u0086\u03ce\u0001\u0000\u0000\u0000\u0088"+ + "\u0404\u0001\u0000\u0000\u0000\u008a\u0413\u0001\u0000\u0000\u0000\u008c"+ + "\u0415\u0001\u0000\u0000\u0000\u008e\u0440\u0001\u0000\u0000\u0000\u0090"+ + "\u0442\u0001\u0000\u0000\u0000\u0092\u044a\u0001\u0000\u0000\u0000\u0094"+ + "\u045b\u0001\u0000\u0000\u0000\u0096\u0467\u0001\u0000\u0000\u0000\u0098"+ "\u0099\u0007\u0000\u0000\u0000\u0099\u0001\u0001\u0000\u0000\u0000\u009a"+ "\u009b\u0005\u0006\u0000\u0000\u009b\u0003\u0001\u0000\u0000\u0000\u009c"+ "\u009d\u0005\u0007\u0000\u0000\u009d\u0005\u0001\u0000\u0000\u0000\u009e"+ @@ -7424,445 +7393,442 @@ public final ModuleContext module() throws RecognitionException { "\u0005<\u0000\u0000\u0176\u0177\u0005\u0003\u0000\u0000\u0177/\u0001\u0000"+ "\u0000\u0000\u0178\u0179\u0005=\u0000\u0000\u0179\u017a\u0005\u0003\u0000"+ "\u0000\u017a1\u0001\u0000\u0000\u0000\u017b\u017c\u0003\u0004\u0002\u0000"+ - "\u017c\u0180\u00059\u0000\u0000\u017d\u017e\u0005?\u0000\u0000\u017e\u017f"+ - "\u0005;\u0000\u0000\u017f\u0181\u0005>\u0000\u0000\u0180\u017d\u0001\u0000"+ - "\u0000\u0000\u0180\u0181\u0001\u0000\u0000\u0000\u01813\u0001\u0000\u0000"+ - "\u0000\u0182\u0183\u0003\u0004\u0002\u0000\u0183\u0185\u0005:\u0000\u0000"+ - "\u0184\u0186\u0005?\u0000\u0000\u0185\u0184\u0001\u0000\u0000\u0000\u0185"+ - "\u0186\u0001\u0000\u0000\u0000\u01865\u0001\u0000\u0000\u0000\u0187\u0188"+ - "\u0005\"\u0000\u0000\u01887\u0001\u0000\u0000\u0000\u0189\u018b\u0005"+ - "$\u0000\u0000\u018a\u018c\u0003 \u0010\u0000\u018b\u018a\u0001\u0000\u0000"+ - "\u0000\u018b\u018c\u0001\u0000\u0000\u0000\u018c\u018d\u0001\u0000\u0000"+ - "\u0000\u018d\u0194\u0003\u001c\u000e\u0000\u018e\u0190\u0005&\u0000\u0000"+ - "\u018f\u0191\u0003 \u0010\u0000\u0190\u018f\u0001\u0000\u0000\u0000\u0190"+ - "\u0191\u0001\u0000\u0000\u0000\u0191\u0192\u0001\u0000\u0000\u0000\u0192"+ - "\u0194\u0003\u001c\u000e\u0000\u0193\u0189\u0001\u0000\u0000\u0000\u0193"+ - "\u018e\u0001\u0000\u0000\u0000\u01949\u0001\u0000\u0000\u0000\u0195\u0196"+ - "\u0005\u0001\u0000\u0000\u0196\u019a\u0005\u0088\u0000\u0000\u0197\u0199"+ - "\u0003\n\u0005\u0000\u0198\u0197\u0001\u0000\u0000\u0000\u0199\u019c\u0001"+ - "\u0000\u0000\u0000\u019a\u0198\u0001\u0000\u0000\u0000\u019a\u019b\u0001"+ - "\u0000\u0000\u0000\u019b\u019d\u0001\u0000\u0000\u0000\u019c\u019a\u0001"+ - "\u0000\u0000\u0000\u019d\u019f\u0005\u0002\u0000\u0000\u019e\u0195\u0001"+ - "\u0000\u0000\u0000\u019f\u01a2\u0001\u0000\u0000\u0000\u01a0\u019e\u0001"+ - "\u0000\u0000\u0000\u01a0\u01a1\u0001\u0000\u0000\u0000\u01a1\u01ae\u0001"+ - "\u0000\u0000\u0000\u01a2\u01a0\u0001\u0000\u0000\u0000\u01a3\u01a4\u0005"+ - "\u0001\u0000\u0000\u01a4\u01a8\u0005\u0089\u0000\u0000\u01a5\u01a7\u0003"+ - "\n\u0005\u0000\u01a6\u01a5\u0001\u0000\u0000\u0000\u01a7\u01aa\u0001\u0000"+ - "\u0000\u0000\u01a8\u01a6\u0001\u0000\u0000\u0000\u01a8\u01a9\u0001\u0000"+ - "\u0000\u0000\u01a9\u01ab\u0001\u0000\u0000\u0000\u01aa\u01a8\u0001\u0000"+ - "\u0000\u0000\u01ab\u01ad\u0005\u0002\u0000\u0000\u01ac\u01a3\u0001\u0000"+ - "\u0000\u0000\u01ad\u01b0\u0001\u0000\u0000\u0000\u01ae\u01ac\u0001\u0000"+ - "\u0000\u0000\u01ae\u01af\u0001\u0000\u0000\u0000\u01af;\u0001\u0000\u0000"+ - "\u0000\u01b0\u01ae\u0001\u0000\u0000\u0000\u01b1\u01b2\u0005\u0001\u0000"+ - "\u0000\u01b2\u01b6\u0005\u0088\u0000\u0000\u01b3\u01b5\u0003\n\u0005\u0000"+ - "\u01b4\u01b3\u0001\u0000\u0000\u0000\u01b5\u01b8\u0001\u0000\u0000\u0000"+ - "\u01b6\u01b4\u0001\u0000\u0000\u0000\u01b6\u01b7\u0001\u0000\u0000\u0000"+ - "\u01b7\u01b9\u0001\u0000\u0000\u0000\u01b8\u01b6\u0001\u0000\u0000\u0000"+ - "\u01b9\u01bb\u0005\u0002\u0000\u0000\u01ba\u01b1\u0001\u0000\u0000\u0000"+ - "\u01bb\u01be\u0001\u0000\u0000\u0000\u01bc\u01ba\u0001\u0000\u0000\u0000"+ - "\u01bc\u01bd\u0001\u0000\u0000\u0000\u01bd\u01bf\u0001\u0000\u0000\u0000"+ - "\u01be\u01bc\u0001\u0000\u0000\u0000\u01bf\u01c0\u0003>\u001f\u0000\u01c0"+ - "=\u0001\u0000\u0000\u0000\u01c1\u01c2\u0005\u0001\u0000\u0000\u01c2\u01c6"+ - "\u0005\u0089\u0000\u0000\u01c3\u01c5\u0003\n\u0005\u0000\u01c4\u01c3\u0001"+ - "\u0000\u0000\u0000\u01c5\u01c8\u0001\u0000\u0000\u0000\u01c6\u01c4\u0001"+ - "\u0000\u0000\u0000\u01c6\u01c7\u0001\u0000\u0000\u0000\u01c7\u01c9\u0001"+ - "\u0000\u0000\u0000\u01c8\u01c6\u0001\u0000\u0000\u0000\u01c9\u01cb\u0005"+ - "\u0002\u0000\u0000\u01ca\u01c1\u0001\u0000\u0000\u0000\u01cb\u01ce\u0001"+ - "\u0000\u0000\u0000\u01cc\u01ca\u0001\u0000\u0000\u0000\u01cc\u01cd\u0001"+ - "\u0000\u0000\u0000\u01cd\u01cf\u0001\u0000\u0000\u0000\u01ce\u01cc\u0001"+ - "\u0000\u0000\u0000\u01cf\u01d0\u0003$\u0012\u0000\u01d0?\u0001\u0000\u0000"+ - "\u0000\u01d1\u01d3\u0005\u0016\u0000\u0000\u01d2\u01d4\u0003\"\u0011\u0000"+ - "\u01d3\u01d2\u0001\u0000\u0000\u0000\u01d3\u01d4\u0001\u0000\u0000\u0000"+ - "\u01d4\u01d5\u0001\u0000\u0000\u0000\u01d5\u01d6\u0003D\"\u0000\u01d6"+ - "\u01d8\u0005\u001a\u0000\u0000\u01d7\u01d9\u0003\"\u0011\u0000\u01d8\u01d7"+ - "\u0001\u0000\u0000\u0000\u01d8\u01d9\u0001\u0000\u0000\u0000\u01d9\u01fa"+ - "\u0001\u0000\u0000\u0000\u01da\u01dc\u0005\u0017\u0000\u0000\u01db\u01dd"+ - "\u0003\"\u0011\u0000\u01dc\u01db\u0001\u0000\u0000\u0000\u01dc\u01dd\u0001"+ - "\u0000\u0000\u0000\u01dd\u01de\u0001\u0000\u0000\u0000\u01de\u01df\u0003"+ - "D\"\u0000\u01df\u01e1\u0005\u001a\u0000\u0000\u01e0\u01e2\u0003\"\u0011"+ - "\u0000\u01e1\u01e0\u0001\u0000\u0000\u0000\u01e1\u01e2\u0001\u0000\u0000"+ - "\u0000\u01e2\u01fa\u0001\u0000\u0000\u0000\u01e3\u01e5\u0005\u001f\u0000"+ - "\u0000\u01e4\u01e6\u0003\"\u0011\u0000\u01e5\u01e4\u0001\u0000\u0000\u0000"+ - "\u01e5\u01e6\u0001\u0000\u0000\u0000\u01e6\u01e7\u0001\u0000\u0000\u0000"+ - "\u01e7\u01ed\u0003D\"\u0000\u01e8\u01ea\u0005!\u0000\u0000\u01e9\u01eb"+ - "\u0003\"\u0011\u0000\u01ea\u01e9\u0001\u0000\u0000\u0000\u01ea\u01eb\u0001"+ - "\u0000\u0000\u0000\u01eb\u01ec\u0001\u0000\u0000\u0000\u01ec\u01ee\u0003"+ - "P(\u0000\u01ed\u01e8\u0001\u0000\u0000\u0000\u01ed\u01ee\u0001\u0000\u0000"+ - "\u0000\u01ee\u01ef\u0001\u0000\u0000\u0000\u01ef\u01f1\u0005\u001a\u0000"+ - "\u0000\u01f0\u01f2\u0003\"\u0011\u0000\u01f1\u01f0\u0001\u0000\u0000\u0000"+ - "\u01f1\u01f2\u0001\u0000\u0000\u0000\u01f2\u01fa\u0001\u0000\u0000\u0000"+ - "\u01f3\u01f4\u00050\u0000\u0000\u01f4\u01f5\u0003D\"\u0000\u01f5\u01f6"+ - "\u00051\u0000\u0000\u01f6\u01f7\u0003D\"\u0000\u01f7\u01f8\u0005\u001a"+ - "\u0000\u0000\u01f8\u01fa\u0001\u0000\u0000\u0000\u01f9\u01d1\u0001\u0000"+ - "\u0000\u0000\u01f9\u01da\u0001\u0000\u0000\u0000\u01f9\u01e3\u0001\u0000"+ - "\u0000\u0000\u01f9\u01f3\u0001\u0000\u0000\u0000\u01faA\u0001\u0000\u0000"+ - "\u0000\u01fb\u01fc\u0005\u0001\u0000\u0000\u01fc\u01fd\u0005\u0089\u0000"+ - "\u0000\u01fd\u01fe\u0003\n\u0005\u0000\u01fe\u01ff\u0005\u0002\u0000\u0000"+ - "\u01ff\u0201\u0001\u0000\u0000\u0000\u0200\u01fb\u0001\u0000\u0000\u0000"+ - "\u0200\u0201\u0001\u0000\u0000\u0000\u0201\u0207\u0001\u0000\u0000\u0000"+ - "\u0202\u0203\u0003\u001c\u000e\u0000\u0203\u0204\u0003\u0016\u000b\u0000"+ - "\u0204\u0207\u0001\u0000\u0000\u0000\u0205\u0207\u0003\u0016\u000b\u0000"+ - "\u0206\u0200\u0001\u0000\u0000\u0000\u0206\u0202\u0001\u0000\u0000\u0000"+ - "\u0206\u0205\u0001\u0000\u0000\u0000\u0207C\u0001\u0000\u0000\u0000\u0208"+ - "\u0209\u0003B!\u0000\u0209\u020a\u0003P(\u0000\u020aE\u0001\u0000\u0000"+ - "\u0000\u020b\u020c\u0005\u0001\u0000\u0000\u020c\u020d\u0003H$\u0000\u020d"+ - "\u020e\u0005\u0002\u0000\u0000\u020eG\u0001\u0000\u0000\u0000\u020f\u0213"+ - "\u0003(\u0014\u0000\u0210\u0212\u0003H$\u0000\u0211\u0210\u0001\u0000"+ - "\u0000\u0000\u0212\u0215\u0001\u0000\u0000\u0000\u0213\u0211\u0001\u0000"+ - "\u0000\u0000\u0213\u0214\u0001\u0000\u0000\u0000\u0214\u023a\u0001\u0000"+ - "\u0000\u0000\u0215\u0213\u0001\u0000\u0000\u0000\u0216\u0217\u0005$\u0000"+ - "\u0000\u0217\u023a\u0003J%\u0000\u0218\u0219\u0005&\u0000\u0000\u0219"+ - "\u023a\u0003J%\u0000\u021a\u021c\u0005\u0016\u0000\u0000\u021b\u021d\u0003"+ - "\"\u0011\u0000\u021c\u021b\u0001\u0000\u0000\u0000\u021c\u021d\u0001\u0000"+ - "\u0000\u0000\u021d\u021e\u0001\u0000\u0000\u0000\u021e\u023a\u0003D\""+ - "\u0000\u021f\u0221\u0005\u0017\u0000\u0000\u0220\u0222\u0003\"\u0011\u0000"+ - "\u0221\u0220\u0001\u0000\u0000\u0000\u0221\u0222\u0001\u0000\u0000\u0000"+ - "\u0222\u0223\u0001\u0000\u0000\u0000\u0223\u023a\u0003D\"\u0000\u0224"+ - "\u0226\u0005\u001f\u0000\u0000\u0225\u0227\u0003\"\u0011\u0000\u0226\u0225"+ - "\u0001\u0000\u0000\u0000\u0226\u0227\u0001\u0000\u0000\u0000\u0227\u0228"+ - "\u0001\u0000\u0000\u0000\u0228\u022c\u0003B!\u0000\u0229\u022b\u0003F"+ - "#\u0000\u022a\u0229\u0001\u0000\u0000\u0000\u022b\u022e\u0001\u0000\u0000"+ - "\u0000\u022c\u022a\u0001\u0000\u0000\u0000\u022c\u022d\u0001\u0000\u0000"+ - "\u0000\u022d\u022f\u0001\u0000\u0000\u0000\u022e\u022c\u0001\u0000\u0000"+ - "\u0000\u022f\u0230\u0005\u0001\u0000\u0000\u0230\u0231\u0005 \u0000\u0000"+ - "\u0231\u0237\u0003P(\u0000\u0232\u0233\u0005\u0001\u0000\u0000\u0233\u0234"+ - "\u0005!\u0000\u0000\u0234\u0235\u0003P(\u0000\u0235\u0236\u0005\u0002"+ - "\u0000\u0000\u0236\u0238\u0001\u0000\u0000\u0000\u0237\u0232\u0001\u0000"+ - "\u0000\u0000\u0237\u0238\u0001\u0000\u0000\u0000\u0238\u023a\u0001\u0000"+ - "\u0000\u0000\u0239\u020f\u0001\u0000\u0000\u0000\u0239\u0216\u0001\u0000"+ - "\u0000\u0000\u0239\u0218\u0001\u0000\u0000\u0000\u0239\u021a\u0001\u0000"+ - "\u0000\u0000\u0239\u021f\u0001\u0000\u0000\u0000\u0239\u0224\u0001\u0000"+ - "\u0000\u0000\u023aI\u0001\u0000\u0000\u0000\u023b\u023d\u0003\u001c\u000e"+ - "\u0000\u023c\u023b\u0001\u0000\u0000\u0000\u023c\u023d\u0001\u0000\u0000"+ - "\u0000\u023d\u023e\u0001\u0000\u0000\u0000\u023e\u023f\u0003L&\u0000\u023f"+ - "K\u0001\u0000\u0000\u0000\u0240\u0241\u0005\u0001\u0000\u0000\u0241\u0245"+ - "\u0005\u0088\u0000\u0000\u0242\u0244\u0003\n\u0005\u0000\u0243\u0242\u0001"+ - "\u0000\u0000\u0000\u0244\u0247\u0001\u0000\u0000\u0000\u0245\u0243\u0001"+ - "\u0000\u0000\u0000\u0245\u0246\u0001\u0000\u0000\u0000\u0246\u0248\u0001"+ - "\u0000\u0000\u0000\u0247\u0245\u0001\u0000\u0000\u0000\u0248\u024a\u0005"+ - "\u0002\u0000\u0000\u0249\u0240\u0001\u0000\u0000\u0000\u024a\u024d\u0001"+ - "\u0000\u0000\u0000\u024b\u0249\u0001\u0000\u0000\u0000\u024b\u024c\u0001"+ - "\u0000\u0000\u0000\u024c\u024e\u0001\u0000\u0000\u0000\u024d\u024b\u0001"+ - "\u0000\u0000\u0000\u024e\u024f\u0003N\'\u0000\u024fM\u0001\u0000\u0000"+ - "\u0000\u0250\u0251\u0005\u0001\u0000\u0000\u0251\u0255\u0005\u0089\u0000"+ - "\u0000\u0252\u0254\u0003\n\u0005\u0000\u0253\u0252\u0001\u0000\u0000\u0000"+ - "\u0254\u0257\u0001\u0000\u0000\u0000\u0255\u0253\u0001\u0000\u0000\u0000"+ - "\u0255\u0256\u0001\u0000\u0000\u0000\u0256\u0258\u0001\u0000\u0000\u0000"+ - "\u0257\u0255\u0001\u0000\u0000\u0000\u0258\u025a\u0005\u0002\u0000\u0000"+ - "\u0259\u0250\u0001\u0000\u0000\u0000\u025a\u025d\u0001\u0000\u0000\u0000"+ - "\u025b\u0259\u0001\u0000\u0000\u0000\u025b\u025c\u0001\u0000\u0000\u0000"+ - "\u025c\u0261\u0001\u0000\u0000\u0000\u025d\u025b\u0001\u0000\u0000\u0000"+ - "\u025e\u0260\u0003H$\u0000\u025f\u025e\u0001\u0000\u0000\u0000\u0260\u0263"+ - "\u0001\u0000\u0000\u0000\u0261\u025f\u0001\u0000\u0000\u0000\u0261\u0262"+ - "\u0001\u0000\u0000\u0000\u0262O\u0001\u0000\u0000\u0000\u0263\u0261\u0001"+ - "\u0000\u0000\u0000\u0264\u0266\u0003$\u0012\u0000\u0265\u0264\u0001\u0000"+ - "\u0000\u0000\u0266\u0269\u0001\u0000\u0000\u0000\u0267\u0265\u0001\u0000"+ - "\u0000\u0000\u0267\u0268\u0001\u0000\u0000\u0000\u0268\u026b\u0001\u0000"+ - "\u0000\u0000\u0269\u0267\u0001\u0000\u0000\u0000\u026a\u026c\u00038\u001c"+ - "\u0000\u026b\u026a\u0001\u0000\u0000\u0000\u026b\u026c\u0001\u0000\u0000"+ - "\u0000\u026cQ\u0001\u0000\u0000\u0000\u026d\u026e\u0003P(\u0000\u026e"+ - "S\u0001\u0000\u0000\u0000\u026f\u0270\u0005\u0001\u0000\u0000\u0270\u0272"+ - "\u0005\u0085\u0000\u0000\u0271\u0273\u0003\"\u0011\u0000\u0272\u0271\u0001"+ - "\u0000\u0000\u0000\u0272\u0273\u0001\u0000\u0000\u0000\u0273\u0274\u0001"+ - "\u0000\u0000\u0000\u0274\u0275\u0003V+\u0000\u0275\u0276\u0005\u0002\u0000"+ - "\u0000\u0276U\u0001\u0000\u0000\u0000\u0277\u0279\u0003\u001c\u000e\u0000"+ - "\u0278\u0277\u0001\u0000\u0000\u0000\u0278\u0279\u0001\u0000\u0000\u0000"+ - "\u0279\u027a\u0001\u0000\u0000\u0000\u027a\u0285\u0003X,\u0000\u027b\u027d"+ - "\u0003r9\u0000\u027c\u027e\u0003\u001c\u000e\u0000\u027d\u027c\u0001\u0000"+ - "\u0000\u0000\u027d\u027e\u0001\u0000\u0000\u0000\u027e\u027f\u0001\u0000"+ - "\u0000\u0000\u027f\u0280\u0003\u0016\u000b\u0000\u0280\u0285\u0001\u0000"+ - "\u0000\u0000\u0281\u0282\u0003x<\u0000\u0282\u0283\u0003V+\u0000\u0283"+ - "\u0285\u0001\u0000\u0000\u0000\u0284\u0278\u0001\u0000\u0000\u0000\u0284"+ - "\u027b\u0001\u0000\u0000\u0000\u0284\u0281\u0001\u0000\u0000\u0000\u0285"+ - "W\u0001\u0000\u0000\u0000\u0286\u0287\u0003\u0016\u000b\u0000\u0287\u0288"+ - "\u0003Z-\u0000\u0288Y\u0001\u0000\u0000\u0000\u0289\u028a\u0005\u0001"+ - "\u0000\u0000\u028a\u0294\u0005\u008a\u0000\u0000\u028b\u028d\u0003\n\u0005"+ - "\u0000\u028c\u028b\u0001\u0000\u0000\u0000\u028d\u0290\u0001\u0000\u0000"+ - "\u0000\u028e\u028c\u0001\u0000\u0000\u0000\u028e\u028f\u0001\u0000\u0000"+ - "\u0000\u028f\u0295\u0001\u0000\u0000\u0000\u0290\u028e\u0001\u0000\u0000"+ - "\u0000\u0291\u0292\u0003\"\u0011\u0000\u0292\u0293\u0003\n\u0005\u0000"+ - "\u0293\u0295\u0001\u0000\u0000\u0000\u0294\u028e\u0001\u0000\u0000\u0000"+ - "\u0294\u0291\u0001\u0000\u0000\u0000\u0295\u0296\u0001\u0000\u0000\u0000"+ - "\u0296\u0298\u0005\u0002\u0000\u0000\u0297\u0289\u0001\u0000\u0000\u0000"+ - "\u0298\u029b\u0001\u0000\u0000\u0000\u0299\u0297\u0001\u0000\u0000\u0000"+ - "\u0299\u029a\u0001\u0000\u0000\u0000\u029a\u029c\u0001\u0000\u0000\u0000"+ - "\u029b\u0299\u0001\u0000\u0000\u0000\u029c\u029d\u0003P(\u0000\u029d["+ - "\u0001\u0000\u0000\u0000\u029e\u029f\u0005\u0001\u0000\u0000\u029f\u02a0"+ - "\u0005\u0090\u0000\u0000\u02a0\u02a1\u0003R)\u0000\u02a1\u02a2\u0005\u0002"+ - "\u0000\u0000\u02a2\u02a5\u0001\u0000\u0000\u0000\u02a3\u02a5\u0003H$\u0000"+ - "\u02a4\u029e\u0001\u0000\u0000\u0000\u02a4\u02a3\u0001\u0000\u0000\u0000"+ - "\u02a5]\u0001\u0000\u0000\u0000\u02a6\u02a7\u0005\u0001\u0000\u0000\u02a7"+ - "\u02a8\u0005\u008e\u0000\u0000\u02a8\u02a9\u0005\u0001\u0000\u0000\u02a9"+ - "\u02aa\u0003$\u0012\u0000\u02aa\u02ab\u0005\u0002\u0000\u0000\u02ab\u02af"+ - "\u0005\u0085\u0000\u0000\u02ac\u02ae\u0003 \u0010\u0000\u02ad\u02ac\u0001"+ - "\u0000\u0000\u0000\u02ae\u02b1\u0001\u0000\u0000\u0000\u02af\u02ad\u0001"+ - "\u0000\u0000\u0000\u02af\u02b0\u0001\u0000\u0000\u0000\u02b0\u02b2\u0001"+ - "\u0000\u0000\u0000\u02b1\u02af\u0001\u0000\u0000\u0000\u02b2\u02b3\u0005"+ - "\u0002\u0000\u0000\u02b3_\u0001\u0000\u0000\u0000\u02b4\u02b5\u0005\u0001"+ - "\u0000\u0000\u02b5\u02b7\u0005\u008c\u0000\u0000\u02b6\u02b8\u0003\"\u0011"+ - "\u0000\u02b7\u02b6\u0001\u0000\u0000\u0000\u02b7\u02b8\u0001\u0000\u0000"+ - "\u0000\u02b8\u02b9\u0001\u0000\u0000\u0000\u02b9\u02ba\u0003b1\u0000\u02ba"+ - "\u02bb\u0005\u0002\u0000\u0000\u02bba\u0001\u0000\u0000\u0000\u02bc\u02cf"+ - "\u0003\u0018\f\u0000\u02bd\u02be\u0003r9\u0000\u02be\u02bf\u0003\u0018"+ - "\f\u0000\u02bf\u02cf\u0001\u0000\u0000\u0000\u02c0\u02c1\u0003x<\u0000"+ - "\u02c1\u02c2\u0003b1\u0000\u02c2\u02cf\u0001\u0000\u0000\u0000\u02c3\u02c4"+ - "\u0003\u0006\u0003\u0000\u02c4\u02c5\u0005\u0001\u0000\u0000\u02c5\u02c9"+ - "\u0005\u008e\u0000\u0000\u02c6\u02c8\u0003 \u0010\u0000\u02c7\u02c6\u0001"+ - "\u0000\u0000\u0000\u02c8\u02cb\u0001\u0000\u0000\u0000\u02c9\u02c7\u0001"+ - "\u0000\u0000\u0000\u02c9\u02ca\u0001\u0000\u0000\u0000\u02ca\u02cc\u0001"+ - "\u0000\u0000\u0000\u02cb\u02c9\u0001\u0000\u0000\u0000\u02cc\u02cd\u0005"+ - "\u0002\u0000\u0000\u02cd\u02cf\u0001\u0000\u0000\u0000\u02ce\u02bc\u0001"+ - "\u0000\u0000\u0000\u02ce\u02bd\u0001\u0000\u0000\u0000\u02ce\u02c0\u0001"+ - "\u0000\u0000\u0000\u02ce\u02c3\u0001\u0000\u0000\u0000\u02cfc\u0001\u0000"+ - "\u0000\u0000\u02d0\u02d1\u0005\u0001\u0000\u0000\u02d1\u02d3\u0005\u008f"+ - "\u0000\u0000\u02d2\u02d4\u0003 \u0010\u0000\u02d3\u02d2\u0001\u0000\u0000"+ - "\u0000\u02d3\u02d4\u0001\u0000\u0000\u0000\u02d4\u02d5\u0001\u0000\u0000"+ - "\u0000\u02d5\u02d6\u0005\u0001\u0000\u0000\u02d6\u02d7\u0003$\u0012\u0000"+ - "\u02d7\u02db\u0005\u0002\u0000\u0000\u02d8\u02da\u0005\u0006\u0000\u0000"+ - "\u02d9\u02d8\u0001\u0000\u0000\u0000\u02da\u02dd\u0001\u0000\u0000\u0000"+ - "\u02db\u02d9\u0001\u0000\u0000\u0000\u02db\u02dc\u0001\u0000\u0000\u0000"+ - "\u02dc\u02de\u0001\u0000\u0000\u0000\u02dd\u02db\u0001\u0000\u0000\u0000"+ - "\u02de\u02df\u0005\u0002\u0000\u0000\u02df\u02ef\u0001\u0000\u0000\u0000"+ - "\u02e0\u02e1\u0005\u0001\u0000\u0000\u02e1\u02e3\u0005\u008f\u0000\u0000"+ - "\u02e2\u02e4\u0003 \u0010\u0000\u02e3\u02e2\u0001\u0000\u0000\u0000\u02e3"+ - "\u02e4\u0001\u0000\u0000\u0000\u02e4\u02e5\u0001\u0000\u0000\u0000\u02e5"+ - "\u02e9\u0003\\.\u0000\u02e6\u02e8\u0005\u0006\u0000\u0000\u02e7\u02e6"+ - "\u0001\u0000\u0000\u0000\u02e8\u02eb\u0001\u0000\u0000\u0000\u02e9\u02e7"+ - "\u0001\u0000\u0000\u0000\u02e9\u02ea\u0001\u0000\u0000\u0000\u02ea\u02ec"+ - "\u0001\u0000\u0000\u0000\u02eb\u02e9\u0001\u0000\u0000\u0000\u02ec\u02ed"+ - "\u0005\u0002\u0000\u0000\u02ed\u02ef\u0001\u0000\u0000\u0000\u02ee\u02d0"+ - "\u0001\u0000\u0000\u0000\u02ee\u02e0\u0001\u0000\u0000\u0000\u02efe\u0001"+ - "\u0000\u0000\u0000\u02f0\u02f1\u0005\u0001\u0000\u0000\u02f1\u02f3\u0005"+ - "\u008d\u0000\u0000\u02f2\u02f4\u0003\"\u0011\u0000\u02f3\u02f2\u0001\u0000"+ - "\u0000\u0000\u02f3\u02f4\u0001\u0000\u0000\u0000\u02f4\u02f5\u0001\u0000"+ - "\u0000\u0000\u02f5\u02f6\u0003h4\u0000\u02f6\u02f7\u0005\u0002\u0000\u0000"+ - "\u02f7g\u0001\u0000\u0000\u0000\u02f8\u0309\u0003\u001a\r\u0000\u02f9"+ - "\u02fa\u0003r9\u0000\u02fa\u02fb\u0003\u001a\r\u0000\u02fb\u0309\u0001"+ - "\u0000\u0000\u0000\u02fc\u02fd\u0003x<\u0000\u02fd\u02fe\u0003h4\u0000"+ - "\u02fe\u0309\u0001\u0000\u0000\u0000\u02ff\u0300\u0005\u0001\u0000\u0000"+ - "\u0300\u0304\u0005\u008f\u0000\u0000\u0301\u0303\u0005\u0006\u0000\u0000"+ - "\u0302\u0301\u0001\u0000\u0000\u0000\u0303\u0306\u0001\u0000\u0000\u0000"+ - "\u0304\u0302\u0001\u0000\u0000\u0000\u0304\u0305\u0001\u0000\u0000\u0000"+ - "\u0305\u0307\u0001\u0000\u0000\u0000\u0306\u0304\u0001\u0000\u0000\u0000"+ - "\u0307\u0309\u0005\u0002\u0000\u0000\u0308\u02f8\u0001\u0000\u0000\u0000"+ - "\u0308\u02f9\u0001\u0000\u0000\u0000\u0308\u02fc\u0001\u0000\u0000\u0000"+ - "\u0308\u02ff\u0001\u0000\u0000\u0000\u0309i\u0001\u0000\u0000\u0000\u030a"+ - "\u030b\u0005\u0001\u0000\u0000\u030b\u030d\u0005\u008b\u0000\u0000\u030c"+ - "\u030e\u0003\"\u0011\u0000\u030d\u030c\u0001\u0000\u0000\u0000\u030d\u030e"+ - "\u0001\u0000\u0000\u0000\u030e\u030f\u0001\u0000\u0000\u0000\u030f\u0310"+ - "\u0003l6\u0000\u0310\u0311\u0005\u0002\u0000\u0000\u0311k\u0001\u0000"+ - "\u0000\u0000\u0312\u0313\u0003\u000e\u0007\u0000\u0313\u0314\u0003R)\u0000"+ - "\u0314\u031c\u0001\u0000\u0000\u0000\u0315\u0316\u0003r9\u0000\u0316\u0317"+ - "\u0003\u000e\u0007\u0000\u0317\u031c\u0001\u0000\u0000\u0000\u0318\u0319"+ - "\u0003x<\u0000\u0319\u031a\u0003l6\u0000\u031a\u031c\u0001\u0000\u0000"+ - "\u0000\u031b\u0312\u0001\u0000\u0000\u0000\u031b\u0315\u0001\u0000\u0000"+ - "\u0000\u031b\u0318\u0001\u0000\u0000\u0000\u031cm\u0001\u0000\u0000\u0000"+ - "\u031d\u031e\u0005\u0001\u0000\u0000\u031e\u0320\u0005\u0085\u0000\u0000"+ - "\u031f\u0321\u0003\"\u0011\u0000\u0320\u031f\u0001\u0000\u0000\u0000\u0320"+ - "\u0321\u0001\u0000\u0000\u0000\u0321\u0322\u0001\u0000\u0000\u0000\u0322"+ - "\u0323\u0003\u001c\u000e\u0000\u0323\u0324\u0005\u0002\u0000\u0000\u0324"+ - "\u0346\u0001\u0000\u0000\u0000\u0325\u0326\u0005\u0001\u0000\u0000\u0326"+ - "\u0328\u0005\u0085\u0000\u0000\u0327\u0329\u0003\"\u0011\u0000\u0328\u0327"+ - "\u0001\u0000\u0000\u0000\u0328\u0329\u0001\u0000\u0000\u0000\u0329\u032a"+ - "\u0001\u0000\u0000\u0000\u032a\u032b\u0003\u0016\u000b\u0000\u032b\u032c"+ - "\u0005\u0002\u0000\u0000\u032c\u0346\u0001\u0000\u0000\u0000\u032d\u032e"+ - "\u0005\u0001\u0000\u0000\u032e\u0330\u0005\u008c\u0000\u0000\u032f\u0331"+ - "\u0003\"\u0011\u0000\u0330\u032f\u0001\u0000\u0000\u0000\u0330\u0331\u0001"+ - "\u0000\u0000\u0000\u0331\u0332\u0001\u0000\u0000\u0000\u0332\u0333\u0003"+ - "\u0018\f\u0000\u0333\u0334\u0005\u0002\u0000\u0000\u0334\u0346\u0001\u0000"+ - "\u0000\u0000\u0335\u0336\u0005\u0001\u0000\u0000\u0336\u0338\u0005\u008d"+ - "\u0000\u0000\u0337\u0339\u0003\"\u0011\u0000\u0338\u0337\u0001\u0000\u0000"+ - "\u0000\u0338\u0339\u0001\u0000\u0000\u0000\u0339\u033a\u0001\u0000\u0000"+ - "\u0000\u033a\u033b\u0003\u001a\r\u0000\u033b\u033c\u0005\u0002\u0000\u0000"+ - "\u033c\u0346\u0001\u0000\u0000\u0000\u033d\u033e\u0005\u0001\u0000\u0000"+ - "\u033e\u0340\u0005\u008b\u0000\u0000\u033f\u0341\u0003\"\u0011\u0000\u0340"+ - "\u033f\u0001\u0000\u0000\u0000\u0340\u0341\u0001\u0000\u0000\u0000\u0341"+ - "\u0342\u0001\u0000\u0000\u0000\u0342\u0343\u0003\u000e\u0007\u0000\u0343"+ - "\u0344\u0005\u0002\u0000\u0000\u0344\u0346\u0001\u0000\u0000\u0000\u0345"+ - "\u031d\u0001\u0000\u0000\u0000\u0345\u0325\u0001\u0000\u0000\u0000\u0345"+ - "\u032d\u0001\u0000\u0000\u0000\u0345\u0335\u0001\u0000\u0000\u0000\u0345"+ - "\u033d\u0001\u0000\u0000\u0000\u0346o\u0001\u0000\u0000\u0000\u0347\u0348"+ - "\u0005\u0001\u0000\u0000\u0348\u0349\u0005\u0091\u0000\u0000\u0349\u034a"+ - "\u0003\u0002\u0001\u0000\u034a\u034b\u0003\u0002\u0001\u0000\u034b\u034c"+ - "\u0003n7\u0000\u034c\u034d\u0005\u0002\u0000\u0000\u034dq\u0001\u0000"+ - "\u0000\u0000\u034e\u034f\u0005\u0001\u0000\u0000\u034f\u0350\u0005\u0091"+ - "\u0000\u0000\u0350\u0351\u0003\u0002\u0001\u0000\u0351\u0352\u0003\u0002"+ - "\u0001\u0000\u0352\u0353\u0005\u0002\u0000\u0000\u0353s\u0001\u0000\u0000"+ - "\u0000\u0354\u0355\u0005\u0001\u0000\u0000\u0355\u0356\u0005\u0085\u0000"+ - "\u0000\u0356\u0357\u0003 \u0010\u0000\u0357\u0358\u0005\u0002\u0000\u0000"+ - "\u0358\u0369\u0001\u0000\u0000\u0000\u0359\u035a\u0005\u0001\u0000\u0000"+ - "\u035a\u035b\u0005\u008c\u0000\u0000\u035b\u035c\u0003 \u0010\u0000\u035c"+ - "\u035d\u0005\u0002\u0000\u0000\u035d\u0369\u0001\u0000\u0000\u0000\u035e"+ - "\u035f\u0005\u0001\u0000\u0000\u035f\u0360\u0005\u008d\u0000\u0000\u0360"+ - "\u0361\u0003 \u0010\u0000\u0361\u0362\u0005\u0002\u0000\u0000\u0362\u0369"+ - "\u0001\u0000\u0000\u0000\u0363\u0364\u0005\u0001\u0000\u0000\u0364\u0365"+ - "\u0005\u008b\u0000\u0000\u0365\u0366\u0003 \u0010\u0000\u0366\u0367\u0005"+ - "\u0002\u0000\u0000\u0367\u0369\u0001\u0000\u0000\u0000\u0368\u0354\u0001"+ - "\u0000\u0000\u0000\u0368\u0359\u0001\u0000\u0000\u0000\u0368\u035e\u0001"+ - "\u0000\u0000\u0000\u0368\u0363\u0001\u0000\u0000\u0000\u0369u\u0001\u0000"+ - "\u0000\u0000\u036a\u036b\u0005\u0001\u0000\u0000\u036b\u036c\u0005\u0092"+ - "\u0000\u0000\u036c\u036d\u0003\u0002\u0001\u0000\u036d\u036e\u0003t:\u0000"+ - "\u036e\u036f\u0005\u0002\u0000\u0000\u036fw\u0001\u0000\u0000\u0000\u0370"+ - "\u0371\u0005\u0001\u0000\u0000\u0371\u0372\u0005\u0092\u0000\u0000\u0372"+ - "\u0373\u0003\u0002\u0001\u0000\u0373\u0374\u0005\u0002\u0000\u0000\u0374"+ - "y\u0001\u0000\u0000\u0000\u0375\u0376\u0005\u0001\u0000\u0000\u0376\u0378"+ - "\u0005\u0093\u0000\u0000\u0377\u0379\u0003\"\u0011\u0000\u0378\u0377\u0001"+ - "\u0000\u0000\u0000\u0378\u0379\u0001\u0000\u0000\u0000\u0379\u037a\u0001"+ - "\u0000\u0000\u0000\u037a\u037b\u0003\u001c\u000e\u0000\u037b\u037c\u0003"+ - "\u0016\u000b\u0000\u037c\u037d\u0005\u0002\u0000\u0000\u037d{\u0001\u0000"+ - "\u0000\u0000\u037e\u037f\u0005\u0001\u0000\u0000\u037f\u0381\u0005\u0084"+ - "\u0000\u0000\u0380\u0382\u0003\"\u0011\u0000\u0381\u0380\u0001\u0000\u0000"+ - "\u0000\u0381\u0382\u0001\u0000\u0000\u0000\u0382\u0383\u0001\u0000\u0000"+ - "\u0000\u0383\u0384\u0003\u0010\b\u0000\u0384\u0385\u0005\u0002\u0000\u0000"+ - "\u0385}\u0001\u0000\u0000\u0000\u0386\u0387\u0005\u0001\u0000\u0000\u0387"+ - "\u0388\u0005\u0087\u0000\u0000\u0388\u0389\u0003 \u0010\u0000\u0389\u038a"+ - "\u0005\u0002\u0000\u0000\u038a\u007f\u0001\u0000\u0000\u0000\u038b\u0397"+ - "\u0003|>\u0000\u038c\u0397\u0003j5\u0000\u038d\u0397\u0003`0\u0000\u038e"+ - "\u0397\u0003f3\u0000\u038f\u0397\u0003T*\u0000\u0390\u0397\u0003^/\u0000"+ - "\u0391\u0397\u0003d2\u0000\u0392\u0397\u0003~?\u0000\u0393\u0397\u0003"+ - "p8\u0000\u0394\u0397\u0003v;\u0000\u0395\u0397\u0003z=\u0000\u0396\u038b"+ - "\u0001\u0000\u0000\u0000\u0396\u038c\u0001\u0000\u0000\u0000\u0396\u038d"+ - "\u0001\u0000\u0000\u0000\u0396\u038e\u0001\u0000\u0000\u0000\u0396\u038f"+ - "\u0001\u0000\u0000\u0000\u0396\u0390\u0001\u0000\u0000\u0000\u0396\u0391"+ - "\u0001\u0000\u0000\u0000\u0396\u0392\u0001\u0000\u0000\u0000\u0396\u0393"+ - "\u0001\u0000\u0000\u0000\u0396\u0394\u0001\u0000\u0000\u0000\u0396\u0395"+ - "\u0001\u0000\u0000\u0000\u0397\u0081\u0001\u0000\u0000\u0000\u0398\u0399"+ - "\u0005\u0001\u0000\u0000\u0399\u039b\u0005\u0095\u0000\u0000\u039a\u039c"+ - "\u0005\u00a8\u0000\u0000\u039b\u039a\u0001\u0000\u0000\u0000\u039b\u039c"+ - "\u0001\u0000\u0000\u0000\u039c\u03a0\u0001\u0000\u0000\u0000\u039d\u039f"+ - "\u0003\u0080@\u0000\u039e\u039d\u0001\u0000\u0000\u0000\u039f\u03a2\u0001"+ - "\u0000\u0000\u0000\u03a0\u039e\u0001\u0000\u0000\u0000\u03a0\u03a1\u0001"+ - "\u0000\u0000\u0000\u03a1\u03a3\u0001\u0000\u0000\u0000\u03a2\u03a0\u0001"+ - "\u0000\u0000\u0000\u03a3\u03a4\u0005\u0002\u0000\u0000\u03a4\u0083\u0001"+ - "\u0000\u0000\u0000\u03a5\u03c2\u0003\u0082A\u0000\u03a6\u03a7\u0005\u0001"+ - "\u0000\u0000\u03a7\u03a9\u0005\u0095\u0000\u0000\u03a8\u03aa\u0005\u00a8"+ - "\u0000\u0000\u03a9\u03a8\u0001\u0000\u0000\u0000\u03a9\u03aa\u0001\u0000"+ - "\u0000\u0000\u03aa\u03ab\u0001\u0000\u0000\u0000\u03ab\u03af\u0007\u0003"+ - "\u0000\u0000\u03ac\u03ae\u0005\u0006\u0000\u0000\u03ad\u03ac\u0001\u0000"+ - "\u0000\u0000\u03ae\u03b1\u0001\u0000\u0000\u0000\u03af\u03ad\u0001\u0000"+ - "\u0000\u0000\u03af\u03b0\u0001\u0000\u0000\u0000\u03b0\u03b2\u0001\u0000"+ - "\u0000\u0000\u03b1\u03af\u0001\u0000\u0000\u0000\u03b2\u03c2\u0005\u0002"+ - "\u0000\u0000\u03b3\u03b4\u0005\u0001\u0000\u0000\u03b4\u03b5\u0005\u0095"+ - "\u0000\u0000\u03b5\u03b7\u0005\u0098\u0000\u0000\u03b6\u03b8\u0005\u00a8"+ - "\u0000\u0000\u03b7\u03b6\u0001\u0000\u0000\u0000\u03b7\u03b8\u0001\u0000"+ - "\u0000\u0000\u03b8\u03b9\u0001\u0000\u0000\u0000\u03b9\u03bd\u0005\u0096"+ - "\u0000\u0000\u03ba\u03bc\u0005\u0006\u0000\u0000\u03bb\u03ba\u0001\u0000"+ - "\u0000\u0000\u03bc\u03bf\u0001\u0000\u0000\u0000\u03bd\u03bb\u0001\u0000"+ - "\u0000\u0000\u03bd\u03be\u0001\u0000\u0000\u0000\u03be\u03c0\u0001\u0000"+ - "\u0000\u0000\u03bf\u03bd\u0001\u0000\u0000\u0000\u03c0\u03c2\u0005\u0002"+ - "\u0000\u0000\u03c1\u03a5\u0001\u0000\u0000\u0000\u03c1\u03a6\u0001\u0000"+ - "\u0000\u0000\u03c1\u03b3\u0001\u0000\u0000\u0000\u03c2\u0085\u0001\u0000"+ - "\u0000\u0000\u03c3\u03c4\u0005\u0001\u0000\u0000\u03c4\u03c6\u0005\u009c"+ - "\u0000\u0000\u03c5\u03c7\u0005\u00a8\u0000\u0000\u03c6\u03c5\u0001\u0000"+ - "\u0000\u0000\u03c6\u03c7\u0001\u0000\u0000\u0000\u03c7\u03c8\u0001\u0000"+ - "\u0000\u0000\u03c8\u03c9\u0003\u0002\u0001\u0000\u03c9\u03ca\u0003\u0092"+ - "I\u0000\u03ca\u03cb\u0005\u0002\u0000\u0000\u03cb\u03d5\u0001\u0000\u0000"+ - "\u0000\u03cc\u03cd\u0005\u0001\u0000\u0000\u03cd\u03cf\u0005\u009d\u0000"+ - "\u0000\u03ce\u03d0\u0005\u00a8\u0000\u0000\u03cf\u03ce\u0001\u0000\u0000"+ - "\u0000\u03cf\u03d0\u0001\u0000\u0000\u0000\u03d0\u03d1\u0001\u0000\u0000"+ - "\u0000\u03d1\u03d2\u0003\u0002\u0001\u0000\u03d2\u03d3\u0005\u0002\u0000"+ - "\u0000\u03d3\u03d5\u0001\u0000\u0000\u0000\u03d4\u03c3\u0001\u0000\u0000"+ - "\u0000\u03d4\u03cc\u0001\u0000\u0000\u0000\u03d5\u0087\u0001\u0000\u0000"+ - "\u0000\u03d6\u03d7\u0005\u0001\u0000\u0000\u03d7\u03d8\u0005\u009e\u0000"+ - "\u0000\u03d8\u03d9\u0003\u0084B\u0000\u03d9\u03da\u0005\u0006\u0000\u0000"+ - "\u03da\u03db\u0005\u0002\u0000\u0000\u03db\u040b\u0001\u0000\u0000\u0000"+ - "\u03dc\u03dd\u0005\u0001\u0000\u0000\u03dd\u03de\u0005\u009f\u0000\u0000"+ - "\u03de\u03df\u0003\u0084B\u0000\u03df\u03e0\u0005\u0006\u0000\u0000\u03e0"+ - "\u03e1\u0005\u0002\u0000\u0000\u03e1\u040b\u0001\u0000\u0000\u0000\u03e2"+ - "\u03e3\u0005\u0001\u0000\u0000\u03e3\u03e4\u0005\u00a0\u0000\u0000\u03e4"+ - "\u03e5\u0003\u0084B\u0000\u03e5\u03e6\u0005\u0006\u0000\u0000\u03e6\u03e7"+ - "\u0005\u0002\u0000\u0000\u03e7\u040b\u0001\u0000\u0000\u0000\u03e8\u03e9"+ - "\u0005\u0001\u0000\u0000\u03e9\u03ea\u0005\u00a4\u0000\u0000\u03ea\u03eb"+ - "\u0003\u0084B\u0000\u03eb\u03ec\u0005\u0006\u0000\u0000\u03ec\u03ed\u0005"+ - "\u0002\u0000\u0000\u03ed\u040b\u0001\u0000\u0000\u0000\u03ee\u03ef\u0005"+ - "\u0001\u0000\u0000\u03ef\u03f0\u0005\u00a1\u0000\u0000\u03f0\u03f1\u0003"+ - "\u0086C\u0000\u03f1\u03f2\u0003\u0092I\u0000\u03f2\u03f3\u0005\u0002\u0000"+ - "\u0000\u03f3\u040b\u0001\u0000\u0000\u0000\u03f4\u03f5\u0005\u0001\u0000"+ - "\u0000\u03f5\u03f6\u0005\u00a2\u0000\u0000\u03f6\u03f7\u0003\u0086C\u0000"+ - "\u03f7\u03f8\u0005\u0002\u0000\u0000\u03f8\u040b\u0001\u0000\u0000\u0000"+ - "\u03f9\u03fa\u0005\u0001\u0000\u0000\u03fa\u03fb\u0005\u00a3\u0000\u0000"+ - "\u03fb\u03fc\u0003\u0086C\u0000\u03fc\u03fd\u0005\u0002\u0000\u0000\u03fd"+ - "\u040b\u0001\u0000\u0000\u0000\u03fe\u03ff\u0005\u0001\u0000\u0000\u03ff"+ - "\u0400\u0005\u00a4\u0000\u0000\u0400\u0401\u0003\u0086C\u0000\u0401\u0402"+ - "\u0005\u0006\u0000\u0000\u0402\u0403\u0005\u0002\u0000\u0000\u0403\u040b"+ - "\u0001\u0000\u0000\u0000\u0404\u0405\u0005\u0001\u0000\u0000\u0405\u0406"+ - "\u0005\u00a5\u0000\u0000\u0406\u0407\u0003\u0086C\u0000\u0407\u0408\u0005"+ - "\u0006\u0000\u0000\u0408\u0409\u0005\u0002\u0000\u0000\u0409\u040b\u0001"+ - "\u0000\u0000\u0000\u040a\u03d6\u0001\u0000\u0000\u0000\u040a\u03dc\u0001"+ - "\u0000\u0000\u0000\u040a\u03e2\u0001\u0000\u0000\u0000\u040a\u03e8\u0001"+ - "\u0000\u0000\u0000\u040a\u03ee\u0001\u0000\u0000\u0000\u040a\u03f4\u0001"+ - "\u0000\u0000\u0000\u040a\u03f9\u0001\u0000\u0000\u0000\u040a\u03fe\u0001"+ - "\u0000\u0000\u0000\u040a\u0404\u0001\u0000\u0000\u0000\u040b\u0089\u0001"+ - "\u0000\u0000\u0000\u040c\u041a\u0003\u0086C\u0000\u040d\u041a\u0003\u0088"+ - "D\u0000\u040e\u041a\u0003\u0084B\u0000\u040f\u0410\u0005\u0001\u0000\u0000"+ - "\u0410\u0411\u0005\u009b\u0000\u0000\u0411\u0413\u0003\u0002\u0001\u0000"+ - "\u0412\u0414\u0005\u00a8\u0000\u0000\u0413\u0412\u0001\u0000\u0000\u0000"+ - "\u0413\u0414\u0001\u0000\u0000\u0000\u0414\u0415\u0001\u0000\u0000\u0000"+ - "\u0415\u0416\u0005\u0002\u0000\u0000\u0416\u041a\u0001\u0000\u0000\u0000"+ - "\u0417\u041a\u0003\u008eG\u0000\u0418\u041a\u0003\u008cF\u0000\u0419\u040c"+ - "\u0001\u0000\u0000\u0000\u0419\u040d\u0001\u0000\u0000\u0000\u0419\u040e"+ - "\u0001\u0000\u0000\u0000\u0419\u040f\u0001\u0000\u0000\u0000\u0419\u0417"+ - "\u0001\u0000\u0000\u0000\u0419\u0418\u0001\u0000\u0000\u0000\u041a\u008b"+ - "\u0001\u0000\u0000\u0000\u041b\u041c\u0005\u0001\u0000\u0000\u041c\u041d"+ - "\u0005\u0095\u0000\u0000\u041d\u041f\u0005\u0099\u0000\u0000\u041e\u0420"+ - "\u0005\u00a8\u0000\u0000\u041f\u041e\u0001\u0000\u0000\u0000\u041f\u0420"+ - "\u0001\u0000\u0000\u0000\u0420\u0422\u0001\u0000\u0000\u0000\u0421\u0423"+ - "\u0005\u00a8\u0000\u0000\u0422\u0421\u0001\u0000\u0000\u0000\u0422\u0423"+ - "\u0001\u0000\u0000\u0000\u0423\u0424\u0001\u0000\u0000\u0000\u0424\u0425"+ - "\u0005\u0002\u0000\u0000\u0425\u008d\u0001\u0000\u0000\u0000\u0426\u0427"+ - "\u0005\u0001\u0000\u0000\u0427\u0429\u0005\u009a\u0000\u0000\u0428\u042a"+ - "\u0005\u00a8\u0000\u0000\u0429\u0428\u0001\u0000\u0000\u0000\u0429\u042a"+ - "\u0001\u0000\u0000\u0000\u042a\u042e\u0001\u0000\u0000\u0000\u042b\u042d"+ - "\u0003\u008aE\u0000\u042c\u042b\u0001\u0000\u0000\u0000\u042d\u0430\u0001"+ - "\u0000\u0000\u0000\u042e\u042c\u0001\u0000\u0000\u0000\u042e\u042f\u0001"+ - "\u0000\u0000\u0000\u042f\u0431\u0001\u0000\u0000\u0000\u0430\u042e\u0001"+ - "\u0000\u0000\u0000\u0431\u0447\u0005\u0002\u0000\u0000\u0432\u0433\u0005"+ - "\u0001\u0000\u0000\u0433\u0435\u0005\u00a6\u0000\u0000\u0434\u0436\u0005"+ - "\u00a8\u0000\u0000\u0435\u0434\u0001\u0000\u0000\u0000\u0435\u0436\u0001"+ - "\u0000\u0000\u0000\u0436\u0437\u0001\u0000\u0000\u0000\u0437\u0438\u0005"+ - "\u0006\u0000\u0000\u0438\u0447\u0005\u0002\u0000\u0000\u0439\u043a\u0005"+ - "\u0001\u0000\u0000\u043a\u043c\u0005\u00a7\u0000\u0000\u043b\u043d\u0005"+ - "\u00a8\u0000\u0000\u043c\u043b\u0001\u0000\u0000\u0000\u043c\u043d\u0001"+ - "\u0000\u0000\u0000\u043d\u043e\u0001\u0000\u0000\u0000\u043e\u043f\u0005"+ - "\u0006\u0000\u0000\u043f\u0447\u0005\u0002\u0000\u0000\u0440\u0441\u0005"+ - "\u0001\u0000\u0000\u0441\u0443\u0005\u00a7\u0000\u0000\u0442\u0444\u0005"+ - "\u00a8\u0000\u0000\u0443\u0442\u0001\u0000\u0000\u0000\u0443\u0444\u0001"+ - "\u0000\u0000\u0000\u0444\u0445\u0001\u0000\u0000\u0000\u0445\u0447\u0005"+ - "\u0002\u0000\u0000\u0446\u0426\u0001\u0000\u0000\u0000\u0446\u0432\u0001"+ - "\u0000\u0000\u0000\u0446\u0439\u0001\u0000\u0000\u0000\u0446\u0440\u0001"+ - "\u0000\u0000\u0000\u0447\u008f\u0001\u0000\u0000\u0000\u0448\u0449\u0005"+ - "\u0001\u0000\u0000\u0449\u044a\u0005\b\u0000\u0000\u044a\u044b\u0003\u001e"+ - "\u000f\u0000\u044b\u044c\u0005\u0002\u0000\u0000\u044c\u0091\u0001\u0000"+ - "\u0000\u0000\u044d\u044f\u0003\u0090H\u0000\u044e\u044d\u0001\u0000\u0000"+ - "\u0000\u044f\u0452\u0001\u0000\u0000\u0000\u0450\u044e\u0001\u0000\u0000"+ - "\u0000\u0450\u0451\u0001\u0000\u0000\u0000\u0451\u0093\u0001\u0000\u0000"+ - "\u0000\u0452\u0450\u0001\u0000\u0000\u0000\u0453\u0455\u0003\u008aE\u0000"+ - "\u0454\u0453\u0001\u0000\u0000\u0000\u0455\u0458\u0001\u0000\u0000\u0000"+ - "\u0456\u0454\u0001\u0000\u0000\u0000\u0456\u0457\u0001\u0000\u0000\u0000"+ - "\u0457\u0459\u0001\u0000\u0000\u0000\u0458\u0456\u0001\u0000\u0000\u0000"+ - "\u0459\u0462\u0005\u0000\u0000\u0001\u045a\u045c\u0003\u0080@\u0000\u045b"+ - "\u045a\u0001\u0000\u0000\u0000\u045c\u045d\u0001\u0000\u0000\u0000\u045d"+ - "\u045b\u0001\u0000\u0000\u0000\u045d\u045e\u0001\u0000\u0000\u0000\u045e"+ - "\u045f\u0001\u0000\u0000\u0000\u045f\u0460\u0005\u0000\u0000\u0001\u0460"+ - "\u0462\u0001\u0000\u0000\u0000\u0461\u0456\u0001\u0000\u0000\u0000\u0461"+ - "\u045b\u0001\u0000\u0000\u0000\u0462\u0095\u0001\u0000\u0000\u0000\u0463"+ - "\u0464\u0003\u0082A\u0000\u0464\u0465\u0005\u0000\u0000\u0001\u0465\u046e"+ - "\u0001\u0000\u0000\u0000\u0466\u0468\u0003\u0080@\u0000\u0467\u0466\u0001"+ - "\u0000\u0000\u0000\u0468\u046b\u0001\u0000\u0000\u0000\u0469\u0467\u0001"+ - "\u0000\u0000\u0000\u0469\u046a\u0001\u0000\u0000\u0000\u046a\u046c\u0001"+ - "\u0000\u0000\u0000\u046b\u0469\u0001\u0000\u0000\u0000\u046c\u046e\u0005"+ - "\u0000\u0000\u0001\u046d\u0463\u0001\u0000\u0000\u0000\u046d\u0469\u0001"+ - "\u0000\u0000\u0000\u046e\u0097\u0001\u0000\u0000\u0000v\u00ab\u00b2\u00b7"+ - "\u00bf\u00cb\u00d2\u00d8\u00dd\u00e5\u00eb\u00f3\u00f9\u010b\u0123\u0136"+ - "\u0139\u013d\u0140\u0165\u016c\u0180\u0185\u018b\u0190\u0193\u019a\u01a0"+ - "\u01a8\u01ae\u01b6\u01bc\u01c6\u01cc\u01d3\u01d8\u01dc\u01e1\u01e5\u01ea"+ - "\u01ed\u01f1\u01f9\u0200\u0206\u0213\u021c\u0221\u0226\u022c\u0237\u0239"+ - "\u023c\u0245\u024b\u0255\u025b\u0261\u0267\u026b\u0272\u0278\u027d\u0284"+ - "\u028e\u0294\u0299\u02a4\u02af\u02b7\u02c9\u02ce\u02d3\u02db\u02e3\u02e9"+ - "\u02ee\u02f3\u0304\u0308\u030d\u031b\u0320\u0328\u0330\u0338\u0340\u0345"+ - "\u0368\u0378\u0381\u0396\u039b\u03a0\u03a9\u03af\u03b7\u03bd\u03c1\u03c6"+ - "\u03cf\u03d4\u040a\u0413\u0419\u041f\u0422\u0429\u042e\u0435\u043c\u0443"+ - "\u0446\u0450\u0456\u045d\u0461\u0469\u046d"; + "\u017c\u017d\u00059\u0000\u0000\u017d3\u0001\u0000\u0000\u0000\u017e\u017f"+ + "\u0003\u0004\u0002\u0000\u017f\u0180\u0005:\u0000\u0000\u01805\u0001\u0000"+ + "\u0000\u0000\u0181\u0182\u0005\"\u0000\u0000\u01827\u0001\u0000\u0000"+ + "\u0000\u0183\u0185\u0005$\u0000\u0000\u0184\u0186\u0003 \u0010\u0000\u0185"+ + "\u0184\u0001\u0000\u0000\u0000\u0185\u0186\u0001\u0000\u0000\u0000\u0186"+ + "\u0187\u0001\u0000\u0000\u0000\u0187\u018e\u0003\u001c\u000e\u0000\u0188"+ + "\u018a\u0005&\u0000\u0000\u0189\u018b\u0003 \u0010\u0000\u018a\u0189\u0001"+ + "\u0000\u0000\u0000\u018a\u018b\u0001\u0000\u0000\u0000\u018b\u018c\u0001"+ + "\u0000\u0000\u0000\u018c\u018e\u0003\u001c\u000e\u0000\u018d\u0183\u0001"+ + "\u0000\u0000\u0000\u018d\u0188\u0001\u0000\u0000\u0000\u018e9\u0001\u0000"+ + "\u0000\u0000\u018f\u0190\u0005\u0001\u0000\u0000\u0190\u0194\u0005\u0088"+ + "\u0000\u0000\u0191\u0193\u0003\n\u0005\u0000\u0192\u0191\u0001\u0000\u0000"+ + "\u0000\u0193\u0196\u0001\u0000\u0000\u0000\u0194\u0192\u0001\u0000\u0000"+ + "\u0000\u0194\u0195\u0001\u0000\u0000\u0000\u0195\u0197\u0001\u0000\u0000"+ + "\u0000\u0196\u0194\u0001\u0000\u0000\u0000\u0197\u0199\u0005\u0002\u0000"+ + "\u0000\u0198\u018f\u0001\u0000\u0000\u0000\u0199\u019c\u0001\u0000\u0000"+ + "\u0000\u019a\u0198\u0001\u0000\u0000\u0000\u019a\u019b\u0001\u0000\u0000"+ + "\u0000\u019b\u01a8\u0001\u0000\u0000\u0000\u019c\u019a\u0001\u0000\u0000"+ + "\u0000\u019d\u019e\u0005\u0001\u0000\u0000\u019e\u01a2\u0005\u0089\u0000"+ + "\u0000\u019f\u01a1\u0003\n\u0005\u0000\u01a0\u019f\u0001\u0000\u0000\u0000"+ + "\u01a1\u01a4\u0001\u0000\u0000\u0000\u01a2\u01a0\u0001\u0000\u0000\u0000"+ + "\u01a2\u01a3\u0001\u0000\u0000\u0000\u01a3\u01a5\u0001\u0000\u0000\u0000"+ + "\u01a4\u01a2\u0001\u0000\u0000\u0000\u01a5\u01a7\u0005\u0002\u0000\u0000"+ + "\u01a6\u019d\u0001\u0000\u0000\u0000\u01a7\u01aa\u0001\u0000\u0000\u0000"+ + "\u01a8\u01a6\u0001\u0000\u0000\u0000\u01a8\u01a9\u0001\u0000\u0000\u0000"+ + "\u01a9;\u0001\u0000\u0000\u0000\u01aa\u01a8\u0001\u0000\u0000\u0000\u01ab"+ + "\u01ac\u0005\u0001\u0000\u0000\u01ac\u01b0\u0005\u0088\u0000\u0000\u01ad"+ + "\u01af\u0003\n\u0005\u0000\u01ae\u01ad\u0001\u0000\u0000\u0000\u01af\u01b2"+ + "\u0001\u0000\u0000\u0000\u01b0\u01ae\u0001\u0000\u0000\u0000\u01b0\u01b1"+ + "\u0001\u0000\u0000\u0000\u01b1\u01b3\u0001\u0000\u0000\u0000\u01b2\u01b0"+ + "\u0001\u0000\u0000\u0000\u01b3\u01b5\u0005\u0002\u0000\u0000\u01b4\u01ab"+ + "\u0001\u0000\u0000\u0000\u01b5\u01b8\u0001\u0000\u0000\u0000\u01b6\u01b4"+ + "\u0001\u0000\u0000\u0000\u01b6\u01b7\u0001\u0000\u0000\u0000\u01b7\u01b9"+ + "\u0001\u0000\u0000\u0000\u01b8\u01b6\u0001\u0000\u0000\u0000\u01b9\u01ba"+ + "\u0003>\u001f\u0000\u01ba=\u0001\u0000\u0000\u0000\u01bb\u01bc\u0005\u0001"+ + "\u0000\u0000\u01bc\u01c0\u0005\u0089\u0000\u0000\u01bd\u01bf\u0003\n\u0005"+ + "\u0000\u01be\u01bd\u0001\u0000\u0000\u0000\u01bf\u01c2\u0001\u0000\u0000"+ + "\u0000\u01c0\u01be\u0001\u0000\u0000\u0000\u01c0\u01c1\u0001\u0000\u0000"+ + "\u0000\u01c1\u01c3\u0001\u0000\u0000\u0000\u01c2\u01c0\u0001\u0000\u0000"+ + "\u0000\u01c3\u01c5\u0005\u0002\u0000\u0000\u01c4\u01bb\u0001\u0000\u0000"+ + "\u0000\u01c5\u01c8\u0001\u0000\u0000\u0000\u01c6\u01c4\u0001\u0000\u0000"+ + "\u0000\u01c6\u01c7\u0001\u0000\u0000\u0000\u01c7\u01c9\u0001\u0000\u0000"+ + "\u0000\u01c8\u01c6\u0001\u0000\u0000\u0000\u01c9\u01ca\u0003$\u0012\u0000"+ + "\u01ca?\u0001\u0000\u0000\u0000\u01cb\u01cd\u0005\u0016\u0000\u0000\u01cc"+ + "\u01ce\u0003\"\u0011\u0000\u01cd\u01cc\u0001\u0000\u0000\u0000\u01cd\u01ce"+ + "\u0001\u0000\u0000\u0000\u01ce\u01cf\u0001\u0000\u0000\u0000\u01cf\u01d0"+ + "\u0003D\"\u0000\u01d0\u01d2\u0005\u001a\u0000\u0000\u01d1\u01d3\u0003"+ + "\"\u0011\u0000\u01d2\u01d1\u0001\u0000\u0000\u0000\u01d2\u01d3\u0001\u0000"+ + "\u0000\u0000\u01d3\u01f4\u0001\u0000\u0000\u0000\u01d4\u01d6\u0005\u0017"+ + "\u0000\u0000\u01d5\u01d7\u0003\"\u0011\u0000\u01d6\u01d5\u0001\u0000\u0000"+ + "\u0000\u01d6\u01d7\u0001\u0000\u0000\u0000\u01d7\u01d8\u0001\u0000\u0000"+ + "\u0000\u01d8\u01d9\u0003D\"\u0000\u01d9\u01db\u0005\u001a\u0000\u0000"+ + "\u01da\u01dc\u0003\"\u0011\u0000\u01db\u01da\u0001\u0000\u0000\u0000\u01db"+ + "\u01dc\u0001\u0000\u0000\u0000\u01dc\u01f4\u0001\u0000\u0000\u0000\u01dd"+ + "\u01df\u0005\u001f\u0000\u0000\u01de\u01e0\u0003\"\u0011\u0000\u01df\u01de"+ + "\u0001\u0000\u0000\u0000\u01df\u01e0\u0001\u0000\u0000\u0000\u01e0\u01e1"+ + "\u0001\u0000\u0000\u0000\u01e1\u01e7\u0003D\"\u0000\u01e2\u01e4\u0005"+ + "!\u0000\u0000\u01e3\u01e5\u0003\"\u0011\u0000\u01e4\u01e3\u0001\u0000"+ + "\u0000\u0000\u01e4\u01e5\u0001\u0000\u0000\u0000\u01e5\u01e6\u0001\u0000"+ + "\u0000\u0000\u01e6\u01e8\u0003P(\u0000\u01e7\u01e2\u0001\u0000\u0000\u0000"+ + "\u01e7\u01e8\u0001\u0000\u0000\u0000\u01e8\u01e9\u0001\u0000\u0000\u0000"+ + "\u01e9\u01eb\u0005\u001a\u0000\u0000\u01ea\u01ec\u0003\"\u0011\u0000\u01eb"+ + "\u01ea\u0001\u0000\u0000\u0000\u01eb\u01ec\u0001\u0000\u0000\u0000\u01ec"+ + "\u01f4\u0001\u0000\u0000\u0000\u01ed\u01ee\u00050\u0000\u0000\u01ee\u01ef"+ + "\u0003D\"\u0000\u01ef\u01f0\u00051\u0000\u0000\u01f0\u01f1\u0003D\"\u0000"+ + "\u01f1\u01f2\u0005\u001a\u0000\u0000\u01f2\u01f4\u0001\u0000\u0000\u0000"+ + "\u01f3\u01cb\u0001\u0000\u0000\u0000\u01f3\u01d4\u0001\u0000\u0000\u0000"+ + "\u01f3\u01dd\u0001\u0000\u0000\u0000\u01f3\u01ed\u0001\u0000\u0000\u0000"+ + "\u01f4A\u0001\u0000\u0000\u0000\u01f5\u01f6\u0005\u0001\u0000\u0000\u01f6"+ + "\u01f7\u0005\u0089\u0000\u0000\u01f7\u01f8\u0003\n\u0005\u0000\u01f8\u01f9"+ + "\u0005\u0002\u0000\u0000\u01f9\u01fb\u0001\u0000\u0000\u0000\u01fa\u01f5"+ + "\u0001\u0000\u0000\u0000\u01fa\u01fb\u0001\u0000\u0000\u0000\u01fb\u0201"+ + "\u0001\u0000\u0000\u0000\u01fc\u01fd\u0003\u001c\u000e\u0000\u01fd\u01fe"+ + "\u0003\u0016\u000b\u0000\u01fe\u0201\u0001\u0000\u0000\u0000\u01ff\u0201"+ + "\u0003\u0016\u000b\u0000\u0200\u01fa\u0001\u0000\u0000\u0000\u0200\u01fc"+ + "\u0001\u0000\u0000\u0000\u0200\u01ff\u0001\u0000\u0000\u0000\u0201C\u0001"+ + "\u0000\u0000\u0000\u0202\u0203\u0003B!\u0000\u0203\u0204\u0003P(\u0000"+ + "\u0204E\u0001\u0000\u0000\u0000\u0205\u0206\u0005\u0001\u0000\u0000\u0206"+ + "\u0207\u0003H$\u0000\u0207\u0208\u0005\u0002\u0000\u0000\u0208G\u0001"+ + "\u0000\u0000\u0000\u0209\u020d\u0003(\u0014\u0000\u020a\u020c\u0003H$"+ + "\u0000\u020b\u020a\u0001\u0000\u0000\u0000\u020c\u020f\u0001\u0000\u0000"+ + "\u0000\u020d\u020b\u0001\u0000\u0000\u0000\u020d\u020e\u0001\u0000\u0000"+ + "\u0000\u020e\u0234\u0001\u0000\u0000\u0000\u020f\u020d\u0001\u0000\u0000"+ + "\u0000\u0210\u0211\u0005$\u0000\u0000\u0211\u0234\u0003J%\u0000\u0212"+ + "\u0213\u0005&\u0000\u0000\u0213\u0234\u0003J%\u0000\u0214\u0216\u0005"+ + "\u0016\u0000\u0000\u0215\u0217\u0003\"\u0011\u0000\u0216\u0215\u0001\u0000"+ + "\u0000\u0000\u0216\u0217\u0001\u0000\u0000\u0000\u0217\u0218\u0001\u0000"+ + "\u0000\u0000\u0218\u0234\u0003D\"\u0000\u0219\u021b\u0005\u0017\u0000"+ + "\u0000\u021a\u021c\u0003\"\u0011\u0000\u021b\u021a\u0001\u0000\u0000\u0000"+ + "\u021b\u021c\u0001\u0000\u0000\u0000\u021c\u021d\u0001\u0000\u0000\u0000"+ + "\u021d\u0234\u0003D\"\u0000\u021e\u0220\u0005\u001f\u0000\u0000\u021f"+ + "\u0221\u0003\"\u0011\u0000\u0220\u021f\u0001\u0000\u0000\u0000\u0220\u0221"+ + "\u0001\u0000\u0000\u0000\u0221\u0222\u0001\u0000\u0000\u0000\u0222\u0226"+ + "\u0003B!\u0000\u0223\u0225\u0003F#\u0000\u0224\u0223\u0001\u0000\u0000"+ + "\u0000\u0225\u0228\u0001\u0000\u0000\u0000\u0226\u0224\u0001\u0000\u0000"+ + "\u0000\u0226\u0227\u0001\u0000\u0000\u0000\u0227\u0229\u0001\u0000\u0000"+ + "\u0000\u0228\u0226\u0001\u0000\u0000\u0000\u0229\u022a\u0005\u0001\u0000"+ + "\u0000\u022a\u022b\u0005 \u0000\u0000\u022b\u0231\u0003P(\u0000\u022c"+ + "\u022d\u0005\u0001\u0000\u0000\u022d\u022e\u0005!\u0000\u0000\u022e\u022f"+ + "\u0003P(\u0000\u022f\u0230\u0005\u0002\u0000\u0000\u0230\u0232\u0001\u0000"+ + "\u0000\u0000\u0231\u022c\u0001\u0000\u0000\u0000\u0231\u0232\u0001\u0000"+ + "\u0000\u0000\u0232\u0234\u0001\u0000\u0000\u0000\u0233\u0209\u0001\u0000"+ + "\u0000\u0000\u0233\u0210\u0001\u0000\u0000\u0000\u0233\u0212\u0001\u0000"+ + "\u0000\u0000\u0233\u0214\u0001\u0000\u0000\u0000\u0233\u0219\u0001\u0000"+ + "\u0000\u0000\u0233\u021e\u0001\u0000\u0000\u0000\u0234I\u0001\u0000\u0000"+ + "\u0000\u0235\u0237\u0003\u001c\u000e\u0000\u0236\u0235\u0001\u0000\u0000"+ + "\u0000\u0236\u0237\u0001\u0000\u0000\u0000\u0237\u0238\u0001\u0000\u0000"+ + "\u0000\u0238\u0239\u0003L&\u0000\u0239K\u0001\u0000\u0000\u0000\u023a"+ + "\u023b\u0005\u0001\u0000\u0000\u023b\u023f\u0005\u0088\u0000\u0000\u023c"+ + "\u023e\u0003\n\u0005\u0000\u023d\u023c\u0001\u0000\u0000\u0000\u023e\u0241"+ + "\u0001\u0000\u0000\u0000\u023f\u023d\u0001\u0000\u0000\u0000\u023f\u0240"+ + "\u0001\u0000\u0000\u0000\u0240\u0242\u0001\u0000\u0000\u0000\u0241\u023f"+ + "\u0001\u0000\u0000\u0000\u0242\u0244\u0005\u0002\u0000\u0000\u0243\u023a"+ + "\u0001\u0000\u0000\u0000\u0244\u0247\u0001\u0000\u0000\u0000\u0245\u0243"+ + "\u0001\u0000\u0000\u0000\u0245\u0246\u0001\u0000\u0000\u0000\u0246\u0248"+ + "\u0001\u0000\u0000\u0000\u0247\u0245\u0001\u0000\u0000\u0000\u0248\u0249"+ + "\u0003N\'\u0000\u0249M\u0001\u0000\u0000\u0000\u024a\u024b\u0005\u0001"+ + "\u0000\u0000\u024b\u024f\u0005\u0089\u0000\u0000\u024c\u024e\u0003\n\u0005"+ + "\u0000\u024d\u024c\u0001\u0000\u0000\u0000\u024e\u0251\u0001\u0000\u0000"+ + "\u0000\u024f\u024d\u0001\u0000\u0000\u0000\u024f\u0250\u0001\u0000\u0000"+ + "\u0000\u0250\u0252\u0001\u0000\u0000\u0000\u0251\u024f\u0001\u0000\u0000"+ + "\u0000\u0252\u0254\u0005\u0002\u0000\u0000\u0253\u024a\u0001\u0000\u0000"+ + "\u0000\u0254\u0257\u0001\u0000\u0000\u0000\u0255\u0253\u0001\u0000\u0000"+ + "\u0000\u0255\u0256\u0001\u0000\u0000\u0000\u0256\u025b\u0001\u0000\u0000"+ + "\u0000\u0257\u0255\u0001\u0000\u0000\u0000\u0258\u025a\u0003H$\u0000\u0259"+ + "\u0258\u0001\u0000\u0000\u0000\u025a\u025d\u0001\u0000\u0000\u0000\u025b"+ + "\u0259\u0001\u0000\u0000\u0000\u025b\u025c\u0001\u0000\u0000\u0000\u025c"+ + "O\u0001\u0000\u0000\u0000\u025d\u025b\u0001\u0000\u0000\u0000\u025e\u0260"+ + "\u0003$\u0012\u0000\u025f\u025e\u0001\u0000\u0000\u0000\u0260\u0263\u0001"+ + "\u0000\u0000\u0000\u0261\u025f\u0001\u0000\u0000\u0000\u0261\u0262\u0001"+ + "\u0000\u0000\u0000\u0262\u0265\u0001\u0000\u0000\u0000\u0263\u0261\u0001"+ + "\u0000\u0000\u0000\u0264\u0266\u00038\u001c\u0000\u0265\u0264\u0001\u0000"+ + "\u0000\u0000\u0265\u0266\u0001\u0000\u0000\u0000\u0266Q\u0001\u0000\u0000"+ + "\u0000\u0267\u0268\u0003P(\u0000\u0268S\u0001\u0000\u0000\u0000\u0269"+ + "\u026a\u0005\u0001\u0000\u0000\u026a\u026c\u0005\u0085\u0000\u0000\u026b"+ + "\u026d\u0003\"\u0011\u0000\u026c\u026b\u0001\u0000\u0000\u0000\u026c\u026d"+ + "\u0001\u0000\u0000\u0000\u026d\u026e\u0001\u0000\u0000\u0000\u026e\u026f"+ + "\u0003V+\u0000\u026f\u0270\u0005\u0002\u0000\u0000\u0270U\u0001\u0000"+ + "\u0000\u0000\u0271\u0273\u0003\u001c\u000e\u0000\u0272\u0271\u0001\u0000"+ + "\u0000\u0000\u0272\u0273\u0001\u0000\u0000\u0000\u0273\u0274\u0001\u0000"+ + "\u0000\u0000\u0274\u027f\u0003X,\u0000\u0275\u0277\u0003r9\u0000\u0276"+ + "\u0278\u0003\u001c\u000e\u0000\u0277\u0276\u0001\u0000\u0000\u0000\u0277"+ + "\u0278\u0001\u0000\u0000\u0000\u0278\u0279\u0001\u0000\u0000\u0000\u0279"+ + "\u027a\u0003\u0016\u000b\u0000\u027a\u027f\u0001\u0000\u0000\u0000\u027b"+ + "\u027c\u0003x<\u0000\u027c\u027d\u0003V+\u0000\u027d\u027f\u0001\u0000"+ + "\u0000\u0000\u027e\u0272\u0001\u0000\u0000\u0000\u027e\u0275\u0001\u0000"+ + "\u0000\u0000\u027e\u027b\u0001\u0000\u0000\u0000\u027fW\u0001\u0000\u0000"+ + "\u0000\u0280\u0281\u0003\u0016\u000b\u0000\u0281\u0282\u0003Z-\u0000\u0282"+ + "Y\u0001\u0000\u0000\u0000\u0283\u0284\u0005\u0001\u0000\u0000\u0284\u028e"+ + "\u0005\u008a\u0000\u0000\u0285\u0287\u0003\n\u0005\u0000\u0286\u0285\u0001"+ + "\u0000\u0000\u0000\u0287\u028a\u0001\u0000\u0000\u0000\u0288\u0286\u0001"+ + "\u0000\u0000\u0000\u0288\u0289\u0001\u0000\u0000\u0000\u0289\u028f\u0001"+ + "\u0000\u0000\u0000\u028a\u0288\u0001\u0000\u0000\u0000\u028b\u028c\u0003"+ + "\"\u0011\u0000\u028c\u028d\u0003\n\u0005\u0000\u028d\u028f\u0001\u0000"+ + "\u0000\u0000\u028e\u0288\u0001\u0000\u0000\u0000\u028e\u028b\u0001\u0000"+ + "\u0000\u0000\u028f\u0290\u0001\u0000\u0000\u0000\u0290\u0292\u0005\u0002"+ + "\u0000\u0000\u0291\u0283\u0001\u0000\u0000\u0000\u0292\u0295\u0001\u0000"+ + "\u0000\u0000\u0293\u0291\u0001\u0000\u0000\u0000\u0293\u0294\u0001\u0000"+ + "\u0000\u0000\u0294\u0296\u0001\u0000\u0000\u0000\u0295\u0293\u0001\u0000"+ + "\u0000\u0000\u0296\u0297\u0003P(\u0000\u0297[\u0001\u0000\u0000\u0000"+ + "\u0298\u0299\u0005\u0001\u0000\u0000\u0299\u029a\u0005\u0090\u0000\u0000"+ + "\u029a\u029b\u0003R)\u0000\u029b\u029c\u0005\u0002\u0000\u0000\u029c\u029f"+ + "\u0001\u0000\u0000\u0000\u029d\u029f\u0003H$\u0000\u029e\u0298\u0001\u0000"+ + "\u0000\u0000\u029e\u029d\u0001\u0000\u0000\u0000\u029f]\u0001\u0000\u0000"+ + "\u0000\u02a0\u02a1\u0005\u0001\u0000\u0000\u02a1\u02a2\u0005\u008e\u0000"+ + "\u0000\u02a2\u02a3\u0005\u0001\u0000\u0000\u02a3\u02a4\u0003$\u0012\u0000"+ + "\u02a4\u02a5\u0005\u0002\u0000\u0000\u02a5\u02a9\u0005\u0085\u0000\u0000"+ + "\u02a6\u02a8\u0003 \u0010\u0000\u02a7\u02a6\u0001\u0000\u0000\u0000\u02a8"+ + "\u02ab\u0001\u0000\u0000\u0000\u02a9\u02a7\u0001\u0000\u0000\u0000\u02a9"+ + "\u02aa\u0001\u0000\u0000\u0000\u02aa\u02ac\u0001\u0000\u0000\u0000\u02ab"+ + "\u02a9\u0001\u0000\u0000\u0000\u02ac\u02ad\u0005\u0002\u0000\u0000\u02ad"+ + "_\u0001\u0000\u0000\u0000\u02ae\u02af\u0005\u0001\u0000\u0000\u02af\u02b1"+ + "\u0005\u008c\u0000\u0000\u02b0\u02b2\u0003\"\u0011\u0000\u02b1\u02b0\u0001"+ + "\u0000\u0000\u0000\u02b1\u02b2\u0001\u0000\u0000\u0000\u02b2\u02b3\u0001"+ + "\u0000\u0000\u0000\u02b3\u02b4\u0003b1\u0000\u02b4\u02b5\u0005\u0002\u0000"+ + "\u0000\u02b5a\u0001\u0000\u0000\u0000\u02b6\u02c9\u0003\u0018\f\u0000"+ + "\u02b7\u02b8\u0003r9\u0000\u02b8\u02b9\u0003\u0018\f\u0000\u02b9\u02c9"+ + "\u0001\u0000\u0000\u0000\u02ba\u02bb\u0003x<\u0000\u02bb\u02bc\u0003b"+ + "1\u0000\u02bc\u02c9\u0001\u0000\u0000\u0000\u02bd\u02be\u0003\u0006\u0003"+ + "\u0000\u02be\u02bf\u0005\u0001\u0000\u0000\u02bf\u02c3\u0005\u008e\u0000"+ + "\u0000\u02c0\u02c2\u0003 \u0010\u0000\u02c1\u02c0\u0001\u0000\u0000\u0000"+ + "\u02c2\u02c5\u0001\u0000\u0000\u0000\u02c3\u02c1\u0001\u0000\u0000\u0000"+ + "\u02c3\u02c4\u0001\u0000\u0000\u0000\u02c4\u02c6\u0001\u0000\u0000\u0000"+ + "\u02c5\u02c3\u0001\u0000\u0000\u0000\u02c6\u02c7\u0005\u0002\u0000\u0000"+ + "\u02c7\u02c9\u0001\u0000\u0000\u0000\u02c8\u02b6\u0001\u0000\u0000\u0000"+ + "\u02c8\u02b7\u0001\u0000\u0000\u0000\u02c8\u02ba\u0001\u0000\u0000\u0000"+ + "\u02c8\u02bd\u0001\u0000\u0000\u0000\u02c9c\u0001\u0000\u0000\u0000\u02ca"+ + "\u02cb\u0005\u0001\u0000\u0000\u02cb\u02cd\u0005\u008f\u0000\u0000\u02cc"+ + "\u02ce\u0003 \u0010\u0000\u02cd\u02cc\u0001\u0000\u0000\u0000\u02cd\u02ce"+ + "\u0001\u0000\u0000\u0000\u02ce\u02cf\u0001\u0000\u0000\u0000\u02cf\u02d0"+ + "\u0005\u0001\u0000\u0000\u02d0\u02d1\u0003$\u0012\u0000\u02d1\u02d5\u0005"+ + "\u0002\u0000\u0000\u02d2\u02d4\u0005\u0006\u0000\u0000\u02d3\u02d2\u0001"+ + "\u0000\u0000\u0000\u02d4\u02d7\u0001\u0000\u0000\u0000\u02d5\u02d3\u0001"+ + "\u0000\u0000\u0000\u02d5\u02d6\u0001\u0000\u0000\u0000\u02d6\u02d8\u0001"+ + "\u0000\u0000\u0000\u02d7\u02d5\u0001\u0000\u0000\u0000\u02d8\u02d9\u0005"+ + "\u0002\u0000\u0000\u02d9\u02e9\u0001\u0000\u0000\u0000\u02da\u02db\u0005"+ + "\u0001\u0000\u0000\u02db\u02dd\u0005\u008f\u0000\u0000\u02dc\u02de\u0003"+ + " \u0010\u0000\u02dd\u02dc\u0001\u0000\u0000\u0000\u02dd\u02de\u0001\u0000"+ + "\u0000\u0000\u02de\u02df\u0001\u0000\u0000\u0000\u02df\u02e3\u0003\\."+ + "\u0000\u02e0\u02e2\u0005\u0006\u0000\u0000\u02e1\u02e0\u0001\u0000\u0000"+ + "\u0000\u02e2\u02e5\u0001\u0000\u0000\u0000\u02e3\u02e1\u0001\u0000\u0000"+ + "\u0000\u02e3\u02e4\u0001\u0000\u0000\u0000\u02e4\u02e6\u0001\u0000\u0000"+ + "\u0000\u02e5\u02e3\u0001\u0000\u0000\u0000\u02e6\u02e7\u0005\u0002\u0000"+ + "\u0000\u02e7\u02e9\u0001\u0000\u0000\u0000\u02e8\u02ca\u0001\u0000\u0000"+ + "\u0000\u02e8\u02da\u0001\u0000\u0000\u0000\u02e9e\u0001\u0000\u0000\u0000"+ + "\u02ea\u02eb\u0005\u0001\u0000\u0000\u02eb\u02ed\u0005\u008d\u0000\u0000"+ + "\u02ec\u02ee\u0003\"\u0011\u0000\u02ed\u02ec\u0001\u0000\u0000\u0000\u02ed"+ + "\u02ee\u0001\u0000\u0000\u0000\u02ee\u02ef\u0001\u0000\u0000\u0000\u02ef"+ + "\u02f0\u0003h4\u0000\u02f0\u02f1\u0005\u0002\u0000\u0000\u02f1g\u0001"+ + "\u0000\u0000\u0000\u02f2\u0303\u0003\u001a\r\u0000\u02f3\u02f4\u0003r"+ + "9\u0000\u02f4\u02f5\u0003\u001a\r\u0000\u02f5\u0303\u0001\u0000\u0000"+ + "\u0000\u02f6\u02f7\u0003x<\u0000\u02f7\u02f8\u0003h4\u0000\u02f8\u0303"+ + "\u0001\u0000\u0000\u0000\u02f9\u02fa\u0005\u0001\u0000\u0000\u02fa\u02fe"+ + "\u0005\u008f\u0000\u0000\u02fb\u02fd\u0005\u0006\u0000\u0000\u02fc\u02fb"+ + "\u0001\u0000\u0000\u0000\u02fd\u0300\u0001\u0000\u0000\u0000\u02fe\u02fc"+ + "\u0001\u0000\u0000\u0000\u02fe\u02ff\u0001\u0000\u0000\u0000\u02ff\u0301"+ + "\u0001\u0000\u0000\u0000\u0300\u02fe\u0001\u0000\u0000\u0000\u0301\u0303"+ + "\u0005\u0002\u0000\u0000\u0302\u02f2\u0001\u0000\u0000\u0000\u0302\u02f3"+ + "\u0001\u0000\u0000\u0000\u0302\u02f6\u0001\u0000\u0000\u0000\u0302\u02f9"+ + "\u0001\u0000\u0000\u0000\u0303i\u0001\u0000\u0000\u0000\u0304\u0305\u0005"+ + "\u0001\u0000\u0000\u0305\u0307\u0005\u008b\u0000\u0000\u0306\u0308\u0003"+ + "\"\u0011\u0000\u0307\u0306\u0001\u0000\u0000\u0000\u0307\u0308\u0001\u0000"+ + "\u0000\u0000\u0308\u0309\u0001\u0000\u0000\u0000\u0309\u030a\u0003l6\u0000"+ + "\u030a\u030b\u0005\u0002\u0000\u0000\u030bk\u0001\u0000\u0000\u0000\u030c"+ + "\u030d\u0003\u000e\u0007\u0000\u030d\u030e\u0003R)\u0000\u030e\u0316\u0001"+ + "\u0000\u0000\u0000\u030f\u0310\u0003r9\u0000\u0310\u0311\u0003\u000e\u0007"+ + "\u0000\u0311\u0316\u0001\u0000\u0000\u0000\u0312\u0313\u0003x<\u0000\u0313"+ + "\u0314\u0003l6\u0000\u0314\u0316\u0001\u0000\u0000\u0000\u0315\u030c\u0001"+ + "\u0000\u0000\u0000\u0315\u030f\u0001\u0000\u0000\u0000\u0315\u0312\u0001"+ + "\u0000\u0000\u0000\u0316m\u0001\u0000\u0000\u0000\u0317\u0318\u0005\u0001"+ + "\u0000\u0000\u0318\u031a\u0005\u0085\u0000\u0000\u0319\u031b\u0003\"\u0011"+ + "\u0000\u031a\u0319\u0001\u0000\u0000\u0000\u031a\u031b\u0001\u0000\u0000"+ + "\u0000\u031b\u031c\u0001\u0000\u0000\u0000\u031c\u031d\u0003\u001c\u000e"+ + "\u0000\u031d\u031e\u0005\u0002\u0000\u0000\u031e\u0340\u0001\u0000\u0000"+ + "\u0000\u031f\u0320\u0005\u0001\u0000\u0000\u0320\u0322\u0005\u0085\u0000"+ + "\u0000\u0321\u0323\u0003\"\u0011\u0000\u0322\u0321\u0001\u0000\u0000\u0000"+ + "\u0322\u0323\u0001\u0000\u0000\u0000\u0323\u0324\u0001\u0000\u0000\u0000"+ + "\u0324\u0325\u0003\u0016\u000b\u0000\u0325\u0326\u0005\u0002\u0000\u0000"+ + "\u0326\u0340\u0001\u0000\u0000\u0000\u0327\u0328\u0005\u0001\u0000\u0000"+ + "\u0328\u032a\u0005\u008c\u0000\u0000\u0329\u032b\u0003\"\u0011\u0000\u032a"+ + "\u0329\u0001\u0000\u0000\u0000\u032a\u032b\u0001\u0000\u0000\u0000\u032b"+ + "\u032c\u0001\u0000\u0000\u0000\u032c\u032d\u0003\u0018\f\u0000\u032d\u032e"+ + "\u0005\u0002\u0000\u0000\u032e\u0340\u0001\u0000\u0000\u0000\u032f\u0330"+ + "\u0005\u0001\u0000\u0000\u0330\u0332\u0005\u008d\u0000\u0000\u0331\u0333"+ + "\u0003\"\u0011\u0000\u0332\u0331\u0001\u0000\u0000\u0000\u0332\u0333\u0001"+ + "\u0000\u0000\u0000\u0333\u0334\u0001\u0000\u0000\u0000\u0334\u0335\u0003"+ + "\u001a\r\u0000\u0335\u0336\u0005\u0002\u0000\u0000\u0336\u0340\u0001\u0000"+ + "\u0000\u0000\u0337\u0338\u0005\u0001\u0000\u0000\u0338\u033a\u0005\u008b"+ + "\u0000\u0000\u0339\u033b\u0003\"\u0011\u0000\u033a\u0339\u0001\u0000\u0000"+ + "\u0000\u033a\u033b\u0001\u0000\u0000\u0000\u033b\u033c\u0001\u0000\u0000"+ + "\u0000\u033c\u033d\u0003\u000e\u0007\u0000\u033d\u033e\u0005\u0002\u0000"+ + "\u0000\u033e\u0340\u0001\u0000\u0000\u0000\u033f\u0317\u0001\u0000\u0000"+ + "\u0000\u033f\u031f\u0001\u0000\u0000\u0000\u033f\u0327\u0001\u0000\u0000"+ + "\u0000\u033f\u032f\u0001\u0000\u0000\u0000\u033f\u0337\u0001\u0000\u0000"+ + "\u0000\u0340o\u0001\u0000\u0000\u0000\u0341\u0342\u0005\u0001\u0000\u0000"+ + "\u0342\u0343\u0005\u0091\u0000\u0000\u0343\u0344\u0003\u0002\u0001\u0000"+ + "\u0344\u0345\u0003\u0002\u0001\u0000\u0345\u0346\u0003n7\u0000\u0346\u0347"+ + "\u0005\u0002\u0000\u0000\u0347q\u0001\u0000\u0000\u0000\u0348\u0349\u0005"+ + "\u0001\u0000\u0000\u0349\u034a\u0005\u0091\u0000\u0000\u034a\u034b\u0003"+ + "\u0002\u0001\u0000\u034b\u034c\u0003\u0002\u0001\u0000\u034c\u034d\u0005"+ + "\u0002\u0000\u0000\u034ds\u0001\u0000\u0000\u0000\u034e\u034f\u0005\u0001"+ + "\u0000\u0000\u034f\u0350\u0005\u0085\u0000\u0000\u0350\u0351\u0003 \u0010"+ + "\u0000\u0351\u0352\u0005\u0002\u0000\u0000\u0352\u0363\u0001\u0000\u0000"+ + "\u0000\u0353\u0354\u0005\u0001\u0000\u0000\u0354\u0355\u0005\u008c\u0000"+ + "\u0000\u0355\u0356\u0003 \u0010\u0000\u0356\u0357\u0005\u0002\u0000\u0000"+ + "\u0357\u0363\u0001\u0000\u0000\u0000\u0358\u0359\u0005\u0001\u0000\u0000"+ + "\u0359\u035a\u0005\u008d\u0000\u0000\u035a\u035b\u0003 \u0010\u0000\u035b"+ + "\u035c\u0005\u0002\u0000\u0000\u035c\u0363\u0001\u0000\u0000\u0000\u035d"+ + "\u035e\u0005\u0001\u0000\u0000\u035e\u035f\u0005\u008b\u0000\u0000\u035f"+ + "\u0360\u0003 \u0010\u0000\u0360\u0361\u0005\u0002\u0000\u0000\u0361\u0363"+ + "\u0001\u0000\u0000\u0000\u0362\u034e\u0001\u0000\u0000\u0000\u0362\u0353"+ + "\u0001\u0000\u0000\u0000\u0362\u0358\u0001\u0000\u0000\u0000\u0362\u035d"+ + "\u0001\u0000\u0000\u0000\u0363u\u0001\u0000\u0000\u0000\u0364\u0365\u0005"+ + "\u0001\u0000\u0000\u0365\u0366\u0005\u0092\u0000\u0000\u0366\u0367\u0003"+ + "\u0002\u0001\u0000\u0367\u0368\u0003t:\u0000\u0368\u0369\u0005\u0002\u0000"+ + "\u0000\u0369w\u0001\u0000\u0000\u0000\u036a\u036b\u0005\u0001\u0000\u0000"+ + "\u036b\u036c\u0005\u0092\u0000\u0000\u036c\u036d\u0003\u0002\u0001\u0000"+ + "\u036d\u036e\u0005\u0002\u0000\u0000\u036ey\u0001\u0000\u0000\u0000\u036f"+ + "\u0370\u0005\u0001\u0000\u0000\u0370\u0372\u0005\u0093\u0000\u0000\u0371"+ + "\u0373\u0003\"\u0011\u0000\u0372\u0371\u0001\u0000\u0000\u0000\u0372\u0373"+ + "\u0001\u0000\u0000\u0000\u0373\u0374\u0001\u0000\u0000\u0000\u0374\u0375"+ + "\u0003\u001c\u000e\u0000\u0375\u0376\u0003\u0016\u000b\u0000\u0376\u0377"+ + "\u0005\u0002\u0000\u0000\u0377{\u0001\u0000\u0000\u0000\u0378\u0379\u0005"+ + "\u0001\u0000\u0000\u0379\u037b\u0005\u0084\u0000\u0000\u037a\u037c\u0003"+ + "\"\u0011\u0000\u037b\u037a\u0001\u0000\u0000\u0000\u037b\u037c\u0001\u0000"+ + "\u0000\u0000\u037c\u037d\u0001\u0000\u0000\u0000\u037d\u037e\u0003\u0010"+ + "\b\u0000\u037e\u037f\u0005\u0002\u0000\u0000\u037f}\u0001\u0000\u0000"+ + "\u0000\u0380\u0381\u0005\u0001\u0000\u0000\u0381\u0382\u0005\u0087\u0000"+ + "\u0000\u0382\u0383\u0003 \u0010\u0000\u0383\u0384\u0005\u0002\u0000\u0000"+ + "\u0384\u007f\u0001\u0000\u0000\u0000\u0385\u0391\u0003|>\u0000\u0386\u0391"+ + "\u0003j5\u0000\u0387\u0391\u0003`0\u0000\u0388\u0391\u0003f3\u0000\u0389"+ + "\u0391\u0003T*\u0000\u038a\u0391\u0003^/\u0000\u038b\u0391\u0003d2\u0000"+ + "\u038c\u0391\u0003~?\u0000\u038d\u0391\u0003p8\u0000\u038e\u0391\u0003"+ + "v;\u0000\u038f\u0391\u0003z=\u0000\u0390\u0385\u0001\u0000\u0000\u0000"+ + "\u0390\u0386\u0001\u0000\u0000\u0000\u0390\u0387\u0001\u0000\u0000\u0000"+ + "\u0390\u0388\u0001\u0000\u0000\u0000\u0390\u0389\u0001\u0000\u0000\u0000"+ + "\u0390\u038a\u0001\u0000\u0000\u0000\u0390\u038b\u0001\u0000\u0000\u0000"+ + "\u0390\u038c\u0001\u0000\u0000\u0000\u0390\u038d\u0001\u0000\u0000\u0000"+ + "\u0390\u038e\u0001\u0000\u0000\u0000\u0390\u038f\u0001\u0000\u0000\u0000"+ + "\u0391\u0081\u0001\u0000\u0000\u0000\u0392\u0393\u0005\u0001\u0000\u0000"+ + "\u0393\u0395\u0005\u0095\u0000\u0000\u0394\u0396\u0005\u00a8\u0000\u0000"+ + "\u0395\u0394\u0001\u0000\u0000\u0000\u0395\u0396\u0001\u0000\u0000\u0000"+ + "\u0396\u039a\u0001\u0000\u0000\u0000\u0397\u0399\u0003\u0080@\u0000\u0398"+ + "\u0397\u0001\u0000\u0000\u0000\u0399\u039c\u0001\u0000\u0000\u0000\u039a"+ + "\u0398\u0001\u0000\u0000\u0000\u039a\u039b\u0001\u0000\u0000\u0000\u039b"+ + "\u039d\u0001\u0000\u0000\u0000\u039c\u039a\u0001\u0000\u0000\u0000\u039d"+ + "\u039e\u0005\u0002\u0000\u0000\u039e\u0083\u0001\u0000\u0000\u0000\u039f"+ + "\u03bc\u0003\u0082A\u0000\u03a0\u03a1\u0005\u0001\u0000\u0000\u03a1\u03a3"+ + "\u0005\u0095\u0000\u0000\u03a2\u03a4\u0005\u00a8\u0000\u0000\u03a3\u03a2"+ + "\u0001\u0000\u0000\u0000\u03a3\u03a4\u0001\u0000\u0000\u0000\u03a4\u03a5"+ + "\u0001\u0000\u0000\u0000\u03a5\u03a9\u0007\u0003\u0000\u0000\u03a6\u03a8"+ + "\u0005\u0006\u0000\u0000\u03a7\u03a6\u0001\u0000\u0000\u0000\u03a8\u03ab"+ + "\u0001\u0000\u0000\u0000\u03a9\u03a7\u0001\u0000\u0000\u0000\u03a9\u03aa"+ + "\u0001\u0000\u0000\u0000\u03aa\u03ac\u0001\u0000\u0000\u0000\u03ab\u03a9"+ + "\u0001\u0000\u0000\u0000\u03ac\u03bc\u0005\u0002\u0000\u0000\u03ad\u03ae"+ + "\u0005\u0001\u0000\u0000\u03ae\u03af\u0005\u0095\u0000\u0000\u03af\u03b1"+ + "\u0005\u0098\u0000\u0000\u03b0\u03b2\u0005\u00a8\u0000\u0000\u03b1\u03b0"+ + "\u0001\u0000\u0000\u0000\u03b1\u03b2\u0001\u0000\u0000\u0000\u03b2\u03b3"+ + "\u0001\u0000\u0000\u0000\u03b3\u03b7\u0005\u0096\u0000\u0000\u03b4\u03b6"+ + "\u0005\u0006\u0000\u0000\u03b5\u03b4\u0001\u0000\u0000\u0000\u03b6\u03b9"+ + "\u0001\u0000\u0000\u0000\u03b7\u03b5\u0001\u0000\u0000\u0000\u03b7\u03b8"+ + "\u0001\u0000\u0000\u0000\u03b8\u03ba\u0001\u0000\u0000\u0000\u03b9\u03b7"+ + "\u0001\u0000\u0000\u0000\u03ba\u03bc\u0005\u0002\u0000\u0000\u03bb\u039f"+ + "\u0001\u0000\u0000\u0000\u03bb\u03a0\u0001\u0000\u0000\u0000\u03bb\u03ad"+ + "\u0001\u0000\u0000\u0000\u03bc\u0085\u0001\u0000\u0000\u0000\u03bd\u03be"+ + "\u0005\u0001\u0000\u0000\u03be\u03c0\u0005\u009c\u0000\u0000\u03bf\u03c1"+ + "\u0005\u00a8\u0000\u0000\u03c0\u03bf\u0001\u0000\u0000\u0000\u03c0\u03c1"+ + "\u0001\u0000\u0000\u0000\u03c1\u03c2\u0001\u0000\u0000\u0000\u03c2\u03c3"+ + "\u0003\u0002\u0001\u0000\u03c3\u03c4\u0003\u0092I\u0000\u03c4\u03c5\u0005"+ + "\u0002\u0000\u0000\u03c5\u03cf\u0001\u0000\u0000\u0000\u03c6\u03c7\u0005"+ + "\u0001\u0000\u0000\u03c7\u03c9\u0005\u009d\u0000\u0000\u03c8\u03ca\u0005"+ + "\u00a8\u0000\u0000\u03c9\u03c8\u0001\u0000\u0000\u0000\u03c9\u03ca\u0001"+ + "\u0000\u0000\u0000\u03ca\u03cb\u0001\u0000\u0000\u0000\u03cb\u03cc\u0003"+ + "\u0002\u0001\u0000\u03cc\u03cd\u0005\u0002\u0000\u0000\u03cd\u03cf\u0001"+ + "\u0000\u0000\u0000\u03ce\u03bd\u0001\u0000\u0000\u0000\u03ce\u03c6\u0001"+ + "\u0000\u0000\u0000\u03cf\u0087\u0001\u0000\u0000\u0000\u03d0\u03d1\u0005"+ + "\u0001\u0000\u0000\u03d1\u03d2\u0005\u009e\u0000\u0000\u03d2\u03d3\u0003"+ + "\u0084B\u0000\u03d3\u03d4\u0005\u0006\u0000\u0000\u03d4\u03d5\u0005\u0002"+ + "\u0000\u0000\u03d5\u0405\u0001\u0000\u0000\u0000\u03d6\u03d7\u0005\u0001"+ + "\u0000\u0000\u03d7\u03d8\u0005\u009f\u0000\u0000\u03d8\u03d9\u0003\u0084"+ + "B\u0000\u03d9\u03da\u0005\u0006\u0000\u0000\u03da\u03db\u0005\u0002\u0000"+ + "\u0000\u03db\u0405\u0001\u0000\u0000\u0000\u03dc\u03dd\u0005\u0001\u0000"+ + "\u0000\u03dd\u03de\u0005\u00a0\u0000\u0000\u03de\u03df\u0003\u0084B\u0000"+ + "\u03df\u03e0\u0005\u0006\u0000\u0000\u03e0\u03e1\u0005\u0002\u0000\u0000"+ + "\u03e1\u0405\u0001\u0000\u0000\u0000\u03e2\u03e3\u0005\u0001\u0000\u0000"+ + "\u03e3\u03e4\u0005\u00a4\u0000\u0000\u03e4\u03e5\u0003\u0084B\u0000\u03e5"+ + "\u03e6\u0005\u0006\u0000\u0000\u03e6\u03e7\u0005\u0002\u0000\u0000\u03e7"+ + "\u0405\u0001\u0000\u0000\u0000\u03e8\u03e9\u0005\u0001\u0000\u0000\u03e9"+ + "\u03ea\u0005\u00a1\u0000\u0000\u03ea\u03eb\u0003\u0086C\u0000\u03eb\u03ec"+ + "\u0003\u0092I\u0000\u03ec\u03ed\u0005\u0002\u0000\u0000\u03ed\u0405\u0001"+ + "\u0000\u0000\u0000\u03ee\u03ef\u0005\u0001\u0000\u0000\u03ef\u03f0\u0005"+ + "\u00a2\u0000\u0000\u03f0\u03f1\u0003\u0086C\u0000\u03f1\u03f2\u0005\u0002"+ + "\u0000\u0000\u03f2\u0405\u0001\u0000\u0000\u0000\u03f3\u03f4\u0005\u0001"+ + "\u0000\u0000\u03f4\u03f5\u0005\u00a3\u0000\u0000\u03f5\u03f6\u0003\u0086"+ + "C\u0000\u03f6\u03f7\u0005\u0002\u0000\u0000\u03f7\u0405\u0001\u0000\u0000"+ + "\u0000\u03f8\u03f9\u0005\u0001\u0000\u0000\u03f9\u03fa\u0005\u00a4\u0000"+ + "\u0000\u03fa\u03fb\u0003\u0086C\u0000\u03fb\u03fc\u0005\u0006\u0000\u0000"+ + "\u03fc\u03fd\u0005\u0002\u0000\u0000\u03fd\u0405\u0001\u0000\u0000\u0000"+ + "\u03fe\u03ff\u0005\u0001\u0000\u0000\u03ff\u0400\u0005\u00a5\u0000\u0000"+ + "\u0400\u0401\u0003\u0086C\u0000\u0401\u0402\u0005\u0006\u0000\u0000\u0402"+ + "\u0403\u0005\u0002\u0000\u0000\u0403\u0405\u0001\u0000\u0000\u0000\u0404"+ + "\u03d0\u0001\u0000\u0000\u0000\u0404\u03d6\u0001\u0000\u0000\u0000\u0404"+ + "\u03dc\u0001\u0000\u0000\u0000\u0404\u03e2\u0001\u0000\u0000\u0000\u0404"+ + "\u03e8\u0001\u0000\u0000\u0000\u0404\u03ee\u0001\u0000\u0000\u0000\u0404"+ + "\u03f3\u0001\u0000\u0000\u0000\u0404\u03f8\u0001\u0000\u0000\u0000\u0404"+ + "\u03fe\u0001\u0000\u0000\u0000\u0405\u0089\u0001\u0000\u0000\u0000\u0406"+ + "\u0414\u0003\u0086C\u0000\u0407\u0414\u0003\u0088D\u0000\u0408\u0414\u0003"+ + "\u0084B\u0000\u0409\u040a\u0005\u0001\u0000\u0000\u040a\u040b\u0005\u009b"+ + "\u0000\u0000\u040b\u040d\u0003\u0002\u0001\u0000\u040c\u040e\u0005\u00a8"+ + "\u0000\u0000\u040d\u040c\u0001\u0000\u0000\u0000\u040d\u040e\u0001\u0000"+ + "\u0000\u0000\u040e\u040f\u0001\u0000\u0000\u0000\u040f\u0410\u0005\u0002"+ + "\u0000\u0000\u0410\u0414\u0001\u0000\u0000\u0000\u0411\u0414\u0003\u008e"+ + "G\u0000\u0412\u0414\u0003\u008cF\u0000\u0413\u0406\u0001\u0000\u0000\u0000"+ + "\u0413\u0407\u0001\u0000\u0000\u0000\u0413\u0408\u0001\u0000\u0000\u0000"+ + "\u0413\u0409\u0001\u0000\u0000\u0000\u0413\u0411\u0001\u0000\u0000\u0000"+ + "\u0413\u0412\u0001\u0000\u0000\u0000\u0414\u008b\u0001\u0000\u0000\u0000"+ + "\u0415\u0416\u0005\u0001\u0000\u0000\u0416\u0417\u0005\u0095\u0000\u0000"+ + "\u0417\u0419\u0005\u0099\u0000\u0000\u0418\u041a\u0005\u00a8\u0000\u0000"+ + "\u0419\u0418\u0001\u0000\u0000\u0000\u0419\u041a\u0001\u0000\u0000\u0000"+ + "\u041a\u041c\u0001\u0000\u0000\u0000\u041b\u041d\u0005\u00a8\u0000\u0000"+ + "\u041c\u041b\u0001\u0000\u0000\u0000\u041c\u041d\u0001\u0000\u0000\u0000"+ + "\u041d\u041e\u0001\u0000\u0000\u0000\u041e\u041f\u0005\u0002\u0000\u0000"+ + "\u041f\u008d\u0001\u0000\u0000\u0000\u0420\u0421\u0005\u0001\u0000\u0000"+ + "\u0421\u0423\u0005\u009a\u0000\u0000\u0422\u0424\u0005\u00a8\u0000\u0000"+ + "\u0423\u0422\u0001\u0000\u0000\u0000\u0423\u0424\u0001\u0000\u0000\u0000"+ + "\u0424\u0428\u0001\u0000\u0000\u0000\u0425\u0427\u0003\u008aE\u0000\u0426"+ + "\u0425\u0001\u0000\u0000\u0000\u0427\u042a\u0001\u0000\u0000\u0000\u0428"+ + "\u0426\u0001\u0000\u0000\u0000\u0428\u0429\u0001\u0000\u0000\u0000\u0429"+ + "\u042b\u0001\u0000\u0000\u0000\u042a\u0428\u0001\u0000\u0000\u0000\u042b"+ + "\u0441\u0005\u0002\u0000\u0000\u042c\u042d\u0005\u0001\u0000\u0000\u042d"+ + "\u042f\u0005\u00a6\u0000\u0000\u042e\u0430\u0005\u00a8\u0000\u0000\u042f"+ + "\u042e\u0001\u0000\u0000\u0000\u042f\u0430\u0001\u0000\u0000\u0000\u0430"+ + "\u0431\u0001\u0000\u0000\u0000\u0431\u0432\u0005\u0006\u0000\u0000\u0432"+ + "\u0441\u0005\u0002\u0000\u0000\u0433\u0434\u0005\u0001\u0000\u0000\u0434"+ + "\u0436\u0005\u00a7\u0000\u0000\u0435\u0437\u0005\u00a8\u0000\u0000\u0436"+ + "\u0435\u0001\u0000\u0000\u0000\u0436\u0437\u0001\u0000\u0000\u0000\u0437"+ + "\u0438\u0001\u0000\u0000\u0000\u0438\u0439\u0005\u0006\u0000\u0000\u0439"+ + "\u0441\u0005\u0002\u0000\u0000\u043a\u043b\u0005\u0001\u0000\u0000\u043b"+ + "\u043d\u0005\u00a7\u0000\u0000\u043c\u043e\u0005\u00a8\u0000\u0000\u043d"+ + "\u043c\u0001\u0000\u0000\u0000\u043d\u043e\u0001\u0000\u0000\u0000\u043e"+ + "\u043f\u0001\u0000\u0000\u0000\u043f\u0441\u0005\u0002\u0000\u0000\u0440"+ + "\u0420\u0001\u0000\u0000\u0000\u0440\u042c\u0001\u0000\u0000\u0000\u0440"+ + "\u0433\u0001\u0000\u0000\u0000\u0440\u043a\u0001\u0000\u0000\u0000\u0441"+ + "\u008f\u0001\u0000\u0000\u0000\u0442\u0443\u0005\u0001\u0000\u0000\u0443"+ + "\u0444\u0005\b\u0000\u0000\u0444\u0445\u0003\u001e\u000f\u0000\u0445\u0446"+ + "\u0005\u0002\u0000\u0000\u0446\u0091\u0001\u0000\u0000\u0000\u0447\u0449"+ + "\u0003\u0090H\u0000\u0448\u0447\u0001\u0000\u0000\u0000\u0449\u044c\u0001"+ + "\u0000\u0000\u0000\u044a\u0448\u0001\u0000\u0000\u0000\u044a\u044b\u0001"+ + "\u0000\u0000\u0000\u044b\u0093\u0001\u0000\u0000\u0000\u044c\u044a\u0001"+ + "\u0000\u0000\u0000\u044d\u044f\u0003\u008aE\u0000\u044e\u044d\u0001\u0000"+ + "\u0000\u0000\u044f\u0452\u0001\u0000\u0000\u0000\u0450\u044e\u0001\u0000"+ + "\u0000\u0000\u0450\u0451\u0001\u0000\u0000\u0000\u0451\u0453\u0001\u0000"+ + "\u0000\u0000\u0452\u0450\u0001\u0000\u0000\u0000\u0453\u045c\u0005\u0000"+ + "\u0000\u0001\u0454\u0456\u0003\u0080@\u0000\u0455\u0454\u0001\u0000\u0000"+ + "\u0000\u0456\u0457\u0001\u0000\u0000\u0000\u0457\u0455\u0001\u0000\u0000"+ + "\u0000\u0457\u0458\u0001\u0000\u0000\u0000\u0458\u0459\u0001\u0000\u0000"+ + "\u0000\u0459\u045a\u0005\u0000\u0000\u0001\u045a\u045c\u0001\u0000\u0000"+ + "\u0000\u045b\u0450\u0001\u0000\u0000\u0000\u045b\u0455\u0001\u0000\u0000"+ + "\u0000\u045c\u0095\u0001\u0000\u0000\u0000\u045d\u045e\u0003\u0082A\u0000"+ + "\u045e\u045f\u0005\u0000\u0000\u0001\u045f\u0468\u0001\u0000\u0000\u0000"+ + "\u0460\u0462\u0003\u0080@\u0000\u0461\u0460\u0001\u0000\u0000\u0000\u0462"+ + "\u0465\u0001\u0000\u0000\u0000\u0463\u0461\u0001\u0000\u0000\u0000\u0463"+ + "\u0464\u0001\u0000\u0000\u0000\u0464\u0466\u0001\u0000\u0000\u0000\u0465"+ + "\u0463\u0001\u0000\u0000\u0000\u0466\u0468\u0005\u0000\u0000\u0001\u0467"+ + "\u045d\u0001\u0000\u0000\u0000\u0467\u0463\u0001\u0000\u0000\u0000\u0468"+ + "\u0097\u0001\u0000\u0000\u0000t\u00ab\u00b2\u00b7\u00bf\u00cb\u00d2\u00d8"+ + "\u00dd\u00e5\u00eb\u00f3\u00f9\u010b\u0123\u0136\u0139\u013d\u0140\u0165"+ + "\u016c\u0185\u018a\u018d\u0194\u019a\u01a2\u01a8\u01b0\u01b6\u01c0\u01c6"+ + "\u01cd\u01d2\u01d6\u01db\u01df\u01e4\u01e7\u01eb\u01f3\u01fa\u0200\u020d"+ + "\u0216\u021b\u0220\u0226\u0231\u0233\u0236\u023f\u0245\u024f\u0255\u025b"+ + "\u0261\u0265\u026c\u0272\u0277\u027e\u0288\u028e\u0293\u029e\u02a9\u02b1"+ + "\u02c3\u02c8\u02cd\u02d5\u02dd\u02e3\u02e8\u02ed\u02fe\u0302\u0307\u0315"+ + "\u031a\u0322\u032a\u0332\u033a\u033f\u0362\u0372\u037b\u0390\u0395\u039a"+ + "\u03a3\u03a9\u03b1\u03b7\u03bb\u03c0\u03c9\u03ce\u0404\u040d\u0413\u0419"+ + "\u041c\u0423\u0428\u042f\u0436\u043d\u0440\u044a\u0450\u0457\u045b\u0463"+ + "\u0467"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/main/scala/wasm/Parser.scala b/src/main/scala/wasm/Parser.scala index d88dbf87..ddc1c4b9 100644 --- a/src/main/scala/wasm/Parser.scala +++ b/src/main/scala/wasm/Parser.scala @@ -340,10 +340,17 @@ class GSWasmVisitor extends WatParserBaseVisitor[WIR] { else if (ctx.GLOBAL_GET() != null) GlobalGet(getVar(ctx.idx(0)).toInt) else if (ctx.load() != null) { val ty = visitNumType(ctx.load.numType) - val (memSize, sign) = if (ctx.load.MEM_SIZE() != null) { - (Some(visitMemSize(ctx.load.MEM_SIZE.getText)), - Some(visitSignExt(ctx.load.SIGN_POSTFIX.getText))) - } else (None, None) + val opStr = ctx.load.LOAD.getText.stripPrefix(".") + val (memSize, sign) = opStr match { + case "load" => (None, None) + case "load8_s" => (Some(Pack8), Some(SX)) + case "load8_u" => (Some(Pack8), Some(ZX)) + case "load16_s" => (Some(Pack16), Some(SX)) + case "load16_u" => (Some(Pack16), Some(ZX)) + case "load32_s" => (Some(Pack32), Some(SX)) + case "load32_u" => (Some(Pack32), Some(ZX)) + case _ => throw new RuntimeException(s"Unsupported load opcode: ${ctx.load.LOAD.getText}") + } val offset = if (ctx.offsetEq() != null) { ctx.offsetEq.NAT.getText.toInt } else 0 @@ -354,9 +361,14 @@ class GSWasmVisitor extends WatParserBaseVisitor[WIR] { } else if (ctx.store() != null) { val ty = visitNumType(ctx.store.numType) - val memSize = if (ctx.store.MEM_SIZE() != null) { - Some(visitMemSize(ctx.store.MEM_SIZE.getText)) - } else None + val opStr = ctx.store.STORE.getText.stripPrefix(".") + val memSize = opStr match { + case "store" => None + case "store8" => Some(Pack8) + case "store16" => Some(Pack16) + case "store32" => Some(Pack32) + case _ => throw new RuntimeException(s"Unsupported store opcode: ${ctx.store.STORE.getText}") + } val offset = if (ctx.offsetEq() != null) { ctx.offsetEq.NAT.getText.toInt } else 0 From 0f4fb59d6726d4989acc38b9499c378684ba7c2c Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Thu, 12 Mar 2026 02:01:41 -0400 Subject: [PATCH 05/16] support all memory operations --- benchmarks/wasm/mem-sym.wat | 394 ++++++++++++++++-- headers/wasm/concrete_rt.hpp | 95 +++++ headers/wasm/sym_rt.hpp | 94 +++++ headers/wasm/symval_factory.hpp | 10 +- src/main/scala/wasm/Parser.scala | 4 +- .../scala/wasm/StagedConcolicMiniWasm.scala | 236 +++++++++-- 6 files changed, 764 insertions(+), 69 deletions(-) diff --git a/benchmarks/wasm/mem-sym.wat b/benchmarks/wasm/mem-sym.wat index 187682ec..0e95453b 100644 --- a/benchmarks/wasm/mem-sym.wat +++ b/benchmarks/wasm/mem-sym.wat @@ -3,8 +3,256 @@ (type (;1;) (func)) (type (;2;) (func (param i32) (result i32))) (type (;3;) (func (param i32))) - (import "console" "assert" (func (type 3))) - (func (;1;) (type 2) (param i32) (result i32) + (import "console" "assert" (func (;0;) (type 3))) + + ;; Concrete memory operations. + ;; Address layout: + ;; 0..39 : i32 tests + ;; 40..95 : i64 tests + ;; 96..111 : floating-point tests + (func (;1;) (type 1) + ;; Full-width i32 roundtrip. + i32.const 0 + i32.const 0x11223344 ;; bytes in memory: 44 33 22 11 + i32.store ;; write 4 bytes at address 0 + i32.const 0 + i32.load ;; read the same 4 bytes back + i32.const 0x11223344 + i32.ne + if + i32.const 0 + call 0 + end + + ;; Concrete i32.store8 / i32.load8_u. + ;; Only the low byte 0xcd is written, at address 17. + i32.const 16 + i32.const 0 + i32.store + i32.const 17 + i32.const 0xabcd + i32.store8 ;; keeps only byte 0xcd + i32.const 16 + i32.load ;; expect byte 1 of the word to become 0xcd + i32.const 0x0000cd00 + i32.ne + if + i32.const 0 + call 0 + end + i32.const 17 + i32.load8_u ;; zero-extend one byte to i32 + i32.const 0xcd + i32.ne + if + i32.const 0 + call 0 + end + + ;; Concrete i32.load8_s should sign-extend 0xef to -17. + i32.const 20 + i32.const 0xef ;; signed 8-bit value -17 + i32.store8 + i32.const 20 + i32.load8_s ;; sign-extend one byte to i32 + i32.const -17 + i32.ne + if + i32.const 0 + call 0 + end + + ;; Concrete i32.store16 / i32.load16_u. + ;; 0xabcd is written as bytes cd ab in little-endian order. + i32.const 24 + i32.const 0 + i32.store + i32.const 25 + i32.const 0xabcd + i32.store16 ;; write bytes at addresses 25 and 26 + i32.const 24 + i32.load ;; expect bytes 1..2 of the word to be cd ab + i32.const 0x00abcd00 + i32.ne + if + i32.const 0 + call 0 + end + i32.const 25 + i32.load16_u ;; zero-extend 16 bits to i32 + i32.const 0xabcd + i32.ne + if + i32.const 0 + call 0 + end + + ;; Concrete i32.load16_s should sign-extend 0xcdef. + i32.const 32 + i32.const 0xcdef ;; signed 16-bit value -12817 + i32.store16 + i32.const 32 + i32.load16_s ;; sign-extend 16 bits to i32 + i32.const -12817 + i32.ne + if + i32.const 0 + call 0 + end + + ;; Full-width i64 roundtrip. + i32.const 40 + i64.const 0x0102030405060708 + i64.store ;; write 8 bytes at address 40 + i32.const 40 + i64.load ;; read the same 8 bytes back + i64.const 0x0102030405060708 + i64.ne + if + i32.const 0 + call 0 + end + + ;; Concrete i64.store8 / i64.load8_u. + ;; Even for i64, store8 writes just one byte. + i32.const 48 + i64.const 0 + i64.store + i32.const 49 + i64.const 0xabcdef + i64.store8 ;; keeps only byte 0xef + i32.const 49 + i64.load8_u ;; zero-extend one byte to i64 + i64.const 0xef + i64.ne + if + i32.const 0 + call 0 + end + + ;; Concrete i64.load8_s should sign-extend 0xef to -17. + i32.const 50 + i64.const 0xef + i64.store8 + i32.const 50 + i64.load8_s ;; sign-extend one byte to i64 + i64.const -17 + i64.ne + if + i32.const 0 + call 0 + end + + ;; Concrete i64.store16 / i64.load16_u. + i32.const 56 + i64.const 0 + i64.store + i32.const 57 + i64.const 0xabcd + i64.store16 ;; write bytes cd ab + i32.const 57 + i64.load16_u ;; zero-extend 16 bits to i64 + i64.const 0xabcd + i64.ne + if + i32.const 0 + call 0 + end + + ;; Concrete i64.load16_s should sign-extend 0xcdef. + i32.const 60 + i64.const 0xcdef + i64.store16 + i32.const 60 + i64.load16_s ;; sign-extend 16 bits to i64 + i64.const -12817 + i64.ne + if + i32.const 0 + call 0 + end + + ;; i64.store32 should overwrite only the upper 4 bytes of the 64-bit word at 64. + ;; Start with: 08 07 06 05 04 03 02 01 + ;; After store32 at address 68: 08 07 06 05 dd cc bb aa + i32.const 64 + i64.const 0x0102030405060708 + i64.store + i32.const 68 + i64.const 0xaabbccdd + i64.store32 + i32.const 64 + i64.load + i64.const 0xaabbccdd05060708 + i64.ne + if + i32.const 0 + call 0 + end + + ;; i64.load32_u should zero-extend the stored low 32 bits to i64. + i32.const 80 + i64.const 0 + i64.store + i32.const 80 + i64.const 0x89abcdef + i64.store32 ;; low 32 bits in memory: ef cd ab 89 + i32.const 80 + i64.load32_u ;; expect 0x0000000089abcdef + i64.const 0x89abcdef + i64.ne + if + i32.const 0 + call 0 + end + + ;; i64.load32_s should sign-extend the stored low 32 bits to i64. + i32.const 88 + i64.const 0 + i64.store + i32.const 88 + i64.const 0x89abcdef + i64.store32 + i32.const 88 + i64.load32_s ;; expect 0xffffffff89abcdef + i64.const -1985229329 + i64.ne + if + i32.const 0 + call 0 + end + + ;; Full-width f32 roundtrip. + i32.const 96 + f32.const 1.5 + f32.store + i32.const 96 + f32.load + f32.const 1.5 + f32.ne + if + i32.const 0 + call 0 + end + + ;; Full-width f64 roundtrip. + i32.const 104 + f64.const 3.25 + f64.store + i32.const 104 + f64.load + f64.const 3.25 + f64.ne + if + i32.const 0 + call 0 + end + ) + + ;; Symbolic i32 memory operations only. + ;; This exercises symbolic full-width i32 stores plus packed i32 store/load behavior. + (func (;2;) (type 3) (param i32) + ;; Full-width symbolic i32 store/load interaction. i32.const 0 local.get 0 i32.store @@ -12,56 +260,136 @@ i32.load i32.const 25 i32.eq - if ;; if x == 25 + if i32.const 0 - call 0 ;; assert false + call 0 end + i32.const 1 i32.load i32.const 1 i32.eq - if ;; if x >> 8 == 1 + if i32.const 0 - call 0 ;; assert false + call 0 end - i32.const 4 - i64.load - i64.eqz - i32.eqz + + ;; store8 should update only one byte of the word at 16. + ;; Expected word: (x & 0xff) shifted into byte position 1. + i32.const 16 + i32.const 0 + i32.store + i32.const 17 + local.get 0 + i32.store8 + i32.const 16 + i32.load + local.get 0 + i32.const 255 + i32.and + i32.const 8 + i32.shl + i32.ne if i32.const 0 - call 0 ;; assert false + call 0 end + + ;; store16 should update only two bytes of the word at 20. + ;; Expected word: (x & 0xffff) shifted into byte positions 1 and 2. + i32.const 20 i32.const 0 - i64.load - i64.const 32 - i64.shr_u - i64.eqz - i32.eqz + i32.store + i32.const 21 + local.get 0 + i32.store16 + i32.const 20 + i32.load + local.get 0 + i32.const 65535 + i32.and + i32.const 8 + i32.shl + i32.ne if i32.const 0 - call 0 ;; assert false + call 0 end - i32.const 8 - i64.const 0x0102030405060708 - i64.store - i32.const 8 - i64.load - i64.const 0x0102030405060708 - i64.ne + + ;; load8_u should produce the low byte of x, zero-extended to i32. + i32.const 32 + i32.const 0 + i32.store + i32.const 32 + local.get 0 + i32.store8 + i32.const 32 + i32.load8_u + local.get 0 + i32.const 255 + i32.and + i32.ne if i32.const 0 - call 0 ;; assert false + call 0 end - i32.const 1 - ) - (func (;2;) (type 1) + + ;; load8_s should sign-extend the low byte of x. + ;; `(x << 24) >> 24` is the expected i32 sign-extension formula. + i32.const 36 + i32.const 0 + i32.store + i32.const 36 + local.get 0 + i32.store8 + i32.const 36 + i32.load8_s + local.get 0 + i32.const 24 + i32.shl + i32.const 24 + i32.shr_s + i32.ne + if + i32.const 0 + call 0 + end + + ;; load16_u should produce the low 16 bits of x, zero-extended to i32. + i32.const 40 i32.const 0 - i32.symbolic ;; call it x + i32.store + i32.const 40 + local.get 0 + i32.store16 + i32.const 40 + i32.load16_u + local.get 0 + i32.const 65535 + i32.and + i32.ne + if + i32.const 0 + call 0 + end +) + + + ;; Driver: run the concrete test first, then run the symbolic-i32 test. + (func (;3;) (type 2) (param i32) (result i32) call 1 - ) - (start 2) + local.get 0 + call 2 + i32.const 1) + + ;; Entry point: create one symbolic i32 and pass it to the symbolic test. + (func (;4;) (type 1) + i32.const 0 + i32.symbolic + call 3 + drop) + (memory (;0;) 2) - (export "main" (func 1)) (global (;0;) (mut i32) (i32.const 42)) -) + (export "main" (func 3)) + (start 4)) diff --git a/headers/wasm/concrete_rt.hpp b/headers/wasm/concrete_rt.hpp index 6584eba2..3e54baac 100644 --- a/headers/wasm/concrete_rt.hpp +++ b/headers/wasm/concrete_rt.hpp @@ -280,6 +280,73 @@ struct Memory_t { return result; } + uint8_t loadByte(int32_t base, int32_t offset) { + int32_t addr = base + offset; + if (!(addr < memory.size()) || addr < 0) { + throw std::runtime_error("Invalid memory access " + std::to_string(addr)); + } + return memory[addr]; + } + + int32_t loadInt8U(int32_t base, int32_t offset) { + return static_cast(loadByte(base, offset)); + } + + int32_t loadInt8S(int32_t base, int32_t offset) { + return static_cast(loadByte(base, offset)); + } + + int32_t loadInt16U(int32_t base, int32_t offset) { + uint32_t b0 = static_cast(loadByte(base, offset)); + uint32_t b1 = static_cast(loadByte(base, offset + 1)); + return static_cast(b0 | (b1 << 8)); + } + + int32_t loadInt16S(int32_t base, int32_t offset) { + uint32_t b0 = static_cast(loadByte(base, offset)); + uint32_t b1 = static_cast(loadByte(base, offset + 1)); + uint16_t raw = static_cast(b0 | (b1 << 8)); + return static_cast(raw); + } + + int64_t loadLong8U(int32_t base, int32_t offset) { + return static_cast(loadByte(base, offset)); + } + + int64_t loadLong8S(int32_t base, int32_t offset) { + return static_cast(loadByte(base, offset)); + } + + int64_t loadLong16U(int32_t base, int32_t offset) { + uint64_t b0 = static_cast(loadByte(base, offset)); + uint64_t b1 = static_cast(loadByte(base, offset + 1)); + return static_cast(b0 | (b1 << 8)); + } + + int64_t loadLong16S(int32_t base, int32_t offset) { + uint64_t b0 = static_cast(loadByte(base, offset)); + uint64_t b1 = static_cast(loadByte(base, offset + 1)); + uint16_t raw = static_cast(b0 | (b1 << 8)); + return static_cast(raw); + } + + int64_t loadLong32U(int32_t base, int32_t offset) { + uint64_t b0 = static_cast(loadByte(base, offset)); + uint64_t b1 = static_cast(loadByte(base, offset + 1)); + uint64_t b2 = static_cast(loadByte(base, offset + 2)); + uint64_t b3 = static_cast(loadByte(base, offset + 3)); + return static_cast(b0 | (b1 << 8) | (b2 << 16) | (b3 << 24)); + } + + int64_t loadLong32S(int32_t base, int32_t offset) { + uint64_t b0 = static_cast(loadByte(base, offset)); + uint64_t b1 = static_cast(loadByte(base, offset + 1)); + uint64_t b2 = static_cast(loadByte(base, offset + 2)); + uint64_t b3 = static_cast(loadByte(base, offset + 3)); + uint32_t raw = static_cast(b0 | (b1 << 8) | (b2 << 16) | (b3 << 24)); + return static_cast(raw); + } + int64_t loadLong(int32_t base, int32_t offset) { int32_t addr = base + offset; if (!(addr + 7 < memory.size()) || addr < 0) { @@ -319,6 +386,34 @@ struct Memory_t { return std::monostate{}; } + std::monostate storeInt8(int32_t base, int32_t offset, int32_t value) { + return store_byte(base + offset, static_cast(value & 0xFF)); + } + + std::monostate storeInt16(int32_t base, int32_t offset, int32_t value) { + store_byte(base + offset, static_cast(value & 0xFF)); + store_byte(base + offset + 1, static_cast((value >> 8) & 0xFF)); + return std::monostate{}; + } + + std::monostate storeLong8(int32_t base, int32_t offset, int64_t value) { + return store_byte(base + offset, static_cast(value & 0xFF)); + } + + std::monostate storeLong16(int32_t base, int32_t offset, int64_t value) { + store_byte(base + offset, static_cast(value & 0xFF)); + store_byte(base + offset + 1, static_cast((value >> 8) & 0xFF)); + return std::monostate{}; + } + + std::monostate storeLong32(int32_t base, int32_t offset, int64_t value) { + store_byte(base + offset, static_cast(value & 0xFF)); + store_byte(base + offset + 1, static_cast((value >> 8) & 0xFF)); + store_byte(base + offset + 2, static_cast((value >> 16) & 0xFF)); + store_byte(base + offset + 3, static_cast((value >> 24) & 0xFF)); + return std::monostate{}; + } + std::monostate store_byte(int32_t addr, uint8_t value) { #ifdef DEBUG std::cout << "[Debug] storing byte " << std::to_string(value) diff --git a/headers/wasm/sym_rt.hpp b/headers/wasm/sym_rt.hpp index b0d025ef..760112b5 100644 --- a/headers/wasm/sym_rt.hpp +++ b/headers/wasm/sym_rt.hpp @@ -376,6 +376,64 @@ class SymMemory_t { } } + SymVal loadSymInt8U(int32_t base, int32_t offset) { + return SVFactory::make_smallbv(24, 0).concat(loadSymByte(base + offset)); + } + + SymVal loadSymInt8S(int32_t base, int32_t offset) { + auto value = loadSymInt8U(base, offset); + auto shift = SVFactory::make_concrete_bv(I32V(24), 32); + return value.shl(shift).shr_s(shift); + } + + SymVal loadSymInt16U(int32_t base, int32_t offset) { + auto low = loadSymByte(base + offset); + auto high = loadSymByte(base + offset + 1); + return SVFactory::make_smallbv(16, 0).concat(high).concat(low); + } + + SymVal loadSymInt16S(int32_t base, int32_t offset) { + auto value = loadSymInt16U(base, offset); + auto shift = SVFactory::make_concrete_bv(I32V(16), 32); + return value.shl(shift).shr_s(shift); + } + + SymVal loadSymLong8U(int32_t base, int32_t offset) { + return SVFactory::make_smallbv(56, 0).concat(loadSymByte(base + offset)); + } + + SymVal loadSymLong8S(int32_t base, int32_t offset) { + auto value = loadSymLong8U(base, offset); + auto shift = SVFactory::make_concrete_bv(I64V(56), 64); + return value.shl(shift).shr_s(shift); + } + + SymVal loadSymLong16U(int32_t base, int32_t offset) { + auto low = loadSymByte(base + offset); + auto high = loadSymByte(base + offset + 1); + return SVFactory::make_smallbv(48, 0).concat(high).concat(low); + } + + SymVal loadSymLong16S(int32_t base, int32_t offset) { + auto value = loadSymLong16U(base, offset); + auto shift = SVFactory::make_concrete_bv(I64V(48), 64); + return value.shl(shift).shr_s(shift); + } + + SymVal loadSymLong32U(int32_t base, int32_t offset) { + auto b0 = loadSymByte(base + offset); + auto b1 = loadSymByte(base + offset + 1); + auto b2 = loadSymByte(base + offset + 2); + auto b3 = loadSymByte(base + offset + 3); + return SVFactory::make_smallbv(32, 0).concat(b3).concat(b2).concat(b1).concat(b0); + } + + SymVal loadSymLong32S(int32_t base, int32_t offset) { + auto value = loadSymLong32U(base, offset); + auto shift = SVFactory::make_concrete_bv(I64V(32), 64); + return value.shl(shift).shr_s(shift); + } + // when loading a symval, we need to concat 4 symbolic values // This sounds terribly bad for SMT... // Load a 4-byte symbolic value from memory @@ -396,6 +454,7 @@ class SymMemory_t { std::monostate storeSymLong(int32_t base, int32_t offset, SymVal value) { int32_t addr = base + offset; + // TODO: Can we receive a float point symbolic value here? which may produce a bug SymVal s0 = value.extract(1, 1); SymVal s1 = value.extract(2, 2); SymVal s2 = value.extract(3, 3); @@ -415,6 +474,41 @@ class SymMemory_t { return std::monostate{}; } + std::monostate storeSymInt8(int32_t base, int32_t offset, SymVal value) { + int32_t addr = base + offset; + storeSymByte(addr, value.extract(1, 1)); + return std::monostate{}; + } + + std::monostate storeSymInt16(int32_t base, int32_t offset, SymVal value) { + int32_t addr = base + offset; + storeSymByte(addr, value.extract(1, 1)); + storeSymByte(addr + 1, value.extract(2, 2)); + return std::monostate{}; + } + + std::monostate storeSymLong8(int32_t base, int32_t offset, SymVal value) { + int32_t addr = base + offset; + storeSymByte(addr, value.extract(1, 1)); + return std::monostate{}; + } + + std::monostate storeSymLong16(int32_t base, int32_t offset, SymVal value) { + int32_t addr = base + offset; + storeSymByte(addr, value.extract(1, 1)); + storeSymByte(addr + 1, value.extract(2, 2)); + return std::monostate{}; + } + + std::monostate storeSymLong32(int32_t base, int32_t offset, SymVal value) { + int32_t addr = base + offset; + storeSymByte(addr, value.extract(1, 1)); + storeSymByte(addr + 1, value.extract(2, 2)); + storeSymByte(addr + 2, value.extract(3, 3)); + storeSymByte(addr + 3, value.extract(4, 4)); + return std::monostate{}; + } + std::monostate storeSymFloat(int32_t base, int32_t offset, SymVal value) { assert(value.is_concrete() && "Currently only support concrete symbolic " "value for float-point values"); diff --git a/headers/wasm/symval_factory.hpp b/headers/wasm/symval_factory.hpp index 31f3041b..14875764 100644 --- a/headers/wasm/symval_factory.hpp +++ b/headers/wasm/symval_factory.hpp @@ -205,10 +205,6 @@ inline SymVal make_extract(const SymVal &value, int high, int low) { int shift_bits = (low - 1) * 8; if (auto concrete = std::dynamic_pointer_cast(value.symptr)) { - if (concrete->kind != KindBV) { - throw std::runtime_error( - "Extract only supports bitvector concrete values"); - } // extract from concrete bitvector value int64_t val = concrete->value.value; int64_t mask = (1LL << ((high - low + 1) * 8)) - 1; @@ -359,6 +355,12 @@ inline SymVal make_binary(BinOperation op, const SymVal &lhs, if (lhs_width == 64 && rhs_width == 64) return make_eval_bv(lhs_value.i64_shr_s(rhs_value), 64); break; + case SHL: + if (lhs_width == 32 && rhs_width == 32) + return make_eval_bv(lhs_value.i32_shl(rhs_value), 32); + if (lhs_width == 64 && rhs_width == 64) + return make_eval_bv(lhs_value.i64_shl(rhs_value), 64); + break; case LTU_BOOL: if (lhs_width == 32 && rhs_width == 32) return make_eval_bool(lhs_value.i32_lt_u(rhs_value)); diff --git a/src/main/scala/wasm/Parser.scala b/src/main/scala/wasm/Parser.scala index ddc1c4b9..4841261f 100644 --- a/src/main/scala/wasm/Parser.scala +++ b/src/main/scala/wasm/Parser.scala @@ -249,7 +249,7 @@ class GSWasmVisitor extends WatParserBaseVisitor[WIR] { ty.kind match { case I32Type => { if (ctx.NAT.getText.startsWith("0x")) { - val parsedValue = java.lang.Long.parseLong(ctx.NAT.getText.substring(2).replace("_", ""), 16) + val parsedValue = java.lang.Long.parseUnsignedLong(ctx.NAT.getText.substring(2).replace("_", ""), 16) // Convert to signed 32-bit integer if it exceeds the max 32-bit signed integer range val intValue = if (parsedValue > Int.MaxValue) (parsedValue - (1L << 32)).toInt else parsedValue.toInt I32V(intValue) @@ -261,7 +261,7 @@ class GSWasmVisitor extends WatParserBaseVisitor[WIR] { if (ctx.NAT.getText.startsWith("0x")) { // println(s"parsing hex: ${ctx.NAT.getText.substring(2)}") // also skip underscore - I64V(java.lang.Long.parseLong(ctx.NAT.getText.substring(2).replace("_", ""), 16)) + I64V(java.lang.Long.parseUnsignedLong(ctx.NAT.getText.substring(2).replace("_", ""), 16)) // I64V(java.lang.Long.parseLong(ctx.NAT.getText.substring(2), 16)) } else { I64V(ctx.NAT.getText.toLong) diff --git a/src/main/scala/wasm/StagedConcolicMiniWasm.scala b/src/main/scala/wasm/StagedConcolicMiniWasm.scala index 5d5b7c4b..fa441d5c 100644 --- a/src/main/scala/wasm/StagedConcolicMiniWasm.scala +++ b/src/main/scala/wasm/StagedConcolicMiniWasm.scala @@ -1073,31 +1073,152 @@ trait StagedFrames extends SAIOps with StagedWasmValueDomains { } @virtualize -trait StagedMemory extends SAIOps with StagedWasmValueDomains with Continuations { +trait StagedMemory extends SAIOps with StagedWasmValueDomains with Continuations { this: ConcreteOps with ValueCreation => + def normalizeStoreOp(ty: ValueType, packSize: Option[PackSize]): PackSize = (ty, packSize) match { + case (NumType(I32Type), None) => Pack32 + case (NumType(I64Type), None) => Pack64 + case (NumType(F32Type), None) => Pack32 + case (NumType(F64Type), None) => Pack64 + case (NumType(I32Type), Some(Pack8 | Pack16)) => packSize.get + case (NumType(I64Type), Some(Pack8 | Pack16 | Pack32)) => packSize.get + case _ => throw new RuntimeException(s"Unsupported memory.store combination: ty=$ty packSize=$packSize") + } + + def normalizeLoadOp(ty: ValueType, packSize: Option[PackSize], sign: Option[Extension]): (PackSize, Extension) = (ty, packSize, sign) match { + case (NumType(I32Type), None, None) => (Pack32, ZX) + case (NumType(I64Type), None, None) => (Pack64, ZX) + case (NumType(F32Type), None, None) => (Pack32, ZX) + case (NumType(F64Type), None, None) => (Pack64, ZX) + case (NumType(I32Type), Some(Pack8 | Pack16), Some(SX | ZX)) => (packSize.get, sign.get) + case (NumType(I64Type), Some(Pack8 | Pack16 | Pack32), Some(SX | ZX)) => (packSize.get, sign.get) + case _ => throw new RuntimeException(s"Unsupported memory.load combination: ty=$ty packSize=$packSize sign=$sign") + } + object Memory { - // TODO: why this is only one function, rather than `storeInC` and `storeInS`? - // TODO: what should the type of SymVal be? - def store(ty: ValueType, base: Rep[Int], offset: Int, value: (StagedConcreteNum, StagedSymbolicNum)): Rep[Unit] = ty match { - case NumType(I32Type) => + def store(ty: ValueType, pack: PackSize, base: Rep[Int], offset: Int, value: (StagedConcreteNum, StagedSymbolicNum)): Rep[Unit] = (ty, pack) match { + case (NumType(I32Type), Pack32) => + "memory-store-int".reflectCtrlWith[Unit](base, offset, value._1.i) + "sym-store-int".reflectCtrlWith[Unit](base, offset, value._2.s) + case (NumType(I32Type), Pack8) => + "memory-store-int8".reflectCtrlWith[Unit](base, offset, value._1.i) + "sym-store-int8".reflectCtrlWith[Unit](base, offset, value._2.s) + case (NumType(I32Type), Pack16) => + "memory-store-int16".reflectCtrlWith[Unit](base, offset, value._1.i) + "sym-store-int16".reflectCtrlWith[Unit](base, offset, value._2.s) + case (NumType(I64Type), Pack64) => + "memory-store-long".reflectCtrlWith[Unit](base, offset, value._1.i) + "sym-store-long".reflectCtrlWith[Unit](base, offset, value._2.s) + case (NumType(I64Type), Pack8) => + "memory-store-long8".reflectCtrlWith[Unit](base, offset, value._1.i) + "sym-store-long8".reflectCtrlWith[Unit](base, offset, value._2.s) + case (NumType(I64Type), Pack16) => + "memory-store-long16".reflectCtrlWith[Unit](base, offset, value._1.i) + "sym-store-long16".reflectCtrlWith[Unit](base, offset, value._2.s) + case (NumType(I64Type), Pack32) => + "memory-store-long32".reflectCtrlWith[Unit](base, offset, value._1.i) + "sym-store-long32".reflectCtrlWith[Unit](base, offset, value._2.s) + case (NumType(F32Type), Pack32) => "memory-store-int".reflectCtrlWith[Unit](base, offset, value._1.i) "sym-store-int".reflectCtrlWith[Unit](base, offset, value._2.s) - case NumType(I64Type) => + case (NumType(F64Type), Pack64) => "memory-store-long".reflectCtrlWith[Unit](base, offset, value._1.i) "sym-store-long".reflectCtrlWith[Unit](base, offset, value._2.s) + case _ => + throw new RuntimeException(s"Unsupported memory.store combination: ty=$ty pack=$pack") + } + + private def loadI32C(pack: PackSize, ext: Extension, base: Rep[Int], offset: Int): StagedConcreteNum = (pack, ext) match { + case (Pack32, ZX) => + StagedConcreteNum(NumType(I32Type), "I32V".reflectCtrlWith[Num]("memory-load-int".reflectCtrlWith[Int](base, offset))) + case (Pack8, ZX) => + StagedConcreteNum(NumType(I32Type), "I32V".reflectCtrlWith[Num]("memory-load-int8-u".reflectCtrlWith[Int](base, offset))) + case (Pack8, SX) => + StagedConcreteNum(NumType(I32Type), "I32V".reflectCtrlWith[Num]("memory-load-int8-s".reflectCtrlWith[Int](base, offset))) + case (Pack16, ZX) => + StagedConcreteNum(NumType(I32Type), "I32V".reflectCtrlWith[Num]("memory-load-int16-u".reflectCtrlWith[Int](base, offset))) + case (Pack16, SX) => + StagedConcreteNum(NumType(I32Type), "I32V".reflectCtrlWith[Num]("memory-load-int16-s".reflectCtrlWith[Int](base, offset))) + case _ => + throw new RuntimeException(s"Unsupported i32.load pack=$pack ext=$ext") + } + + private def loadI64C(pack: PackSize, ext: Extension, base: Rep[Int], offset: Int): StagedConcreteNum = (pack, ext) match { + case (Pack64, ZX) => + StagedConcreteNum(NumType(I64Type), "I64V".reflectCtrlWith[Num]("memory-load-long".reflectCtrlWith[Long](base, offset))) + case (Pack8, ZX) => + StagedConcreteNum(NumType(I64Type), "I64V".reflectCtrlWith[Num]("memory-load-long8-u".reflectCtrlWith[Long](base, offset))) + case (Pack8, SX) => + StagedConcreteNum(NumType(I64Type), "I64V".reflectCtrlWith[Num]("memory-load-long8-s".reflectCtrlWith[Long](base, offset))) + case (Pack16, ZX) => + StagedConcreteNum(NumType(I64Type), "I64V".reflectCtrlWith[Num]("memory-load-long16-u".reflectCtrlWith[Long](base, offset))) + case (Pack16, SX) => + StagedConcreteNum(NumType(I64Type), "I64V".reflectCtrlWith[Num]("memory-load-long16-s".reflectCtrlWith[Long](base, offset))) + case (Pack32, ZX) => + StagedConcreteNum(NumType(I64Type), "I64V".reflectCtrlWith[Num]("memory-load-long32-u".reflectCtrlWith[Long](base, offset))) + case (Pack32, SX) => + StagedConcreteNum(NumType(I64Type), "I64V".reflectCtrlWith[Num]("memory-load-long32-s".reflectCtrlWith[Long](base, offset))) + case _ => + throw new RuntimeException(s"Unsupported i64.load pack=$pack ext=$ext") + } + + private def loadI32S(pack: PackSize, ext: Extension, base: Rep[Int], offset: Int): StagedSymbolicNum = (pack, ext) match { + case (Pack32, ZX) => + StagedSymbolicNum(NumType(I32Type), "sym-load-int".reflectCtrlWith[SymVal](base, offset)) + case (Pack8, ZX) => + StagedSymbolicNum(NumType(I32Type), "sym-load-int8-u".reflectCtrlWith[SymVal](base, offset)) + case (Pack8, SX) => + StagedSymbolicNum(NumType(I32Type), "sym-load-int8-s".reflectCtrlWith[SymVal](base, offset)) + case (Pack16, ZX) => + StagedSymbolicNum(NumType(I32Type), "sym-load-int16-u".reflectCtrlWith[SymVal](base, offset)) + case (Pack16, SX) => + StagedSymbolicNum(NumType(I32Type), "sym-load-int16-s".reflectCtrlWith[SymVal](base, offset)) + case _ => + throw new RuntimeException(s"Unsupported symbolic i32.load pack=$pack ext=$ext") + } + + private def loadI64S(pack: PackSize, ext: Extension, base: Rep[Int], offset: Int): StagedSymbolicNum = (pack, ext) match { + case (Pack64, ZX) => + StagedSymbolicNum(NumType(I64Type), "sym-load-long".reflectCtrlWith[SymVal](base, offset)) + case (Pack8, ZX) => + StagedSymbolicNum(NumType(I64Type), "sym-load-long8-u".reflectCtrlWith[SymVal](base, offset)) + case (Pack8, SX) => + StagedSymbolicNum(NumType(I64Type), "sym-load-long8-s".reflectCtrlWith[SymVal](base, offset)) + case (Pack16, ZX) => + StagedSymbolicNum(NumType(I64Type), "sym-load-long16-u".reflectCtrlWith[SymVal](base, offset)) + case (Pack16, SX) => + StagedSymbolicNum(NumType(I64Type), "sym-load-long16-s".reflectCtrlWith[SymVal](base, offset)) + case (Pack32, ZX) => + StagedSymbolicNum(NumType(I64Type), "sym-load-long32-u".reflectCtrlWith[SymVal](base, offset)) + case (Pack32, SX) => + StagedSymbolicNum(NumType(I64Type), "sym-load-long32-s".reflectCtrlWith[SymVal](base, offset)) + case _ => + throw new RuntimeException(s"Unsupported symbolic i64.load pack=$pack ext=$ext") } - def loadC(ty: ValueType, base: Rep[Int], offset: Int): StagedConcreteNum = ty match { - case NumType(I32Type) => StagedConcreteNum(NumType(I32Type), "I32V".reflectCtrlWith[Num]("memory-load-int".reflectCtrlWith[Int](base, offset))) - case NumType(I64Type) => StagedConcreteNum(NumType(I64Type), "I64V".reflectCtrlWith[Num]("memory-load-long".reflectCtrlWith[Long](base, offset))) - case NumType(F32Type) => StagedConcreteNum(NumType(F32Type), "F32V".reflectCtrlWith[Num]("memory-load-float".reflectCtrlWith[Float](base, offset))) - case NumType(F64Type) => StagedConcreteNum(NumType(F64Type), "F64V".reflectCtrlWith[Num]("memory-load-double".reflectCtrlWith[Double](base, offset))) + def loadC(ty: ValueType, pack: PackSize, ext: Extension, base: Rep[Int], offset: Int): StagedConcreteNum = ty match { + case NumType(I32Type) => + loadI32C(pack, ext, base, offset) + case NumType(I64Type) => + loadI64C(pack, ext, base, offset) + case NumType(F32Type) if pack == Pack32 && ext == ZX => + StagedConcreteNum(NumType(F32Type), "I32V".reflectCtrlWith[Num]("memory-load-int".reflectCtrlWith[Float](base, offset))) + case NumType(F64Type) if pack == Pack64 && ext == ZX => + StagedConcreteNum(NumType(F64Type), "I64V".reflectCtrlWith[Num]("memory-load-long".reflectCtrlWith[Double](base, offset))) + case _ => + throw new RuntimeException(s"Unsupported memory.load concrete combination: ty=$ty pack=$pack ext=$ext") } - def loadS(ty: ValueType, base: Rep[Int], offset: Int): StagedSymbolicNum = ty match { - case NumType(I32Type) => StagedSymbolicNum(NumType(I32Type), "sym-load-int".reflectCtrlWith[SymVal](base, offset)) - case NumType(I64Type) => StagedSymbolicNum(NumType(I64Type), "sym-load-long".reflectCtrlWith[SymVal](base, offset)) - case NumType(F32Type) => StagedSymbolicNum(NumType(F32Type), "sym-load-float".reflectCtrlWith[SymVal](base, offset)) - case NumType(F64Type) => StagedSymbolicNum(NumType(F64Type), "sym-load-double".reflectCtrlWith[SymVal](base, offset)) + def loadS(ty: ValueType, pack: PackSize, ext: Extension, base: Rep[Int], offset: Int): StagedSymbolicNum = ty match { + case NumType(I32Type) => + loadI32S(pack, ext, base, offset) + case NumType(I64Type) => + loadI64S(pack, ext, base, offset) + case NumType(F32Type) if pack == Pack32 && ext == ZX => + StagedSymbolicNum(NumType(F32Type), "sym-load-float".reflectCtrlWith[SymVal](base, offset)) + case NumType(F64Type) if pack == Pack64 && ext == ZX => + StagedSymbolicNum(NumType(F64Type), "sym-load-double".reflectCtrlWith[SymVal](base, offset)) + case _ => + throw new RuntimeException(s"Unsupported memory.load symbolic combination: ty=$ty pack=$pack ext=$ext") } // Returns the previous memory size on success, or -1 if the memory cannot be grown. @@ -1372,7 +1493,7 @@ trait StagedWasmEvaluator extends SAIOps } eval(rest, kont, trail)(newCtx) case Nop => eval(rest, kont, trail) - case Store(StoreOp(align, offset, ty, None)) => + case Store(StoreOp(align, offset, ty, packSize)) => val newCtx2 = withBlock { val (ty1, newCtx1) = ctx.pop() val value = Stack.popC(ty1) @@ -1380,22 +1501,23 @@ trait StagedWasmEvaluator extends SAIOps val (ty2, newCtx2) = newCtx1.pop() val addr = Stack.popC(ty2) val symAddr = Stack.popS(ty2) - Memory.store(ty, addr.toInt, offset, (value, symValue)) + val normalizedPack = normalizeStoreOp(ty, packSize) + Memory.store(ty, normalizedPack, addr.toInt, offset, (value, symValue)) newCtx2 } eval(rest, kont, trail)(newCtx2) - case Load(LoadOp(align, offset, ty, None, None)) => - val newCtx1 = withBlock { + case Load(LoadOp(align, offset, ty, packSize, sign)) => + val newCtx2 = withBlock { val (ty1, newCtx1) = ctx.pop() val addr = Stack.popC(ty1) Stack.popS(ty1) - val num = Memory.loadC(ty, addr.toInt, offset) - val sym = Memory.loadS(ty, addr.toInt, offset) + val (normalizedPack, normalizedExt) = normalizeLoadOp(ty, packSize, sign) + val num = Memory.loadC(ty, normalizedPack, normalizedExt, addr.toInt, offset) + val sym = Memory.loadS(ty, normalizedPack, normalizedExt, addr.toInt, offset) Stack.pushC(num) Stack.pushS(sym) - newCtx1 + newCtx1.push(ty) } - val newCtx2 = newCtx1.push(ty) eval(rest, kont, trail)(newCtx2) case MemorySize => ??? case MemoryGrow => @@ -1639,8 +1761,6 @@ trait StagedWasmEvaluator extends SAIOps val functy = module.types(ty) evalCallIndirect(rest, kont, trail, functy.asInstanceOf[FuncType]) case _ => - val todo = "todo-op".reflectCtrlWith[Unit]() - Predef.println(s"[WARNING] Encountered unimplemented instruction $inst, treat it as NOP") Predef.assert(false, s"Unimplemented instruction $inst") eval(rest, kont, trail) } @@ -2271,16 +2391,42 @@ trait StagedWasmCppGen extends CGenBase with CppSAICodeGenBase { shallow(slice); emit(".reverse") case Node(_, "memory-store-int", List(base, offset, value), _) => emit("Memory.storeInt("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(value); emit(".toInt())") + case Node(_, "memory-store-int8", List(base, offset, value), _) => + emit("Memory.storeInt8("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(value); emit(".toInt())") + case Node(_, "memory-store-int16", List(base, offset, value), _) => + emit("Memory.storeInt16("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(value); emit(".toInt())") case Node(_, "memory-store-long", List(base, offset, value), _) => emit("Memory.storeLong("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(value); emit(".toInt64())") + case Node(_, "memory-store-long8", List(base, offset, value), _) => + emit("Memory.storeLong8("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(value); emit(".toInt64())") + case Node(_, "memory-store-long16", List(base, offset, value), _) => + emit("Memory.storeLong16("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(value); emit(".toInt64())") + case Node(_, "memory-store-long32", List(base, offset, value), _) => + emit("Memory.storeLong32("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(value); emit(".toInt64())") case Node(_, "memory-load-int", List(base, offset), _) => emit("Memory.loadInt("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "memory-load-int8-u", List(base, offset), _) => + emit("Memory.loadInt8U("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "memory-load-int8-s", List(base, offset), _) => + emit("Memory.loadInt8S("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "memory-load-int16-u", List(base, offset), _) => + emit("Memory.loadInt16U("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "memory-load-int16-s", List(base, offset), _) => + emit("Memory.loadInt16S("); shallow(base); emit(", "); shallow(offset); emit(")") case Node(_, "memory-load-long", List(base, offset), _) => emit("Memory.loadLong("); shallow(base); emit(", "); shallow(offset); emit(")") - case Node(_, "memory-load-float", List(base, offset), _) => - emit("Memory.loadInt("); shallow(base); emit(", "); shallow(offset); emit(")") - case Node(_, "memory-load-double", List(base, offset), _) => - emit("Memory.loadLong("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "memory-load-long8-u", List(base, offset), _) => + emit("Memory.loadLong8U("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "memory-load-long8-s", List(base, offset), _) => + emit("Memory.loadLong8S("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "memory-load-long16-u", List(base, offset), _) => + emit("Memory.loadLong16U("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "memory-load-long16-s", List(base, offset), _) => + emit("Memory.loadLong16S("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "memory-load-long32-u", List(base, offset), _) => + emit("Memory.loadLong32U("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "memory-load-long32-s", List(base, offset), _) => + emit("Memory.loadLong32S("); shallow(base); emit(", "); shallow(offset); emit(")") case Node(_, "memory-grow", List(delta), _) => emit("Memory.grow("); shallow(delta); emit(")") case Node(_, "stack-size", _, _) => @@ -2288,12 +2434,42 @@ trait StagedWasmCppGen extends CGenBase with CppSAICodeGenBase { // Symbolic Memory case Node(_, "sym-store-int", List(base, offset, s_value), _) => emit("SymMemory.storeSym("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(s_value); emit(")") + case Node(_, "sym-store-int8", List(base, offset, s_value), _) => + emit("SymMemory.storeSymInt8("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(s_value); emit(")") + case Node(_, "sym-store-int16", List(base, offset, s_value), _) => + emit("SymMemory.storeSymInt16("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(s_value); emit(")") case Node(_, "sym-store-long", List(base, offset, s_value), _) => emit("SymMemory.storeSymLong("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(s_value); emit(")") + case Node(_, "sym-store-long8", List(base, offset, s_value), _) => + emit("SymMemory.storeSymLong8("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(s_value); emit(")") + case Node(_, "sym-store-long16", List(base, offset, s_value), _) => + emit("SymMemory.storeSymLong16("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(s_value); emit(")") + case Node(_, "sym-store-long32", List(base, offset, s_value), _) => + emit("SymMemory.storeSymLong32("); shallow(base); emit(", "); shallow(offset); emit(", "); shallow(s_value); emit(")") case Node(_, "sym-load-int", List(base, offset), _) => emit("SymMemory.loadSym("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "sym-load-int8-u", List(base, offset), _) => + emit("SymMemory.loadSymInt8U("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "sym-load-int8-s", List(base, offset), _) => + emit("SymMemory.loadSymInt8S("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "sym-load-int16-u", List(base, offset), _) => + emit("SymMemory.loadSymInt16U("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "sym-load-int16-s", List(base, offset), _) => + emit("SymMemory.loadSymInt16S("); shallow(base); emit(", "); shallow(offset); emit(")") case Node(_, "sym-load-long", List(base, offset), _) => emit("SymMemory.loadSymLong("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "sym-load-long8-u", List(base, offset), _) => + emit("SymMemory.loadSymLong8U("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "sym-load-long8-s", List(base, offset), _) => + emit("SymMemory.loadSymLong8S("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "sym-load-long16-u", List(base, offset), _) => + emit("SymMemory.loadSymLong16U("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "sym-load-long16-s", List(base, offset), _) => + emit("SymMemory.loadSymLong16S("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "sym-load-long32-u", List(base, offset), _) => + emit("SymMemory.loadSymLong32U("); shallow(base); emit(", "); shallow(offset); emit(")") + case Node(_, "sym-load-long32-s", List(base, offset), _) => + emit("SymMemory.loadSymLong32S("); shallow(base); emit(", "); shallow(offset); emit(")") case Node(_, "sym-load-float", List(base, offset), _) => emit("SymMemory.loadSymFloat("); shallow(base); emit(", "); shallow(offset); emit(")") case Node(_, "sym-load-double", List(base, offset), _) => From ca5501ad9fb6b5a7304d320563b27fc3dcb99e75 Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Thu, 12 Mar 2026 02:07:29 -0400 Subject: [PATCH 06/16] a note --- grammar/gen-wat-parser.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/grammar/gen-wat-parser.sh b/grammar/gen-wat-parser.sh index 19923715..65a5d79f 100755 --- a/grammar/gen-wat-parser.sh +++ b/grammar/gen-wat-parser.sh @@ -19,6 +19,7 @@ do rm $file done +# Move the generated files to .antlr folder so we can debug the syntax with Antlr vscode extension mkdir -p "$(dirname "$0")/.antlr" mv *.tokens *.interp .antlr/ From e1816fe2e23ffcd310bef19e74e3f504e879fb45 Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Thu, 12 Mar 2026 02:18:51 -0400 Subject: [PATCH 07/16] remove a print in test --- benchmarks/wasm/long_loop.wat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/wasm/long_loop.wat b/benchmarks/wasm/long_loop.wat index c2eaf691..58a1dbeb 100644 --- a/benchmarks/wasm/long_loop.wat +++ b/benchmarks/wasm/long_loop.wat @@ -16,7 +16,7 @@ i32.add local.set 1 local.get 0 - call 0 + drop local.get 0 i32.const 100000 i32.lt_s From b4943d2db6965433897d74675ef1a35f9c4d8d83 Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Fri, 13 Mar 2026 15:55:21 -0400 Subject: [PATCH 08/16] fix profile file dumping --- headers/wasm/profile.hpp | 126 +++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 58 deletions(-) diff --git a/headers/wasm/profile.hpp b/headers/wasm/profile.hpp index 922b1d45..32329cdc 100644 --- a/headers/wasm/profile.hpp +++ b/headers/wasm/profile.hpp @@ -235,72 +235,82 @@ class Profile_t { void write_as_json(std::ostream &os) const { os << " \"profile_summary\": {\n"; + bool needs_comma = false; + auto write_field_prefix = [&](const char *key) { + if (needs_comma) { + os << ",\n"; + } + os << " \"" << key << "\": "; + needs_comma = true; + }; + auto write_field = [&](const char *key, const auto &value) { + write_field_prefix(key); + os << value; + }; if (PROFILE_STEP) { - os << " \"total_push_operations\": " - << op_count[static_cast(StepProfileKind::PUSH)] << ",\n"; - os << " \"total_pop_operations\": " - << op_count[static_cast(StepProfileKind::POP)] << ",\n"; - os << " \"total_peek_operations\": " - << op_count[static_cast(StepProfileKind::PEEK)] << ",\n"; - os << " \"total_shift_operations\": " - << op_count[static_cast(StepProfileKind::SHIFT)] << ",\n"; - os << " \"total_set_operations\": " - << op_count[static_cast(StepProfileKind::SET)] << ",\n"; - os << " \"total_get_operations\": " - << op_count[static_cast(StepProfileKind::GET)] << ",\n"; - os << " \"total_binary_operations\": " - << op_count[static_cast(StepProfileKind::BINARY)] - << ",\n"; - os << " \"total_tree_fill_operations\": " - << op_count[static_cast(StepProfileKind::TREE_FILL)] - << ",\n"; - os << " \"total_cursor_move_operations\": " - << op_count[static_cast(StepProfileKind::CURSOR_MOVE)] - << ",\n"; - os << " \"total_other_instructions_executed\": " << step_count - << ",\n"; - os << " \"total_mem_grow_operations\": " - << op_count[static_cast(StepProfileKind::MEM_GROW)] - << ",\n"; - os << " \"total_snapshot_create_operations\": " - << op_count[static_cast(StepProfileKind::SNAPSHOT_CREATE)] - << ",\n"; - os << " \"total_sym_eval_operations\": " - << op_count[static_cast(StepProfileKind::SYM_EVAL)] - << "\n"; + write_field( + "total_push_operations", + op_count[static_cast(StepProfileKind::PUSH)]); + write_field("total_pop_operations", + op_count[static_cast(StepProfileKind::POP)]); + write_field("total_peek_operations", + op_count[static_cast(StepProfileKind::PEEK)]); + write_field("total_shift_operations", + op_count[static_cast(StepProfileKind::SHIFT)]); + write_field("total_set_operations", + op_count[static_cast(StepProfileKind::SET)]); + write_field("total_get_operations", + op_count[static_cast(StepProfileKind::GET)]); + write_field("total_binary_operations", + op_count[static_cast(StepProfileKind::BINARY)]); + write_field( + "total_tree_fill_operations", + op_count[static_cast(StepProfileKind::TREE_FILL)]); + write_field( + "total_cursor_move_operations", + op_count[static_cast(StepProfileKind::CURSOR_MOVE)]); + write_field("total_other_instructions_executed", step_count); + write_field("total_mem_grow_operations", + op_count[static_cast(StepProfileKind::MEM_GROW)]); + write_field("total_snapshot_create_operations", + op_count[static_cast( + StepProfileKind::SNAPSHOT_CREATE)]); + write_field("total_sym_eval_operations", + op_count[static_cast(StepProfileKind::SYM_EVAL)]); } if (PROFILE_TIME) { - os << " \"total_time_instruction_execution_s\": " - << std::setprecision(15) - << time_count[static_cast(TimeProfileKind::INSTR)] - << ",\n"; - os << " \"total_time_solver_s\": " << std::setprecision(15) + write_field_prefix("total_time_instruction_execution_s"); + os << std::setprecision(15) + << time_count[static_cast(TimeProfileKind::INSTR)]; + write_field_prefix("total_time_solver_s"); + os << std::setprecision(15) << time_count[static_cast( - TimeProfileKind::CALL_Z3_SOLVER)] - << ",\n"; - os << " \"total_time_resuming_from_snapshot_s\": " - << std::setprecision(15) + TimeProfileKind::CALL_Z3_SOLVER)]; + write_field_prefix("total_time_resuming_from_snapshot_s"); + os << std::setprecision(15) << time_count[static_cast( - TimeProfileKind::RESUME_SNAPSHOT)] - << ",\n"; - os << " \"total_time_counting_symbolic_size_s\": " - << std::setprecision(15) + TimeProfileKind::RESUME_SNAPSHOT)]; + write_field_prefix("total_time_counting_symbolic_size_s"); + os << std::setprecision(15) << time_count[static_cast( - TimeProfileKind::COUNT_SYM_SIZE)] - << "\n"; - os << " \"total_time_splitting_path_conditions_s\": " - << std::setprecision(15) + TimeProfileKind::COUNT_SYM_SIZE)]; + write_field_prefix("total_time_splitting_path_conditions_s"); + os << std::setprecision(15) << time_count[static_cast( - TimeProfileKind::SPLIT_CONDITIONS)] - << ",\n"; + TimeProfileKind::SPLIT_CONDITIONS)]; + write_field_prefix("total_time_main_loop_s"); + os << std::setprecision(15) + << time_count[static_cast(TimeProfileKind::MAIN_LOOP)]; } if (PROFILE_CACHE) { - os << " \"total_cache_hits\": " << cache_hit_count << ",\n"; - os << " \"total_cache_misses\": " << cache_miss_count << ",\n"; - os << " \"cache_hit_rate\": " - << static_cast(cache_hit_count) / - static_cast(cache_hit_count + cache_miss_count) - << "\n"; + write_field("total_cache_hits", cache_hit_count); + write_field("total_cache_misses", cache_miss_count); + write_field("cache_hit_rate", + static_cast(cache_hit_count) / + static_cast(cache_hit_count + cache_miss_count)); + } + if (needs_comma) { + os << '\n'; } os << " }\n"; } @@ -413,4 +423,4 @@ struct CostManager_t { static CostManager_t CostManager; -#endif // PROFILE_HPP \ No newline at end of file +#endif // PROFILE_HPP From d36b57d8021d216380df5012a6912f31a246bedb Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Sat, 14 Mar 2026 00:39:44 -0400 Subject: [PATCH 09/16] update --- benchmarks/wasm/fp_ops.wat | 12 ++++++ headers/wasm/concolic_driver.hpp | 2 +- headers/wasm/concrete_num.hpp | 42 +++++++++++++++++++ headers/wasm/concrete_rt.hpp | 7 +++- headers/wasm/profile.hpp | 4 ++ .../scala/wasm/StagedConcolicMiniWasm.scala | 14 +++++++ src/test/scala/genwasym/TestBenchmark.scala | 18 +++++++- 7 files changed, 95 insertions(+), 4 deletions(-) diff --git a/benchmarks/wasm/fp_ops.wat b/benchmarks/wasm/fp_ops.wat index 17fdaf1c..09f6e18a 100644 --- a/benchmarks/wasm/fp_ops.wat +++ b/benchmarks/wasm/fp_ops.wat @@ -139,6 +139,18 @@ f64.convert_i64_s f64.const -1.0 f64.eq + call 0 + + f32.const 3.75 + i32.trunc_f32_s + i32.const 3 + i32.eq + call 0 + + f32.const 3.75 + i32.trunc_f32_u + i32.const 3 + i32.eq call 0) ;; symbolic branch guard for f32 diff --git a/headers/wasm/concolic_driver.hpp b/headers/wasm/concolic_driver.hpp index fb8ffb4e..81c7ff57 100644 --- a/headers/wasm/concolic_driver.hpp +++ b/headers/wasm/concolic_driver.hpp @@ -86,6 +86,7 @@ class DefaultPathPicker : public PathPicker { : PathPicker(unexplored_paths, visited) {} std::optional pick_path() override { + ManagedTimer timer(TimeProfileKind::SOLVER_TOTAL); NodeBox *node = unexplored_paths.back(); unexplored_paths.pop_back(); @@ -102,7 +103,6 @@ class DefaultPathPicker : public PathPicker { std::optional result; { - ManagedTimer timer(TimeProfileKind::SOLVER_TOTAL); auto cond = node->collect_path_conds(); result = solver.solve_path_conds(cond, true); } diff --git a/headers/wasm/concrete_num.hpp b/headers/wasm/concrete_num.hpp index 6a2eafc5..56e44d24 100644 --- a/headers/wasm/concrete_num.hpp +++ b/headers/wasm/concrete_num.hpp @@ -640,6 +640,48 @@ struct Num { return Num(static_cast(r_bits)); } + inline Num trunc_f32_to_i32_s() const { + uint32_t bits = toUInt(); + float value = f32_from_bits(bits); + + if (std::isnan(value)) { + throw std::runtime_error("i32.trunc_f32_s: NaN"); + } + if (std::isinf(value)) { + throw std::runtime_error("i32.trunc_f32_s: Infinity"); + } + if (value < -2147483648.0f || value >= 2147483648.0f) { + throw std::runtime_error("i32.trunc_f32_s: Out of range"); + } + + float truncated = std::trunc(value); + int32_t result = static_cast(truncated); + Num res(result); + debug_print("i32.trunc_f32_s", *this, *this, res); + return res; + } + + inline Num trunc_f32_to_i32_u() const { + uint32_t bits = toUInt(); + float value = f32_from_bits(bits); + + if (std::isnan(value)) { + throw std::runtime_error("i32.trunc_f32_u: NaN"); + } + if (std::isinf(value)) { + throw std::runtime_error("i32.trunc_f32_u: Infinity"); + } + if (value < 0.0f || value >= 4294967296.0f) { + throw std::runtime_error("i32.trunc_f32_u: Out of range"); + } + + float truncated = std::trunc(value); + uint32_t result = static_cast(truncated); + Num res(static_cast(result)); + debug_print("i32.trunc_f32_u", *this, *this, res); + return res; + } + // f32.min / f32.max: follow wasm-ish semantics: if either is NaN, return NaN // (propagate) inline Num f32_min(const Num &other) const { diff --git a/headers/wasm/concrete_rt.hpp b/headers/wasm/concrete_rt.hpp index 3e54baac..ac50af05 100644 --- a/headers/wasm/concrete_rt.hpp +++ b/headers/wasm/concrete_rt.hpp @@ -475,7 +475,9 @@ struct FuncTable_t { std::to_string(index)); } if (!table[index]) { - assert(false); + std::cout << "Function table entry at index " << index + << " is empty or invalid" << std::endl; + assert(false && "Function table entry is empty or invalid"); throw std::runtime_error("Function table entry at index " + std::to_string(index) + " is empty or invalid"); } @@ -483,11 +485,12 @@ struct FuncTable_t { } std::monostate set(Num offset, int32_t index, Func_t func) { + assert(offset.value == 1 && "Only support one function table per module for now"); if (index < 0 || index >= table.size()) { throw std::runtime_error("Function table set out of bounds: " + std::to_string(index)); } - table[offset.toInt() + index] = func; + table[index] = func; return std::monostate{}; } }; diff --git a/headers/wasm/profile.hpp b/headers/wasm/profile.hpp index 32329cdc..1f621b81 100644 --- a/headers/wasm/profile.hpp +++ b/headers/wasm/profile.hpp @@ -283,6 +283,10 @@ class Profile_t { os << std::setprecision(15) << time_count[static_cast(TimeProfileKind::INSTR)]; write_field_prefix("total_time_solver_s"); + os << std::setprecision(15) + << time_count[static_cast( + TimeProfileKind::SOLVER_TOTAL)]; + write_field_prefix("total_time_z3_api_call_s"); os << std::setprecision(15) << time_count[static_cast( TimeProfileKind::CALL_Z3_SOLVER)]; diff --git a/src/main/scala/wasm/StagedConcolicMiniWasm.scala b/src/main/scala/wasm/StagedConcolicMiniWasm.scala index fa441d5c..caba418b 100644 --- a/src/main/scala/wasm/StagedConcolicMiniWasm.scala +++ b/src/main/scala/wasm/StagedConcolicMiniWasm.scala @@ -559,6 +559,14 @@ trait ConcreteOps extends StagedWasmValueDomains with ValueCreation { case NumType(F64Type) => StagedConcreteNum(NumType(I32Type), "f64-trunc-to-i32-u".reflectCtrlWith[Num](num.i)) } + def truncF32ToI32S(): StagedConcreteNum = num.tipe match { + case NumType(F32Type) => StagedConcreteNum(NumType(I32Type), "f32-trunc-to-i32-s".reflectCtrlWith[Num](num.i)) + } + + def truncF32ToI32U(): StagedConcreteNum = num.tipe match { + case NumType(F32Type) => StagedConcreteNum(NumType(I32Type), "f32-trunc-to-i32-u".reflectCtrlWith[Num](num.i)) + } + def assert(): Rep[Unit] = { "assert-true".reflectCtrlWith[Unit](num.toInt != 0) } @@ -2080,6 +2088,8 @@ trait StagedWasmEvaluator extends SAIOps case ConvertTo(NumType(I32Type), NumType(F64Type), ZX) => value.convertI32ToF64U() case ConvertTo(NumType(I64Type), NumType(F64Type), SX) => value.convertI64ToF64S() case ConvertTo(NumType(I64Type), NumType(F64Type), ZX) => value.convertI64ToF64U() + case TruncTo(NumType(F32Type), NumType(I32Type), SX) => value.truncF32ToI32S() + case TruncTo(NumType(F32Type), NumType(I32Type), ZX) => value.truncF32ToI32U() case TruncTo(NumType(F64Type),NumType(I32Type),ZX) => value.truncF64ToI32U() case _ => throw new UnsupportedOperationException(s"Unsupported concrete conversion $op") } @@ -2605,6 +2615,10 @@ trait StagedWasmCppGen extends CGenBase with CppSAICodeGenBase { emit("("); shallow(num); emit(".convert_i64_to_f64_s())") case Node(_, "i64-convert-to-f64-u", List(num), _) => emit("("); shallow(num); emit(".convert_i64_to_f64_u())") + case Node(_, "f32-trunc-to-i32-s", List(num), _) => + emit("("); shallow(num); emit(".trunc_f32_to_i32_s())") + case Node(_, "f32-trunc-to-i32-u", List(num), _) => + emit("("); shallow(num); emit(".trunc_f32_to_i32_u())") case Node(_, "f64-trunc-to-i32-u", List(num), _) => emit("("); shallow(num); emit(".trunc_f64_to_i32_u())") case Node(_, "f32-binary-add", List(lhs, rhs), _) => diff --git a/src/test/scala/genwasym/TestBenchmark.scala b/src/test/scala/genwasym/TestBenchmark.scala index ab962f61..0c4f2edb 100644 --- a/src/test/scala/genwasym/TestBenchmark.scala +++ b/src/test/scala/genwasym/TestBenchmark.scala @@ -37,9 +37,25 @@ class TestBenchmark extends FunSuite { } } - test("compile-btree-benchmarks") { compileDirToCpp("./benchmarks/pldi2026/btree/", Some("main")) } + def compileDirTreeToCpp(dir: String, + main: Option[String] = None): Unit = { + import java.io.File + + def walk(file: File): Unit = { + if (file.isDirectory) { + Option(file.listFiles()).getOrElse(Array.empty).foreach(walk) + } else if (file.getName.endsWith(".wat")) { + compileToCpp(file.getAbsolutePath, main) + } + } + + walk(new File(dir)) + } + + test("compile-btree-benchmarks") { compileDirToCpp("./benchmarks/pldi2026/btree/tests-normalized", Some("main")) } test("compile-crafted-benchmarks") { compileDirToCpp("./benchmarks/pldi2026/crafted/") } test("compile-aws-aws-encryption-sdk") { compileDirToCpp("./benchmarks/pldi2026/aws-encryption-sdk/tests-original-normalized/", Some("__original_main")) } + test("compile-collection-c-benchmarks") { compileDirTreeToCpp("./benchmarks/pldi2026/Collection-C/tests-normalized/", Some("__original_main")) } test("compile-a-single-file") { sys.env.get("INPUT") match { case Some(path) => compileToCpp(path) From 906f26b2b3829536548a0214265c27b13e540187 Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Sat, 14 Mar 2026 23:15:51 -0400 Subject: [PATCH 10/16] update --- benchmarks/wasm/fp_ops.wat | 10 +++++ headers/wasm/concrete_rt.hpp | 13 +++++-- headers/wasm/sym_rt.hpp | 20 ++++++++-- headers/wasm/symbolic_decl.hpp | 8 ++++ headers/wasm/symbolic_impl.hpp | 5 +++ headers/wasm/symval_decl.hpp | 3 ++ headers/wasm/symval_factory.hpp | 16 ++++++++ headers/wasm/symval_impl.hpp | 4 ++ src/main/scala/wasm/Parser.scala | 1 + .../scala/wasm/StagedConcolicMiniWasm.scala | 38 ++++++++++++++++++- src/test/scala/genwasym/TestBenchmark.scala | 4 +- 11 files changed, 113 insertions(+), 9 deletions(-) diff --git a/benchmarks/wasm/fp_ops.wat b/benchmarks/wasm/fp_ops.wat index 09f6e18a..3c994cce 100644 --- a/benchmarks/wasm/fp_ops.wat +++ b/benchmarks/wasm/fp_ops.wat @@ -15,6 +15,16 @@ f64.const 0x1p-1 (;=0.5;) local.set 3 local.get 0 + f32.abs + f32.const 0x1.cp+1 (;=3.5;) + f32.eq + call 0 + local.get 2 + f64.abs + f64.const 0x1.48p+3 (;=10.25;) + f64.eq + call 0 + local.get 0 local.get 1 f32.add f32.const 0x1.6p+2 (;=5.5;) diff --git a/headers/wasm/concrete_rt.hpp b/headers/wasm/concrete_rt.hpp index ac50af05..47844d65 100644 --- a/headers/wasm/concrete_rt.hpp +++ b/headers/wasm/concrete_rt.hpp @@ -50,7 +50,9 @@ class Stack_t { Num pop() { Profile.step(StepProfileKind::POP); - assert(count > 0 && "Stack underflow"); + if (count <= 0) { + throw std::runtime_error("Stack underflow"); + } #ifdef DEBUG printf("[Debug] popping a value %ld from stack, size of concrete stack is: " "%d\n", @@ -343,7 +345,8 @@ struct Memory_t { uint64_t b1 = static_cast(loadByte(base, offset + 1)); uint64_t b2 = static_cast(loadByte(base, offset + 2)); uint64_t b3 = static_cast(loadByte(base, offset + 3)); - uint32_t raw = static_cast(b0 | (b1 << 8) | (b2 << 16) | (b3 << 24)); + uint32_t raw = + static_cast(b0 | (b1 << 8) | (b2 << 16) | (b3 << 24)); return static_cast(raw); } @@ -381,7 +384,8 @@ struct Memory_t { throw std::runtime_error("Invalid memory access " + std::to_string(addr)); } for (int i = 0; i < 8; ++i) { - memory[addr + i] = static_cast((static_cast(value) >> (8 * i)) & 0xFF); + memory[addr + i] = static_cast( + (static_cast(value) >> (8 * i)) & 0xFF); } return std::monostate{}; } @@ -485,7 +489,8 @@ struct FuncTable_t { } std::monostate set(Num offset, int32_t index, Func_t func) { - assert(offset.value == 1 && "Only support one function table per module for now"); + assert(offset.value == 1 && + "Only support one function table per module for now"); if (index < 0 || index >= table.size()) { throw std::runtime_error("Function table set out of bounds: " + std::to_string(index)); diff --git a/headers/wasm/sym_rt.hpp b/headers/wasm/sym_rt.hpp index 760112b5..0ff47827 100644 --- a/headers/wasm/sym_rt.hpp +++ b/headers/wasm/sym_rt.hpp @@ -425,7 +425,11 @@ class SymMemory_t { auto b1 = loadSymByte(base + offset + 1); auto b2 = loadSymByte(base + offset + 2); auto b3 = loadSymByte(base + offset + 3); - return SVFactory::make_smallbv(32, 0).concat(b3).concat(b2).concat(b1).concat(b0); + return SVFactory::make_smallbv(32, 0) + .concat(b3) + .concat(b2) + .concat(b1) + .concat(b0); } SymVal loadSymLong32S(int32_t base, int32_t offset) { @@ -454,7 +458,8 @@ class SymMemory_t { std::monostate storeSymLong(int32_t base, int32_t offset, SymVal value) { int32_t addr = base + offset; - // TODO: Can we receive a float point symbolic value here? which may produce a bug + // TODO: Can we receive a float point symbolic value here? which may produce + // a bug SymVal s0 = value.extract(1, 1); SymVal s1 = value.extract(2, 2); SymVal s2 = value.extract(3, 3); @@ -659,6 +664,15 @@ class SymEnv_t { static SymEnv_t SymEnv; +inline Num isSymbolic(int index) { + auto it = SVFactory::SymbolStore.find(index); + if (it != SVFactory::SymbolStore.end()) { + return Num(I32V(1)); + } else { + return Num(I32V(0)); + } +} + // A snapshot of the symbolic state and execution context (control) class Snapshot_t { public: @@ -732,7 +746,7 @@ struct NodeBox { struct Node { friend struct NodeBox; - virtual ~Node(){}; + virtual ~Node() {}; void set_cost(double c) { instr_cost = c; } double get_cost() const { return instr_cost; } virtual std::string to_string() = 0; diff --git a/headers/wasm/symbolic_decl.hpp b/headers/wasm/symbolic_decl.hpp index 0e2b5bd2..7885a615 100644 --- a/headers/wasm/symbolic_decl.hpp +++ b/headers/wasm/symbolic_decl.hpp @@ -37,6 +37,7 @@ enum UnaryOperation { NOT, // bool not BOOL2BV, // bool to bitvector, EXTEND, // bitvector extension, extend i32 to i64 + ABS, // floating-point absolute value }; enum ValueKind { KindBV, KindBool, KindFP }; @@ -231,6 +232,10 @@ struct SymUnary : public Symbolic { case NOT: _width = 1; break; + case ABS: + assert(value->value_kind() == KindFP); + _width = value->width(); + break; default: assert(false && "Unknown unary operation"); } @@ -254,6 +259,9 @@ struct SymUnary : public Symbolic { case BOOL2BV: { return ValueKind::KindBV; } + case ABS: { + return ValueKind::KindFP; + } default: { assert(false && "Unknown unary operation"); } diff --git a/headers/wasm/symbolic_impl.hpp b/headers/wasm/symbolic_impl.hpp index 8c6fb067..28e9795a 100644 --- a/headers/wasm/symbolic_impl.hpp +++ b/headers/wasm/symbolic_impl.hpp @@ -155,6 +155,11 @@ inline z3::expr Symbolic::build_z3_expr_aux() { z3::expr bool_expr = unary->value->z3_expr(); return z3::ite(bool_expr, one_bv, zero_bv); } + case ABS: { + z3::expr fp_expr = unary->value->z3_expr(); + return z3::to_expr(global_z3_ctx(), + Z3_mk_fpa_abs(global_z3_ctx(), fp_expr)); + } default: throw std::runtime_error("Unary operation not supported: " + std::to_string(unary->op)); diff --git a/headers/wasm/symval_decl.hpp b/headers/wasm/symval_decl.hpp index 8f9ac1a3..b3739692 100644 --- a/headers/wasm/symval_decl.hpp +++ b/headers/wasm/symval_decl.hpp @@ -51,6 +51,7 @@ struct SymVal { SymVal bitwise_and(const SymVal &other) const; SymVal bitwise_xor(const SymVal &other) const; SymVal bitwise_or(const SymVal &other) const; + SymVal abs() const; SymVal concat(const SymVal &other) const; SymVal extract(int high, int low) const; SymVal bv2bool() const; @@ -84,6 +85,8 @@ template inline bool allConcrete(const Args &...args) { return (... && args.is_concrete()); } +inline Num isSymbolic(int index); + inline SymVal Concrete(Num num, int width); [[noreturn]] inline SymVal debug_unreachable(const char* msg) { diff --git a/headers/wasm/symval_factory.hpp b/headers/wasm/symval_factory.hpp index 14875764..5c4a09a5 100644 --- a/headers/wasm/symval_factory.hpp +++ b/headers/wasm/symval_factory.hpp @@ -613,6 +613,22 @@ inline SymVal make_unary(UnaryOperation op, const SymVal &value) { } } + if (op == ABS) { + if (auto concrete = dynamic_cast(value.symptr.get())) { + if (concrete->kind == KindFP) { + if (concrete->width() == 32) { + auto result = SVFactory::make_concrete_fp(concrete->value.f32_abs(), 32); + UnaryOperationStore.insert({key, result}); + return result; + } else if (concrete->width() == 64) { + auto result = SVFactory::make_concrete_fp(concrete->value.f64_abs(), 64); + UnaryOperationStore.insert({key, result}); + return result; + } + } + } + } + auto result = SymVal(SVFactory::SymBookKeeper.allocate(op, value)); UnaryOperationStore.insert({key, result}); return result; diff --git a/headers/wasm/symval_impl.hpp b/headers/wasm/symval_impl.hpp index b7b3684c..d05d30ca 100644 --- a/headers/wasm/symval_impl.hpp +++ b/headers/wasm/symval_impl.hpp @@ -125,6 +125,10 @@ inline SymVal SymVal::bool_not() const { return SVFactory::make_unary(NOT, *this); } +inline SymVal SymVal::abs() const { + return SVFactory::make_unary(ABS, *this); +} + inline SymVal SymVal::concat(const SymVal &other) const { return SVFactory::make_concat(*this, other); } diff --git a/src/main/scala/wasm/Parser.scala b/src/main/scala/wasm/Parser.scala index 4841261f..9206451c 100644 --- a/src/main/scala/wasm/Parser.scala +++ b/src/main/scala/wasm/Parser.scala @@ -491,6 +491,7 @@ class GSWasmVisitor extends WatParserBaseVisitor[WIR] { case "reinterpret" => val fromTy = toNumType(fromTySign) Reinterpret(fromTy, toTy) + case _ => throw new RuntimeException(s"Unsupported convert opcode: ${ctx.CONVERT.getText}") } Convert(op) } else if (ctx.SYM_ASSERT != null) { diff --git a/src/main/scala/wasm/StagedConcolicMiniWasm.scala b/src/main/scala/wasm/StagedConcolicMiniWasm.scala index caba418b..fa85fd01 100644 --- a/src/main/scala/wasm/StagedConcolicMiniWasm.scala +++ b/src/main/scala/wasm/StagedConcolicMiniWasm.scala @@ -515,6 +515,11 @@ trait ConcreteOps extends StagedWasmValueDomains with ValueCreation { } } + def abs(): StagedConcreteNum = num.tipe match { + case NumType(F32Type) => StagedConcreteNum(NumType(F32Type), "f32-unary-abs".reflectCtrlWith[Num](num.i)) + case NumType(F64Type) => StagedConcreteNum(NumType(F64Type), "f64-unary-abs".reflectCtrlWith[Num](num.i)) + } + def extendS(): StagedConcreteNum = num.tipe match { case NumType(I32Type) => StagedConcreteNum(NumType(I64Type), "i32-extend-to-i64-s".reflectCtrlWith[Num](num.i)) } @@ -604,6 +609,11 @@ trait SymbolicOps extends StagedWasmValueDomains { case NumType(I64Type) => StagedSymbolicNum(NumType(I64Type), "sym-popcnt".reflectCtrlWith[SymVal](num.s)) } + def abs(): StagedSymbolicNum = num.tipe match { + case NumType(F32Type) => StagedSymbolicNum(NumType(F32Type), "sym-unary-abs".reflectCtrlWith[SymVal](num.s)) + case NumType(F64Type) => StagedSymbolicNum(NumType(F64Type), "sym-unary-abs".reflectCtrlWith[SymVal](num.s)) + } + def +(rhs: StagedSymbolicNum): StagedSymbolicNum = { (num.tipe, rhs.tipe) match { case (NumType(I32Type), NumType(I32Type)) => @@ -1928,6 +1938,18 @@ trait StagedWasmEvaluator extends SAIOps v.assert() } eval(rest, kont, trail)(newCtx) + case Import("i32", "is_symbolic", _) => + val newCtx2 = withBlock { + val (ty, newCtx) = ctx.pop() + Stack.popC(ty) + Stack.popS(ty) + val (ty1, newCtx1) = ctx.pop() + val idx = Stack.popC(ty1) + Stack.popS(ty) + Stack.pushC(isSymbolic(idx.toInt)) + newCtx1.push(NumType(I32Type)) + } + eval(rest, kont, trail)(newCtx2) case Import("mem", "alloc", _) => // this semantics here is not standardized in wasp, here is wasp's impl // https://github.com/formalsec/wasp/blob/release/0.2.3/wasp/symbolic/concolic.ml#L449 @@ -1969,7 +1991,8 @@ trait StagedWasmEvaluator extends SAIOps case Clz(_) => value.clz() case Ctz(_) => value.ctz() case Popcnt(_) => value.popcnt() - case _ => ??? + case Abs(_) => value.abs() + case _ => throw new Exception(s"Unknown unary operation $op") } def evalUnaryOpS(op: UnaryOp, value: StagedSymbolicNum, c: StagedConcreteNum): StagedSymbolicNum = { @@ -1980,6 +2003,7 @@ trait StagedWasmEvaluator extends SAIOps case Clz(_) => value.clz() case Ctz(_) => value.ctz() case Popcnt(_) => value.popcnt() + case Abs(_) => value.abs() case _ => throw new Exception(s"Unknown unary operation $op") }).s } @@ -2170,6 +2194,10 @@ trait StagedWasmEvaluator extends SAIOps "reset-stacks".reflectCtrlWith[Unit]() } + def isSymbolic(index: Rep[Int]): StagedConcreteNum = { + StagedConcreteNum(NumType(I32Type), "is-symbolic".reflectCtrlWith[Num](index)) + } + def evalSeq(instrs: List[Instr], kont: Context => Rep[Cont[Unit]], trail: Trail[Unit]): Rep[Unit] = { @@ -2505,6 +2533,8 @@ trait StagedWasmCppGen extends CGenBase with CppSAICodeGenBase { emit("(0 == "); shallow(num); emit(")") case Node(_, "sym-is-zero", List(s_num), _) => shallow(s_num); emit(".is_zero().bool2bv()") + case Node(_, "sym-unary-abs", List(s_num), _) => + shallow(s_num); emit(".abs()") case Node(_, "i32-binary-add", List(lhs, rhs), _) => shallow(lhs); emit(".i32_add("); shallow(rhs); emit(")") case Node(_, "i64-binary-add", List(lhs, rhs), _) => @@ -2621,6 +2651,10 @@ trait StagedWasmCppGen extends CGenBase with CppSAICodeGenBase { emit("("); shallow(num); emit(".trunc_f32_to_i32_u())") case Node(_, "f64-trunc-to-i32-u", List(num), _) => emit("("); shallow(num); emit(".trunc_f64_to_i32_u())") + case Node(_, "f32-unary-abs", List(num), _) => + emit("("); shallow(num); emit(".f32_abs())") + case Node(_, "f64-unary-abs", List(num), _) => + emit("("); shallow(num); emit(".f64_abs())") case Node(_, "f32-binary-add", List(lhs, rhs), _) => shallow(lhs); emit(".f32_add("); shallow(rhs); emit(")") case Node(_, "f64-binary-add", List(lhs, rhs), _) => @@ -2753,6 +2787,8 @@ trait StagedWasmCppGen extends CGenBase with CppSAICodeGenBase { emit("prependCont("); shallow(kont); emit(", "); shallow(mkont); emit(")") case Node(_, "enter-current-mkont", List(), _) => emit("enterCC(std::monostate())") + case Node(_, "is-symbolic", List(index), _) => + emit("isSymbolic("); shallow(index); emit(")") case Node(_, "init-func-table", List(offset, i, func), _) => emit("FuncTable.set("); shallow(offset); emit(", "); shallow(i); emit(", "); shallow(func); emit(")") case Node(_, "tree-fill-call-indirect", List(s, id), _) => diff --git a/src/test/scala/genwasym/TestBenchmark.scala b/src/test/scala/genwasym/TestBenchmark.scala index 0c4f2edb..68d550c7 100644 --- a/src/test/scala/genwasym/TestBenchmark.scala +++ b/src/test/scala/genwasym/TestBenchmark.scala @@ -58,7 +58,9 @@ class TestBenchmark extends FunSuite { test("compile-collection-c-benchmarks") { compileDirTreeToCpp("./benchmarks/pldi2026/Collection-C/tests-normalized/", Some("__original_main")) } test("compile-a-single-file") { sys.env.get("INPUT") match { - case Some(path) => compileToCpp(path) + case Some(path) => + val main = sys.env.get("MAIN") + compileToCpp(path, main) case None => println("Environment variable INPUT not set; skipping compileToCpp") } } From 2ae5641ff3f605b8abc825e9393905bf93393c3b Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Sun, 15 Mar 2026 15:06:43 -0400 Subject: [PATCH 11/16] more test for call_indirect --- benchmarks/wasm/call_indirect_test.wat | 34 ++++++++++++------- .../genwasym/TestStagedConcolicEval.scala | 2 +- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/benchmarks/wasm/call_indirect_test.wat b/benchmarks/wasm/call_indirect_test.wat index e38f4b97..d5a119ad 100644 --- a/benchmarks/wasm/call_indirect_test.wat +++ b/benchmarks/wasm/call_indirect_test.wat @@ -3,9 +3,6 @@ (type (;1;) (func (param i32 i32) (result i32))) (type (;2;) (func (result i32))) (func (;0;) (type 0) (param i32) (result i32) - (local i32 i32 i32 i32 i32) - local.get 3 - drop local.get 0 i32.const 1 i32.add) @@ -13,16 +10,29 @@ local.get 0 i32.const 2 i32.mul) - (func (;2;) (type 1) (param i32 i32) (result i32) + (func (;2;) (type 0) (param i32) (result i32) + local.get 0 + i32.const 3 + i32.sub) + (func (;3;) (type 1) (param i32 i32) (result i32) local.get 1 local.get 0 call_indirect (type 0)) - (func (;3;) (type 2) (result i32) + (func (;4;) (type 2) (result i32) + ;; (1 + 10) + (2 * 10) + (10 - 3) = 38 i32.const 0 - i32.const 41 - call 2) - (table (;0;) 2 funcref) - (export "run" (func 3)) - (export "dispatch" (func 2)) - (elem (;0;) (i32.const 0) func 0 1) - (start 3)) + i32.const 10 + call 3 + i32.const 1 + i32.const 10 + call 3 + i32.add + i32.const 2 + i32.const 10 + call 3 + i32.add) + (table (;0;) 3 funcref) + (export "run" (func 4)) + (export "dispatch" (func 3)) + (elem (;0;) (i32.const 0) func 0 1 2) + (start 4)) diff --git a/src/test/scala/genwasym/TestStagedConcolicEval.scala b/src/test/scala/genwasym/TestStagedConcolicEval.scala index 4df5b012..c45a962c 100644 --- a/src/test/scala/genwasym/TestStagedConcolicEval.scala +++ b/src/test/scala/genwasym/TestStagedConcolicEval.scala @@ -207,7 +207,7 @@ class TestStagedConcolicEval extends CppCompilationTestBase { } test("call-indirect-concrete") { - testFileConcreteCpp("./benchmarks/wasm/call_indirect_test.wat", expect=Some(List(42))) + testFileConcreteCpp("./benchmarks/wasm/call_indirect_test.wat", expect=Some(List(38))) } test("data-section-concrete") { From a94b8e0fd307f01b7bd632b236c35aabd71f2d3e Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Sun, 15 Mar 2026 16:10:03 -0400 Subject: [PATCH 12/16] fix function table index --- benchmarks/wasm/call_indirect_test.1.wat | 38 +++++++++++++++++++ headers/wasm/concrete_rt.hpp | 31 ++++++++++++--- .../scala/wasm/StagedConcolicMiniWasm.scala | 2 +- .../genwasym/TestStagedConcolicEval.scala | 4 ++ 4 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 benchmarks/wasm/call_indirect_test.1.wat diff --git a/benchmarks/wasm/call_indirect_test.1.wat b/benchmarks/wasm/call_indirect_test.1.wat new file mode 100644 index 00000000..070224ce --- /dev/null +++ b/benchmarks/wasm/call_indirect_test.1.wat @@ -0,0 +1,38 @@ +(module + (type (;0;) (func (param i32) (result i32))) + (type (;1;) (func (param i32 i32) (result i32))) + (type (;2;) (func (result i32))) + (func (;0;) (type 0) (param i32) (result i32) + local.get 0 + i32.const 1 + i32.add) + (func (;1;) (type 0) (param i32) (result i32) + local.get 0 + i32.const 2 + i32.mul) + (func (;2;) (type 0) (param i32) (result i32) + local.get 0 + i32.const 3 + i32.sub) + (func (;3;) (type 1) (param i32 i32) (result i32) + local.get 1 + local.get 0 + call_indirect (type 0)) + (func (;4;) (type 2) (result i32) + ;; (1 + 10) + (2 * 10) + (10 - 3) = 38 + i32.const 1000 + i32.const 10 + call 3 + i32.const 1001 + i32.const 10 + call 3 + i32.add + i32.const 1002 + i32.const 10 + call 3 + i32.add) + (table (;0;) 4 funcref) + (export "run" (func 4)) + (export "dispatch" (func 3)) + (elem (;0;) (i32.const 1000) func 0 1 2) + (start 4)) diff --git a/headers/wasm/concrete_rt.hpp b/headers/wasm/concrete_rt.hpp index 47844d65..277a331b 100644 --- a/headers/wasm/concrete_rt.hpp +++ b/headers/wasm/concrete_rt.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ class Stack_t { Num pop() { Profile.step(StepProfileKind::POP); if (count <= 0) { + assert(false); throw std::runtime_error("Stack underflow"); } #ifdef DEBUG @@ -266,6 +268,7 @@ struct Memory_t { int32_t loadInt(int32_t base, int32_t offset) { int32_t addr = base + offset; if (!(addr + 3 < memory.size()) || addr < 0) { + assert(false); throw std::runtime_error("Invalid memory access " + std::to_string(addr)); } int32_t result = 0; @@ -285,6 +288,7 @@ struct Memory_t { uint8_t loadByte(int32_t base, int32_t offset) { int32_t addr = base + offset; if (!(addr < memory.size()) || addr < 0) { + assert(false); throw std::runtime_error("Invalid memory access " + std::to_string(addr)); } return memory[addr]; @@ -353,6 +357,7 @@ struct Memory_t { int64_t loadLong(int32_t base, int32_t offset) { int32_t addr = base + offset; if (!(addr + 7 < memory.size()) || addr < 0) { + assert(false); throw std::runtime_error("Invalid memory access " + std::to_string(addr)); } int64_t result = 0; @@ -366,6 +371,7 @@ struct Memory_t { int32_t addr = base + offset; // Ensure we don't write out of bounds if (!(addr + 3 < memory.size())) { + assert(false); throw std::runtime_error("Invalid memory access " + std::to_string(addr)); } for (int i = 0; i < 4; ++i) { @@ -381,6 +387,7 @@ struct Memory_t { std::monostate storeLong(int32_t base, int32_t offset, int64_t value) { int32_t addr = base + offset; if (!(addr + 7 < memory.size()) || addr < 0) { + assert(false); throw std::runtime_error("Invalid memory access " + std::to_string(addr)); } for (int i = 0; i < 8; ++i) { @@ -474,23 +481,28 @@ struct FuncTable_t { std::vector table; Func_t read(int32_t index) { - if (index < 0 || index >= table.size()) { + auto offset = index - start_index.value(); + if (offset < 0 || offset >= table.size()) { throw std::runtime_error("Function table read out of bounds: " + std::to_string(index)); } - if (!table[index]) { + if (!table[offset]) { std::cout << "Function table entry at index " << index << " is empty or invalid" << std::endl; assert(false && "Function table entry is empty or invalid"); throw std::runtime_error("Function table entry at index " + std::to_string(index) + " is empty or invalid"); } - return table[index]; + return table[offset]; } std::monostate set(Num offset, int32_t index, Func_t func) { - assert(offset.value == 1 && - "Only support one function table per module for now"); + if (start_index.has_value()) { + assert(offset.toInt() == start_index && + "Currently only supporting one function table per module."); + } else { + start_index = offset.toInt(); + } if (index < 0 || index >= table.size()) { throw std::runtime_error("Function table set out of bounds: " + std::to_string(index)); @@ -498,6 +510,15 @@ struct FuncTable_t { table[index] = func; return std::monostate{}; } + + std::monostate setStart(int32_t index) { + // set start index to be the function at index 0 + start_index = index; + return std::monostate{}; + } + +private: + std::optional start_index; }; static FuncTable_t FuncTable; diff --git a/src/main/scala/wasm/StagedConcolicMiniWasm.scala b/src/main/scala/wasm/StagedConcolicMiniWasm.scala index fa85fd01..766195c1 100644 --- a/src/main/scala/wasm/StagedConcolicMiniWasm.scala +++ b/src/main/scala/wasm/StagedConcolicMiniWasm.scala @@ -2246,7 +2246,7 @@ trait StagedWasmEvaluator extends SAIOps evalSeq(offset, (_: Context) => forwardKont, ((_: Context) => forwardKont)::Nil) val offsetC = Stack.popC(NumType(I32Type)) Stack.popS(NumType(I32Type)) - Predef.println(s"funcIndices: $funcIndices") + // Predef.println(s"funcIndices: $funcIndices") for ((fidx, i) <- funcIndices.asInstanceOf[ElemListFunc].funcs.view.zipWithIndex) { val FuncDef(_, FuncBodyDef(ty, _, bodyLocals, body)) = module.funcs(fidx) val func = evalFunc(ty, body, fidx, ty.inps, bodyLocals) diff --git a/src/test/scala/genwasym/TestStagedConcolicEval.scala b/src/test/scala/genwasym/TestStagedConcolicEval.scala index c45a962c..21535d9b 100644 --- a/src/test/scala/genwasym/TestStagedConcolicEval.scala +++ b/src/test/scala/genwasym/TestStagedConcolicEval.scala @@ -210,6 +210,10 @@ class TestStagedConcolicEval extends CppCompilationTestBase { testFileConcreteCpp("./benchmarks/wasm/call_indirect_test.wat", expect=Some(List(38))) } + test("call-indirect-offset-concrete") { + testFileConcreteCpp("./benchmarks/wasm/call_indirect_test.1.wat", expect=Some(List(38))) + } + test("data-section-concrete") { testFileConcreteCpp("./benchmarks/wasm/data_sec.wat", expect=Some(List(67305985))) } From c815e02abf817df5377b08b357e01cf7ba87c339 Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Sun, 15 Mar 2026 18:00:48 -0400 Subject: [PATCH 13/16] a soft assert option --- headers/wasm/config.hpp | 6 ++++++ headers/wasm/smt_solver.hpp | 9 ++++++--- headers/wasm/utils.hpp | 11 ++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/headers/wasm/config.hpp b/headers/wasm/config.hpp index 6b64cbaf..4e4f2c35 100644 --- a/headers/wasm/config.hpp +++ b/headers/wasm/config.hpp @@ -79,4 +79,10 @@ static const bool ENABLE_COST_MODEL = true; static const bool ENABLE_COST_MODEL = false; #endif +#ifdef USE_SOFT_ASSERT +static const bool SOFT_ASSERT = true; +#else +static const bool SOFT_ASSERT = false; +#endif + #endif // CONFIG_HPP \ No newline at end of file diff --git a/headers/wasm/smt_solver.hpp b/headers/wasm/smt_solver.hpp index 562eeecb..08d3ea4c 100644 --- a/headers/wasm/smt_solver.hpp +++ b/headers/wasm/smt_solver.hpp @@ -53,7 +53,8 @@ compose_query_results(const std::vector &results) { starts_with(name, "s_f64")) && "Unexpected declaration in query result model"); assert(!combined_model.has_interp(decl) && - "Internal Error: Conflicting constant declarations when composing query results"); + "Internal Error: Conflicting constant declarations when composing " + "query results"); z3::expr value = model.get_const_interp(decl); combined_model.add_const_interp(decl, value); } @@ -450,8 +451,10 @@ inline std::monostate GENSYM_SYM_ASSERT(SymVal &sym_cond) { Profile.remove_instruction_time(TimeProfileKind::INSTR, time_need_to_be_removed.count()); if (result.has_value()) { - std::cout << "Symbolic assertion failed" << std::endl; - throw std::runtime_error("Symbolic assertion failed"); + GENSYM_INFO("Symbolic assertion failed"); + if (!SOFT_ASSERT) + throw std::runtime_error("Symbolic assertion failed"); + GENSYM_INFO("Soft assertion configured, continuing execution..."); } return std::monostate{}; } diff --git a/headers/wasm/utils.hpp b/headers/wasm/utils.hpp index 62c5bb8a..54aed2cd 100644 --- a/headers/wasm/utils.hpp +++ b/headers/wasm/utils.hpp @@ -1,5 +1,6 @@ #ifndef UTILS_HPP #define UTILS_HPP +#include "config.hpp" #include #include @@ -7,9 +8,13 @@ #define GENSYM_ASSERT(condition) \ do { \ if (!(condition)) { \ - throw std::runtime_error(std::string("Assertion failed: ") + " (" + \ - __FILE__ + ":" + std::to_string(__LINE__) + \ - ")"); \ + std::string message = std::string("Assertion failed: ") + " (" + \ + __FILE__ + ":" + std::to_string(__LINE__) + ")"; \ + if (SOFT_ASSERT) { \ + GENSYM_INFO(message); \ + } else { \ + throw std::runtime_error(message); \ + } \ } \ } while (0) #endif From 1b8c98dfbdcd0e94a21929bff31b39c1ba676ff1 Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Mon, 16 Mar 2026 17:23:03 -0400 Subject: [PATCH 14/16] an assertion --- headers/wasm/symbolic_decl.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/headers/wasm/symbolic_decl.hpp b/headers/wasm/symbolic_decl.hpp index 7885a615..22bd4c03 100644 --- a/headers/wasm/symbolic_decl.hpp +++ b/headers/wasm/symbolic_decl.hpp @@ -111,7 +111,9 @@ struct SymExtract : public Symbolic { int low; SymExtract(SymVal value, int high, int low) - : value(value), high(high), low(low) {} + : value(value), high(high), low(low) { + assert(value->value_kind() == KindBV); + } int size() override { if (_cached_dag_size.has_value()) { From 2866cd0e0964b9d024ae66d5f509d3c8f19f41e5 Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Tue, 17 Mar 2026 21:56:48 -0400 Subject: [PATCH 15/16] internal alloc and free --- headers/wasm/concolic_driver.hpp | 1 + headers/wasm/concrete_rt.hpp | 34 ++++------ headers/wasm/utils.hpp | 68 ++++++++++++++++++- .../scala/wasm/StagedConcolicMiniWasm.scala | 31 +++++++-- 4 files changed, 105 insertions(+), 29 deletions(-) diff --git a/headers/wasm/concolic_driver.hpp b/headers/wasm/concolic_driver.hpp index 81c7ff57..ce1eedbb 100644 --- a/headers/wasm/concolic_driver.hpp +++ b/headers/wasm/concolic_driver.hpp @@ -223,6 +223,7 @@ inline void ConcolicDriver::main_exploration_loop() { GENSYM_INFO("Caught runtime error during execution"); switch (EXPLORE_MODE) { case ExploreMode::EarlyExit: + GENSYM_INFO("Exiting exploration due to error..."); return; case ExploreMode::ExitByCoverage: if (ExploreTree.all_branch_covered()) { diff --git a/headers/wasm/concrete_rt.hpp b/headers/wasm/concrete_rt.hpp index 277a331b..c102ffbe 100644 --- a/headers/wasm/concrete_rt.hpp +++ b/headers/wasm/concrete_rt.hpp @@ -265,12 +265,15 @@ struct Memory_t { reset(); } + void assert_valid_range(int32_t addr, size_t width) const { + assert(addr >= 0); + assert(static_cast(addr) + width <= memory.size()); + GENSYM_ASSERT_ADDR_ALLOCATED(addr, width); + } + int32_t loadInt(int32_t base, int32_t offset) { int32_t addr = base + offset; - if (!(addr + 3 < memory.size()) || addr < 0) { - assert(false); - throw std::runtime_error("Invalid memory access " + std::to_string(addr)); - } + assert_valid_range(addr, 4); int32_t result = 0; // Little-endian: lowest byte at lowest address for (int i = 0; i < 4; ++i) { @@ -287,10 +290,7 @@ struct Memory_t { uint8_t loadByte(int32_t base, int32_t offset) { int32_t addr = base + offset; - if (!(addr < memory.size()) || addr < 0) { - assert(false); - throw std::runtime_error("Invalid memory access " + std::to_string(addr)); - } + assert_valid_range(addr, 1); return memory[addr]; } @@ -356,10 +356,7 @@ struct Memory_t { int64_t loadLong(int32_t base, int32_t offset) { int32_t addr = base + offset; - if (!(addr + 7 < memory.size()) || addr < 0) { - assert(false); - throw std::runtime_error("Invalid memory access " + std::to_string(addr)); - } + assert_valid_range(addr, 8); int64_t result = 0; for (int i = 0; i < 8; ++i) { result |= static_cast(memory[addr + i]) << (8 * i); @@ -369,11 +366,7 @@ struct Memory_t { std::monostate storeInt(int32_t base, int32_t offset, int32_t value) { int32_t addr = base + offset; - // Ensure we don't write out of bounds - if (!(addr + 3 < memory.size())) { - assert(false); - throw std::runtime_error("Invalid memory access " + std::to_string(addr)); - } + assert_valid_range(addr, 4); for (int i = 0; i < 4; ++i) { memory[addr + i] = static_cast((value >> (8 * i)) & 0xFF); } @@ -386,10 +379,7 @@ struct Memory_t { std::monostate storeLong(int32_t base, int32_t offset, int64_t value) { int32_t addr = base + offset; - if (!(addr + 7 < memory.size()) || addr < 0) { - assert(false); - throw std::runtime_error("Invalid memory access " + std::to_string(addr)); - } + assert_valid_range(addr, 8); for (int i = 0; i < 8; ++i) { memory[addr + i] = static_cast( (static_cast(value) >> (8 * i)) & 0xFF); @@ -430,7 +420,7 @@ struct Memory_t { std::cout << "[Debug] storing byte " << std::to_string(value) << " to memory at address " << addr << std::endl; #endif - assert(addr < memory.size()); + assert_valid_range(addr, 1); memory[addr] = value; return std::monostate{}; } diff --git a/headers/wasm/utils.hpp b/headers/wasm/utils.hpp index 54aed2cd..2782d6d9 100644 --- a/headers/wasm/utils.hpp +++ b/headers/wasm/utils.hpp @@ -1,7 +1,11 @@ #ifndef UTILS_HPP #define UTILS_HPP #include "config.hpp" +#include +#include #include +#include +#include #include #ifndef GENSYM_ASSERT @@ -43,6 +47,68 @@ #endif +enum class GensymHeapStatus { Allocated, Freed }; + +struct GensymHeapRecord { + int32_t size; + GensymHeapStatus status; +}; + +inline std::unordered_map GENSYM_HEAP_RECORDS; + +inline bool GENSYM_IS_IN_ALLOCATED_RANGE(int32_t addr, size_t width) { + const int64_t start = addr; + const int64_t end = start + static_cast(width); + for (const auto &[base, record] : GENSYM_HEAP_RECORDS) { + if (record.status != GensymHeapStatus::Allocated) { + continue; + } + const int64_t alloc_start = base; + const int64_t alloc_end = alloc_start + static_cast(record.size); + if (alloc_start <= start && end <= alloc_end) { + return true; + } + } + return false; +} + +inline bool GENSYM_SHOULD_CHECK_ALLOCATION(int32_t addr) { + if (GENSYM_HEAP_RECORDS.empty()) { + return false; + } + int32_t heap_base = std::numeric_limits::max(); + for (const auto &[base, _] : GENSYM_HEAP_RECORDS) { + heap_base = std::min(heap_base, base); + } + return addr >= heap_base; +} + +inline void GENSYM_ASSERT_ADDR_ALLOCATED(int32_t addr, size_t width) { + if (!GENSYM_SHOULD_CHECK_ALLOCATION(addr)) { + return; + } + GENSYM_ASSERT(GENSYM_IS_IN_ALLOCATED_RANGE(addr, width)); +} + +inline int32_t GENSYM_ALLOC(int32_t base, int32_t size) { + // std::cout << "Allocating memory at address " << base << " with size " << size + // << std::endl; + GENSYM_ASSERT(base >= 0); + GENSYM_ASSERT(size >= 0); + GENSYM_HEAP_RECORDS[base] = + GensymHeapRecord{size, GensymHeapStatus::Allocated}; + return base; +} + +inline std::monostate GENSYM_FREE(int32_t ptr) { + // std::cout << "Freeing memory at address " << ptr << std::endl; + GENSYM_ASSERT(ptr >= 0); + auto it = GENSYM_HEAP_RECORDS.find(ptr); + GENSYM_ASSERT(it != GENSYM_HEAP_RECORDS.end()); + it->second.status = GensymHeapStatus::Freed; + return std::monostate{}; +} + #if __cplusplus < 202002L #include @@ -94,4 +160,4 @@ std::monostate infoWhen(const char *dbg_option, const Args &...args) { inline std::monostate get_unit() { return std::monostate{}; } inline std::monostate get_unit(std::monostate x) { return std::monostate{}; } -#endif // UTILS_HPP \ No newline at end of file +#endif // UTILS_HPP diff --git a/src/main/scala/wasm/StagedConcolicMiniWasm.scala b/src/main/scala/wasm/StagedConcolicMiniWasm.scala index 766195c1..82faf70e 100644 --- a/src/main/scala/wasm/StagedConcolicMiniWasm.scala +++ b/src/main/scala/wasm/StagedConcolicMiniWasm.scala @@ -1630,7 +1630,12 @@ trait StagedWasmEvaluator extends SAIOps val newRestCtx = restCtx.shift(offset, funcTy.out.size) eval(rest, kont, trail)(newRestCtx) }) - eval(inner, restK _, restK _ :: trail) + def innerK: Rep[Cont[Unit]] = topFun((_: Rep[Unit]) => { + info(s"Entering the block, stackSize =", Stack.size) + eval(inner, restK _, restK _ :: trail) + }) + tailCall(innerK, ()) + () case Loop(ty, inner) => val funcTy = ty.funcType val exitSize = ctx.stackTypes.size - funcTy.inps.size + funcTy.out.size @@ -1954,19 +1959,21 @@ trait StagedWasmEvaluator extends SAIOps // this semantics here is not standardized in wasp, here is wasp's impl // https://github.com/formalsec/wasp/blob/release/0.2.3/wasp/symbolic/concolic.ml#L449 val (_, newCtx1) = ctx.pop() - val a = Stack.popC(NumType(I32Type)) + val size = Stack.popC(NumType(I32Type)) Stack.popS(NumType(I32Type)) val (_, newCtx2) = newCtx1.pop() - val b = Stack.popC(NumType(I32Type)) + val base = Stack.popC(NumType(I32Type)) Stack.popS(NumType(I32Type)) - Stack.pushC(b) - val s = "Concrete".reflectCtrlWith[SymVal](Values.I32V(b.toInt), 32) + val ptr = Values.I32V(gensymAlloc(base.toInt, size.toInt)) + Stack.pushC(StagedConcreteNum(NumType(I32Type), ptr)) + val s = "Concrete".reflectCtrlWith[SymVal](ptr, 32) Stack.pushS(StagedSymbolicNum(NumType(I32Type), s)) eval(rest, kont, trail)(newCtx1) case Import("mem", "free", _) => val (_, newCtx) = ctx.pop() - Stack.popC(NumType(I32Type)) + val ptr = Stack.popC(NumType(I32Type)) Stack.popS(NumType(I32Type)) + gensymFree(ptr.toInt) eval(rest, kont, trail)(newCtx) case Import("env", "proc_exit", _) => val (_, newCtx) = ctx.pop() @@ -2194,6 +2201,14 @@ trait StagedWasmEvaluator extends SAIOps "reset-stacks".reflectCtrlWith[Unit]() } + def gensymAlloc(base: Rep[Int], size: Rep[Int]): Rep[Int] = { + "gensym-alloc".reflectCtrlWith[Int](base, size) + } + + def gensymFree(ptr: Rep[Int]): Rep[Unit] = { + "gensym-free".reflectCtrlWith[Unit](ptr) + } + def isSymbolic(index: Rep[Int]): StagedConcreteNum = { StagedConcreteNum(NumType(I32Type), "is-symbolic".reflectCtrlWith[Num](index)) } @@ -2743,6 +2758,10 @@ trait StagedWasmCppGen extends CGenBase with CppSAICodeGenBase { shallow(lhs); emit(".rem_u("); shallow(rhs); emit(")") case Node(_, "sym-i32-extend-to-i64", List(num), _) => shallow(num); emit(".extend_to_i64()") + case Node(_, "gensym-alloc", List(base, size), _) => + emit("GENSYM_ALLOC("); shallow(base); emit(", "); shallow(size); emit(")") + case Node(_, "gensym-free", List(ptr), _) => + emit("GENSYM_FREE("); shallow(ptr); emit(")") case Node(_, "num-to-int", List(num), _) => shallow(num); emit(".toInt()") case Node(_, "make-i32-symbol", List(num), _) => From 2e8b73f68f51f3a7e5d9a4cf5736fe7c178eda4f Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Sat, 6 Jun 2026 19:12:46 -0400 Subject: [PATCH 16/16] profile heuristics --- headers/wasm/concolic_driver.hpp | 10 +- headers/wasm/config.hpp | 8 +- headers/wasm/output_report.hpp | 4 +- headers/wasm/profile.hpp | 31 ++++++ headers/wasm/sym_rt.hpp | 8 +- scripts/genwasym_profile_analyzer.py | 111 ++++++++++++++++++++ src/test/scala/genwasym/TestBenchmark.scala | 1 + 7 files changed, 166 insertions(+), 7 deletions(-) create mode 100755 scripts/genwasym_profile_analyzer.py diff --git a/headers/wasm/concolic_driver.hpp b/headers/wasm/concolic_driver.hpp index ce1eedbb..0bd4ca3a 100644 --- a/headers/wasm/concolic_driver.hpp +++ b/headers/wasm/concolic_driver.hpp @@ -196,7 +196,15 @@ inline void ConcolicDriver::main_exploration_loop() { GENSYM_INFO("Now execute the program with symbolic environment: "); GENSYM_INFO(SymEnv.to_string()); auto snapshot = dynamic_cast(node->node.get()); + if (snapshot && PROFILE_SNAPSHOT) { + auto resume_cost = snapshot->cost_of_snapshot_resume(); + auto restart_cost = snapshot->cost_of_restart(); + Profile.record_snapshot_history(resume_cost, restart_cost); + } if (REUSE_SNAPSHOT && snapshot && snapshot->worth_to_reuse()) { + // If we enabled snapshot reuse and the current snapshot is worth to + // reuse, resume the execution from the snapshot with the model we got + // from SMT solver. assert(REUSE_SNAPSHOT); Profile.incr_fromsnapshot_count(); auto snap = snapshot->get_snapshot(); @@ -275,4 +283,4 @@ static void start_concolic_execution_with( std::quick_exit(0); } -#endif // CONCOLIC_DRIVER_HPP \ No newline at end of file +#endif // CONCOLIC_DRIVER_HPP diff --git a/headers/wasm/config.hpp b/headers/wasm/config.hpp index 4e4f2c35..79790041 100644 --- a/headers/wasm/config.hpp +++ b/headers/wasm/config.hpp @@ -37,6 +37,12 @@ const bool PROFILE_PATH_CONDS = true; const bool PROFILE_PATH_CONDS = false; #endif +#ifdef ENABLE_PROFILE_SNAPSHOT +const bool PROFILE_SNAPSHOT = true; +#else +const bool PROFILE_SNAPSHOT = false; +#endif + // This variable define when concolic execution will stop enum class ExploreMode { EarlyExit, // Stop at the first error encountered @@ -85,4 +91,4 @@ static const bool SOFT_ASSERT = true; static const bool SOFT_ASSERT = false; #endif -#endif // CONFIG_HPP \ No newline at end of file +#endif // CONFIG_HPP diff --git a/headers/wasm/output_report.hpp b/headers/wasm/output_report.hpp index 26bf5410..9eafa0ec 100644 --- a/headers/wasm/output_report.hpp +++ b/headers/wasm/output_report.hpp @@ -40,11 +40,11 @@ inline void dump_all_summary_json(const Profile_t &profile, ofs << " \"not_to_explore_count\": " << overall.not_to_explore_count << ",\n"; ofs << " \"unreachable_count\": " << overall.unreachable_count; - if (PROFILE_STEP || PROFILE_TIME) { + if (PROFILE_STEP || PROFILE_TIME || PROFILE_SNAPSHOT) { ofs << ",\n"; profile.write_as_json(ofs); } ofs << "}\n"; ofs.close(); } -#endif // WASM_OUTPUT_REPORT_HPP \ No newline at end of file +#endif // WASM_OUTPUT_REPORT_HPP diff --git a/headers/wasm/profile.hpp b/headers/wasm/profile.hpp index 1f621b81..fb0ab64e 100644 --- a/headers/wasm/profile.hpp +++ b/headers/wasm/profile.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -220,6 +221,11 @@ class Profile_t { TimeProfileKind::COLLECT_PATH_CONDITIONS)] << std::endl; } + if (PROFILE_SNAPSHOT) { + std::cout << "Snapshot Profile Summary:" << std::endl; + std::cout << "Total snapshot records: " << snapshot_history.size() + << std::endl; + } std::cout << "Number of calls to solver: " << call_solver_count << std::endl; std::cout << "Execution Kind Summary:" << std::endl; @@ -313,6 +319,25 @@ class Profile_t { static_cast(cache_hit_count) / static_cast(cache_hit_count + cache_miss_count)); } + if (PROFILE_SNAPSHOT) { + write_field("total_snapshot_records", snapshot_history.size()); + write_field_prefix("snapshot_history"); + os << "["; + for (std::size_t i = 0; i < snapshot_history.size(); ++i) { + if (i != 0) { + os << ","; + } + os << "\n {" + << "\"resume_cost\": " << std::setprecision(15) + << snapshot_history[i].first << ", " + << "\"restart_cost\": " << std::setprecision(15) + << snapshot_history[i].second << "}"; + } + if (!snapshot_history.empty()) { + os << "\n "; + } + os << "]"; + } if (needs_comma) { os << '\n'; } @@ -352,6 +377,12 @@ class Profile_t { time_count[static_cast(kind)] -= time; } + void record_snapshot_history(double resume_cost, double restart_cost) { + snapshot_history.emplace_back(resume_cost, restart_cost); + } + + std::vector> snapshot_history; + int step_count; std::array(StepProfileKind::OperationCount)> op_count; diff --git a/headers/wasm/sym_rt.hpp b/headers/wasm/sym_rt.hpp index 0ff47827..c0118c09 100644 --- a/headers/wasm/sym_rt.hpp +++ b/headers/wasm/sym_rt.hpp @@ -748,7 +748,7 @@ struct Node { friend struct NodeBox; virtual ~Node() {}; void set_cost(double c) { instr_cost = c; } - double get_cost() const { return instr_cost; } + double cost_of_restart() const { return instr_cost; } virtual std::string to_string() = 0; void to_graphviz(std::ostream &os) { os << "digraph G {\n"; @@ -789,7 +789,7 @@ struct Node { inline double NodeBox::instr_cost() const { if (node) { - return node->get_cost(); + return node->cost_of_restart(); } else { return 0.0; } @@ -932,6 +932,8 @@ struct SnapshotNode : Node { const Snapshot_t &get_snapshot() const { return snapshot; } Snapshot_t move_out_snapshot() { return std::move(snapshot); } + double cost_of_snapshot_resume() const { return snapshot.cost_of_snapshot(); } + bool worth_to_reuse() const { if (!ENABLE_COST_MODEL) { // If we are not using cost model, always create snapshot @@ -939,7 +941,7 @@ struct SnapshotNode : Node { } // find out the best way to reach the current position via our cost model auto snapshot_cost = snapshot.cost_of_snapshot(); - double re_execution_cost = get_cost(); + double re_execution_cost = cost_of_restart(); // std::cout << "Snapshot cost: " << snapshot_cost // << ", re-execution cost: " << re_execution_cost << std::endl; if (snapshot_cost <= re_execution_cost) { diff --git a/scripts/genwasym_profile_analyzer.py b/scripts/genwasym_profile_analyzer.py new file mode 100755 index 00000000..b9313a7d --- /dev/null +++ b/scripts/genwasym_profile_analyzer.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 + +import argparse +import csv +import json +import sys +from pathlib import Path +from typing import Any + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Analyze a GenWasm profile JSON file." + ) + parser.add_argument("profile", type=Path, help="profile JSON file to read") + parser.add_argument( + "-o", + "--output", + type=Path, + help="CSV file to write; defaults to stdout", + ) + parser.add_argument( + "--plot", + type=Path, + help="write a snapshot cost scatter plot to this image file", + ) + return parser.parse_args() + + +def snapshot_costs(profile: dict[str, Any]) -> tuple[list[float], list[float]]: + history = profile.get("profile_summary", {}).get("snapshot_history", []) + restart_costs = [] + resume_costs = [] + for entry in history: + restart_costs.append(float(entry["restart_cost"])) + resume_costs.append(float(entry["resume_cost"])) + return restart_costs, resume_costs + + +def write_snapshot_csv(profile: dict[str, Any], output_file: Any) -> None: + restart_costs, resume_costs = snapshot_costs(profile) + writer = csv.writer(output_file) + writer.writerow(["restart_cost", "resume_cost"]) + writer.writerows(zip(restart_costs, resume_costs)) + + +def write_snapshot_plot(profile: dict[str, Any], output: Path) -> None: + try: + import matplotlib + + matplotlib.use("Agg") + import matplotlib.pyplot as plt + except ImportError as exc: + raise RuntimeError( + "plotting requires matplotlib; install it with " + "`python3 -m pip install matplotlib`" + ) from exc + + restart_costs, resume_costs = snapshot_costs(profile) + if not restart_costs: + raise ValueError("profile does not contain snapshot history records") + + min_restart_cost = min(restart_costs) + max_restart_cost = max(restart_costs) + x_margin = (max_restart_cost - min_restart_cost) * 0.05 + if x_margin == 0: + x_margin = max_restart_cost * 0.05 + x_min = min_restart_cost - x_margin + x_max = max_restart_cost + x_margin + + y_min = 0 + y_max = max(resume_costs) * 1.05 + line_max = min(x_max, y_max) + line_min = max(x_min, y_min) + + fig, ax = plt.subplots(figsize=(8, 6)) + ax.scatter(restart_costs, resume_costs, s=14, alpha=0.75) + ax.plot([line_min, line_max], [line_min, line_max], color="black", linewidth=1.2) + ax.set_xlabel("restart_cost") + ax.set_ylabel("resume_cost") + ax.set_title("Snapshot cost profile") + ax.set_xlim(x_min, x_max) + ax.set_ylim(y_min, y_max) + ax.grid(True, linewidth=0.4, alpha=0.4) + fig.tight_layout() + fig.savefig(output) + plt.close(fig) + + +def main() -> None: + args = parse_args() + with args.profile.open() as profile_file: + profile = json.load(profile_file) + + output_file = args.output.open("w", newline="") if args.output else sys.stdout + try: + write_snapshot_csv(profile, output_file) + finally: + if args.output: + output_file.close() + + if args.plot: + try: + write_snapshot_plot(profile, args.plot) + except RuntimeError as exc: + print(f"error: {exc}", file=sys.stderr) + raise SystemExit(1) from exc + + +if __name__ == "__main__": + main() diff --git a/src/test/scala/genwasym/TestBenchmark.scala b/src/test/scala/genwasym/TestBenchmark.scala index 68d550c7..ee88e728 100644 --- a/src/test/scala/genwasym/TestBenchmark.scala +++ b/src/test/scala/genwasym/TestBenchmark.scala @@ -56,6 +56,7 @@ class TestBenchmark extends FunSuite { test("compile-crafted-benchmarks") { compileDirToCpp("./benchmarks/pldi2026/crafted/") } test("compile-aws-aws-encryption-sdk") { compileDirToCpp("./benchmarks/pldi2026/aws-encryption-sdk/tests-original-normalized/", Some("__original_main")) } test("compile-collection-c-benchmarks") { compileDirTreeToCpp("./benchmarks/pldi2026/Collection-C/tests-normalized/", Some("__original_main")) } + test("compile-quicksort-benchmark") { compileDirToCpp("/home/zdh/WorkSpace/cJSON", Some("main")) } test("compile-a-single-file") { sys.env.get("INPUT") match { case Some(path) =>