mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-16 08:33:37 +00:00
Added support for allocating specific zeropage addresses for variables using the register(0x12) directive. This also includes function parameters making it possible to the calling convention pretty well. Closes #287
This commit is contained in:
parent
67157f0a70
commit
8c56181554
@ -37,7 +37,7 @@ public class Program {
|
||||
/** Absolute start address of the code. Null to start ad 0x080d. PASS 0-5 (STATIC) */
|
||||
private Number programPc;
|
||||
/** Reserved ZP addresses that the compiler cannot use. PASS 0-5 (STATIC) */
|
||||
private List<Number> reservedZps;
|
||||
private List<Integer> reservedZps;
|
||||
/** Resource files that should be copied to the output folder to be compiled with the generated ASM. PASS 0-5 (STATIC) */
|
||||
private List<Path> asmResourceFiles;
|
||||
/** Comments for the (main) file. PASS 0-4 (STATIC) */
|
||||
@ -398,15 +398,15 @@ public class Program {
|
||||
*
|
||||
* @param reservedZp addresses to reserve
|
||||
*/
|
||||
public void addReservedZps(List<Number> reservedZp) {
|
||||
for(Number zp : reservedZp) {
|
||||
public void addReservedZps(List<Integer> reservedZp) {
|
||||
for(Integer zp : reservedZp) {
|
||||
if(!this.reservedZps.contains(zp)) {
|
||||
this.reservedZps.add(zp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Number> getReservedZps() {
|
||||
public List<Integer> getReservedZps() {
|
||||
return reservedZps;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.values.ConstantValue;
|
||||
import dk.camelot64.kickc.model.values.Value;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
/** The different registers available for a program */
|
||||
public class Registers {
|
||||
@ -49,6 +50,7 @@ public class Registers {
|
||||
ZP_DWORD,
|
||||
ZP_STRUCT,
|
||||
ZP_BOOL,
|
||||
ZP_VAR,
|
||||
CONSTANT
|
||||
}
|
||||
|
||||
@ -97,15 +99,48 @@ public class Registers {
|
||||
if(o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RegisterZp that = (RegisterZp) o;
|
||||
|
||||
return zp == that.zp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return zp;
|
||||
return zp+31*getClass().hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A zero page address used as a register for a declared register allocation. Size is initially unknown and will be resolved when performing allocation by setting the type. */
|
||||
public static class RegisterZpDeclared extends RegisterZp {
|
||||
|
||||
private RegisterType type;
|
||||
|
||||
public RegisterZpDeclared(int zp) {
|
||||
super(zp);
|
||||
this.type = RegisterType.ZP_VAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegisterType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(RegisterType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(this == o) return true;
|
||||
if(o == null || getClass() != o.getClass()) return false;
|
||||
if(!super.equals(o)) return false;
|
||||
RegisterZpDeclared that = (RegisterZpDeclared) o;
|
||||
return type == that.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), type);
|
||||
}
|
||||
|
||||
}
|
||||
@ -186,7 +221,6 @@ public class Registers {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** A zero page address used as a register for a boolean variable. */
|
||||
public static class RegisterZpBool extends RegisterZp {
|
||||
|
||||
|
@ -24,7 +24,7 @@ public class Procedure extends Scope {
|
||||
/** Comments preceding the procedure in the source code. */
|
||||
private List<Comment> comments;
|
||||
/** Reserved zeropage addresses. */
|
||||
private List<Number> reservedZps;
|
||||
private List<Integer> reservedZps;
|
||||
/** The code segment to put the procedure into. */
|
||||
private String codeSegment;
|
||||
|
||||
@ -120,16 +120,16 @@ public class Procedure extends Scope {
|
||||
*
|
||||
* @return reserved addresses
|
||||
*/
|
||||
public List<Number> getReservedZps() {
|
||||
public List<Integer> getReservedZps() {
|
||||
return reservedZps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any reserved zero-page addresses that the compiler is not allowed to use.
|
||||
*
|
||||
* @param reservedZp reserved addresses
|
||||
* @param reservedZps reserved addresses
|
||||
*/
|
||||
public void setReservedZps(List<Number> reservedZps) {
|
||||
public void setReservedZps(List<Integer> reservedZps) {
|
||||
this.reservedZps = reservedZps;
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ directive
|
||||
| EXTERN #directiveExtern
|
||||
| EXPORT #directiveExport
|
||||
| ALIGN PAR_BEGIN NUMBER PAR_END #directiveAlign
|
||||
| REGISTER ( PAR_BEGIN NAME PAR_END)? #directiveRegister
|
||||
| REGISTER ( PAR_BEGIN ( NAME | NUMBER ) PAR_END)? #directiveRegister
|
||||
| INLINE #directiveInline
|
||||
| VOLATILE #directiveVolatile
|
||||
| INTERRUPT ( PAR_BEGIN NAME PAR_END )? #directiveInterrupt
|
||||
|
@ -1663,8 +1663,9 @@ public class KickCParser extends Parser {
|
||||
public static class DirectiveRegisterContext extends DirectiveContext {
|
||||
public TerminalNode REGISTER() { return getToken(KickCParser.REGISTER, 0); }
|
||||
public TerminalNode PAR_BEGIN() { return getToken(KickCParser.PAR_BEGIN, 0); }
|
||||
public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); }
|
||||
public TerminalNode PAR_END() { return getToken(KickCParser.PAR_END, 0); }
|
||||
public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); }
|
||||
public TerminalNode NUMBER() { return getToken(KickCParser.NUMBER, 0); }
|
||||
public DirectiveRegisterContext(DirectiveContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
@ -1741,7 +1742,15 @@ public class KickCParser extends Parser {
|
||||
setState(250);
|
||||
match(PAR_BEGIN);
|
||||
setState(251);
|
||||
match(NAME);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==NUMBER || _la==NAME) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
}
|
||||
else {
|
||||
if ( _input.LA(1)==Token.EOF ) matchedEOF = true;
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(252);
|
||||
match(PAR_END);
|
||||
}
|
||||
@ -6440,240 +6449,240 @@ public class KickCParser extends Parser {
|
||||
"\5+\u02cb\n+\3,\3,\3,\3,\3,\3,\3,\3,\3,\3,\3,\3,\3,\3,\5,\u02db\n,\3,"+
|
||||
"\3,\3,\3,\3,\3,\3,\3,\3,\3,\3,\3,\7,\u02e9\n,\f,\16,\u02ec\13,\3,\2\b"+
|
||||
"\24.:>@V-\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\66"+
|
||||
"8:<>@BDFHJLNPRTV\2\r\3\2\26\27\5\2\21\22\30\31PP\4\2 ##\3\2\34\35\3\2"+
|
||||
"\23\25\3\2\21\22\3\2\36#\3\2ps\3\2no\3\2tu\3\2pq\2\u0355\2X\3\2\2\2\4"+
|
||||
"[\3\2\2\2\6a\3\2\2\2\bf\3\2\2\2\nh\3\2\2\2\fz\3\2\2\2\16|\3\2\2\2\20\u0084"+
|
||||
"\3\2\2\2\22\u008e\3\2\2\2\24\u0091\3\2\2\2\26\u00a4\3\2\2\2\30\u00a6\3"+
|
||||
"\2\2\2\32\u00b3\3\2\2\2\34\u00bf\3\2\2\2\36\u00f2\3\2\2\2 \u0114\3\2\2"+
|
||||
"\2\"\u0117\3\2\2\2$\u016f\3\2\2\2&\u0172\3\2\2\2(\u017d\3\2\2\2*\u0193"+
|
||||
"\3\2\2\2,\u0199\3\2\2\2.\u01aa\3\2\2\2\60\u01bc\3\2\2\2\62\u01bf\3\2\2"+
|
||||
"\2\64\u01cb\3\2\2\2\66\u01ce\3\2\2\28\u01d1\3\2\2\2:\u01d9\3\2\2\2<\u01e4"+
|
||||
"\3\2\2\2>\u01e9\3\2\2\2@\u022a\3\2\2\2B\u026b\3\2\2\2D\u0273\3\2\2\2F"+
|
||||
"\u0279\3\2\2\2H\u0293\3\2\2\2J\u0298\3\2\2\2L\u029e\3\2\2\2N\u02a4\3\2"+
|
||||
"\2\2P\u02a6\3\2\2\2R\u02aa\3\2\2\2T\u02ca\3\2\2\2V\u02da\3\2\2\2XY\5\6"+
|
||||
"\4\2YZ\7\2\2\3Z\3\3\2\2\2[\\\5J&\2\\]\7\2\2\3]\5\3\2\2\2^`\5\b\5\2_^\3"+
|
||||
"\2\2\2`c\3\2\2\2a_\3\2\2\2ab\3\2\2\2b\7\3\2\2\2ca\3\2\2\2dg\5\f\7\2eg"+
|
||||
"\5\n\6\2fd\3\2\2\2fe\3\2\2\2g\t\3\2\2\2hi\7(\2\2ij\7U\2\2j\13\3\2\2\2"+
|
||||
"kl\5\22\n\2lm\7\n\2\2m{\3\2\2\2no\5\62\32\2op\7\n\2\2p{\3\2\2\2qr\58\35"+
|
||||
"\2rs\7\n\2\2s{\3\2\2\2t{\5\30\r\2u{\5D#\2v{\5\36\20\2wx\5\16\b\2xy\7\n"+
|
||||
"\2\2y{\3\2\2\2zk\3\2\2\2zn\3\2\2\2zq\3\2\2\2zt\3\2\2\2zu\3\2\2\2zv\3\2"+
|
||||
"\2\2zw\3\2\2\2{\r\3\2\2\2|}\7)\2\2}~\5.\30\2~\177\7`\2\2\177\u0080\b\b"+
|
||||
"\1\2\u0080\17\3\2\2\2\u0081\u0083\5 \21\2\u0082\u0081\3\2\2\2\u0083\u0086"+
|
||||
"\3\2\2\2\u0084\u0082\3\2\2\2\u0084\u0085\3\2\2\2\u0085\u0087\3\2\2\2\u0086"+
|
||||
"\u0084\3\2\2\2\u0087\u008b\5.\30\2\u0088\u008a\5 \21\2\u0089\u0088\3\2"+
|
||||
"\2\2\u008a\u008d\3\2\2\2\u008b\u0089\3\2\2\2\u008b\u008c\3\2\2\2\u008c"+
|
||||
"\21\3\2\2\2\u008d\u008b\3\2\2\2\u008e\u008f\5\20\t\2\u008f\u0090\5\24"+
|
||||
"\13\2\u0090\23\3\2\2\2\u0091\u0092\b\13\1\2\u0092\u0093\5\26\f\2\u0093"+
|
||||
"\u0099\3\2\2\2\u0094\u0095\f\3\2\2\u0095\u0096\7\f\2\2\u0096\u0098\5\26"+
|
||||
"\f\2\u0097\u0094\3\2\2\2\u0098\u009b\3\2\2\2\u0099\u0097\3\2\2\2\u0099"+
|
||||
"\u009a\3\2\2\2\u009a\25\3\2\2\2\u009b\u0099\3\2\2\2\u009c\u009f\7`\2\2"+
|
||||
"\u009d\u009e\7&\2\2\u009e\u00a0\5@!\2\u009f\u009d\3\2\2\2\u009f\u00a0"+
|
||||
"\3\2\2\2\u00a0\u00a5\3\2\2\2\u00a1\u00a2\7`\2\2\u00a2\u00a3\7&\2\2\u00a3"+
|
||||
"\u00a5\5D#\2\u00a4\u009c\3\2\2\2\u00a4\u00a1\3\2\2\2\u00a5\27\3\2\2\2"+
|
||||
"\u00a6\u00a7\5\20\t\2\u00a7\u00a8\7`\2\2\u00a8\u00aa\7\b\2\2\u00a9\u00ab"+
|
||||
"\5\32\16\2\u00aa\u00a9\3\2\2\2\u00aa\u00ab\3\2\2\2\u00ab\u00ac\3\2\2\2"+
|
||||
"\u00ac\u00ad\7\t\2\2\u00ad\u00af\7\4\2\2\u00ae\u00b0\5\"\22\2\u00af\u00ae"+
|
||||
"\3\2\2\2\u00af\u00b0\3\2\2\2\u00b0\u00b1\3\2\2\2\u00b1\u00b2\7\5\2\2\u00b2"+
|
||||
"\31\3\2\2\2\u00b3\u00b8\5\34\17\2\u00b4\u00b5\7\f\2\2\u00b5\u00b7\5\34"+
|
||||
"\17\2\u00b6\u00b4\3\2\2\2\u00b7\u00ba\3\2\2\2\u00b8\u00b6\3\2\2\2\u00b8"+
|
||||
"\u00b9\3\2\2\2\u00b9\33\3\2\2\2\u00ba\u00b8\3\2\2\2\u00bb\u00bc\5\20\t"+
|
||||
"\2\u00bc\u00bd\7`\2\2\u00bd\u00c0\3\2\2\2\u00be\u00c0\7R\2\2\u00bf\u00bb"+
|
||||
"\3\2\2\2\u00bf\u00be\3\2\2\2\u00c0\35\3\2\2\2\u00c1\u00c2\7*\2\2\u00c2"+
|
||||
"\u00c3\7+\2\2\u00c3\u00c4\3\2\2\2\u00c4\u00c5\7\b\2\2\u00c5\u00ca\7W\2"+
|
||||
"\2\u00c6\u00c7\7\f\2\2\u00c7\u00c9\7W\2\2\u00c8\u00c6\3\2\2\2\u00c9\u00cc"+
|
||||
"\3\2\2\2\u00ca\u00c8\3\2\2\2\u00ca\u00cb\3\2\2\2\u00cb\u00cd\3\2\2\2\u00cc"+
|
||||
"\u00ca\3\2\2\2\u00cd\u00f3\7\t\2\2\u00ce\u00cf\7*\2\2\u00cf\u00d0\7,\2"+
|
||||
"\2\u00d0\u00d1\3\2\2\2\u00d1\u00d2\7\b\2\2\u00d2\u00d3\7W\2\2\u00d3\u00f3"+
|
||||
"\7\t\2\2\u00d4\u00d5\7*\2\2\u00d5\u00d6\7-\2\2\u00d6\u00d7\3\2\2\2\u00d7"+
|
||||
"\u00d8\7\b\2\2\u00d8\u00d9\7`\2\2\u00d9\u00f3\7\t\2\2\u00da\u00db\7*\2"+
|
||||
"\2\u00db\u00dc\7.\2\2\u00dc\u00dd\3\2\2\2\u00dd\u00de\7\b\2\2\u00de\u00df"+
|
||||
"\7U\2\2\u00df\u00f3\7\t\2\2\u00e0\u00e1\7*\2\2\u00e1\u00e2\7/\2\2\u00e2"+
|
||||
"\u00e3\3\2\2\2\u00e3\u00e4\7\b\2\2\u00e4\u00e5\7`\2\2\u00e5\u00f3\7\t"+
|
||||
"\2\2\u00e6\u00e7\7*\2\2\u00e7\u00e8\7\60\2\2\u00e8\u00e9\3\2\2\2\u00e9"+
|
||||
"\u00ea\7\b\2\2\u00ea\u00eb\7`\2\2\u00eb\u00f3\7\t\2\2\u00ec\u00ed\7*\2"+
|
||||
"\2\u00ed\u00ee\7\61\2\2\u00ee\u00ef\3\2\2\2\u00ef\u00f0\7\b\2\2\u00f0"+
|
||||
"\u00f1\7`\2\2\u00f1\u00f3\7\t\2\2\u00f2\u00c1\3\2\2\2\u00f2\u00ce\3\2"+
|
||||
"\2\2\u00f2\u00d4\3\2\2\2\u00f2\u00da\3\2\2\2\u00f2\u00e0\3\2\2\2\u00f2"+
|
||||
"\u00e6\3\2\2\2\u00f2\u00ec\3\2\2\2\u00f3\37\3\2\2\2\u00f4\u0115\7\62\2"+
|
||||
"\2\u00f5\u0115\7\63\2\2\u00f6\u0115\7\64\2\2\u00f7\u00f8\7\65\2\2\u00f8"+
|
||||
"\u00f9\7\b\2\2\u00f9\u00fa\7W\2\2\u00fa\u0115\7\t\2\2\u00fb\u00ff\7\66"+
|
||||
"\2\2\u00fc\u00fd\7\b\2\2\u00fd\u00fe\7`\2\2\u00fe\u0100\7\t\2\2\u00ff"+
|
||||
"\u00fc\3\2\2\2\u00ff\u0100\3\2\2\2\u0100\u0115\3\2\2\2\u0101\u0115\7\67"+
|
||||
"\2\2\u0102\u0115\78\2\2\u0103\u0107\79\2\2\u0104\u0105\7\b\2\2\u0105\u0106"+
|
||||
"\7`\2\2\u0106\u0108\7\t\2\2\u0107\u0104\3\2\2\2\u0107\u0108\3\2\2\2\u0108"+
|
||||
"\u0115\3\2\2\2\u0109\u010a\7+\2\2\u010a\u010b\7\b\2\2\u010b\u0110\7W\2"+
|
||||
"\2\u010c\u010d\7\f\2\2\u010d\u010f\7W\2\2\u010e\u010c\3\2\2\2\u010f\u0112"+
|
||||
"\3\2\2\2\u0110\u010e\3\2\2\2\u0110\u0111\3\2\2\2\u0111\u0113\3\2\2\2\u0112"+
|
||||
"\u0110\3\2\2\2\u0113\u0115\7\t\2\2\u0114\u00f4\3\2\2\2\u0114\u00f5\3\2"+
|
||||
"\2\2\u0114\u00f6\3\2\2\2\u0114\u00f7\3\2\2\2\u0114\u00fb\3\2\2\2\u0114"+
|
||||
"\u0101\3\2\2\2\u0114\u0102\3\2\2\2\u0114\u0103\3\2\2\2\u0114\u0109\3\2"+
|
||||
"\2\2\u0115!\3\2\2\2\u0116\u0118\5$\23\2\u0117\u0116\3\2\2\2\u0118\u0119"+
|
||||
"\3\2\2\2\u0119\u0117\3\2\2\2\u0119\u011a\3\2\2\2\u011a#\3\2\2\2\u011b"+
|
||||
"\u011c\5\22\n\2\u011c\u011d\7\n\2\2\u011d\u0170\3\2\2\2\u011e\u0120\7"+
|
||||
"\4\2\2\u011f\u0121\5\"\22\2\u0120\u011f\3\2\2\2\u0120\u0121\3\2\2\2\u0121"+
|
||||
"\u0122\3\2\2\2\u0122\u0170\7\5\2\2\u0123\u0124\5> \2\u0124\u0125\7\n\2"+
|
||||
"\2\u0125\u0170\3\2\2\2\u0126\u0127\7:\2\2\u0127\u0128\7\b\2\2\u0128\u0129"+
|
||||
"\5> \2\u0129\u012a\7\t\2\2\u012a\u012d\5$\23\2\u012b\u012c\7;\2\2\u012c"+
|
||||
"\u012e\5$\23\2\u012d\u012b\3\2\2\2\u012d\u012e\3\2\2\2\u012e\u0170\3\2"+
|
||||
"\2\2\u012f\u0131\5 \21\2\u0130\u012f\3\2\2\2\u0131\u0134\3\2\2\2\u0132"+
|
||||
"\u0130\3\2\2\2\u0132\u0133\3\2\2\2\u0133\u0135\3\2\2\2\u0134\u0132\3\2"+
|
||||
"\2\2\u0135\u0136\7<\2\2\u0136\u0137\7\b\2\2\u0137\u0138\5> \2\u0138\u0139"+
|
||||
"\7\t\2\2\u0139\u013a\5$\23\2\u013a\u0170\3\2\2\2\u013b\u013d\5 \21\2\u013c"+
|
||||
"\u013b\3\2\2\2\u013d\u0140\3\2\2\2\u013e\u013c\3\2\2\2\u013e\u013f\3\2"+
|
||||
"\2\2\u013f\u0141\3\2\2\2\u0140\u013e\3\2\2\2\u0141\u0142\7=\2\2\u0142"+
|
||||
"\u0143\5$\23\2\u0143\u0144\7<\2\2\u0144\u0145\7\b\2\2\u0145\u0146\5> "+
|
||||
"\2\u0146\u0147\7\t\2\2\u0147\u0148\7\n\2\2\u0148\u0170\3\2\2\2\u0149\u014b"+
|
||||
"\5 \21\2\u014a\u0149\3\2\2\2\u014b\u014e\3\2\2\2\u014c\u014a\3\2\2\2\u014c"+
|
||||
"\u014d\3\2\2\2\u014d\u014f\3\2\2\2\u014e\u014c\3\2\2\2\u014f\u0150\7>"+
|
||||
"\2\2\u0150\u0151\7\b\2\2\u0151\u0152\5*\26\2\u0152\u0153\7\t\2\2\u0153"+
|
||||
"\u0154\5$\23\2\u0154\u0170\3\2\2\2\u0155\u0156\7?\2\2\u0156\u0157\7\b"+
|
||||
"\2\2\u0157\u0158\5> \2\u0158\u0159\7\t\2\2\u0159\u015a\7\4\2\2\u015a\u015b"+
|
||||
"\5&\24\2\u015b\u015c\7\5\2\2\u015c\u0170\3\2\2\2\u015d\u015f\7@\2\2\u015e"+
|
||||
"\u0160\5> \2\u015f\u015e\3\2\2\2\u015f\u0160\3\2\2\2\u0160\u0161\3\2\2"+
|
||||
"\2\u0161\u0170\7\n\2\2\u0162\u0163\7A\2\2\u0163\u0170\7\n\2\2\u0164\u0165"+
|
||||
"\7B\2\2\u0165\u0170\7\n\2\2\u0166\u0168\7C\2\2\u0167\u0169\5F$\2\u0168"+
|
||||
"\u0167\3\2\2\2\u0168\u0169\3\2\2\2\u0169\u016a\3\2\2\2\u016a\u016b\7\4"+
|
||||
"\2\2\u016b\u016c\5J&\2\u016c\u016d\7w\2\2\u016d\u0170\3\2\2\2\u016e\u0170"+
|
||||
"\5D#\2\u016f\u011b\3\2\2\2\u016f\u011e\3\2\2\2\u016f\u0123\3\2\2\2\u016f"+
|
||||
"\u0126\3\2\2\2\u016f\u0132\3\2\2\2\u016f\u013e\3\2\2\2\u016f\u014c\3\2"+
|
||||
"\2\2\u016f\u0155\3\2\2\2\u016f\u015d\3\2\2\2\u016f\u0162\3\2\2\2\u016f"+
|
||||
"\u0164\3\2\2\2\u016f\u0166\3\2\2\2\u016f\u016e\3\2\2\2\u0170%\3\2\2\2"+
|
||||
"\u0171\u0173\5(\25\2\u0172\u0171\3\2\2\2\u0173\u0174\3\2\2\2\u0174\u0172"+
|
||||
"\3\2\2\2\u0174\u0175\3\2\2\2\u0175\u017b\3\2\2\2\u0176\u0177\7D\2\2\u0177"+
|
||||
"\u0179\7\13\2\2\u0178\u017a\5\"\22\2\u0179\u0178\3\2\2\2\u0179\u017a\3"+
|
||||
"\2\2\2\u017a\u017c\3\2\2\2\u017b\u0176\3\2\2\2\u017b\u017c\3\2\2\2\u017c"+
|
||||
"\'\3\2\2\2\u017d\u017e\7E\2\2\u017e\u017f\5@!\2\u017f\u0181\7\13\2\2\u0180"+
|
||||
"\u0182\5\"\22\2\u0181\u0180\3\2\2\2\u0181\u0182\3\2\2\2\u0182)\3\2\2\2"+
|
||||
"\u0183\u0184\5,\27\2\u0184\u0185\7\n\2\2\u0185\u0186\5> \2\u0186\u0188"+
|
||||
"\7\n\2\2\u0187\u0189\5> \2\u0188\u0187\3\2\2\2\u0188\u0189\3\2\2\2\u0189"+
|
||||
"\u0194\3\2\2\2\u018a\u018c\5\20\t\2\u018b\u018a\3\2\2\2\u018b\u018c\3"+
|
||||
"\2\2\2\u018c\u018d\3\2\2\2\u018d\u018e\7`\2\2\u018e\u018f\7\13\2\2\u018f"+
|
||||
"\u0190\5@!\2\u0190\u0191\7\r\2\2\u0191\u0192\5@!\2\u0192\u0194\3\2\2\2"+
|
||||
"\u0193\u0183\3\2\2\2\u0193\u018b\3\2\2\2\u0194+\3\2\2\2\u0195\u0197\5"+
|
||||
"\22\n\2\u0196\u0195\3\2\2\2\u0196\u0197\3\2\2\2\u0197\u019a\3\2\2\2\u0198"+
|
||||
"\u019a\5> \2\u0199\u0196\3\2\2\2\u0199\u0198\3\2\2\2\u019a-\3\2\2\2\u019b"+
|
||||
"\u019c\b\30\1\2\u019c\u019d\7\b\2\2\u019d\u019e\5.\30\2\u019e\u019f\7"+
|
||||
"\t\2\2\u019f\u01ab\3\2\2\2\u01a0\u01ab\7R\2\2\u01a1\u01a3\7Q\2\2\u01a2"+
|
||||
"\u01a4\7R\2\2\u01a3\u01a2\3\2\2\2\u01a3\u01a4\3\2\2\2\u01a4\u01ab\3\2"+
|
||||
"\2\2\u01a5\u01ab\5\62\32\2\u01a6\u01ab\5\60\31\2\u01a7\u01ab\58\35\2\u01a8"+
|
||||
"\u01ab\5\66\34\2\u01a9\u01ab\7\3\2\2\u01aa\u019b\3\2\2\2\u01aa\u01a0\3"+
|
||||
"\2\2\2\u01aa\u01a1\3\2\2\2\u01aa\u01a5\3\2\2\2\u01aa\u01a6\3\2\2\2\u01aa"+
|
||||
"\u01a7\3\2\2\2\u01aa\u01a8\3\2\2\2\u01aa\u01a9\3\2\2\2\u01ab\u01b9\3\2"+
|
||||
"\2\2\u01ac\u01ad\f\n\2\2\u01ad\u01b8\7\23\2\2\u01ae\u01af\f\t\2\2\u01af"+
|
||||
"\u01b1\7\6\2\2\u01b0\u01b2\5@!\2\u01b1\u01b0\3\2\2\2\u01b1\u01b2\3\2\2"+
|
||||
"\2\u01b2\u01b3\3\2\2\2\u01b3\u01b8\7\7\2\2\u01b4\u01b5\f\b\2\2\u01b5\u01b6"+
|
||||
"\7\b\2\2\u01b6\u01b8\7\t\2\2\u01b7\u01ac\3\2\2\2\u01b7\u01ae\3\2\2\2\u01b7"+
|
||||
"\u01b4\3\2\2\2\u01b8\u01bb\3\2\2\2\u01b9\u01b7\3\2\2\2\u01b9\u01ba\3\2"+
|
||||
"\2\2\u01ba/\3\2\2\2\u01bb\u01b9\3\2\2\2\u01bc\u01bd\7F\2\2\u01bd\u01be"+
|
||||
"\7`\2\2\u01be\61\3\2\2\2\u01bf\u01c1\7F\2\2\u01c0\u01c2\7`\2\2\u01c1\u01c0"+
|
||||
"\3\2\2\2\u01c1\u01c2\3\2\2\2\u01c2\u01c3\3\2\2\2\u01c3\u01c5\7\4\2\2\u01c4"+
|
||||
"\u01c6\5\64\33\2\u01c5\u01c4\3\2\2\2\u01c6\u01c7\3\2\2\2\u01c7\u01c5\3"+
|
||||
"\2\2\2\u01c7\u01c8\3\2\2\2\u01c8\u01c9\3\2\2\2\u01c9\u01ca\7\5\2\2\u01ca"+
|
||||
"\63\3\2\2\2\u01cb\u01cc\5\22\n\2\u01cc\u01cd\7\n\2\2\u01cd\65\3\2\2\2"+
|
||||
"\u01ce\u01cf\7G\2\2\u01cf\u01d0\7`\2\2\u01d0\67\3\2\2\2\u01d1\u01d3\7"+
|
||||
"G\2\2\u01d2\u01d4\7`\2\2\u01d3\u01d2\3\2\2\2\u01d3\u01d4\3\2\2\2\u01d4"+
|
||||
"\u01d5\3\2\2\2\u01d5\u01d6\7\4\2\2\u01d6\u01d7\5:\36\2\u01d7\u01d8\7\5"+
|
||||
"\2\2\u01d89\3\2\2\2\u01d9\u01da\b\36\1\2\u01da\u01db\5<\37\2\u01db\u01e1"+
|
||||
"\3\2\2\2\u01dc\u01dd\f\3\2\2\u01dd\u01de\7\f\2\2\u01de\u01e0\5<\37\2\u01df"+
|
||||
"\u01dc\3\2\2\2\u01e0\u01e3\3\2\2\2\u01e1\u01df\3\2\2\2\u01e1\u01e2\3\2"+
|
||||
"\2\2\u01e2;\3\2\2\2\u01e3\u01e1\3\2\2\2\u01e4\u01e7\7`\2\2\u01e5\u01e6"+
|
||||
"\7&\2\2\u01e6\u01e8\5@!\2\u01e7\u01e5\3\2\2\2\u01e7\u01e8\3\2\2\2\u01e8"+
|
||||
"=\3\2\2\2\u01e9\u01ea\b \1\2\u01ea\u01eb\5@!\2\u01eb\u01f1\3\2\2\2\u01ec"+
|
||||
"\u01ed\f\3\2\2\u01ed\u01ee\7\f\2\2\u01ee\u01f0\5@!\2\u01ef\u01ec\3\2\2"+
|
||||
"\2\u01f0\u01f3\3\2\2\2\u01f1\u01ef\3\2\2\2\u01f1\u01f2\3\2\2\2\u01f2?"+
|
||||
"\3\2\2\2\u01f3\u01f1\3\2\2\2\u01f4\u01f5\b!\1\2\u01f5\u01f6\7\b\2\2\u01f6"+
|
||||
"\u01f7\5> \2\u01f7\u01f8\7\t\2\2\u01f8\u022b\3\2\2\2\u01f9\u01fa\7H\2"+
|
||||
"\2\u01fa\u01fd\7\b\2\2\u01fb\u01fe\5@!\2\u01fc\u01fe\5.\30\2\u01fd\u01fb"+
|
||||
"\3\2\2\2\u01fd\u01fc\3\2\2\2\u01fe\u01ff\3\2\2\2\u01ff\u0200\7\t\2\2\u0200"+
|
||||
"\u022b\3\2\2\2\u0201\u0202\7I\2\2\u0202\u0205\7\b\2\2\u0203\u0206\5@!"+
|
||||
"\2\u0204\u0206\5.\30\2\u0205\u0203\3\2\2\2\u0205\u0204\3\2\2\2\u0206\u0207"+
|
||||
"\3\2\2\2\u0207\u0208\7\t\2\2\u0208\u022b\3\2\2\2\u0209\u020a\7\b\2\2\u020a"+
|
||||
"\u020b\5.\30\2\u020b\u020c\7\t\2\2\u020c\u020d\5@!\32\u020d\u022b\3\2"+
|
||||
"\2\2\u020e\u020f\t\2\2\2\u020f\u022b\5@!\31\u0210\u0211\7\23\2\2\u0211"+
|
||||
"\u022b\5@!\27\u0212\u0213\t\3\2\2\u0213\u022b\5@!\26\u0214\u0215\t\4\2"+
|
||||
"\2\u0215\u022b\5@!\22\u0216\u0217\7\4\2\2\u0217\u021c\5@!\2\u0218\u0219"+
|
||||
"\7\f\2\2\u0219\u021b\5@!\2\u021a\u0218\3\2\2\2\u021b\u021e\3\2\2\2\u021c"+
|
||||
"\u021a\3\2\2\2\u021c\u021d\3\2\2\2\u021d\u021f\3\2\2\2\u021e\u021c\3\2"+
|
||||
"\2\2\u021f\u0220\7\5\2\2\u0220\u022b\3\2\2\2\u0221\u022b\7`\2\2\u0222"+
|
||||
"\u022b\7W\2\2\u0223\u0225\7U\2\2\u0224\u0223\3\2\2\2\u0225\u0226\3\2\2"+
|
||||
"\2\u0226\u0224\3\2\2\2\u0226\u0227\3\2\2\2\u0227\u022b\3\2\2\2\u0228\u022b"+
|
||||
"\7V\2\2\u0229\u022b\7S\2\2\u022a\u01f4\3\2\2\2\u022a\u01f9\3\2\2\2\u022a"+
|
||||
"\u0201\3\2\2\2\u022a\u0209\3\2\2\2\u022a\u020e\3\2\2\2\u022a\u0210\3\2"+
|
||||
"\2\2\u022a\u0212\3\2\2\2\u022a\u0214\3\2\2\2\u022a\u0216\3\2\2\2\u022a"+
|
||||
"\u0221\3\2\2\2\u022a\u0222\3\2\2\2\u022a\u0224\3\2\2\2\u022a\u0228\3\2"+
|
||||
"\2\2\u022a\u0229\3\2\2\2\u022b\u0268\3\2\2\2\u022c\u022d\f\25\2\2\u022d"+
|
||||
"\u022e\t\5\2\2\u022e\u0267\5@!\26\u022f\u0230\f\24\2\2\u0230\u0231\t\6"+
|
||||
"\2\2\u0231\u0267\5@!\25\u0232\u0233\f\23\2\2\u0233\u0234\t\7\2\2\u0234"+
|
||||
"\u0267\5@!\24\u0235\u0236\f\21\2\2\u0236\u0237\t\b\2\2\u0237\u0267\5@"+
|
||||
"!\22\u0238\u0239\f\20\2\2\u0239\u023a\7\30\2\2\u023a\u0267\5@!\21\u023b"+
|
||||
"\u023c\f\17\2\2\u023c\u023d\7\32\2\2\u023d\u0267\5@!\20\u023e\u023f\f"+
|
||||
"\16\2\2\u023f\u0240\7\33\2\2\u0240\u0267\5@!\17\u0241\u0242\f\r\2\2\u0242"+
|
||||
"\u0243\7$\2\2\u0243\u0267\5@!\16\u0244\u0245\f\f\2\2\u0245\u0246\7%\2"+
|
||||
"\2\u0246\u0267\5@!\r\u0247\u0248\f\13\2\2\u0248\u0249\7\16\2\2\u0249\u024a"+
|
||||
"\5@!\2\u024a\u024b\7\13\2\2\u024b\u024c\5@!\f\u024c\u0267\3\2\2\2\u024d"+
|
||||
"\u024e\f\n\2\2\u024e\u024f\7&\2\2\u024f\u0267\5@!\n\u0250\u0251\f\t\2"+
|
||||
"\2\u0251\u0252\7\'\2\2\u0252\u0267\5@!\t\u0253\u0254\f \2\2\u0254\u0255"+
|
||||
"\7\17\2\2\u0255\u0267\7`\2\2\u0256\u0257\f\37\2\2\u0257\u0258\7\20\2\2"+
|
||||
"\u0258\u0267\7`\2\2\u0259\u025a\f\36\2\2\u025a\u025c\7\b\2\2\u025b\u025d"+
|
||||
"\5B\"\2\u025c\u025b\3\2\2\2\u025c\u025d\3\2\2\2\u025d\u025e\3\2\2\2\u025e"+
|
||||
"\u0267\7\t\2\2\u025f\u0260\f\33\2\2\u0260\u0261\7\6\2\2\u0261\u0262\5"+
|
||||
"> \2\u0262\u0263\7\7\2\2\u0263\u0267\3\2\2\2\u0264\u0265\f\30\2\2\u0265"+
|
||||
"\u0267\t\2\2\2\u0266\u022c\3\2\2\2\u0266\u022f\3\2\2\2\u0266\u0232\3\2"+
|
||||
"\2\2\u0266\u0235\3\2\2\2\u0266\u0238\3\2\2\2\u0266\u023b\3\2\2\2\u0266"+
|
||||
"\u023e\3\2\2\2\u0266\u0241\3\2\2\2\u0266\u0244\3\2\2\2\u0266\u0247\3\2"+
|
||||
"\2\2\u0266\u024d\3\2\2\2\u0266\u0250\3\2\2\2\u0266\u0253\3\2\2\2\u0266"+
|
||||
"\u0256\3\2\2\2\u0266\u0259\3\2\2\2\u0266\u025f\3\2\2\2\u0266\u0264\3\2"+
|
||||
"\2\2\u0267\u026a\3\2\2\2\u0268\u0266\3\2\2\2\u0268\u0269\3\2\2\2\u0269"+
|
||||
"A\3\2\2\2\u026a\u0268\3\2\2\2\u026b\u0270\5@!\2\u026c\u026d\7\f\2\2\u026d"+
|
||||
"\u026f\5@!\2\u026e\u026c\3\2\2\2\u026f\u0272\3\2\2\2\u0270\u026e\3\2\2"+
|
||||
"\2\u0270\u0271\3\2\2\2\u0271C\3\2\2\2\u0272\u0270\3\2\2\2\u0273\u0275"+
|
||||
"\7J\2\2\u0274\u0276\5F$\2\u0275\u0274\3\2\2\2\u0275\u0276\3\2\2\2\u0276"+
|
||||
"\u0277\3\2\2\2\u0277\u0278\7T\2\2\u0278E\3\2\2\2\u0279\u027a\7\b\2\2\u027a"+
|
||||
"\u027f\5H%\2\u027b\u027c\7\f\2\2\u027c\u027e\5H%\2\u027d\u027b\3\2\2\2"+
|
||||
"\u027e\u0281\3\2\2\2\u027f\u027d\3\2\2\2\u027f\u0280\3\2\2\2\u0280\u0282"+
|
||||
"\3\2\2\2\u0281\u027f\3\2\2\2\u0282\u0283\7\t\2\2\u0283G\3\2\2\2\u0284"+
|
||||
"\u0285\7K\2\2\u0285\u0294\7U\2\2\u0286\u0287\7L\2\2\u0287\u0294\7`\2\2"+
|
||||
"\u0288\u0289\7M\2\2\u0289\u0294\7U\2\2\u028a\u028b\7N\2\2\u028b\u0294"+
|
||||
"\5@!\2\u028c\u028d\7O\2\2\u028d\u0294\5@!\2\u028e\u0291\7,\2\2\u028f\u0292"+
|
||||
"\7\67\2\2\u0290\u0292\5@!\2\u0291\u028f\3\2\2\2\u0291\u0290\3\2\2\2\u0292"+
|
||||
"\u0294\3\2\2\2\u0293\u0284\3\2\2\2\u0293\u0286\3\2\2\2\u0293\u0288\3\2"+
|
||||
"\2\2\u0293\u028a\3\2\2\2\u0293\u028c\3\2\2\2\u0293\u028e\3\2\2\2\u0294"+
|
||||
"I\3\2\2\2\u0295\u0297\5L\'\2\u0296\u0295\3\2\2\2\u0297\u029a\3\2\2\2\u0298"+
|
||||
"\u0296\3\2\2\2\u0298\u0299\3\2\2\2\u0299K\3\2\2\2\u029a\u0298\3\2\2\2"+
|
||||
"\u029b\u029f\5N(\2\u029c\u029f\5P)\2\u029d\u029f\5R*\2\u029e\u029b\3\2"+
|
||||
"\2\2\u029e\u029c\3\2\2\2\u029e\u029d\3\2\2\2\u029fM\3\2\2\2\u02a0\u02a1"+
|
||||
"\7\u0084\2\2\u02a1\u02a5\7g\2\2\u02a2\u02a3\7\u0083\2\2\u02a3\u02a5\7"+
|
||||
"g\2\2\u02a4\u02a0\3\2\2\2\u02a4\u02a2\3\2\2\2\u02a5O\3\2\2\2\u02a6\u02a8"+
|
||||
"\7e\2\2\u02a7\u02a9\5T+\2\u02a8\u02a7\3\2\2\2\u02a8\u02a9\3\2\2\2\u02a9"+
|
||||
"Q\3\2\2\2\u02aa\u02ab\7d\2\2\u02ab\u02b0\5V,\2\u02ac\u02ad\7h\2\2\u02ad"+
|
||||
"\u02af\5V,\2\u02ae\u02ac\3\2\2\2\u02af\u02b2\3\2\2\2\u02b0\u02ae\3\2\2"+
|
||||
"\2\u02b0\u02b1\3\2\2\2\u02b1S\3\2\2\2\u02b2\u02b0\3\2\2\2\u02b3\u02cb"+
|
||||
"\5V,\2\u02b4\u02b5\7f\2\2\u02b5\u02cb\5V,\2\u02b6\u02b7\5V,\2\u02b7\u02b8"+
|
||||
"\7h\2\2\u02b8\u02b9\7\u0084\2\2\u02b9\u02cb\3\2\2\2\u02ba\u02bb\7i\2\2"+
|
||||
"\u02bb\u02bc\5V,\2\u02bc\u02bd\7j\2\2\u02bd\u02be\7h\2\2\u02be\u02bf\7"+
|
||||
"\u0084\2\2\u02bf\u02cb\3\2\2\2\u02c0\u02c1\7i\2\2\u02c1\u02c2\5V,\2\u02c2"+
|
||||
"\u02c3\7h\2\2\u02c3\u02c4\7\u0084\2\2\u02c4\u02c5\7j\2\2\u02c5\u02cb\3"+
|
||||
"\2\2\2\u02c6\u02c7\7i\2\2\u02c7\u02c8\5V,\2\u02c8\u02c9\7j\2\2\u02c9\u02cb"+
|
||||
"\3\2\2\2\u02ca\u02b3\3\2\2\2\u02ca\u02b4\3\2\2\2\u02ca\u02b6\3\2\2\2\u02ca"+
|
||||
"\u02ba\3\2\2\2\u02ca\u02c0\3\2\2\2\u02ca\u02c6\3\2\2\2\u02cbU\3\2\2\2"+
|
||||
"\u02cc\u02cd\b,\1\2\u02cd\u02ce\7k\2\2\u02ce\u02cf\5V,\2\u02cf\u02d0\7"+
|
||||
"l\2\2\u02d0\u02db\3\2\2\2\u02d1\u02d2\t\t\2\2\u02d2\u02db\5V,\n\u02d3"+
|
||||
"\u02db\7\u0084\2\2\u02d4\u02db\7\u0082\2\2\u02d5\u02d6\7v\2\2\u02d6\u02d7"+
|
||||
"\7\u0084\2\2\u02d7\u02db\7w\2\2\u02d8\u02db\7x\2\2\u02d9\u02db\7\u0081"+
|
||||
"\2\2\u02da\u02cc\3\2\2\2\u02da\u02d1\3\2\2\2\u02da\u02d3\3\2\2\2\u02da"+
|
||||
"\u02d4\3\2\2\2\u02da\u02d5\3\2\2\2\u02da\u02d8\3\2\2\2\u02da\u02d9\3\2"+
|
||||
"\2\2\u02db\u02ea\3\2\2\2\u02dc\u02dd\f\f\2\2\u02dd\u02de\7m\2\2\u02de"+
|
||||
"\u02e9\5V,\r\u02df\u02e0\f\13\2\2\u02e0\u02e1\t\n\2\2\u02e1\u02e9\5V,"+
|
||||
"\f\u02e2\u02e3\f\t\2\2\u02e3\u02e4\t\13\2\2\u02e4\u02e9\5V,\n\u02e5\u02e6"+
|
||||
"\f\b\2\2\u02e6\u02e7\t\f\2\2\u02e7\u02e9\5V,\t\u02e8\u02dc\3\2\2\2\u02e8"+
|
||||
"\u02df\3\2\2\2\u02e8\u02e2\3\2\2\2\u02e8\u02e5\3\2\2\2\u02e9\u02ec\3\2"+
|
||||
"\2\2\u02ea\u02e8\3\2\2\2\u02ea\u02eb\3\2\2\2\u02ebW\3\2\2\2\u02ec\u02ea"+
|
||||
"\3\2\2\2Gafz\u0084\u008b\u0099\u009f\u00a4\u00aa\u00af\u00b8\u00bf\u00ca"+
|
||||
"\u00f2\u00ff\u0107\u0110\u0114\u0119\u0120\u012d\u0132\u013e\u014c\u015f"+
|
||||
"\u0168\u016f\u0174\u0179\u017b\u0181\u0188\u018b\u0193\u0196\u0199\u01a3"+
|
||||
"\u01aa\u01b1\u01b7\u01b9\u01c1\u01c7\u01d3\u01e1\u01e7\u01f1\u01fd\u0205"+
|
||||
"\u021c\u0226\u022a\u025c\u0266\u0268\u0270\u0275\u027f\u0291\u0293\u0298"+
|
||||
"\u029e\u02a4\u02a8\u02b0\u02ca\u02da\u02e8\u02ea";
|
||||
"8:<>@BDFHJLNPRTV\2\16\4\2WW``\3\2\26\27\5\2\21\22\30\31PP\4\2 ##\3\2"+
|
||||
"\34\35\3\2\23\25\3\2\21\22\3\2\36#\3\2ps\3\2no\3\2tu\3\2pq\2\u0355\2X"+
|
||||
"\3\2\2\2\4[\3\2\2\2\6a\3\2\2\2\bf\3\2\2\2\nh\3\2\2\2\fz\3\2\2\2\16|\3"+
|
||||
"\2\2\2\20\u0084\3\2\2\2\22\u008e\3\2\2\2\24\u0091\3\2\2\2\26\u00a4\3\2"+
|
||||
"\2\2\30\u00a6\3\2\2\2\32\u00b3\3\2\2\2\34\u00bf\3\2\2\2\36\u00f2\3\2\2"+
|
||||
"\2 \u0114\3\2\2\2\"\u0117\3\2\2\2$\u016f\3\2\2\2&\u0172\3\2\2\2(\u017d"+
|
||||
"\3\2\2\2*\u0193\3\2\2\2,\u0199\3\2\2\2.\u01aa\3\2\2\2\60\u01bc\3\2\2\2"+
|
||||
"\62\u01bf\3\2\2\2\64\u01cb\3\2\2\2\66\u01ce\3\2\2\28\u01d1\3\2\2\2:\u01d9"+
|
||||
"\3\2\2\2<\u01e4\3\2\2\2>\u01e9\3\2\2\2@\u022a\3\2\2\2B\u026b\3\2\2\2D"+
|
||||
"\u0273\3\2\2\2F\u0279\3\2\2\2H\u0293\3\2\2\2J\u0298\3\2\2\2L\u029e\3\2"+
|
||||
"\2\2N\u02a4\3\2\2\2P\u02a6\3\2\2\2R\u02aa\3\2\2\2T\u02ca\3\2\2\2V\u02da"+
|
||||
"\3\2\2\2XY\5\6\4\2YZ\7\2\2\3Z\3\3\2\2\2[\\\5J&\2\\]\7\2\2\3]\5\3\2\2\2"+
|
||||
"^`\5\b\5\2_^\3\2\2\2`c\3\2\2\2a_\3\2\2\2ab\3\2\2\2b\7\3\2\2\2ca\3\2\2"+
|
||||
"\2dg\5\f\7\2eg\5\n\6\2fd\3\2\2\2fe\3\2\2\2g\t\3\2\2\2hi\7(\2\2ij\7U\2"+
|
||||
"\2j\13\3\2\2\2kl\5\22\n\2lm\7\n\2\2m{\3\2\2\2no\5\62\32\2op\7\n\2\2p{"+
|
||||
"\3\2\2\2qr\58\35\2rs\7\n\2\2s{\3\2\2\2t{\5\30\r\2u{\5D#\2v{\5\36\20\2"+
|
||||
"wx\5\16\b\2xy\7\n\2\2y{\3\2\2\2zk\3\2\2\2zn\3\2\2\2zq\3\2\2\2zt\3\2\2"+
|
||||
"\2zu\3\2\2\2zv\3\2\2\2zw\3\2\2\2{\r\3\2\2\2|}\7)\2\2}~\5.\30\2~\177\7"+
|
||||
"`\2\2\177\u0080\b\b\1\2\u0080\17\3\2\2\2\u0081\u0083\5 \21\2\u0082\u0081"+
|
||||
"\3\2\2\2\u0083\u0086\3\2\2\2\u0084\u0082\3\2\2\2\u0084\u0085\3\2\2\2\u0085"+
|
||||
"\u0087\3\2\2\2\u0086\u0084\3\2\2\2\u0087\u008b\5.\30\2\u0088\u008a\5 "+
|
||||
"\21\2\u0089\u0088\3\2\2\2\u008a\u008d\3\2\2\2\u008b\u0089\3\2\2\2\u008b"+
|
||||
"\u008c\3\2\2\2\u008c\21\3\2\2\2\u008d\u008b\3\2\2\2\u008e\u008f\5\20\t"+
|
||||
"\2\u008f\u0090\5\24\13\2\u0090\23\3\2\2\2\u0091\u0092\b\13\1\2\u0092\u0093"+
|
||||
"\5\26\f\2\u0093\u0099\3\2\2\2\u0094\u0095\f\3\2\2\u0095\u0096\7\f\2\2"+
|
||||
"\u0096\u0098\5\26\f\2\u0097\u0094\3\2\2\2\u0098\u009b\3\2\2\2\u0099\u0097"+
|
||||
"\3\2\2\2\u0099\u009a\3\2\2\2\u009a\25\3\2\2\2\u009b\u0099\3\2\2\2\u009c"+
|
||||
"\u009f\7`\2\2\u009d\u009e\7&\2\2\u009e\u00a0\5@!\2\u009f\u009d\3\2\2\2"+
|
||||
"\u009f\u00a0\3\2\2\2\u00a0\u00a5\3\2\2\2\u00a1\u00a2\7`\2\2\u00a2\u00a3"+
|
||||
"\7&\2\2\u00a3\u00a5\5D#\2\u00a4\u009c\3\2\2\2\u00a4\u00a1\3\2\2\2\u00a5"+
|
||||
"\27\3\2\2\2\u00a6\u00a7\5\20\t\2\u00a7\u00a8\7`\2\2\u00a8\u00aa\7\b\2"+
|
||||
"\2\u00a9\u00ab\5\32\16\2\u00aa\u00a9\3\2\2\2\u00aa\u00ab\3\2\2\2\u00ab"+
|
||||
"\u00ac\3\2\2\2\u00ac\u00ad\7\t\2\2\u00ad\u00af\7\4\2\2\u00ae\u00b0\5\""+
|
||||
"\22\2\u00af\u00ae\3\2\2\2\u00af\u00b0\3\2\2\2\u00b0\u00b1\3\2\2\2\u00b1"+
|
||||
"\u00b2\7\5\2\2\u00b2\31\3\2\2\2\u00b3\u00b8\5\34\17\2\u00b4\u00b5\7\f"+
|
||||
"\2\2\u00b5\u00b7\5\34\17\2\u00b6\u00b4\3\2\2\2\u00b7\u00ba\3\2\2\2\u00b8"+
|
||||
"\u00b6\3\2\2\2\u00b8\u00b9\3\2\2\2\u00b9\33\3\2\2\2\u00ba\u00b8\3\2\2"+
|
||||
"\2\u00bb\u00bc\5\20\t\2\u00bc\u00bd\7`\2\2\u00bd\u00c0\3\2\2\2\u00be\u00c0"+
|
||||
"\7R\2\2\u00bf\u00bb\3\2\2\2\u00bf\u00be\3\2\2\2\u00c0\35\3\2\2\2\u00c1"+
|
||||
"\u00c2\7*\2\2\u00c2\u00c3\7+\2\2\u00c3\u00c4\3\2\2\2\u00c4\u00c5\7\b\2"+
|
||||
"\2\u00c5\u00ca\7W\2\2\u00c6\u00c7\7\f\2\2\u00c7\u00c9\7W\2\2\u00c8\u00c6"+
|
||||
"\3\2\2\2\u00c9\u00cc\3\2\2\2\u00ca\u00c8\3\2\2\2\u00ca\u00cb\3\2\2\2\u00cb"+
|
||||
"\u00cd\3\2\2\2\u00cc\u00ca\3\2\2\2\u00cd\u00f3\7\t\2\2\u00ce\u00cf\7*"+
|
||||
"\2\2\u00cf\u00d0\7,\2\2\u00d0\u00d1\3\2\2\2\u00d1\u00d2\7\b\2\2\u00d2"+
|
||||
"\u00d3\7W\2\2\u00d3\u00f3\7\t\2\2\u00d4\u00d5\7*\2\2\u00d5\u00d6\7-\2"+
|
||||
"\2\u00d6\u00d7\3\2\2\2\u00d7\u00d8\7\b\2\2\u00d8\u00d9\7`\2\2\u00d9\u00f3"+
|
||||
"\7\t\2\2\u00da\u00db\7*\2\2\u00db\u00dc\7.\2\2\u00dc\u00dd\3\2\2\2\u00dd"+
|
||||
"\u00de\7\b\2\2\u00de\u00df\7U\2\2\u00df\u00f3\7\t\2\2\u00e0\u00e1\7*\2"+
|
||||
"\2\u00e1\u00e2\7/\2\2\u00e2\u00e3\3\2\2\2\u00e3\u00e4\7\b\2\2\u00e4\u00e5"+
|
||||
"\7`\2\2\u00e5\u00f3\7\t\2\2\u00e6\u00e7\7*\2\2\u00e7\u00e8\7\60\2\2\u00e8"+
|
||||
"\u00e9\3\2\2\2\u00e9\u00ea\7\b\2\2\u00ea\u00eb\7`\2\2\u00eb\u00f3\7\t"+
|
||||
"\2\2\u00ec\u00ed\7*\2\2\u00ed\u00ee\7\61\2\2\u00ee\u00ef\3\2\2\2\u00ef"+
|
||||
"\u00f0\7\b\2\2\u00f0\u00f1\7`\2\2\u00f1\u00f3\7\t\2\2\u00f2\u00c1\3\2"+
|
||||
"\2\2\u00f2\u00ce\3\2\2\2\u00f2\u00d4\3\2\2\2\u00f2\u00da\3\2\2\2\u00f2"+
|
||||
"\u00e0\3\2\2\2\u00f2\u00e6\3\2\2\2\u00f2\u00ec\3\2\2\2\u00f3\37\3\2\2"+
|
||||
"\2\u00f4\u0115\7\62\2\2\u00f5\u0115\7\63\2\2\u00f6\u0115\7\64\2\2\u00f7"+
|
||||
"\u00f8\7\65\2\2\u00f8\u00f9\7\b\2\2\u00f9\u00fa\7W\2\2\u00fa\u0115\7\t"+
|
||||
"\2\2\u00fb\u00ff\7\66\2\2\u00fc\u00fd\7\b\2\2\u00fd\u00fe\t\2\2\2\u00fe"+
|
||||
"\u0100\7\t\2\2\u00ff\u00fc\3\2\2\2\u00ff\u0100\3\2\2\2\u0100\u0115\3\2"+
|
||||
"\2\2\u0101\u0115\7\67\2\2\u0102\u0115\78\2\2\u0103\u0107\79\2\2\u0104"+
|
||||
"\u0105\7\b\2\2\u0105\u0106\7`\2\2\u0106\u0108\7\t\2\2\u0107\u0104\3\2"+
|
||||
"\2\2\u0107\u0108\3\2\2\2\u0108\u0115\3\2\2\2\u0109\u010a\7+\2\2\u010a"+
|
||||
"\u010b\7\b\2\2\u010b\u0110\7W\2\2\u010c\u010d\7\f\2\2\u010d\u010f\7W\2"+
|
||||
"\2\u010e\u010c\3\2\2\2\u010f\u0112\3\2\2\2\u0110\u010e\3\2\2\2\u0110\u0111"+
|
||||
"\3\2\2\2\u0111\u0113\3\2\2\2\u0112\u0110\3\2\2\2\u0113\u0115\7\t\2\2\u0114"+
|
||||
"\u00f4\3\2\2\2\u0114\u00f5\3\2\2\2\u0114\u00f6\3\2\2\2\u0114\u00f7\3\2"+
|
||||
"\2\2\u0114\u00fb\3\2\2\2\u0114\u0101\3\2\2\2\u0114\u0102\3\2\2\2\u0114"+
|
||||
"\u0103\3\2\2\2\u0114\u0109\3\2\2\2\u0115!\3\2\2\2\u0116\u0118\5$\23\2"+
|
||||
"\u0117\u0116\3\2\2\2\u0118\u0119\3\2\2\2\u0119\u0117\3\2\2\2\u0119\u011a"+
|
||||
"\3\2\2\2\u011a#\3\2\2\2\u011b\u011c\5\22\n\2\u011c\u011d\7\n\2\2\u011d"+
|
||||
"\u0170\3\2\2\2\u011e\u0120\7\4\2\2\u011f\u0121\5\"\22\2\u0120\u011f\3"+
|
||||
"\2\2\2\u0120\u0121\3\2\2\2\u0121\u0122\3\2\2\2\u0122\u0170\7\5\2\2\u0123"+
|
||||
"\u0124\5> \2\u0124\u0125\7\n\2\2\u0125\u0170\3\2\2\2\u0126\u0127\7:\2"+
|
||||
"\2\u0127\u0128\7\b\2\2\u0128\u0129\5> \2\u0129\u012a\7\t\2\2\u012a\u012d"+
|
||||
"\5$\23\2\u012b\u012c\7;\2\2\u012c\u012e\5$\23\2\u012d\u012b\3\2\2\2\u012d"+
|
||||
"\u012e\3\2\2\2\u012e\u0170\3\2\2\2\u012f\u0131\5 \21\2\u0130\u012f\3\2"+
|
||||
"\2\2\u0131\u0134\3\2\2\2\u0132\u0130\3\2\2\2\u0132\u0133\3\2\2\2\u0133"+
|
||||
"\u0135\3\2\2\2\u0134\u0132\3\2\2\2\u0135\u0136\7<\2\2\u0136\u0137\7\b"+
|
||||
"\2\2\u0137\u0138\5> \2\u0138\u0139\7\t\2\2\u0139\u013a\5$\23\2\u013a\u0170"+
|
||||
"\3\2\2\2\u013b\u013d\5 \21\2\u013c\u013b\3\2\2\2\u013d\u0140\3\2\2\2\u013e"+
|
||||
"\u013c\3\2\2\2\u013e\u013f\3\2\2\2\u013f\u0141\3\2\2\2\u0140\u013e\3\2"+
|
||||
"\2\2\u0141\u0142\7=\2\2\u0142\u0143\5$\23\2\u0143\u0144\7<\2\2\u0144\u0145"+
|
||||
"\7\b\2\2\u0145\u0146\5> \2\u0146\u0147\7\t\2\2\u0147\u0148\7\n\2\2\u0148"+
|
||||
"\u0170\3\2\2\2\u0149\u014b\5 \21\2\u014a\u0149\3\2\2\2\u014b\u014e\3\2"+
|
||||
"\2\2\u014c\u014a\3\2\2\2\u014c\u014d\3\2\2\2\u014d\u014f\3\2\2\2\u014e"+
|
||||
"\u014c\3\2\2\2\u014f\u0150\7>\2\2\u0150\u0151\7\b\2\2\u0151\u0152\5*\26"+
|
||||
"\2\u0152\u0153\7\t\2\2\u0153\u0154\5$\23\2\u0154\u0170\3\2\2\2\u0155\u0156"+
|
||||
"\7?\2\2\u0156\u0157\7\b\2\2\u0157\u0158\5> \2\u0158\u0159\7\t\2\2\u0159"+
|
||||
"\u015a\7\4\2\2\u015a\u015b\5&\24\2\u015b\u015c\7\5\2\2\u015c\u0170\3\2"+
|
||||
"\2\2\u015d\u015f\7@\2\2\u015e\u0160\5> \2\u015f\u015e\3\2\2\2\u015f\u0160"+
|
||||
"\3\2\2\2\u0160\u0161\3\2\2\2\u0161\u0170\7\n\2\2\u0162\u0163\7A\2\2\u0163"+
|
||||
"\u0170\7\n\2\2\u0164\u0165\7B\2\2\u0165\u0170\7\n\2\2\u0166\u0168\7C\2"+
|
||||
"\2\u0167\u0169\5F$\2\u0168\u0167\3\2\2\2\u0168\u0169\3\2\2\2\u0169\u016a"+
|
||||
"\3\2\2\2\u016a\u016b\7\4\2\2\u016b\u016c\5J&\2\u016c\u016d\7w\2\2\u016d"+
|
||||
"\u0170\3\2\2\2\u016e\u0170\5D#\2\u016f\u011b\3\2\2\2\u016f\u011e\3\2\2"+
|
||||
"\2\u016f\u0123\3\2\2\2\u016f\u0126\3\2\2\2\u016f\u0132\3\2\2\2\u016f\u013e"+
|
||||
"\3\2\2\2\u016f\u014c\3\2\2\2\u016f\u0155\3\2\2\2\u016f\u015d\3\2\2\2\u016f"+
|
||||
"\u0162\3\2\2\2\u016f\u0164\3\2\2\2\u016f\u0166\3\2\2\2\u016f\u016e\3\2"+
|
||||
"\2\2\u0170%\3\2\2\2\u0171\u0173\5(\25\2\u0172\u0171\3\2\2\2\u0173\u0174"+
|
||||
"\3\2\2\2\u0174\u0172\3\2\2\2\u0174\u0175\3\2\2\2\u0175\u017b\3\2\2\2\u0176"+
|
||||
"\u0177\7D\2\2\u0177\u0179\7\13\2\2\u0178\u017a\5\"\22\2\u0179\u0178\3"+
|
||||
"\2\2\2\u0179\u017a\3\2\2\2\u017a\u017c\3\2\2\2\u017b\u0176\3\2\2\2\u017b"+
|
||||
"\u017c\3\2\2\2\u017c\'\3\2\2\2\u017d\u017e\7E\2\2\u017e\u017f\5@!\2\u017f"+
|
||||
"\u0181\7\13\2\2\u0180\u0182\5\"\22\2\u0181\u0180\3\2\2\2\u0181\u0182\3"+
|
||||
"\2\2\2\u0182)\3\2\2\2\u0183\u0184\5,\27\2\u0184\u0185\7\n\2\2\u0185\u0186"+
|
||||
"\5> \2\u0186\u0188\7\n\2\2\u0187\u0189\5> \2\u0188\u0187\3\2\2\2\u0188"+
|
||||
"\u0189\3\2\2\2\u0189\u0194\3\2\2\2\u018a\u018c\5\20\t\2\u018b\u018a\3"+
|
||||
"\2\2\2\u018b\u018c\3\2\2\2\u018c\u018d\3\2\2\2\u018d\u018e\7`\2\2\u018e"+
|
||||
"\u018f\7\13\2\2\u018f\u0190\5@!\2\u0190\u0191\7\r\2\2\u0191\u0192\5@!"+
|
||||
"\2\u0192\u0194\3\2\2\2\u0193\u0183\3\2\2\2\u0193\u018b\3\2\2\2\u0194+"+
|
||||
"\3\2\2\2\u0195\u0197\5\22\n\2\u0196\u0195\3\2\2\2\u0196\u0197\3\2\2\2"+
|
||||
"\u0197\u019a\3\2\2\2\u0198\u019a\5> \2\u0199\u0196\3\2\2\2\u0199\u0198"+
|
||||
"\3\2\2\2\u019a-\3\2\2\2\u019b\u019c\b\30\1\2\u019c\u019d\7\b\2\2\u019d"+
|
||||
"\u019e\5.\30\2\u019e\u019f\7\t\2\2\u019f\u01ab\3\2\2\2\u01a0\u01ab\7R"+
|
||||
"\2\2\u01a1\u01a3\7Q\2\2\u01a2\u01a4\7R\2\2\u01a3\u01a2\3\2\2\2\u01a3\u01a4"+
|
||||
"\3\2\2\2\u01a4\u01ab\3\2\2\2\u01a5\u01ab\5\62\32\2\u01a6\u01ab\5\60\31"+
|
||||
"\2\u01a7\u01ab\58\35\2\u01a8\u01ab\5\66\34\2\u01a9\u01ab\7\3\2\2\u01aa"+
|
||||
"\u019b\3\2\2\2\u01aa\u01a0\3\2\2\2\u01aa\u01a1\3\2\2\2\u01aa\u01a5\3\2"+
|
||||
"\2\2\u01aa\u01a6\3\2\2\2\u01aa\u01a7\3\2\2\2\u01aa\u01a8\3\2\2\2\u01aa"+
|
||||
"\u01a9\3\2\2\2\u01ab\u01b9\3\2\2\2\u01ac\u01ad\f\n\2\2\u01ad\u01b8\7\23"+
|
||||
"\2\2\u01ae\u01af\f\t\2\2\u01af\u01b1\7\6\2\2\u01b0\u01b2\5@!\2\u01b1\u01b0"+
|
||||
"\3\2\2\2\u01b1\u01b2\3\2\2\2\u01b2\u01b3\3\2\2\2\u01b3\u01b8\7\7\2\2\u01b4"+
|
||||
"\u01b5\f\b\2\2\u01b5\u01b6\7\b\2\2\u01b6\u01b8\7\t\2\2\u01b7\u01ac\3\2"+
|
||||
"\2\2\u01b7\u01ae\3\2\2\2\u01b7\u01b4\3\2\2\2\u01b8\u01bb\3\2\2\2\u01b9"+
|
||||
"\u01b7\3\2\2\2\u01b9\u01ba\3\2\2\2\u01ba/\3\2\2\2\u01bb\u01b9\3\2\2\2"+
|
||||
"\u01bc\u01bd\7F\2\2\u01bd\u01be\7`\2\2\u01be\61\3\2\2\2\u01bf\u01c1\7"+
|
||||
"F\2\2\u01c0\u01c2\7`\2\2\u01c1\u01c0\3\2\2\2\u01c1\u01c2\3\2\2\2\u01c2"+
|
||||
"\u01c3\3\2\2\2\u01c3\u01c5\7\4\2\2\u01c4\u01c6\5\64\33\2\u01c5\u01c4\3"+
|
||||
"\2\2\2\u01c6\u01c7\3\2\2\2\u01c7\u01c5\3\2\2\2\u01c7\u01c8\3\2\2\2\u01c8"+
|
||||
"\u01c9\3\2\2\2\u01c9\u01ca\7\5\2\2\u01ca\63\3\2\2\2\u01cb\u01cc\5\22\n"+
|
||||
"\2\u01cc\u01cd\7\n\2\2\u01cd\65\3\2\2\2\u01ce\u01cf\7G\2\2\u01cf\u01d0"+
|
||||
"\7`\2\2\u01d0\67\3\2\2\2\u01d1\u01d3\7G\2\2\u01d2\u01d4\7`\2\2\u01d3\u01d2"+
|
||||
"\3\2\2\2\u01d3\u01d4\3\2\2\2\u01d4\u01d5\3\2\2\2\u01d5\u01d6\7\4\2\2\u01d6"+
|
||||
"\u01d7\5:\36\2\u01d7\u01d8\7\5\2\2\u01d89\3\2\2\2\u01d9\u01da\b\36\1\2"+
|
||||
"\u01da\u01db\5<\37\2\u01db\u01e1\3\2\2\2\u01dc\u01dd\f\3\2\2\u01dd\u01de"+
|
||||
"\7\f\2\2\u01de\u01e0\5<\37\2\u01df\u01dc\3\2\2\2\u01e0\u01e3\3\2\2\2\u01e1"+
|
||||
"\u01df\3\2\2\2\u01e1\u01e2\3\2\2\2\u01e2;\3\2\2\2\u01e3\u01e1\3\2\2\2"+
|
||||
"\u01e4\u01e7\7`\2\2\u01e5\u01e6\7&\2\2\u01e6\u01e8\5@!\2\u01e7\u01e5\3"+
|
||||
"\2\2\2\u01e7\u01e8\3\2\2\2\u01e8=\3\2\2\2\u01e9\u01ea\b \1\2\u01ea\u01eb"+
|
||||
"\5@!\2\u01eb\u01f1\3\2\2\2\u01ec\u01ed\f\3\2\2\u01ed\u01ee\7\f\2\2\u01ee"+
|
||||
"\u01f0\5@!\2\u01ef\u01ec\3\2\2\2\u01f0\u01f3\3\2\2\2\u01f1\u01ef\3\2\2"+
|
||||
"\2\u01f1\u01f2\3\2\2\2\u01f2?\3\2\2\2\u01f3\u01f1\3\2\2\2\u01f4\u01f5"+
|
||||
"\b!\1\2\u01f5\u01f6\7\b\2\2\u01f6\u01f7\5> \2\u01f7\u01f8\7\t\2\2\u01f8"+
|
||||
"\u022b\3\2\2\2\u01f9\u01fa\7H\2\2\u01fa\u01fd\7\b\2\2\u01fb\u01fe\5@!"+
|
||||
"\2\u01fc\u01fe\5.\30\2\u01fd\u01fb\3\2\2\2\u01fd\u01fc\3\2\2\2\u01fe\u01ff"+
|
||||
"\3\2\2\2\u01ff\u0200\7\t\2\2\u0200\u022b\3\2\2\2\u0201\u0202\7I\2\2\u0202"+
|
||||
"\u0205\7\b\2\2\u0203\u0206\5@!\2\u0204\u0206\5.\30\2\u0205\u0203\3\2\2"+
|
||||
"\2\u0205\u0204\3\2\2\2\u0206\u0207\3\2\2\2\u0207\u0208\7\t\2\2\u0208\u022b"+
|
||||
"\3\2\2\2\u0209\u020a\7\b\2\2\u020a\u020b\5.\30\2\u020b\u020c\7\t\2\2\u020c"+
|
||||
"\u020d\5@!\32\u020d\u022b\3\2\2\2\u020e\u020f\t\3\2\2\u020f\u022b\5@!"+
|
||||
"\31\u0210\u0211\7\23\2\2\u0211\u022b\5@!\27\u0212\u0213\t\4\2\2\u0213"+
|
||||
"\u022b\5@!\26\u0214\u0215\t\5\2\2\u0215\u022b\5@!\22\u0216\u0217\7\4\2"+
|
||||
"\2\u0217\u021c\5@!\2\u0218\u0219\7\f\2\2\u0219\u021b\5@!\2\u021a\u0218"+
|
||||
"\3\2\2\2\u021b\u021e\3\2\2\2\u021c\u021a\3\2\2\2\u021c\u021d\3\2\2\2\u021d"+
|
||||
"\u021f\3\2\2\2\u021e\u021c\3\2\2\2\u021f\u0220\7\5\2\2\u0220\u022b\3\2"+
|
||||
"\2\2\u0221\u022b\7`\2\2\u0222\u022b\7W\2\2\u0223\u0225\7U\2\2\u0224\u0223"+
|
||||
"\3\2\2\2\u0225\u0226\3\2\2\2\u0226\u0224\3\2\2\2\u0226\u0227\3\2\2\2\u0227"+
|
||||
"\u022b\3\2\2\2\u0228\u022b\7V\2\2\u0229\u022b\7S\2\2\u022a\u01f4\3\2\2"+
|
||||
"\2\u022a\u01f9\3\2\2\2\u022a\u0201\3\2\2\2\u022a\u0209\3\2\2\2\u022a\u020e"+
|
||||
"\3\2\2\2\u022a\u0210\3\2\2\2\u022a\u0212\3\2\2\2\u022a\u0214\3\2\2\2\u022a"+
|
||||
"\u0216\3\2\2\2\u022a\u0221\3\2\2\2\u022a\u0222\3\2\2\2\u022a\u0224\3\2"+
|
||||
"\2\2\u022a\u0228\3\2\2\2\u022a\u0229\3\2\2\2\u022b\u0268\3\2\2\2\u022c"+
|
||||
"\u022d\f\25\2\2\u022d\u022e\t\6\2\2\u022e\u0267\5@!\26\u022f\u0230\f\24"+
|
||||
"\2\2\u0230\u0231\t\7\2\2\u0231\u0267\5@!\25\u0232\u0233\f\23\2\2\u0233"+
|
||||
"\u0234\t\b\2\2\u0234\u0267\5@!\24\u0235\u0236\f\21\2\2\u0236\u0237\t\t"+
|
||||
"\2\2\u0237\u0267\5@!\22\u0238\u0239\f\20\2\2\u0239\u023a\7\30\2\2\u023a"+
|
||||
"\u0267\5@!\21\u023b\u023c\f\17\2\2\u023c\u023d\7\32\2\2\u023d\u0267\5"+
|
||||
"@!\20\u023e\u023f\f\16\2\2\u023f\u0240\7\33\2\2\u0240\u0267\5@!\17\u0241"+
|
||||
"\u0242\f\r\2\2\u0242\u0243\7$\2\2\u0243\u0267\5@!\16\u0244\u0245\f\f\2"+
|
||||
"\2\u0245\u0246\7%\2\2\u0246\u0267\5@!\r\u0247\u0248\f\13\2\2\u0248\u0249"+
|
||||
"\7\16\2\2\u0249\u024a\5@!\2\u024a\u024b\7\13\2\2\u024b\u024c\5@!\f\u024c"+
|
||||
"\u0267\3\2\2\2\u024d\u024e\f\n\2\2\u024e\u024f\7&\2\2\u024f\u0267\5@!"+
|
||||
"\n\u0250\u0251\f\t\2\2\u0251\u0252\7\'\2\2\u0252\u0267\5@!\t\u0253\u0254"+
|
||||
"\f \2\2\u0254\u0255\7\17\2\2\u0255\u0267\7`\2\2\u0256\u0257\f\37\2\2\u0257"+
|
||||
"\u0258\7\20\2\2\u0258\u0267\7`\2\2\u0259\u025a\f\36\2\2\u025a\u025c\7"+
|
||||
"\b\2\2\u025b\u025d\5B\"\2\u025c\u025b\3\2\2\2\u025c\u025d\3\2\2\2\u025d"+
|
||||
"\u025e\3\2\2\2\u025e\u0267\7\t\2\2\u025f\u0260\f\33\2\2\u0260\u0261\7"+
|
||||
"\6\2\2\u0261\u0262\5> \2\u0262\u0263\7\7\2\2\u0263\u0267\3\2\2\2\u0264"+
|
||||
"\u0265\f\30\2\2\u0265\u0267\t\3\2\2\u0266\u022c\3\2\2\2\u0266\u022f\3"+
|
||||
"\2\2\2\u0266\u0232\3\2\2\2\u0266\u0235\3\2\2\2\u0266\u0238\3\2\2\2\u0266"+
|
||||
"\u023b\3\2\2\2\u0266\u023e\3\2\2\2\u0266\u0241\3\2\2\2\u0266\u0244\3\2"+
|
||||
"\2\2\u0266\u0247\3\2\2\2\u0266\u024d\3\2\2\2\u0266\u0250\3\2\2\2\u0266"+
|
||||
"\u0253\3\2\2\2\u0266\u0256\3\2\2\2\u0266\u0259\3\2\2\2\u0266\u025f\3\2"+
|
||||
"\2\2\u0266\u0264\3\2\2\2\u0267\u026a\3\2\2\2\u0268\u0266\3\2\2\2\u0268"+
|
||||
"\u0269\3\2\2\2\u0269A\3\2\2\2\u026a\u0268\3\2\2\2\u026b\u0270\5@!\2\u026c"+
|
||||
"\u026d\7\f\2\2\u026d\u026f\5@!\2\u026e\u026c\3\2\2\2\u026f\u0272\3\2\2"+
|
||||
"\2\u0270\u026e\3\2\2\2\u0270\u0271\3\2\2\2\u0271C\3\2\2\2\u0272\u0270"+
|
||||
"\3\2\2\2\u0273\u0275\7J\2\2\u0274\u0276\5F$\2\u0275\u0274\3\2\2\2\u0275"+
|
||||
"\u0276\3\2\2\2\u0276\u0277\3\2\2\2\u0277\u0278\7T\2\2\u0278E\3\2\2\2\u0279"+
|
||||
"\u027a\7\b\2\2\u027a\u027f\5H%\2\u027b\u027c\7\f\2\2\u027c\u027e\5H%\2"+
|
||||
"\u027d\u027b\3\2\2\2\u027e\u0281\3\2\2\2\u027f\u027d\3\2\2\2\u027f\u0280"+
|
||||
"\3\2\2\2\u0280\u0282\3\2\2\2\u0281\u027f\3\2\2\2\u0282\u0283\7\t\2\2\u0283"+
|
||||
"G\3\2\2\2\u0284\u0285\7K\2\2\u0285\u0294\7U\2\2\u0286\u0287\7L\2\2\u0287"+
|
||||
"\u0294\7`\2\2\u0288\u0289\7M\2\2\u0289\u0294\7U\2\2\u028a\u028b\7N\2\2"+
|
||||
"\u028b\u0294\5@!\2\u028c\u028d\7O\2\2\u028d\u0294\5@!\2\u028e\u0291\7"+
|
||||
",\2\2\u028f\u0292\7\67\2\2\u0290\u0292\5@!\2\u0291\u028f\3\2\2\2\u0291"+
|
||||
"\u0290\3\2\2\2\u0292\u0294\3\2\2\2\u0293\u0284\3\2\2\2\u0293\u0286\3\2"+
|
||||
"\2\2\u0293\u0288\3\2\2\2\u0293\u028a\3\2\2\2\u0293\u028c\3\2\2\2\u0293"+
|
||||
"\u028e\3\2\2\2\u0294I\3\2\2\2\u0295\u0297\5L\'\2\u0296\u0295\3\2\2\2\u0297"+
|
||||
"\u029a\3\2\2\2\u0298\u0296\3\2\2\2\u0298\u0299\3\2\2\2\u0299K\3\2\2\2"+
|
||||
"\u029a\u0298\3\2\2\2\u029b\u029f\5N(\2\u029c\u029f\5P)\2\u029d\u029f\5"+
|
||||
"R*\2\u029e\u029b\3\2\2\2\u029e\u029c\3\2\2\2\u029e\u029d\3\2\2\2\u029f"+
|
||||
"M\3\2\2\2\u02a0\u02a1\7\u0084\2\2\u02a1\u02a5\7g\2\2\u02a2\u02a3\7\u0083"+
|
||||
"\2\2\u02a3\u02a5\7g\2\2\u02a4\u02a0\3\2\2\2\u02a4\u02a2\3\2\2\2\u02a5"+
|
||||
"O\3\2\2\2\u02a6\u02a8\7e\2\2\u02a7\u02a9\5T+\2\u02a8\u02a7\3\2\2\2\u02a8"+
|
||||
"\u02a9\3\2\2\2\u02a9Q\3\2\2\2\u02aa\u02ab\7d\2\2\u02ab\u02b0\5V,\2\u02ac"+
|
||||
"\u02ad\7h\2\2\u02ad\u02af\5V,\2\u02ae\u02ac\3\2\2\2\u02af\u02b2\3\2\2"+
|
||||
"\2\u02b0\u02ae\3\2\2\2\u02b0\u02b1\3\2\2\2\u02b1S\3\2\2\2\u02b2\u02b0"+
|
||||
"\3\2\2\2\u02b3\u02cb\5V,\2\u02b4\u02b5\7f\2\2\u02b5\u02cb\5V,\2\u02b6"+
|
||||
"\u02b7\5V,\2\u02b7\u02b8\7h\2\2\u02b8\u02b9\7\u0084\2\2\u02b9\u02cb\3"+
|
||||
"\2\2\2\u02ba\u02bb\7i\2\2\u02bb\u02bc\5V,\2\u02bc\u02bd\7j\2\2\u02bd\u02be"+
|
||||
"\7h\2\2\u02be\u02bf\7\u0084\2\2\u02bf\u02cb\3\2\2\2\u02c0\u02c1\7i\2\2"+
|
||||
"\u02c1\u02c2\5V,\2\u02c2\u02c3\7h\2\2\u02c3\u02c4\7\u0084\2\2\u02c4\u02c5"+
|
||||
"\7j\2\2\u02c5\u02cb\3\2\2\2\u02c6\u02c7\7i\2\2\u02c7\u02c8\5V,\2\u02c8"+
|
||||
"\u02c9\7j\2\2\u02c9\u02cb\3\2\2\2\u02ca\u02b3\3\2\2\2\u02ca\u02b4\3\2"+
|
||||
"\2\2\u02ca\u02b6\3\2\2\2\u02ca\u02ba\3\2\2\2\u02ca\u02c0\3\2\2\2\u02ca"+
|
||||
"\u02c6\3\2\2\2\u02cbU\3\2\2\2\u02cc\u02cd\b,\1\2\u02cd\u02ce\7k\2\2\u02ce"+
|
||||
"\u02cf\5V,\2\u02cf\u02d0\7l\2\2\u02d0\u02db\3\2\2\2\u02d1\u02d2\t\n\2"+
|
||||
"\2\u02d2\u02db\5V,\n\u02d3\u02db\7\u0084\2\2\u02d4\u02db\7\u0082\2\2\u02d5"+
|
||||
"\u02d6\7v\2\2\u02d6\u02d7\7\u0084\2\2\u02d7\u02db\7w\2\2\u02d8\u02db\7"+
|
||||
"x\2\2\u02d9\u02db\7\u0081\2\2\u02da\u02cc\3\2\2\2\u02da\u02d1\3\2\2\2"+
|
||||
"\u02da\u02d3\3\2\2\2\u02da\u02d4\3\2\2\2\u02da\u02d5\3\2\2\2\u02da\u02d8"+
|
||||
"\3\2\2\2\u02da\u02d9\3\2\2\2\u02db\u02ea\3\2\2\2\u02dc\u02dd\f\f\2\2\u02dd"+
|
||||
"\u02de\7m\2\2\u02de\u02e9\5V,\r\u02df\u02e0\f\13\2\2\u02e0\u02e1\t\13"+
|
||||
"\2\2\u02e1\u02e9\5V,\f\u02e2\u02e3\f\t\2\2\u02e3\u02e4\t\f\2\2\u02e4\u02e9"+
|
||||
"\5V,\n\u02e5\u02e6\f\b\2\2\u02e6\u02e7\t\r\2\2\u02e7\u02e9\5V,\t\u02e8"+
|
||||
"\u02dc\3\2\2\2\u02e8\u02df\3\2\2\2\u02e8\u02e2\3\2\2\2\u02e8\u02e5\3\2"+
|
||||
"\2\2\u02e9\u02ec\3\2\2\2\u02ea\u02e8\3\2\2\2\u02ea\u02eb\3\2\2\2\u02eb"+
|
||||
"W\3\2\2\2\u02ec\u02ea\3\2\2\2Gafz\u0084\u008b\u0099\u009f\u00a4\u00aa"+
|
||||
"\u00af\u00b8\u00bf\u00ca\u00f2\u00ff\u0107\u0110\u0114\u0119\u0120\u012d"+
|
||||
"\u0132\u013e\u014c\u015f\u0168\u016f\u0174\u0179\u017b\u0181\u0188\u018b"+
|
||||
"\u0193\u0196\u0199\u01a3\u01aa\u01b1\u01b7\u01b9\u01c1\u01c7\u01d3\u01e1"+
|
||||
"\u01e7\u01f1\u01fd\u0205\u021c\u0226\u022a\u025c\u0266\u0268\u0270\u0275"+
|
||||
"\u027f\u0291\u0293\u0298\u029e\u02a4\u02a8\u02b0\u02ca\u02da\u02e8\u02ea";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.parser.*;
|
||||
import dk.camelot64.kickc.NumberParser;
|
||||
import dk.camelot64.kickc.SourceLoader;
|
||||
import dk.camelot64.kickc.asm.AsmClobber;
|
||||
@ -10,7 +9,13 @@ import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
import dk.camelot64.kickc.model.types.*;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import dk.camelot64.kickc.parser.CParser;
|
||||
import dk.camelot64.kickc.parser.KickCParser;
|
||||
import dk.camelot64.kickc.parser.KickCParserBaseVisitor;
|
||||
import org.antlr.v4.runtime.BufferedTokenStream;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.misc.Interval;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
@ -100,10 +105,10 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
|
||||
@Override
|
||||
public Object visitGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx) {
|
||||
List<Number> reservedZps = new ArrayList<>();
|
||||
List<Integer> reservedZps = new ArrayList<>();
|
||||
for(TerminalNode reservedNum : ctx.NUMBER()) {
|
||||
Number reservedZp = NumberParser.parseLiteral(reservedNum.getText());
|
||||
reservedZps.add(reservedZp);
|
||||
reservedZps.add(reservedZp.intValue());
|
||||
}
|
||||
program.addReservedZps(reservedZps);
|
||||
return null;
|
||||
@ -663,6 +668,14 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
throw new CompileError("Error! Unknown register " + directiveRegister.getName(), source);
|
||||
}
|
||||
lValue.setDeclaredRegister(register);
|
||||
} else if(directiveRegister.getAddress() != null) {
|
||||
// Allocate to specific address
|
||||
Long address = ((DirectiveRegister) directive).address;
|
||||
if(address>255) {
|
||||
throw new CompileError("Error! Register not on zeropage " + directiveRegister.getAddress(), source);
|
||||
}
|
||||
Registers.Register register = new Registers.RegisterZpDeclared(address.intValue());
|
||||
lValue.setDeclaredRegister(register);
|
||||
}
|
||||
} else {
|
||||
throw new CompileError("Unsupported variable directive " + directive, source);
|
||||
@ -753,11 +766,18 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
|
||||
@Override
|
||||
public Directive visitDirectiveRegister(KickCParser.DirectiveRegisterContext ctx) {
|
||||
String name = null;
|
||||
if(ctx.NAME() != null) {
|
||||
name = ctx.NAME().getText();
|
||||
return new DirectiveRegister(ctx.NAME().getText());
|
||||
} else if(ctx.NUMBER() != null) {
|
||||
try {
|
||||
ConstantInteger registerAddress = NumberParser.parseIntegerLiteral(ctx.NUMBER().getText());
|
||||
return new DirectiveRegister(registerAddress.getInteger());
|
||||
} catch(NumberFormatException e) {
|
||||
throw new CompileError(e.getMessage(), new StatementSource(ctx));
|
||||
}
|
||||
} else {
|
||||
return new DirectiveRegister(null);
|
||||
}
|
||||
return new DirectiveRegister(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -772,9 +792,9 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
|
||||
@Override
|
||||
public Directive visitDirectiveReserveZp(KickCParser.DirectiveReserveZpContext ctx) {
|
||||
List<Number> reservedZps = new ArrayList<>();
|
||||
List<Integer> reservedZps = new ArrayList<>();
|
||||
for(TerminalNode reservedNum : ctx.NUMBER()) {
|
||||
Number reservedZp = NumberParser.parseLiteral(reservedNum.getText());
|
||||
int reservedZp = NumberParser.parseLiteral(reservedNum.getText()).intValue();
|
||||
reservedZps.add(reservedZp);
|
||||
}
|
||||
return new DirectiveReserveZp(reservedZps);
|
||||
@ -1213,10 +1233,10 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
Label continueLabel;
|
||||
if(currentLoop.isSwitch) {
|
||||
continueLabel = currentLoop.getContinueLabel();
|
||||
if(continueLabel==null) {
|
||||
if(continueLabel == null) {
|
||||
throw new CompileError("Continue not inside a loop! ", new StatementSource(ctx));
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
continueLabel = currentLoop.getOrCreateContinueLabel();
|
||||
}
|
||||
Statement continueJmpStmt = new StatementJump(continueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS);
|
||||
@ -1545,11 +1565,12 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
}
|
||||
|
||||
|
||||
/** RValues that have not yet been output as part of a statement.
|
||||
/**
|
||||
* RValues that have not yet been output as part of a statement.
|
||||
* The expression visitor methods updates this so that the surrounding
|
||||
* statement can make sure to output any rValue that has not been output.
|
||||
* Null if we are not currently monitoring this.
|
||||
* */
|
||||
*/
|
||||
public Set<RValue> exprNotConsumed = null;
|
||||
|
||||
/**
|
||||
@ -1569,24 +1590,27 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
/**
|
||||
* Consumes an RValue by outputting it as part of a statement.
|
||||
* This helps ensure that all expression RValues are output in statements
|
||||
*
|
||||
* @param rValue The RValue being consume
|
||||
*/
|
||||
void consumeExpr(RValue rValue) {
|
||||
if(exprNotConsumed!=null)
|
||||
if(exprNotConsumed != null)
|
||||
exprNotConsumed.remove(rValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks an expression that has been produced which has not been output as part of a statement.
|
||||
* When the RValue is output in a statement it will be consumed using {@link #consumeExpr(RValue)}.
|
||||
*
|
||||
* @param rValue The RValue that has been produced but not consumed
|
||||
*/
|
||||
void addExprToConsume(RValue rValue) {
|
||||
if(exprNotConsumed!=null)
|
||||
if(exprNotConsumed != null)
|
||||
exprNotConsumed.add(rValue);
|
||||
}
|
||||
|
||||
/** Examines whether an RValue is in the list of non-consumed RValues.
|
||||
/**
|
||||
* Examines whether an RValue is in the list of non-consumed RValues.
|
||||
*
|
||||
* @return true if the RValue is in the list
|
||||
*/
|
||||
@ -2133,32 +2157,39 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
}
|
||||
}
|
||||
|
||||
/** Variable memory alignment. */
|
||||
/** Variable register allocation. */
|
||||
private static class DirectiveRegister implements Directive {
|
||||
/** Name of register to use for the variable */
|
||||
private String name;
|
||||
/** Address to use as register for the variable */
|
||||
private Long address;
|
||||
|
||||
public DirectiveRegister(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public DirectiveRegister(long address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
public Long getAddress() {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
/** Reservation of zero-page addresses */
|
||||
private static class DirectiveReserveZp implements Directive {
|
||||
List<Number> reservedZp;
|
||||
List<Integer> reservedZp;
|
||||
|
||||
public DirectiveReserveZp(List<Number> reservedZp) {
|
||||
public DirectiveReserveZp(List<Integer> reservedZp) {
|
||||
this.reservedZp = reservedZp;
|
||||
}
|
||||
|
||||
public List<Number> getReservedZp() {
|
||||
public List<Integer> getReservedZp() {
|
||||
return reservedZp;
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,13 @@ package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.Registers;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.symbols.Symbol;
|
||||
import dk.camelot64.kickc.model.symbols.SymbolVariable;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.SymbolVariableRef;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
@ -34,6 +38,14 @@ public class Pass2IdenticalPhiElimination extends Pass2SsaOptimization {
|
||||
RValue rValue = null;
|
||||
boolean identical = true;
|
||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
if(phiRValue.getrValue() instanceof SymbolVariableRef) {
|
||||
SymbolVariable symbolVar = (SymbolVariable) getScope().getSymbol((SymbolVariableRef) phiRValue.getrValue());
|
||||
if(symbolVar.getDeclaredRegister() !=null) {
|
||||
// Do not collapse PHI's for variables with declared registers (this prevents procedure parameters from being turned into constants)
|
||||
identical = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(phiRValue.getrValue().equals(phiVariable.getVariable())) {
|
||||
// Self PHI - skip that
|
||||
continue;
|
||||
@ -43,7 +55,7 @@ public class Pass2IdenticalPhiElimination extends Pass2SsaOptimization {
|
||||
} else {
|
||||
if(!rValue.equals(phiRValue.getrValue())) {
|
||||
identical = false;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||
import dk.camelot64.kickc.model.symbols.Scope;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -24,18 +24,31 @@ public class Pass4RegistersFinalize extends Pass2Base {
|
||||
private int currentZp = 2;
|
||||
|
||||
/** All reserved zeropage addresses not available for the compiler. */
|
||||
private List<Number> reservedZp;
|
||||
private List<Integer> reservedZp;
|
||||
|
||||
public Pass4RegistersFinalize(Program program) {
|
||||
super(program);
|
||||
this.reservedZp = new ArrayList<>();
|
||||
// Add all ZP's declared as reserved
|
||||
this.reservedZp.addAll(program.getReservedZps());
|
||||
// Add all ZP's declared as reserved in a procedure
|
||||
for(Procedure procedure : getSymbols().getAllProcedures(true)) {
|
||||
List<Number> procedureReservedZps = procedure.getReservedZps();
|
||||
List<Integer> procedureReservedZps = procedure.getReservedZps();
|
||||
if(procedureReservedZps!=null) {
|
||||
this.reservedZp.addAll(procedureReservedZps);
|
||||
}
|
||||
}
|
||||
// Add all ZP's declared hardcoded register for a live variable
|
||||
for(Variable variable : getSymbols().getAllVariables(true)) {
|
||||
if(variable.getDeclaredRegister() instanceof Registers.RegisterZpDeclared) {
|
||||
int zp = ((Registers.RegisterZpDeclared) variable.getDeclaredRegister()).getZp();
|
||||
int sizeBytes = variable.getType().getSizeBytes();
|
||||
for(int i=0;i<sizeBytes; i++) {
|
||||
if(!reservedZp.contains(zp+i))
|
||||
this.reservedZp.add(zp+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void allocate(boolean reallocateZp) {
|
||||
@ -43,15 +56,25 @@ public class Pass4RegistersFinalize extends Pass2Base {
|
||||
for(LiveRangeEquivalenceClass equivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
for(VariableRef variableRef : equivalenceClass.getVariables()) {
|
||||
Variable variable = getProgram().getScope().getVariable(variableRef);
|
||||
if(variable.getDeclaredRegister()!=null) {
|
||||
if(equivalenceClass.getRegister()!=null && !variable.getDeclaredRegister().equals(equivalenceClass.getRegister())) {
|
||||
Registers.Register declaredRegister = variable.getDeclaredRegister();
|
||||
if(declaredRegister !=null) {
|
||||
|
||||
if(declaredRegister instanceof Registers.RegisterZpDeclared) {
|
||||
if(declaredRegister.getType().equals(Registers.RegisterType.ZP_VAR)) {
|
||||
Registers.RegisterType registerType = getRegisterType(variable);
|
||||
((Registers.RegisterZpDeclared) declaredRegister).setType(registerType);
|
||||
getLog().append("Setting declared register type "+variable.toString(getProgram())+" to "+registerType);
|
||||
}
|
||||
}
|
||||
|
||||
if(equivalenceClass.getRegister()!=null && !declaredRegister.equals(equivalenceClass.getRegister())) {
|
||||
throw new CompileError("Equivalence class has variables with different declared registers \n" +
|
||||
" - equivalence class: " + equivalenceClass.toString(true) + "\n" +
|
||||
" - one register: " + equivalenceClass.getRegister().toString() + "\n" +
|
||||
" - other register: " + variable.getDeclaredRegister().toString()
|
||||
" - other register: " + declaredRegister.toString()
|
||||
);
|
||||
}
|
||||
equivalenceClass.setRegister(variable.getDeclaredRegister());
|
||||
equivalenceClass.setRegister(declaredRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -148,7 +171,17 @@ public class Pass4RegistersFinalize extends Pass2Base {
|
||||
private void reallocateZpRegisters(LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
|
||||
for(LiveRangeEquivalenceClass equivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
Registers.Register register = equivalenceClass.getRegister();
|
||||
if(register == null || register.isZp()) {
|
||||
boolean reallocate = true;
|
||||
if(register!=null) {
|
||||
if(!register.isZp()) {
|
||||
// Do not allocate non-ZP registers
|
||||
reallocate = false;
|
||||
} else if(register instanceof Registers.RegisterZpDeclared) {
|
||||
// Do not allocate declared ZP registers
|
||||
reallocate = false;
|
||||
}
|
||||
}
|
||||
if(reallocate) {
|
||||
String before = register == null ? null : register.toString();
|
||||
VariableRef variableRef = equivalenceClass.getVariables().get(0);
|
||||
Variable variable = getProgram().getSymbolInfos().getVariable(variableRef);
|
||||
@ -174,7 +207,7 @@ public class Pass4RegistersFinalize extends Pass2Base {
|
||||
reserved = false;
|
||||
int candidateZp = currentZp;
|
||||
for(int i=0;i<size;i++) {
|
||||
if(reservedZp.contains(new Long(candidateZp+i))) {
|
||||
if(reservedZp.contains(new Integer(candidateZp+i))) {
|
||||
reserved = true;
|
||||
currentZp++;
|
||||
break;
|
||||
@ -234,5 +267,41 @@ public class Pass4RegistersFinalize extends Pass2Base {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the register type for a specific variable type.
|
||||
*
|
||||
* @param variable The variable to create a register for.
|
||||
* The register type based on the variable type
|
||||
* @return The zeropage register type
|
||||
*/
|
||||
private Registers.RegisterType getRegisterType(Variable variable) {
|
||||
SymbolType varType = variable.getType();
|
||||
if(SymbolType.BYTE.equals(varType)) {
|
||||
return Registers.RegisterType.ZP_BYTE;
|
||||
} else if(SymbolType.SBYTE.equals(varType)) {
|
||||
return Registers.RegisterType.ZP_BYTE;
|
||||
} else if(SymbolType.WORD.equals(varType)) {
|
||||
return Registers.RegisterType.ZP_WORD;
|
||||
} else if(SymbolType.SWORD.equals(varType)) {
|
||||
return Registers.RegisterType.ZP_WORD;
|
||||
} else if(SymbolType.DWORD.equals(varType)) {
|
||||
return Registers.RegisterType.ZP_DWORD;
|
||||
} else if(SymbolType.SDWORD.equals(varType)) {
|
||||
return Registers.RegisterType.ZP_DWORD;
|
||||
} else if(varType.equals(SymbolType.BOOLEAN)) {
|
||||
return Registers.RegisterType.ZP_BOOL;
|
||||
} else if(varType.equals(SymbolType.VOID)) {
|
||||
// No need to register for VOID value
|
||||
return null;
|
||||
} else if(varType instanceof SymbolTypePointer) {
|
||||
return Registers.RegisterType.ZP_WORD;
|
||||
} else if(varType instanceof SymbolTypeStruct) {
|
||||
return Registers.RegisterType.ZP_STRUCT;
|
||||
} else {
|
||||
throw new RuntimeException("Unhandled variable type " + varType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -2487,6 +2487,21 @@ public class TestPrograms {
|
||||
compileAndCompare("var-register-noarg");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarRegisterZp() throws IOException, URISyntaxException {
|
||||
compileAndCompare("var-register-zp");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarRegisterZp2() throws IOException, URISyntaxException {
|
||||
assertError("var-register-zp-2", "Error! Register not on zeropage");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarRegisterZp3() throws IOException, URISyntaxException {
|
||||
compileAndCompare("var-register-zp-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDword() throws IOException, URISyntaxException {
|
||||
compileAndCompare("dword");
|
||||
|
7
src/test/kc/var-register-zp-2.kc
Normal file
7
src/test/kc/var-register-zp-2.kc
Normal file
@ -0,0 +1,7 @@
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
|
||||
int* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
register(257) char i=0;
|
||||
}
|
20
src/test/kc/var-register-zp-3.kc
Normal file
20
src/test/kc/var-register-zp-3.kc
Normal file
@ -0,0 +1,20 @@
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
|
||||
char* screen = $400;
|
||||
|
||||
void main() {
|
||||
print2(screen, "hello");
|
||||
//print2(screen+80, "hello");
|
||||
}
|
||||
|
||||
void print2(char* register(250) at, char* register(252) msg) {
|
||||
byte j=0;
|
||||
for(byte i=0; msg[i]; i++) {
|
||||
print_char(at, j, msg[i]);
|
||||
j += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void print_char(char* register(250) at, char register(X) idx, char register(A) ch) {
|
||||
at[idx] = ch;
|
||||
}
|
13
src/test/kc/var-register-zp.kc
Normal file
13
src/test/kc/var-register-zp.kc
Normal file
@ -0,0 +1,13 @@
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
|
||||
int* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
register(0x2) char i=0;
|
||||
register(0x4) int j=0;
|
||||
while(i<4) {
|
||||
SCREEN[i++] = j++;
|
||||
int k = (int)i*2;
|
||||
SCREEN[i++] = k;
|
||||
}
|
||||
}
|
50
src/test/ref/var-register-zp-3.asm
Normal file
50
src/test/ref/var-register-zp-3.asm
Normal file
@ -0,0 +1,50 @@
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label screen = $400
|
||||
main: {
|
||||
jsr print2
|
||||
rts
|
||||
msg: .text "hello"
|
||||
.byte 0
|
||||
}
|
||||
// print2(byte* zeropage($fa) at, byte* zeropage($fc) msg)
|
||||
print2: {
|
||||
.label i = 2
|
||||
.label msg = $fc
|
||||
.label at = $fa
|
||||
ldx #0
|
||||
lda #<screen
|
||||
sta.z at
|
||||
lda #>screen
|
||||
sta.z at+1
|
||||
txa
|
||||
sta.z i
|
||||
lda #<main.msg
|
||||
sta.z msg
|
||||
lda #>main.msg
|
||||
sta.z msg+1
|
||||
b1:
|
||||
ldy.z i
|
||||
lda (msg),y
|
||||
cmp #0
|
||||
bne b2
|
||||
rts
|
||||
b2:
|
||||
ldy.z i
|
||||
lda (msg),y
|
||||
jsr print_char
|
||||
inx
|
||||
inx
|
||||
inc.z i
|
||||
jmp b1
|
||||
}
|
||||
// print_char(byte* zeropage($fa) at, byte register(X) idx, byte register(A) ch)
|
||||
print_char: {
|
||||
.label at = $fa
|
||||
stx.z $ff
|
||||
ldy.z $ff
|
||||
sta (at),y
|
||||
rts
|
||||
}
|
48
src/test/ref/var-register-zp-3.cfg
Normal file
48
src/test/ref/var-register-zp-3.cfg
Normal file
@ -0,0 +1,48 @@
|
||||
@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()
|
||||
[5] call print2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[6] return
|
||||
to:@return
|
||||
print2: scope:[print2] from main
|
||||
[7] phi()
|
||||
to:print2::@1
|
||||
print2::@1: scope:[print2] from print2 print2::@3
|
||||
[8] (byte) print2::j#2 ← phi( print2/(byte) 0 print2::@3/(byte) print2::j#1 )
|
||||
[8] (byte*) print2::at#1 ← phi( print2/(const byte*) screen#0 print2::@3/(byte*) print2::at#1 )
|
||||
[8] (byte) print2::i#2 ← phi( print2/(byte) 0 print2::@3/(byte) print2::i#1 )
|
||||
[8] (byte*) print2::msg#1 ← phi( print2/(const string) main::msg print2::@3/(byte*) print2::msg#1 )
|
||||
[9] if((byte) 0!=*((byte*) print2::msg#1 + (byte) print2::i#2)) goto print2::@2
|
||||
to:print2::@return
|
||||
print2::@return: scope:[print2] from print2::@1
|
||||
[10] return
|
||||
to:@return
|
||||
print2::@2: scope:[print2] from print2::@1
|
||||
[11] (byte*) print_char::at#0 ← (byte*) print2::at#1
|
||||
[12] (byte) print_char::idx#0 ← (byte) print2::j#2
|
||||
[13] (byte) print_char::ch#0 ← *((byte*) print2::msg#1 + (byte) print2::i#2)
|
||||
[14] call print_char
|
||||
to:print2::@3
|
||||
print2::@3: scope:[print2] from print2::@2
|
||||
[15] (byte) print2::j#1 ← (byte) print2::j#2 + (byte) 2
|
||||
[16] (byte) print2::i#1 ← ++ (byte) print2::i#2
|
||||
to:print2::@1
|
||||
print_char: scope:[print_char] from print2::@2
|
||||
[17] (byte) print_char::idx#1 ← phi( print2::@2/(byte) print_char::idx#0 )
|
||||
[17] (byte*) print_char::at#1 ← phi( print2::@2/(byte*) print_char::at#0 )
|
||||
[17] (byte) print_char::ch#1 ← phi( print2::@2/(byte) print_char::ch#0 )
|
||||
[18] *((byte*) print_char::at#1 + (byte) print_char::idx#1) ← (byte) print_char::ch#1
|
||||
to:print_char::@return
|
||||
print_char::@return: scope:[print_char] from print_char
|
||||
[19] return
|
||||
to:@return
|
772
src/test/ref/var-register-zp-3.log
Normal file
772
src/test/ref/var-register-zp-3.log
Normal file
@ -0,0 +1,772 @@
|
||||
Warning! Adding boolean cast to non-boolean condition *((byte*) print2::msg + (byte) print2::i)
|
||||
Identified constant variable (byte*) screen
|
||||
Culled Empty Block (label) @1
|
||||
Culled Empty Block (label) print2::@4
|
||||
Culled Empty Block (label) print2::@3
|
||||
Culled Empty Block (label) print2::@5
|
||||
Culled Empty Block (label) print2::@6
|
||||
Culled Empty Block (label) @2
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte*) screen#0 ← ((byte*)) (number) $400
|
||||
to:@3
|
||||
main: scope:[main] from @3
|
||||
(byte*) print2::at#0 ← (byte*) screen#0
|
||||
(byte*) print2::msg#0 ← (const string) main::msg
|
||||
call print2
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
print2: scope:[print2] from main
|
||||
(byte*) print2::at#3 ← phi( main/(byte*) print2::at#0 )
|
||||
(byte*) print2::msg#3 ← phi( main/(byte*) print2::msg#0 )
|
||||
(byte) print2::j#0 ← (number) 0
|
||||
(byte) print2::i#0 ← (number) 0
|
||||
to:print2::@1
|
||||
print2::@1: scope:[print2] from print2 print2::@7
|
||||
(byte) print2::j#4 ← phi( print2/(byte) print2::j#0 print2::@7/(byte) print2::j#1 )
|
||||
(byte*) print2::at#2 ← phi( print2/(byte*) print2::at#3 print2::@7/(byte*) print2::at#4 )
|
||||
(byte) print2::i#2 ← phi( print2/(byte) print2::i#0 print2::@7/(byte) print2::i#1 )
|
||||
(byte*) print2::msg#1 ← phi( print2/(byte*) print2::msg#3 print2::@7/(byte*) print2::msg#4 )
|
||||
(bool~) print2::$1 ← (number) 0 != *((byte*) print2::msg#1 + (byte) print2::i#2)
|
||||
if((bool~) print2::$1) goto print2::@2
|
||||
to:print2::@return
|
||||
print2::@2: scope:[print2] from print2::@1
|
||||
(byte) print2::i#3 ← phi( print2::@1/(byte) print2::i#2 )
|
||||
(byte*) print2::msg#2 ← phi( print2::@1/(byte*) print2::msg#1 )
|
||||
(byte) print2::j#2 ← phi( print2::@1/(byte) print2::j#4 )
|
||||
(byte*) print2::at#1 ← phi( print2::@1/(byte*) print2::at#2 )
|
||||
(byte*) print_char::at#0 ← (byte*) print2::at#1
|
||||
(byte) print_char::idx#0 ← (byte) print2::j#2
|
||||
(byte) print_char::ch#0 ← *((byte*) print2::msg#2 + (byte) print2::i#3)
|
||||
call print_char
|
||||
to:print2::@7
|
||||
print2::@7: scope:[print2] from print2::@2
|
||||
(byte*) print2::at#4 ← phi( print2::@2/(byte*) print2::at#1 )
|
||||
(byte*) print2::msg#4 ← phi( print2::@2/(byte*) print2::msg#2 )
|
||||
(byte) print2::i#4 ← phi( print2::@2/(byte) print2::i#3 )
|
||||
(byte) print2::j#3 ← phi( print2::@2/(byte) print2::j#2 )
|
||||
(byte) print2::j#1 ← (byte) print2::j#3 + (number) 2
|
||||
(byte) print2::i#1 ← ++ (byte) print2::i#4
|
||||
to:print2::@1
|
||||
print2::@return: scope:[print2] from print2::@1
|
||||
return
|
||||
to:@return
|
||||
print_char: scope:[print_char] from print2::@2
|
||||
(byte) print_char::idx#1 ← phi( print2::@2/(byte) print_char::idx#0 )
|
||||
(byte*) print_char::at#1 ← phi( print2::@2/(byte*) print_char::at#0 )
|
||||
(byte) print_char::ch#1 ← phi( print2::@2/(byte) print_char::ch#0 )
|
||||
*((byte*) print_char::at#1 + (byte) print_char::idx#1) ← (byte) print_char::ch#1
|
||||
to:print_char::@return
|
||||
print_char::@return: scope:[print_char] from print_char
|
||||
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()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(const string) main::msg = (string) "hello"
|
||||
(void()) print2((byte*) print2::at , (byte*) print2::msg)
|
||||
(bool~) print2::$1
|
||||
(label) print2::@1
|
||||
(label) print2::@2
|
||||
(label) print2::@7
|
||||
(label) print2::@return
|
||||
(byte*) print2::at !zp ZP_VAR:250
|
||||
(byte*) print2::at#0 !zp ZP_VAR:250
|
||||
(byte*) print2::at#1 !zp ZP_VAR:250
|
||||
(byte*) print2::at#2 !zp ZP_VAR:250
|
||||
(byte*) print2::at#3 !zp ZP_VAR:250
|
||||
(byte*) print2::at#4 !zp ZP_VAR:250
|
||||
(byte) print2::i
|
||||
(byte) print2::i#0
|
||||
(byte) print2::i#1
|
||||
(byte) print2::i#2
|
||||
(byte) print2::i#3
|
||||
(byte) print2::i#4
|
||||
(byte) print2::j
|
||||
(byte) print2::j#0
|
||||
(byte) print2::j#1
|
||||
(byte) print2::j#2
|
||||
(byte) print2::j#3
|
||||
(byte) print2::j#4
|
||||
(byte*) print2::msg !zp ZP_VAR:252
|
||||
(byte*) print2::msg#0 !zp ZP_VAR:252
|
||||
(byte*) print2::msg#1 !zp ZP_VAR:252
|
||||
(byte*) print2::msg#2 !zp ZP_VAR:252
|
||||
(byte*) print2::msg#3 !zp ZP_VAR:252
|
||||
(byte*) print2::msg#4 !zp ZP_VAR:252
|
||||
(void()) print_char((byte*) print_char::at , (byte) print_char::idx , (byte) print_char::ch)
|
||||
(label) print_char::@return
|
||||
(byte*) print_char::at !zp ZP_VAR:250
|
||||
(byte*) print_char::at#0 !zp ZP_VAR:250
|
||||
(byte*) print_char::at#1 !zp ZP_VAR:250
|
||||
(byte) print_char::ch !reg byte a
|
||||
(byte) print_char::ch#0 !reg byte a
|
||||
(byte) print_char::ch#1 !reg byte a
|
||||
(byte) print_char::idx !reg byte x
|
||||
(byte) print_char::idx#0 !reg byte x
|
||||
(byte) print_char::idx#1 !reg byte x
|
||||
(byte*) screen
|
||||
(byte*) screen#0
|
||||
|
||||
Adding number conversion cast (unumber) 0 in (byte) print2::j#0 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (byte) print2::i#0 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (bool~) print2::$1 ← (number) 0 != *((byte*) print2::msg#1 + (byte) print2::i#2)
|
||||
Adding number conversion cast (unumber) 2 in (byte) print2::j#1 ← (byte) print2::j#3 + (number) 2
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte*) screen#0 ← (byte*)(number) $400
|
||||
Inlining cast (byte) print2::j#0 ← (unumber)(number) 0
|
||||
Inlining cast (byte) print2::i#0 ← (unumber)(number) 0
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 2
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 2
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias (byte*) print2::at#1 = (byte*) print2::at#2 (byte*) print2::at#4
|
||||
Alias (byte) print2::j#2 = (byte) print2::j#4 (byte) print2::j#3
|
||||
Alias (byte*) print2::msg#1 = (byte*) print2::msg#2 (byte*) print2::msg#4
|
||||
Alias (byte) print2::i#2 = (byte) print2::i#3 (byte) print2::i#4
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Simple Condition (bool~) print2::$1 [10] if((byte) 0!=*((byte*) print2::msg#1 + (byte) print2::i#2)) goto print2::@2
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant (const byte*) screen#0 = (byte*) 1024
|
||||
Constant (const byte*) print2::msg#0 = main::msg
|
||||
Constant (const byte) print2::j#0 = 0
|
||||
Constant (const byte) print2::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const byte*) print2::at#0 = screen#0
|
||||
Constant (const byte*) print2::msg#3 = print2::msg#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const byte*) print2::at#3 = print2::at#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Inlining constant with var siblings (const byte*) print2::msg#0
|
||||
Inlining constant with var siblings (const byte) print2::j#0
|
||||
Inlining constant with var siblings (const byte) print2::i#0
|
||||
Inlining constant with var siblings (const byte*) print2::at#0
|
||||
Inlining constant with var siblings (const byte*) print2::msg#3
|
||||
Inlining constant with var siblings (const byte*) print2::at#3
|
||||
Constant inlined print2::at#0 = (const byte*) screen#0
|
||||
Constant inlined print2::msg#3 = (const string) main::msg
|
||||
Constant inlined print2::j#0 = (byte) 0
|
||||
Constant inlined print2::msg#0 = (const string) main::msg
|
||||
Constant inlined print2::i#0 = (byte) 0
|
||||
Constant inlined print2::at#3 = (const byte*) screen#0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @4
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@1
|
||||
Adding NOP phi() at start of print2
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
Calls in [main] to print2:6
|
||||
Calls in [print2] to print_char:19
|
||||
|
||||
Created 7 initial phi equivalence classes
|
||||
Coalesced [16] print_char::ch#2 ← print_char::ch#0
|
||||
Coalesced [17] print_char::at#2 ← print_char::at#0
|
||||
Coalesced [18] print_char::idx#2 ← print_char::idx#0
|
||||
Coalesced (already) [22] print2::msg#5 ← print2::msg#1
|
||||
Coalesced [23] print2::i#5 ← print2::i#1
|
||||
Coalesced (already) [24] print2::at#5 ← print2::at#1
|
||||
Coalesced [25] print2::j#5 ← print2::j#1
|
||||
Coalesced down to 7 phi equivalence classes
|
||||
Culled Empty Block (label) @4
|
||||
Culled Empty Block (label) main::@1
|
||||
Renumbering block @3 to @1
|
||||
Renumbering block print2::@7 to print2::@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 print2
|
||||
|
||||
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()
|
||||
[5] call print2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[6] return
|
||||
to:@return
|
||||
print2: scope:[print2] from main
|
||||
[7] phi()
|
||||
to:print2::@1
|
||||
print2::@1: scope:[print2] from print2 print2::@3
|
||||
[8] (byte) print2::j#2 ← phi( print2/(byte) 0 print2::@3/(byte) print2::j#1 )
|
||||
[8] (byte*) print2::at#1 ← phi( print2/(const byte*) screen#0 print2::@3/(byte*) print2::at#1 )
|
||||
[8] (byte) print2::i#2 ← phi( print2/(byte) 0 print2::@3/(byte) print2::i#1 )
|
||||
[8] (byte*) print2::msg#1 ← phi( print2/(const string) main::msg print2::@3/(byte*) print2::msg#1 )
|
||||
[9] if((byte) 0!=*((byte*) print2::msg#1 + (byte) print2::i#2)) goto print2::@2
|
||||
to:print2::@return
|
||||
print2::@return: scope:[print2] from print2::@1
|
||||
[10] return
|
||||
to:@return
|
||||
print2::@2: scope:[print2] from print2::@1
|
||||
[11] (byte*) print_char::at#0 ← (byte*) print2::at#1
|
||||
[12] (byte) print_char::idx#0 ← (byte) print2::j#2
|
||||
[13] (byte) print_char::ch#0 ← *((byte*) print2::msg#1 + (byte) print2::i#2)
|
||||
[14] call print_char
|
||||
to:print2::@3
|
||||
print2::@3: scope:[print2] from print2::@2
|
||||
[15] (byte) print2::j#1 ← (byte) print2::j#2 + (byte) 2
|
||||
[16] (byte) print2::i#1 ← ++ (byte) print2::i#2
|
||||
to:print2::@1
|
||||
print_char: scope:[print_char] from print2::@2
|
||||
[17] (byte) print_char::idx#1 ← phi( print2::@2/(byte) print_char::idx#0 )
|
||||
[17] (byte*) print_char::at#1 ← phi( print2::@2/(byte*) print_char::at#0 )
|
||||
[17] (byte) print_char::ch#1 ← phi( print2::@2/(byte) print_char::ch#0 )
|
||||
[18] *((byte*) print_char::at#1 + (byte) print_char::idx#1) ← (byte) print_char::ch#1
|
||||
to:print_char::@return
|
||||
print_char::@return: scope:[print_char] from print_char
|
||||
[19] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(void()) main()
|
||||
(void()) print2((byte*) print2::at , (byte*) print2::msg)
|
||||
(byte*) print2::at !zp ZP_VAR:250
|
||||
(byte*) print2::at#1 !zp ZP_VAR:250 4.125
|
||||
(byte) print2::i
|
||||
(byte) print2::i#1 22.0
|
||||
(byte) print2::i#2 6.285714285714286
|
||||
(byte) print2::j
|
||||
(byte) print2::j#1 11.0
|
||||
(byte) print2::j#2 5.5
|
||||
(byte*) print2::msg !zp ZP_VAR:252
|
||||
(byte*) print2::msg#1 !zp ZP_VAR:252 5.5
|
||||
(void()) print_char((byte*) print_char::at , (byte) print_char::idx , (byte) print_char::ch)
|
||||
(byte*) print_char::at !zp ZP_VAR:250
|
||||
(byte*) print_char::at#0 !zp ZP_VAR:250 7.333333333333333
|
||||
(byte*) print_char::at#1 !zp ZP_VAR:250 13.0
|
||||
(byte) print_char::ch !reg byte a
|
||||
(byte) print_char::ch#0 !reg byte a 22.0
|
||||
(byte) print_char::ch#1 !reg byte a 13.0
|
||||
(byte) print_char::idx !reg byte x
|
||||
(byte) print_char::idx#0 !reg byte x 11.0
|
||||
(byte) print_char::idx#1 !reg byte x 13.0
|
||||
(byte*) screen
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ print2::msg#1 ]
|
||||
[ print2::i#2 print2::i#1 ]
|
||||
[ print2::at#1 ]
|
||||
[ print2::j#2 print2::j#1 ]
|
||||
[ print_char::ch#1 print_char::ch#0 ]
|
||||
[ print_char::at#1 print_char::at#0 ]
|
||||
[ print_char::idx#1 print_char::idx#0 ]
|
||||
Complete equivalence classes
|
||||
[ print2::msg#1 ]
|
||||
[ print2::i#2 print2::i#1 ]
|
||||
[ print2::at#1 ]
|
||||
[ print2::j#2 print2::j#1 ]
|
||||
[ print_char::ch#1 print_char::ch#0 ]
|
||||
[ print_char::at#1 print_char::at#0 ]
|
||||
[ print_char::idx#1 print_char::idx#0 ]
|
||||
Setting declared register type (byte*) print2::msg#1 to ZP_WORD
|
||||
Setting declared register type (byte*) print2::at#1 to ZP_WORD
|
||||
Setting declared register type (byte*) print_char::at#1 to ZP_WORD
|
||||
Allocated zp ZP_BYTE:2 [ print2::i#2 print2::i#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ print2::j#2 print2::j#1 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic
|
||||
// File Comments
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label screen = $400
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
// [5] call print2
|
||||
// [7] phi from main to print2 [phi:main->print2]
|
||||
print2_from_main:
|
||||
jsr print2
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [6] return
|
||||
rts
|
||||
msg: .text "hello"
|
||||
.byte 0
|
||||
}
|
||||
// print2
|
||||
// print2(byte* zeropage($fa) at, byte* zeropage($fc) msg)
|
||||
print2: {
|
||||
.label j = 3
|
||||
.label i = 2
|
||||
.label msg = $fc
|
||||
.label at = $fa
|
||||
// [8] phi from print2 to print2::@1 [phi:print2->print2::@1]
|
||||
b1_from_print2:
|
||||
// [8] phi (byte) print2::j#2 = (byte) 0 [phi:print2->print2::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z j
|
||||
// [8] phi (byte*) print2::at#1 = (const byte*) screen#0 [phi:print2->print2::@1#1] -- pbuz1=pbuc1
|
||||
lda #<screen
|
||||
sta.z at
|
||||
lda #>screen
|
||||
sta.z at+1
|
||||
// [8] phi (byte) print2::i#2 = (byte) 0 [phi:print2->print2::@1#2] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
// [8] phi (byte*) print2::msg#1 = (const string) main::msg [phi:print2->print2::@1#3] -- pbuz1=pbuc1
|
||||
lda #<main.msg
|
||||
sta.z msg
|
||||
lda #>main.msg
|
||||
sta.z msg+1
|
||||
jmp b1
|
||||
// print2::@1
|
||||
b1:
|
||||
// [9] if((byte) 0!=*((byte*) print2::msg#1 + (byte) print2::i#2)) goto print2::@2 -- vbuc1_neq_pbuz1_derefidx_vbuz2_then_la1
|
||||
ldy.z i
|
||||
lda (msg),y
|
||||
cmp #0
|
||||
bne b2
|
||||
jmp breturn
|
||||
// print2::@return
|
||||
breturn:
|
||||
// [10] return
|
||||
rts
|
||||
// print2::@2
|
||||
b2:
|
||||
// [11] (byte*) print_char::at#0 ← (byte*) print2::at#1
|
||||
// [12] (byte) print_char::idx#0 ← (byte) print2::j#2 -- vbuxx=vbuz1
|
||||
ldx.z j
|
||||
// [13] (byte) print_char::ch#0 ← *((byte*) print2::msg#1 + (byte) print2::i#2) -- vbuaa=pbuz1_derefidx_vbuz2
|
||||
ldy.z i
|
||||
lda (msg),y
|
||||
// [14] call print_char
|
||||
// [17] phi from print2::@2 to print_char [phi:print2::@2->print_char]
|
||||
print_char_from_b2:
|
||||
// [17] phi (byte) print_char::idx#1 = (byte) print_char::idx#0 [phi:print2::@2->print_char#0] -- register_copy
|
||||
// [17] phi (byte*) print_char::at#1 = (byte*) print_char::at#0 [phi:print2::@2->print_char#1] -- register_copy
|
||||
// [17] phi (byte) print_char::ch#1 = (byte) print_char::ch#0 [phi:print2::@2->print_char#2] -- register_copy
|
||||
jsr print_char
|
||||
jmp b3
|
||||
// print2::@3
|
||||
b3:
|
||||
// [15] (byte) print2::j#1 ← (byte) print2::j#2 + (byte) 2 -- vbuz1=vbuz1_plus_2
|
||||
lda.z j
|
||||
clc
|
||||
adc #2
|
||||
sta.z j
|
||||
// [16] (byte) print2::i#1 ← ++ (byte) print2::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [8] phi from print2::@3 to print2::@1 [phi:print2::@3->print2::@1]
|
||||
b1_from_b3:
|
||||
// [8] phi (byte) print2::j#2 = (byte) print2::j#1 [phi:print2::@3->print2::@1#0] -- register_copy
|
||||
// [8] phi (byte*) print2::at#1 = (byte*) print2::at#1 [phi:print2::@3->print2::@1#1] -- register_copy
|
||||
// [8] phi (byte) print2::i#2 = (byte) print2::i#1 [phi:print2::@3->print2::@1#2] -- register_copy
|
||||
// [8] phi (byte*) print2::msg#1 = (byte*) print2::msg#1 [phi:print2::@3->print2::@1#3] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// print_char
|
||||
// print_char(byte* zeropage($fa) at, byte register(X) idx, byte register(A) ch)
|
||||
print_char: {
|
||||
.label at = $fa
|
||||
// [18] *((byte*) print_char::at#1 + (byte) print_char::idx#1) ← (byte) print_char::ch#1 -- pbuz1_derefidx_vbuxx=vbuaa
|
||||
stx.z $ff
|
||||
ldy.z $ff
|
||||
sta (at),y
|
||||
jmp breturn
|
||||
// print_char::@return
|
||||
breturn:
|
||||
// [19] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [9] if((byte) 0!=*((byte*) print2::msg#1 + (byte) print2::i#2)) goto print2::@2 [ print2::msg#1 print2::i#2 print2::at#1 print2::j#2 ] ( main:2::print2:5 [ print2::msg#1 print2::i#2 print2::at#1 print2::j#2 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ print2::i#2 print2::i#1 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ print2::j#2 print2::j#1 ]
|
||||
Statement [13] (byte) print_char::ch#0 ← *((byte*) print2::msg#1 + (byte) print2::i#2) [ print2::msg#1 print2::i#2 print2::at#1 print2::j#2 print_char::at#0 print_char::idx#0 print_char::ch#0 ] ( main:2::print2:5 [ print2::msg#1 print2::i#2 print2::at#1 print2::j#2 print_char::at#0 print_char::idx#0 print_char::ch#0 ] ) always clobbers reg byte a
|
||||
Statement [18] *((byte*) print_char::at#1 + (byte) print_char::idx#1) ← (byte) print_char::ch#1 [ ] ( main:2::print2:5::print_char:14 [ print2::msg#1 print2::i#2 print2::at#1 print2::j#2 ] ) always clobbers reg byte y
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ print2::i#2 print2::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:3 [ print2::j#2 print2::j#1 ]
|
||||
Statement [9] if((byte) 0!=*((byte*) print2::msg#1 + (byte) print2::i#2)) goto print2::@2 [ print2::msg#1 print2::i#2 print2::at#1 print2::j#2 ] ( main:2::print2:5 [ print2::msg#1 print2::i#2 print2::at#1 print2::j#2 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [13] (byte) print_char::ch#0 ← *((byte*) print2::msg#1 + (byte) print2::i#2) [ print2::msg#1 print2::i#2 print2::at#1 print2::j#2 print_char::at#0 print_char::idx#0 print_char::ch#0 ] ( main:2::print2:5 [ print2::msg#1 print2::i#2 print2::at#1 print2::j#2 print_char::at#0 print_char::idx#0 print_char::ch#0 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [18] *((byte*) print_char::at#1 + (byte) print_char::idx#1) ← (byte) print_char::ch#1 [ ] ( main:2::print2:5::print_char:14 [ print2::msg#1 print2::i#2 print2::at#1 print2::j#2 ] ) always clobbers reg byte y
|
||||
Potential registers zp ZP_WORD:252 [ print2::msg#1 ] : zp ZP_WORD:252 ,
|
||||
Potential registers zp ZP_BYTE:2 [ print2::i#2 print2::i#1 ] : zp ZP_BYTE:2 , reg byte x ,
|
||||
Potential registers zp ZP_WORD:250 [ print2::at#1 ] : zp ZP_WORD:250 ,
|
||||
Potential registers zp ZP_BYTE:3 [ print2::j#2 print2::j#1 ] : zp ZP_BYTE:3 , reg byte x ,
|
||||
Potential registers reg byte a [ print_char::ch#1 print_char::ch#0 ] : reg byte a ,
|
||||
Potential registers zp ZP_WORD:250 [ print_char::at#1 print_char::at#0 ] : zp ZP_WORD:250 ,
|
||||
Potential registers reg byte x [ print_char::idx#1 print_char::idx#0 ] : reg byte x ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [print_char] 35: reg byte a [ print_char::ch#1 print_char::ch#0 ] 24: reg byte x [ print_char::idx#1 print_char::idx#0 ] 20.33: zp ZP_WORD:250 [ print_char::at#1 print_char::at#0 ]
|
||||
Uplift Scope [print2] 28.29: zp ZP_BYTE:2 [ print2::i#2 print2::i#1 ] 16.5: zp ZP_BYTE:3 [ print2::j#2 print2::j#1 ] 5.5: zp ZP_WORD:252 [ print2::msg#1 ] 4.12: zp ZP_WORD:250 [ print2::at#1 ]
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [print_char] best 848 combination reg byte a [ print_char::ch#1 print_char::ch#0 ] reg byte x [ print_char::idx#1 print_char::idx#0 ] zp ZP_WORD:250 [ print_char::at#1 print_char::at#0 ]
|
||||
Uplifting [print2] best 728 combination zp ZP_BYTE:2 [ print2::i#2 print2::i#1 ] reg byte x [ print2::j#2 print2::j#1 ] zp ZP_WORD:252 [ print2::msg#1 ] zp ZP_WORD:250 [ print2::at#1 ]
|
||||
Uplifting [main] best 728 combination
|
||||
Uplifting [] best 728 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ print2::i#2 print2::i#1 ]
|
||||
Uplifting [print2] best 728 combination zp ZP_BYTE:2 [ print2::i#2 print2::i#1 ]
|
||||
Coalescing zero page register [ zp ZP_WORD:250 [ print2::at#1 ] ] with [ zp ZP_WORD:250 [ print_char::at#1 print_char::at#0 ] ] - score: 1
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label screen = $400
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
// [5] call print2
|
||||
// [7] phi from main to print2 [phi:main->print2]
|
||||
print2_from_main:
|
||||
jsr print2
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [6] return
|
||||
rts
|
||||
msg: .text "hello"
|
||||
.byte 0
|
||||
}
|
||||
// print2
|
||||
// print2(byte* zeropage($fa) at, byte* zeropage($fc) msg)
|
||||
print2: {
|
||||
.label i = 2
|
||||
.label msg = $fc
|
||||
.label at = $fa
|
||||
// [8] phi from print2 to print2::@1 [phi:print2->print2::@1]
|
||||
b1_from_print2:
|
||||
// [8] phi (byte) print2::j#2 = (byte) 0 [phi:print2->print2::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [8] phi (byte*) print2::at#1 = (const byte*) screen#0 [phi:print2->print2::@1#1] -- pbuz1=pbuc1
|
||||
lda #<screen
|
||||
sta.z at
|
||||
lda #>screen
|
||||
sta.z at+1
|
||||
// [8] phi (byte) print2::i#2 = (byte) 0 [phi:print2->print2::@1#2] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
// [8] phi (byte*) print2::msg#1 = (const string) main::msg [phi:print2->print2::@1#3] -- pbuz1=pbuc1
|
||||
lda #<main.msg
|
||||
sta.z msg
|
||||
lda #>main.msg
|
||||
sta.z msg+1
|
||||
jmp b1
|
||||
// print2::@1
|
||||
b1:
|
||||
// [9] if((byte) 0!=*((byte*) print2::msg#1 + (byte) print2::i#2)) goto print2::@2 -- vbuc1_neq_pbuz1_derefidx_vbuz2_then_la1
|
||||
ldy.z i
|
||||
lda (msg),y
|
||||
cmp #0
|
||||
bne b2
|
||||
jmp breturn
|
||||
// print2::@return
|
||||
breturn:
|
||||
// [10] return
|
||||
rts
|
||||
// print2::@2
|
||||
b2:
|
||||
// [11] (byte*) print_char::at#0 ← (byte*) print2::at#1
|
||||
// [12] (byte) print_char::idx#0 ← (byte) print2::j#2
|
||||
// [13] (byte) print_char::ch#0 ← *((byte*) print2::msg#1 + (byte) print2::i#2) -- vbuaa=pbuz1_derefidx_vbuz2
|
||||
ldy.z i
|
||||
lda (msg),y
|
||||
// [14] call print_char
|
||||
// [17] phi from print2::@2 to print_char [phi:print2::@2->print_char]
|
||||
print_char_from_b2:
|
||||
// [17] phi (byte) print_char::idx#1 = (byte) print_char::idx#0 [phi:print2::@2->print_char#0] -- register_copy
|
||||
// [17] phi (byte*) print_char::at#1 = (byte*) print_char::at#0 [phi:print2::@2->print_char#1] -- register_copy
|
||||
// [17] phi (byte) print_char::ch#1 = (byte) print_char::ch#0 [phi:print2::@2->print_char#2] -- register_copy
|
||||
jsr print_char
|
||||
jmp b3
|
||||
// print2::@3
|
||||
b3:
|
||||
// [15] (byte) print2::j#1 ← (byte) print2::j#2 + (byte) 2 -- vbuxx=vbuxx_plus_2
|
||||
inx
|
||||
inx
|
||||
// [16] (byte) print2::i#1 ← ++ (byte) print2::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [8] phi from print2::@3 to print2::@1 [phi:print2::@3->print2::@1]
|
||||
b1_from_b3:
|
||||
// [8] phi (byte) print2::j#2 = (byte) print2::j#1 [phi:print2::@3->print2::@1#0] -- register_copy
|
||||
// [8] phi (byte*) print2::at#1 = (byte*) print2::at#1 [phi:print2::@3->print2::@1#1] -- register_copy
|
||||
// [8] phi (byte) print2::i#2 = (byte) print2::i#1 [phi:print2::@3->print2::@1#2] -- register_copy
|
||||
// [8] phi (byte*) print2::msg#1 = (byte*) print2::msg#1 [phi:print2::@3->print2::@1#3] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// print_char
|
||||
// print_char(byte* zeropage($fa) at, byte register(X) idx, byte register(A) ch)
|
||||
print_char: {
|
||||
.label at = $fa
|
||||
// [18] *((byte*) print_char::at#1 + (byte) print_char::idx#1) ← (byte) print_char::ch#1 -- pbuz1_derefidx_vbuxx=vbuaa
|
||||
stx.z $ff
|
||||
ldy.z $ff
|
||||
sta (at),y
|
||||
jmp breturn
|
||||
// print_char::@return
|
||||
breturn:
|
||||
// [19] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp b3
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing instruction lda #0 with TXA
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction main_from_b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction print2_from_main:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_print2:
|
||||
Removing instruction breturn:
|
||||
Removing instruction print_char_from_b2:
|
||||
Removing instruction b3:
|
||||
Removing instruction b1_from_b3:
|
||||
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()) main()
|
||||
(label) main::@return
|
||||
(const string) main::msg msg = (string) "hello"
|
||||
(void()) print2((byte*) print2::at , (byte*) print2::msg)
|
||||
(label) print2::@1
|
||||
(label) print2::@2
|
||||
(label) print2::@3
|
||||
(label) print2::@return
|
||||
(byte*) print2::at !zp ZP_WORD:250
|
||||
(byte*) print2::at#1 at !zp ZP_WORD:250 4.125
|
||||
(byte) print2::i
|
||||
(byte) print2::i#1 i zp ZP_BYTE:2 22.0
|
||||
(byte) print2::i#2 i zp ZP_BYTE:2 6.285714285714286
|
||||
(byte) print2::j
|
||||
(byte) print2::j#1 reg byte x 11.0
|
||||
(byte) print2::j#2 reg byte x 5.5
|
||||
(byte*) print2::msg !zp ZP_WORD:252
|
||||
(byte*) print2::msg#1 msg !zp ZP_WORD:252 5.5
|
||||
(void()) print_char((byte*) print_char::at , (byte) print_char::idx , (byte) print_char::ch)
|
||||
(label) print_char::@return
|
||||
(byte*) print_char::at !zp ZP_WORD:250
|
||||
(byte*) print_char::at#0 at !zp ZP_WORD:250 7.333333333333333
|
||||
(byte*) print_char::at#1 at !zp ZP_WORD:250 13.0
|
||||
(byte) print_char::ch !reg byte a
|
||||
(byte) print_char::ch#0 !reg byte a 22.0
|
||||
(byte) print_char::ch#1 !reg byte a 13.0
|
||||
(byte) print_char::idx !reg byte x
|
||||
(byte) print_char::idx#0 !reg byte x 11.0
|
||||
(byte) print_char::idx#1 !reg byte x 13.0
|
||||
(byte*) screen
|
||||
(const byte*) screen#0 screen = (byte*) 1024
|
||||
|
||||
zp ZP_WORD:252 [ print2::msg#1 ]
|
||||
zp ZP_BYTE:2 [ print2::i#2 print2::i#1 ]
|
||||
zp ZP_WORD:250 [ print2::at#1 print_char::at#1 print_char::at#0 ]
|
||||
reg byte x [ print2::j#2 print2::j#1 ]
|
||||
reg byte a [ print_char::ch#1 print_char::ch#0 ]
|
||||
reg byte x [ print_char::idx#1 print_char::idx#0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 647
|
||||
|
||||
// File Comments
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label screen = $400
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
// print2(screen, "hello")
|
||||
// [5] call print2
|
||||
// [7] phi from main to print2 [phi:main->print2]
|
||||
jsr print2
|
||||
// main::@return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
msg: .text "hello"
|
||||
.byte 0
|
||||
}
|
||||
// print2
|
||||
// print2(byte* zeropage($fa) at, byte* zeropage($fc) msg)
|
||||
print2: {
|
||||
.label i = 2
|
||||
.label msg = $fc
|
||||
.label at = $fa
|
||||
// [8] phi from print2 to print2::@1 [phi:print2->print2::@1]
|
||||
// [8] phi (byte) print2::j#2 = (byte) 0 [phi:print2->print2::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [8] phi (byte*) print2::at#1 = (const byte*) screen#0 [phi:print2->print2::@1#1] -- pbuz1=pbuc1
|
||||
lda #<screen
|
||||
sta.z at
|
||||
lda #>screen
|
||||
sta.z at+1
|
||||
// [8] phi (byte) print2::i#2 = (byte) 0 [phi:print2->print2::@1#2] -- vbuz1=vbuc1
|
||||
txa
|
||||
sta.z i
|
||||
// [8] phi (byte*) print2::msg#1 = (const string) main::msg [phi:print2->print2::@1#3] -- pbuz1=pbuc1
|
||||
lda #<main.msg
|
||||
sta.z msg
|
||||
lda #>main.msg
|
||||
sta.z msg+1
|
||||
// print2::@1
|
||||
b1:
|
||||
// for(byte i=0; msg[i]; i++)
|
||||
// [9] if((byte) 0!=*((byte*) print2::msg#1 + (byte) print2::i#2)) goto print2::@2 -- vbuc1_neq_pbuz1_derefidx_vbuz2_then_la1
|
||||
ldy.z i
|
||||
lda (msg),y
|
||||
cmp #0
|
||||
bne b2
|
||||
// print2::@return
|
||||
// }
|
||||
// [10] return
|
||||
rts
|
||||
// print2::@2
|
||||
b2:
|
||||
// print_char(at, j, msg[i])
|
||||
// [11] (byte*) print_char::at#0 ← (byte*) print2::at#1
|
||||
// [12] (byte) print_char::idx#0 ← (byte) print2::j#2
|
||||
// [13] (byte) print_char::ch#0 ← *((byte*) print2::msg#1 + (byte) print2::i#2) -- vbuaa=pbuz1_derefidx_vbuz2
|
||||
ldy.z i
|
||||
lda (msg),y
|
||||
// [14] call print_char
|
||||
// [17] phi from print2::@2 to print_char [phi:print2::@2->print_char]
|
||||
// [17] phi (byte) print_char::idx#1 = (byte) print_char::idx#0 [phi:print2::@2->print_char#0] -- register_copy
|
||||
// [17] phi (byte*) print_char::at#1 = (byte*) print_char::at#0 [phi:print2::@2->print_char#1] -- register_copy
|
||||
// [17] phi (byte) print_char::ch#1 = (byte) print_char::ch#0 [phi:print2::@2->print_char#2] -- register_copy
|
||||
jsr print_char
|
||||
// print2::@3
|
||||
// j += 2
|
||||
// [15] (byte) print2::j#1 ← (byte) print2::j#2 + (byte) 2 -- vbuxx=vbuxx_plus_2
|
||||
inx
|
||||
inx
|
||||
// for(byte i=0; msg[i]; i++)
|
||||
// [16] (byte) print2::i#1 ← ++ (byte) print2::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [8] phi from print2::@3 to print2::@1 [phi:print2::@3->print2::@1]
|
||||
// [8] phi (byte) print2::j#2 = (byte) print2::j#1 [phi:print2::@3->print2::@1#0] -- register_copy
|
||||
// [8] phi (byte*) print2::at#1 = (byte*) print2::at#1 [phi:print2::@3->print2::@1#1] -- register_copy
|
||||
// [8] phi (byte) print2::i#2 = (byte) print2::i#1 [phi:print2::@3->print2::@1#2] -- register_copy
|
||||
// [8] phi (byte*) print2::msg#1 = (byte*) print2::msg#1 [phi:print2::@3->print2::@1#3] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// print_char
|
||||
// print_char(byte* zeropage($fa) at, byte register(X) idx, byte register(A) ch)
|
||||
print_char: {
|
||||
.label at = $fa
|
||||
// at[idx] = ch
|
||||
// [18] *((byte*) print_char::at#1 + (byte) print_char::idx#1) ← (byte) print_char::ch#1 -- pbuz1_derefidx_vbuxx=vbuaa
|
||||
stx.z $ff
|
||||
ldy.z $ff
|
||||
sta (at),y
|
||||
// print_char::@return
|
||||
// }
|
||||
// [19] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
41
src/test/ref/var-register-zp-3.sym
Normal file
41
src/test/ref/var-register-zp-3.sym
Normal file
@ -0,0 +1,41 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const string) main::msg msg = (string) "hello"
|
||||
(void()) print2((byte*) print2::at , (byte*) print2::msg)
|
||||
(label) print2::@1
|
||||
(label) print2::@2
|
||||
(label) print2::@3
|
||||
(label) print2::@return
|
||||
(byte*) print2::at !zp ZP_WORD:250
|
||||
(byte*) print2::at#1 at !zp ZP_WORD:250 4.125
|
||||
(byte) print2::i
|
||||
(byte) print2::i#1 i zp ZP_BYTE:2 22.0
|
||||
(byte) print2::i#2 i zp ZP_BYTE:2 6.285714285714286
|
||||
(byte) print2::j
|
||||
(byte) print2::j#1 reg byte x 11.0
|
||||
(byte) print2::j#2 reg byte x 5.5
|
||||
(byte*) print2::msg !zp ZP_WORD:252
|
||||
(byte*) print2::msg#1 msg !zp ZP_WORD:252 5.5
|
||||
(void()) print_char((byte*) print_char::at , (byte) print_char::idx , (byte) print_char::ch)
|
||||
(label) print_char::@return
|
||||
(byte*) print_char::at !zp ZP_WORD:250
|
||||
(byte*) print_char::at#0 at !zp ZP_WORD:250 7.333333333333333
|
||||
(byte*) print_char::at#1 at !zp ZP_WORD:250 13.0
|
||||
(byte) print_char::ch !reg byte a
|
||||
(byte) print_char::ch#0 !reg byte a 22.0
|
||||
(byte) print_char::ch#1 !reg byte a 13.0
|
||||
(byte) print_char::idx !reg byte x
|
||||
(byte) print_char::idx#0 !reg byte x 11.0
|
||||
(byte) print_char::idx#1 !reg byte x 13.0
|
||||
(byte*) screen
|
||||
(const byte*) screen#0 screen = (byte*) 1024
|
||||
|
||||
zp ZP_WORD:252 [ print2::msg#1 ]
|
||||
zp ZP_BYTE:2 [ print2::i#2 print2::i#1 ]
|
||||
zp ZP_WORD:250 [ print2::at#1 print_char::at#1 print_char::at#0 ]
|
||||
reg byte x [ print2::j#2 print2::j#1 ]
|
||||
reg byte a [ print_char::ch#1 print_char::ch#0 ]
|
||||
reg byte x [ print_char::idx#1 print_char::idx#0 ]
|
48
src/test/ref/var-register-zp.asm
Normal file
48
src/test/ref/var-register-zp.asm
Normal file
@ -0,0 +1,48 @@
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
.label _1 = 6
|
||||
.label i = 2
|
||||
.label j = 4
|
||||
.label k = 6
|
||||
lda #<0
|
||||
sta.z j
|
||||
sta.z j+1
|
||||
sta.z i
|
||||
b1:
|
||||
lda.z i
|
||||
cmp #4
|
||||
bcc b2
|
||||
rts
|
||||
b2:
|
||||
lda.z i
|
||||
asl
|
||||
tay
|
||||
lda.z j
|
||||
sta SCREEN,y
|
||||
lda.z j+1
|
||||
sta SCREEN+1,y
|
||||
inc.z i
|
||||
inc.z j
|
||||
bne !+
|
||||
inc.z j+1
|
||||
!:
|
||||
lda.z i
|
||||
sta.z _1
|
||||
lda #0
|
||||
sta.z _1+1
|
||||
asl.z k
|
||||
rol.z k+1
|
||||
lda.z i
|
||||
asl
|
||||
tay
|
||||
lda.z k
|
||||
sta SCREEN,y
|
||||
lda.z k+1
|
||||
sta SCREEN+1,y
|
||||
inc.z i
|
||||
jmp b1
|
||||
}
|
31
src/test/ref/var-register-zp.cfg
Normal file
31
src/test/ref/var-register-zp.cfg
Normal file
@ -0,0 +1,31 @@
|
||||
@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] (signed word) main::j#2 ← phi( main/(signed byte) 0 main::@2/(signed word) main::j#1 )
|
||||
[5] (byte) main::i#3 ← phi( main/(byte) 0 main::@2/(byte) main::i#2 )
|
||||
[6] if((byte) main::i#3<(byte) 4) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[7] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[8] (byte~) main::$3 ← (byte) main::i#3 << (byte) 1
|
||||
[9] *((const signed word*) SCREEN#0 + (byte~) main::$3) ← (signed word) main::j#2
|
||||
[10] (byte) main::i#1 ← ++ (byte) main::i#3
|
||||
[11] (signed word) main::j#1 ← ++ (signed word) main::j#2
|
||||
[12] (signed word~) main::$1 ← (signed word)(byte) main::i#1
|
||||
[13] (signed word) main::k#0 ← (signed word~) main::$1 << (byte) 1
|
||||
[14] (byte~) main::$4 ← (byte) main::i#1 << (byte) 1
|
||||
[15] *((const signed word*) SCREEN#0 + (byte~) main::$4) ← (signed word) main::k#0
|
||||
[16] (byte) main::i#2 ← ++ (byte) main::i#1
|
||||
to:main::@1
|
593
src/test/ref/var-register-zp.log
Normal file
593
src/test/ref/var-register-zp.log
Normal file
@ -0,0 +1,593 @@
|
||||
Fixing pointer array-indexing *((signed word*) SCREEN + (byte) main::i)
|
||||
Fixing pointer array-indexing *((signed word*) SCREEN + (byte) main::i)
|
||||
Identified constant variable (signed word*) SCREEN
|
||||
Culled Empty Block (label) main::@4
|
||||
Culled Empty Block (label) main::@3
|
||||
Culled Empty Block (label) main::@5
|
||||
Culled Empty Block (label) main::@6
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(signed word*) SCREEN#0 ← ((signed word*)) (number) $400
|
||||
to:@1
|
||||
main: scope:[main] from @1
|
||||
(byte) main::i#0 ← (number) 0
|
||||
(signed word) main::j#0 ← (number) 0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
(signed word) main::j#3 ← phi( main/(signed word) main::j#0 main::@2/(signed word) main::j#1 )
|
||||
(byte) main::i#3 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#2 )
|
||||
(bool~) main::$0 ← (byte) main::i#3 < (number) 4
|
||||
if((bool~) main::$0) goto main::@2
|
||||
to:main::@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
(signed word) main::j#2 ← phi( main::@1/(signed word) main::j#3 )
|
||||
(byte) main::i#4 ← phi( main::@1/(byte) main::i#3 )
|
||||
(byte~) main::$3 ← (byte) main::i#4 * (const byte) SIZEOF_SIGNED_WORD
|
||||
*((signed word*) SCREEN#0 + (byte~) main::$3) ← (signed word) main::j#2
|
||||
(byte) main::i#1 ← ++ (byte) main::i#4
|
||||
(signed word) main::j#1 ← ++ (signed word) main::j#2
|
||||
(signed word~) main::$1 ← ((signed word)) (byte) main::i#1
|
||||
(number~) main::$2 ← (signed word~) main::$1 * (number) 2
|
||||
(signed word) main::k#0 ← (number~) main::$2
|
||||
(byte~) main::$4 ← (byte) main::i#1 * (const byte) SIZEOF_SIGNED_WORD
|
||||
*((signed word*) SCREEN#0 + (byte~) main::$4) ← (signed word) main::k#0
|
||||
(byte) main::i#2 ← ++ (byte) main::i#1
|
||||
to:main::@1
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(signed word*) SCREEN
|
||||
(signed word*) SCREEN#0
|
||||
(const byte) SIZEOF_SIGNED_WORD = (byte) 2
|
||||
(void()) main()
|
||||
(bool~) main::$0
|
||||
(signed word~) main::$1
|
||||
(number~) main::$2
|
||||
(byte~) main::$3
|
||||
(byte~) main::$4
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte) main::i !zp ZP_VAR:2
|
||||
(byte) main::i#0 !zp ZP_VAR:2
|
||||
(byte) main::i#1 !zp ZP_VAR:2
|
||||
(byte) main::i#2 !zp ZP_VAR:2
|
||||
(byte) main::i#3 !zp ZP_VAR:2
|
||||
(byte) main::i#4 !zp ZP_VAR:2
|
||||
(signed word) main::j !zp ZP_VAR:4
|
||||
(signed word) main::j#0 !zp ZP_VAR:4
|
||||
(signed word) main::j#1 !zp ZP_VAR:4
|
||||
(signed word) main::j#2 !zp ZP_VAR:4
|
||||
(signed word) main::j#3 !zp ZP_VAR:4
|
||||
(signed word) main::k
|
||||
(signed word) main::k#0
|
||||
|
||||
Adding number conversion cast (unumber) 0 in (byte) main::i#0 ← (number) 0
|
||||
Adding number conversion cast (snumber) 0 in (signed word) main::j#0 ← (number) 0
|
||||
Adding number conversion cast (unumber) 4 in (bool~) main::$0 ← (byte) main::i#3 < (number) 4
|
||||
Adding number conversion cast (snumber) 2 in (number~) main::$2 ← (signed word~) main::$1 * (number) 2
|
||||
Adding number conversion cast (snumber) main::$2 in (number~) main::$2 ← (signed word~) main::$1 * (snumber)(number) 2
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (signed word*) SCREEN#0 ← (signed word*)(number) $400
|
||||
Inlining cast (byte) main::i#0 ← (unumber)(number) 0
|
||||
Inlining cast (signed word) main::j#0 ← (snumber)(number) 0
|
||||
Inlining cast (signed word~) main::$1 ← (signed word)(byte) main::i#1
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (signed word*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 2
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized signed number type (signed byte) 0
|
||||
Finalized unsigned number type (byte) 4
|
||||
Finalized signed number type (signed byte) 2
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Inferred type updated to signed word in (snumber~) main::$2 ← (signed word~) main::$1 * (signed byte) 2
|
||||
Alias (byte) main::i#3 = (byte) main::i#4
|
||||
Alias (signed word) main::j#2 = (signed word) main::j#3
|
||||
Alias (signed word) main::k#0 = (signed word~) main::$2
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Simple Condition (bool~) main::$0 [5] if((byte) main::i#3<(byte) 4) goto main::@2
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant (const signed word*) SCREEN#0 = (signed word*) 1024
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Constant (const signed word) main::j#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Rewriting multiplication to use shift [2] (byte~) main::$3 ← (byte) main::i#3 * (const byte) SIZEOF_SIGNED_WORD
|
||||
Rewriting multiplication to use shift [7] (signed word) main::k#0 ← (signed word~) main::$1 * (signed byte) 2
|
||||
Rewriting multiplication to use shift [8] (byte~) main::$4 ← (byte) main::i#1 * (const byte) SIZEOF_SIGNED_WORD
|
||||
Successful SSA optimization Pass2MultiplyToShiftRewriting
|
||||
Inlining constant with var siblings (const byte) main::i#0
|
||||
Inlining constant with var siblings (const signed word) main::j#0
|
||||
Constant inlined main::i#0 = (byte) 0
|
||||
Constant inlined main::j#0 = (signed byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Eliminating unused constant (const byte) SIZEOF_SIGNED_WORD
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 2 initial phi equivalence classes
|
||||
Coalesced [18] main::i#5 ← main::i#2
|
||||
Coalesced [19] main::j#4 ← main::j#1
|
||||
Coalesced down to 2 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
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
|
||||
|
||||
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] (signed word) main::j#2 ← phi( main/(signed byte) 0 main::@2/(signed word) main::j#1 )
|
||||
[5] (byte) main::i#3 ← phi( main/(byte) 0 main::@2/(byte) main::i#2 )
|
||||
[6] if((byte) main::i#3<(byte) 4) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[7] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[8] (byte~) main::$3 ← (byte) main::i#3 << (byte) 1
|
||||
[9] *((const signed word*) SCREEN#0 + (byte~) main::$3) ← (signed word) main::j#2
|
||||
[10] (byte) main::i#1 ← ++ (byte) main::i#3
|
||||
[11] (signed word) main::j#1 ← ++ (signed word) main::j#2
|
||||
[12] (signed word~) main::$1 ← (signed word)(byte) main::i#1
|
||||
[13] (signed word) main::k#0 ← (signed word~) main::$1 << (byte) 1
|
||||
[14] (byte~) main::$4 ← (byte) main::i#1 << (byte) 1
|
||||
[15] *((const signed word*) SCREEN#0 + (byte~) main::$4) ← (signed word) main::k#0
|
||||
[16] (byte) main::i#2 ← ++ (byte) main::i#1
|
||||
to:main::@1
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(signed word*) SCREEN
|
||||
(void()) main()
|
||||
(signed word~) main::$1 22.0
|
||||
(byte~) main::$3 22.0
|
||||
(byte~) main::$4 22.0
|
||||
(byte) main::i !zp ZP_VAR:2
|
||||
(byte) main::i#1 !zp ZP_VAR:2 5.5
|
||||
(byte) main::i#2 !zp ZP_VAR:2 22.0
|
||||
(byte) main::i#3 !zp ZP_VAR:2 11.0
|
||||
(signed word) main::j !zp ZP_VAR:4
|
||||
(signed word) main::j#1 !zp ZP_VAR:4 3.6666666666666665
|
||||
(signed word) main::j#2 !zp ZP_VAR:4 6.6000000000000005
|
||||
(signed word) main::k
|
||||
(signed word) main::k#0 11.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#3 main::i#2 ]
|
||||
[ main::j#2 main::j#1 ]
|
||||
Added variable main::$3 to zero page equivalence class [ main::$3 ]
|
||||
Added variable main::i#1 to zero page equivalence class [ main::i#1 ]
|
||||
Added variable main::$1 to zero page equivalence class [ main::$1 ]
|
||||
Added variable main::k#0 to zero page equivalence class [ main::k#0 ]
|
||||
Added variable main::$4 to zero page equivalence class [ main::$4 ]
|
||||
Complete equivalence classes
|
||||
[ main::i#3 main::i#2 ]
|
||||
[ main::j#2 main::j#1 ]
|
||||
[ main::$3 ]
|
||||
[ main::i#1 ]
|
||||
[ main::$1 ]
|
||||
[ main::k#0 ]
|
||||
[ main::$4 ]
|
||||
Setting declared register type (byte) main::i#3 to ZP_BYTE
|
||||
Setting declared register type (signed word) main::j#2 to ZP_WORD
|
||||
Allocated zp ZP_BYTE:3 [ main::$3 ]
|
||||
Allocated zp ZP_WORD:6 [ main::$1 ]
|
||||
Allocated zp ZP_WORD:8 [ main::k#0 ]
|
||||
Allocated zp ZP_BYTE:10 [ main::$4 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic
|
||||
// File Comments
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
.label _1 = 6
|
||||
.label _3 = 3
|
||||
.label _4 = $a
|
||||
.label i = 2
|
||||
.label j = 4
|
||||
.label k = 8
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
// [5] phi (signed word) main::j#2 = (signed byte) 0 [phi:main->main::@1#0] -- vwsz1=vbsc1
|
||||
lda #<0
|
||||
sta.z j
|
||||
lda #>0
|
||||
sta.z j+1
|
||||
// [5] phi (byte) main::i#3 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [6] if((byte) main::i#3<(byte) 4) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
|
||||
lda.z i
|
||||
cmp #4
|
||||
bcc b2
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [7] return
|
||||
rts
|
||||
// main::@2
|
||||
b2:
|
||||
// [8] (byte~) main::$3 ← (byte) main::i#3 << (byte) 1 -- vbuz1=vbuz2_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
sta.z _3
|
||||
// [9] *((const signed word*) SCREEN#0 + (byte~) main::$3) ← (signed word) main::j#2 -- pwsc1_derefidx_vbuz1=vwsz2
|
||||
ldy.z _3
|
||||
lda.z j
|
||||
sta SCREEN,y
|
||||
lda.z j+1
|
||||
sta SCREEN+1,y
|
||||
// [10] (byte) main::i#1 ← ++ (byte) main::i#3 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [11] (signed word) main::j#1 ← ++ (signed word) main::j#2 -- vwsz1=_inc_vwsz1
|
||||
inc.z j
|
||||
bne !+
|
||||
inc.z j+1
|
||||
!:
|
||||
// [12] (signed word~) main::$1 ← (signed word)(byte) main::i#1 -- vwsz1=_sword_vbuz2
|
||||
lda.z i
|
||||
sta.z _1
|
||||
lda #0
|
||||
sta.z _1+1
|
||||
// [13] (signed word) main::k#0 ← (signed word~) main::$1 << (byte) 1 -- vwsz1=vwsz2_rol_1
|
||||
lda.z _1
|
||||
asl
|
||||
sta.z k
|
||||
lda.z _1+1
|
||||
rol
|
||||
sta.z k+1
|
||||
// [14] (byte~) main::$4 ← (byte) main::i#1 << (byte) 1 -- vbuz1=vbuz2_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
sta.z _4
|
||||
// [15] *((const signed word*) SCREEN#0 + (byte~) main::$4) ← (signed word) main::k#0 -- pwsc1_derefidx_vbuz1=vwsz2
|
||||
ldy.z _4
|
||||
lda.z k
|
||||
sta SCREEN,y
|
||||
lda.z k+1
|
||||
sta SCREEN+1,y
|
||||
// [16] (byte) main::i#2 ← ++ (byte) main::i#1 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
b1_from_b2:
|
||||
// [5] phi (signed word) main::j#2 = (signed word) main::j#1 [phi:main::@2->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#3 = (byte) main::i#2 [phi:main::@2->main::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [6] if((byte) main::i#3<(byte) 4) goto main::@2 [ main::i#3 main::j#2 ] ( main:2 [ main::i#3 main::j#2 ] ) always clobbers reg byte a
|
||||
Statement [8] (byte~) main::$3 ← (byte) main::i#3 << (byte) 1 [ main::i#3 main::j#2 main::$3 ] ( main:2 [ main::i#3 main::j#2 main::$3 ] ) always clobbers reg byte a
|
||||
Statement [9] *((const signed word*) SCREEN#0 + (byte~) main::$3) ← (signed word) main::j#2 [ main::i#3 main::j#2 ] ( main:2 [ main::i#3 main::j#2 ] ) always clobbers reg byte a
|
||||
Statement [12] (signed word~) main::$1 ← (signed word)(byte) main::i#1 [ main::j#1 main::i#1 main::$1 ] ( main:2 [ main::j#1 main::i#1 main::$1 ] ) always clobbers reg byte a
|
||||
Statement [13] (signed word) main::k#0 ← (signed word~) main::$1 << (byte) 1 [ main::j#1 main::i#1 main::k#0 ] ( main:2 [ main::j#1 main::i#1 main::k#0 ] ) always clobbers reg byte a
|
||||
Statement [14] (byte~) main::$4 ← (byte) main::i#1 << (byte) 1 [ main::j#1 main::i#1 main::k#0 main::$4 ] ( main:2 [ main::j#1 main::i#1 main::k#0 main::$4 ] ) always clobbers reg byte a
|
||||
Statement [15] *((const signed word*) SCREEN#0 + (byte~) main::$4) ← (signed word) main::k#0 [ main::j#1 main::i#1 ] ( main:2 [ main::j#1 main::i#1 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#3 main::i#2 ] : zp ZP_BYTE:2 ,
|
||||
Potential registers zp ZP_WORD:4 [ main::j#2 main::j#1 ] : zp ZP_WORD:4 ,
|
||||
Potential registers zp ZP_BYTE:3 [ main::$3 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#1 ] : zp ZP_BYTE:2 ,
|
||||
Potential registers zp ZP_WORD:6 [ main::$1 ] : zp ZP_WORD:6 ,
|
||||
Potential registers zp ZP_WORD:8 [ main::k#0 ] : zp ZP_WORD:8 ,
|
||||
Potential registers zp ZP_BYTE:10 [ main::$4 ] : zp ZP_BYTE:10 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 33: zp ZP_BYTE:2 [ main::i#3 main::i#2 ] 22: zp ZP_BYTE:3 [ main::$3 ] 22: zp ZP_WORD:6 [ main::$1 ] 22: zp ZP_BYTE:10 [ main::$4 ] 11: zp ZP_WORD:8 [ main::k#0 ] 10.27: zp ZP_WORD:4 [ main::j#2 main::j#1 ] 5.5: zp ZP_BYTE:2 [ main::i#1 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 1288 combination zp ZP_BYTE:2 [ main::i#3 main::i#2 ] reg byte a [ main::$3 ] zp ZP_WORD:6 [ main::$1 ] reg byte a [ main::$4 ] zp ZP_WORD:8 [ main::k#0 ] zp ZP_WORD:4 [ main::j#2 main::j#1 ] zp ZP_BYTE:2 [ main::i#1 ]
|
||||
Uplifting [] best 1288 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::i#3 main::i#2 ]
|
||||
Uplifting [main] best 1288 combination zp ZP_BYTE:2 [ main::i#3 main::i#2 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::i#1 ]
|
||||
Uplifting [main] best 1288 combination zp ZP_BYTE:2 [ main::i#1 ]
|
||||
Coalescing zero page register [ zp ZP_BYTE:2 [ main::i#3 main::i#2 ] ] with [ zp ZP_BYTE:2 [ main::i#1 ] ] - score: 2
|
||||
Coalescing zero page register [ zp ZP_WORD:6 [ main::$1 ] ] with [ zp ZP_WORD:8 [ main::k#0 ] ] - score: 1
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
.label _1 = 6
|
||||
.label i = 2
|
||||
.label j = 4
|
||||
.label k = 6
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
// [5] phi (signed word) main::j#2 = (signed byte) 0 [phi:main->main::@1#0] -- vwsz1=vbsc1
|
||||
lda #<0
|
||||
sta.z j
|
||||
lda #>0
|
||||
sta.z j+1
|
||||
// [5] phi (byte) main::i#3 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [6] if((byte) main::i#3<(byte) 4) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
|
||||
lda.z i
|
||||
cmp #4
|
||||
bcc b2
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [7] return
|
||||
rts
|
||||
// main::@2
|
||||
b2:
|
||||
// [8] (byte~) main::$3 ← (byte) main::i#3 << (byte) 1 -- vbuaa=vbuz1_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
// [9] *((const signed word*) SCREEN#0 + (byte~) main::$3) ← (signed word) main::j#2 -- pwsc1_derefidx_vbuaa=vwsz1
|
||||
tay
|
||||
lda.z j
|
||||
sta SCREEN,y
|
||||
lda.z j+1
|
||||
sta SCREEN+1,y
|
||||
// [10] (byte) main::i#1 ← ++ (byte) main::i#3 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [11] (signed word) main::j#1 ← ++ (signed word) main::j#2 -- vwsz1=_inc_vwsz1
|
||||
inc.z j
|
||||
bne !+
|
||||
inc.z j+1
|
||||
!:
|
||||
// [12] (signed word~) main::$1 ← (signed word)(byte) main::i#1 -- vwsz1=_sword_vbuz2
|
||||
lda.z i
|
||||
sta.z _1
|
||||
lda #0
|
||||
sta.z _1+1
|
||||
// [13] (signed word) main::k#0 ← (signed word~) main::$1 << (byte) 1 -- vwsz1=vwsz1_rol_1
|
||||
asl.z k
|
||||
rol.z k+1
|
||||
// [14] (byte~) main::$4 ← (byte) main::i#1 << (byte) 1 -- vbuaa=vbuz1_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
// [15] *((const signed word*) SCREEN#0 + (byte~) main::$4) ← (signed word) main::k#0 -- pwsc1_derefidx_vbuaa=vwsz1
|
||||
tay
|
||||
lda.z k
|
||||
sta SCREEN,y
|
||||
lda.z k+1
|
||||
sta SCREEN+1,y
|
||||
// [16] (byte) main::i#2 ← ++ (byte) main::i#1 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
b1_from_b2:
|
||||
// [5] phi (signed word) main::j#2 = (signed word) main::j#1 [phi:main::@2->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#3 = (byte) main::i#2 [phi:main::@2->main::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #>0
|
||||
Removing instruction lda #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction main_from_b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_b2:
|
||||
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
|
||||
(signed word*) SCREEN
|
||||
(const signed word*) SCREEN#0 SCREEN = (signed word*) 1024
|
||||
(void()) main()
|
||||
(signed word~) main::$1 $1 zp ZP_WORD:6 22.0
|
||||
(byte~) main::$3 reg byte a 22.0
|
||||
(byte~) main::$4 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte) main::i !zp ZP_BYTE:2
|
||||
(byte) main::i#1 i !zp ZP_BYTE:2 5.5
|
||||
(byte) main::i#2 i !zp ZP_BYTE:2 22.0
|
||||
(byte) main::i#3 i !zp ZP_BYTE:2 11.0
|
||||
(signed word) main::j !zp ZP_WORD:4
|
||||
(signed word) main::j#1 j !zp ZP_WORD:4 3.6666666666666665
|
||||
(signed word) main::j#2 j !zp ZP_WORD:4 6.6000000000000005
|
||||
(signed word) main::k
|
||||
(signed word) main::k#0 k zp ZP_WORD:6 11.0
|
||||
|
||||
zp ZP_BYTE:2 [ main::i#3 main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:4 [ main::j#2 main::j#1 ]
|
||||
reg byte a [ main::$3 ]
|
||||
zp ZP_WORD:6 [ main::$1 main::k#0 ]
|
||||
reg byte a [ main::$4 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 1116
|
||||
|
||||
// File Comments
|
||||
// Test declaring a variable as register on a specific ZP address
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label _1 = 6
|
||||
.label i = 2
|
||||
.label j = 4
|
||||
.label k = 6
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi (signed word) main::j#2 = (signed byte) 0 [phi:main->main::@1#0] -- vwsz1=vbsc1
|
||||
lda #<0
|
||||
sta.z j
|
||||
sta.z j+1
|
||||
// [5] phi (byte) main::i#3 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
|
||||
sta.z i
|
||||
// main::@1
|
||||
b1:
|
||||
// while(i<4)
|
||||
// [6] if((byte) main::i#3<(byte) 4) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
|
||||
lda.z i
|
||||
cmp #4
|
||||
bcc b2
|
||||
// main::@return
|
||||
// }
|
||||
// [7] return
|
||||
rts
|
||||
// main::@2
|
||||
b2:
|
||||
// SCREEN[i++] = j++
|
||||
// [8] (byte~) main::$3 ← (byte) main::i#3 << (byte) 1 -- vbuaa=vbuz1_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
// [9] *((const signed word*) SCREEN#0 + (byte~) main::$3) ← (signed word) main::j#2 -- pwsc1_derefidx_vbuaa=vwsz1
|
||||
tay
|
||||
lda.z j
|
||||
sta SCREEN,y
|
||||
lda.z j+1
|
||||
sta SCREEN+1,y
|
||||
// SCREEN[i++] = j++;
|
||||
// [10] (byte) main::i#1 ← ++ (byte) main::i#3 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [11] (signed word) main::j#1 ← ++ (signed word) main::j#2 -- vwsz1=_inc_vwsz1
|
||||
inc.z j
|
||||
bne !+
|
||||
inc.z j+1
|
||||
!:
|
||||
// (int)i
|
||||
// [12] (signed word~) main::$1 ← (signed word)(byte) main::i#1 -- vwsz1=_sword_vbuz2
|
||||
lda.z i
|
||||
sta.z _1
|
||||
lda #0
|
||||
sta.z _1+1
|
||||
// k = (int)i*2
|
||||
// [13] (signed word) main::k#0 ← (signed word~) main::$1 << (byte) 1 -- vwsz1=vwsz1_rol_1
|
||||
asl.z k
|
||||
rol.z k+1
|
||||
// SCREEN[i++] = k
|
||||
// [14] (byte~) main::$4 ← (byte) main::i#1 << (byte) 1 -- vbuaa=vbuz1_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
// [15] *((const signed word*) SCREEN#0 + (byte~) main::$4) ← (signed word) main::k#0 -- pwsc1_derefidx_vbuaa=vwsz1
|
||||
tay
|
||||
lda.z k
|
||||
sta SCREEN,y
|
||||
lda.z k+1
|
||||
sta SCREEN+1,y
|
||||
// SCREEN[i++] = k;
|
||||
// [16] (byte) main::i#2 ← ++ (byte) main::i#1 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
// [5] phi (signed word) main::j#2 = (signed word) main::j#1 [phi:main::@2->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#3 = (byte) main::i#2 [phi:main::@2->main::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
|
27
src/test/ref/var-register-zp.sym
Normal file
27
src/test/ref/var-register-zp.sym
Normal file
@ -0,0 +1,27 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(signed word*) SCREEN
|
||||
(const signed word*) SCREEN#0 SCREEN = (signed word*) 1024
|
||||
(void()) main()
|
||||
(signed word~) main::$1 $1 zp ZP_WORD:6 22.0
|
||||
(byte~) main::$3 reg byte a 22.0
|
||||
(byte~) main::$4 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte) main::i !zp ZP_BYTE:2
|
||||
(byte) main::i#1 i !zp ZP_BYTE:2 5.5
|
||||
(byte) main::i#2 i !zp ZP_BYTE:2 22.0
|
||||
(byte) main::i#3 i !zp ZP_BYTE:2 11.0
|
||||
(signed word) main::j !zp ZP_WORD:4
|
||||
(signed word) main::j#1 j !zp ZP_WORD:4 3.6666666666666665
|
||||
(signed word) main::j#2 j !zp ZP_WORD:4 6.6000000000000005
|
||||
(signed word) main::k
|
||||
(signed word) main::k#0 k zp ZP_WORD:6 11.0
|
||||
|
||||
zp ZP_BYTE:2 [ main::i#3 main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:4 [ main::j#2 main::j#1 ]
|
||||
reg byte a [ main::$3 ]
|
||||
zp ZP_WORD:6 [ main::$1 main::k#0 ]
|
||||
reg byte a [ main::$4 ]
|
@ -15,10 +15,12 @@ main::@1: scope:[main] from main main::@5
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@4
|
||||
[6] (byte) main::y#4 ← phi( main::@1/(byte) 0 main::@4/(byte) main::y#1 )
|
||||
[6] (byte) main::x#4 ← phi( main::@1/(byte) main::x#7 main::@4/(byte) main::x#2 )
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@6
|
||||
[7] (byte) main::x#2 ← phi( main::@2/(byte) main::x#4 main::@6/(byte) main::x#2 )
|
||||
[7] (byte) main::a#2 ← phi( main::@2/(byte) 0 main::@6/(byte) main::a#1 )
|
||||
[8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#7
|
||||
[8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#2
|
||||
[9] (byte) print::idx#0 ← (byte) main::y#4
|
||||
[10] (byte) print::val#0 ← (byte) main::val1#0
|
||||
[11] call print
|
||||
@ -32,15 +34,16 @@ main::@4: scope:[main] from main::@6
|
||||
[15] if((byte) main::y#1!=(byte) $65) goto main::@2
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@4
|
||||
[16] (byte) main::x#1 ← ++ (byte) main::x#7
|
||||
[16] (byte) main::x#1 ← ++ (byte) main::x#2
|
||||
[17] if((byte) main::x#1!=(byte) $65) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@5
|
||||
[18] return
|
||||
to:@return
|
||||
print: scope:[print] from main::@3
|
||||
[19] *((const byte*) print::SCREEN#0 + (byte) print::idx#0) ← (byte) print::val#0
|
||||
[19] (byte) print::idx#1 ← phi( main::@3/(byte) print::idx#0 )
|
||||
[20] *((const byte*) print::SCREEN#0 + (byte) print::idx#1) ← (byte) print::val#0
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
[20] return
|
||||
[21] return
|
||||
to:@return
|
||||
|
@ -127,12 +127,8 @@ Alias (byte) main::a#2 = (byte) main::a#3
|
||||
Alias (byte) main::x#2 = (byte) main::x#5 (byte) main::x#6 (byte) main::x#3
|
||||
Alias (byte) main::y#2 = (byte) main::y#5 (byte) main::y#3
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values (byte) main::x#2 (byte) main::x#4
|
||||
Identical Phi Values (byte) main::y#2 (byte) main::y#4
|
||||
Identical Phi Values (byte) print::val#1 (byte) print::val#0
|
||||
Identical Phi Values (byte) print::idx#1 (byte) print::idx#0
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Identical Phi Values (byte) main::x#4 (byte) main::x#7
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition (bool~) main::$2 [14] if((byte) main::a#1!=rangelast(0,$64)) goto main::@3
|
||||
Simple Condition (bool~) main::$3 [18] if((byte) main::y#1!=rangelast(0,$64)) goto main::@2
|
||||
@ -147,7 +143,7 @@ Resolved ranged next value [12] main::a#1 ← ++ main::a#2 to ++
|
||||
Resolved ranged comparison value [14] if(main::a#1!=rangelast(0,$64)) goto main::@3 to (number) $65
|
||||
Resolved ranged next value [16] main::y#1 ← ++ main::y#4 to ++
|
||||
Resolved ranged comparison value [18] if(main::y#1!=rangelast(0,$64)) goto main::@2 to (number) $65
|
||||
Resolved ranged next value [20] main::x#1 ← ++ main::x#7 to ++
|
||||
Resolved ranged next value [20] main::x#1 ← ++ main::x#2 to ++
|
||||
Resolved ranged comparison value [22] if(main::x#1!=rangelast(0,$64)) goto main::@1 to (number) $65
|
||||
Adding number conversion cast (unumber) $65 in if((byte) main::a#1!=(number) $65) goto main::@3
|
||||
Adding number conversion cast (unumber) $65 in if((byte) main::y#1!=(number) $65) goto main::@2
|
||||
@ -178,13 +174,18 @@ Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
Calls in [main] to print:12
|
||||
Calls in [main] to print:15
|
||||
|
||||
Created 3 initial phi equivalence classes
|
||||
Coalesced [20] main::x#8 ← main::x#1
|
||||
Coalesced [21] main::y#6 ← main::y#1
|
||||
Coalesced [22] main::a#4 ← main::a#1
|
||||
Coalesced down to 3 phi equivalence classes
|
||||
Created 6 initial phi equivalence classes
|
||||
Coalesced [7] main::x#9 ← main::x#7
|
||||
Coalesced [9] main::x#11 ← main::x#4
|
||||
Coalesced [14] print::idx#2 ← print::idx#0
|
||||
Coalesced [23] main::x#8 ← main::x#1
|
||||
Coalesced (already) [24] main::x#10 ← main::x#2
|
||||
Coalesced [25] main::y#6 ← main::y#1
|
||||
Coalesced [26] main::a#4 ← main::a#1
|
||||
Coalesced (already) [27] main::x#12 ← main::x#2
|
||||
Coalesced down to 4 phi equivalence classes
|
||||
Culled Empty Block (label) @3
|
||||
Culled Empty Block (label) main::@8
|
||||
Culled Empty Block (label) main::@9
|
||||
@ -214,10 +215,12 @@ main::@1: scope:[main] from main main::@5
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@4
|
||||
[6] (byte) main::y#4 ← phi( main::@1/(byte) 0 main::@4/(byte) main::y#1 )
|
||||
[6] (byte) main::x#4 ← phi( main::@1/(byte) main::x#7 main::@4/(byte) main::x#2 )
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@6
|
||||
[7] (byte) main::x#2 ← phi( main::@2/(byte) main::x#4 main::@6/(byte) main::x#2 )
|
||||
[7] (byte) main::a#2 ← phi( main::@2/(byte) 0 main::@6/(byte) main::a#1 )
|
||||
[8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#7
|
||||
[8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#2
|
||||
[9] (byte) print::idx#0 ← (byte) main::y#4
|
||||
[10] (byte) print::val#0 ← (byte) main::val1#0
|
||||
[11] call print
|
||||
@ -231,17 +234,18 @@ main::@4: scope:[main] from main::@6
|
||||
[15] if((byte) main::y#1!=(byte) $65) goto main::@2
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@4
|
||||
[16] (byte) main::x#1 ← ++ (byte) main::x#7
|
||||
[16] (byte) main::x#1 ← ++ (byte) main::x#2
|
||||
[17] if((byte) main::x#1!=(byte) $65) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@5
|
||||
[18] return
|
||||
to:@return
|
||||
print: scope:[print] from main::@3
|
||||
[19] *((const byte*) print::SCREEN#0 + (byte) print::idx#0) ← (byte) print::val#0
|
||||
[19] (byte) print::idx#1 ← phi( main::@3/(byte) print::idx#0 )
|
||||
[20] *((const byte*) print::SCREEN#0 + (byte) print::idx#1) ← (byte) print::val#0
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
[20] return
|
||||
[21] return
|
||||
to:@return
|
||||
|
||||
|
||||
@ -254,30 +258,33 @@ VARIABLE REGISTER WEIGHTS
|
||||
(byte) main::val1#0 !reg byte a 1001.0
|
||||
(byte) main::x !reg byte y
|
||||
(byte) main::x#1 !reg byte y 16.5
|
||||
(byte) main::x#7 !reg byte y 93.0
|
||||
(byte) main::x#2 !reg byte y 357.33333333333337
|
||||
(byte) main::x#4 !reg byte y 213.0
|
||||
(byte) main::x#7 !reg byte y 22.0
|
||||
(byte) main::y
|
||||
(byte) main::y#1 151.5
|
||||
(byte) main::y#4 150.375
|
||||
(void()) print((byte) print::idx , (byte) print::val)
|
||||
(byte*) print::SCREEN
|
||||
(byte) print::idx !reg byte x
|
||||
(byte) print::idx#0 !reg byte x 501.5
|
||||
(byte) print::idx#0 !reg byte x 1001.0
|
||||
(byte) print::idx#1 !reg byte x 1003.0
|
||||
(byte) print::val
|
||||
(byte) print::val#0 1003.0
|
||||
(byte) print::val#0 501.5
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::x#7 main::x#1 ]
|
||||
[ main::x#4 main::x#7 main::x#1 main::x#2 ]
|
||||
[ main::y#4 main::y#1 ]
|
||||
[ main::a#2 main::a#1 ]
|
||||
[ print::idx#1 print::idx#0 ]
|
||||
Added variable main::val1#0 to zero page equivalence class [ main::val1#0 ]
|
||||
Added variable print::idx#0 to zero page equivalence class [ print::idx#0 ]
|
||||
Added variable print::val#0 to zero page equivalence class [ print::val#0 ]
|
||||
Complete equivalence classes
|
||||
[ main::x#7 main::x#1 ]
|
||||
[ main::x#4 main::x#7 main::x#1 main::x#2 ]
|
||||
[ main::y#4 main::y#1 ]
|
||||
[ main::a#2 main::a#1 ]
|
||||
[ print::idx#1 print::idx#0 ]
|
||||
[ main::val1#0 ]
|
||||
[ print::idx#0 ]
|
||||
[ print::val#0 ]
|
||||
Allocated zp ZP_BYTE:2 [ main::y#4 main::y#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ main::a#2 main::a#1 ]
|
||||
@ -327,26 +334,30 @@ main: {
|
||||
// [6] phi (byte) main::y#4 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z y
|
||||
// [6] phi (byte) main::x#4 = (byte) main::x#7 [phi:main::@1->main::@2#1] -- register_copy
|
||||
jmp b2
|
||||
// [6] phi from main::@4 to main::@2 [phi:main::@4->main::@2]
|
||||
b2_from_b4:
|
||||
// [6] phi (byte) main::y#4 = (byte) main::y#1 [phi:main::@4->main::@2#0] -- register_copy
|
||||
// [6] phi (byte) main::x#4 = (byte) main::x#2 [phi:main::@4->main::@2#1] -- register_copy
|
||||
jmp b2
|
||||
// main::@2
|
||||
b2:
|
||||
// [7] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
|
||||
b3_from_b2:
|
||||
// [7] phi (byte) main::a#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuz1=vbuc1
|
||||
// [7] phi (byte) main::x#2 = (byte) main::x#4 [phi:main::@2->main::@3#0] -- register_copy
|
||||
// [7] phi (byte) main::a#2 = (byte) 0 [phi:main::@2->main::@3#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z a
|
||||
jmp b3
|
||||
// [7] phi from main::@6 to main::@3 [phi:main::@6->main::@3]
|
||||
b3_from_b6:
|
||||
// [7] phi (byte) main::a#2 = (byte) main::a#1 [phi:main::@6->main::@3#0] -- register_copy
|
||||
// [7] phi (byte) main::x#2 = (byte) main::x#2 [phi:main::@6->main::@3#0] -- register_copy
|
||||
// [7] phi (byte) main::a#2 = (byte) main::a#1 [phi:main::@6->main::@3#1] -- register_copy
|
||||
jmp b3
|
||||
// main::@3
|
||||
b3:
|
||||
// [8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#7 -- vbuaa=vbuz1_plus_vbuyy
|
||||
// [8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#2 -- vbuaa=vbuz1_plus_vbuyy
|
||||
tya
|
||||
clc
|
||||
adc.z a
|
||||
@ -355,6 +366,9 @@ main: {
|
||||
// [10] (byte) print::val#0 ← (byte) main::val1#0 -- vbuz1=vbuaa
|
||||
sta.z print.val
|
||||
// [11] call print
|
||||
// [19] phi from main::@3 to print [phi:main::@3->print]
|
||||
print_from_b3:
|
||||
// [19] phi (byte) print::idx#1 = (byte) print::idx#0 [phi:main::@3->print#0] -- register_copy
|
||||
jsr print
|
||||
jmp b6
|
||||
// main::@6
|
||||
@ -377,7 +391,7 @@ main: {
|
||||
jmp b5
|
||||
// main::@5
|
||||
b5:
|
||||
// [16] (byte) main::x#1 ← ++ (byte) main::x#7 -- vbuyy=_inc_vbuyy
|
||||
// [16] (byte) main::x#1 ← ++ (byte) main::x#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [17] if((byte) main::x#1!=(byte) $65) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
|
||||
cpy #$65
|
||||
@ -393,41 +407,41 @@ main: {
|
||||
print: {
|
||||
.label SCREEN = $400
|
||||
.label val = 4
|
||||
// [19] *((const byte*) print::SCREEN#0 + (byte) print::idx#0) ← (byte) print::val#0 -- pbuc1_derefidx_vbuxx=vbuz1
|
||||
// [20] *((const byte*) print::SCREEN#0 + (byte) print::idx#1) ← (byte) print::val#0 -- pbuc1_derefidx_vbuxx=vbuz1
|
||||
lda.z val
|
||||
sta SCREEN,x
|
||||
jmp breturn
|
||||
// print::@return
|
||||
breturn:
|
||||
// [20] return
|
||||
// [21] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#7 [ main::x#7 main::y#4 main::a#2 main::val1#0 ] ( main:2 [ main::x#7 main::y#4 main::a#2 main::val1#0 ] ) always clobbers reg byte a
|
||||
Statement [8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#2 [ main::y#4 main::x#2 main::a#2 main::val1#0 ] ( main:2 [ main::y#4 main::x#2 main::a#2 main::val1#0 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::y#4 main::y#1 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::a#2 main::a#1 ]
|
||||
Statement [16] (byte) main::x#1 ← ++ (byte) main::x#7 [ main::x#1 ] ( main:2 [ main::x#1 ] ) always clobbers reg byte y
|
||||
Statement [8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#7 [ main::x#7 main::y#4 main::a#2 main::val1#0 ] ( main:2 [ main::x#7 main::y#4 main::a#2 main::val1#0 ] ) always clobbers reg byte a
|
||||
Statement [16] (byte) main::x#1 ← ++ (byte) main::x#7 [ main::x#1 ] ( main:2 [ main::x#1 ] ) always clobbers reg byte y
|
||||
Potential registers reg byte y [ main::x#7 main::x#1 ] : reg byte y ,
|
||||
Statement [16] (byte) main::x#1 ← ++ (byte) main::x#2 [ main::x#1 ] ( main:2 [ main::x#1 ] ) always clobbers reg byte y
|
||||
Statement [8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#2 [ main::y#4 main::x#2 main::a#2 main::val1#0 ] ( main:2 [ main::y#4 main::x#2 main::a#2 main::val1#0 ] ) always clobbers reg byte a
|
||||
Statement [16] (byte) main::x#1 ← ++ (byte) main::x#2 [ main::x#1 ] ( main:2 [ main::x#1 ] ) always clobbers reg byte y
|
||||
Potential registers reg byte y [ main::x#4 main::x#7 main::x#1 main::x#2 ] : reg byte y ,
|
||||
Potential registers zp ZP_BYTE:2 [ main::y#4 main::y#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:3 [ main::a#2 main::a#1 ] : zp ZP_BYTE:3 , reg byte x , reg byte y ,
|
||||
Potential registers reg byte x [ print::idx#1 print::idx#0 ] : reg byte x ,
|
||||
Potential registers reg byte a [ main::val1#0 ] : reg byte a ,
|
||||
Potential registers reg byte x [ print::idx#0 ] : reg byte x ,
|
||||
Potential registers zp ZP_BYTE:4 [ print::val#0 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 2,102.1: zp ZP_BYTE:3 [ main::a#2 main::a#1 ] 1,001: reg byte a [ main::val1#0 ] 301.88: zp ZP_BYTE:2 [ main::y#4 main::y#1 ] 109.5: reg byte y [ main::x#7 main::x#1 ]
|
||||
Uplift Scope [print] 1,003: zp ZP_BYTE:4 [ print::val#0 ] 501.5: reg byte x [ print::idx#0 ]
|
||||
Uplift Scope [main] 2,102.1: zp ZP_BYTE:3 [ main::a#2 main::a#1 ] 1,001: reg byte a [ main::val1#0 ] 608.83: reg byte y [ main::x#4 main::x#7 main::x#1 main::x#2 ] 301.88: zp ZP_BYTE:2 [ main::y#4 main::y#1 ]
|
||||
Uplift Scope [print] 2,004: reg byte x [ print::idx#1 print::idx#0 ] 501.5: zp ZP_BYTE:4 [ print::val#0 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 47460 combination zp ZP_BYTE:3 [ main::a#2 main::a#1 ] reg byte a [ main::val1#0 ] reg byte x [ main::y#4 main::y#1 ] reg byte y [ main::x#7 main::x#1 ]
|
||||
Uplifting [print] best 44457 combination reg byte a [ print::val#0 ] reg byte x [ print::idx#0 ]
|
||||
Uplifting [] best 44457 combination
|
||||
Uplifting [main] best 38469 combination zp ZP_BYTE:3 [ main::a#2 main::a#1 ] reg byte a [ main::val1#0 ] reg byte y [ main::x#4 main::x#7 main::x#1 main::x#2 ] reg byte x [ main::y#4 main::y#1 ]
|
||||
Uplifting [print] best 35466 combination reg byte x [ print::idx#1 print::idx#0 ] reg byte a [ print::val#0 ]
|
||||
Uplifting [] best 35466 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:3 [ main::a#2 main::a#1 ]
|
||||
Uplifting [main] best 44457 combination zp ZP_BYTE:3 [ main::a#2 main::a#1 ]
|
||||
Uplifting [main] best 35466 combination zp ZP_BYTE:3 [ main::a#2 main::a#1 ]
|
||||
Allocated (was zp ZP_BYTE:3) zp ZP_BYTE:2 [ main::a#2 main::a#1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
@ -471,32 +485,39 @@ main: {
|
||||
b2_from_b1:
|
||||
// [6] phi (byte) main::y#4 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [6] phi (byte) main::x#4 = (byte) main::x#7 [phi:main::@1->main::@2#1] -- register_copy
|
||||
jmp b2
|
||||
// [6] phi from main::@4 to main::@2 [phi:main::@4->main::@2]
|
||||
b2_from_b4:
|
||||
// [6] phi (byte) main::y#4 = (byte) main::y#1 [phi:main::@4->main::@2#0] -- register_copy
|
||||
// [6] phi (byte) main::x#4 = (byte) main::x#2 [phi:main::@4->main::@2#1] -- register_copy
|
||||
jmp b2
|
||||
// main::@2
|
||||
b2:
|
||||
// [7] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
|
||||
b3_from_b2:
|
||||
// [7] phi (byte) main::a#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuz1=vbuc1
|
||||
// [7] phi (byte) main::x#2 = (byte) main::x#4 [phi:main::@2->main::@3#0] -- register_copy
|
||||
// [7] phi (byte) main::a#2 = (byte) 0 [phi:main::@2->main::@3#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z a
|
||||
jmp b3
|
||||
// [7] phi from main::@6 to main::@3 [phi:main::@6->main::@3]
|
||||
b3_from_b6:
|
||||
// [7] phi (byte) main::a#2 = (byte) main::a#1 [phi:main::@6->main::@3#0] -- register_copy
|
||||
// [7] phi (byte) main::x#2 = (byte) main::x#2 [phi:main::@6->main::@3#0] -- register_copy
|
||||
// [7] phi (byte) main::a#2 = (byte) main::a#1 [phi:main::@6->main::@3#1] -- register_copy
|
||||
jmp b3
|
||||
// main::@3
|
||||
b3:
|
||||
// [8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#7 -- vbuaa=vbuz1_plus_vbuyy
|
||||
// [8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#2 -- vbuaa=vbuz1_plus_vbuyy
|
||||
tya
|
||||
clc
|
||||
adc.z a
|
||||
// [9] (byte) print::idx#0 ← (byte) main::y#4
|
||||
// [10] (byte) print::val#0 ← (byte) main::val1#0
|
||||
// [11] call print
|
||||
// [19] phi from main::@3 to print [phi:main::@3->print]
|
||||
print_from_b3:
|
||||
// [19] phi (byte) print::idx#1 = (byte) print::idx#0 [phi:main::@3->print#0] -- register_copy
|
||||
jsr print
|
||||
jmp b6
|
||||
// main::@6
|
||||
@ -518,7 +539,7 @@ main: {
|
||||
jmp b5
|
||||
// main::@5
|
||||
b5:
|
||||
// [16] (byte) main::x#1 ← ++ (byte) main::x#7 -- vbuyy=_inc_vbuyy
|
||||
// [16] (byte) main::x#1 ← ++ (byte) main::x#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [17] if((byte) main::x#1!=(byte) $65) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
|
||||
cpy #$65
|
||||
@ -533,12 +554,12 @@ main: {
|
||||
// print(byte register(X) idx, byte register(A) val)
|
||||
print: {
|
||||
.label SCREEN = $400
|
||||
// [19] *((const byte*) print::SCREEN#0 + (byte) print::idx#0) ← (byte) print::val#0 -- pbuc1_derefidx_vbuxx=vbuaa
|
||||
// [20] *((const byte*) print::SCREEN#0 + (byte) print::idx#1) ← (byte) print::val#0 -- pbuc1_derefidx_vbuxx=vbuaa
|
||||
sta SCREEN,x
|
||||
jmp breturn
|
||||
// print::@return
|
||||
breturn:
|
||||
// [20] return
|
||||
// [21] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
@ -570,6 +591,7 @@ Removing instruction b3_from_b6:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction print_from_b3:
|
||||
Removing instruction b6:
|
||||
Removing instruction b4:
|
||||
Removing instruction b5:
|
||||
@ -605,7 +627,9 @@ FINAL SYMBOL TABLE
|
||||
(byte) main::val1#0 !reg byte a 1001.0
|
||||
(byte) main::x !reg byte y
|
||||
(byte) main::x#1 !reg byte y 16.5
|
||||
(byte) main::x#7 !reg byte y 93.0
|
||||
(byte) main::x#2 !reg byte y 357.33333333333337
|
||||
(byte) main::x#4 !reg byte y 213.0
|
||||
(byte) main::x#7 !reg byte y 22.0
|
||||
(byte) main::y
|
||||
(byte) main::y#1 reg byte x 151.5
|
||||
(byte) main::y#4 reg byte x 150.375
|
||||
@ -614,20 +638,21 @@ FINAL SYMBOL TABLE
|
||||
(byte*) print::SCREEN
|
||||
(const byte*) print::SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) print::idx !reg byte x
|
||||
(byte) print::idx#0 !reg byte x 501.5
|
||||
(byte) print::idx#0 !reg byte x 1001.0
|
||||
(byte) print::idx#1 !reg byte x 1003.0
|
||||
(byte) print::val
|
||||
(byte) print::val#0 reg byte a 1003.0
|
||||
(byte) print::val#0 reg byte a 501.5
|
||||
|
||||
reg byte y [ main::x#7 main::x#1 ]
|
||||
reg byte y [ main::x#4 main::x#7 main::x#1 main::x#2 ]
|
||||
reg byte x [ main::y#4 main::y#1 ]
|
||||
zp ZP_BYTE:2 [ main::a#2 main::a#1 ]
|
||||
reg byte x [ print::idx#1 print::idx#0 ]
|
||||
reg byte a [ main::val1#0 ]
|
||||
reg byte x [ print::idx#0 ]
|
||||
reg byte a [ print::val#0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 31452
|
||||
Score: 25458
|
||||
|
||||
// File Comments
|
||||
// Upstart
|
||||
@ -655,20 +680,24 @@ main: {
|
||||
// [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
// [6] phi (byte) main::y#4 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [6] phi (byte) main::x#4 = (byte) main::x#7 [phi:main::@1->main::@2#1] -- register_copy
|
||||
// [6] phi from main::@4 to main::@2 [phi:main::@4->main::@2]
|
||||
// [6] phi (byte) main::y#4 = (byte) main::y#1 [phi:main::@4->main::@2#0] -- register_copy
|
||||
// [6] phi (byte) main::x#4 = (byte) main::x#2 [phi:main::@4->main::@2#1] -- register_copy
|
||||
// main::@2
|
||||
b2:
|
||||
// [7] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
|
||||
// [7] phi (byte) main::a#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuz1=vbuc1
|
||||
// [7] phi (byte) main::x#2 = (byte) main::x#4 [phi:main::@2->main::@3#0] -- register_copy
|
||||
// [7] phi (byte) main::a#2 = (byte) 0 [phi:main::@2->main::@3#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z a
|
||||
// [7] phi from main::@6 to main::@3 [phi:main::@6->main::@3]
|
||||
// [7] phi (byte) main::a#2 = (byte) main::a#1 [phi:main::@6->main::@3#0] -- register_copy
|
||||
// [7] phi (byte) main::x#2 = (byte) main::x#2 [phi:main::@6->main::@3#0] -- register_copy
|
||||
// [7] phi (byte) main::a#2 = (byte) main::a#1 [phi:main::@6->main::@3#1] -- register_copy
|
||||
// main::@3
|
||||
b3:
|
||||
// val1 = a+x
|
||||
// [8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#7 -- vbuaa=vbuz1_plus_vbuyy
|
||||
// [8] (byte) main::val1#0 ← (byte) main::a#2 + (byte) main::x#2 -- vbuaa=vbuz1_plus_vbuyy
|
||||
tya
|
||||
clc
|
||||
adc.z a
|
||||
@ -676,6 +705,8 @@ main: {
|
||||
// [9] (byte) print::idx#0 ← (byte) main::y#4
|
||||
// [10] (byte) print::val#0 ← (byte) main::val1#0
|
||||
// [11] call print
|
||||
// [19] phi from main::@3 to print [phi:main::@3->print]
|
||||
// [19] phi (byte) print::idx#1 = (byte) print::idx#0 [phi:main::@3->print#0] -- register_copy
|
||||
jsr print
|
||||
// main::@6
|
||||
// for( byte a: 0..100 )
|
||||
@ -694,7 +725,7 @@ main: {
|
||||
bne b2
|
||||
// main::@5
|
||||
// for( register(Y) byte x: 0..100 )
|
||||
// [16] (byte) main::x#1 ← ++ (byte) main::x#7 -- vbuyy=_inc_vbuyy
|
||||
// [16] (byte) main::x#1 ← ++ (byte) main::x#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [17] if((byte) main::x#1!=(byte) $65) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
|
||||
cpy #$65
|
||||
@ -709,11 +740,11 @@ main: {
|
||||
print: {
|
||||
.label SCREEN = $400
|
||||
// SCREEN[idx] = val
|
||||
// [19] *((const byte*) print::SCREEN#0 + (byte) print::idx#0) ← (byte) print::val#0 -- pbuc1_derefidx_vbuxx=vbuaa
|
||||
// [20] *((const byte*) print::SCREEN#0 + (byte) print::idx#1) ← (byte) print::val#0 -- pbuc1_derefidx_vbuxx=vbuaa
|
||||
sta SCREEN,x
|
||||
// print::@return
|
||||
// }
|
||||
// [20] return
|
||||
// [21] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
@ -16,7 +16,9 @@
|
||||
(byte) main::val1#0 !reg byte a 1001.0
|
||||
(byte) main::x !reg byte y
|
||||
(byte) main::x#1 !reg byte y 16.5
|
||||
(byte) main::x#7 !reg byte y 93.0
|
||||
(byte) main::x#2 !reg byte y 357.33333333333337
|
||||
(byte) main::x#4 !reg byte y 213.0
|
||||
(byte) main::x#7 !reg byte y 22.0
|
||||
(byte) main::y
|
||||
(byte) main::y#1 reg byte x 151.5
|
||||
(byte) main::y#4 reg byte x 150.375
|
||||
@ -25,13 +27,14 @@
|
||||
(byte*) print::SCREEN
|
||||
(const byte*) print::SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) print::idx !reg byte x
|
||||
(byte) print::idx#0 !reg byte x 501.5
|
||||
(byte) print::idx#0 !reg byte x 1001.0
|
||||
(byte) print::idx#1 !reg byte x 1003.0
|
||||
(byte) print::val
|
||||
(byte) print::val#0 reg byte a 1003.0
|
||||
(byte) print::val#0 reg byte a 501.5
|
||||
|
||||
reg byte y [ main::x#7 main::x#1 ]
|
||||
reg byte y [ main::x#4 main::x#7 main::x#1 main::x#2 ]
|
||||
reg byte x [ main::y#4 main::y#1 ]
|
||||
zp ZP_BYTE:2 [ main::a#2 main::a#1 ]
|
||||
reg byte x [ print::idx#1 print::idx#0 ]
|
||||
reg byte a [ main::val1#0 ]
|
||||
reg byte x [ print::idx#0 ]
|
||||
reg byte a [ print::val#0 ]
|
||||
|
Loading…
x
Reference in New Issue
Block a user