mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-23 23:32:55 +00:00
Implemented a bunch of the foundation needed for function pointers - incl. the parser and handling of pointers in zeropage variables.
This commit is contained in:
parent
de8c42eba8
commit
3434a695d2
4
src/main/fragment/pprz1=pprc1.asm
Normal file
4
src/main/fragment/pprz1=pprc1.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda #<{c1}
|
||||
sta {z1}
|
||||
lda #>{c1}
|
||||
sta {z1}+1
|
@ -90,7 +90,7 @@ typeDecl
|
||||
|
||||
expr
|
||||
: '(' expr ')' #exprPar
|
||||
| NAME '(' parameterList? ')' #exprCall
|
||||
| expr '(' parameterList? ')' #exprCall
|
||||
| expr '[' expr ']' #exprArray
|
||||
| '(' typeDecl ')' expr #exprCast
|
||||
| ('--' | '++' ) expr #exprPreMod
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
@ -2309,7 +2309,9 @@ public class KickCParser extends Parser {
|
||||
}
|
||||
}
|
||||
public static class ExprCallContext extends ExprContext {
|
||||
public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); }
|
||||
public ExprContext expr() {
|
||||
return getRuleContext(ExprContext.class,0);
|
||||
}
|
||||
public ParameterListContext parameterList() {
|
||||
return getRuleContext(ParameterListContext.class,0);
|
||||
}
|
||||
@ -2481,9 +2483,9 @@ public class KickCParser extends Parser {
|
||||
int _alt;
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(352);
|
||||
setState(346);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,36,_ctx) ) {
|
||||
switch ( getInterpreter().adaptivePredict(_input,35,_ctx) ) {
|
||||
case 1:
|
||||
{
|
||||
_localctx = new ExprParContext(_localctx);
|
||||
@ -2500,48 +2502,25 @@ public class KickCParser extends Parser {
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
_localctx = new ExprCallContext(_localctx);
|
||||
_localctx = new ExprCastContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(317);
|
||||
match(NAME);
|
||||
setState(318);
|
||||
match(T__3);
|
||||
setState(320);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__5) | (1L << T__27) | (1L << T__30) | (1L << T__31) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__41) | (1L << T__42))) != 0) || ((((_la - 75)) & ~0x3f) == 0 && ((1L << (_la - 75)) & ((1L << (STRING - 75)) | (1L << (CHAR - 75)) | (1L << (BOOLEAN - 75)) | (1L << (NUMBER - 75)) | (1L << (NAME - 75)))) != 0)) {
|
||||
{
|
||||
setState(319);
|
||||
parameterList();
|
||||
}
|
||||
}
|
||||
|
||||
setState(322);
|
||||
setState(318);
|
||||
typeDecl(0);
|
||||
setState(319);
|
||||
match(T__4);
|
||||
setState(320);
|
||||
expr(23);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
_localctx = new ExprCastContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(323);
|
||||
match(T__3);
|
||||
setState(324);
|
||||
typeDecl(0);
|
||||
setState(325);
|
||||
match(T__4);
|
||||
setState(326);
|
||||
expr(23);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
_localctx = new ExprPreModContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(328);
|
||||
setState(322);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==T__30 || _la==T__31) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -2551,27 +2530,27 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(329);
|
||||
setState(323);
|
||||
expr(22);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
case 4:
|
||||
{
|
||||
_localctx = new ExprPtrContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(330);
|
||||
setState(324);
|
||||
match(T__27);
|
||||
setState(331);
|
||||
setState(325);
|
||||
expr(20);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
case 5:
|
||||
{
|
||||
_localctx = new ExprUnaryContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(332);
|
||||
setState(326);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36))) != 0)) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -2581,16 +2560,16 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(333);
|
||||
setState(327);
|
||||
expr(19);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
case 6:
|
||||
{
|
||||
_localctx = new ExprUnaryContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(334);
|
||||
setState(328);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==T__41 || _la==T__42) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -2600,81 +2579,81 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(335);
|
||||
setState(329);
|
||||
expr(15);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
case 7:
|
||||
{
|
||||
_localctx = new InitListContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(336);
|
||||
setState(330);
|
||||
match(T__5);
|
||||
setState(337);
|
||||
setState(331);
|
||||
expr(0);
|
||||
setState(342);
|
||||
setState(336);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
while (_la==T__7) {
|
||||
{
|
||||
{
|
||||
setState(338);
|
||||
setState(332);
|
||||
match(T__7);
|
||||
setState(339);
|
||||
setState(333);
|
||||
expr(0);
|
||||
}
|
||||
}
|
||||
setState(344);
|
||||
setState(338);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
}
|
||||
setState(345);
|
||||
setState(339);
|
||||
match(T__6);
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
case 8:
|
||||
{
|
||||
_localctx = new ExprIdContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(347);
|
||||
setState(341);
|
||||
match(NAME);
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
case 9:
|
||||
{
|
||||
_localctx = new ExprNumberContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(348);
|
||||
setState(342);
|
||||
match(NUMBER);
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
case 10:
|
||||
{
|
||||
_localctx = new ExprStringContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(349);
|
||||
setState(343);
|
||||
match(STRING);
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
case 11:
|
||||
{
|
||||
_localctx = new ExprCharContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(350);
|
||||
setState(344);
|
||||
match(CHAR);
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
case 12:
|
||||
{
|
||||
_localctx = new ExprBoolContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(351);
|
||||
setState(345);
|
||||
match(BOOLEAN);
|
||||
}
|
||||
break;
|
||||
@ -2695,9 +2674,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(354);
|
||||
setState(348);
|
||||
if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)");
|
||||
setState(355);
|
||||
setState(349);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==T__37 || _la==T__38) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -2707,7 +2686,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(356);
|
||||
setState(350);
|
||||
expr(19);
|
||||
}
|
||||
break;
|
||||
@ -2715,9 +2694,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(357);
|
||||
setState(351);
|
||||
if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)");
|
||||
setState(358);
|
||||
setState(352);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__27) | (1L << T__39) | (1L << T__40))) != 0)) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -2727,7 +2706,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(359);
|
||||
setState(353);
|
||||
expr(18);
|
||||
}
|
||||
break;
|
||||
@ -2735,9 +2714,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(360);
|
||||
setState(354);
|
||||
if (!(precpred(_ctx, 16))) throw new FailedPredicateException(this, "precpred(_ctx, 16)");
|
||||
setState(361);
|
||||
setState(355);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==T__32 || _la==T__33) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -2747,7 +2726,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(362);
|
||||
setState(356);
|
||||
expr(17);
|
||||
}
|
||||
break;
|
||||
@ -2755,9 +2734,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(363);
|
||||
setState(357);
|
||||
if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)");
|
||||
setState(364);
|
||||
setState(358);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__44) | (1L << T__45) | (1L << T__46))) != 0)) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -2767,7 +2746,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(365);
|
||||
setState(359);
|
||||
expr(15);
|
||||
}
|
||||
break;
|
||||
@ -2775,13 +2754,13 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(366);
|
||||
setState(360);
|
||||
if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)");
|
||||
{
|
||||
setState(367);
|
||||
setState(361);
|
||||
match(T__35);
|
||||
}
|
||||
setState(368);
|
||||
setState(362);
|
||||
expr(14);
|
||||
}
|
||||
break;
|
||||
@ -2789,13 +2768,13 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(369);
|
||||
setState(363);
|
||||
if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)");
|
||||
{
|
||||
setState(370);
|
||||
setState(364);
|
||||
match(T__47);
|
||||
}
|
||||
setState(371);
|
||||
setState(365);
|
||||
expr(13);
|
||||
}
|
||||
break;
|
||||
@ -2803,13 +2782,13 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(372);
|
||||
setState(366);
|
||||
if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)");
|
||||
{
|
||||
setState(373);
|
||||
setState(367);
|
||||
match(T__48);
|
||||
}
|
||||
setState(374);
|
||||
setState(368);
|
||||
expr(12);
|
||||
}
|
||||
break;
|
||||
@ -2817,13 +2796,13 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(375);
|
||||
setState(369);
|
||||
if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
|
||||
{
|
||||
setState(376);
|
||||
setState(370);
|
||||
match(T__49);
|
||||
}
|
||||
setState(377);
|
||||
setState(371);
|
||||
expr(11);
|
||||
}
|
||||
break;
|
||||
@ -2831,13 +2810,13 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(378);
|
||||
setState(372);
|
||||
if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
|
||||
{
|
||||
setState(379);
|
||||
setState(373);
|
||||
match(T__50);
|
||||
}
|
||||
setState(380);
|
||||
setState(374);
|
||||
expr(10);
|
||||
}
|
||||
break;
|
||||
@ -2845,11 +2824,11 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprAssignmentContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(381);
|
||||
setState(375);
|
||||
if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)");
|
||||
setState(382);
|
||||
setState(376);
|
||||
match(T__1);
|
||||
setState(383);
|
||||
setState(377);
|
||||
expr(8);
|
||||
}
|
||||
break;
|
||||
@ -2857,9 +2836,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprAssignmentCompoundContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(384);
|
||||
setState(378);
|
||||
if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
|
||||
setState(385);
|
||||
setState(379);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__51) | (1L << T__52) | (1L << T__53) | (1L << T__54) | (1L << T__55) | (1L << T__56) | (1L << T__57) | (1L << T__58) | (1L << T__59) | (1L << T__60))) != 0)) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -2869,11 +2848,33 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(386);
|
||||
setState(380);
|
||||
expr(7);
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
{
|
||||
_localctx = new ExprCallContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(381);
|
||||
if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)");
|
||||
setState(382);
|
||||
match(T__3);
|
||||
setState(384);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__5) | (1L << T__27) | (1L << T__30) | (1L << T__31) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__41) | (1L << T__42))) != 0) || ((((_la - 75)) & ~0x3f) == 0 && ((1L << (_la - 75)) & ((1L << (STRING - 75)) | (1L << (CHAR - 75)) | (1L << (BOOLEAN - 75)) | (1L << (NUMBER - 75)) | (1L << (NAME - 75)))) != 0)) {
|
||||
{
|
||||
setState(383);
|
||||
parameterList();
|
||||
}
|
||||
}
|
||||
|
||||
setState(386);
|
||||
match(T__4);
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
{
|
||||
_localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
@ -2887,7 +2888,7 @@ public class KickCParser extends Parser {
|
||||
match(T__29);
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
case 14:
|
||||
{
|
||||
_localctx = new ExprPostModContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
@ -4342,21 +4343,23 @@ public class KickCParser extends Parser {
|
||||
case 13:
|
||||
return precpred(_ctx, 7);
|
||||
case 14:
|
||||
return precpred(_ctx, 24);
|
||||
return precpred(_ctx, 25);
|
||||
case 15:
|
||||
return precpred(_ctx, 24);
|
||||
case 16:
|
||||
return precpred(_ctx, 21);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private boolean asmExpr_sempred(AsmExprContext _localctx, int predIndex) {
|
||||
switch (predIndex) {
|
||||
case 16:
|
||||
return precpred(_ctx, 10);
|
||||
case 17:
|
||||
return precpred(_ctx, 9);
|
||||
return precpred(_ctx, 10);
|
||||
case 18:
|
||||
return precpred(_ctx, 7);
|
||||
return precpred(_ctx, 9);
|
||||
case 19:
|
||||
return precpred(_ctx, 7);
|
||||
case 20:
|
||||
return precpred(_ctx, 6);
|
||||
}
|
||||
return true;
|
||||
@ -4388,12 +4391,12 @@ public class KickCParser extends Parser {
|
||||
"\20\3\20\3\20\3\20\3\20\3\20\3\20\5\20\u011f\n\20\3\21\3\21\3\21\3\21"+
|
||||
"\3\21\3\21\3\21\3\21\5\21\u0129\n\21\3\21\3\21\3\21\3\21\3\21\5\21\u0130"+
|
||||
"\n\21\3\21\3\21\3\21\3\21\7\21\u0136\n\21\f\21\16\21\u0139\13\21\3\22"+
|
||||
"\3\22\3\22\3\22\3\22\3\22\3\22\3\22\5\22\u0143\n\22\3\22\3\22\3\22\3\22"+
|
||||
"\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22"+
|
||||
"\7\22\u0157\n\22\f\22\16\22\u015a\13\22\3\22\3\22\3\22\3\22\3\22\3\22"+
|
||||
"\3\22\5\22\u0163\n\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22"+
|
||||
"\3\22\3\22\3\22\3\22\3\22\3\22\3\22\7\22\u0151\n\22\f\22\16\22\u0154\13"+
|
||||
"\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\5\22\u015d\n\22\3\22\3\22\3\22"+
|
||||
"\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22"+
|
||||
"\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22"+
|
||||
"\3\22\3\22\3\22\3\22\3\22\5\22\u0183\n\22\3\22\3\22\3\22\3\22\3\22\3\22"+
|
||||
"\3\22\3\22\7\22\u018d\n\22\f\22\16\22\u0190\13\22\3\23\3\23\3\23\7\23"+
|
||||
"\u0195\n\23\f\23\16\23\u0198\13\23\3\24\3\24\5\24\u019c\n\24\3\24\3\24"+
|
||||
"\3\25\3\25\3\25\3\25\7\25\u01a4\n\25\f\25\16\25\u01a7\13\25\3\25\3\25"+
|
||||
@ -4411,7 +4414,7 @@ public class KickCParser extends Parser {
|
||||
"?\4\2#$,-\4\2\36\36**\2\u0268\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"+
|
||||
"\u008c\3\2\2\2\26\u00aa\3\2\2\2\30\u00ad\3\2\2\2\32\u00fe\3\2\2\2\34\u0103"+
|
||||
"\3\2\2\2\36\u011e\3\2\2\2 \u0128\3\2\2\2\"\u0162\3\2\2\2$\u0191\3\2\2"+
|
||||
"\3\2\2\2\36\u011e\3\2\2\2 \u0128\3\2\2\2\"\u015c\3\2\2\2$\u0191\3\2\2"+
|
||||
"\2&\u0199\3\2\2\2(\u019f\3\2\2\2*\u01b9\3\2\2\2,\u01be\3\2\2\2.\u01c4"+
|
||||
"\3\2\2\2\60\u01cd\3\2\2\2\62\u01cf\3\2\2\2\64\u01d3\3\2\2\2\66\u01f3\3"+
|
||||
"\2\2\28\u0203\3\2\2\2:;\5\6\4\2;<\5\n\6\2<=\7\2\2\3=\3\3\2\2\2>?\5,\27"+
|
||||
@ -4492,51 +4495,51 @@ public class KickCParser extends Parser {
|
||||
"\u012c\3\2\2\2\u0135\u0132\3\2\2\2\u0136\u0139\3\2\2\2\u0137\u0135\3\2"+
|
||||
"\2\2\u0137\u0138\3\2\2\2\u0138!\3\2\2\2\u0139\u0137\3\2\2\2\u013a\u013b"+
|
||||
"\b\22\1\2\u013b\u013c\7\6\2\2\u013c\u013d\5\"\22\2\u013d\u013e\7\7\2\2"+
|
||||
"\u013e\u0163\3\2\2\2\u013f\u0140\7Y\2\2\u0140\u0142\7\6\2\2\u0141\u0143"+
|
||||
"\5$\23\2\u0142\u0141\3\2\2\2\u0142\u0143\3\2\2\2\u0143\u0144\3\2\2\2\u0144"+
|
||||
"\u0163\7\7\2\2\u0145\u0146\7\6\2\2\u0146\u0147\5 \21\2\u0147\u0148\7\7"+
|
||||
"\2\2\u0148\u0149\5\"\22\31\u0149\u0163\3\2\2\2\u014a\u014b\t\2\2\2\u014b"+
|
||||
"\u0163\5\"\22\30\u014c\u014d\7\36\2\2\u014d\u0163\5\"\22\26\u014e\u014f"+
|
||||
"\t\3\2\2\u014f\u0163\5\"\22\25\u0150\u0151\t\4\2\2\u0151\u0163\5\"\22"+
|
||||
"\21\u0152\u0153\7\b\2\2\u0153\u0158\5\"\22\2\u0154\u0155\7\n\2\2\u0155"+
|
||||
"\u0157\5\"\22\2\u0156\u0154\3\2\2\2\u0157\u015a\3\2\2\2\u0158\u0156\3"+
|
||||
"\2\2\2\u0158\u0159\3\2\2\2\u0159\u015b\3\2\2\2\u015a\u0158\3\2\2\2\u015b"+
|
||||
"\u015c\7\t\2\2\u015c\u0163\3\2\2\2\u015d\u0163\7Y\2\2\u015e\u0163\7P\2"+
|
||||
"\2\u015f\u0163\7M\2\2\u0160\u0163\7N\2\2\u0161\u0163\7O\2\2\u0162\u013a"+
|
||||
"\3\2\2\2\u0162\u013f\3\2\2\2\u0162\u0145\3\2\2\2\u0162\u014a\3\2\2\2\u0162"+
|
||||
"\u014c\3\2\2\2\u0162\u014e\3\2\2\2\u0162\u0150\3\2\2\2\u0162\u0152\3\2"+
|
||||
"\2\2\u0162\u015d\3\2\2\2\u0162\u015e\3\2\2\2\u0162\u015f\3\2\2\2\u0162"+
|
||||
"\u0160\3\2\2\2\u0162\u0161\3\2\2\2\u0163\u018e\3\2\2\2\u0164\u0165\f\24"+
|
||||
"\2\2\u0165\u0166\t\5\2\2\u0166\u018d\5\"\22\25\u0167\u0168\f\23\2\2\u0168"+
|
||||
"\u0169\t\6\2\2\u0169\u018d\5\"\22\24\u016a\u016b\f\22\2\2\u016b\u016c"+
|
||||
"\t\7\2\2\u016c\u018d\5\"\22\23\u016d\u016e\f\20\2\2\u016e\u016f\t\b\2"+
|
||||
"\2\u016f\u018d\5\"\22\21\u0170\u0171\f\17\2\2\u0171\u0172\7&\2\2\u0172"+
|
||||
"\u018d\5\"\22\20\u0173\u0174\f\16\2\2\u0174\u0175\7\62\2\2\u0175\u018d"+
|
||||
"\5\"\22\17\u0176\u0177\f\r\2\2\u0177\u0178\7\63\2\2\u0178\u018d\5\"\22"+
|
||||
"\16\u0179\u017a\f\f\2\2\u017a\u017b\7\64\2\2\u017b\u018d\5\"\22\r\u017c"+
|
||||
"\u017d\f\13\2\2\u017d\u017e\7\65\2\2\u017e\u018d\5\"\22\f\u017f\u0180"+
|
||||
"\f\n\2\2\u0180\u0181\7\4\2\2\u0181\u018d\5\"\22\n\u0182\u0183\f\t\2\2"+
|
||||
"\u0183\u0184\t\t\2\2\u0184\u018d\5\"\22\t\u0185\u0186\f\32\2\2\u0186\u0187"+
|
||||
"\7\37\2\2\u0187\u0188\5\"\22\2\u0188\u0189\7 \2\2\u0189\u018d\3\2\2\2"+
|
||||
"\u018a\u018b\f\27\2\2\u018b\u018d\t\2\2\2\u018c\u0164\3\2\2\2\u018c\u0167"+
|
||||
"\3\2\2\2\u018c\u016a\3\2\2\2\u018c\u016d\3\2\2\2\u018c\u0170\3\2\2\2\u018c"+
|
||||
"\u0173\3\2\2\2\u018c\u0176\3\2\2\2\u018c\u0179\3\2\2\2\u018c\u017c\3\2"+
|
||||
"\2\2\u018c\u017f\3\2\2\2\u018c\u0182\3\2\2\2\u018c\u0185\3\2\2\2\u018c"+
|
||||
"\u018a\3\2\2\2\u018d\u0190\3\2\2\2\u018e\u018c\3\2\2\2\u018e\u018f\3\2"+
|
||||
"\2\2\u018f#\3\2\2\2\u0190\u018e\3\2\2\2\u0191\u0196\5\"\22\2\u0192\u0193"+
|
||||
"\7\n\2\2\u0193\u0195\5\"\22\2\u0194\u0192\3\2\2\2\u0195\u0198\3\2\2\2"+
|
||||
"\u0196\u0194\3\2\2\2\u0196\u0197\3\2\2\2\u0197%\3\2\2\2\u0198\u0196\3"+
|
||||
"\2\2\2\u0199\u019b\7@\2\2\u019a\u019c\5(\25\2\u019b\u019a\3\2\2\2\u019b"+
|
||||
"\u019c\3\2\2\2\u019c\u019d\3\2\2\2\u019d\u019e\7K\2\2\u019e\'\3\2\2\2"+
|
||||
"\u019f\u01a0\7\6\2\2\u01a0\u01a5\5*\26\2\u01a1\u01a2\7\n\2\2\u01a2\u01a4"+
|
||||
"\5*\26\2\u01a3\u01a1\3\2\2\2\u01a4\u01a7\3\2\2\2\u01a5\u01a3\3\2\2\2\u01a5"+
|
||||
"\u01a6\3\2\2\2\u01a6\u01a8\3\2\2\2\u01a7\u01a5\3\2\2\2\u01a8\u01a9\7\7"+
|
||||
"\2\2\u01a9)\3\2\2\2\u01aa\u01ab\7A\2\2\u01ab\u01ba\7M\2\2\u01ac\u01ad"+
|
||||
"\7B\2\2\u01ad\u01ba\7Y\2\2\u01ae\u01af\7C\2\2\u01af\u01ba\7M\2\2\u01b0"+
|
||||
"\u01b1\7D\2\2\u01b1\u01ba\5\"\22\2\u01b2\u01b3\7E\2\2\u01b3\u01ba\5\""+
|
||||
"\22\2\u01b4\u01b7\7F\2\2\u01b5\u01b8\7\17\2\2\u01b6\u01b8\5\"\22\2\u01b7"+
|
||||
"\u01b5\3\2\2\2\u01b7\u01b6\3\2\2\2\u01b8\u01ba\3\2\2\2\u01b9\u01aa\3\2"+
|
||||
"\2\2\u01b9\u01ac\3\2\2\2\u01b9\u01ae\3\2\2\2\u01b9\u01b0\3\2\2\2\u01b9"+
|
||||
"\u013e\u015d\3\2\2\2\u013f\u0140\7\6\2\2\u0140\u0141\5 \21\2\u0141\u0142"+
|
||||
"\7\7\2\2\u0142\u0143\5\"\22\31\u0143\u015d\3\2\2\2\u0144\u0145\t\2\2\2"+
|
||||
"\u0145\u015d\5\"\22\30\u0146\u0147\7\36\2\2\u0147\u015d\5\"\22\26\u0148"+
|
||||
"\u0149\t\3\2\2\u0149\u015d\5\"\22\25\u014a\u014b\t\4\2\2\u014b\u015d\5"+
|
||||
"\"\22\21\u014c\u014d\7\b\2\2\u014d\u0152\5\"\22\2\u014e\u014f\7\n\2\2"+
|
||||
"\u014f\u0151\5\"\22\2\u0150\u014e\3\2\2\2\u0151\u0154\3\2\2\2\u0152\u0150"+
|
||||
"\3\2\2\2\u0152\u0153\3\2\2\2\u0153\u0155\3\2\2\2\u0154\u0152\3\2\2\2\u0155"+
|
||||
"\u0156\7\t\2\2\u0156\u015d\3\2\2\2\u0157\u015d\7Y\2\2\u0158\u015d\7P\2"+
|
||||
"\2\u0159\u015d\7M\2\2\u015a\u015d\7N\2\2\u015b\u015d\7O\2\2\u015c\u013a"+
|
||||
"\3\2\2\2\u015c\u013f\3\2\2\2\u015c\u0144\3\2\2\2\u015c\u0146\3\2\2\2\u015c"+
|
||||
"\u0148\3\2\2\2\u015c\u014a\3\2\2\2\u015c\u014c\3\2\2\2\u015c\u0157\3\2"+
|
||||
"\2\2\u015c\u0158\3\2\2\2\u015c\u0159\3\2\2\2\u015c\u015a\3\2\2\2\u015c"+
|
||||
"\u015b\3\2\2\2\u015d\u018e\3\2\2\2\u015e\u015f\f\24\2\2\u015f\u0160\t"+
|
||||
"\5\2\2\u0160\u018d\5\"\22\25\u0161\u0162\f\23\2\2\u0162\u0163\t\6\2\2"+
|
||||
"\u0163\u018d\5\"\22\24\u0164\u0165\f\22\2\2\u0165\u0166\t\7\2\2\u0166"+
|
||||
"\u018d\5\"\22\23\u0167\u0168\f\20\2\2\u0168\u0169\t\b\2\2\u0169\u018d"+
|
||||
"\5\"\22\21\u016a\u016b\f\17\2\2\u016b\u016c\7&\2\2\u016c\u018d\5\"\22"+
|
||||
"\20\u016d\u016e\f\16\2\2\u016e\u016f\7\62\2\2\u016f\u018d\5\"\22\17\u0170"+
|
||||
"\u0171\f\r\2\2\u0171\u0172\7\63\2\2\u0172\u018d\5\"\22\16\u0173\u0174"+
|
||||
"\f\f\2\2\u0174\u0175\7\64\2\2\u0175\u018d\5\"\22\r\u0176\u0177\f\13\2"+
|
||||
"\2\u0177\u0178\7\65\2\2\u0178\u018d\5\"\22\f\u0179\u017a\f\n\2\2\u017a"+
|
||||
"\u017b\7\4\2\2\u017b\u018d\5\"\22\n\u017c\u017d\f\t\2\2\u017d\u017e\t"+
|
||||
"\t\2\2\u017e\u018d\5\"\22\t\u017f\u0180\f\33\2\2\u0180\u0182\7\6\2\2\u0181"+
|
||||
"\u0183\5$\23\2\u0182\u0181\3\2\2\2\u0182\u0183\3\2\2\2\u0183\u0184\3\2"+
|
||||
"\2\2\u0184\u018d\7\7\2\2\u0185\u0186\f\32\2\2\u0186\u0187\7\37\2\2\u0187"+
|
||||
"\u0188\5\"\22\2\u0188\u0189\7 \2\2\u0189\u018d\3\2\2\2\u018a\u018b\f\27"+
|
||||
"\2\2\u018b\u018d\t\2\2\2\u018c\u015e\3\2\2\2\u018c\u0161\3\2\2\2\u018c"+
|
||||
"\u0164\3\2\2\2\u018c\u0167\3\2\2\2\u018c\u016a\3\2\2\2\u018c\u016d\3\2"+
|
||||
"\2\2\u018c\u0170\3\2\2\2\u018c\u0173\3\2\2\2\u018c\u0176\3\2\2\2\u018c"+
|
||||
"\u0179\3\2\2\2\u018c\u017c\3\2\2\2\u018c\u017f\3\2\2\2\u018c\u0185\3\2"+
|
||||
"\2\2\u018c\u018a\3\2\2\2\u018d\u0190\3\2\2\2\u018e\u018c\3\2\2\2\u018e"+
|
||||
"\u018f\3\2\2\2\u018f#\3\2\2\2\u0190\u018e\3\2\2\2\u0191\u0196\5\"\22\2"+
|
||||
"\u0192\u0193\7\n\2\2\u0193\u0195\5\"\22\2\u0194\u0192\3\2\2\2\u0195\u0198"+
|
||||
"\3\2\2\2\u0196\u0194\3\2\2\2\u0196\u0197\3\2\2\2\u0197%\3\2\2\2\u0198"+
|
||||
"\u0196\3\2\2\2\u0199\u019b\7@\2\2\u019a\u019c\5(\25\2\u019b\u019a\3\2"+
|
||||
"\2\2\u019b\u019c\3\2\2\2\u019c\u019d\3\2\2\2\u019d\u019e\7K\2\2\u019e"+
|
||||
"\'\3\2\2\2\u019f\u01a0\7\6\2\2\u01a0\u01a5\5*\26\2\u01a1\u01a2\7\n\2\2"+
|
||||
"\u01a2\u01a4\5*\26\2\u01a3\u01a1\3\2\2\2\u01a4\u01a7\3\2\2\2\u01a5\u01a3"+
|
||||
"\3\2\2\2\u01a5\u01a6\3\2\2\2\u01a6\u01a8\3\2\2\2\u01a7\u01a5\3\2\2\2\u01a8"+
|
||||
"\u01a9\7\7\2\2\u01a9)\3\2\2\2\u01aa\u01ab\7A\2\2\u01ab\u01ba\7M\2\2\u01ac"+
|
||||
"\u01ad\7B\2\2\u01ad\u01ba\7Y\2\2\u01ae\u01af\7C\2\2\u01af\u01ba\7M\2\2"+
|
||||
"\u01b0\u01b1\7D\2\2\u01b1\u01ba\5\"\22\2\u01b2\u01b3\7E\2\2\u01b3\u01ba"+
|
||||
"\5\"\22\2\u01b4\u01b7\7F\2\2\u01b5\u01b8\7\17\2\2\u01b6\u01b8\5\"\22\2"+
|
||||
"\u01b7\u01b5\3\2\2\2\u01b7\u01b6\3\2\2\2\u01b8\u01ba\3\2\2\2\u01b9\u01aa"+
|
||||
"\3\2\2\2\u01b9\u01ac\3\2\2\2\u01b9\u01ae\3\2\2\2\u01b9\u01b0\3\2\2\2\u01b9"+
|
||||
"\u01b2\3\2\2\2\u01b9\u01b4\3\2\2\2\u01ba+\3\2\2\2\u01bb\u01bd\5.\30\2"+
|
||||
"\u01bc\u01bb\3\2\2\2\u01bd\u01c0\3\2\2\2\u01be\u01bc\3\2\2\2\u01be\u01bf"+
|
||||
"\3\2\2\2\u01bf-\3\2\2\2\u01c0\u01be\3\2\2\2\u01c1\u01c5\5\60\31\2\u01c2"+
|
||||
@ -4571,7 +4574,7 @@ public class KickCParser extends Parser {
|
||||
"\2\2\u0213\u0211\3\2\2\2\u0213\u0214\3\2\2\2\u02149\3\2\2\2\u0215\u0213"+
|
||||
"\3\2\2\28DMRW^dkrx}\u0086\u008c\u0093\u00a8\u00aa\u00af\u00b4\u00c1\u00c6"+
|
||||
"\u00d2\u00e0\u00e6\u00ee\u00f7\u00fe\u0103\u0107\u010c\u0112\u011e\u0128"+
|
||||
"\u012f\u0135\u0137\u0142\u0158\u0162\u018c\u018e\u0196\u019b\u01a5\u01b7"+
|
||||
"\u012f\u0135\u0137\u0152\u015c\u0182\u018c\u018e\u0196\u019b\u01a5\u01b7"+
|
||||
"\u01b9\u01be\u01c4\u01ca\u01cd\u01d1\u01d9\u01f3\u0203\u0211\u0213";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
|
||||
|
||||
|
@ -1119,6 +1119,14 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public Object visitExprCall(KickCParser.ExprCallContext ctx) {
|
||||
|
||||
String procedureName;
|
||||
if(ctx.expr() instanceof KickCParser.ExprIdContext) {
|
||||
procedureName = ctx.expr().getText();
|
||||
} else {
|
||||
throw new CompileError("Function pointer calls not supported.", new StatementSource(ctx));
|
||||
}
|
||||
|
||||
List<RValue> parameters;
|
||||
KickCParser.ParameterListContext parameterList = ctx.parameterList();
|
||||
if(parameterList != null) {
|
||||
@ -1128,7 +1136,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
}
|
||||
VariableIntermediate tmpVar = getCurrentScope().addVariableIntermediate();
|
||||
VariableRef tmpVarRef = tmpVar.getRef();
|
||||
sequence.addStatement(new StatementCall(tmpVarRef, ctx.NAME().getText(), parameters, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx))));
|
||||
sequence.addStatement(new StatementCall(tmpVarRef, procedureName, parameters, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx))));
|
||||
return tmpVarRef;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,21 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoarg3() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoarg2() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoarg() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoopBreakContinue() throws IOException, URISyntaxException {
|
||||
compileAndCompare("loop-break-continue");
|
||||
|
25
src/test/kc/function-pointer-noarg-2.kc
Normal file
25
src/test/kc/function-pointer-noarg-2.kc
Normal file
@ -0,0 +1,25 @@
|
||||
// Tests creating and assigning pointers to non-args no-return functions
|
||||
|
||||
void main() {
|
||||
const byte* SCREEN = $400;
|
||||
|
||||
void()* f;
|
||||
|
||||
for ( byte i: 0..100) {
|
||||
if((i&1)==0) {
|
||||
f = &fn1;
|
||||
} else {
|
||||
f = &fn2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
||||
void fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
}
|
35
src/test/kc/function-pointer-noarg-3.kc
Normal file
35
src/test/kc/function-pointer-noarg-3.kc
Normal file
@ -0,0 +1,35 @@
|
||||
// Tests creating and assigning pointers to non-args no-return functions - plus inline kickasm-based calling
|
||||
|
||||
void main() {
|
||||
const byte* SCREEN = $400;
|
||||
|
||||
void()* f;
|
||||
|
||||
byte i = 0;
|
||||
while(true) {
|
||||
++i;
|
||||
if((i&1)==0) {
|
||||
f = &fn1;
|
||||
} else {
|
||||
f = &fn2;
|
||||
}
|
||||
kickasm(uses f) {{
|
||||
jsr ff
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
kickasm {{
|
||||
ff:
|
||||
jmp (main.f)
|
||||
}}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
||||
void fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
}
|
24
src/test/kc/function-pointer-noarg.kc
Normal file
24
src/test/kc/function-pointer-noarg.kc
Normal file
@ -0,0 +1,24 @@
|
||||
// Tests creating pointers to non-args no-return functions
|
||||
|
||||
void main() {
|
||||
const byte* SCREEN = $400;
|
||||
|
||||
void()* f;
|
||||
f = &fn1;
|
||||
SCREEN[0] = <(word)f;
|
||||
SCREEN[1] = >(word)f;
|
||||
f = &fn2;
|
||||
SCREEN[2] = <(word)f;
|
||||
SCREEN[3] = >(word)f;
|
||||
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
||||
void fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
}
|
15
src/test/ref/function-pointer-noarg-2.asm
Normal file
15
src/test/ref/function-pointer-noarg-2.asm
Normal file
@ -0,0 +1,15 @@
|
||||
// Tests creating and assigning pointers to non-args no-return functions
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
main: {
|
||||
ldx #0
|
||||
b1:
|
||||
txa
|
||||
and #1
|
||||
cmp #0
|
||||
inx
|
||||
cpx #$65
|
||||
bne b1
|
||||
rts
|
||||
}
|
27
src/test/ref/function-pointer-noarg-2.cfg
Normal file
27
src/test/ref/function-pointer-noarg-2.cfg
Normal file
@ -0,0 +1,27 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
[5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@2/(byte) main::i#1 )
|
||||
[6] (byte~) main::$0 ← (byte) main::i#2 & (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[7] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@1
|
||||
[8] phi()
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@3
|
||||
[9] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[10] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $65) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[11] return
|
||||
to:@return
|
437
src/test/ref/function-pointer-noarg-2.log
Normal file
437
src/test/ref/function-pointer-noarg-2.log
Normal file
@ -0,0 +1,437 @@
|
||||
Resolved forward reference fn1 to (void()) fn1()
|
||||
Resolved forward reference fn2 to (void()) fn2()
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@3
|
||||
main: scope:[main] from @3
|
||||
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
|
||||
(void()*) main::f#0 ← (void()*) 0
|
||||
(byte) main::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@3/(byte) main::i#1 )
|
||||
(byte~) main::$0 ← (byte) main::i#2 & (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
(bool~) main::$1 ← (byte~) main::$0 == (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
if((bool~) main::$1) goto main::@2
|
||||
to:main::@4
|
||||
main::@2: scope:[main] from main::@1
|
||||
(byte) main::i#4 ← phi( main::@1/(byte) main::i#2 )
|
||||
(void()*~) main::$3 ← & (void()) fn1()
|
||||
(void()*) main::f#1 ← (void()*~) main::$3
|
||||
to:main::@3
|
||||
main::@4: scope:[main] from main::@1
|
||||
(byte) main::i#5 ← phi( main::@1/(byte) main::i#2 )
|
||||
(void()*~) main::$2 ← & (void()) fn2()
|
||||
(void()*) main::f#2 ← (void()*~) main::$2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@4
|
||||
(byte) main::i#3 ← phi( main::@2/(byte) main::i#4 main::@4/(byte) main::i#5 )
|
||||
(byte) main::i#1 ← (byte) main::i#3 + rangenext(0,$64)
|
||||
(bool~) main::$4 ← (byte) main::i#1 != rangelast(0,$64)
|
||||
if((bool~) main::$4) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@3
|
||||
return
|
||||
to:@return
|
||||
fn1: scope:[fn1] from
|
||||
(byte*) fn1::BORDERCOL#0 ← ((byte*)) (word/dword/signed dword) $d020
|
||||
*((byte*) fn1::BORDERCOL#0) ← ++ *((byte*) fn1::BORDERCOL#0)
|
||||
to:fn1::@return
|
||||
fn1::@return: scope:[fn1] from fn1
|
||||
return
|
||||
to:@return
|
||||
fn2: scope:[fn2] from
|
||||
(byte*) fn2::BGCOL#0 ← ((byte*)) (word/dword/signed dword) $d021
|
||||
*((byte*) fn2::BGCOL#0) ← ++ *((byte*) fn2::BGCOL#0)
|
||||
to:fn2::@return
|
||||
fn2::@return: scope:[fn2] from fn2
|
||||
return
|
||||
to:@return
|
||||
@3: scope:[] from @begin
|
||||
call main
|
||||
to:@4
|
||||
@4: scope:[] from @3
|
||||
to:@end
|
||||
@end: scope:[] from @4
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @3
|
||||
(label) @4
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) fn1()
|
||||
(label) fn1::@return
|
||||
(byte*) fn1::BORDERCOL
|
||||
(byte*) fn1::BORDERCOL#0
|
||||
(void()) fn2()
|
||||
(label) fn2::@return
|
||||
(byte*) fn2::BGCOL
|
||||
(byte*) fn2::BGCOL#0
|
||||
(void()) main()
|
||||
(byte~) main::$0
|
||||
(bool~) main::$1
|
||||
(void()*~) main::$2
|
||||
(void()*~) main::$3
|
||||
(bool~) main::$4
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@4
|
||||
(label) main::@return
|
||||
(byte*) main::SCREEN
|
||||
(byte*) main::SCREEN#0
|
||||
(void()*) main::f
|
||||
(void()*) main::f#0
|
||||
(void()*) main::f#1
|
||||
(void()*) main::f#2
|
||||
(byte) main::i
|
||||
(byte) main::i#0
|
||||
(byte) main::i#1
|
||||
(byte) main::i#2
|
||||
(byte) main::i#3
|
||||
(byte) main::i#4
|
||||
(byte) main::i#5
|
||||
|
||||
Culled Empty Block (label) @4
|
||||
Successful SSA optimization Pass2CullEmptyBlocks
|
||||
Alias (byte) main::i#2 = (byte) main::i#4 (byte) main::i#5
|
||||
Alias (void()*) main::f#1 = (void()*~) main::$3
|
||||
Alias (void()*) main::f#2 = (void()*~) main::$2
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Alias (byte) main::i#2 = (byte) main::i#3
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Simple Condition (bool~) main::$1 [6] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@2
|
||||
Simple Condition (bool~) main::$4 [16] if((byte) main::i#1!=rangelast(0,$64)) goto main::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant (const byte*) main::SCREEN#0 = ((byte*))$400
|
||||
Constant (const void()*) main::f#0 = 0
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Constant (const void()*) main::f#1 = &fn1
|
||||
Constant (const void()*) main::f#2 = &fn2
|
||||
Constant (const byte*) fn1::BORDERCOL#0 = ((byte*))$d020
|
||||
Constant (const byte*) fn2::BGCOL#0 = ((byte*))$d021
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Removing unused procedure fn1
|
||||
Removing unused procedure block fn1
|
||||
Removing unused procedure block fn1::@return
|
||||
Removing unused procedure fn2
|
||||
Removing unused procedure block fn2
|
||||
Removing unused procedure block fn2::@return
|
||||
Successful SSA optimization Pass2EliminateUnusedBlocks
|
||||
Resolved ranged next value main::i#1 ← ++ main::i#2 to ++
|
||||
Resolved ranged comparison value if(main::i#1!=rangelast(0,$64)) goto main::@1 to (byte/signed byte/word/signed word/dword/signed dword) $65
|
||||
Culled Empty Block (label) main::@2
|
||||
Successful SSA optimization Pass2CullEmptyBlocks
|
||||
Inlining constant with var siblings (const byte) main::i#0
|
||||
Constant inlined main::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Added new block during phi lifting main::@7(between main::@3 and main::@1)
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@4
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [12] main::i#6 ← main::i#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Culled Empty Block (label) main::@7
|
||||
Renumbering block @3 to @1
|
||||
Renumbering block main::@3 to main::@2
|
||||
Renumbering block main::@4 to main::@3
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@3
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
[5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@2/(byte) main::i#1 )
|
||||
[6] (byte~) main::$0 ← (byte) main::i#2 & (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[7] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@1
|
||||
[8] phi()
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@3
|
||||
[9] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[10] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $65) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[11] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(void()) main()
|
||||
(byte~) main::$0 22.0
|
||||
(byte*) main::SCREEN
|
||||
(void()*) main::f
|
||||
(byte) main::i
|
||||
(byte) main::i#1 16.5
|
||||
(byte) main::i#2 8.25
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
Added variable main::$0 to zero page equivalence class [ main::$0 ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ main::$0 ]
|
||||
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ main::$0 ]
|
||||
|
||||
INITIAL ASM
|
||||
//SEG0 File Comments
|
||||
// Tests creating and assigning pointers to non-args no-return functions
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
//SEG5 @1
|
||||
b1:
|
||||
//SEG6 [2] call main
|
||||
//SEG7 [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
//SEG9 @end
|
||||
bend:
|
||||
//SEG10 main
|
||||
main: {
|
||||
.label _0 = 3
|
||||
.label i = 2
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG13 [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
b1_from_b2:
|
||||
//SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy
|
||||
jmp b1
|
||||
//SEG15 main::@1
|
||||
b1:
|
||||
//SEG16 [6] (byte~) main::$0 ← (byte) main::i#2 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuz1=vbuz2_band_vbuc1
|
||||
lda #1
|
||||
and i
|
||||
sta _0
|
||||
//SEG17 [7] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@2 -- vbuz1_eq_0_then_la1
|
||||
lda _0
|
||||
cmp #0
|
||||
beq b2
|
||||
//SEG18 [8] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
|
||||
b3_from_b1:
|
||||
jmp b3
|
||||
//SEG19 main::@3
|
||||
b3:
|
||||
jmp b2
|
||||
//SEG20 main::@2
|
||||
b2:
|
||||
//SEG21 [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG22 [10] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $65) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #$65
|
||||
cmp i
|
||||
bne b1_from_b2
|
||||
jmp breturn
|
||||
//SEG23 main::@return
|
||||
breturn:
|
||||
//SEG24 [11] return
|
||||
rts
|
||||
}
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:3 [ main::$0 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 24.75: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 22: zp ZP_BYTE:3 [ main::$0 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 338 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$0 ]
|
||||
Uplifting [] best 338 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
// Tests creating and assigning pointers to non-args no-return functions
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
//SEG5 @1
|
||||
b1:
|
||||
//SEG6 [2] call main
|
||||
//SEG7 [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
//SEG9 @end
|
||||
bend:
|
||||
//SEG10 main
|
||||
main: {
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp b1
|
||||
//SEG13 [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
b1_from_b2:
|
||||
//SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy
|
||||
jmp b1
|
||||
//SEG15 main::@1
|
||||
b1:
|
||||
//SEG16 [6] (byte~) main::$0 ← (byte) main::i#2 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuxx_band_vbuc1
|
||||
txa
|
||||
and #1
|
||||
//SEG17 [7] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@2 -- vbuaa_eq_0_then_la1
|
||||
cmp #0
|
||||
beq b2
|
||||
//SEG18 [8] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
|
||||
b3_from_b1:
|
||||
jmp b3
|
||||
//SEG19 main::@3
|
||||
b3:
|
||||
jmp b2
|
||||
//SEG20 main::@2
|
||||
b2:
|
||||
//SEG21 [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG22 [10] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $65) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #$65
|
||||
bne b1_from_b2
|
||||
jmp breturn
|
||||
//SEG23 main::@return
|
||||
breturn:
|
||||
//SEG24 [11] return
|
||||
rts
|
||||
}
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b3
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label b1_from_b2 with b1
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction main_from_b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Removing instruction b1_from_b2:
|
||||
Removing instruction b3_from_b1:
|
||||
Removing instruction b3:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction jmp b1
|
||||
Removing instruction beq b2
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction bbegin:
|
||||
Removing instruction b2:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) main()
|
||||
(byte~) main::$0 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@return
|
||||
(byte*) main::SCREEN
|
||||
(void()*) main::f
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 16.5
|
||||
(byte) main::i#2 reg byte x 8.25
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
reg byte a [ main::$0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 151
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests creating and assigning pointers to non-args no-return functions
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
//SEG3 @begin
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
//SEG5 @1
|
||||
//SEG6 [2] call main
|
||||
//SEG7 [4] phi from @1 to main [phi:@1->main]
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
main: {
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG13 [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
//SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy
|
||||
//SEG15 main::@1
|
||||
b1:
|
||||
//SEG16 [6] (byte~) main::$0 ← (byte) main::i#2 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuxx_band_vbuc1
|
||||
txa
|
||||
and #1
|
||||
//SEG17 [7] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@2 -- vbuaa_eq_0_then_la1
|
||||
cmp #0
|
||||
//SEG18 [8] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
|
||||
//SEG19 main::@3
|
||||
//SEG20 main::@2
|
||||
//SEG21 [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG22 [10] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $65) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #$65
|
||||
bne b1
|
||||
//SEG23 main::@return
|
||||
//SEG24 [11] return
|
||||
rts
|
||||
}
|
||||
|
17
src/test/ref/function-pointer-noarg-2.sym
Normal file
17
src/test/ref/function-pointer-noarg-2.sym
Normal file
@ -0,0 +1,17 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) main()
|
||||
(byte~) main::$0 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@return
|
||||
(byte*) main::SCREEN
|
||||
(void()*) main::f
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 16.5
|
||||
(byte) main::i#2 reg byte x 8.25
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
reg byte a [ main::$0 ]
|
41
src/test/ref/function-pointer-noarg-3.asm
Normal file
41
src/test/ref/function-pointer-noarg-3.asm
Normal file
@ -0,0 +1,41 @@
|
||||
// Tests creating and assigning pointers to non-args no-return functions - plus inline kickasm-based calling
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
ff:
|
||||
jmp (main.f)
|
||||
|
||||
main: {
|
||||
.label f = 2
|
||||
ldx #0
|
||||
b2:
|
||||
inx
|
||||
txa
|
||||
and #1
|
||||
cmp #0
|
||||
beq b1
|
||||
lda #<fn2
|
||||
sta f
|
||||
lda #>fn2
|
||||
sta f+1
|
||||
jmp b3
|
||||
b1:
|
||||
lda #<fn1
|
||||
sta f
|
||||
lda #>fn1
|
||||
sta f+1
|
||||
b3:
|
||||
jsr ff
|
||||
|
||||
jmp b2
|
||||
}
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
inc BGCOL
|
||||
rts
|
||||
}
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
inc BORDERCOL
|
||||
rts
|
||||
}
|
45
src/test/ref/function-pointer-noarg-3.cfg
Normal file
45
src/test/ref/function-pointer-noarg-3.cfg
Normal file
@ -0,0 +1,45 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
kickasm() {{ ff:
|
||||
jmp (main.f)
|
||||
}}
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[4] phi()
|
||||
main: scope:[main] from @2
|
||||
[5] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
[6] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@3/(byte) main::i#1 )
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[7] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[8] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[9] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@2
|
||||
[10] phi()
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@4
|
||||
[11] (void()*) main::f#3 ← phi( main::@2/&(void()) fn1() main::@4/&(void()) fn2() )
|
||||
kickasm( uses main::f#3) {{ jsr ff
|
||||
}}
|
||||
to:main::@1
|
||||
fn2: scope:[fn2] from
|
||||
[13] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0)
|
||||
to:fn2::@return
|
||||
fn2::@return: scope:[fn2] from fn2
|
||||
[14] return
|
||||
to:@return
|
||||
fn1: scope:[fn1] from
|
||||
[15] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0)
|
||||
to:fn1::@return
|
||||
fn1::@return: scope:[fn1] from fn1
|
||||
[16] return
|
||||
to:@return
|
619
src/test/ref/function-pointer-noarg-3.log
Normal file
619
src/test/ref/function-pointer-noarg-3.log
Normal file
@ -0,0 +1,619 @@
|
||||
Resolved forward reference fn1 to (void()) fn1()
|
||||
Resolved forward reference fn2 to (void()) fn2()
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
main: scope:[main] from @3
|
||||
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
|
||||
(void()*) main::f#0 ← (void()*) 0
|
||||
(byte) main::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@5
|
||||
(byte) main::i#3 ← phi( main/(byte) main::i#0 main::@5/(byte) main::i#4 )
|
||||
if(true) goto main::@2
|
||||
to:main::@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
(byte) main::i#2 ← phi( main::@1/(byte) main::i#3 )
|
||||
(byte) main::i#1 ← ++ (byte) main::i#2
|
||||
(byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
(bool~) main::$1 ← (byte~) main::$0 == (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
if((bool~) main::$1) goto main::@4
|
||||
to:main::@8
|
||||
main::@4: scope:[main] from main::@2
|
||||
(byte) main::i#5 ← phi( main::@2/(byte) main::i#1 )
|
||||
(void()*~) main::$3 ← & (void()) fn1()
|
||||
(void()*) main::f#1 ← (void()*~) main::$3
|
||||
to:main::@5
|
||||
main::@8: scope:[main] from main::@2
|
||||
(byte) main::i#6 ← phi( main::@2/(byte) main::i#1 )
|
||||
(void()*~) main::$2 ← & (void()) fn2()
|
||||
(void()*) main::f#2 ← (void()*~) main::$2
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@4 main::@8
|
||||
(byte) main::i#4 ← phi( main::@4/(byte) main::i#5 main::@8/(byte) main::i#6 )
|
||||
(void()*) main::f#3 ← phi( main::@4/(void()*) main::f#1 main::@8/(void()*) main::f#2 )
|
||||
kickasm( uses main::f#3) {{ jsr ff
|
||||
}}
|
||||
to:main::@1
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
kickasm() {{ ff:
|
||||
jmp (main.f)
|
||||
}}
|
||||
to:@3
|
||||
fn1: scope:[fn1] from
|
||||
(byte*) fn1::BORDERCOL#0 ← ((byte*)) (word/dword/signed dword) $d020
|
||||
*((byte*) fn1::BORDERCOL#0) ← ++ *((byte*) fn1::BORDERCOL#0)
|
||||
to:fn1::@return
|
||||
fn1::@return: scope:[fn1] from fn1
|
||||
return
|
||||
to:@return
|
||||
fn2: scope:[fn2] from
|
||||
(byte*) fn2::BGCOL#0 ← ((byte*)) (word/dword/signed dword) $d021
|
||||
*((byte*) fn2::BGCOL#0) ← ++ *((byte*) fn2::BGCOL#0)
|
||||
to:fn2::@return
|
||||
fn2::@return: scope:[fn2] from fn2
|
||||
return
|
||||
to:@return
|
||||
@3: scope:[] from @1
|
||||
call main
|
||||
to:@4
|
||||
@4: scope:[] from @3
|
||||
to:@end
|
||||
@end: scope:[] from @4
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @3
|
||||
(label) @4
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) fn1()
|
||||
(label) fn1::@return
|
||||
(byte*) fn1::BORDERCOL
|
||||
(byte*) fn1::BORDERCOL#0
|
||||
(void()) fn2()
|
||||
(label) fn2::@return
|
||||
(byte*) fn2::BGCOL
|
||||
(byte*) fn2::BGCOL#0
|
||||
(void()) main()
|
||||
(byte~) main::$0
|
||||
(bool~) main::$1
|
||||
(void()*~) main::$2
|
||||
(void()*~) main::$3
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@4
|
||||
(label) main::@5
|
||||
(label) main::@8
|
||||
(label) main::@return
|
||||
(byte*) main::SCREEN
|
||||
(byte*) main::SCREEN#0
|
||||
(void()*) main::f
|
||||
(void()*) main::f#0
|
||||
(void()*) main::f#1
|
||||
(void()*) main::f#2
|
||||
(void()*) main::f#3
|
||||
(byte) main::i
|
||||
(byte) main::i#0
|
||||
(byte) main::i#1
|
||||
(byte) main::i#2
|
||||
(byte) main::i#3
|
||||
(byte) main::i#4
|
||||
(byte) main::i#5
|
||||
(byte) main::i#6
|
||||
|
||||
Culled Empty Block (label) @4
|
||||
Successful SSA optimization Pass2CullEmptyBlocks
|
||||
Alias (byte) main::i#2 = (byte) main::i#3
|
||||
Alias (byte) main::i#1 = (byte) main::i#5 (byte) main::i#6
|
||||
Alias (void()*) main::f#1 = (void()*~) main::$3
|
||||
Alias (void()*) main::f#2 = (void()*~) main::$2
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Alias (byte) main::i#1 = (byte) main::i#4
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Simple Condition (bool~) main::$1 [9] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@4
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant (const byte*) main::SCREEN#0 = ((byte*))$400
|
||||
Constant (const void()*) main::f#0 = 0
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Constant (const void()*) main::f#1 = &fn1
|
||||
Constant (const void()*) main::f#2 = &fn2
|
||||
Constant (const byte*) fn1::BORDERCOL#0 = ((byte*))$d020
|
||||
Constant (const byte*) fn2::BGCOL#0 = ((byte*))$d021
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
if() condition always true - replacing block destination [1] if(true) goto main::@2
|
||||
Successful SSA optimization Pass2ConstantIfs
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Removing unused block main::@return
|
||||
Successful SSA optimization Pass2EliminateUnusedBlocks
|
||||
Culled Empty Block (label) main::@4
|
||||
Successful SSA optimization Pass2CullEmptyBlocks
|
||||
Inlining constant with var siblings (const byte) main::i#0
|
||||
Inlining constant with var siblings (const void()*) main::f#1
|
||||
Inlining constant with var siblings (const void()*) main::f#2
|
||||
Constant inlined main::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
Constant inlined main::f#2 = &(void()) fn2()
|
||||
Constant inlined main::f#1 = &(void()) fn1()
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@8
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
|
||||
Created 2 initial phi equivalence classes
|
||||
Coalesced [13] main::i#7 ← main::i#1
|
||||
Coalesced down to 2 phi equivalence classes
|
||||
Renumbering block @3 to @2
|
||||
Renumbering block main::@5 to main::@3
|
||||
Renumbering block main::@8 to main::@4
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@4
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
kickasm() {{ ff:
|
||||
jmp (main.f)
|
||||
}}
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[4] phi()
|
||||
main: scope:[main] from @2
|
||||
[5] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
[6] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@3/(byte) main::i#1 )
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[7] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[8] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[9] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@2
|
||||
[10] phi()
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@4
|
||||
[11] (void()*) main::f#3 ← phi( main::@2/&(void()) fn1() main::@4/&(void()) fn2() )
|
||||
kickasm( uses main::f#3) {{ jsr ff
|
||||
}}
|
||||
to:main::@1
|
||||
fn2: scope:[fn2] from
|
||||
[13] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0)
|
||||
to:fn2::@return
|
||||
fn2::@return: scope:[fn2] from fn2
|
||||
[14] return
|
||||
to:@return
|
||||
fn1: scope:[fn1] from
|
||||
[15] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0)
|
||||
to:fn1::@return
|
||||
fn1::@return: scope:[fn1] from fn1
|
||||
[16] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(void()) fn1()
|
||||
(byte*) fn1::BORDERCOL
|
||||
(void()) fn2()
|
||||
(byte*) fn2::BGCOL
|
||||
(void()) main()
|
||||
(byte~) main::$0 22.0
|
||||
(byte*) main::SCREEN
|
||||
(void()*) main::f
|
||||
(void()*) main::f#3
|
||||
(byte) main::i
|
||||
(byte) main::i#1 5.5
|
||||
(byte) main::i#2 22.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ main::f#3 ]
|
||||
Added variable main::$0 to zero page equivalence class [ main::$0 ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ main::f#3 ]
|
||||
[ main::$0 ]
|
||||
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Allocated zp ZP_WORD:3 [ main::f#3 ]
|
||||
Allocated zp ZP_BYTE:5 [ main::$0 ]
|
||||
|
||||
INITIAL ASM
|
||||
//SEG0 File Comments
|
||||
// Tests creating and assigning pointers to non-args no-return functions - plus inline kickasm-based calling
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
jmp b1
|
||||
//SEG4 @1
|
||||
b1:
|
||||
//SEG5 kickasm() {{ ff: jmp (main.f) }}
|
||||
ff:
|
||||
jmp (main.f)
|
||||
|
||||
//SEG6 [2] phi from @1 to @2 [phi:@1->@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG7 @2
|
||||
b2:
|
||||
//SEG8 [3] call main
|
||||
//SEG9 [5] phi from @2 to main [phi:@2->main]
|
||||
main_from_b2:
|
||||
jsr main
|
||||
//SEG10 [4] phi from @2 to @end [phi:@2->@end]
|
||||
bend_from_b2:
|
||||
jmp bend
|
||||
//SEG11 @end
|
||||
bend:
|
||||
//SEG12 main
|
||||
main: {
|
||||
.label _0 = 5
|
||||
.label i = 2
|
||||
.label f = 3
|
||||
//SEG13 [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
//SEG14 [6] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG15 main::@1
|
||||
b1:
|
||||
jmp b2
|
||||
//SEG16 main::@2
|
||||
b2:
|
||||
//SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG18 [8] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuz1=vbuz2_band_vbuc1
|
||||
lda #1
|
||||
and i
|
||||
sta _0
|
||||
//SEG19 [9] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3 -- vbuz1_eq_0_then_la1
|
||||
lda _0
|
||||
cmp #0
|
||||
beq b3_from_b2
|
||||
//SEG20 [10] phi from main::@2 to main::@4 [phi:main::@2->main::@4]
|
||||
b4_from_b2:
|
||||
jmp b4
|
||||
//SEG21 main::@4
|
||||
b4:
|
||||
//SEG22 [11] phi from main::@4 to main::@3 [phi:main::@4->main::@3]
|
||||
b3_from_b4:
|
||||
//SEG23 [11] phi (void()*) main::f#3 = &(void()) fn2() [phi:main::@4->main::@3#0] -- pprz1=pprc1
|
||||
lda #<fn2
|
||||
sta f
|
||||
lda #>fn2
|
||||
sta f+1
|
||||
jmp b3
|
||||
//SEG24 [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
|
||||
b3_from_b2:
|
||||
//SEG25 [11] phi (void()*) main::f#3 = &(void()) fn1() [phi:main::@2->main::@3#0] -- pprz1=pprc1
|
||||
lda #<fn1
|
||||
sta f
|
||||
lda #>fn1
|
||||
sta f+1
|
||||
jmp b3
|
||||
//SEG26 main::@3
|
||||
b3:
|
||||
//SEG27 kickasm( uses main::f#3) {{ jsr ff }}
|
||||
jsr ff
|
||||
|
||||
//SEG28 [6] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
b1_from_b3:
|
||||
//SEG29 [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
//SEG30 fn2
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
//SEG31 [13] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
jmp breturn
|
||||
//SEG32 fn2::@return
|
||||
breturn:
|
||||
//SEG33 [14] return
|
||||
rts
|
||||
}
|
||||
//SEG34 fn1
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
//SEG35 [15] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BORDERCOL
|
||||
jmp breturn
|
||||
//SEG36 fn1::@return
|
||||
breturn:
|
||||
//SEG37 [16] return
|
||||
rts
|
||||
}
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_WORD:3 [ main::f#3 ] : zp ZP_WORD:3 ,
|
||||
Potential registers zp ZP_BYTE:5 [ main::$0 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 27.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 22: zp ZP_BYTE:5 [ main::$0 ] 0: zp ZP_WORD:3 [ main::f#3 ]
|
||||
Uplift Scope [fn1]
|
||||
Uplift Scope [fn2]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 3393 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$0 ] zp ZP_WORD:3 [ main::f#3 ]
|
||||
Uplifting [fn1] best 3393 combination
|
||||
Uplifting [fn2] best 3393 combination
|
||||
Uplifting [] best 3393 combination
|
||||
Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ main::f#3 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
// Tests creating and assigning pointers to non-args no-return functions - plus inline kickasm-based calling
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
jmp b1
|
||||
//SEG4 @1
|
||||
b1:
|
||||
//SEG5 kickasm() {{ ff: jmp (main.f) }}
|
||||
ff:
|
||||
jmp (main.f)
|
||||
|
||||
//SEG6 [2] phi from @1 to @2 [phi:@1->@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG7 @2
|
||||
b2:
|
||||
//SEG8 [3] call main
|
||||
//SEG9 [5] phi from @2 to main [phi:@2->main]
|
||||
main_from_b2:
|
||||
jsr main
|
||||
//SEG10 [4] phi from @2 to @end [phi:@2->@end]
|
||||
bend_from_b2:
|
||||
jmp bend
|
||||
//SEG11 @end
|
||||
bend:
|
||||
//SEG12 main
|
||||
main: {
|
||||
.label f = 2
|
||||
//SEG13 [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
//SEG14 [6] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp b1
|
||||
//SEG15 main::@1
|
||||
b1:
|
||||
jmp b2
|
||||
//SEG16 main::@2
|
||||
b2:
|
||||
//SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG18 [8] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuxx_band_vbuc1
|
||||
txa
|
||||
and #1
|
||||
//SEG19 [9] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3 -- vbuaa_eq_0_then_la1
|
||||
cmp #0
|
||||
beq b3_from_b2
|
||||
//SEG20 [10] phi from main::@2 to main::@4 [phi:main::@2->main::@4]
|
||||
b4_from_b2:
|
||||
jmp b4
|
||||
//SEG21 main::@4
|
||||
b4:
|
||||
//SEG22 [11] phi from main::@4 to main::@3 [phi:main::@4->main::@3]
|
||||
b3_from_b4:
|
||||
//SEG23 [11] phi (void()*) main::f#3 = &(void()) fn2() [phi:main::@4->main::@3#0] -- pprz1=pprc1
|
||||
lda #<fn2
|
||||
sta f
|
||||
lda #>fn2
|
||||
sta f+1
|
||||
jmp b3
|
||||
//SEG24 [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
|
||||
b3_from_b2:
|
||||
//SEG25 [11] phi (void()*) main::f#3 = &(void()) fn1() [phi:main::@2->main::@3#0] -- pprz1=pprc1
|
||||
lda #<fn1
|
||||
sta f
|
||||
lda #>fn1
|
||||
sta f+1
|
||||
jmp b3
|
||||
//SEG26 main::@3
|
||||
b3:
|
||||
//SEG27 kickasm( uses main::f#3) {{ jsr ff }}
|
||||
jsr ff
|
||||
|
||||
//SEG28 [6] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
b1_from_b3:
|
||||
//SEG29 [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
//SEG30 fn2
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
//SEG31 [13] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
jmp breturn
|
||||
//SEG32 fn2::@return
|
||||
breturn:
|
||||
//SEG33 [14] return
|
||||
rts
|
||||
}
|
||||
//SEG34 fn1
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
//SEG35 [15] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BORDERCOL
|
||||
jmp breturn
|
||||
//SEG36 fn1::@return
|
||||
breturn:
|
||||
//SEG37 [16] return
|
||||
rts
|
||||
}
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp b4
|
||||
Removing instruction jmp b3
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label b1 with b2
|
||||
Removing instruction b1:
|
||||
Removing instruction b2_from_b1:
|
||||
Removing instruction main_from_b2:
|
||||
Removing instruction bend_from_b2:
|
||||
Removing instruction b1:
|
||||
Removing instruction b4_from_b2:
|
||||
Removing instruction b3_from_b4:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction b2:
|
||||
Removing instruction bend:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction b4:
|
||||
Removing instruction b1_from_b3:
|
||||
Removing instruction breturn:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Relabelling long label b3_from_b2 to b1
|
||||
Succesful ASM optimization Pass5RelabelLongLabels
|
||||
Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) fn1()
|
||||
(label) fn1::@return
|
||||
(byte*) fn1::BORDERCOL
|
||||
(const byte*) fn1::BORDERCOL#0 BORDERCOL = ((byte*))(word/dword/signed dword) $d020
|
||||
(void()) fn2()
|
||||
(label) fn2::@return
|
||||
(byte*) fn2::BGCOL
|
||||
(const byte*) fn2::BGCOL#0 BGCOL = ((byte*))(word/dword/signed dword) $d021
|
||||
(void()) main()
|
||||
(byte~) main::$0 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@4
|
||||
(byte*) main::SCREEN
|
||||
(void()*) main::f
|
||||
(void()*) main::f#3 f zp ZP_WORD:2
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 5.5
|
||||
(byte) main::i#2 reg byte x 22.0
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:2 [ main::f#3 ]
|
||||
reg byte a [ main::$0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 3225
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests creating and assigning pointers to non-args no-return functions - plus inline kickasm-based calling
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
//SEG3 @begin
|
||||
//SEG4 @1
|
||||
//SEG5 kickasm() {{ ff: jmp (main.f) }}
|
||||
ff:
|
||||
jmp (main.f)
|
||||
|
||||
//SEG6 [2] phi from @1 to @2 [phi:@1->@2]
|
||||
//SEG7 @2
|
||||
//SEG8 [3] call main
|
||||
//SEG9 [5] phi from @2 to main [phi:@2->main]
|
||||
//SEG10 [4] phi from @2 to @end [phi:@2->@end]
|
||||
//SEG11 @end
|
||||
//SEG12 main
|
||||
main: {
|
||||
.label f = 2
|
||||
//SEG13 [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
//SEG14 [6] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG15 main::@1
|
||||
//SEG16 main::@2
|
||||
b2:
|
||||
//SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG18 [8] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuxx_band_vbuc1
|
||||
txa
|
||||
and #1
|
||||
//SEG19 [9] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3 -- vbuaa_eq_0_then_la1
|
||||
cmp #0
|
||||
beq b1
|
||||
//SEG20 [10] phi from main::@2 to main::@4 [phi:main::@2->main::@4]
|
||||
//SEG21 main::@4
|
||||
//SEG22 [11] phi from main::@4 to main::@3 [phi:main::@4->main::@3]
|
||||
//SEG23 [11] phi (void()*) main::f#3 = &(void()) fn2() [phi:main::@4->main::@3#0] -- pprz1=pprc1
|
||||
lda #<fn2
|
||||
sta f
|
||||
lda #>fn2
|
||||
sta f+1
|
||||
jmp b3
|
||||
//SEG24 [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
|
||||
b1:
|
||||
//SEG25 [11] phi (void()*) main::f#3 = &(void()) fn1() [phi:main::@2->main::@3#0] -- pprz1=pprc1
|
||||
lda #<fn1
|
||||
sta f
|
||||
lda #>fn1
|
||||
sta f+1
|
||||
//SEG26 main::@3
|
||||
b3:
|
||||
//SEG27 kickasm( uses main::f#3) {{ jsr ff }}
|
||||
jsr ff
|
||||
|
||||
//SEG28 [6] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
//SEG29 [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
|
||||
jmp b2
|
||||
}
|
||||
//SEG30 fn2
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
//SEG31 [13] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
//SEG32 fn2::@return
|
||||
//SEG33 [14] return
|
||||
rts
|
||||
}
|
||||
//SEG34 fn1
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
//SEG35 [15] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BORDERCOL
|
||||
//SEG36 fn1::@return
|
||||
//SEG37 [16] return
|
||||
rts
|
||||
}
|
||||
|
28
src/test/ref/function-pointer-noarg-3.sym
Normal file
28
src/test/ref/function-pointer-noarg-3.sym
Normal file
@ -0,0 +1,28 @@
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) fn1()
|
||||
(label) fn1::@return
|
||||
(byte*) fn1::BORDERCOL
|
||||
(const byte*) fn1::BORDERCOL#0 BORDERCOL = ((byte*))(word/dword/signed dword) $d020
|
||||
(void()) fn2()
|
||||
(label) fn2::@return
|
||||
(byte*) fn2::BGCOL
|
||||
(const byte*) fn2::BGCOL#0 BGCOL = ((byte*))(word/dword/signed dword) $d021
|
||||
(void()) main()
|
||||
(byte~) main::$0 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@4
|
||||
(byte*) main::SCREEN
|
||||
(void()*) main::f
|
||||
(void()*) main::f#3 f zp ZP_WORD:2
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 5.5
|
||||
(byte) main::i#2 reg byte x 22.0
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:2 [ main::f#3 ]
|
||||
reg byte a [ main::$0 ]
|
26
src/test/ref/function-pointer-noarg.asm
Normal file
26
src/test/ref/function-pointer-noarg.asm
Normal file
@ -0,0 +1,26 @@
|
||||
// Tests creating pointers to non-args no-return functions
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
lda #<fn1
|
||||
sta SCREEN
|
||||
lda #>fn1
|
||||
sta SCREEN+1
|
||||
lda #<fn2
|
||||
sta SCREEN+2
|
||||
lda #>fn2
|
||||
sta SCREEN+3
|
||||
rts
|
||||
}
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
inc BGCOL
|
||||
rts
|
||||
}
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
inc BORDERCOL
|
||||
rts
|
||||
}
|
30
src/test/ref/function-pointer-noarg.cfg
Normal file
30
src/test/ref/function-pointer-noarg.cfg
Normal file
@ -0,0 +1,30 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] *((const byte*) main::SCREEN#0) ← <((word))&(void()) fn1()
|
||||
[5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← >((word))&(void()) fn1()
|
||||
[6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← <((word))&(void()) fn2()
|
||||
[7] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← >((word))&(void()) fn2()
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
to:@return
|
||||
fn2: scope:[fn2] from
|
||||
[9] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0)
|
||||
to:fn2::@return
|
||||
fn2::@return: scope:[fn2] from fn2
|
||||
[10] return
|
||||
to:@return
|
||||
fn1: scope:[fn1] from
|
||||
[11] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0)
|
||||
to:fn1::@return
|
||||
fn1::@return: scope:[fn1] from fn1
|
||||
[12] return
|
||||
to:@return
|
427
src/test/ref/function-pointer-noarg.log
Normal file
427
src/test/ref/function-pointer-noarg.log
Normal file
@ -0,0 +1,427 @@
|
||||
Resolved forward reference fn1 to (void()) fn1()
|
||||
Resolved forward reference fn2 to (void()) fn2()
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@3
|
||||
main: scope:[main] from @3
|
||||
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
|
||||
(void()*) main::f#0 ← (void()*) 0
|
||||
(void()*~) main::$0 ← & (void()) fn1()
|
||||
(void()*) main::f#1 ← (void()*~) main::$0
|
||||
(word~) main::$1 ← ((word)) (void()*) main::f#1
|
||||
(byte~) main::$2 ← < (word~) main::$1
|
||||
*((byte*) main::SCREEN#0 + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte~) main::$2
|
||||
(word~) main::$3 ← ((word)) (void()*) main::f#1
|
||||
(byte~) main::$4 ← > (word~) main::$3
|
||||
*((byte*) main::SCREEN#0 + (byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$4
|
||||
(void()*~) main::$5 ← & (void()) fn2()
|
||||
(void()*) main::f#2 ← (void()*~) main::$5
|
||||
(word~) main::$6 ← ((word)) (void()*) main::f#2
|
||||
(byte~) main::$7 ← < (word~) main::$6
|
||||
*((byte*) main::SCREEN#0 + (byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte~) main::$7
|
||||
(word~) main::$8 ← ((word)) (void()*) main::f#2
|
||||
(byte~) main::$9 ← > (word~) main::$8
|
||||
*((byte*) main::SCREEN#0 + (byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte~) main::$9
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
fn1: scope:[fn1] from
|
||||
(byte*) fn1::BORDERCOL#0 ← ((byte*)) (word/dword/signed dword) $d020
|
||||
*((byte*) fn1::BORDERCOL#0) ← ++ *((byte*) fn1::BORDERCOL#0)
|
||||
to:fn1::@return
|
||||
fn1::@return: scope:[fn1] from fn1
|
||||
return
|
||||
to:@return
|
||||
fn2: scope:[fn2] from
|
||||
(byte*) fn2::BGCOL#0 ← ((byte*)) (word/dword/signed dword) $d021
|
||||
*((byte*) fn2::BGCOL#0) ← ++ *((byte*) fn2::BGCOL#0)
|
||||
to:fn2::@return
|
||||
fn2::@return: scope:[fn2] from fn2
|
||||
return
|
||||
to:@return
|
||||
@3: scope:[] from @begin
|
||||
call main
|
||||
to:@4
|
||||
@4: scope:[] from @3
|
||||
to:@end
|
||||
@end: scope:[] from @4
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @3
|
||||
(label) @4
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) fn1()
|
||||
(label) fn1::@return
|
||||
(byte*) fn1::BORDERCOL
|
||||
(byte*) fn1::BORDERCOL#0
|
||||
(void()) fn2()
|
||||
(label) fn2::@return
|
||||
(byte*) fn2::BGCOL
|
||||
(byte*) fn2::BGCOL#0
|
||||
(void()) main()
|
||||
(void()*~) main::$0
|
||||
(word~) main::$1
|
||||
(byte~) main::$2
|
||||
(word~) main::$3
|
||||
(byte~) main::$4
|
||||
(void()*~) main::$5
|
||||
(word~) main::$6
|
||||
(byte~) main::$7
|
||||
(word~) main::$8
|
||||
(byte~) main::$9
|
||||
(label) main::@return
|
||||
(byte*) main::SCREEN
|
||||
(byte*) main::SCREEN#0
|
||||
(void()*) main::f
|
||||
(void()*) main::f#0
|
||||
(void()*) main::f#1
|
||||
(void()*) main::f#2
|
||||
|
||||
Culled Empty Block (label) @4
|
||||
Successful SSA optimization Pass2CullEmptyBlocks
|
||||
Alias (void()*) main::f#1 = (void()*~) main::$0
|
||||
Alias (void()*) main::f#2 = (void()*~) main::$5
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Constant (const byte*) main::SCREEN#0 = ((byte*))$400
|
||||
Constant (const void()*) main::f#0 = 0
|
||||
Constant (const void()*) main::f#1 = &fn1
|
||||
Constant (const void()*) main::f#2 = &fn2
|
||||
Constant (const byte*) fn1::BORDERCOL#0 = ((byte*))$d020
|
||||
Constant (const byte*) fn2::BGCOL#0 = ((byte*))$d021
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const word) main::$1 = ((word))main::f#1
|
||||
Constant (const word) main::$3 = ((word))main::f#1
|
||||
Constant (const word) main::$6 = ((word))main::f#2
|
||||
Constant (const word) main::$8 = ((word))main::f#2
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const byte) main::$2 = <main::$1
|
||||
Constant (const byte) main::$4 = >main::$3
|
||||
Constant (const byte) main::$7 = <main::$6
|
||||
Constant (const byte) main::$9 = >main::$8
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Consolidated array index constant in *(main::SCREEN#0+0)
|
||||
Consolidated array index constant in *(main::SCREEN#0+1)
|
||||
Consolidated array index constant in *(main::SCREEN#0+2)
|
||||
Consolidated array index constant in *(main::SCREEN#0+3)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Inlining constant with different constant siblings (const void()*) main::f#1
|
||||
Inlining constant with different constant siblings (const void()*) main::f#2
|
||||
Constant inlined main::$1 = ((word))&(void()) fn1()
|
||||
Constant inlined main::$2 = <((word))&(void()) fn1()
|
||||
Constant inlined main::$6 = ((word))&(void()) fn2()
|
||||
Constant inlined main::f#2 = &(void()) fn2()
|
||||
Constant inlined main::$3 = ((word))&(void()) fn1()
|
||||
Constant inlined main::$4 = >((word))&(void()) fn1()
|
||||
Constant inlined main::$9 = >((word))&(void()) fn2()
|
||||
Constant inlined main::$7 = <((word))&(void()) fn2()
|
||||
Constant inlined main::f#1 = &(void()) fn1()
|
||||
Constant inlined main::$8 = ((word))&(void()) fn2()
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Simplifying constant plus zero main::SCREEN#0+0
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Renumbering block @3 to @1
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] *((const byte*) main::SCREEN#0) ← <((word))&(void()) fn1()
|
||||
[5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← >((word))&(void()) fn1()
|
||||
[6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← <((word))&(void()) fn2()
|
||||
[7] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← >((word))&(void()) fn2()
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
to:@return
|
||||
fn2: scope:[fn2] from
|
||||
[9] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0)
|
||||
to:fn2::@return
|
||||
fn2::@return: scope:[fn2] from fn2
|
||||
[10] return
|
||||
to:@return
|
||||
fn1: scope:[fn1] from
|
||||
[11] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0)
|
||||
to:fn1::@return
|
||||
fn1::@return: scope:[fn1] from fn1
|
||||
[12] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(void()) fn1()
|
||||
(byte*) fn1::BORDERCOL
|
||||
(void()) fn2()
|
||||
(byte*) fn2::BGCOL
|
||||
(void()) main()
|
||||
(byte*) main::SCREEN
|
||||
(void()*) main::f
|
||||
|
||||
Initial phi equivalence classes
|
||||
Complete equivalence classes
|
||||
|
||||
INITIAL ASM
|
||||
//SEG0 File Comments
|
||||
// Tests creating pointers to non-args no-return functions
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
//SEG5 @1
|
||||
b1:
|
||||
//SEG6 [2] call main
|
||||
jsr main
|
||||
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
//SEG8 @end
|
||||
bend:
|
||||
//SEG9 main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
//SEG10 [4] *((const byte*) main::SCREEN#0) ← <((word))&(void()) fn1() -- _deref_pbuc1=vbuc2
|
||||
lda #<fn1
|
||||
sta SCREEN
|
||||
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← >((word))&(void()) fn1() -- _deref_pbuc1=vbuc2
|
||||
lda #>fn1
|
||||
sta SCREEN+1
|
||||
//SEG12 [6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← <((word))&(void()) fn2() -- _deref_pbuc1=vbuc2
|
||||
lda #<fn2
|
||||
sta SCREEN+2
|
||||
//SEG13 [7] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← >((word))&(void()) fn2() -- _deref_pbuc1=vbuc2
|
||||
lda #>fn2
|
||||
sta SCREEN+3
|
||||
jmp breturn
|
||||
//SEG14 main::@return
|
||||
breturn:
|
||||
//SEG15 [8] return
|
||||
rts
|
||||
}
|
||||
//SEG16 fn2
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
//SEG17 [9] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
jmp breturn
|
||||
//SEG18 fn2::@return
|
||||
breturn:
|
||||
//SEG19 [10] return
|
||||
rts
|
||||
}
|
||||
//SEG20 fn1
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
//SEG21 [11] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BORDERCOL
|
||||
jmp breturn
|
||||
//SEG22 fn1::@return
|
||||
breturn:
|
||||
//SEG23 [12] return
|
||||
rts
|
||||
}
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((const byte*) main::SCREEN#0) ← <((word))&(void()) fn1() [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← >((word))&(void()) fn1() [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← <((word))&(void()) fn2() [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← >((word))&(void()) fn2() [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope [fn1]
|
||||
Uplift Scope [fn2]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 75 combination
|
||||
Uplifting [fn1] best 75 combination
|
||||
Uplifting [fn2] best 75 combination
|
||||
Uplifting [] best 75 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
// Tests creating pointers to non-args no-return functions
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
//SEG5 @1
|
||||
b1:
|
||||
//SEG6 [2] call main
|
||||
jsr main
|
||||
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
//SEG8 @end
|
||||
bend:
|
||||
//SEG9 main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
//SEG10 [4] *((const byte*) main::SCREEN#0) ← <((word))&(void()) fn1() -- _deref_pbuc1=vbuc2
|
||||
lda #<fn1
|
||||
sta SCREEN
|
||||
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← >((word))&(void()) fn1() -- _deref_pbuc1=vbuc2
|
||||
lda #>fn1
|
||||
sta SCREEN+1
|
||||
//SEG12 [6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← <((word))&(void()) fn2() -- _deref_pbuc1=vbuc2
|
||||
lda #<fn2
|
||||
sta SCREEN+2
|
||||
//SEG13 [7] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← >((word))&(void()) fn2() -- _deref_pbuc1=vbuc2
|
||||
lda #>fn2
|
||||
sta SCREEN+3
|
||||
jmp breturn
|
||||
//SEG14 main::@return
|
||||
breturn:
|
||||
//SEG15 [8] return
|
||||
rts
|
||||
}
|
||||
//SEG16 fn2
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
//SEG17 [9] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
jmp breturn
|
||||
//SEG18 fn2::@return
|
||||
breturn:
|
||||
//SEG19 [10] return
|
||||
rts
|
||||
}
|
||||
//SEG20 fn1
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
//SEG21 [11] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BORDERCOL
|
||||
jmp breturn
|
||||
//SEG22 fn1::@return
|
||||
breturn:
|
||||
//SEG23 [12] return
|
||||
rts
|
||||
}
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction breturn:
|
||||
Removing instruction breturn:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) fn1()
|
||||
(label) fn1::@return
|
||||
(byte*) fn1::BORDERCOL
|
||||
(const byte*) fn1::BORDERCOL#0 BORDERCOL = ((byte*))(word/dword/signed dword) $d020
|
||||
(void()) fn2()
|
||||
(label) fn2::@return
|
||||
(byte*) fn2::BGCOL
|
||||
(const byte*) fn2::BGCOL#0 BGCOL = ((byte*))(word/dword/signed dword) $d021
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(byte*) main::SCREEN
|
||||
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
|
||||
(void()*) main::f
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 54
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests creating pointers to non-args no-return functions
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
//SEG3 @begin
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
//SEG5 @1
|
||||
//SEG6 [2] call main
|
||||
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG8 @end
|
||||
//SEG9 main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
//SEG10 [4] *((const byte*) main::SCREEN#0) ← <((word))&(void()) fn1() -- _deref_pbuc1=vbuc2
|
||||
lda #<fn1
|
||||
sta SCREEN
|
||||
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← >((word))&(void()) fn1() -- _deref_pbuc1=vbuc2
|
||||
lda #>fn1
|
||||
sta SCREEN+1
|
||||
//SEG12 [6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← <((word))&(void()) fn2() -- _deref_pbuc1=vbuc2
|
||||
lda #<fn2
|
||||
sta SCREEN+2
|
||||
//SEG13 [7] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← >((word))&(void()) fn2() -- _deref_pbuc1=vbuc2
|
||||
lda #>fn2
|
||||
sta SCREEN+3
|
||||
//SEG14 main::@return
|
||||
//SEG15 [8] return
|
||||
rts
|
||||
}
|
||||
//SEG16 fn2
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
//SEG17 [9] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
//SEG18 fn2::@return
|
||||
//SEG19 [10] return
|
||||
rts
|
||||
}
|
||||
//SEG20 fn1
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
//SEG21 [11] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BORDERCOL
|
||||
//SEG22 fn1::@return
|
||||
//SEG23 [12] return
|
||||
rts
|
||||
}
|
||||
|
17
src/test/ref/function-pointer-noarg.sym
Normal file
17
src/test/ref/function-pointer-noarg.sym
Normal file
@ -0,0 +1,17 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) fn1()
|
||||
(label) fn1::@return
|
||||
(byte*) fn1::BORDERCOL
|
||||
(const byte*) fn1::BORDERCOL#0 BORDERCOL = ((byte*))(word/dword/signed dword) $d020
|
||||
(void()) fn2()
|
||||
(label) fn2::@return
|
||||
(byte*) fn2::BGCOL
|
||||
(const byte*) fn2::BGCOL#0 BGCOL = ((byte*))(word/dword/signed dword) $d021
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(byte*) main::SCREEN
|
||||
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
|
||||
(void()*) main::f
|
||||
|
Loading…
Reference in New Issue
Block a user