From b19bf2246e94674bfe714c0a3aa9fbe055928d08 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sun, 19 Aug 2018 21:48:26 +0200 Subject: [PATCH] Created "loop-unroll" branch. --- .../java/dk/camelot64/kickc/CompileLog.java | 4 +- .../java/dk/camelot64/kickc/Compiler.java | 42 +- .../model/ControlFlowGraphCopyVisitor.java | 4 +- .../camelot64/kickc/model/NaturalLoopSet.java | 3 +- .../kickc/model/VariableReferenceInfos.java | 17 + .../statements/StatementConditionalJump.java | 28 +- .../model/statements/StatementInfos.java | 2 +- .../model/statements/StatementPhiBlock.java | 2 +- .../java/dk/camelot64/kickc/parser/KickC.g4 | 6 +- .../camelot64/kickc/parser/KickCParser.java | 874 +++++++++--------- .../Pass0GenerateStatementSequence.java | 38 +- .../kickc/passes/Pass1AssertUsedVars.java | 4 +- .../kickc/passes/Pass1ProcedureInline.java | 169 ++-- .../Pass2ConditionalAndOrRewriting.java | 12 +- ...ysis.java => Pass2DominatorsAnalysis.java} | 10 +- ...opAnalysis.java => Pass2LoopAnalysis.java} | 18 +- .../kickc/passes/Pass2LoopUnroll.java | 230 +++++ .../kickc/passes/Pass3StatementInfos.java | 10 +- .../passes/PassNEliminateUnusedVars.java | 4 +- .../kickc/passes/PassNStatementIndices.java | 7 +- .../passes/PassNVariableReferenceInfos.java | 103 ++- .../dk/camelot64/kickc/test/TestPrograms.java | 18 +- .../dk/camelot64/kickc/test/kc/loop100.kc | 4 + .../kickc/test/kc/unroll-screenfill.kc | 25 + .../kickc/test/kc/unusedblockproblem.kc | 11 + 25 files changed, 1030 insertions(+), 615 deletions(-) rename src/main/java/dk/camelot64/kickc/passes/{Pass3DominatorsAnalysis.java => Pass2DominatorsAnalysis.java} (94%) rename src/main/java/dk/camelot64/kickc/passes/{Pass3LoopAnalysis.java => Pass2LoopAnalysis.java} (89%) create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2LoopUnroll.java create mode 100644 src/test/java/dk/camelot64/kickc/test/kc/loop100.kc create mode 100644 src/test/java/dk/camelot64/kickc/test/kc/unusedblockproblem.kc diff --git a/src/main/java/dk/camelot64/kickc/CompileLog.java b/src/main/java/dk/camelot64/kickc/CompileLog.java index 579113205..93d70fcdf 100644 --- a/src/main/java/dk/camelot64/kickc/CompileLog.java +++ b/src/main/java/dk/camelot64/kickc/CompileLog.java @@ -30,12 +30,12 @@ public class CompileLog { /** * Should SSA optimization be verbose. */ - private boolean verboseSSAOptimize = false; + private boolean verboseSSAOptimize = true; /** * Should the log be output to System.out while being built */ - private boolean sysOut = false; + private boolean sysOut = true; public CompileLog() { this.log = new StringBuilder(); diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 5b4009e48..3368cddf0 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -94,6 +94,8 @@ public class Compiler { pass1GenerateSSA(); pass2OptimizeSSA(); + pass2UnrollLoops(); + pass2InlineConstants(); pass3Analysis(); pass4RegisterAllocation(); pass5GenerateAndOptimizeAsm(); @@ -201,9 +203,30 @@ public class Compiler { optimizations.add(new Pass2NopCastElimination(program)); optimizations.add(new Pass2EliminateUnusedBlocks(program)); optimizations.add(new Pass2RangeResolving(program)); - pass2OptimizeSSA(optimizations); + } + + private void pass2UnrollLoops() { + getLog().append("CONTROL FLOW GRAPH BEFORE UNROLLING"); + getLog().append(program.getGraph().toString(program)); + + new Pass2DominatorsAnalysis(program).step(); + getLog().append("NATURAL LOOPS"); + new Pass2LoopAnalysis(program).step(); + getLog().append(program.getLoopSet().toString()); + + List loopUnrolling = new ArrayList<>(); + loopUnrolling.add(new PassNStatementIndices(program)); + loopUnrolling.add(new PassNVariableReferenceInfos(program)); + loopUnrolling.add(new Pass3StatementInfos(program)); + loopUnrolling.add(new Pass2DominatorsAnalysis(program)); + loopUnrolling.add(new Pass2LoopAnalysis(program)); + loopUnrolling.add(new Pass2LoopUnroll(program)); + pass2OptimizeSSA(loopUnrolling); + } + + private void pass2InlineConstants() { // Constant inlining optimizations - as the last step to ensure that constant identification has been completed List constantOptimizations = new ArrayList<>(); constantOptimizations.add(new Pass2ConstantInlining(program)); @@ -212,7 +235,6 @@ public class Compiler { constantOptimizations.add(new Pass2ConstantAdditionElimination(program)); constantOptimizations.add(new Pass2ConstantIfs(program)); pass2OptimizeSSA(constantOptimizations); - } private void pass2OptimizeSSA(List optimizations) { @@ -252,7 +274,7 @@ public class Compiler { //getLog().append(program.getGraph().toString(program)); pass2AssertSSA(); new Pass3AddNopBeforeCallOns(program).generate(); - new PassNStatementIndices(program).generateStatementIndices(); + new PassNStatementIndices(program).execute(); getLog().append("CALL GRAPH"); new Pass3CallGraphAnalysis(program).findCallGraph(); @@ -260,8 +282,8 @@ public class Compiler { //getLog().setVerboseLiveRanges(true); - new Pass3StatementInfos(program).generateStatementInfos(); - new PassNVariableReferenceInfos(program).generateVariableReferenceInfos(); + new Pass3StatementInfos(program).execute(); + new PassNVariableReferenceInfos(program).execute(); new Pass3LiveRangesAnalysis(program).findLiveRanges(); //getLog().append("CONTROL FLOW GRAPH - LIVE RANGES FOUND"); //getLog().append(program.getGraph().toString(program)); @@ -274,10 +296,10 @@ public class Compiler { new Pass2CullEmptyBlocks(program).step(); new Pass3BlockSequencePlanner(program).plan(); new Pass3AddNopBeforeCallOns(program).generate(); - new PassNStatementIndices(program).generateStatementIndices(); + new PassNStatementIndices(program).execute(); new Pass3CallGraphAnalysis(program).findCallGraph(); - new Pass3StatementInfos(program).generateStatementInfos(); - new PassNVariableReferenceInfos(program).generateVariableReferenceInfos(); + new Pass3StatementInfos(program).execute(); + new PassNVariableReferenceInfos(program).execute(); new Pass3SymbolInfos(program).generateSymbolInfos(); new Pass3LiveRangesAnalysis(program).findLiveRanges(); //getLog().append("CONTROL FLOW GRAPH - BEFORE EFFECTIVE LIVE RANGES"); @@ -294,11 +316,11 @@ public class Compiler { private void pass4RegisterAllocation() { getLog().append("DOMINATORS"); - new Pass3DominatorsAnalysis(program).findDominators(); + new Pass2DominatorsAnalysis(program).step(); getLog().append(program.getDominators().toString()); getLog().append("NATURAL LOOPS"); - new Pass3LoopAnalysis(program).findLoops(); + new Pass2LoopAnalysis(program).step(); getLog().append(program.getLoopSet().toString()); getLog().append("NATURAL LOOPS WITH DEPTH"); diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java index dfdd9d1c4..490d87ef8 100644 --- a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java +++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java @@ -151,7 +151,9 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitorFor definitions and more see http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf - *

Created by {@link dk.camelot64.kickc.passes.Pass3LoopAnalysis} + *

Created by {@link Pass2LoopAnalysis} */ public class NaturalLoopSet { diff --git a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java index 73a873365..85c4634a1 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java @@ -230,6 +230,23 @@ public class VariableReferenceInfos { return stmts; } + /** + * Get all statements referencing a variable + * + * @param varRef The variable to look for + * @return Index of all statements referencing the constant + */ + public Collection getVarRefStatements(VariableRef varRef) { + Collection refs = symbolVarReferences.get(varRef); + LinkedHashSet stmts = new LinkedHashSet<>(); + refs.stream() + .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) + .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx())); + return stmts; + } + + + /** * Get all constatns referencing another constant * diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java index 702ace68e..deff022f3 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java @@ -6,8 +6,7 @@ import dk.camelot64.kickc.model.operators.Operator; import dk.camelot64.kickc.model.values.RValue; /** - * Intermediate Compiler Form Statement with a conditional jump. - * Intermediate form used for compiler optimization. + * SSA form conditional jump. Intermediate form used for compiler optimization. *
* if ( Yj ) goto XX *
@@ -19,6 +18,7 @@ public class StatementConditionalJump extends StatementBase { private Operator operator; private RValue rValue2; private LabelRef destination; + private boolean declaredUnroll; public StatementConditionalJump(RValue condition, LabelRef destination,StatementSource source) { super(null, source); @@ -34,17 +34,7 @@ public class StatementConditionalJump extends StatementBase { RValue rValue2, LabelRef destination, StatementSource source) { - this(rValue1, operator, rValue2, destination, null, source); - } - - public StatementConditionalJump( - RValue rValue1, - Operator operator, - RValue rValue2, - LabelRef destination, - Integer index, - StatementSource source) { - super(index, source); + super(null, source); this.rValue1 = rValue1; this.operator = operator; this.rValue2 = rValue2; @@ -83,10 +73,22 @@ public class StatementConditionalJump extends StatementBase { this.destination = destination; } + public boolean isDeclaredUnroll() { + return declaredUnroll; + } + + public void setDeclaredUnroll(boolean declaredUnroll) { + this.declaredUnroll = declaredUnroll; + } + @Override public String toString(Program program, boolean aliveInfo) { StringBuilder out = new StringBuilder(); out.append(super.idxString()); + if(declaredUnroll) { + out.append("unroll "); + + } out.append("if("); if(rValue1 != null) { out.append(rValue1.toString(program)); diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementInfos.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementInfos.java index 8afbf3d06..b13d7cbc0 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementInfos.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementInfos.java @@ -68,7 +68,7 @@ public class StatementInfos { /** * Get statement from index * - * @param Statement index + * @param index Statement index * @return The statement with the passed index */ public Statement getStatement(int index) { diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java index e472f130d..0dad57a02 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java @@ -54,7 +54,7 @@ public class StatementPhiBlock extends StatementBase { return getPhiVariable(variable).getrValue(predecessor); } - private PhiVariable getPhiVariable(VariableRef variable) { + public PhiVariable getPhiVariable(VariableRef variable) { for(PhiVariable phiVariable : phiVariables) { if(phiVariable.getVariable().equals(variable)) { return phiVariable; diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 index de1fb1aa7..f2bcd4067 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 +++ b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 @@ -77,9 +77,9 @@ stmt | '{' stmtSeq? '}' #stmtBlock | expr ';' #stmtExpr | 'if' '(' expr ')' stmt ( 'else' stmt )? #stmtIfElse - | directive? 'while' '(' expr ')' stmt #stmtWhile - | directive? 'do' stmt 'while' '(' expr ')' ';' #stmtDoWhile - | directive? 'for' '(' forDeclaration? forIteration ')' stmt #stmtFor + | directive* 'while' '(' expr ')' stmt #stmtWhile + | directive* 'do' stmt 'while' '(' expr ')' ';' #stmtDoWhile + | directive* 'for' '(' forDeclaration? forIteration ')' stmt #stmtFor | 'return' expr? ';' #stmtReturn | 'asm' '{' asmLines '}' #stmtAsm | declKasm #stmtDeclKasm diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java index f55952dcc..1d448b6c6 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java @@ -1564,8 +1564,11 @@ public class KickCParser extends Parser { public StmtContext stmt() { return getRuleContext(StmtContext.class,0); } - public DirectiveContext directive() { - return getRuleContext(DirectiveContext.class,0); + public List directive() { + return getRuleContexts(DirectiveContext.class); + } + public DirectiveContext directive(int i) { + return getRuleContext(DirectiveContext.class,i); } public StmtWhileContext(StmtContext ctx) { copyFrom(ctx); } @Override @@ -1589,8 +1592,11 @@ public class KickCParser extends Parser { public ExprContext expr() { return getRuleContext(ExprContext.class,0); } - public DirectiveContext directive() { - return getRuleContext(DirectiveContext.class,0); + public List directive() { + return getRuleContexts(DirectiveContext.class); + } + public DirectiveContext directive(int i) { + return getRuleContext(DirectiveContext.class,i); } public StmtDoWhileContext(StmtContext ctx) { copyFrom(ctx); } @Override @@ -1614,8 +1620,11 @@ public class KickCParser extends Parser { public StmtContext stmt() { return getRuleContext(StmtContext.class,0); } - public DirectiveContext directive() { - return getRuleContext(DirectiveContext.class,0); + public List directive() { + return getRuleContexts(DirectiveContext.class); + } + public DirectiveContext directive(int i) { + return getRuleContext(DirectiveContext.class,i); } public ForDeclarationContext forDeclaration() { return getRuleContext(ForDeclarationContext.class,0); @@ -1704,7 +1713,7 @@ public class KickCParser extends Parser { enterRule(_localctx, 30, RULE_stmt); int _la; try { - setState(272); + setState(281); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) { case 1: @@ -1777,25 +1786,29 @@ public class KickCParser extends Parser { _localctx = new StmtWhileContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(230); + setState(232); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) { + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) { + { { setState(229); directive(); } + } + setState(234); + _errHandler.sync(this); + _la = _input.LA(1); } - - setState(232); - match(T__25); - setState(233); - match(T__3); - setState(234); - expr(0); setState(235); - match(T__4); + match(T__25); setState(236); + match(T__3); + setState(237); + expr(0); + setState(238); + match(T__4); + setState(239); stmt(); } break; @@ -1803,29 +1816,33 @@ public class KickCParser extends Parser { _localctx = new StmtDoWhileContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(239); + setState(244); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) { + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) { { - setState(238); + { + setState(241); directive(); } + } + setState(246); + _errHandler.sync(this); + _la = _input.LA(1); } - - setState(241); - match(T__26); - setState(242); - stmt(); - setState(243); - match(T__25); - setState(244); - match(T__3); - setState(245); - expr(0); - setState(246); - match(T__4); setState(247); + match(T__26); + setState(248); + stmt(); + setState(249); + match(T__25); + setState(250); + match(T__3); + setState(251); + expr(0); + setState(252); + match(T__4); + setState(253); match(T__2); } break; @@ -1833,35 +1850,39 @@ public class KickCParser extends Parser { _localctx = new StmtForContext(_localctx); enterOuterAlt(_localctx, 7); { - setState(250); + setState(258); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) { + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) { { - setState(249); + { + setState(255); directive(); } + } + setState(260); + _errHandler.sync(this); + _la = _input.LA(1); } - - setState(252); + setState(261); match(T__27); - setState(253); + setState(262); match(T__3); - setState(255); + setState(264); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__31))) != 0) || _la==SIMPLETYPE || _la==NAME) { { - setState(254); + setState(263); forDeclaration(); } } - setState(257); + setState(266); forIteration(); - setState(258); + setState(267); match(T__4); - setState(259); + setState(268); stmt(); } break; @@ -1869,19 +1890,19 @@ public class KickCParser extends Parser { _localctx = new StmtReturnContext(_localctx); enterOuterAlt(_localctx, 8); { - setState(261); + setState(270); match(T__28); - setState(263); + setState(272); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__5) | (1L << T__32) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 72)) & ~0x3f) == 0 && ((1L << (_la - 72)) & ((1L << (STRING - 72)) | (1L << (CHAR - 72)) | (1L << (BOOLEAN - 72)) | (1L << (NUMBER - 72)) | (1L << (NAME - 72)))) != 0)) { { - setState(262); + setState(271); expr(0); } } - setState(265); + setState(274); match(T__2); } break; @@ -1889,13 +1910,13 @@ public class KickCParser extends Parser { _localctx = new StmtAsmContext(_localctx); enterOuterAlt(_localctx, 9); { - setState(266); + setState(275); match(T__29); - setState(267); + setState(276); match(T__5); - setState(268); + setState(277); asmLines(); - setState(269); + setState(278); match(T__6); } break; @@ -1903,7 +1924,7 @@ public class KickCParser extends Parser { _localctx = new StmtDeclKasmContext(_localctx); enterOuterAlt(_localctx, 10); { - setState(271); + setState(280); declKasm(); } break; @@ -1970,56 +1991,56 @@ public class KickCParser extends Parser { _localctx = new ForDeclContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(277); + setState(286); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,28,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(274); + setState(283); directive(); } } } - setState(279); + setState(288); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,28,_ctx); } - setState(281); + setState(290); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__3 || _la==T__31 || _la==SIMPLETYPE) { { - setState(280); + setState(289); typeDecl(0); } } - setState(286); + setState(295); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) { { { - setState(283); + setState(292); directive(); } } - setState(288); + setState(297); _errHandler.sync(this); _la = _input.LA(1); } - setState(289); + setState(298); match(NAME); - setState(292); + setState(301); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__1) { { - setState(290); + setState(299); match(T__1); - setState(291); + setState(300); expr(0); } } @@ -2097,20 +2118,20 @@ public class KickCParser extends Parser { ForIterationContext _localctx = new ForIterationContext(_ctx, getState()); enterRule(_localctx, 34, RULE_forIteration); try { - setState(304); + setState(313); _errHandler.sync(this); switch (_input.LA(1)) { case T__2: _localctx = new ForClassicContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(294); + setState(303); match(T__2); - setState(295); + setState(304); expr(0); - setState(296); + setState(305); match(T__2); - setState(297); + setState(306); expr(0); } break; @@ -2118,15 +2139,15 @@ public class KickCParser extends Parser { _localctx = new ForRangeContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(299); + setState(308); match(T__12); - setState(300); + setState(309); expr(0); { - setState(301); + setState(310); match(T__30); } - setState(302); + setState(311); expr(0); } break; @@ -2286,7 +2307,7 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(314); + setState(323); _errHandler.sync(this); switch (_input.LA(1)) { case T__3: @@ -2295,11 +2316,11 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(307); + setState(316); match(T__3); - setState(308); + setState(317); typeDecl(0); - setState(309); + setState(318); match(T__4); } break; @@ -2308,7 +2329,7 @@ public class KickCParser extends Parser { _localctx = new TypeSimpleContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(311); + setState(320); match(SIMPLETYPE); } break; @@ -2317,9 +2338,9 @@ public class KickCParser extends Parser { _localctx = new TypeSignedSimpleContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(312); + setState(321); match(T__31); - setState(313); + setState(322); match(SIMPLETYPE); } break; @@ -2327,7 +2348,7 @@ public class KickCParser extends Parser { throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(329); + setState(338); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,36,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -2335,16 +2356,16 @@ public class KickCParser extends Parser { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(327); + setState(336); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,35,_ctx) ) { case 1: { _localctx = new TypePtrContext(new TypeDeclContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_typeDecl); - setState(316); + setState(325); if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); - setState(317); + setState(326); match(T__32); } break; @@ -2352,21 +2373,21 @@ public class KickCParser extends Parser { { _localctx = new TypeArrayContext(new TypeDeclContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_typeDecl); - setState(318); + setState(327); if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(319); + setState(328); match(T__33); - setState(321); + setState(330); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__5) | (1L << T__32) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 72)) & ~0x3f) == 0 && ((1L << (_la - 72)) & ((1L << (STRING - 72)) | (1L << (CHAR - 72)) | (1L << (BOOLEAN - 72)) | (1L << (NUMBER - 72)) | (1L << (NAME - 72)))) != 0)) { { - setState(320); + setState(329); expr(0); } } - setState(323); + setState(332); match(T__34); } break; @@ -2374,18 +2395,18 @@ public class KickCParser extends Parser { { _localctx = new TypeProcedureContext(new TypeDeclContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_typeDecl); - setState(324); + setState(333); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(325); + setState(334); match(T__3); - setState(326); + setState(335); match(T__4); } break; } } } - setState(331); + setState(340); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,36,_ctx); } @@ -2762,7 +2783,7 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(372); + setState(381); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,39,_ctx) ) { case 1: @@ -2771,11 +2792,11 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(333); + setState(342); match(T__3); - setState(334); + setState(343); expr(0); - setState(335); + setState(344); match(T__4); } break; @@ -2784,21 +2805,21 @@ public class KickCParser extends Parser { _localctx = new ExprCallContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(337); + setState(346); match(NAME); - setState(338); + setState(347); match(T__3); - setState(340); + setState(349); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__5) | (1L << T__32) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 72)) & ~0x3f) == 0 && ((1L << (_la - 72)) & ((1L << (STRING - 72)) | (1L << (CHAR - 72)) | (1L << (BOOLEAN - 72)) | (1L << (NUMBER - 72)) | (1L << (NAME - 72)))) != 0)) { { - setState(339); + setState(348); parameterList(); } } - setState(342); + setState(351); match(T__4); } break; @@ -2807,13 +2828,13 @@ public class KickCParser extends Parser { _localctx = new ExprCastContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(343); + setState(352); match(T__3); - setState(344); + setState(353); typeDecl(0); - setState(345); + setState(354); match(T__4); - setState(346); + setState(355); expr(23); } break; @@ -2822,7 +2843,7 @@ public class KickCParser extends Parser { _localctx = new ExprPreModContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(348); + setState(357); _la = _input.LA(1); if ( !(_la==T__35 || _la==T__36) ) { _errHandler.recoverInline(this); @@ -2832,7 +2853,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(349); + setState(358); expr(22); } break; @@ -2841,9 +2862,9 @@ public class KickCParser extends Parser { _localctx = new ExprPtrContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(350); + setState(359); match(T__32); - setState(351); + setState(360); expr(20); } break; @@ -2852,7 +2873,7 @@ public class KickCParser extends Parser { _localctx = new ExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(352); + setState(361); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41))) != 0)) ) { _errHandler.recoverInline(this); @@ -2862,7 +2883,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(353); + setState(362); expr(19); } break; @@ -2871,7 +2892,7 @@ public class KickCParser extends Parser { _localctx = new ExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(354); + setState(363); _la = _input.LA(1); if ( !(_la==T__46 || _la==T__47) ) { _errHandler.recoverInline(this); @@ -2881,7 +2902,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(355); + setState(364); expr(15); } break; @@ -2890,27 +2911,27 @@ public class KickCParser extends Parser { _localctx = new InitListContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(356); + setState(365); match(T__5); - setState(357); + setState(366); expr(0); - setState(362); + setState(371); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__8) { { { - setState(358); + setState(367); match(T__8); - setState(359); + setState(368); expr(0); } } - setState(364); + setState(373); _errHandler.sync(this); _la = _input.LA(1); } - setState(365); + setState(374); match(T__6); } break; @@ -2919,7 +2940,7 @@ public class KickCParser extends Parser { _localctx = new ExprIdContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(367); + setState(376); match(NAME); } break; @@ -2928,7 +2949,7 @@ public class KickCParser extends Parser { _localctx = new ExprNumberContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(368); + setState(377); match(NUMBER); } break; @@ -2937,7 +2958,7 @@ public class KickCParser extends Parser { _localctx = new ExprStringContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(369); + setState(378); match(STRING); } break; @@ -2946,7 +2967,7 @@ public class KickCParser extends Parser { _localctx = new ExprCharContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(370); + setState(379); match(CHAR); } break; @@ -2955,13 +2976,13 @@ public class KickCParser extends Parser { _localctx = new ExprBoolContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(371); + setState(380); match(BOOLEAN); } break; } _ctx.stop = _input.LT(-1); - setState(416); + setState(425); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,41,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -2969,16 +2990,16 @@ public class KickCParser extends Parser { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(414); + setState(423); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) { case 1: { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(374); + setState(383); if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)"); - setState(375); + setState(384); _la = _input.LA(1); if ( !(_la==T__42 || _la==T__43) ) { _errHandler.recoverInline(this); @@ -2988,7 +3009,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(376); + setState(385); expr(19); } break; @@ -2996,9 +3017,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(377); + setState(386); if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)"); - setState(378); + setState(387); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__32) | (1L << T__44) | (1L << T__45))) != 0)) ) { _errHandler.recoverInline(this); @@ -3008,7 +3029,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(379); + setState(388); expr(18); } break; @@ -3016,9 +3037,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(380); + setState(389); if (!(precpred(_ctx, 16))) throw new FailedPredicateException(this, "precpred(_ctx, 16)"); - setState(381); + setState(390); _la = _input.LA(1); if ( !(_la==T__37 || _la==T__38) ) { _errHandler.recoverInline(this); @@ -3028,7 +3049,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(382); + setState(391); expr(17); } break; @@ -3036,9 +3057,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(383); + setState(392); if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)"); - setState(384); + setState(393); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__46) | (1L << T__47) | (1L << T__48) | (1L << T__49) | (1L << T__50) | (1L << T__51))) != 0)) ) { _errHandler.recoverInline(this); @@ -3048,7 +3069,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(385); + setState(394); expr(15); } break; @@ -3056,13 +3077,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(386); + setState(395); if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); { - setState(387); + setState(396); match(T__40); } - setState(388); + setState(397); expr(14); } break; @@ -3070,13 +3091,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(389); + setState(398); if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); { - setState(390); + setState(399); match(T__52); } - setState(391); + setState(400); expr(13); } break; @@ -3084,13 +3105,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(392); + setState(401); if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); { - setState(393); + setState(402); match(T__53); } - setState(394); + setState(403); expr(12); } break; @@ -3098,13 +3119,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(395); + setState(404); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); { - setState(396); + setState(405); match(T__54); } - setState(397); + setState(406); expr(11); } break; @@ -3112,13 +3133,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(398); + setState(407); if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); { - setState(399); + setState(408); match(T__55); } - setState(400); + setState(409); expr(10); } break; @@ -3126,11 +3147,11 @@ public class KickCParser extends Parser { { _localctx = new ExprAssignmentContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(401); + setState(410); if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); - setState(402); + setState(411); match(T__1); - setState(403); + setState(412); expr(8); } break; @@ -3138,9 +3159,9 @@ public class KickCParser extends Parser { { _localctx = new ExprAssignmentCompoundContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(404); + setState(413); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(405); + setState(414); _la = _input.LA(1); if ( !(((((_la - 57)) & ~0x3f) == 0 && ((1L << (_la - 57)) & ((1L << (T__56 - 57)) | (1L << (T__57 - 57)) | (1L << (T__58 - 57)) | (1L << (T__59 - 57)) | (1L << (T__60 - 57)) | (1L << (T__61 - 57)) | (1L << (T__62 - 57)) | (1L << (T__63 - 57)) | (1L << (T__64 - 57)) | (1L << (T__65 - 57)))) != 0)) ) { _errHandler.recoverInline(this); @@ -3150,7 +3171,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(406); + setState(415); expr(7); } break; @@ -3158,13 +3179,13 @@ public class KickCParser extends Parser { { _localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(407); + setState(416); if (!(precpred(_ctx, 24))) throw new FailedPredicateException(this, "precpred(_ctx, 24)"); - setState(408); + setState(417); match(T__33); - setState(409); + setState(418); expr(0); - setState(410); + setState(419); match(T__34); } break; @@ -3172,9 +3193,9 @@ public class KickCParser extends Parser { { _localctx = new ExprPostModContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(412); + setState(421); if (!(precpred(_ctx, 21))) throw new FailedPredicateException(this, "precpred(_ctx, 21)"); - setState(413); + setState(422); _la = _input.LA(1); if ( !(_la==T__35 || _la==T__36) ) { _errHandler.recoverInline(this); @@ -3189,7 +3210,7 @@ public class KickCParser extends Parser { } } } - setState(418); + setState(427); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,41,_ctx); } @@ -3239,21 +3260,21 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(419); + setState(428); expr(0); - setState(424); + setState(433); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__8) { { { - setState(420); + setState(429); match(T__8); - setState(421); + setState(430); expr(0); } } - setState(426); + setState(435); _errHandler.sync(this); _la = _input.LA(1); } @@ -3303,17 +3324,17 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(430); + setState(439); _errHandler.sync(this); _la = _input.LA(1); while (((((_la - 40)) & ~0x3f) == 0 && ((1L << (_la - 40)) & ((1L << (T__39 - 40)) | (1L << (T__66 - 40)) | (1L << (MNEMONIC - 40)) | (1L << (NAME - 40)))) != 0)) { { { - setState(427); + setState(436); asmLine(); } } - setState(432); + setState(441); _errHandler.sync(this); _la = _input.LA(1); } @@ -3363,28 +3384,28 @@ public class KickCParser extends Parser { AsmLineContext _localctx = new AsmLineContext(_ctx, getState()); enterRule(_localctx, 44, RULE_asmLine); try { - setState(436); + setState(445); _errHandler.sync(this); switch (_input.LA(1)) { case T__39: case NAME: enterOuterAlt(_localctx, 1); { - setState(433); + setState(442); asmLabel(); } break; case MNEMONIC: enterOuterAlt(_localctx, 2); { - setState(434); + setState(443); asmInstruction(); } break; case T__66: enterOuterAlt(_localctx, 3); { - setState(435); + setState(444); asmBytes(); } break; @@ -3454,16 +3475,16 @@ public class KickCParser extends Parser { enterRule(_localctx, 46, RULE_asmLabel); int _la; try { - setState(445); + setState(454); _errHandler.sync(this); switch (_input.LA(1)) { case NAME: _localctx = new AsmLabelNameContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(438); + setState(447); match(NAME); - setState(439); + setState(448); match(T__12); } break; @@ -3471,19 +3492,19 @@ public class KickCParser extends Parser { _localctx = new AsmLabelMultiContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(440); + setState(449); match(T__39); - setState(442); + setState(451); _errHandler.sync(this); _la = _input.LA(1); if (_la==NAME) { { - setState(441); + setState(450); match(NAME); } } - setState(444); + setState(453); match(T__12); } break; @@ -3532,14 +3553,14 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(447); + setState(456); match(MNEMONIC); - setState(449); + setState(458); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,47,_ctx) ) { case 1: { - setState(448); + setState(457); asmParamMode(); } break; @@ -3590,23 +3611,23 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(451); + setState(460); match(T__66); - setState(452); + setState(461); asmExpr(0); - setState(457); + setState(466); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__8) { { { - setState(453); + setState(462); match(T__8); - setState(454); + setState(463); asmExpr(0); } } - setState(459); + setState(468); _errHandler.sync(this); _la = _input.LA(1); } @@ -3756,14 +3777,14 @@ public class KickCParser extends Parser { AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState()); enterRule(_localctx, 52, RULE_asmParamMode); try { - setState(483); + setState(492); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,49,_ctx) ) { case 1: _localctx = new AsmModeAbsContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(460); + setState(469); asmExpr(0); } break; @@ -3771,9 +3792,9 @@ public class KickCParser extends Parser { _localctx = new AsmModeImmContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(461); + setState(470); match(T__67); - setState(462); + setState(471); asmExpr(0); } break; @@ -3781,11 +3802,11 @@ public class KickCParser extends Parser { _localctx = new AsmModeAbsXYContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(463); + setState(472); asmExpr(0); - setState(464); + setState(473); match(T__8); - setState(465); + setState(474); match(NAME); } break; @@ -3793,15 +3814,15 @@ public class KickCParser extends Parser { _localctx = new AsmModeIndIdxXYContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(467); + setState(476); match(T__3); - setState(468); + setState(477); asmExpr(0); - setState(469); + setState(478); match(T__4); - setState(470); + setState(479); match(T__8); - setState(471); + setState(480); match(NAME); } break; @@ -3809,15 +3830,15 @@ public class KickCParser extends Parser { _localctx = new AsmModeIdxIndXYContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(473); + setState(482); match(T__3); - setState(474); + setState(483); asmExpr(0); - setState(475); + setState(484); match(T__8); - setState(476); + setState(485); match(NAME); - setState(477); + setState(486); match(T__4); } break; @@ -3825,11 +3846,11 @@ public class KickCParser extends Parser { _localctx = new AsmModeIndContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(479); + setState(488); match(T__3); - setState(480); + setState(489); asmExpr(0); - setState(481); + setState(490); match(T__4); } break; @@ -4019,7 +4040,7 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(499); + setState(508); _errHandler.sync(this); switch (_input.LA(1)) { case T__33: @@ -4028,11 +4049,11 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(486); + setState(495); match(T__33); - setState(487); + setState(496); asmExpr(0); - setState(488); + setState(497); match(T__34); } break; @@ -4044,7 +4065,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(490); + setState(499); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__37) | (1L << T__38) | (1L << T__46) | (1L << T__47))) != 0)) ) { _errHandler.recoverInline(this); @@ -4054,7 +4075,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(491); + setState(500); asmExpr(8); } break; @@ -4063,7 +4084,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprLabelContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(492); + setState(501); match(NAME); } break; @@ -4072,7 +4093,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprLabelRelContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(493); + setState(502); match(ASMREL); } break; @@ -4081,11 +4102,11 @@ public class KickCParser extends Parser { _localctx = new AsmExprReplaceContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(494); + setState(503); match(T__5); - setState(495); + setState(504); match(NAME); - setState(496); + setState(505); match(T__6); } break; @@ -4094,7 +4115,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprIntContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(497); + setState(506); match(NUMBER); } break; @@ -4103,7 +4124,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprCharContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(498); + setState(507); match(CHAR); } break; @@ -4111,7 +4132,7 @@ public class KickCParser extends Parser { throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(512); + setState(521); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,52,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -4119,16 +4140,16 @@ public class KickCParser extends Parser { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(510); + setState(519); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { case 1: { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(501); + setState(510); if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(502); + setState(511); _la = _input.LA(1); if ( !(_la==T__42 || _la==T__43) ) { _errHandler.recoverInline(this); @@ -4138,7 +4159,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(503); + setState(512); asmExpr(10); } break; @@ -4146,9 +4167,9 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(504); + setState(513); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(505); + setState(514); _la = _input.LA(1); if ( !(_la==T__32 || _la==T__44) ) { _errHandler.recoverInline(this); @@ -4158,7 +4179,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(506); + setState(515); asmExpr(8); } break; @@ -4166,9 +4187,9 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(507); + setState(516); if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); - setState(508); + setState(517); _la = _input.LA(1); if ( !(_la==T__37 || _la==T__38) ) { _errHandler.recoverInline(this); @@ -4178,14 +4199,14 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(509); + setState(518); asmExpr(7); } break; } } } - setState(514); + setState(523); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,52,_ctx); } @@ -4268,7 +4289,7 @@ public class KickCParser extends Parser { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3Z\u0206\4\2\t\2\4"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3Z\u020f\4\2\t\2\4"+ "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ "\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -4285,191 +4306,194 @@ public class KickCParser extends Parser { "\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\5"+ "\17\u00cd\n\17\5\17\u00cf\n\17\3\20\6\20\u00d2\n\20\r\20\16\20\u00d3\3"+ "\21\3\21\3\21\5\21\u00d9\n\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+ - "\3\21\3\21\3\21\5\21\u00e6\n\21\3\21\5\21\u00e9\n\21\3\21\3\21\3\21\3"+ - "\21\3\21\3\21\3\21\5\21\u00f2\n\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+ - "\3\21\3\21\5\21\u00fd\n\21\3\21\3\21\3\21\5\21\u0102\n\21\3\21\3\21\3"+ - "\21\3\21\3\21\3\21\5\21\u010a\n\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+ - "\5\21\u0113\n\21\3\22\7\22\u0116\n\22\f\22\16\22\u0119\13\22\3\22\5\22"+ - "\u011c\n\22\3\22\7\22\u011f\n\22\f\22\16\22\u0122\13\22\3\22\3\22\3\22"+ - "\5\22\u0127\n\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23"+ - "\u0133\n\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\5\24\u013d\n\24\3"+ - "\24\3\24\3\24\3\24\3\24\5\24\u0144\n\24\3\24\3\24\3\24\3\24\7\24\u014a"+ - "\n\24\f\24\16\24\u014d\13\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\5"+ - "\25\u0157\n\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25"+ - "\3\25\3\25\3\25\3\25\3\25\3\25\3\25\7\25\u016b\n\25\f\25\16\25\u016e\13"+ - "\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\5\25\u0177\n\25\3\25\3\25\3\25"+ + "\3\21\3\21\3\21\5\21\u00e6\n\21\3\21\7\21\u00e9\n\21\f\21\16\21\u00ec"+ + "\13\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\7\21\u00f5\n\21\f\21\16\21\u00f8"+ + "\13\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\7\21\u0103\n\21\f"+ + "\21\16\21\u0106\13\21\3\21\3\21\3\21\5\21\u010b\n\21\3\21\3\21\3\21\3"+ + "\21\3\21\3\21\5\21\u0113\n\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\5\21"+ + "\u011c\n\21\3\22\7\22\u011f\n\22\f\22\16\22\u0122\13\22\3\22\5\22\u0125"+ + "\n\22\3\22\7\22\u0128\n\22\f\22\16\22\u012b\13\22\3\22\3\22\3\22\5\22"+ + "\u0130\n\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u013c"+ + "\n\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\5\24\u0146\n\24\3\24\3\24"+ + "\3\24\3\24\3\24\5\24\u014d\n\24\3\24\3\24\3\24\3\24\7\24\u0153\n\24\f"+ + "\24\16\24\u0156\13\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\5\25\u0160"+ + "\n\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25"+ + "\3\25\3\25\3\25\3\25\3\25\7\25\u0174\n\25\f\25\16\25\u0177\13\25\3\25"+ + "\3\25\3\25\3\25\3\25\3\25\3\25\5\25\u0180\n\25\3\25\3\25\3\25\3\25\3\25"+ "\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25"+ "\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25"+ - "\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\7\25\u01a1\n\25\f\25\16"+ - "\25\u01a4\13\25\3\26\3\26\3\26\7\26\u01a9\n\26\f\26\16\26\u01ac\13\26"+ - "\3\27\7\27\u01af\n\27\f\27\16\27\u01b2\13\27\3\30\3\30\3\30\5\30\u01b7"+ - "\n\30\3\31\3\31\3\31\3\31\5\31\u01bd\n\31\3\31\5\31\u01c0\n\31\3\32\3"+ - "\32\5\32\u01c4\n\32\3\33\3\33\3\33\3\33\7\33\u01ca\n\33\f\33\16\33\u01cd"+ - "\13\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34"+ - "\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\5\34\u01e6\n\34\3\35"+ - "\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\5\35"+ - "\u01f6\n\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\7\35\u0201\n"+ - "\35\f\35\16\35\u0204\13\35\3\35\2\5&(8\36\2\4\6\b\n\f\16\20\22\24\26\30"+ - "\32\34\36 \"$&(*,.\60\62\64\668\2\f\3\2&\'\3\2(,\3\2\61\62\3\2-.\4\2#"+ - "#/\60\3\2()\3\2\61\66\3\2;D\4\2()\61\62\4\2##//\2\u0253\2:\3\2\2\2\4>"+ - "\3\2\2\2\6D\3\2\2\2\bG\3\2\2\2\nK\3\2\2\2\fR\3\2\2\2\16W\3\2\2\2\20k\3"+ - "\2\2\2\22\u0081\3\2\2\2\24\u0087\3\2\2\2\26\u00a3\3\2\2\2\30\u00a5\3\2"+ - "\2\2\32\u00b0\3\2\2\2\34\u00ce\3\2\2\2\36\u00d1\3\2\2\2 \u0112\3\2\2\2"+ - "\"\u0117\3\2\2\2$\u0132\3\2\2\2&\u013c\3\2\2\2(\u0176\3\2\2\2*\u01a5\3"+ - "\2\2\2,\u01b0\3\2\2\2.\u01b6\3\2\2\2\60\u01bf\3\2\2\2\62\u01c1\3\2\2\2"+ - "\64\u01c5\3\2\2\2\66\u01e5\3\2\2\28\u01f5\3\2\2\2:;\5\6\4\2;<\5\n\6\2"+ - "<=\7\2\2\3=\3\3\2\2\2>?\5,\27\2?@\7\2\2\3@\5\3\2\2\2AC\5\b\5\2BA\3\2\2"+ - "\2CF\3\2\2\2DB\3\2\2\2DE\3\2\2\2E\7\3\2\2\2FD\3\2\2\2GH\7\3\2\2HI\7J\2"+ - "\2I\t\3\2\2\2JL\5\f\7\2KJ\3\2\2\2LM\3\2\2\2MK\3\2\2\2MN\3\2\2\2N\13\3"+ - "\2\2\2OS\5\16\b\2PS\5\20\t\2QS\5\22\n\2RO\3\2\2\2RP\3\2\2\2RQ\3\2\2\2"+ - "S\r\3\2\2\2TV\5\34\17\2UT\3\2\2\2VY\3\2\2\2WU\3\2\2\2WX\3\2\2\2XZ\3\2"+ - "\2\2YW\3\2\2\2Z^\5&\24\2[]\5\34\17\2\\[\3\2\2\2]`\3\2\2\2^\\\3\2\2\2^"+ - "_\3\2\2\2_a\3\2\2\2`^\3\2\2\2ad\7V\2\2bc\7\4\2\2ce\5(\25\2db\3\2\2\2d"+ - "e\3\2\2\2ef\3\2\2\2fg\7\5\2\2g\17\3\2\2\2hj\5\34\17\2ih\3\2\2\2jm\3\2"+ - "\2\2ki\3\2\2\2kl\3\2\2\2ln\3\2\2\2mk\3\2\2\2nr\5&\24\2oq\5\34\17\2po\3"+ - "\2\2\2qt\3\2\2\2rp\3\2\2\2rs\3\2\2\2su\3\2\2\2tr\3\2\2\2uv\7V\2\2vx\7"+ - "\6\2\2wy\5\30\r\2xw\3\2\2\2xy\3\2\2\2yz\3\2\2\2z{\7\7\2\2{}\7\b\2\2|~"+ - "\5\36\20\2}|\3\2\2\2}~\3\2\2\2~\177\3\2\2\2\177\u0080\7\t\2\2\u0080\21"+ - "\3\2\2\2\u0081\u0083\7\n\2\2\u0082\u0084\5\24\13\2\u0083\u0082\3\2\2\2"+ - "\u0083\u0084\3\2\2\2\u0084\u0085\3\2\2\2\u0085\u0086\7H\2\2\u0086\23\3"+ - "\2\2\2\u0087\u0088\7\6\2\2\u0088\u008d\5\26\f\2\u0089\u008a\7\13\2\2\u008a"+ - "\u008c\5\26\f\2\u008b\u0089\3\2\2\2\u008c\u008f\3\2\2\2\u008d\u008b\3"+ - "\2\2\2\u008d\u008e\3\2\2\2\u008e\u0090\3\2\2\2\u008f\u008d\3\2\2\2\u0090"+ - "\u0091\7\7\2\2\u0091\25\3\2\2\2\u0092\u0093\7\f\2\2\u0093\u00a4\7J\2\2"+ - "\u0094\u0095\7\r\2\2\u0095\u00a4\7J\2\2\u0096\u0097\7\16\2\2\u0097\u0098"+ - "\7V\2\2\u0098\u0099\7\17\2\2\u0099\u00a4\5(\25\2\u009a\u009b\7\20\2\2"+ - "\u009b\u00a4\5(\25\2\u009c\u009d\7\21\2\2\u009d\u00a4\5(\25\2\u009e\u00a1"+ - "\7\22\2\2\u009f\u00a2\7\23\2\2\u00a0\u00a2\5(\25\2\u00a1\u009f\3\2\2\2"+ - "\u00a1\u00a0\3\2\2\2\u00a2\u00a4\3\2\2\2\u00a3\u0092\3\2\2\2\u00a3\u0094"+ - "\3\2\2\2\u00a3\u0096\3\2\2\2\u00a3\u009a\3\2\2\2\u00a3\u009c\3\2\2\2\u00a3"+ - "\u009e\3\2\2\2\u00a4\27\3\2\2\2\u00a5\u00aa\5\32\16\2\u00a6\u00a7\7\13"+ - "\2\2\u00a7\u00a9\5\32\16\2\u00a8\u00a6\3\2\2\2\u00a9\u00ac\3\2\2\2\u00aa"+ - "\u00a8\3\2\2\2\u00aa\u00ab\3\2\2\2\u00ab\31\3\2\2\2\u00ac\u00aa\3\2\2"+ - "\2\u00ad\u00af\5\34\17\2\u00ae\u00ad\3\2\2\2\u00af\u00b2\3\2\2\2\u00b0"+ - "\u00ae\3\2\2\2\u00b0\u00b1\3\2\2\2\u00b1\u00b3\3\2\2\2\u00b2\u00b0\3\2"+ - "\2\2\u00b3\u00b7\5&\24\2\u00b4\u00b6\5\34\17\2\u00b5\u00b4\3\2\2\2\u00b6"+ - "\u00b9\3\2\2\2\u00b7\u00b5\3\2\2\2\u00b7\u00b8\3\2\2\2\u00b8\u00ba\3\2"+ - "\2\2\u00b9\u00b7\3\2\2\2\u00ba\u00bb\7V\2\2\u00bb\33\3\2\2\2\u00bc\u00cf"+ - "\7\24\2\2\u00bd\u00cf\7\25\2\2\u00be\u00bf\7\26\2\2\u00bf\u00c0\7\6\2"+ - "\2\u00c0\u00c1\7M\2\2\u00c1\u00cf\7\7\2\2\u00c2\u00c3\7\27\2\2\u00c3\u00c4"+ - "\7\6\2\2\u00c4\u00c5\7V\2\2\u00c5\u00cf\7\7\2\2\u00c6\u00cf\7\23\2\2\u00c7"+ - "\u00cf\7\30\2\2\u00c8\u00cc\7\31\2\2\u00c9\u00ca\7\6\2\2\u00ca\u00cb\7"+ - "V\2\2\u00cb\u00cd\7\7\2\2\u00cc\u00c9\3\2\2\2\u00cc\u00cd\3\2\2\2\u00cd"+ - "\u00cf\3\2\2\2\u00ce\u00bc\3\2\2\2\u00ce\u00bd\3\2\2\2\u00ce\u00be\3\2"+ - "\2\2\u00ce\u00c2\3\2\2\2\u00ce\u00c6\3\2\2\2\u00ce\u00c7\3\2\2\2\u00ce"+ - "\u00c8\3\2\2\2\u00cf\35\3\2\2\2\u00d0\u00d2\5 \21\2\u00d1\u00d0\3\2\2"+ - "\2\u00d2\u00d3\3\2\2\2\u00d3\u00d1\3\2\2\2\u00d3\u00d4\3\2\2\2\u00d4\37"+ - "\3\2\2\2\u00d5\u0113\5\16\b\2\u00d6\u00d8\7\b\2\2\u00d7\u00d9\5\36\20"+ - "\2\u00d8\u00d7\3\2\2\2\u00d8\u00d9\3\2\2\2\u00d9\u00da\3\2\2\2\u00da\u0113"+ - "\7\t\2\2\u00db\u00dc\5(\25\2\u00dc\u00dd\7\5\2\2\u00dd\u0113\3\2\2\2\u00de"+ - "\u00df\7\32\2\2\u00df\u00e0\7\6\2\2\u00e0\u00e1\5(\25\2\u00e1\u00e2\7"+ - "\7\2\2\u00e2\u00e5\5 \21\2\u00e3\u00e4\7\33\2\2\u00e4\u00e6\5 \21\2\u00e5"+ - "\u00e3\3\2\2\2\u00e5\u00e6\3\2\2\2\u00e6\u0113\3\2\2\2\u00e7\u00e9\5\34"+ - "\17\2\u00e8\u00e7\3\2\2\2\u00e8\u00e9\3\2\2\2\u00e9\u00ea\3\2\2\2\u00ea"+ - "\u00eb\7\34\2\2\u00eb\u00ec\7\6\2\2\u00ec\u00ed\5(\25\2\u00ed\u00ee\7"+ - "\7\2\2\u00ee\u00ef\5 \21\2\u00ef\u0113\3\2\2\2\u00f0\u00f2\5\34\17\2\u00f1"+ - "\u00f0\3\2\2\2\u00f1\u00f2\3\2\2\2\u00f2\u00f3\3\2\2\2\u00f3\u00f4\7\35"+ - "\2\2\u00f4\u00f5\5 \21\2\u00f5\u00f6\7\34\2\2\u00f6\u00f7\7\6\2\2\u00f7"+ - "\u00f8\5(\25\2\u00f8\u00f9\7\7\2\2\u00f9\u00fa\7\5\2\2\u00fa\u0113\3\2"+ - "\2\2\u00fb\u00fd\5\34\17\2\u00fc\u00fb\3\2\2\2\u00fc\u00fd\3\2\2\2\u00fd"+ - "\u00fe\3\2\2\2\u00fe\u00ff\7\36\2\2\u00ff\u0101\7\6\2\2\u0100\u0102\5"+ - "\"\22\2\u0101\u0100\3\2\2\2\u0101\u0102\3\2\2\2\u0102\u0103\3\2\2\2\u0103"+ - "\u0104\5$\23\2\u0104\u0105\7\7\2\2\u0105\u0106\5 \21\2\u0106\u0113\3\2"+ - "\2\2\u0107\u0109\7\37\2\2\u0108\u010a\5(\25\2\u0109\u0108\3\2\2\2\u0109"+ - "\u010a\3\2\2\2\u010a\u010b\3\2\2\2\u010b\u0113\7\5\2\2\u010c\u010d\7 "+ - "\2\2\u010d\u010e\7\b\2\2\u010e\u010f\5,\27\2\u010f\u0110\7\t\2\2\u0110"+ - "\u0113\3\2\2\2\u0111\u0113\5\22\n\2\u0112\u00d5\3\2\2\2\u0112\u00d6\3"+ - "\2\2\2\u0112\u00db\3\2\2\2\u0112\u00de\3\2\2\2\u0112\u00e8\3\2\2\2\u0112"+ - "\u00f1\3\2\2\2\u0112\u00fc\3\2\2\2\u0112\u0107\3\2\2\2\u0112\u010c\3\2"+ - "\2\2\u0112\u0111\3\2\2\2\u0113!\3\2\2\2\u0114\u0116\5\34\17\2\u0115\u0114"+ - "\3\2\2\2\u0116\u0119\3\2\2\2\u0117\u0115\3\2\2\2\u0117\u0118\3\2\2\2\u0118"+ - "\u011b\3\2\2\2\u0119\u0117\3\2\2\2\u011a\u011c\5&\24\2\u011b\u011a\3\2"+ - "\2\2\u011b\u011c\3\2\2\2\u011c\u0120\3\2\2\2\u011d\u011f\5\34\17\2\u011e"+ - "\u011d\3\2\2\2\u011f\u0122\3\2\2\2\u0120\u011e\3\2\2\2\u0120\u0121\3\2"+ - "\2\2\u0121\u0123\3\2\2\2\u0122\u0120\3\2\2\2\u0123\u0126\7V\2\2\u0124"+ - "\u0125\7\4\2\2\u0125\u0127\5(\25\2\u0126\u0124\3\2\2\2\u0126\u0127\3\2"+ - "\2\2\u0127#\3\2\2\2\u0128\u0129\7\5\2\2\u0129\u012a\5(\25\2\u012a\u012b"+ - "\7\5\2\2\u012b\u012c\5(\25\2\u012c\u0133\3\2\2\2\u012d\u012e\7\17\2\2"+ - "\u012e\u012f\5(\25\2\u012f\u0130\7!\2\2\u0130\u0131\5(\25\2\u0131\u0133"+ - "\3\2\2\2\u0132\u0128\3\2\2\2\u0132\u012d\3\2\2\2\u0133%\3\2\2\2\u0134"+ - "\u0135\b\24\1\2\u0135\u0136\7\6\2\2\u0136\u0137\5&\24\2\u0137\u0138\7"+ - "\7\2\2\u0138\u013d\3\2\2\2\u0139\u013d\7I\2\2\u013a\u013b\7\"\2\2\u013b"+ - "\u013d\7I\2\2\u013c\u0134\3\2\2\2\u013c\u0139\3\2\2\2\u013c\u013a\3\2"+ - "\2\2\u013d\u014b\3\2\2\2\u013e\u013f\f\5\2\2\u013f\u014a\7#\2\2\u0140"+ - "\u0141\f\4\2\2\u0141\u0143\7$\2\2\u0142\u0144\5(\25\2\u0143\u0142\3\2"+ - "\2\2\u0143\u0144\3\2\2\2\u0144\u0145\3\2\2\2\u0145\u014a\7%\2\2\u0146"+ - "\u0147\f\3\2\2\u0147\u0148\7\6\2\2\u0148\u014a\7\7\2\2\u0149\u013e\3\2"+ - "\2\2\u0149\u0140\3\2\2\2\u0149\u0146\3\2\2\2\u014a\u014d\3\2\2\2\u014b"+ - "\u0149\3\2\2\2\u014b\u014c\3\2\2\2\u014c\'\3\2\2\2\u014d\u014b\3\2\2\2"+ - "\u014e\u014f\b\25\1\2\u014f\u0150\7\6\2\2\u0150\u0151\5(\25\2\u0151\u0152"+ - "\7\7\2\2\u0152\u0177\3\2\2\2\u0153\u0154\7V\2\2\u0154\u0156\7\6\2\2\u0155"+ - "\u0157\5*\26\2\u0156\u0155\3\2\2\2\u0156\u0157\3\2\2\2\u0157\u0158\3\2"+ - "\2\2\u0158\u0177\7\7\2\2\u0159\u015a\7\6\2\2\u015a\u015b\5&\24\2\u015b"+ - "\u015c\7\7\2\2\u015c\u015d\5(\25\31\u015d\u0177\3\2\2\2\u015e\u015f\t"+ - "\2\2\2\u015f\u0177\5(\25\30\u0160\u0161\7#\2\2\u0161\u0177\5(\25\26\u0162"+ - "\u0163\t\3\2\2\u0163\u0177\5(\25\25\u0164\u0165\t\4\2\2\u0165\u0177\5"+ - "(\25\21\u0166\u0167\7\b\2\2\u0167\u016c\5(\25\2\u0168\u0169\7\13\2\2\u0169"+ - "\u016b\5(\25\2\u016a\u0168\3\2\2\2\u016b\u016e\3\2\2\2\u016c\u016a\3\2"+ - "\2\2\u016c\u016d\3\2\2\2\u016d\u016f\3\2\2\2\u016e\u016c\3\2\2\2\u016f"+ - "\u0170\7\t\2\2\u0170\u0177\3\2\2\2\u0171\u0177\7V\2\2\u0172\u0177\7M\2"+ - "\2\u0173\u0177\7J\2\2\u0174\u0177\7K\2\2\u0175\u0177\7L\2\2\u0176\u014e"+ - "\3\2\2\2\u0176\u0153\3\2\2\2\u0176\u0159\3\2\2\2\u0176\u015e\3\2\2\2\u0176"+ - "\u0160\3\2\2\2\u0176\u0162\3\2\2\2\u0176\u0164\3\2\2\2\u0176\u0166\3\2"+ - "\2\2\u0176\u0171\3\2\2\2\u0176\u0172\3\2\2\2\u0176\u0173\3\2\2\2\u0176"+ - "\u0174\3\2\2\2\u0176\u0175\3\2\2\2\u0177\u01a2\3\2\2\2\u0178\u0179\f\24"+ - "\2\2\u0179\u017a\t\5\2\2\u017a\u01a1\5(\25\25\u017b\u017c\f\23\2\2\u017c"+ - "\u017d\t\6\2\2\u017d\u01a1\5(\25\24\u017e\u017f\f\22\2\2\u017f\u0180\t"+ - "\7\2\2\u0180\u01a1\5(\25\23\u0181\u0182\f\20\2\2\u0182\u0183\t\b\2\2\u0183"+ - "\u01a1\5(\25\21\u0184\u0185\f\17\2\2\u0185\u0186\7+\2\2\u0186\u01a1\5"+ - "(\25\20\u0187\u0188\f\16\2\2\u0188\u0189\7\67\2\2\u0189\u01a1\5(\25\17"+ - "\u018a\u018b\f\r\2\2\u018b\u018c\78\2\2\u018c\u01a1\5(\25\16\u018d\u018e"+ - "\f\f\2\2\u018e\u018f\79\2\2\u018f\u01a1\5(\25\r\u0190\u0191\f\13\2\2\u0191"+ - "\u0192\7:\2\2\u0192\u01a1\5(\25\f\u0193\u0194\f\n\2\2\u0194\u0195\7\4"+ - "\2\2\u0195\u01a1\5(\25\n\u0196\u0197\f\t\2\2\u0197\u0198\t\t\2\2\u0198"+ - "\u01a1\5(\25\t\u0199\u019a\f\32\2\2\u019a\u019b\7$\2\2\u019b\u019c\5("+ - "\25\2\u019c\u019d\7%\2\2\u019d\u01a1\3\2\2\2\u019e\u019f\f\27\2\2\u019f"+ - "\u01a1\t\2\2\2\u01a0\u0178\3\2\2\2\u01a0\u017b\3\2\2\2\u01a0\u017e\3\2"+ - "\2\2\u01a0\u0181\3\2\2\2\u01a0\u0184\3\2\2\2\u01a0\u0187\3\2\2\2\u01a0"+ - "\u018a\3\2\2\2\u01a0\u018d\3\2\2\2\u01a0\u0190\3\2\2\2\u01a0\u0193\3\2"+ - "\2\2\u01a0\u0196\3\2\2\2\u01a0\u0199\3\2\2\2\u01a0\u019e\3\2\2\2\u01a1"+ - "\u01a4\3\2\2\2\u01a2\u01a0\3\2\2\2\u01a2\u01a3\3\2\2\2\u01a3)\3\2\2\2"+ - "\u01a4\u01a2\3\2\2\2\u01a5\u01aa\5(\25\2\u01a6\u01a7\7\13\2\2\u01a7\u01a9"+ - "\5(\25\2\u01a8\u01a6\3\2\2\2\u01a9\u01ac\3\2\2\2\u01aa\u01a8\3\2\2\2\u01aa"+ - "\u01ab\3\2\2\2\u01ab+\3\2\2\2\u01ac\u01aa\3\2\2\2\u01ad\u01af\5.\30\2"+ - "\u01ae\u01ad\3\2\2\2\u01af\u01b2\3\2\2\2\u01b0\u01ae\3\2\2\2\u01b0\u01b1"+ - "\3\2\2\2\u01b1-\3\2\2\2\u01b2\u01b0\3\2\2\2\u01b3\u01b7\5\60\31\2\u01b4"+ - "\u01b7\5\62\32\2\u01b5\u01b7\5\64\33\2\u01b6\u01b3\3\2\2\2\u01b6\u01b4"+ - "\3\2\2\2\u01b6\u01b5\3\2\2\2\u01b7/\3\2\2\2\u01b8\u01b9\7V\2\2\u01b9\u01c0"+ - "\7\17\2\2\u01ba\u01bc\7*\2\2\u01bb\u01bd\7V\2\2\u01bc\u01bb\3\2\2\2\u01bc"+ - "\u01bd\3\2\2\2\u01bd\u01be\3\2\2\2\u01be\u01c0\7\17\2\2\u01bf\u01b8\3"+ - "\2\2\2\u01bf\u01ba\3\2\2\2\u01c0\61\3\2\2\2\u01c1\u01c3\7G\2\2\u01c2\u01c4"+ - "\5\66\34\2\u01c3\u01c2\3\2\2\2\u01c3\u01c4\3\2\2\2\u01c4\63\3\2\2\2\u01c5"+ - "\u01c6\7E\2\2\u01c6\u01cb\58\35\2\u01c7\u01c8\7\13\2\2\u01c8\u01ca\58"+ - "\35\2\u01c9\u01c7\3\2\2\2\u01ca\u01cd\3\2\2\2\u01cb\u01c9\3\2\2\2\u01cb"+ - "\u01cc\3\2\2\2\u01cc\65\3\2\2\2\u01cd\u01cb\3\2\2\2\u01ce\u01e6\58\35"+ - "\2\u01cf\u01d0\7F\2\2\u01d0\u01e6\58\35\2\u01d1\u01d2\58\35\2\u01d2\u01d3"+ - "\7\13\2\2\u01d3\u01d4\7V\2\2\u01d4\u01e6\3\2\2\2\u01d5\u01d6\7\6\2\2\u01d6"+ - "\u01d7\58\35\2\u01d7\u01d8\7\7\2\2\u01d8\u01d9\7\13\2\2\u01d9\u01da\7"+ - "V\2\2\u01da\u01e6\3\2\2\2\u01db\u01dc\7\6\2\2\u01dc\u01dd\58\35\2\u01dd"+ - "\u01de\7\13\2\2\u01de\u01df\7V\2\2\u01df\u01e0\7\7\2\2\u01e0\u01e6\3\2"+ - "\2\2\u01e1\u01e2\7\6\2\2\u01e2\u01e3\58\35\2\u01e3\u01e4\7\7\2\2\u01e4"+ - "\u01e6\3\2\2\2\u01e5\u01ce\3\2\2\2\u01e5\u01cf\3\2\2\2\u01e5\u01d1\3\2"+ - "\2\2\u01e5\u01d5\3\2\2\2\u01e5\u01db\3\2\2\2\u01e5\u01e1\3\2\2\2\u01e6"+ - "\67\3\2\2\2\u01e7\u01e8\b\35\1\2\u01e8\u01e9\7$\2\2\u01e9\u01ea\58\35"+ - "\2\u01ea\u01eb\7%\2\2\u01eb\u01f6\3\2\2\2\u01ec\u01ed\t\n\2\2\u01ed\u01f6"+ - "\58\35\n\u01ee\u01f6\7V\2\2\u01ef\u01f6\7W\2\2\u01f0\u01f1\7\b\2\2\u01f1"+ - "\u01f2\7V\2\2\u01f2\u01f6\7\t\2\2\u01f3\u01f6\7M\2\2\u01f4\u01f6\7K\2"+ - "\2\u01f5\u01e7\3\2\2\2\u01f5\u01ec\3\2\2\2\u01f5\u01ee\3\2\2\2\u01f5\u01ef"+ - "\3\2\2\2\u01f5\u01f0\3\2\2\2\u01f5\u01f3\3\2\2\2\u01f5\u01f4\3\2\2\2\u01f6"+ - "\u0202\3\2\2\2\u01f7\u01f8\f\13\2\2\u01f8\u01f9\t\5\2\2\u01f9\u0201\5"+ - "8\35\f\u01fa\u01fb\f\t\2\2\u01fb\u01fc\t\13\2\2\u01fc\u0201\58\35\n\u01fd"+ - "\u01fe\f\b\2\2\u01fe\u01ff\t\7\2\2\u01ff\u0201\58\35\t\u0200\u01f7\3\2"+ - "\2\2\u0200\u01fa\3\2\2\2\u0200\u01fd\3\2\2\2\u0201\u0204\3\2\2\2\u0202"+ - "\u0200\3\2\2\2\u0202\u0203\3\2\2\2\u02039\3\2\2\2\u0204\u0202\3\2\2\2"+ + "\3\25\3\25\3\25\3\25\3\25\3\25\3\25\7\25\u01aa\n\25\f\25\16\25\u01ad\13"+ + "\25\3\26\3\26\3\26\7\26\u01b2\n\26\f\26\16\26\u01b5\13\26\3\27\7\27\u01b8"+ + "\n\27\f\27\16\27\u01bb\13\27\3\30\3\30\3\30\5\30\u01c0\n\30\3\31\3\31"+ + "\3\31\3\31\5\31\u01c6\n\31\3\31\5\31\u01c9\n\31\3\32\3\32\5\32\u01cd\n"+ + "\32\3\33\3\33\3\33\3\33\7\33\u01d3\n\33\f\33\16\33\u01d6\13\33\3\34\3"+ + "\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3"+ + "\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\5\34\u01ef\n\34\3\35\3\35\3\35"+ + "\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\5\35\u01ff\n\35"+ + "\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\7\35\u020a\n\35\f\35\16"+ + "\35\u020d\13\35\3\35\2\5&(8\36\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36"+ + " \"$&(*,.\60\62\64\668\2\f\3\2&\'\3\2(,\3\2\61\62\3\2-.\4\2##/\60\3\2"+ + "()\3\2\61\66\3\2;D\4\2()\61\62\4\2##//\2\u025c\2:\3\2\2\2\4>\3\2\2\2\6"+ + "D\3\2\2\2\bG\3\2\2\2\nK\3\2\2\2\fR\3\2\2\2\16W\3\2\2\2\20k\3\2\2\2\22"+ + "\u0081\3\2\2\2\24\u0087\3\2\2\2\26\u00a3\3\2\2\2\30\u00a5\3\2\2\2\32\u00b0"+ + "\3\2\2\2\34\u00ce\3\2\2\2\36\u00d1\3\2\2\2 \u011b\3\2\2\2\"\u0120\3\2"+ + "\2\2$\u013b\3\2\2\2&\u0145\3\2\2\2(\u017f\3\2\2\2*\u01ae\3\2\2\2,\u01b9"+ + "\3\2\2\2.\u01bf\3\2\2\2\60\u01c8\3\2\2\2\62\u01ca\3\2\2\2\64\u01ce\3\2"+ + "\2\2\66\u01ee\3\2\2\28\u01fe\3\2\2\2:;\5\6\4\2;<\5\n\6\2<=\7\2\2\3=\3"+ + "\3\2\2\2>?\5,\27\2?@\7\2\2\3@\5\3\2\2\2AC\5\b\5\2BA\3\2\2\2CF\3\2\2\2"+ + "DB\3\2\2\2DE\3\2\2\2E\7\3\2\2\2FD\3\2\2\2GH\7\3\2\2HI\7J\2\2I\t\3\2\2"+ + "\2JL\5\f\7\2KJ\3\2\2\2LM\3\2\2\2MK\3\2\2\2MN\3\2\2\2N\13\3\2\2\2OS\5\16"+ + "\b\2PS\5\20\t\2QS\5\22\n\2RO\3\2\2\2RP\3\2\2\2RQ\3\2\2\2S\r\3\2\2\2TV"+ + "\5\34\17\2UT\3\2\2\2VY\3\2\2\2WU\3\2\2\2WX\3\2\2\2XZ\3\2\2\2YW\3\2\2\2"+ + "Z^\5&\24\2[]\5\34\17\2\\[\3\2\2\2]`\3\2\2\2^\\\3\2\2\2^_\3\2\2\2_a\3\2"+ + "\2\2`^\3\2\2\2ad\7V\2\2bc\7\4\2\2ce\5(\25\2db\3\2\2\2de\3\2\2\2ef\3\2"+ + "\2\2fg\7\5\2\2g\17\3\2\2\2hj\5\34\17\2ih\3\2\2\2jm\3\2\2\2ki\3\2\2\2k"+ + "l\3\2\2\2ln\3\2\2\2mk\3\2\2\2nr\5&\24\2oq\5\34\17\2po\3\2\2\2qt\3\2\2"+ + "\2rp\3\2\2\2rs\3\2\2\2su\3\2\2\2tr\3\2\2\2uv\7V\2\2vx\7\6\2\2wy\5\30\r"+ + "\2xw\3\2\2\2xy\3\2\2\2yz\3\2\2\2z{\7\7\2\2{}\7\b\2\2|~\5\36\20\2}|\3\2"+ + "\2\2}~\3\2\2\2~\177\3\2\2\2\177\u0080\7\t\2\2\u0080\21\3\2\2\2\u0081\u0083"+ + "\7\n\2\2\u0082\u0084\5\24\13\2\u0083\u0082\3\2\2\2\u0083\u0084\3\2\2\2"+ + "\u0084\u0085\3\2\2\2\u0085\u0086\7H\2\2\u0086\23\3\2\2\2\u0087\u0088\7"+ + "\6\2\2\u0088\u008d\5\26\f\2\u0089\u008a\7\13\2\2\u008a\u008c\5\26\f\2"+ + "\u008b\u0089\3\2\2\2\u008c\u008f\3\2\2\2\u008d\u008b\3\2\2\2\u008d\u008e"+ + "\3\2\2\2\u008e\u0090\3\2\2\2\u008f\u008d\3\2\2\2\u0090\u0091\7\7\2\2\u0091"+ + "\25\3\2\2\2\u0092\u0093\7\f\2\2\u0093\u00a4\7J\2\2\u0094\u0095\7\r\2\2"+ + "\u0095\u00a4\7J\2\2\u0096\u0097\7\16\2\2\u0097\u0098\7V\2\2\u0098\u0099"+ + "\7\17\2\2\u0099\u00a4\5(\25\2\u009a\u009b\7\20\2\2\u009b\u00a4\5(\25\2"+ + "\u009c\u009d\7\21\2\2\u009d\u00a4\5(\25\2\u009e\u00a1\7\22\2\2\u009f\u00a2"+ + "\7\23\2\2\u00a0\u00a2\5(\25\2\u00a1\u009f\3\2\2\2\u00a1\u00a0\3\2\2\2"+ + "\u00a2\u00a4\3\2\2\2\u00a3\u0092\3\2\2\2\u00a3\u0094\3\2\2\2\u00a3\u0096"+ + "\3\2\2\2\u00a3\u009a\3\2\2\2\u00a3\u009c\3\2\2\2\u00a3\u009e\3\2\2\2\u00a4"+ + "\27\3\2\2\2\u00a5\u00aa\5\32\16\2\u00a6\u00a7\7\13\2\2\u00a7\u00a9\5\32"+ + "\16\2\u00a8\u00a6\3\2\2\2\u00a9\u00ac\3\2\2\2\u00aa\u00a8\3\2\2\2\u00aa"+ + "\u00ab\3\2\2\2\u00ab\31\3\2\2\2\u00ac\u00aa\3\2\2\2\u00ad\u00af\5\34\17"+ + "\2\u00ae\u00ad\3\2\2\2\u00af\u00b2\3\2\2\2\u00b0\u00ae\3\2\2\2\u00b0\u00b1"+ + "\3\2\2\2\u00b1\u00b3\3\2\2\2\u00b2\u00b0\3\2\2\2\u00b3\u00b7\5&\24\2\u00b4"+ + "\u00b6\5\34\17\2\u00b5\u00b4\3\2\2\2\u00b6\u00b9\3\2\2\2\u00b7\u00b5\3"+ + "\2\2\2\u00b7\u00b8\3\2\2\2\u00b8\u00ba\3\2\2\2\u00b9\u00b7\3\2\2\2\u00ba"+ + "\u00bb\7V\2\2\u00bb\33\3\2\2\2\u00bc\u00cf\7\24\2\2\u00bd\u00cf\7\25\2"+ + "\2\u00be\u00bf\7\26\2\2\u00bf\u00c0\7\6\2\2\u00c0\u00c1\7M\2\2\u00c1\u00cf"+ + "\7\7\2\2\u00c2\u00c3\7\27\2\2\u00c3\u00c4\7\6\2\2\u00c4\u00c5\7V\2\2\u00c5"+ + "\u00cf\7\7\2\2\u00c6\u00cf\7\23\2\2\u00c7\u00cf\7\30\2\2\u00c8\u00cc\7"+ + "\31\2\2\u00c9\u00ca\7\6\2\2\u00ca\u00cb\7V\2\2\u00cb\u00cd\7\7\2\2\u00cc"+ + "\u00c9\3\2\2\2\u00cc\u00cd\3\2\2\2\u00cd\u00cf\3\2\2\2\u00ce\u00bc\3\2"+ + "\2\2\u00ce\u00bd\3\2\2\2\u00ce\u00be\3\2\2\2\u00ce\u00c2\3\2\2\2\u00ce"+ + "\u00c6\3\2\2\2\u00ce\u00c7\3\2\2\2\u00ce\u00c8\3\2\2\2\u00cf\35\3\2\2"+ + "\2\u00d0\u00d2\5 \21\2\u00d1\u00d0\3\2\2\2\u00d2\u00d3\3\2\2\2\u00d3\u00d1"+ + "\3\2\2\2\u00d3\u00d4\3\2\2\2\u00d4\37\3\2\2\2\u00d5\u011c\5\16\b\2\u00d6"+ + "\u00d8\7\b\2\2\u00d7\u00d9\5\36\20\2\u00d8\u00d7\3\2\2\2\u00d8\u00d9\3"+ + "\2\2\2\u00d9\u00da\3\2\2\2\u00da\u011c\7\t\2\2\u00db\u00dc\5(\25\2\u00dc"+ + "\u00dd\7\5\2\2\u00dd\u011c\3\2\2\2\u00de\u00df\7\32\2\2\u00df\u00e0\7"+ + "\6\2\2\u00e0\u00e1\5(\25\2\u00e1\u00e2\7\7\2\2\u00e2\u00e5\5 \21\2\u00e3"+ + "\u00e4\7\33\2\2\u00e4\u00e6\5 \21\2\u00e5\u00e3\3\2\2\2\u00e5\u00e6\3"+ + "\2\2\2\u00e6\u011c\3\2\2\2\u00e7\u00e9\5\34\17\2\u00e8\u00e7\3\2\2\2\u00e9"+ + "\u00ec\3\2\2\2\u00ea\u00e8\3\2\2\2\u00ea\u00eb\3\2\2\2\u00eb\u00ed\3\2"+ + "\2\2\u00ec\u00ea\3\2\2\2\u00ed\u00ee\7\34\2\2\u00ee\u00ef\7\6\2\2\u00ef"+ + "\u00f0\5(\25\2\u00f0\u00f1\7\7\2\2\u00f1\u00f2\5 \21\2\u00f2\u011c\3\2"+ + "\2\2\u00f3\u00f5\5\34\17\2\u00f4\u00f3\3\2\2\2\u00f5\u00f8\3\2\2\2\u00f6"+ + "\u00f4\3\2\2\2\u00f6\u00f7\3\2\2\2\u00f7\u00f9\3\2\2\2\u00f8\u00f6\3\2"+ + "\2\2\u00f9\u00fa\7\35\2\2\u00fa\u00fb\5 \21\2\u00fb\u00fc\7\34\2\2\u00fc"+ + "\u00fd\7\6\2\2\u00fd\u00fe\5(\25\2\u00fe\u00ff\7\7\2\2\u00ff\u0100\7\5"+ + "\2\2\u0100\u011c\3\2\2\2\u0101\u0103\5\34\17\2\u0102\u0101\3\2\2\2\u0103"+ + "\u0106\3\2\2\2\u0104\u0102\3\2\2\2\u0104\u0105\3\2\2\2\u0105\u0107\3\2"+ + "\2\2\u0106\u0104\3\2\2\2\u0107\u0108\7\36\2\2\u0108\u010a\7\6\2\2\u0109"+ + "\u010b\5\"\22\2\u010a\u0109\3\2\2\2\u010a\u010b\3\2\2\2\u010b\u010c\3"+ + "\2\2\2\u010c\u010d\5$\23\2\u010d\u010e\7\7\2\2\u010e\u010f\5 \21\2\u010f"+ + "\u011c\3\2\2\2\u0110\u0112\7\37\2\2\u0111\u0113\5(\25\2\u0112\u0111\3"+ + "\2\2\2\u0112\u0113\3\2\2\2\u0113\u0114\3\2\2\2\u0114\u011c\7\5\2\2\u0115"+ + "\u0116\7 \2\2\u0116\u0117\7\b\2\2\u0117\u0118\5,\27\2\u0118\u0119\7\t"+ + "\2\2\u0119\u011c\3\2\2\2\u011a\u011c\5\22\n\2\u011b\u00d5\3\2\2\2\u011b"+ + "\u00d6\3\2\2\2\u011b\u00db\3\2\2\2\u011b\u00de\3\2\2\2\u011b\u00ea\3\2"+ + "\2\2\u011b\u00f6\3\2\2\2\u011b\u0104\3\2\2\2\u011b\u0110\3\2\2\2\u011b"+ + "\u0115\3\2\2\2\u011b\u011a\3\2\2\2\u011c!\3\2\2\2\u011d\u011f\5\34\17"+ + "\2\u011e\u011d\3\2\2\2\u011f\u0122\3\2\2\2\u0120\u011e\3\2\2\2\u0120\u0121"+ + "\3\2\2\2\u0121\u0124\3\2\2\2\u0122\u0120\3\2\2\2\u0123\u0125\5&\24\2\u0124"+ + "\u0123\3\2\2\2\u0124\u0125\3\2\2\2\u0125\u0129\3\2\2\2\u0126\u0128\5\34"+ + "\17\2\u0127\u0126\3\2\2\2\u0128\u012b\3\2\2\2\u0129\u0127\3\2\2\2\u0129"+ + "\u012a\3\2\2\2\u012a\u012c\3\2\2\2\u012b\u0129\3\2\2\2\u012c\u012f\7V"+ + "\2\2\u012d\u012e\7\4\2\2\u012e\u0130\5(\25\2\u012f\u012d\3\2\2\2\u012f"+ + "\u0130\3\2\2\2\u0130#\3\2\2\2\u0131\u0132\7\5\2\2\u0132\u0133\5(\25\2"+ + "\u0133\u0134\7\5\2\2\u0134\u0135\5(\25\2\u0135\u013c\3\2\2\2\u0136\u0137"+ + "\7\17\2\2\u0137\u0138\5(\25\2\u0138\u0139\7!\2\2\u0139\u013a\5(\25\2\u013a"+ + "\u013c\3\2\2\2\u013b\u0131\3\2\2\2\u013b\u0136\3\2\2\2\u013c%\3\2\2\2"+ + "\u013d\u013e\b\24\1\2\u013e\u013f\7\6\2\2\u013f\u0140\5&\24\2\u0140\u0141"+ + "\7\7\2\2\u0141\u0146\3\2\2\2\u0142\u0146\7I\2\2\u0143\u0144\7\"\2\2\u0144"+ + "\u0146\7I\2\2\u0145\u013d\3\2\2\2\u0145\u0142\3\2\2\2\u0145\u0143\3\2"+ + "\2\2\u0146\u0154\3\2\2\2\u0147\u0148\f\5\2\2\u0148\u0153\7#\2\2\u0149"+ + "\u014a\f\4\2\2\u014a\u014c\7$\2\2\u014b\u014d\5(\25\2\u014c\u014b\3\2"+ + "\2\2\u014c\u014d\3\2\2\2\u014d\u014e\3\2\2\2\u014e\u0153\7%\2\2\u014f"+ + "\u0150\f\3\2\2\u0150\u0151\7\6\2\2\u0151\u0153\7\7\2\2\u0152\u0147\3\2"+ + "\2\2\u0152\u0149\3\2\2\2\u0152\u014f\3\2\2\2\u0153\u0156\3\2\2\2\u0154"+ + "\u0152\3\2\2\2\u0154\u0155\3\2\2\2\u0155\'\3\2\2\2\u0156\u0154\3\2\2\2"+ + "\u0157\u0158\b\25\1\2\u0158\u0159\7\6\2\2\u0159\u015a\5(\25\2\u015a\u015b"+ + "\7\7\2\2\u015b\u0180\3\2\2\2\u015c\u015d\7V\2\2\u015d\u015f\7\6\2\2\u015e"+ + "\u0160\5*\26\2\u015f\u015e\3\2\2\2\u015f\u0160\3\2\2\2\u0160\u0161\3\2"+ + "\2\2\u0161\u0180\7\7\2\2\u0162\u0163\7\6\2\2\u0163\u0164\5&\24\2\u0164"+ + "\u0165\7\7\2\2\u0165\u0166\5(\25\31\u0166\u0180\3\2\2\2\u0167\u0168\t"+ + "\2\2\2\u0168\u0180\5(\25\30\u0169\u016a\7#\2\2\u016a\u0180\5(\25\26\u016b"+ + "\u016c\t\3\2\2\u016c\u0180\5(\25\25\u016d\u016e\t\4\2\2\u016e\u0180\5"+ + "(\25\21\u016f\u0170\7\b\2\2\u0170\u0175\5(\25\2\u0171\u0172\7\13\2\2\u0172"+ + "\u0174\5(\25\2\u0173\u0171\3\2\2\2\u0174\u0177\3\2\2\2\u0175\u0173\3\2"+ + "\2\2\u0175\u0176\3\2\2\2\u0176\u0178\3\2\2\2\u0177\u0175\3\2\2\2\u0178"+ + "\u0179\7\t\2\2\u0179\u0180\3\2\2\2\u017a\u0180\7V\2\2\u017b\u0180\7M\2"+ + "\2\u017c\u0180\7J\2\2\u017d\u0180\7K\2\2\u017e\u0180\7L\2\2\u017f\u0157"+ + "\3\2\2\2\u017f\u015c\3\2\2\2\u017f\u0162\3\2\2\2\u017f\u0167\3\2\2\2\u017f"+ + "\u0169\3\2\2\2\u017f\u016b\3\2\2\2\u017f\u016d\3\2\2\2\u017f\u016f\3\2"+ + "\2\2\u017f\u017a\3\2\2\2\u017f\u017b\3\2\2\2\u017f\u017c\3\2\2\2\u017f"+ + "\u017d\3\2\2\2\u017f\u017e\3\2\2\2\u0180\u01ab\3\2\2\2\u0181\u0182\f\24"+ + "\2\2\u0182\u0183\t\5\2\2\u0183\u01aa\5(\25\25\u0184\u0185\f\23\2\2\u0185"+ + "\u0186\t\6\2\2\u0186\u01aa\5(\25\24\u0187\u0188\f\22\2\2\u0188\u0189\t"+ + "\7\2\2\u0189\u01aa\5(\25\23\u018a\u018b\f\20\2\2\u018b\u018c\t\b\2\2\u018c"+ + "\u01aa\5(\25\21\u018d\u018e\f\17\2\2\u018e\u018f\7+\2\2\u018f\u01aa\5"+ + "(\25\20\u0190\u0191\f\16\2\2\u0191\u0192\7\67\2\2\u0192\u01aa\5(\25\17"+ + "\u0193\u0194\f\r\2\2\u0194\u0195\78\2\2\u0195\u01aa\5(\25\16\u0196\u0197"+ + "\f\f\2\2\u0197\u0198\79\2\2\u0198\u01aa\5(\25\r\u0199\u019a\f\13\2\2\u019a"+ + "\u019b\7:\2\2\u019b\u01aa\5(\25\f\u019c\u019d\f\n\2\2\u019d\u019e\7\4"+ + "\2\2\u019e\u01aa\5(\25\n\u019f\u01a0\f\t\2\2\u01a0\u01a1\t\t\2\2\u01a1"+ + "\u01aa\5(\25\t\u01a2\u01a3\f\32\2\2\u01a3\u01a4\7$\2\2\u01a4\u01a5\5("+ + "\25\2\u01a5\u01a6\7%\2\2\u01a6\u01aa\3\2\2\2\u01a7\u01a8\f\27\2\2\u01a8"+ + "\u01aa\t\2\2\2\u01a9\u0181\3\2\2\2\u01a9\u0184\3\2\2\2\u01a9\u0187\3\2"+ + "\2\2\u01a9\u018a\3\2\2\2\u01a9\u018d\3\2\2\2\u01a9\u0190\3\2\2\2\u01a9"+ + "\u0193\3\2\2\2\u01a9\u0196\3\2\2\2\u01a9\u0199\3\2\2\2\u01a9\u019c\3\2"+ + "\2\2\u01a9\u019f\3\2\2\2\u01a9\u01a2\3\2\2\2\u01a9\u01a7\3\2\2\2\u01aa"+ + "\u01ad\3\2\2\2\u01ab\u01a9\3\2\2\2\u01ab\u01ac\3\2\2\2\u01ac)\3\2\2\2"+ + "\u01ad\u01ab\3\2\2\2\u01ae\u01b3\5(\25\2\u01af\u01b0\7\13\2\2\u01b0\u01b2"+ + "\5(\25\2\u01b1\u01af\3\2\2\2\u01b2\u01b5\3\2\2\2\u01b3\u01b1\3\2\2\2\u01b3"+ + "\u01b4\3\2\2\2\u01b4+\3\2\2\2\u01b5\u01b3\3\2\2\2\u01b6\u01b8\5.\30\2"+ + "\u01b7\u01b6\3\2\2\2\u01b8\u01bb\3\2\2\2\u01b9\u01b7\3\2\2\2\u01b9\u01ba"+ + "\3\2\2\2\u01ba-\3\2\2\2\u01bb\u01b9\3\2\2\2\u01bc\u01c0\5\60\31\2\u01bd"+ + "\u01c0\5\62\32\2\u01be\u01c0\5\64\33\2\u01bf\u01bc\3\2\2\2\u01bf\u01bd"+ + "\3\2\2\2\u01bf\u01be\3\2\2\2\u01c0/\3\2\2\2\u01c1\u01c2\7V\2\2\u01c2\u01c9"+ + "\7\17\2\2\u01c3\u01c5\7*\2\2\u01c4\u01c6\7V\2\2\u01c5\u01c4\3\2\2\2\u01c5"+ + "\u01c6\3\2\2\2\u01c6\u01c7\3\2\2\2\u01c7\u01c9\7\17\2\2\u01c8\u01c1\3"+ + "\2\2\2\u01c8\u01c3\3\2\2\2\u01c9\61\3\2\2\2\u01ca\u01cc\7G\2\2\u01cb\u01cd"+ + "\5\66\34\2\u01cc\u01cb\3\2\2\2\u01cc\u01cd\3\2\2\2\u01cd\63\3\2\2\2\u01ce"+ + "\u01cf\7E\2\2\u01cf\u01d4\58\35\2\u01d0\u01d1\7\13\2\2\u01d1\u01d3\58"+ + "\35\2\u01d2\u01d0\3\2\2\2\u01d3\u01d6\3\2\2\2\u01d4\u01d2\3\2\2\2\u01d4"+ + "\u01d5\3\2\2\2\u01d5\65\3\2\2\2\u01d6\u01d4\3\2\2\2\u01d7\u01ef\58\35"+ + "\2\u01d8\u01d9\7F\2\2\u01d9\u01ef\58\35\2\u01da\u01db\58\35\2\u01db\u01dc"+ + "\7\13\2\2\u01dc\u01dd\7V\2\2\u01dd\u01ef\3\2\2\2\u01de\u01df\7\6\2\2\u01df"+ + "\u01e0\58\35\2\u01e0\u01e1\7\7\2\2\u01e1\u01e2\7\13\2\2\u01e2\u01e3\7"+ + "V\2\2\u01e3\u01ef\3\2\2\2\u01e4\u01e5\7\6\2\2\u01e5\u01e6\58\35\2\u01e6"+ + "\u01e7\7\13\2\2\u01e7\u01e8\7V\2\2\u01e8\u01e9\7\7\2\2\u01e9\u01ef\3\2"+ + "\2\2\u01ea\u01eb\7\6\2\2\u01eb\u01ec\58\35\2\u01ec\u01ed\7\7\2\2\u01ed"+ + "\u01ef\3\2\2\2\u01ee\u01d7\3\2\2\2\u01ee\u01d8\3\2\2\2\u01ee\u01da\3\2"+ + "\2\2\u01ee\u01de\3\2\2\2\u01ee\u01e4\3\2\2\2\u01ee\u01ea\3\2\2\2\u01ef"+ + "\67\3\2\2\2\u01f0\u01f1\b\35\1\2\u01f1\u01f2\7$\2\2\u01f2\u01f3\58\35"+ + "\2\u01f3\u01f4\7%\2\2\u01f4\u01ff\3\2\2\2\u01f5\u01f6\t\n\2\2\u01f6\u01ff"+ + "\58\35\n\u01f7\u01ff\7V\2\2\u01f8\u01ff\7W\2\2\u01f9\u01fa\7\b\2\2\u01fa"+ + "\u01fb\7V\2\2\u01fb\u01ff\7\t\2\2\u01fc\u01ff\7M\2\2\u01fd\u01ff\7K\2"+ + "\2\u01fe\u01f0\3\2\2\2\u01fe\u01f5\3\2\2\2\u01fe\u01f7\3\2\2\2\u01fe\u01f8"+ + "\3\2\2\2\u01fe\u01f9\3\2\2\2\u01fe\u01fc\3\2\2\2\u01fe\u01fd\3\2\2\2\u01ff"+ + "\u020b\3\2\2\2\u0200\u0201\f\13\2\2\u0201\u0202\t\5\2\2\u0202\u020a\5"+ + "8\35\f\u0203\u0204\f\t\2\2\u0204\u0205\t\13\2\2\u0205\u020a\58\35\n\u0206"+ + "\u0207\f\b\2\2\u0207\u0208\t\7\2\2\u0208\u020a\58\35\t\u0209\u0200\3\2"+ + "\2\2\u0209\u0203\3\2\2\2\u0209\u0206\3\2\2\2\u020a\u020d\3\2\2\2\u020b"+ + "\u0209\3\2\2\2\u020b\u020c\3\2\2\2\u020c9\3\2\2\2\u020d\u020b\3\2\2\2"+ "\67DMRW^dkrx}\u0083\u008d\u00a1\u00a3\u00aa\u00b0\u00b7\u00cc\u00ce\u00d3"+ - "\u00d8\u00e5\u00e8\u00f1\u00fc\u0101\u0109\u0112\u0117\u011b\u0120\u0126"+ - "\u0132\u013c\u0143\u0149\u014b\u0156\u016c\u0176\u01a0\u01a2\u01aa\u01b0"+ - "\u01b6\u01bc\u01bf\u01c3\u01cb\u01e5\u01f5\u0200\u0202"; + "\u00d8\u00e5\u00ea\u00f6\u0104\u010a\u0112\u011b\u0120\u0124\u0129\u012f"+ + "\u013b\u0145\u014c\u0152\u0154\u015f\u0175\u017f\u01a9\u01ab\u01b3\u01b9"+ + "\u01bf\u01c5\u01c8\u01cc\u01d4\u01ee\u01fe\u0209\u020b"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 286dceba4..1d77c87fb 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -359,6 +359,28 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { } } + /** + * Add declared directives to a conditional jump (as part of a loop). + * + * @param conditional The loop conditional + * @param directivesCtx The directives to add + */ + private void addDirectives(StatementConditionalJump conditional, List directivesCtx) { + List directives = new ArrayList<>(); + for(KickCParser.DirectiveContext directiveContext : directivesCtx) { + directives.add((Directive) this.visit(directiveContext)); + } + for(Directive directive : directives) { + StatementSource source = new StatementSource(directivesCtx.get(0)); + if(directive instanceof DirectiveInline) { + conditional.setDeclaredUnroll(true); + } else { + throw new CompileError("Unsupported loop directive " + directive, source); + } + } + } + + @Override public Directive visitDirectiveConst(KickCParser.DirectiveConstContext ctx) { return new DirectiveConst(); @@ -466,7 +488,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { PrePostModifierHandler.addPreModifiers(this, ctx.expr()); RValue rValue = (RValue) this.visit(ctx.expr()); PrePostModifierHandler.addPostModifiers(this, ctx.expr()); - Statement doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel.getRef(), new StatementSource(ctx)); + StatementConditionalJump doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(doJmpStmt); Statement endJmpStmt = new StatementJump(endJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(endJmpStmt); @@ -477,6 +499,9 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { sequence.addStatement(beginJmpStmt); StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(endJumpTarget); + + // Add directives + addDirectives(doJmpStmt, ctx.directive()); return null; } @@ -491,8 +516,11 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { PrePostModifierHandler.addPreModifiers(this, ctx.expr()); RValue rValue = (RValue) this.visit(ctx.expr()); PrePostModifierHandler.addPostModifiers(this, ctx.expr()); - Statement doJmpStmt = new StatementConditionalJump(rValue, beginJumpLabel.getRef(), new StatementSource(ctx)); + StatementConditionalJump doJmpStmt = new StatementConditionalJump(rValue, beginJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(doJmpStmt); + + addDirectives(doJmpStmt, ctx.directive()); + return null; } @@ -536,8 +564,9 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { RValue rValue = (RValue) this.visit(ctx.expr(0)); PrePostModifierHandler.addPostModifiers(this, ctx.expr(0)); // Add jump if condition was met - Statement doJmpStmt = new StatementConditionalJump(rValue, repeatLabel.getRef(), new StatementSource(ctx)); + StatementConditionalJump doJmpStmt = new StatementConditionalJump(rValue, repeatLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(doJmpStmt); + addDirectives(doJmpStmt, stmtForCtx.directive()); return null; } @@ -572,8 +601,9 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { Statement stmtTmpVar = new StatementAssignment(tmpVarRef, lValue.getRef(), Operators.NEQ, beyondLastVal, new StatementSource(ctx)); sequence.addStatement(stmtTmpVar); // Add jump if condition was met - Statement doJmpStmt = new StatementConditionalJump(tmpVarRef, repeatLabel.getRef(), new StatementSource(ctx)); + StatementConditionalJump doJmpStmt = new StatementConditionalJump(tmpVarRef, repeatLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(doJmpStmt); + addDirectives(doJmpStmt, stmtForCtx.directive()); return null; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java index 459a36ad0..e7d314606 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java @@ -24,8 +24,8 @@ public class Pass1AssertUsedVars extends Pass1Base { @Override public boolean step() { - new PassNStatementIndices(getProgram()).generateStatementIndices(); - new PassNVariableReferenceInfos(getProgram()).generateVariableReferenceInfos(); + new PassNStatementIndices(getProgram()).execute(); + new PassNVariableReferenceInfos(getProgram()).execute(); VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos(); ControlFlowBlock beginBlock = getProgram().getGraph().getBlock(new LabelRef(SymbolRef.BEGIN_BLOCK_NAME)); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureInline.java b/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureInline.java index 3984a6626..914e9bffa 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureInline.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureInline.java @@ -40,82 +40,7 @@ public class Pass1ProcedureInline extends Pass1Base { if(procedure.getInterruptType()!=null) { throw new CompileError("Error! Interrupts cannot be inlined. "+procedure.getRef().toString()); } - Scope callScope = getScope().getScope(block.getScope()); - // Remove call - statementsIt.remove(); - // Find call serial number (handles when multiple calls to the same procedure is made in the call scope) - int serial = nextSerial(procedure, callScope); - // Copy all procedure symbols - inlineSymbols(procedure, callScope, serial); - // Generate parameter assignments - inlineParameterAssignments(statementsIt, call, procedure, callScope, serial); - // Create a new block label for the rest of the calling block - Label restBlockLabel = callScope.addLabelIntermediate(); - // Copy all procedure blocks - List procedureBlocks = getGraph().getScopeBlocks(procedure.getRef()); - for(ControlFlowBlock procedureBlock : procedureBlocks) { - LabelRef procBlockLabelRef = procedureBlock.getLabel(); - Symbol procBlockLabel = getScope().getSymbol(procBlockLabelRef); - Label inlinedBlockLabel; - if(procedure.equals(procBlockLabel)) { - inlinedBlockLabel = callScope.getLabel(procedure.getLocalName() + serial); - } else { - String inlinedBlockLabelName = getInlineSymbolName(procedure, procBlockLabel, serial); - inlinedBlockLabel = callScope.getLabel(inlinedBlockLabelName); - } - ControlFlowBlock inlineBlock = new ControlFlowBlock(inlinedBlockLabel.getRef(), callScope.getRef()); - blocksIt.add(inlineBlock); - for(Statement procStatement : procedureBlock.getStatements()) { - Statement inlinedStatement = inlineStatement(procStatement, procedure, callScope, serial); - if(inlinedStatement != null) { - inlineBlock.addStatement(inlinedStatement); - } - } - // Set successors - if(procedureBlock.getDefaultSuccessor() != null) { - LabelRef procBlockSuccessorRef = procedureBlock.getDefaultSuccessor(); - LabelRef inlinedSuccessor = inlineSuccessor(procBlockSuccessorRef, procedure, callScope, serial, restBlockLabel); - inlineBlock.setDefaultSuccessor(inlinedSuccessor); - } - if(procedureBlock.getConditionalSuccessor() != null) { - LabelRef procBlockSuccessorRef = procedureBlock.getConditionalSuccessor(); - LabelRef inlinedSuccessor = inlineSuccessor(procBlockSuccessorRef, procedure, callScope, serial, restBlockLabel); - inlineBlock.setConditionalSuccessor(inlinedSuccessor); - } - } - // Create a new block for the rest of the calling block - ControlFlowBlock restBlock = new ControlFlowBlock(restBlockLabel.getRef(), callScope.getRef()); - blocksIt.add(restBlock); - // Generate return assignment - if(!procedure.getReturnType().equals(SymbolType.VOID)) { - Variable procReturnVar = procedure.getVariable("return"); - String inlinedReturnVarName = getInlineSymbolName(procedure, procReturnVar, serial); - Variable inlinedReturnVar = callScope.getVariable(inlinedReturnVarName); - restBlock.addStatement(new StatementAssignment(call.getlValue(), inlinedReturnVar.getRef(), call.getSource())); - } else { - // Remove the tmp var receiving the result - LValue lValue = call.getlValue(); - if(lValue instanceof VariableRef) { - callScope.remove(getScope().getVariable((VariableRef) lValue)); - call.setlValue(null); - } - } - // Copy the rest of the calling block to the new block - while(statementsIt.hasNext()) { - Statement restStatement = statementsIt.next(); - statementsIt.remove(); - restBlock.addStatement(restStatement); - } - // Set the successors for the rest block - restBlock.setDefaultSuccessor(block.getDefaultSuccessor()); - restBlock.setConditionalSuccessor(block.getConditionalSuccessor()); - // Set default successor to the original block to the inlined procedure block - Label inlinedProcLabel = callScope.getLabel(procedure.getLocalName() + serial); - block.setDefaultSuccessor(inlinedProcLabel.getRef()); - // Set conditional successor of original block to null (as any condition has been moved to the rest block) - block.setConditionalSuccessor(null); - // Log the inlining - getLog().append("Inlined call " + call.toString(getProgram(), false)); + inlineProcedureCall(call, procedure, statementsIt, block, blocksIt); // Exit and restart return true; } @@ -125,6 +50,94 @@ public class Pass1ProcedureInline extends Pass1Base { return false; } + /** + * Inline a specific call to a procedure. + * + * @param call The call to inline + * @param procedure The procedure being called + * @param statementsIt The statement iterator pointing to the call statement + * @param block The block containing the call + * @param blocksIt The block iterator pointing to the block containing the call + */ + private void inlineProcedureCall(StatementCall call, Procedure procedure, ListIterator statementsIt, ControlFlowBlock block, ListIterator blocksIt) { + Scope callScope = getScope().getScope(block.getScope()); + // Remove call + statementsIt.remove(); + // Find call serial number (handles when multiple calls to the same procedure is made in the call scope) + int serial = nextSerial(procedure, callScope); + // Copy all procedure symbols + inlineSymbols(procedure, callScope, serial); + // Generate parameter assignments + inlineParameterAssignments(statementsIt, call, procedure, callScope, serial); + // Create a new block label for the rest of the calling block + Label restBlockLabel = callScope.addLabelIntermediate(); + // Copy all procedure blocks + List procedureBlocks = getGraph().getScopeBlocks(procedure.getRef()); + for(ControlFlowBlock procedureBlock : procedureBlocks) { + LabelRef procBlockLabelRef = procedureBlock.getLabel(); + Symbol procBlockLabel = getScope().getSymbol(procBlockLabelRef); + Label inlinedBlockLabel; + if(procedure.equals(procBlockLabel)) { + inlinedBlockLabel = callScope.getLabel(procedure.getLocalName() + serial); + } else { + String inlinedBlockLabelName = getInlineSymbolName(procedure, procBlockLabel, serial); + inlinedBlockLabel = callScope.getLabel(inlinedBlockLabelName); + } + ControlFlowBlock inlineBlock = new ControlFlowBlock(inlinedBlockLabel.getRef(), callScope.getRef()); + blocksIt.add(inlineBlock); + for(Statement procStatement : procedureBlock.getStatements()) { + Statement inlinedStatement = inlineStatement(procStatement, procedure, callScope, serial); + if(inlinedStatement != null) { + inlineBlock.addStatement(inlinedStatement); + } + } + // Set successors + if(procedureBlock.getDefaultSuccessor() != null) { + LabelRef procBlockSuccessorRef = procedureBlock.getDefaultSuccessor(); + LabelRef inlinedSuccessor = inlineSuccessor(procBlockSuccessorRef, procedure, callScope, serial, restBlockLabel); + inlineBlock.setDefaultSuccessor(inlinedSuccessor); + } + if(procedureBlock.getConditionalSuccessor() != null) { + LabelRef procBlockSuccessorRef = procedureBlock.getConditionalSuccessor(); + LabelRef inlinedSuccessor = inlineSuccessor(procBlockSuccessorRef, procedure, callScope, serial, restBlockLabel); + inlineBlock.setConditionalSuccessor(inlinedSuccessor); + } + } + // Create a new block for the rest of the calling block + ControlFlowBlock restBlock = new ControlFlowBlock(restBlockLabel.getRef(), callScope.getRef()); + blocksIt.add(restBlock); + // Generate return assignment + if(!procedure.getReturnType().equals(SymbolType.VOID)) { + Variable procReturnVar = procedure.getVariable("return"); + String inlinedReturnVarName = getInlineSymbolName(procedure, procReturnVar, serial); + Variable inlinedReturnVar = callScope.getVariable(inlinedReturnVarName); + restBlock.addStatement(new StatementAssignment(call.getlValue(), inlinedReturnVar.getRef(), call.getSource())); + } else { + // Remove the tmp var receiving the result + LValue lValue = call.getlValue(); + if(lValue instanceof VariableRef) { + callScope.remove(getScope().getVariable((VariableRef) lValue)); + call.setlValue(null); + } + } + // Copy the rest of the calling block to the new block + while(statementsIt.hasNext()) { + Statement restStatement = statementsIt.next(); + statementsIt.remove(); + restBlock.addStatement(restStatement); + } + // Set the successors for the rest block + restBlock.setDefaultSuccessor(block.getDefaultSuccessor()); + restBlock.setConditionalSuccessor(block.getConditionalSuccessor()); + // Set default successor to the original block to the inlined procedure block + Label inlinedProcLabel = callScope.getLabel(procedure.getLocalName() + serial); + block.setDefaultSuccessor(inlinedProcLabel.getRef()); + // Set conditional successor of original block to null (as any condition has been moved to the rest block) + block.setConditionalSuccessor(null); + // Log the inlining + getLog().append("Inlined call " + call.toString(getProgram(), false)); + } + private LabelRef inlineSuccessor(LabelRef procBlockSuccessorRef, Procedure procedure, Scope callScope, int serial, Label restBlockLabel) { LabelRef inlinedSuccessor; if(procBlockSuccessorRef.getFullName().equals(SymbolRef.PROCEXIT_BLOCK_NAME)) { @@ -188,7 +201,9 @@ public class Pass1ProcedureInline extends Pass1Base { String inlineSymbolName = getInlineSymbolName(procedure, procDestination, serial); inlinedDest = callScope.getLabel(inlineSymbolName); } - inlinedStatement = new StatementConditionalJump(procConditional.getrValue1(), procConditional.getOperator(), procConditional.getrValue2(), inlinedDest.getRef(), procConditional.getSource()); + StatementConditionalJump inlinedConditionalJump = new StatementConditionalJump(procConditional.getrValue1(), procConditional.getOperator(), procConditional.getrValue2(), inlinedDest.getRef(), procConditional.getSource()); + inlinedConditionalJump.setDeclaredUnroll(procConditional.isDeclaredUnroll()); + inlinedStatement = inlinedConditionalJump; } else if(procStatement instanceof StatementReturn) { // No statement needed return null; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalAndOrRewriting.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalAndOrRewriting.java index 999f36c38..65114acf1 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalAndOrRewriting.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalAndOrRewriting.java @@ -89,7 +89,9 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization { ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef); getGraph().addBlock(newBlock); LabelRef destLabel = conditional.getDestination(); - newBlock.getStatements().add(new StatementConditionalJump(conditionAssignment.getrValue2(), destLabel, conditional.getSource())); + StatementConditionalJump newConditional = new StatementConditionalJump(conditionAssignment.getrValue2(), destLabel, conditional.getSource()); + newConditional.setDeclaredUnroll(conditional.isDeclaredUnroll()); + newBlock.getStatements().add(newConditional); newBlock.setDefaultSuccessor(block.getDefaultSuccessor()); newBlock.setConditionalSuccessor(destLabel); // Rewrite the conditional to use only the first part of the && condition expression @@ -119,13 +121,17 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization { Label newBlockLabel = currentScope.addLabelIntermediate(); ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef); getGraph().addBlock(newBlock); - newBlock.getStatements().add(new StatementConditionalJump(conditionAssignment.getrValue2(), conditional.getDestination(), conditional.getSource())); + StatementConditionalJump newConditional = new StatementConditionalJump(conditionAssignment.getrValue2(), conditional.getDestination(), conditional.getSource()); + // Copy unrolling to the new conditional + newConditional.setDeclaredUnroll(conditional.isDeclaredUnroll()); + newBlock.getStatements().add(newConditional); newBlock.setConditionalSuccessor(conditional.getDestination()); newBlock.setDefaultSuccessor(block.getDefaultSuccessor()); // Rewrite the conditional to use only the first part of the && condition expression block.setDefaultSuccessor(newBlockLabel.getRef()); conditional.setrValue2(conditionAssignment.getrValue1()); - + // Remove any unrolling from the original conditional as only the new one leaves the loop + conditional.setDeclaredUnroll(false); // TODO: Fix phi-values inside the destination phi-blocks to reflect the new control flow! Use replaceLabels(block, replacement) ControlFlowBlock conditionalDestBlock = getGraph().getBlock(conditional.getDestination()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3DominatorsAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DominatorsAnalysis.java similarity index 94% rename from src/main/java/dk/camelot64/kickc/passes/Pass3DominatorsAnalysis.java rename to src/main/java/dk/camelot64/kickc/passes/Pass2DominatorsAnalysis.java index 4c201cc8a..5a9a9760a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3DominatorsAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DominatorsAnalysis.java @@ -7,9 +7,9 @@ import java.util.ArrayList; import java.util.List; /** Finds the dominators for the control flow graph. */ -public class Pass3DominatorsAnalysis extends Pass2Base { +public class Pass2DominatorsAnalysis extends Pass2SsaOptimization { - public Pass3DominatorsAnalysis(Program program) { + public Pass2DominatorsAnalysis(Program program) { super(program); } @@ -19,10 +19,9 @@ public class Pass3DominatorsAnalysis extends Pass2Base { * Definition: d dom i if all paths from entry to node i include d *

* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf - * - * @return The graph dominators */ - public void findDominators() { + @Override + public boolean step() { DominatorsGraph dominatorsGraph = new DominatorsGraph(); // Initialize dominators: Dom[first]={first}, Dom[block]={all} @@ -75,6 +74,7 @@ public class Pass3DominatorsAnalysis extends Pass2Base { } while(change); getProgram().setDominators(dominatorsGraph); + return false; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3LoopAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass2LoopAnalysis.java similarity index 89% rename from src/main/java/dk/camelot64/kickc/passes/Pass3LoopAnalysis.java rename to src/main/java/dk/camelot64/kickc/passes/Pass2LoopAnalysis.java index 223caee8c..0a9b012a9 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3LoopAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2LoopAnalysis.java @@ -11,19 +11,21 @@ import java.util.*; *

* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf */ -public class Pass3LoopAnalysis extends Pass2Base { +public class Pass2LoopAnalysis extends Pass2SsaOptimization { - public Pass3LoopAnalysis(Program program) { + public Pass2LoopAnalysis(Program program) { super(program); } + /** * Finds loops and nested loops in the control flow graph. * Uses the dominators of the graph to find loops. *

* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf */ - public void findLoops() { + @Override + public boolean step() { DominatorsGraph dominators = getProgram().getDominators(); Collection blocks = getGraph().getAllBlocks(); @@ -35,7 +37,9 @@ public class Pass3LoopAnalysis extends Pass2Base { if(blockDominators.contains(successor)) { // Found a loop back edge! NaturalLoop loop = new NaturalLoop(successor, block.getLabel()); - getLog().append("Found back edge: " + loop.toString()); + if(getLog().isVerboseSSAOptimize()) { + getLog().append("Found back edge: " + loop.toString()); + } loopSet.addLoop(loop); } } @@ -61,15 +65,17 @@ public class Pass3LoopAnalysis extends Pass2Base { } } loop.setBlocks(loopBlocks); - getLog().append("Populated: " + loop.toString()); + if(getLog().isVerboseSSAOptimize()) { + getLog().append("Populated: " + loop.toString()); + } } boolean coalesceMore = true; while(coalesceMore) { coalesceMore = coalesceLoops(loopSet); } - getProgram().setLoopSet(loopSet); + return false; } /** diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2LoopUnroll.java b/src/main/java/dk/camelot64/kickc/passes/Pass2LoopUnroll.java new file mode 100644 index 000000000..0b6db7849 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2LoopUnroll.java @@ -0,0 +1,230 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.*; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementConditionalJump; +import dk.camelot64.kickc.model.statements.StatementInfos; +import dk.camelot64.kickc.model.statements.StatementPhiBlock; +import dk.camelot64.kickc.model.symbols.Label; +import dk.camelot64.kickc.model.symbols.Variable; +import dk.camelot64.kickc.model.symbols.VariableVersion; +import dk.camelot64.kickc.model.values.LabelRef; +import dk.camelot64.kickc.model.values.RValue; +import dk.camelot64.kickc.model.values.VariableRef; + +import java.util.*; + +/** Unroll Loops declared as inline. */ +public class Pass2LoopUnroll extends Pass2SsaOptimization { + + public Pass2LoopUnroll(Program program) { + super(program); + } + + @Override + public boolean step() { + // Look for loops to unroll + NaturalLoopSet loops = getProgram().getLoopSet(); + List unrollLoopCandidates = findUnrollLoopCandidates(loops); + // Is there any unrolling to do? + if(unrollLoopCandidates.isEmpty()) { + return false; + } + // Choose the candidate loop with the fewest blocks (and if several have the same number of blocks the first one encountered) + NaturalLoop unrollLoop = chooseUnrollLoop(unrollLoopCandidates); + getLog().append("Unrolling loop " + unrollLoop); + + List unrollBlocks = new ArrayList<>(); + for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { + if(unrollLoop.getBlocks().contains(block.getLabel())) { + unrollBlocks.add(block); + } + } + + // Unroll the first iteration of the loop + + // 0. Unroll Symbols + // - Create new versions of all symbols assigned inside the loop + Map definedToNewVar = new LinkedHashMap<>(); + VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos(); + for(ControlFlowBlock block : unrollBlocks) { + for(Statement statement : block.getStatements()) { + Collection definedVars = variableReferenceInfos.getDefinedVars(statement); + for(VariableRef definedVarRef : definedVars) { + Variable definedVar = getScope().getVariable(definedVarRef); + Variable newVar; + if(definedVarRef.isIntermediate()) { + newVar = definedVar.getScope().addVariableIntermediate(); + } else if(definedVarRef.isVersion()) { + newVar = ((VariableVersion) definedVar).getVersionOf().createVersion(); + } else { + throw new RuntimeException("Error! Variable is not versioned or intermediate " + definedVar.toString(getProgram())); + } + definedToNewVar.put(definedVarRef, newVar.getRef()); + getLog().append("Defined in loop: " + definedVarRef.getFullName() + " -> " + newVar.getRef().getFullName()); + } + } + } + + // - Ensure that all variables assigned inside the loop has a PHI in successor blocks to the loop + // - Find loop successor blocks + List loopSuccessors = new ArrayList<>(); + List loopSuccessorPredecessors = new ArrayList<>(); + for(ControlFlowBlock block : unrollBlocks) { + if(block.getDefaultSuccessor() != null && !unrollLoop.getBlocks().contains(block.getDefaultSuccessor())) { + // Default successor is outside + loopSuccessors.add(block.getDefaultSuccessor()); + loopSuccessorPredecessors.add(block.getLabel()); + } + if(block.getConditionalSuccessor() != null && !unrollLoop.getBlocks().contains(block.getConditionalSuccessor())) { + // Default successor is outside + loopSuccessors.add(block.getConditionalSuccessor()); + loopSuccessorPredecessors.add(block.getLabel()); + } + } + // - Add any needed PHI-statements to the successors + StatementInfos statementInfos = getProgram().getStatementInfos(); + for(VariableRef definedVarRef : definedToNewVar.keySet()) { + + // Find out if the variable is ever referenced outside the loop + boolean referencedOutsideLoop = false; + Collection varRefStatements = variableReferenceInfos.getVarRefStatements(definedVarRef); + for(Integer varRefStatement : varRefStatements) { + ControlFlowBlock refBlock = statementInfos.getBlock(varRefStatement); + if(!unrollLoop.getBlocks().contains(refBlock.getLabel())) { + referencedOutsideLoop = true; + break; + } + } + if(referencedOutsideLoop) { + for(int i = 0; i < loopSuccessors.size(); i++) { + LabelRef successorBlockRef = loopSuccessors.get(i); + LabelRef successorPredecessorRef = loopSuccessorPredecessors.get(i); + ControlFlowBlock successorBlock = getGraph().getBlock(successorBlockRef); + StatementPhiBlock phiBlock = successorBlock.getPhiBlock(); + + // Look for a phi-variable + boolean phiFound = false; + for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) { + if(phiVariable.getVariable().isVersion() && definedVarRef.isVersion()) { + if(phiVariable.getVariable().getFullNameUnversioned().equals(definedVarRef.getFullNameUnversioned())) { + phiFound = true; + } + } + } + if(!phiFound) { + Variable definedVar = getScope().getVariable(definedVarRef); + Variable newVar = ((VariableVersion) definedVar).getVersionOf().createVersion(); + StatementPhiBlock.PhiVariable newPhiVar = phiBlock.addPhiVariable(newVar.getRef()); + newPhiVar.setrValue(successorPredecessorRef, definedVarRef); + getLog().append("Missing PHI for " + definedVarRef.getFullName() + " in block " + successorBlock.getLabel() + " - " + phiBlock.toString(getProgram(), false)); + + // TODO: Replace all references to definedVarRef outside loop to newVar! + + } + } + } + } + + getLog().append(getGraph().toString(getProgram())); + + // 1. Copy all loop blocks to create the "rest of the loop" and modifying the existing loop to only be the first iteration) + // - Unroll Statements (copy all statements, replace symbols properly (with the new versions / the versions assigned in the existing loop) + // - Includes unrolling PHI-statements properly + // - Unroll Successors (loop-exit successors should point to the same exit, loop-internal successors should point to the new loop-internal block) + for(ControlFlowBlock block : unrollBlocks) { + // Find the serial number + int unrollSerial = 1; + String unrollLabelName = block.getLabel() + "_" + unrollSerial; + while(getScope().getLabel(unrollLabelName) != null) { + unrollSerial++; + } + // Create a label + Label unrollLabel = getScope().getScope(block.getScope()).addLabel(unrollLabelName); + // Create the new block + ControlFlowBlock unrollBlock = new ControlFlowBlock(unrollLabel.getRef(), block.getScope()); + getProgram().getGraph().addBlock(unrollBlock); + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementPhiBlock) { + StatementPhiBlock phiBlock = (StatementPhiBlock) statement; + StatementPhiBlock unrollPhiBlock = new StatementPhiBlock(); + for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) { + VariableRef phiVar = phiVariable.getVariable(); + VariableRef newVar = definedToNewVar.get(phiVar); + StatementPhiBlock.PhiVariable unrollPhiVariable = unrollPhiBlock.addPhiVariable(newVar); + for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { + /* FIX */ + LabelRef predecessor = phiRValue.getPredecessor(); + /* FIX */ + RValue rValue = phiRValue.getrValue(); + unrollPhiVariable.setrValue(predecessor, rValue); + } + } + } else { + throw new RuntimeException("Statement not handled by unroll " + statement); + } + } + } + + // Patch the "old loop" to only contain the first iteration + // - All successors in the old loop to the loop head should point to the new loop head instead. + // - Remove phi-variables in the old head from looping. (as this predecessor now no longer exists) + // - Remove the "unroll" directive on the condition in the old loop (as it is already unrolled). + + return false; + + } + + /** + * Choose which loop to unroll first from a candidate set. + * The smallest loop (fewest control flow blocks) is chosen. + * If multiple loops have the same size the first one is chosen. + * + * @param unrollLoopCandidates All loops that are decalred to be unrolled + * @return The loop to unroll first. + */ + private NaturalLoop chooseUnrollLoop(List unrollLoopCandidates) { + NaturalLoop unrollLoop = null; + for(NaturalLoop unrollLoopCandidate : unrollLoopCandidates) { + if(unrollLoop == null) { + unrollLoop = unrollLoopCandidate; + } else { + if(unrollLoopCandidate.getBlocks().size() < unrollLoop.getBlocks().size()) { + unrollLoop = unrollLoopCandidate; + } + } + } + return unrollLoop; + } + + /** + * Find all loops declared for unrolling. This is done by examining all conditional jumps, which hold the loop unroll declaration. + * + * @param loops All loops identified in the program + * @return All loops declared to be unrolled + */ + private List findUnrollLoopCandidates(NaturalLoopSet loops) { + List unrollLoopCandidates = new ArrayList<>(); + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementConditionalJump) { + if(((StatementConditionalJump) statement).isDeclaredUnroll()) { + // Found a candidate for unrolling - identify the loop + for(NaturalLoop loopCandidate : loops.getLoopsContainingBlock(block.getLabel())) { + if(!loopCandidate.getBlocks().contains(block.getConditionalSuccessor())) { + // The conditional jump exits the loopCandidate - so we have identified the right one! + unrollLoopCandidates.add(loopCandidate); + break; + } else if(!loopCandidate.getBlocks().contains(block.getDefaultSuccessor())) { + // The default successor of the conditional exits the loopCandidate - so we have identified the right one! + unrollLoopCandidates.add(loopCandidate); + break; + } + } + } + } + } + } + return unrollLoopCandidates; + } +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3StatementInfos.java b/src/main/java/dk/camelot64/kickc/passes/Pass3StatementInfos.java index a73715b9d..7bf99e7dd 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3StatementInfos.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3StatementInfos.java @@ -1,7 +1,8 @@ package dk.camelot64.kickc.passes; -import dk.camelot64.kickc.model.*; +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementInfos; import dk.camelot64.kickc.model.values.LabelRef; @@ -11,16 +12,18 @@ import java.util.LinkedHashMap; /** * Identify the block for each statement. */ -public class Pass3StatementInfos extends Pass2Base { +public class Pass3StatementInfos extends Pass2SsaOptimization { public Pass3StatementInfos(Program program) { super(program); } + /** * Create map from statement index to block */ - public void generateStatementInfos() { + @Override + public boolean step() { LinkedHashMap stmtBlocks = new LinkedHashMap<>(); LinkedHashMap stmtIdx = new LinkedHashMap<>(); for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { @@ -30,6 +33,7 @@ public class Pass3StatementInfos extends Pass2Base { } } getProgram().setStatementInfos(new StatementInfos(getProgram(), stmtBlocks, stmtIdx)); + return false; } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedVars.java b/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedVars.java index 230e809a0..fa6a88fd6 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedVars.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedVars.java @@ -24,8 +24,8 @@ public class PassNEliminateUnusedVars extends Pass2SsaOptimization { @Override public boolean step() { - new PassNStatementIndices(getProgram()).generateStatementIndices(); - new PassNVariableReferenceInfos(getProgram()).generateVariableReferenceInfos(); + new PassNStatementIndices(getProgram()).execute(); + new PassNVariableReferenceInfos(getProgram()).execute(); VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos(); boolean modified = false; for(ControlFlowBlock block : getGraph().getAllBlocks()) { diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNStatementIndices.java b/src/main/java/dk/camelot64/kickc/passes/PassNStatementIndices.java index 19d890854..53a355118 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNStatementIndices.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNStatementIndices.java @@ -8,22 +8,25 @@ import dk.camelot64.kickc.model.ControlFlowBlock; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; -public class PassNStatementIndices extends Pass2Base { +public class PassNStatementIndices extends Pass2SsaOptimization { public PassNStatementIndices(Program program) { super(program); } + /** * Create index numbers for all statements in the control flow graph. */ - public void generateStatementIndices() { + @Override + public boolean step() { int currentIdx = 0; for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { for(Statement statement : block.getStatements()) { statement.setIndex(currentIdx++); } } + return false; } /** diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNVariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/passes/PassNVariableReferenceInfos.java index a8e07a3e7..d678332af 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNVariableReferenceInfos.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNVariableReferenceInfos.java @@ -17,62 +17,15 @@ import java.util.*; /** * Identify variables defined/referenced for each block & statement. */ -public class PassNVariableReferenceInfos extends Pass2Base { +public class PassNVariableReferenceInfos extends Pass2SsaOptimization { public PassNVariableReferenceInfos(Program program) { super(program); } - /** - * Get all variables referenced in an rValue - * - * @param rValue The rValue - * @return All referenced variables - */ - public static Collection getReferencedVars(RValue rValue) { - LinkedHashSet referencedVars = new LinkedHashSet<>(); - for(SymbolRef symbolRef : getReferenced(rValue)) { - if(symbolRef instanceof VariableRef) { - referencedVars.add((VariableRef) symbolRef); - } - } - return referencedVars; - } - - /** - * Get all constants referenced in an rValue - * - * @param rValue The rValue - * @return All referenced constants - */ - public static Collection getReferencedConsts(RValue rValue) { - LinkedHashSet referencedConsts = new LinkedHashSet<>(); - for(SymbolRef symbolRef : getReferenced(rValue)) { - if(symbolRef instanceof ConstantRef) { - referencedConsts.add((ConstantRef) symbolRef); - } - } - return referencedConsts; - } - - /** - * Get all variables /constants referenced in an rValue - * - * @param rValue The rValue - * @return All referenced variables / constants - */ - private static Collection getReferenced(RValue rValue) { - Collection referenced = new LinkedHashSet<>(); - ProgramValueIterator.execute(new ProgramValue.GenericValue(rValue), (programValue, currentStmt, stmtIt, currentBlock) -> { - if(programValue.get() instanceof SymbolVariableRef) { - referenced.add((SymbolVariableRef) programValue.get()); - } - }, null, null, null); - return referenced; - } - /** Create defined/referenced maps */ - public void generateVariableReferenceInfos() { + @Override + public boolean step() { LinkedHashMap> blockReferencedVars = new LinkedHashMap<>(); LinkedHashMap> blockUsedVars = new LinkedHashMap<>(); LinkedHashMap> stmtReferenced = new LinkedHashMap<>(); @@ -128,6 +81,56 @@ public class PassNVariableReferenceInfos extends Pass2Base { }); } getProgram().setVariableReferenceInfos(new VariableReferenceInfos(blockReferencedVars, blockUsedVars, stmtReferenced, stmtDefined, symbolVarReferences)); + return false; + } + + + /** + * Get all variables referenced in an rValue + * + * @param rValue The rValue + * @return All referenced variables + */ + public static Collection getReferencedVars(RValue rValue) { + LinkedHashSet referencedVars = new LinkedHashSet<>(); + for(SymbolRef symbolRef : getReferenced(rValue)) { + if(symbolRef instanceof VariableRef) { + referencedVars.add((VariableRef) symbolRef); + } + } + return referencedVars; + } + + /** + * Get all constants referenced in an rValue + * + * @param rValue The rValue + * @return All referenced constants + */ + public static Collection getReferencedConsts(RValue rValue) { + LinkedHashSet referencedConsts = new LinkedHashSet<>(); + for(SymbolRef symbolRef : getReferenced(rValue)) { + if(symbolRef instanceof ConstantRef) { + referencedConsts.add((ConstantRef) symbolRef); + } + } + return referencedConsts; + } + + /** + * Get all variables /constants referenced in an rValue + * + * @param rValue The rValue + * @return All referenced variables / constants + */ + private static Collection getReferenced(RValue rValue) { + Collection referenced = new LinkedHashSet<>(); + ProgramValueIterator.execute(new ProgramValue.GenericValue(rValue), (programValue, currentStmt, stmtIt, currentBlock) -> { + if(programValue.get() instanceof SymbolVariableRef) { + referenced.add((SymbolVariableRef) programValue.get()); + } + }, null, null, null); + return referenced; } /** diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index f62fc2532..2c4db87ae 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -46,10 +46,20 @@ public class TestPrograms { AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false); } -// @Test -// public void testUnrollScreenFill() throws IOException, URISyntaxException { -// compileAndCompare("unroll-screenfill"); -// } + @Test + public void testUnusedBlockProblem() throws IOException, URISyntaxException { + compileAndCompare("unusedblockproblem"); + } + + @Test + public void testUnrollScreenFill() throws IOException, URISyntaxException { + compileAndCompare("unroll-screenfill"); + } + + @Test + public void testLoop100() throws IOException, URISyntaxException { + compileAndCompare("loop100"); + } @Test public void testIrqHardwareClobberJsr() throws IOException, URISyntaxException { diff --git a/src/test/java/dk/camelot64/kickc/test/kc/loop100.kc b/src/test/java/dk/camelot64/kickc/test/kc/loop100.kc new file mode 100644 index 000000000..2761e4fb8 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/kc/loop100.kc @@ -0,0 +1,4 @@ + +void main() { + for(byte i=0; i<100; i++) { } +} \ No newline at end of file diff --git a/src/test/java/dk/camelot64/kickc/test/kc/unroll-screenfill.kc b/src/test/java/dk/camelot64/kickc/test/kc/unroll-screenfill.kc index 22a8db7ff..6acb5333c 100644 --- a/src/test/java/dk/camelot64/kickc/test/kc/unroll-screenfill.kc +++ b/src/test/java/dk/camelot64/kickc/test/kc/unroll-screenfill.kc @@ -2,9 +2,34 @@ void main() { byte* SCREEN = $400; + + byte a=3; + inline do { + SCREEN[a]=a; + a++; + } while(a<14); + SCREEN[a]=a; + + + +/* for(byte x: 0..39) { + inline for(byte line: 0..24) { (SCREEN+line*40)[x] = x; } + } + */ + +/* + for(byte x: 0..39) { + byte line = 0; + inline while(line!=25 || x<10) { + (SCREEN+line*40)[x] = x; + line++; + } + } + */ + } \ No newline at end of file diff --git a/src/test/java/dk/camelot64/kickc/test/kc/unusedblockproblem.kc b/src/test/java/dk/camelot64/kickc/test/kc/unusedblockproblem.kc new file mode 100644 index 000000000..05fe301f6 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/kc/unusedblockproblem.kc @@ -0,0 +1,11 @@ +// Problem with eliminating unused blocks/vars after the infinite loop (symbol line#2 not removed from symbol table) + +void main() { + byte* SCREEN = $400; + while(true) { + (*SCREEN)++; + } + for(byte line: 0..24) { + SCREEN[line] = line; + } +} \ No newline at end of file