From 21d7c6849c2a07d72592afcbd88235eddc3b8e32 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Mon, 22 Apr 2019 13:47:22 +0200 Subject: [PATCH 01/93] Added tests failing due to constant type interference problems. Working on #181 --- .../java/dk/camelot64/kickc/test/TestPrograms.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 8877be5d6..59d4212f9 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -37,15 +37,15 @@ public class TestPrograms { // compileAndCompare("pointer-cast-3"); //} - //@Test - //public void testTypeIdPlusByteProblem() throws IOException, URISyntaxException { - // compileAndCompare("typeid-plus-byte-problem"); - //} + @Test + public void testTypeIdPlusByteProblem() throws IOException, URISyntaxException { + compileAndCompare("typeid-plus-byte-problem"); + } //@Test - //public void testTypeIdPlusBytes() throws IOException, URISyntaxException { - // compileAndCompare("typeid-plus-bytes"); - //} + public void testTypeIdPlusBytes() throws IOException, URISyntaxException { + compileAndCompare("typeid-plus-bytes"); + } @Test public void testTypeIdSimple() throws IOException, URISyntaxException { From 1fa41859b0663b4550406ebf1e900d30a0ca9c8d Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 23 Apr 2019 20:42:18 +0200 Subject: [PATCH 02/93] Starting work on type system. --- .../kickc/model/types/SymbolTypeMulti.java | 18 ++++++++++ .../kickc/model/values/ConstantInteger.java | 25 +++++++------ .../passes/Pass2ConstantIdentification.java | 35 ++++++++++++------- .../dk/camelot64/kickc/test/TestPrograms.java | 2 +- src/test/kc/typeid-plus-byte-problem.kc | 5 +-- 5 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java index 802810c7f..5b1ca45a5 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java @@ -1,5 +1,6 @@ package dk.camelot64.kickc.model.types; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -11,6 +12,7 @@ public class SymbolTypeMulti implements SymbolType { /** All numeric types. */ public static final SymbolTypeMulti NUMERIC = new SymbolTypeMulti(Arrays.asList(BYTE, SBYTE, WORD, SWORD, DWORD, SDWORD)); + /** * All potential types for the inline constant. */ @@ -24,6 +26,22 @@ public class SymbolTypeMulti implements SymbolType { return types; } + + /** + * Get the multi-type that can contain the passed number. + * @param number The number + * @return The multi-type + */ + public static SymbolType getMultiType(Long number) { + ArrayList<SymbolType> potentialTypes = new ArrayList<>(); + for(SymbolTypeInteger typeInteger : SymbolType.getIntegerTypes()) { + if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) { + potentialTypes.add(typeInteger); + } + } + return new SymbolTypeMulti(potentialTypes); + } + @Override public int getSizeBytes() { // Find the minimal sizeof - and return that diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java index c56e01657..b0131e99e 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java @@ -5,17 +5,23 @@ import dk.camelot64.kickc.model.*; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeMulti; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; -import java.util.ArrayList; - -/** SSA form constant integer value */ +/** Constant integer value */ public class ConstantInteger implements ConstantEnumerable<Long> { private Long number; - public ConstantInteger( Long number) { + /** The type of the number. (Either specific or the multi-type)*/ + private SymbolType type; + + public ConstantInteger(Long number) { this.number = number; + this.type = SymbolTypeMulti.getMultiType(number); + } + + public ConstantInteger(Long number, SymbolType type) { + this.number = number; + this.type = type; } @Override @@ -32,14 +38,7 @@ public class ConstantInteger implements ConstantEnumerable<Long> { } public SymbolType getType() { - ArrayList<SymbolType> potentialTypes = new ArrayList<>(); - Long number = getValue(); - for(SymbolTypeInteger typeInteger : SymbolType.getIntegerTypes()) { - if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) { - potentialTypes.add(typeInteger); - } - } - return new SymbolTypeMulti(potentialTypes); + return type; } @Override diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java index 7ae4366dd..f3c968da0 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java @@ -4,7 +4,9 @@ import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.ControlFlowBlock; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.iterator.ProgramValueIterator; -import dk.camelot64.kickc.model.operators.*; +import dk.camelot64.kickc.model.operators.OperatorBinary; +import dk.camelot64.kickc.model.operators.OperatorUnary; +import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementPhiBlock; @@ -50,7 +52,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { // If the assignment has an operator then replace it with the single constant value if(constVarVal.getAssignment() instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) constVarVal.getAssignment(); - if(assignment.getOperator()!=null) { + if(assignment.getOperator() != null) { getLog().append("Constant right-side identified " + assignment.toString(getProgram(), false)); assignment.setOperator(null); assignment.setrValue1(null); @@ -201,6 +203,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { /** * Examine the right side of an assignment and if it is constant then return the constant value. + * * @param assignment The assignment to examine * @param lValueType The type of the lvalue * @return The constant value if the right side is constant @@ -259,7 +262,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { } if(allConstant && listType != null) { // Constant list confirmed! - return new ConstantArrayList(elements, listType); + return new ConstantArrayList(elements, listType); } } } else if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && assignment.getrValue1() == null) { @@ -307,18 +310,24 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { } static ConstantValue createBinary(ConstantValue c1, OperatorBinary operator, ConstantValue c2, ProgramScope programScope) { + + // Special handling of string append using + + if(Operators.PLUS.equals(operator) && SymbolType.STRING.equals(c1.getType(programScope))) { + if(c1 instanceof ConstantRef) { + c1 = programScope.getConstant((ConstantRef) c1).getValue(); + } + if(c2 instanceof ConstantRef) { + c2 = programScope.getConstant((ConstantRef) c2).getValue(); + } + return new ConstantBinary(c1, operator, c2); + } + + if(Operators.PLUS.equals(operator)) { + return new ConstantBinary(c1, operator, c2); + } + switch(operator.getOperator()) { case "-": - case "+": - if(SymbolType.STRING.equals(c1.getType(programScope))) { - if(c1 instanceof ConstantRef) { - c1 = programScope.getConstant((ConstantRef) c1).getValue(); - } - if(c2 instanceof ConstantRef) { - c2 = programScope.getConstant((ConstantRef) c2).getValue(); - } - return new ConstantBinary(c1, operator, c2); - } case "*": case "/": case "%": diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 59d4212f9..c47e892ae 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -39,7 +39,7 @@ public class TestPrograms { @Test public void testTypeIdPlusByteProblem() throws IOException, URISyntaxException { - compileAndCompare("typeid-plus-byte-problem"); + compileAndCompare("typeid-plus-byte-problem", log()); } //@Test diff --git a/src/test/kc/typeid-plus-byte-problem.kc b/src/test/kc/typeid-plus-byte-problem.kc index c4ddec78f..1b7cc98c6 100644 --- a/src/test/kc/typeid-plus-byte-problem.kc +++ b/src/test/kc/typeid-plus-byte-problem.kc @@ -3,7 +3,8 @@ const byte* SCREEN = $400; void main() { - unsigned byte ubc1 = 250; - SCREEN[0] = ubc1+250; + unsigned byte ubc1 = 12+13+14; + unsigned byte ubc2 = 250; + SCREEN[0] = ubc1+ubc2; } From fd72ecc0c746edcc1b47a9cb22c12742ca24dd29 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 27 Apr 2019 12:12:44 +0200 Subject: [PATCH 03/93] Added syntax for typed integer literal postfix (ub/sb/uc/sc/uw/sw/ui/si/us/ss/ud/sd/ul/sl and l) --- .../java/dk/camelot64/kickc/parser/KickC.g4 | 2 +- .../dk/camelot64/kickc/parser/KickCLexer.java | 614 +++++++++--------- .../dk/camelot64/kickc/test/TestPrograms.java | 2 +- 3 files changed, 310 insertions(+), 308 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 index dbc6688a9..9c0cbfe03 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 +++ b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 @@ -236,7 +236,7 @@ NUMFLOAT : BINFLOAT | DECFLOAT | HEXFLOAT; BINFLOAT : ('%' | '0b' | '0B' ) (BINDIGIT)* '.' BINDIGIT+; DECFLOAT : (DECDIGIT)* '.' DECDIGIT+; HEXFLOAT : ('$' | '0x' | '0X' ) (HEXDIGIT)* '.' HEXDIGIT+; -NUMINT : DECINTEGER | HEXINTEGER | BININTEGER ; +NUMINT : (DECINTEGER | HEXINTEGER | BININTEGER ) ([us][bcwisdl] | 'l')? ; BININTEGER : '0' [bB] BINDIGIT+ | '%' BINDIGIT+ ; DECINTEGER : DECDIGIT+ ; HEXINTEGER : ( '$' | '0x' | '0X' ) HEXDIGIT+ ; diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java index c628f18ce..4b9fc4407 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java @@ -138,7 +138,7 @@ public class KickCLexer extends Lexer { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2b\u03d7\b\1\4\2\t"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2b\u03dc\b\1\4\2\t"+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -186,311 +186,313 @@ public class KickCLexer extends Lexer { "\16V\u034f\13V\3V\3V\6V\u0353\nV\rV\16V\u0354\3W\7W\u0358\nW\fW\16W\u035b"+ "\13W\3W\3W\6W\u035f\nW\rW\16W\u0360\3X\3X\3X\3X\3X\5X\u0368\nX\3X\7X\u036b"+ "\nX\fX\16X\u036e\13X\3X\3X\6X\u0372\nX\rX\16X\u0373\3Y\3Y\3Y\5Y\u0379"+ - "\nY\3Z\3Z\3Z\6Z\u037e\nZ\rZ\16Z\u037f\3Z\3Z\6Z\u0384\nZ\rZ\16Z\u0385\5"+ - "Z\u0388\nZ\3[\6[\u038b\n[\r[\16[\u038c\3\\\3\\\3\\\3\\\3\\\5\\\u0394\n"+ - "\\\3\\\6\\\u0397\n\\\r\\\16\\\u0398\3]\3]\3^\3^\3_\3_\3`\3`\7`\u03a3\n"+ - "`\f`\16`\u03a6\13`\3a\3a\3b\3b\3c\3c\7c\u03ae\nc\fc\16c\u03b1\13c\3c\6"+ - "c\u03b4\nc\rc\16c\u03b5\3d\6d\u03b9\nd\rd\16d\u03ba\3d\3d\3e\3e\3e\3e"+ - "\7e\u03c3\ne\fe\16e\u03c6\13e\3e\3e\3f\3f\3f\3f\7f\u03ce\nf\ff\16f\u03d1"+ - "\13f\3f\3f\3f\3f\3f\4\u02ed\u03cf\2g\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21"+ - "\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30"+ - "/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.["+ - "/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083"+ - "C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097"+ - "M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00ab"+ - "W\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9\2\u00bb\2\u00bd\2\u00bf"+ - "^\u00c1\2\u00c3\2\u00c5_\u00c7`\u00c9a\u00cbb\3\2\r\3\2$$\3\2))\4\2DD"+ - "dd\3\2\62\63\3\2\62;\5\2\62;CHch\5\2C\\aac|\6\2\62;C\\aac|\4\2--//\6\2"+ - "\13\f\17\17\"\"\u00a2\u00a2\4\2\f\f\17\17\2\u0444\2\3\3\2\2\2\2\5\3\2"+ - "\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21"+ - "\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2"+ - "\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3"+ - "\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3"+ - "\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3"+ - "\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2"+ - "\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2"+ - "Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3"+ - "\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2"+ - "\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2"+ - "\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3"+ - "\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2"+ - "\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099"+ - "\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2"+ - "\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab"+ - "\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2"+ - "\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00bf\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7"+ - "\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\3\u00cd\3\2\2\2\5\u00d4\3\2\2"+ - "\2\7\u00d6\3\2\2\2\t\u00d8\3\2\2\2\13\u00da\3\2\2\2\r\u00dc\3\2\2\2\17"+ - "\u00de\3\2\2\2\21\u00e0\3\2\2\2\23\u00e2\3\2\2\2\25\u00e8\3\2\2\2\27\u00ef"+ - "\3\2\2\2\31\u00f5\3\2\2\2\33\u00fe\3\2\2\2\35\u0105\3\2\2\2\37\u010e\3"+ - "\2\2\2!\u0118\3\2\2\2#\u0120\3\2\2\2%\u0123\3\2\2\2\'\u0128\3\2\2\2)\u012e"+ - "\3\2\2\2+\u0131\3\2\2\2-\u0135\3\2\2\2/\u013c\3\2\2\2\61\u0142\3\2\2\2"+ - "\63\u014b\3\2\2\2\65\u014f\3\2\2\2\67\u0151\3\2\2\29\u0154\3\2\2\2;\u015b"+ - "\3\2\2\2=\u0164\3\2\2\2?\u0166\3\2\2\2A\u0168\3\2\2\2C\u016a\3\2\2\2E"+ - "\u0171\3\2\2\2G\u0178\3\2\2\2I\u017b\3\2\2\2K\u017e\3\2\2\2M\u0180\3\2"+ - "\2\2O\u0182\3\2\2\2Q\u0184\3\2\2\2S\u0186\3\2\2\2U\u0188\3\2\2\2W\u018b"+ - "\3\2\2\2Y\u018e\3\2\2\2[\u0190\3\2\2\2]\u0192\3\2\2\2_\u0194\3\2\2\2a"+ - "\u0196\3\2\2\2c\u0199\3\2\2\2e\u019c\3\2\2\2g\u019f\3\2\2\2i\u01a2\3\2"+ - "\2\2k\u01a4\3\2\2\2m\u01a6\3\2\2\2o\u01a9\3\2\2\2q\u01ac\3\2\2\2s\u01ae"+ - "\3\2\2\2u\u01b1\3\2\2\2w\u01b4\3\2\2\2y\u01b7\3\2\2\2{\u01ba\3\2\2\2}"+ - "\u01bd\3\2\2\2\177\u01c1\3\2\2\2\u0081\u01c5\3\2\2\2\u0083\u01c8\3\2\2"+ - "\2\u0085\u01cb\3\2\2\2\u0087\u01ce\3\2\2\2\u0089\u01d6\3\2\2\2\u008b\u01df"+ - "\3\2\2\2\u008d\u01e4\3\2\2\2\u008f\u01ed\3\2\2\2\u0091\u01f3\3\2\2\2\u0093"+ - "\u01fa\3\2\2\2\u0095\u01fd\3\2\2\2\u0097\u0203\3\2\2\2\u0099\u0205\3\2"+ - "\2\2\u009b\u02e5\3\2\2\2\u009d\u02e7\3\2\2\2\u009f\u0318\3\2\2\2\u00a1"+ - "\u031a\3\2\2\2\u00a3\u0327\3\2\2\2\u00a5\u0338\3\2\2\2\u00a7\u033c\3\2"+ - "\2\2\u00a9\u0341\3\2\2\2\u00ab\u0348\3\2\2\2\u00ad\u0359\3\2\2\2\u00af"+ - "\u0367\3\2\2\2\u00b1\u0378\3\2\2\2\u00b3\u0387\3\2\2\2\u00b5\u038a\3\2"+ - "\2\2\u00b7\u0393\3\2\2\2\u00b9\u039a\3\2\2\2\u00bb\u039c\3\2\2\2\u00bd"+ - "\u039e\3\2\2\2\u00bf\u03a0\3\2\2\2\u00c1\u03a7\3\2\2\2\u00c3\u03a9\3\2"+ - "\2\2\u00c5\u03ab\3\2\2\2\u00c7\u03b8\3\2\2\2\u00c9\u03be\3\2\2\2\u00cb"+ - "\u03c9\3\2\2\2\u00cd\u00ce\7k\2\2\u00ce\u00cf\7o\2\2\u00cf\u00d0\7r\2"+ - "\2\u00d0\u00d1\7q\2\2\u00d1\u00d2\7t\2\2\u00d2\u00d3\7v\2\2\u00d3\4\3"+ - "\2\2\2\u00d4\u00d5\7=\2\2\u00d5\6\3\2\2\2\u00d6\u00d7\7.\2\2\u00d7\b\3"+ - "\2\2\2\u00d8\u00d9\7?\2\2\u00d9\n\3\2\2\2\u00da\u00db\7*\2\2\u00db\f\3"+ - "\2\2\2\u00dc\u00dd\7+\2\2\u00dd\16\3\2\2\2\u00de\u00df\7}\2\2\u00df\20"+ - "\3\2\2\2\u00e0\u00e1\7\177\2\2\u00e1\22\3\2\2\2\u00e2\u00e3\7e\2\2\u00e3"+ - "\u00e4\7q\2\2\u00e4\u00e5\7p\2\2\u00e5\u00e6\7u\2\2\u00e6\u00e7\7v\2\2"+ - "\u00e7\24\3\2\2\2\u00e8\u00e9\7g\2\2\u00e9\u00ea\7z\2\2\u00ea\u00eb\7"+ - "v\2\2\u00eb\u00ec\7g\2\2\u00ec\u00ed\7t\2\2\u00ed\u00ee\7p\2\2\u00ee\26"+ - "\3\2\2\2\u00ef\u00f0\7c\2\2\u00f0\u00f1\7n\2\2\u00f1\u00f2\7k\2\2\u00f2"+ - "\u00f3\7i\2\2\u00f3\u00f4\7p\2\2\u00f4\30\3\2\2\2\u00f5\u00f6\7t\2\2\u00f6"+ - "\u00f7\7g\2\2\u00f7\u00f8\7i\2\2\u00f8\u00f9\7k\2\2\u00f9\u00fa\7u\2\2"+ - "\u00fa\u00fb\7v\2\2\u00fb\u00fc\7g\2\2\u00fc\u00fd\7t\2\2\u00fd\32\3\2"+ - "\2\2\u00fe\u00ff\7k\2\2\u00ff\u0100\7p\2\2\u0100\u0101\7n\2\2\u0101\u0102"+ - "\7k\2\2\u0102\u0103\7p\2\2\u0103\u0104\7g\2\2\u0104\34\3\2\2\2\u0105\u0106"+ - "\7x\2\2\u0106\u0107\7q\2\2\u0107\u0108\7n\2\2\u0108\u0109\7c\2\2\u0109"+ - "\u010a\7v\2\2\u010a\u010b\7k\2\2\u010b\u010c\7n\2\2\u010c\u010d\7g\2\2"+ - "\u010d\36\3\2\2\2\u010e\u010f\7k\2\2\u010f\u0110\7p\2\2\u0110\u0111\7"+ - "v\2\2\u0111\u0112\7g\2\2\u0112\u0113\7t\2\2\u0113\u0114\7t\2\2\u0114\u0115"+ - "\7w\2\2\u0115\u0116\7r\2\2\u0116\u0117\7v\2\2\u0117 \3\2\2\2\u0118\u0119"+ - "\7t\2\2\u0119\u011a\7g\2\2\u011a\u011b\7u\2\2\u011b\u011c\7g\2\2\u011c"+ - "\u011d\7t\2\2\u011d\u011e\7x\2\2\u011e\u011f\7g\2\2\u011f\"\3\2\2\2\u0120"+ - "\u0121\7k\2\2\u0121\u0122\7h\2\2\u0122$\3\2\2\2\u0123\u0124\7g\2\2\u0124"+ - "\u0125\7n\2\2\u0125\u0126\7u\2\2\u0126\u0127\7g\2\2\u0127&\3\2\2\2\u0128"+ - "\u0129\7y\2\2\u0129\u012a\7j\2\2\u012a\u012b\7k\2\2\u012b\u012c\7n\2\2"+ - "\u012c\u012d\7g\2\2\u012d(\3\2\2\2\u012e\u012f\7f\2\2\u012f\u0130\7q\2"+ - "\2\u0130*\3\2\2\2\u0131\u0132\7h\2\2\u0132\u0133\7q\2\2\u0133\u0134\7"+ - "t\2\2\u0134,\3\2\2\2\u0135\u0136\7t\2\2\u0136\u0137\7g\2\2\u0137\u0138"+ - "\7v\2\2\u0138\u0139\7w\2\2\u0139\u013a\7t\2\2\u013a\u013b\7p\2\2\u013b"+ - ".\3\2\2\2\u013c\u013d\7d\2\2\u013d\u013e\7t\2\2\u013e\u013f\7g\2\2\u013f"+ - "\u0140\7c\2\2\u0140\u0141\7m\2\2\u0141\60\3\2\2\2\u0142\u0143\7e\2\2\u0143"+ - "\u0144\7q\2\2\u0144\u0145\7p\2\2\u0145\u0146\7v\2\2\u0146\u0147\7k\2\2"+ - "\u0147\u0148\7p\2\2\u0148\u0149\7w\2\2\u0149\u014a\7g\2\2\u014a\62\3\2"+ - "\2\2\u014b\u014c\7c\2\2\u014c\u014d\7u\2\2\u014d\u014e\7o\2\2\u014e\64"+ - "\3\2\2\2\u014f\u0150\7<\2\2\u0150\66\3\2\2\2\u0151\u0152\7\60\2\2\u0152"+ - "\u0153\7\60\2\2\u01538\3\2\2\2\u0154\u0155\7u\2\2\u0155\u0156\7k\2\2\u0156"+ - "\u0157\7i\2\2\u0157\u0158\7p\2\2\u0158\u0159\7g\2\2\u0159\u015a\7f\2\2"+ - "\u015a:\3\2\2\2\u015b\u015c\7w\2\2\u015c\u015d\7p\2\2\u015d\u015e\7u\2"+ - "\2\u015e\u015f\7k\2\2\u015f\u0160\7i\2\2\u0160\u0161\7p\2\2\u0161\u0162"+ - "\7g\2\2\u0162\u0163\7f\2\2\u0163<\3\2\2\2\u0164\u0165\7,\2\2\u0165>\3"+ - "\2\2\2\u0166\u0167\7]\2\2\u0167@\3\2\2\2\u0168\u0169\7_\2\2\u0169B\3\2"+ - "\2\2\u016a\u016b\7u\2\2\u016b\u016c\7k\2\2\u016c\u016d\7|\2\2\u016d\u016e"+ - "\7g\2\2\u016e\u016f\7q\2\2\u016f\u0170\7h\2\2\u0170D\3\2\2\2\u0171\u0172"+ - "\7v\2\2\u0172\u0173\7{\2\2\u0173\u0174\7r\2\2\u0174\u0175\7g\2\2\u0175"+ - "\u0176\7k\2\2\u0176\u0177\7f\2\2\u0177F\3\2\2\2\u0178\u0179\7/\2\2\u0179"+ - "\u017a\7/\2\2\u017aH\3\2\2\2\u017b\u017c\7-\2\2\u017c\u017d\7-\2\2\u017d"+ - "J\3\2\2\2\u017e\u017f\7-\2\2\u017fL\3\2\2\2\u0180\u0181\7/\2\2\u0181N"+ - "\3\2\2\2\u0182\u0183\7#\2\2\u0183P\3\2\2\2\u0184\u0185\7(\2\2\u0185R\3"+ - "\2\2\2\u0186\u0187\7\u0080\2\2\u0187T\3\2\2\2\u0188\u0189\7@\2\2\u0189"+ - "\u018a\7@\2\2\u018aV\3\2\2\2\u018b\u018c\7>\2\2\u018c\u018d\7>\2\2\u018d"+ - "X\3\2\2\2\u018e\u018f\7\61\2\2\u018fZ\3\2\2\2\u0190\u0191\7\'\2\2\u0191"+ - "\\\3\2\2\2\u0192\u0193\7>\2\2\u0193^\3\2\2\2\u0194\u0195\7@\2\2\u0195"+ - "`\3\2\2\2\u0196\u0197\7?\2\2\u0197\u0198\7?\2\2\u0198b\3\2\2\2\u0199\u019a"+ - "\7#\2\2\u019a\u019b\7?\2\2\u019bd\3\2\2\2\u019c\u019d\7>\2\2\u019d\u019e"+ - "\7?\2\2\u019ef\3\2\2\2\u019f\u01a0\7@\2\2\u01a0\u01a1\7?\2\2\u01a1h\3"+ - "\2\2\2\u01a2\u01a3\7`\2\2\u01a3j\3\2\2\2\u01a4\u01a5\7~\2\2\u01a5l\3\2"+ - "\2\2\u01a6\u01a7\7(\2\2\u01a7\u01a8\7(\2\2\u01a8n\3\2\2\2\u01a9\u01aa"+ - "\7~\2\2\u01aa\u01ab\7~\2\2\u01abp\3\2\2\2\u01ac\u01ad\7A\2\2\u01adr\3"+ - "\2\2\2\u01ae\u01af\7-\2\2\u01af\u01b0\7?\2\2\u01b0t\3\2\2\2\u01b1\u01b2"+ - "\7/\2\2\u01b2\u01b3\7?\2\2\u01b3v\3\2\2\2\u01b4\u01b5\7,\2\2\u01b5\u01b6"+ - "\7?\2\2\u01b6x\3\2\2\2\u01b7\u01b8\7\61\2\2\u01b8\u01b9\7?\2\2\u01b9z"+ - "\3\2\2\2\u01ba\u01bb\7\'\2\2\u01bb\u01bc\7?\2\2\u01bc|\3\2\2\2\u01bd\u01be"+ - "\7>\2\2\u01be\u01bf\7>\2\2\u01bf\u01c0\7?\2\2\u01c0~\3\2\2\2\u01c1\u01c2"+ - "\7@\2\2\u01c2\u01c3\7@\2\2\u01c3\u01c4\7?\2\2\u01c4\u0080\3\2\2\2\u01c5"+ - "\u01c6\7(\2\2\u01c6\u01c7\7?\2\2\u01c7\u0082\3\2\2\2\u01c8\u01c9\7~\2"+ - "\2\u01c9\u01ca\7?\2\2\u01ca\u0084\3\2\2\2\u01cb\u01cc\7`\2\2\u01cc\u01cd"+ - "\7?\2\2\u01cd\u0086\3\2\2\2\u01ce\u01cf\7m\2\2\u01cf\u01d0\7k\2\2\u01d0"+ - "\u01d1\7e\2\2\u01d1\u01d2\7m\2\2\u01d2\u01d3\7c\2\2\u01d3\u01d4\7u\2\2"+ - "\u01d4\u01d5\7o\2\2\u01d5\u0088\3\2\2\2\u01d6\u01d7\7t\2\2\u01d7\u01d8"+ - "\7g\2\2\u01d8\u01d9\7u\2\2\u01d9\u01da\7q\2\2\u01da\u01db\7w\2\2\u01db"+ - "\u01dc\7t\2\2\u01dc\u01dd\7e\2\2\u01dd\u01de\7g\2\2\u01de\u008a\3\2\2"+ - "\2\u01df\u01e0\7w\2\2\u01e0\u01e1\7u\2\2\u01e1\u01e2\7g\2\2\u01e2\u01e3"+ - "\7u\2\2\u01e3\u008c\3\2\2\2\u01e4\u01e5\7e\2\2\u01e5\u01e6\7n\2\2\u01e6"+ - "\u01e7\7q\2\2\u01e7\u01e8\7d\2\2\u01e8\u01e9\7d\2\2\u01e9\u01ea\7g\2\2"+ - "\u01ea\u01eb\7t\2\2\u01eb\u01ec\7u\2\2\u01ec\u008e\3\2\2\2\u01ed\u01ee"+ - "\7d\2\2\u01ee\u01ef\7{\2\2\u01ef\u01f0\7v\2\2\u01f0\u01f1\7g\2\2\u01f1"+ - "\u01f2\7u\2\2\u01f2\u0090\3\2\2\2\u01f3\u01f4\7e\2\2\u01f4\u01f5\7{\2"+ - "\2\u01f5\u01f6\7e\2\2\u01f6\u01f7\7n\2\2\u01f7\u01f8\7g\2\2\u01f8\u01f9"+ - "\7u\2\2\u01f9\u0092\3\2\2\2\u01fa\u01fb\7r\2\2\u01fb\u01fc\7e\2\2\u01fc"+ - "\u0094\3\2\2\2\u01fd\u01fe\7\60\2\2\u01fe\u01ff\7d\2\2\u01ff\u0200\7{"+ - "\2\2\u0200\u0201\7v\2\2\u0201\u0202\7g\2\2\u0202\u0096\3\2\2\2\u0203\u0204"+ - "\7%\2\2\u0204\u0098\3\2\2\2\u0205\u0206\7\60\2\2\u0206\u009a\3\2\2\2\u0207"+ - "\u0208\7d\2\2\u0208\u0209\7t\2\2\u0209\u02e6\7m\2\2\u020a\u020b\7q\2\2"+ - "\u020b\u020c\7t\2\2\u020c\u02e6\7c\2\2\u020d\u020e\7m\2\2\u020e\u020f"+ - "\7k\2\2\u020f\u02e6\7n\2\2\u0210\u0211\7u\2\2\u0211\u0212\7n\2\2\u0212"+ - "\u02e6\7q\2\2\u0213\u0214\7p\2\2\u0214\u0215\7q\2\2\u0215\u02e6\7r\2\2"+ - "\u0216\u0217\7c\2\2\u0217\u0218\7u\2\2\u0218\u02e6\7n\2\2\u0219\u021a"+ - "\7r\2\2\u021a\u021b\7j\2\2\u021b\u02e6\7r\2\2\u021c\u021d\7c\2\2\u021d"+ - "\u021e\7p\2\2\u021e\u02e6\7e\2\2\u021f\u0220\7d\2\2\u0220\u0221\7r\2\2"+ - "\u0221\u02e6\7n\2\2\u0222\u0223\7e\2\2\u0223\u0224\7n\2\2\u0224\u02e6"+ - "\7e\2\2\u0225\u0226\7l\2\2\u0226\u0227\7u\2\2\u0227\u02e6\7t\2\2\u0228"+ - "\u0229\7c\2\2\u0229\u022a\7p\2\2\u022a\u02e6\7f\2\2\u022b\u022c\7t\2\2"+ - "\u022c\u022d\7n\2\2\u022d\u02e6\7c\2\2\u022e\u022f\7d\2\2\u022f\u0230"+ - "\7k\2\2\u0230\u02e6\7v\2\2\u0231\u0232\7t\2\2\u0232\u0233\7q\2\2\u0233"+ - "\u02e6\7n\2\2\u0234\u0235\7r\2\2\u0235\u0236\7n\2\2\u0236\u02e6\7c\2\2"+ - "\u0237\u0238\7r\2\2\u0238\u0239\7n\2\2\u0239\u02e6\7r\2\2\u023a\u023b"+ - "\7d\2\2\u023b\u023c\7o\2\2\u023c\u02e6\7k\2\2\u023d\u023e\7u\2\2\u023e"+ - "\u023f\7g\2\2\u023f\u02e6\7e\2\2\u0240\u0241\7t\2\2\u0241\u0242\7v\2\2"+ - "\u0242\u02e6\7k\2\2\u0243\u0244\7g\2\2\u0244\u0245\7q\2\2\u0245\u02e6"+ - "\7t\2\2\u0246\u0247\7u\2\2\u0247\u0248\7t\2\2\u0248\u02e6\7g\2\2\u0249"+ - "\u024a\7n\2\2\u024a\u024b\7u\2\2\u024b\u02e6\7t\2\2\u024c\u024d\7r\2\2"+ - "\u024d\u024e\7j\2\2\u024e\u02e6\7c\2\2\u024f\u0250\7c\2\2\u0250\u0251"+ - "\7n\2\2\u0251\u02e6\7t\2\2\u0252\u0253\7l\2\2\u0253\u0254\7o\2\2\u0254"+ - "\u02e6\7r\2\2\u0255\u0256\7d\2\2\u0256\u0257\7x\2\2\u0257\u02e6\7e\2\2"+ - "\u0258\u0259\7e\2\2\u0259\u025a\7n\2\2\u025a\u02e6\7k\2\2\u025b\u025c"+ - "\7t\2\2\u025c\u025d\7v\2\2\u025d\u02e6\7u\2\2\u025e\u025f\7c\2\2\u025f"+ - "\u0260\7f\2\2\u0260\u02e6\7e\2\2\u0261\u0262\7t\2\2\u0262\u0263\7t\2\2"+ - "\u0263\u02e6\7c\2\2\u0264\u0265\7d\2\2\u0265\u0266\7x\2\2\u0266\u02e6"+ - "\7u\2\2\u0267\u0268\7u\2\2\u0268\u0269\7g\2\2\u0269\u02e6\7k\2\2\u026a"+ - "\u026b\7u\2\2\u026b\u026c\7c\2\2\u026c\u02e6\7z\2\2\u026d\u026e\7u\2\2"+ - "\u026e\u026f\7v\2\2\u026f\u02e6\7{\2\2\u0270\u0271\7u\2\2\u0271\u0272"+ - "\7v\2\2\u0272\u02e6\7c\2\2\u0273\u0274\7u\2\2\u0274\u0275\7v\2\2\u0275"+ - "\u02e6\7z\2\2\u0276\u0277\7f\2\2\u0277\u0278\7g\2\2\u0278\u02e6\7{\2\2"+ - "\u0279\u027a\7v\2\2\u027a\u027b\7z\2\2\u027b\u02e6\7c\2\2\u027c\u027d"+ - "\7z\2\2\u027d\u027e\7c\2\2\u027e\u02e6\7c\2\2\u027f\u0280\7d\2\2\u0280"+ - "\u0281\7e\2\2\u0281\u02e6\7e\2\2\u0282\u0283\7c\2\2\u0283\u0284\7j\2\2"+ - "\u0284\u02e6\7z\2\2\u0285\u0286\7v\2\2\u0286\u0287\7{\2\2\u0287\u02e6"+ - "\7c\2\2\u0288\u0289\7v\2\2\u0289\u028a\7z\2\2\u028a\u02e6\7u\2\2\u028b"+ - "\u028c\7v\2\2\u028c\u028d\7c\2\2\u028d\u02e6\7u\2\2\u028e\u028f\7u\2\2"+ - "\u028f\u0290\7j\2\2\u0290\u02e6\7{\2\2\u0291\u0292\7u\2\2\u0292\u0293"+ - "\7j\2\2\u0293\u02e6\7z\2\2\u0294\u0295\7n\2\2\u0295\u0296\7f\2\2\u0296"+ - "\u02e6\7{\2\2\u0297\u0298\7n\2\2\u0298\u0299\7f\2\2\u0299\u02e6\7c\2\2"+ - "\u029a\u029b\7n\2\2\u029b\u029c\7f\2\2\u029c\u02e6\7z\2\2\u029d\u029e"+ - "\7n\2\2\u029e\u029f\7c\2\2\u029f\u02e6\7z\2\2\u02a0\u02a1\7v\2\2\u02a1"+ - "\u02a2\7c\2\2\u02a2\u02e6\7{\2\2\u02a3\u02a4\7v\2\2\u02a4\u02a5\7c\2\2"+ - "\u02a5\u02e6\7z\2\2\u02a6\u02a7\7d\2\2\u02a7\u02a8\7e\2\2\u02a8\u02e6"+ - "\7u\2\2\u02a9\u02aa\7e\2\2\u02aa\u02ab\7n\2\2\u02ab\u02e6\7x\2\2\u02ac"+ - "\u02ad\7v\2\2\u02ad\u02ae\7u\2\2\u02ae\u02e6\7z\2\2\u02af\u02b0\7n\2\2"+ - "\u02b0\u02b1\7c\2\2\u02b1\u02e6\7u\2\2\u02b2\u02b3\7e\2\2\u02b3\u02b4"+ - "\7r\2\2\u02b4\u02e6\7{\2\2\u02b5\u02b6\7e\2\2\u02b6\u02b7\7o\2\2\u02b7"+ - "\u02e6\7r\2\2\u02b8\u02b9\7e\2\2\u02b9\u02ba\7r\2\2\u02ba\u02e6\7z\2\2"+ - "\u02bb\u02bc\7f\2\2\u02bc\u02bd\7e\2\2\u02bd\u02e6\7r\2\2\u02be\u02bf"+ - "\7f\2\2\u02bf\u02c0\7g\2\2\u02c0\u02e6\7e\2\2\u02c1\u02c2\7k\2\2\u02c2"+ - "\u02c3\7p\2\2\u02c3\u02e6\7e\2\2\u02c4\u02c5\7c\2\2\u02c5\u02c6\7z\2\2"+ - "\u02c6\u02e6\7u\2\2\u02c7\u02c8\7d\2\2\u02c8\u02c9\7p\2\2\u02c9\u02e6"+ - "\7g\2\2\u02ca\u02cb\7e\2\2\u02cb\u02cc\7n\2\2\u02cc\u02e6\7f\2\2\u02cd"+ - "\u02ce\7u\2\2\u02ce\u02cf\7d\2\2\u02cf\u02e6\7e\2\2\u02d0\u02d1\7k\2\2"+ - "\u02d1\u02d2\7u\2\2\u02d2\u02e6\7e\2\2\u02d3\u02d4\7k\2\2\u02d4\u02d5"+ - "\7p\2\2\u02d5\u02e6\7z\2\2\u02d6\u02d7\7d\2\2\u02d7\u02d8\7g\2\2\u02d8"+ - "\u02e6\7s\2\2\u02d9\u02da\7u\2\2\u02da\u02db\7g\2\2\u02db\u02e6\7f\2\2"+ - "\u02dc\u02dd\7f\2\2\u02dd\u02de\7g\2\2\u02de\u02e6\7z\2\2\u02df\u02e0"+ - "\7k\2\2\u02e0\u02e1\7p\2\2\u02e1\u02e6\7{\2\2\u02e2\u02e3\7t\2\2\u02e3"+ - "\u02e4\7q\2\2\u02e4\u02e6\7t\2\2\u02e5\u0207\3\2\2\2\u02e5\u020a\3\2\2"+ - "\2\u02e5\u020d\3\2\2\2\u02e5\u0210\3\2\2\2\u02e5\u0213\3\2\2\2\u02e5\u0216"+ - "\3\2\2\2\u02e5\u0219\3\2\2\2\u02e5\u021c\3\2\2\2\u02e5\u021f\3\2\2\2\u02e5"+ - "\u0222\3\2\2\2\u02e5\u0225\3\2\2\2\u02e5\u0228\3\2\2\2\u02e5\u022b\3\2"+ - "\2\2\u02e5\u022e\3\2\2\2\u02e5\u0231\3\2\2\2\u02e5\u0234\3\2\2\2\u02e5"+ - "\u0237\3\2\2\2\u02e5\u023a\3\2\2\2\u02e5\u023d\3\2\2\2\u02e5\u0240\3\2"+ - "\2\2\u02e5\u0243\3\2\2\2\u02e5\u0246\3\2\2\2\u02e5\u0249\3\2\2\2\u02e5"+ - "\u024c\3\2\2\2\u02e5\u024f\3\2\2\2\u02e5\u0252\3\2\2\2\u02e5\u0255\3\2"+ - "\2\2\u02e5\u0258\3\2\2\2\u02e5\u025b\3\2\2\2\u02e5\u025e\3\2\2\2\u02e5"+ - "\u0261\3\2\2\2\u02e5\u0264\3\2\2\2\u02e5\u0267\3\2\2\2\u02e5\u026a\3\2"+ - "\2\2\u02e5\u026d\3\2\2\2\u02e5\u0270\3\2\2\2\u02e5\u0273\3\2\2\2\u02e5"+ - "\u0276\3\2\2\2\u02e5\u0279\3\2\2\2\u02e5\u027c\3\2\2\2\u02e5\u027f\3\2"+ - "\2\2\u02e5\u0282\3\2\2\2\u02e5\u0285\3\2\2\2\u02e5\u0288\3\2\2\2\u02e5"+ - "\u028b\3\2\2\2\u02e5\u028e\3\2\2\2\u02e5\u0291\3\2\2\2\u02e5\u0294\3\2"+ - "\2\2\u02e5\u0297\3\2\2\2\u02e5\u029a\3\2\2\2\u02e5\u029d\3\2\2\2\u02e5"+ - "\u02a0\3\2\2\2\u02e5\u02a3\3\2\2\2\u02e5\u02a6\3\2\2\2\u02e5\u02a9\3\2"+ - "\2\2\u02e5\u02ac\3\2\2\2\u02e5\u02af\3\2\2\2\u02e5\u02b2\3\2\2\2\u02e5"+ - "\u02b5\3\2\2\2\u02e5\u02b8\3\2\2\2\u02e5\u02bb\3\2\2\2\u02e5\u02be\3\2"+ - "\2\2\u02e5\u02c1\3\2\2\2\u02e5\u02c4\3\2\2\2\u02e5\u02c7\3\2\2\2\u02e5"+ - "\u02ca\3\2\2\2\u02e5\u02cd\3\2\2\2\u02e5\u02d0\3\2\2\2\u02e5\u02d3\3\2"+ - "\2\2\u02e5\u02d6\3\2\2\2\u02e5\u02d9\3\2\2\2\u02e5\u02dc\3\2\2\2\u02e5"+ - "\u02df\3\2\2\2\u02e5\u02e2\3\2\2\2\u02e6\u009c\3\2\2\2\u02e7\u02e8\7}"+ - "\2\2\u02e8\u02e9\7}\2\2\u02e9\u02ed\3\2\2\2\u02ea\u02ec\13\2\2\2\u02eb"+ - "\u02ea\3\2\2\2\u02ec\u02ef\3\2\2\2\u02ed\u02ee\3\2\2\2\u02ed\u02eb\3\2"+ - "\2\2\u02ee\u02f0\3\2\2\2\u02ef\u02ed\3\2\2\2\u02f0\u02f1\7\177\2\2\u02f1"+ - "\u02f2\7\177\2\2\u02f2\u009e\3\2\2\2\u02f3\u02f4\7d\2\2\u02f4\u02f5\7"+ - "{\2\2\u02f5\u02f6\7v\2\2\u02f6\u0319\7g\2\2\u02f7\u02f8\7y\2\2\u02f8\u02f9"+ - "\7q\2\2\u02f9\u02fa\7t\2\2\u02fa\u0319\7f\2\2\u02fb\u02fc\7f\2\2\u02fc"+ - "\u02fd\7y\2\2\u02fd\u02fe\7q\2\2\u02fe\u02ff\7t\2\2\u02ff\u0319\7f\2\2"+ - "\u0300\u0301\7d\2\2\u0301\u0302\7q\2\2\u0302\u0303\7q\2\2\u0303\u0319"+ - "\7n\2\2\u0304\u0305\7e\2\2\u0305\u0306\7j\2\2\u0306\u0307\7c\2\2\u0307"+ - "\u0319\7t\2\2\u0308\u0309\7u\2\2\u0309\u030a\7j\2\2\u030a\u030b\7q\2\2"+ - "\u030b\u030c\7t\2\2\u030c\u0319\7v\2\2\u030d\u030e\7k\2\2\u030e\u030f"+ - "\7p\2\2\u030f\u0319\7v\2\2\u0310\u0311\7n\2\2\u0311\u0312\7q\2\2\u0312"+ - "\u0313\7p\2\2\u0313\u0319\7i\2\2\u0314\u0315\7x\2\2\u0315\u0316\7q\2\2"+ - "\u0316\u0317\7k\2\2\u0317\u0319\7f\2\2\u0318\u02f3\3\2\2\2\u0318\u02f7"+ - "\3\2\2\2\u0318\u02fb\3\2\2\2\u0318\u0300\3\2\2\2\u0318\u0304\3\2\2\2\u0318"+ - "\u0308\3\2\2\2\u0318\u030d\3\2\2\2\u0318\u0310\3\2\2\2\u0318\u0314\3\2"+ - "\2\2\u0319\u00a0\3\2\2\2\u031a\u0320\7$\2\2\u031b\u031c\7^\2\2\u031c\u031f"+ - "\7$\2\2\u031d\u031f\n\2\2\2\u031e\u031b\3\2\2\2\u031e\u031d\3\2\2\2\u031f"+ - "\u0322\3\2\2\2\u0320\u031e\3\2\2\2\u0320\u0321\3\2\2\2\u0321\u0323\3\2"+ - "\2\2\u0322\u0320\3\2\2\2\u0323\u0325\7$\2\2\u0324\u0326\7|\2\2\u0325\u0324"+ - "\3\2\2\2\u0325\u0326\3\2\2\2\u0326\u00a2\3\2\2\2\u0327\u032b\7)\2\2\u0328"+ - "\u0329\7^\2\2\u0329\u032c\7)\2\2\u032a\u032c\n\3\2\2\u032b\u0328\3\2\2"+ - "\2\u032b\u032a\3\2\2\2\u032c\u032d\3\2\2\2\u032d\u032e\7)\2\2\u032e\u00a4"+ - "\3\2\2\2\u032f\u0330\7v\2\2\u0330\u0331\7t\2\2\u0331\u0332\7w\2\2\u0332"+ - "\u0339\7g\2\2\u0333\u0334\7h\2\2\u0334\u0335\7c\2\2\u0335\u0336\7n\2\2"+ - "\u0336\u0337\7u\2\2\u0337\u0339\7g\2\2\u0338\u032f\3\2\2\2\u0338\u0333"+ - "\3\2\2\2\u0339\u00a6\3\2\2\2\u033a\u033d\5\u00a9U\2\u033b\u033d\5\u00b1"+ - "Y\2\u033c\u033a\3\2\2\2\u033c\u033b\3\2\2\2\u033d\u00a8\3\2\2\2\u033e"+ - "\u0342\5\u00abV\2\u033f\u0342\5\u00adW\2\u0340\u0342\5\u00afX\2\u0341"+ - "\u033e\3\2\2\2\u0341\u033f\3\2\2\2\u0341\u0340\3\2\2\2\u0342\u00aa\3\2"+ - "\2\2\u0343\u0349\7\'\2\2\u0344\u0345\7\62\2\2\u0345\u0349\7d\2\2\u0346"+ - "\u0347\7\62\2\2\u0347\u0349\7D\2\2\u0348\u0343\3\2\2\2\u0348\u0344\3\2"+ - "\2\2\u0348\u0346\3\2\2\2\u0349\u034d\3\2\2\2\u034a\u034c\5\u00b9]\2\u034b"+ - "\u034a\3\2\2\2\u034c\u034f\3\2\2\2\u034d\u034b\3\2\2\2\u034d\u034e\3\2"+ - "\2\2\u034e\u0350\3\2\2\2\u034f\u034d\3\2\2\2\u0350\u0352\7\60\2\2\u0351"+ - "\u0353\5\u00b9]\2\u0352\u0351\3\2\2\2\u0353\u0354\3\2\2\2\u0354\u0352"+ - "\3\2\2\2\u0354\u0355\3\2\2\2\u0355\u00ac\3\2\2\2\u0356\u0358\5\u00bb^"+ - "\2\u0357\u0356\3\2\2\2\u0358\u035b\3\2\2\2\u0359\u0357\3\2\2\2\u0359\u035a"+ - "\3\2\2\2\u035a\u035c\3\2\2\2\u035b\u0359\3\2\2\2\u035c\u035e\7\60\2\2"+ - "\u035d\u035f\5\u00bb^\2\u035e\u035d\3\2\2\2\u035f\u0360\3\2\2\2\u0360"+ - "\u035e\3\2\2\2\u0360\u0361\3\2\2\2\u0361\u00ae\3\2\2\2\u0362\u0368\7&"+ - "\2\2\u0363\u0364\7\62\2\2\u0364\u0368\7z\2\2\u0365\u0366\7\62\2\2\u0366"+ - "\u0368\7Z\2\2\u0367\u0362\3\2\2\2\u0367\u0363\3\2\2\2\u0367\u0365\3\2"+ - "\2\2\u0368\u036c\3\2\2\2\u0369\u036b\5\u00bd_\2\u036a\u0369\3\2\2\2\u036b"+ - "\u036e\3\2\2\2\u036c\u036a\3\2\2\2\u036c\u036d\3\2\2\2\u036d\u036f\3\2"+ - "\2\2\u036e\u036c\3\2\2\2\u036f\u0371\7\60\2\2\u0370\u0372\5\u00bd_\2\u0371"+ - "\u0370\3\2\2\2\u0372\u0373\3\2\2\2\u0373\u0371\3\2\2\2\u0373\u0374\3\2"+ - "\2\2\u0374\u00b0\3\2\2\2\u0375\u0379\5\u00b5[\2\u0376\u0379\5\u00b7\\"+ - "\2\u0377\u0379\5\u00b3Z\2\u0378\u0375\3\2\2\2\u0378\u0376\3\2\2\2\u0378"+ - "\u0377\3\2\2\2\u0379\u00b2\3\2\2\2\u037a\u037b\7\62\2\2\u037b\u037d\t"+ - "\4\2\2\u037c\u037e\5\u00b9]\2\u037d\u037c\3\2\2\2\u037e\u037f\3\2\2\2"+ - "\u037f\u037d\3\2\2\2\u037f\u0380\3\2\2\2\u0380\u0388\3\2\2\2\u0381\u0383"+ - "\7\'\2\2\u0382\u0384\5\u00b9]\2\u0383\u0382\3\2\2\2\u0384\u0385\3\2\2"+ - "\2\u0385\u0383\3\2\2\2\u0385\u0386\3\2\2\2\u0386\u0388\3\2\2\2\u0387\u037a"+ - "\3\2\2\2\u0387\u0381\3\2\2\2\u0388\u00b4\3\2\2\2\u0389\u038b\5\u00bb^"+ - "\2\u038a\u0389\3\2\2\2\u038b\u038c\3\2\2\2\u038c\u038a\3\2\2\2\u038c\u038d"+ - "\3\2\2\2\u038d\u00b6\3\2\2\2\u038e\u0394\7&\2\2\u038f\u0390\7\62\2\2\u0390"+ - "\u0394\7z\2\2\u0391\u0392\7\62\2\2\u0392\u0394\7Z\2\2\u0393\u038e\3\2"+ - "\2\2\u0393\u038f\3\2\2\2\u0393\u0391\3\2\2\2\u0394\u0396\3\2\2\2\u0395"+ - "\u0397\5\u00bd_\2\u0396\u0395\3\2\2\2\u0397\u0398\3\2\2\2\u0398\u0396"+ - "\3\2\2\2\u0398\u0399\3\2\2\2\u0399\u00b8\3\2\2\2\u039a\u039b\t\5\2\2\u039b"+ - "\u00ba\3\2\2\2\u039c\u039d\t\6\2\2\u039d\u00bc\3\2\2\2\u039e\u039f\t\7"+ - "\2\2\u039f\u00be\3\2\2\2\u03a0\u03a4\5\u00c1a\2\u03a1\u03a3\5\u00c3b\2"+ - "\u03a2\u03a1\3\2\2\2\u03a3\u03a6\3\2\2\2\u03a4\u03a2\3\2\2\2\u03a4\u03a5"+ - "\3\2\2\2\u03a5\u00c0\3\2\2\2\u03a6\u03a4\3\2\2\2\u03a7\u03a8\t\b\2\2\u03a8"+ - "\u00c2\3\2\2\2\u03a9\u03aa\t\t\2\2\u03aa\u00c4\3\2\2\2\u03ab\u03af\7#"+ - "\2\2\u03ac\u03ae\5\u00c3b\2\u03ad\u03ac\3\2\2\2\u03ae\u03b1\3\2\2\2\u03af"+ - "\u03ad\3\2\2\2\u03af\u03b0\3\2\2\2\u03b0\u03b3\3\2\2\2\u03b1\u03af\3\2"+ - "\2\2\u03b2\u03b4\t\n\2\2\u03b3\u03b2\3\2\2\2\u03b4\u03b5\3\2\2\2\u03b5"+ - "\u03b3\3\2\2\2\u03b5\u03b6\3\2\2\2\u03b6\u00c6\3\2\2\2\u03b7\u03b9\t\13"+ - "\2\2\u03b8\u03b7\3\2\2\2\u03b9\u03ba\3\2\2\2\u03ba\u03b8\3\2\2\2\u03ba"+ - "\u03bb\3\2\2\2\u03bb\u03bc\3\2\2\2\u03bc\u03bd\bd\2\2\u03bd\u00c8\3\2"+ - "\2\2\u03be\u03bf\7\61\2\2\u03bf\u03c0\7\61\2\2\u03c0\u03c4\3\2\2\2\u03c1"+ - "\u03c3\n\f\2\2\u03c2\u03c1\3\2\2\2\u03c3\u03c6\3\2\2\2\u03c4\u03c2\3\2"+ - "\2\2\u03c4\u03c5\3\2\2\2\u03c5\u03c7\3\2\2\2\u03c6\u03c4\3\2\2\2\u03c7"+ - "\u03c8\be\3\2\u03c8\u00ca\3\2\2\2\u03c9\u03ca\7\61\2\2\u03ca\u03cb\7,"+ - "\2\2\u03cb\u03cf\3\2\2\2\u03cc\u03ce\13\2\2\2\u03cd\u03cc\3\2\2\2\u03ce"+ - "\u03d1\3\2\2\2\u03cf\u03d0\3\2\2\2\u03cf\u03cd\3\2\2\2\u03d0\u03d2\3\2"+ - "\2\2\u03d1\u03cf\3\2\2\2\u03d2\u03d3\7,\2\2\u03d3\u03d4\7\61\2\2\u03d4"+ - "\u03d5\3\2\2\2\u03d5\u03d6\bf\3\2\u03d6\u00cc\3\2\2\2\"\2\u02e5\u02ed"+ - "\u0318\u031e\u0320\u0325\u032b\u0338\u033c\u0341\u0348\u034d\u0354\u0359"+ - "\u0360\u0367\u036c\u0373\u0378\u037f\u0385\u0387\u038c\u0393\u0398\u03a4"+ - "\u03af\u03b5\u03ba\u03c4\u03cf\4\2\3\2\2\4\2"; + "\nY\3Y\3Y\3Y\5Y\u037e\nY\3Z\3Z\3Z\6Z\u0383\nZ\rZ\16Z\u0384\3Z\3Z\6Z\u0389"+ + "\nZ\rZ\16Z\u038a\5Z\u038d\nZ\3[\6[\u0390\n[\r[\16[\u0391\3\\\3\\\3\\\3"+ + "\\\3\\\5\\\u0399\n\\\3\\\6\\\u039c\n\\\r\\\16\\\u039d\3]\3]\3^\3^\3_\3"+ + "_\3`\3`\7`\u03a8\n`\f`\16`\u03ab\13`\3a\3a\3b\3b\3c\3c\7c\u03b3\nc\fc"+ + "\16c\u03b6\13c\3c\6c\u03b9\nc\rc\16c\u03ba\3d\6d\u03be\nd\rd\16d\u03bf"+ + "\3d\3d\3e\3e\3e\3e\7e\u03c8\ne\fe\16e\u03cb\13e\3e\3e\3f\3f\3f\3f\7f\u03d3"+ + "\nf\ff\16f\u03d6\13f\3f\3f\3f\3f\3f\4\u02ed\u03d4\2g\3\3\5\4\7\5\t\6\13"+ + "\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'"+ + "\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'"+ + "M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177"+ + "A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093"+ + "K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7"+ + "U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9\2\u00bb"+ + "\2\u00bd\2\u00bf^\u00c1\2\u00c3\2\u00c5_\u00c7`\u00c9a\u00cbb\3\2\17\3"+ + "\2$$\3\2))\4\2uuww\7\2dfkknnuuyy\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHc"+ + "h\5\2C\\aac|\6\2\62;C\\aac|\4\2--//\6\2\13\f\17\17\"\"\u00a2\u00a2\4\2"+ + "\f\f\17\17\2\u044b\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13"+ + "\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2"+ + "\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2"+ + "!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3"+ + "\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2"+ + "\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E"+ + "\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2"+ + "\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2"+ + "\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k"+ + "\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2"+ + "\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2"+ + "\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b"+ + "\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2"+ + "\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d"+ + "\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2"+ + "\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af"+ + "\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2"+ + "\2\2\u00bf\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb"+ + "\3\2\2\2\3\u00cd\3\2\2\2\5\u00d4\3\2\2\2\7\u00d6\3\2\2\2\t\u00d8\3\2\2"+ + "\2\13\u00da\3\2\2\2\r\u00dc\3\2\2\2\17\u00de\3\2\2\2\21\u00e0\3\2\2\2"+ + "\23\u00e2\3\2\2\2\25\u00e8\3\2\2\2\27\u00ef\3\2\2\2\31\u00f5\3\2\2\2\33"+ + "\u00fe\3\2\2\2\35\u0105\3\2\2\2\37\u010e\3\2\2\2!\u0118\3\2\2\2#\u0120"+ + "\3\2\2\2%\u0123\3\2\2\2\'\u0128\3\2\2\2)\u012e\3\2\2\2+\u0131\3\2\2\2"+ + "-\u0135\3\2\2\2/\u013c\3\2\2\2\61\u0142\3\2\2\2\63\u014b\3\2\2\2\65\u014f"+ + "\3\2\2\2\67\u0151\3\2\2\29\u0154\3\2\2\2;\u015b\3\2\2\2=\u0164\3\2\2\2"+ + "?\u0166\3\2\2\2A\u0168\3\2\2\2C\u016a\3\2\2\2E\u0171\3\2\2\2G\u0178\3"+ + "\2\2\2I\u017b\3\2\2\2K\u017e\3\2\2\2M\u0180\3\2\2\2O\u0182\3\2\2\2Q\u0184"+ + "\3\2\2\2S\u0186\3\2\2\2U\u0188\3\2\2\2W\u018b\3\2\2\2Y\u018e\3\2\2\2["+ + "\u0190\3\2\2\2]\u0192\3\2\2\2_\u0194\3\2\2\2a\u0196\3\2\2\2c\u0199\3\2"+ + "\2\2e\u019c\3\2\2\2g\u019f\3\2\2\2i\u01a2\3\2\2\2k\u01a4\3\2\2\2m\u01a6"+ + "\3\2\2\2o\u01a9\3\2\2\2q\u01ac\3\2\2\2s\u01ae\3\2\2\2u\u01b1\3\2\2\2w"+ + "\u01b4\3\2\2\2y\u01b7\3\2\2\2{\u01ba\3\2\2\2}\u01bd\3\2\2\2\177\u01c1"+ + "\3\2\2\2\u0081\u01c5\3\2\2\2\u0083\u01c8\3\2\2\2\u0085\u01cb\3\2\2\2\u0087"+ + "\u01ce\3\2\2\2\u0089\u01d6\3\2\2\2\u008b\u01df\3\2\2\2\u008d\u01e4\3\2"+ + "\2\2\u008f\u01ed\3\2\2\2\u0091\u01f3\3\2\2\2\u0093\u01fa\3\2\2\2\u0095"+ + "\u01fd\3\2\2\2\u0097\u0203\3\2\2\2\u0099\u0205\3\2\2\2\u009b\u02e5\3\2"+ + "\2\2\u009d\u02e7\3\2\2\2\u009f\u0318\3\2\2\2\u00a1\u031a\3\2\2\2\u00a3"+ + "\u0327\3\2\2\2\u00a5\u0338\3\2\2\2\u00a7\u033c\3\2\2\2\u00a9\u0341\3\2"+ + "\2\2\u00ab\u0348\3\2\2\2\u00ad\u0359\3\2\2\2\u00af\u0367\3\2\2\2\u00b1"+ + "\u0378\3\2\2\2\u00b3\u038c\3\2\2\2\u00b5\u038f\3\2\2\2\u00b7\u0398\3\2"+ + "\2\2\u00b9\u039f\3\2\2\2\u00bb\u03a1\3\2\2\2\u00bd\u03a3\3\2\2\2\u00bf"+ + "\u03a5\3\2\2\2\u00c1\u03ac\3\2\2\2\u00c3\u03ae\3\2\2\2\u00c5\u03b0\3\2"+ + "\2\2\u00c7\u03bd\3\2\2\2\u00c9\u03c3\3\2\2\2\u00cb\u03ce\3\2\2\2\u00cd"+ + "\u00ce\7k\2\2\u00ce\u00cf\7o\2\2\u00cf\u00d0\7r\2\2\u00d0\u00d1\7q\2\2"+ + "\u00d1\u00d2\7t\2\2\u00d2\u00d3\7v\2\2\u00d3\4\3\2\2\2\u00d4\u00d5\7="+ + "\2\2\u00d5\6\3\2\2\2\u00d6\u00d7\7.\2\2\u00d7\b\3\2\2\2\u00d8\u00d9\7"+ + "?\2\2\u00d9\n\3\2\2\2\u00da\u00db\7*\2\2\u00db\f\3\2\2\2\u00dc\u00dd\7"+ + "+\2\2\u00dd\16\3\2\2\2\u00de\u00df\7}\2\2\u00df\20\3\2\2\2\u00e0\u00e1"+ + "\7\177\2\2\u00e1\22\3\2\2\2\u00e2\u00e3\7e\2\2\u00e3\u00e4\7q\2\2\u00e4"+ + "\u00e5\7p\2\2\u00e5\u00e6\7u\2\2\u00e6\u00e7\7v\2\2\u00e7\24\3\2\2\2\u00e8"+ + "\u00e9\7g\2\2\u00e9\u00ea\7z\2\2\u00ea\u00eb\7v\2\2\u00eb\u00ec\7g\2\2"+ + "\u00ec\u00ed\7t\2\2\u00ed\u00ee\7p\2\2\u00ee\26\3\2\2\2\u00ef\u00f0\7"+ + "c\2\2\u00f0\u00f1\7n\2\2\u00f1\u00f2\7k\2\2\u00f2\u00f3\7i\2\2\u00f3\u00f4"+ + "\7p\2\2\u00f4\30\3\2\2\2\u00f5\u00f6\7t\2\2\u00f6\u00f7\7g\2\2\u00f7\u00f8"+ + "\7i\2\2\u00f8\u00f9\7k\2\2\u00f9\u00fa\7u\2\2\u00fa\u00fb\7v\2\2\u00fb"+ + "\u00fc\7g\2\2\u00fc\u00fd\7t\2\2\u00fd\32\3\2\2\2\u00fe\u00ff\7k\2\2\u00ff"+ + "\u0100\7p\2\2\u0100\u0101\7n\2\2\u0101\u0102\7k\2\2\u0102\u0103\7p\2\2"+ + "\u0103\u0104\7g\2\2\u0104\34\3\2\2\2\u0105\u0106\7x\2\2\u0106\u0107\7"+ + "q\2\2\u0107\u0108\7n\2\2\u0108\u0109\7c\2\2\u0109\u010a\7v\2\2\u010a\u010b"+ + "\7k\2\2\u010b\u010c\7n\2\2\u010c\u010d\7g\2\2\u010d\36\3\2\2\2\u010e\u010f"+ + "\7k\2\2\u010f\u0110\7p\2\2\u0110\u0111\7v\2\2\u0111\u0112\7g\2\2\u0112"+ + "\u0113\7t\2\2\u0113\u0114\7t\2\2\u0114\u0115\7w\2\2\u0115\u0116\7r\2\2"+ + "\u0116\u0117\7v\2\2\u0117 \3\2\2\2\u0118\u0119\7t\2\2\u0119\u011a\7g\2"+ + "\2\u011a\u011b\7u\2\2\u011b\u011c\7g\2\2\u011c\u011d\7t\2\2\u011d\u011e"+ + "\7x\2\2\u011e\u011f\7g\2\2\u011f\"\3\2\2\2\u0120\u0121\7k\2\2\u0121\u0122"+ + "\7h\2\2\u0122$\3\2\2\2\u0123\u0124\7g\2\2\u0124\u0125\7n\2\2\u0125\u0126"+ + "\7u\2\2\u0126\u0127\7g\2\2\u0127&\3\2\2\2\u0128\u0129\7y\2\2\u0129\u012a"+ + "\7j\2\2\u012a\u012b\7k\2\2\u012b\u012c\7n\2\2\u012c\u012d\7g\2\2\u012d"+ + "(\3\2\2\2\u012e\u012f\7f\2\2\u012f\u0130\7q\2\2\u0130*\3\2\2\2\u0131\u0132"+ + "\7h\2\2\u0132\u0133\7q\2\2\u0133\u0134\7t\2\2\u0134,\3\2\2\2\u0135\u0136"+ + "\7t\2\2\u0136\u0137\7g\2\2\u0137\u0138\7v\2\2\u0138\u0139\7w\2\2\u0139"+ + "\u013a\7t\2\2\u013a\u013b\7p\2\2\u013b.\3\2\2\2\u013c\u013d\7d\2\2\u013d"+ + "\u013e\7t\2\2\u013e\u013f\7g\2\2\u013f\u0140\7c\2\2\u0140\u0141\7m\2\2"+ + "\u0141\60\3\2\2\2\u0142\u0143\7e\2\2\u0143\u0144\7q\2\2\u0144\u0145\7"+ + "p\2\2\u0145\u0146\7v\2\2\u0146\u0147\7k\2\2\u0147\u0148\7p\2\2\u0148\u0149"+ + "\7w\2\2\u0149\u014a\7g\2\2\u014a\62\3\2\2\2\u014b\u014c\7c\2\2\u014c\u014d"+ + "\7u\2\2\u014d\u014e\7o\2\2\u014e\64\3\2\2\2\u014f\u0150\7<\2\2\u0150\66"+ + "\3\2\2\2\u0151\u0152\7\60\2\2\u0152\u0153\7\60\2\2\u01538\3\2\2\2\u0154"+ + "\u0155\7u\2\2\u0155\u0156\7k\2\2\u0156\u0157\7i\2\2\u0157\u0158\7p\2\2"+ + "\u0158\u0159\7g\2\2\u0159\u015a\7f\2\2\u015a:\3\2\2\2\u015b\u015c\7w\2"+ + "\2\u015c\u015d\7p\2\2\u015d\u015e\7u\2\2\u015e\u015f\7k\2\2\u015f\u0160"+ + "\7i\2\2\u0160\u0161\7p\2\2\u0161\u0162\7g\2\2\u0162\u0163\7f\2\2\u0163"+ + "<\3\2\2\2\u0164\u0165\7,\2\2\u0165>\3\2\2\2\u0166\u0167\7]\2\2\u0167@"+ + "\3\2\2\2\u0168\u0169\7_\2\2\u0169B\3\2\2\2\u016a\u016b\7u\2\2\u016b\u016c"+ + "\7k\2\2\u016c\u016d\7|\2\2\u016d\u016e\7g\2\2\u016e\u016f\7q\2\2\u016f"+ + "\u0170\7h\2\2\u0170D\3\2\2\2\u0171\u0172\7v\2\2\u0172\u0173\7{\2\2\u0173"+ + "\u0174\7r\2\2\u0174\u0175\7g\2\2\u0175\u0176\7k\2\2\u0176\u0177\7f\2\2"+ + "\u0177F\3\2\2\2\u0178\u0179\7/\2\2\u0179\u017a\7/\2\2\u017aH\3\2\2\2\u017b"+ + "\u017c\7-\2\2\u017c\u017d\7-\2\2\u017dJ\3\2\2\2\u017e\u017f\7-\2\2\u017f"+ + "L\3\2\2\2\u0180\u0181\7/\2\2\u0181N\3\2\2\2\u0182\u0183\7#\2\2\u0183P"+ + "\3\2\2\2\u0184\u0185\7(\2\2\u0185R\3\2\2\2\u0186\u0187\7\u0080\2\2\u0187"+ + "T\3\2\2\2\u0188\u0189\7@\2\2\u0189\u018a\7@\2\2\u018aV\3\2\2\2\u018b\u018c"+ + "\7>\2\2\u018c\u018d\7>\2\2\u018dX\3\2\2\2\u018e\u018f\7\61\2\2\u018fZ"+ + "\3\2\2\2\u0190\u0191\7\'\2\2\u0191\\\3\2\2\2\u0192\u0193\7>\2\2\u0193"+ + "^\3\2\2\2\u0194\u0195\7@\2\2\u0195`\3\2\2\2\u0196\u0197\7?\2\2\u0197\u0198"+ + "\7?\2\2\u0198b\3\2\2\2\u0199\u019a\7#\2\2\u019a\u019b\7?\2\2\u019bd\3"+ + "\2\2\2\u019c\u019d\7>\2\2\u019d\u019e\7?\2\2\u019ef\3\2\2\2\u019f\u01a0"+ + "\7@\2\2\u01a0\u01a1\7?\2\2\u01a1h\3\2\2\2\u01a2\u01a3\7`\2\2\u01a3j\3"+ + "\2\2\2\u01a4\u01a5\7~\2\2\u01a5l\3\2\2\2\u01a6\u01a7\7(\2\2\u01a7\u01a8"+ + "\7(\2\2\u01a8n\3\2\2\2\u01a9\u01aa\7~\2\2\u01aa\u01ab\7~\2\2\u01abp\3"+ + "\2\2\2\u01ac\u01ad\7A\2\2\u01adr\3\2\2\2\u01ae\u01af\7-\2\2\u01af\u01b0"+ + "\7?\2\2\u01b0t\3\2\2\2\u01b1\u01b2\7/\2\2\u01b2\u01b3\7?\2\2\u01b3v\3"+ + "\2\2\2\u01b4\u01b5\7,\2\2\u01b5\u01b6\7?\2\2\u01b6x\3\2\2\2\u01b7\u01b8"+ + "\7\61\2\2\u01b8\u01b9\7?\2\2\u01b9z\3\2\2\2\u01ba\u01bb\7\'\2\2\u01bb"+ + "\u01bc\7?\2\2\u01bc|\3\2\2\2\u01bd\u01be\7>\2\2\u01be\u01bf\7>\2\2\u01bf"+ + "\u01c0\7?\2\2\u01c0~\3\2\2\2\u01c1\u01c2\7@\2\2\u01c2\u01c3\7@\2\2\u01c3"+ + "\u01c4\7?\2\2\u01c4\u0080\3\2\2\2\u01c5\u01c6\7(\2\2\u01c6\u01c7\7?\2"+ + "\2\u01c7\u0082\3\2\2\2\u01c8\u01c9\7~\2\2\u01c9\u01ca\7?\2\2\u01ca\u0084"+ + "\3\2\2\2\u01cb\u01cc\7`\2\2\u01cc\u01cd\7?\2\2\u01cd\u0086\3\2\2\2\u01ce"+ + "\u01cf\7m\2\2\u01cf\u01d0\7k\2\2\u01d0\u01d1\7e\2\2\u01d1\u01d2\7m\2\2"+ + "\u01d2\u01d3\7c\2\2\u01d3\u01d4\7u\2\2\u01d4\u01d5\7o\2\2\u01d5\u0088"+ + "\3\2\2\2\u01d6\u01d7\7t\2\2\u01d7\u01d8\7g\2\2\u01d8\u01d9\7u\2\2\u01d9"+ + "\u01da\7q\2\2\u01da\u01db\7w\2\2\u01db\u01dc\7t\2\2\u01dc\u01dd\7e\2\2"+ + "\u01dd\u01de\7g\2\2\u01de\u008a\3\2\2\2\u01df\u01e0\7w\2\2\u01e0\u01e1"+ + "\7u\2\2\u01e1\u01e2\7g\2\2\u01e2\u01e3\7u\2\2\u01e3\u008c\3\2\2\2\u01e4"+ + "\u01e5\7e\2\2\u01e5\u01e6\7n\2\2\u01e6\u01e7\7q\2\2\u01e7\u01e8\7d\2\2"+ + "\u01e8\u01e9\7d\2\2\u01e9\u01ea\7g\2\2\u01ea\u01eb\7t\2\2\u01eb\u01ec"+ + "\7u\2\2\u01ec\u008e\3\2\2\2\u01ed\u01ee\7d\2\2\u01ee\u01ef\7{\2\2\u01ef"+ + "\u01f0\7v\2\2\u01f0\u01f1\7g\2\2\u01f1\u01f2\7u\2\2\u01f2\u0090\3\2\2"+ + "\2\u01f3\u01f4\7e\2\2\u01f4\u01f5\7{\2\2\u01f5\u01f6\7e\2\2\u01f6\u01f7"+ + "\7n\2\2\u01f7\u01f8\7g\2\2\u01f8\u01f9\7u\2\2\u01f9\u0092\3\2\2\2\u01fa"+ + "\u01fb\7r\2\2\u01fb\u01fc\7e\2\2\u01fc\u0094\3\2\2\2\u01fd\u01fe\7\60"+ + "\2\2\u01fe\u01ff\7d\2\2\u01ff\u0200\7{\2\2\u0200\u0201\7v\2\2\u0201\u0202"+ + "\7g\2\2\u0202\u0096\3\2\2\2\u0203\u0204\7%\2\2\u0204\u0098\3\2\2\2\u0205"+ + "\u0206\7\60\2\2\u0206\u009a\3\2\2\2\u0207\u0208\7d\2\2\u0208\u0209\7t"+ + "\2\2\u0209\u02e6\7m\2\2\u020a\u020b\7q\2\2\u020b\u020c\7t\2\2\u020c\u02e6"+ + "\7c\2\2\u020d\u020e\7m\2\2\u020e\u020f\7k\2\2\u020f\u02e6\7n\2\2\u0210"+ + "\u0211\7u\2\2\u0211\u0212\7n\2\2\u0212\u02e6\7q\2\2\u0213\u0214\7p\2\2"+ + "\u0214\u0215\7q\2\2\u0215\u02e6\7r\2\2\u0216\u0217\7c\2\2\u0217\u0218"+ + "\7u\2\2\u0218\u02e6\7n\2\2\u0219\u021a\7r\2\2\u021a\u021b\7j\2\2\u021b"+ + "\u02e6\7r\2\2\u021c\u021d\7c\2\2\u021d\u021e\7p\2\2\u021e\u02e6\7e\2\2"+ + "\u021f\u0220\7d\2\2\u0220\u0221\7r\2\2\u0221\u02e6\7n\2\2\u0222\u0223"+ + "\7e\2\2\u0223\u0224\7n\2\2\u0224\u02e6\7e\2\2\u0225\u0226\7l\2\2\u0226"+ + "\u0227\7u\2\2\u0227\u02e6\7t\2\2\u0228\u0229\7c\2\2\u0229\u022a\7p\2\2"+ + "\u022a\u02e6\7f\2\2\u022b\u022c\7t\2\2\u022c\u022d\7n\2\2\u022d\u02e6"+ + "\7c\2\2\u022e\u022f\7d\2\2\u022f\u0230\7k\2\2\u0230\u02e6\7v\2\2\u0231"+ + "\u0232\7t\2\2\u0232\u0233\7q\2\2\u0233\u02e6\7n\2\2\u0234\u0235\7r\2\2"+ + "\u0235\u0236\7n\2\2\u0236\u02e6\7c\2\2\u0237\u0238\7r\2\2\u0238\u0239"+ + "\7n\2\2\u0239\u02e6\7r\2\2\u023a\u023b\7d\2\2\u023b\u023c\7o\2\2\u023c"+ + "\u02e6\7k\2\2\u023d\u023e\7u\2\2\u023e\u023f\7g\2\2\u023f\u02e6\7e\2\2"+ + "\u0240\u0241\7t\2\2\u0241\u0242\7v\2\2\u0242\u02e6\7k\2\2\u0243\u0244"+ + "\7g\2\2\u0244\u0245\7q\2\2\u0245\u02e6\7t\2\2\u0246\u0247\7u\2\2\u0247"+ + "\u0248\7t\2\2\u0248\u02e6\7g\2\2\u0249\u024a\7n\2\2\u024a\u024b\7u\2\2"+ + "\u024b\u02e6\7t\2\2\u024c\u024d\7r\2\2\u024d\u024e\7j\2\2\u024e\u02e6"+ + "\7c\2\2\u024f\u0250\7c\2\2\u0250\u0251\7n\2\2\u0251\u02e6\7t\2\2\u0252"+ + "\u0253\7l\2\2\u0253\u0254\7o\2\2\u0254\u02e6\7r\2\2\u0255\u0256\7d\2\2"+ + "\u0256\u0257\7x\2\2\u0257\u02e6\7e\2\2\u0258\u0259\7e\2\2\u0259\u025a"+ + "\7n\2\2\u025a\u02e6\7k\2\2\u025b\u025c\7t\2\2\u025c\u025d\7v\2\2\u025d"+ + "\u02e6\7u\2\2\u025e\u025f\7c\2\2\u025f\u0260\7f\2\2\u0260\u02e6\7e\2\2"+ + "\u0261\u0262\7t\2\2\u0262\u0263\7t\2\2\u0263\u02e6\7c\2\2\u0264\u0265"+ + "\7d\2\2\u0265\u0266\7x\2\2\u0266\u02e6\7u\2\2\u0267\u0268\7u\2\2\u0268"+ + "\u0269\7g\2\2\u0269\u02e6\7k\2\2\u026a\u026b\7u\2\2\u026b\u026c\7c\2\2"+ + "\u026c\u02e6\7z\2\2\u026d\u026e\7u\2\2\u026e\u026f\7v\2\2\u026f\u02e6"+ + "\7{\2\2\u0270\u0271\7u\2\2\u0271\u0272\7v\2\2\u0272\u02e6\7c\2\2\u0273"+ + "\u0274\7u\2\2\u0274\u0275\7v\2\2\u0275\u02e6\7z\2\2\u0276\u0277\7f\2\2"+ + "\u0277\u0278\7g\2\2\u0278\u02e6\7{\2\2\u0279\u027a\7v\2\2\u027a\u027b"+ + "\7z\2\2\u027b\u02e6\7c\2\2\u027c\u027d\7z\2\2\u027d\u027e\7c\2\2\u027e"+ + "\u02e6\7c\2\2\u027f\u0280\7d\2\2\u0280\u0281\7e\2\2\u0281\u02e6\7e\2\2"+ + "\u0282\u0283\7c\2\2\u0283\u0284\7j\2\2\u0284\u02e6\7z\2\2\u0285\u0286"+ + "\7v\2\2\u0286\u0287\7{\2\2\u0287\u02e6\7c\2\2\u0288\u0289\7v\2\2\u0289"+ + "\u028a\7z\2\2\u028a\u02e6\7u\2\2\u028b\u028c\7v\2\2\u028c\u028d\7c\2\2"+ + "\u028d\u02e6\7u\2\2\u028e\u028f\7u\2\2\u028f\u0290\7j\2\2\u0290\u02e6"+ + "\7{\2\2\u0291\u0292\7u\2\2\u0292\u0293\7j\2\2\u0293\u02e6\7z\2\2\u0294"+ + "\u0295\7n\2\2\u0295\u0296\7f\2\2\u0296\u02e6\7{\2\2\u0297\u0298\7n\2\2"+ + "\u0298\u0299\7f\2\2\u0299\u02e6\7c\2\2\u029a\u029b\7n\2\2\u029b\u029c"+ + "\7f\2\2\u029c\u02e6\7z\2\2\u029d\u029e\7n\2\2\u029e\u029f\7c\2\2\u029f"+ + "\u02e6\7z\2\2\u02a0\u02a1\7v\2\2\u02a1\u02a2\7c\2\2\u02a2\u02e6\7{\2\2"+ + "\u02a3\u02a4\7v\2\2\u02a4\u02a5\7c\2\2\u02a5\u02e6\7z\2\2\u02a6\u02a7"+ + "\7d\2\2\u02a7\u02a8\7e\2\2\u02a8\u02e6\7u\2\2\u02a9\u02aa\7e\2\2\u02aa"+ + "\u02ab\7n\2\2\u02ab\u02e6\7x\2\2\u02ac\u02ad\7v\2\2\u02ad\u02ae\7u\2\2"+ + "\u02ae\u02e6\7z\2\2\u02af\u02b0\7n\2\2\u02b0\u02b1\7c\2\2\u02b1\u02e6"+ + "\7u\2\2\u02b2\u02b3\7e\2\2\u02b3\u02b4\7r\2\2\u02b4\u02e6\7{\2\2\u02b5"+ + "\u02b6\7e\2\2\u02b6\u02b7\7o\2\2\u02b7\u02e6\7r\2\2\u02b8\u02b9\7e\2\2"+ + "\u02b9\u02ba\7r\2\2\u02ba\u02e6\7z\2\2\u02bb\u02bc\7f\2\2\u02bc\u02bd"+ + "\7e\2\2\u02bd\u02e6\7r\2\2\u02be\u02bf\7f\2\2\u02bf\u02c0\7g\2\2\u02c0"+ + "\u02e6\7e\2\2\u02c1\u02c2\7k\2\2\u02c2\u02c3\7p\2\2\u02c3\u02e6\7e\2\2"+ + "\u02c4\u02c5\7c\2\2\u02c5\u02c6\7z\2\2\u02c6\u02e6\7u\2\2\u02c7\u02c8"+ + "\7d\2\2\u02c8\u02c9\7p\2\2\u02c9\u02e6\7g\2\2\u02ca\u02cb\7e\2\2\u02cb"+ + "\u02cc\7n\2\2\u02cc\u02e6\7f\2\2\u02cd\u02ce\7u\2\2\u02ce\u02cf\7d\2\2"+ + "\u02cf\u02e6\7e\2\2\u02d0\u02d1\7k\2\2\u02d1\u02d2\7u\2\2\u02d2\u02e6"+ + "\7e\2\2\u02d3\u02d4\7k\2\2\u02d4\u02d5\7p\2\2\u02d5\u02e6\7z\2\2\u02d6"+ + "\u02d7\7d\2\2\u02d7\u02d8\7g\2\2\u02d8\u02e6\7s\2\2\u02d9\u02da\7u\2\2"+ + "\u02da\u02db\7g\2\2\u02db\u02e6\7f\2\2\u02dc\u02dd\7f\2\2\u02dd\u02de"+ + "\7g\2\2\u02de\u02e6\7z\2\2\u02df\u02e0\7k\2\2\u02e0\u02e1\7p\2\2\u02e1"+ + "\u02e6\7{\2\2\u02e2\u02e3\7t\2\2\u02e3\u02e4\7q\2\2\u02e4\u02e6\7t\2\2"+ + "\u02e5\u0207\3\2\2\2\u02e5\u020a\3\2\2\2\u02e5\u020d\3\2\2\2\u02e5\u0210"+ + "\3\2\2\2\u02e5\u0213\3\2\2\2\u02e5\u0216\3\2\2\2\u02e5\u0219\3\2\2\2\u02e5"+ + "\u021c\3\2\2\2\u02e5\u021f\3\2\2\2\u02e5\u0222\3\2\2\2\u02e5\u0225\3\2"+ + "\2\2\u02e5\u0228\3\2\2\2\u02e5\u022b\3\2\2\2\u02e5\u022e\3\2\2\2\u02e5"+ + "\u0231\3\2\2\2\u02e5\u0234\3\2\2\2\u02e5\u0237\3\2\2\2\u02e5\u023a\3\2"+ + "\2\2\u02e5\u023d\3\2\2\2\u02e5\u0240\3\2\2\2\u02e5\u0243\3\2\2\2\u02e5"+ + "\u0246\3\2\2\2\u02e5\u0249\3\2\2\2\u02e5\u024c\3\2\2\2\u02e5\u024f\3\2"+ + "\2\2\u02e5\u0252\3\2\2\2\u02e5\u0255\3\2\2\2\u02e5\u0258\3\2\2\2\u02e5"+ + "\u025b\3\2\2\2\u02e5\u025e\3\2\2\2\u02e5\u0261\3\2\2\2\u02e5\u0264\3\2"+ + "\2\2\u02e5\u0267\3\2\2\2\u02e5\u026a\3\2\2\2\u02e5\u026d\3\2\2\2\u02e5"+ + "\u0270\3\2\2\2\u02e5\u0273\3\2\2\2\u02e5\u0276\3\2\2\2\u02e5\u0279\3\2"+ + "\2\2\u02e5\u027c\3\2\2\2\u02e5\u027f\3\2\2\2\u02e5\u0282\3\2\2\2\u02e5"+ + "\u0285\3\2\2\2\u02e5\u0288\3\2\2\2\u02e5\u028b\3\2\2\2\u02e5\u028e\3\2"+ + "\2\2\u02e5\u0291\3\2\2\2\u02e5\u0294\3\2\2\2\u02e5\u0297\3\2\2\2\u02e5"+ + "\u029a\3\2\2\2\u02e5\u029d\3\2\2\2\u02e5\u02a0\3\2\2\2\u02e5\u02a3\3\2"+ + "\2\2\u02e5\u02a6\3\2\2\2\u02e5\u02a9\3\2\2\2\u02e5\u02ac\3\2\2\2\u02e5"+ + "\u02af\3\2\2\2\u02e5\u02b2\3\2\2\2\u02e5\u02b5\3\2\2\2\u02e5\u02b8\3\2"+ + "\2\2\u02e5\u02bb\3\2\2\2\u02e5\u02be\3\2\2\2\u02e5\u02c1\3\2\2\2\u02e5"+ + "\u02c4\3\2\2\2\u02e5\u02c7\3\2\2\2\u02e5\u02ca\3\2\2\2\u02e5\u02cd\3\2"+ + "\2\2\u02e5\u02d0\3\2\2\2\u02e5\u02d3\3\2\2\2\u02e5\u02d6\3\2\2\2\u02e5"+ + "\u02d9\3\2\2\2\u02e5\u02dc\3\2\2\2\u02e5\u02df\3\2\2\2\u02e5\u02e2\3\2"+ + "\2\2\u02e6\u009c\3\2\2\2\u02e7\u02e8\7}\2\2\u02e8\u02e9\7}\2\2\u02e9\u02ed"+ + "\3\2\2\2\u02ea\u02ec\13\2\2\2\u02eb\u02ea\3\2\2\2\u02ec\u02ef\3\2\2\2"+ + "\u02ed\u02ee\3\2\2\2\u02ed\u02eb\3\2\2\2\u02ee\u02f0\3\2\2\2\u02ef\u02ed"+ + "\3\2\2\2\u02f0\u02f1\7\177\2\2\u02f1\u02f2\7\177\2\2\u02f2\u009e\3\2\2"+ + "\2\u02f3\u02f4\7d\2\2\u02f4\u02f5\7{\2\2\u02f5\u02f6\7v\2\2\u02f6\u0319"+ + "\7g\2\2\u02f7\u02f8\7y\2\2\u02f8\u02f9\7q\2\2\u02f9\u02fa\7t\2\2\u02fa"+ + "\u0319\7f\2\2\u02fb\u02fc\7f\2\2\u02fc\u02fd\7y\2\2\u02fd\u02fe\7q\2\2"+ + "\u02fe\u02ff\7t\2\2\u02ff\u0319\7f\2\2\u0300\u0301\7d\2\2\u0301\u0302"+ + "\7q\2\2\u0302\u0303\7q\2\2\u0303\u0319\7n\2\2\u0304\u0305\7e\2\2\u0305"+ + "\u0306\7j\2\2\u0306\u0307\7c\2\2\u0307\u0319\7t\2\2\u0308\u0309\7u\2\2"+ + "\u0309\u030a\7j\2\2\u030a\u030b\7q\2\2\u030b\u030c\7t\2\2\u030c\u0319"+ + "\7v\2\2\u030d\u030e\7k\2\2\u030e\u030f\7p\2\2\u030f\u0319\7v\2\2\u0310"+ + "\u0311\7n\2\2\u0311\u0312\7q\2\2\u0312\u0313\7p\2\2\u0313\u0319\7i\2\2"+ + "\u0314\u0315\7x\2\2\u0315\u0316\7q\2\2\u0316\u0317\7k\2\2\u0317\u0319"+ + "\7f\2\2\u0318\u02f3\3\2\2\2\u0318\u02f7\3\2\2\2\u0318\u02fb\3\2\2\2\u0318"+ + "\u0300\3\2\2\2\u0318\u0304\3\2\2\2\u0318\u0308\3\2\2\2\u0318\u030d\3\2"+ + "\2\2\u0318\u0310\3\2\2\2\u0318\u0314\3\2\2\2\u0319\u00a0\3\2\2\2\u031a"+ + "\u0320\7$\2\2\u031b\u031c\7^\2\2\u031c\u031f\7$\2\2\u031d\u031f\n\2\2"+ + "\2\u031e\u031b\3\2\2\2\u031e\u031d\3\2\2\2\u031f\u0322\3\2\2\2\u0320\u031e"+ + "\3\2\2\2\u0320\u0321\3\2\2\2\u0321\u0323\3\2\2\2\u0322\u0320\3\2\2\2\u0323"+ + "\u0325\7$\2\2\u0324\u0326\7|\2\2\u0325\u0324\3\2\2\2\u0325\u0326\3\2\2"+ + "\2\u0326\u00a2\3\2\2\2\u0327\u032b\7)\2\2\u0328\u0329\7^\2\2\u0329\u032c"+ + "\7)\2\2\u032a\u032c\n\3\2\2\u032b\u0328\3\2\2\2\u032b\u032a\3\2\2\2\u032c"+ + "\u032d\3\2\2\2\u032d\u032e\7)\2\2\u032e\u00a4\3\2\2\2\u032f\u0330\7v\2"+ + "\2\u0330\u0331\7t\2\2\u0331\u0332\7w\2\2\u0332\u0339\7g\2\2\u0333\u0334"+ + "\7h\2\2\u0334\u0335\7c\2\2\u0335\u0336\7n\2\2\u0336\u0337\7u\2\2\u0337"+ + "\u0339\7g\2\2\u0338\u032f\3\2\2\2\u0338\u0333\3\2\2\2\u0339\u00a6\3\2"+ + "\2\2\u033a\u033d\5\u00a9U\2\u033b\u033d\5\u00b1Y\2\u033c\u033a\3\2\2\2"+ + "\u033c\u033b\3\2\2\2\u033d\u00a8\3\2\2\2\u033e\u0342\5\u00abV\2\u033f"+ + "\u0342\5\u00adW\2\u0340\u0342\5\u00afX\2\u0341\u033e\3\2\2\2\u0341\u033f"+ + "\3\2\2\2\u0341\u0340\3\2\2\2\u0342\u00aa\3\2\2\2\u0343\u0349\7\'\2\2\u0344"+ + "\u0345\7\62\2\2\u0345\u0349\7d\2\2\u0346\u0347\7\62\2\2\u0347\u0349\7"+ + "D\2\2\u0348\u0343\3\2\2\2\u0348\u0344\3\2\2\2\u0348\u0346\3\2\2\2\u0349"+ + "\u034d\3\2\2\2\u034a\u034c\5\u00b9]\2\u034b\u034a\3\2\2\2\u034c\u034f"+ + "\3\2\2\2\u034d\u034b\3\2\2\2\u034d\u034e\3\2\2\2\u034e\u0350\3\2\2\2\u034f"+ + "\u034d\3\2\2\2\u0350\u0352\7\60\2\2\u0351\u0353\5\u00b9]\2\u0352\u0351"+ + "\3\2\2\2\u0353\u0354\3\2\2\2\u0354\u0352\3\2\2\2\u0354\u0355\3\2\2\2\u0355"+ + "\u00ac\3\2\2\2\u0356\u0358\5\u00bb^\2\u0357\u0356\3\2\2\2\u0358\u035b"+ + "\3\2\2\2\u0359\u0357\3\2\2\2\u0359\u035a\3\2\2\2\u035a\u035c\3\2\2\2\u035b"+ + "\u0359\3\2\2\2\u035c\u035e\7\60\2\2\u035d\u035f\5\u00bb^\2\u035e\u035d"+ + "\3\2\2\2\u035f\u0360\3\2\2\2\u0360\u035e\3\2\2\2\u0360\u0361\3\2\2\2\u0361"+ + "\u00ae\3\2\2\2\u0362\u0368\7&\2\2\u0363\u0364\7\62\2\2\u0364\u0368\7z"+ + "\2\2\u0365\u0366\7\62\2\2\u0366\u0368\7Z\2\2\u0367\u0362\3\2\2\2\u0367"+ + "\u0363\3\2\2\2\u0367\u0365\3\2\2\2\u0368\u036c\3\2\2\2\u0369\u036b\5\u00bd"+ + "_\2\u036a\u0369\3\2\2\2\u036b\u036e\3\2\2\2\u036c\u036a\3\2\2\2\u036c"+ + "\u036d\3\2\2\2\u036d\u036f\3\2\2\2\u036e\u036c\3\2\2\2\u036f\u0371\7\60"+ + "\2\2\u0370\u0372\5\u00bd_\2\u0371\u0370\3\2\2\2\u0372\u0373\3\2\2\2\u0373"+ + "\u0371\3\2\2\2\u0373\u0374\3\2\2\2\u0374\u00b0\3\2\2\2\u0375\u0379\5\u00b5"+ + "[\2\u0376\u0379\5\u00b7\\\2\u0377\u0379\5\u00b3Z\2\u0378\u0375\3\2\2\2"+ + "\u0378\u0376\3\2\2\2\u0378\u0377\3\2\2\2\u0379\u037d\3\2\2\2\u037a\u037b"+ + "\t\4\2\2\u037b\u037e\t\5\2\2\u037c\u037e\7n\2\2\u037d\u037a\3\2\2\2\u037d"+ + "\u037c\3\2\2\2\u037d\u037e\3\2\2\2\u037e\u00b2\3\2\2\2\u037f\u0380\7\62"+ + "\2\2\u0380\u0382\t\6\2\2\u0381\u0383\5\u00b9]\2\u0382\u0381\3\2\2\2\u0383"+ + "\u0384\3\2\2\2\u0384\u0382\3\2\2\2\u0384\u0385\3\2\2\2\u0385\u038d\3\2"+ + "\2\2\u0386\u0388\7\'\2\2\u0387\u0389\5\u00b9]\2\u0388\u0387\3\2\2\2\u0389"+ + "\u038a\3\2\2\2\u038a\u0388\3\2\2\2\u038a\u038b\3\2\2\2\u038b\u038d\3\2"+ + "\2\2\u038c\u037f\3\2\2\2\u038c\u0386\3\2\2\2\u038d\u00b4\3\2\2\2\u038e"+ + "\u0390\5\u00bb^\2\u038f\u038e\3\2\2\2\u0390\u0391\3\2\2\2\u0391\u038f"+ + "\3\2\2\2\u0391\u0392\3\2\2\2\u0392\u00b6\3\2\2\2\u0393\u0399\7&\2\2\u0394"+ + "\u0395\7\62\2\2\u0395\u0399\7z\2\2\u0396\u0397\7\62\2\2\u0397\u0399\7"+ + "Z\2\2\u0398\u0393\3\2\2\2\u0398\u0394\3\2\2\2\u0398\u0396\3\2\2\2\u0399"+ + "\u039b\3\2\2\2\u039a\u039c\5\u00bd_\2\u039b\u039a\3\2\2\2\u039c\u039d"+ + "\3\2\2\2\u039d\u039b\3\2\2\2\u039d\u039e\3\2\2\2\u039e\u00b8\3\2\2\2\u039f"+ + "\u03a0\t\7\2\2\u03a0\u00ba\3\2\2\2\u03a1\u03a2\t\b\2\2\u03a2\u00bc\3\2"+ + "\2\2\u03a3\u03a4\t\t\2\2\u03a4\u00be\3\2\2\2\u03a5\u03a9\5\u00c1a\2\u03a6"+ + "\u03a8\5\u00c3b\2\u03a7\u03a6\3\2\2\2\u03a8\u03ab\3\2\2\2\u03a9\u03a7"+ + "\3\2\2\2\u03a9\u03aa\3\2\2\2\u03aa\u00c0\3\2\2\2\u03ab\u03a9\3\2\2\2\u03ac"+ + "\u03ad\t\n\2\2\u03ad\u00c2\3\2\2\2\u03ae\u03af\t\13\2\2\u03af\u00c4\3"+ + "\2\2\2\u03b0\u03b4\7#\2\2\u03b1\u03b3\5\u00c3b\2\u03b2\u03b1\3\2\2\2\u03b3"+ + "\u03b6\3\2\2\2\u03b4\u03b2\3\2\2\2\u03b4\u03b5\3\2\2\2\u03b5\u03b8\3\2"+ + "\2\2\u03b6\u03b4\3\2\2\2\u03b7\u03b9\t\f\2\2\u03b8\u03b7\3\2\2\2\u03b9"+ + "\u03ba\3\2\2\2\u03ba\u03b8\3\2\2\2\u03ba\u03bb\3\2\2\2\u03bb\u00c6\3\2"+ + "\2\2\u03bc\u03be\t\r\2\2\u03bd\u03bc\3\2\2\2\u03be\u03bf\3\2\2\2\u03bf"+ + "\u03bd\3\2\2\2\u03bf\u03c0\3\2\2\2\u03c0\u03c1\3\2\2\2\u03c1\u03c2\bd"+ + "\2\2\u03c2\u00c8\3\2\2\2\u03c3\u03c4\7\61\2\2\u03c4\u03c5\7\61\2\2\u03c5"+ + "\u03c9\3\2\2\2\u03c6\u03c8\n\16\2\2\u03c7\u03c6\3\2\2\2\u03c8\u03cb\3"+ + "\2\2\2\u03c9\u03c7\3\2\2\2\u03c9\u03ca\3\2\2\2\u03ca\u03cc\3\2\2\2\u03cb"+ + "\u03c9\3\2\2\2\u03cc\u03cd\be\3\2\u03cd\u00ca\3\2\2\2\u03ce\u03cf\7\61"+ + "\2\2\u03cf\u03d0\7,\2\2\u03d0\u03d4\3\2\2\2\u03d1\u03d3\13\2\2\2\u03d2"+ + "\u03d1\3\2\2\2\u03d3\u03d6\3\2\2\2\u03d4\u03d5\3\2\2\2\u03d4\u03d2\3\2"+ + "\2\2\u03d5\u03d7\3\2\2\2\u03d6\u03d4\3\2\2\2\u03d7\u03d8\7,\2\2\u03d8"+ + "\u03d9\7\61\2\2\u03d9\u03da\3\2\2\2\u03da\u03db\bf\3\2\u03db\u00cc\3\2"+ + "\2\2#\2\u02e5\u02ed\u0318\u031e\u0320\u0325\u032b\u0338\u033c\u0341\u0348"+ + "\u034d\u0354\u0359\u0360\u0367\u036c\u0373\u0378\u037d\u0384\u038a\u038c"+ + "\u0391\u0398\u039d\u03a9\u03b4\u03ba\u03bf\u03c9\u03d4\4\2\3\2\2\4\2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index ed67c18d6..fe61073bd 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,7 +63,7 @@ public class TestPrograms { compileAndCompare("typeid-plus-byte-problem", log()); } - //@Test + @Test public void testTypeIdPlusBytes() throws IOException, URISyntaxException { compileAndCompare("typeid-plus-bytes"); } From eb895fffef967cace46cd921b7d5a92f02ad3236 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 2 May 2019 01:23:49 +0200 Subject: [PATCH 04/93] Added parser for typed integer literal postfix (ub/sb/uc/sc/uw/sw/ui/si/us/ss/ud/sd/ul/sl and l) --- .../java/dk/camelot64/kickc/NumberParser.java | 73 ++++++++++++------- .../kickc/model/values/ConstantInteger.java | 6 +- .../Pass0GenerateStatementSequence.java | 7 +- .../dk/camelot64/kickc/test/TestPrograms.java | 5 ++ src/test/kc/int-literals.kc | 19 +++++ 5 files changed, 78 insertions(+), 32 deletions(-) create mode 100644 src/test/kc/int-literals.kc diff --git a/src/main/java/dk/camelot64/kickc/NumberParser.java b/src/main/java/dk/camelot64/kickc/NumberParser.java index 5465bad9a..4f222860d 100644 --- a/src/main/java/dk/camelot64/kickc/NumberParser.java +++ b/src/main/java/dk/camelot64/kickc/NumberParser.java @@ -1,38 +1,61 @@ package dk.camelot64.kickc; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.ConstantInteger; + /** Parser for converting literal numbers to the corresponding Java Integer/Double */ public class NumberParser { - public static Number parseLiteral(String literal) { - boolean isInt = !literal.contains("."); + public static ConstantInteger parseIntegerLiteral(String literal) { - if(isInt) { - if(literal.startsWith("0x")) { - return parseHexInt(literal.substring(2)); - } else if(literal.startsWith("$")) { - return parseHexInt(literal.substring(1)); - } else if(literal.startsWith("0b")) { - return parseBinInt(literal.substring(2)); - } else if(literal.startsWith("%")) { - return parseBinInt(literal.substring(1)); - } else { - return parseDecInt(literal); - } - } else { + boolean isInt = !literal.contains("."); + if(!isInt) { throw new NumberFormatException("Not Implemented: non-integer parsing. " + literal); } + + SymbolType type = null; + if(literal.endsWith("ub") || literal.endsWith("uc")) { + type = SymbolType.BYTE; + literal = literal.substring(0, literal.length()-2); + } else if(literal.endsWith("sb") || literal.endsWith("sc")) { + type = SymbolType.SBYTE; + literal = literal.substring(0, literal.length()-2); + } else if(literal.endsWith("uw") || literal.endsWith("ui")|| literal.endsWith("us")) { + type = SymbolType.WORD; + literal = literal.substring(0, literal.length()-2); + } else if(literal.endsWith("sw") || literal.endsWith("si")|| literal.endsWith("ss")) { + type = SymbolType.SWORD; + literal = literal.substring(0, literal.length()-2); + } else if(literal.endsWith("ud") || literal.endsWith("ul")) { + type = SymbolType.DWORD; + literal = literal.substring(0, literal.length()-2); + } else if(literal.endsWith("sd") || literal.endsWith("sl")) { + type = SymbolType.SDWORD; + literal = literal.substring(0, literal.length()-2); + } else if(literal.endsWith("l")) { + type = SymbolType.SDWORD; + literal = literal.substring(0, literal.length()-1); + } + + Long value; + if(literal.startsWith("0x")) { + value = Long.parseLong(literal.substring(2), 16); + } else if(literal.startsWith("$")) { + value = Long.parseLong(literal.substring(1), 16); + } else if(literal.startsWith("0b")) { + value = Long.parseLong(literal.substring(2), 2); + } else if(literal.startsWith("%")) { + value = Long.parseLong(literal.substring(1), 2); + } else { + value = Long.parseLong(literal); + } + return new ConstantInteger(value, type); + } - private static Long parseHexInt(String literal) { - return Long.parseLong(literal, 16); - } - - private static Long parseBinInt(String literal) { - return Long.parseLong(literal, 2); - } - - private static Long parseDecInt(String literal) { - return Long.parseLong(literal); + public static Number parseLiteral(String literal) { + ConstantInteger constantInteger = parseIntegerLiteral(literal); + return constantInteger.getValue(); } diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java index b0131e99e..c4f8620eb 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java @@ -21,7 +21,11 @@ public class ConstantInteger implements ConstantEnumerable<Long> { public ConstantInteger(Long number, SymbolType type) { this.number = number; - this.type = type; + if(type!=null) { + this.type = type; + } else { + this.type = SymbolTypeMulti.getMultiType(number); + } } @Override diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 6889b48b4..efc72cdbd 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -1298,12 +1298,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { @Override public RValue visitExprNumber(KickCParser.ExprNumberContext ctx) { - Number number = NumberParser.parseLiteral(ctx.getText()); - if(number instanceof Long) { - return new ConstantInteger((Long) number); - } else { - return new ConstantDouble((Double) number); - } + return NumberParser.parseIntegerLiteral(ctx.getText()); } @Override diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index fe61073bd..cbc3675db 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,6 +32,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testIntegerLiterals() throws IOException, URISyntaxException { + compileAndCompare("int-literals"); + } + @Test public void testSimpleLoop() throws IOException, URISyntaxException { compileAndCompare("simple-loop"); diff --git a/src/test/kc/int-literals.kc b/src/test/kc/int-literals.kc new file mode 100644 index 000000000..0a66f2042 --- /dev/null +++ b/src/test/kc/int-literals.kc @@ -0,0 +1,19 @@ +// Tests different integer literals + +void main() { + unsigned byte ub = 12ub; + unsigned char uc = 12uc; + signed byte sb = 12sb; + signed byte sc = 12sc; + unsigned word uw = 12uw; + unsigned int ui = 12ui; + unsigned short us = 12us; + signed word sw = 12sw; + signed int si = 12si; + signed short ss = 12ss; + unsigned dword ud = 12ud; + unsigned long ul = 12ul; + signed dword sd = 12sd; + signed long sl = 12sl; + long l = 12l; +} \ No newline at end of file From facd8c6c5b611f33cfba2a50864879cdb8c1e089 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Fri, 3 May 2019 08:45:33 +0200 Subject: [PATCH 05/93] Expanded testing of types to include operators --- src/test/kc/int-literals.kc | 77 +++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/src/test/kc/int-literals.kc b/src/test/kc/int-literals.kc index 0a66f2042..d3fd609c6 100644 --- a/src/test/kc/int-literals.kc +++ b/src/test/kc/int-literals.kc @@ -1,19 +1,64 @@ -// Tests different integer literals +// Tests different integer literal types + +const byte RED = 2; +const byte GREEN = 5; + +const byte* SCREEN = $0400; +const byte* COLS = $d800; +byte idx = 0; void main() { - unsigned byte ub = 12ub; - unsigned char uc = 12uc; - signed byte sb = 12sb; - signed byte sc = 12sc; - unsigned word uw = 12uw; - unsigned int ui = 12ui; - unsigned short us = 12us; - signed word sw = 12sw; - signed int si = 12si; - signed short ss = 12ss; - unsigned dword ud = 12ud; - unsigned long ul = 12ul; - signed dword sd = 12sd; - signed long sl = 12sl; - long l = 12l; + for(byte* s: SCREEN..SCREEN+999) *s = ' '; + idx = 0; + testSimpleTypes(); + idx = 40; + testBinaryOperator(); +} + +void testSimpleTypes() { + // Simple types + assertType(typeid(12ub), typeid(byte)); + assertType(typeid(12uc), typeid(byte)); + assertType(typeid(12sb), typeid(signed byte)); + assertType(typeid(12sc), typeid(signed byte)); + assertType(typeid(12uw), typeid(word)); + assertType(typeid(12ui), typeid(word)); + assertType(typeid(12us), typeid(word)); + assertType(typeid(12sw), typeid(signed word)); + assertType(typeid(12si), typeid(signed word)); + assertType(typeid(12ss), typeid(signed word)); + assertType(typeid(12ud), typeid(dword)); + assertType(typeid(12ul), typeid(dword)); + assertType(typeid(12sd), typeid(signed dword)); + assertType(typeid(12sl), typeid(signed dword)); + assertType(typeid(12l), typeid(signed dword)); +} + +void testBinaryOperator() { + // Binary Operations between unsigned byte & other types + assertType(typeid(12ub+12ub), typeid(byte)); + assertType(typeid(12ub+12sb), typeid(byte)); + assertType(typeid(12ub+12uw), typeid(word)); + assertType(typeid(12ub+12sw), typeid(signed word)); + assertType(typeid(12ub+12ud), typeid(dword)); + assertType(typeid(12ub+12sd), typeid(signed dword)); + idx++; + // Binary Operations between signed byte & other types + assertType(typeid(12sb+12ub), typeid(byte)); + assertType(typeid(12sb+12sb), typeid(signed byte)); + assertType(typeid(12sb+12uw), typeid(word)); + assertType(typeid(12sb+12sw), typeid(signed word)); + assertType(typeid(12sb+12ud), typeid(dword)); + assertType(typeid(12sb+12sd), typeid(signed dword)); +} + + + +void assertType(byte t1, byte t2) { + if(t1==t2) { + COLS[idx] = GREEN; + } else { + COLS[idx] = RED; + } + SCREEN[idx++] = t1; } \ No newline at end of file From 35ec65ce94542548f2e5cfa7e19ec8cc59ffbddd Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 5 May 2019 01:26:40 +0200 Subject: [PATCH 06/93] Implemented much of integer type conversion and the number type. Still a lot left to do. --- .../java/dk/camelot64/kickc/Compiler.java | 9 +- .../camelot64/kickc/fragment/AsmFormat.java | 77 +++++---- .../camelot64/kickc/model/InternalError.java | 24 +++ .../model/operators/OperatorBitwiseAnd.java | 13 +- .../model/operators/OperatorBitwiseOr.java | 9 +- .../model/operators/OperatorBitwiseXor.java | 9 +- .../model/operators/OperatorCastByte.java | 4 +- .../model/operators/OperatorCastDWord.java | 4 +- .../model/operators/OperatorCastSByte.java | 2 +- .../model/operators/OperatorCastSDWord.java | 2 +- .../model/operators/OperatorCastSWord.java | 2 +- .../model/operators/OperatorCastWord.java | 4 +- .../kickc/model/operators/OperatorDivide.java | 2 +- .../kickc/model/operators/OperatorMinus.java | 8 +- .../kickc/model/operators/OperatorModulo.java | 2 +- .../model/operators/OperatorMultiply.java | 3 +- .../kickc/model/operators/OperatorPlus.java | 21 +-- .../kickc/model/types/SymbolType.java | 66 +++++--- .../model/types/SymbolTypeInference.java | 152 +----------------- .../kickc/model/types/SymbolTypeInteger.java | 48 +----- .../model/types/SymbolTypeIntegerAuto.java | 42 +++++ .../model/types/SymbolTypeIntegerFixed.java | 50 ++++++ .../kickc/model/types/SymbolTypeMulti.java | 2 +- .../types/SymbolTypeNumberInference.java | 104 ++++++++++++ .../kickc/model/values/ConstantInteger.java | 16 +- .../Pass0GenerateStatementSequence.java | 2 +- .../kickc/passes/Pass1AddTypePromotions.java | 102 ------------ .../kickc/passes/Pass1Procedures.java | 43 +++++ .../kickc/passes/Pass2AssertTypeMatch.java | 7 +- .../passes/Pass2ComparisonOptimization.java | 6 +- .../passes/Pass2ConstantIdentification.java | 82 +--------- .../Pass2ConstantRValueConsolidation.java | 125 ++++++++++++++ .../passes/Pass2FixInlineConstructors.java | 6 +- .../kickc/passes/Pass2RangeResolving.java | 8 +- .../kickc/passes/PassNAddTypeConversions.java | 134 +++++++++++++++ ...Inference.java => PassNTypeInference.java} | 15 +- .../dk/camelot64/kickc/test/TestPrograms.java | 12 +- src/test/kc/int-literals.kc | 91 ++++++++--- src/test/kc/number-type.kc | 23 +++ 39 files changed, 793 insertions(+), 538 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/model/InternalError.java create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerAuto.java create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java rename src/main/java/dk/camelot64/kickc/passes/{Pass1TypeInference.java => PassNTypeInference.java} (68%) create mode 100644 src/test/kc/number-type.kc diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index cb8d88400..f9a6b1fc6 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -153,7 +153,8 @@ public class Compiler { new Pass1GenerateControlFlowGraph(program).execute(); new Pass1ResolveForwardReferences(program).execute(); new Pass1UnwindBlockScopes(program).execute(); - new Pass1TypeInference(program).execute(); + new Pass1Procedures(program).execute(); + new PassNTypeInference(program).execute(); new Pass1TypeIdSimplification(program).execute(); if(getLog().isVerbosePass1CreateSsa()) { @@ -164,7 +165,7 @@ public class Compiler { new Pass1FixLValuesLoHi(program).execute(); new Pass1AssertNoLValueIntermediate(program).execute(); new Pass1PointerSizeofFix(program).execute(); - new Pass1AddTypePromotions(program).execute(); + new PassNAddTypeConversions(program).execute(); new Pass1EarlyConstantIdentification(program).execute(); new PassNStatementIndices(program).step(); new PassNCallGraphAnalysis(program).step(); @@ -230,6 +231,8 @@ public class Compiler { private void pass2Optimize() { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); + optimizations.add(new PassNTypeInference(program)); + optimizations.add(new PassNAddTypeConversions(program)); optimizations.add(new Pass2CullEmptyBlocks(program)); optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNVariableReferenceInfos(program)); @@ -240,6 +243,7 @@ public class Compiler { optimizations.add(new Pass2IdenticalPhiElimination(program)); optimizations.add(new Pass2ConditionalJumpSimplification(program)); optimizations.add(new Pass2ConditionalAndOrRewriting(program)); + optimizations.add(new Pass2ConstantRValueConsolidation(program)); optimizations.add(new Pass2ConstantIdentification(program)); optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNVariableReferenceInfos(program)); @@ -294,6 +298,7 @@ public class Compiler { constantOptimizations.add(new Pass2ConstantInlining(program)); constantOptimizations.add(new Pass2ConstantStringConsolidation(program)); constantOptimizations.add(new Pass2IdenticalPhiElimination(program)); + constantOptimizations.add(new Pass2ConstantRValueConsolidation(program)); constantOptimizations.add(new Pass2ConstantIdentification(program)); constantOptimizations.add(new Pass2ConstantAdditionElimination(program)); constantOptimizations.add(new Pass2ConstantSimplification(program)); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java index 28f28111f..895e806a8 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java @@ -7,11 +7,11 @@ import dk.camelot64.kickc.model.symbols.ConstantVar; import dk.camelot64.kickc.model.symbols.Procedure; import dk.camelot64.kickc.model.symbols.Symbol; import dk.camelot64.kickc.model.symbols.Variable; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypePointer; +import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.*; +import java.util.List; + /** Formatting of numbers, constants, names and more for KickAssembler */ public class AsmFormat { @@ -61,7 +61,7 @@ public class AsmFormat { } else if(symbol instanceof Procedure) { return getAsmParamName((Procedure) symbol, codeScope); } else { - throw new RuntimeException("Unhandled symbol type "+symbol); + throw new RuntimeException("Unhandled symbol type " + symbol); } } else if(value instanceof ConstantCastValue) { ConstantCastValue castValue = (ConstantCastValue) value; @@ -75,6 +75,7 @@ public class AsmFormat { /** * Get ASM for a binary constant expression + * * @param program The program * @param left The left operand of the expression * @param operator The binary operator @@ -85,12 +86,12 @@ public class AsmFormat { private static String getAsmConstantBinary(Program program, ConstantValue left, OperatorBinary operator, ConstantValue right, ScopeRef codeScope) { if(Operators.MODULO.equals(operator)) { // Remainder operator % not supported by KickAss - use modulo function instead - return "mod("+ + return "mod(" + getAsmConstant(program, left, operator.getPrecedence(), codeScope) + "," + - getAsmConstant(program, right, operator.getPrecedence(), codeScope)+ + getAsmConstant(program, right, operator.getPrecedence(), codeScope) + ")"; - } else { + } else { return getAsmConstant(program, left, operator.getPrecedence(), codeScope) + operator.getOperator() + getAsmConstant(program, right, operator.getPrecedence(), codeScope); @@ -109,28 +110,49 @@ public class AsmFormat { private static String getAsmConstantUnary(Program program, ScopeRef codeScope, Operator operator, ConstantValue operand, int outerPrecedence) { if(Operators.CAST_BYTE.equals(operator) || Operators.CAST_SBYTE.equals(operator)) { SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand); - if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) { + if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) { // No cast needed return getAsmConstant(program, operand, outerPrecedence, codeScope); - } else { - return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long)0xff), Operators.BOOL_AND, operand), outerPrecedence, codeScope); } - } else if(operator instanceof OperatorCastPtr || Operators.CAST_WORD.equals(operator) || Operators.CAST_SWORD.equals(operator) ) { + if(SymbolType.NUMBER.equals(operandType)) { + List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand); + if(operandInferedTypes.contains(SymbolType.BYTE) || operandInferedTypes.contains(SymbolType.SBYTE)) { + // No cast needed + return getAsmConstant(program, operand, outerPrecedence, codeScope); + } + } + // Cast is needed + return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xff), Operators.BOOL_AND, operand), outerPrecedence, codeScope); + } else if(operator instanceof OperatorCastPtr || Operators.CAST_WORD.equals(operator) || Operators.CAST_SWORD.equals(operator)) { SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand); - if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || SymbolType.isByte(operandType) || SymbolType.isSByte(operandType) || operandType instanceof SymbolTypePointer) { + if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType) || operandType instanceof SymbolTypePointer) { // No cast needed return getAsmConstant(program, operand, outerPrecedence, codeScope); - } else { - return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long)0xffff), Operators.BOOL_AND, operand), outerPrecedence, codeScope); } + if(SymbolType.NUMBER.equals(operandType)) { + List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand); + if(operandInferedTypes.contains(SymbolType.WORD) || operandInferedTypes.contains(SymbolType.SWORD)) { + // No cast needed + return getAsmConstant(program, operand, outerPrecedence, codeScope); + } + } + // Cast is needed + return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffff), Operators.BOOL_AND, operand), outerPrecedence, codeScope); } else if(Operators.CAST_DWORD.equals(operator) || Operators.CAST_SDWORD.equals(operator)) { SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand); - if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) { + if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType) || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType) || operandType instanceof SymbolTypePointer) { // No cast needed return getAsmConstant(program, operand, outerPrecedence, codeScope); - } else { - return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long)0xffffffffL), Operators.BOOL_AND, operand), outerPrecedence, codeScope); } + if(SymbolType.NUMBER.equals(operandType)) { + List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand); + if(operandInferedTypes.contains(SymbolType.DWORD) || operandInferedTypes.contains(SymbolType.SDWORD)) { + // No cast needed + return getAsmConstant(program, operand, outerPrecedence, codeScope); + } + } + // Cast is needed + return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffffffffL), Operators.BOOL_AND, operand), outerPrecedence, codeScope); } else if(Operators.LOWBYTE.equals(operator)) { SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand); if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) { @@ -138,9 +160,9 @@ public class AsmFormat { } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) { return "<" + getAsmConstant(program, operand, outerPrecedence, codeScope); } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) { - return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_AND, new ConstantInteger((long)0xffff)), outerPrecedence, codeScope); + return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_AND, new ConstantInteger((long) 0xffff)), outerPrecedence, codeScope); } else { - throw new CompileError("Unhandled type "+operand); + throw new CompileError("Unhandled type " + operand); } } else if(Operators.HIBYTE.equals(operator)) { SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand); @@ -149,24 +171,24 @@ public class AsmFormat { } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) { return ">" + getAsmConstant(program, operand, outerPrecedence, codeScope); } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) { - return getAsmConstant(program, new ConstantBinary(operand, Operators.SHIFT_RIGHT, new ConstantInteger((long)16)), outerPrecedence, codeScope); + return getAsmConstant(program, new ConstantBinary(operand, Operators.SHIFT_RIGHT, new ConstantInteger((long) 16)), outerPrecedence, codeScope); } else { - throw new CompileError("Unhandled type "+operand); + throw new CompileError("Unhandled type " + operand); } } else if(Operators.INCREMENT.equals(operator)) { - return getAsmConstant(program, new ConstantBinary(operand, Operators.PLUS, new ConstantInteger((long)1)), outerPrecedence, codeScope); + return getAsmConstant(program, new ConstantBinary(operand, Operators.PLUS, new ConstantInteger((long) 1)), outerPrecedence, codeScope); } else if(Operators.DECREMENT.equals(operator)) { - return getAsmConstant(program, new ConstantBinary(operand, Operators.MINUS, new ConstantInteger((long)1)), outerPrecedence, codeScope); + return getAsmConstant(program, new ConstantBinary(operand, Operators.MINUS, new ConstantInteger((long) 1)), outerPrecedence, codeScope); } else if(Operators.BOOL_NOT.equals(operator)) { SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand); if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) { - return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long)0xff)), outerPrecedence, codeScope); + return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xff)), outerPrecedence, codeScope); } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) { - return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long)0xffff)), outerPrecedence, codeScope); + return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xffff)), outerPrecedence, codeScope); } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) { - return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long)0xffffffff)), outerPrecedence, codeScope); + return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xffffffff)), outerPrecedence, codeScope); } else { - throw new CompileError("Unhandled type "+operand); + throw new CompileError("Unhandled type " + operand); } } else { return operator.getOperator() + @@ -208,6 +230,7 @@ public class AsmFormat { /** * Get the ASM code for a boolean value + * * @param bool the boolean vallue * @return "0" / "1" */ diff --git a/src/main/java/dk/camelot64/kickc/model/InternalError.java b/src/main/java/dk/camelot64/kickc/model/InternalError.java new file mode 100644 index 000000000..abf3ec469 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/InternalError.java @@ -0,0 +1,24 @@ +package dk.camelot64.kickc.model; + +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementSource; + +/** Signals an internal error in the compiler. Should be reported to the author. */ +public class InternalError extends RuntimeException { + + public InternalError(String message) { + super(message); + } + + public InternalError(String message, StatementSource source) { + super(message+"\n"+source.toString()); + } + + public InternalError(String message, Statement statement) { + this(message, statement.getSource()); + } + + public InternalError(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java index af0323d3e..022611a5b 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java @@ -32,16 +32,9 @@ public class OperatorBitwiseAnd extends OperatorBinary { if(type2 instanceof SymbolTypePointer) { type2 = SymbolType.WORD; } - // Find smallest bitwise type - if(type1 instanceof SymbolTypeInteger && type2 instanceof SymbolTypeInteger) { - - for(SymbolTypeInteger candidate : SymbolType.getIntegerTypes()) { - boolean match1 = ((SymbolTypeInteger) type1).getBits() <= candidate.getBits(); - boolean match2 = ((SymbolTypeInteger) type2).getBits() <= candidate.getBits(); - if(!candidate.isSigned() && (match1 || match2)) { - return candidate; - } - } + // Handle numeric types + if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { + return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); } throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java index 5b7669cf1..cad932fb1 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java @@ -1,10 +1,7 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; -import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; +import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -32,9 +29,9 @@ public class OperatorBitwiseOr extends OperatorBinary { if(type2 instanceof SymbolTypePointer) { type2 = SymbolType.WORD; } - // Handle numeric types through proper promotion + // Handle numeric types if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { - return SymbolType.promotedBitwiseType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); + return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); } throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java index f829640ef..b383ac3f0 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java @@ -1,10 +1,7 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; -import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; +import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -32,9 +29,9 @@ public class OperatorBitwiseXor extends OperatorBinary { if(type2 instanceof SymbolTypePointer) { type2 = SymbolType.WORD; } - // Handle numeric types through proper promotion + // Handle numeric types if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { - return SymbolType.promotedBitwiseType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); + return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); } throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java index de2a37f71..ea24ee803 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java @@ -18,9 +18,9 @@ public class OperatorCastByte extends OperatorUnary { @Override public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { - return new ConstantInteger(0xff & ((ConstantInteger) value).getValue()); + return new ConstantInteger(0xff & ((ConstantInteger) value).getValue(), SymbolType.BYTE); } else if(value instanceof ConstantPointer) { - return new ConstantInteger(0xff & ((ConstantPointer) value).getLocation()); + return new ConstantInteger(0xff & ((ConstantPointer) value).getLocation(), SymbolType.BYTE); } throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java index f27ae69e2..af76dbff4 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java @@ -18,10 +18,10 @@ public class OperatorCastDWord extends OperatorUnary { @Override public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { - return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue()); + return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue(), SymbolType.DWORD); } if(value instanceof ConstantPointer) { - return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation()); + return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation(), SymbolType.DWORD); } throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java index 8013ce770..d81cf7414 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java @@ -17,7 +17,7 @@ public class OperatorCastSByte extends OperatorUnary { @Override public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { - return new ConstantInteger(0xff & ((ConstantInteger) value).getValue()); + return new ConstantInteger(0xff & ((ConstantInteger) value).getValue(), SymbolType.SBYTE); } throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java index 01f5137bf..a07c5cd38 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java @@ -17,7 +17,7 @@ public class OperatorCastSDWord extends OperatorUnary { @Override public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { - return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue()); + return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue(), SymbolType.SDWORD); } throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java index ca7f35d83..094be277d 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java @@ -17,7 +17,7 @@ public class OperatorCastSWord extends OperatorUnary { @Override public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { - return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue()); + return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue(), SymbolType.SWORD); } throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java index 6414be198..f84aec9f0 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java @@ -18,10 +18,10 @@ public class OperatorCastWord extends OperatorUnary { @Override public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { - return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue()); + return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue(), SymbolType.WORD); } if(value instanceof ConstantPointer) { - return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation()); + return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation(), SymbolType.WORD); } throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java index 1e1ce9cd6..2a4058f16 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java @@ -38,7 +38,7 @@ public class OperatorDivide extends OperatorBinary { } // Handle numeric types through proper promotion if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { - return SymbolType.promotedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); + return SymbolType.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right); } throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java index 3f018c9d5..c06f6b938 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java @@ -1,10 +1,7 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; -import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; +import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.ConstantChar; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -39,10 +36,9 @@ public class OperatorMinus extends OperatorBinary { } else if(type1 instanceof SymbolTypePointer && type2 instanceof SymbolTypePointer) { return SymbolType.WORD; } - // Handle numeric types through proper promotion if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { - return SymbolType.promotedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); + return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); } throw new RuntimeException("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java index c26e36089..2931f6db1 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java @@ -27,7 +27,7 @@ public class OperatorModulo extends OperatorBinary { public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { // Handle numeric types through proper promotion if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { - return SymbolType.promotedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); + return SymbolType.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); } if(left instanceof ConstantPointer && right instanceof ConstantInteger) { return ((ConstantInteger) right).getType(); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java index 5da795636..7c3894bb5 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java @@ -3,6 +3,7 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInteger; +import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -26,7 +27,7 @@ public class OperatorMultiply extends OperatorBinary { public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { // Handle numeric types through proper promotion if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { - return SymbolType.promotedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); + return SymbolType.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); } throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java index 99556aa2e..f4f6e0ec7 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java @@ -39,31 +39,14 @@ public class OperatorPlus extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) { // Handle all non-numeric types - if(type1.equals(SymbolType.STRING) && isStringLike(type2)) { - return SymbolType.STRING; - } else if(isStringLike(type1) && type2.equals(SymbolType.STRING)) { - return SymbolType.STRING; - } else if(type1 instanceof SymbolTypeArray && type2 instanceof SymbolTypeArray) { - SymbolType elemType1 = ((SymbolTypeArray) type1).getElementType(); - SymbolType elemType2 = ((SymbolTypeArray) type2).getElementType(); - if(SymbolTypeInference.typeMatch(elemType1, elemType2)) { - return new SymbolTypeArray(elemType1); - } else if(SymbolTypeInference.typeMatch(elemType2, elemType1)) { - return new SymbolTypeArray(elemType2); - } else { - throw new RuntimeException("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); - } - } else if(SymbolType.isInteger(type1) && type2 instanceof SymbolTypePointer ) { + if(SymbolType.isInteger(type1) && type2 instanceof SymbolTypePointer) { return new SymbolTypePointer(((SymbolTypePointer) type2).getElementType()); } else if(type1 instanceof SymbolTypePointer && SymbolType.isInteger(type2)) { return new SymbolTypePointer(((SymbolTypePointer) type1).getElementType()); - } else if(type1 instanceof SymbolTypePointer && type2 instanceof SymbolTypePointer) { - throw new NoMatchingType("Two pointers cannot be added."); } - // Handle numeric types through proper promotion if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { - return SymbolType.promotedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); + return SymbolType.convertedMathType( (SymbolTypeInteger) type1, (SymbolTypeInteger)type2); } throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java index 9bf23a2f8..c8a043c17 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java @@ -9,17 +9,19 @@ import java.util.Collection; public interface SymbolType { /** Unsigned byte (8 bits)). */ - SymbolTypeInteger BYTE = new SymbolTypeInteger("byte", 0, 255, false, 8); + SymbolTypeIntegerFixed BYTE = new SymbolTypeIntegerFixed("byte", 0, 255, false, 8); /** Signed byte (8 bits). */ - SymbolTypeInteger SBYTE = new SymbolTypeInteger("signed byte", -128, 127, true, 8); + SymbolTypeIntegerFixed SBYTE = new SymbolTypeIntegerFixed("signed byte", -128, 127, true, 8); /** Unsigned word (2 bytes, 16 bits). */ - SymbolTypeInteger WORD = new SymbolTypeInteger("word", 0, 65_535, false, 16); + SymbolTypeIntegerFixed WORD = new SymbolTypeIntegerFixed("word", 0, 65_535, false, 16); /** Signed word (2 bytes, 16 bits). */ - SymbolTypeInteger SWORD = new SymbolTypeInteger("signed word", -32_768, 32_767, true, 16); + SymbolTypeIntegerFixed SWORD = new SymbolTypeIntegerFixed("signed word", -32_768, 32_767, true, 16); /** Unsigned double word (4 bytes, 32 bits). */ - SymbolTypeInteger DWORD = new SymbolTypeInteger("dword", 0, 4_294_967_296L, false, 32); + SymbolTypeIntegerFixed DWORD = new SymbolTypeIntegerFixed("dword", 0, 4_294_967_296L, false, 32); /** Signed double word (4 bytes, 32 bits). */ - SymbolTypeInteger SDWORD = new SymbolTypeInteger("signed dword", -2_147_483_648, 2_147_483_647, true, 32); + SymbolTypeIntegerFixed SDWORD = new SymbolTypeIntegerFixed("signed dword", -2_147_483_648, 2_147_483_647, true, 32); + /** Integer with unknown size. */ + SymbolTypeIntegerAuto NUMBER = new SymbolTypeIntegerAuto("number"); /** String value (treated like byte* ). */ SymbolTypeNamed STRING = new SymbolTypeNamed("string", 99); /** Boolean value. */ @@ -204,13 +206,13 @@ public interface SymbolType { } /** - * Is the type an integer type or compatible {@link SymbolTypeMulti} + * Is the type an integer type (including {@link #NUMBER}) * * @param type The type to examine * @return true if the type is integer */ static boolean isInteger(SymbolType type) { - return isSDWord(type) || isDWord(type) || isSWord(type) || isWord(type) || isSByte(type) || isByte(type); + return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type); } /** @@ -218,8 +220,8 @@ public interface SymbolType { * * @return All integeer types */ - static Collection<SymbolTypeInteger> getIntegerTypes() { - ArrayList<SymbolTypeInteger> types = new ArrayList<>(); + static Collection<SymbolTypeIntegerFixed> getIntegerFixedTypes() { + ArrayList<SymbolTypeIntegerFixed> types = new ArrayList<>(); types.add(BYTE); types.add(SBYTE); types.add(WORD); @@ -230,21 +232,41 @@ public interface SymbolType { } /** - * Find the smallest integer type that contains both sub-types usable for math ( + - * / ). + * Find the integer type that results from a binary operator according to C99 6.3.1.8 + * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70 * * @param type1 Left type in a binary expression * @param type2 Right type in a binary expression - * @return + * @return The type resulting from a binary operator performed on the two parameters */ - static SymbolType promotedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) { - for(SymbolTypeInteger candidate : getIntegerTypes()) { - boolean match1 = type1.getMinValue() >= candidate.getMinValue() && type1.getMaxValue() <= candidate.getMaxValue(); - boolean match2 = type2.getMinValue() >= candidate.getMinValue() && type2.getMaxValue() <= candidate.getMaxValue(); - if(match1 && match2) { - return candidate; - } + static SymbolType convertedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) { + if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) { + return NUMBER; } - throw new NoMatchingType("Cannot promote to a common type for "+type1.toString()+" and "+type2.toString()); + SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1; + SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2; + // C99 6.3.1.8 a. If two operands have the same type no conversion is performed + if(type1.equals(type2)) + return type1; + // C99 6.3.1.8 b. If both are signed or both are unsigned then the smallest type is converted to the size of the large type (byte->word->sword, sbyte->sword->sdword) + if(fixed1.isSigned()==fixed2.isSigned()) + return (fixed1.getBits()>fixed2.getBits()) ? fixed1 : fixed2; + // C99 6.3.1.8 c. One is signed and one unsigned. + // If the signed type can contain all values of the unsigned type then the unsigned value is converted to the signed type. (byte->sword, byte->sdword, word->sdword). + SymbolTypeIntegerFixed typeS, typeU; + if(fixed1.isSigned()) { + typeS = fixed1; + typeU = fixed2; + } else { + typeS = fixed2; + typeU = fixed1; + } + if(typeS.getBits()>typeU.getBits()) + return typeS; + // C99 6.3.1.8 d. The unsigned type is the same size as or larger than the signed type. + // The signed value is first converted to the size of the unsigned type and then converted to unsigned changing the sign and the value + // (sbyte->byte, sbyte->word, sbyte->dword, sword->word, sword->dword, sdword->dword). + return typeU; } /** @@ -254,8 +276,8 @@ public interface SymbolType { * @param type2 Right type in a binary expression * @return */ - static SymbolType promotedBitwiseType(SymbolTypeInteger type1, SymbolTypeInteger type2) { - for(SymbolTypeInteger candidate : getIntegerTypes()) { + static SymbolType promotedBitwiseType(SymbolTypeIntegerFixed type1, SymbolTypeIntegerFixed type2) { + for(SymbolTypeIntegerFixed candidate : getIntegerFixedTypes()) { if(!candidate.isSigned() && type1.getBits()<=candidate.getBits() && type2.getBits()<=candidate.getBits()) { return candidate; } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index d80e44138..477a34d28 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -1,18 +1,15 @@ package dk.camelot64.kickc.model.types; import dk.camelot64.kickc.model.CompileError; -import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.operators.Operator; import dk.camelot64.kickc.model.operators.OperatorBinary; import dk.camelot64.kickc.model.operators.OperatorUnary; -import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.*; import dk.camelot64.kickc.model.symbols.*; import dk.camelot64.kickc.model.values.*; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -30,23 +27,6 @@ public class SymbolTypeInference { * @return The type of the resulting value */ public static SymbolType inferType(ProgramScope programScope, OperatorUnary operator, RValue rValue) { - if(Operators.TYPEID.equals(operator)) { - return SymbolType.BYTE; - } else if(Operators.SIZEOF.equals(operator)) { - return SymbolType.BYTE; - } - if(rValue instanceof ConstantValue) { - // Calculate resulting constant literal - try { - ConstantValue constRValue = (ConstantValue) rValue; - ConstantLiteral literalRValue = constRValue.calculateLiteral(programScope); - ConstantValue value = operator.calculateLiteral(literalRValue, programScope); - return value.getType(programScope); - } catch(ConstantNotLiteral e) { - // Value literal cannot be calculated - } - } - // Infer value type - and then infer operator result type SymbolType valueType = inferType(programScope, rValue); return inferType(operator, valueType); } @@ -62,19 +42,7 @@ public class SymbolTypeInference { if(operandType instanceof SymbolTypeSimple) { return operator.inferType((SymbolTypeSimple) operandType); } else { - // Infer all resulting types for each sub-type of the multi-type - ArrayList<SymbolType> resultTypes = new ArrayList<>(); - for(SymbolType opType : ((SymbolTypeMulti) operandType).getTypes()) { - SymbolType resType = inferType(operator, opType); - if(!resultTypes.contains(resType)) { - resultTypes.add(resType); - } - } - if(resultTypes.size() == 1) { - return resultTypes.get(0); - } else { - return new SymbolTypeMulti(resultTypes); - } + throw new RuntimeException("Not implemented!"); } } @@ -88,18 +56,6 @@ public class SymbolTypeInference { * @return The type of the resulting value */ public static SymbolType inferType(ProgramScope programScope, RValue left, OperatorBinary operator, RValue right) { - if(left instanceof ConstantValue && right instanceof ConstantValue) { - // Calculate resulting constant literal - try { - ConstantValue value = operator.calculateLiteral( - ((ConstantValue) left).calculateLiteral(programScope), - ((ConstantValue) right).calculateLiteral(programScope) - ); - return value.getType(programScope); - } catch(ConstantNotLiteral e) { - // Value literal cannot be calculated - } - } SymbolType leftType = inferType(programScope, left); SymbolType rightType = inferType(programScope, right); return inferType(leftType, operator, rightType); @@ -109,32 +65,7 @@ public class SymbolTypeInference { if(left instanceof SymbolTypeSimple && right instanceof SymbolTypeSimple) { return operator.inferType((SymbolTypeSimple) left, (SymbolTypeSimple) right); } else { - // Infer all resulting types for each sub-type of the multi-type - if(left instanceof SymbolTypeSimple) { - left = new SymbolTypeMulti(Arrays.asList(left)); - } - if(right instanceof SymbolTypeSimple) { - right = new SymbolTypeMulti(Arrays.asList(right)); - } - ArrayList<SymbolType> resultTypes = new ArrayList<>(); - for(SymbolType leftType : ((SymbolTypeMulti) left).getTypes()) { - for(SymbolType rightType : ((SymbolTypeMulti) right).getTypes()) { - SymbolType resType; - try { - resType = inferType(leftType, operator, rightType); - if(!resultTypes.contains(resType)) { - resultTypes.add(resType); - } - } catch(NoMatchingType e) { - // Cannot promote to common type - ignore! - } - } - } - if(resultTypes.size() == 1) { - return resultTypes.get(0); - } else { - return new SymbolTypeMulti(resultTypes); - } + throw new RuntimeException("Not implemented!"); } } @@ -209,13 +140,8 @@ public class SymbolTypeInference { if(elmType == null) { elmType = type; } else { - // element type already defined - check for a match - if(!typeMatch(elmType, type)) { - if(typeMatch(type, elmType)) { - elmType = type; - } else { - throw new RuntimeException("Array element has type mismatch " + elm.toString() + " not matching type " + elmType.getTypeName()); - } + if(!elmType.equals(type)) { + throw new RuntimeException("Array element has type mismatch " + elm.toString() + " not matching type " + elmType.getTypeName()); } } } @@ -256,74 +182,12 @@ public class SymbolTypeInference { return rValueType; } - /** - * Determine if lValue and rValue types match (the same types, not needing a cast). - * - * @param lValueType The lValue type - * @param rValueType The rvalue type - * @return true if the types match - */ - public static boolean typeMatch(SymbolType lValueType, SymbolType rValueType) { - if(lValueType.equals(rValueType)) { - // Types match directly - return true; - } else if(rValueType instanceof SymbolTypeMulti) { - Collection<SymbolType> rTypes = ((SymbolTypeMulti) rValueType).getTypes(); - if(lValueType instanceof SymbolTypeMulti) { - // Both are inline types - RValue type must be superset of LValue - Collection<SymbolType> lTypes = ((SymbolTypeMulti) lValueType).getTypes(); - return typeContainsMatchAll(lTypes, rTypes); - } else { - // Types match because the right side matches the left side - return typeContainsMatch(lValueType, rTypes); - } - } else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer) { - return typeMatch( - ((SymbolTypePointer) lValueType).getElementType(), - ((SymbolTypePointer) rValueType).getElementType()); - } else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType)) { - if(SymbolType.isByte(((SymbolTypePointer) lValueType).getElementType())) { - return true; - } - } else if(SymbolType.STRING.equals(lValueType) && rValueType instanceof SymbolTypePointer) { - if(SymbolType.isByte(((SymbolTypePointer) rValueType).getElementType())) { - return true; - } - } - return false; - } - - private static boolean typeContainsMatchAll(Collection<SymbolType> lTypes, Collection<SymbolType> rTypes) { - for(SymbolType lType : lTypes) { - if(!typeContainsMatch(lType, rTypes)) { - return false; - } - } - return true; - } - - /** - * Determine is a list of potential inferred types contains a match for another type - * - * @param lValueType The type (rValue) we want to find a match for in the list - * @param rTypes The list of inferred potential types - * @return true if the list has a match - */ - private static boolean typeContainsMatch(SymbolType lValueType, Collection<SymbolType> rTypes) { - for(SymbolType rType : rTypes) { - if(typeMatch(lValueType, rType)) { - return true; - } - } - return false; - } - public static void inferCallLValue(Program program, StatementCall call, boolean reinfer) { ProgramScope programScope = program.getScope(); LValue lValue = call.getlValue(); if(lValue instanceof VariableRef) { Variable symbol = programScope.getVariable((VariableRef) lValue); - if(SymbolType.VAR.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { Procedure procedure = programScope.getProcedure(call.getProcedure()); SymbolType type = procedure.getReturnType(); setInferedType(program, call, symbol, type); @@ -336,7 +200,7 @@ public class SymbolTypeInference { LValue lValue = call.getlValue(); if(lValue instanceof VariableRef) { Variable symbol = programScope.getVariable((VariableRef) lValue); - if(SymbolType.VAR.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { SymbolType procedureType = inferType(programScope, call.getProcedure()); if(procedureType instanceof SymbolTypeProcedure) { SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType(); @@ -350,7 +214,7 @@ public class SymbolTypeInference { ProgramScope programScope = program.getScope(); Variable symbol = programScope.getVariable(phiVariable.getVariable()); - if(SymbolType.VAR.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { SymbolType type = null; for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { RValue rValue = phiRValue.getrValue(); @@ -377,7 +241,7 @@ public class SymbolTypeInference { LValue lValue = assignment.getlValue(); if(lValue instanceof VariableRef) { Variable symbol = programScope.getVariable((VariableRef) lValue); - if(SymbolType.VAR.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { // Unresolved symbol - perform inference Operator operator = assignment.getOperator(); if(assignment.getrValue1() == null && operator == null) { diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java index 1813650c8..2a4cdfa7f 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java @@ -1,50 +1,6 @@ package dk.camelot64.kickc.model.types; -/** Integer symbol types (byte, signed byte, word, ...). */ -public class SymbolTypeInteger implements SymbolTypeSimple { +/** Integer type marker interface. */ +public interface SymbolTypeInteger extends SymbolTypeSimple { - private final String typeName; - private final long minValue; - private final long maxValue; - private final boolean signed; - private final int bits; - - SymbolTypeInteger(String typeName, long minValue, long maxValue, boolean signed, int bits) { - this.typeName = typeName; - this.minValue = minValue; - this.maxValue = maxValue; - this.signed = signed; - this.bits = bits; - } - - @Override - public String getTypeName() { - return typeName; - } - - public long getMinValue() { - return minValue; - } - - public long getMaxValue() { - return maxValue; - } - - public boolean isSigned() { - return signed; - } - - public int getBits() { - return bits; - } - - @Override - public int getSizeBytes() { - return bits/8; - } - - @Override - public String toString() { - return getTypeName(); - } } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerAuto.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerAuto.java new file mode 100644 index 000000000..6e643aad8 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerAuto.java @@ -0,0 +1,42 @@ +package dk.camelot64.kickc.model.types; + +import java.util.Objects; + +/** Integer type that has not yet been fixed. This is used for constant expressions. The type is fixed when the constant meets a fixed type. */ +public class SymbolTypeIntegerAuto implements SymbolTypeInteger { + + private final String typeName; + + SymbolTypeIntegerAuto(String typeName) { + this.typeName = typeName; + } + + @Override + public String getTypeName() { + return typeName; + } + + @Override + public int getSizeBytes() { + return -1; + } + + @Override + public String toString() { + return getTypeName(); + } + + + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + SymbolTypeIntegerAuto that = (SymbolTypeIntegerAuto) o; + return Objects.equals(typeName, that.typeName); + } + + @Override + public int hashCode() { + return Objects.hash(typeName); + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java new file mode 100644 index 000000000..1c6a35cc5 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java @@ -0,0 +1,50 @@ +package dk.camelot64.kickc.model.types; + +/** Integer type with a fixed size (byte, signed byte, word, ...). */ +public class SymbolTypeIntegerFixed implements SymbolTypeInteger { + + private final String typeName; + private final long minValue; + private final long maxValue; + private final boolean signed; + private final int bits; + + SymbolTypeIntegerFixed(String typeName, long minValue, long maxValue, boolean signed, int bits) { + this.typeName = typeName; + this.minValue = minValue; + this.maxValue = maxValue; + this.signed = signed; + this.bits = bits; + } + + @Override + public String getTypeName() { + return typeName; + } + + public long getMinValue() { + return minValue; + } + + public long getMaxValue() { + return maxValue; + } + + public boolean isSigned() { + return signed; + } + + public int getBits() { + return bits; + } + + @Override + public int getSizeBytes() { + return bits/8; + } + + @Override + public String toString() { + return getTypeName(); + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java index 5b1ca45a5..ced732cb9 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java @@ -34,7 +34,7 @@ public class SymbolTypeMulti implements SymbolType { */ public static SymbolType getMultiType(Long number) { ArrayList<SymbolType> potentialTypes = new ArrayList<>(); - for(SymbolTypeInteger typeInteger : SymbolType.getIntegerTypes()) { + for(SymbolTypeIntegerFixed typeInteger : SymbolType.getIntegerFixedTypes()) { if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) { potentialTypes.add(typeInteger); } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java new file mode 100644 index 000000000..7473e4230 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java @@ -0,0 +1,104 @@ +package dk.camelot64.kickc.model.types; + +import dk.camelot64.kickc.model.InternalError; +import dk.camelot64.kickc.model.operators.OperatorBinary; +import dk.camelot64.kickc.model.operators.OperatorUnary; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.symbols.ProgramScope; +import dk.camelot64.kickc.model.values.ConstantInteger; +import dk.camelot64.kickc.model.values.ConstantLiteral; +import dk.camelot64.kickc.model.values.ConstantValue; +import dk.camelot64.kickc.model.values.RValue; + +import java.util.ArrayList; +import java.util.List; + +/** + * Interference of possible types for constant expressions with the {@link SymbolType#NUMBER} type. + * This is done by evaluating the constant expression to find the literal value. + */ +public class SymbolTypeNumberInference { + + /** + * Infer the potential types for an RValue with {@link SymbolType#NUMBER} type + * + * @return The potential types + */ + public static List<SymbolTypeIntegerFixed> inferTypesRValue(ProgramScope symbols, StatementAssignment assignment) { + RValue rValue1 = assignment.getrValue1(); + RValue rValue2 = assignment.getrValue2(); + if(assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof ConstantValue) { + return inferTypes(symbols, (ConstantValue) rValue2); + } else if(assignment.getrValue1() == null && assignment.getOperator() instanceof OperatorUnary && assignment.getrValue2() instanceof ConstantValue) { + return inferTypes(symbols, (OperatorUnary) assignment.getOperator(), (ConstantValue) rValue2); + } else if(assignment.getOperator() instanceof OperatorBinary && assignment.getrValue1() instanceof ConstantValue && assignment.getrValue2() instanceof ConstantValue) { + return inferTypes(symbols, (ConstantValue) rValue1, (OperatorBinary) assignment.getOperator(), (ConstantValue) rValue2); + } else { + return new ArrayList<>(); + } + } + + /** + * Infer the potential types for a binary operator with {@link SymbolType#NUMBER} type + * + * @return The potential types + */ + public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantValue leftValue, OperatorBinary operator, ConstantValue rightValue) { + if(SymbolType.NUMBER.equals(leftValue.getType(programScope)) && SymbolType.NUMBER.equals(rightValue.getType(programScope))) { + // Calculate resulting constant literal + ConstantLiteral leftLiteral = leftValue.calculateLiteral(programScope); + ConstantLiteral rightLiteral = rightValue.calculateLiteral(programScope); + ConstantLiteral constantLiteral = operator.calculateLiteral(leftLiteral, rightLiteral); + return inferTypes(programScope, constantLiteral); + } else { + throw new InternalError("Both operands must be number type."); + } + } + + /** + * Infer the potential types for a unary operator with {@link SymbolType#NUMBER} type + * + * @return The potential types + */ + public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, OperatorUnary operator, ConstantValue constantValue) { + if(SymbolType.NUMBER.equals(constantValue.getType(programScope))) { + // Calculate resulting constant literal + ConstantLiteral operandLiteral = constantValue.calculateLiteral(programScope); + ConstantLiteral constantLiteral = operator.calculateLiteral(operandLiteral, programScope); + return inferTypes(programScope, constantLiteral); + } else { + throw new InternalError("Operand must be number type."); + } + } + + /** + * Infer the potential types for a constant value with {@link SymbolType#NUMBER} type + * + * @return The potential types + */ + public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantValue constantValue) { + // Calculate resulting constant literal + ConstantLiteral constantLiteral = constantValue.calculateLiteral(programScope); + return inferTypes(programScope, constantLiteral); + } + + /** + * Infer the potential types for a constant literal with {@link SymbolType#NUMBER} type + */ + public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantLiteral literal) { + if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) { + ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>(); + ConstantInteger constantInteger = (ConstantInteger) literal; + Long number = constantInteger.getValue(); + for(SymbolTypeIntegerFixed typeInteger : SymbolType.getIntegerFixedTypes()) { + if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) { + potentialTypes.add(typeInteger); + } + } + return potentialTypes; + } else { + throw new InternalError("Literal must number type."); + } + } + +} diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java index c4f8620eb..7eccd45a4 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java @@ -1,30 +1,29 @@ package dk.camelot64.kickc.model.values; import dk.camelot64.kickc.fragment.AsmFormat; -import dk.camelot64.kickc.model.*; +import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeMulti; /** Constant integer value */ public class ConstantInteger implements ConstantEnumerable<Long> { private Long number; - /** The type of the number. (Either specific or the multi-type)*/ + /** The type of the number. (Either fixed size og the "number" type) */ private SymbolType type; public ConstantInteger(Long number) { this.number = number; - this.type = SymbolTypeMulti.getMultiType(number); + this.type = SymbolType.NUMBER; } public ConstantInteger(Long number, SymbolType type) { this.number = number; - if(type!=null) { + if(type != null) { this.type = type; } else { - this.type = SymbolTypeMulti.getMultiType(number); + this.type = SymbolType.NUMBER; } } @@ -45,6 +44,10 @@ public class ConstantInteger implements ConstantEnumerable<Long> { return type; } + public void setType(SymbolType type) { + this.type = type; + } + @Override public String toString() { return toString(null); @@ -71,4 +74,5 @@ public class ConstantInteger implements ConstantEnumerable<Long> { public int hashCode() { return number != null ? number.hashCode() : 0; } + } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index efc72cdbd..65afaf38f 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -499,7 +499,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { if(initializer != null) { addInitialAssignment(initializer, lValue, comments); } else { - if(type instanceof SymbolTypeInteger) { + if(type instanceof SymbolTypeIntegerFixed) { // Add an zero value initializer ConstantInteger zero = new ConstantInteger(0L); Statement stmt = new StatementAssignment(lValue.getRef(), zero, new StatementSource(ctx), ensureUnusedComments(comments)); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java b/src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java deleted file mode 100644 index afe0863aa..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java +++ /dev/null @@ -1,102 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.*; -import dk.camelot64.kickc.model.operators.Operators; -import dk.camelot64.kickc.model.statements.StatementSource; -import dk.camelot64.kickc.model.values.LValue; -import dk.camelot64.kickc.model.statements.Statement; -import dk.camelot64.kickc.model.statements.StatementAssignment; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypePointer; - -import java.util.List; -import java.util.ListIterator; - -/** - * Add casts in all assignments where types are not equal, but the rValue type can be promoted to the lValue type. - */ -public class Pass1AddTypePromotions extends Pass1Base { - - public Pass1AddTypePromotions(Program program) { - super(program); - } - - @Override - public boolean step() { - for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { - List<Statement> statements = block.getStatements(); - ListIterator<Statement> stmtIt = statements.listIterator(); - while(stmtIt.hasNext()) { - Statement statement = stmtIt.next(); - if(statement instanceof StatementAssignment) { - getPromotionAssignment((StatementAssignment) statement, stmtIt); - } - // TODO: Implement promotion for calls - } - } - return false; - } - - /** - * Examines an assignment to determine if a cast of the rValue is needed (the lvalue type and the rvalue type is not equal) - * and possible (the types are promotion compatible). - * <p> - * If a promotion is needed it is added by adding a new tmp-var with a cast and modifying the statement. - * - * @param assignment The assignment to examine - * @param stmtIt Iterator allowing the method to add a tmp-var-assignment. - */ - private void getPromotionAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt) { - LValue lValue = assignment.getlValue(); - SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue); - SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), assignment); - if(SymbolTypeInference.typeMatch(lValueType, rValueType)) { - return; - } - // No direct type match - attempt promotion - if(canPromote(lValueType, rValueType)) { - // Promotion possible - add tmp-var and a cast - if(assignment.getOperator() == null) { - // No operator - add cast directly! - assignment.setOperator(Operators.getCastUnary(lValueType)); - if(getLog().isVerbosePass1CreateSsa()) { - getLog().append("Promoting " + rValueType + " to " + lValueType + " in " + assignment); - } - } else { - throw new RuntimeException("Tmp-var promotions not implemented yet " + assignment); - } - } else { - String msg = "ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). " + - "In " + assignment.toString(getProgram(), false); - getProgram().getLog().append(msg); - throw new CompileError(msg, assignment.getSource()); - } - } - - /** - * Determines if it is possible to promote (cast without loss) one type to another - * - * @param lValueType The type of the lValue - * @param rValueType The type of the rValue (that will be cast) - * @return True if a cast is possible without any loss - */ - private boolean canPromote(SymbolType lValueType, SymbolType rValueType) { - if(lValueType instanceof SymbolTypePointer && SymbolType.isWord(rValueType)) { - return true; - } - if(lValueType.equals(SymbolType.WORD) && SymbolType.isByte(rValueType)) { - return true; - } - if(lValueType.equals(SymbolType.DWORD) && SymbolType.isWord(rValueType)) { - return true; - } - if(lValueType.equals(SymbolType.DWORD) && SymbolType.isByte(rValueType)) { - return true; - } - // No type promotion found - return false; - } - - -} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java b/src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java new file mode 100644 index 000000000..8ba6364d2 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java @@ -0,0 +1,43 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementCall; +import dk.camelot64.kickc.model.symbols.Procedure; +import dk.camelot64.kickc.model.symbols.Scope; + +/** + * Updates procedure calls to point to the actual procedure called. + */ +public class Pass1Procedures extends Pass2SsaOptimization { + + public Pass1Procedures(Program program) { + super(program); + } + + @Override + public boolean step() { + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementCall) { + StatementCall call = (StatementCall) statement; + String procedureName = call.getProcedureName(); + Scope currentScope = getScope().getScope(block.getScope()); + Procedure procedure = currentScope.getProcedure(procedureName); + if(procedure == null) { + throw new CompileError("Called procedure not found. " + call.toString(getProgram(), false), statement.getSource()); + } + call.setProcedure(procedure.getRef()); + if(procedure.getParameters().size() != call.getParameters().size()) { + throw new CompileError("Wrong number of parameters in call. Expected " + procedure.getParameters().size() + ". " + statement.toString(), statement.getSource()); + } + } + + } + } + return false; + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java index ea2611f26..466599cf3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java @@ -30,7 +30,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion { if(conditionalJump.getOperator()==null) { RValue rValue = conditionalJump.getrValue2(); SymbolType rValueType = SymbolTypeInference.inferType(getScope(), rValue); - if(!SymbolTypeInference.typeMatch(SymbolType.BOOLEAN, rValueType)) { + if(!SymbolType.BOOLEAN.equals(rValueType)) { getLog().append("ERROR! Type mismatch non-boolean condition from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false)); throw new CompileError("ERROR! Type mismatch non-boolean condition from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource()); } @@ -48,10 +48,11 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion { LValue lValue = statement.getlValue(); SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue); SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), statement); - if(SymbolTypeInference.typeMatch(lValueType, rValueType)) { + if(lValueType.equals(rValueType)) { return; } - if(SymbolTypeInference.typeMatch(rValueType, lValueType)) { + if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) { + // L-value is still a number - constants are probably not done being identified & typed return; } // Types do not match diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ComparisonOptimization.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ComparisonOptimization.java index 3c9658e9c..0354d3104 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ComparisonOptimization.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ComparisonOptimization.java @@ -9,7 +9,7 @@ import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementConditionalJump; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; +import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; import dk.camelot64.kickc.model.values.ConstantBinary; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -48,7 +48,7 @@ public class Pass2ComparisonOptimization extends Pass2SsaOptimization { } catch(ConstantNotLiteral e) { // Ignore } - if(Operators.GT.equals(operator) && valueType instanceof SymbolTypeInteger && constantLiteral instanceof ConstantInteger) { + if(Operators.GT.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) { // Found > C - rewrite to >= C+1 if possible Long longValue = (Long) constantLiteral.getValue(); if(longValue > 0x00L && longValue < 0xffL) { @@ -58,7 +58,7 @@ public class Pass2ComparisonOptimization extends Pass2SsaOptimization { conditionalJump.setrValue2(new ConstantBinary(constantValue, Operators.PLUS, new ConstantInteger(1L))); } } - if(Operators.LE.equals(operator) && valueType instanceof SymbolTypeInteger && constantLiteral instanceof ConstantInteger) { + if(Operators.LE.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) { // Found <= C - rewrite to < C+1 if possible Long longValue = (Long) constantLiteral.getValue(); if(longValue > 0x00L && longValue < 0xffL) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java index f3c968da0..0cde91c25 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java @@ -72,10 +72,8 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { SymbolType constType = variableType; if(!valueType.equals(variableType)) { - if(SymbolTypeInference.typeMatch(variableType, valueType)) { + if(variableType.equals(valueType)) { constType = variableType; - } else if(SymbolTypeInference.typeMatch(valueType, variableType)) { - constType = valueType; } else { throw new CompileError( "Constant variable has a non-matching type \n variable: " + variable.toString(getProgram()) + @@ -194,86 +192,12 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { // Volatile variables cannot be constant return; } - ConstantValue constant = getConstantAssignmentValue(assignment, var.getType()); - if(constant != null) { - constants.put(variable, new ConstantVariableValue(variable, constant, assignment)); + if(assignment.getrValue1()==null && assignment.getOperator()==null && assignment.getrValue2() instanceof ConstantValue) { + constants.put(variable, new ConstantVariableValue(variable, (ConstantValue) assignment.getrValue2(), assignment)); } } } - /** - * Examine the right side of an assignment and if it is constant then return the constant value. - * - * @param assignment The assignment to examine - * @param lValueType The type of the lvalue - * @return The constant value if the right side is constant - */ - private ConstantValue getConstantAssignmentValue(StatementAssignment assignment, SymbolType lValueType) { - if(assignment.getrValue1() == null && getConstant(assignment.getrValue2()) != null) { - if(assignment.getOperator() == null) { - // Constant assignment - return getConstant(assignment.getrValue2()); - } else { - // Constant unary expression - return createUnary( - (OperatorUnary) assignment.getOperator(), - getConstant(assignment.getrValue2()) - ); - } - } else if(getConstant(assignment.getrValue1()) != null && getConstant(assignment.getrValue2()) != null) { - // Constant binary expression - return createBinary( - getConstant(assignment.getrValue1()), - (OperatorBinary) assignment.getOperator(), - getConstant(assignment.getrValue2()), - getScope()); - } else if(assignment.getrValue2() instanceof ValueList && assignment.getOperator() == null && assignment.getrValue1() == null) { - // A candidate for a constant list - examine to confirm - if(lValueType instanceof SymbolTypeArray) { - ValueList valueList = (ValueList) assignment.getrValue2(); - List<RValue> values = valueList.getList(); - boolean allConstant = true; - // Type of the elements of the list (deducted from the type of all elements) - SymbolType listType = null; - List<ConstantValue> elements = new ArrayList<>(); - for(RValue elmValue : values) { - if(elmValue instanceof ConstantValue) { - ConstantValue constantValue = (ConstantValue) elmValue; - SymbolType elmType = constantValue.getType(getScope()); - if(listType == null) { - listType = elmType; - } else { - if(!SymbolTypeInference.typeMatch(listType, elmType)) { - SymbolType intersectType = SymbolTypeInference.intersectTypes(listType, elmType); - if(intersectType == null) { - // No overlap between list type and element type - throw new RuntimeException("Array type " + listType + " does not match element type" + elmType + ". Array: " + valueList.toString(getProgram())); - } else { - listType = intersectType; - } - } - } - elements.add(constantValue); - } else { - allConstant = false; - listType = null; - break; - } - } - if(allConstant && listType != null) { - // Constant list confirmed! - return new ConstantArrayList(elements, listType); - } - } - } else if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && assignment.getrValue1() == null) { - // Constant address-of variable - if(assignment.getrValue2() instanceof SymbolRef) { - return new ConstantSymbolPointer((SymbolRef) assignment.getrValue2()); - } - } - return null; - } - /** * If the rValue is a known constant return the constant value. * diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java new file mode 100644 index 000000000..a473bd5f8 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java @@ -0,0 +1,125 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.operators.OperatorBinary; +import dk.camelot64.kickc.model.operators.OperatorUnary; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeArray; +import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.values.*; + +import java.util.ArrayList; +import java.util.List; + +/** + * Compiler Pass consolidating L-values that are constant into a single {@link ConstantValue} + */ +public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization { + + public Pass2ConstantRValueConsolidation(Program program) { + super(program); + } + + /** + * Propagate constants, replacing variables with constants where possible. + * + * @return true optimization was performed. false if no optimization was possible. + */ + @Override + public boolean step() { + boolean modified = false; + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementAssignment) { + StatementAssignment assignment = (StatementAssignment) statement; + if(assignment.getrValue1() != null || assignment.getOperator() != null || !(assignment.getrValue2() instanceof ConstantValue)) { + SymbolType lValueType = SymbolTypeInference.inferType(getScope(), assignment.getlValue()); + ConstantValue constant = getConstantAssignmentValue(assignment, lValueType); + if(constant != null) { + getLog().append("Constant right-side identified " + assignment.toString(getProgram(), false)); + assignment.setrValue2(constant); + assignment.setOperator(null); + assignment.setrValue1(null); + modified = true; + } + } + } + } + } + return modified; + } + + /** + * Examine the right side of an assignment and if it is constant then return the constant value. + * + * @param assignment The assignment to examine + * @param lValueType The type of the lvalue + * @return The constant value if the right side is constant + */ + private ConstantValue getConstantAssignmentValue(StatementAssignment assignment, SymbolType lValueType) { + + if(assignment.getrValue1() == null && Pass2ConstantIdentification.getConstant(assignment.getrValue2()) != null) { + if(assignment.getOperator() == null) { + // Constant assignment + return Pass2ConstantIdentification.getConstant(assignment.getrValue2()); + } else { + // Constant unary expression + return Pass2ConstantIdentification.createUnary( + (OperatorUnary) assignment.getOperator(), + Pass2ConstantIdentification.getConstant(assignment.getrValue2()) + ); + } + } else if(Pass2ConstantIdentification.getConstant(assignment.getrValue1()) != null && Pass2ConstantIdentification.getConstant(assignment.getrValue2()) != null) { + // Constant binary expression + return Pass2ConstantIdentification.createBinary( + Pass2ConstantIdentification.getConstant(assignment.getrValue1()), + (OperatorBinary) assignment.getOperator(), + Pass2ConstantIdentification.getConstant(assignment.getrValue2()), + getScope()); + } else if(assignment.getrValue2() instanceof ValueList && assignment.getOperator() == null && assignment.getrValue1() == null) { + // A candidate for a constant list - examine to confirm + if(lValueType instanceof SymbolTypeArray) { + ValueList valueList = (ValueList) assignment.getrValue2(); + List<RValue> values = valueList.getList(); + boolean allConstant = true; + // Type of the elements of the list (deducted from the type of all elements) + SymbolType listType = null; + List<ConstantValue> elements = new ArrayList<>(); + for(RValue elmValue : values) { + if(elmValue instanceof ConstantValue) { + ConstantValue constantValue = (ConstantValue) elmValue; + SymbolType elmType = constantValue.getType(getScope()); + if(listType == null) { + listType = elmType; + } else { + if(!listType.equals(elmType)) { + // No overlap between list type and element type + throw new RuntimeException("Array type " + listType + " does not match element type" + elmType + ". Array: " + valueList.toString(getProgram())); + } + } + elements.add(constantValue); + } else { + allConstant = false; + listType = null; + break; + } + } + if(allConstant && listType != null) { + // Constant list confirmed! + return new ConstantArrayList(elements, listType); + } + } + } else if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && assignment.getrValue1() == null) { + // Constant address-of variable + if(assignment.getrValue2() instanceof SymbolRef) { + return new ConstantSymbolPointer((SymbolRef) assignment.getrValue2()); + } + } + return null; + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java index 1bdd74241..49b6afce4 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java @@ -15,7 +15,7 @@ import dk.camelot64.kickc.model.symbols.VariableIntermediate; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeArray; import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; +import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; import dk.camelot64.kickc.model.values.Value; import dk.camelot64.kickc.model.values.ValueList; @@ -68,11 +68,11 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization { private abstract class InlineConstructor implements ProgramValueHandler { - private SymbolTypeInteger constructType; + private SymbolTypeIntegerFixed constructType; private Operator constructOperator; private boolean optimized; - public InlineConstructor(SymbolTypeInteger constructType, Operator constructOperator) { + public InlineConstructor(SymbolTypeIntegerFixed constructType, Operator constructOperator) { this.constructType = constructType; this.constructOperator = constructOperator; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2RangeResolving.java b/src/main/java/dk/camelot64/kickc/passes/Pass2RangeResolving.java index b5694442d..5bc71e830 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2RangeResolving.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2RangeResolving.java @@ -6,7 +6,7 @@ import dk.camelot64.kickc.model.iterator.ProgramValueIterator; import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; +import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; import dk.camelot64.kickc.model.types.SymbolTypePointer; import dk.camelot64.kickc.model.values.*; @@ -51,9 +51,9 @@ public class Pass2RangeResolving extends Pass2SsaOptimization { if(rangeValue instanceof RangeComparison) { SymbolType type = ((RangeComparison) rangeValue).getType(); - SymbolTypeInteger valueType; - if(type instanceof SymbolTypeInteger) { - valueType = (SymbolTypeInteger) type; + SymbolTypeIntegerFixed valueType; + if(type instanceof SymbolTypeIntegerFixed) { + valueType = (SymbolTypeIntegerFixed) type; } else if(type instanceof SymbolTypePointer) { valueType = SymbolType.WORD; } else { diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java new file mode 100644 index 000000000..bf0f55c6f --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java @@ -0,0 +1,134 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.types.*; +import dk.camelot64.kickc.model.values.ConstantInteger; +import dk.camelot64.kickc.model.values.LValue; +import dk.camelot64.kickc.model.values.RValue; + +import java.util.List; +import java.util.ListIterator; + +/** + * Add casts in all assignments where types are not equal, but the rValue type can be converted to the lValue type. + */ +public class PassNAddTypeConversions extends Pass2SsaOptimization { + + public PassNAddTypeConversions(Program program) { + super(program); + } + + @Override + public boolean step() { + for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { + List<Statement> statements = block.getStatements(); + ListIterator<Statement> stmtIt = statements.listIterator(); + while(stmtIt.hasNext()) { + Statement statement = stmtIt.next(); + if(statement instanceof StatementAssignment) { + doConversionAssignment((StatementAssignment) statement, stmtIt); + } + // TODO: Implement conversion for calls + } + } + return false; + } + + /** + * Examines an assignment to determine if a cast of the rValue is needed (the lvalue type and the rvalue type is not equal) + * and possible (the types are conversion compatible). + * <p> + * If a conversion is needed it is added by adding a new tmp-var with a cast and modifying the statement. + * + * @param assignment The assignment to examine + * @param stmtIt Iterator allowing the method to add a tmp-var-assignment. + */ + private void doConversionAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt) { + LValue lValue = assignment.getlValue(); + SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue); + SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), assignment); + if(lValueType.equals(rValueType)) { + return; + } + if(SymbolType.NUMBER.equals(rValueType)) { + // If the rValue is number type - find the potential types based on the literal value + List<SymbolTypeIntegerFixed> potentialTypes = SymbolTypeNumberInference.inferTypesRValue(getScope(), assignment); + if(potentialTypes.size()==0) { + // number type cannot be calculated currently - save for later + return; + } + for(SymbolTypeIntegerFixed potentialType : potentialTypes) { + if(lValueType.equals(potentialType) || canConvert(lValueType, potentialType)) { + addConversionCast(assignment, lValueType, rValueType); + return; + } + } + } else { + // No direct type match - attempt conversion + if(canConvert(lValueType, rValueType)) { + addConversionCast(assignment, lValueType, rValueType); + return; + } + } + + // Conversion not possible - report a type error! + String msg = "ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). " + + "In " + assignment.toString(getProgram(), false); + getProgram().getLog().append(msg); + throw new CompileError(msg, assignment.getSource()); + } + + /** + * Add a conversion cast to the rvalue of an assignment + * + * @param assignment The assignment to add the cast to + * @param lValueType The type of the lValue + * @param rValueType The type of the rValue + */ + private void addConversionCast(StatementAssignment assignment, SymbolType lValueType, SymbolType rValueType) { + // Promotion possible - add tmp-var and a cast + if(assignment.getOperator() == null) { + // No operator - add cast directly! + RValue rValue = assignment.getrValue2(); + if((rValue instanceof ConstantInteger) && SymbolType.NUMBER.equals(((ConstantInteger) rValue).getType()) && SymbolType.isInteger(lValueType)) { + ((ConstantInteger) rValue).setType(lValueType); + } else { + assignment.setOperator(Operators.getCastUnary(lValueType)); + } + if(getLog().isVerbosePass1CreateSsa()) { + getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment); + } + } else { + throw new RuntimeException("Tmp-var conversion not implemented yet " + assignment); + } + } + + /** + * Determines if it is possible to convert one type to another + * as described in C99 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70 + * + * @param lValueType The type of the lValue + * @param rValueType The type of the rValue (that will be cast) + * @return True if a cast is possible without any loss + */ + private boolean canConvert(SymbolType lValueType, SymbolType rValueType) { + if(lValueType instanceof SymbolTypePointer && SymbolType.isWord(rValueType)) { + return true; + } + if(lValueType instanceof SymbolTypeInteger && rValueType instanceof SymbolTypeInteger) { + SymbolType convertedMathType = SymbolType.convertedMathType((SymbolTypeInteger) lValueType, (SymbolTypeInteger) rValueType); + if(lValueType.equals(convertedMathType)) { + return true; + } + } + // No type promotion found + return false; + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java similarity index 68% rename from src/main/java/dk/camelot64/kickc/passes/Pass1TypeInference.java rename to src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java index 0f296642d..d4baa4e7d 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeInference.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java @@ -12,9 +12,9 @@ import dk.camelot64.kickc.model.types.SymbolTypeInference; * Pass through the generated statements inferring types of unresolved variables. * Also updates procedure calls to point to the actual procedure called. */ -public class Pass1TypeInference extends Pass1Base { +public class PassNTypeInference extends Pass2SsaOptimization { - public Pass1TypeInference(Program program) { + public PassNTypeInference(Program program) { super(program); } @@ -38,17 +38,6 @@ public class Pass1TypeInference extends Pass1Base { } } } else if(statement instanceof StatementCall) { - StatementCall call = (StatementCall) statement; - String procedureName = call.getProcedureName(); - Scope currentScope = getScope().getScope(block.getScope()); - Procedure procedure = currentScope.getProcedure(procedureName); - if(procedure == null) { - throw new CompileError("Called procedure not found. " + call.toString(getProgram(), false), statement.getSource()); - } - call.setProcedure(procedure.getRef()); - if(procedure.getParameters().size() != call.getParameters().size()) { - throw new CompileError("Wrong number of parameters in call. Expected " + procedure.getParameters().size() + ". " + statement.toString(), statement.getSource()); - } SymbolTypeInference.inferCallLValue(getProgram(), (StatementCall) statement, false); } else if(statement instanceof StatementCallPointer) { SymbolTypeInference.inferCallPointerLValue(getProgram(), (StatementCallPointer) statement, false); diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index cbc3675db..89f5ff376 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,11 +32,21 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testIntegerLiteralsMin() throws IOException, URISyntaxException { + compileAndCompare("int-literals-min"); + } + @Test public void testIntegerLiterals() throws IOException, URISyntaxException { compileAndCompare("int-literals"); } + @Test + public void testNumberType() throws IOException, URISyntaxException { + compileAndCompare("number-type", log()); + } + @Test public void testSimpleLoop() throws IOException, URISyntaxException { compileAndCompare("simple-loop"); @@ -1636,7 +1646,7 @@ public class TestPrograms { @Test public void testForClassicMin() throws IOException, URISyntaxException { - compileAndCompare("forclassicmin"); + compileAndCompare("forclassicmin", log()); } @Test diff --git a/src/test/kc/int-literals.kc b/src/test/kc/int-literals.kc index d3fd609c6..5afa560bb 100644 --- a/src/test/kc/int-literals.kc +++ b/src/test/kc/int-literals.kc @@ -1,59 +1,106 @@ // Tests different integer literal types -const byte RED = 2; -const byte GREEN = 5; +const byte RED = 2ub; +const byte GREEN = 5ub; -const byte* SCREEN = $0400; -const byte* COLS = $d800; -byte idx = 0; +const byte* SCREEN = $0400uw; +const byte* COLS = $d800uw; +byte idx = 0ub; void main() { - for(byte* s: SCREEN..SCREEN+999) *s = ' '; - idx = 0; + for(byte* s=SCREEN;s<SCREEN+1000uw;s++) *s = ' '; testSimpleTypes(); - idx = 40; + testUnaryOperator(); testBinaryOperator(); } void testSimpleTypes() { + idx = 0ub; // Simple types - assertType(typeid(12ub), typeid(byte)); - assertType(typeid(12uc), typeid(byte)); + assertType(typeid(12ub), typeid(unsigned byte)); + assertType(typeid(12uc), typeid(unsigned byte)); assertType(typeid(12sb), typeid(signed byte)); assertType(typeid(12sc), typeid(signed byte)); - assertType(typeid(12uw), typeid(word)); - assertType(typeid(12ui), typeid(word)); - assertType(typeid(12us), typeid(word)); + assertType(typeid(12uw), typeid(unsigned word)); + assertType(typeid(12ui), typeid(unsigned word)); + assertType(typeid(12us), typeid(unsigned word)); assertType(typeid(12sw), typeid(signed word)); assertType(typeid(12si), typeid(signed word)); assertType(typeid(12ss), typeid(signed word)); - assertType(typeid(12ud), typeid(dword)); - assertType(typeid(12ul), typeid(dword)); + assertType(typeid(12ud), typeid(unsigned dword)); + assertType(typeid(12ul), typeid(unsigned dword)); assertType(typeid(12sd), typeid(signed dword)); assertType(typeid(12sl), typeid(signed dword)); assertType(typeid(12l), typeid(signed dword)); } +void testUnaryOperator() { + idx = 40ub; + // Unary Operations + assertType(typeid(-12ub), typeid(unsigned byte)); + assertType(typeid(-12sb), typeid(signed byte)); + assertType(typeid(-12uw), typeid(unsigned word)); + assertType(typeid(-12sw), typeid(signed word)); + assertType(typeid(-12ud), typeid(unsigned dword)); + assertType(typeid(-12sd), typeid(signed dword)); +} + void testBinaryOperator() { + idx = 80ub; // Binary Operations between unsigned byte & other types - assertType(typeid(12ub+12ub), typeid(byte)); - assertType(typeid(12ub+12sb), typeid(byte)); - assertType(typeid(12ub+12uw), typeid(word)); + assertType(typeid(12ub+12ub), typeid(unsigned byte)); + assertType(typeid(12ub+12sb), typeid(unsigned byte)); + assertType(typeid(12ub+12uw), typeid(unsigned word)); assertType(typeid(12ub+12sw), typeid(signed word)); - assertType(typeid(12ub+12ud), typeid(dword)); + assertType(typeid(12ub+12ud), typeid(unsigned dword)); assertType(typeid(12ub+12sd), typeid(signed dword)); idx++; // Binary Operations between signed byte & other types - assertType(typeid(12sb+12ub), typeid(byte)); + assertType(typeid(12sb+12ub), typeid(unsigned byte)); assertType(typeid(12sb+12sb), typeid(signed byte)); - assertType(typeid(12sb+12uw), typeid(word)); + assertType(typeid(12sb+12uw), typeid(unsigned word)); assertType(typeid(12sb+12sw), typeid(signed word)); - assertType(typeid(12sb+12ud), typeid(dword)); + assertType(typeid(12sb+12ud), typeid(unsigned dword)); assertType(typeid(12sb+12sd), typeid(signed dword)); + idx++; + // Binary Operations between unsigned word & other types + assertType(typeid(12uw+12ub), typeid(unsigned word)); + assertType(typeid(12uw+12sb), typeid(unsigned word)); + assertType(typeid(12uw+12uw), typeid(unsigned word)); + assertType(typeid(12uw+12sw), typeid(unsigned word)); + assertType(typeid(12uw+12ud), typeid(unsigned dword)); + assertType(typeid(12uw+12sd), typeid(signed dword)); + idx = 120ub; + // Binary Operations between signed word & other types + assertType(typeid(12sw+12ub), typeid(signed word)); + assertType(typeid(12sw+12sb), typeid(signed word)); + assertType(typeid(12sw+12uw), typeid(unsigned word)); + assertType(typeid(12sw+12sw), typeid(signed word)); + assertType(typeid(12sw+12ud), typeid(unsigned dword)); + assertType(typeid(12sw+12sd), typeid(signed dword)); + idx++; + // Binary Operations between unsigned dword & other types + assertType(typeid(12ud+12ub), typeid(unsigned dword)); + assertType(typeid(12ud+12sb), typeid(unsigned dword)); + assertType(typeid(12ud+12uw), typeid(unsigned dword)); + assertType(typeid(12ud+12sw), typeid(unsigned dword)); + assertType(typeid(12ud+12ud), typeid(unsigned dword)); + assertType(typeid(12ud+12sd), typeid(unsigned dword)); + idx++; + // Binary Operations between signed dword & other types + assertType(typeid(12sd+12ub), typeid(signed dword)); + assertType(typeid(12sd+12sb), typeid(signed dword)); + assertType(typeid(12sd+12uw), typeid(signed dword)); + assertType(typeid(12sd+12sw), typeid(signed dword)); + assertType(typeid(12sd+12ud), typeid(unsigned dword)); + assertType(typeid(12sd+12sd), typeid(signed dword)); } +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. void assertType(byte t1, byte t2) { if(t1==t2) { COLS[idx] = GREEN; diff --git a/src/test/kc/number-type.kc b/src/test/kc/number-type.kc new file mode 100644 index 000000000..6c333531f --- /dev/null +++ b/src/test/kc/number-type.kc @@ -0,0 +1,23 @@ +// Tests the number type used for constant expressions + +const byte* SCREENB = 0x0400; + +void main() { + // Constant values resolvable to bytes + byte idx = 0; + SCREENB[idx++] = 12; + SCREENB[idx++] = 6+6; + SCREENB[idx++] = 18-6; + SCREENB[idx++] = 1812-1800; + SCREENB[idx++] = 1+2+3+6; + SCREENB[idx++] = 2*6; + SCREENB[idx++] = 3<<2; + SCREENB[idx++] = 24>>1; + SCREENB[idx++] = 15&28; + SCREENB[idx++] = 4|8; + SCREENB[idx++] = 5^9; + SCREENB[idx++] = (2+2)*(15/5); + SCREENB[idx++] = (byte)(4096+12); +} + + From d0d5b5715ba2ae62851039da0bf78521edfb680e Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Mon, 6 May 2019 01:08:41 +0200 Subject: [PATCH 07/93] Implemented framework for number type conversion - the BinaryExpressionIterator. Added first case (type match) in new PassNAddNumberTybeConversions. --- .../java/dk/camelot64/kickc/CompileLog.java | 2 +- .../java/dk/camelot64/kickc/Compiler.java | 5 +- .../model/iterator/BinaryExpression.java | 166 ++++++++++++++++++ .../iterator/BinaryExpressionHandler.java | 25 +++ .../iterator/BinaryExpressionIterator.java | 63 +++++++ .../model/operators/OperatorAssignment.java | 27 +++ .../kickc/model/operators/Operators.java | 1 + .../kickc/model/types/SymbolType.java | 2 +- .../model/types/SymbolTypeInference.java | 2 + .../kickc/model/values/AssignmentRValue.java | 28 +++ .../passes/Pass1TypeIdSimplification.java | 24 ++- .../kickc/passes/Pass3AssertNoNumbers.java | 63 +++++++ .../kickc/passes/Pass3AssertNoTypeId.java | 34 ++++ .../kickc/passes/Pass3AssertRValues.java | 6 +- .../passes/PassNAddNumberTypeConversions.java | 59 +++++++ .../kickc/passes/PassNAddTypeConversions.java | 27 ++- .../dk/camelot64/kickc/test/TestPrograms.java | 23 ++- src/test/kc/int-conversion.kc | 90 ++++++++++ src/test/kc/int-literals.kc | 66 ------- src/test/kc/number-conversion.kc | 83 +++++++++ src/test/kc/number-type.kc | 53 ++++-- 21 files changed, 738 insertions(+), 111 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java create mode 100644 src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java create mode 100644 src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoNumbers.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoTypeId.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java create mode 100644 src/test/kc/int-conversion.kc create mode 100644 src/test/kc/number-conversion.kc diff --git a/src/main/java/dk/camelot64/kickc/CompileLog.java b/src/main/java/dk/camelot64/kickc/CompileLog.java index 2b82efc32..545d45140 100644 --- a/src/main/java/dk/camelot64/kickc/CompileLog.java +++ b/src/main/java/dk/camelot64/kickc/CompileLog.java @@ -192,7 +192,7 @@ public class CompileLog { return verboseSSAOptimize; } - public CompileLog setVerboseSSAOptimize() { + public CompileLog verboseSSAOptimize() { setVerboseSSAOptimize(true); return this; } diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index f9a6b1fc6..bf72c2051 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -233,6 +233,7 @@ public class Compiler { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); optimizations.add(new PassNTypeInference(program)); optimizations.add(new PassNAddTypeConversions(program)); + optimizations.add(new PassNAddNumberTypeConversions(program)); optimizations.add(new Pass2CullEmptyBlocks(program)); optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNVariableReferenceInfos(program)); @@ -247,7 +248,7 @@ public class Compiler { optimizations.add(new Pass2ConstantIdentification(program)); optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNVariableReferenceInfos(program)); - optimizations.add(new Pass2ConstantAdditionElimination(program)); + //optimizations.add(new Pass2ConstantAdditionElimination(program)); optimizations.add(new Pass2ConstantIfs(program)); optimizations.add(new Pass2ConstantStringConsolidation(program)); optimizations.add(new Pass2FixInlineConstructors(program)); @@ -356,7 +357,9 @@ public class Compiler { } private void pass3Analysis() { + new Pass3AssertNoTypeId(program).check(); new Pass3AssertRValues(program).check(); + new Pass3AssertNoNumbers(program).check(); new Pass3AssertConstants(program).check(); new Pass3AssertArrayLengths(program).check(); new Pass3AssertNoMulDivMod(program).check(); diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java new file mode 100644 index 000000000..d0993af17 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java @@ -0,0 +1,166 @@ +package dk.camelot64.kickc.model.iterator; + +import dk.camelot64.kickc.model.operators.OperatorBinary; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.statements.StatementConditionalJump; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.*; + +/** + * A binary expression in the program being iterated by {@link BinaryExpressionIterator} + */ +public interface BinaryExpression { + + /** + * Get the left operand + * + * @return The left operand + */ + RValue getLeft(); + + /** + * Get the binary operator + * + * @return the operator + */ + OperatorBinary getOperator(); + + /** + * Get the right operand + * + * @return The right operand + */ + RValue getRight(); + + /** + * Adds a cast to the right operand + * @param toType The toType to cast to + */ + void addRightCast(SymbolType toType); + + /** Binary expression assignment rvalue. */ + class BinaryExpressionAssignmentRValue implements BinaryExpression { + private final StatementAssignment assignment; + + BinaryExpressionAssignmentRValue(StatementAssignment assignment) { + this.assignment = assignment; + } + + @Override + public RValue getLeft() { + return assignment.getrValue1(); + } + + @Override + public OperatorBinary getOperator() { + return (OperatorBinary) assignment.getOperator(); + } + + @Override + public RValue getRight() { + return assignment.getrValue2(); + } + + @Override + public void addRightCast(SymbolType toType) { + if(assignment.getrValue2() instanceof ConstantValue) { + assignment.setrValue2(new ConstantCastValue(toType, (ConstantValue) assignment.getrValue2())); + } else { + throw new InternalError("Not implemented!"); + } + } + } + + /** Binary expression - assignment lvalue and the "total" rvalue. */ + class BinaryExpressionAssignmentLValue implements BinaryExpression { + private final StatementAssignment assignment; + + BinaryExpressionAssignmentLValue(StatementAssignment assignment) { + this.assignment = assignment; + } + + @Override + public RValue getLeft() { + return assignment.getlValue(); + } + + @Override + public OperatorBinary getOperator() { + return Operators.ASSIGNMENT; + } + + @Override + public RValue getRight() { + return new AssignmentRValue(assignment); + } + + @Override + public void addRightCast(SymbolType toType) { + throw new InternalError("Not implemented!"); + } + + + } + + + /** Binary expression conditional jump. */ + class BinaryExpressionConditionalJump implements BinaryExpression { + private final StatementConditionalJump conditionalJump; + + BinaryExpressionConditionalJump(StatementConditionalJump assignment) { + this.conditionalJump = assignment; + } + + @Override + public RValue getLeft() { + return conditionalJump.getrValue1(); + } + + @Override + public OperatorBinary getOperator() { + return (OperatorBinary) conditionalJump.getOperator(); + } + + @Override + public RValue getRight() { + return conditionalJump.getrValue2(); + } + + @Override + public void addRightCast(SymbolType toType) { + throw new InternalError("Not implemented!"); + } + + + } + + /** Binary expression as part of a constant expression. */ + class BinaryExpressionConstant implements BinaryExpression { + private ConstantBinary constantBinary; + + BinaryExpressionConstant(ConstantBinary constantBinary) { + this.constantBinary = constantBinary; + } + + @Override + public RValue getLeft() { + return constantBinary.getLeft(); + } + + @Override + public OperatorBinary getOperator() { + return constantBinary.getOperator(); + } + + @Override + public RValue getRight() { + return constantBinary.getRight(); + } + + @Override + public void addRightCast(SymbolType toType) { + constantBinary.setRight(new ConstantCastValue(toType, constantBinary.getRight())); + } + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java new file mode 100644 index 000000000..f5b10f5e0 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java @@ -0,0 +1,25 @@ +package dk.camelot64.kickc.model.iterator; + +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.statements.Statement; + +import java.util.ListIterator; + +/** A handler that performs some action for binary expressions in the program. + * A {@link BinaryExpressionIterator} can be used to iterate all binary expressions in a part of the program. + * The Handler then receives all binary expressions one at a time. The Handler has the option of modifying the binary expression. After the handler is executed all sub-values are recursed. + * The execute() method furthermore receives some extra parameters with information about the context of the passed value. + */ +public interface BinaryExpressionHandler { + + /** + * Handle a single binary expression + * + * @param binaryExpression The binary expression + * @param currentStmt The statement iterator - just past the current statement that the value is a part of. Current statment can be retrieved by calling + * @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block. + * @param currentBlock The current block that the value is a part of + */ + void execute(BinaryExpression binaryExpression, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock); + +} diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java new file mode 100644 index 000000000..05c761267 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java @@ -0,0 +1,63 @@ +package dk.camelot64.kickc.model.iterator; + +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.statements.StatementConditionalJump; +import dk.camelot64.kickc.model.values.ConstantBinary; + +import java.util.ListIterator; + +/** + * Capable of iterating the different structures of a Program (graph, block, statement, symboltable, symbol). + * Creates appropriate BinaryExpressions and passes them to a BinaryExpressionHandler. + * Iteration might be guided (eg. filtering some types of the structure to iterate at call-time) + */ +public class BinaryExpressionIterator { + + /** + * Execute a handler on all values in the entire program (both in the control flow graph and the symbol table.) + * + * @param program The program + * @param handler The handler to execute + */ + public static void execute(Program program, BinaryExpressionHandler handler) { + // Iterate all symbols + ProgramValueIterator.execute(program.getScope(), (programValue, currentStmt, stmtIt, currentBlock) -> { + if(programValue.get() instanceof ConstantBinary) { + ConstantBinary constantBinary = (ConstantBinary) programValue.get(); + handler.execute( new BinaryExpression.BinaryExpressionConstant(constantBinary), null, null, null); + } + }); + + // Iterate all blocks/statements + for(ControlFlowBlock block : program.getGraph().getAllBlocks()) { + ListIterator<Statement> stmtIt = block.getStatements().listIterator(); + while(stmtIt.hasNext()) { + Statement stmt = stmtIt.next(); + if(stmt instanceof StatementAssignment) { + StatementAssignment assignment = (StatementAssignment) stmt; + if(assignment.getrValue1() != null && assignment.getOperator()!=null &&assignment.getrValue2() != null) { + handler.execute( new BinaryExpression.BinaryExpressionAssignmentRValue(assignment), stmt, stmtIt, block); + } + handler.execute( new BinaryExpression.BinaryExpressionAssignmentLValue(assignment), stmt, stmtIt, block); + } else if(stmt instanceof StatementConditionalJump) { + StatementConditionalJump condJump = (StatementConditionalJump) stmt; + if(condJump.getrValue1()!=null && condJump.getOperator()!=null && condJump.getrValue2()!=null) { + handler.execute( new BinaryExpression.BinaryExpressionConditionalJump(condJump), stmt, stmtIt, block); + } + } + // Iterate all statement values + ProgramValueIterator.execute(stmt, (programValue, currentStmt, stmtIt1, currentBlock) -> { + if(programValue.get() instanceof ConstantBinary) { + ConstantBinary constantBinary = (ConstantBinary) programValue.get(); + handler.execute( new BinaryExpression.BinaryExpressionConstant(constantBinary), stmt, stmtIt, block); + } + }, stmtIt, block); + } + } + + } + +} diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java new file mode 100644 index 000000000..b42c177eb --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java @@ -0,0 +1,27 @@ +package dk.camelot64.kickc.model.operators; + +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeSimple; +import dk.camelot64.kickc.model.values.ConstantBool; +import dk.camelot64.kickc.model.values.ConstantLiteral; + +/** Binary assignment operator ( x = y ) */ +public class OperatorAssignment extends OperatorBinary { + + public OperatorAssignment(int precedence) { + super("=", "_assign_", precedence); + } + + @Override + public ConstantLiteral calculateLiteral(ConstantLiteral left, ConstantLiteral right) { + throw new CompileError("Calculation not implemented " + left + " " + getOperator() + " " + right); + } + + @Override + public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + return left; + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java index b9470a3c8..d50decce2 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java @@ -48,6 +48,7 @@ public class Operators { public static final OperatorBinary BOOL_OR = new OperatorBitwiseOr(11); public static final OperatorBinary LOGIC_AND = new OperatorLogicAnd(12); public static final OperatorBinary LOGIC_OR = new OperatorLogicOr(13); + public static final OperatorBinary ASSIGNMENT = new OperatorAssignment(14); public static Operator getBinary(String op) { switch(op) { diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java index c8a043c17..685017e26 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java @@ -20,7 +20,7 @@ public interface SymbolType { SymbolTypeIntegerFixed DWORD = new SymbolTypeIntegerFixed("dword", 0, 4_294_967_296L, false, 32); /** Signed double word (4 bytes, 32 bits). */ SymbolTypeIntegerFixed SDWORD = new SymbolTypeIntegerFixed("signed dword", -2_147_483_648, 2_147_483_647, true, 32); - /** Integer with unknown size. */ + /** Integer with unknown size (used for constant expressions). */ SymbolTypeIntegerAuto NUMBER = new SymbolTypeIntegerAuto("number"); /** String value (treated like byte* ). */ SymbolTypeNamed STRING = new SymbolTypeNamed("string", 99); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index 477a34d28..31bf4b7a9 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -126,6 +126,8 @@ public class SymbolTypeInference { } else if(rValue instanceof ProcedureRef) { Procedure procedure = symbols.getProcedure((ProcedureRef) rValue); return procedure.getType(); + } else if(rValue instanceof AssignmentRValue) { + return inferTypeRValue(symbols, ((AssignmentRValue) rValue).getAssignment()); } if(type == null) { throw new RuntimeException("Cannot infer type for " + rValue.toString()); diff --git a/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java b/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java new file mode 100644 index 000000000..6222c6fd2 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java @@ -0,0 +1,28 @@ +package dk.camelot64.kickc.model.values; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.statements.StatementAssignment; + +/** The "total" RValue of an assigment. */ +public class AssignmentRValue implements RValue { + + private StatementAssignment assignment; + + public AssignmentRValue(StatementAssignment assignment) { + this.assignment = assignment; + } + + public StatementAssignment getAssignment() { + return assignment; + } + + @Override + public String toString(Program program) { + return + (assignment.getrValue1() == null ? "" : assignment.getrValue1().toString(program) + " ") + + (assignment.getOperator() == null ? "" : assignment.getOperator() + " ") + + assignment.getrValue2().toString(program) + ; + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java index 736cb21ca..a1ffcf01a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java @@ -1,6 +1,7 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.InternalError; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.operators.OperatorTypeId; import dk.camelot64.kickc.model.operators.Operators; @@ -8,9 +9,15 @@ import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; +import dk.camelot64.kickc.model.types.SymbolTypeNumberInference; +import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantRef; +import dk.camelot64.kickc.model.values.ConstantValue; import dk.camelot64.kickc.model.values.RValue; +import java.util.List; + /** * Converts typeid() operators to constants */ @@ -30,11 +37,18 @@ public class Pass1TypeIdSimplification extends Pass1Base { if(Operators.TYPEID.equals(assignment.getOperator())) { RValue rValue = assignment.getrValue2(); SymbolType symbolType = SymbolTypeInference.inferType(getScope(), rValue); - getLog().append("Resolving typeid() " + assignment.toString(getProgram(), false)); - ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getScope(), symbolType); - assignment.setrValue2(typeIDConstantVar); - assignment.setOperator(null); - modified = true; + if(SymbolType.NUMBER.equals(symbolType)) { + if(rValue instanceof ConstantValue) { + List<SymbolTypeIntegerFixed> fixedTypes = SymbolTypeNumberInference.inferTypes(getScope(), (ConstantLiteral) rValue); + throw new InternalError("TODO: Implement typeof(const)!"); + } + } else { + getLog().append("Resolving typeid() " + assignment.toString(getProgram(), false)); + ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getScope(), symbolType); + assignment.setrValue2(typeIDConstantVar); + assignment.setOperator(null); + modified = true; + } } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoNumbers.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoNumbers.java new file mode 100644 index 000000000..2a92f6d79 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoNumbers.java @@ -0,0 +1,63 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.InternalError; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.statements.StatementConditionalJump; +import dk.camelot64.kickc.model.statements.StatementPhiBlock; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.values.RValue; + +/** + * Assert that all values with type number have been resolved to fixed size in pass 2. + */ +public class Pass3AssertNoNumbers extends Pass2SsaAssertion { + + public Pass3AssertNoNumbers(Program program) { + super(program); + } + + @Override + public void check() throws AssertionFailed { + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementAssignment) { + checkValue(((StatementAssignment) statement).getlValue(), statement); + checkValue(((StatementAssignment) statement).getrValue1(), statement); + checkValue(((StatementAssignment) statement).getrValue2(), statement); + } else if(statement instanceof StatementPhiBlock) { + for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) { + for(StatementPhiBlock.PhiRValue value : phiVariable.getValues()) { + checkValue(value.getrValue(), statement); + } + } + } else if(statement instanceof StatementConditionalJump) { + checkValue(((StatementConditionalJump) statement).getrValue1(), statement); + checkValue(((StatementConditionalJump) statement).getrValue2(), statement); + } + } + } + } + + /** + * Check a value to ensure it is does not have the {@link SymbolType#NUMBER}. + * + * @param rValue The value to check + * @param statement The statement containing the value + */ + public void checkValue(RValue rValue, Statement statement) { + if(rValue == null) return; + SymbolType symbolType = SymbolTypeInference.inferType(getScope(), rValue); + if(SymbolType.NUMBER.equals(symbolType)) { + throw new InternalError( + "Error! Number integer type not resolved to fixed size integer type " + + "\n value: " + rValue.toString(getProgram()) + + "\n statement: " + statement.toString(getProgram(), false) + , statement.getSource() + ); + } + } +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoTypeId.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoTypeId.java new file mode 100644 index 000000000..fa8c01773 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoTypeId.java @@ -0,0 +1,34 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.InternalError; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramValueIterator; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.values.ConstantUnary; +import dk.camelot64.kickc.model.values.Value; + +/** + * Assert that no typeid() expressions exist in the code anymore (they must have been resolved to constants in phase 1-2) + */ +public class Pass3AssertNoTypeId extends Pass2SsaAssertion { + + public Pass3AssertNoTypeId(Program program) { + super(program); + } + + @Override + public void check() throws AssertionFailed { + ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> { + Value value = programValue.get(); + if(value instanceof ConstantUnary) { + if(Operators.TYPEID.equals(((ConstantUnary) value).getOperator())) { + throw new InternalError( + "Error! Typeid() not resolved during compile. " + + "\n statement: " + currentStmt.toString(getProgram(), false) + , currentStmt.getSource() + ); + } + } + }); + } +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertRValues.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertRValues.java index 70a4e99f8..b0b9cdf05 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertRValues.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertRValues.java @@ -1,6 +1,6 @@ package dk.camelot64.kickc.passes; -import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.InternalError; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.iterator.ProgramValueIterator; import dk.camelot64.kickc.model.values.RangeValue; @@ -24,7 +24,7 @@ public class Pass3AssertRValues extends Pass2SsaAssertion { ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> { Value value = programValue.get(); if(value instanceof ValueList) { - throw new CompileError( + throw new InternalError( "Error! Value list not resolved to word constructor or array initializer" + "\n value list: " + value.toString(getProgram()) + "\n statement: " + currentStmt.toString(getProgram(), false) @@ -32,7 +32,7 @@ public class Pass3AssertRValues extends Pass2SsaAssertion { ); } if(value instanceof RangeValue) { - throw new CompileError( + throw new InternalError( "Error! Ranged for() not resolved to constants" + "\n Range: " + value.toString(getProgram()) + "\n statement: " + currentStmt.toString(getProgram(), false) diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java new file mode 100644 index 000000000..f1bed6038 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java @@ -0,0 +1,59 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.InternalError; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.BinaryExpressionIterator; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; +import dk.camelot64.kickc.model.values.*; + +/** + * Add casts to {@link SymbolType#NUMBER} expressions that meet a typed value in a binary expression (including assignment) + */ +public class PassNAddNumberTypeConversions extends Pass2SsaOptimization { + + public PassNAddNumberTypeConversions(Program program) { + super(program); + } + + @Override + public boolean step() { + BinaryExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> { + RValue left = binaryExpression.getLeft(); + RValue right = binaryExpression.getRight(); + + SymbolType leftType = SymbolTypeInference.inferType(getScope(), left); + SymbolType rightType = SymbolTypeInference.inferType(getScope(), right); + if(SymbolType.isInteger(leftType) && !SymbolType.NUMBER.equals(leftType) && SymbolType.NUMBER.equals(rightType)) { + SymbolTypeIntegerFixed leftIntType = (SymbolTypeIntegerFixed) leftType; + // Attempt to find number conversion! + if(right instanceof ConstantValue) { + ConstantLiteral constantLiteral = ((ConstantValue) right).calculateLiteral(getProgram().getScope()); + if(constantLiteral instanceof ConstantInteger) { + ConstantInteger constantInteger = (ConstantInteger) constantLiteral; + if(SymbolType.NUMBER.equals(constantInteger.getType())) { + Long value = constantInteger.getValue(); + if(leftIntType.getMinValue()<=value && leftIntType.getMaxValue()>=value) { + // The value matches the left type! + getLog().append("Adding number conversion cast ("+leftIntType+") "+binaryExpression.getRight().toString()+" in "+currentStmt.toString(getProgram(), false)); + binaryExpression.addRightCast(leftIntType); + } else { + throw new InternalError("TODO: Implement number conversion for non-equal types "+right.toString(), currentStmt); + } + } else { + throw new InternalError("Non-number constant has type number "+right.toString(), currentStmt); + } + } + } else { + // Postpone til later! + // Maybe handle AssignmentRValue separately! + getLog().append("Postponed number conversion " + right.toString()); + } + } + }); + return false; + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java index bf0f55c6f..562d251f0 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java @@ -1,15 +1,19 @@ package dk.camelot64.kickc.passes; +import dk.camelot64.kickc.model.Comment; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.ControlFlowBlock; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.symbols.Scope; +import dk.camelot64.kickc.model.symbols.VariableIntermediate; import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.RValue; +import dk.camelot64.kickc.model.values.ScopeRef; import java.util.List; import java.util.ListIterator; @@ -31,7 +35,7 @@ public class PassNAddTypeConversions extends Pass2SsaOptimization { while(stmtIt.hasNext()) { Statement statement = stmtIt.next(); if(statement instanceof StatementAssignment) { - doConversionAssignment((StatementAssignment) statement, stmtIt); + doConversionAssignment((StatementAssignment) statement, stmtIt, block); } // TODO: Implement conversion for calls } @@ -48,7 +52,7 @@ public class PassNAddTypeConversions extends Pass2SsaOptimization { * @param assignment The assignment to examine * @param stmtIt Iterator allowing the method to add a tmp-var-assignment. */ - private void doConversionAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt) { + private void doConversionAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt, ControlFlowBlock block) { LValue lValue = assignment.getlValue(); SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue); SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), assignment); @@ -64,14 +68,14 @@ public class PassNAddTypeConversions extends Pass2SsaOptimization { } for(SymbolTypeIntegerFixed potentialType : potentialTypes) { if(lValueType.equals(potentialType) || canConvert(lValueType, potentialType)) { - addConversionCast(assignment, lValueType, rValueType); + addConversionCast(assignment, stmtIt, block, lValueType, rValueType); return; } } } else { // No direct type match - attempt conversion if(canConvert(lValueType, rValueType)) { - addConversionCast(assignment, lValueType, rValueType); + addConversionCast(assignment, stmtIt, block, lValueType, rValueType); return; } } @@ -90,7 +94,7 @@ public class PassNAddTypeConversions extends Pass2SsaOptimization { * @param lValueType The type of the lValue * @param rValueType The type of the rValue */ - private void addConversionCast(StatementAssignment assignment, SymbolType lValueType, SymbolType rValueType) { + private void addConversionCast(StatementAssignment assignment, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, SymbolType lValueType, SymbolType rValueType) { // Promotion possible - add tmp-var and a cast if(assignment.getOperator() == null) { // No operator - add cast directly! @@ -100,11 +104,16 @@ public class PassNAddTypeConversions extends Pass2SsaOptimization { } else { assignment.setOperator(Operators.getCastUnary(lValueType)); } - if(getLog().isVerbosePass1CreateSsa()) { - getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment); - } + getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment); } else { - throw new RuntimeException("Tmp-var conversion not implemented yet " + assignment); + ScopeRef currentScope = currentBlock.getScope(); + Scope blockScope = getScope().getScope(currentScope); + VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); + tmpVar.setType(rValueType); + StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(lValueType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS); + getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment + " adding "+tmpVar); + assignment.setlValue(tmpVar.getRef()); + stmtIt.add(newAssignment); } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 89f5ff376..95b07f371 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -33,8 +33,18 @@ public class TestPrograms { } @Test - public void testIntegerLiteralsMin() throws IOException, URISyntaxException { - compileAndCompare("int-literals-min"); + public void testNumberConversion() throws IOException, URISyntaxException { + compileAndCompare("number-conversion", log()); + } + + @Test + public void testNumberType() throws IOException, URISyntaxException { + compileAndCompare("number-type"); + } + + @Test + public void testIntegerConversion() throws IOException, URISyntaxException { + compileAndCompare("int-conversion"); } @Test @@ -42,11 +52,6 @@ public class TestPrograms { compileAndCompare("int-literals"); } - @Test - public void testNumberType() throws IOException, URISyntaxException { - compileAndCompare("number-type", log()); - } - @Test public void testSimpleLoop() throws IOException, URISyntaxException { compileAndCompare("simple-loop"); @@ -59,7 +64,7 @@ public class TestPrograms { @Test public void testPaulNelsenSandboxTernaryError() throws IOException, URISyntaxException { - compileAndCompare("sandbox-ternary-error", log().verboseParse().verboseCreateSsa().setVerboseSSAOptimize().verboseStatementSequence()); + compileAndCompare("sandbox-ternary-error"); } @Test @@ -75,7 +80,7 @@ public class TestPrograms { @Test public void testTypeIdPlusByteProblem() throws IOException, URISyntaxException { - compileAndCompare("typeid-plus-byte-problem", log()); + compileAndCompare("typeid-plus-byte-problem"); } @Test diff --git a/src/test/kc/int-conversion.kc b/src/test/kc/int-conversion.kc new file mode 100644 index 000000000..2617ce6af --- /dev/null +++ b/src/test/kc/int-conversion.kc @@ -0,0 +1,90 @@ +// Tests different integer literal types + +const byte RED = 2ub; +const byte GREEN = 5ub; + +const byte* SCREEN = $0400uw; +const byte* COLS = $d800uw; +byte idx = 0ub; + +void main() { + for(byte* s=SCREEN;s<SCREEN+1000uw;s++) *s = ' '; + testUnaryOperator(); + testBinaryOperator(); +} + +void testUnaryOperator() { + idx = 00ub; + // Unary Operations + assertType(typeid(-12ub), typeid(unsigned byte)); + assertType(typeid(-12sb), typeid(signed byte)); + assertType(typeid(-12uw), typeid(unsigned word)); + assertType(typeid(-12sw), typeid(signed word)); + assertType(typeid(-12ud), typeid(unsigned dword)); + assertType(typeid(-12sd), typeid(signed dword)); +} + +void testBinaryOperator() { + idx = 40ub; + // Binary Operations between unsigned byte & other types + assertType(typeid(12ub+12ub), typeid(unsigned byte)); + assertType(typeid(12ub+12sb), typeid(unsigned byte)); + assertType(typeid(12ub+12uw), typeid(unsigned word)); + assertType(typeid(12ub+12sw), typeid(signed word)); + assertType(typeid(12ub+12ud), typeid(unsigned dword)); + assertType(typeid(12ub+12sd), typeid(signed dword)); + idx++; + // Binary Operations between signed byte & other types + assertType(typeid(12sb+12ub), typeid(unsigned byte)); + assertType(typeid(12sb+12sb), typeid(signed byte)); + assertType(typeid(12sb+12uw), typeid(unsigned word)); + assertType(typeid(12sb+12sw), typeid(signed word)); + assertType(typeid(12sb+12ud), typeid(unsigned dword)); + assertType(typeid(12sb+12sd), typeid(signed dword)); + idx++; + // Binary Operations between unsigned word & other types + assertType(typeid(12uw+12ub), typeid(unsigned word)); + assertType(typeid(12uw+12sb), typeid(unsigned word)); + assertType(typeid(12uw+12uw), typeid(unsigned word)); + assertType(typeid(12uw+12sw), typeid(unsigned word)); + assertType(typeid(12uw+12ud), typeid(unsigned dword)); + assertType(typeid(12uw+12sd), typeid(signed dword)); + idx = 80ub; + // Binary Operations between signed word & other types + assertType(typeid(12sw+12ub), typeid(signed word)); + assertType(typeid(12sw+12sb), typeid(signed word)); + assertType(typeid(12sw+12uw), typeid(unsigned word)); + assertType(typeid(12sw+12sw), typeid(signed word)); + assertType(typeid(12sw+12ud), typeid(unsigned dword)); + assertType(typeid(12sw+12sd), typeid(signed dword)); + idx++; + // Binary Operations between unsigned dword & other types + assertType(typeid(12ud+12ub), typeid(unsigned dword)); + assertType(typeid(12ud+12sb), typeid(unsigned dword)); + assertType(typeid(12ud+12uw), typeid(unsigned dword)); + assertType(typeid(12ud+12sw), typeid(unsigned dword)); + assertType(typeid(12ud+12ud), typeid(unsigned dword)); + assertType(typeid(12ud+12sd), typeid(unsigned dword)); + idx++; + // Binary Operations between signed dword & other types + assertType(typeid(12sd+12ub), typeid(signed dword)); + assertType(typeid(12sd+12sb), typeid(signed dword)); + assertType(typeid(12sd+12uw), typeid(signed dword)); + assertType(typeid(12sd+12sw), typeid(signed dword)); + assertType(typeid(12sd+12ud), typeid(unsigned dword)); + assertType(typeid(12sd+12sd), typeid(signed dword)); +} + + + +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +void assertType(byte t1, byte t2) { + if(t1==t2) { + COLS[idx] = GREEN; + } else { + COLS[idx] = RED; + } + SCREEN[idx++] = t1; +} \ No newline at end of file diff --git a/src/test/kc/int-literals.kc b/src/test/kc/int-literals.kc index 5afa560bb..6c478a300 100644 --- a/src/test/kc/int-literals.kc +++ b/src/test/kc/int-literals.kc @@ -10,8 +10,6 @@ byte idx = 0ub; void main() { for(byte* s=SCREEN;s<SCREEN+1000uw;s++) *s = ' '; testSimpleTypes(); - testUnaryOperator(); - testBinaryOperator(); } void testSimpleTypes() { @@ -34,70 +32,6 @@ void testSimpleTypes() { assertType(typeid(12l), typeid(signed dword)); } -void testUnaryOperator() { - idx = 40ub; - // Unary Operations - assertType(typeid(-12ub), typeid(unsigned byte)); - assertType(typeid(-12sb), typeid(signed byte)); - assertType(typeid(-12uw), typeid(unsigned word)); - assertType(typeid(-12sw), typeid(signed word)); - assertType(typeid(-12ud), typeid(unsigned dword)); - assertType(typeid(-12sd), typeid(signed dword)); -} - -void testBinaryOperator() { - idx = 80ub; - // Binary Operations between unsigned byte & other types - assertType(typeid(12ub+12ub), typeid(unsigned byte)); - assertType(typeid(12ub+12sb), typeid(unsigned byte)); - assertType(typeid(12ub+12uw), typeid(unsigned word)); - assertType(typeid(12ub+12sw), typeid(signed word)); - assertType(typeid(12ub+12ud), typeid(unsigned dword)); - assertType(typeid(12ub+12sd), typeid(signed dword)); - idx++; - // Binary Operations between signed byte & other types - assertType(typeid(12sb+12ub), typeid(unsigned byte)); - assertType(typeid(12sb+12sb), typeid(signed byte)); - assertType(typeid(12sb+12uw), typeid(unsigned word)); - assertType(typeid(12sb+12sw), typeid(signed word)); - assertType(typeid(12sb+12ud), typeid(unsigned dword)); - assertType(typeid(12sb+12sd), typeid(signed dword)); - idx++; - // Binary Operations between unsigned word & other types - assertType(typeid(12uw+12ub), typeid(unsigned word)); - assertType(typeid(12uw+12sb), typeid(unsigned word)); - assertType(typeid(12uw+12uw), typeid(unsigned word)); - assertType(typeid(12uw+12sw), typeid(unsigned word)); - assertType(typeid(12uw+12ud), typeid(unsigned dword)); - assertType(typeid(12uw+12sd), typeid(signed dword)); - idx = 120ub; - // Binary Operations between signed word & other types - assertType(typeid(12sw+12ub), typeid(signed word)); - assertType(typeid(12sw+12sb), typeid(signed word)); - assertType(typeid(12sw+12uw), typeid(unsigned word)); - assertType(typeid(12sw+12sw), typeid(signed word)); - assertType(typeid(12sw+12ud), typeid(unsigned dword)); - assertType(typeid(12sw+12sd), typeid(signed dword)); - idx++; - // Binary Operations between unsigned dword & other types - assertType(typeid(12ud+12ub), typeid(unsigned dword)); - assertType(typeid(12ud+12sb), typeid(unsigned dword)); - assertType(typeid(12ud+12uw), typeid(unsigned dword)); - assertType(typeid(12ud+12sw), typeid(unsigned dword)); - assertType(typeid(12ud+12ud), typeid(unsigned dword)); - assertType(typeid(12ud+12sd), typeid(unsigned dword)); - idx++; - // Binary Operations between signed dword & other types - assertType(typeid(12sd+12ub), typeid(signed dword)); - assertType(typeid(12sd+12sb), typeid(signed dword)); - assertType(typeid(12sd+12uw), typeid(signed dword)); - assertType(typeid(12sd+12sw), typeid(signed dword)); - assertType(typeid(12sd+12ud), typeid(unsigned dword)); - assertType(typeid(12sd+12sd), typeid(signed dword)); -} - - - // Check that the two passed type IDs are equal. // Shows a letter symbolizing t1 // If they are equal the letter is green - if not it is red. diff --git a/src/test/kc/number-conversion.kc b/src/test/kc/number-conversion.kc new file mode 100644 index 000000000..6d7a7b833 --- /dev/null +++ b/src/test/kc/number-conversion.kc @@ -0,0 +1,83 @@ +// Tests conversion of numbers to correct int types +// See https://gitlab.com/camelot/kickc/issues/181 + +void main() { + + // Signed type and number + // a) If one operand is a signed type and the other a number. + // The number becomes the smallest signed type that can hold its value (if one exists). + // The two operands are then converted normally (using 2a or 2b). + idx = 0ub; + assertType(typeid(12sb+12), typeid(signed byte)); + assertType(typeid(12sb+130), typeid(signed word)); + assertType(typeid(12sb+32000), typeid(signed dword)); + assertType(typeid(12sw+12), typeid(signed word)); + assertType(typeid(12sw+130), typeid(signed word)); + assertType(typeid(12sw+100000), typeid(signed dword)); + assertType(typeid(12sd+12), typeid(signed dword)); + assertType(typeid(12sd+130), typeid(signed dword)); + assertType(typeid(12sd+100000), typeid(signed dword)); + // Test number larger than largest signed type + assertType(typeid(12sb+3000000000), typeid(unsigned dword)); + + // Unsigned type and positive number + // b) If one operand is an unsigned type and the other a positive number. + // The number is converted to the smallest unsigned type that can hold the value. + // The two operands are then converted normally (using 2a or 2b). + idx = 40ub; + assertType(typeid(12ub+12), typeid(unsigned byte)); + assertType(typeid(12ub+250), typeid(unsigned byte)); + assertType(typeid(12ub+300), typeid(unsigned word)); + assertType(typeid(12ub+65534), typeid(unsigned word)); + assertType(typeid(12ub+66000), typeid(unsigned dword)); + assertType(typeid(12uw+12), typeid(unsigned word)); + assertType(typeid(12uw+130), typeid(unsigned word)); + assertType(typeid(12uw+66000), typeid(unsigned dword)); + assertType(typeid(12ud+12), typeid(unsigned dword)); + assertType(typeid(12ud+130), typeid(unsigned dword)); + assertType(typeid(12ud+66000), typeid(unsigned dword)); + assertType(typeid(12sb+3000000000), typeid(unsigned dword)); + + // Unsigned type and negative number + // If one operand is an unsigned type and the other a negative number. + // The number is first converted to the smallest signed type that can hold its value (if one exits). + // If the signed type is smaller than the unsigned type it is converted up to the size of the unsigned type. + // The signed type is finally converted to unsigned. + // The two unsigned operands are then finally converted to the size of the largest type (using 2b). + idx = 80ub; + assertType(typeid(12ub+-12), typeid(unsigned byte)); + assertType(typeid(12ub+-120), typeid(unsigned byte)); + assertType(typeid(12ub+-250), typeid(unsigned word)); + assertType(typeid(12ub+-32000), typeid(unsigned dword)); + assertType(typeid(12ub+-66000), typeid(unsigned dword)); + assertType(typeid(12uw+-12), typeid(unsigned word)); + assertType(typeid(12uw+-130), typeid(unsigned word)); + assertType(typeid(12uw+-32000), typeid(unsigned dword)); + assertType(typeid(12ud+-12), typeid(unsigned dword)); + assertType(typeid(12ud+-130), typeid(unsigned dword)); + assertType(typeid(12ud+-66000), typeid(unsigned dword)); + assertType(typeid(12sb+-3000000000), typeid(unsigned dword)); + +} + + + + +const byte RED = 2ub; +const byte GREEN = 5ub; + +const byte* SCREEN = $0400uw; +const byte* COLS = $d800uw; +byte idx = 0ub; + +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +void assertType(byte t1, byte t2) { + if(t1==t2) { + COLS[idx] = GREEN; + } else { + COLS[idx] = RED; + } + SCREEN[idx++] = t1; +} \ No newline at end of file diff --git a/src/test/kc/number-type.kc b/src/test/kc/number-type.kc index 6c333531f..74f270661 100644 --- a/src/test/kc/number-type.kc +++ b/src/test/kc/number-type.kc @@ -1,23 +1,44 @@ // Tests the number type used for constant expressions -const byte* SCREENB = 0x0400; void main() { - // Constant values resolvable to bytes - byte idx = 0; - SCREENB[idx++] = 12; - SCREENB[idx++] = 6+6; - SCREENB[idx++] = 18-6; - SCREENB[idx++] = 1812-1800; - SCREENB[idx++] = 1+2+3+6; - SCREENB[idx++] = 2*6; - SCREENB[idx++] = 3<<2; - SCREENB[idx++] = 24>>1; - SCREENB[idx++] = 15&28; - SCREENB[idx++] = 4|8; - SCREENB[idx++] = 5^9; - SCREENB[idx++] = (2+2)*(15/5); - SCREENB[idx++] = (byte)(4096+12); + testBytes(); + testSBytes(); } +void testBytes() { + // Constant values resolvable to bytes + const byte* SCREEN = 0x0400; + byte idx = 0; + SCREEN[idx++] = 12; + SCREEN[idx++] = 6+6; + SCREEN[idx++] = 18-6; + SCREEN[idx++] = 1812-1800; + SCREEN[idx++] = 1+2+3+6; + SCREEN[idx++] = 2*6; + SCREEN[idx++] = 3<<2; + SCREEN[idx++] = 24>>1; + SCREEN[idx++] = 15&28; + SCREEN[idx++] = 4|8; + SCREEN[idx++] = 5^9; + SCREEN[idx++] = (2+2)*(15/5); + SCREEN[idx++] = (byte)(4096+12); +} +void testSBytes() { + // Constant values resolvable to signed bytes + const signed byte* SCREEN = 0x0428; + byte idx = 0; + SCREEN[idx++] = -12; + SCREEN[idx++] = -6-6; + SCREEN[idx++] = -18+6; + SCREEN[idx++] = -1812+1800; + SCREEN[idx++] = -1-2-3-6; + SCREEN[idx++] = -2*6; + SCREEN[idx++] = -3<<2; + SCREEN[idx++] = -24>>1; + SCREEN[idx++] = -4&-9; + SCREEN[idx++] = -0x10|-0xfc; + SCREEN[idx++] = (-2-2)*(15/5); + SCREEN[idx++] = (signed byte)(4096-12); +} From 49ae6a0e66317e017644b26b4ca3d62a007b0c3c Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Mon, 6 May 2019 08:06:18 +0200 Subject: [PATCH 08/93] Working on number conversion... not compiling atm. --- .../passes/PassNAddNumberTypeConversions.java | 108 +++++++++++++----- 1 file changed, 80 insertions(+), 28 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java index f1bed6038..b12ad19ca 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java @@ -1,12 +1,16 @@ package dk.camelot64.kickc.passes; +import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.InternalError; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.iterator.BinaryExpressionIterator; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; -import dk.camelot64.kickc.model.values.*; +import dk.camelot64.kickc.model.values.ConstantInteger; +import dk.camelot64.kickc.model.values.ConstantLiteral; +import dk.camelot64.kickc.model.values.ConstantValue; +import dk.camelot64.kickc.model.values.RValue; /** * Add casts to {@link SymbolType#NUMBER} expressions that meet a typed value in a binary expression (including assignment) @@ -22,38 +26,86 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization { BinaryExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> { RValue left = binaryExpression.getLeft(); RValue right = binaryExpression.getRight(); + SymbolType conversionType = getNumberConversionType(left, right); + if(conversionType != null) { + // Convert both left and right to the found type + + getLog().append("Adding number conversion cast (" + fixedType+ ") " + binaryExpression.getRight().toString() + " in " + currentStmt.toString(getProgram(), false)); + - SymbolType leftType = SymbolTypeInference.inferType(getScope(), left); - SymbolType rightType = SymbolTypeInference.inferType(getScope(), right); - if(SymbolType.isInteger(leftType) && !SymbolType.NUMBER.equals(leftType) && SymbolType.NUMBER.equals(rightType)) { - SymbolTypeIntegerFixed leftIntType = (SymbolTypeIntegerFixed) leftType; - // Attempt to find number conversion! - if(right instanceof ConstantValue) { - ConstantLiteral constantLiteral = ((ConstantValue) right).calculateLiteral(getProgram().getScope()); - if(constantLiteral instanceof ConstantInteger) { - ConstantInteger constantInteger = (ConstantInteger) constantLiteral; - if(SymbolType.NUMBER.equals(constantInteger.getType())) { - Long value = constantInteger.getValue(); - if(leftIntType.getMinValue()<=value && leftIntType.getMaxValue()>=value) { - // The value matches the left type! - getLog().append("Adding number conversion cast ("+leftIntType+") "+binaryExpression.getRight().toString()+" in "+currentStmt.toString(getProgram(), false)); - binaryExpression.addRightCast(leftIntType); - } else { - throw new InternalError("TODO: Implement number conversion for non-equal types "+right.toString(), currentStmt); - } - } else { - throw new InternalError("Non-number constant has type number "+right.toString(), currentStmt); - } - } - } else { - // Postpone til later! - // Maybe handle AssignmentRValue separately! - getLog().append("Postponed number conversion " + right.toString()); - } } + }); return false; } + private SymbolType getNumberConversionType(RValue left, RValue right) { + + SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left); + SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right); + + if(SymbolType.NUMBER.equals(leftType) || SymbolType.NUMBER.equals(rightType)) { + // A special type number is assigned to integer constants without a postfix literal. + // Numbers are flexible and will take a type based on their actual value when they meet a typed number in a calculation. + // Number types are only usable at compile time. + + if(leftType.equals(rightType)) { + // a) If the two operands are numbers the result is a number + return null; + } + + RValue numberVal; + SymbolTypeIntegerFixed fixedType; + if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) { + // Left is the number + numberVal = left; + fixedType = (SymbolTypeIntegerFixed) rightType; + } else if(SymbolType.NUMBER.equals(rightType) && SymbolType.isInteger(leftType)) { + // Right is the number + numberVal = right; + fixedType = (SymbolTypeIntegerFixed) leftType; + } else { + // Non-integer number binary + throw new CompileError("Error! Incompatible operands "+left.toString()+" and "+right.toString()); + } + + if(numberVal instanceof ConstantValue) { + ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(getProgram().getScope()); + if(constantLiteral instanceof ConstantInteger) { + ConstantInteger constantInteger = (ConstantInteger) constantLiteral; + if(SymbolType.NUMBER.equals(constantInteger.getType())) { + Long value = constantInteger.getValue(); + if(fixedType.getMinValue() <= value && fixedType.getMaxValue() >= value) { + // The value matches the left type! + binaryExpression.addRightCast(leftIntType); + } else { + throw new InternalError("TODO: Implement number conversion for non-equal types " + right.toString(), currentStmt); + } + } else { + throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt); + } + } + } else { + // Postpone til later! + // Maybe handle AssignmentRValue separately! + getLog().append("Postponed number conversion " + right.toString()); + } + + + + + } + + // No number conversion + return null; + + if(SymbolType.isInteger(leftType) && !SymbolType.NUMBER.equals(leftType) && SymbolType.NUMBER.equals(rightType)) { + SymbolTypeIntegerFixed leftIntType = (SymbolTypeIntegerFixed) leftType; + // Attempt to find number conversion! + } + + return null; + } + } From 7e174898b85a700603f06ec28196360d2175fd3f Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 7 May 2019 00:59:54 +0200 Subject: [PATCH 09/93] Number conversion working. Added program expression iterator. --- .../java/dk/camelot64/kickc/Compiler.java | 11 +- .../model/iterator/BinaryExpression.java | 166 - .../model/iterator/ProgramExpression.java | 28 + .../iterator/ProgramExpressionBinary.java | 262 ++ ...ler.java => ProgramExpressionHandler.java} | 15 +- ...or.java => ProgramExpressionIterator.java} | 28 +- .../iterator/ProgramExpressionUnary.java | 84 + .../kickc/model/iterator/ProgramValue.java | 989 ++-- .../model/iterator/ProgramValueIterator.java | 50 +- .../model/operators/OperatorBitwiseAnd.java | 7 +- .../model/operators/OperatorBitwiseOr.java | 2 +- .../model/operators/OperatorBitwiseXor.java | 2 +- .../kickc/model/operators/OperatorCast.java | 18 + .../model/operators/OperatorCastBool.java | 4 +- .../model/operators/OperatorCastByte.java | 4 +- .../model/operators/OperatorCastDWord.java | 4 +- .../model/operators/OperatorCastPtr.java | 4 +- .../model/operators/OperatorCastSByte.java | 4 +- .../model/operators/OperatorCastSDWord.java | 4 +- .../model/operators/OperatorCastSWord.java | 4 +- .../model/operators/OperatorCastWord.java | 4 +- .../kickc/model/operators/OperatorDivide.java | 2 +- .../kickc/model/operators/OperatorMinus.java | 2 +- .../kickc/model/operators/OperatorModulo.java | 2 +- .../model/operators/OperatorMultiply.java | 7 +- .../kickc/model/operators/OperatorPlus.java | 2 +- .../kickc/model/operators/Operators.java | 1 + .../kickc/model/types/SymbolType.java | 79 +- .../model/types/SymbolTypeConversion.java | 134 + .../model/types/SymbolTypeIntegerFixed.java | 55 + .../kickc/model/types/SymbolTypeMulti.java | 16 - .../types/SymbolTypeNumberInference.java | 4 +- .../kickc/model/values/AssignmentRValue.java | 2 +- ...ss1GenerateSingleStaticAssignmentForm.java | 2 +- .../Pass2ConstantCastSimplification.java | 43 + .../passes/PassNAddNumberTypeConversions.java | 108 +- .../kickc/passes/PassNAddTypeConversions.java | 143 - .../passes/PassNAddTypeConversionsNew.java | 55 + ...on.java => PassNTypeIdSimplification.java} | 46 +- .../dk/camelot64/kickc/test/TestPrograms.java | 4 +- src/test/kc/number-conversion.kc | 17 +- src/test/ref/int-conversion.asm | 242 + src/test/ref/int-conversion.cfg | 222 + src/test/ref/int-conversion.log | 4159 +++++++++++++++++ src/test/ref/int-conversion.sym | 90 + src/test/ref/int-literals.asm | 122 + src/test/ref/int-literals.cfg | 107 + src/test/ref/int-literals.log | 1947 ++++++++ src/test/ref/int-literals.sym | 55 + src/test/ref/number-conversion.asm | 180 + src/test/ref/number-conversion.cfg | 171 + src/test/ref/number-conversion.log | 3609 ++++++++++++++ src/test/ref/number-conversion.sym | 67 + src/test/ref/number-type.asm | 69 + src/test/ref/number-type.cfg | 55 + src/test/ref/number-type.log | 1204 +++++ src/test/ref/number-type.sym | 17 + 57 files changed, 13641 insertions(+), 1093 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpression.java create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java rename src/main/java/dk/camelot64/kickc/model/iterator/{BinaryExpressionHandler.java => ProgramExpressionHandler.java} (51%) rename src/main/java/dk/camelot64/kickc/model/iterator/{BinaryExpressionIterator.java => ProgramExpressionIterator.java} (56%) create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java create mode 100644 src/main/java/dk/camelot64/kickc/model/operators/OperatorCast.java create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java delete mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java rename src/main/java/dk/camelot64/kickc/passes/{Pass1TypeIdSimplification.java => PassNTypeIdSimplification.java} (52%) create mode 100644 src/test/ref/int-conversion.asm create mode 100644 src/test/ref/int-conversion.cfg create mode 100644 src/test/ref/int-conversion.log create mode 100644 src/test/ref/int-conversion.sym create mode 100644 src/test/ref/int-literals.asm create mode 100644 src/test/ref/int-literals.cfg create mode 100644 src/test/ref/int-literals.log create mode 100644 src/test/ref/int-literals.sym create mode 100644 src/test/ref/number-conversion.asm create mode 100644 src/test/ref/number-conversion.cfg create mode 100644 src/test/ref/number-conversion.log create mode 100644 src/test/ref/number-conversion.sym create mode 100644 src/test/ref/number-type.asm create mode 100644 src/test/ref/number-type.cfg create mode 100644 src/test/ref/number-type.log create mode 100644 src/test/ref/number-type.sym diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index bf72c2051..74445a9ff 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -155,7 +155,7 @@ public class Compiler { new Pass1UnwindBlockScopes(program).execute(); new Pass1Procedures(program).execute(); new PassNTypeInference(program).execute(); - new Pass1TypeIdSimplification(program).execute(); + new PassNTypeIdSimplification(program).execute(); if(getLog().isVerbosePass1CreateSsa()) { getLog().append("SYMBOLS"); @@ -165,7 +165,7 @@ public class Compiler { new Pass1FixLValuesLoHi(program).execute(); new Pass1AssertNoLValueIntermediate(program).execute(); new Pass1PointerSizeofFix(program).execute(); - new PassNAddTypeConversions(program).execute(); + new PassNAddTypeConversionsNew(program).execute(); new Pass1EarlyConstantIdentification(program).execute(); new PassNStatementIndices(program).step(); new PassNCallGraphAnalysis(program).step(); @@ -231,9 +231,10 @@ public class Compiler { private void pass2Optimize() { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); - optimizations.add(new PassNTypeInference(program)); - optimizations.add(new PassNAddTypeConversions(program)); + optimizations.add(new PassNAddTypeConversionsNew(program)); optimizations.add(new PassNAddNumberTypeConversions(program)); + optimizations.add(new PassNTypeInference(program)); + optimizations.add(new PassNTypeIdSimplification(program)); optimizations.add(new Pass2CullEmptyBlocks(program)); optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNVariableReferenceInfos(program)); @@ -264,6 +265,7 @@ public class Compiler { optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new Pass2InlineDerefIdx(program)); optimizations.add(new Pass2DeInlineWordDerefIdx(program)); + optimizations.add(new Pass2ConstantCastSimplification(program)); pass2Execute(optimizations); } @@ -303,6 +305,7 @@ public class Compiler { constantOptimizations.add(new Pass2ConstantIdentification(program)); constantOptimizations.add(new Pass2ConstantAdditionElimination(program)); constantOptimizations.add(new Pass2ConstantSimplification(program)); + constantOptimizations.add(new Pass2ConstantCastSimplification(program)); constantOptimizations.add(new Pass2ConstantIfs(program)); pass2Execute(constantOptimizations); diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java deleted file mode 100644 index d0993af17..000000000 --- a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java +++ /dev/null @@ -1,166 +0,0 @@ -package dk.camelot64.kickc.model.iterator; - -import dk.camelot64.kickc.model.operators.OperatorBinary; -import dk.camelot64.kickc.model.operators.Operators; -import dk.camelot64.kickc.model.statements.StatementAssignment; -import dk.camelot64.kickc.model.statements.StatementConditionalJump; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.values.*; - -/** - * A binary expression in the program being iterated by {@link BinaryExpressionIterator} - */ -public interface BinaryExpression { - - /** - * Get the left operand - * - * @return The left operand - */ - RValue getLeft(); - - /** - * Get the binary operator - * - * @return the operator - */ - OperatorBinary getOperator(); - - /** - * Get the right operand - * - * @return The right operand - */ - RValue getRight(); - - /** - * Adds a cast to the right operand - * @param toType The toType to cast to - */ - void addRightCast(SymbolType toType); - - /** Binary expression assignment rvalue. */ - class BinaryExpressionAssignmentRValue implements BinaryExpression { - private final StatementAssignment assignment; - - BinaryExpressionAssignmentRValue(StatementAssignment assignment) { - this.assignment = assignment; - } - - @Override - public RValue getLeft() { - return assignment.getrValue1(); - } - - @Override - public OperatorBinary getOperator() { - return (OperatorBinary) assignment.getOperator(); - } - - @Override - public RValue getRight() { - return assignment.getrValue2(); - } - - @Override - public void addRightCast(SymbolType toType) { - if(assignment.getrValue2() instanceof ConstantValue) { - assignment.setrValue2(new ConstantCastValue(toType, (ConstantValue) assignment.getrValue2())); - } else { - throw new InternalError("Not implemented!"); - } - } - } - - /** Binary expression - assignment lvalue and the "total" rvalue. */ - class BinaryExpressionAssignmentLValue implements BinaryExpression { - private final StatementAssignment assignment; - - BinaryExpressionAssignmentLValue(StatementAssignment assignment) { - this.assignment = assignment; - } - - @Override - public RValue getLeft() { - return assignment.getlValue(); - } - - @Override - public OperatorBinary getOperator() { - return Operators.ASSIGNMENT; - } - - @Override - public RValue getRight() { - return new AssignmentRValue(assignment); - } - - @Override - public void addRightCast(SymbolType toType) { - throw new InternalError("Not implemented!"); - } - - - } - - - /** Binary expression conditional jump. */ - class BinaryExpressionConditionalJump implements BinaryExpression { - private final StatementConditionalJump conditionalJump; - - BinaryExpressionConditionalJump(StatementConditionalJump assignment) { - this.conditionalJump = assignment; - } - - @Override - public RValue getLeft() { - return conditionalJump.getrValue1(); - } - - @Override - public OperatorBinary getOperator() { - return (OperatorBinary) conditionalJump.getOperator(); - } - - @Override - public RValue getRight() { - return conditionalJump.getrValue2(); - } - - @Override - public void addRightCast(SymbolType toType) { - throw new InternalError("Not implemented!"); - } - - - } - - /** Binary expression as part of a constant expression. */ - class BinaryExpressionConstant implements BinaryExpression { - private ConstantBinary constantBinary; - - BinaryExpressionConstant(ConstantBinary constantBinary) { - this.constantBinary = constantBinary; - } - - @Override - public RValue getLeft() { - return constantBinary.getLeft(); - } - - @Override - public OperatorBinary getOperator() { - return constantBinary.getOperator(); - } - - @Override - public RValue getRight() { - return constantBinary.getRight(); - } - - @Override - public void addRightCast(SymbolType toType) { - constantBinary.setRight(new ConstantCastValue(toType, constantBinary.getRight())); - } - } -} diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpression.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpression.java new file mode 100644 index 000000000..68658fc11 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpression.java @@ -0,0 +1,28 @@ +package dk.camelot64.kickc.model.iterator; + +import dk.camelot64.kickc.model.operators.Operator; +import dk.camelot64.kickc.model.values.ConstantRef; +import dk.camelot64.kickc.model.values.RValue; +import dk.camelot64.kickc.model.values.Value; + +/** A unary or binary operator expression. + * Iterable using {@link ProgramExpressionIterator}. + * */ +public interface ProgramExpression { + + /** + * Get the operator + * + * @return the operator + */ + Operator getOperator(); + + /** + * Replace the unary/binary expression with a new value. + * + * Throws an exception if replacement is not possible + * + * @param value The new value. + */ + void set(Value value); +} diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java new file mode 100644 index 000000000..655ca17e4 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java @@ -0,0 +1,262 @@ +package dk.camelot64.kickc.model.iterator; + +import dk.camelot64.kickc.model.Comment; +import dk.camelot64.kickc.model.InternalError; +import dk.camelot64.kickc.model.operators.OperatorBinary; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.statements.StatementConditionalJump; +import dk.camelot64.kickc.model.symbols.ProgramScope; +import dk.camelot64.kickc.model.symbols.Scope; +import dk.camelot64.kickc.model.symbols.VariableIntermediate; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.values.*; + +import java.util.ListIterator; + +/** + * A binary expression in the program being iterated by {@link ProgramExpressionIterator} + */ +public interface ProgramExpressionBinary extends ProgramExpression { + + /** + * Get the left operand + * + * @return The left operand + */ + RValue getLeft(); + + /** + * Get the binary operator + * + * @return the operator + */ + OperatorBinary getOperator(); + + /** + * Get the right operand + * + * @return The right operand + */ + RValue getRight(); + + /** + * Adds a cast to the left operand + * @param toType The toType to cast to + */ + void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols); + + /** + * Adds a cast to the right operand + * @param toType The toType to cast to + */ + void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols); + + + /** Binary expression assignment rvalue. */ + class ProgramExpressionBinaryAssignmentRValue implements ProgramExpressionBinary { + + private final StatementAssignment assignment; + + ProgramExpressionBinaryAssignmentRValue(StatementAssignment assignment) { + this.assignment = assignment; + } + + @Override + public RValue getLeft() { + return assignment.getrValue1(); + } + + @Override + public OperatorBinary getOperator() { + return (OperatorBinary) assignment.getOperator(); + } + + @Override + public RValue getRight() { + return assignment.getrValue2(); + } + + @Override + public void set(Value value) { + assignment.setrValue2((RValue) value); + assignment.setOperator(null); + assignment.setrValue1(null); + } + + @Override + public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + if(assignment.getrValue1() instanceof ConstantValue) { + assignment.setrValue1(new ConstantCastValue(toType, (ConstantValue) assignment.getrValue1())); + } else { + Scope blockScope = symbols.getScope(currentScope); + VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); + tmpVar.setType(toType); + StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue1(), assignment.getSource(), Comment.NO_COMMENTS); + assignment.setrValue1(tmpVar.getRef()); + stmtIt.add(newAssignment); + } + } + + @Override + public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + if(assignment.getrValue2() instanceof ConstantValue) { + assignment.setrValue2(new ConstantCastValue(toType, (ConstantValue) assignment.getrValue2())); + } else { + Scope blockScope = symbols.getScope(currentScope); + VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); + tmpVar.setType(toType); + StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue2(), assignment.getSource(), Comment.NO_COMMENTS); + assignment.setrValue2(tmpVar.getRef()); + stmtIt.add(newAssignment); + } + } + } + + /** Binary expression - assignment lvalue and the "total" rvalue. */ + class ProgramExpressionBinaryAssignmentLValue implements ProgramExpressionBinary { + private final StatementAssignment assignment; + + ProgramExpressionBinaryAssignmentLValue(StatementAssignment assignment) { + this.assignment = assignment; + } + + @Override + public RValue getLeft() { + return assignment.getlValue(); + } + + @Override + public OperatorBinary getOperator() { + return Operators.ASSIGNMENT; + } + + @Override + public RValue getRight() { + if(assignment.getrValue1()==null && assignment.getOperator()==null) { + return assignment.getrValue2(); + } else { + return new AssignmentRValue(assignment); + } + } + + @Override + public void set(Value value) { + throw new InternalError("Updating an entire assignment is not allowed!"); + } + + @Override + public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + Scope blockScope = symbols.getScope(currentScope); + VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); + SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight()); + tmpVar.setType(rightType); + StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS); + assignment.setlValue(tmpVar.getRef()); + stmtIt.add(newAssignment); + } + + @Override + public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + if(assignment.getrValue1()==null && assignment.getOperator()==null) { + //if(assignment.getrValue2() instanceof ConstantInteger) { + // ((ConstantInteger) assignment.getrValue2()).setType(toType); + //} else { + assignment.setOperator(Operators.getCastUnary(toType)); + //} + } else { + throw new InternalError("Not implemented!"); + } + } + + } + + /** Binary expression conditional jump. */ + class ProgramExpressionBinaryConditionalJump implements ProgramExpressionBinary { + private final StatementConditionalJump conditionalJump; + + ProgramExpressionBinaryConditionalJump(StatementConditionalJump assignment) { + this.conditionalJump = assignment; + } + + @Override + public RValue getLeft() { + return conditionalJump.getrValue1(); + } + + @Override + public OperatorBinary getOperator() { + return (OperatorBinary) conditionalJump.getOperator(); + } + + @Override + public RValue getRight() { + return conditionalJump.getrValue2(); + } + + @Override + public void set(Value value) { + conditionalJump.setrValue2((RValue) value); + conditionalJump.setOperator(null); + conditionalJump.setrValue1(null); + } + + @Override + public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + throw new InternalError("Not implemented!"); + } + + @Override + public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + throw new InternalError("Not implemented!"); + } + + + } + + /** Binary expression as part of a constant expression. */ + class ProgramExpressionBinaryConstant implements ProgramExpressionBinary { + /** A program value containing a {@link ConstantBinary}. */ + private ProgramValue programValue; + + public ProgramExpressionBinaryConstant(ProgramValue programValue) { + this.programValue = programValue; + } + + public ConstantBinary getConstantBinary() { + return (ConstantBinary)programValue.get(); + } + + @Override + public RValue getLeft() { + return getConstantBinary().getLeft(); + } + + @Override + public OperatorBinary getOperator() { + return getConstantBinary().getOperator(); + } + + @Override + public RValue getRight() { + return getConstantBinary().getRight(); + } + + @Override + public void set(Value value) { + programValue.set(value); + } + + @Override + public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + getConstantBinary().setLeft(new ConstantCastValue(toType, getConstantBinary().getLeft())); + } + + @Override + public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + getConstantBinary().setRight(new ConstantCastValue(toType, getConstantBinary().getRight())); + } + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionHandler.java similarity index 51% rename from src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java rename to src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionHandler.java index f5b10f5e0..077eb7cdd 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionHandler.java @@ -5,21 +5,22 @@ import dk.camelot64.kickc.model.statements.Statement; import java.util.ListIterator; -/** A handler that performs some action for binary expressions in the program. - * A {@link BinaryExpressionIterator} can be used to iterate all binary expressions in a part of the program. - * The Handler then receives all binary expressions one at a time. The Handler has the option of modifying the binary expression. After the handler is executed all sub-values are recursed. +/** A handler that performs some action for unary/binary expressions in the program. + * A {@link ProgramExpressionIterator} can be used to iterate all unary/binary expressions in a part of the program. + * The Handler then receives all unary/binary expressions one at a time. + * The Handler has the option of modifying the expression. After the handler is executed all sub-values are recursed. * The execute() method furthermore receives some extra parameters with information about the context of the passed value. */ -public interface BinaryExpressionHandler { +public interface ProgramExpressionHandler { /** - * Handle a single binary expression + * Handle a single expression * - * @param binaryExpression The binary expression + * @param programExpression The expression * @param currentStmt The statement iterator - just past the current statement that the value is a part of. Current statment can be retrieved by calling * @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block. * @param currentBlock The current block that the value is a part of */ - void execute(BinaryExpression binaryExpression, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock); + void execute(ProgramExpression programExpression, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock); } diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java similarity index 56% rename from src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java rename to src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java index 05c761267..a8ae53aca 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java @@ -6,15 +6,16 @@ import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementConditionalJump; import dk.camelot64.kickc.model.values.ConstantBinary; +import dk.camelot64.kickc.model.values.ConstantUnary; import java.util.ListIterator; /** * Capable of iterating the different structures of a Program (graph, block, statement, symboltable, symbol). - * Creates appropriate BinaryExpressions and passes them to a BinaryExpressionHandler. + * Creates appropriate BinaryExpressions and passes them to a ProgramExpressionHandler. * Iteration might be guided (eg. filtering some types of the structure to iterate at call-time) */ -public class BinaryExpressionIterator { +public class ProgramExpressionIterator { /** * Execute a handler on all values in the entire program (both in the control flow graph and the symbol table.) @@ -22,12 +23,11 @@ public class BinaryExpressionIterator { * @param program The program * @param handler The handler to execute */ - public static void execute(Program program, BinaryExpressionHandler handler) { + public static void execute(Program program, ProgramExpressionHandler handler) { // Iterate all symbols ProgramValueIterator.execute(program.getScope(), (programValue, currentStmt, stmtIt, currentBlock) -> { if(programValue.get() instanceof ConstantBinary) { - ConstantBinary constantBinary = (ConstantBinary) programValue.get(); - handler.execute( new BinaryExpression.BinaryExpressionConstant(constantBinary), null, null, null); + handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), null, null, null); } }); @@ -38,22 +38,26 @@ public class BinaryExpressionIterator { Statement stmt = stmtIt.next(); if(stmt instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) stmt; - if(assignment.getrValue1() != null && assignment.getOperator()!=null &&assignment.getrValue2() != null) { - handler.execute( new BinaryExpression.BinaryExpressionAssignmentRValue(assignment), stmt, stmtIt, block); + if(assignment.getrValue1() != null && assignment.getOperator() != null && assignment.getrValue2() != null) { + handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryAssignmentRValue(assignment), stmt, stmtIt, block); + } else if(assignment.getrValue1() == null && assignment.getOperator() != null && assignment.getrValue2() != null) { + handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryAssignmentRValue(assignment), stmt, stmtIt, block); } - handler.execute( new BinaryExpression.BinaryExpressionAssignmentLValue(assignment), stmt, stmtIt, block); + handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue(assignment), stmt, stmtIt, block); } else if(stmt instanceof StatementConditionalJump) { StatementConditionalJump condJump = (StatementConditionalJump) stmt; - if(condJump.getrValue1()!=null && condJump.getOperator()!=null && condJump.getrValue2()!=null) { - handler.execute( new BinaryExpression.BinaryExpressionConditionalJump(condJump), stmt, stmtIt, block); + if(condJump.getrValue1() != null && condJump.getOperator() != null && condJump.getrValue2() != null) { + handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConditionalJump(condJump), stmt, stmtIt, block); } } // Iterate all statement values ProgramValueIterator.execute(stmt, (programValue, currentStmt, stmtIt1, currentBlock) -> { if(programValue.get() instanceof ConstantBinary) { - ConstantBinary constantBinary = (ConstantBinary) programValue.get(); - handler.execute( new BinaryExpression.BinaryExpressionConstant(constantBinary), stmt, stmtIt, block); + handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), stmt, stmtIt, block); + } else if(programValue.get() instanceof ConstantUnary) { + handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), stmt, stmtIt, block); } + }, stmtIt, block); } } diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java new file mode 100644 index 000000000..a2795032d --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java @@ -0,0 +1,84 @@ +package dk.camelot64.kickc.model.iterator; + +import dk.camelot64.kickc.model.operators.OperatorUnary; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.values.ConstantUnary; +import dk.camelot64.kickc.model.values.RValue; +import dk.camelot64.kickc.model.values.Value; + +/** + * A binary expression in the program being iterated by {@link ProgramExpressionIterator} + */ +public interface ProgramExpressionUnary extends ProgramExpression { + + /** + * Get the unary operator + * + * @return the operator + */ + OperatorUnary getOperator(); + + /** + * Get the right operand + * + * @return The right operand + */ + RValue getOperand(); + + /** Unary expression assignment rvalue. */ + class ProgramExpressionUnaryAssignmentRValue implements ProgramExpressionUnary { + private final StatementAssignment assignment; + + ProgramExpressionUnaryAssignmentRValue(StatementAssignment assignment) { + this.assignment = assignment; + } + + @Override + public OperatorUnary getOperator() { + return (OperatorUnary) assignment.getOperator(); + } + + @Override + public RValue getOperand() { + return assignment.getrValue2(); + } + + @Override + public void set(Value value) { + assignment.setrValue2((RValue) value); + assignment.setOperator(null); + } + } + + /** Unary expression as part of a constant expression. */ + class ProgramExpressionUnaryConstant implements ProgramExpressionUnary { + + /** A ProgramValue containing a {@link ConstantUnary}. */ + private ProgramValue programValue; + + ProgramExpressionUnaryConstant(ProgramValue programValue) { + this.programValue = programValue; + } + + public ConstantUnary getConstantUnary() { + return (ConstantUnary) programValue.get(); + } + + @Override + public OperatorUnary getOperator() { + return (getConstantUnary()).getOperator(); + } + + @Override + public RValue getOperand() { + return getConstantUnary().getOperand(); + } + + @Override + public void set(Value value) { + programValue.set(value); + } + + } + +} diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java index 9f34e3c20..551863bf9 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java @@ -7,489 +7,23 @@ import dk.camelot64.kickc.model.types.SymbolTypeArray; import dk.camelot64.kickc.model.values.*; /** - * An RValue in the program being iterated by {@link ProgramValueIterator}. + * Any Value in the program being iterated by {@link ProgramValueIterator}. * - * The RValue can be inspected using get() and replaced inside the model using set(val). + * The Value can be inspected using get() and replaced inside the model using set(val). * - * The context of the RValue can be determined from the sub-class containing it plus the parameters to the ProgramValueHandler. + * The context of the Value can be determined from the sub-class containing it plus the parameters to the ProgramValueHandler. * */ -public abstract class ProgramValue { +public interface ProgramValue { - public abstract Value get(); + Value get(); - public abstract void set(Value value); + void set(Value value); - public static class ConstantVariableValue extends ProgramValue { - private final ConstantVar constantVar; - - ConstantVariableValue(ConstantVar constantVar) { - this.constantVar = constantVar; - } - - @Override - public Value get() { - return constantVar.getValue(); - } - - @Override - public void set(Value val) { - constantVar.setValue((ConstantValue) val); - } - - } - - /** Size inside a fixed size array. */ - public static class TypeArraySize extends ProgramValue { - private final SymbolTypeArray array; - - TypeArraySize(SymbolTypeArray array) { - this.array = array; - } - - @Override - public Value get() { - return array.getSize(); - } - - @Override - public void set(Value val) { - array.setSize((RValue) val); - } - - } - - /** Value inside a array filled expression. */ - public static class ArrayFilledSize extends ProgramValue { - private final ArrayFilled array; - - ArrayFilledSize(ArrayFilled array) { - this.array = array; - } - - @Override - public Value get() { - return array.getSize(); - } - - @Override - public void set(Value val) { - array.setSize((RValue) val); - } - - } - - /** Value inside an intermediate LValue. */ - public static class LValueIntermediateVariable extends ProgramValue { - private final LvalueIntermediate intermediate; - - LValueIntermediateVariable(LvalueIntermediate intermediate) { - this.intermediate = intermediate; - } - - @Override - public Value get() { - return intermediate.getVariable(); - } - - @Override - public void set(Value val) { - intermediate.setVariable((VariableRef) val); - } - - } - - /** Value inside a constant array filled expression. */ - public static class ConstantArrayFilledSize extends ProgramValue { - private final ConstantArrayFilled array; - - ConstantArrayFilledSize(ConstantArrayFilled array) { - this.array = array; - } - - @Override - public Value get() { - return array.getSize(); - } - - @Override - public void set(Value val) { - array.setSize((ConstantValue) val); - } - - } - - /** Value inside a constant unary expression. */ - public static class ConstantUnaryValue extends ProgramValue { - private final ConstantUnary unary; - - ConstantUnaryValue(ConstantUnary unary) { - this.unary = unary; - } - - @Override - public Value get() { - return unary.getOperand(); - } - - @Override - public void set(Value val) { - unary.setOperand((ConstantValue) val); - } - - } - - /** Left value inside a constant binary expression. */ - public static class ConstantBinaryLeft extends ProgramValue { - private final ConstantBinary binary; - - ConstantBinaryLeft(ConstantBinary binary) { - this.binary = binary; - } - - @Override - public Value get() { - return binary.getLeft(); - } - - @Override - public void set(Value val) { - binary.setLeft((ConstantValue) val); - } - - } - - /** Right value inside a constant binary expression. */ - public static class ConstantBinaryRight extends ProgramValue { - private final ConstantBinary binary; - - ConstantBinaryRight(ConstantBinary range) { - this.binary = range; - } - - @Override - public Value get() { - return binary.getRight(); - } - - @Override - public void set(Value val) { - binary.setRight((ConstantValue) val); - } - - } - - /** - * First value inside a ranged comparison value. - */ - public static class RangeFirst extends ProgramValue { - private final RangeValue range; - - RangeFirst(RangeValue range) { - this.range = range; - } - - @Override - public Value get() { - return range.getRangeFirst(); - } - - @Override - public void set(Value val) { - range.setRangeFirst((RValue) val); - } - - } - - /** - * Last value inside inside a ranged comparison value. - */ - public static class RangeLast extends ProgramValue { - private final RangeValue range; - - RangeLast(RangeValue range) { - this.range = range; - } - - @Override - public Value get() { - return range.getRangeLast(); - } - - @Override - public void set(Value val) { - range.setRangeLast((RValue) val); - } - - } - - /** A variable/constant referenced inside inline ASM. */ - public static class AsmReferenced extends ProgramValue { - private StatementAsm statementAsm; - private String label; - - public AsmReferenced(StatementAsm statementAsm, String label) { - this.statementAsm = statementAsm; - this.label = label; - } - - @Override - public Value get() { - return statementAsm.getReferenced().get(label); - } - - @Override - public void set(Value value) { - statementAsm.getReferenced().put(label, (SymbolVariableRef) value); - } - } - - /** Location inside inline kickasm code. */ - public static class KickAsmLocation extends ProgramValue { - - private StatementKickAsm statementKickAsm; - - KickAsmLocation(StatementKickAsm statementKickAsm) { - super(); - this.statementKickAsm = statementKickAsm; - } - - @Override - public Value get() { - return statementKickAsm.getLocation(); - } - - @Override - public void set(Value value) { - statementKickAsm.setLocation((RValue) value); - } - - } - - /** Bytes inside inline kickasm code. */ - public static class KickAsmBytes extends ProgramValue { - - private StatementKickAsm statementKickAsm; - - KickAsmBytes(StatementKickAsm statementKickAsm) { - super(); - this.statementKickAsm = statementKickAsm; - } - - @Override - public Value get() { - return statementKickAsm.getBytes(); - } - - @Override - public void set(Value value) { - statementKickAsm.setBytes((RValue) value); - } - - } - - /** Cycles inside inline kickasm code. */ - public static class KickAsmCycles extends ProgramValue { - - private StatementKickAsm statementKickAsm; - - KickAsmCycles(StatementKickAsm statementKickAsm) { - super(); - this.statementKickAsm = statementKickAsm; - } - - @Override - public Value get() { - return statementKickAsm.getCycles(); - } - - @Override - public void set(Value value) { - statementKickAsm.setCycles((RValue) value); - } - - } - - /** - * LValue as part of an assignment statement (or a call). - */ - public static class LValue extends ProgramValue { - private final StatementLValue statement; - - public LValue(StatementLValue statement) { - this.statement = statement; - } - - @Override - public Value get() { - return statement.getlValue(); - } - - @Override - public void set(Value value) { - statement.setlValue((dk.camelot64.kickc.model.values.LValue) value); - } - - } - - /** - * Pointer inside a pointer dererence value. - */ - public static class Pointer extends ProgramValue { - private final PointerDereference pointer; - - Pointer(PointerDereference pointer) { - this.pointer = pointer; - } - - @Override - public Value get() { - return pointer.getPointer(); - } - - @Override - public void set(Value val) { - pointer.setPointer((RValue) val); - } - - } - - /** - * Value inside a noop cast. - */ - public static class CastValue extends ProgramValue { - private final dk.camelot64.kickc.model.values.CastValue castValue; - - - public CastValue(dk.camelot64.kickc.model.values.CastValue castValue) { - this.castValue = castValue; - } - - @Override - public Value get() { - return castValue.getValue(); - } - - @Override - public void set(Value val) { - castValue.setValue((RValue) val); - } - - } - - /** - * Value inside a constant noop cast. - */ - public static class ConstantCastValue extends ProgramValue { - private final dk.camelot64.kickc.model.values.ConstantCastValue castValue; - - - ConstantCastValue(dk.camelot64.kickc.model.values.ConstantCastValue castValue) { - this.castValue = castValue; - } - - @Override - public Value get() { - return castValue.getValue(); - } - - @Override - public void set(Value val) { - castValue.setValue((ConstantValue) val); - } - - } - - /** - * Pointer inside a variable pointer. - */ - public static class ConstantSymbolPointerTo extends ProgramValue { - private final ConstantSymbolPointer varPointer; - - - ConstantSymbolPointerTo(ConstantSymbolPointer varPointer) { - this.varPointer = varPointer; - } - - @Override - public Value get() { - return (RValue) varPointer.getToSymbol(); - } - - @Override - public void set(Value val) { - varPointer.setToSymbol((VariableRef) val); - } - - } - - public static class ConstantArrayElement extends ProgramValue { - private final ConstantArrayList arrayList; - private final int idx; - - ConstantArrayElement(ConstantArrayList arrayList, int idx) { - this.arrayList = arrayList; - this.idx = idx; - } - - @Override - public Value get() { - return arrayList.getElements().get(idx); - } - - @Override - public void set(Value value) { - arrayList.getElements().set(idx, (ConstantValue) value); - } - } - - public static class ListElement extends ProgramValue { - private ValueList list; - private int idx; - - ListElement(ValueList list, int idx) { - this.list = list; - this.idx = idx; - } - - @Override - public Value get() { - return list.getList().get(idx); - } - - @Override - public void set(Value value) { - list.getList().set(idx, (RValue) value); - } - - } - - /** - * Pointer index inside a indexed pointer dererence value. - */ - public static class PointerIndex extends ProgramValue { - private final PointerDereferenceIndexed pointer; - - PointerIndex(PointerDereferenceIndexed pointer) { - this.pointer = pointer; - } - - @Override - public Value get() { - return pointer.getIndex(); - } - - @Override - public void set(Value val) { - pointer.setIndex((RValue) val); - } - - } - - public static class RValue1 extends ProgramValue { + class RValue1 implements ProgramValue { private final StatementAssignment statement; - public RValue1(StatementAssignment statement) { + RValue1(StatementAssignment statement) { this.statement = statement; } @@ -504,10 +38,10 @@ public abstract class ProgramValue { } } - public static class RValue2 extends ProgramValue { + class RValue2 implements ProgramValue { private final StatementAssignment statement; - public RValue2(StatementAssignment statement) { + RValue2(StatementAssignment statement) { this.statement = statement; } @@ -522,7 +56,7 @@ public abstract class ProgramValue { } } - public static class CallParameter extends ProgramValue { + class CallParameter implements ProgramValue { private final StatementCall call; private final int i; @@ -542,7 +76,7 @@ public abstract class ProgramValue { } } - public static class CallPointerProcedure extends ProgramValue { + class CallPointerProcedure implements ProgramValue { private final StatementCallPointer call; CallPointerProcedure(StatementCallPointer call) { @@ -560,7 +94,7 @@ public abstract class ProgramValue { } } - public static class CallPointerParameter extends ProgramValue { + class CallPointerParameter implements ProgramValue { private final StatementCallPointer call; private final int i; @@ -580,10 +114,10 @@ public abstract class ProgramValue { } } - public static class CondRValue1 extends ProgramValue { + class CondRValue1 implements ProgramValue { private final StatementConditionalJump statement; - public CondRValue1(StatementConditionalJump statement) { + CondRValue1(StatementConditionalJump statement) { this.statement = statement; } @@ -598,10 +132,10 @@ public abstract class ProgramValue { } } - public static class CondRValue2 extends ProgramValue { + class CondRValue2 implements ProgramValue { private final StatementConditionalJump statement; - public CondRValue2(StatementConditionalJump statement) { + CondRValue2(StatementConditionalJump statement) { this.statement = statement; } @@ -616,10 +150,10 @@ public abstract class ProgramValue { } } - public static class CondLabel extends ProgramValue { + class CondLabel implements ProgramValue { private final StatementConditionalJump statement; - public CondLabel(StatementConditionalJump statement) { + CondLabel(StatementConditionalJump statement) { this.statement = statement; } @@ -634,7 +168,7 @@ public abstract class ProgramValue { } } - public static class Return extends ProgramValue { + class Return implements ProgramValue { private final StatementReturn statement; public Return(StatementReturn statement) { @@ -652,7 +186,7 @@ public abstract class ProgramValue { } } - public static class PhiValue extends ProgramValue { + class PhiValue implements ProgramValue { private final StatementPhiBlock.PhiVariable phiVariable; private final int i; @@ -672,7 +206,7 @@ public abstract class ProgramValue { } } - public static class PhiValuePredecessor extends ProgramValue { + class PhiValuePredecessor implements ProgramValue { private final StatementPhiBlock.PhiVariable phiVariable; private final int i; @@ -695,7 +229,7 @@ public abstract class ProgramValue { /** * LValue as part of an assignment statement (or a call). */ - public static class PhiVariable extends ProgramValue { + class PhiVariable implements ProgramValue { private final StatementPhiBlock.PhiVariable phiVariable; public PhiVariable(StatementPhiBlock.PhiVariable phiVariable) { @@ -715,7 +249,7 @@ public abstract class ProgramValue { } /** A generic Value. */ - public static class GenericValue extends ProgramValue { + class GenericValue implements ProgramValue { private RValue rValue; public GenericValue(RValue rValue) { @@ -734,11 +268,11 @@ public abstract class ProgramValue { } /** A variable used by inline kickasm. */ - public static class KickAsmUses extends ProgramValue { + class KickAsmUses implements ProgramValue { private StatementKickAsm statementKickAsm; private int idx; - public KickAsmUses(StatementKickAsm statementKickAsm, int idx) { + KickAsmUses(StatementKickAsm statementKickAsm, int idx) { this.statementKickAsm = statementKickAsm; this.idx = idx; } @@ -756,7 +290,7 @@ public abstract class ProgramValue { } - public static class BlockLabel extends ProgramValue { + class BlockLabel implements ProgramValue { private final ControlFlowBlock block; @@ -776,7 +310,7 @@ public abstract class ProgramValue { } - public static class BlockDefaultSuccessor extends ProgramValue { + class BlockDefaultSuccessor implements ProgramValue { private final ControlFlowBlock block; @@ -796,7 +330,7 @@ public abstract class ProgramValue { } - public static class BlockConditionalSuccessor extends ProgramValue { + class BlockConditionalSuccessor implements ProgramValue { private final ControlFlowBlock block; @@ -816,7 +350,7 @@ public abstract class ProgramValue { } - public static class BlockCallSuccessor extends ProgramValue { + class BlockCallSuccessor implements ProgramValue { private final ControlFlowBlock block; @@ -836,4 +370,467 @@ public abstract class ProgramValue { } + /** Value inside a array filled expression. */ + class ProgramValueArrayFilledSize implements ProgramValue { + private final ArrayFilled array; + + ProgramValueArrayFilledSize(ArrayFilled array) { + this.array = array; + } + + @Override + public Value get() { + return array.getSize(); + } + + @Override + public void set(Value val) { + array.setSize((RValue) val); + } + + } + + /** A variable/constant referenced inside inline ASM. */ + class ProgramValueAsmReferenced implements ProgramValue { + private StatementAsm statementAsm; + private String label; + + ProgramValueAsmReferenced(StatementAsm statementAsm, String label) { + this.statementAsm = statementAsm; + this.label = label; + } + + @Override + public Value get() { + return statementAsm.getReferenced().get(label); + } + + @Override + public void set(Value value) { + statementAsm.getReferenced().put(label, (SymbolVariableRef) value); + } + } + + /** + * Value inside a noop cast. + */ + class ProgramValueCastValue implements ProgramValue { + private final CastValue castValue; + + + public ProgramValueCastValue(CastValue castValue) { + this.castValue = castValue; + } + + @Override + public Value get() { + return castValue.getValue(); + } + + @Override + public void set(Value val) { + castValue.setValue((RValue) val); + } + + } + + class ProgramValueConstantArrayElement implements ProgramValue { + private final ConstantArrayList arrayList; + private final int idx; + + ProgramValueConstantArrayElement(ConstantArrayList arrayList, int idx) { + this.arrayList = arrayList; + this.idx = idx; + } + + @Override + public Value get() { + return arrayList.getElements().get(idx); + } + + @Override + public void set(Value value) { + arrayList.getElements().set(idx, (ConstantValue) value); + } + } + + /** Value inside a constant array filled expression. */ + class ProgramValueConstantArrayFilledSize implements ProgramValue { + private final ConstantArrayFilled array; + + ProgramValueConstantArrayFilledSize(ConstantArrayFilled array) { + this.array = array; + } + + @Override + public Value get() { + return array.getSize(); + } + + @Override + public void set(Value val) { + array.setSize((ConstantValue) val); + } + + } + + /** Left value inside a constant binary expression. */ + class ProgramValueConstantBinaryLeft implements ProgramValue { + private final ConstantBinary binary; + + ProgramValueConstantBinaryLeft(ConstantBinary binary) { + this.binary = binary; + } + + @Override + public Value get() { + return binary.getLeft(); + } + + @Override + public void set(Value val) { + binary.setLeft((ConstantValue) val); + } + + } + + /** Right value inside a constant binary expression. */ + class ProgramValueConstantBinaryRight implements ProgramValue { + private final ConstantBinary binary; + + ProgramValueConstantBinaryRight(ConstantBinary range) { + this.binary = range; + } + + @Override + public Value get() { + return binary.getRight(); + } + + @Override + public void set(Value val) { + binary.setRight((ConstantValue) val); + } + + } + + /** + * Value inside a constant noop cast. + */ + class ProgramValueConstantCastValue implements ProgramValue { + private final ConstantCastValue castValue; + + + ProgramValueConstantCastValue(ConstantCastValue castValue) { + this.castValue = castValue; + } + + @Override + public Value get() { + return castValue.getValue(); + } + + @Override + public void set(Value val) { + castValue.setValue((ConstantValue) val); + } + + } + + /** + * Pointer inside a variable pointer. + */ + class ProgramValueConstantSymbolPointerTo implements ProgramValue { + private final ConstantSymbolPointer varPointer; + + + ProgramValueConstantSymbolPointerTo(ConstantSymbolPointer varPointer) { + this.varPointer = varPointer; + } + + @Override + public Value get() { + return varPointer.getToSymbol(); + } + + @Override + public void set(Value val) { + varPointer.setToSymbol((VariableRef) val); + } + + } + + /** Value inside a constant unary expression. */ + class ProgramValueConstantUnaryValue implements ProgramValue { + private final ConstantUnary unary; + + ProgramValueConstantUnaryValue(ConstantUnary unary) { + this.unary = unary; + } + + @Override + public Value get() { + return unary.getOperand(); + } + + @Override + public void set(Value val) { + unary.setOperand((ConstantValue) val); + } + + } + + class ProgramValueConstantVar implements ProgramValue { + private final ConstantVar constantVar; + + ProgramValueConstantVar(ConstantVar constantVar) { + this.constantVar = constantVar; + } + + @Override + public Value get() { + return constantVar.getValue(); + } + + @Override + public void set(Value val) { + constantVar.setValue((ConstantValue) val); + } + + } + + /** Bytes inside inline kickasm code. */ + class ProgramValueKickAsmBytes implements ProgramValue { + + private StatementKickAsm statementKickAsm; + + ProgramValueKickAsmBytes(StatementKickAsm statementKickAsm) { + this.statementKickAsm = statementKickAsm; + } + + @Override + public Value get() { + return statementKickAsm.getBytes(); + } + + @Override + public void set(Value value) { + statementKickAsm.setBytes((RValue) value); + } + + } + + /** Cycles inside inline kickasm code. */ + class ProgramValueKickAsmCycles implements ProgramValue { + + private StatementKickAsm statementKickAsm; + + ProgramValueKickAsmCycles(StatementKickAsm statementKickAsm) { + this.statementKickAsm = statementKickAsm; + } + + @Override + public Value get() { + return statementKickAsm.getCycles(); + } + + @Override + public void set(Value value) { + statementKickAsm.setCycles((RValue) value); + } + + } + + /** Location inside inline kickasm code. */ + class ProgramValueKickAsmLocation implements ProgramValue { + + private StatementKickAsm statementKickAsm; + + ProgramValueKickAsmLocation(StatementKickAsm statementKickAsm) { + super(); + this.statementKickAsm = statementKickAsm; + } + + @Override + public Value get() { + return statementKickAsm.getLocation(); + } + + @Override + public void set(Value value) { + statementKickAsm.setLocation((RValue) value); + } + + } + + class ProgramValueListElement implements ProgramValue { + private ValueList list; + private int idx; + + ProgramValueListElement(ValueList list, int idx) { + this.list = list; + this.idx = idx; + } + + @Override + public Value get() { + return list.getList().get(idx); + } + + @Override + public void set(Value value) { + list.getList().set(idx, (RValue) value); + } + + } + + /** + * LValue as part of an assignment statement (or a call). + */ + class ProgramValueLValue implements ProgramValue { + private final StatementLValue statement; + + public ProgramValueLValue(StatementLValue statement) { + this.statement = statement; + } + + @Override + public Value get() { + return statement.getlValue(); + } + + @Override + public void set(Value value) { + statement.setlValue((LValue) value); + } + + } + + /** Value inside an intermediate LValue. */ + class ProgramValueLValueIntermediateVariable implements ProgramValue { + private final LvalueIntermediate intermediate; + + ProgramValueLValueIntermediateVariable(LvalueIntermediate intermediate) { + this.intermediate = intermediate; + } + + @Override + public Value get() { + return intermediate.getVariable(); + } + + @Override + public void set(Value val) { + intermediate.setVariable((VariableRef) val); + } + + } + + /** + * Pointer inside a pointer dererence value. + */ + class ProgramValuePointer implements ProgramValue { + private final PointerDereference pointer; + + ProgramValuePointer(PointerDereference pointer) { + this.pointer = pointer; + } + + @Override + public Value get() { + return pointer.getPointer(); + } + + @Override + public void set(Value val) { + pointer.setPointer((RValue) val); + } + + } + + /** + * Pointer index inside a indexed pointer dererence value. + */ + class ProgramValuePointerIndex implements ProgramValue { + private final PointerDereferenceIndexed pointer; + + ProgramValuePointerIndex(PointerDereferenceIndexed pointer) { + this.pointer = pointer; + } + + @Override + public Value get() { + return pointer.getIndex(); + } + + @Override + public void set(Value val) { + pointer.setIndex((RValue) val); + } + + } + + /** + * First value inside a ranged comparison value. + */ + class ProgramValueRangeFirst implements ProgramValue { + private final RangeValue range; + + ProgramValueRangeFirst(RangeValue range) { + this.range = range; + } + + @Override + public Value get() { + return range.getRangeFirst(); + } + + @Override + public void set(Value val) { + range.setRangeFirst((RValue) val); + } + + } + + /** + * Last value inside inside a ranged comparison value. + */ + class ProgramValueRangeLast implements ProgramValue { + private final RangeValue range; + + ProgramValueRangeLast(RangeValue range) { + this.range = range; + } + + @Override + public Value get() { + return range.getRangeLast(); + } + + @Override + public void set(Value val) { + range.setRangeLast((RValue) val); + } + + } + + /** Size inside a fixed size array. */ + class ProgramValueTypeArraySize implements ProgramValue { + private final SymbolTypeArray array; + + ProgramValueTypeArraySize(SymbolTypeArray array) { + this.array = array; + } + + @Override + public Value get() { + return array.getSize(); + } + + @Override + public void set(Value val) { + array.setSize((RValue) val); + } + + } } diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java index 7ca0243de..6fe274204 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java @@ -50,10 +50,10 @@ public class ProgramValueIterator { */ public static void execute(SymbolVariable symbolVariable, ProgramValueHandler programValueHandler) { if(symbolVariable.getType() instanceof SymbolTypeArray) { - execute(new ProgramValue.TypeArraySize((SymbolTypeArray) symbolVariable.getType()), programValueHandler, null, null, null); + execute(new ProgramValue.ProgramValueTypeArraySize((SymbolTypeArray) symbolVariable.getType()), programValueHandler, null, null, null); } if(symbolVariable instanceof ConstantVar) { - execute(new ProgramValue.ConstantVariableValue((ConstantVar) symbolVariable), programValueHandler, null, null, null); + execute(new ProgramValue.ProgramValueConstantVar((ConstantVar) symbolVariable), programValueHandler, null, null, null); } } @@ -98,7 +98,7 @@ public class ProgramValueIterator { // The sequence RValue1, RValue2, LValue is important - as it is essential for {@link dk.camelot64.kickc.passes.Pass1GenerateSingleStaticAssignmentForm} to create the correct SSA execute(new ProgramValue.RValue1((StatementAssignment) statement), handler, statement, statementsIt, block); execute(new ProgramValue.RValue2((StatementAssignment) statement), handler, statement, statementsIt, block); - execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block); + execute(new ProgramValue.ProgramValueLValue((StatementLValue) statement), handler, statement, statementsIt, block); } else if(statement instanceof StatementCall) { StatementCall call = (StatementCall) statement; if(call.getParameters() != null) { @@ -107,7 +107,7 @@ public class ProgramValueIterator { execute(new ProgramValue.CallParameter(call, i), handler, statement, statementsIt, block); } } - execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block); + execute(new ProgramValue.ProgramValueLValue((StatementLValue) statement), handler, statement, statementsIt, block); } else if(statement instanceof StatementCallPointer) { StatementCallPointer call = (StatementCallPointer) statement; execute(new ProgramValue.CallPointerProcedure((StatementCallPointer) statement), handler, statement, statementsIt, block); @@ -117,7 +117,7 @@ public class ProgramValueIterator { execute(new ProgramValue.CallPointerParameter(call, i), handler, statement, statementsIt, block); } } - execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block); + execute(new ProgramValue.ProgramValueLValue((StatementLValue) statement), handler, statement, statementsIt, block); } else if(statement instanceof StatementConditionalJump) { execute(new ProgramValue.CondRValue1((StatementConditionalJump) statement), handler, statement, statementsIt, block); execute(new ProgramValue.CondRValue2((StatementConditionalJump) statement), handler, statement, statementsIt, block); @@ -137,15 +137,15 @@ public class ProgramValueIterator { StatementKickAsm statementKickAsm = (StatementKickAsm) statement; RValue location = statementKickAsm.getLocation(); if(location!=null) { - execute(new ProgramValue.KickAsmLocation(statementKickAsm), handler, statement, statementsIt, block); + execute(new ProgramValue.ProgramValueKickAsmLocation(statementKickAsm), handler, statement, statementsIt, block); } RValue bytes = statementKickAsm.getLocation(); if(bytes!=null) { - execute(new ProgramValue.KickAsmBytes(statementKickAsm), handler, statement, statementsIt, block); + execute(new ProgramValue.ProgramValueKickAsmBytes(statementKickAsm), handler, statement, statementsIt, block); } RValue cycles = statementKickAsm.getLocation(); if(cycles!=null) { - execute(new ProgramValue.KickAsmCycles(statementKickAsm), handler, statement, statementsIt, block); + execute(new ProgramValue.ProgramValueKickAsmCycles(statementKickAsm), handler, statement, statementsIt, block); } List<SymbolVariableRef> uses = statementKickAsm.getUses(); for(int i = 0; i < uses.size(); i++) { @@ -155,7 +155,7 @@ public class ProgramValueIterator { StatementAsm statementAsm = (StatementAsm) statement; Map<String, SymbolVariableRef> referenced = statementAsm.getReferenced(); for(String label : referenced.keySet()) { - execute(new ProgramValue.AsmReferenced(statementAsm, label), handler, statement, statementsIt, block); + execute(new ProgramValue.ProgramValueAsmReferenced(statementAsm, label), handler, statement, statementsIt, block); } } } @@ -182,42 +182,42 @@ public class ProgramValueIterator { private static Collection<ProgramValue> getSubValues(Value value) { ArrayList<ProgramValue> subValues = new ArrayList<>(); if(value instanceof PointerDereferenceIndexed) { - subValues.add(new ProgramValue.Pointer((PointerDereference) value)); - subValues.add(new ProgramValue.PointerIndex((PointerDereferenceIndexed) value)); + subValues.add(new ProgramValue.ProgramValuePointer((PointerDereference) value)); + subValues.add(new ProgramValue.ProgramValuePointerIndex((PointerDereferenceIndexed) value)); } else if(value instanceof PointerDereferenceSimple) { - subValues.add(new ProgramValue.Pointer((PointerDereference) value)); + subValues.add(new ProgramValue.ProgramValuePointer((PointerDereference) value)); } else if(value instanceof ValueList) { ValueList valueList = (ValueList) value; int size = valueList.getList().size(); for(int i = 0; i < size; i++) { - subValues.add(new ProgramValue.ListElement(valueList, i)); + subValues.add(new ProgramValue.ProgramValueListElement(valueList, i)); } } else if(value instanceof ConstantArrayList) { ConstantArrayList constantArrayList = (ConstantArrayList) value; int size = constantArrayList.getElements().size(); for(int i = 0; i < size; i++) { - subValues.add(new ProgramValue.ConstantArrayElement(constantArrayList, i)); + subValues.add(new ProgramValue.ProgramValueConstantArrayElement(constantArrayList, i)); } } else if(value instanceof CastValue) { - subValues.add(new ProgramValue.CastValue((CastValue) value)); + subValues.add(new ProgramValue.ProgramValueCastValue((CastValue) value)); } else if(value instanceof ConstantCastValue) { - subValues.add(new ProgramValue.ConstantCastValue((ConstantCastValue) value)); + subValues.add(new ProgramValue.ProgramValueConstantCastValue((ConstantCastValue) value)); } else if(value instanceof ConstantSymbolPointer) { - subValues.add(new ProgramValue.ConstantSymbolPointerTo((ConstantSymbolPointer) value)); + subValues.add(new ProgramValue.ProgramValueConstantSymbolPointerTo((ConstantSymbolPointer) value)); } else if(value instanceof RangeValue) { - subValues.add(new ProgramValue.RangeFirst((RangeValue) value)); - subValues.add(new ProgramValue.RangeLast((RangeValue) value)); + subValues.add(new ProgramValue.ProgramValueRangeFirst((RangeValue) value)); + subValues.add(new ProgramValue.ProgramValueRangeLast((RangeValue) value)); } else if(value instanceof ConstantBinary) { - subValues.add(new ProgramValue.ConstantBinaryLeft((ConstantBinary) value)); - subValues.add(new ProgramValue.ConstantBinaryRight((ConstantBinary) value)); + subValues.add(new ProgramValue.ProgramValueConstantBinaryLeft((ConstantBinary) value)); + subValues.add(new ProgramValue.ProgramValueConstantBinaryRight((ConstantBinary) value)); } else if(value instanceof ConstantUnary) { - subValues.add(new ProgramValue.ConstantUnaryValue((ConstantUnary) value)); + subValues.add(new ProgramValue.ProgramValueConstantUnaryValue((ConstantUnary) value)); } else if(value instanceof ArrayFilled) { - subValues.add(new ProgramValue.ArrayFilledSize((ArrayFilled) value)); + subValues.add(new ProgramValue.ProgramValueArrayFilledSize((ArrayFilled) value)); } else if(value instanceof ConstantArrayFilled) { - subValues.add(new ProgramValue.ConstantArrayFilledSize((ConstantArrayFilled) value)); + subValues.add(new ProgramValue.ProgramValueConstantArrayFilledSize((ConstantArrayFilled) value)); } else if(value instanceof LvalueIntermediate) { - subValues.add(new ProgramValue.LValueIntermediateVariable((LvalueIntermediate) value)); + subValues.add(new ProgramValue.ProgramValueLValueIntermediateVariable((LvalueIntermediate) value)); } else if(value == null || value instanceof VariableRef || value instanceof ProcedureRef || diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java index 022611a5b..e7906ff6f 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java @@ -1,10 +1,7 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; -import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; +import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -34,7 +31,7 @@ public class OperatorBitwiseAnd extends OperatorBinary { } // Handle numeric types if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { - return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); + return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); } throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java index cad932fb1..3e6a46208 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java @@ -31,7 +31,7 @@ public class OperatorBitwiseOr extends OperatorBinary { } // Handle numeric types if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { - return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); + return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); } throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java index b383ac3f0..2d614f2ab 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java @@ -31,7 +31,7 @@ public class OperatorBitwiseXor extends OperatorBinary { } // Handle numeric types if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { - return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); + return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); } throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCast.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCast.java new file mode 100644 index 000000000..8783a1e60 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCast.java @@ -0,0 +1,18 @@ +package dk.camelot64.kickc.model.operators; + +import dk.camelot64.kickc.model.types.SymbolType; + +/** Abstract cast operator. */ +public abstract class OperatorCast extends OperatorUnary { + + private SymbolType toType; + + public OperatorCast(String operator, String asmOperator, int precedence, SymbolType toType) { + super(operator, asmOperator, precedence); + this.toType = toType; + } + + public SymbolType getToType() { + return toType; + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java index cb1c8a00e..24b02a921 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java @@ -9,10 +9,10 @@ import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; /** Unary Cast to boolean operator ( (boolean) x ) */ -public class OperatorCastBool extends OperatorUnary { +public class OperatorCastBool extends OperatorCast { public OperatorCastBool(int precedence) { - super("((bool))", "_bool_", precedence); + super("((bool))", "_bool_", precedence, SymbolType.BOOLEAN); } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java index ea24ee803..b00ba311a 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java @@ -9,10 +9,10 @@ import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; /** Unary Cast to byte operator ( (byte) x ) */ -public class OperatorCastByte extends OperatorUnary { +public class OperatorCastByte extends OperatorCast { public OperatorCastByte(int precedence) { - super("((byte))", "_byte_", precedence); + super("((byte))", "_byte_", precedence, SymbolType.BYTE); } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java index af76dbff4..111b94b7a 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java @@ -9,10 +9,10 @@ import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; /** Unary Cast to double word operator ( (dword) x ) */ -public class OperatorCastDWord extends OperatorUnary { +public class OperatorCastDWord extends OperatorCast { public OperatorCastDWord(int precedence) { - super("((dword))", "_dword_", precedence); + super("((dword))", "_dword_", precedence, SymbolType.DWORD); } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java index 33215cfdb..142ecc533 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java @@ -10,12 +10,12 @@ import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; /** Unary Cast to a pointer ( type* ) */ -public class OperatorCastPtr extends OperatorUnary { +public class OperatorCastPtr extends OperatorCast { private final SymbolType elementType; public OperatorCastPtr(int precedence, SymbolType elementType) { - super("((" + elementType.toString() + "*))", "_ptr_", precedence); + super("((" + elementType.toString() + "*))", "_ptr_", precedence, new SymbolTypePointer(elementType)); this.elementType = elementType; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java index d81cf7414..9487eae97 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java @@ -8,10 +8,10 @@ import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; /** Unary Cast to signed byte operator ( (signed byte) x ) */ -public class OperatorCastSByte extends OperatorUnary { +public class OperatorCastSByte extends OperatorCast { public OperatorCastSByte(int precedence) { - super("((signed byte))", "_sbyte_", precedence); + super("((signed byte))", "_sbyte_", precedence, SymbolType.SBYTE); } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java index a07c5cd38..6ec765ca7 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java @@ -8,10 +8,10 @@ import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; /** Unary Cast to signed double word operator ( (signed dword) x ) */ -public class OperatorCastSDWord extends OperatorUnary { +public class OperatorCastSDWord extends OperatorCast { public OperatorCastSDWord(int precedence) { - super("((signed dword))", "_sdword_", precedence); + super("((signed dword))", "_sdword_", precedence, SymbolType.SDWORD); } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java index 094be277d..b8a618979 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java @@ -8,10 +8,10 @@ import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; /** Unary Cast to signed word operator ( (signed word) x ) */ -public class OperatorCastSWord extends OperatorUnary { +public class OperatorCastSWord extends OperatorCast { public OperatorCastSWord(int precedence) { - super("((signed word))", "_sword_", precedence); + super("((signed word))", "_sword_", precedence, SymbolType.SWORD); } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java index f84aec9f0..0b1097086 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java @@ -9,10 +9,10 @@ import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; /** Unary Cast to word operator ( (word) x ) */ -public class OperatorCastWord extends OperatorUnary { +public class OperatorCastWord extends OperatorCast { public OperatorCastWord(int precedence) { - super("((word))", "_word_", precedence); + super("((word))", "_word_", precedence, SymbolType.WORD); } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java index 2a4058f16..3ce383230 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java @@ -38,7 +38,7 @@ public class OperatorDivide extends OperatorBinary { } // Handle numeric types through proper promotion if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { - return SymbolType.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right); + return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right); } throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java index c06f6b938..ce472ffd7 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java @@ -38,7 +38,7 @@ public class OperatorMinus extends OperatorBinary { } // Handle numeric types through proper promotion if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { - return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); + return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); } throw new RuntimeException("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java index 2931f6db1..4fc0a3388 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java @@ -27,7 +27,7 @@ public class OperatorModulo extends OperatorBinary { public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { // Handle numeric types through proper promotion if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { - return SymbolType.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); + return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); } if(left instanceof ConstantPointer && right instanceof ConstantInteger) { return ((ConstantInteger) right).getType(); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java index 7c3894bb5..76bb36ec6 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java @@ -1,10 +1,7 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; -import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; +import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -27,7 +24,7 @@ public class OperatorMultiply extends OperatorBinary { public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { // Handle numeric types through proper promotion if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { - return SymbolType.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); + return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); } throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java index f4f6e0ec7..00844a779 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java @@ -46,7 +46,7 @@ public class OperatorPlus extends OperatorBinary { } // Handle numeric types through proper promotion if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { - return SymbolType.convertedMathType( (SymbolTypeInteger) type1, (SymbolTypeInteger)type2); + return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) type1, (SymbolTypeInteger)type2); } throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java index d50decce2..173ab0e8c 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java @@ -159,4 +159,5 @@ public class Operators { } } + } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java index 685017e26..2d6c20a6b 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java @@ -1,10 +1,5 @@ package dk.camelot64.kickc.model.types; -import dk.camelot64.kickc.model.CompileError; - -import java.util.ArrayList; -import java.util.Collection; - /** Symbol Types */ public interface SymbolType { @@ -91,6 +86,8 @@ public interface SymbolType { return BOOLEAN; case "void": return VOID; + case "number": + return NUMBER; } return null; } @@ -105,7 +102,7 @@ public interface SymbolType { /** * Get the size of the type (in bytes). - * @return The size + * @return The size. -1 if the type is compile-time only. */ int getSizeBytes(); @@ -215,74 +212,4 @@ public interface SymbolType { return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type); } - /** - * Get all integer types. - * - * @return All integeer types - */ - static Collection<SymbolTypeIntegerFixed> getIntegerFixedTypes() { - ArrayList<SymbolTypeIntegerFixed> types = new ArrayList<>(); - types.add(BYTE); - types.add(SBYTE); - types.add(WORD); - types.add(SWORD); - types.add(DWORD); - types.add(SDWORD); - return types; - } - - /** - * Find the integer type that results from a binary operator according to C99 6.3.1.8 - * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70 - * - * @param type1 Left type in a binary expression - * @param type2 Right type in a binary expression - * @return The type resulting from a binary operator performed on the two parameters - */ - static SymbolType convertedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) { - if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) { - return NUMBER; - } - SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1; - SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2; - // C99 6.3.1.8 a. If two operands have the same type no conversion is performed - if(type1.equals(type2)) - return type1; - // C99 6.3.1.8 b. If both are signed or both are unsigned then the smallest type is converted to the size of the large type (byte->word->sword, sbyte->sword->sdword) - if(fixed1.isSigned()==fixed2.isSigned()) - return (fixed1.getBits()>fixed2.getBits()) ? fixed1 : fixed2; - // C99 6.3.1.8 c. One is signed and one unsigned. - // If the signed type can contain all values of the unsigned type then the unsigned value is converted to the signed type. (byte->sword, byte->sdword, word->sdword). - SymbolTypeIntegerFixed typeS, typeU; - if(fixed1.isSigned()) { - typeS = fixed1; - typeU = fixed2; - } else { - typeS = fixed2; - typeU = fixed1; - } - if(typeS.getBits()>typeU.getBits()) - return typeS; - // C99 6.3.1.8 d. The unsigned type is the same size as or larger than the signed type. - // The signed value is first converted to the size of the unsigned type and then converted to unsigned changing the sign and the value - // (sbyte->byte, sbyte->word, sbyte->dword, sword->word, sword->dword, sdword->dword). - return typeU; - } - - /** - * Find the unsigned integer type that contains both sub-types usable for binary operations ( & | ^ ). - * - * @param type1 Left type in a binary expression - * @param type2 Right type in a binary expression - * @return - */ - static SymbolType promotedBitwiseType(SymbolTypeIntegerFixed type1, SymbolTypeIntegerFixed type2) { - for(SymbolTypeIntegerFixed candidate : getIntegerFixedTypes()) { - if(!candidate.isSigned() && type1.getBits()<=candidate.getBits() && type2.getBits()<=candidate.getBits()) { - return candidate; - } - } - throw new CompileError("Cannot promote to a common type for "+type1.toString()+" and "+type2.toString()); - } - } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java new file mode 100644 index 000000000..7b93fa1de --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -0,0 +1,134 @@ +package dk.camelot64.kickc.model.types; + +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.InternalError; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.symbols.ProgramScope; +import dk.camelot64.kickc.model.values.ConstantInteger; +import dk.camelot64.kickc.model.values.ConstantLiteral; +import dk.camelot64.kickc.model.values.ConstantValue; +import dk.camelot64.kickc.model.values.RValue; + +/** + * Rules for converting integer types. + * + * Integer conversion implements C99 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70 + * + * The special number type is converted as described here https://gitlab.com/camelot/kickc/issues/181 + * + */ +public class SymbolTypeConversion { + + /** + * Find the integer type that results from a binary operator according to C99 6.3.1.8 + * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70 + * + * @param type1 Left type in a binary expression + * @param type2 Right type in a binary expression + * @return The type resulting from a binary operator performed on the two parameters + */ + public static SymbolType convertedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) { + if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) { + return SymbolType.NUMBER; + } + SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1; + SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2; + // C99 6.3.1.8 a. If two operands have the same type no conversion is performed + if(type1.equals(type2)) + return type1; + // C99 6.3.1.8 b. If both are signed or both are unsigned then the smallest type is converted to the size of the large type (byte->word->sword, sbyte->sword->sdword) + if(fixed1.isSigned()==fixed2.isSigned()) + return (fixed1.getBits()>fixed2.getBits()) ? fixed1 : fixed2; + // C99 6.3.1.8 c. One is signed and one unsigned. + // If the signed type can contain all values of the unsigned type then the unsigned value is converted to the signed type. (byte->sword, byte->sdword, word->sdword). + SymbolTypeIntegerFixed typeS, typeU; + if(fixed1.isSigned()) { + typeS = fixed1; + typeU = fixed2; + } else { + typeS = fixed2; + typeU = fixed1; + } + if(typeS.getBits()>typeU.getBits()) + return typeS; + // C99 6.3.1.8 d. The unsigned type is the same size as or larger than the signed type. + // The signed value is first converted to the size of the unsigned type and then converted to unsigned changing the sign and the value + // (sbyte->byte, sbyte->word, sbyte->dword, sword->word, sword->dword, sdword->dword). + return typeU; + } + + /** + * Find the integer type that results from a binary operator according to the special number type conversion https://gitlab.com/camelot/kickc/issues/181 + * @param left The left value + * @param right The right value + * @param symbols The program scope symbols (used for looking up symbols and constants) + * @param currentStmt The current statement (used only for exception context) + * @return a non-null fixed integer type if a number type conversion is relevant. + */ + public static SymbolType convertedNumberType(RValue left, RValue right, ProgramScope symbols, Statement currentStmt) { + + SymbolType leftType = SymbolTypeInference.inferType(symbols, left); + SymbolType rightType = SymbolTypeInference.inferType(symbols, right); + + if(SymbolType.NUMBER.equals(leftType) || SymbolType.NUMBER.equals(rightType)) { + // A special type number is assigned to integer constants without a postfix literal. + // Numbers are flexible and will take a type based on their actual value when they meet a typed number in a calculation. + // Number types are only usable at compile time. + + if(leftType.equals(rightType)) { + // a) If the two operands are numbers the result is a number + return null; + } + + RValue numberVal; + SymbolTypeIntegerFixed fixedType; + if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) { + // Left is the number type - right is the fixed type + numberVal = left; + fixedType = (SymbolTypeIntegerFixed) rightType; + } else if(SymbolType.NUMBER.equals(rightType) && SymbolType.isInteger(leftType)) { + // Right is the number type - left is the fixed type + numberVal = right; + fixedType = (SymbolTypeIntegerFixed) leftType; + } else { + // Binary operator combining number and non-integer + throw new CompileError("Error! Incompatible operands " + left.toString() + " and " + right.toString(), currentStmt); + } + + if(numberVal instanceof ConstantValue) { + ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols); + if(constantLiteral instanceof ConstantInteger) { + ConstantInteger constantInteger = (ConstantInteger) constantLiteral; + if(SymbolType.NUMBER.equals(constantInteger.getType())) { + Long value = constantInteger.getValue(); + if(fixedType.isSigned()) { + // b) If one operand is a signed type and the other a number they are both converted to the smallest signed type that can hold the values. + SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value); + if(smallestSignedType == null) { + throw new CompileError("Number constant has value that cannot be represented by a signed type " + value, currentStmt); + } + return smallestSignedType.getBits() > fixedType.getBits() ? smallestSignedType : fixedType; + } else { + // c) If one operand is an unsigned type and the other a number they are both converted to the smallest unsigned type that can hold the values. + // If the number value is negative it is converted to unsigned using two's complement. + SymbolTypeIntegerFixed smallestUnsignedType; + if(value < 0) { + smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(-value); + } else { + smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value); + } + return smallestUnsignedType.getBits() > fixedType.getBits() ? smallestUnsignedType : fixedType; + } + } else { + throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt); + } + } + } else { + // Postpone til later! + return null; + } + } + // No number conversion + return null; + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java index 1c6a35cc5..42f4a2659 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java @@ -1,5 +1,8 @@ package dk.camelot64.kickc.model.types; +import java.util.ArrayList; +import java.util.Collection; + /** Integer type with a fixed size (byte, signed byte, word, ...). */ public class SymbolTypeIntegerFixed implements SymbolTypeInteger { @@ -17,6 +20,58 @@ public class SymbolTypeIntegerFixed implements SymbolTypeInteger { this.bits = bits; } + /** + * Get all fixed size integer types. + * + * @return All fixed size integer types + */ + public static Collection<SymbolTypeIntegerFixed> getIntegerFixedTypes() { + ArrayList<SymbolTypeIntegerFixed> types = new ArrayList<>(); + types.add(BYTE); + types.add(SBYTE); + types.add(WORD); + types.add(SWORD); + types.add(DWORD); + types.add(SDWORD); + return types; + } + /** + * Find the smallest signed type that can hold the passed value + * @param value The value + * @return The smallest signed type that can hold the value + */ + public static SymbolTypeIntegerFixed getSmallestSigned(Long value) { + for(SymbolTypeIntegerFixed fixedType : getIntegerFixedTypes()) { + if(fixedType.isSigned() && fixedType.contains(value)) + return fixedType; + } + return null; + } + + /** + * Find the smallest unsigned type that can hold the passed value + * @param value The value + * @return The smallest unsigned type that can hold the value + */ + public static SymbolTypeIntegerFixed getSmallestUnsigned(Long value) { + for(SymbolTypeIntegerFixed fixedType : getIntegerFixedTypes()) { + if(!fixedType.isSigned() && fixedType.contains(value)) + return fixedType; + } + return null; + } + + + /** + * Determines if a value can be represented by the type without loss of information + * + * @param value The value to examine + * @return true if the type contains the value + */ + public boolean contains(Long number) { + return number >= getMinValue() && number <= getMaxValue(); + } + @Override public String getTypeName() { return typeName; diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java index ced732cb9..f3438573e 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java @@ -26,22 +26,6 @@ public class SymbolTypeMulti implements SymbolType { return types; } - - /** - * Get the multi-type that can contain the passed number. - * @param number The number - * @return The multi-type - */ - public static SymbolType getMultiType(Long number) { - ArrayList<SymbolType> potentialTypes = new ArrayList<>(); - for(SymbolTypeIntegerFixed typeInteger : SymbolType.getIntegerFixedTypes()) { - if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) { - potentialTypes.add(typeInteger); - } - } - return new SymbolTypeMulti(potentialTypes); - } - @Override public int getSizeBytes() { // Find the minimal sizeof - and return that diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java index 7473e4230..4967f0bfa 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java @@ -90,8 +90,8 @@ public class SymbolTypeNumberInference { ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>(); ConstantInteger constantInteger = (ConstantInteger) literal; Long number = constantInteger.getValue(); - for(SymbolTypeIntegerFixed typeInteger : SymbolType.getIntegerFixedTypes()) { - if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) { + for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) { + if(typeInteger.contains(number)) { potentialTypes.add(typeInteger); } } diff --git a/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java b/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java index 6222c6fd2..36cb5d6ea 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java +++ b/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java @@ -3,7 +3,7 @@ package dk.camelot64.kickc.model.values; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.StatementAssignment; -/** The "total" RValue of an assigment. */ +/** The "total" RValue of an assignment. */ public class AssignmentRValue implements RValue { private StatementAssignment assignment; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java index db834cb48..b1f4777da 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java @@ -96,7 +96,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base { programValue.set(version.getRef()); } // Update map of versions encountered in the block - if(currentStmt instanceof StatementAssignment && programValue instanceof ProgramValue.LValue) { + if(currentStmt instanceof StatementAssignment && programValue instanceof ProgramValue.ProgramValueLValue) { StatementAssignment assignment = (StatementAssignment) currentStmt; LValue lValue = assignment.getlValue(); if(lValue instanceof VariableRef) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java new file mode 100644 index 000000000..a40c02fd0 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java @@ -0,0 +1,43 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramExpression; +import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; +import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary; +import dk.camelot64.kickc.model.operators.OperatorCast; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.ConstantInteger; +import dk.camelot64.kickc.model.values.ConstantValue; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** Simplifies casts of (number) constants to a type. */ +public class Pass2ConstantCastSimplification extends Pass2SsaOptimization { + + public Pass2ConstantCastSimplification(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean optimized = new AtomicBoolean(false); + ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> { + if(programExpression.getOperator() instanceof OperatorCast) { + OperatorCast operatorCast = (OperatorCast) programExpression.getOperator(); + ProgramExpressionUnary unary = (ProgramExpressionUnary) programExpression; + if(unary.getOperand() instanceof ConstantInteger) { + ConstantInteger constantInteger = (ConstantInteger) unary.getOperand(); + if(constantInteger.getType().equals(SymbolType.NUMBER)) { + SymbolType castType = operatorCast.getToType(); + ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); + programExpression.set(newConstInt); + getLog().append("Simplifying constant integer cast "+newConstInt); + } + } + } + }); + return optimized.get(); + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java index b12ad19ca..39d15dc0c 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java @@ -1,15 +1,11 @@ package dk.camelot64.kickc.passes; -import dk.camelot64.kickc.model.CompileError; -import dk.camelot64.kickc.model.InternalError; import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.iterator.BinaryExpressionIterator; +import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; +import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeConversion; import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; -import dk.camelot64.kickc.model.values.ConstantInteger; -import dk.camelot64.kickc.model.values.ConstantLiteral; -import dk.camelot64.kickc.model.values.ConstantValue; import dk.camelot64.kickc.model.values.RValue; /** @@ -23,89 +19,29 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization { @Override public boolean step() { - BinaryExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> { - RValue left = binaryExpression.getLeft(); - RValue right = binaryExpression.getRight(); - SymbolType conversionType = getNumberConversionType(left, right); - if(conversionType != null) { - // Convert both left and right to the found type - - getLog().append("Adding number conversion cast (" + fixedType+ ") " + binaryExpression.getRight().toString() + " in " + currentStmt.toString(getProgram(), false)); - - + ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> { + if(binaryExpression instanceof ProgramExpressionBinary) { + ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression; + RValue left = binary.getLeft(); + RValue right = binary.getRight(); + SymbolType conversionType = SymbolTypeConversion.convertedNumberType(left, right, getScope(), currentStmt); + if(conversionType != null) { + // Convert both left and right to the found type + SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left); + if(!leftType.equals(conversionType)) { + getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false)); + binary.addLeftCast(conversionType, stmtIt, currentBlock.getScope(), getScope()); + } + SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right); + if(!rightType.equals(conversionType)) { + getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false)); + binary.addRightCast(conversionType, stmtIt, currentBlock.getScope(), getScope()); + } + } } - }); return false; } - private SymbolType getNumberConversionType(RValue left, RValue right) { - - SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left); - SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right); - - if(SymbolType.NUMBER.equals(leftType) || SymbolType.NUMBER.equals(rightType)) { - // A special type number is assigned to integer constants without a postfix literal. - // Numbers are flexible and will take a type based on their actual value when they meet a typed number in a calculation. - // Number types are only usable at compile time. - - if(leftType.equals(rightType)) { - // a) If the two operands are numbers the result is a number - return null; - } - - RValue numberVal; - SymbolTypeIntegerFixed fixedType; - if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) { - // Left is the number - numberVal = left; - fixedType = (SymbolTypeIntegerFixed) rightType; - } else if(SymbolType.NUMBER.equals(rightType) && SymbolType.isInteger(leftType)) { - // Right is the number - numberVal = right; - fixedType = (SymbolTypeIntegerFixed) leftType; - } else { - // Non-integer number binary - throw new CompileError("Error! Incompatible operands "+left.toString()+" and "+right.toString()); - } - - if(numberVal instanceof ConstantValue) { - ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(getProgram().getScope()); - if(constantLiteral instanceof ConstantInteger) { - ConstantInteger constantInteger = (ConstantInteger) constantLiteral; - if(SymbolType.NUMBER.equals(constantInteger.getType())) { - Long value = constantInteger.getValue(); - if(fixedType.getMinValue() <= value && fixedType.getMaxValue() >= value) { - // The value matches the left type! - binaryExpression.addRightCast(leftIntType); - } else { - throw new InternalError("TODO: Implement number conversion for non-equal types " + right.toString(), currentStmt); - } - } else { - throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt); - } - } - } else { - // Postpone til later! - // Maybe handle AssignmentRValue separately! - getLog().append("Postponed number conversion " + right.toString()); - } - - - - - } - - // No number conversion - return null; - - if(SymbolType.isInteger(leftType) && !SymbolType.NUMBER.equals(leftType) && SymbolType.NUMBER.equals(rightType)) { - SymbolTypeIntegerFixed leftIntType = (SymbolTypeIntegerFixed) leftType; - // Attempt to find number conversion! - } - - return null; - } - } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java deleted file mode 100644 index 562d251f0..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java +++ /dev/null @@ -1,143 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.Comment; -import dk.camelot64.kickc.model.CompileError; -import dk.camelot64.kickc.model.ControlFlowBlock; -import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.operators.Operators; -import dk.camelot64.kickc.model.statements.Statement; -import dk.camelot64.kickc.model.statements.StatementAssignment; -import dk.camelot64.kickc.model.symbols.Scope; -import dk.camelot64.kickc.model.symbols.VariableIntermediate; -import dk.camelot64.kickc.model.types.*; -import dk.camelot64.kickc.model.values.ConstantInteger; -import dk.camelot64.kickc.model.values.LValue; -import dk.camelot64.kickc.model.values.RValue; -import dk.camelot64.kickc.model.values.ScopeRef; - -import java.util.List; -import java.util.ListIterator; - -/** - * Add casts in all assignments where types are not equal, but the rValue type can be converted to the lValue type. - */ -public class PassNAddTypeConversions extends Pass2SsaOptimization { - - public PassNAddTypeConversions(Program program) { - super(program); - } - - @Override - public boolean step() { - for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { - List<Statement> statements = block.getStatements(); - ListIterator<Statement> stmtIt = statements.listIterator(); - while(stmtIt.hasNext()) { - Statement statement = stmtIt.next(); - if(statement instanceof StatementAssignment) { - doConversionAssignment((StatementAssignment) statement, stmtIt, block); - } - // TODO: Implement conversion for calls - } - } - return false; - } - - /** - * Examines an assignment to determine if a cast of the rValue is needed (the lvalue type and the rvalue type is not equal) - * and possible (the types are conversion compatible). - * <p> - * If a conversion is needed it is added by adding a new tmp-var with a cast and modifying the statement. - * - * @param assignment The assignment to examine - * @param stmtIt Iterator allowing the method to add a tmp-var-assignment. - */ - private void doConversionAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt, ControlFlowBlock block) { - LValue lValue = assignment.getlValue(); - SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue); - SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), assignment); - if(lValueType.equals(rValueType)) { - return; - } - if(SymbolType.NUMBER.equals(rValueType)) { - // If the rValue is number type - find the potential types based on the literal value - List<SymbolTypeIntegerFixed> potentialTypes = SymbolTypeNumberInference.inferTypesRValue(getScope(), assignment); - if(potentialTypes.size()==0) { - // number type cannot be calculated currently - save for later - return; - } - for(SymbolTypeIntegerFixed potentialType : potentialTypes) { - if(lValueType.equals(potentialType) || canConvert(lValueType, potentialType)) { - addConversionCast(assignment, stmtIt, block, lValueType, rValueType); - return; - } - } - } else { - // No direct type match - attempt conversion - if(canConvert(lValueType, rValueType)) { - addConversionCast(assignment, stmtIt, block, lValueType, rValueType); - return; - } - } - - // Conversion not possible - report a type error! - String msg = "ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). " + - "In " + assignment.toString(getProgram(), false); - getProgram().getLog().append(msg); - throw new CompileError(msg, assignment.getSource()); - } - - /** - * Add a conversion cast to the rvalue of an assignment - * - * @param assignment The assignment to add the cast to - * @param lValueType The type of the lValue - * @param rValueType The type of the rValue - */ - private void addConversionCast(StatementAssignment assignment, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, SymbolType lValueType, SymbolType rValueType) { - // Promotion possible - add tmp-var and a cast - if(assignment.getOperator() == null) { - // No operator - add cast directly! - RValue rValue = assignment.getrValue2(); - if((rValue instanceof ConstantInteger) && SymbolType.NUMBER.equals(((ConstantInteger) rValue).getType()) && SymbolType.isInteger(lValueType)) { - ((ConstantInteger) rValue).setType(lValueType); - } else { - assignment.setOperator(Operators.getCastUnary(lValueType)); - } - getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment); - } else { - ScopeRef currentScope = currentBlock.getScope(); - Scope blockScope = getScope().getScope(currentScope); - VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); - tmpVar.setType(rValueType); - StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(lValueType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS); - getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment + " adding "+tmpVar); - assignment.setlValue(tmpVar.getRef()); - stmtIt.add(newAssignment); - } - } - - /** - * Determines if it is possible to convert one type to another - * as described in C99 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70 - * - * @param lValueType The type of the lValue - * @param rValueType The type of the rValue (that will be cast) - * @return True if a cast is possible without any loss - */ - private boolean canConvert(SymbolType lValueType, SymbolType rValueType) { - if(lValueType instanceof SymbolTypePointer && SymbolType.isWord(rValueType)) { - return true; - } - if(lValueType instanceof SymbolTypeInteger && rValueType instanceof SymbolTypeInteger) { - SymbolType convertedMathType = SymbolType.convertedMathType((SymbolTypeInteger) lValueType, (SymbolTypeInteger) rValueType); - if(lValueType.equals(convertedMathType)) { - return true; - } - } - // No type promotion found - return false; - } - - -} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java new file mode 100644 index 000000000..fd47ffd3c --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java @@ -0,0 +1,55 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; +import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; +import dk.camelot64.kickc.model.types.*; +import dk.camelot64.kickc.model.values.RValue; + +/** + * Add casts in binary expressions where left/right types are not equal according to the C99 type conversion rules + * 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70. + */ +public class PassNAddTypeConversionsNew extends Pass2SsaOptimization { + + public PassNAddTypeConversionsNew(Program program) { + super(program); + } + + @Override + public boolean step() { + ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> { + if(programExpression instanceof ProgramExpressionBinary) { + ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression; + RValue left = binary.getLeft(); + RValue right = binary.getRight(); + SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left); + SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right); + + // Special handling of assigning a pointer from an unsigned word + if((programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue) && (leftType instanceof SymbolTypePointer) && SymbolType.isInteger(rightType)) { + getLog().append("Adding pointer type conversion cast (" + leftType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false)); + binary.addLeftCast(leftType, stmtIt, currentBlock.getScope(), getScope()); + } + + if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) { + SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType); + if(conversionType != null && !SymbolType.NUMBER.equals(conversionType)) { + // Convert both left and right to the found type + if(!leftType.equals(conversionType)) { + getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false)); + binary.addLeftCast(conversionType, stmtIt, currentBlock.getScope(), getScope()); + } + if(!rightType.equals(conversionType)) { + getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false)); + binary.addRightCast(conversionType, stmtIt, currentBlock.getScope(), getScope()); + } + } + } + } + }); + return false; + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java similarity index 52% rename from src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java rename to src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java index a1ffcf01a..43d47670d 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java @@ -1,50 +1,63 @@ package dk.camelot64.kickc.passes; -import dk.camelot64.kickc.model.ControlFlowBlock; -import dk.camelot64.kickc.model.InternalError; import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; +import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary; import dk.camelot64.kickc.model.operators.OperatorTypeId; import dk.camelot64.kickc.model.operators.Operators; -import dk.camelot64.kickc.model.statements.Statement; -import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; -import dk.camelot64.kickc.model.types.SymbolTypeNumberInference; -import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantRef; -import dk.camelot64.kickc.model.values.ConstantValue; import dk.camelot64.kickc.model.values.RValue; -import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; /** * Converts typeid() operators to constants */ -public class Pass1TypeIdSimplification extends Pass1Base { +public class PassNTypeIdSimplification extends Pass2SsaOptimization { - public Pass1TypeIdSimplification(Program program) { + public PassNTypeIdSimplification(Program program) { super(program); } @Override public boolean step() { - boolean modified = false; + AtomicBoolean modified = new AtomicBoolean(false); + ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> { + if(programExpression instanceof ProgramExpressionUnary) { + ProgramExpressionUnary unary = (ProgramExpressionUnary) programExpression; + if(Operators.TYPEID.equals(unary.getOperator())) { + RValue rValue = unary.getOperand(); + SymbolType symbolType = SymbolTypeInference.inferType(getScope(), rValue); + if(symbolType.equals(SymbolType.VAR) || symbolType.equals(SymbolType.NUMBER)) { + + } else { + getLog().append("Resolving typeid() " + currentStmt.toString(getProgram(), false)); + ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getScope(), symbolType); + unary.set(typeIDConstantVar); + modified.set(true); + } + } + } + }); + + /* for(ControlFlowBlock block : getGraph().getAllBlocks()) { for(Statement statement : block.getStatements()) { if(statement instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) statement; if(Operators.TYPEID.equals(assignment.getOperator())) { RValue rValue = assignment.getrValue2(); - SymbolType symbolType = SymbolTypeInference.inferType(getScope(), rValue); + SymbolType symbolType = SymbolTypeInference.inferType(getSymbols(), rValue); if(SymbolType.NUMBER.equals(symbolType)) { if(rValue instanceof ConstantValue) { - List<SymbolTypeIntegerFixed> fixedTypes = SymbolTypeNumberInference.inferTypes(getScope(), (ConstantLiteral) rValue); + List<SymbolTypeIntegerFixed> fixedTypes = SymbolTypeNumberInference.inferTypes(getSymbols(), (ConstantLiteral) rValue); throw new InternalError("TODO: Implement typeof(const)!"); } } else { getLog().append("Resolving typeid() " + assignment.toString(getProgram(), false)); - ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getScope(), symbolType); + ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getSymbols(), symbolType); assignment.setrValue2(typeIDConstantVar); assignment.setOperator(null); modified = true; @@ -53,6 +66,7 @@ public class Pass1TypeIdSimplification extends Pass1Base { } } } - return modified; + */ + return modified.get(); } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 95b07f371..b77d09e82 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -34,12 +34,12 @@ public class TestPrograms { @Test public void testNumberConversion() throws IOException, URISyntaxException { - compileAndCompare("number-conversion", log()); + compileAndCompare("number-conversion"); } @Test public void testNumberType() throws IOException, URISyntaxException { - compileAndCompare("number-type"); + compileAndCompare("number-type", log()); } @Test diff --git a/src/test/kc/number-conversion.kc b/src/test/kc/number-conversion.kc index 6d7a7b833..67ee702f6 100644 --- a/src/test/kc/number-conversion.kc +++ b/src/test/kc/number-conversion.kc @@ -10,15 +10,13 @@ void main() { idx = 0ub; assertType(typeid(12sb+12), typeid(signed byte)); assertType(typeid(12sb+130), typeid(signed word)); - assertType(typeid(12sb+32000), typeid(signed dword)); + assertType(typeid(12sb+33000), typeid(signed dword)); assertType(typeid(12sw+12), typeid(signed word)); assertType(typeid(12sw+130), typeid(signed word)); assertType(typeid(12sw+100000), typeid(signed dword)); assertType(typeid(12sd+12), typeid(signed dword)); assertType(typeid(12sd+130), typeid(signed dword)); assertType(typeid(12sd+100000), typeid(signed dword)); - // Test number larger than largest signed type - assertType(typeid(12sb+3000000000), typeid(unsigned dword)); // Unsigned type and positive number // b) If one operand is an unsigned type and the other a positive number. @@ -36,7 +34,7 @@ void main() { assertType(typeid(12ud+12), typeid(unsigned dword)); assertType(typeid(12ud+130), typeid(unsigned dword)); assertType(typeid(12ud+66000), typeid(unsigned dword)); - assertType(typeid(12sb+3000000000), typeid(unsigned dword)); + assertType(typeid(12ub+3000000000), typeid(unsigned dword)); // Unsigned type and negative number // If one operand is an unsigned type and the other a negative number. @@ -47,16 +45,19 @@ void main() { idx = 80ub; assertType(typeid(12ub+-12), typeid(unsigned byte)); assertType(typeid(12ub+-120), typeid(unsigned byte)); - assertType(typeid(12ub+-250), typeid(unsigned word)); - assertType(typeid(12ub+-32000), typeid(unsigned dword)); + assertType(typeid(12ub+-250), typeid(unsigned byte)); + assertType(typeid(12ub+-260), typeid(unsigned word)); + assertType(typeid(12ub+-65000), typeid(unsigned word)); assertType(typeid(12ub+-66000), typeid(unsigned dword)); assertType(typeid(12uw+-12), typeid(unsigned word)); assertType(typeid(12uw+-130), typeid(unsigned word)); - assertType(typeid(12uw+-32000), typeid(unsigned dword)); + assertType(typeid(12uw+-65000), typeid(unsigned word)); + assertType(typeid(12uw+-66000), typeid(unsigned dword)); assertType(typeid(12ud+-12), typeid(unsigned dword)); assertType(typeid(12ud+-130), typeid(unsigned dword)); assertType(typeid(12ud+-66000), typeid(unsigned dword)); - assertType(typeid(12sb+-3000000000), typeid(unsigned dword)); + assertType(typeid(12sb+-2100000000), typeid(unsigned dword)); + } diff --git a/src/test/ref/int-conversion.asm b/src/test/ref/int-conversion.asm new file mode 100644 index 000000000..9ad08351c --- /dev/null +++ b/src/test/ref/int-conversion.asm @@ -0,0 +1,242 @@ +// Tests different integer literal types +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const TYPEID_BYTE = 1 + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_WORD = 3 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_DWORD = 5 + .const TYPEID_SIGNED_DWORD = 6 + .const RED = 2 + .const GREEN = 5 + .label SCREEN = $400 + .label COLS = $d800 +main: { + .label s = 2 + lda #<SCREEN + sta s + lda #>SCREEN + sta s+1 + b1: + lda #' ' + ldy #0 + sta (s),y + inc s + bne !+ + inc s+1 + !: + lda s+1 + cmp #>SCREEN+$3e8 + bcc b1 + bne !+ + lda s + cmp #<SCREEN+$3e8 + bcc b1 + !: + jsr testUnaryOperator + jsr testBinaryOperator + rts +} +testBinaryOperator: { + ldx #$28 + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + inx + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + inx + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + ldx #$50 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + inx + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + inx + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + rts +} +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte register(Y) t1, byte zeropage(4) t2) +assertType: { + .label t2 = 4 + tya + cmp t2 + beq b1 + lda #RED + sta COLS,x + b2: + tya + sta SCREEN,x + inx + rts + b1: + lda #GREEN + sta COLS,x + jmp b2 +} +testUnaryOperator: { + ldx #0 + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + rts +} diff --git a/src/test/ref/int-conversion.cfg b/src/test/ref/int-conversion.cfg new file mode 100644 index 000000000..a3454c904 --- /dev/null +++ b/src/test/ref/int-conversion.cfg @@ -0,0 +1,222 @@ +@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::@1 + [5] (byte*) main::s#2 ← phi( main/(const byte*) SCREEN#0 main::@1/(byte*) main::s#1 ) + [6] *((byte*) main::s#2) ← (byte) ' ' + [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 + [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] phi() + [10] call testUnaryOperator + to:main::@3 +main::@3: scope:[main] from main::@2 + [11] phi() + [12] call testBinaryOperator + to:main::@return +main::@return: scope:[main] from main::@3 + [13] return + to:@return +testBinaryOperator: scope:[testBinaryOperator] from main::@3 + [14] phi() + [15] call assertType + to:testBinaryOperator::@1 +testBinaryOperator::@1: scope:[testBinaryOperator] from testBinaryOperator + [16] phi() + [17] call assertType + to:testBinaryOperator::@2 +testBinaryOperator::@2: scope:[testBinaryOperator] from testBinaryOperator::@1 + [18] phi() + [19] call assertType + to:testBinaryOperator::@3 +testBinaryOperator::@3: scope:[testBinaryOperator] from testBinaryOperator::@2 + [20] phi() + [21] call assertType + to:testBinaryOperator::@4 +testBinaryOperator::@4: scope:[testBinaryOperator] from testBinaryOperator::@3 + [22] phi() + [23] call assertType + to:testBinaryOperator::@5 +testBinaryOperator::@5: scope:[testBinaryOperator] from testBinaryOperator::@4 + [24] phi() + [25] call assertType + to:testBinaryOperator::@6 +testBinaryOperator::@6: scope:[testBinaryOperator] from testBinaryOperator::@5 + [26] (byte) idx#19 ← ++ (byte) idx#108 + [27] call assertType + to:testBinaryOperator::@7 +testBinaryOperator::@7: scope:[testBinaryOperator] from testBinaryOperator::@6 + [28] phi() + [29] call assertType + to:testBinaryOperator::@8 +testBinaryOperator::@8: scope:[testBinaryOperator] from testBinaryOperator::@7 + [30] phi() + [31] call assertType + to:testBinaryOperator::@9 +testBinaryOperator::@9: scope:[testBinaryOperator] from testBinaryOperator::@8 + [32] phi() + [33] call assertType + to:testBinaryOperator::@10 +testBinaryOperator::@10: scope:[testBinaryOperator] from testBinaryOperator::@9 + [34] phi() + [35] call assertType + to:testBinaryOperator::@11 +testBinaryOperator::@11: scope:[testBinaryOperator] from testBinaryOperator::@10 + [36] phi() + [37] call assertType + to:testBinaryOperator::@12 +testBinaryOperator::@12: scope:[testBinaryOperator] from testBinaryOperator::@11 + [38] (byte) idx#26 ← ++ (byte) idx#108 + [39] call assertType + to:testBinaryOperator::@13 +testBinaryOperator::@13: scope:[testBinaryOperator] from testBinaryOperator::@12 + [40] phi() + [41] call assertType + to:testBinaryOperator::@14 +testBinaryOperator::@14: scope:[testBinaryOperator] from testBinaryOperator::@13 + [42] phi() + [43] call assertType + to:testBinaryOperator::@15 +testBinaryOperator::@15: scope:[testBinaryOperator] from testBinaryOperator::@14 + [44] phi() + [45] call assertType + to:testBinaryOperator::@16 +testBinaryOperator::@16: scope:[testBinaryOperator] from testBinaryOperator::@15 + [46] phi() + [47] call assertType + to:testBinaryOperator::@17 +testBinaryOperator::@17: scope:[testBinaryOperator] from testBinaryOperator::@16 + [48] phi() + [49] call assertType + to:testBinaryOperator::@18 +testBinaryOperator::@18: scope:[testBinaryOperator] from testBinaryOperator::@17 + [50] phi() + [51] call assertType + to:testBinaryOperator::@19 +testBinaryOperator::@19: scope:[testBinaryOperator] from testBinaryOperator::@18 + [52] phi() + [53] call assertType + to:testBinaryOperator::@20 +testBinaryOperator::@20: scope:[testBinaryOperator] from testBinaryOperator::@19 + [54] phi() + [55] call assertType + to:testBinaryOperator::@21 +testBinaryOperator::@21: scope:[testBinaryOperator] from testBinaryOperator::@20 + [56] phi() + [57] call assertType + to:testBinaryOperator::@22 +testBinaryOperator::@22: scope:[testBinaryOperator] from testBinaryOperator::@21 + [58] phi() + [59] call assertType + to:testBinaryOperator::@23 +testBinaryOperator::@23: scope:[testBinaryOperator] from testBinaryOperator::@22 + [60] phi() + [61] call assertType + to:testBinaryOperator::@24 +testBinaryOperator::@24: scope:[testBinaryOperator] from testBinaryOperator::@23 + [62] (byte) idx#40 ← ++ (byte) idx#108 + [63] call assertType + to:testBinaryOperator::@25 +testBinaryOperator::@25: scope:[testBinaryOperator] from testBinaryOperator::@24 + [64] phi() + [65] call assertType + to:testBinaryOperator::@26 +testBinaryOperator::@26: scope:[testBinaryOperator] from testBinaryOperator::@25 + [66] phi() + [67] call assertType + to:testBinaryOperator::@27 +testBinaryOperator::@27: scope:[testBinaryOperator] from testBinaryOperator::@26 + [68] phi() + [69] call assertType + to:testBinaryOperator::@28 +testBinaryOperator::@28: scope:[testBinaryOperator] from testBinaryOperator::@27 + [70] phi() + [71] call assertType + to:testBinaryOperator::@29 +testBinaryOperator::@29: scope:[testBinaryOperator] from testBinaryOperator::@28 + [72] phi() + [73] call assertType + to:testBinaryOperator::@30 +testBinaryOperator::@30: scope:[testBinaryOperator] from testBinaryOperator::@29 + [74] (byte) idx#47 ← ++ (byte) idx#108 + [75] call assertType + to:testBinaryOperator::@31 +testBinaryOperator::@31: scope:[testBinaryOperator] from testBinaryOperator::@30 + [76] phi() + [77] call assertType + to:testBinaryOperator::@32 +testBinaryOperator::@32: scope:[testBinaryOperator] from testBinaryOperator::@31 + [78] phi() + [79] call assertType + to:testBinaryOperator::@33 +testBinaryOperator::@33: scope:[testBinaryOperator] from testBinaryOperator::@32 + [80] phi() + [81] call assertType + to:testBinaryOperator::@34 +testBinaryOperator::@34: scope:[testBinaryOperator] from testBinaryOperator::@33 + [82] phi() + [83] call assertType + to:testBinaryOperator::@35 +testBinaryOperator::@35: scope:[testBinaryOperator] from testBinaryOperator::@34 + [84] phi() + [85] call assertType + to:testBinaryOperator::@return +testBinaryOperator::@return: scope:[testBinaryOperator] from testBinaryOperator::@35 + [86] return + to:@return +assertType: scope:[assertType] from testBinaryOperator testBinaryOperator::@1 testBinaryOperator::@10 testBinaryOperator::@11 testBinaryOperator::@12 testBinaryOperator::@13 testBinaryOperator::@14 testBinaryOperator::@15 testBinaryOperator::@16 testBinaryOperator::@17 testBinaryOperator::@18 testBinaryOperator::@19 testBinaryOperator::@2 testBinaryOperator::@20 testBinaryOperator::@21 testBinaryOperator::@22 testBinaryOperator::@23 testBinaryOperator::@24 testBinaryOperator::@25 testBinaryOperator::@26 testBinaryOperator::@27 testBinaryOperator::@28 testBinaryOperator::@29 testBinaryOperator::@3 testBinaryOperator::@30 testBinaryOperator::@31 testBinaryOperator::@32 testBinaryOperator::@33 testBinaryOperator::@34 testBinaryOperator::@35 testBinaryOperator::@4 testBinaryOperator::@5 testBinaryOperator::@6 testBinaryOperator::@7 testBinaryOperator::@8 testBinaryOperator::@9 testUnaryOperator testUnaryOperator::@1 testUnaryOperator::@2 testUnaryOperator::@3 testUnaryOperator::@4 testUnaryOperator::@5 + [87] (byte) idx#105 ← phi( testBinaryOperator/(byte) $28 testBinaryOperator::@1/(byte) idx#108 testBinaryOperator::@10/(byte) idx#108 testBinaryOperator::@11/(byte) idx#108 testBinaryOperator::@12/(byte) idx#26 testBinaryOperator::@13/(byte) idx#108 testBinaryOperator::@14/(byte) idx#108 testBinaryOperator::@15/(byte) idx#108 testBinaryOperator::@16/(byte) idx#108 testBinaryOperator::@17/(byte) idx#108 testBinaryOperator::@18/(byte) $50 testBinaryOperator::@19/(byte) idx#108 testBinaryOperator::@2/(byte) idx#108 testBinaryOperator::@20/(byte) idx#108 testBinaryOperator::@21/(byte) idx#108 testBinaryOperator::@22/(byte) idx#108 testBinaryOperator::@23/(byte) idx#108 testBinaryOperator::@24/(byte) idx#40 testBinaryOperator::@25/(byte) idx#108 testBinaryOperator::@26/(byte) idx#108 testBinaryOperator::@27/(byte) idx#108 testBinaryOperator::@28/(byte) idx#108 testBinaryOperator::@29/(byte) idx#108 testBinaryOperator::@3/(byte) idx#108 testBinaryOperator::@30/(byte) idx#47 testBinaryOperator::@31/(byte) idx#108 testBinaryOperator::@32/(byte) idx#108 testBinaryOperator::@33/(byte) idx#108 testBinaryOperator::@34/(byte) idx#108 testBinaryOperator::@35/(byte) idx#108 testBinaryOperator::@4/(byte) idx#108 testBinaryOperator::@5/(byte) idx#108 testBinaryOperator::@6/(byte) idx#19 testBinaryOperator::@7/(byte) idx#108 testBinaryOperator::@8/(byte) idx#108 testBinaryOperator::@9/(byte) idx#108 testUnaryOperator/(byte) 0 testUnaryOperator::@1/(byte) idx#108 testUnaryOperator::@2/(byte) idx#108 testUnaryOperator::@3/(byte) idx#108 testUnaryOperator::@4/(byte) idx#108 testUnaryOperator::@5/(byte) idx#108 ) + [87] (byte) assertType::t2#42 ← phi( testBinaryOperator/(const byte) TYPEID_BYTE testBinaryOperator::@1/(const byte) TYPEID_BYTE testBinaryOperator::@10/(const byte) TYPEID_DWORD testBinaryOperator::@11/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@12/(const byte) TYPEID_WORD testBinaryOperator::@13/(const byte) TYPEID_WORD testBinaryOperator::@14/(const byte) TYPEID_WORD testBinaryOperator::@15/(const byte) TYPEID_WORD testBinaryOperator::@16/(const byte) TYPEID_DWORD testBinaryOperator::@17/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@18/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@19/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@2/(const byte) TYPEID_WORD testBinaryOperator::@20/(const byte) TYPEID_WORD testBinaryOperator::@21/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@22/(const byte) TYPEID_DWORD testBinaryOperator::@23/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@24/(const byte) TYPEID_DWORD testBinaryOperator::@25/(const byte) TYPEID_DWORD testBinaryOperator::@26/(const byte) TYPEID_DWORD testBinaryOperator::@27/(const byte) TYPEID_DWORD testBinaryOperator::@28/(const byte) TYPEID_DWORD testBinaryOperator::@29/(const byte) TYPEID_DWORD testBinaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@30/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@31/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@32/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@33/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@34/(const byte) TYPEID_DWORD testBinaryOperator::@35/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@4/(const byte) TYPEID_DWORD testBinaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@6/(const byte) TYPEID_BYTE testBinaryOperator::@7/(const byte) TYPEID_SIGNED_BYTE testBinaryOperator::@8/(const byte) TYPEID_WORD testBinaryOperator::@9/(const byte) TYPEID_SIGNED_WORD testUnaryOperator/(const byte) TYPEID_BYTE testUnaryOperator::@1/(const byte) TYPEID_SIGNED_BYTE testUnaryOperator::@2/(const byte) TYPEID_WORD testUnaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testUnaryOperator::@4/(const byte) TYPEID_DWORD testUnaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD ) + [87] (byte) assertType::t1#42 ← phi( testBinaryOperator/(const byte) TYPEID_BYTE testBinaryOperator::@1/(const byte) TYPEID_BYTE testBinaryOperator::@10/(const byte) TYPEID_DWORD testBinaryOperator::@11/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@12/(const byte) TYPEID_WORD testBinaryOperator::@13/(const byte) TYPEID_WORD testBinaryOperator::@14/(const byte) TYPEID_WORD testBinaryOperator::@15/(const byte) TYPEID_WORD testBinaryOperator::@16/(const byte) TYPEID_DWORD testBinaryOperator::@17/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@18/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@19/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@2/(const byte) TYPEID_WORD testBinaryOperator::@20/(const byte) TYPEID_WORD testBinaryOperator::@21/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@22/(const byte) TYPEID_DWORD testBinaryOperator::@23/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@24/(const byte) TYPEID_DWORD testBinaryOperator::@25/(const byte) TYPEID_DWORD testBinaryOperator::@26/(const byte) TYPEID_DWORD testBinaryOperator::@27/(const byte) TYPEID_DWORD testBinaryOperator::@28/(const byte) TYPEID_DWORD testBinaryOperator::@29/(const byte) TYPEID_DWORD testBinaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@30/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@31/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@32/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@33/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@34/(const byte) TYPEID_DWORD testBinaryOperator::@35/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@4/(const byte) TYPEID_DWORD testBinaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@6/(const byte) TYPEID_BYTE testBinaryOperator::@7/(const byte) TYPEID_SIGNED_BYTE testBinaryOperator::@8/(const byte) TYPEID_WORD testBinaryOperator::@9/(const byte) TYPEID_SIGNED_WORD testUnaryOperator/(const byte) TYPEID_BYTE testUnaryOperator::@1/(const byte) TYPEID_SIGNED_BYTE testUnaryOperator::@2/(const byte) TYPEID_WORD testUnaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testUnaryOperator::@4/(const byte) TYPEID_DWORD testUnaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD ) + [88] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1 + to:assertType::@3 +assertType::@3: scope:[assertType] from assertType + [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 + to:assertType::@2 +assertType::@2: scope:[assertType] from assertType::@1 assertType::@3 + [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 + [91] (byte) idx#108 ← ++ (byte) idx#105 + to:assertType::@return +assertType::@return: scope:[assertType] from assertType::@2 + [92] return + to:@return +assertType::@1: scope:[assertType] from assertType + [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 + to:assertType::@2 +testUnaryOperator: scope:[testUnaryOperator] from main::@2 + [94] phi() + [95] call assertType + to:testUnaryOperator::@1 +testUnaryOperator::@1: scope:[testUnaryOperator] from testUnaryOperator + [96] phi() + [97] call assertType + to:testUnaryOperator::@2 +testUnaryOperator::@2: scope:[testUnaryOperator] from testUnaryOperator::@1 + [98] phi() + [99] call assertType + to:testUnaryOperator::@3 +testUnaryOperator::@3: scope:[testUnaryOperator] from testUnaryOperator::@2 + [100] phi() + [101] call assertType + to:testUnaryOperator::@4 +testUnaryOperator::@4: scope:[testUnaryOperator] from testUnaryOperator::@3 + [102] phi() + [103] call assertType + to:testUnaryOperator::@5 +testUnaryOperator::@5: scope:[testUnaryOperator] from testUnaryOperator::@4 + [104] phi() + [105] call assertType + to:testUnaryOperator::@return +testUnaryOperator::@return: scope:[testUnaryOperator] from testUnaryOperator::@5 + [106] return + to:@return diff --git a/src/test/ref/int-conversion.log b/src/test/ref/int-conversion.log new file mode 100644 index 000000000..df50fcd7f --- /dev/null +++ b/src/test/ref/int-conversion.log @@ -0,0 +1,4159 @@ +Resolving typeid() (byte~) testUnaryOperator::$1 ← typeid (byte~) testUnaryOperator::$0 +Resolving typeid() (byte~) testUnaryOperator::$4 ← typeid (signed byte~) testUnaryOperator::$3 +Resolving typeid() (byte~) testUnaryOperator::$7 ← typeid (word~) testUnaryOperator::$6 +Resolving typeid() (byte~) testUnaryOperator::$10 ← typeid (signed word~) testUnaryOperator::$9 +Resolving typeid() (byte~) testUnaryOperator::$13 ← typeid (dword~) testUnaryOperator::$12 +Resolving typeid() (byte~) testUnaryOperator::$16 ← typeid (signed dword~) testUnaryOperator::$15 +Resolving typeid() (byte~) testBinaryOperator::$1 ← typeid (byte~) testBinaryOperator::$0 +Resolving typeid() (byte~) testBinaryOperator::$4 ← typeid (byte~) testBinaryOperator::$3 +Resolving typeid() (byte~) testBinaryOperator::$7 ← typeid (word~) testBinaryOperator::$6 +Resolving typeid() (byte~) testBinaryOperator::$10 ← typeid (signed word~) testBinaryOperator::$9 +Resolving typeid() (byte~) testBinaryOperator::$13 ← typeid (dword~) testBinaryOperator::$12 +Resolving typeid() (byte~) testBinaryOperator::$16 ← typeid (signed dword~) testBinaryOperator::$15 +Resolving typeid() (byte~) testBinaryOperator::$19 ← typeid (byte~) testBinaryOperator::$18 +Resolving typeid() (byte~) testBinaryOperator::$22 ← typeid (signed byte~) testBinaryOperator::$21 +Resolving typeid() (byte~) testBinaryOperator::$25 ← typeid (word~) testBinaryOperator::$24 +Resolving typeid() (byte~) testBinaryOperator::$28 ← typeid (signed word~) testBinaryOperator::$27 +Resolving typeid() (byte~) testBinaryOperator::$31 ← typeid (dword~) testBinaryOperator::$30 +Resolving typeid() (byte~) testBinaryOperator::$34 ← typeid (signed dword~) testBinaryOperator::$33 +Resolving typeid() (byte~) testBinaryOperator::$37 ← typeid (word~) testBinaryOperator::$36 +Resolving typeid() (byte~) testBinaryOperator::$40 ← typeid (word~) testBinaryOperator::$39 +Resolving typeid() (byte~) testBinaryOperator::$43 ← typeid (word~) testBinaryOperator::$42 +Resolving typeid() (byte~) testBinaryOperator::$46 ← typeid (word~) testBinaryOperator::$45 +Resolving typeid() (byte~) testBinaryOperator::$49 ← typeid (dword~) testBinaryOperator::$48 +Resolving typeid() (byte~) testBinaryOperator::$52 ← typeid (signed dword~) testBinaryOperator::$51 +Resolving typeid() (byte~) testBinaryOperator::$55 ← typeid (signed word~) testBinaryOperator::$54 +Resolving typeid() (byte~) testBinaryOperator::$58 ← typeid (signed word~) testBinaryOperator::$57 +Resolving typeid() (byte~) testBinaryOperator::$61 ← typeid (word~) testBinaryOperator::$60 +Resolving typeid() (byte~) testBinaryOperator::$64 ← typeid (signed word~) testBinaryOperator::$63 +Resolving typeid() (byte~) testBinaryOperator::$67 ← typeid (dword~) testBinaryOperator::$66 +Resolving typeid() (byte~) testBinaryOperator::$70 ← typeid (signed dword~) testBinaryOperator::$69 +Resolving typeid() (byte~) testBinaryOperator::$73 ← typeid (dword~) testBinaryOperator::$72 +Resolving typeid() (byte~) testBinaryOperator::$76 ← typeid (dword~) testBinaryOperator::$75 +Resolving typeid() (byte~) testBinaryOperator::$79 ← typeid (dword~) testBinaryOperator::$78 +Resolving typeid() (byte~) testBinaryOperator::$82 ← typeid (dword~) testBinaryOperator::$81 +Resolving typeid() (byte~) testBinaryOperator::$85 ← typeid (dword~) testBinaryOperator::$84 +Resolving typeid() (byte~) testBinaryOperator::$88 ← typeid (dword~) testBinaryOperator::$87 +Resolving typeid() (byte~) testBinaryOperator::$91 ← typeid (signed dword~) testBinaryOperator::$90 +Resolving typeid() (byte~) testBinaryOperator::$94 ← typeid (signed dword~) testBinaryOperator::$93 +Resolving typeid() (byte~) testBinaryOperator::$97 ← typeid (signed dword~) testBinaryOperator::$96 +Resolving typeid() (byte~) testBinaryOperator::$100 ← typeid (signed dword~) testBinaryOperator::$99 +Resolving typeid() (byte~) testBinaryOperator::$103 ← typeid (dword~) testBinaryOperator::$102 +Resolving typeid() (byte~) testBinaryOperator::$106 ← typeid (signed dword~) testBinaryOperator::$105 +Converting word to byte* in SCREEN ← ((byte*)) $400 +Converting word to byte* in COLS ← ((byte*)) $d800 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + (byte) RED#0 ← (byte) 2 + (byte) GREEN#0 ← (byte) 5 + (byte*) SCREEN#0 ← ((byte*)) (word) $400 + (byte*) COLS#0 ← ((byte*)) (word) $d800 + (byte) idx#0 ← (byte) 0 + to:@4 +main: scope:[main] from @4 + (byte) idx#114 ← phi( @4/(byte) idx#112 ) + (byte*) main::s#0 ← (byte*) SCREEN#0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) idx#113 ← phi( main/(byte) idx#114 main::@1/(byte) idx#113 ) + (byte*) main::s#2 ← phi( main/(byte*) main::s#0 main::@1/(byte*) main::s#1 ) + *((byte*) main::s#2) ← (byte) ' ' + (byte*) main::s#1 ← ++ (byte*) main::s#2 + (byte*~) main::$2 ← (byte*) SCREEN#0 + (word) $3e8 + (bool~) main::$3 ← (byte*) main::s#1 < (byte*~) main::$2 + if((bool~) main::$3) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte) idx#110 ← phi( main::@1/(byte) idx#113 ) + call testUnaryOperator + to:main::@3 +main::@3: scope:[main] from main::@2 + (byte) idx#58 ← phi( main::@2/(byte) idx#11 ) + (byte) idx#1 ← (byte) idx#58 + call testBinaryOperator + to:main::@4 +main::@4: scope:[main] from main::@3 + (byte) idx#59 ← phi( main::@3/(byte) idx#54 ) + (byte) idx#2 ← (byte) idx#59 + to:main::@return +main::@return: scope:[main] from main::@4 + (byte) idx#60 ← phi( main::@4/(byte) idx#2 ) + (byte) idx#3 ← (byte) idx#60 + return + to:@return +testUnaryOperator: scope:[testUnaryOperator] from main::@2 + (byte) idx#4 ← (byte) 0 + (byte~) testUnaryOperator::$1 ← (const byte) TYPEID_BYTE + (byte) assertType::t1#0 ← (byte~) testUnaryOperator::$1 + (byte) assertType::t2#0 ← (const byte) TYPEID_BYTE + call assertType + to:testUnaryOperator::@1 +testUnaryOperator::@1: scope:[testUnaryOperator] from testUnaryOperator + (byte) idx#61 ← phi( testUnaryOperator/(byte) idx#56 ) + (byte) idx#5 ← (byte) idx#61 + (byte~) testUnaryOperator::$4 ← (const byte) TYPEID_SIGNED_BYTE + (byte) assertType::t1#1 ← (byte~) testUnaryOperator::$4 + (byte) assertType::t2#1 ← (const byte) TYPEID_SIGNED_BYTE + call assertType + to:testUnaryOperator::@2 +testUnaryOperator::@2: scope:[testUnaryOperator] from testUnaryOperator::@1 + (byte) idx#62 ← phi( testUnaryOperator::@1/(byte) idx#56 ) + (byte) idx#6 ← (byte) idx#62 + (byte~) testUnaryOperator::$7 ← (const byte) TYPEID_WORD + (byte) assertType::t1#2 ← (byte~) testUnaryOperator::$7 + (byte) assertType::t2#2 ← (const byte) TYPEID_WORD + call assertType + to:testUnaryOperator::@3 +testUnaryOperator::@3: scope:[testUnaryOperator] from testUnaryOperator::@2 + (byte) idx#63 ← phi( testUnaryOperator::@2/(byte) idx#56 ) + (byte) idx#7 ← (byte) idx#63 + (byte~) testUnaryOperator::$10 ← (const byte) TYPEID_SIGNED_WORD + (byte) assertType::t1#3 ← (byte~) testUnaryOperator::$10 + (byte) assertType::t2#3 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:testUnaryOperator::@4 +testUnaryOperator::@4: scope:[testUnaryOperator] from testUnaryOperator::@3 + (byte) idx#64 ← phi( testUnaryOperator::@3/(byte) idx#56 ) + (byte) idx#8 ← (byte) idx#64 + (byte~) testUnaryOperator::$13 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#4 ← (byte~) testUnaryOperator::$13 + (byte) assertType::t2#4 ← (const byte) TYPEID_DWORD + call assertType + to:testUnaryOperator::@5 +testUnaryOperator::@5: scope:[testUnaryOperator] from testUnaryOperator::@4 + (byte) idx#65 ← phi( testUnaryOperator::@4/(byte) idx#56 ) + (byte) idx#9 ← (byte) idx#65 + (byte~) testUnaryOperator::$16 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#5 ← (byte~) testUnaryOperator::$16 + (byte) assertType::t2#5 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testUnaryOperator::@6 +testUnaryOperator::@6: scope:[testUnaryOperator] from testUnaryOperator::@5 + (byte) idx#66 ← phi( testUnaryOperator::@5/(byte) idx#56 ) + (byte) idx#10 ← (byte) idx#66 + to:testUnaryOperator::@return +testUnaryOperator::@return: scope:[testUnaryOperator] from testUnaryOperator::@6 + (byte) idx#67 ← phi( testUnaryOperator::@6/(byte) idx#10 ) + (byte) idx#11 ← (byte) idx#67 + return + to:@return +testBinaryOperator: scope:[testBinaryOperator] from main::@3 + (byte) idx#12 ← (byte) $28 + (byte~) testBinaryOperator::$1 ← (const byte) TYPEID_BYTE + (byte) assertType::t1#6 ← (byte~) testBinaryOperator::$1 + (byte) assertType::t2#6 ← (const byte) TYPEID_BYTE + call assertType + to:testBinaryOperator::@1 +testBinaryOperator::@1: scope:[testBinaryOperator] from testBinaryOperator + (byte) idx#68 ← phi( testBinaryOperator/(byte) idx#56 ) + (byte) idx#13 ← (byte) idx#68 + (byte~) testBinaryOperator::$4 ← (const byte) TYPEID_BYTE + (byte) assertType::t1#7 ← (byte~) testBinaryOperator::$4 + (byte) assertType::t2#7 ← (const byte) TYPEID_BYTE + call assertType + to:testBinaryOperator::@2 +testBinaryOperator::@2: scope:[testBinaryOperator] from testBinaryOperator::@1 + (byte) idx#69 ← phi( testBinaryOperator::@1/(byte) idx#56 ) + (byte) idx#14 ← (byte) idx#69 + (byte~) testBinaryOperator::$7 ← (const byte) TYPEID_WORD + (byte) assertType::t1#8 ← (byte~) testBinaryOperator::$7 + (byte) assertType::t2#8 ← (const byte) TYPEID_WORD + call assertType + to:testBinaryOperator::@3 +testBinaryOperator::@3: scope:[testBinaryOperator] from testBinaryOperator::@2 + (byte) idx#70 ← phi( testBinaryOperator::@2/(byte) idx#56 ) + (byte) idx#15 ← (byte) idx#70 + (byte~) testBinaryOperator::$10 ← (const byte) TYPEID_SIGNED_WORD + (byte) assertType::t1#9 ← (byte~) testBinaryOperator::$10 + (byte) assertType::t2#9 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:testBinaryOperator::@4 +testBinaryOperator::@4: scope:[testBinaryOperator] from testBinaryOperator::@3 + (byte) idx#71 ← phi( testBinaryOperator::@3/(byte) idx#56 ) + (byte) idx#16 ← (byte) idx#71 + (byte~) testBinaryOperator::$13 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#10 ← (byte~) testBinaryOperator::$13 + (byte) assertType::t2#10 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@5 +testBinaryOperator::@5: scope:[testBinaryOperator] from testBinaryOperator::@4 + (byte) idx#72 ← phi( testBinaryOperator::@4/(byte) idx#56 ) + (byte) idx#17 ← (byte) idx#72 + (byte~) testBinaryOperator::$16 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#11 ← (byte~) testBinaryOperator::$16 + (byte) assertType::t2#11 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testBinaryOperator::@6 +testBinaryOperator::@6: scope:[testBinaryOperator] from testBinaryOperator::@5 + (byte) idx#73 ← phi( testBinaryOperator::@5/(byte) idx#56 ) + (byte) idx#18 ← (byte) idx#73 + (byte) idx#19 ← ++ (byte) idx#18 + (byte~) testBinaryOperator::$19 ← (const byte) TYPEID_BYTE + (byte) assertType::t1#12 ← (byte~) testBinaryOperator::$19 + (byte) assertType::t2#12 ← (const byte) TYPEID_BYTE + call assertType + to:testBinaryOperator::@7 +testBinaryOperator::@7: scope:[testBinaryOperator] from testBinaryOperator::@6 + (byte) idx#74 ← phi( testBinaryOperator::@6/(byte) idx#56 ) + (byte) idx#20 ← (byte) idx#74 + (byte~) testBinaryOperator::$22 ← (const byte) TYPEID_SIGNED_BYTE + (byte) assertType::t1#13 ← (byte~) testBinaryOperator::$22 + (byte) assertType::t2#13 ← (const byte) TYPEID_SIGNED_BYTE + call assertType + to:testBinaryOperator::@8 +testBinaryOperator::@8: scope:[testBinaryOperator] from testBinaryOperator::@7 + (byte) idx#75 ← phi( testBinaryOperator::@7/(byte) idx#56 ) + (byte) idx#21 ← (byte) idx#75 + (byte~) testBinaryOperator::$25 ← (const byte) TYPEID_WORD + (byte) assertType::t1#14 ← (byte~) testBinaryOperator::$25 + (byte) assertType::t2#14 ← (const byte) TYPEID_WORD + call assertType + to:testBinaryOperator::@9 +testBinaryOperator::@9: scope:[testBinaryOperator] from testBinaryOperator::@8 + (byte) idx#76 ← phi( testBinaryOperator::@8/(byte) idx#56 ) + (byte) idx#22 ← (byte) idx#76 + (byte~) testBinaryOperator::$28 ← (const byte) TYPEID_SIGNED_WORD + (byte) assertType::t1#15 ← (byte~) testBinaryOperator::$28 + (byte) assertType::t2#15 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:testBinaryOperator::@10 +testBinaryOperator::@10: scope:[testBinaryOperator] from testBinaryOperator::@9 + (byte) idx#77 ← phi( testBinaryOperator::@9/(byte) idx#56 ) + (byte) idx#23 ← (byte) idx#77 + (byte~) testBinaryOperator::$31 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#16 ← (byte~) testBinaryOperator::$31 + (byte) assertType::t2#16 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@11 +testBinaryOperator::@11: scope:[testBinaryOperator] from testBinaryOperator::@10 + (byte) idx#78 ← phi( testBinaryOperator::@10/(byte) idx#56 ) + (byte) idx#24 ← (byte) idx#78 + (byte~) testBinaryOperator::$34 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#17 ← (byte~) testBinaryOperator::$34 + (byte) assertType::t2#17 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testBinaryOperator::@12 +testBinaryOperator::@12: scope:[testBinaryOperator] from testBinaryOperator::@11 + (byte) idx#79 ← phi( testBinaryOperator::@11/(byte) idx#56 ) + (byte) idx#25 ← (byte) idx#79 + (byte) idx#26 ← ++ (byte) idx#25 + (byte~) testBinaryOperator::$37 ← (const byte) TYPEID_WORD + (byte) assertType::t1#18 ← (byte~) testBinaryOperator::$37 + (byte) assertType::t2#18 ← (const byte) TYPEID_WORD + call assertType + to:testBinaryOperator::@13 +testBinaryOperator::@13: scope:[testBinaryOperator] from testBinaryOperator::@12 + (byte) idx#80 ← phi( testBinaryOperator::@12/(byte) idx#56 ) + (byte) idx#27 ← (byte) idx#80 + (byte~) testBinaryOperator::$40 ← (const byte) TYPEID_WORD + (byte) assertType::t1#19 ← (byte~) testBinaryOperator::$40 + (byte) assertType::t2#19 ← (const byte) TYPEID_WORD + call assertType + to:testBinaryOperator::@14 +testBinaryOperator::@14: scope:[testBinaryOperator] from testBinaryOperator::@13 + (byte) idx#81 ← phi( testBinaryOperator::@13/(byte) idx#56 ) + (byte) idx#28 ← (byte) idx#81 + (byte~) testBinaryOperator::$43 ← (const byte) TYPEID_WORD + (byte) assertType::t1#20 ← (byte~) testBinaryOperator::$43 + (byte) assertType::t2#20 ← (const byte) TYPEID_WORD + call assertType + to:testBinaryOperator::@15 +testBinaryOperator::@15: scope:[testBinaryOperator] from testBinaryOperator::@14 + (byte) idx#82 ← phi( testBinaryOperator::@14/(byte) idx#56 ) + (byte) idx#29 ← (byte) idx#82 + (byte~) testBinaryOperator::$46 ← (const byte) TYPEID_WORD + (byte) assertType::t1#21 ← (byte~) testBinaryOperator::$46 + (byte) assertType::t2#21 ← (const byte) TYPEID_WORD + call assertType + to:testBinaryOperator::@16 +testBinaryOperator::@16: scope:[testBinaryOperator] from testBinaryOperator::@15 + (byte) idx#83 ← phi( testBinaryOperator::@15/(byte) idx#56 ) + (byte) idx#30 ← (byte) idx#83 + (byte~) testBinaryOperator::$49 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#22 ← (byte~) testBinaryOperator::$49 + (byte) assertType::t2#22 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@17 +testBinaryOperator::@17: scope:[testBinaryOperator] from testBinaryOperator::@16 + (byte) idx#84 ← phi( testBinaryOperator::@16/(byte) idx#56 ) + (byte) idx#31 ← (byte) idx#84 + (byte~) testBinaryOperator::$52 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#23 ← (byte~) testBinaryOperator::$52 + (byte) assertType::t2#23 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testBinaryOperator::@18 +testBinaryOperator::@18: scope:[testBinaryOperator] from testBinaryOperator::@17 + (byte) idx#85 ← phi( testBinaryOperator::@17/(byte) idx#56 ) + (byte) idx#32 ← (byte) idx#85 + (byte) idx#33 ← (byte) $50 + (byte~) testBinaryOperator::$55 ← (const byte) TYPEID_SIGNED_WORD + (byte) assertType::t1#24 ← (byte~) testBinaryOperator::$55 + (byte) assertType::t2#24 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:testBinaryOperator::@19 +testBinaryOperator::@19: scope:[testBinaryOperator] from testBinaryOperator::@18 + (byte) idx#86 ← phi( testBinaryOperator::@18/(byte) idx#56 ) + (byte) idx#34 ← (byte) idx#86 + (byte~) testBinaryOperator::$58 ← (const byte) TYPEID_SIGNED_WORD + (byte) assertType::t1#25 ← (byte~) testBinaryOperator::$58 + (byte) assertType::t2#25 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:testBinaryOperator::@20 +testBinaryOperator::@20: scope:[testBinaryOperator] from testBinaryOperator::@19 + (byte) idx#87 ← phi( testBinaryOperator::@19/(byte) idx#56 ) + (byte) idx#35 ← (byte) idx#87 + (byte~) testBinaryOperator::$61 ← (const byte) TYPEID_WORD + (byte) assertType::t1#26 ← (byte~) testBinaryOperator::$61 + (byte) assertType::t2#26 ← (const byte) TYPEID_WORD + call assertType + to:testBinaryOperator::@21 +testBinaryOperator::@21: scope:[testBinaryOperator] from testBinaryOperator::@20 + (byte) idx#88 ← phi( testBinaryOperator::@20/(byte) idx#56 ) + (byte) idx#36 ← (byte) idx#88 + (byte~) testBinaryOperator::$64 ← (const byte) TYPEID_SIGNED_WORD + (byte) assertType::t1#27 ← (byte~) testBinaryOperator::$64 + (byte) assertType::t2#27 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:testBinaryOperator::@22 +testBinaryOperator::@22: scope:[testBinaryOperator] from testBinaryOperator::@21 + (byte) idx#89 ← phi( testBinaryOperator::@21/(byte) idx#56 ) + (byte) idx#37 ← (byte) idx#89 + (byte~) testBinaryOperator::$67 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#28 ← (byte~) testBinaryOperator::$67 + (byte) assertType::t2#28 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@23 +testBinaryOperator::@23: scope:[testBinaryOperator] from testBinaryOperator::@22 + (byte) idx#90 ← phi( testBinaryOperator::@22/(byte) idx#56 ) + (byte) idx#38 ← (byte) idx#90 + (byte~) testBinaryOperator::$70 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#29 ← (byte~) testBinaryOperator::$70 + (byte) assertType::t2#29 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testBinaryOperator::@24 +testBinaryOperator::@24: scope:[testBinaryOperator] from testBinaryOperator::@23 + (byte) idx#91 ← phi( testBinaryOperator::@23/(byte) idx#56 ) + (byte) idx#39 ← (byte) idx#91 + (byte) idx#40 ← ++ (byte) idx#39 + (byte~) testBinaryOperator::$73 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#30 ← (byte~) testBinaryOperator::$73 + (byte) assertType::t2#30 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@25 +testBinaryOperator::@25: scope:[testBinaryOperator] from testBinaryOperator::@24 + (byte) idx#92 ← phi( testBinaryOperator::@24/(byte) idx#56 ) + (byte) idx#41 ← (byte) idx#92 + (byte~) testBinaryOperator::$76 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#31 ← (byte~) testBinaryOperator::$76 + (byte) assertType::t2#31 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@26 +testBinaryOperator::@26: scope:[testBinaryOperator] from testBinaryOperator::@25 + (byte) idx#93 ← phi( testBinaryOperator::@25/(byte) idx#56 ) + (byte) idx#42 ← (byte) idx#93 + (byte~) testBinaryOperator::$79 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#32 ← (byte~) testBinaryOperator::$79 + (byte) assertType::t2#32 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@27 +testBinaryOperator::@27: scope:[testBinaryOperator] from testBinaryOperator::@26 + (byte) idx#94 ← phi( testBinaryOperator::@26/(byte) idx#56 ) + (byte) idx#43 ← (byte) idx#94 + (byte~) testBinaryOperator::$82 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#33 ← (byte~) testBinaryOperator::$82 + (byte) assertType::t2#33 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@28 +testBinaryOperator::@28: scope:[testBinaryOperator] from testBinaryOperator::@27 + (byte) idx#95 ← phi( testBinaryOperator::@27/(byte) idx#56 ) + (byte) idx#44 ← (byte) idx#95 + (byte~) testBinaryOperator::$85 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#34 ← (byte~) testBinaryOperator::$85 + (byte) assertType::t2#34 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@29 +testBinaryOperator::@29: scope:[testBinaryOperator] from testBinaryOperator::@28 + (byte) idx#96 ← phi( testBinaryOperator::@28/(byte) idx#56 ) + (byte) idx#45 ← (byte) idx#96 + (byte~) testBinaryOperator::$88 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#35 ← (byte~) testBinaryOperator::$88 + (byte) assertType::t2#35 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@30 +testBinaryOperator::@30: scope:[testBinaryOperator] from testBinaryOperator::@29 + (byte) idx#97 ← phi( testBinaryOperator::@29/(byte) idx#56 ) + (byte) idx#46 ← (byte) idx#97 + (byte) idx#47 ← ++ (byte) idx#46 + (byte~) testBinaryOperator::$91 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#36 ← (byte~) testBinaryOperator::$91 + (byte) assertType::t2#36 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testBinaryOperator::@31 +testBinaryOperator::@31: scope:[testBinaryOperator] from testBinaryOperator::@30 + (byte) idx#98 ← phi( testBinaryOperator::@30/(byte) idx#56 ) + (byte) idx#48 ← (byte) idx#98 + (byte~) testBinaryOperator::$94 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#37 ← (byte~) testBinaryOperator::$94 + (byte) assertType::t2#37 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testBinaryOperator::@32 +testBinaryOperator::@32: scope:[testBinaryOperator] from testBinaryOperator::@31 + (byte) idx#99 ← phi( testBinaryOperator::@31/(byte) idx#56 ) + (byte) idx#49 ← (byte) idx#99 + (byte~) testBinaryOperator::$97 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#38 ← (byte~) testBinaryOperator::$97 + (byte) assertType::t2#38 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testBinaryOperator::@33 +testBinaryOperator::@33: scope:[testBinaryOperator] from testBinaryOperator::@32 + (byte) idx#100 ← phi( testBinaryOperator::@32/(byte) idx#56 ) + (byte) idx#50 ← (byte) idx#100 + (byte~) testBinaryOperator::$100 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#39 ← (byte~) testBinaryOperator::$100 + (byte) assertType::t2#39 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testBinaryOperator::@34 +testBinaryOperator::@34: scope:[testBinaryOperator] from testBinaryOperator::@33 + (byte) idx#101 ← phi( testBinaryOperator::@33/(byte) idx#56 ) + (byte) idx#51 ← (byte) idx#101 + (byte~) testBinaryOperator::$103 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#40 ← (byte~) testBinaryOperator::$103 + (byte) assertType::t2#40 ← (const byte) TYPEID_DWORD + call assertType + to:testBinaryOperator::@35 +testBinaryOperator::@35: scope:[testBinaryOperator] from testBinaryOperator::@34 + (byte) idx#102 ← phi( testBinaryOperator::@34/(byte) idx#56 ) + (byte) idx#52 ← (byte) idx#102 + (byte~) testBinaryOperator::$106 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#41 ← (byte~) testBinaryOperator::$106 + (byte) assertType::t2#41 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testBinaryOperator::@36 +testBinaryOperator::@36: scope:[testBinaryOperator] from testBinaryOperator::@35 + (byte) idx#103 ← phi( testBinaryOperator::@35/(byte) idx#56 ) + (byte) idx#53 ← (byte) idx#103 + to:testBinaryOperator::@return +testBinaryOperator::@return: scope:[testBinaryOperator] from testBinaryOperator::@36 + (byte) idx#104 ← phi( testBinaryOperator::@36/(byte) idx#53 ) + (byte) idx#54 ← (byte) idx#104 + return + to:@return +assertType: scope:[assertType] from testBinaryOperator testBinaryOperator::@1 testBinaryOperator::@10 testBinaryOperator::@11 testBinaryOperator::@12 testBinaryOperator::@13 testBinaryOperator::@14 testBinaryOperator::@15 testBinaryOperator::@16 testBinaryOperator::@17 testBinaryOperator::@18 testBinaryOperator::@19 testBinaryOperator::@2 testBinaryOperator::@20 testBinaryOperator::@21 testBinaryOperator::@22 testBinaryOperator::@23 testBinaryOperator::@24 testBinaryOperator::@25 testBinaryOperator::@26 testBinaryOperator::@27 testBinaryOperator::@28 testBinaryOperator::@29 testBinaryOperator::@3 testBinaryOperator::@30 testBinaryOperator::@31 testBinaryOperator::@32 testBinaryOperator::@33 testBinaryOperator::@34 testBinaryOperator::@35 testBinaryOperator::@4 testBinaryOperator::@5 testBinaryOperator::@6 testBinaryOperator::@7 testBinaryOperator::@8 testBinaryOperator::@9 testUnaryOperator testUnaryOperator::@1 testUnaryOperator::@2 testUnaryOperator::@3 testUnaryOperator::@4 testUnaryOperator::@5 + (byte) idx#111 ← phi( testBinaryOperator/(byte) idx#12 testBinaryOperator::@1/(byte) idx#13 testBinaryOperator::@10/(byte) idx#23 testBinaryOperator::@11/(byte) idx#24 testBinaryOperator::@12/(byte) idx#26 testBinaryOperator::@13/(byte) idx#27 testBinaryOperator::@14/(byte) idx#28 testBinaryOperator::@15/(byte) idx#29 testBinaryOperator::@16/(byte) idx#30 testBinaryOperator::@17/(byte) idx#31 testBinaryOperator::@18/(byte) idx#33 testBinaryOperator::@19/(byte) idx#34 testBinaryOperator::@2/(byte) idx#14 testBinaryOperator::@20/(byte) idx#35 testBinaryOperator::@21/(byte) idx#36 testBinaryOperator::@22/(byte) idx#37 testBinaryOperator::@23/(byte) idx#38 testBinaryOperator::@24/(byte) idx#40 testBinaryOperator::@25/(byte) idx#41 testBinaryOperator::@26/(byte) idx#42 testBinaryOperator::@27/(byte) idx#43 testBinaryOperator::@28/(byte) idx#44 testBinaryOperator::@29/(byte) idx#45 testBinaryOperator::@3/(byte) idx#15 testBinaryOperator::@30/(byte) idx#47 testBinaryOperator::@31/(byte) idx#48 testBinaryOperator::@32/(byte) idx#49 testBinaryOperator::@33/(byte) idx#50 testBinaryOperator::@34/(byte) idx#51 testBinaryOperator::@35/(byte) idx#52 testBinaryOperator::@4/(byte) idx#16 testBinaryOperator::@5/(byte) idx#17 testBinaryOperator::@6/(byte) idx#19 testBinaryOperator::@7/(byte) idx#20 testBinaryOperator::@8/(byte) idx#21 testBinaryOperator::@9/(byte) idx#22 testUnaryOperator/(byte) idx#4 testUnaryOperator::@1/(byte) idx#5 testUnaryOperator::@2/(byte) idx#6 testUnaryOperator::@3/(byte) idx#7 testUnaryOperator::@4/(byte) idx#8 testUnaryOperator::@5/(byte) idx#9 ) + (byte) assertType::t2#42 ← phi( testBinaryOperator/(byte) assertType::t2#6 testBinaryOperator::@1/(byte) assertType::t2#7 testBinaryOperator::@10/(byte) assertType::t2#16 testBinaryOperator::@11/(byte) assertType::t2#17 testBinaryOperator::@12/(byte) assertType::t2#18 testBinaryOperator::@13/(byte) assertType::t2#19 testBinaryOperator::@14/(byte) assertType::t2#20 testBinaryOperator::@15/(byte) assertType::t2#21 testBinaryOperator::@16/(byte) assertType::t2#22 testBinaryOperator::@17/(byte) assertType::t2#23 testBinaryOperator::@18/(byte) assertType::t2#24 testBinaryOperator::@19/(byte) assertType::t2#25 testBinaryOperator::@2/(byte) assertType::t2#8 testBinaryOperator::@20/(byte) assertType::t2#26 testBinaryOperator::@21/(byte) assertType::t2#27 testBinaryOperator::@22/(byte) assertType::t2#28 testBinaryOperator::@23/(byte) assertType::t2#29 testBinaryOperator::@24/(byte) assertType::t2#30 testBinaryOperator::@25/(byte) assertType::t2#31 testBinaryOperator::@26/(byte) assertType::t2#32 testBinaryOperator::@27/(byte) assertType::t2#33 testBinaryOperator::@28/(byte) assertType::t2#34 testBinaryOperator::@29/(byte) assertType::t2#35 testBinaryOperator::@3/(byte) assertType::t2#9 testBinaryOperator::@30/(byte) assertType::t2#36 testBinaryOperator::@31/(byte) assertType::t2#37 testBinaryOperator::@32/(byte) assertType::t2#38 testBinaryOperator::@33/(byte) assertType::t2#39 testBinaryOperator::@34/(byte) assertType::t2#40 testBinaryOperator::@35/(byte) assertType::t2#41 testBinaryOperator::@4/(byte) assertType::t2#10 testBinaryOperator::@5/(byte) assertType::t2#11 testBinaryOperator::@6/(byte) assertType::t2#12 testBinaryOperator::@7/(byte) assertType::t2#13 testBinaryOperator::@8/(byte) assertType::t2#14 testBinaryOperator::@9/(byte) assertType::t2#15 testUnaryOperator/(byte) assertType::t2#0 testUnaryOperator::@1/(byte) assertType::t2#1 testUnaryOperator::@2/(byte) assertType::t2#2 testUnaryOperator::@3/(byte) assertType::t2#3 testUnaryOperator::@4/(byte) assertType::t2#4 testUnaryOperator::@5/(byte) assertType::t2#5 ) + (byte) assertType::t1#42 ← phi( testBinaryOperator/(byte) assertType::t1#6 testBinaryOperator::@1/(byte) assertType::t1#7 testBinaryOperator::@10/(byte) assertType::t1#16 testBinaryOperator::@11/(byte) assertType::t1#17 testBinaryOperator::@12/(byte) assertType::t1#18 testBinaryOperator::@13/(byte) assertType::t1#19 testBinaryOperator::@14/(byte) assertType::t1#20 testBinaryOperator::@15/(byte) assertType::t1#21 testBinaryOperator::@16/(byte) assertType::t1#22 testBinaryOperator::@17/(byte) assertType::t1#23 testBinaryOperator::@18/(byte) assertType::t1#24 testBinaryOperator::@19/(byte) assertType::t1#25 testBinaryOperator::@2/(byte) assertType::t1#8 testBinaryOperator::@20/(byte) assertType::t1#26 testBinaryOperator::@21/(byte) assertType::t1#27 testBinaryOperator::@22/(byte) assertType::t1#28 testBinaryOperator::@23/(byte) assertType::t1#29 testBinaryOperator::@24/(byte) assertType::t1#30 testBinaryOperator::@25/(byte) assertType::t1#31 testBinaryOperator::@26/(byte) assertType::t1#32 testBinaryOperator::@27/(byte) assertType::t1#33 testBinaryOperator::@28/(byte) assertType::t1#34 testBinaryOperator::@29/(byte) assertType::t1#35 testBinaryOperator::@3/(byte) assertType::t1#9 testBinaryOperator::@30/(byte) assertType::t1#36 testBinaryOperator::@31/(byte) assertType::t1#37 testBinaryOperator::@32/(byte) assertType::t1#38 testBinaryOperator::@33/(byte) assertType::t1#39 testBinaryOperator::@34/(byte) assertType::t1#40 testBinaryOperator::@35/(byte) assertType::t1#41 testBinaryOperator::@4/(byte) assertType::t1#10 testBinaryOperator::@5/(byte) assertType::t1#11 testBinaryOperator::@6/(byte) assertType::t1#12 testBinaryOperator::@7/(byte) assertType::t1#13 testBinaryOperator::@8/(byte) assertType::t1#14 testBinaryOperator::@9/(byte) assertType::t1#15 testUnaryOperator/(byte) assertType::t1#0 testUnaryOperator::@1/(byte) assertType::t1#1 testUnaryOperator::@2/(byte) assertType::t1#2 testUnaryOperator::@3/(byte) assertType::t1#3 testUnaryOperator::@4/(byte) assertType::t1#4 testUnaryOperator::@5/(byte) assertType::t1#5 ) + (bool~) assertType::$0 ← (byte) assertType::t1#42 == (byte) assertType::t2#42 + if((bool~) assertType::$0) goto assertType::@1 + to:assertType::@3 +assertType::@1: scope:[assertType] from assertType + (byte) assertType::t1#44 ← phi( assertType/(byte) assertType::t1#42 ) + (byte) idx#105 ← phi( assertType/(byte) idx#111 ) + *((byte*) COLS#0 + (byte) idx#105) ← (byte) GREEN#0 + to:assertType::@2 +assertType::@3: scope:[assertType] from assertType + (byte) assertType::t1#45 ← phi( assertType/(byte) assertType::t1#42 ) + (byte) idx#106 ← phi( assertType/(byte) idx#111 ) + *((byte*) COLS#0 + (byte) idx#106) ← (byte) RED#0 + to:assertType::@2 +assertType::@2: scope:[assertType] from assertType::@1 assertType::@3 + (byte) idx#107 ← phi( assertType::@1/(byte) idx#105 assertType::@3/(byte) idx#106 ) + (byte) assertType::t1#43 ← phi( assertType::@1/(byte) assertType::t1#44 assertType::@3/(byte) assertType::t1#45 ) + *((byte*) SCREEN#0 + (byte) idx#107) ← (byte) assertType::t1#43 + (byte) idx#55 ← ++ (byte) idx#107 + to:assertType::@return +assertType::@return: scope:[assertType] from assertType::@2 + (byte) idx#108 ← phi( assertType::@2/(byte) idx#55 ) + (byte) idx#56 ← (byte) idx#108 + return + to:@return +@4: scope:[] from @begin + (byte) idx#112 ← phi( @begin/(byte) idx#0 ) + call main + to:@5 +@5: scope:[] from @4 + (byte) idx#109 ← phi( @4/(byte) idx#3 ) + (byte) idx#57 ← (byte) idx#109 + to:@end +@end: scope:[] from @5 + +SYMBOL TABLE SSA +(label) @4 +(label) @5 +(label) @begin +(label) @end +(byte*) COLS +(byte*) COLS#0 +(byte) GREEN +(byte) GREEN#0 +(byte) RED +(byte) RED#0 +(byte*) SCREEN +(byte*) SCREEN#0 +(const byte) TYPEID_BYTE = (number) 1 +(const byte) TYPEID_DWORD = (number) 5 +(const byte) TYPEID_SIGNED_BYTE = (number) 2 +(const byte) TYPEID_SIGNED_DWORD = (number) 6 +(const byte) TYPEID_SIGNED_WORD = (number) 4 +(const byte) TYPEID_WORD = (number) 3 +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(bool~) assertType::$0 +(label) assertType::@1 +(label) assertType::@2 +(label) assertType::@3 +(label) assertType::@return +(byte) assertType::t1 +(byte) assertType::t1#0 +(byte) assertType::t1#1 +(byte) assertType::t1#10 +(byte) assertType::t1#11 +(byte) assertType::t1#12 +(byte) assertType::t1#13 +(byte) assertType::t1#14 +(byte) assertType::t1#15 +(byte) assertType::t1#16 +(byte) assertType::t1#17 +(byte) assertType::t1#18 +(byte) assertType::t1#19 +(byte) assertType::t1#2 +(byte) assertType::t1#20 +(byte) assertType::t1#21 +(byte) assertType::t1#22 +(byte) assertType::t1#23 +(byte) assertType::t1#24 +(byte) assertType::t1#25 +(byte) assertType::t1#26 +(byte) assertType::t1#27 +(byte) assertType::t1#28 +(byte) assertType::t1#29 +(byte) assertType::t1#3 +(byte) assertType::t1#30 +(byte) assertType::t1#31 +(byte) assertType::t1#32 +(byte) assertType::t1#33 +(byte) assertType::t1#34 +(byte) assertType::t1#35 +(byte) assertType::t1#36 +(byte) assertType::t1#37 +(byte) assertType::t1#38 +(byte) assertType::t1#39 +(byte) assertType::t1#4 +(byte) assertType::t1#40 +(byte) assertType::t1#41 +(byte) assertType::t1#42 +(byte) assertType::t1#43 +(byte) assertType::t1#44 +(byte) assertType::t1#45 +(byte) assertType::t1#5 +(byte) assertType::t1#6 +(byte) assertType::t1#7 +(byte) assertType::t1#8 +(byte) assertType::t1#9 +(byte) assertType::t2 +(byte) assertType::t2#0 +(byte) assertType::t2#1 +(byte) assertType::t2#10 +(byte) assertType::t2#11 +(byte) assertType::t2#12 +(byte) assertType::t2#13 +(byte) assertType::t2#14 +(byte) assertType::t2#15 +(byte) assertType::t2#16 +(byte) assertType::t2#17 +(byte) assertType::t2#18 +(byte) assertType::t2#19 +(byte) assertType::t2#2 +(byte) assertType::t2#20 +(byte) assertType::t2#21 +(byte) assertType::t2#22 +(byte) assertType::t2#23 +(byte) assertType::t2#24 +(byte) assertType::t2#25 +(byte) assertType::t2#26 +(byte) assertType::t2#27 +(byte) assertType::t2#28 +(byte) assertType::t2#29 +(byte) assertType::t2#3 +(byte) assertType::t2#30 +(byte) assertType::t2#31 +(byte) assertType::t2#32 +(byte) assertType::t2#33 +(byte) assertType::t2#34 +(byte) assertType::t2#35 +(byte) assertType::t2#36 +(byte) assertType::t2#37 +(byte) assertType::t2#38 +(byte) assertType::t2#39 +(byte) assertType::t2#4 +(byte) assertType::t2#40 +(byte) assertType::t2#41 +(byte) assertType::t2#42 +(byte) assertType::t2#5 +(byte) assertType::t2#6 +(byte) assertType::t2#7 +(byte) assertType::t2#8 +(byte) assertType::t2#9 +(byte) idx +(byte) idx#0 +(byte) idx#1 +(byte) idx#10 +(byte) idx#100 +(byte) idx#101 +(byte) idx#102 +(byte) idx#103 +(byte) idx#104 +(byte) idx#105 +(byte) idx#106 +(byte) idx#107 +(byte) idx#108 +(byte) idx#109 +(byte) idx#11 +(byte) idx#110 +(byte) idx#111 +(byte) idx#112 +(byte) idx#113 +(byte) idx#114 +(byte) idx#12 +(byte) idx#13 +(byte) idx#14 +(byte) idx#15 +(byte) idx#16 +(byte) idx#17 +(byte) idx#18 +(byte) idx#19 +(byte) idx#2 +(byte) idx#20 +(byte) idx#21 +(byte) idx#22 +(byte) idx#23 +(byte) idx#24 +(byte) idx#25 +(byte) idx#26 +(byte) idx#27 +(byte) idx#28 +(byte) idx#29 +(byte) idx#3 +(byte) idx#30 +(byte) idx#31 +(byte) idx#32 +(byte) idx#33 +(byte) idx#34 +(byte) idx#35 +(byte) idx#36 +(byte) idx#37 +(byte) idx#38 +(byte) idx#39 +(byte) idx#4 +(byte) idx#40 +(byte) idx#41 +(byte) idx#42 +(byte) idx#43 +(byte) idx#44 +(byte) idx#45 +(byte) idx#46 +(byte) idx#47 +(byte) idx#48 +(byte) idx#49 +(byte) idx#5 +(byte) idx#50 +(byte) idx#51 +(byte) idx#52 +(byte) idx#53 +(byte) idx#54 +(byte) idx#55 +(byte) idx#56 +(byte) idx#57 +(byte) idx#58 +(byte) idx#59 +(byte) idx#6 +(byte) idx#60 +(byte) idx#61 +(byte) idx#62 +(byte) idx#63 +(byte) idx#64 +(byte) idx#65 +(byte) idx#66 +(byte) idx#67 +(byte) idx#68 +(byte) idx#69 +(byte) idx#7 +(byte) idx#70 +(byte) idx#71 +(byte) idx#72 +(byte) idx#73 +(byte) idx#74 +(byte) idx#75 +(byte) idx#76 +(byte) idx#77 +(byte) idx#78 +(byte) idx#79 +(byte) idx#8 +(byte) idx#80 +(byte) idx#81 +(byte) idx#82 +(byte) idx#83 +(byte) idx#84 +(byte) idx#85 +(byte) idx#86 +(byte) idx#87 +(byte) idx#88 +(byte) idx#89 +(byte) idx#9 +(byte) idx#90 +(byte) idx#91 +(byte) idx#92 +(byte) idx#93 +(byte) idx#94 +(byte) idx#95 +(byte) idx#96 +(byte) idx#97 +(byte) idx#98 +(byte) idx#99 +(void()) main() +(byte*~) main::$2 +(bool~) main::$3 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@return +(byte*) main::s +(byte*) main::s#0 +(byte*) main::s#1 +(byte*) main::s#2 +(void()) testBinaryOperator() +(byte~) testBinaryOperator::$1 +(byte~) testBinaryOperator::$10 +(byte~) testBinaryOperator::$100 +(byte~) testBinaryOperator::$103 +(byte~) testBinaryOperator::$106 +(byte~) testBinaryOperator::$13 +(byte~) testBinaryOperator::$16 +(byte~) testBinaryOperator::$19 +(byte~) testBinaryOperator::$22 +(byte~) testBinaryOperator::$25 +(byte~) testBinaryOperator::$28 +(byte~) testBinaryOperator::$31 +(byte~) testBinaryOperator::$34 +(byte~) testBinaryOperator::$37 +(byte~) testBinaryOperator::$4 +(byte~) testBinaryOperator::$40 +(byte~) testBinaryOperator::$43 +(byte~) testBinaryOperator::$46 +(byte~) testBinaryOperator::$49 +(byte~) testBinaryOperator::$52 +(byte~) testBinaryOperator::$55 +(byte~) testBinaryOperator::$58 +(byte~) testBinaryOperator::$61 +(byte~) testBinaryOperator::$64 +(byte~) testBinaryOperator::$67 +(byte~) testBinaryOperator::$7 +(byte~) testBinaryOperator::$70 +(byte~) testBinaryOperator::$73 +(byte~) testBinaryOperator::$76 +(byte~) testBinaryOperator::$79 +(byte~) testBinaryOperator::$82 +(byte~) testBinaryOperator::$85 +(byte~) testBinaryOperator::$88 +(byte~) testBinaryOperator::$91 +(byte~) testBinaryOperator::$94 +(byte~) testBinaryOperator::$97 +(label) testBinaryOperator::@1 +(label) testBinaryOperator::@10 +(label) testBinaryOperator::@11 +(label) testBinaryOperator::@12 +(label) testBinaryOperator::@13 +(label) testBinaryOperator::@14 +(label) testBinaryOperator::@15 +(label) testBinaryOperator::@16 +(label) testBinaryOperator::@17 +(label) testBinaryOperator::@18 +(label) testBinaryOperator::@19 +(label) testBinaryOperator::@2 +(label) testBinaryOperator::@20 +(label) testBinaryOperator::@21 +(label) testBinaryOperator::@22 +(label) testBinaryOperator::@23 +(label) testBinaryOperator::@24 +(label) testBinaryOperator::@25 +(label) testBinaryOperator::@26 +(label) testBinaryOperator::@27 +(label) testBinaryOperator::@28 +(label) testBinaryOperator::@29 +(label) testBinaryOperator::@3 +(label) testBinaryOperator::@30 +(label) testBinaryOperator::@31 +(label) testBinaryOperator::@32 +(label) testBinaryOperator::@33 +(label) testBinaryOperator::@34 +(label) testBinaryOperator::@35 +(label) testBinaryOperator::@36 +(label) testBinaryOperator::@4 +(label) testBinaryOperator::@5 +(label) testBinaryOperator::@6 +(label) testBinaryOperator::@7 +(label) testBinaryOperator::@8 +(label) testBinaryOperator::@9 +(label) testBinaryOperator::@return +(void()) testUnaryOperator() +(byte~) testUnaryOperator::$1 +(byte~) testUnaryOperator::$10 +(byte~) testUnaryOperator::$13 +(byte~) testUnaryOperator::$16 +(byte~) testUnaryOperator::$4 +(byte~) testUnaryOperator::$7 +(label) testUnaryOperator::@1 +(label) testUnaryOperator::@2 +(label) testUnaryOperator::@3 +(label) testUnaryOperator::@4 +(label) testUnaryOperator::@5 +(label) testUnaryOperator::@6 +(label) testUnaryOperator::@return + +Alias (byte) idx#110 = (byte) idx#113 +Alias (byte) idx#1 = (byte) idx#58 +Alias (byte) idx#2 = (byte) idx#59 (byte) idx#60 (byte) idx#3 +Alias (byte) assertType::t1#0 = (byte~) testUnaryOperator::$1 +Alias (byte) idx#5 = (byte) idx#61 +Alias (byte) assertType::t1#1 = (byte~) testUnaryOperator::$4 +Alias (byte) idx#6 = (byte) idx#62 +Alias (byte) assertType::t1#2 = (byte~) testUnaryOperator::$7 +Alias (byte) idx#63 = (byte) idx#7 +Alias (byte) assertType::t1#3 = (byte~) testUnaryOperator::$10 +Alias (byte) idx#64 = (byte) idx#8 +Alias (byte) assertType::t1#4 = (byte~) testUnaryOperator::$13 +Alias (byte) idx#65 = (byte) idx#9 +Alias (byte) assertType::t1#5 = (byte~) testUnaryOperator::$16 +Alias (byte) idx#10 = (byte) idx#66 (byte) idx#67 (byte) idx#11 +Alias (byte) assertType::t1#6 = (byte~) testBinaryOperator::$1 +Alias (byte) idx#13 = (byte) idx#68 +Alias (byte) assertType::t1#7 = (byte~) testBinaryOperator::$4 +Alias (byte) idx#14 = (byte) idx#69 +Alias (byte) assertType::t1#8 = (byte~) testBinaryOperator::$7 +Alias (byte) idx#15 = (byte) idx#70 +Alias (byte) assertType::t1#9 = (byte~) testBinaryOperator::$10 +Alias (byte) idx#16 = (byte) idx#71 +Alias (byte) assertType::t1#10 = (byte~) testBinaryOperator::$13 +Alias (byte) idx#17 = (byte) idx#72 +Alias (byte) assertType::t1#11 = (byte~) testBinaryOperator::$16 +Alias (byte) idx#18 = (byte) idx#73 +Alias (byte) assertType::t1#12 = (byte~) testBinaryOperator::$19 +Alias (byte) idx#20 = (byte) idx#74 +Alias (byte) assertType::t1#13 = (byte~) testBinaryOperator::$22 +Alias (byte) idx#21 = (byte) idx#75 +Alias (byte) assertType::t1#14 = (byte~) testBinaryOperator::$25 +Alias (byte) idx#22 = (byte) idx#76 +Alias (byte) assertType::t1#15 = (byte~) testBinaryOperator::$28 +Alias (byte) idx#23 = (byte) idx#77 +Alias (byte) assertType::t1#16 = (byte~) testBinaryOperator::$31 +Alias (byte) idx#24 = (byte) idx#78 +Alias (byte) assertType::t1#17 = (byte~) testBinaryOperator::$34 +Alias (byte) idx#25 = (byte) idx#79 +Alias (byte) assertType::t1#18 = (byte~) testBinaryOperator::$37 +Alias (byte) idx#27 = (byte) idx#80 +Alias (byte) assertType::t1#19 = (byte~) testBinaryOperator::$40 +Alias (byte) idx#28 = (byte) idx#81 +Alias (byte) assertType::t1#20 = (byte~) testBinaryOperator::$43 +Alias (byte) idx#29 = (byte) idx#82 +Alias (byte) assertType::t1#21 = (byte~) testBinaryOperator::$46 +Alias (byte) idx#30 = (byte) idx#83 +Alias (byte) assertType::t1#22 = (byte~) testBinaryOperator::$49 +Alias (byte) idx#31 = (byte) idx#84 +Alias (byte) assertType::t1#23 = (byte~) testBinaryOperator::$52 +Alias (byte) idx#32 = (byte) idx#85 +Alias (byte) assertType::t1#24 = (byte~) testBinaryOperator::$55 +Alias (byte) idx#34 = (byte) idx#86 +Alias (byte) assertType::t1#25 = (byte~) testBinaryOperator::$58 +Alias (byte) idx#35 = (byte) idx#87 +Alias (byte) assertType::t1#26 = (byte~) testBinaryOperator::$61 +Alias (byte) idx#36 = (byte) idx#88 +Alias (byte) assertType::t1#27 = (byte~) testBinaryOperator::$64 +Alias (byte) idx#37 = (byte) idx#89 +Alias (byte) assertType::t1#28 = (byte~) testBinaryOperator::$67 +Alias (byte) idx#38 = (byte) idx#90 +Alias (byte) assertType::t1#29 = (byte~) testBinaryOperator::$70 +Alias (byte) idx#39 = (byte) idx#91 +Alias (byte) assertType::t1#30 = (byte~) testBinaryOperator::$73 +Alias (byte) idx#41 = (byte) idx#92 +Alias (byte) assertType::t1#31 = (byte~) testBinaryOperator::$76 +Alias (byte) idx#42 = (byte) idx#93 +Alias (byte) assertType::t1#32 = (byte~) testBinaryOperator::$79 +Alias (byte) idx#43 = (byte) idx#94 +Alias (byte) assertType::t1#33 = (byte~) testBinaryOperator::$82 +Alias (byte) idx#44 = (byte) idx#95 +Alias (byte) assertType::t1#34 = (byte~) testBinaryOperator::$85 +Alias (byte) idx#45 = (byte) idx#96 +Alias (byte) assertType::t1#35 = (byte~) testBinaryOperator::$88 +Alias (byte) idx#46 = (byte) idx#97 +Alias (byte) assertType::t1#36 = (byte~) testBinaryOperator::$91 +Alias (byte) idx#48 = (byte) idx#98 +Alias (byte) assertType::t1#37 = (byte~) testBinaryOperator::$94 +Alias (byte) idx#49 = (byte) idx#99 +Alias (byte) assertType::t1#38 = (byte~) testBinaryOperator::$97 +Alias (byte) idx#100 = (byte) idx#50 +Alias (byte) assertType::t1#39 = (byte~) testBinaryOperator::$100 +Alias (byte) idx#101 = (byte) idx#51 +Alias (byte) assertType::t1#40 = (byte~) testBinaryOperator::$103 +Alias (byte) idx#102 = (byte) idx#52 +Alias (byte) assertType::t1#41 = (byte~) testBinaryOperator::$106 +Alias (byte) idx#103 = (byte) idx#53 (byte) idx#104 (byte) idx#54 +Alias (byte) idx#105 = (byte) idx#111 (byte) idx#106 +Alias (byte) assertType::t1#42 = (byte) assertType::t1#44 (byte) assertType::t1#45 +Alias (byte) idx#108 = (byte) idx#55 (byte) idx#56 +Alias (byte) idx#0 = (byte) idx#112 +Alias (byte) idx#109 = (byte) idx#57 +Successful SSA optimization Pass2AliasElimination +Alias (byte) assertType::t1#42 = (byte) assertType::t1#43 +Alias (byte) idx#105 = (byte) idx#107 +Successful SSA optimization Pass2AliasElimination +Self Phi Eliminated (byte) idx#110 +Successful SSA optimization Pass2SelfPhiElimination +Redundant Phi (byte) idx#114 (byte) idx#0 +Redundant Phi (byte) idx#110 (byte) idx#114 +Redundant Phi (byte) idx#1 (byte) idx#10 +Redundant Phi (byte) idx#2 (byte) idx#103 +Redundant Phi (byte) idx#5 (byte) idx#108 +Redundant Phi (byte) idx#6 (byte) idx#108 +Redundant Phi (byte) idx#63 (byte) idx#108 +Redundant Phi (byte) idx#64 (byte) idx#108 +Redundant Phi (byte) idx#65 (byte) idx#108 +Redundant Phi (byte) idx#10 (byte) idx#108 +Redundant Phi (byte) idx#13 (byte) idx#108 +Redundant Phi (byte) idx#14 (byte) idx#108 +Redundant Phi (byte) idx#15 (byte) idx#108 +Redundant Phi (byte) idx#16 (byte) idx#108 +Redundant Phi (byte) idx#17 (byte) idx#108 +Redundant Phi (byte) idx#18 (byte) idx#108 +Redundant Phi (byte) idx#20 (byte) idx#108 +Redundant Phi (byte) idx#21 (byte) idx#108 +Redundant Phi (byte) idx#22 (byte) idx#108 +Redundant Phi (byte) idx#23 (byte) idx#108 +Redundant Phi (byte) idx#24 (byte) idx#108 +Redundant Phi (byte) idx#25 (byte) idx#108 +Redundant Phi (byte) idx#27 (byte) idx#108 +Redundant Phi (byte) idx#28 (byte) idx#108 +Redundant Phi (byte) idx#29 (byte) idx#108 +Redundant Phi (byte) idx#30 (byte) idx#108 +Redundant Phi (byte) idx#31 (byte) idx#108 +Redundant Phi (byte) idx#32 (byte) idx#108 +Redundant Phi (byte) idx#34 (byte) idx#108 +Redundant Phi (byte) idx#35 (byte) idx#108 +Redundant Phi (byte) idx#36 (byte) idx#108 +Redundant Phi (byte) idx#37 (byte) idx#108 +Redundant Phi (byte) idx#38 (byte) idx#108 +Redundant Phi (byte) idx#39 (byte) idx#108 +Redundant Phi (byte) idx#41 (byte) idx#108 +Redundant Phi (byte) idx#42 (byte) idx#108 +Redundant Phi (byte) idx#43 (byte) idx#108 +Redundant Phi (byte) idx#44 (byte) idx#108 +Redundant Phi (byte) idx#45 (byte) idx#108 +Redundant Phi (byte) idx#46 (byte) idx#108 +Redundant Phi (byte) idx#48 (byte) idx#108 +Redundant Phi (byte) idx#49 (byte) idx#108 +Redundant Phi (byte) idx#100 (byte) idx#108 +Redundant Phi (byte) idx#101 (byte) idx#108 +Redundant Phi (byte) idx#102 (byte) idx#108 +Redundant Phi (byte) idx#103 (byte) idx#108 +Redundant Phi (byte) idx#109 (byte) idx#2 +Successful SSA optimization Pass2RedundantPhiElimination +Simple Condition (bool~) main::$3 [12] if((byte*) main::s#1<(byte*~) main::$2) goto main::@1 +Simple Condition (bool~) assertType::$0 [290] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant right-side identified [2] (byte*) SCREEN#0 ← ((byte*)) (word) $400 +Constant right-side identified [3] (byte*) COLS#0 ← ((byte*)) (word) $d800 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) RED#0 = 2 +Constant (const byte) GREEN#0 = 5 +Constant (const byte*) SCREEN#0 = ((byte*))$400 +Constant (const byte*) COLS#0 = ((byte*))$d800 +Constant (const byte) idx#0 = 0 +Constant (const byte) idx#4 = 0 +Constant (const byte) assertType::t1#0 = TYPEID_BYTE +Constant (const byte) assertType::t2#0 = TYPEID_BYTE +Constant (const byte) assertType::t1#1 = TYPEID_SIGNED_BYTE +Constant (const byte) assertType::t2#1 = TYPEID_SIGNED_BYTE +Constant (const byte) assertType::t1#2 = TYPEID_WORD +Constant (const byte) assertType::t2#2 = TYPEID_WORD +Constant (const byte) assertType::t1#3 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#3 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t1#4 = TYPEID_DWORD +Constant (const byte) assertType::t2#4 = TYPEID_DWORD +Constant (const byte) assertType::t1#5 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#5 = TYPEID_SIGNED_DWORD +Constant (const byte) idx#12 = $28 +Constant (const byte) assertType::t1#6 = TYPEID_BYTE +Constant (const byte) assertType::t2#6 = TYPEID_BYTE +Constant (const byte) assertType::t1#7 = TYPEID_BYTE +Constant (const byte) assertType::t2#7 = TYPEID_BYTE +Constant (const byte) assertType::t1#8 = TYPEID_WORD +Constant (const byte) assertType::t2#8 = TYPEID_WORD +Constant (const byte) assertType::t1#9 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#9 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t1#10 = TYPEID_DWORD +Constant (const byte) assertType::t2#10 = TYPEID_DWORD +Constant (const byte) assertType::t1#11 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#11 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t1#12 = TYPEID_BYTE +Constant (const byte) assertType::t2#12 = TYPEID_BYTE +Constant (const byte) assertType::t1#13 = TYPEID_SIGNED_BYTE +Constant (const byte) assertType::t2#13 = TYPEID_SIGNED_BYTE +Constant (const byte) assertType::t1#14 = TYPEID_WORD +Constant (const byte) assertType::t2#14 = TYPEID_WORD +Constant (const byte) assertType::t1#15 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#15 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t1#16 = TYPEID_DWORD +Constant (const byte) assertType::t2#16 = TYPEID_DWORD +Constant (const byte) assertType::t1#17 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#17 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t1#18 = TYPEID_WORD +Constant (const byte) assertType::t2#18 = TYPEID_WORD +Constant (const byte) assertType::t1#19 = TYPEID_WORD +Constant (const byte) assertType::t2#19 = TYPEID_WORD +Constant (const byte) assertType::t1#20 = TYPEID_WORD +Constant (const byte) assertType::t2#20 = TYPEID_WORD +Constant (const byte) assertType::t1#21 = TYPEID_WORD +Constant (const byte) assertType::t2#21 = TYPEID_WORD +Constant (const byte) assertType::t1#22 = TYPEID_DWORD +Constant (const byte) assertType::t2#22 = TYPEID_DWORD +Constant (const byte) assertType::t1#23 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#23 = TYPEID_SIGNED_DWORD +Constant (const byte) idx#33 = $50 +Constant (const byte) assertType::t1#24 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#24 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t1#25 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#25 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t1#26 = TYPEID_WORD +Constant (const byte) assertType::t2#26 = TYPEID_WORD +Constant (const byte) assertType::t1#27 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#27 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t1#28 = TYPEID_DWORD +Constant (const byte) assertType::t2#28 = TYPEID_DWORD +Constant (const byte) assertType::t1#29 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#29 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t1#30 = TYPEID_DWORD +Constant (const byte) assertType::t2#30 = TYPEID_DWORD +Constant (const byte) assertType::t1#31 = TYPEID_DWORD +Constant (const byte) assertType::t2#31 = TYPEID_DWORD +Constant (const byte) assertType::t1#32 = TYPEID_DWORD +Constant (const byte) assertType::t2#32 = TYPEID_DWORD +Constant (const byte) assertType::t1#33 = TYPEID_DWORD +Constant (const byte) assertType::t2#33 = TYPEID_DWORD +Constant (const byte) assertType::t1#34 = TYPEID_DWORD +Constant (const byte) assertType::t2#34 = TYPEID_DWORD +Constant (const byte) assertType::t1#35 = TYPEID_DWORD +Constant (const byte) assertType::t2#35 = TYPEID_DWORD +Constant (const byte) assertType::t1#36 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#36 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t1#37 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#37 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t1#38 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#38 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t1#39 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#39 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t1#40 = TYPEID_DWORD +Constant (const byte) assertType::t2#40 = TYPEID_DWORD +Constant (const byte) assertType::t1#41 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#41 = TYPEID_SIGNED_DWORD +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte*) main::s#0 = SCREEN#0 +Successful SSA optimization Pass2ConstantIdentification +Eliminating unused constant (const byte) idx#0 +Successful SSA optimization PassNEliminateUnusedVars +Culled Empty Block (label) main::@4 +Culled Empty Block (label) testUnaryOperator::@6 +Culled Empty Block (label) testBinaryOperator::@36 +Culled Empty Block (label) @5 +Successful SSA optimization Pass2CullEmptyBlocks +Constant right-side identified [3] (byte*~) main::$2 ← (const byte*) SCREEN#0 + (word) $3e8 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte*) main::$2 = SCREEN#0+$3e8 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with var siblings (const byte*) main::s#0 +Inlining constant with var siblings (const byte) assertType::t1#0 +Inlining constant with var siblings (const byte) assertType::t2#0 +Inlining constant with var siblings (const byte) assertType::t1#1 +Inlining constant with var siblings (const byte) assertType::t2#1 +Inlining constant with var siblings (const byte) assertType::t1#2 +Inlining constant with var siblings (const byte) assertType::t2#2 +Inlining constant with var siblings (const byte) assertType::t1#3 +Inlining constant with var siblings (const byte) assertType::t2#3 +Inlining constant with var siblings (const byte) assertType::t1#4 +Inlining constant with var siblings (const byte) assertType::t2#4 +Inlining constant with var siblings (const byte) assertType::t1#5 +Inlining constant with var siblings (const byte) assertType::t2#5 +Inlining constant with var siblings (const byte) assertType::t1#6 +Inlining constant with var siblings (const byte) assertType::t2#6 +Inlining constant with var siblings (const byte) assertType::t1#7 +Inlining constant with var siblings (const byte) assertType::t2#7 +Inlining constant with var siblings (const byte) assertType::t1#8 +Inlining constant with var siblings (const byte) assertType::t2#8 +Inlining constant with var siblings (const byte) assertType::t1#9 +Inlining constant with var siblings (const byte) assertType::t2#9 +Inlining constant with var siblings (const byte) assertType::t1#10 +Inlining constant with var siblings (const byte) assertType::t2#10 +Inlining constant with var siblings (const byte) assertType::t1#11 +Inlining constant with var siblings (const byte) assertType::t2#11 +Inlining constant with var siblings (const byte) assertType::t1#12 +Inlining constant with var siblings (const byte) assertType::t2#12 +Inlining constant with var siblings (const byte) assertType::t1#13 +Inlining constant with var siblings (const byte) assertType::t2#13 +Inlining constant with var siblings (const byte) assertType::t1#14 +Inlining constant with var siblings (const byte) assertType::t2#14 +Inlining constant with var siblings (const byte) assertType::t1#15 +Inlining constant with var siblings (const byte) assertType::t2#15 +Inlining constant with var siblings (const byte) assertType::t1#16 +Inlining constant with var siblings (const byte) assertType::t2#16 +Inlining constant with var siblings (const byte) assertType::t1#17 +Inlining constant with var siblings (const byte) assertType::t2#17 +Inlining constant with var siblings (const byte) assertType::t1#18 +Inlining constant with var siblings (const byte) assertType::t2#18 +Inlining constant with var siblings (const byte) assertType::t1#19 +Inlining constant with var siblings (const byte) assertType::t2#19 +Inlining constant with var siblings (const byte) assertType::t1#20 +Inlining constant with var siblings (const byte) assertType::t2#20 +Inlining constant with var siblings (const byte) assertType::t1#21 +Inlining constant with var siblings (const byte) assertType::t2#21 +Inlining constant with var siblings (const byte) assertType::t1#22 +Inlining constant with var siblings (const byte) assertType::t2#22 +Inlining constant with var siblings (const byte) assertType::t1#23 +Inlining constant with var siblings (const byte) assertType::t2#23 +Inlining constant with var siblings (const byte) assertType::t1#24 +Inlining constant with var siblings (const byte) assertType::t2#24 +Inlining constant with var siblings (const byte) assertType::t1#25 +Inlining constant with var siblings (const byte) assertType::t2#25 +Inlining constant with var siblings (const byte) assertType::t1#26 +Inlining constant with var siblings (const byte) assertType::t2#26 +Inlining constant with var siblings (const byte) assertType::t1#27 +Inlining constant with var siblings (const byte) assertType::t2#27 +Inlining constant with var siblings (const byte) assertType::t1#28 +Inlining constant with var siblings (const byte) assertType::t2#28 +Inlining constant with var siblings (const byte) assertType::t1#29 +Inlining constant with var siblings (const byte) assertType::t2#29 +Inlining constant with var siblings (const byte) assertType::t1#30 +Inlining constant with var siblings (const byte) assertType::t2#30 +Inlining constant with var siblings (const byte) assertType::t1#31 +Inlining constant with var siblings (const byte) assertType::t2#31 +Inlining constant with var siblings (const byte) assertType::t1#32 +Inlining constant with var siblings (const byte) assertType::t2#32 +Inlining constant with var siblings (const byte) assertType::t1#33 +Inlining constant with var siblings (const byte) assertType::t2#33 +Inlining constant with var siblings (const byte) assertType::t1#34 +Inlining constant with var siblings (const byte) assertType::t2#34 +Inlining constant with var siblings (const byte) assertType::t1#35 +Inlining constant with var siblings (const byte) assertType::t2#35 +Inlining constant with var siblings (const byte) assertType::t1#36 +Inlining constant with var siblings (const byte) assertType::t2#36 +Inlining constant with var siblings (const byte) assertType::t1#37 +Inlining constant with var siblings (const byte) assertType::t2#37 +Inlining constant with var siblings (const byte) assertType::t1#38 +Inlining constant with var siblings (const byte) assertType::t2#38 +Inlining constant with var siblings (const byte) assertType::t1#39 +Inlining constant with var siblings (const byte) assertType::t2#39 +Inlining constant with var siblings (const byte) assertType::t1#40 +Inlining constant with var siblings (const byte) assertType::t2#40 +Inlining constant with var siblings (const byte) assertType::t1#41 +Inlining constant with var siblings (const byte) assertType::t2#41 +Inlining constant with var siblings (const byte) idx#4 +Inlining constant with var siblings (const byte) idx#12 +Inlining constant with var siblings (const byte) idx#33 +Constant inlined assertType::t2#5 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#6 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#7 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#8 = (const byte) TYPEID_WORD +Constant inlined idx#33 = (byte) $50 +Constant inlined assertType::t2#9 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#31 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#30 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#21 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#33 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#20 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#32 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#23 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#35 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#22 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#34 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#25 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#37 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined idx#4 = (byte) 0 +Constant inlined assertType::t1#24 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#36 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#27 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#39 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#0 = (const byte) TYPEID_BYTE +Constant inlined assertType::t1#26 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#38 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#1 = (const byte) TYPEID_SIGNED_BYTE +Constant inlined assertType::t1#29 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#2 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#28 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#3 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#4 = (const byte) TYPEID_DWORD +Constant inlined main::s#0 = (const byte*) SCREEN#0 +Constant inlined assertType::t2#20 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#10 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#22 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#21 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#12 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#24 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t1#11 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#23 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#14 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#26 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#13 = (const byte) TYPEID_SIGNED_BYTE +Constant inlined assertType::t2#25 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t1#16 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#28 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#27 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t1#18 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#17 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#29 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#19 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#6 = (const byte) TYPEID_BYTE +Constant inlined assertType::t1#7 = (const byte) TYPEID_BYTE +Constant inlined assertType::t1#8 = (const byte) TYPEID_WORD +Constant inlined idx#12 = (byte) $28 +Constant inlined assertType::t1#9 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t1#41 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#40 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#11 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#10 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#13 = (const byte) TYPEID_SIGNED_BYTE +Constant inlined assertType::t2#12 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#14 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#0 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#17 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#1 = (const byte) TYPEID_SIGNED_BYTE +Constant inlined assertType::t2#16 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#2 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#19 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#3 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#18 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#4 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#5 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#40 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#30 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#41 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#32 = (const byte) TYPEID_DWORD +Constant inlined main::$2 = (const byte*) SCREEN#0+(word) $3e8 +Constant inlined assertType::t1#31 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#34 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#33 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#36 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#35 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#38 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#37 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#39 = (const byte) TYPEID_SIGNED_DWORD +Successful SSA optimization Pass2ConstantInlining +Added new block during phi lifting main::@5(between main::@1 and main::@1) +Adding NOP phi() at start of @begin +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::@2 +Adding NOP phi() at start of main::@3 +Adding NOP phi() at start of testBinaryOperator +Adding NOP phi() at start of testBinaryOperator::@18 +Adding NOP phi() at start of testUnaryOperator +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to testUnaryOperator:10 testBinaryOperator:12 +Calls in [testBinaryOperator] to assertType:16 assertType:18 assertType:20 assertType:22 assertType:24 assertType:26 assertType:29 assertType:31 assertType:33 assertType:35 assertType:37 assertType:39 assertType:42 assertType:44 assertType:46 assertType:48 assertType:50 assertType:52 assertType:54 assertType:56 assertType:58 assertType:60 assertType:62 assertType:64 assertType:67 assertType:69 assertType:71 assertType:73 assertType:75 assertType:77 assertType:80 assertType:82 assertType:84 assertType:86 assertType:88 assertType:90 +Calls in [testUnaryOperator] to assertType:100 assertType:102 assertType:104 assertType:106 assertType:108 assertType:110 + +Created 4 initial phi equivalence classes +Coalesced [14] main::s#3 ← main::s#1 +Coalesced [17] idx#115 ← idx#108 +Coalesced (already) [19] idx#125 ← idx#108 +Coalesced (already) [21] idx#136 ← idx#108 +Coalesced (already) [23] idx#143 ← idx#108 +Coalesced (already) [25] idx#144 ← idx#108 +Coalesced [28] idx#145 ← idx#19 +Coalesced (already) [30] idx#146 ← idx#108 +Coalesced (already) [32] idx#147 ← idx#108 +Coalesced (already) [34] idx#148 ← idx#108 +Coalesced (already) [36] idx#116 ← idx#108 +Coalesced (already) [38] idx#117 ← idx#108 +Coalesced [41] idx#118 ← idx#26 +Coalesced (already) [43] idx#119 ← idx#108 +Coalesced (already) [45] idx#120 ← idx#108 +Coalesced (already) [47] idx#121 ← idx#108 +Coalesced (already) [49] idx#122 ← idx#108 +Coalesced (already) [51] idx#123 ← idx#108 +Coalesced (already) [55] idx#124 ← idx#108 +Coalesced (already) [57] idx#126 ← idx#108 +Coalesced (already) [59] idx#127 ← idx#108 +Coalesced (already) [61] idx#128 ← idx#108 +Coalesced (already) [63] idx#129 ← idx#108 +Coalesced [66] idx#130 ← idx#40 +Coalesced (already) [68] idx#131 ← idx#108 +Coalesced (already) [70] idx#132 ← idx#108 +Coalesced (already) [72] idx#133 ← idx#108 +Coalesced (already) [74] idx#134 ← idx#108 +Coalesced (already) [76] idx#135 ← idx#108 +Coalesced [79] idx#137 ← idx#47 +Coalesced (already) [81] idx#138 ← idx#108 +Coalesced (already) [83] idx#139 ← idx#108 +Coalesced (already) [85] idx#140 ← idx#108 +Coalesced (already) [87] idx#141 ← idx#108 +Coalesced (already) [89] idx#142 ← idx#108 +Coalesced (already) [101] idx#149 ← idx#108 +Coalesced (already) [103] idx#150 ← idx#108 +Coalesced (already) [105] idx#151 ← idx#108 +Coalesced (already) [107] idx#152 ← idx#108 +Coalesced (already) [109] idx#153 ← idx#108 +Coalesced down to 4 phi equivalence classes +Culled Empty Block (label) main::@5 +Renumbering block @4 to @1 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@2 +Adding NOP phi() at start of main::@3 +Adding NOP phi() at start of testBinaryOperator +Adding NOP phi() at start of testBinaryOperator::@1 +Adding NOP phi() at start of testBinaryOperator::@2 +Adding NOP phi() at start of testBinaryOperator::@3 +Adding NOP phi() at start of testBinaryOperator::@4 +Adding NOP phi() at start of testBinaryOperator::@5 +Adding NOP phi() at start of testBinaryOperator::@7 +Adding NOP phi() at start of testBinaryOperator::@8 +Adding NOP phi() at start of testBinaryOperator::@9 +Adding NOP phi() at start of testBinaryOperator::@10 +Adding NOP phi() at start of testBinaryOperator::@11 +Adding NOP phi() at start of testBinaryOperator::@13 +Adding NOP phi() at start of testBinaryOperator::@14 +Adding NOP phi() at start of testBinaryOperator::@15 +Adding NOP phi() at start of testBinaryOperator::@16 +Adding NOP phi() at start of testBinaryOperator::@17 +Adding NOP phi() at start of testBinaryOperator::@18 +Adding NOP phi() at start of testBinaryOperator::@19 +Adding NOP phi() at start of testBinaryOperator::@20 +Adding NOP phi() at start of testBinaryOperator::@21 +Adding NOP phi() at start of testBinaryOperator::@22 +Adding NOP phi() at start of testBinaryOperator::@23 +Adding NOP phi() at start of testBinaryOperator::@25 +Adding NOP phi() at start of testBinaryOperator::@26 +Adding NOP phi() at start of testBinaryOperator::@27 +Adding NOP phi() at start of testBinaryOperator::@28 +Adding NOP phi() at start of testBinaryOperator::@29 +Adding NOP phi() at start of testBinaryOperator::@31 +Adding NOP phi() at start of testBinaryOperator::@32 +Adding NOP phi() at start of testBinaryOperator::@33 +Adding NOP phi() at start of testBinaryOperator::@34 +Adding NOP phi() at start of testBinaryOperator::@35 +Adding NOP phi() at start of testUnaryOperator +Adding NOP phi() at start of testUnaryOperator::@1 +Adding NOP phi() at start of testUnaryOperator::@2 +Adding NOP phi() at start of testUnaryOperator::@3 +Adding NOP phi() at start of testUnaryOperator::@4 +Adding NOP phi() at start of testUnaryOperator::@5 + +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::@1 + [5] (byte*) main::s#2 ← phi( main/(const byte*) SCREEN#0 main::@1/(byte*) main::s#1 ) + [6] *((byte*) main::s#2) ← (byte) ' ' + [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 + [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] phi() + [10] call testUnaryOperator + to:main::@3 +main::@3: scope:[main] from main::@2 + [11] phi() + [12] call testBinaryOperator + to:main::@return +main::@return: scope:[main] from main::@3 + [13] return + to:@return +testBinaryOperator: scope:[testBinaryOperator] from main::@3 + [14] phi() + [15] call assertType + to:testBinaryOperator::@1 +testBinaryOperator::@1: scope:[testBinaryOperator] from testBinaryOperator + [16] phi() + [17] call assertType + to:testBinaryOperator::@2 +testBinaryOperator::@2: scope:[testBinaryOperator] from testBinaryOperator::@1 + [18] phi() + [19] call assertType + to:testBinaryOperator::@3 +testBinaryOperator::@3: scope:[testBinaryOperator] from testBinaryOperator::@2 + [20] phi() + [21] call assertType + to:testBinaryOperator::@4 +testBinaryOperator::@4: scope:[testBinaryOperator] from testBinaryOperator::@3 + [22] phi() + [23] call assertType + to:testBinaryOperator::@5 +testBinaryOperator::@5: scope:[testBinaryOperator] from testBinaryOperator::@4 + [24] phi() + [25] call assertType + to:testBinaryOperator::@6 +testBinaryOperator::@6: scope:[testBinaryOperator] from testBinaryOperator::@5 + [26] (byte) idx#19 ← ++ (byte) idx#108 + [27] call assertType + to:testBinaryOperator::@7 +testBinaryOperator::@7: scope:[testBinaryOperator] from testBinaryOperator::@6 + [28] phi() + [29] call assertType + to:testBinaryOperator::@8 +testBinaryOperator::@8: scope:[testBinaryOperator] from testBinaryOperator::@7 + [30] phi() + [31] call assertType + to:testBinaryOperator::@9 +testBinaryOperator::@9: scope:[testBinaryOperator] from testBinaryOperator::@8 + [32] phi() + [33] call assertType + to:testBinaryOperator::@10 +testBinaryOperator::@10: scope:[testBinaryOperator] from testBinaryOperator::@9 + [34] phi() + [35] call assertType + to:testBinaryOperator::@11 +testBinaryOperator::@11: scope:[testBinaryOperator] from testBinaryOperator::@10 + [36] phi() + [37] call assertType + to:testBinaryOperator::@12 +testBinaryOperator::@12: scope:[testBinaryOperator] from testBinaryOperator::@11 + [38] (byte) idx#26 ← ++ (byte) idx#108 + [39] call assertType + to:testBinaryOperator::@13 +testBinaryOperator::@13: scope:[testBinaryOperator] from testBinaryOperator::@12 + [40] phi() + [41] call assertType + to:testBinaryOperator::@14 +testBinaryOperator::@14: scope:[testBinaryOperator] from testBinaryOperator::@13 + [42] phi() + [43] call assertType + to:testBinaryOperator::@15 +testBinaryOperator::@15: scope:[testBinaryOperator] from testBinaryOperator::@14 + [44] phi() + [45] call assertType + to:testBinaryOperator::@16 +testBinaryOperator::@16: scope:[testBinaryOperator] from testBinaryOperator::@15 + [46] phi() + [47] call assertType + to:testBinaryOperator::@17 +testBinaryOperator::@17: scope:[testBinaryOperator] from testBinaryOperator::@16 + [48] phi() + [49] call assertType + to:testBinaryOperator::@18 +testBinaryOperator::@18: scope:[testBinaryOperator] from testBinaryOperator::@17 + [50] phi() + [51] call assertType + to:testBinaryOperator::@19 +testBinaryOperator::@19: scope:[testBinaryOperator] from testBinaryOperator::@18 + [52] phi() + [53] call assertType + to:testBinaryOperator::@20 +testBinaryOperator::@20: scope:[testBinaryOperator] from testBinaryOperator::@19 + [54] phi() + [55] call assertType + to:testBinaryOperator::@21 +testBinaryOperator::@21: scope:[testBinaryOperator] from testBinaryOperator::@20 + [56] phi() + [57] call assertType + to:testBinaryOperator::@22 +testBinaryOperator::@22: scope:[testBinaryOperator] from testBinaryOperator::@21 + [58] phi() + [59] call assertType + to:testBinaryOperator::@23 +testBinaryOperator::@23: scope:[testBinaryOperator] from testBinaryOperator::@22 + [60] phi() + [61] call assertType + to:testBinaryOperator::@24 +testBinaryOperator::@24: scope:[testBinaryOperator] from testBinaryOperator::@23 + [62] (byte) idx#40 ← ++ (byte) idx#108 + [63] call assertType + to:testBinaryOperator::@25 +testBinaryOperator::@25: scope:[testBinaryOperator] from testBinaryOperator::@24 + [64] phi() + [65] call assertType + to:testBinaryOperator::@26 +testBinaryOperator::@26: scope:[testBinaryOperator] from testBinaryOperator::@25 + [66] phi() + [67] call assertType + to:testBinaryOperator::@27 +testBinaryOperator::@27: scope:[testBinaryOperator] from testBinaryOperator::@26 + [68] phi() + [69] call assertType + to:testBinaryOperator::@28 +testBinaryOperator::@28: scope:[testBinaryOperator] from testBinaryOperator::@27 + [70] phi() + [71] call assertType + to:testBinaryOperator::@29 +testBinaryOperator::@29: scope:[testBinaryOperator] from testBinaryOperator::@28 + [72] phi() + [73] call assertType + to:testBinaryOperator::@30 +testBinaryOperator::@30: scope:[testBinaryOperator] from testBinaryOperator::@29 + [74] (byte) idx#47 ← ++ (byte) idx#108 + [75] call assertType + to:testBinaryOperator::@31 +testBinaryOperator::@31: scope:[testBinaryOperator] from testBinaryOperator::@30 + [76] phi() + [77] call assertType + to:testBinaryOperator::@32 +testBinaryOperator::@32: scope:[testBinaryOperator] from testBinaryOperator::@31 + [78] phi() + [79] call assertType + to:testBinaryOperator::@33 +testBinaryOperator::@33: scope:[testBinaryOperator] from testBinaryOperator::@32 + [80] phi() + [81] call assertType + to:testBinaryOperator::@34 +testBinaryOperator::@34: scope:[testBinaryOperator] from testBinaryOperator::@33 + [82] phi() + [83] call assertType + to:testBinaryOperator::@35 +testBinaryOperator::@35: scope:[testBinaryOperator] from testBinaryOperator::@34 + [84] phi() + [85] call assertType + to:testBinaryOperator::@return +testBinaryOperator::@return: scope:[testBinaryOperator] from testBinaryOperator::@35 + [86] return + to:@return +assertType: scope:[assertType] from testBinaryOperator testBinaryOperator::@1 testBinaryOperator::@10 testBinaryOperator::@11 testBinaryOperator::@12 testBinaryOperator::@13 testBinaryOperator::@14 testBinaryOperator::@15 testBinaryOperator::@16 testBinaryOperator::@17 testBinaryOperator::@18 testBinaryOperator::@19 testBinaryOperator::@2 testBinaryOperator::@20 testBinaryOperator::@21 testBinaryOperator::@22 testBinaryOperator::@23 testBinaryOperator::@24 testBinaryOperator::@25 testBinaryOperator::@26 testBinaryOperator::@27 testBinaryOperator::@28 testBinaryOperator::@29 testBinaryOperator::@3 testBinaryOperator::@30 testBinaryOperator::@31 testBinaryOperator::@32 testBinaryOperator::@33 testBinaryOperator::@34 testBinaryOperator::@35 testBinaryOperator::@4 testBinaryOperator::@5 testBinaryOperator::@6 testBinaryOperator::@7 testBinaryOperator::@8 testBinaryOperator::@9 testUnaryOperator testUnaryOperator::@1 testUnaryOperator::@2 testUnaryOperator::@3 testUnaryOperator::@4 testUnaryOperator::@5 + [87] (byte) idx#105 ← phi( testBinaryOperator/(byte) $28 testBinaryOperator::@1/(byte) idx#108 testBinaryOperator::@10/(byte) idx#108 testBinaryOperator::@11/(byte) idx#108 testBinaryOperator::@12/(byte) idx#26 testBinaryOperator::@13/(byte) idx#108 testBinaryOperator::@14/(byte) idx#108 testBinaryOperator::@15/(byte) idx#108 testBinaryOperator::@16/(byte) idx#108 testBinaryOperator::@17/(byte) idx#108 testBinaryOperator::@18/(byte) $50 testBinaryOperator::@19/(byte) idx#108 testBinaryOperator::@2/(byte) idx#108 testBinaryOperator::@20/(byte) idx#108 testBinaryOperator::@21/(byte) idx#108 testBinaryOperator::@22/(byte) idx#108 testBinaryOperator::@23/(byte) idx#108 testBinaryOperator::@24/(byte) idx#40 testBinaryOperator::@25/(byte) idx#108 testBinaryOperator::@26/(byte) idx#108 testBinaryOperator::@27/(byte) idx#108 testBinaryOperator::@28/(byte) idx#108 testBinaryOperator::@29/(byte) idx#108 testBinaryOperator::@3/(byte) idx#108 testBinaryOperator::@30/(byte) idx#47 testBinaryOperator::@31/(byte) idx#108 testBinaryOperator::@32/(byte) idx#108 testBinaryOperator::@33/(byte) idx#108 testBinaryOperator::@34/(byte) idx#108 testBinaryOperator::@35/(byte) idx#108 testBinaryOperator::@4/(byte) idx#108 testBinaryOperator::@5/(byte) idx#108 testBinaryOperator::@6/(byte) idx#19 testBinaryOperator::@7/(byte) idx#108 testBinaryOperator::@8/(byte) idx#108 testBinaryOperator::@9/(byte) idx#108 testUnaryOperator/(byte) 0 testUnaryOperator::@1/(byte) idx#108 testUnaryOperator::@2/(byte) idx#108 testUnaryOperator::@3/(byte) idx#108 testUnaryOperator::@4/(byte) idx#108 testUnaryOperator::@5/(byte) idx#108 ) + [87] (byte) assertType::t2#42 ← phi( testBinaryOperator/(const byte) TYPEID_BYTE testBinaryOperator::@1/(const byte) TYPEID_BYTE testBinaryOperator::@10/(const byte) TYPEID_DWORD testBinaryOperator::@11/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@12/(const byte) TYPEID_WORD testBinaryOperator::@13/(const byte) TYPEID_WORD testBinaryOperator::@14/(const byte) TYPEID_WORD testBinaryOperator::@15/(const byte) TYPEID_WORD testBinaryOperator::@16/(const byte) TYPEID_DWORD testBinaryOperator::@17/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@18/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@19/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@2/(const byte) TYPEID_WORD testBinaryOperator::@20/(const byte) TYPEID_WORD testBinaryOperator::@21/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@22/(const byte) TYPEID_DWORD testBinaryOperator::@23/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@24/(const byte) TYPEID_DWORD testBinaryOperator::@25/(const byte) TYPEID_DWORD testBinaryOperator::@26/(const byte) TYPEID_DWORD testBinaryOperator::@27/(const byte) TYPEID_DWORD testBinaryOperator::@28/(const byte) TYPEID_DWORD testBinaryOperator::@29/(const byte) TYPEID_DWORD testBinaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@30/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@31/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@32/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@33/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@34/(const byte) TYPEID_DWORD testBinaryOperator::@35/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@4/(const byte) TYPEID_DWORD testBinaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@6/(const byte) TYPEID_BYTE testBinaryOperator::@7/(const byte) TYPEID_SIGNED_BYTE testBinaryOperator::@8/(const byte) TYPEID_WORD testBinaryOperator::@9/(const byte) TYPEID_SIGNED_WORD testUnaryOperator/(const byte) TYPEID_BYTE testUnaryOperator::@1/(const byte) TYPEID_SIGNED_BYTE testUnaryOperator::@2/(const byte) TYPEID_WORD testUnaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testUnaryOperator::@4/(const byte) TYPEID_DWORD testUnaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD ) + [87] (byte) assertType::t1#42 ← phi( testBinaryOperator/(const byte) TYPEID_BYTE testBinaryOperator::@1/(const byte) TYPEID_BYTE testBinaryOperator::@10/(const byte) TYPEID_DWORD testBinaryOperator::@11/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@12/(const byte) TYPEID_WORD testBinaryOperator::@13/(const byte) TYPEID_WORD testBinaryOperator::@14/(const byte) TYPEID_WORD testBinaryOperator::@15/(const byte) TYPEID_WORD testBinaryOperator::@16/(const byte) TYPEID_DWORD testBinaryOperator::@17/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@18/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@19/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@2/(const byte) TYPEID_WORD testBinaryOperator::@20/(const byte) TYPEID_WORD testBinaryOperator::@21/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@22/(const byte) TYPEID_DWORD testBinaryOperator::@23/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@24/(const byte) TYPEID_DWORD testBinaryOperator::@25/(const byte) TYPEID_DWORD testBinaryOperator::@26/(const byte) TYPEID_DWORD testBinaryOperator::@27/(const byte) TYPEID_DWORD testBinaryOperator::@28/(const byte) TYPEID_DWORD testBinaryOperator::@29/(const byte) TYPEID_DWORD testBinaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@30/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@31/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@32/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@33/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@34/(const byte) TYPEID_DWORD testBinaryOperator::@35/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@4/(const byte) TYPEID_DWORD testBinaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@6/(const byte) TYPEID_BYTE testBinaryOperator::@7/(const byte) TYPEID_SIGNED_BYTE testBinaryOperator::@8/(const byte) TYPEID_WORD testBinaryOperator::@9/(const byte) TYPEID_SIGNED_WORD testUnaryOperator/(const byte) TYPEID_BYTE testUnaryOperator::@1/(const byte) TYPEID_SIGNED_BYTE testUnaryOperator::@2/(const byte) TYPEID_WORD testUnaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testUnaryOperator::@4/(const byte) TYPEID_DWORD testUnaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD ) + [88] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1 + to:assertType::@3 +assertType::@3: scope:[assertType] from assertType + [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 + to:assertType::@2 +assertType::@2: scope:[assertType] from assertType::@1 assertType::@3 + [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 + [91] (byte) idx#108 ← ++ (byte) idx#105 + to:assertType::@return +assertType::@return: scope:[assertType] from assertType::@2 + [92] return + to:@return +assertType::@1: scope:[assertType] from assertType + [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 + to:assertType::@2 +testUnaryOperator: scope:[testUnaryOperator] from main::@2 + [94] phi() + [95] call assertType + to:testUnaryOperator::@1 +testUnaryOperator::@1: scope:[testUnaryOperator] from testUnaryOperator + [96] phi() + [97] call assertType + to:testUnaryOperator::@2 +testUnaryOperator::@2: scope:[testUnaryOperator] from testUnaryOperator::@1 + [98] phi() + [99] call assertType + to:testUnaryOperator::@3 +testUnaryOperator::@3: scope:[testUnaryOperator] from testUnaryOperator::@2 + [100] phi() + [101] call assertType + to:testUnaryOperator::@4 +testUnaryOperator::@4: scope:[testUnaryOperator] from testUnaryOperator::@3 + [102] phi() + [103] call assertType + to:testUnaryOperator::@5 +testUnaryOperator::@5: scope:[testUnaryOperator] from testUnaryOperator::@4 + [104] phi() + [105] call assertType + to:testUnaryOperator::@return +testUnaryOperator::@return: scope:[testUnaryOperator] from testUnaryOperator::@5 + [106] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte*) COLS +(byte) GREEN +(byte) RED +(byte*) SCREEN +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(byte) assertType::t1 +(byte) assertType::t1#42 1.0 +(byte) assertType::t2 +(byte) assertType::t2#42 2.0 +(byte) idx +(byte) idx#105 17.200000000000003 +(byte) idx#108 1.0526315789473677 +(byte) idx#19 4.0 +(byte) idx#26 4.0 +(byte) idx#40 4.0 +(byte) idx#47 4.0 +(void()) main() +(byte*) main::s +(byte*) main::s#1 16.5 +(byte*) main::s#2 16.5 +(void()) testBinaryOperator() +(void()) testUnaryOperator() + +Initial phi equivalence classes +[ main::s#2 main::s#1 ] +[ assertType::t1#42 ] +[ assertType::t2#42 ] +[ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] +Complete equivalence classes +[ main::s#2 main::s#1 ] +[ assertType::t1#42 ] +[ assertType::t2#42 ] +[ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] +Allocated zp ZP_WORD:2 [ main::s#2 main::s#1 ] +Allocated zp ZP_BYTE:4 [ assertType::t1#42 ] +Allocated zp ZP_BYTE:5 [ assertType::t2#42 ] +Allocated zp ZP_BYTE:6 [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] + +INITIAL ASM +//SEG0 File Comments +// Tests different integer literal types +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const TYPEID_BYTE = 1 + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_WORD = 3 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_DWORD = 5 + .const TYPEID_SIGNED_DWORD = 6 + .const RED = 2 + .const GREEN = 5 + .label SCREEN = $400 + .label COLS = $d800 + .label idx = 6 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG9 @end +bend: +//SEG10 main +main: { + .label s = 2 + //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG12 [5] phi (byte*) main::s#2 = (const byte*) SCREEN#0 [phi:main->main::@1#0] -- pbuz1=pbuc1 + lda #<SCREEN + sta s + lda #>SCREEN + sta s+1 + jmp b1 + //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy + jmp b1 + //SEG15 main::@1 + b1: + //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 + lda #' ' + ldy #0 + sta (s),y + //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 + inc s + bne !+ + inc s+1 + !: + //SEG18 [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 + lda s+1 + cmp #>SCREEN+$3e8 + bcc b1_from_b1 + bne !+ + lda s + cmp #<SCREEN+$3e8 + bcc b1_from_b1 + !: + //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + jmp b2 + //SEG20 main::@2 + b2: + //SEG21 [10] call testUnaryOperator + //SEG22 [94] phi from main::@2 to testUnaryOperator [phi:main::@2->testUnaryOperator] + testUnaryOperator_from_b2: + jsr testUnaryOperator + //SEG23 [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + b3_from_b2: + jmp b3 + //SEG24 main::@3 + b3: + //SEG25 [12] call testBinaryOperator + //SEG26 [14] phi from main::@3 to testBinaryOperator [phi:main::@3->testBinaryOperator] + testBinaryOperator_from_b3: + jsr testBinaryOperator + jmp breturn + //SEG27 main::@return + breturn: + //SEG28 [13] return + rts +} +//SEG29 testBinaryOperator +testBinaryOperator: { + //SEG30 [15] call assertType + //SEG31 [87] phi from testBinaryOperator to assertType [phi:testBinaryOperator->assertType] + assertType_from_testBinaryOperator: + //SEG32 [87] phi (byte) idx#105 = (byte) $28 [phi:testBinaryOperator->assertType#0] -- vbuz1=vbuc1 + lda #$28 + sta idx + //SEG33 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG34 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG35 [16] phi from testBinaryOperator to testBinaryOperator::@1 [phi:testBinaryOperator->testBinaryOperator::@1] + b1_from_testBinaryOperator: + jmp b1 + //SEG36 testBinaryOperator::@1 + b1: + //SEG37 [17] call assertType + //SEG38 [87] phi from testBinaryOperator::@1 to assertType [phi:testBinaryOperator::@1->assertType] + assertType_from_b1: + //SEG39 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@1->assertType#0] -- register_copy + //SEG40 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG41 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG42 [18] phi from testBinaryOperator::@1 to testBinaryOperator::@2 [phi:testBinaryOperator::@1->testBinaryOperator::@2] + b2_from_b1: + jmp b2 + //SEG43 testBinaryOperator::@2 + b2: + //SEG44 [19] call assertType + //SEG45 [87] phi from testBinaryOperator::@2 to assertType [phi:testBinaryOperator::@2->assertType] + assertType_from_b2: + //SEG46 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@2->assertType#0] -- register_copy + //SEG47 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG48 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG49 [20] phi from testBinaryOperator::@2 to testBinaryOperator::@3 [phi:testBinaryOperator::@2->testBinaryOperator::@3] + b3_from_b2: + jmp b3 + //SEG50 testBinaryOperator::@3 + b3: + //SEG51 [21] call assertType + //SEG52 [87] phi from testBinaryOperator::@3 to assertType [phi:testBinaryOperator::@3->assertType] + assertType_from_b3: + //SEG53 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@3->assertType#0] -- register_copy + //SEG54 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG55 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG56 [22] phi from testBinaryOperator::@3 to testBinaryOperator::@4 [phi:testBinaryOperator::@3->testBinaryOperator::@4] + b4_from_b3: + jmp b4 + //SEG57 testBinaryOperator::@4 + b4: + //SEG58 [23] call assertType + //SEG59 [87] phi from testBinaryOperator::@4 to assertType [phi:testBinaryOperator::@4->assertType] + assertType_from_b4: + //SEG60 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@4->assertType#0] -- register_copy + //SEG61 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG62 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG63 [24] phi from testBinaryOperator::@4 to testBinaryOperator::@5 [phi:testBinaryOperator::@4->testBinaryOperator::@5] + b5_from_b4: + jmp b5 + //SEG64 testBinaryOperator::@5 + b5: + //SEG65 [25] call assertType + //SEG66 [87] phi from testBinaryOperator::@5 to assertType [phi:testBinaryOperator::@5->assertType] + assertType_from_b5: + //SEG67 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@5->assertType#0] -- register_copy + //SEG68 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG69 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + jmp b6 + //SEG70 testBinaryOperator::@6 + b6: + //SEG71 [26] (byte) idx#19 ← ++ (byte) idx#108 -- vbuz1=_inc_vbuz1 + inc idx + //SEG72 [27] call assertType + //SEG73 [87] phi from testBinaryOperator::@6 to assertType [phi:testBinaryOperator::@6->assertType] + assertType_from_b6: + //SEG74 [87] phi (byte) idx#105 = (byte) idx#19 [phi:testBinaryOperator::@6->assertType#0] -- register_copy + //SEG75 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG76 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG77 [28] phi from testBinaryOperator::@6 to testBinaryOperator::@7 [phi:testBinaryOperator::@6->testBinaryOperator::@7] + b7_from_b6: + jmp b7 + //SEG78 testBinaryOperator::@7 + b7: + //SEG79 [29] call assertType + //SEG80 [87] phi from testBinaryOperator::@7 to assertType [phi:testBinaryOperator::@7->assertType] + assertType_from_b7: + //SEG81 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@7->assertType#0] -- register_copy + //SEG82 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG83 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t1 + jsr assertType + //SEG84 [30] phi from testBinaryOperator::@7 to testBinaryOperator::@8 [phi:testBinaryOperator::@7->testBinaryOperator::@8] + b8_from_b7: + jmp b8 + //SEG85 testBinaryOperator::@8 + b8: + //SEG86 [31] call assertType + //SEG87 [87] phi from testBinaryOperator::@8 to assertType [phi:testBinaryOperator::@8->assertType] + assertType_from_b8: + //SEG88 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@8->assertType#0] -- register_copy + //SEG89 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG90 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG91 [32] phi from testBinaryOperator::@8 to testBinaryOperator::@9 [phi:testBinaryOperator::@8->testBinaryOperator::@9] + b9_from_b8: + jmp b9 + //SEG92 testBinaryOperator::@9 + b9: + //SEG93 [33] call assertType + //SEG94 [87] phi from testBinaryOperator::@9 to assertType [phi:testBinaryOperator::@9->assertType] + assertType_from_b9: + //SEG95 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@9->assertType#0] -- register_copy + //SEG96 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG97 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG98 [34] phi from testBinaryOperator::@9 to testBinaryOperator::@10 [phi:testBinaryOperator::@9->testBinaryOperator::@10] + b10_from_b9: + jmp b10 + //SEG99 testBinaryOperator::@10 + b10: + //SEG100 [35] call assertType + //SEG101 [87] phi from testBinaryOperator::@10 to assertType [phi:testBinaryOperator::@10->assertType] + assertType_from_b10: + //SEG102 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@10->assertType#0] -- register_copy + //SEG103 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG104 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG105 [36] phi from testBinaryOperator::@10 to testBinaryOperator::@11 [phi:testBinaryOperator::@10->testBinaryOperator::@11] + b11_from_b10: + jmp b11 + //SEG106 testBinaryOperator::@11 + b11: + //SEG107 [37] call assertType + //SEG108 [87] phi from testBinaryOperator::@11 to assertType [phi:testBinaryOperator::@11->assertType] + assertType_from_b11: + //SEG109 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@11->assertType#0] -- register_copy + //SEG110 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG111 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + jmp b12 + //SEG112 testBinaryOperator::@12 + b12: + //SEG113 [38] (byte) idx#26 ← ++ (byte) idx#108 -- vbuz1=_inc_vbuz1 + inc idx + //SEG114 [39] call assertType + //SEG115 [87] phi from testBinaryOperator::@12 to assertType [phi:testBinaryOperator::@12->assertType] + assertType_from_b12: + //SEG116 [87] phi (byte) idx#105 = (byte) idx#26 [phi:testBinaryOperator::@12->assertType#0] -- register_copy + //SEG117 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG118 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG119 [40] phi from testBinaryOperator::@12 to testBinaryOperator::@13 [phi:testBinaryOperator::@12->testBinaryOperator::@13] + b13_from_b12: + jmp b13 + //SEG120 testBinaryOperator::@13 + b13: + //SEG121 [41] call assertType + //SEG122 [87] phi from testBinaryOperator::@13 to assertType [phi:testBinaryOperator::@13->assertType] + assertType_from_b13: + //SEG123 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@13->assertType#0] -- register_copy + //SEG124 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG125 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG126 [42] phi from testBinaryOperator::@13 to testBinaryOperator::@14 [phi:testBinaryOperator::@13->testBinaryOperator::@14] + b14_from_b13: + jmp b14 + //SEG127 testBinaryOperator::@14 + b14: + //SEG128 [43] call assertType + //SEG129 [87] phi from testBinaryOperator::@14 to assertType [phi:testBinaryOperator::@14->assertType] + assertType_from_b14: + //SEG130 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@14->assertType#0] -- register_copy + //SEG131 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG132 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG133 [44] phi from testBinaryOperator::@14 to testBinaryOperator::@15 [phi:testBinaryOperator::@14->testBinaryOperator::@15] + b15_from_b14: + jmp b15 + //SEG134 testBinaryOperator::@15 + b15: + //SEG135 [45] call assertType + //SEG136 [87] phi from testBinaryOperator::@15 to assertType [phi:testBinaryOperator::@15->assertType] + assertType_from_b15: + //SEG137 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@15->assertType#0] -- register_copy + //SEG138 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG139 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG140 [46] phi from testBinaryOperator::@15 to testBinaryOperator::@16 [phi:testBinaryOperator::@15->testBinaryOperator::@16] + b16_from_b15: + jmp b16 + //SEG141 testBinaryOperator::@16 + b16: + //SEG142 [47] call assertType + //SEG143 [87] phi from testBinaryOperator::@16 to assertType [phi:testBinaryOperator::@16->assertType] + assertType_from_b16: + //SEG144 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@16->assertType#0] -- register_copy + //SEG145 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG146 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG147 [48] phi from testBinaryOperator::@16 to testBinaryOperator::@17 [phi:testBinaryOperator::@16->testBinaryOperator::@17] + b17_from_b16: + jmp b17 + //SEG148 testBinaryOperator::@17 + b17: + //SEG149 [49] call assertType + //SEG150 [87] phi from testBinaryOperator::@17 to assertType [phi:testBinaryOperator::@17->assertType] + assertType_from_b17: + //SEG151 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@17->assertType#0] -- register_copy + //SEG152 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG153 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG154 [50] phi from testBinaryOperator::@17 to testBinaryOperator::@18 [phi:testBinaryOperator::@17->testBinaryOperator::@18] + b18_from_b17: + jmp b18 + //SEG155 testBinaryOperator::@18 + b18: + //SEG156 [51] call assertType + //SEG157 [87] phi from testBinaryOperator::@18 to assertType [phi:testBinaryOperator::@18->assertType] + assertType_from_b18: + //SEG158 [87] phi (byte) idx#105 = (byte) $50 [phi:testBinaryOperator::@18->assertType#0] -- vbuz1=vbuc1 + lda #$50 + sta idx + //SEG159 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG160 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG161 [52] phi from testBinaryOperator::@18 to testBinaryOperator::@19 [phi:testBinaryOperator::@18->testBinaryOperator::@19] + b19_from_b18: + jmp b19 + //SEG162 testBinaryOperator::@19 + b19: + //SEG163 [53] call assertType + //SEG164 [87] phi from testBinaryOperator::@19 to assertType [phi:testBinaryOperator::@19->assertType] + assertType_from_b19: + //SEG165 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@19->assertType#0] -- register_copy + //SEG166 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG167 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG168 [54] phi from testBinaryOperator::@19 to testBinaryOperator::@20 [phi:testBinaryOperator::@19->testBinaryOperator::@20] + b20_from_b19: + jmp b20 + //SEG169 testBinaryOperator::@20 + b20: + //SEG170 [55] call assertType + //SEG171 [87] phi from testBinaryOperator::@20 to assertType [phi:testBinaryOperator::@20->assertType] + assertType_from_b20: + //SEG172 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@20->assertType#0] -- register_copy + //SEG173 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG174 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG175 [56] phi from testBinaryOperator::@20 to testBinaryOperator::@21 [phi:testBinaryOperator::@20->testBinaryOperator::@21] + b21_from_b20: + jmp b21 + //SEG176 testBinaryOperator::@21 + b21: + //SEG177 [57] call assertType + //SEG178 [87] phi from testBinaryOperator::@21 to assertType [phi:testBinaryOperator::@21->assertType] + assertType_from_b21: + //SEG179 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@21->assertType#0] -- register_copy + //SEG180 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG181 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG182 [58] phi from testBinaryOperator::@21 to testBinaryOperator::@22 [phi:testBinaryOperator::@21->testBinaryOperator::@22] + b22_from_b21: + jmp b22 + //SEG183 testBinaryOperator::@22 + b22: + //SEG184 [59] call assertType + //SEG185 [87] phi from testBinaryOperator::@22 to assertType [phi:testBinaryOperator::@22->assertType] + assertType_from_b22: + //SEG186 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@22->assertType#0] -- register_copy + //SEG187 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG188 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG189 [60] phi from testBinaryOperator::@22 to testBinaryOperator::@23 [phi:testBinaryOperator::@22->testBinaryOperator::@23] + b23_from_b22: + jmp b23 + //SEG190 testBinaryOperator::@23 + b23: + //SEG191 [61] call assertType + //SEG192 [87] phi from testBinaryOperator::@23 to assertType [phi:testBinaryOperator::@23->assertType] + assertType_from_b23: + //SEG193 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@23->assertType#0] -- register_copy + //SEG194 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG195 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + jmp b24 + //SEG196 testBinaryOperator::@24 + b24: + //SEG197 [62] (byte) idx#40 ← ++ (byte) idx#108 -- vbuz1=_inc_vbuz1 + inc idx + //SEG198 [63] call assertType + //SEG199 [87] phi from testBinaryOperator::@24 to assertType [phi:testBinaryOperator::@24->assertType] + assertType_from_b24: + //SEG200 [87] phi (byte) idx#105 = (byte) idx#40 [phi:testBinaryOperator::@24->assertType#0] -- register_copy + //SEG201 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG202 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG203 [64] phi from testBinaryOperator::@24 to testBinaryOperator::@25 [phi:testBinaryOperator::@24->testBinaryOperator::@25] + b25_from_b24: + jmp b25 + //SEG204 testBinaryOperator::@25 + b25: + //SEG205 [65] call assertType + //SEG206 [87] phi from testBinaryOperator::@25 to assertType [phi:testBinaryOperator::@25->assertType] + assertType_from_b25: + //SEG207 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@25->assertType#0] -- register_copy + //SEG208 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG209 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG210 [66] phi from testBinaryOperator::@25 to testBinaryOperator::@26 [phi:testBinaryOperator::@25->testBinaryOperator::@26] + b26_from_b25: + jmp b26 + //SEG211 testBinaryOperator::@26 + b26: + //SEG212 [67] call assertType + //SEG213 [87] phi from testBinaryOperator::@26 to assertType [phi:testBinaryOperator::@26->assertType] + assertType_from_b26: + //SEG214 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@26->assertType#0] -- register_copy + //SEG215 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG216 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG217 [68] phi from testBinaryOperator::@26 to testBinaryOperator::@27 [phi:testBinaryOperator::@26->testBinaryOperator::@27] + b27_from_b26: + jmp b27 + //SEG218 testBinaryOperator::@27 + b27: + //SEG219 [69] call assertType + //SEG220 [87] phi from testBinaryOperator::@27 to assertType [phi:testBinaryOperator::@27->assertType] + assertType_from_b27: + //SEG221 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@27->assertType#0] -- register_copy + //SEG222 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG223 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG224 [70] phi from testBinaryOperator::@27 to testBinaryOperator::@28 [phi:testBinaryOperator::@27->testBinaryOperator::@28] + b28_from_b27: + jmp b28 + //SEG225 testBinaryOperator::@28 + b28: + //SEG226 [71] call assertType + //SEG227 [87] phi from testBinaryOperator::@28 to assertType [phi:testBinaryOperator::@28->assertType] + assertType_from_b28: + //SEG228 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@28->assertType#0] -- register_copy + //SEG229 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG230 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG231 [72] phi from testBinaryOperator::@28 to testBinaryOperator::@29 [phi:testBinaryOperator::@28->testBinaryOperator::@29] + b29_from_b28: + jmp b29 + //SEG232 testBinaryOperator::@29 + b29: + //SEG233 [73] call assertType + //SEG234 [87] phi from testBinaryOperator::@29 to assertType [phi:testBinaryOperator::@29->assertType] + assertType_from_b29: + //SEG235 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@29->assertType#0] -- register_copy + //SEG236 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG237 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + jmp b30 + //SEG238 testBinaryOperator::@30 + b30: + //SEG239 [74] (byte) idx#47 ← ++ (byte) idx#108 -- vbuz1=_inc_vbuz1 + inc idx + //SEG240 [75] call assertType + //SEG241 [87] phi from testBinaryOperator::@30 to assertType [phi:testBinaryOperator::@30->assertType] + assertType_from_b30: + //SEG242 [87] phi (byte) idx#105 = (byte) idx#47 [phi:testBinaryOperator::@30->assertType#0] -- register_copy + //SEG243 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG244 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG245 [76] phi from testBinaryOperator::@30 to testBinaryOperator::@31 [phi:testBinaryOperator::@30->testBinaryOperator::@31] + b31_from_b30: + jmp b31 + //SEG246 testBinaryOperator::@31 + b31: + //SEG247 [77] call assertType + //SEG248 [87] phi from testBinaryOperator::@31 to assertType [phi:testBinaryOperator::@31->assertType] + assertType_from_b31: + //SEG249 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@31->assertType#0] -- register_copy + //SEG250 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG251 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG252 [78] phi from testBinaryOperator::@31 to testBinaryOperator::@32 [phi:testBinaryOperator::@31->testBinaryOperator::@32] + b32_from_b31: + jmp b32 + //SEG253 testBinaryOperator::@32 + b32: + //SEG254 [79] call assertType + //SEG255 [87] phi from testBinaryOperator::@32 to assertType [phi:testBinaryOperator::@32->assertType] + assertType_from_b32: + //SEG256 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@32->assertType#0] -- register_copy + //SEG257 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG258 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG259 [80] phi from testBinaryOperator::@32 to testBinaryOperator::@33 [phi:testBinaryOperator::@32->testBinaryOperator::@33] + b33_from_b32: + jmp b33 + //SEG260 testBinaryOperator::@33 + b33: + //SEG261 [81] call assertType + //SEG262 [87] phi from testBinaryOperator::@33 to assertType [phi:testBinaryOperator::@33->assertType] + assertType_from_b33: + //SEG263 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@33->assertType#0] -- register_copy + //SEG264 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG265 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG266 [82] phi from testBinaryOperator::@33 to testBinaryOperator::@34 [phi:testBinaryOperator::@33->testBinaryOperator::@34] + b34_from_b33: + jmp b34 + //SEG267 testBinaryOperator::@34 + b34: + //SEG268 [83] call assertType + //SEG269 [87] phi from testBinaryOperator::@34 to assertType [phi:testBinaryOperator::@34->assertType] + assertType_from_b34: + //SEG270 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@34->assertType#0] -- register_copy + //SEG271 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG272 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG273 [84] phi from testBinaryOperator::@34 to testBinaryOperator::@35 [phi:testBinaryOperator::@34->testBinaryOperator::@35] + b35_from_b34: + jmp b35 + //SEG274 testBinaryOperator::@35 + b35: + //SEG275 [85] call assertType + //SEG276 [87] phi from testBinaryOperator::@35 to assertType [phi:testBinaryOperator::@35->assertType] + assertType_from_b35: + //SEG277 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@35->assertType#0] -- register_copy + //SEG278 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG279 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + jmp breturn + //SEG280 testBinaryOperator::@return + breturn: + //SEG281 [86] return + rts +} +//SEG282 assertType +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte zeropage(4) t1, byte zeropage(5) t2) +assertType: { + .label t1 = 4 + .label t2 = 5 + //SEG283 [88] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1 -- vbuz1_eq_vbuz2_then_la1 + lda t1 + cmp t2 + beq b1 + jmp b3 + //SEG284 assertType::@3 + b3: + //SEG285 [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #RED + ldy idx + sta COLS,y + jmp b2 + //SEG286 assertType::@2 + b2: + //SEG287 [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 -- pbuc1_derefidx_vbuz1=vbuz2 + lda t1 + ldy idx + sta SCREEN,y + //SEG288 [91] (byte) idx#108 ← ++ (byte) idx#105 -- vbuz1=_inc_vbuz1 + inc idx + jmp breturn + //SEG289 assertType::@return + breturn: + //SEG290 [92] return + rts + //SEG291 assertType::@1 + b1: + //SEG292 [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #GREEN + ldy idx + sta COLS,y + jmp b2 +} +//SEG293 testUnaryOperator +testUnaryOperator: { + //SEG294 [95] call assertType + //SEG295 [87] phi from testUnaryOperator to assertType [phi:testUnaryOperator->assertType] + assertType_from_testUnaryOperator: + //SEG296 [87] phi (byte) idx#105 = (byte) 0 [phi:testUnaryOperator->assertType#0] -- vbuz1=vbuc1 + lda #0 + sta idx + //SEG297 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG298 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG299 [96] phi from testUnaryOperator to testUnaryOperator::@1 [phi:testUnaryOperator->testUnaryOperator::@1] + b1_from_testUnaryOperator: + jmp b1 + //SEG300 testUnaryOperator::@1 + b1: + //SEG301 [97] call assertType + //SEG302 [87] phi from testUnaryOperator::@1 to assertType [phi:testUnaryOperator::@1->assertType] + assertType_from_b1: + //SEG303 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@1->assertType#0] -- register_copy + //SEG304 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG305 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t1 + jsr assertType + //SEG306 [98] phi from testUnaryOperator::@1 to testUnaryOperator::@2 [phi:testUnaryOperator::@1->testUnaryOperator::@2] + b2_from_b1: + jmp b2 + //SEG307 testUnaryOperator::@2 + b2: + //SEG308 [99] call assertType + //SEG309 [87] phi from testUnaryOperator::@2 to assertType [phi:testUnaryOperator::@2->assertType] + assertType_from_b2: + //SEG310 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@2->assertType#0] -- register_copy + //SEG311 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG312 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG313 [100] phi from testUnaryOperator::@2 to testUnaryOperator::@3 [phi:testUnaryOperator::@2->testUnaryOperator::@3] + b3_from_b2: + jmp b3 + //SEG314 testUnaryOperator::@3 + b3: + //SEG315 [101] call assertType + //SEG316 [87] phi from testUnaryOperator::@3 to assertType [phi:testUnaryOperator::@3->assertType] + assertType_from_b3: + //SEG317 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@3->assertType#0] -- register_copy + //SEG318 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG319 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG320 [102] phi from testUnaryOperator::@3 to testUnaryOperator::@4 [phi:testUnaryOperator::@3->testUnaryOperator::@4] + b4_from_b3: + jmp b4 + //SEG321 testUnaryOperator::@4 + b4: + //SEG322 [103] call assertType + //SEG323 [87] phi from testUnaryOperator::@4 to assertType [phi:testUnaryOperator::@4->assertType] + assertType_from_b4: + //SEG324 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@4->assertType#0] -- register_copy + //SEG325 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG326 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG327 [104] phi from testUnaryOperator::@4 to testUnaryOperator::@5 [phi:testUnaryOperator::@4->testUnaryOperator::@5] + b5_from_b4: + jmp b5 + //SEG328 testUnaryOperator::@5 + b5: + //SEG329 [105] call assertType + //SEG330 [87] phi from testUnaryOperator::@5 to assertType [phi:testUnaryOperator::@5->assertType] + assertType_from_b5: + //SEG331 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@5->assertType#0] -- register_copy + //SEG332 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG333 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + jmp breturn + //SEG334 testUnaryOperator::@return + breturn: + //SEG335 [106] return + rts +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [6] *((byte*) main::s#2) ← (byte) ' ' [ main::s#2 ] ( main:2 [ main::s#2 ] ) always clobbers reg byte a reg byte y +Statement [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 [ main::s#1 ] ( main:2 [ main::s#1 ] ) always clobbers reg byte a +Statement [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 [ assertType::t1#42 idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ assertType::t1#42 idx#105 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ assertType::t1#42 ] +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] +Statement [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 [ idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ idx#105 ] ) always clobbers reg byte a +Statement [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 [ assertType::t1#42 idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ assertType::t1#42 idx#105 ] ) always clobbers reg byte a +Statement [6] *((byte*) main::s#2) ← (byte) ' ' [ main::s#2 ] ( main:2 [ main::s#2 ] ) always clobbers reg byte a reg byte y +Statement [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 [ main::s#1 ] ( main:2 [ main::s#1 ] ) always clobbers reg byte a +Statement [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 [ assertType::t1#42 idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ assertType::t1#42 idx#105 ] ) always clobbers reg byte a +Statement [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 [ idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ idx#105 ] ) always clobbers reg byte a +Statement [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 [ assertType::t1#42 idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ assertType::t1#42 idx#105 ] ) always clobbers reg byte a +Potential registers zp ZP_WORD:2 [ main::s#2 main::s#1 ] : zp ZP_WORD:2 , +Potential registers zp ZP_BYTE:4 [ assertType::t1#42 ] : zp ZP_BYTE:4 , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:5 [ assertType::t2#42 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:6 [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] : zp ZP_BYTE:6 , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [] 34.25: zp ZP_BYTE:6 [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] +Uplift Scope [main] 33: zp ZP_WORD:2 [ main::s#2 main::s#1 ] +Uplift Scope [assertType] 2: zp ZP_BYTE:5 [ assertType::t2#42 ] 1: zp ZP_BYTE:4 [ assertType::t1#42 ] +Uplift Scope [testUnaryOperator] +Uplift Scope [testBinaryOperator] + +Uplifting [] best 1503 combination reg byte x [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] +Uplifting [main] best 1503 combination zp ZP_WORD:2 [ main::s#2 main::s#1 ] +Uplifting [assertType] best 1375 combination zp ZP_BYTE:5 [ assertType::t2#42 ] reg byte y [ assertType::t1#42 ] +Uplifting [testUnaryOperator] best 1375 combination +Uplifting [testBinaryOperator] best 1375 combination +Attempting to uplift remaining variables inzp ZP_BYTE:5 [ assertType::t2#42 ] +Uplifting [assertType] best 1375 combination zp ZP_BYTE:5 [ assertType::t2#42 ] +Allocated (was zp ZP_BYTE:5) zp ZP_BYTE:4 [ assertType::t2#42 ] + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 File Comments +// Tests different integer literal types +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const TYPEID_BYTE = 1 + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_WORD = 3 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_DWORD = 5 + .const TYPEID_SIGNED_DWORD = 6 + .const RED = 2 + .const GREEN = 5 + .label SCREEN = $400 + .label COLS = $d800 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG9 @end +bend: +//SEG10 main +main: { + .label s = 2 + //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG12 [5] phi (byte*) main::s#2 = (const byte*) SCREEN#0 [phi:main->main::@1#0] -- pbuz1=pbuc1 + lda #<SCREEN + sta s + lda #>SCREEN + sta s+1 + jmp b1 + //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy + jmp b1 + //SEG15 main::@1 + b1: + //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 + lda #' ' + ldy #0 + sta (s),y + //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 + inc s + bne !+ + inc s+1 + !: + //SEG18 [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 + lda s+1 + cmp #>SCREEN+$3e8 + bcc b1_from_b1 + bne !+ + lda s + cmp #<SCREEN+$3e8 + bcc b1_from_b1 + !: + //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + jmp b2 + //SEG20 main::@2 + b2: + //SEG21 [10] call testUnaryOperator + //SEG22 [94] phi from main::@2 to testUnaryOperator [phi:main::@2->testUnaryOperator] + testUnaryOperator_from_b2: + jsr testUnaryOperator + //SEG23 [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + b3_from_b2: + jmp b3 + //SEG24 main::@3 + b3: + //SEG25 [12] call testBinaryOperator + //SEG26 [14] phi from main::@3 to testBinaryOperator [phi:main::@3->testBinaryOperator] + testBinaryOperator_from_b3: + jsr testBinaryOperator + jmp breturn + //SEG27 main::@return + breturn: + //SEG28 [13] return + rts +} +//SEG29 testBinaryOperator +testBinaryOperator: { + //SEG30 [15] call assertType + //SEG31 [87] phi from testBinaryOperator to assertType [phi:testBinaryOperator->assertType] + assertType_from_testBinaryOperator: + //SEG32 [87] phi (byte) idx#105 = (byte) $28 [phi:testBinaryOperator->assertType#0] -- vbuxx=vbuc1 + ldx #$28 + //SEG33 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG34 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG35 [16] phi from testBinaryOperator to testBinaryOperator::@1 [phi:testBinaryOperator->testBinaryOperator::@1] + b1_from_testBinaryOperator: + jmp b1 + //SEG36 testBinaryOperator::@1 + b1: + //SEG37 [17] call assertType + //SEG38 [87] phi from testBinaryOperator::@1 to assertType [phi:testBinaryOperator::@1->assertType] + assertType_from_b1: + //SEG39 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@1->assertType#0] -- register_copy + //SEG40 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG41 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG42 [18] phi from testBinaryOperator::@1 to testBinaryOperator::@2 [phi:testBinaryOperator::@1->testBinaryOperator::@2] + b2_from_b1: + jmp b2 + //SEG43 testBinaryOperator::@2 + b2: + //SEG44 [19] call assertType + //SEG45 [87] phi from testBinaryOperator::@2 to assertType [phi:testBinaryOperator::@2->assertType] + assertType_from_b2: + //SEG46 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@2->assertType#0] -- register_copy + //SEG47 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG48 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG49 [20] phi from testBinaryOperator::@2 to testBinaryOperator::@3 [phi:testBinaryOperator::@2->testBinaryOperator::@3] + b3_from_b2: + jmp b3 + //SEG50 testBinaryOperator::@3 + b3: + //SEG51 [21] call assertType + //SEG52 [87] phi from testBinaryOperator::@3 to assertType [phi:testBinaryOperator::@3->assertType] + assertType_from_b3: + //SEG53 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@3->assertType#0] -- register_copy + //SEG54 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG55 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG56 [22] phi from testBinaryOperator::@3 to testBinaryOperator::@4 [phi:testBinaryOperator::@3->testBinaryOperator::@4] + b4_from_b3: + jmp b4 + //SEG57 testBinaryOperator::@4 + b4: + //SEG58 [23] call assertType + //SEG59 [87] phi from testBinaryOperator::@4 to assertType [phi:testBinaryOperator::@4->assertType] + assertType_from_b4: + //SEG60 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@4->assertType#0] -- register_copy + //SEG61 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG62 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG63 [24] phi from testBinaryOperator::@4 to testBinaryOperator::@5 [phi:testBinaryOperator::@4->testBinaryOperator::@5] + b5_from_b4: + jmp b5 + //SEG64 testBinaryOperator::@5 + b5: + //SEG65 [25] call assertType + //SEG66 [87] phi from testBinaryOperator::@5 to assertType [phi:testBinaryOperator::@5->assertType] + assertType_from_b5: + //SEG67 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@5->assertType#0] -- register_copy + //SEG68 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG69 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + jmp b6 + //SEG70 testBinaryOperator::@6 + b6: + //SEG71 [26] (byte) idx#19 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx + inx + //SEG72 [27] call assertType + //SEG73 [87] phi from testBinaryOperator::@6 to assertType [phi:testBinaryOperator::@6->assertType] + assertType_from_b6: + //SEG74 [87] phi (byte) idx#105 = (byte) idx#19 [phi:testBinaryOperator::@6->assertType#0] -- register_copy + //SEG75 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG76 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG77 [28] phi from testBinaryOperator::@6 to testBinaryOperator::@7 [phi:testBinaryOperator::@6->testBinaryOperator::@7] + b7_from_b6: + jmp b7 + //SEG78 testBinaryOperator::@7 + b7: + //SEG79 [29] call assertType + //SEG80 [87] phi from testBinaryOperator::@7 to assertType [phi:testBinaryOperator::@7->assertType] + assertType_from_b7: + //SEG81 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@7->assertType#0] -- register_copy + //SEG82 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG83 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_BYTE + jsr assertType + //SEG84 [30] phi from testBinaryOperator::@7 to testBinaryOperator::@8 [phi:testBinaryOperator::@7->testBinaryOperator::@8] + b8_from_b7: + jmp b8 + //SEG85 testBinaryOperator::@8 + b8: + //SEG86 [31] call assertType + //SEG87 [87] phi from testBinaryOperator::@8 to assertType [phi:testBinaryOperator::@8->assertType] + assertType_from_b8: + //SEG88 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@8->assertType#0] -- register_copy + //SEG89 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG90 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG91 [32] phi from testBinaryOperator::@8 to testBinaryOperator::@9 [phi:testBinaryOperator::@8->testBinaryOperator::@9] + b9_from_b8: + jmp b9 + //SEG92 testBinaryOperator::@9 + b9: + //SEG93 [33] call assertType + //SEG94 [87] phi from testBinaryOperator::@9 to assertType [phi:testBinaryOperator::@9->assertType] + assertType_from_b9: + //SEG95 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@9->assertType#0] -- register_copy + //SEG96 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG97 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG98 [34] phi from testBinaryOperator::@9 to testBinaryOperator::@10 [phi:testBinaryOperator::@9->testBinaryOperator::@10] + b10_from_b9: + jmp b10 + //SEG99 testBinaryOperator::@10 + b10: + //SEG100 [35] call assertType + //SEG101 [87] phi from testBinaryOperator::@10 to assertType [phi:testBinaryOperator::@10->assertType] + assertType_from_b10: + //SEG102 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@10->assertType#0] -- register_copy + //SEG103 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG104 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG105 [36] phi from testBinaryOperator::@10 to testBinaryOperator::@11 [phi:testBinaryOperator::@10->testBinaryOperator::@11] + b11_from_b10: + jmp b11 + //SEG106 testBinaryOperator::@11 + b11: + //SEG107 [37] call assertType + //SEG108 [87] phi from testBinaryOperator::@11 to assertType [phi:testBinaryOperator::@11->assertType] + assertType_from_b11: + //SEG109 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@11->assertType#0] -- register_copy + //SEG110 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG111 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + jmp b12 + //SEG112 testBinaryOperator::@12 + b12: + //SEG113 [38] (byte) idx#26 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx + inx + //SEG114 [39] call assertType + //SEG115 [87] phi from testBinaryOperator::@12 to assertType [phi:testBinaryOperator::@12->assertType] + assertType_from_b12: + //SEG116 [87] phi (byte) idx#105 = (byte) idx#26 [phi:testBinaryOperator::@12->assertType#0] -- register_copy + //SEG117 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG118 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG119 [40] phi from testBinaryOperator::@12 to testBinaryOperator::@13 [phi:testBinaryOperator::@12->testBinaryOperator::@13] + b13_from_b12: + jmp b13 + //SEG120 testBinaryOperator::@13 + b13: + //SEG121 [41] call assertType + //SEG122 [87] phi from testBinaryOperator::@13 to assertType [phi:testBinaryOperator::@13->assertType] + assertType_from_b13: + //SEG123 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@13->assertType#0] -- register_copy + //SEG124 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG125 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG126 [42] phi from testBinaryOperator::@13 to testBinaryOperator::@14 [phi:testBinaryOperator::@13->testBinaryOperator::@14] + b14_from_b13: + jmp b14 + //SEG127 testBinaryOperator::@14 + b14: + //SEG128 [43] call assertType + //SEG129 [87] phi from testBinaryOperator::@14 to assertType [phi:testBinaryOperator::@14->assertType] + assertType_from_b14: + //SEG130 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@14->assertType#0] -- register_copy + //SEG131 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG132 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG133 [44] phi from testBinaryOperator::@14 to testBinaryOperator::@15 [phi:testBinaryOperator::@14->testBinaryOperator::@15] + b15_from_b14: + jmp b15 + //SEG134 testBinaryOperator::@15 + b15: + //SEG135 [45] call assertType + //SEG136 [87] phi from testBinaryOperator::@15 to assertType [phi:testBinaryOperator::@15->assertType] + assertType_from_b15: + //SEG137 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@15->assertType#0] -- register_copy + //SEG138 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG139 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG140 [46] phi from testBinaryOperator::@15 to testBinaryOperator::@16 [phi:testBinaryOperator::@15->testBinaryOperator::@16] + b16_from_b15: + jmp b16 + //SEG141 testBinaryOperator::@16 + b16: + //SEG142 [47] call assertType + //SEG143 [87] phi from testBinaryOperator::@16 to assertType [phi:testBinaryOperator::@16->assertType] + assertType_from_b16: + //SEG144 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@16->assertType#0] -- register_copy + //SEG145 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG146 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG147 [48] phi from testBinaryOperator::@16 to testBinaryOperator::@17 [phi:testBinaryOperator::@16->testBinaryOperator::@17] + b17_from_b16: + jmp b17 + //SEG148 testBinaryOperator::@17 + b17: + //SEG149 [49] call assertType + //SEG150 [87] phi from testBinaryOperator::@17 to assertType [phi:testBinaryOperator::@17->assertType] + assertType_from_b17: + //SEG151 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@17->assertType#0] -- register_copy + //SEG152 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG153 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG154 [50] phi from testBinaryOperator::@17 to testBinaryOperator::@18 [phi:testBinaryOperator::@17->testBinaryOperator::@18] + b18_from_b17: + jmp b18 + //SEG155 testBinaryOperator::@18 + b18: + //SEG156 [51] call assertType + //SEG157 [87] phi from testBinaryOperator::@18 to assertType [phi:testBinaryOperator::@18->assertType] + assertType_from_b18: + //SEG158 [87] phi (byte) idx#105 = (byte) $50 [phi:testBinaryOperator::@18->assertType#0] -- vbuxx=vbuc1 + ldx #$50 + //SEG159 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG160 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG161 [52] phi from testBinaryOperator::@18 to testBinaryOperator::@19 [phi:testBinaryOperator::@18->testBinaryOperator::@19] + b19_from_b18: + jmp b19 + //SEG162 testBinaryOperator::@19 + b19: + //SEG163 [53] call assertType + //SEG164 [87] phi from testBinaryOperator::@19 to assertType [phi:testBinaryOperator::@19->assertType] + assertType_from_b19: + //SEG165 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@19->assertType#0] -- register_copy + //SEG166 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG167 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG168 [54] phi from testBinaryOperator::@19 to testBinaryOperator::@20 [phi:testBinaryOperator::@19->testBinaryOperator::@20] + b20_from_b19: + jmp b20 + //SEG169 testBinaryOperator::@20 + b20: + //SEG170 [55] call assertType + //SEG171 [87] phi from testBinaryOperator::@20 to assertType [phi:testBinaryOperator::@20->assertType] + assertType_from_b20: + //SEG172 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@20->assertType#0] -- register_copy + //SEG173 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG174 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG175 [56] phi from testBinaryOperator::@20 to testBinaryOperator::@21 [phi:testBinaryOperator::@20->testBinaryOperator::@21] + b21_from_b20: + jmp b21 + //SEG176 testBinaryOperator::@21 + b21: + //SEG177 [57] call assertType + //SEG178 [87] phi from testBinaryOperator::@21 to assertType [phi:testBinaryOperator::@21->assertType] + assertType_from_b21: + //SEG179 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@21->assertType#0] -- register_copy + //SEG180 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG181 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG182 [58] phi from testBinaryOperator::@21 to testBinaryOperator::@22 [phi:testBinaryOperator::@21->testBinaryOperator::@22] + b22_from_b21: + jmp b22 + //SEG183 testBinaryOperator::@22 + b22: + //SEG184 [59] call assertType + //SEG185 [87] phi from testBinaryOperator::@22 to assertType [phi:testBinaryOperator::@22->assertType] + assertType_from_b22: + //SEG186 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@22->assertType#0] -- register_copy + //SEG187 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG188 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG189 [60] phi from testBinaryOperator::@22 to testBinaryOperator::@23 [phi:testBinaryOperator::@22->testBinaryOperator::@23] + b23_from_b22: + jmp b23 + //SEG190 testBinaryOperator::@23 + b23: + //SEG191 [61] call assertType + //SEG192 [87] phi from testBinaryOperator::@23 to assertType [phi:testBinaryOperator::@23->assertType] + assertType_from_b23: + //SEG193 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@23->assertType#0] -- register_copy + //SEG194 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG195 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + jmp b24 + //SEG196 testBinaryOperator::@24 + b24: + //SEG197 [62] (byte) idx#40 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx + inx + //SEG198 [63] call assertType + //SEG199 [87] phi from testBinaryOperator::@24 to assertType [phi:testBinaryOperator::@24->assertType] + assertType_from_b24: + //SEG200 [87] phi (byte) idx#105 = (byte) idx#40 [phi:testBinaryOperator::@24->assertType#0] -- register_copy + //SEG201 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG202 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG203 [64] phi from testBinaryOperator::@24 to testBinaryOperator::@25 [phi:testBinaryOperator::@24->testBinaryOperator::@25] + b25_from_b24: + jmp b25 + //SEG204 testBinaryOperator::@25 + b25: + //SEG205 [65] call assertType + //SEG206 [87] phi from testBinaryOperator::@25 to assertType [phi:testBinaryOperator::@25->assertType] + assertType_from_b25: + //SEG207 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@25->assertType#0] -- register_copy + //SEG208 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG209 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG210 [66] phi from testBinaryOperator::@25 to testBinaryOperator::@26 [phi:testBinaryOperator::@25->testBinaryOperator::@26] + b26_from_b25: + jmp b26 + //SEG211 testBinaryOperator::@26 + b26: + //SEG212 [67] call assertType + //SEG213 [87] phi from testBinaryOperator::@26 to assertType [phi:testBinaryOperator::@26->assertType] + assertType_from_b26: + //SEG214 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@26->assertType#0] -- register_copy + //SEG215 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG216 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG217 [68] phi from testBinaryOperator::@26 to testBinaryOperator::@27 [phi:testBinaryOperator::@26->testBinaryOperator::@27] + b27_from_b26: + jmp b27 + //SEG218 testBinaryOperator::@27 + b27: + //SEG219 [69] call assertType + //SEG220 [87] phi from testBinaryOperator::@27 to assertType [phi:testBinaryOperator::@27->assertType] + assertType_from_b27: + //SEG221 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@27->assertType#0] -- register_copy + //SEG222 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG223 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG224 [70] phi from testBinaryOperator::@27 to testBinaryOperator::@28 [phi:testBinaryOperator::@27->testBinaryOperator::@28] + b28_from_b27: + jmp b28 + //SEG225 testBinaryOperator::@28 + b28: + //SEG226 [71] call assertType + //SEG227 [87] phi from testBinaryOperator::@28 to assertType [phi:testBinaryOperator::@28->assertType] + assertType_from_b28: + //SEG228 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@28->assertType#0] -- register_copy + //SEG229 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG230 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG231 [72] phi from testBinaryOperator::@28 to testBinaryOperator::@29 [phi:testBinaryOperator::@28->testBinaryOperator::@29] + b29_from_b28: + jmp b29 + //SEG232 testBinaryOperator::@29 + b29: + //SEG233 [73] call assertType + //SEG234 [87] phi from testBinaryOperator::@29 to assertType [phi:testBinaryOperator::@29->assertType] + assertType_from_b29: + //SEG235 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@29->assertType#0] -- register_copy + //SEG236 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG237 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + jmp b30 + //SEG238 testBinaryOperator::@30 + b30: + //SEG239 [74] (byte) idx#47 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx + inx + //SEG240 [75] call assertType + //SEG241 [87] phi from testBinaryOperator::@30 to assertType [phi:testBinaryOperator::@30->assertType] + assertType_from_b30: + //SEG242 [87] phi (byte) idx#105 = (byte) idx#47 [phi:testBinaryOperator::@30->assertType#0] -- register_copy + //SEG243 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG244 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG245 [76] phi from testBinaryOperator::@30 to testBinaryOperator::@31 [phi:testBinaryOperator::@30->testBinaryOperator::@31] + b31_from_b30: + jmp b31 + //SEG246 testBinaryOperator::@31 + b31: + //SEG247 [77] call assertType + //SEG248 [87] phi from testBinaryOperator::@31 to assertType [phi:testBinaryOperator::@31->assertType] + assertType_from_b31: + //SEG249 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@31->assertType#0] -- register_copy + //SEG250 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG251 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG252 [78] phi from testBinaryOperator::@31 to testBinaryOperator::@32 [phi:testBinaryOperator::@31->testBinaryOperator::@32] + b32_from_b31: + jmp b32 + //SEG253 testBinaryOperator::@32 + b32: + //SEG254 [79] call assertType + //SEG255 [87] phi from testBinaryOperator::@32 to assertType [phi:testBinaryOperator::@32->assertType] + assertType_from_b32: + //SEG256 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@32->assertType#0] -- register_copy + //SEG257 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG258 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG259 [80] phi from testBinaryOperator::@32 to testBinaryOperator::@33 [phi:testBinaryOperator::@32->testBinaryOperator::@33] + b33_from_b32: + jmp b33 + //SEG260 testBinaryOperator::@33 + b33: + //SEG261 [81] call assertType + //SEG262 [87] phi from testBinaryOperator::@33 to assertType [phi:testBinaryOperator::@33->assertType] + assertType_from_b33: + //SEG263 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@33->assertType#0] -- register_copy + //SEG264 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG265 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG266 [82] phi from testBinaryOperator::@33 to testBinaryOperator::@34 [phi:testBinaryOperator::@33->testBinaryOperator::@34] + b34_from_b33: + jmp b34 + //SEG267 testBinaryOperator::@34 + b34: + //SEG268 [83] call assertType + //SEG269 [87] phi from testBinaryOperator::@34 to assertType [phi:testBinaryOperator::@34->assertType] + assertType_from_b34: + //SEG270 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@34->assertType#0] -- register_copy + //SEG271 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG272 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG273 [84] phi from testBinaryOperator::@34 to testBinaryOperator::@35 [phi:testBinaryOperator::@34->testBinaryOperator::@35] + b35_from_b34: + jmp b35 + //SEG274 testBinaryOperator::@35 + b35: + //SEG275 [85] call assertType + //SEG276 [87] phi from testBinaryOperator::@35 to assertType [phi:testBinaryOperator::@35->assertType] + assertType_from_b35: + //SEG277 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@35->assertType#0] -- register_copy + //SEG278 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG279 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + jmp breturn + //SEG280 testBinaryOperator::@return + breturn: + //SEG281 [86] return + rts +} +//SEG282 assertType +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte register(Y) t1, byte zeropage(4) t2) +assertType: { + .label t2 = 4 + //SEG283 [88] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 + tya + cmp t2 + beq b1 + jmp b3 + //SEG284 assertType::@3 + b3: + //SEG285 [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #RED + sta COLS,x + jmp b2 + //SEG286 assertType::@2 + b2: + //SEG287 [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 -- pbuc1_derefidx_vbuxx=vbuyy + tya + sta SCREEN,x + //SEG288 [91] (byte) idx#108 ← ++ (byte) idx#105 -- vbuxx=_inc_vbuxx + inx + jmp breturn + //SEG289 assertType::@return + breturn: + //SEG290 [92] return + rts + //SEG291 assertType::@1 + b1: + //SEG292 [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #GREEN + sta COLS,x + jmp b2 +} +//SEG293 testUnaryOperator +testUnaryOperator: { + //SEG294 [95] call assertType + //SEG295 [87] phi from testUnaryOperator to assertType [phi:testUnaryOperator->assertType] + assertType_from_testUnaryOperator: + //SEG296 [87] phi (byte) idx#105 = (byte) 0 [phi:testUnaryOperator->assertType#0] -- vbuxx=vbuc1 + ldx #0 + //SEG297 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG298 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG299 [96] phi from testUnaryOperator to testUnaryOperator::@1 [phi:testUnaryOperator->testUnaryOperator::@1] + b1_from_testUnaryOperator: + jmp b1 + //SEG300 testUnaryOperator::@1 + b1: + //SEG301 [97] call assertType + //SEG302 [87] phi from testUnaryOperator::@1 to assertType [phi:testUnaryOperator::@1->assertType] + assertType_from_b1: + //SEG303 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@1->assertType#0] -- register_copy + //SEG304 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG305 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_BYTE + jsr assertType + //SEG306 [98] phi from testUnaryOperator::@1 to testUnaryOperator::@2 [phi:testUnaryOperator::@1->testUnaryOperator::@2] + b2_from_b1: + jmp b2 + //SEG307 testUnaryOperator::@2 + b2: + //SEG308 [99] call assertType + //SEG309 [87] phi from testUnaryOperator::@2 to assertType [phi:testUnaryOperator::@2->assertType] + assertType_from_b2: + //SEG310 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@2->assertType#0] -- register_copy + //SEG311 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG312 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG313 [100] phi from testUnaryOperator::@2 to testUnaryOperator::@3 [phi:testUnaryOperator::@2->testUnaryOperator::@3] + b3_from_b2: + jmp b3 + //SEG314 testUnaryOperator::@3 + b3: + //SEG315 [101] call assertType + //SEG316 [87] phi from testUnaryOperator::@3 to assertType [phi:testUnaryOperator::@3->assertType] + assertType_from_b3: + //SEG317 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@3->assertType#0] -- register_copy + //SEG318 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG319 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG320 [102] phi from testUnaryOperator::@3 to testUnaryOperator::@4 [phi:testUnaryOperator::@3->testUnaryOperator::@4] + b4_from_b3: + jmp b4 + //SEG321 testUnaryOperator::@4 + b4: + //SEG322 [103] call assertType + //SEG323 [87] phi from testUnaryOperator::@4 to assertType [phi:testUnaryOperator::@4->assertType] + assertType_from_b4: + //SEG324 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@4->assertType#0] -- register_copy + //SEG325 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG326 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG327 [104] phi from testUnaryOperator::@4 to testUnaryOperator::@5 [phi:testUnaryOperator::@4->testUnaryOperator::@5] + b5_from_b4: + jmp b5 + //SEG328 testUnaryOperator::@5 + b5: + //SEG329 [105] call assertType + //SEG330 [87] phi from testUnaryOperator::@5 to assertType [phi:testUnaryOperator::@5->assertType] + assertType_from_b5: + //SEG331 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@5->assertType#0] -- register_copy + //SEG332 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG333 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + jmp breturn + //SEG334 testUnaryOperator::@return + breturn: + //SEG335 [106] return + rts +} + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp b3 +Removing instruction jmp breturn +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp b3 +Removing instruction jmp b4 +Removing instruction jmp b5 +Removing instruction jmp b6 +Removing instruction jmp b7 +Removing instruction jmp b8 +Removing instruction jmp b9 +Removing instruction jmp b10 +Removing instruction jmp b11 +Removing instruction jmp b12 +Removing instruction jmp b13 +Removing instruction jmp b14 +Removing instruction jmp b15 +Removing instruction jmp b16 +Removing instruction jmp b17 +Removing instruction jmp b18 +Removing instruction jmp b19 +Removing instruction jmp b20 +Removing instruction jmp b21 +Removing instruction jmp b22 +Removing instruction jmp b23 +Removing instruction jmp b24 +Removing instruction jmp b25 +Removing instruction jmp b26 +Removing instruction jmp b27 +Removing instruction jmp b28 +Removing instruction jmp b29 +Removing instruction jmp b30 +Removing instruction jmp b31 +Removing instruction jmp b32 +Removing instruction jmp b33 +Removing instruction jmp b34 +Removing instruction jmp b35 +Removing instruction jmp breturn +Removing instruction jmp b3 +Removing instruction jmp b2 +Removing instruction jmp breturn +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp b3 +Removing instruction jmp b4 +Removing instruction jmp b5 +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_SIGNED_BYTE with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_SIGNED_BYTE with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing label b1_from_b1 with b1 +Replacing label b1_from_b1 with b1 +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Removing instruction b1_from_b1: +Removing instruction b2_from_b1: +Removing instruction testUnaryOperator_from_b2: +Removing instruction b3_from_b2: +Removing instruction testBinaryOperator_from_b3: +Removing instruction b1_from_testBinaryOperator: +Removing instruction assertType_from_b1: +Removing instruction b2_from_b1: +Removing instruction assertType_from_b2: +Removing instruction b3_from_b2: +Removing instruction assertType_from_b3: +Removing instruction b4_from_b3: +Removing instruction assertType_from_b4: +Removing instruction b5_from_b4: +Removing instruction assertType_from_b5: +Removing instruction b7_from_b6: +Removing instruction assertType_from_b7: +Removing instruction b8_from_b7: +Removing instruction assertType_from_b8: +Removing instruction b9_from_b8: +Removing instruction assertType_from_b9: +Removing instruction b10_from_b9: +Removing instruction assertType_from_b10: +Removing instruction b11_from_b10: +Removing instruction assertType_from_b11: +Removing instruction b13_from_b12: +Removing instruction assertType_from_b13: +Removing instruction b14_from_b13: +Removing instruction assertType_from_b14: +Removing instruction b15_from_b14: +Removing instruction assertType_from_b15: +Removing instruction b16_from_b15: +Removing instruction assertType_from_b16: +Removing instruction b17_from_b16: +Removing instruction assertType_from_b17: +Removing instruction b18_from_b17: +Removing instruction assertType_from_b18: +Removing instruction b19_from_b18: +Removing instruction assertType_from_b19: +Removing instruction b20_from_b19: +Removing instruction assertType_from_b20: +Removing instruction b21_from_b20: +Removing instruction assertType_from_b21: +Removing instruction b22_from_b21: +Removing instruction assertType_from_b22: +Removing instruction b23_from_b22: +Removing instruction assertType_from_b23: +Removing instruction b25_from_b24: +Removing instruction assertType_from_b25: +Removing instruction b26_from_b25: +Removing instruction assertType_from_b26: +Removing instruction b27_from_b26: +Removing instruction assertType_from_b27: +Removing instruction b28_from_b27: +Removing instruction assertType_from_b28: +Removing instruction b29_from_b28: +Removing instruction assertType_from_b29: +Removing instruction b31_from_b30: +Removing instruction assertType_from_b31: +Removing instruction b32_from_b31: +Removing instruction assertType_from_b32: +Removing instruction b33_from_b32: +Removing instruction assertType_from_b33: +Removing instruction b34_from_b33: +Removing instruction assertType_from_b34: +Removing instruction b35_from_b34: +Removing instruction assertType_from_b35: +Removing instruction b1_from_testUnaryOperator: +Removing instruction assertType_from_b1: +Removing instruction b2_from_b1: +Removing instruction assertType_from_b2: +Removing instruction b3_from_b2: +Removing instruction assertType_from_b3: +Removing instruction b4_from_b3: +Removing instruction assertType_from_b4: +Removing instruction b5_from_b4: +Removing instruction assertType_from_b5: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction b2: +Removing instruction b3: +Removing instruction breturn: +Removing instruction assertType_from_testBinaryOperator: +Removing instruction b1: +Removing instruction b2: +Removing instruction b3: +Removing instruction b4: +Removing instruction b5: +Removing instruction b6: +Removing instruction assertType_from_b6: +Removing instruction b7: +Removing instruction b8: +Removing instruction b9: +Removing instruction b10: +Removing instruction b11: +Removing instruction b12: +Removing instruction assertType_from_b12: +Removing instruction b13: +Removing instruction b14: +Removing instruction b15: +Removing instruction b16: +Removing instruction b17: +Removing instruction b18: +Removing instruction b19: +Removing instruction b20: +Removing instruction b21: +Removing instruction b22: +Removing instruction b23: +Removing instruction b24: +Removing instruction assertType_from_b24: +Removing instruction b25: +Removing instruction b26: +Removing instruction b27: +Removing instruction b28: +Removing instruction b29: +Removing instruction b30: +Removing instruction assertType_from_b30: +Removing instruction b31: +Removing instruction b32: +Removing instruction b33: +Removing instruction b34: +Removing instruction b35: +Removing instruction breturn: +Removing instruction b3: +Removing instruction breturn: +Removing instruction assertType_from_testUnaryOperator: +Removing instruction b1: +Removing instruction b2: +Removing instruction b3: +Removing instruction b4: +Removing instruction b5: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction jmp b1 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(byte*) COLS +(const byte*) COLS#0 COLS = ((byte*))(word) $d800 +(byte) GREEN +(const byte) GREEN#0 GREEN = (byte) 5 +(byte) RED +(const byte) RED#0 RED = (byte) 2 +(byte*) SCREEN +(const byte*) SCREEN#0 SCREEN = ((byte*))(word) $400 +(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1 +(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5 +(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2 +(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6 +(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4 +(const byte) TYPEID_WORD TYPEID_WORD = (number) 3 +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(label) assertType::@1 +(label) assertType::@2 +(label) assertType::@3 +(label) assertType::@return +(byte) assertType::t1 +(byte) assertType::t1#42 reg byte y 1.0 +(byte) assertType::t2 +(byte) assertType::t2#42 t2 zp ZP_BYTE:4 2.0 +(byte) idx +(byte) idx#105 reg byte x 17.200000000000003 +(byte) idx#108 reg byte x 1.0526315789473677 +(byte) idx#19 reg byte x 4.0 +(byte) idx#26 reg byte x 4.0 +(byte) idx#40 reg byte x 4.0 +(byte) idx#47 reg byte x 4.0 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(byte*) main::s +(byte*) main::s#1 s zp ZP_WORD:2 16.5 +(byte*) main::s#2 s zp ZP_WORD:2 16.5 +(void()) testBinaryOperator() +(label) testBinaryOperator::@1 +(label) testBinaryOperator::@10 +(label) testBinaryOperator::@11 +(label) testBinaryOperator::@12 +(label) testBinaryOperator::@13 +(label) testBinaryOperator::@14 +(label) testBinaryOperator::@15 +(label) testBinaryOperator::@16 +(label) testBinaryOperator::@17 +(label) testBinaryOperator::@18 +(label) testBinaryOperator::@19 +(label) testBinaryOperator::@2 +(label) testBinaryOperator::@20 +(label) testBinaryOperator::@21 +(label) testBinaryOperator::@22 +(label) testBinaryOperator::@23 +(label) testBinaryOperator::@24 +(label) testBinaryOperator::@25 +(label) testBinaryOperator::@26 +(label) testBinaryOperator::@27 +(label) testBinaryOperator::@28 +(label) testBinaryOperator::@29 +(label) testBinaryOperator::@3 +(label) testBinaryOperator::@30 +(label) testBinaryOperator::@31 +(label) testBinaryOperator::@32 +(label) testBinaryOperator::@33 +(label) testBinaryOperator::@34 +(label) testBinaryOperator::@35 +(label) testBinaryOperator::@4 +(label) testBinaryOperator::@5 +(label) testBinaryOperator::@6 +(label) testBinaryOperator::@7 +(label) testBinaryOperator::@8 +(label) testBinaryOperator::@9 +(label) testBinaryOperator::@return +(void()) testUnaryOperator() +(label) testUnaryOperator::@1 +(label) testUnaryOperator::@2 +(label) testUnaryOperator::@3 +(label) testUnaryOperator::@4 +(label) testUnaryOperator::@5 +(label) testUnaryOperator::@return + +zp ZP_WORD:2 [ main::s#2 main::s#1 ] +reg byte y [ assertType::t1#42 ] +zp ZP_BYTE:4 [ assertType::t2#42 ] +reg byte x [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] + + +FINAL ASSEMBLER +Score: 1159 + +//SEG0 File Comments +// Tests different integer literal types +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const TYPEID_BYTE = 1 + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_WORD = 3 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_DWORD = 5 + .const TYPEID_SIGNED_DWORD = 6 + .const RED = 2 + .const GREEN = 5 + .label SCREEN = $400 + .label COLS = $d800 +//SEG3 @begin +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +//SEG5 @1 +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +//SEG9 @end +//SEG10 main +main: { + .label s = 2 + //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] + //SEG12 [5] phi (byte*) main::s#2 = (const byte*) SCREEN#0 [phi:main->main::@1#0] -- pbuz1=pbuc1 + lda #<SCREEN + sta s + lda #>SCREEN + sta s+1 + //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG15 main::@1 + b1: + //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 + lda #' ' + ldy #0 + sta (s),y + //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 + inc s + bne !+ + inc s+1 + !: + //SEG18 [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 + lda s+1 + cmp #>SCREEN+$3e8 + bcc b1 + bne !+ + lda s + cmp #<SCREEN+$3e8 + bcc b1 + !: + //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + //SEG20 main::@2 + //SEG21 [10] call testUnaryOperator + //SEG22 [94] phi from main::@2 to testUnaryOperator [phi:main::@2->testUnaryOperator] + jsr testUnaryOperator + //SEG23 [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + //SEG24 main::@3 + //SEG25 [12] call testBinaryOperator + //SEG26 [14] phi from main::@3 to testBinaryOperator [phi:main::@3->testBinaryOperator] + jsr testBinaryOperator + //SEG27 main::@return + //SEG28 [13] return + rts +} +//SEG29 testBinaryOperator +testBinaryOperator: { + //SEG30 [15] call assertType + //SEG31 [87] phi from testBinaryOperator to assertType [phi:testBinaryOperator->assertType] + //SEG32 [87] phi (byte) idx#105 = (byte) $28 [phi:testBinaryOperator->assertType#0] -- vbuxx=vbuc1 + ldx #$28 + //SEG33 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG34 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG35 [16] phi from testBinaryOperator to testBinaryOperator::@1 [phi:testBinaryOperator->testBinaryOperator::@1] + //SEG36 testBinaryOperator::@1 + //SEG37 [17] call assertType + //SEG38 [87] phi from testBinaryOperator::@1 to assertType [phi:testBinaryOperator::@1->assertType] + //SEG39 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@1->assertType#0] -- register_copy + //SEG40 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG41 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG42 [18] phi from testBinaryOperator::@1 to testBinaryOperator::@2 [phi:testBinaryOperator::@1->testBinaryOperator::@2] + //SEG43 testBinaryOperator::@2 + //SEG44 [19] call assertType + //SEG45 [87] phi from testBinaryOperator::@2 to assertType [phi:testBinaryOperator::@2->assertType] + //SEG46 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@2->assertType#0] -- register_copy + //SEG47 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG48 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG49 [20] phi from testBinaryOperator::@2 to testBinaryOperator::@3 [phi:testBinaryOperator::@2->testBinaryOperator::@3] + //SEG50 testBinaryOperator::@3 + //SEG51 [21] call assertType + //SEG52 [87] phi from testBinaryOperator::@3 to assertType [phi:testBinaryOperator::@3->assertType] + //SEG53 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@3->assertType#0] -- register_copy + //SEG54 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG55 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG56 [22] phi from testBinaryOperator::@3 to testBinaryOperator::@4 [phi:testBinaryOperator::@3->testBinaryOperator::@4] + //SEG57 testBinaryOperator::@4 + //SEG58 [23] call assertType + //SEG59 [87] phi from testBinaryOperator::@4 to assertType [phi:testBinaryOperator::@4->assertType] + //SEG60 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@4->assertType#0] -- register_copy + //SEG61 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG62 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG63 [24] phi from testBinaryOperator::@4 to testBinaryOperator::@5 [phi:testBinaryOperator::@4->testBinaryOperator::@5] + //SEG64 testBinaryOperator::@5 + //SEG65 [25] call assertType + //SEG66 [87] phi from testBinaryOperator::@5 to assertType [phi:testBinaryOperator::@5->assertType] + //SEG67 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@5->assertType#0] -- register_copy + //SEG68 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG69 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG70 testBinaryOperator::@6 + //SEG71 [26] (byte) idx#19 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx + inx + //SEG72 [27] call assertType + //SEG73 [87] phi from testBinaryOperator::@6 to assertType [phi:testBinaryOperator::@6->assertType] + //SEG74 [87] phi (byte) idx#105 = (byte) idx#19 [phi:testBinaryOperator::@6->assertType#0] -- register_copy + //SEG75 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG76 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG77 [28] phi from testBinaryOperator::@6 to testBinaryOperator::@7 [phi:testBinaryOperator::@6->testBinaryOperator::@7] + //SEG78 testBinaryOperator::@7 + //SEG79 [29] call assertType + //SEG80 [87] phi from testBinaryOperator::@7 to assertType [phi:testBinaryOperator::@7->assertType] + //SEG81 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@7->assertType#0] -- register_copy + //SEG82 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG83 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG84 [30] phi from testBinaryOperator::@7 to testBinaryOperator::@8 [phi:testBinaryOperator::@7->testBinaryOperator::@8] + //SEG85 testBinaryOperator::@8 + //SEG86 [31] call assertType + //SEG87 [87] phi from testBinaryOperator::@8 to assertType [phi:testBinaryOperator::@8->assertType] + //SEG88 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@8->assertType#0] -- register_copy + //SEG89 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG90 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG91 [32] phi from testBinaryOperator::@8 to testBinaryOperator::@9 [phi:testBinaryOperator::@8->testBinaryOperator::@9] + //SEG92 testBinaryOperator::@9 + //SEG93 [33] call assertType + //SEG94 [87] phi from testBinaryOperator::@9 to assertType [phi:testBinaryOperator::@9->assertType] + //SEG95 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@9->assertType#0] -- register_copy + //SEG96 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG97 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG98 [34] phi from testBinaryOperator::@9 to testBinaryOperator::@10 [phi:testBinaryOperator::@9->testBinaryOperator::@10] + //SEG99 testBinaryOperator::@10 + //SEG100 [35] call assertType + //SEG101 [87] phi from testBinaryOperator::@10 to assertType [phi:testBinaryOperator::@10->assertType] + //SEG102 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@10->assertType#0] -- register_copy + //SEG103 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG104 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG105 [36] phi from testBinaryOperator::@10 to testBinaryOperator::@11 [phi:testBinaryOperator::@10->testBinaryOperator::@11] + //SEG106 testBinaryOperator::@11 + //SEG107 [37] call assertType + //SEG108 [87] phi from testBinaryOperator::@11 to assertType [phi:testBinaryOperator::@11->assertType] + //SEG109 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@11->assertType#0] -- register_copy + //SEG110 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG111 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG112 testBinaryOperator::@12 + //SEG113 [38] (byte) idx#26 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx + inx + //SEG114 [39] call assertType + //SEG115 [87] phi from testBinaryOperator::@12 to assertType [phi:testBinaryOperator::@12->assertType] + //SEG116 [87] phi (byte) idx#105 = (byte) idx#26 [phi:testBinaryOperator::@12->assertType#0] -- register_copy + //SEG117 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG118 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG119 [40] phi from testBinaryOperator::@12 to testBinaryOperator::@13 [phi:testBinaryOperator::@12->testBinaryOperator::@13] + //SEG120 testBinaryOperator::@13 + //SEG121 [41] call assertType + //SEG122 [87] phi from testBinaryOperator::@13 to assertType [phi:testBinaryOperator::@13->assertType] + //SEG123 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@13->assertType#0] -- register_copy + //SEG124 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG125 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG126 [42] phi from testBinaryOperator::@13 to testBinaryOperator::@14 [phi:testBinaryOperator::@13->testBinaryOperator::@14] + //SEG127 testBinaryOperator::@14 + //SEG128 [43] call assertType + //SEG129 [87] phi from testBinaryOperator::@14 to assertType [phi:testBinaryOperator::@14->assertType] + //SEG130 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@14->assertType#0] -- register_copy + //SEG131 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG132 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG133 [44] phi from testBinaryOperator::@14 to testBinaryOperator::@15 [phi:testBinaryOperator::@14->testBinaryOperator::@15] + //SEG134 testBinaryOperator::@15 + //SEG135 [45] call assertType + //SEG136 [87] phi from testBinaryOperator::@15 to assertType [phi:testBinaryOperator::@15->assertType] + //SEG137 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@15->assertType#0] -- register_copy + //SEG138 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG139 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG140 [46] phi from testBinaryOperator::@15 to testBinaryOperator::@16 [phi:testBinaryOperator::@15->testBinaryOperator::@16] + //SEG141 testBinaryOperator::@16 + //SEG142 [47] call assertType + //SEG143 [87] phi from testBinaryOperator::@16 to assertType [phi:testBinaryOperator::@16->assertType] + //SEG144 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@16->assertType#0] -- register_copy + //SEG145 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG146 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG147 [48] phi from testBinaryOperator::@16 to testBinaryOperator::@17 [phi:testBinaryOperator::@16->testBinaryOperator::@17] + //SEG148 testBinaryOperator::@17 + //SEG149 [49] call assertType + //SEG150 [87] phi from testBinaryOperator::@17 to assertType [phi:testBinaryOperator::@17->assertType] + //SEG151 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@17->assertType#0] -- register_copy + //SEG152 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG153 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG154 [50] phi from testBinaryOperator::@17 to testBinaryOperator::@18 [phi:testBinaryOperator::@17->testBinaryOperator::@18] + //SEG155 testBinaryOperator::@18 + //SEG156 [51] call assertType + //SEG157 [87] phi from testBinaryOperator::@18 to assertType [phi:testBinaryOperator::@18->assertType] + //SEG158 [87] phi (byte) idx#105 = (byte) $50 [phi:testBinaryOperator::@18->assertType#0] -- vbuxx=vbuc1 + ldx #$50 + //SEG159 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG160 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG161 [52] phi from testBinaryOperator::@18 to testBinaryOperator::@19 [phi:testBinaryOperator::@18->testBinaryOperator::@19] + //SEG162 testBinaryOperator::@19 + //SEG163 [53] call assertType + //SEG164 [87] phi from testBinaryOperator::@19 to assertType [phi:testBinaryOperator::@19->assertType] + //SEG165 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@19->assertType#0] -- register_copy + //SEG166 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG167 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG168 [54] phi from testBinaryOperator::@19 to testBinaryOperator::@20 [phi:testBinaryOperator::@19->testBinaryOperator::@20] + //SEG169 testBinaryOperator::@20 + //SEG170 [55] call assertType + //SEG171 [87] phi from testBinaryOperator::@20 to assertType [phi:testBinaryOperator::@20->assertType] + //SEG172 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@20->assertType#0] -- register_copy + //SEG173 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG174 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG175 [56] phi from testBinaryOperator::@20 to testBinaryOperator::@21 [phi:testBinaryOperator::@20->testBinaryOperator::@21] + //SEG176 testBinaryOperator::@21 + //SEG177 [57] call assertType + //SEG178 [87] phi from testBinaryOperator::@21 to assertType [phi:testBinaryOperator::@21->assertType] + //SEG179 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@21->assertType#0] -- register_copy + //SEG180 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG181 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG182 [58] phi from testBinaryOperator::@21 to testBinaryOperator::@22 [phi:testBinaryOperator::@21->testBinaryOperator::@22] + //SEG183 testBinaryOperator::@22 + //SEG184 [59] call assertType + //SEG185 [87] phi from testBinaryOperator::@22 to assertType [phi:testBinaryOperator::@22->assertType] + //SEG186 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@22->assertType#0] -- register_copy + //SEG187 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG188 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG189 [60] phi from testBinaryOperator::@22 to testBinaryOperator::@23 [phi:testBinaryOperator::@22->testBinaryOperator::@23] + //SEG190 testBinaryOperator::@23 + //SEG191 [61] call assertType + //SEG192 [87] phi from testBinaryOperator::@23 to assertType [phi:testBinaryOperator::@23->assertType] + //SEG193 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@23->assertType#0] -- register_copy + //SEG194 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG195 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG196 testBinaryOperator::@24 + //SEG197 [62] (byte) idx#40 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx + inx + //SEG198 [63] call assertType + //SEG199 [87] phi from testBinaryOperator::@24 to assertType [phi:testBinaryOperator::@24->assertType] + //SEG200 [87] phi (byte) idx#105 = (byte) idx#40 [phi:testBinaryOperator::@24->assertType#0] -- register_copy + //SEG201 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG202 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG203 [64] phi from testBinaryOperator::@24 to testBinaryOperator::@25 [phi:testBinaryOperator::@24->testBinaryOperator::@25] + //SEG204 testBinaryOperator::@25 + //SEG205 [65] call assertType + //SEG206 [87] phi from testBinaryOperator::@25 to assertType [phi:testBinaryOperator::@25->assertType] + //SEG207 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@25->assertType#0] -- register_copy + //SEG208 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG209 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG210 [66] phi from testBinaryOperator::@25 to testBinaryOperator::@26 [phi:testBinaryOperator::@25->testBinaryOperator::@26] + //SEG211 testBinaryOperator::@26 + //SEG212 [67] call assertType + //SEG213 [87] phi from testBinaryOperator::@26 to assertType [phi:testBinaryOperator::@26->assertType] + //SEG214 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@26->assertType#0] -- register_copy + //SEG215 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG216 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG217 [68] phi from testBinaryOperator::@26 to testBinaryOperator::@27 [phi:testBinaryOperator::@26->testBinaryOperator::@27] + //SEG218 testBinaryOperator::@27 + //SEG219 [69] call assertType + //SEG220 [87] phi from testBinaryOperator::@27 to assertType [phi:testBinaryOperator::@27->assertType] + //SEG221 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@27->assertType#0] -- register_copy + //SEG222 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG223 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG224 [70] phi from testBinaryOperator::@27 to testBinaryOperator::@28 [phi:testBinaryOperator::@27->testBinaryOperator::@28] + //SEG225 testBinaryOperator::@28 + //SEG226 [71] call assertType + //SEG227 [87] phi from testBinaryOperator::@28 to assertType [phi:testBinaryOperator::@28->assertType] + //SEG228 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@28->assertType#0] -- register_copy + //SEG229 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG230 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG231 [72] phi from testBinaryOperator::@28 to testBinaryOperator::@29 [phi:testBinaryOperator::@28->testBinaryOperator::@29] + //SEG232 testBinaryOperator::@29 + //SEG233 [73] call assertType + //SEG234 [87] phi from testBinaryOperator::@29 to assertType [phi:testBinaryOperator::@29->assertType] + //SEG235 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@29->assertType#0] -- register_copy + //SEG236 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG237 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG238 testBinaryOperator::@30 + //SEG239 [74] (byte) idx#47 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx + inx + //SEG240 [75] call assertType + //SEG241 [87] phi from testBinaryOperator::@30 to assertType [phi:testBinaryOperator::@30->assertType] + //SEG242 [87] phi (byte) idx#105 = (byte) idx#47 [phi:testBinaryOperator::@30->assertType#0] -- register_copy + //SEG243 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG244 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG245 [76] phi from testBinaryOperator::@30 to testBinaryOperator::@31 [phi:testBinaryOperator::@30->testBinaryOperator::@31] + //SEG246 testBinaryOperator::@31 + //SEG247 [77] call assertType + //SEG248 [87] phi from testBinaryOperator::@31 to assertType [phi:testBinaryOperator::@31->assertType] + //SEG249 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@31->assertType#0] -- register_copy + //SEG250 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG251 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG252 [78] phi from testBinaryOperator::@31 to testBinaryOperator::@32 [phi:testBinaryOperator::@31->testBinaryOperator::@32] + //SEG253 testBinaryOperator::@32 + //SEG254 [79] call assertType + //SEG255 [87] phi from testBinaryOperator::@32 to assertType [phi:testBinaryOperator::@32->assertType] + //SEG256 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@32->assertType#0] -- register_copy + //SEG257 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG258 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG259 [80] phi from testBinaryOperator::@32 to testBinaryOperator::@33 [phi:testBinaryOperator::@32->testBinaryOperator::@33] + //SEG260 testBinaryOperator::@33 + //SEG261 [81] call assertType + //SEG262 [87] phi from testBinaryOperator::@33 to assertType [phi:testBinaryOperator::@33->assertType] + //SEG263 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@33->assertType#0] -- register_copy + //SEG264 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG265 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG266 [82] phi from testBinaryOperator::@33 to testBinaryOperator::@34 [phi:testBinaryOperator::@33->testBinaryOperator::@34] + //SEG267 testBinaryOperator::@34 + //SEG268 [83] call assertType + //SEG269 [87] phi from testBinaryOperator::@34 to assertType [phi:testBinaryOperator::@34->assertType] + //SEG270 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@34->assertType#0] -- register_copy + //SEG271 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG272 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG273 [84] phi from testBinaryOperator::@34 to testBinaryOperator::@35 [phi:testBinaryOperator::@34->testBinaryOperator::@35] + //SEG274 testBinaryOperator::@35 + //SEG275 [85] call assertType + //SEG276 [87] phi from testBinaryOperator::@35 to assertType [phi:testBinaryOperator::@35->assertType] + //SEG277 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@35->assertType#0] -- register_copy + //SEG278 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG279 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG280 testBinaryOperator::@return + //SEG281 [86] return + rts +} +//SEG282 assertType +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte register(Y) t1, byte zeropage(4) t2) +assertType: { + .label t2 = 4 + //SEG283 [88] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 + tya + cmp t2 + beq b1 + //SEG284 assertType::@3 + //SEG285 [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #RED + sta COLS,x + //SEG286 assertType::@2 + b2: + //SEG287 [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 -- pbuc1_derefidx_vbuxx=vbuyy + tya + sta SCREEN,x + //SEG288 [91] (byte) idx#108 ← ++ (byte) idx#105 -- vbuxx=_inc_vbuxx + inx + //SEG289 assertType::@return + //SEG290 [92] return + rts + //SEG291 assertType::@1 + b1: + //SEG292 [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #GREEN + sta COLS,x + jmp b2 +} +//SEG293 testUnaryOperator +testUnaryOperator: { + //SEG294 [95] call assertType + //SEG295 [87] phi from testUnaryOperator to assertType [phi:testUnaryOperator->assertType] + //SEG296 [87] phi (byte) idx#105 = (byte) 0 [phi:testUnaryOperator->assertType#0] -- vbuxx=vbuc1 + ldx #0 + //SEG297 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG298 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG299 [96] phi from testUnaryOperator to testUnaryOperator::@1 [phi:testUnaryOperator->testUnaryOperator::@1] + //SEG300 testUnaryOperator::@1 + //SEG301 [97] call assertType + //SEG302 [87] phi from testUnaryOperator::@1 to assertType [phi:testUnaryOperator::@1->assertType] + //SEG303 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@1->assertType#0] -- register_copy + //SEG304 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG305 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG306 [98] phi from testUnaryOperator::@1 to testUnaryOperator::@2 [phi:testUnaryOperator::@1->testUnaryOperator::@2] + //SEG307 testUnaryOperator::@2 + //SEG308 [99] call assertType + //SEG309 [87] phi from testUnaryOperator::@2 to assertType [phi:testUnaryOperator::@2->assertType] + //SEG310 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@2->assertType#0] -- register_copy + //SEG311 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG312 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG313 [100] phi from testUnaryOperator::@2 to testUnaryOperator::@3 [phi:testUnaryOperator::@2->testUnaryOperator::@3] + //SEG314 testUnaryOperator::@3 + //SEG315 [101] call assertType + //SEG316 [87] phi from testUnaryOperator::@3 to assertType [phi:testUnaryOperator::@3->assertType] + //SEG317 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@3->assertType#0] -- register_copy + //SEG318 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG319 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG320 [102] phi from testUnaryOperator::@3 to testUnaryOperator::@4 [phi:testUnaryOperator::@3->testUnaryOperator::@4] + //SEG321 testUnaryOperator::@4 + //SEG322 [103] call assertType + //SEG323 [87] phi from testUnaryOperator::@4 to assertType [phi:testUnaryOperator::@4->assertType] + //SEG324 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@4->assertType#0] -- register_copy + //SEG325 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG326 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG327 [104] phi from testUnaryOperator::@4 to testUnaryOperator::@5 [phi:testUnaryOperator::@4->testUnaryOperator::@5] + //SEG328 testUnaryOperator::@5 + //SEG329 [105] call assertType + //SEG330 [87] phi from testUnaryOperator::@5 to assertType [phi:testUnaryOperator::@5->assertType] + //SEG331 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@5->assertType#0] -- register_copy + //SEG332 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG333 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG334 testUnaryOperator::@return + //SEG335 [106] return + rts +} + diff --git a/src/test/ref/int-conversion.sym b/src/test/ref/int-conversion.sym new file mode 100644 index 000000000..c17ed3db6 --- /dev/null +++ b/src/test/ref/int-conversion.sym @@ -0,0 +1,90 @@ +(label) @1 +(label) @begin +(label) @end +(byte*) COLS +(const byte*) COLS#0 COLS = ((byte*))(word) $d800 +(byte) GREEN +(const byte) GREEN#0 GREEN = (byte) 5 +(byte) RED +(const byte) RED#0 RED = (byte) 2 +(byte*) SCREEN +(const byte*) SCREEN#0 SCREEN = ((byte*))(word) $400 +(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1 +(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5 +(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2 +(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6 +(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4 +(const byte) TYPEID_WORD TYPEID_WORD = (number) 3 +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(label) assertType::@1 +(label) assertType::@2 +(label) assertType::@3 +(label) assertType::@return +(byte) assertType::t1 +(byte) assertType::t1#42 reg byte y 1.0 +(byte) assertType::t2 +(byte) assertType::t2#42 t2 zp ZP_BYTE:4 2.0 +(byte) idx +(byte) idx#105 reg byte x 17.200000000000003 +(byte) idx#108 reg byte x 1.0526315789473677 +(byte) idx#19 reg byte x 4.0 +(byte) idx#26 reg byte x 4.0 +(byte) idx#40 reg byte x 4.0 +(byte) idx#47 reg byte x 4.0 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(byte*) main::s +(byte*) main::s#1 s zp ZP_WORD:2 16.5 +(byte*) main::s#2 s zp ZP_WORD:2 16.5 +(void()) testBinaryOperator() +(label) testBinaryOperator::@1 +(label) testBinaryOperator::@10 +(label) testBinaryOperator::@11 +(label) testBinaryOperator::@12 +(label) testBinaryOperator::@13 +(label) testBinaryOperator::@14 +(label) testBinaryOperator::@15 +(label) testBinaryOperator::@16 +(label) testBinaryOperator::@17 +(label) testBinaryOperator::@18 +(label) testBinaryOperator::@19 +(label) testBinaryOperator::@2 +(label) testBinaryOperator::@20 +(label) testBinaryOperator::@21 +(label) testBinaryOperator::@22 +(label) testBinaryOperator::@23 +(label) testBinaryOperator::@24 +(label) testBinaryOperator::@25 +(label) testBinaryOperator::@26 +(label) testBinaryOperator::@27 +(label) testBinaryOperator::@28 +(label) testBinaryOperator::@29 +(label) testBinaryOperator::@3 +(label) testBinaryOperator::@30 +(label) testBinaryOperator::@31 +(label) testBinaryOperator::@32 +(label) testBinaryOperator::@33 +(label) testBinaryOperator::@34 +(label) testBinaryOperator::@35 +(label) testBinaryOperator::@4 +(label) testBinaryOperator::@5 +(label) testBinaryOperator::@6 +(label) testBinaryOperator::@7 +(label) testBinaryOperator::@8 +(label) testBinaryOperator::@9 +(label) testBinaryOperator::@return +(void()) testUnaryOperator() +(label) testUnaryOperator::@1 +(label) testUnaryOperator::@2 +(label) testUnaryOperator::@3 +(label) testUnaryOperator::@4 +(label) testUnaryOperator::@5 +(label) testUnaryOperator::@return + +zp ZP_WORD:2 [ main::s#2 main::s#1 ] +reg byte y [ assertType::t1#42 ] +zp ZP_BYTE:4 [ assertType::t2#42 ] +reg byte x [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] diff --git a/src/test/ref/int-literals.asm b/src/test/ref/int-literals.asm new file mode 100644 index 000000000..8f7755754 --- /dev/null +++ b/src/test/ref/int-literals.asm @@ -0,0 +1,122 @@ +// Tests different integer literal types +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const TYPEID_BYTE = 1 + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_WORD = 3 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_DWORD = 5 + .const TYPEID_SIGNED_DWORD = 6 + .const RED = 2 + .const GREEN = 5 +main: { + .label s = 2 + lda #<$400 + sta s + lda #>$400 + sta s+1 + b1: + lda #' ' + ldy #0 + sta (s),y + inc s + bne !+ + inc s+1 + !: + lda s+1 + cmp #>$400+$3e8 + bcc b1 + bne !+ + lda s + cmp #<$400+$3e8 + bcc b1 + !: + jsr testSimpleTypes + rts +} +testSimpleTypes: { + ldx #0 + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + rts +} +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte register(Y) t1, byte zeropage(4) t2) +assertType: { + .label t2 = 4 + tya + cmp t2 + beq b1 + lda #RED + sta $d800,x + b2: + tya + sta $400,x + inx + rts + b1: + lda #GREEN + sta $d800,x + jmp b2 +} diff --git a/src/test/ref/int-literals.cfg b/src/test/ref/int-literals.cfg new file mode 100644 index 000000000..eb00a0ab4 --- /dev/null +++ b/src/test/ref/int-literals.cfg @@ -0,0 +1,107 @@ +@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::@1 + [5] (byte*) main::s#2 ← phi( main/(byte*)(word) $400 main::@1/(byte*) main::s#1 ) + [6] *((byte*) main::s#2) ← (byte) ' ' + [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 + [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] phi() + [10] call testSimpleTypes + to:main::@return +main::@return: scope:[main] from main::@2 + [11] return + to:@return +testSimpleTypes: scope:[testSimpleTypes] from main::@2 + [12] phi() + [13] call assertType + to:testSimpleTypes::@1 +testSimpleTypes::@1: scope:[testSimpleTypes] from testSimpleTypes + [14] phi() + [15] call assertType + to:testSimpleTypes::@2 +testSimpleTypes::@2: scope:[testSimpleTypes] from testSimpleTypes::@1 + [16] phi() + [17] call assertType + to:testSimpleTypes::@3 +testSimpleTypes::@3: scope:[testSimpleTypes] from testSimpleTypes::@2 + [18] phi() + [19] call assertType + to:testSimpleTypes::@4 +testSimpleTypes::@4: scope:[testSimpleTypes] from testSimpleTypes::@3 + [20] phi() + [21] call assertType + to:testSimpleTypes::@5 +testSimpleTypes::@5: scope:[testSimpleTypes] from testSimpleTypes::@4 + [22] phi() + [23] call assertType + to:testSimpleTypes::@6 +testSimpleTypes::@6: scope:[testSimpleTypes] from testSimpleTypes::@5 + [24] phi() + [25] call assertType + to:testSimpleTypes::@7 +testSimpleTypes::@7: scope:[testSimpleTypes] from testSimpleTypes::@6 + [26] phi() + [27] call assertType + to:testSimpleTypes::@8 +testSimpleTypes::@8: scope:[testSimpleTypes] from testSimpleTypes::@7 + [28] phi() + [29] call assertType + to:testSimpleTypes::@9 +testSimpleTypes::@9: scope:[testSimpleTypes] from testSimpleTypes::@8 + [30] phi() + [31] call assertType + to:testSimpleTypes::@10 +testSimpleTypes::@10: scope:[testSimpleTypes] from testSimpleTypes::@9 + [32] phi() + [33] call assertType + to:testSimpleTypes::@11 +testSimpleTypes::@11: scope:[testSimpleTypes] from testSimpleTypes::@10 + [34] phi() + [35] call assertType + to:testSimpleTypes::@12 +testSimpleTypes::@12: scope:[testSimpleTypes] from testSimpleTypes::@11 + [36] phi() + [37] call assertType + to:testSimpleTypes::@13 +testSimpleTypes::@13: scope:[testSimpleTypes] from testSimpleTypes::@12 + [38] phi() + [39] call assertType + to:testSimpleTypes::@14 +testSimpleTypes::@14: scope:[testSimpleTypes] from testSimpleTypes::@13 + [40] phi() + [41] call assertType + to:testSimpleTypes::@return +testSimpleTypes::@return: scope:[testSimpleTypes] from testSimpleTypes::@14 + [42] return + to:@return +assertType: scope:[assertType] from testSimpleTypes testSimpleTypes::@1 testSimpleTypes::@10 testSimpleTypes::@11 testSimpleTypes::@12 testSimpleTypes::@13 testSimpleTypes::@14 testSimpleTypes::@2 testSimpleTypes::@3 testSimpleTypes::@4 testSimpleTypes::@5 testSimpleTypes::@6 testSimpleTypes::@7 testSimpleTypes::@8 testSimpleTypes::@9 + [43] (byte) idx#41 ← phi( testSimpleTypes/(byte) 0 testSimpleTypes::@1/(byte) idx#20 testSimpleTypes::@10/(byte) idx#20 testSimpleTypes::@11/(byte) idx#20 testSimpleTypes::@12/(byte) idx#20 testSimpleTypes::@13/(byte) idx#20 testSimpleTypes::@14/(byte) idx#20 testSimpleTypes::@2/(byte) idx#20 testSimpleTypes::@3/(byte) idx#20 testSimpleTypes::@4/(byte) idx#20 testSimpleTypes::@5/(byte) idx#20 testSimpleTypes::@6/(byte) idx#20 testSimpleTypes::@7/(byte) idx#20 testSimpleTypes::@8/(byte) idx#20 testSimpleTypes::@9/(byte) idx#20 ) + [43] (byte) assertType::t2#15 ← phi( testSimpleTypes/(const byte) TYPEID_BYTE testSimpleTypes::@1/(const byte) TYPEID_BYTE testSimpleTypes::@10/(const byte) TYPEID_DWORD testSimpleTypes::@11/(const byte) TYPEID_DWORD testSimpleTypes::@12/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@13/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@14/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@2/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@3/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@4/(const byte) TYPEID_WORD testSimpleTypes::@5/(const byte) TYPEID_WORD testSimpleTypes::@6/(const byte) TYPEID_WORD testSimpleTypes::@7/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@8/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@9/(const byte) TYPEID_SIGNED_WORD ) + [43] (byte) assertType::t1#15 ← phi( testSimpleTypes/(const byte) TYPEID_BYTE testSimpleTypes::@1/(const byte) TYPEID_BYTE testSimpleTypes::@10/(const byte) TYPEID_DWORD testSimpleTypes::@11/(const byte) TYPEID_DWORD testSimpleTypes::@12/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@13/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@14/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@2/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@3/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@4/(const byte) TYPEID_WORD testSimpleTypes::@5/(const byte) TYPEID_WORD testSimpleTypes::@6/(const byte) TYPEID_WORD testSimpleTypes::@7/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@8/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@9/(const byte) TYPEID_SIGNED_WORD ) + [44] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1 + to:assertType::@3 +assertType::@3: scope:[assertType] from assertType + [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 + to:assertType::@2 +assertType::@2: scope:[assertType] from assertType::@1 assertType::@3 + [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 + [47] (byte) idx#20 ← ++ (byte) idx#41 + to:assertType::@return +assertType::@return: scope:[assertType] from assertType::@2 + [48] return + to:@return +assertType::@1: scope:[assertType] from assertType + [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 + to:assertType::@2 diff --git a/src/test/ref/int-literals.log b/src/test/ref/int-literals.log new file mode 100644 index 000000000..4030e6548 --- /dev/null +++ b/src/test/ref/int-literals.log @@ -0,0 +1,1947 @@ +Resolving typeid() (byte~) testSimpleTypes::$0 ← typeid (byte) $c +Resolving typeid() (byte~) testSimpleTypes::$2 ← typeid (byte) $c +Resolving typeid() (byte~) testSimpleTypes::$4 ← typeid (signed byte) $c +Resolving typeid() (byte~) testSimpleTypes::$6 ← typeid (signed byte) $c +Resolving typeid() (byte~) testSimpleTypes::$8 ← typeid (word) $c +Resolving typeid() (byte~) testSimpleTypes::$10 ← typeid (word) $c +Resolving typeid() (byte~) testSimpleTypes::$12 ← typeid (word) $c +Resolving typeid() (byte~) testSimpleTypes::$14 ← typeid (signed word) $c +Resolving typeid() (byte~) testSimpleTypes::$16 ← typeid (signed word) $c +Resolving typeid() (byte~) testSimpleTypes::$18 ← typeid (signed word) $c +Resolving typeid() (byte~) testSimpleTypes::$20 ← typeid (dword) $c +Resolving typeid() (byte~) testSimpleTypes::$22 ← typeid (dword) $c +Resolving typeid() (byte~) testSimpleTypes::$24 ← typeid (signed dword) $c +Resolving typeid() (byte~) testSimpleTypes::$26 ← typeid (signed dword) $c +Resolving typeid() (byte~) testSimpleTypes::$28 ← typeid (signed dword) $c +Adding pointer type conversion cast (byte*) SCREEN in (byte*) SCREEN ← (word) $400 +Adding pointer type conversion cast (byte*) COLS in (byte*) COLS ← (word) $d800 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + (byte) RED#0 ← (byte) 2 + (byte) GREEN#0 ← (byte) 5 + (word) $0 ← (word) $400 + (byte*) SCREEN#0 ← ((byte*)) (word) $0 + (word) $1 ← (word) $d800 + (byte*) COLS#0 ← ((byte*)) (word) $1 + (byte) idx#0 ← (byte) 0 + to:@3 +main: scope:[main] from @3 + (byte) idx#50 ← phi( @3/(byte) idx#48 ) + (byte*) main::s#0 ← (byte*) SCREEN#0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) idx#49 ← phi( main/(byte) idx#50 main::@1/(byte) idx#49 ) + (byte*) main::s#2 ← phi( main/(byte*) main::s#0 main::@1/(byte*) main::s#1 ) + *((byte*) main::s#2) ← (byte) ' ' + (byte*) main::s#1 ← ++ (byte*) main::s#2 + (byte*~) main::$1 ← (byte*) SCREEN#0 + (word) $3e8 + (bool~) main::$2 ← (byte*) main::s#1 < (byte*~) main::$1 + if((bool~) main::$2) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte) idx#46 ← phi( main::@1/(byte) idx#49 ) + call testSimpleTypes + to:main::@3 +main::@3: scope:[main] from main::@2 + (byte) idx#23 ← phi( main::@2/(byte) idx#19 ) + (byte) idx#1 ← (byte) idx#23 + to:main::@return +main::@return: scope:[main] from main::@3 + (byte) idx#24 ← phi( main::@3/(byte) idx#1 ) + (byte) idx#2 ← (byte) idx#24 + return + to:@return +testSimpleTypes: scope:[testSimpleTypes] from main::@2 + (byte) idx#3 ← (byte) 0 + (byte~) testSimpleTypes::$0 ← (const byte) TYPEID_BYTE + (byte) assertType::t1#0 ← (byte~) testSimpleTypes::$0 + (byte) assertType::t2#0 ← (const byte) TYPEID_BYTE + call assertType + to:testSimpleTypes::@1 +testSimpleTypes::@1: scope:[testSimpleTypes] from testSimpleTypes + (byte) idx#25 ← phi( testSimpleTypes/(byte) idx#21 ) + (byte) idx#4 ← (byte) idx#25 + (byte~) testSimpleTypes::$2 ← (const byte) TYPEID_BYTE + (byte) assertType::t1#1 ← (byte~) testSimpleTypes::$2 + (byte) assertType::t2#1 ← (const byte) TYPEID_BYTE + call assertType + to:testSimpleTypes::@2 +testSimpleTypes::@2: scope:[testSimpleTypes] from testSimpleTypes::@1 + (byte) idx#26 ← phi( testSimpleTypes::@1/(byte) idx#21 ) + (byte) idx#5 ← (byte) idx#26 + (byte~) testSimpleTypes::$4 ← (const byte) TYPEID_SIGNED_BYTE + (byte) assertType::t1#2 ← (byte~) testSimpleTypes::$4 + (byte) assertType::t2#2 ← (const byte) TYPEID_SIGNED_BYTE + call assertType + to:testSimpleTypes::@3 +testSimpleTypes::@3: scope:[testSimpleTypes] from testSimpleTypes::@2 + (byte) idx#27 ← phi( testSimpleTypes::@2/(byte) idx#21 ) + (byte) idx#6 ← (byte) idx#27 + (byte~) testSimpleTypes::$6 ← (const byte) TYPEID_SIGNED_BYTE + (byte) assertType::t1#3 ← (byte~) testSimpleTypes::$6 + (byte) assertType::t2#3 ← (const byte) TYPEID_SIGNED_BYTE + call assertType + to:testSimpleTypes::@4 +testSimpleTypes::@4: scope:[testSimpleTypes] from testSimpleTypes::@3 + (byte) idx#28 ← phi( testSimpleTypes::@3/(byte) idx#21 ) + (byte) idx#7 ← (byte) idx#28 + (byte~) testSimpleTypes::$8 ← (const byte) TYPEID_WORD + (byte) assertType::t1#4 ← (byte~) testSimpleTypes::$8 + (byte) assertType::t2#4 ← (const byte) TYPEID_WORD + call assertType + to:testSimpleTypes::@5 +testSimpleTypes::@5: scope:[testSimpleTypes] from testSimpleTypes::@4 + (byte) idx#29 ← phi( testSimpleTypes::@4/(byte) idx#21 ) + (byte) idx#8 ← (byte) idx#29 + (byte~) testSimpleTypes::$10 ← (const byte) TYPEID_WORD + (byte) assertType::t1#5 ← (byte~) testSimpleTypes::$10 + (byte) assertType::t2#5 ← (const byte) TYPEID_WORD + call assertType + to:testSimpleTypes::@6 +testSimpleTypes::@6: scope:[testSimpleTypes] from testSimpleTypes::@5 + (byte) idx#30 ← phi( testSimpleTypes::@5/(byte) idx#21 ) + (byte) idx#9 ← (byte) idx#30 + (byte~) testSimpleTypes::$12 ← (const byte) TYPEID_WORD + (byte) assertType::t1#6 ← (byte~) testSimpleTypes::$12 + (byte) assertType::t2#6 ← (const byte) TYPEID_WORD + call assertType + to:testSimpleTypes::@7 +testSimpleTypes::@7: scope:[testSimpleTypes] from testSimpleTypes::@6 + (byte) idx#31 ← phi( testSimpleTypes::@6/(byte) idx#21 ) + (byte) idx#10 ← (byte) idx#31 + (byte~) testSimpleTypes::$14 ← (const byte) TYPEID_SIGNED_WORD + (byte) assertType::t1#7 ← (byte~) testSimpleTypes::$14 + (byte) assertType::t2#7 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:testSimpleTypes::@8 +testSimpleTypes::@8: scope:[testSimpleTypes] from testSimpleTypes::@7 + (byte) idx#32 ← phi( testSimpleTypes::@7/(byte) idx#21 ) + (byte) idx#11 ← (byte) idx#32 + (byte~) testSimpleTypes::$16 ← (const byte) TYPEID_SIGNED_WORD + (byte) assertType::t1#8 ← (byte~) testSimpleTypes::$16 + (byte) assertType::t2#8 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:testSimpleTypes::@9 +testSimpleTypes::@9: scope:[testSimpleTypes] from testSimpleTypes::@8 + (byte) idx#33 ← phi( testSimpleTypes::@8/(byte) idx#21 ) + (byte) idx#12 ← (byte) idx#33 + (byte~) testSimpleTypes::$18 ← (const byte) TYPEID_SIGNED_WORD + (byte) assertType::t1#9 ← (byte~) testSimpleTypes::$18 + (byte) assertType::t2#9 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:testSimpleTypes::@10 +testSimpleTypes::@10: scope:[testSimpleTypes] from testSimpleTypes::@9 + (byte) idx#34 ← phi( testSimpleTypes::@9/(byte) idx#21 ) + (byte) idx#13 ← (byte) idx#34 + (byte~) testSimpleTypes::$20 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#10 ← (byte~) testSimpleTypes::$20 + (byte) assertType::t2#10 ← (const byte) TYPEID_DWORD + call assertType + to:testSimpleTypes::@11 +testSimpleTypes::@11: scope:[testSimpleTypes] from testSimpleTypes::@10 + (byte) idx#35 ← phi( testSimpleTypes::@10/(byte) idx#21 ) + (byte) idx#14 ← (byte) idx#35 + (byte~) testSimpleTypes::$22 ← (const byte) TYPEID_DWORD + (byte) assertType::t1#11 ← (byte~) testSimpleTypes::$22 + (byte) assertType::t2#11 ← (const byte) TYPEID_DWORD + call assertType + to:testSimpleTypes::@12 +testSimpleTypes::@12: scope:[testSimpleTypes] from testSimpleTypes::@11 + (byte) idx#36 ← phi( testSimpleTypes::@11/(byte) idx#21 ) + (byte) idx#15 ← (byte) idx#36 + (byte~) testSimpleTypes::$24 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#12 ← (byte~) testSimpleTypes::$24 + (byte) assertType::t2#12 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testSimpleTypes::@13 +testSimpleTypes::@13: scope:[testSimpleTypes] from testSimpleTypes::@12 + (byte) idx#37 ← phi( testSimpleTypes::@12/(byte) idx#21 ) + (byte) idx#16 ← (byte) idx#37 + (byte~) testSimpleTypes::$26 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#13 ← (byte~) testSimpleTypes::$26 + (byte) assertType::t2#13 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testSimpleTypes::@14 +testSimpleTypes::@14: scope:[testSimpleTypes] from testSimpleTypes::@13 + (byte) idx#38 ← phi( testSimpleTypes::@13/(byte) idx#21 ) + (byte) idx#17 ← (byte) idx#38 + (byte~) testSimpleTypes::$28 ← (const byte) TYPEID_SIGNED_DWORD + (byte) assertType::t1#14 ← (byte~) testSimpleTypes::$28 + (byte) assertType::t2#14 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:testSimpleTypes::@15 +testSimpleTypes::@15: scope:[testSimpleTypes] from testSimpleTypes::@14 + (byte) idx#39 ← phi( testSimpleTypes::@14/(byte) idx#21 ) + (byte) idx#18 ← (byte) idx#39 + to:testSimpleTypes::@return +testSimpleTypes::@return: scope:[testSimpleTypes] from testSimpleTypes::@15 + (byte) idx#40 ← phi( testSimpleTypes::@15/(byte) idx#18 ) + (byte) idx#19 ← (byte) idx#40 + return + to:@return +assertType: scope:[assertType] from testSimpleTypes testSimpleTypes::@1 testSimpleTypes::@10 testSimpleTypes::@11 testSimpleTypes::@12 testSimpleTypes::@13 testSimpleTypes::@14 testSimpleTypes::@2 testSimpleTypes::@3 testSimpleTypes::@4 testSimpleTypes::@5 testSimpleTypes::@6 testSimpleTypes::@7 testSimpleTypes::@8 testSimpleTypes::@9 + (byte) idx#47 ← phi( testSimpleTypes/(byte) idx#3 testSimpleTypes::@1/(byte) idx#4 testSimpleTypes::@10/(byte) idx#13 testSimpleTypes::@11/(byte) idx#14 testSimpleTypes::@12/(byte) idx#15 testSimpleTypes::@13/(byte) idx#16 testSimpleTypes::@14/(byte) idx#17 testSimpleTypes::@2/(byte) idx#5 testSimpleTypes::@3/(byte) idx#6 testSimpleTypes::@4/(byte) idx#7 testSimpleTypes::@5/(byte) idx#8 testSimpleTypes::@6/(byte) idx#9 testSimpleTypes::@7/(byte) idx#10 testSimpleTypes::@8/(byte) idx#11 testSimpleTypes::@9/(byte) idx#12 ) + (byte) assertType::t2#15 ← phi( testSimpleTypes/(byte) assertType::t2#0 testSimpleTypes::@1/(byte) assertType::t2#1 testSimpleTypes::@10/(byte) assertType::t2#10 testSimpleTypes::@11/(byte) assertType::t2#11 testSimpleTypes::@12/(byte) assertType::t2#12 testSimpleTypes::@13/(byte) assertType::t2#13 testSimpleTypes::@14/(byte) assertType::t2#14 testSimpleTypes::@2/(byte) assertType::t2#2 testSimpleTypes::@3/(byte) assertType::t2#3 testSimpleTypes::@4/(byte) assertType::t2#4 testSimpleTypes::@5/(byte) assertType::t2#5 testSimpleTypes::@6/(byte) assertType::t2#6 testSimpleTypes::@7/(byte) assertType::t2#7 testSimpleTypes::@8/(byte) assertType::t2#8 testSimpleTypes::@9/(byte) assertType::t2#9 ) + (byte) assertType::t1#15 ← phi( testSimpleTypes/(byte) assertType::t1#0 testSimpleTypes::@1/(byte) assertType::t1#1 testSimpleTypes::@10/(byte) assertType::t1#10 testSimpleTypes::@11/(byte) assertType::t1#11 testSimpleTypes::@12/(byte) assertType::t1#12 testSimpleTypes::@13/(byte) assertType::t1#13 testSimpleTypes::@14/(byte) assertType::t1#14 testSimpleTypes::@2/(byte) assertType::t1#2 testSimpleTypes::@3/(byte) assertType::t1#3 testSimpleTypes::@4/(byte) assertType::t1#4 testSimpleTypes::@5/(byte) assertType::t1#5 testSimpleTypes::@6/(byte) assertType::t1#6 testSimpleTypes::@7/(byte) assertType::t1#7 testSimpleTypes::@8/(byte) assertType::t1#8 testSimpleTypes::@9/(byte) assertType::t1#9 ) + (bool~) assertType::$0 ← (byte) assertType::t1#15 == (byte) assertType::t2#15 + if((bool~) assertType::$0) goto assertType::@1 + to:assertType::@3 +assertType::@1: scope:[assertType] from assertType + (byte) assertType::t1#17 ← phi( assertType/(byte) assertType::t1#15 ) + (byte) idx#41 ← phi( assertType/(byte) idx#47 ) + *((byte*) COLS#0 + (byte) idx#41) ← (byte) GREEN#0 + to:assertType::@2 +assertType::@3: scope:[assertType] from assertType + (byte) assertType::t1#18 ← phi( assertType/(byte) assertType::t1#15 ) + (byte) idx#42 ← phi( assertType/(byte) idx#47 ) + *((byte*) COLS#0 + (byte) idx#42) ← (byte) RED#0 + to:assertType::@2 +assertType::@2: scope:[assertType] from assertType::@1 assertType::@3 + (byte) idx#43 ← phi( assertType::@1/(byte) idx#41 assertType::@3/(byte) idx#42 ) + (byte) assertType::t1#16 ← phi( assertType::@1/(byte) assertType::t1#17 assertType::@3/(byte) assertType::t1#18 ) + *((byte*) SCREEN#0 + (byte) idx#43) ← (byte) assertType::t1#16 + (byte) idx#20 ← ++ (byte) idx#43 + to:assertType::@return +assertType::@return: scope:[assertType] from assertType::@2 + (byte) idx#44 ← phi( assertType::@2/(byte) idx#20 ) + (byte) idx#21 ← (byte) idx#44 + return + to:@return +@3: scope:[] from @begin + (byte) idx#48 ← phi( @begin/(byte) idx#0 ) + call main + to:@4 +@4: scope:[] from @3 + (byte) idx#45 ← phi( @3/(byte) idx#2 ) + (byte) idx#22 ← (byte) idx#45 + to:@end +@end: scope:[] from @4 + +SYMBOL TABLE SSA +(word) $0 +(word) $1 +(label) @3 +(label) @4 +(label) @begin +(label) @end +(byte*) COLS +(byte*) COLS#0 +(byte) GREEN +(byte) GREEN#0 +(byte) RED +(byte) RED#0 +(byte*) SCREEN +(byte*) SCREEN#0 +(const byte) TYPEID_BYTE = (number) 1 +(const byte) TYPEID_DWORD = (number) 5 +(const byte) TYPEID_SIGNED_BYTE = (number) 2 +(const byte) TYPEID_SIGNED_DWORD = (number) 6 +(const byte) TYPEID_SIGNED_WORD = (number) 4 +(const byte) TYPEID_WORD = (number) 3 +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(bool~) assertType::$0 +(label) assertType::@1 +(label) assertType::@2 +(label) assertType::@3 +(label) assertType::@return +(byte) assertType::t1 +(byte) assertType::t1#0 +(byte) assertType::t1#1 +(byte) assertType::t1#10 +(byte) assertType::t1#11 +(byte) assertType::t1#12 +(byte) assertType::t1#13 +(byte) assertType::t1#14 +(byte) assertType::t1#15 +(byte) assertType::t1#16 +(byte) assertType::t1#17 +(byte) assertType::t1#18 +(byte) assertType::t1#2 +(byte) assertType::t1#3 +(byte) assertType::t1#4 +(byte) assertType::t1#5 +(byte) assertType::t1#6 +(byte) assertType::t1#7 +(byte) assertType::t1#8 +(byte) assertType::t1#9 +(byte) assertType::t2 +(byte) assertType::t2#0 +(byte) assertType::t2#1 +(byte) assertType::t2#10 +(byte) assertType::t2#11 +(byte) assertType::t2#12 +(byte) assertType::t2#13 +(byte) assertType::t2#14 +(byte) assertType::t2#15 +(byte) assertType::t2#2 +(byte) assertType::t2#3 +(byte) assertType::t2#4 +(byte) assertType::t2#5 +(byte) assertType::t2#6 +(byte) assertType::t2#7 +(byte) assertType::t2#8 +(byte) assertType::t2#9 +(byte) idx +(byte) idx#0 +(byte) idx#1 +(byte) idx#10 +(byte) idx#11 +(byte) idx#12 +(byte) idx#13 +(byte) idx#14 +(byte) idx#15 +(byte) idx#16 +(byte) idx#17 +(byte) idx#18 +(byte) idx#19 +(byte) idx#2 +(byte) idx#20 +(byte) idx#21 +(byte) idx#22 +(byte) idx#23 +(byte) idx#24 +(byte) idx#25 +(byte) idx#26 +(byte) idx#27 +(byte) idx#28 +(byte) idx#29 +(byte) idx#3 +(byte) idx#30 +(byte) idx#31 +(byte) idx#32 +(byte) idx#33 +(byte) idx#34 +(byte) idx#35 +(byte) idx#36 +(byte) idx#37 +(byte) idx#38 +(byte) idx#39 +(byte) idx#4 +(byte) idx#40 +(byte) idx#41 +(byte) idx#42 +(byte) idx#43 +(byte) idx#44 +(byte) idx#45 +(byte) idx#46 +(byte) idx#47 +(byte) idx#48 +(byte) idx#49 +(byte) idx#5 +(byte) idx#50 +(byte) idx#6 +(byte) idx#7 +(byte) idx#8 +(byte) idx#9 +(void()) main() +(byte*~) main::$1 +(bool~) main::$2 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(byte*) main::s +(byte*) main::s#0 +(byte*) main::s#1 +(byte*) main::s#2 +(void()) testSimpleTypes() +(byte~) testSimpleTypes::$0 +(byte~) testSimpleTypes::$10 +(byte~) testSimpleTypes::$12 +(byte~) testSimpleTypes::$14 +(byte~) testSimpleTypes::$16 +(byte~) testSimpleTypes::$18 +(byte~) testSimpleTypes::$2 +(byte~) testSimpleTypes::$20 +(byte~) testSimpleTypes::$22 +(byte~) testSimpleTypes::$24 +(byte~) testSimpleTypes::$26 +(byte~) testSimpleTypes::$28 +(byte~) testSimpleTypes::$4 +(byte~) testSimpleTypes::$6 +(byte~) testSimpleTypes::$8 +(label) testSimpleTypes::@1 +(label) testSimpleTypes::@10 +(label) testSimpleTypes::@11 +(label) testSimpleTypes::@12 +(label) testSimpleTypes::@13 +(label) testSimpleTypes::@14 +(label) testSimpleTypes::@15 +(label) testSimpleTypes::@2 +(label) testSimpleTypes::@3 +(label) testSimpleTypes::@4 +(label) testSimpleTypes::@5 +(label) testSimpleTypes::@6 +(label) testSimpleTypes::@7 +(label) testSimpleTypes::@8 +(label) testSimpleTypes::@9 +(label) testSimpleTypes::@return + +Alias (byte) idx#46 = (byte) idx#49 +Alias (byte) idx#1 = (byte) idx#23 (byte) idx#24 (byte) idx#2 +Alias (byte) assertType::t1#0 = (byte~) testSimpleTypes::$0 +Alias (byte) idx#25 = (byte) idx#4 +Alias (byte) assertType::t1#1 = (byte~) testSimpleTypes::$2 +Alias (byte) idx#26 = (byte) idx#5 +Alias (byte) assertType::t1#2 = (byte~) testSimpleTypes::$4 +Alias (byte) idx#27 = (byte) idx#6 +Alias (byte) assertType::t1#3 = (byte~) testSimpleTypes::$6 +Alias (byte) idx#28 = (byte) idx#7 +Alias (byte) assertType::t1#4 = (byte~) testSimpleTypes::$8 +Alias (byte) idx#29 = (byte) idx#8 +Alias (byte) assertType::t1#5 = (byte~) testSimpleTypes::$10 +Alias (byte) idx#30 = (byte) idx#9 +Alias (byte) assertType::t1#6 = (byte~) testSimpleTypes::$12 +Alias (byte) idx#10 = (byte) idx#31 +Alias (byte) assertType::t1#7 = (byte~) testSimpleTypes::$14 +Alias (byte) idx#11 = (byte) idx#32 +Alias (byte) assertType::t1#8 = (byte~) testSimpleTypes::$16 +Alias (byte) idx#12 = (byte) idx#33 +Alias (byte) assertType::t1#9 = (byte~) testSimpleTypes::$18 +Alias (byte) idx#13 = (byte) idx#34 +Alias (byte) assertType::t1#10 = (byte~) testSimpleTypes::$20 +Alias (byte) idx#14 = (byte) idx#35 +Alias (byte) assertType::t1#11 = (byte~) testSimpleTypes::$22 +Alias (byte) idx#15 = (byte) idx#36 +Alias (byte) assertType::t1#12 = (byte~) testSimpleTypes::$24 +Alias (byte) idx#16 = (byte) idx#37 +Alias (byte) assertType::t1#13 = (byte~) testSimpleTypes::$26 +Alias (byte) idx#17 = (byte) idx#38 +Alias (byte) assertType::t1#14 = (byte~) testSimpleTypes::$28 +Alias (byte) idx#18 = (byte) idx#39 (byte) idx#40 (byte) idx#19 +Alias (byte) idx#41 = (byte) idx#47 (byte) idx#42 +Alias (byte) assertType::t1#15 = (byte) assertType::t1#17 (byte) assertType::t1#18 +Alias (byte) idx#20 = (byte) idx#44 (byte) idx#21 +Alias (byte) idx#0 = (byte) idx#48 +Alias (byte) idx#22 = (byte) idx#45 +Successful SSA optimization Pass2AliasElimination +Alias (byte) assertType::t1#15 = (byte) assertType::t1#16 +Alias (byte) idx#41 = (byte) idx#43 +Successful SSA optimization Pass2AliasElimination +Self Phi Eliminated (byte) idx#46 +Successful SSA optimization Pass2SelfPhiElimination +Redundant Phi (byte) idx#50 (byte) idx#0 +Redundant Phi (byte) idx#46 (byte) idx#50 +Redundant Phi (byte) idx#1 (byte) idx#18 +Redundant Phi (byte) idx#25 (byte) idx#20 +Redundant Phi (byte) idx#26 (byte) idx#20 +Redundant Phi (byte) idx#27 (byte) idx#20 +Redundant Phi (byte) idx#28 (byte) idx#20 +Redundant Phi (byte) idx#29 (byte) idx#20 +Redundant Phi (byte) idx#30 (byte) idx#20 +Redundant Phi (byte) idx#10 (byte) idx#20 +Redundant Phi (byte) idx#11 (byte) idx#20 +Redundant Phi (byte) idx#12 (byte) idx#20 +Redundant Phi (byte) idx#13 (byte) idx#20 +Redundant Phi (byte) idx#14 (byte) idx#20 +Redundant Phi (byte) idx#15 (byte) idx#20 +Redundant Phi (byte) idx#16 (byte) idx#20 +Redundant Phi (byte) idx#17 (byte) idx#20 +Redundant Phi (byte) idx#18 (byte) idx#20 +Redundant Phi (byte) idx#22 (byte) idx#1 +Successful SSA optimization Pass2RedundantPhiElimination +Simple Condition (bool~) main::$2 [14] if((byte*) main::s#1<(byte*~) main::$1) goto main::@1 +Simple Condition (bool~) assertType::$0 [118] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant (const byte) RED#0 = 2 +Constant (const byte) GREEN#0 = 5 +Constant (const word) $0 = $400 +Constant (const word) $1 = $d800 +Constant (const byte) idx#0 = 0 +Constant (const byte) idx#3 = 0 +Constant (const byte) assertType::t1#0 = TYPEID_BYTE +Constant (const byte) assertType::t2#0 = TYPEID_BYTE +Constant (const byte) assertType::t1#1 = TYPEID_BYTE +Constant (const byte) assertType::t2#1 = TYPEID_BYTE +Constant (const byte) assertType::t1#2 = TYPEID_SIGNED_BYTE +Constant (const byte) assertType::t2#2 = TYPEID_SIGNED_BYTE +Constant (const byte) assertType::t1#3 = TYPEID_SIGNED_BYTE +Constant (const byte) assertType::t2#3 = TYPEID_SIGNED_BYTE +Constant (const byte) assertType::t1#4 = TYPEID_WORD +Constant (const byte) assertType::t2#4 = TYPEID_WORD +Constant (const byte) assertType::t1#5 = TYPEID_WORD +Constant (const byte) assertType::t2#5 = TYPEID_WORD +Constant (const byte) assertType::t1#6 = TYPEID_WORD +Constant (const byte) assertType::t2#6 = TYPEID_WORD +Constant (const byte) assertType::t1#7 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#7 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t1#8 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#8 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t1#9 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#9 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t1#10 = TYPEID_DWORD +Constant (const byte) assertType::t2#10 = TYPEID_DWORD +Constant (const byte) assertType::t1#11 = TYPEID_DWORD +Constant (const byte) assertType::t2#11 = TYPEID_DWORD +Constant (const byte) assertType::t1#12 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#12 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t1#13 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#13 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t1#14 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#14 = TYPEID_SIGNED_DWORD +Successful SSA optimization Pass2ConstantIdentification +Eliminating unused constant (const byte) idx#0 +Successful SSA optimization PassNEliminateUnusedVars +Eliminating Noop Cast (byte*) SCREEN#0 ← ((byte*)) (const word) $0 +Eliminating Noop Cast (byte*) COLS#0 ← ((byte*)) (const word) $1 +Successful SSA optimization Pass2NopCastElimination +Culled Empty Block (label) main::@3 +Culled Empty Block (label) testSimpleTypes::@15 +Culled Empty Block (label) @4 +Successful SSA optimization Pass2CullEmptyBlocks +Constant right-side identified [4] (byte*~) main::$1 ← (byte*)(const word) $0 + (word) $3e8 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte*) main::s#0 = (byte*)$0 +Constant (const byte*) main::$1 = (byte*)$0+$3e8 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with var siblings (const byte*) main::s#0 +Inlining constant with var siblings (const byte) assertType::t1#0 +Inlining constant with var siblings (const byte) assertType::t2#0 +Inlining constant with var siblings (const byte) assertType::t1#1 +Inlining constant with var siblings (const byte) assertType::t2#1 +Inlining constant with var siblings (const byte) assertType::t1#2 +Inlining constant with var siblings (const byte) assertType::t2#2 +Inlining constant with var siblings (const byte) assertType::t1#3 +Inlining constant with var siblings (const byte) assertType::t2#3 +Inlining constant with var siblings (const byte) assertType::t1#4 +Inlining constant with var siblings (const byte) assertType::t2#4 +Inlining constant with var siblings (const byte) assertType::t1#5 +Inlining constant with var siblings (const byte) assertType::t2#5 +Inlining constant with var siblings (const byte) assertType::t1#6 +Inlining constant with var siblings (const byte) assertType::t2#6 +Inlining constant with var siblings (const byte) assertType::t1#7 +Inlining constant with var siblings (const byte) assertType::t2#7 +Inlining constant with var siblings (const byte) assertType::t1#8 +Inlining constant with var siblings (const byte) assertType::t2#8 +Inlining constant with var siblings (const byte) assertType::t1#9 +Inlining constant with var siblings (const byte) assertType::t2#9 +Inlining constant with var siblings (const byte) assertType::t1#10 +Inlining constant with var siblings (const byte) assertType::t2#10 +Inlining constant with var siblings (const byte) assertType::t1#11 +Inlining constant with var siblings (const byte) assertType::t2#11 +Inlining constant with var siblings (const byte) assertType::t1#12 +Inlining constant with var siblings (const byte) assertType::t2#12 +Inlining constant with var siblings (const byte) assertType::t1#13 +Inlining constant with var siblings (const byte) assertType::t2#13 +Inlining constant with var siblings (const byte) assertType::t1#14 +Inlining constant with var siblings (const byte) assertType::t2#14 +Inlining constant with var siblings (const byte) idx#3 +Constant inlined assertType::t2#5 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#6 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#6 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#7 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#7 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t1#8 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#8 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t1#9 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#9 = (const byte) TYPEID_SIGNED_WORD +Constant inlined $0 = (word) $400 +Constant inlined $1 = (word) $d800 +Constant inlined assertType::t2#11 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#10 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#13 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#12 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#14 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#0 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#0 = (const byte) TYPEID_BYTE +Constant inlined assertType::t1#1 = (const byte) TYPEID_BYTE +Constant inlined idx#3 = (byte) 0 +Constant inlined assertType::t2#1 = (const byte) TYPEID_BYTE +Constant inlined assertType::t1#2 = (const byte) TYPEID_SIGNED_BYTE +Constant inlined assertType::t2#2 = (const byte) TYPEID_SIGNED_BYTE +Constant inlined assertType::t1#3 = (const byte) TYPEID_SIGNED_BYTE +Constant inlined assertType::t2#3 = (const byte) TYPEID_SIGNED_BYTE +Constant inlined assertType::t1#4 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#4 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#5 = (const byte) TYPEID_WORD +Constant inlined main::s#0 = (byte*)(word) $400 +Constant inlined main::$1 = (byte*)(word) $400+(word) $3e8 +Constant inlined assertType::t1#10 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#12 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#11 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#14 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#13 = (const byte) TYPEID_SIGNED_DWORD +Successful SSA optimization Pass2ConstantInlining +Added new block during phi lifting main::@4(between main::@1 and main::@1) +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @3 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@2 +Adding NOP phi() at start of testSimpleTypes +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to testSimpleTypes:10 +Calls in [testSimpleTypes] to assertType:14 assertType:16 assertType:18 assertType:20 assertType:22 assertType:24 assertType:26 assertType:28 assertType:30 assertType:32 assertType:34 assertType:36 assertType:38 assertType:40 assertType:42 + +Created 4 initial phi equivalence classes +Coalesced [12] main::s#3 ← main::s#1 +Coalesced [15] idx#51 ← idx#20 +Coalesced (already) [17] idx#57 ← idx#20 +Coalesced (already) [19] idx#58 ← idx#20 +Coalesced (already) [21] idx#59 ← idx#20 +Coalesced (already) [23] idx#60 ← idx#20 +Coalesced (already) [25] idx#61 ← idx#20 +Coalesced (already) [27] idx#62 ← idx#20 +Coalesced (already) [29] idx#63 ← idx#20 +Coalesced (already) [31] idx#64 ← idx#20 +Coalesced (already) [33] idx#52 ← idx#20 +Coalesced (already) [35] idx#53 ← idx#20 +Coalesced (already) [37] idx#54 ← idx#20 +Coalesced (already) [39] idx#55 ← idx#20 +Coalesced (already) [41] idx#56 ← idx#20 +Coalesced down to 4 phi equivalence classes +Culled Empty Block (label) main::@4 +Renumbering block @3 to @1 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@2 +Adding NOP phi() at start of testSimpleTypes +Adding NOP phi() at start of testSimpleTypes::@1 +Adding NOP phi() at start of testSimpleTypes::@2 +Adding NOP phi() at start of testSimpleTypes::@3 +Adding NOP phi() at start of testSimpleTypes::@4 +Adding NOP phi() at start of testSimpleTypes::@5 +Adding NOP phi() at start of testSimpleTypes::@6 +Adding NOP phi() at start of testSimpleTypes::@7 +Adding NOP phi() at start of testSimpleTypes::@8 +Adding NOP phi() at start of testSimpleTypes::@9 +Adding NOP phi() at start of testSimpleTypes::@10 +Adding NOP phi() at start of testSimpleTypes::@11 +Adding NOP phi() at start of testSimpleTypes::@12 +Adding NOP phi() at start of testSimpleTypes::@13 +Adding NOP phi() at start of testSimpleTypes::@14 + +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::@1 + [5] (byte*) main::s#2 ← phi( main/(byte*)(word) $400 main::@1/(byte*) main::s#1 ) + [6] *((byte*) main::s#2) ← (byte) ' ' + [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 + [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] phi() + [10] call testSimpleTypes + to:main::@return +main::@return: scope:[main] from main::@2 + [11] return + to:@return +testSimpleTypes: scope:[testSimpleTypes] from main::@2 + [12] phi() + [13] call assertType + to:testSimpleTypes::@1 +testSimpleTypes::@1: scope:[testSimpleTypes] from testSimpleTypes + [14] phi() + [15] call assertType + to:testSimpleTypes::@2 +testSimpleTypes::@2: scope:[testSimpleTypes] from testSimpleTypes::@1 + [16] phi() + [17] call assertType + to:testSimpleTypes::@3 +testSimpleTypes::@3: scope:[testSimpleTypes] from testSimpleTypes::@2 + [18] phi() + [19] call assertType + to:testSimpleTypes::@4 +testSimpleTypes::@4: scope:[testSimpleTypes] from testSimpleTypes::@3 + [20] phi() + [21] call assertType + to:testSimpleTypes::@5 +testSimpleTypes::@5: scope:[testSimpleTypes] from testSimpleTypes::@4 + [22] phi() + [23] call assertType + to:testSimpleTypes::@6 +testSimpleTypes::@6: scope:[testSimpleTypes] from testSimpleTypes::@5 + [24] phi() + [25] call assertType + to:testSimpleTypes::@7 +testSimpleTypes::@7: scope:[testSimpleTypes] from testSimpleTypes::@6 + [26] phi() + [27] call assertType + to:testSimpleTypes::@8 +testSimpleTypes::@8: scope:[testSimpleTypes] from testSimpleTypes::@7 + [28] phi() + [29] call assertType + to:testSimpleTypes::@9 +testSimpleTypes::@9: scope:[testSimpleTypes] from testSimpleTypes::@8 + [30] phi() + [31] call assertType + to:testSimpleTypes::@10 +testSimpleTypes::@10: scope:[testSimpleTypes] from testSimpleTypes::@9 + [32] phi() + [33] call assertType + to:testSimpleTypes::@11 +testSimpleTypes::@11: scope:[testSimpleTypes] from testSimpleTypes::@10 + [34] phi() + [35] call assertType + to:testSimpleTypes::@12 +testSimpleTypes::@12: scope:[testSimpleTypes] from testSimpleTypes::@11 + [36] phi() + [37] call assertType + to:testSimpleTypes::@13 +testSimpleTypes::@13: scope:[testSimpleTypes] from testSimpleTypes::@12 + [38] phi() + [39] call assertType + to:testSimpleTypes::@14 +testSimpleTypes::@14: scope:[testSimpleTypes] from testSimpleTypes::@13 + [40] phi() + [41] call assertType + to:testSimpleTypes::@return +testSimpleTypes::@return: scope:[testSimpleTypes] from testSimpleTypes::@14 + [42] return + to:@return +assertType: scope:[assertType] from testSimpleTypes testSimpleTypes::@1 testSimpleTypes::@10 testSimpleTypes::@11 testSimpleTypes::@12 testSimpleTypes::@13 testSimpleTypes::@14 testSimpleTypes::@2 testSimpleTypes::@3 testSimpleTypes::@4 testSimpleTypes::@5 testSimpleTypes::@6 testSimpleTypes::@7 testSimpleTypes::@8 testSimpleTypes::@9 + [43] (byte) idx#41 ← phi( testSimpleTypes/(byte) 0 testSimpleTypes::@1/(byte) idx#20 testSimpleTypes::@10/(byte) idx#20 testSimpleTypes::@11/(byte) idx#20 testSimpleTypes::@12/(byte) idx#20 testSimpleTypes::@13/(byte) idx#20 testSimpleTypes::@14/(byte) idx#20 testSimpleTypes::@2/(byte) idx#20 testSimpleTypes::@3/(byte) idx#20 testSimpleTypes::@4/(byte) idx#20 testSimpleTypes::@5/(byte) idx#20 testSimpleTypes::@6/(byte) idx#20 testSimpleTypes::@7/(byte) idx#20 testSimpleTypes::@8/(byte) idx#20 testSimpleTypes::@9/(byte) idx#20 ) + [43] (byte) assertType::t2#15 ← phi( testSimpleTypes/(const byte) TYPEID_BYTE testSimpleTypes::@1/(const byte) TYPEID_BYTE testSimpleTypes::@10/(const byte) TYPEID_DWORD testSimpleTypes::@11/(const byte) TYPEID_DWORD testSimpleTypes::@12/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@13/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@14/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@2/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@3/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@4/(const byte) TYPEID_WORD testSimpleTypes::@5/(const byte) TYPEID_WORD testSimpleTypes::@6/(const byte) TYPEID_WORD testSimpleTypes::@7/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@8/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@9/(const byte) TYPEID_SIGNED_WORD ) + [43] (byte) assertType::t1#15 ← phi( testSimpleTypes/(const byte) TYPEID_BYTE testSimpleTypes::@1/(const byte) TYPEID_BYTE testSimpleTypes::@10/(const byte) TYPEID_DWORD testSimpleTypes::@11/(const byte) TYPEID_DWORD testSimpleTypes::@12/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@13/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@14/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@2/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@3/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@4/(const byte) TYPEID_WORD testSimpleTypes::@5/(const byte) TYPEID_WORD testSimpleTypes::@6/(const byte) TYPEID_WORD testSimpleTypes::@7/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@8/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@9/(const byte) TYPEID_SIGNED_WORD ) + [44] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1 + to:assertType::@3 +assertType::@3: scope:[assertType] from assertType + [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 + to:assertType::@2 +assertType::@2: scope:[assertType] from assertType::@1 assertType::@3 + [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 + [47] (byte) idx#20 ← ++ (byte) idx#41 + to:assertType::@return +assertType::@return: scope:[assertType] from assertType::@2 + [48] return + to:@return +assertType::@1: scope:[assertType] from assertType + [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 + to:assertType::@2 + + +VARIABLE REGISTER WEIGHTS +(byte*) COLS +(byte) GREEN +(byte) RED +(byte*) SCREEN +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(byte) assertType::t1 +(byte) assertType::t1#15 1.0 +(byte) assertType::t2 +(byte) assertType::t2#15 2.0 +(byte) idx +(byte) idx#20 0.9999999999999999 +(byte) idx#41 7.200000000000002 +(void()) main() +(byte*) main::s +(byte*) main::s#1 16.5 +(byte*) main::s#2 16.5 +(void()) testSimpleTypes() + +Initial phi equivalence classes +[ main::s#2 main::s#1 ] +[ assertType::t1#15 ] +[ assertType::t2#15 ] +[ idx#41 idx#20 ] +Complete equivalence classes +[ main::s#2 main::s#1 ] +[ assertType::t1#15 ] +[ assertType::t2#15 ] +[ idx#41 idx#20 ] +Allocated zp ZP_WORD:2 [ main::s#2 main::s#1 ] +Allocated zp ZP_BYTE:4 [ assertType::t1#15 ] +Allocated zp ZP_BYTE:5 [ assertType::t2#15 ] +Allocated zp ZP_BYTE:6 [ idx#41 idx#20 ] + +INITIAL ASM +//SEG0 File Comments +// Tests different integer literal types +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const TYPEID_BYTE = 1 + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_WORD = 3 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_DWORD = 5 + .const TYPEID_SIGNED_DWORD = 6 + .const RED = 2 + .const GREEN = 5 + .label idx = 6 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG9 @end +bend: +//SEG10 main +main: { + .label s = 2 + //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG12 [5] phi (byte*) main::s#2 = (byte*)(word) $400 [phi:main->main::@1#0] -- pbuz1=pbuc1 + lda #<$400 + sta s + lda #>$400 + sta s+1 + jmp b1 + //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy + jmp b1 + //SEG15 main::@1 + b1: + //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 + lda #' ' + ldy #0 + sta (s),y + //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 + inc s + bne !+ + inc s+1 + !: + //SEG18 [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 + lda s+1 + cmp #>$400+$3e8 + bcc b1_from_b1 + bne !+ + lda s + cmp #<$400+$3e8 + bcc b1_from_b1 + !: + //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + jmp b2 + //SEG20 main::@2 + b2: + //SEG21 [10] call testSimpleTypes + //SEG22 [12] phi from main::@2 to testSimpleTypes [phi:main::@2->testSimpleTypes] + testSimpleTypes_from_b2: + jsr testSimpleTypes + jmp breturn + //SEG23 main::@return + breturn: + //SEG24 [11] return + rts +} +//SEG25 testSimpleTypes +testSimpleTypes: { + //SEG26 [13] call assertType + //SEG27 [43] phi from testSimpleTypes to assertType [phi:testSimpleTypes->assertType] + assertType_from_testSimpleTypes: + //SEG28 [43] phi (byte) idx#41 = (byte) 0 [phi:testSimpleTypes->assertType#0] -- vbuz1=vbuc1 + lda #0 + sta idx + //SEG29 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG30 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG31 [14] phi from testSimpleTypes to testSimpleTypes::@1 [phi:testSimpleTypes->testSimpleTypes::@1] + b1_from_testSimpleTypes: + jmp b1 + //SEG32 testSimpleTypes::@1 + b1: + //SEG33 [15] call assertType + //SEG34 [43] phi from testSimpleTypes::@1 to assertType [phi:testSimpleTypes::@1->assertType] + assertType_from_b1: + //SEG35 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@1->assertType#0] -- register_copy + //SEG36 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG37 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG38 [16] phi from testSimpleTypes::@1 to testSimpleTypes::@2 [phi:testSimpleTypes::@1->testSimpleTypes::@2] + b2_from_b1: + jmp b2 + //SEG39 testSimpleTypes::@2 + b2: + //SEG40 [17] call assertType + //SEG41 [43] phi from testSimpleTypes::@2 to assertType [phi:testSimpleTypes::@2->assertType] + assertType_from_b2: + //SEG42 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@2->assertType#0] -- register_copy + //SEG43 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG44 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t1 + jsr assertType + //SEG45 [18] phi from testSimpleTypes::@2 to testSimpleTypes::@3 [phi:testSimpleTypes::@2->testSimpleTypes::@3] + b3_from_b2: + jmp b3 + //SEG46 testSimpleTypes::@3 + b3: + //SEG47 [19] call assertType + //SEG48 [43] phi from testSimpleTypes::@3 to assertType [phi:testSimpleTypes::@3->assertType] + assertType_from_b3: + //SEG49 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@3->assertType#0] -- register_copy + //SEG50 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG51 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t1 + jsr assertType + //SEG52 [20] phi from testSimpleTypes::@3 to testSimpleTypes::@4 [phi:testSimpleTypes::@3->testSimpleTypes::@4] + b4_from_b3: + jmp b4 + //SEG53 testSimpleTypes::@4 + b4: + //SEG54 [21] call assertType + //SEG55 [43] phi from testSimpleTypes::@4 to assertType [phi:testSimpleTypes::@4->assertType] + assertType_from_b4: + //SEG56 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@4->assertType#0] -- register_copy + //SEG57 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG58 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG59 [22] phi from testSimpleTypes::@4 to testSimpleTypes::@5 [phi:testSimpleTypes::@4->testSimpleTypes::@5] + b5_from_b4: + jmp b5 + //SEG60 testSimpleTypes::@5 + b5: + //SEG61 [23] call assertType + //SEG62 [43] phi from testSimpleTypes::@5 to assertType [phi:testSimpleTypes::@5->assertType] + assertType_from_b5: + //SEG63 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@5->assertType#0] -- register_copy + //SEG64 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG65 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG66 [24] phi from testSimpleTypes::@5 to testSimpleTypes::@6 [phi:testSimpleTypes::@5->testSimpleTypes::@6] + b6_from_b5: + jmp b6 + //SEG67 testSimpleTypes::@6 + b6: + //SEG68 [25] call assertType + //SEG69 [43] phi from testSimpleTypes::@6 to assertType [phi:testSimpleTypes::@6->assertType] + assertType_from_b6: + //SEG70 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@6->assertType#0] -- register_copy + //SEG71 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG72 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG73 [26] phi from testSimpleTypes::@6 to testSimpleTypes::@7 [phi:testSimpleTypes::@6->testSimpleTypes::@7] + b7_from_b6: + jmp b7 + //SEG74 testSimpleTypes::@7 + b7: + //SEG75 [27] call assertType + //SEG76 [43] phi from testSimpleTypes::@7 to assertType [phi:testSimpleTypes::@7->assertType] + assertType_from_b7: + //SEG77 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@7->assertType#0] -- register_copy + //SEG78 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG79 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG80 [28] phi from testSimpleTypes::@7 to testSimpleTypes::@8 [phi:testSimpleTypes::@7->testSimpleTypes::@8] + b8_from_b7: + jmp b8 + //SEG81 testSimpleTypes::@8 + b8: + //SEG82 [29] call assertType + //SEG83 [43] phi from testSimpleTypes::@8 to assertType [phi:testSimpleTypes::@8->assertType] + assertType_from_b8: + //SEG84 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@8->assertType#0] -- register_copy + //SEG85 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG86 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG87 [30] phi from testSimpleTypes::@8 to testSimpleTypes::@9 [phi:testSimpleTypes::@8->testSimpleTypes::@9] + b9_from_b8: + jmp b9 + //SEG88 testSimpleTypes::@9 + b9: + //SEG89 [31] call assertType + //SEG90 [43] phi from testSimpleTypes::@9 to assertType [phi:testSimpleTypes::@9->assertType] + assertType_from_b9: + //SEG91 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@9->assertType#0] -- register_copy + //SEG92 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG93 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG94 [32] phi from testSimpleTypes::@9 to testSimpleTypes::@10 [phi:testSimpleTypes::@9->testSimpleTypes::@10] + b10_from_b9: + jmp b10 + //SEG95 testSimpleTypes::@10 + b10: + //SEG96 [33] call assertType + //SEG97 [43] phi from testSimpleTypes::@10 to assertType [phi:testSimpleTypes::@10->assertType] + assertType_from_b10: + //SEG98 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@10->assertType#0] -- register_copy + //SEG99 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG100 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG101 [34] phi from testSimpleTypes::@10 to testSimpleTypes::@11 [phi:testSimpleTypes::@10->testSimpleTypes::@11] + b11_from_b10: + jmp b11 + //SEG102 testSimpleTypes::@11 + b11: + //SEG103 [35] call assertType + //SEG104 [43] phi from testSimpleTypes::@11 to assertType [phi:testSimpleTypes::@11->assertType] + assertType_from_b11: + //SEG105 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@11->assertType#0] -- register_copy + //SEG106 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG107 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG108 [36] phi from testSimpleTypes::@11 to testSimpleTypes::@12 [phi:testSimpleTypes::@11->testSimpleTypes::@12] + b12_from_b11: + jmp b12 + //SEG109 testSimpleTypes::@12 + b12: + //SEG110 [37] call assertType + //SEG111 [43] phi from testSimpleTypes::@12 to assertType [phi:testSimpleTypes::@12->assertType] + assertType_from_b12: + //SEG112 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@12->assertType#0] -- register_copy + //SEG113 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG114 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG115 [38] phi from testSimpleTypes::@12 to testSimpleTypes::@13 [phi:testSimpleTypes::@12->testSimpleTypes::@13] + b13_from_b12: + jmp b13 + //SEG116 testSimpleTypes::@13 + b13: + //SEG117 [39] call assertType + //SEG118 [43] phi from testSimpleTypes::@13 to assertType [phi:testSimpleTypes::@13->assertType] + assertType_from_b13: + //SEG119 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@13->assertType#0] -- register_copy + //SEG120 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG121 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG122 [40] phi from testSimpleTypes::@13 to testSimpleTypes::@14 [phi:testSimpleTypes::@13->testSimpleTypes::@14] + b14_from_b13: + jmp b14 + //SEG123 testSimpleTypes::@14 + b14: + //SEG124 [41] call assertType + //SEG125 [43] phi from testSimpleTypes::@14 to assertType [phi:testSimpleTypes::@14->assertType] + assertType_from_b14: + //SEG126 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@14->assertType#0] -- register_copy + //SEG127 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG128 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + jmp breturn + //SEG129 testSimpleTypes::@return + breturn: + //SEG130 [42] return + rts +} +//SEG131 assertType +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte zeropage(4) t1, byte zeropage(5) t2) +assertType: { + .label t1 = 4 + .label t2 = 5 + //SEG132 [44] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1 -- vbuz1_eq_vbuz2_then_la1 + lda t1 + cmp t2 + beq b1 + jmp b3 + //SEG133 assertType::@3 + b3: + //SEG134 [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #RED + ldy idx + sta $d800,y + jmp b2 + //SEG135 assertType::@2 + b2: + //SEG136 [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 -- pbuc1_derefidx_vbuz1=vbuz2 + lda t1 + ldy idx + sta $400,y + //SEG137 [47] (byte) idx#20 ← ++ (byte) idx#41 -- vbuz1=_inc_vbuz1 + inc idx + jmp breturn + //SEG138 assertType::@return + breturn: + //SEG139 [48] return + rts + //SEG140 assertType::@1 + b1: + //SEG141 [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #GREEN + ldy idx + sta $d800,y + jmp b2 +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [6] *((byte*) main::s#2) ← (byte) ' ' [ main::s#2 ] ( main:2 [ main::s#2 ] ) always clobbers reg byte a reg byte y +Statement [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 [ main::s#1 ] ( main:2 [ main::s#1 ] ) always clobbers reg byte a +Statement [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 [ assertType::t1#15 idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ assertType::t1#15 idx#41 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ assertType::t1#15 ] +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ idx#41 idx#20 ] +Statement [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 [ idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ idx#41 ] ) always clobbers reg byte a +Statement [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 [ assertType::t1#15 idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ assertType::t1#15 idx#41 ] ) always clobbers reg byte a +Statement [6] *((byte*) main::s#2) ← (byte) ' ' [ main::s#2 ] ( main:2 [ main::s#2 ] ) always clobbers reg byte a reg byte y +Statement [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 [ main::s#1 ] ( main:2 [ main::s#1 ] ) always clobbers reg byte a +Statement [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 [ assertType::t1#15 idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ assertType::t1#15 idx#41 ] ) always clobbers reg byte a +Statement [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 [ idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ idx#41 ] ) always clobbers reg byte a +Statement [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 [ assertType::t1#15 idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ assertType::t1#15 idx#41 ] ) always clobbers reg byte a +Potential registers zp ZP_WORD:2 [ main::s#2 main::s#1 ] : zp ZP_WORD:2 , +Potential registers zp ZP_BYTE:4 [ assertType::t1#15 ] : zp ZP_BYTE:4 , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:5 [ assertType::t2#15 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:6 [ idx#41 idx#20 ] : zp ZP_BYTE:6 , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 33: zp ZP_WORD:2 [ main::s#2 main::s#1 ] +Uplift Scope [] 8.2: zp ZP_BYTE:6 [ idx#41 idx#20 ] +Uplift Scope [assertType] 2: zp ZP_BYTE:5 [ assertType::t2#15 ] 1: zp ZP_BYTE:4 [ assertType::t1#15 ] +Uplift Scope [testSimpleTypes] + +Uplifting [main] best 978 combination zp ZP_WORD:2 [ main::s#2 main::s#1 ] +Uplifting [] best 963 combination reg byte x [ idx#41 idx#20 ] +Uplifting [assertType] best 916 combination zp ZP_BYTE:5 [ assertType::t2#15 ] reg byte y [ assertType::t1#15 ] +Uplifting [testSimpleTypes] best 916 combination +Attempting to uplift remaining variables inzp ZP_BYTE:5 [ assertType::t2#15 ] +Uplifting [assertType] best 916 combination zp ZP_BYTE:5 [ assertType::t2#15 ] +Allocated (was zp ZP_BYTE:5) zp ZP_BYTE:4 [ assertType::t2#15 ] + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 File Comments +// Tests different integer literal types +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const TYPEID_BYTE = 1 + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_WORD = 3 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_DWORD = 5 + .const TYPEID_SIGNED_DWORD = 6 + .const RED = 2 + .const GREEN = 5 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG9 @end +bend: +//SEG10 main +main: { + .label s = 2 + //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG12 [5] phi (byte*) main::s#2 = (byte*)(word) $400 [phi:main->main::@1#0] -- pbuz1=pbuc1 + lda #<$400 + sta s + lda #>$400 + sta s+1 + jmp b1 + //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy + jmp b1 + //SEG15 main::@1 + b1: + //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 + lda #' ' + ldy #0 + sta (s),y + //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 + inc s + bne !+ + inc s+1 + !: + //SEG18 [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 + lda s+1 + cmp #>$400+$3e8 + bcc b1_from_b1 + bne !+ + lda s + cmp #<$400+$3e8 + bcc b1_from_b1 + !: + //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + jmp b2 + //SEG20 main::@2 + b2: + //SEG21 [10] call testSimpleTypes + //SEG22 [12] phi from main::@2 to testSimpleTypes [phi:main::@2->testSimpleTypes] + testSimpleTypes_from_b2: + jsr testSimpleTypes + jmp breturn + //SEG23 main::@return + breturn: + //SEG24 [11] return + rts +} +//SEG25 testSimpleTypes +testSimpleTypes: { + //SEG26 [13] call assertType + //SEG27 [43] phi from testSimpleTypes to assertType [phi:testSimpleTypes->assertType] + assertType_from_testSimpleTypes: + //SEG28 [43] phi (byte) idx#41 = (byte) 0 [phi:testSimpleTypes->assertType#0] -- vbuxx=vbuc1 + ldx #0 + //SEG29 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG30 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG31 [14] phi from testSimpleTypes to testSimpleTypes::@1 [phi:testSimpleTypes->testSimpleTypes::@1] + b1_from_testSimpleTypes: + jmp b1 + //SEG32 testSimpleTypes::@1 + b1: + //SEG33 [15] call assertType + //SEG34 [43] phi from testSimpleTypes::@1 to assertType [phi:testSimpleTypes::@1->assertType] + assertType_from_b1: + //SEG35 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@1->assertType#0] -- register_copy + //SEG36 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG37 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG38 [16] phi from testSimpleTypes::@1 to testSimpleTypes::@2 [phi:testSimpleTypes::@1->testSimpleTypes::@2] + b2_from_b1: + jmp b2 + //SEG39 testSimpleTypes::@2 + b2: + //SEG40 [17] call assertType + //SEG41 [43] phi from testSimpleTypes::@2 to assertType [phi:testSimpleTypes::@2->assertType] + assertType_from_b2: + //SEG42 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@2->assertType#0] -- register_copy + //SEG43 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG44 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_BYTE + jsr assertType + //SEG45 [18] phi from testSimpleTypes::@2 to testSimpleTypes::@3 [phi:testSimpleTypes::@2->testSimpleTypes::@3] + b3_from_b2: + jmp b3 + //SEG46 testSimpleTypes::@3 + b3: + //SEG47 [19] call assertType + //SEG48 [43] phi from testSimpleTypes::@3 to assertType [phi:testSimpleTypes::@3->assertType] + assertType_from_b3: + //SEG49 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@3->assertType#0] -- register_copy + //SEG50 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG51 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_BYTE + jsr assertType + //SEG52 [20] phi from testSimpleTypes::@3 to testSimpleTypes::@4 [phi:testSimpleTypes::@3->testSimpleTypes::@4] + b4_from_b3: + jmp b4 + //SEG53 testSimpleTypes::@4 + b4: + //SEG54 [21] call assertType + //SEG55 [43] phi from testSimpleTypes::@4 to assertType [phi:testSimpleTypes::@4->assertType] + assertType_from_b4: + //SEG56 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@4->assertType#0] -- register_copy + //SEG57 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG58 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG59 [22] phi from testSimpleTypes::@4 to testSimpleTypes::@5 [phi:testSimpleTypes::@4->testSimpleTypes::@5] + b5_from_b4: + jmp b5 + //SEG60 testSimpleTypes::@5 + b5: + //SEG61 [23] call assertType + //SEG62 [43] phi from testSimpleTypes::@5 to assertType [phi:testSimpleTypes::@5->assertType] + assertType_from_b5: + //SEG63 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@5->assertType#0] -- register_copy + //SEG64 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG65 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG66 [24] phi from testSimpleTypes::@5 to testSimpleTypes::@6 [phi:testSimpleTypes::@5->testSimpleTypes::@6] + b6_from_b5: + jmp b6 + //SEG67 testSimpleTypes::@6 + b6: + //SEG68 [25] call assertType + //SEG69 [43] phi from testSimpleTypes::@6 to assertType [phi:testSimpleTypes::@6->assertType] + assertType_from_b6: + //SEG70 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@6->assertType#0] -- register_copy + //SEG71 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG72 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG73 [26] phi from testSimpleTypes::@6 to testSimpleTypes::@7 [phi:testSimpleTypes::@6->testSimpleTypes::@7] + b7_from_b6: + jmp b7 + //SEG74 testSimpleTypes::@7 + b7: + //SEG75 [27] call assertType + //SEG76 [43] phi from testSimpleTypes::@7 to assertType [phi:testSimpleTypes::@7->assertType] + assertType_from_b7: + //SEG77 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@7->assertType#0] -- register_copy + //SEG78 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG79 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG80 [28] phi from testSimpleTypes::@7 to testSimpleTypes::@8 [phi:testSimpleTypes::@7->testSimpleTypes::@8] + b8_from_b7: + jmp b8 + //SEG81 testSimpleTypes::@8 + b8: + //SEG82 [29] call assertType + //SEG83 [43] phi from testSimpleTypes::@8 to assertType [phi:testSimpleTypes::@8->assertType] + assertType_from_b8: + //SEG84 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@8->assertType#0] -- register_copy + //SEG85 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG86 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG87 [30] phi from testSimpleTypes::@8 to testSimpleTypes::@9 [phi:testSimpleTypes::@8->testSimpleTypes::@9] + b9_from_b8: + jmp b9 + //SEG88 testSimpleTypes::@9 + b9: + //SEG89 [31] call assertType + //SEG90 [43] phi from testSimpleTypes::@9 to assertType [phi:testSimpleTypes::@9->assertType] + assertType_from_b9: + //SEG91 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@9->assertType#0] -- register_copy + //SEG92 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG93 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG94 [32] phi from testSimpleTypes::@9 to testSimpleTypes::@10 [phi:testSimpleTypes::@9->testSimpleTypes::@10] + b10_from_b9: + jmp b10 + //SEG95 testSimpleTypes::@10 + b10: + //SEG96 [33] call assertType + //SEG97 [43] phi from testSimpleTypes::@10 to assertType [phi:testSimpleTypes::@10->assertType] + assertType_from_b10: + //SEG98 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@10->assertType#0] -- register_copy + //SEG99 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG100 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG101 [34] phi from testSimpleTypes::@10 to testSimpleTypes::@11 [phi:testSimpleTypes::@10->testSimpleTypes::@11] + b11_from_b10: + jmp b11 + //SEG102 testSimpleTypes::@11 + b11: + //SEG103 [35] call assertType + //SEG104 [43] phi from testSimpleTypes::@11 to assertType [phi:testSimpleTypes::@11->assertType] + assertType_from_b11: + //SEG105 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@11->assertType#0] -- register_copy + //SEG106 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG107 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG108 [36] phi from testSimpleTypes::@11 to testSimpleTypes::@12 [phi:testSimpleTypes::@11->testSimpleTypes::@12] + b12_from_b11: + jmp b12 + //SEG109 testSimpleTypes::@12 + b12: + //SEG110 [37] call assertType + //SEG111 [43] phi from testSimpleTypes::@12 to assertType [phi:testSimpleTypes::@12->assertType] + assertType_from_b12: + //SEG112 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@12->assertType#0] -- register_copy + //SEG113 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG114 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG115 [38] phi from testSimpleTypes::@12 to testSimpleTypes::@13 [phi:testSimpleTypes::@12->testSimpleTypes::@13] + b13_from_b12: + jmp b13 + //SEG116 testSimpleTypes::@13 + b13: + //SEG117 [39] call assertType + //SEG118 [43] phi from testSimpleTypes::@13 to assertType [phi:testSimpleTypes::@13->assertType] + assertType_from_b13: + //SEG119 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@13->assertType#0] -- register_copy + //SEG120 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG121 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG122 [40] phi from testSimpleTypes::@13 to testSimpleTypes::@14 [phi:testSimpleTypes::@13->testSimpleTypes::@14] + b14_from_b13: + jmp b14 + //SEG123 testSimpleTypes::@14 + b14: + //SEG124 [41] call assertType + //SEG125 [43] phi from testSimpleTypes::@14 to assertType [phi:testSimpleTypes::@14->assertType] + assertType_from_b14: + //SEG126 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@14->assertType#0] -- register_copy + //SEG127 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG128 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + jmp breturn + //SEG129 testSimpleTypes::@return + breturn: + //SEG130 [42] return + rts +} +//SEG131 assertType +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte register(Y) t1, byte zeropage(4) t2) +assertType: { + .label t2 = 4 + //SEG132 [44] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 + tya + cmp t2 + beq b1 + jmp b3 + //SEG133 assertType::@3 + b3: + //SEG134 [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #RED + sta $d800,x + jmp b2 + //SEG135 assertType::@2 + b2: + //SEG136 [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 -- pbuc1_derefidx_vbuxx=vbuyy + tya + sta $400,x + //SEG137 [47] (byte) idx#20 ← ++ (byte) idx#41 -- vbuxx=_inc_vbuxx + inx + jmp breturn + //SEG138 assertType::@return + breturn: + //SEG139 [48] return + rts + //SEG140 assertType::@1 + b1: + //SEG141 [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #GREEN + sta $d800,x + jmp b2 +} + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp breturn +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp b3 +Removing instruction jmp b4 +Removing instruction jmp b5 +Removing instruction jmp b6 +Removing instruction jmp b7 +Removing instruction jmp b8 +Removing instruction jmp b9 +Removing instruction jmp b10 +Removing instruction jmp b11 +Removing instruction jmp b12 +Removing instruction jmp b13 +Removing instruction jmp b14 +Removing instruction jmp breturn +Removing instruction jmp b3 +Removing instruction jmp b2 +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_SIGNED_BYTE with TAY +Replacing instruction ldy #TYPEID_SIGNED_BYTE with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing label b1_from_b1 with b1 +Replacing label b1_from_b1 with b1 +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Removing instruction b1_from_b1: +Removing instruction b2_from_b1: +Removing instruction testSimpleTypes_from_b2: +Removing instruction b1_from_testSimpleTypes: +Removing instruction assertType_from_b1: +Removing instruction b2_from_b1: +Removing instruction assertType_from_b2: +Removing instruction b3_from_b2: +Removing instruction assertType_from_b3: +Removing instruction b4_from_b3: +Removing instruction assertType_from_b4: +Removing instruction b5_from_b4: +Removing instruction assertType_from_b5: +Removing instruction b6_from_b5: +Removing instruction assertType_from_b6: +Removing instruction b7_from_b6: +Removing instruction assertType_from_b7: +Removing instruction b8_from_b7: +Removing instruction assertType_from_b8: +Removing instruction b9_from_b8: +Removing instruction assertType_from_b9: +Removing instruction b10_from_b9: +Removing instruction assertType_from_b10: +Removing instruction b11_from_b10: +Removing instruction assertType_from_b11: +Removing instruction b12_from_b11: +Removing instruction assertType_from_b12: +Removing instruction b13_from_b12: +Removing instruction assertType_from_b13: +Removing instruction b14_from_b13: +Removing instruction assertType_from_b14: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction b2: +Removing instruction breturn: +Removing instruction assertType_from_testSimpleTypes: +Removing instruction b1: +Removing instruction b2: +Removing instruction b3: +Removing instruction b4: +Removing instruction b5: +Removing instruction b6: +Removing instruction b7: +Removing instruction b8: +Removing instruction b9: +Removing instruction b10: +Removing instruction b11: +Removing instruction b12: +Removing instruction b13: +Removing instruction b14: +Removing instruction breturn: +Removing instruction b3: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction jmp b1 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(byte*) COLS +(byte) GREEN +(const byte) GREEN#0 GREEN = (byte) 5 +(byte) RED +(const byte) RED#0 RED = (byte) 2 +(byte*) SCREEN +(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1 +(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5 +(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2 +(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6 +(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4 +(const byte) TYPEID_WORD TYPEID_WORD = (number) 3 +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(label) assertType::@1 +(label) assertType::@2 +(label) assertType::@3 +(label) assertType::@return +(byte) assertType::t1 +(byte) assertType::t1#15 reg byte y 1.0 +(byte) assertType::t2 +(byte) assertType::t2#15 t2 zp ZP_BYTE:4 2.0 +(byte) idx +(byte) idx#20 reg byte x 0.9999999999999999 +(byte) idx#41 reg byte x 7.200000000000002 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(byte*) main::s +(byte*) main::s#1 s zp ZP_WORD:2 16.5 +(byte*) main::s#2 s zp ZP_WORD:2 16.5 +(void()) testSimpleTypes() +(label) testSimpleTypes::@1 +(label) testSimpleTypes::@10 +(label) testSimpleTypes::@11 +(label) testSimpleTypes::@12 +(label) testSimpleTypes::@13 +(label) testSimpleTypes::@14 +(label) testSimpleTypes::@2 +(label) testSimpleTypes::@3 +(label) testSimpleTypes::@4 +(label) testSimpleTypes::@5 +(label) testSimpleTypes::@6 +(label) testSimpleTypes::@7 +(label) testSimpleTypes::@8 +(label) testSimpleTypes::@9 +(label) testSimpleTypes::@return + +zp ZP_WORD:2 [ main::s#2 main::s#1 ] +reg byte y [ assertType::t1#15 ] +zp ZP_BYTE:4 [ assertType::t2#15 ] +reg byte x [ idx#41 idx#20 ] + + +FINAL ASSEMBLER +Score: 784 + +//SEG0 File Comments +// Tests different integer literal types +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const TYPEID_BYTE = 1 + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_WORD = 3 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_DWORD = 5 + .const TYPEID_SIGNED_DWORD = 6 + .const RED = 2 + .const GREEN = 5 +//SEG3 @begin +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +//SEG5 @1 +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +//SEG9 @end +//SEG10 main +main: { + .label s = 2 + //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] + //SEG12 [5] phi (byte*) main::s#2 = (byte*)(word) $400 [phi:main->main::@1#0] -- pbuz1=pbuc1 + lda #<$400 + sta s + lda #>$400 + sta s+1 + //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG15 main::@1 + b1: + //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 + lda #' ' + ldy #0 + sta (s),y + //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 + inc s + bne !+ + inc s+1 + !: + //SEG18 [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 + lda s+1 + cmp #>$400+$3e8 + bcc b1 + bne !+ + lda s + cmp #<$400+$3e8 + bcc b1 + !: + //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + //SEG20 main::@2 + //SEG21 [10] call testSimpleTypes + //SEG22 [12] phi from main::@2 to testSimpleTypes [phi:main::@2->testSimpleTypes] + jsr testSimpleTypes + //SEG23 main::@return + //SEG24 [11] return + rts +} +//SEG25 testSimpleTypes +testSimpleTypes: { + //SEG26 [13] call assertType + //SEG27 [43] phi from testSimpleTypes to assertType [phi:testSimpleTypes->assertType] + //SEG28 [43] phi (byte) idx#41 = (byte) 0 [phi:testSimpleTypes->assertType#0] -- vbuxx=vbuc1 + ldx #0 + //SEG29 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG30 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG31 [14] phi from testSimpleTypes to testSimpleTypes::@1 [phi:testSimpleTypes->testSimpleTypes::@1] + //SEG32 testSimpleTypes::@1 + //SEG33 [15] call assertType + //SEG34 [43] phi from testSimpleTypes::@1 to assertType [phi:testSimpleTypes::@1->assertType] + //SEG35 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@1->assertType#0] -- register_copy + //SEG36 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG37 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG38 [16] phi from testSimpleTypes::@1 to testSimpleTypes::@2 [phi:testSimpleTypes::@1->testSimpleTypes::@2] + //SEG39 testSimpleTypes::@2 + //SEG40 [17] call assertType + //SEG41 [43] phi from testSimpleTypes::@2 to assertType [phi:testSimpleTypes::@2->assertType] + //SEG42 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@2->assertType#0] -- register_copy + //SEG43 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG44 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG45 [18] phi from testSimpleTypes::@2 to testSimpleTypes::@3 [phi:testSimpleTypes::@2->testSimpleTypes::@3] + //SEG46 testSimpleTypes::@3 + //SEG47 [19] call assertType + //SEG48 [43] phi from testSimpleTypes::@3 to assertType [phi:testSimpleTypes::@3->assertType] + //SEG49 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@3->assertType#0] -- register_copy + //SEG50 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG51 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG52 [20] phi from testSimpleTypes::@3 to testSimpleTypes::@4 [phi:testSimpleTypes::@3->testSimpleTypes::@4] + //SEG53 testSimpleTypes::@4 + //SEG54 [21] call assertType + //SEG55 [43] phi from testSimpleTypes::@4 to assertType [phi:testSimpleTypes::@4->assertType] + //SEG56 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@4->assertType#0] -- register_copy + //SEG57 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG58 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG59 [22] phi from testSimpleTypes::@4 to testSimpleTypes::@5 [phi:testSimpleTypes::@4->testSimpleTypes::@5] + //SEG60 testSimpleTypes::@5 + //SEG61 [23] call assertType + //SEG62 [43] phi from testSimpleTypes::@5 to assertType [phi:testSimpleTypes::@5->assertType] + //SEG63 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@5->assertType#0] -- register_copy + //SEG64 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG65 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG66 [24] phi from testSimpleTypes::@5 to testSimpleTypes::@6 [phi:testSimpleTypes::@5->testSimpleTypes::@6] + //SEG67 testSimpleTypes::@6 + //SEG68 [25] call assertType + //SEG69 [43] phi from testSimpleTypes::@6 to assertType [phi:testSimpleTypes::@6->assertType] + //SEG70 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@6->assertType#0] -- register_copy + //SEG71 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG72 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG73 [26] phi from testSimpleTypes::@6 to testSimpleTypes::@7 [phi:testSimpleTypes::@6->testSimpleTypes::@7] + //SEG74 testSimpleTypes::@7 + //SEG75 [27] call assertType + //SEG76 [43] phi from testSimpleTypes::@7 to assertType [phi:testSimpleTypes::@7->assertType] + //SEG77 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@7->assertType#0] -- register_copy + //SEG78 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG79 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG80 [28] phi from testSimpleTypes::@7 to testSimpleTypes::@8 [phi:testSimpleTypes::@7->testSimpleTypes::@8] + //SEG81 testSimpleTypes::@8 + //SEG82 [29] call assertType + //SEG83 [43] phi from testSimpleTypes::@8 to assertType [phi:testSimpleTypes::@8->assertType] + //SEG84 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@8->assertType#0] -- register_copy + //SEG85 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG86 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG87 [30] phi from testSimpleTypes::@8 to testSimpleTypes::@9 [phi:testSimpleTypes::@8->testSimpleTypes::@9] + //SEG88 testSimpleTypes::@9 + //SEG89 [31] call assertType + //SEG90 [43] phi from testSimpleTypes::@9 to assertType [phi:testSimpleTypes::@9->assertType] + //SEG91 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@9->assertType#0] -- register_copy + //SEG92 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG93 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG94 [32] phi from testSimpleTypes::@9 to testSimpleTypes::@10 [phi:testSimpleTypes::@9->testSimpleTypes::@10] + //SEG95 testSimpleTypes::@10 + //SEG96 [33] call assertType + //SEG97 [43] phi from testSimpleTypes::@10 to assertType [phi:testSimpleTypes::@10->assertType] + //SEG98 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@10->assertType#0] -- register_copy + //SEG99 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG100 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG101 [34] phi from testSimpleTypes::@10 to testSimpleTypes::@11 [phi:testSimpleTypes::@10->testSimpleTypes::@11] + //SEG102 testSimpleTypes::@11 + //SEG103 [35] call assertType + //SEG104 [43] phi from testSimpleTypes::@11 to assertType [phi:testSimpleTypes::@11->assertType] + //SEG105 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@11->assertType#0] -- register_copy + //SEG106 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG107 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG108 [36] phi from testSimpleTypes::@11 to testSimpleTypes::@12 [phi:testSimpleTypes::@11->testSimpleTypes::@12] + //SEG109 testSimpleTypes::@12 + //SEG110 [37] call assertType + //SEG111 [43] phi from testSimpleTypes::@12 to assertType [phi:testSimpleTypes::@12->assertType] + //SEG112 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@12->assertType#0] -- register_copy + //SEG113 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG114 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG115 [38] phi from testSimpleTypes::@12 to testSimpleTypes::@13 [phi:testSimpleTypes::@12->testSimpleTypes::@13] + //SEG116 testSimpleTypes::@13 + //SEG117 [39] call assertType + //SEG118 [43] phi from testSimpleTypes::@13 to assertType [phi:testSimpleTypes::@13->assertType] + //SEG119 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@13->assertType#0] -- register_copy + //SEG120 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG121 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG122 [40] phi from testSimpleTypes::@13 to testSimpleTypes::@14 [phi:testSimpleTypes::@13->testSimpleTypes::@14] + //SEG123 testSimpleTypes::@14 + //SEG124 [41] call assertType + //SEG125 [43] phi from testSimpleTypes::@14 to assertType [phi:testSimpleTypes::@14->assertType] + //SEG126 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@14->assertType#0] -- register_copy + //SEG127 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG128 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG129 testSimpleTypes::@return + //SEG130 [42] return + rts +} +//SEG131 assertType +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte register(Y) t1, byte zeropage(4) t2) +assertType: { + .label t2 = 4 + //SEG132 [44] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 + tya + cmp t2 + beq b1 + //SEG133 assertType::@3 + //SEG134 [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #RED + sta $d800,x + //SEG135 assertType::@2 + b2: + //SEG136 [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 -- pbuc1_derefidx_vbuxx=vbuyy + tya + sta $400,x + //SEG137 [47] (byte) idx#20 ← ++ (byte) idx#41 -- vbuxx=_inc_vbuxx + inx + //SEG138 assertType::@return + //SEG139 [48] return + rts + //SEG140 assertType::@1 + b1: + //SEG141 [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #GREEN + sta $d800,x + jmp b2 +} + diff --git a/src/test/ref/int-literals.sym b/src/test/ref/int-literals.sym new file mode 100644 index 000000000..ea8cfda80 --- /dev/null +++ b/src/test/ref/int-literals.sym @@ -0,0 +1,55 @@ +(label) @1 +(label) @begin +(label) @end +(byte*) COLS +(byte) GREEN +(const byte) GREEN#0 GREEN = (byte) 5 +(byte) RED +(const byte) RED#0 RED = (byte) 2 +(byte*) SCREEN +(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1 +(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5 +(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2 +(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6 +(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4 +(const byte) TYPEID_WORD TYPEID_WORD = (number) 3 +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(label) assertType::@1 +(label) assertType::@2 +(label) assertType::@3 +(label) assertType::@return +(byte) assertType::t1 +(byte) assertType::t1#15 reg byte y 1.0 +(byte) assertType::t2 +(byte) assertType::t2#15 t2 zp ZP_BYTE:4 2.0 +(byte) idx +(byte) idx#20 reg byte x 0.9999999999999999 +(byte) idx#41 reg byte x 7.200000000000002 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(byte*) main::s +(byte*) main::s#1 s zp ZP_WORD:2 16.5 +(byte*) main::s#2 s zp ZP_WORD:2 16.5 +(void()) testSimpleTypes() +(label) testSimpleTypes::@1 +(label) testSimpleTypes::@10 +(label) testSimpleTypes::@11 +(label) testSimpleTypes::@12 +(label) testSimpleTypes::@13 +(label) testSimpleTypes::@14 +(label) testSimpleTypes::@2 +(label) testSimpleTypes::@3 +(label) testSimpleTypes::@4 +(label) testSimpleTypes::@5 +(label) testSimpleTypes::@6 +(label) testSimpleTypes::@7 +(label) testSimpleTypes::@8 +(label) testSimpleTypes::@9 +(label) testSimpleTypes::@return + +zp ZP_WORD:2 [ main::s#2 main::s#1 ] +reg byte y [ assertType::t1#15 ] +zp ZP_BYTE:4 [ assertType::t2#15 ] +reg byte x [ idx#41 idx#20 ] diff --git a/src/test/ref/number-conversion.asm b/src/test/ref/number-conversion.asm new file mode 100644 index 000000000..17df64b44 --- /dev/null +++ b/src/test/ref/number-conversion.asm @@ -0,0 +1,180 @@ +// Tests conversion of numbers to correct int types +// See https://gitlab.com/camelot/kickc/issues/181 +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_SIGNED_DWORD = 6 + .const TYPEID_BYTE = 1 + .const TYPEID_WORD = 3 + .const TYPEID_DWORD = 5 + .const RED = 2 + .const GREEN = 5 +main: { + ldx #0 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + tay + jsr assertType + ldx #$28 + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + ldx #$50 + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_BYTE + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_WORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + tay + jsr assertType + lda #TYPEID_DWORD + sta assertType.t2 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + rts +} +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte register(Y) t1, byte zeropage(2) t2) +assertType: { + .label t2 = 2 + tya + cmp t2 + beq b1 + lda #RED + sta $d800,x + b2: + tya + sta $400,x + inx + rts + b1: + lda #GREEN + sta $d800,x + jmp b2 +} diff --git a/src/test/ref/number-conversion.cfg b/src/test/ref/number-conversion.cfg new file mode 100644 index 000000000..746b50917 --- /dev/null +++ b/src/test/ref/number-conversion.cfg @@ -0,0 +1,171 @@ +@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 assertType + to:main::@1 +main::@1: scope:[main] from main + [6] phi() + [7] call assertType + to:main::@2 +main::@2: scope:[main] from main::@1 + [8] phi() + [9] call assertType + to:main::@3 +main::@3: scope:[main] from main::@2 + [10] phi() + [11] call assertType + to:main::@4 +main::@4: scope:[main] from main::@3 + [12] phi() + [13] call assertType + to:main::@5 +main::@5: scope:[main] from main::@4 + [14] phi() + [15] call assertType + to:main::@6 +main::@6: scope:[main] from main::@5 + [16] phi() + [17] call assertType + to:main::@7 +main::@7: scope:[main] from main::@6 + [18] phi() + [19] call assertType + to:main::@8 +main::@8: scope:[main] from main::@7 + [20] phi() + [21] call assertType + to:main::@9 +main::@9: scope:[main] from main::@8 + [22] phi() + [23] call assertType + to:main::@10 +main::@10: scope:[main] from main::@9 + [24] phi() + [25] call assertType + to:main::@11 +main::@11: scope:[main] from main::@10 + [26] phi() + [27] call assertType + to:main::@12 +main::@12: scope:[main] from main::@11 + [28] phi() + [29] call assertType + to:main::@13 +main::@13: scope:[main] from main::@12 + [30] phi() + [31] call assertType + to:main::@14 +main::@14: scope:[main] from main::@13 + [32] phi() + [33] call assertType + to:main::@15 +main::@15: scope:[main] from main::@14 + [34] phi() + [35] call assertType + to:main::@16 +main::@16: scope:[main] from main::@15 + [36] phi() + [37] call assertType + to:main::@17 +main::@17: scope:[main] from main::@16 + [38] phi() + [39] call assertType + to:main::@18 +main::@18: scope:[main] from main::@17 + [40] phi() + [41] call assertType + to:main::@19 +main::@19: scope:[main] from main::@18 + [42] phi() + [43] call assertType + to:main::@20 +main::@20: scope:[main] from main::@19 + [44] phi() + [45] call assertType + to:main::@21 +main::@21: scope:[main] from main::@20 + [46] phi() + [47] call assertType + to:main::@22 +main::@22: scope:[main] from main::@21 + [48] phi() + [49] call assertType + to:main::@23 +main::@23: scope:[main] from main::@22 + [50] phi() + [51] call assertType + to:main::@24 +main::@24: scope:[main] from main::@23 + [52] phi() + [53] call assertType + to:main::@25 +main::@25: scope:[main] from main::@24 + [54] phi() + [55] call assertType + to:main::@26 +main::@26: scope:[main] from main::@25 + [56] phi() + [57] call assertType + to:main::@27 +main::@27: scope:[main] from main::@26 + [58] phi() + [59] call assertType + to:main::@28 +main::@28: scope:[main] from main::@27 + [60] phi() + [61] call assertType + to:main::@29 +main::@29: scope:[main] from main::@28 + [62] phi() + [63] call assertType + to:main::@30 +main::@30: scope:[main] from main::@29 + [64] phi() + [65] call assertType + to:main::@31 +main::@31: scope:[main] from main::@30 + [66] phi() + [67] call assertType + to:main::@32 +main::@32: scope:[main] from main::@31 + [68] phi() + [69] call assertType + to:main::@33 +main::@33: scope:[main] from main::@32 + [70] phi() + [71] call assertType + to:main::@34 +main::@34: scope:[main] from main::@33 + [72] phi() + [73] call assertType + to:main::@return +main::@return: scope:[main] from main::@34 + [74] return + to:@return +assertType: scope:[assertType] from main main::@1 main::@10 main::@11 main::@12 main::@13 main::@14 main::@15 main::@16 main::@17 main::@18 main::@19 main::@2 main::@20 main::@21 main::@22 main::@23 main::@24 main::@25 main::@26 main::@27 main::@28 main::@29 main::@3 main::@30 main::@31 main::@32 main::@33 main::@34 main::@4 main::@5 main::@6 main::@7 main::@8 main::@9 + [75] (byte) idx#79 ← phi( main/(byte) 0 main::@1/(byte) idx#40 main::@10/(byte) idx#40 main::@11/(byte) idx#40 main::@12/(byte) idx#40 main::@13/(byte) idx#40 main::@14/(byte) idx#40 main::@15/(byte) idx#40 main::@16/(byte) idx#40 main::@17/(byte) idx#40 main::@18/(byte) idx#40 main::@19/(byte) idx#40 main::@2/(byte) idx#40 main::@20/(byte) idx#40 main::@21/(byte) $50 main::@22/(byte) idx#40 main::@23/(byte) idx#40 main::@24/(byte) idx#40 main::@25/(byte) idx#40 main::@26/(byte) idx#40 main::@27/(byte) idx#40 main::@28/(byte) idx#40 main::@29/(byte) idx#40 main::@3/(byte) idx#40 main::@30/(byte) idx#40 main::@31/(byte) idx#40 main::@32/(byte) idx#40 main::@33/(byte) idx#40 main::@34/(byte) idx#40 main::@4/(byte) idx#40 main::@5/(byte) idx#40 main::@6/(byte) idx#40 main::@7/(byte) idx#40 main::@8/(byte) idx#40 main::@9/(byte) $28 ) + [75] (byte) assertType::t2#35 ← phi( main/(const byte) TYPEID_SIGNED_BYTE main::@1/(const byte) TYPEID_SIGNED_WORD main::@10/(const byte) TYPEID_BYTE main::@11/(const byte) TYPEID_WORD main::@12/(const byte) TYPEID_WORD main::@13/(const byte) TYPEID_DWORD main::@14/(const byte) TYPEID_WORD main::@15/(const byte) TYPEID_WORD main::@16/(const byte) TYPEID_DWORD main::@17/(const byte) TYPEID_DWORD main::@18/(const byte) TYPEID_DWORD main::@19/(const byte) TYPEID_DWORD main::@2/(const byte) TYPEID_SIGNED_DWORD main::@20/(const byte) TYPEID_DWORD main::@21/(const byte) TYPEID_BYTE main::@22/(const byte) TYPEID_BYTE main::@23/(const byte) TYPEID_BYTE main::@24/(const byte) TYPEID_WORD main::@25/(const byte) TYPEID_WORD main::@26/(const byte) TYPEID_DWORD main::@27/(const byte) TYPEID_WORD main::@28/(const byte) TYPEID_WORD main::@29/(const byte) TYPEID_WORD main::@3/(const byte) TYPEID_SIGNED_WORD main::@30/(const byte) TYPEID_DWORD main::@31/(const byte) TYPEID_DWORD main::@32/(const byte) TYPEID_DWORD main::@33/(const byte) TYPEID_DWORD main::@34/(const byte) TYPEID_DWORD main::@4/(const byte) TYPEID_SIGNED_WORD main::@5/(const byte) TYPEID_SIGNED_DWORD main::@6/(const byte) TYPEID_SIGNED_DWORD main::@7/(const byte) TYPEID_SIGNED_DWORD main::@8/(const byte) TYPEID_SIGNED_DWORD main::@9/(const byte) TYPEID_BYTE ) + [75] (byte) assertType::t1#35 ← phi( main/(const byte) TYPEID_SIGNED_BYTE main::@1/(const byte) TYPEID_SIGNED_WORD main::@10/(const byte) TYPEID_BYTE main::@11/(const byte) TYPEID_WORD main::@12/(const byte) TYPEID_WORD main::@13/(const byte) TYPEID_DWORD main::@14/(const byte) TYPEID_WORD main::@15/(const byte) TYPEID_WORD main::@16/(const byte) TYPEID_DWORD main::@17/(const byte) TYPEID_DWORD main::@18/(const byte) TYPEID_DWORD main::@19/(const byte) TYPEID_DWORD main::@2/(const byte) TYPEID_SIGNED_DWORD main::@20/(const byte) TYPEID_DWORD main::@21/(const byte) TYPEID_BYTE main::@22/(const byte) TYPEID_BYTE main::@23/(const byte) TYPEID_BYTE main::@24/(const byte) TYPEID_WORD main::@25/(const byte) TYPEID_WORD main::@26/(const byte) TYPEID_DWORD main::@27/(const byte) TYPEID_WORD main::@28/(const byte) TYPEID_WORD main::@29/(const byte) TYPEID_WORD main::@3/(const byte) TYPEID_SIGNED_WORD main::@30/(const byte) TYPEID_DWORD main::@31/(const byte) TYPEID_DWORD main::@32/(const byte) TYPEID_DWORD main::@33/(const byte) TYPEID_DWORD main::@34/(const byte) TYPEID_SIGNED_DWORD main::@4/(const byte) TYPEID_SIGNED_WORD main::@5/(const byte) TYPEID_SIGNED_DWORD main::@6/(const byte) TYPEID_SIGNED_DWORD main::@7/(const byte) TYPEID_SIGNED_DWORD main::@8/(const byte) TYPEID_SIGNED_DWORD main::@9/(const byte) TYPEID_BYTE ) + [76] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1 + to:assertType::@3 +assertType::@3: scope:[assertType] from assertType + [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 + to:assertType::@2 +assertType::@2: scope:[assertType] from assertType::@1 assertType::@3 + [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 + [79] (byte) idx#40 ← ++ (byte) idx#79 + to:assertType::@return +assertType::@return: scope:[assertType] from assertType::@2 + [80] return + to:@return +assertType::@1: scope:[assertType] from assertType + [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 + to:assertType::@2 diff --git a/src/test/ref/number-conversion.log b/src/test/ref/number-conversion.log new file mode 100644 index 000000000..72d68592f --- /dev/null +++ b/src/test/ref/number-conversion.log @@ -0,0 +1,3609 @@ +Resolved forward reference idx to (byte) idx +Resolved forward reference idx to (byte) idx +Resolved forward reference idx to (byte) idx +Adding pointer type conversion cast (byte*) SCREEN in (byte*) SCREEN ← (word) $400 +Adding pointer type conversion cast (byte*) COLS in (byte*) COLS ← (word) $d800 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 +main: scope:[main] from @2 + (byte) idx#0 ← (byte) 0 + (number~) main::$0 ← (signed byte) $c + (number) $c + (byte~) main::$1 ← typeid (number~) main::$0 + (byte) assertType::t1#0 ← (byte~) main::$1 + (byte) assertType::t2#0 ← (const byte) TYPEID_SIGNED_BYTE + call assertType + to:main::@1 +main::@1: scope:[main] from main + (byte) idx#43 ← phi( main/(byte) idx#41 ) + (byte) idx#1 ← (byte) idx#43 + (number~) main::$3 ← (signed byte) $c + (number) $82 + (byte~) main::$4 ← typeid (number~) main::$3 + (byte) assertType::t1#1 ← (byte~) main::$4 + (byte) assertType::t2#1 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte) idx#44 ← phi( main::@1/(byte) idx#41 ) + (byte) idx#2 ← (byte) idx#44 + (number~) main::$6 ← (signed byte) $c + (number) $80e8 + (byte~) main::$7 ← typeid (number~) main::$6 + (byte) assertType::t1#2 ← (byte~) main::$7 + (byte) assertType::t2#2 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:main::@3 +main::@3: scope:[main] from main::@2 + (byte) idx#45 ← phi( main::@2/(byte) idx#41 ) + (byte) idx#3 ← (byte) idx#45 + (number~) main::$9 ← (signed word) $c + (number) $c + (byte~) main::$10 ← typeid (number~) main::$9 + (byte) assertType::t1#3 ← (byte~) main::$10 + (byte) assertType::t2#3 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:main::@4 +main::@4: scope:[main] from main::@3 + (byte) idx#46 ← phi( main::@3/(byte) idx#41 ) + (byte) idx#4 ← (byte) idx#46 + (number~) main::$12 ← (signed word) $c + (number) $82 + (byte~) main::$13 ← typeid (number~) main::$12 + (byte) assertType::t1#4 ← (byte~) main::$13 + (byte) assertType::t2#4 ← (const byte) TYPEID_SIGNED_WORD + call assertType + to:main::@5 +main::@5: scope:[main] from main::@4 + (byte) idx#47 ← phi( main::@4/(byte) idx#41 ) + (byte) idx#5 ← (byte) idx#47 + (number~) main::$15 ← (signed word) $c + (number) $186a0 + (byte~) main::$16 ← typeid (number~) main::$15 + (byte) assertType::t1#5 ← (byte~) main::$16 + (byte) assertType::t2#5 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:main::@6 +main::@6: scope:[main] from main::@5 + (byte) idx#48 ← phi( main::@5/(byte) idx#41 ) + (byte) idx#6 ← (byte) idx#48 + (number~) main::$18 ← (signed dword) $c + (number) $c + (byte~) main::$19 ← typeid (number~) main::$18 + (byte) assertType::t1#6 ← (byte~) main::$19 + (byte) assertType::t2#6 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:main::@7 +main::@7: scope:[main] from main::@6 + (byte) idx#49 ← phi( main::@6/(byte) idx#41 ) + (byte) idx#7 ← (byte) idx#49 + (number~) main::$21 ← (signed dword) $c + (number) $82 + (byte~) main::$22 ← typeid (number~) main::$21 + (byte) assertType::t1#7 ← (byte~) main::$22 + (byte) assertType::t2#7 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:main::@8 +main::@8: scope:[main] from main::@7 + (byte) idx#50 ← phi( main::@7/(byte) idx#41 ) + (byte) idx#8 ← (byte) idx#50 + (number~) main::$24 ← (signed dword) $c + (number) $186a0 + (byte~) main::$25 ← typeid (number~) main::$24 + (byte) assertType::t1#8 ← (byte~) main::$25 + (byte) assertType::t2#8 ← (const byte) TYPEID_SIGNED_DWORD + call assertType + to:main::@9 +main::@9: scope:[main] from main::@8 + (byte) idx#51 ← phi( main::@8/(byte) idx#41 ) + (byte) idx#9 ← (byte) idx#51 + (byte) idx#10 ← (byte) $28 + (number~) main::$27 ← (byte) $c + (number) $c + (byte~) main::$28 ← typeid (number~) main::$27 + (byte) assertType::t1#9 ← (byte~) main::$28 + (byte) assertType::t2#9 ← (const byte) TYPEID_BYTE + call assertType + to:main::@10 +main::@10: scope:[main] from main::@9 + (byte) idx#52 ← phi( main::@9/(byte) idx#41 ) + (byte) idx#11 ← (byte) idx#52 + (number~) main::$30 ← (byte) $c + (number) $fa + (byte~) main::$31 ← typeid (number~) main::$30 + (byte) assertType::t1#10 ← (byte~) main::$31 + (byte) assertType::t2#10 ← (const byte) TYPEID_BYTE + call assertType + to:main::@11 +main::@11: scope:[main] from main::@10 + (byte) idx#53 ← phi( main::@10/(byte) idx#41 ) + (byte) idx#12 ← (byte) idx#53 + (number~) main::$33 ← (byte) $c + (number) $12c + (byte~) main::$34 ← typeid (number~) main::$33 + (byte) assertType::t1#11 ← (byte~) main::$34 + (byte) assertType::t2#11 ← (const byte) TYPEID_WORD + call assertType + to:main::@12 +main::@12: scope:[main] from main::@11 + (byte) idx#54 ← phi( main::@11/(byte) idx#41 ) + (byte) idx#13 ← (byte) idx#54 + (number~) main::$36 ← (byte) $c + (number) $fffe + (byte~) main::$37 ← typeid (number~) main::$36 + (byte) assertType::t1#12 ← (byte~) main::$37 + (byte) assertType::t2#12 ← (const byte) TYPEID_WORD + call assertType + to:main::@13 +main::@13: scope:[main] from main::@12 + (byte) idx#55 ← phi( main::@12/(byte) idx#41 ) + (byte) idx#14 ← (byte) idx#55 + (number~) main::$39 ← (byte) $c + (number) $101d0 + (byte~) main::$40 ← typeid (number~) main::$39 + (byte) assertType::t1#13 ← (byte~) main::$40 + (byte) assertType::t2#13 ← (const byte) TYPEID_DWORD + call assertType + to:main::@14 +main::@14: scope:[main] from main::@13 + (byte) idx#56 ← phi( main::@13/(byte) idx#41 ) + (byte) idx#15 ← (byte) idx#56 + (number~) main::$42 ← (word) $c + (number) $c + (byte~) main::$43 ← typeid (number~) main::$42 + (byte) assertType::t1#14 ← (byte~) main::$43 + (byte) assertType::t2#14 ← (const byte) TYPEID_WORD + call assertType + to:main::@15 +main::@15: scope:[main] from main::@14 + (byte) idx#57 ← phi( main::@14/(byte) idx#41 ) + (byte) idx#16 ← (byte) idx#57 + (number~) main::$45 ← (word) $c + (number) $82 + (byte~) main::$46 ← typeid (number~) main::$45 + (byte) assertType::t1#15 ← (byte~) main::$46 + (byte) assertType::t2#15 ← (const byte) TYPEID_WORD + call assertType + to:main::@16 +main::@16: scope:[main] from main::@15 + (byte) idx#58 ← phi( main::@15/(byte) idx#41 ) + (byte) idx#17 ← (byte) idx#58 + (number~) main::$48 ← (word) $c + (number) $101d0 + (byte~) main::$49 ← typeid (number~) main::$48 + (byte) assertType::t1#16 ← (byte~) main::$49 + (byte) assertType::t2#16 ← (const byte) TYPEID_DWORD + call assertType + to:main::@17 +main::@17: scope:[main] from main::@16 + (byte) idx#59 ← phi( main::@16/(byte) idx#41 ) + (byte) idx#18 ← (byte) idx#59 + (number~) main::$51 ← (dword) $c + (number) $c + (byte~) main::$52 ← typeid (number~) main::$51 + (byte) assertType::t1#17 ← (byte~) main::$52 + (byte) assertType::t2#17 ← (const byte) TYPEID_DWORD + call assertType + to:main::@18 +main::@18: scope:[main] from main::@17 + (byte) idx#60 ← phi( main::@17/(byte) idx#41 ) + (byte) idx#19 ← (byte) idx#60 + (number~) main::$54 ← (dword) $c + (number) $82 + (byte~) main::$55 ← typeid (number~) main::$54 + (byte) assertType::t1#18 ← (byte~) main::$55 + (byte) assertType::t2#18 ← (const byte) TYPEID_DWORD + call assertType + to:main::@19 +main::@19: scope:[main] from main::@18 + (byte) idx#61 ← phi( main::@18/(byte) idx#41 ) + (byte) idx#20 ← (byte) idx#61 + (number~) main::$57 ← (dword) $c + (number) $101d0 + (byte~) main::$58 ← typeid (number~) main::$57 + (byte) assertType::t1#19 ← (byte~) main::$58 + (byte) assertType::t2#19 ← (const byte) TYPEID_DWORD + call assertType + to:main::@20 +main::@20: scope:[main] from main::@19 + (byte) idx#62 ← phi( main::@19/(byte) idx#41 ) + (byte) idx#21 ← (byte) idx#62 + (number~) main::$60 ← (byte) $c + (number) $b2d05e00 + (byte~) main::$61 ← typeid (number~) main::$60 + (byte) assertType::t1#20 ← (byte~) main::$61 + (byte) assertType::t2#20 ← (const byte) TYPEID_DWORD + call assertType + to:main::@21 +main::@21: scope:[main] from main::@20 + (byte) idx#63 ← phi( main::@20/(byte) idx#41 ) + (byte) idx#22 ← (byte) idx#63 + (byte) idx#23 ← (byte) $50 + (number~) main::$63 ← - (number) $c + (number~) main::$64 ← (byte) $c + (number~) main::$63 + (byte~) main::$65 ← typeid (number~) main::$64 + (byte) assertType::t1#21 ← (byte~) main::$65 + (byte) assertType::t2#21 ← (const byte) TYPEID_BYTE + call assertType + to:main::@22 +main::@22: scope:[main] from main::@21 + (byte) idx#64 ← phi( main::@21/(byte) idx#41 ) + (byte) idx#24 ← (byte) idx#64 + (number~) main::$67 ← - (number) $78 + (number~) main::$68 ← (byte) $c + (number~) main::$67 + (byte~) main::$69 ← typeid (number~) main::$68 + (byte) assertType::t1#22 ← (byte~) main::$69 + (byte) assertType::t2#22 ← (const byte) TYPEID_BYTE + call assertType + to:main::@23 +main::@23: scope:[main] from main::@22 + (byte) idx#65 ← phi( main::@22/(byte) idx#41 ) + (byte) idx#25 ← (byte) idx#65 + (number~) main::$71 ← - (number) $fa + (number~) main::$72 ← (byte) $c + (number~) main::$71 + (byte~) main::$73 ← typeid (number~) main::$72 + (byte) assertType::t1#23 ← (byte~) main::$73 + (byte) assertType::t2#23 ← (const byte) TYPEID_BYTE + call assertType + to:main::@24 +main::@24: scope:[main] from main::@23 + (byte) idx#66 ← phi( main::@23/(byte) idx#41 ) + (byte) idx#26 ← (byte) idx#66 + (number~) main::$75 ← - (number) $104 + (number~) main::$76 ← (byte) $c + (number~) main::$75 + (byte~) main::$77 ← typeid (number~) main::$76 + (byte) assertType::t1#24 ← (byte~) main::$77 + (byte) assertType::t2#24 ← (const byte) TYPEID_WORD + call assertType + to:main::@25 +main::@25: scope:[main] from main::@24 + (byte) idx#67 ← phi( main::@24/(byte) idx#41 ) + (byte) idx#27 ← (byte) idx#67 + (number~) main::$79 ← - (number) $fde8 + (number~) main::$80 ← (byte) $c + (number~) main::$79 + (byte~) main::$81 ← typeid (number~) main::$80 + (byte) assertType::t1#25 ← (byte~) main::$81 + (byte) assertType::t2#25 ← (const byte) TYPEID_WORD + call assertType + to:main::@26 +main::@26: scope:[main] from main::@25 + (byte) idx#68 ← phi( main::@25/(byte) idx#41 ) + (byte) idx#28 ← (byte) idx#68 + (number~) main::$83 ← - (number) $101d0 + (number~) main::$84 ← (byte) $c + (number~) main::$83 + (byte~) main::$85 ← typeid (number~) main::$84 + (byte) assertType::t1#26 ← (byte~) main::$85 + (byte) assertType::t2#26 ← (const byte) TYPEID_DWORD + call assertType + to:main::@27 +main::@27: scope:[main] from main::@26 + (byte) idx#69 ← phi( main::@26/(byte) idx#41 ) + (byte) idx#29 ← (byte) idx#69 + (number~) main::$87 ← - (number) $c + (number~) main::$88 ← (word) $c + (number~) main::$87 + (byte~) main::$89 ← typeid (number~) main::$88 + (byte) assertType::t1#27 ← (byte~) main::$89 + (byte) assertType::t2#27 ← (const byte) TYPEID_WORD + call assertType + to:main::@28 +main::@28: scope:[main] from main::@27 + (byte) idx#70 ← phi( main::@27/(byte) idx#41 ) + (byte) idx#30 ← (byte) idx#70 + (number~) main::$91 ← - (number) $82 + (number~) main::$92 ← (word) $c + (number~) main::$91 + (byte~) main::$93 ← typeid (number~) main::$92 + (byte) assertType::t1#28 ← (byte~) main::$93 + (byte) assertType::t2#28 ← (const byte) TYPEID_WORD + call assertType + to:main::@29 +main::@29: scope:[main] from main::@28 + (byte) idx#71 ← phi( main::@28/(byte) idx#41 ) + (byte) idx#31 ← (byte) idx#71 + (number~) main::$95 ← - (number) $fde8 + (number~) main::$96 ← (word) $c + (number~) main::$95 + (byte~) main::$97 ← typeid (number~) main::$96 + (byte) assertType::t1#29 ← (byte~) main::$97 + (byte) assertType::t2#29 ← (const byte) TYPEID_WORD + call assertType + to:main::@30 +main::@30: scope:[main] from main::@29 + (byte) idx#72 ← phi( main::@29/(byte) idx#41 ) + (byte) idx#32 ← (byte) idx#72 + (number~) main::$99 ← - (number) $101d0 + (number~) main::$100 ← (word) $c + (number~) main::$99 + (byte~) main::$101 ← typeid (number~) main::$100 + (byte) assertType::t1#30 ← (byte~) main::$101 + (byte) assertType::t2#30 ← (const byte) TYPEID_DWORD + call assertType + to:main::@31 +main::@31: scope:[main] from main::@30 + (byte) idx#73 ← phi( main::@30/(byte) idx#41 ) + (byte) idx#33 ← (byte) idx#73 + (number~) main::$103 ← - (number) $c + (number~) main::$104 ← (dword) $c + (number~) main::$103 + (byte~) main::$105 ← typeid (number~) main::$104 + (byte) assertType::t1#31 ← (byte~) main::$105 + (byte) assertType::t2#31 ← (const byte) TYPEID_DWORD + call assertType + to:main::@32 +main::@32: scope:[main] from main::@31 + (byte) idx#74 ← phi( main::@31/(byte) idx#41 ) + (byte) idx#34 ← (byte) idx#74 + (number~) main::$107 ← - (number) $82 + (number~) main::$108 ← (dword) $c + (number~) main::$107 + (byte~) main::$109 ← typeid (number~) main::$108 + (byte) assertType::t1#32 ← (byte~) main::$109 + (byte) assertType::t2#32 ← (const byte) TYPEID_DWORD + call assertType + to:main::@33 +main::@33: scope:[main] from main::@32 + (byte) idx#75 ← phi( main::@32/(byte) idx#41 ) + (byte) idx#35 ← (byte) idx#75 + (number~) main::$111 ← - (number) $101d0 + (number~) main::$112 ← (dword) $c + (number~) main::$111 + (byte~) main::$113 ← typeid (number~) main::$112 + (byte) assertType::t1#33 ← (byte~) main::$113 + (byte) assertType::t2#33 ← (const byte) TYPEID_DWORD + call assertType + to:main::@34 +main::@34: scope:[main] from main::@33 + (byte) idx#76 ← phi( main::@33/(byte) idx#41 ) + (byte) idx#36 ← (byte) idx#76 + (number~) main::$115 ← - (number) $7d2b7500 + (number~) main::$116 ← (signed byte) $c + (number~) main::$115 + (byte~) main::$117 ← typeid (number~) main::$116 + (byte) assertType::t1#34 ← (byte~) main::$117 + (byte) assertType::t2#34 ← (const byte) TYPEID_DWORD + call assertType + to:main::@35 +main::@35: scope:[main] from main::@34 + (byte) idx#77 ← phi( main::@34/(byte) idx#41 ) + (byte) idx#37 ← (byte) idx#77 + to:main::@return +main::@return: scope:[main] from main::@35 + (byte) idx#78 ← phi( main::@35/(byte) idx#37 ) + (byte) idx#38 ← (byte) idx#78 + return + to:@return +@1: scope:[] from @begin + (byte) RED#0 ← (byte) 2 + (byte) GREEN#0 ← (byte) 5 + (word) $0 ← (word) $400 + (byte*) SCREEN#0 ← ((byte*)) (word) $0 + (word) $1 ← (word) $d800 + (byte*) COLS#0 ← ((byte*)) (word) $1 + (byte) idx#39 ← (byte) 0 + to:@2 +assertType: scope:[assertType] from main main::@1 main::@10 main::@11 main::@12 main::@13 main::@14 main::@15 main::@16 main::@17 main::@18 main::@19 main::@2 main::@20 main::@21 main::@22 main::@23 main::@24 main::@25 main::@26 main::@27 main::@28 main::@29 main::@3 main::@30 main::@31 main::@32 main::@33 main::@34 main::@4 main::@5 main::@6 main::@7 main::@8 main::@9 + (byte) idx#84 ← phi( main/(byte) idx#0 main::@1/(byte) idx#1 main::@10/(byte) idx#11 main::@11/(byte) idx#12 main::@12/(byte) idx#13 main::@13/(byte) idx#14 main::@14/(byte) idx#15 main::@15/(byte) idx#16 main::@16/(byte) idx#17 main::@17/(byte) idx#18 main::@18/(byte) idx#19 main::@19/(byte) idx#20 main::@2/(byte) idx#2 main::@20/(byte) idx#21 main::@21/(byte) idx#23 main::@22/(byte) idx#24 main::@23/(byte) idx#25 main::@24/(byte) idx#26 main::@25/(byte) idx#27 main::@26/(byte) idx#28 main::@27/(byte) idx#29 main::@28/(byte) idx#30 main::@29/(byte) idx#31 main::@3/(byte) idx#3 main::@30/(byte) idx#32 main::@31/(byte) idx#33 main::@32/(byte) idx#34 main::@33/(byte) idx#35 main::@34/(byte) idx#36 main::@4/(byte) idx#4 main::@5/(byte) idx#5 main::@6/(byte) idx#6 main::@7/(byte) idx#7 main::@8/(byte) idx#8 main::@9/(byte) idx#10 ) + (byte) assertType::t2#35 ← phi( main/(byte) assertType::t2#0 main::@1/(byte) assertType::t2#1 main::@10/(byte) assertType::t2#10 main::@11/(byte) assertType::t2#11 main::@12/(byte) assertType::t2#12 main::@13/(byte) assertType::t2#13 main::@14/(byte) assertType::t2#14 main::@15/(byte) assertType::t2#15 main::@16/(byte) assertType::t2#16 main::@17/(byte) assertType::t2#17 main::@18/(byte) assertType::t2#18 main::@19/(byte) assertType::t2#19 main::@2/(byte) assertType::t2#2 main::@20/(byte) assertType::t2#20 main::@21/(byte) assertType::t2#21 main::@22/(byte) assertType::t2#22 main::@23/(byte) assertType::t2#23 main::@24/(byte) assertType::t2#24 main::@25/(byte) assertType::t2#25 main::@26/(byte) assertType::t2#26 main::@27/(byte) assertType::t2#27 main::@28/(byte) assertType::t2#28 main::@29/(byte) assertType::t2#29 main::@3/(byte) assertType::t2#3 main::@30/(byte) assertType::t2#30 main::@31/(byte) assertType::t2#31 main::@32/(byte) assertType::t2#32 main::@33/(byte) assertType::t2#33 main::@34/(byte) assertType::t2#34 main::@4/(byte) assertType::t2#4 main::@5/(byte) assertType::t2#5 main::@6/(byte) assertType::t2#6 main::@7/(byte) assertType::t2#7 main::@8/(byte) assertType::t2#8 main::@9/(byte) assertType::t2#9 ) + (byte) assertType::t1#35 ← phi( main/(byte) assertType::t1#0 main::@1/(byte) assertType::t1#1 main::@10/(byte) assertType::t1#10 main::@11/(byte) assertType::t1#11 main::@12/(byte) assertType::t1#12 main::@13/(byte) assertType::t1#13 main::@14/(byte) assertType::t1#14 main::@15/(byte) assertType::t1#15 main::@16/(byte) assertType::t1#16 main::@17/(byte) assertType::t1#17 main::@18/(byte) assertType::t1#18 main::@19/(byte) assertType::t1#19 main::@2/(byte) assertType::t1#2 main::@20/(byte) assertType::t1#20 main::@21/(byte) assertType::t1#21 main::@22/(byte) assertType::t1#22 main::@23/(byte) assertType::t1#23 main::@24/(byte) assertType::t1#24 main::@25/(byte) assertType::t1#25 main::@26/(byte) assertType::t1#26 main::@27/(byte) assertType::t1#27 main::@28/(byte) assertType::t1#28 main::@29/(byte) assertType::t1#29 main::@3/(byte) assertType::t1#3 main::@30/(byte) assertType::t1#30 main::@31/(byte) assertType::t1#31 main::@32/(byte) assertType::t1#32 main::@33/(byte) assertType::t1#33 main::@34/(byte) assertType::t1#34 main::@4/(byte) assertType::t1#4 main::@5/(byte) assertType::t1#5 main::@6/(byte) assertType::t1#6 main::@7/(byte) assertType::t1#7 main::@8/(byte) assertType::t1#8 main::@9/(byte) assertType::t1#9 ) + (bool~) assertType::$0 ← (byte) assertType::t1#35 == (byte) assertType::t2#35 + if((bool~) assertType::$0) goto assertType::@1 + to:assertType::@3 +assertType::@1: scope:[assertType] from assertType + (byte) assertType::t1#37 ← phi( assertType/(byte) assertType::t1#35 ) + (byte) idx#79 ← phi( assertType/(byte) idx#84 ) + *((byte*) COLS#0 + (byte) idx#79) ← (byte) GREEN#0 + to:assertType::@2 +assertType::@3: scope:[assertType] from assertType + (byte) assertType::t1#38 ← phi( assertType/(byte) assertType::t1#35 ) + (byte) idx#80 ← phi( assertType/(byte) idx#84 ) + *((byte*) COLS#0 + (byte) idx#80) ← (byte) RED#0 + to:assertType::@2 +assertType::@2: scope:[assertType] from assertType::@1 assertType::@3 + (byte) idx#81 ← phi( assertType::@1/(byte) idx#79 assertType::@3/(byte) idx#80 ) + (byte) assertType::t1#36 ← phi( assertType::@1/(byte) assertType::t1#37 assertType::@3/(byte) assertType::t1#38 ) + *((byte*) SCREEN#0 + (byte) idx#81) ← (byte) assertType::t1#36 + (byte) idx#40 ← ++ (byte) idx#81 + to:assertType::@return +assertType::@return: scope:[assertType] from assertType::@2 + (byte) idx#82 ← phi( assertType::@2/(byte) idx#40 ) + (byte) idx#41 ← (byte) idx#82 + return + to:@return +@2: scope:[] from @1 + (byte) idx#85 ← phi( @1/(byte) idx#39 ) + call main + to:@3 +@3: scope:[] from @2 + (byte) idx#83 ← phi( @2/(byte) idx#38 ) + (byte) idx#42 ← (byte) idx#83 + to:@end +@end: scope:[] from @3 + +SYMBOL TABLE SSA +(word) $0 +(word) $1 +(label) @1 +(label) @2 +(label) @3 +(label) @begin +(label) @end +(byte*) COLS +(byte*) COLS#0 +(byte) GREEN +(byte) GREEN#0 +(byte) RED +(byte) RED#0 +(byte*) SCREEN +(byte*) SCREEN#0 +(const byte) TYPEID_BYTE = (number) 1 +(const byte) TYPEID_DWORD = (number) 5 +(const byte) TYPEID_SIGNED_BYTE = (number) 2 +(const byte) TYPEID_SIGNED_DWORD = (number) 6 +(const byte) TYPEID_SIGNED_WORD = (number) 4 +(const byte) TYPEID_WORD = (number) 3 +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(bool~) assertType::$0 +(label) assertType::@1 +(label) assertType::@2 +(label) assertType::@3 +(label) assertType::@return +(byte) assertType::t1 +(byte) assertType::t1#0 +(byte) assertType::t1#1 +(byte) assertType::t1#10 +(byte) assertType::t1#11 +(byte) assertType::t1#12 +(byte) assertType::t1#13 +(byte) assertType::t1#14 +(byte) assertType::t1#15 +(byte) assertType::t1#16 +(byte) assertType::t1#17 +(byte) assertType::t1#18 +(byte) assertType::t1#19 +(byte) assertType::t1#2 +(byte) assertType::t1#20 +(byte) assertType::t1#21 +(byte) assertType::t1#22 +(byte) assertType::t1#23 +(byte) assertType::t1#24 +(byte) assertType::t1#25 +(byte) assertType::t1#26 +(byte) assertType::t1#27 +(byte) assertType::t1#28 +(byte) assertType::t1#29 +(byte) assertType::t1#3 +(byte) assertType::t1#30 +(byte) assertType::t1#31 +(byte) assertType::t1#32 +(byte) assertType::t1#33 +(byte) assertType::t1#34 +(byte) assertType::t1#35 +(byte) assertType::t1#36 +(byte) assertType::t1#37 +(byte) assertType::t1#38 +(byte) assertType::t1#4 +(byte) assertType::t1#5 +(byte) assertType::t1#6 +(byte) assertType::t1#7 +(byte) assertType::t1#8 +(byte) assertType::t1#9 +(byte) assertType::t2 +(byte) assertType::t2#0 +(byte) assertType::t2#1 +(byte) assertType::t2#10 +(byte) assertType::t2#11 +(byte) assertType::t2#12 +(byte) assertType::t2#13 +(byte) assertType::t2#14 +(byte) assertType::t2#15 +(byte) assertType::t2#16 +(byte) assertType::t2#17 +(byte) assertType::t2#18 +(byte) assertType::t2#19 +(byte) assertType::t2#2 +(byte) assertType::t2#20 +(byte) assertType::t2#21 +(byte) assertType::t2#22 +(byte) assertType::t2#23 +(byte) assertType::t2#24 +(byte) assertType::t2#25 +(byte) assertType::t2#26 +(byte) assertType::t2#27 +(byte) assertType::t2#28 +(byte) assertType::t2#29 +(byte) assertType::t2#3 +(byte) assertType::t2#30 +(byte) assertType::t2#31 +(byte) assertType::t2#32 +(byte) assertType::t2#33 +(byte) assertType::t2#34 +(byte) assertType::t2#35 +(byte) assertType::t2#4 +(byte) assertType::t2#5 +(byte) assertType::t2#6 +(byte) assertType::t2#7 +(byte) assertType::t2#8 +(byte) assertType::t2#9 +(byte) idx +(byte) idx#0 +(byte) idx#1 +(byte) idx#10 +(byte) idx#11 +(byte) idx#12 +(byte) idx#13 +(byte) idx#14 +(byte) idx#15 +(byte) idx#16 +(byte) idx#17 +(byte) idx#18 +(byte) idx#19 +(byte) idx#2 +(byte) idx#20 +(byte) idx#21 +(byte) idx#22 +(byte) idx#23 +(byte) idx#24 +(byte) idx#25 +(byte) idx#26 +(byte) idx#27 +(byte) idx#28 +(byte) idx#29 +(byte) idx#3 +(byte) idx#30 +(byte) idx#31 +(byte) idx#32 +(byte) idx#33 +(byte) idx#34 +(byte) idx#35 +(byte) idx#36 +(byte) idx#37 +(byte) idx#38 +(byte) idx#39 +(byte) idx#4 +(byte) idx#40 +(byte) idx#41 +(byte) idx#42 +(byte) idx#43 +(byte) idx#44 +(byte) idx#45 +(byte) idx#46 +(byte) idx#47 +(byte) idx#48 +(byte) idx#49 +(byte) idx#5 +(byte) idx#50 +(byte) idx#51 +(byte) idx#52 +(byte) idx#53 +(byte) idx#54 +(byte) idx#55 +(byte) idx#56 +(byte) idx#57 +(byte) idx#58 +(byte) idx#59 +(byte) idx#6 +(byte) idx#60 +(byte) idx#61 +(byte) idx#62 +(byte) idx#63 +(byte) idx#64 +(byte) idx#65 +(byte) idx#66 +(byte) idx#67 +(byte) idx#68 +(byte) idx#69 +(byte) idx#7 +(byte) idx#70 +(byte) idx#71 +(byte) idx#72 +(byte) idx#73 +(byte) idx#74 +(byte) idx#75 +(byte) idx#76 +(byte) idx#77 +(byte) idx#78 +(byte) idx#79 +(byte) idx#8 +(byte) idx#80 +(byte) idx#81 +(byte) idx#82 +(byte) idx#83 +(byte) idx#84 +(byte) idx#85 +(byte) idx#9 +(void()) main() +(number~) main::$0 +(byte~) main::$1 +(byte~) main::$10 +(number~) main::$100 +(byte~) main::$101 +(number~) main::$103 +(number~) main::$104 +(byte~) main::$105 +(number~) main::$107 +(number~) main::$108 +(byte~) main::$109 +(number~) main::$111 +(number~) main::$112 +(byte~) main::$113 +(number~) main::$115 +(number~) main::$116 +(byte~) main::$117 +(number~) main::$12 +(byte~) main::$13 +(number~) main::$15 +(byte~) main::$16 +(number~) main::$18 +(byte~) main::$19 +(number~) main::$21 +(byte~) main::$22 +(number~) main::$24 +(byte~) main::$25 +(number~) main::$27 +(byte~) main::$28 +(number~) main::$3 +(number~) main::$30 +(byte~) main::$31 +(number~) main::$33 +(byte~) main::$34 +(number~) main::$36 +(byte~) main::$37 +(number~) main::$39 +(byte~) main::$4 +(byte~) main::$40 +(number~) main::$42 +(byte~) main::$43 +(number~) main::$45 +(byte~) main::$46 +(number~) main::$48 +(byte~) main::$49 +(number~) main::$51 +(byte~) main::$52 +(number~) main::$54 +(byte~) main::$55 +(number~) main::$57 +(byte~) main::$58 +(number~) main::$6 +(number~) main::$60 +(byte~) main::$61 +(number~) main::$63 +(number~) main::$64 +(byte~) main::$65 +(number~) main::$67 +(number~) main::$68 +(byte~) main::$69 +(byte~) main::$7 +(number~) main::$71 +(number~) main::$72 +(byte~) main::$73 +(number~) main::$75 +(number~) main::$76 +(byte~) main::$77 +(number~) main::$79 +(number~) main::$80 +(byte~) main::$81 +(number~) main::$83 +(number~) main::$84 +(byte~) main::$85 +(number~) main::$87 +(number~) main::$88 +(byte~) main::$89 +(number~) main::$9 +(number~) main::$91 +(number~) main::$92 +(byte~) main::$93 +(number~) main::$95 +(number~) main::$96 +(byte~) main::$97 +(number~) main::$99 +(label) main::@1 +(label) main::@10 +(label) main::@11 +(label) main::@12 +(label) main::@13 +(label) main::@14 +(label) main::@15 +(label) main::@16 +(label) main::@17 +(label) main::@18 +(label) main::@19 +(label) main::@2 +(label) main::@20 +(label) main::@21 +(label) main::@22 +(label) main::@23 +(label) main::@24 +(label) main::@25 +(label) main::@26 +(label) main::@27 +(label) main::@28 +(label) main::@29 +(label) main::@3 +(label) main::@30 +(label) main::@31 +(label) main::@32 +(label) main::@33 +(label) main::@34 +(label) main::@35 +(label) main::@4 +(label) main::@5 +(label) main::@6 +(label) main::@7 +(label) main::@8 +(label) main::@9 +(label) main::@return + +Adding number conversion cast (signed byte) $c in (number~) main::$0 ← (signed byte) $c + (number) $c +Adding number conversion cast (signed word) $c in (number~) main::$3 ← (signed byte) $c + (number) $82 +Adding number conversion cast (signed word) $82 in (number~) main::$3 ← (signed word)(signed byte) $c + (number) $82 +Adding number conversion cast (signed dword) $c in (number~) main::$6 ← (signed byte) $c + (number) $80e8 +Adding number conversion cast (signed dword) $80e8 in (number~) main::$6 ← (signed dword)(signed byte) $c + (number) $80e8 +Adding number conversion cast (signed word) $c in (number~) main::$9 ← (signed word) $c + (number) $c +Adding number conversion cast (signed word) $82 in (number~) main::$12 ← (signed word) $c + (number) $82 +Adding number conversion cast (signed dword) $c in (number~) main::$15 ← (signed word) $c + (number) $186a0 +Adding number conversion cast (signed dword) $186a0 in (number~) main::$15 ← (signed dword)(signed word) $c + (number) $186a0 +Adding number conversion cast (signed dword) $c in (number~) main::$18 ← (signed dword) $c + (number) $c +Adding number conversion cast (signed dword) $82 in (number~) main::$21 ← (signed dword) $c + (number) $82 +Adding number conversion cast (signed dword) $186a0 in (number~) main::$24 ← (signed dword) $c + (number) $186a0 +Adding number conversion cast (byte) $c in (number~) main::$27 ← (byte) $c + (number) $c +Adding number conversion cast (byte) $fa in (number~) main::$30 ← (byte) $c + (number) $fa +Adding number conversion cast (word) $c in (number~) main::$33 ← (byte) $c + (number) $12c +Adding number conversion cast (word) $12c in (number~) main::$33 ← (word)(byte) $c + (number) $12c +Adding number conversion cast (word) $c in (number~) main::$36 ← (byte) $c + (number) $fffe +Adding number conversion cast (word) $fffe in (number~) main::$36 ← (word)(byte) $c + (number) $fffe +Adding number conversion cast (dword) $c in (number~) main::$39 ← (byte) $c + (number) $101d0 +Adding number conversion cast (dword) $101d0 in (number~) main::$39 ← (dword)(byte) $c + (number) $101d0 +Adding number conversion cast (word) $c in (number~) main::$42 ← (word) $c + (number) $c +Adding number conversion cast (word) $82 in (number~) main::$45 ← (word) $c + (number) $82 +Adding number conversion cast (dword) $c in (number~) main::$48 ← (word) $c + (number) $101d0 +Adding number conversion cast (dword) $101d0 in (number~) main::$48 ← (dword)(word) $c + (number) $101d0 +Adding number conversion cast (dword) $c in (number~) main::$51 ← (dword) $c + (number) $c +Adding number conversion cast (dword) $82 in (number~) main::$54 ← (dword) $c + (number) $82 +Adding number conversion cast (dword) $101d0 in (number~) main::$57 ← (dword) $c + (number) $101d0 +Adding number conversion cast (dword) $c in (number~) main::$60 ← (byte) $c + (number) $b2d05e00 +Adding number conversion cast (dword) $b2d05e00 in (number~) main::$60 ← (dword)(byte) $c + (number) $b2d05e00 +Inferred type updated to signed byte in (number~) main::$0 ← (signed byte) $c + (signed byte)(number) $c +Inferred type updated to signed word in (number~) main::$3 ← (signed word)(signed byte) $c + (signed word)(number) $82 +Inferred type updated to signed dword in (number~) main::$6 ← (signed dword)(signed byte) $c + (signed dword)(number) $80e8 +Inferred type updated to signed word in (number~) main::$9 ← (signed word) $c + (signed word)(number) $c +Inferred type updated to signed word in (number~) main::$12 ← (signed word) $c + (signed word)(number) $82 +Inferred type updated to signed dword in (number~) main::$15 ← (signed dword)(signed word) $c + (signed dword)(number) $186a0 +Inferred type updated to signed dword in (number~) main::$18 ← (signed dword) $c + (signed dword)(number) $c +Inferred type updated to signed dword in (number~) main::$21 ← (signed dword) $c + (signed dword)(number) $82 +Inferred type updated to signed dword in (number~) main::$24 ← (signed dword) $c + (signed dword)(number) $186a0 +Inferred type updated to byte in (number~) main::$27 ← (byte) $c + (byte)(number) $c +Inferred type updated to byte in (number~) main::$30 ← (byte) $c + (byte)(number) $fa +Inferred type updated to word in (number~) main::$33 ← (word)(byte) $c + (word)(number) $12c +Inferred type updated to word in (number~) main::$36 ← (word)(byte) $c + (word)(number) $fffe +Inferred type updated to dword in (number~) main::$39 ← (dword)(byte) $c + (dword)(number) $101d0 +Inferred type updated to word in (number~) main::$42 ← (word) $c + (word)(number) $c +Inferred type updated to word in (number~) main::$45 ← (word) $c + (word)(number) $82 +Inferred type updated to dword in (number~) main::$48 ← (dword)(word) $c + (dword)(number) $101d0 +Inferred type updated to dword in (number~) main::$51 ← (dword) $c + (dword)(number) $c +Inferred type updated to dword in (number~) main::$54 ← (dword) $c + (dword)(number) $82 +Inferred type updated to dword in (number~) main::$57 ← (dword) $c + (dword)(number) $101d0 +Inferred type updated to dword in (number~) main::$60 ← (dword)(byte) $c + (dword)(number) $b2d05e00 +Resolving typeid() (byte~) main::$1 ← typeid (signed byte~) main::$0 +Resolving typeid() (byte~) main::$4 ← typeid (signed word~) main::$3 +Resolving typeid() (byte~) main::$7 ← typeid (signed dword~) main::$6 +Resolving typeid() (byte~) main::$10 ← typeid (signed word~) main::$9 +Resolving typeid() (byte~) main::$13 ← typeid (signed word~) main::$12 +Resolving typeid() (byte~) main::$16 ← typeid (signed dword~) main::$15 +Resolving typeid() (byte~) main::$19 ← typeid (signed dword~) main::$18 +Resolving typeid() (byte~) main::$22 ← typeid (signed dword~) main::$21 +Resolving typeid() (byte~) main::$25 ← typeid (signed dword~) main::$24 +Resolving typeid() (byte~) main::$28 ← typeid (byte~) main::$27 +Resolving typeid() (byte~) main::$31 ← typeid (byte~) main::$30 +Resolving typeid() (byte~) main::$34 ← typeid (word~) main::$33 +Resolving typeid() (byte~) main::$37 ← typeid (word~) main::$36 +Resolving typeid() (byte~) main::$40 ← typeid (dword~) main::$39 +Resolving typeid() (byte~) main::$43 ← typeid (word~) main::$42 +Resolving typeid() (byte~) main::$46 ← typeid (word~) main::$45 +Resolving typeid() (byte~) main::$49 ← typeid (dword~) main::$48 +Resolving typeid() (byte~) main::$52 ← typeid (dword~) main::$51 +Resolving typeid() (byte~) main::$55 ← typeid (dword~) main::$54 +Resolving typeid() (byte~) main::$58 ← typeid (dword~) main::$57 +Resolving typeid() (byte~) main::$61 ← typeid (dword~) main::$60 +Successful SSA optimization PassNTypeIdSimplification +Alias (byte) assertType::t1#0 = (byte~) main::$1 +Alias (byte) idx#1 = (byte) idx#43 +Alias (byte) assertType::t1#1 = (byte~) main::$4 +Alias (byte) idx#2 = (byte) idx#44 +Alias (byte) assertType::t1#2 = (byte~) main::$7 +Alias (byte) idx#3 = (byte) idx#45 +Alias (byte) assertType::t1#3 = (byte~) main::$10 +Alias (byte) idx#4 = (byte) idx#46 +Alias (byte) assertType::t1#4 = (byte~) main::$13 +Alias (byte) idx#47 = (byte) idx#5 +Alias (byte) assertType::t1#5 = (byte~) main::$16 +Alias (byte) idx#48 = (byte) idx#6 +Alias (byte) assertType::t1#6 = (byte~) main::$19 +Alias (byte) idx#49 = (byte) idx#7 +Alias (byte) assertType::t1#7 = (byte~) main::$22 +Alias (byte) idx#50 = (byte) idx#8 +Alias (byte) assertType::t1#8 = (byte~) main::$25 +Alias (byte) idx#51 = (byte) idx#9 +Alias (byte) assertType::t1#9 = (byte~) main::$28 +Alias (byte) idx#11 = (byte) idx#52 +Alias (byte) assertType::t1#10 = (byte~) main::$31 +Alias (byte) idx#12 = (byte) idx#53 +Alias (byte) assertType::t1#11 = (byte~) main::$34 +Alias (byte) idx#13 = (byte) idx#54 +Alias (byte) assertType::t1#12 = (byte~) main::$37 +Alias (byte) idx#14 = (byte) idx#55 +Alias (byte) assertType::t1#13 = (byte~) main::$40 +Alias (byte) idx#15 = (byte) idx#56 +Alias (byte) assertType::t1#14 = (byte~) main::$43 +Alias (byte) idx#16 = (byte) idx#57 +Alias (byte) assertType::t1#15 = (byte~) main::$46 +Alias (byte) idx#17 = (byte) idx#58 +Alias (byte) assertType::t1#16 = (byte~) main::$49 +Alias (byte) idx#18 = (byte) idx#59 +Alias (byte) assertType::t1#17 = (byte~) main::$52 +Alias (byte) idx#19 = (byte) idx#60 +Alias (byte) assertType::t1#18 = (byte~) main::$55 +Alias (byte) idx#20 = (byte) idx#61 +Alias (byte) assertType::t1#19 = (byte~) main::$58 +Alias (byte) idx#21 = (byte) idx#62 +Alias (byte) assertType::t1#20 = (byte~) main::$61 +Alias (byte) idx#22 = (byte) idx#63 +Alias (byte) assertType::t1#21 = (byte~) main::$65 +Alias (byte) idx#24 = (byte) idx#64 +Alias (byte) assertType::t1#22 = (byte~) main::$69 +Alias (byte) idx#25 = (byte) idx#65 +Alias (byte) assertType::t1#23 = (byte~) main::$73 +Alias (byte) idx#26 = (byte) idx#66 +Alias (byte) assertType::t1#24 = (byte~) main::$77 +Alias (byte) idx#27 = (byte) idx#67 +Alias (byte) assertType::t1#25 = (byte~) main::$81 +Alias (byte) idx#28 = (byte) idx#68 +Alias (byte) assertType::t1#26 = (byte~) main::$85 +Alias (byte) idx#29 = (byte) idx#69 +Alias (byte) assertType::t1#27 = (byte~) main::$89 +Alias (byte) idx#30 = (byte) idx#70 +Alias (byte) assertType::t1#28 = (byte~) main::$93 +Alias (byte) idx#31 = (byte) idx#71 +Alias (byte) assertType::t1#29 = (byte~) main::$97 +Alias (byte) idx#32 = (byte) idx#72 +Alias (byte) assertType::t1#30 = (byte~) main::$101 +Alias (byte) idx#33 = (byte) idx#73 +Alias (byte) assertType::t1#31 = (byte~) main::$105 +Alias (byte) idx#34 = (byte) idx#74 +Alias (byte) assertType::t1#32 = (byte~) main::$109 +Alias (byte) idx#35 = (byte) idx#75 +Alias (byte) assertType::t1#33 = (byte~) main::$113 +Alias (byte) idx#36 = (byte) idx#76 +Alias (byte) assertType::t1#34 = (byte~) main::$117 +Alias (byte) idx#37 = (byte) idx#77 (byte) idx#78 (byte) idx#38 +Alias (byte) idx#79 = (byte) idx#84 (byte) idx#80 +Alias (byte) assertType::t1#35 = (byte) assertType::t1#37 (byte) assertType::t1#38 +Alias (byte) idx#40 = (byte) idx#82 (byte) idx#41 +Alias (byte) idx#39 = (byte) idx#85 +Alias (byte) idx#42 = (byte) idx#83 +Successful SSA optimization Pass2AliasElimination +Alias (byte) assertType::t1#35 = (byte) assertType::t1#36 +Alias (byte) idx#79 = (byte) idx#81 +Successful SSA optimization Pass2AliasElimination +Redundant Phi (byte) idx#1 (byte) idx#40 +Redundant Phi (byte) idx#2 (byte) idx#40 +Redundant Phi (byte) idx#3 (byte) idx#40 +Redundant Phi (byte) idx#4 (byte) idx#40 +Redundant Phi (byte) idx#47 (byte) idx#40 +Redundant Phi (byte) idx#48 (byte) idx#40 +Redundant Phi (byte) idx#49 (byte) idx#40 +Redundant Phi (byte) idx#50 (byte) idx#40 +Redundant Phi (byte) idx#51 (byte) idx#40 +Redundant Phi (byte) idx#11 (byte) idx#40 +Redundant Phi (byte) idx#12 (byte) idx#40 +Redundant Phi (byte) idx#13 (byte) idx#40 +Redundant Phi (byte) idx#14 (byte) idx#40 +Redundant Phi (byte) idx#15 (byte) idx#40 +Redundant Phi (byte) idx#16 (byte) idx#40 +Redundant Phi (byte) idx#17 (byte) idx#40 +Redundant Phi (byte) idx#18 (byte) idx#40 +Redundant Phi (byte) idx#19 (byte) idx#40 +Redundant Phi (byte) idx#20 (byte) idx#40 +Redundant Phi (byte) idx#21 (byte) idx#40 +Redundant Phi (byte) idx#22 (byte) idx#40 +Redundant Phi (byte) idx#24 (byte) idx#40 +Redundant Phi (byte) idx#25 (byte) idx#40 +Redundant Phi (byte) idx#26 (byte) idx#40 +Redundant Phi (byte) idx#27 (byte) idx#40 +Redundant Phi (byte) idx#28 (byte) idx#40 +Redundant Phi (byte) idx#29 (byte) idx#40 +Redundant Phi (byte) idx#30 (byte) idx#40 +Redundant Phi (byte) idx#31 (byte) idx#40 +Redundant Phi (byte) idx#32 (byte) idx#40 +Redundant Phi (byte) idx#33 (byte) idx#40 +Redundant Phi (byte) idx#34 (byte) idx#40 +Redundant Phi (byte) idx#35 (byte) idx#40 +Redundant Phi (byte) idx#36 (byte) idx#40 +Redundant Phi (byte) idx#37 (byte) idx#40 +Redundant Phi (byte) idx#42 (byte) idx#37 +Successful SSA optimization Pass2RedundantPhiElimination +Simple Condition (bool~) assertType::$0 [274] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant right-side identified [1] (signed byte~) main::$0 ← (signed byte) $c + (signed byte)(number) $c +Constant right-side identified [8] (signed word~) main::$3 ← (signed word)(signed byte) $c + (signed word)(number) $82 +Constant right-side identified [15] (signed dword~) main::$6 ← (signed dword)(signed byte) $c + (signed dword)(number) $80e8 +Constant right-side identified [22] (signed word~) main::$9 ← (signed word) $c + (signed word)(number) $c +Constant right-side identified [29] (signed word~) main::$12 ← (signed word) $c + (signed word)(number) $82 +Constant right-side identified [36] (signed dword~) main::$15 ← (signed dword)(signed word) $c + (signed dword)(number) $186a0 +Constant right-side identified [43] (signed dword~) main::$18 ← (signed dword) $c + (signed dword)(number) $c +Constant right-side identified [50] (signed dword~) main::$21 ← (signed dword) $c + (signed dword)(number) $82 +Constant right-side identified [57] (signed dword~) main::$24 ← (signed dword) $c + (signed dword)(number) $186a0 +Constant right-side identified [65] (byte~) main::$27 ← (byte) $c + (byte)(number) $c +Constant right-side identified [72] (byte~) main::$30 ← (byte) $c + (byte)(number) $fa +Constant right-side identified [79] (word~) main::$33 ← (word)(byte) $c + (word)(number) $12c +Constant right-side identified [86] (word~) main::$36 ← (word)(byte) $c + (word)(number) $fffe +Constant right-side identified [93] (dword~) main::$39 ← (dword)(byte) $c + (dword)(number) $101d0 +Constant right-side identified [100] (word~) main::$42 ← (word) $c + (word)(number) $c +Constant right-side identified [107] (word~) main::$45 ← (word) $c + (word)(number) $82 +Constant right-side identified [114] (dword~) main::$48 ← (dword)(word) $c + (dword)(number) $101d0 +Constant right-side identified [121] (dword~) main::$51 ← (dword) $c + (dword)(number) $c +Constant right-side identified [128] (dword~) main::$54 ← (dword) $c + (dword)(number) $82 +Constant right-side identified [135] (dword~) main::$57 ← (dword) $c + (dword)(number) $101d0 +Constant right-side identified [142] (dword~) main::$60 ← (dword)(byte) $c + (dword)(number) $b2d05e00 +Constant right-side identified [150] (number~) main::$63 ← - (number) $c +Constant right-side identified [158] (number~) main::$67 ← - (number) $78 +Constant right-side identified [166] (number~) main::$71 ← - (number) $fa +Constant right-side identified [174] (number~) main::$75 ← - (number) $104 +Constant right-side identified [182] (number~) main::$79 ← - (number) $fde8 +Constant right-side identified [190] (number~) main::$83 ← - (number) $101d0 +Constant right-side identified [198] (number~) main::$87 ← - (number) $c +Constant right-side identified [206] (number~) main::$91 ← - (number) $82 +Constant right-side identified [214] (number~) main::$95 ← - (number) $fde8 +Constant right-side identified [222] (number~) main::$99 ← - (number) $101d0 +Constant right-side identified [230] (number~) main::$103 ← - (number) $c +Constant right-side identified [238] (number~) main::$107 ← - (number) $82 +Constant right-side identified [246] (number~) main::$111 ← - (number) $101d0 +Constant right-side identified [254] (number~) main::$115 ← - (number) $7d2b7500 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) idx#0 = 0 +Constant (const signed byte) main::$0 = $c+(signed byte)$c +Constant (const byte) assertType::t1#0 = TYPEID_SIGNED_BYTE +Constant (const byte) assertType::t2#0 = TYPEID_SIGNED_BYTE +Constant (const signed word) main::$3 = (signed word)$c+(signed word)$82 +Constant (const byte) assertType::t1#1 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#1 = TYPEID_SIGNED_WORD +Constant (const signed dword) main::$6 = (signed dword)$c+(signed dword)$80e8 +Constant (const byte) assertType::t1#2 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#2 = TYPEID_SIGNED_DWORD +Constant (const signed word) main::$9 = $c+(signed word)$c +Constant (const byte) assertType::t1#3 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#3 = TYPEID_SIGNED_WORD +Constant (const signed word) main::$12 = $c+(signed word)$82 +Constant (const byte) assertType::t1#4 = TYPEID_SIGNED_WORD +Constant (const byte) assertType::t2#4 = TYPEID_SIGNED_WORD +Constant (const signed dword) main::$15 = (signed dword)$c+(signed dword)$186a0 +Constant (const byte) assertType::t1#5 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#5 = TYPEID_SIGNED_DWORD +Constant (const signed dword) main::$18 = $c+(signed dword)$c +Constant (const byte) assertType::t1#6 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#6 = TYPEID_SIGNED_DWORD +Constant (const signed dword) main::$21 = $c+(signed dword)$82 +Constant (const byte) assertType::t1#7 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#7 = TYPEID_SIGNED_DWORD +Constant (const signed dword) main::$24 = $c+(signed dword)$186a0 +Constant (const byte) assertType::t1#8 = TYPEID_SIGNED_DWORD +Constant (const byte) assertType::t2#8 = TYPEID_SIGNED_DWORD +Constant (const byte) idx#10 = $28 +Constant (const byte) main::$27 = $c+(byte)$c +Constant (const byte) assertType::t1#9 = TYPEID_BYTE +Constant (const byte) assertType::t2#9 = TYPEID_BYTE +Constant (const byte) main::$30 = $c+(byte)$fa +Constant (const byte) assertType::t1#10 = TYPEID_BYTE +Constant (const byte) assertType::t2#10 = TYPEID_BYTE +Constant (const word) main::$33 = (word)$c+(word)$12c +Constant (const byte) assertType::t1#11 = TYPEID_WORD +Constant (const byte) assertType::t2#11 = TYPEID_WORD +Constant (const word) main::$36 = (word)$c+(word)$fffe +Constant (const byte) assertType::t1#12 = TYPEID_WORD +Constant (const byte) assertType::t2#12 = TYPEID_WORD +Constant (const dword) main::$39 = (dword)$c+(dword)$101d0 +Constant (const byte) assertType::t1#13 = TYPEID_DWORD +Constant (const byte) assertType::t2#13 = TYPEID_DWORD +Constant (const word) main::$42 = $c+(word)$c +Constant (const byte) assertType::t1#14 = TYPEID_WORD +Constant (const byte) assertType::t2#14 = TYPEID_WORD +Constant (const word) main::$45 = $c+(word)$82 +Constant (const byte) assertType::t1#15 = TYPEID_WORD +Constant (const byte) assertType::t2#15 = TYPEID_WORD +Constant (const dword) main::$48 = (dword)$c+(dword)$101d0 +Constant (const byte) assertType::t1#16 = TYPEID_DWORD +Constant (const byte) assertType::t2#16 = TYPEID_DWORD +Constant (const dword) main::$51 = $c+(dword)$c +Constant (const byte) assertType::t1#17 = TYPEID_DWORD +Constant (const byte) assertType::t2#17 = TYPEID_DWORD +Constant (const dword) main::$54 = $c+(dword)$82 +Constant (const byte) assertType::t1#18 = TYPEID_DWORD +Constant (const byte) assertType::t2#18 = TYPEID_DWORD +Constant (const dword) main::$57 = $c+(dword)$101d0 +Constant (const byte) assertType::t1#19 = TYPEID_DWORD +Constant (const byte) assertType::t2#19 = TYPEID_DWORD +Constant (const dword) main::$60 = (dword)$c+(dword)$b2d05e00 +Constant (const byte) assertType::t1#20 = TYPEID_DWORD +Constant (const byte) assertType::t2#20 = TYPEID_DWORD +Constant (const byte) idx#23 = $50 +Constant (const number) main::$63 = -$c +Constant (const byte) assertType::t2#21 = TYPEID_BYTE +Constant (const number) main::$67 = -$78 +Constant (const byte) assertType::t2#22 = TYPEID_BYTE +Constant (const number) main::$71 = -$fa +Constant (const byte) assertType::t2#23 = TYPEID_BYTE +Constant (const number) main::$75 = -$104 +Constant (const byte) assertType::t2#24 = TYPEID_WORD +Constant (const number) main::$79 = -$fde8 +Constant (const byte) assertType::t2#25 = TYPEID_WORD +Constant (const number) main::$83 = -$101d0 +Constant (const byte) assertType::t2#26 = TYPEID_DWORD +Constant (const number) main::$87 = -$c +Constant (const byte) assertType::t2#27 = TYPEID_WORD +Constant (const number) main::$91 = -$82 +Constant (const byte) assertType::t2#28 = TYPEID_WORD +Constant (const number) main::$95 = -$fde8 +Constant (const byte) assertType::t2#29 = TYPEID_WORD +Constant (const number) main::$99 = -$101d0 +Constant (const byte) assertType::t2#30 = TYPEID_DWORD +Constant (const number) main::$103 = -$c +Constant (const byte) assertType::t2#31 = TYPEID_DWORD +Constant (const number) main::$107 = -$82 +Constant (const byte) assertType::t2#32 = TYPEID_DWORD +Constant (const number) main::$111 = -$101d0 +Constant (const byte) assertType::t2#33 = TYPEID_DWORD +Constant (const number) main::$115 = -$7d2b7500 +Constant (const byte) assertType::t2#34 = TYPEID_DWORD +Constant (const byte) RED#0 = 2 +Constant (const byte) GREEN#0 = 5 +Constant (const word) $0 = $400 +Constant (const word) $1 = $d800 +Constant (const byte) idx#39 = 0 +Successful SSA optimization Pass2ConstantIdentification +Eliminating unused constant (const signed byte) main::$0 +Eliminating unused constant (const signed word) main::$3 +Eliminating unused constant (const signed dword) main::$6 +Eliminating unused constant (const signed word) main::$9 +Eliminating unused constant (const signed word) main::$12 +Eliminating unused constant (const signed dword) main::$15 +Eliminating unused constant (const signed dword) main::$18 +Eliminating unused constant (const signed dword) main::$21 +Eliminating unused constant (const signed dword) main::$24 +Eliminating unused constant (const byte) main::$27 +Eliminating unused constant (const byte) main::$30 +Eliminating unused constant (const word) main::$33 +Eliminating unused constant (const word) main::$36 +Eliminating unused constant (const dword) main::$39 +Eliminating unused constant (const word) main::$42 +Eliminating unused constant (const word) main::$45 +Eliminating unused constant (const dword) main::$48 +Eliminating unused constant (const dword) main::$51 +Eliminating unused constant (const dword) main::$54 +Eliminating unused constant (const dword) main::$57 +Eliminating unused constant (const dword) main::$60 +Eliminating unused constant (const byte) idx#39 +Successful SSA optimization PassNEliminateUnusedVars +Eliminating Noop Cast (byte*) SCREEN#0 ← ((byte*)) (const word) $0 +Eliminating Noop Cast (byte*) COLS#0 ← ((byte*)) (const word) $1 +Successful SSA optimization Pass2NopCastElimination +Adding number conversion cast (byte) main::$63 in (number~) main::$64 ← (byte) $c + (const number) main::$63 +Adding number conversion cast (byte) main::$67 in (number~) main::$68 ← (byte) $c + (const number) main::$67 +Adding number conversion cast (byte) main::$71 in (number~) main::$72 ← (byte) $c + (const number) main::$71 +Adding number conversion cast (word) $c in (number~) main::$76 ← (byte) $c + (const number) main::$75 +Adding number conversion cast (word) main::$75 in (number~) main::$76 ← (word)(byte) $c + (const number) main::$75 +Adding number conversion cast (word) $c in (number~) main::$80 ← (byte) $c + (const number) main::$79 +Adding number conversion cast (word) main::$79 in (number~) main::$80 ← (word)(byte) $c + (const number) main::$79 +Adding number conversion cast (dword) $c in (number~) main::$84 ← (byte) $c + (const number) main::$83 +Adding number conversion cast (dword) main::$83 in (number~) main::$84 ← (dword)(byte) $c + (const number) main::$83 +Adding number conversion cast (word) main::$87 in (number~) main::$88 ← (word) $c + (const number) main::$87 +Adding number conversion cast (word) main::$91 in (number~) main::$92 ← (word) $c + (const number) main::$91 +Adding number conversion cast (word) main::$95 in (number~) main::$96 ← (word) $c + (const number) main::$95 +Adding number conversion cast (dword) $c in (number~) main::$100 ← (word) $c + (const number) main::$99 +Adding number conversion cast (dword) main::$99 in (number~) main::$100 ← (dword)(word) $c + (const number) main::$99 +Adding number conversion cast (dword) main::$103 in (number~) main::$104 ← (dword) $c + (const number) main::$103 +Adding number conversion cast (dword) main::$107 in (number~) main::$108 ← (dword) $c + (const number) main::$107 +Adding number conversion cast (dword) main::$111 in (number~) main::$112 ← (dword) $c + (const number) main::$111 +Adding number conversion cast (signed dword) $c in (number~) main::$116 ← (signed byte) $c + (const number) main::$115 +Adding number conversion cast (signed dword) main::$115 in (number~) main::$116 ← (signed dword)(signed byte) $c + (const number) main::$115 +Inferred type updated to byte in (number~) main::$64 ← (byte) $c + (byte)(const number) main::$63 +Inferred type updated to byte in (number~) main::$68 ← (byte) $c + (byte)(const number) main::$67 +Inferred type updated to byte in (number~) main::$72 ← (byte) $c + (byte)(const number) main::$71 +Inferred type updated to word in (number~) main::$76 ← (word)(byte) $c + (word)(const number) main::$75 +Inferred type updated to word in (number~) main::$80 ← (word)(byte) $c + (word)(const number) main::$79 +Inferred type updated to dword in (number~) main::$84 ← (dword)(byte) $c + (dword)(const number) main::$83 +Inferred type updated to word in (number~) main::$88 ← (word) $c + (word)(const number) main::$87 +Inferred type updated to word in (number~) main::$92 ← (word) $c + (word)(const number) main::$91 +Inferred type updated to word in (number~) main::$96 ← (word) $c + (word)(const number) main::$95 +Inferred type updated to dword in (number~) main::$100 ← (dword)(word) $c + (dword)(const number) main::$99 +Inferred type updated to dword in (number~) main::$104 ← (dword) $c + (dword)(const number) main::$103 +Inferred type updated to dword in (number~) main::$108 ← (dword) $c + (dword)(const number) main::$107 +Inferred type updated to dword in (number~) main::$112 ← (dword) $c + (dword)(const number) main::$111 +Inferred type updated to signed dword in (number~) main::$116 ← (signed dword)(signed byte) $c + (signed dword)(const number) main::$115 +Resolving typeid() (byte) assertType::t1#21 ← typeid (byte~) main::$64 +Resolving typeid() (byte) assertType::t1#22 ← typeid (byte~) main::$68 +Resolving typeid() (byte) assertType::t1#23 ← typeid (byte~) main::$72 +Resolving typeid() (byte) assertType::t1#24 ← typeid (word~) main::$76 +Resolving typeid() (byte) assertType::t1#25 ← typeid (word~) main::$80 +Resolving typeid() (byte) assertType::t1#26 ← typeid (dword~) main::$84 +Resolving typeid() (byte) assertType::t1#27 ← typeid (word~) main::$88 +Resolving typeid() (byte) assertType::t1#28 ← typeid (word~) main::$92 +Resolving typeid() (byte) assertType::t1#29 ← typeid (word~) main::$96 +Resolving typeid() (byte) assertType::t1#30 ← typeid (dword~) main::$100 +Resolving typeid() (byte) assertType::t1#31 ← typeid (dword~) main::$104 +Resolving typeid() (byte) assertType::t1#32 ← typeid (dword~) main::$108 +Resolving typeid() (byte) assertType::t1#33 ← typeid (dword~) main::$112 +Resolving typeid() (byte) assertType::t1#34 ← typeid (signed dword~) main::$116 +Successful SSA optimization PassNTypeIdSimplification +Culled Empty Block (label) main::@35 +Culled Empty Block (label) @1 +Culled Empty Block (label) @3 +Successful SSA optimization Pass2CullEmptyBlocks +Constant right-side identified [21] (byte~) main::$64 ← (byte) $c + (byte)(const number) main::$63 +Constant right-side identified [24] (byte~) main::$68 ← (byte) $c + (byte)(const number) main::$67 +Constant right-side identified [27] (byte~) main::$72 ← (byte) $c + (byte)(const number) main::$71 +Constant right-side identified [30] (word~) main::$76 ← (word)(byte) $c + (word)(const number) main::$75 +Constant right-side identified [33] (word~) main::$80 ← (word)(byte) $c + (word)(const number) main::$79 +Constant right-side identified [36] (dword~) main::$84 ← (dword)(byte) $c + (dword)(const number) main::$83 +Constant right-side identified [39] (word~) main::$88 ← (word) $c + (word)(const number) main::$87 +Constant right-side identified [42] (word~) main::$92 ← (word) $c + (word)(const number) main::$91 +Constant right-side identified [45] (word~) main::$96 ← (word) $c + (word)(const number) main::$95 +Constant right-side identified [48] (dword~) main::$100 ← (dword)(word) $c + (dword)(const number) main::$99 +Constant right-side identified [51] (dword~) main::$104 ← (dword) $c + (dword)(const number) main::$103 +Constant right-side identified [54] (dword~) main::$108 ← (dword) $c + (dword)(const number) main::$107 +Constant right-side identified [57] (dword~) main::$112 ← (dword) $c + (dword)(const number) main::$111 +Constant right-side identified [60] (signed dword~) main::$116 ← (signed dword)(signed byte) $c + (signed dword)(const number) main::$115 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::$64 = $c+(byte)main::$63 +Constant (const byte) assertType::t1#21 = TYPEID_BYTE +Constant (const byte) main::$68 = $c+(byte)main::$67 +Constant (const byte) assertType::t1#22 = TYPEID_BYTE +Constant (const byte) main::$72 = $c+(byte)main::$71 +Constant (const byte) assertType::t1#23 = TYPEID_BYTE +Constant (const word) main::$76 = (word)$c+(word)main::$75 +Constant (const byte) assertType::t1#24 = TYPEID_WORD +Constant (const word) main::$80 = (word)$c+(word)main::$79 +Constant (const byte) assertType::t1#25 = TYPEID_WORD +Constant (const dword) main::$84 = (dword)$c+(dword)main::$83 +Constant (const byte) assertType::t1#26 = TYPEID_DWORD +Constant (const word) main::$88 = $c+(word)main::$87 +Constant (const byte) assertType::t1#27 = TYPEID_WORD +Constant (const word) main::$92 = $c+(word)main::$91 +Constant (const byte) assertType::t1#28 = TYPEID_WORD +Constant (const word) main::$96 = $c+(word)main::$95 +Constant (const byte) assertType::t1#29 = TYPEID_WORD +Constant (const dword) main::$100 = (dword)$c+(dword)main::$99 +Constant (const byte) assertType::t1#30 = TYPEID_DWORD +Constant (const dword) main::$104 = $c+(dword)main::$103 +Constant (const byte) assertType::t1#31 = TYPEID_DWORD +Constant (const dword) main::$108 = $c+(dword)main::$107 +Constant (const byte) assertType::t1#32 = TYPEID_DWORD +Constant (const dword) main::$112 = $c+(dword)main::$111 +Constant (const byte) assertType::t1#33 = TYPEID_DWORD +Constant (const signed dword) main::$116 = (signed dword)$c+(signed dword)main::$115 +Constant (const byte) assertType::t1#34 = TYPEID_SIGNED_DWORD +Successful SSA optimization Pass2ConstantIdentification +Eliminating unused constant (const byte) main::$64 +Eliminating unused constant (const byte) main::$68 +Eliminating unused constant (const byte) main::$72 +Eliminating unused constant (const word) main::$76 +Eliminating unused constant (const word) main::$80 +Eliminating unused constant (const dword) main::$84 +Eliminating unused constant (const word) main::$88 +Eliminating unused constant (const word) main::$92 +Eliminating unused constant (const word) main::$96 +Eliminating unused constant (const dword) main::$100 +Eliminating unused constant (const dword) main::$104 +Eliminating unused constant (const dword) main::$108 +Eliminating unused constant (const dword) main::$112 +Eliminating unused constant (const signed dword) main::$116 +Successful SSA optimization PassNEliminateUnusedVars +Eliminating unused constant (const number) main::$63 +Eliminating unused constant (const number) main::$67 +Eliminating unused constant (const number) main::$71 +Eliminating unused constant (const number) main::$75 +Eliminating unused constant (const number) main::$79 +Eliminating unused constant (const number) main::$83 +Eliminating unused constant (const number) main::$87 +Eliminating unused constant (const number) main::$91 +Eliminating unused constant (const number) main::$95 +Eliminating unused constant (const number) main::$99 +Eliminating unused constant (const number) main::$103 +Eliminating unused constant (const number) main::$107 +Eliminating unused constant (const number) main::$111 +Eliminating unused constant (const number) main::$115 +Successful SSA optimization PassNEliminateUnusedVars +Inlining constant with var siblings (const byte) assertType::t1#0 +Inlining constant with var siblings (const byte) assertType::t2#0 +Inlining constant with var siblings (const byte) assertType::t1#1 +Inlining constant with var siblings (const byte) assertType::t2#1 +Inlining constant with var siblings (const byte) assertType::t1#2 +Inlining constant with var siblings (const byte) assertType::t2#2 +Inlining constant with var siblings (const byte) assertType::t1#3 +Inlining constant with var siblings (const byte) assertType::t2#3 +Inlining constant with var siblings (const byte) assertType::t1#4 +Inlining constant with var siblings (const byte) assertType::t2#4 +Inlining constant with var siblings (const byte) assertType::t1#5 +Inlining constant with var siblings (const byte) assertType::t2#5 +Inlining constant with var siblings (const byte) assertType::t1#6 +Inlining constant with var siblings (const byte) assertType::t2#6 +Inlining constant with var siblings (const byte) assertType::t1#7 +Inlining constant with var siblings (const byte) assertType::t2#7 +Inlining constant with var siblings (const byte) assertType::t1#8 +Inlining constant with var siblings (const byte) assertType::t2#8 +Inlining constant with var siblings (const byte) assertType::t1#9 +Inlining constant with var siblings (const byte) assertType::t2#9 +Inlining constant with var siblings (const byte) assertType::t1#10 +Inlining constant with var siblings (const byte) assertType::t2#10 +Inlining constant with var siblings (const byte) assertType::t1#11 +Inlining constant with var siblings (const byte) assertType::t2#11 +Inlining constant with var siblings (const byte) assertType::t1#12 +Inlining constant with var siblings (const byte) assertType::t2#12 +Inlining constant with var siblings (const byte) assertType::t1#13 +Inlining constant with var siblings (const byte) assertType::t2#13 +Inlining constant with var siblings (const byte) assertType::t1#14 +Inlining constant with var siblings (const byte) assertType::t2#14 +Inlining constant with var siblings (const byte) assertType::t1#15 +Inlining constant with var siblings (const byte) assertType::t2#15 +Inlining constant with var siblings (const byte) assertType::t1#16 +Inlining constant with var siblings (const byte) assertType::t2#16 +Inlining constant with var siblings (const byte) assertType::t1#17 +Inlining constant with var siblings (const byte) assertType::t2#17 +Inlining constant with var siblings (const byte) assertType::t1#18 +Inlining constant with var siblings (const byte) assertType::t2#18 +Inlining constant with var siblings (const byte) assertType::t1#19 +Inlining constant with var siblings (const byte) assertType::t2#19 +Inlining constant with var siblings (const byte) assertType::t1#20 +Inlining constant with var siblings (const byte) assertType::t2#20 +Inlining constant with var siblings (const byte) assertType::t2#21 +Inlining constant with var siblings (const byte) assertType::t2#22 +Inlining constant with var siblings (const byte) assertType::t2#23 +Inlining constant with var siblings (const byte) assertType::t2#24 +Inlining constant with var siblings (const byte) assertType::t2#25 +Inlining constant with var siblings (const byte) assertType::t2#26 +Inlining constant with var siblings (const byte) assertType::t2#27 +Inlining constant with var siblings (const byte) assertType::t2#28 +Inlining constant with var siblings (const byte) assertType::t2#29 +Inlining constant with var siblings (const byte) assertType::t2#30 +Inlining constant with var siblings (const byte) assertType::t2#31 +Inlining constant with var siblings (const byte) assertType::t2#32 +Inlining constant with var siblings (const byte) assertType::t2#33 +Inlining constant with var siblings (const byte) assertType::t2#34 +Inlining constant with var siblings (const byte) assertType::t1#21 +Inlining constant with var siblings (const byte) assertType::t1#22 +Inlining constant with var siblings (const byte) assertType::t1#23 +Inlining constant with var siblings (const byte) assertType::t1#24 +Inlining constant with var siblings (const byte) assertType::t1#25 +Inlining constant with var siblings (const byte) assertType::t1#26 +Inlining constant with var siblings (const byte) assertType::t1#27 +Inlining constant with var siblings (const byte) assertType::t1#28 +Inlining constant with var siblings (const byte) assertType::t1#29 +Inlining constant with var siblings (const byte) assertType::t1#30 +Inlining constant with var siblings (const byte) assertType::t1#31 +Inlining constant with var siblings (const byte) assertType::t1#32 +Inlining constant with var siblings (const byte) assertType::t1#33 +Inlining constant with var siblings (const byte) assertType::t1#34 +Inlining constant with var siblings (const byte) idx#0 +Inlining constant with var siblings (const byte) idx#10 +Inlining constant with var siblings (const byte) idx#23 +Constant inlined assertType::t2#5 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#6 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#7 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#8 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#9 = (const byte) TYPEID_BYTE +Constant inlined $0 = (word) $400 +Constant inlined $1 = (word) $d800 +Constant inlined assertType::t2#31 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#30 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#33 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#21 = (const byte) TYPEID_BYTE +Constant inlined assertType::t1#20 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#32 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#23 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#34 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#22 = (const byte) TYPEID_BYTE +Constant inlined assertType::t1#25 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#24 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#27 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#0 = (const byte) TYPEID_SIGNED_BYTE +Constant inlined assertType::t1#26 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#1 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t1#29 = (const byte) TYPEID_WORD +Constant inlined idx#0 = (byte) 0 +Constant inlined assertType::t2#2 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#28 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#3 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#4 = (const byte) TYPEID_SIGNED_WORD +Constant inlined idx#23 = (byte) $50 +Constant inlined assertType::t2#20 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#10 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#22 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#21 = (const byte) TYPEID_BYTE +Constant inlined assertType::t1#12 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#24 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#11 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#23 = (const byte) TYPEID_BYTE +Constant inlined assertType::t1#14 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#26 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#13 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#25 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#16 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#28 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#15 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#27 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#18 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#17 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#29 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#19 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#6 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined idx#10 = (byte) $28 +Constant inlined assertType::t1#7 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#8 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#9 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#11 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#10 = (const byte) TYPEID_BYTE +Constant inlined assertType::t2#13 = (const byte) TYPEID_DWORD +Constant inlined assertType::t2#12 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#15 = (const byte) TYPEID_WORD +Constant inlined assertType::t2#14 = (const byte) TYPEID_WORD +Constant inlined assertType::t1#0 = (const byte) TYPEID_SIGNED_BYTE +Constant inlined assertType::t2#17 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#1 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#16 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#2 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t2#19 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#3 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t2#18 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#4 = (const byte) TYPEID_SIGNED_WORD +Constant inlined assertType::t1#5 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#30 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#32 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#31 = (const byte) TYPEID_DWORD +Constant inlined assertType::t1#34 = (const byte) TYPEID_SIGNED_DWORD +Constant inlined assertType::t1#33 = (const byte) TYPEID_DWORD +Successful SSA optimization Pass2ConstantInlining +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@9 +Adding NOP phi() at start of main::@21 +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to assertType:5 assertType:7 assertType:9 assertType:11 assertType:13 assertType:15 assertType:17 assertType:19 assertType:21 assertType:23 assertType:25 assertType:27 assertType:29 assertType:31 assertType:33 assertType:35 assertType:37 assertType:39 assertType:41 assertType:43 assertType:45 assertType:47 assertType:49 assertType:51 assertType:53 assertType:55 assertType:57 assertType:59 assertType:61 assertType:63 assertType:65 assertType:67 assertType:69 assertType:71 assertType:73 + +Created 3 initial phi equivalence classes +Coalesced [6] idx#86 ← idx#40 +Coalesced (already) [8] idx#97 ← idx#40 +Coalesced (already) [10] idx#107 ← idx#40 +Coalesced (already) [12] idx#113 ← idx#40 +Coalesced (already) [14] idx#114 ← idx#40 +Coalesced (already) [16] idx#115 ← idx#40 +Coalesced (already) [18] idx#116 ← idx#40 +Coalesced (already) [20] idx#117 ← idx#40 +Coalesced (already) [24] idx#87 ← idx#40 +Coalesced (already) [26] idx#88 ← idx#40 +Coalesced (already) [28] idx#89 ← idx#40 +Coalesced (already) [30] idx#90 ← idx#40 +Coalesced (already) [32] idx#91 ← idx#40 +Coalesced (already) [34] idx#92 ← idx#40 +Coalesced (already) [36] idx#93 ← idx#40 +Coalesced (already) [38] idx#94 ← idx#40 +Coalesced (already) [40] idx#95 ← idx#40 +Coalesced (already) [42] idx#96 ← idx#40 +Coalesced (already) [44] idx#98 ← idx#40 +Coalesced (already) [48] idx#99 ← idx#40 +Coalesced (already) [50] idx#100 ← idx#40 +Coalesced (already) [52] idx#101 ← idx#40 +Coalesced (already) [54] idx#102 ← idx#40 +Coalesced (already) [56] idx#103 ← idx#40 +Coalesced (already) [58] idx#104 ← idx#40 +Coalesced (already) [60] idx#105 ← idx#40 +Coalesced (already) [62] idx#106 ← idx#40 +Coalesced (already) [64] idx#108 ← idx#40 +Coalesced (already) [66] idx#109 ← idx#40 +Coalesced (already) [68] idx#110 ← idx#40 +Coalesced (already) [70] idx#111 ← idx#40 +Coalesced (already) [72] idx#112 ← idx#40 +Coalesced down to 3 phi equivalence classes +Renumbering block @2 to @1 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@1 +Adding NOP phi() at start of main::@2 +Adding NOP phi() at start of main::@3 +Adding NOP phi() at start of main::@4 +Adding NOP phi() at start of main::@5 +Adding NOP phi() at start of main::@6 +Adding NOP phi() at start of main::@7 +Adding NOP phi() at start of main::@8 +Adding NOP phi() at start of main::@9 +Adding NOP phi() at start of main::@10 +Adding NOP phi() at start of main::@11 +Adding NOP phi() at start of main::@12 +Adding NOP phi() at start of main::@13 +Adding NOP phi() at start of main::@14 +Adding NOP phi() at start of main::@15 +Adding NOP phi() at start of main::@16 +Adding NOP phi() at start of main::@17 +Adding NOP phi() at start of main::@18 +Adding NOP phi() at start of main::@19 +Adding NOP phi() at start of main::@20 +Adding NOP phi() at start of main::@21 +Adding NOP phi() at start of main::@22 +Adding NOP phi() at start of main::@23 +Adding NOP phi() at start of main::@24 +Adding NOP phi() at start of main::@25 +Adding NOP phi() at start of main::@26 +Adding NOP phi() at start of main::@27 +Adding NOP phi() at start of main::@28 +Adding NOP phi() at start of main::@29 +Adding NOP phi() at start of main::@30 +Adding NOP phi() at start of main::@31 +Adding NOP phi() at start of main::@32 +Adding NOP phi() at start of main::@33 +Adding NOP phi() at start of main::@34 + +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 assertType + to:main::@1 +main::@1: scope:[main] from main + [6] phi() + [7] call assertType + to:main::@2 +main::@2: scope:[main] from main::@1 + [8] phi() + [9] call assertType + to:main::@3 +main::@3: scope:[main] from main::@2 + [10] phi() + [11] call assertType + to:main::@4 +main::@4: scope:[main] from main::@3 + [12] phi() + [13] call assertType + to:main::@5 +main::@5: scope:[main] from main::@4 + [14] phi() + [15] call assertType + to:main::@6 +main::@6: scope:[main] from main::@5 + [16] phi() + [17] call assertType + to:main::@7 +main::@7: scope:[main] from main::@6 + [18] phi() + [19] call assertType + to:main::@8 +main::@8: scope:[main] from main::@7 + [20] phi() + [21] call assertType + to:main::@9 +main::@9: scope:[main] from main::@8 + [22] phi() + [23] call assertType + to:main::@10 +main::@10: scope:[main] from main::@9 + [24] phi() + [25] call assertType + to:main::@11 +main::@11: scope:[main] from main::@10 + [26] phi() + [27] call assertType + to:main::@12 +main::@12: scope:[main] from main::@11 + [28] phi() + [29] call assertType + to:main::@13 +main::@13: scope:[main] from main::@12 + [30] phi() + [31] call assertType + to:main::@14 +main::@14: scope:[main] from main::@13 + [32] phi() + [33] call assertType + to:main::@15 +main::@15: scope:[main] from main::@14 + [34] phi() + [35] call assertType + to:main::@16 +main::@16: scope:[main] from main::@15 + [36] phi() + [37] call assertType + to:main::@17 +main::@17: scope:[main] from main::@16 + [38] phi() + [39] call assertType + to:main::@18 +main::@18: scope:[main] from main::@17 + [40] phi() + [41] call assertType + to:main::@19 +main::@19: scope:[main] from main::@18 + [42] phi() + [43] call assertType + to:main::@20 +main::@20: scope:[main] from main::@19 + [44] phi() + [45] call assertType + to:main::@21 +main::@21: scope:[main] from main::@20 + [46] phi() + [47] call assertType + to:main::@22 +main::@22: scope:[main] from main::@21 + [48] phi() + [49] call assertType + to:main::@23 +main::@23: scope:[main] from main::@22 + [50] phi() + [51] call assertType + to:main::@24 +main::@24: scope:[main] from main::@23 + [52] phi() + [53] call assertType + to:main::@25 +main::@25: scope:[main] from main::@24 + [54] phi() + [55] call assertType + to:main::@26 +main::@26: scope:[main] from main::@25 + [56] phi() + [57] call assertType + to:main::@27 +main::@27: scope:[main] from main::@26 + [58] phi() + [59] call assertType + to:main::@28 +main::@28: scope:[main] from main::@27 + [60] phi() + [61] call assertType + to:main::@29 +main::@29: scope:[main] from main::@28 + [62] phi() + [63] call assertType + to:main::@30 +main::@30: scope:[main] from main::@29 + [64] phi() + [65] call assertType + to:main::@31 +main::@31: scope:[main] from main::@30 + [66] phi() + [67] call assertType + to:main::@32 +main::@32: scope:[main] from main::@31 + [68] phi() + [69] call assertType + to:main::@33 +main::@33: scope:[main] from main::@32 + [70] phi() + [71] call assertType + to:main::@34 +main::@34: scope:[main] from main::@33 + [72] phi() + [73] call assertType + to:main::@return +main::@return: scope:[main] from main::@34 + [74] return + to:@return +assertType: scope:[assertType] from main main::@1 main::@10 main::@11 main::@12 main::@13 main::@14 main::@15 main::@16 main::@17 main::@18 main::@19 main::@2 main::@20 main::@21 main::@22 main::@23 main::@24 main::@25 main::@26 main::@27 main::@28 main::@29 main::@3 main::@30 main::@31 main::@32 main::@33 main::@34 main::@4 main::@5 main::@6 main::@7 main::@8 main::@9 + [75] (byte) idx#79 ← phi( main/(byte) 0 main::@1/(byte) idx#40 main::@10/(byte) idx#40 main::@11/(byte) idx#40 main::@12/(byte) idx#40 main::@13/(byte) idx#40 main::@14/(byte) idx#40 main::@15/(byte) idx#40 main::@16/(byte) idx#40 main::@17/(byte) idx#40 main::@18/(byte) idx#40 main::@19/(byte) idx#40 main::@2/(byte) idx#40 main::@20/(byte) idx#40 main::@21/(byte) $50 main::@22/(byte) idx#40 main::@23/(byte) idx#40 main::@24/(byte) idx#40 main::@25/(byte) idx#40 main::@26/(byte) idx#40 main::@27/(byte) idx#40 main::@28/(byte) idx#40 main::@29/(byte) idx#40 main::@3/(byte) idx#40 main::@30/(byte) idx#40 main::@31/(byte) idx#40 main::@32/(byte) idx#40 main::@33/(byte) idx#40 main::@34/(byte) idx#40 main::@4/(byte) idx#40 main::@5/(byte) idx#40 main::@6/(byte) idx#40 main::@7/(byte) idx#40 main::@8/(byte) idx#40 main::@9/(byte) $28 ) + [75] (byte) assertType::t2#35 ← phi( main/(const byte) TYPEID_SIGNED_BYTE main::@1/(const byte) TYPEID_SIGNED_WORD main::@10/(const byte) TYPEID_BYTE main::@11/(const byte) TYPEID_WORD main::@12/(const byte) TYPEID_WORD main::@13/(const byte) TYPEID_DWORD main::@14/(const byte) TYPEID_WORD main::@15/(const byte) TYPEID_WORD main::@16/(const byte) TYPEID_DWORD main::@17/(const byte) TYPEID_DWORD main::@18/(const byte) TYPEID_DWORD main::@19/(const byte) TYPEID_DWORD main::@2/(const byte) TYPEID_SIGNED_DWORD main::@20/(const byte) TYPEID_DWORD main::@21/(const byte) TYPEID_BYTE main::@22/(const byte) TYPEID_BYTE main::@23/(const byte) TYPEID_BYTE main::@24/(const byte) TYPEID_WORD main::@25/(const byte) TYPEID_WORD main::@26/(const byte) TYPEID_DWORD main::@27/(const byte) TYPEID_WORD main::@28/(const byte) TYPEID_WORD main::@29/(const byte) TYPEID_WORD main::@3/(const byte) TYPEID_SIGNED_WORD main::@30/(const byte) TYPEID_DWORD main::@31/(const byte) TYPEID_DWORD main::@32/(const byte) TYPEID_DWORD main::@33/(const byte) TYPEID_DWORD main::@34/(const byte) TYPEID_DWORD main::@4/(const byte) TYPEID_SIGNED_WORD main::@5/(const byte) TYPEID_SIGNED_DWORD main::@6/(const byte) TYPEID_SIGNED_DWORD main::@7/(const byte) TYPEID_SIGNED_DWORD main::@8/(const byte) TYPEID_SIGNED_DWORD main::@9/(const byte) TYPEID_BYTE ) + [75] (byte) assertType::t1#35 ← phi( main/(const byte) TYPEID_SIGNED_BYTE main::@1/(const byte) TYPEID_SIGNED_WORD main::@10/(const byte) TYPEID_BYTE main::@11/(const byte) TYPEID_WORD main::@12/(const byte) TYPEID_WORD main::@13/(const byte) TYPEID_DWORD main::@14/(const byte) TYPEID_WORD main::@15/(const byte) TYPEID_WORD main::@16/(const byte) TYPEID_DWORD main::@17/(const byte) TYPEID_DWORD main::@18/(const byte) TYPEID_DWORD main::@19/(const byte) TYPEID_DWORD main::@2/(const byte) TYPEID_SIGNED_DWORD main::@20/(const byte) TYPEID_DWORD main::@21/(const byte) TYPEID_BYTE main::@22/(const byte) TYPEID_BYTE main::@23/(const byte) TYPEID_BYTE main::@24/(const byte) TYPEID_WORD main::@25/(const byte) TYPEID_WORD main::@26/(const byte) TYPEID_DWORD main::@27/(const byte) TYPEID_WORD main::@28/(const byte) TYPEID_WORD main::@29/(const byte) TYPEID_WORD main::@3/(const byte) TYPEID_SIGNED_WORD main::@30/(const byte) TYPEID_DWORD main::@31/(const byte) TYPEID_DWORD main::@32/(const byte) TYPEID_DWORD main::@33/(const byte) TYPEID_DWORD main::@34/(const byte) TYPEID_SIGNED_DWORD main::@4/(const byte) TYPEID_SIGNED_WORD main::@5/(const byte) TYPEID_SIGNED_DWORD main::@6/(const byte) TYPEID_SIGNED_DWORD main::@7/(const byte) TYPEID_SIGNED_DWORD main::@8/(const byte) TYPEID_SIGNED_DWORD main::@9/(const byte) TYPEID_BYTE ) + [76] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1 + to:assertType::@3 +assertType::@3: scope:[assertType] from assertType + [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 + to:assertType::@2 +assertType::@2: scope:[assertType] from assertType::@1 assertType::@3 + [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 + [79] (byte) idx#40 ← ++ (byte) idx#79 + to:assertType::@return +assertType::@return: scope:[assertType] from assertType::@2 + [80] return + to:@return +assertType::@1: scope:[assertType] from assertType + [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 + to:assertType::@2 + + +VARIABLE REGISTER WEIGHTS +(byte*) COLS +(byte) GREEN +(byte) RED +(byte*) SCREEN +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(byte) assertType::t1 +(byte) assertType::t1#35 1.0 +(byte) assertType::t2 +(byte) assertType::t2#35 2.0 +(byte) idx +(byte) idx#40 0.9999999999999993 +(byte) idx#79 14.400000000000007 +(void()) main() + +Initial phi equivalence classes +[ assertType::t1#35 ] +[ assertType::t2#35 ] +[ idx#79 idx#40 ] +Complete equivalence classes +[ assertType::t1#35 ] +[ assertType::t2#35 ] +[ idx#79 idx#40 ] +Allocated zp ZP_BYTE:2 [ assertType::t1#35 ] +Allocated zp ZP_BYTE:3 [ assertType::t2#35 ] +Allocated zp ZP_BYTE:4 [ idx#79 idx#40 ] + +INITIAL ASM +//SEG0 File Comments +// Tests conversion of numbers to correct int types +// See https://gitlab.com/camelot/kickc/issues/181 +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_SIGNED_DWORD = 6 + .const TYPEID_BYTE = 1 + .const TYPEID_WORD = 3 + .const TYPEID_DWORD = 5 + .const RED = 2 + .const GREEN = 5 + .label idx = 4 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG9 @end +bend: +//SEG10 main +main: { + //SEG11 [5] call assertType + //SEG12 [75] phi from main to assertType [phi:main->assertType] + assertType_from_main: + //SEG13 [75] phi (byte) idx#79 = (byte) 0 [phi:main->assertType#0] -- vbuz1=vbuc1 + lda #0 + sta idx + //SEG14 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG15 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t1 + jsr assertType + //SEG16 [6] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + jmp b1 + //SEG17 main::@1 + b1: + //SEG18 [7] call assertType + //SEG19 [75] phi from main::@1 to assertType [phi:main::@1->assertType] + assertType_from_b1: + //SEG20 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@1->assertType#0] -- register_copy + //SEG21 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG22 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG23 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + jmp b2 + //SEG24 main::@2 + b2: + //SEG25 [9] call assertType + //SEG26 [75] phi from main::@2 to assertType [phi:main::@2->assertType] + assertType_from_b2: + //SEG27 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@2->assertType#0] -- register_copy + //SEG28 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG29 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG30 [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + b3_from_b2: + jmp b3 + //SEG31 main::@3 + b3: + //SEG32 [11] call assertType + //SEG33 [75] phi from main::@3 to assertType [phi:main::@3->assertType] + assertType_from_b3: + //SEG34 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@3->assertType#0] -- register_copy + //SEG35 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG36 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG37 [12] phi from main::@3 to main::@4 [phi:main::@3->main::@4] + b4_from_b3: + jmp b4 + //SEG38 main::@4 + b4: + //SEG39 [13] call assertType + //SEG40 [75] phi from main::@4 to assertType [phi:main::@4->assertType] + assertType_from_b4: + //SEG41 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@4->assertType#0] -- register_copy + //SEG42 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG43 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t1 + jsr assertType + //SEG44 [14] phi from main::@4 to main::@5 [phi:main::@4->main::@5] + b5_from_b4: + jmp b5 + //SEG45 main::@5 + b5: + //SEG46 [15] call assertType + //SEG47 [75] phi from main::@5 to assertType [phi:main::@5->assertType] + assertType_from_b5: + //SEG48 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@5->assertType#0] -- register_copy + //SEG49 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG50 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG51 [16] phi from main::@5 to main::@6 [phi:main::@5->main::@6] + b6_from_b5: + jmp b6 + //SEG52 main::@6 + b6: + //SEG53 [17] call assertType + //SEG54 [75] phi from main::@6 to assertType [phi:main::@6->assertType] + assertType_from_b6: + //SEG55 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@6->assertType#0] -- register_copy + //SEG56 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG57 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG58 [18] phi from main::@6 to main::@7 [phi:main::@6->main::@7] + b7_from_b6: + jmp b7 + //SEG59 main::@7 + b7: + //SEG60 [19] call assertType + //SEG61 [75] phi from main::@7 to assertType [phi:main::@7->assertType] + assertType_from_b7: + //SEG62 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@7->assertType#0] -- register_copy + //SEG63 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG64 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG65 [20] phi from main::@7 to main::@8 [phi:main::@7->main::@8] + b8_from_b7: + jmp b8 + //SEG66 main::@8 + b8: + //SEG67 [21] call assertType + //SEG68 [75] phi from main::@8 to assertType [phi:main::@8->assertType] + assertType_from_b8: + //SEG69 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@8->assertType#0] -- register_copy + //SEG70 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG71 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + //SEG72 [22] phi from main::@8 to main::@9 [phi:main::@8->main::@9] + b9_from_b8: + jmp b9 + //SEG73 main::@9 + b9: + //SEG74 [23] call assertType + //SEG75 [75] phi from main::@9 to assertType [phi:main::@9->assertType] + assertType_from_b9: + //SEG76 [75] phi (byte) idx#79 = (byte) $28 [phi:main::@9->assertType#0] -- vbuz1=vbuc1 + lda #$28 + sta idx + //SEG77 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG78 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG79 [24] phi from main::@9 to main::@10 [phi:main::@9->main::@10] + b10_from_b9: + jmp b10 + //SEG80 main::@10 + b10: + //SEG81 [25] call assertType + //SEG82 [75] phi from main::@10 to assertType [phi:main::@10->assertType] + assertType_from_b10: + //SEG83 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@10->assertType#0] -- register_copy + //SEG84 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG85 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG86 [26] phi from main::@10 to main::@11 [phi:main::@10->main::@11] + b11_from_b10: + jmp b11 + //SEG87 main::@11 + b11: + //SEG88 [27] call assertType + //SEG89 [75] phi from main::@11 to assertType [phi:main::@11->assertType] + assertType_from_b11: + //SEG90 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@11->assertType#0] -- register_copy + //SEG91 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG92 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG93 [28] phi from main::@11 to main::@12 [phi:main::@11->main::@12] + b12_from_b11: + jmp b12 + //SEG94 main::@12 + b12: + //SEG95 [29] call assertType + //SEG96 [75] phi from main::@12 to assertType [phi:main::@12->assertType] + assertType_from_b12: + //SEG97 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@12->assertType#0] -- register_copy + //SEG98 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG99 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG100 [30] phi from main::@12 to main::@13 [phi:main::@12->main::@13] + b13_from_b12: + jmp b13 + //SEG101 main::@13 + b13: + //SEG102 [31] call assertType + //SEG103 [75] phi from main::@13 to assertType [phi:main::@13->assertType] + assertType_from_b13: + //SEG104 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@13->assertType#0] -- register_copy + //SEG105 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG106 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG107 [32] phi from main::@13 to main::@14 [phi:main::@13->main::@14] + b14_from_b13: + jmp b14 + //SEG108 main::@14 + b14: + //SEG109 [33] call assertType + //SEG110 [75] phi from main::@14 to assertType [phi:main::@14->assertType] + assertType_from_b14: + //SEG111 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@14->assertType#0] -- register_copy + //SEG112 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG113 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG114 [34] phi from main::@14 to main::@15 [phi:main::@14->main::@15] + b15_from_b14: + jmp b15 + //SEG115 main::@15 + b15: + //SEG116 [35] call assertType + //SEG117 [75] phi from main::@15 to assertType [phi:main::@15->assertType] + assertType_from_b15: + //SEG118 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@15->assertType#0] -- register_copy + //SEG119 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG120 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG121 [36] phi from main::@15 to main::@16 [phi:main::@15->main::@16] + b16_from_b15: + jmp b16 + //SEG122 main::@16 + b16: + //SEG123 [37] call assertType + //SEG124 [75] phi from main::@16 to assertType [phi:main::@16->assertType] + assertType_from_b16: + //SEG125 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@16->assertType#0] -- register_copy + //SEG126 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG127 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG128 [38] phi from main::@16 to main::@17 [phi:main::@16->main::@17] + b17_from_b16: + jmp b17 + //SEG129 main::@17 + b17: + //SEG130 [39] call assertType + //SEG131 [75] phi from main::@17 to assertType [phi:main::@17->assertType] + assertType_from_b17: + //SEG132 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@17->assertType#0] -- register_copy + //SEG133 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG134 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG135 [40] phi from main::@17 to main::@18 [phi:main::@17->main::@18] + b18_from_b17: + jmp b18 + //SEG136 main::@18 + b18: + //SEG137 [41] call assertType + //SEG138 [75] phi from main::@18 to assertType [phi:main::@18->assertType] + assertType_from_b18: + //SEG139 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@18->assertType#0] -- register_copy + //SEG140 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG141 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG142 [42] phi from main::@18 to main::@19 [phi:main::@18->main::@19] + b19_from_b18: + jmp b19 + //SEG143 main::@19 + b19: + //SEG144 [43] call assertType + //SEG145 [75] phi from main::@19 to assertType [phi:main::@19->assertType] + assertType_from_b19: + //SEG146 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@19->assertType#0] -- register_copy + //SEG147 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG148 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG149 [44] phi from main::@19 to main::@20 [phi:main::@19->main::@20] + b20_from_b19: + jmp b20 + //SEG150 main::@20 + b20: + //SEG151 [45] call assertType + //SEG152 [75] phi from main::@20 to assertType [phi:main::@20->assertType] + assertType_from_b20: + //SEG153 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@20->assertType#0] -- register_copy + //SEG154 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG155 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG156 [46] phi from main::@20 to main::@21 [phi:main::@20->main::@21] + b21_from_b20: + jmp b21 + //SEG157 main::@21 + b21: + //SEG158 [47] call assertType + //SEG159 [75] phi from main::@21 to assertType [phi:main::@21->assertType] + assertType_from_b21: + //SEG160 [75] phi (byte) idx#79 = (byte) $50 [phi:main::@21->assertType#0] -- vbuz1=vbuc1 + lda #$50 + sta idx + //SEG161 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG162 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG163 [48] phi from main::@21 to main::@22 [phi:main::@21->main::@22] + b22_from_b21: + jmp b22 + //SEG164 main::@22 + b22: + //SEG165 [49] call assertType + //SEG166 [75] phi from main::@22 to assertType [phi:main::@22->assertType] + assertType_from_b22: + //SEG167 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@22->assertType#0] -- register_copy + //SEG168 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG169 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG170 [50] phi from main::@22 to main::@23 [phi:main::@22->main::@23] + b23_from_b22: + jmp b23 + //SEG171 main::@23 + b23: + //SEG172 [51] call assertType + //SEG173 [75] phi from main::@23 to assertType [phi:main::@23->assertType] + assertType_from_b23: + //SEG174 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@23->assertType#0] -- register_copy + //SEG175 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG176 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t1 + jsr assertType + //SEG177 [52] phi from main::@23 to main::@24 [phi:main::@23->main::@24] + b24_from_b23: + jmp b24 + //SEG178 main::@24 + b24: + //SEG179 [53] call assertType + //SEG180 [75] phi from main::@24 to assertType [phi:main::@24->assertType] + assertType_from_b24: + //SEG181 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@24->assertType#0] -- register_copy + //SEG182 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG183 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG184 [54] phi from main::@24 to main::@25 [phi:main::@24->main::@25] + b25_from_b24: + jmp b25 + //SEG185 main::@25 + b25: + //SEG186 [55] call assertType + //SEG187 [75] phi from main::@25 to assertType [phi:main::@25->assertType] + assertType_from_b25: + //SEG188 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@25->assertType#0] -- register_copy + //SEG189 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG190 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG191 [56] phi from main::@25 to main::@26 [phi:main::@25->main::@26] + b26_from_b25: + jmp b26 + //SEG192 main::@26 + b26: + //SEG193 [57] call assertType + //SEG194 [75] phi from main::@26 to assertType [phi:main::@26->assertType] + assertType_from_b26: + //SEG195 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@26->assertType#0] -- register_copy + //SEG196 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG197 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG198 [58] phi from main::@26 to main::@27 [phi:main::@26->main::@27] + b27_from_b26: + jmp b27 + //SEG199 main::@27 + b27: + //SEG200 [59] call assertType + //SEG201 [75] phi from main::@27 to assertType [phi:main::@27->assertType] + assertType_from_b27: + //SEG202 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@27->assertType#0] -- register_copy + //SEG203 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG204 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG205 [60] phi from main::@27 to main::@28 [phi:main::@27->main::@28] + b28_from_b27: + jmp b28 + //SEG206 main::@28 + b28: + //SEG207 [61] call assertType + //SEG208 [75] phi from main::@28 to assertType [phi:main::@28->assertType] + assertType_from_b28: + //SEG209 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@28->assertType#0] -- register_copy + //SEG210 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG211 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG212 [62] phi from main::@28 to main::@29 [phi:main::@28->main::@29] + b29_from_b28: + jmp b29 + //SEG213 main::@29 + b29: + //SEG214 [63] call assertType + //SEG215 [75] phi from main::@29 to assertType [phi:main::@29->assertType] + assertType_from_b29: + //SEG216 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@29->assertType#0] -- register_copy + //SEG217 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG218 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t1 + jsr assertType + //SEG219 [64] phi from main::@29 to main::@30 [phi:main::@29->main::@30] + b30_from_b29: + jmp b30 + //SEG220 main::@30 + b30: + //SEG221 [65] call assertType + //SEG222 [75] phi from main::@30 to assertType [phi:main::@30->assertType] + assertType_from_b30: + //SEG223 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@30->assertType#0] -- register_copy + //SEG224 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG225 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG226 [66] phi from main::@30 to main::@31 [phi:main::@30->main::@31] + b31_from_b30: + jmp b31 + //SEG227 main::@31 + b31: + //SEG228 [67] call assertType + //SEG229 [75] phi from main::@31 to assertType [phi:main::@31->assertType] + assertType_from_b31: + //SEG230 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@31->assertType#0] -- register_copy + //SEG231 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG232 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG233 [68] phi from main::@31 to main::@32 [phi:main::@31->main::@32] + b32_from_b31: + jmp b32 + //SEG234 main::@32 + b32: + //SEG235 [69] call assertType + //SEG236 [75] phi from main::@32 to assertType [phi:main::@32->assertType] + assertType_from_b32: + //SEG237 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@32->assertType#0] -- register_copy + //SEG238 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG239 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG240 [70] phi from main::@32 to main::@33 [phi:main::@32->main::@33] + b33_from_b32: + jmp b33 + //SEG241 main::@33 + b33: + //SEG242 [71] call assertType + //SEG243 [75] phi from main::@33 to assertType [phi:main::@33->assertType] + assertType_from_b33: + //SEG244 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@33->assertType#0] -- register_copy + //SEG245 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG246 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t1 + jsr assertType + //SEG247 [72] phi from main::@33 to main::@34 [phi:main::@33->main::@34] + b34_from_b33: + jmp b34 + //SEG248 main::@34 + b34: + //SEG249 [73] call assertType + //SEG250 [75] phi from main::@34 to assertType [phi:main::@34->assertType] + assertType_from_b34: + //SEG251 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@34->assertType#0] -- register_copy + //SEG252 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@34->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG253 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@34->assertType#2] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t1 + jsr assertType + jmp breturn + //SEG254 main::@return + breturn: + //SEG255 [74] return + rts +} +//SEG256 assertType +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte zeropage(2) t1, byte zeropage(3) t2) +assertType: { + .label t1 = 2 + .label t2 = 3 + //SEG257 [76] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1 -- vbuz1_eq_vbuz2_then_la1 + lda t1 + cmp t2 + beq b1 + jmp b3 + //SEG258 assertType::@3 + b3: + //SEG259 [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #RED + ldy idx + sta $d800,y + jmp b2 + //SEG260 assertType::@2 + b2: + //SEG261 [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 -- pbuc1_derefidx_vbuz1=vbuz2 + lda t1 + ldy idx + sta $400,y + //SEG262 [79] (byte) idx#40 ← ++ (byte) idx#79 -- vbuz1=_inc_vbuz1 + inc idx + jmp breturn + //SEG263 assertType::@return + breturn: + //SEG264 [80] return + rts + //SEG265 assertType::@1 + b1: + //SEG266 [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuz1=vbuc2 + lda #GREEN + ldy idx + sta $d800,y + jmp b2 +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 [ assertType::t1#35 idx#79 ] ( main:2::assertType:5 [ assertType::t1#35 idx#79 ] main:2::assertType:7 [ assertType::t1#35 idx#79 ] main:2::assertType:9 [ assertType::t1#35 idx#79 ] main:2::assertType:11 [ assertType::t1#35 idx#79 ] main:2::assertType:13 [ assertType::t1#35 idx#79 ] main:2::assertType:15 [ assertType::t1#35 idx#79 ] main:2::assertType:17 [ assertType::t1#35 idx#79 ] main:2::assertType:19 [ assertType::t1#35 idx#79 ] main:2::assertType:21 [ assertType::t1#35 idx#79 ] main:2::assertType:23 [ assertType::t1#35 idx#79 ] main:2::assertType:25 [ assertType::t1#35 idx#79 ] main:2::assertType:27 [ assertType::t1#35 idx#79 ] main:2::assertType:29 [ assertType::t1#35 idx#79 ] main:2::assertType:31 [ assertType::t1#35 idx#79 ] main:2::assertType:33 [ assertType::t1#35 idx#79 ] main:2::assertType:35 [ assertType::t1#35 idx#79 ] main:2::assertType:37 [ assertType::t1#35 idx#79 ] main:2::assertType:39 [ assertType::t1#35 idx#79 ] main:2::assertType:41 [ assertType::t1#35 idx#79 ] main:2::assertType:43 [ assertType::t1#35 idx#79 ] main:2::assertType:45 [ assertType::t1#35 idx#79 ] main:2::assertType:47 [ assertType::t1#35 idx#79 ] main:2::assertType:49 [ assertType::t1#35 idx#79 ] main:2::assertType:51 [ assertType::t1#35 idx#79 ] main:2::assertType:53 [ assertType::t1#35 idx#79 ] main:2::assertType:55 [ assertType::t1#35 idx#79 ] main:2::assertType:57 [ assertType::t1#35 idx#79 ] main:2::assertType:59 [ assertType::t1#35 idx#79 ] main:2::assertType:61 [ assertType::t1#35 idx#79 ] main:2::assertType:63 [ assertType::t1#35 idx#79 ] main:2::assertType:65 [ assertType::t1#35 idx#79 ] main:2::assertType:67 [ assertType::t1#35 idx#79 ] main:2::assertType:69 [ assertType::t1#35 idx#79 ] main:2::assertType:71 [ assertType::t1#35 idx#79 ] main:2::assertType:73 [ assertType::t1#35 idx#79 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ assertType::t1#35 ] +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ idx#79 idx#40 ] +Statement [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 [ idx#79 ] ( main:2::assertType:5 [ idx#79 ] main:2::assertType:7 [ idx#79 ] main:2::assertType:9 [ idx#79 ] main:2::assertType:11 [ idx#79 ] main:2::assertType:13 [ idx#79 ] main:2::assertType:15 [ idx#79 ] main:2::assertType:17 [ idx#79 ] main:2::assertType:19 [ idx#79 ] main:2::assertType:21 [ idx#79 ] main:2::assertType:23 [ idx#79 ] main:2::assertType:25 [ idx#79 ] main:2::assertType:27 [ idx#79 ] main:2::assertType:29 [ idx#79 ] main:2::assertType:31 [ idx#79 ] main:2::assertType:33 [ idx#79 ] main:2::assertType:35 [ idx#79 ] main:2::assertType:37 [ idx#79 ] main:2::assertType:39 [ idx#79 ] main:2::assertType:41 [ idx#79 ] main:2::assertType:43 [ idx#79 ] main:2::assertType:45 [ idx#79 ] main:2::assertType:47 [ idx#79 ] main:2::assertType:49 [ idx#79 ] main:2::assertType:51 [ idx#79 ] main:2::assertType:53 [ idx#79 ] main:2::assertType:55 [ idx#79 ] main:2::assertType:57 [ idx#79 ] main:2::assertType:59 [ idx#79 ] main:2::assertType:61 [ idx#79 ] main:2::assertType:63 [ idx#79 ] main:2::assertType:65 [ idx#79 ] main:2::assertType:67 [ idx#79 ] main:2::assertType:69 [ idx#79 ] main:2::assertType:71 [ idx#79 ] main:2::assertType:73 [ idx#79 ] ) always clobbers reg byte a +Statement [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 [ assertType::t1#35 idx#79 ] ( main:2::assertType:5 [ assertType::t1#35 idx#79 ] main:2::assertType:7 [ assertType::t1#35 idx#79 ] main:2::assertType:9 [ assertType::t1#35 idx#79 ] main:2::assertType:11 [ assertType::t1#35 idx#79 ] main:2::assertType:13 [ assertType::t1#35 idx#79 ] main:2::assertType:15 [ assertType::t1#35 idx#79 ] main:2::assertType:17 [ assertType::t1#35 idx#79 ] main:2::assertType:19 [ assertType::t1#35 idx#79 ] main:2::assertType:21 [ assertType::t1#35 idx#79 ] main:2::assertType:23 [ assertType::t1#35 idx#79 ] main:2::assertType:25 [ assertType::t1#35 idx#79 ] main:2::assertType:27 [ assertType::t1#35 idx#79 ] main:2::assertType:29 [ assertType::t1#35 idx#79 ] main:2::assertType:31 [ assertType::t1#35 idx#79 ] main:2::assertType:33 [ assertType::t1#35 idx#79 ] main:2::assertType:35 [ assertType::t1#35 idx#79 ] main:2::assertType:37 [ assertType::t1#35 idx#79 ] main:2::assertType:39 [ assertType::t1#35 idx#79 ] main:2::assertType:41 [ assertType::t1#35 idx#79 ] main:2::assertType:43 [ assertType::t1#35 idx#79 ] main:2::assertType:45 [ assertType::t1#35 idx#79 ] main:2::assertType:47 [ assertType::t1#35 idx#79 ] main:2::assertType:49 [ assertType::t1#35 idx#79 ] main:2::assertType:51 [ assertType::t1#35 idx#79 ] main:2::assertType:53 [ assertType::t1#35 idx#79 ] main:2::assertType:55 [ assertType::t1#35 idx#79 ] main:2::assertType:57 [ assertType::t1#35 idx#79 ] main:2::assertType:59 [ assertType::t1#35 idx#79 ] main:2::assertType:61 [ assertType::t1#35 idx#79 ] main:2::assertType:63 [ assertType::t1#35 idx#79 ] main:2::assertType:65 [ assertType::t1#35 idx#79 ] main:2::assertType:67 [ assertType::t1#35 idx#79 ] main:2::assertType:69 [ assertType::t1#35 idx#79 ] main:2::assertType:71 [ assertType::t1#35 idx#79 ] main:2::assertType:73 [ assertType::t1#35 idx#79 ] ) always clobbers reg byte a +Statement [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 [ assertType::t1#35 idx#79 ] ( main:2::assertType:5 [ assertType::t1#35 idx#79 ] main:2::assertType:7 [ assertType::t1#35 idx#79 ] main:2::assertType:9 [ assertType::t1#35 idx#79 ] main:2::assertType:11 [ assertType::t1#35 idx#79 ] main:2::assertType:13 [ assertType::t1#35 idx#79 ] main:2::assertType:15 [ assertType::t1#35 idx#79 ] main:2::assertType:17 [ assertType::t1#35 idx#79 ] main:2::assertType:19 [ assertType::t1#35 idx#79 ] main:2::assertType:21 [ assertType::t1#35 idx#79 ] main:2::assertType:23 [ assertType::t1#35 idx#79 ] main:2::assertType:25 [ assertType::t1#35 idx#79 ] main:2::assertType:27 [ assertType::t1#35 idx#79 ] main:2::assertType:29 [ assertType::t1#35 idx#79 ] main:2::assertType:31 [ assertType::t1#35 idx#79 ] main:2::assertType:33 [ assertType::t1#35 idx#79 ] main:2::assertType:35 [ assertType::t1#35 idx#79 ] main:2::assertType:37 [ assertType::t1#35 idx#79 ] main:2::assertType:39 [ assertType::t1#35 idx#79 ] main:2::assertType:41 [ assertType::t1#35 idx#79 ] main:2::assertType:43 [ assertType::t1#35 idx#79 ] main:2::assertType:45 [ assertType::t1#35 idx#79 ] main:2::assertType:47 [ assertType::t1#35 idx#79 ] main:2::assertType:49 [ assertType::t1#35 idx#79 ] main:2::assertType:51 [ assertType::t1#35 idx#79 ] main:2::assertType:53 [ assertType::t1#35 idx#79 ] main:2::assertType:55 [ assertType::t1#35 idx#79 ] main:2::assertType:57 [ assertType::t1#35 idx#79 ] main:2::assertType:59 [ assertType::t1#35 idx#79 ] main:2::assertType:61 [ assertType::t1#35 idx#79 ] main:2::assertType:63 [ assertType::t1#35 idx#79 ] main:2::assertType:65 [ assertType::t1#35 idx#79 ] main:2::assertType:67 [ assertType::t1#35 idx#79 ] main:2::assertType:69 [ assertType::t1#35 idx#79 ] main:2::assertType:71 [ assertType::t1#35 idx#79 ] main:2::assertType:73 [ assertType::t1#35 idx#79 ] ) always clobbers reg byte a +Statement [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 [ idx#79 ] ( main:2::assertType:5 [ idx#79 ] main:2::assertType:7 [ idx#79 ] main:2::assertType:9 [ idx#79 ] main:2::assertType:11 [ idx#79 ] main:2::assertType:13 [ idx#79 ] main:2::assertType:15 [ idx#79 ] main:2::assertType:17 [ idx#79 ] main:2::assertType:19 [ idx#79 ] main:2::assertType:21 [ idx#79 ] main:2::assertType:23 [ idx#79 ] main:2::assertType:25 [ idx#79 ] main:2::assertType:27 [ idx#79 ] main:2::assertType:29 [ idx#79 ] main:2::assertType:31 [ idx#79 ] main:2::assertType:33 [ idx#79 ] main:2::assertType:35 [ idx#79 ] main:2::assertType:37 [ idx#79 ] main:2::assertType:39 [ idx#79 ] main:2::assertType:41 [ idx#79 ] main:2::assertType:43 [ idx#79 ] main:2::assertType:45 [ idx#79 ] main:2::assertType:47 [ idx#79 ] main:2::assertType:49 [ idx#79 ] main:2::assertType:51 [ idx#79 ] main:2::assertType:53 [ idx#79 ] main:2::assertType:55 [ idx#79 ] main:2::assertType:57 [ idx#79 ] main:2::assertType:59 [ idx#79 ] main:2::assertType:61 [ idx#79 ] main:2::assertType:63 [ idx#79 ] main:2::assertType:65 [ idx#79 ] main:2::assertType:67 [ idx#79 ] main:2::assertType:69 [ idx#79 ] main:2::assertType:71 [ idx#79 ] main:2::assertType:73 [ idx#79 ] ) always clobbers reg byte a +Statement [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 [ assertType::t1#35 idx#79 ] ( main:2::assertType:5 [ assertType::t1#35 idx#79 ] main:2::assertType:7 [ assertType::t1#35 idx#79 ] main:2::assertType:9 [ assertType::t1#35 idx#79 ] main:2::assertType:11 [ assertType::t1#35 idx#79 ] main:2::assertType:13 [ assertType::t1#35 idx#79 ] main:2::assertType:15 [ assertType::t1#35 idx#79 ] main:2::assertType:17 [ assertType::t1#35 idx#79 ] main:2::assertType:19 [ assertType::t1#35 idx#79 ] main:2::assertType:21 [ assertType::t1#35 idx#79 ] main:2::assertType:23 [ assertType::t1#35 idx#79 ] main:2::assertType:25 [ assertType::t1#35 idx#79 ] main:2::assertType:27 [ assertType::t1#35 idx#79 ] main:2::assertType:29 [ assertType::t1#35 idx#79 ] main:2::assertType:31 [ assertType::t1#35 idx#79 ] main:2::assertType:33 [ assertType::t1#35 idx#79 ] main:2::assertType:35 [ assertType::t1#35 idx#79 ] main:2::assertType:37 [ assertType::t1#35 idx#79 ] main:2::assertType:39 [ assertType::t1#35 idx#79 ] main:2::assertType:41 [ assertType::t1#35 idx#79 ] main:2::assertType:43 [ assertType::t1#35 idx#79 ] main:2::assertType:45 [ assertType::t1#35 idx#79 ] main:2::assertType:47 [ assertType::t1#35 idx#79 ] main:2::assertType:49 [ assertType::t1#35 idx#79 ] main:2::assertType:51 [ assertType::t1#35 idx#79 ] main:2::assertType:53 [ assertType::t1#35 idx#79 ] main:2::assertType:55 [ assertType::t1#35 idx#79 ] main:2::assertType:57 [ assertType::t1#35 idx#79 ] main:2::assertType:59 [ assertType::t1#35 idx#79 ] main:2::assertType:61 [ assertType::t1#35 idx#79 ] main:2::assertType:63 [ assertType::t1#35 idx#79 ] main:2::assertType:65 [ assertType::t1#35 idx#79 ] main:2::assertType:67 [ assertType::t1#35 idx#79 ] main:2::assertType:69 [ assertType::t1#35 idx#79 ] main:2::assertType:71 [ assertType::t1#35 idx#79 ] main:2::assertType:73 [ assertType::t1#35 idx#79 ] ) always clobbers reg byte a +Potential registers zp ZP_BYTE:2 [ assertType::t1#35 ] : zp ZP_BYTE:2 , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:3 [ assertType::t2#35 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:4 [ idx#79 idx#40 ] : zp ZP_BYTE:4 , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [] 15.4: zp ZP_BYTE:4 [ idx#79 idx#40 ] +Uplift Scope [assertType] 2: zp ZP_BYTE:3 [ assertType::t2#35 ] 1: zp ZP_BYTE:2 [ assertType::t1#35 ] +Uplift Scope [main] + +Uplifting [] best 739 combination reg byte x [ idx#79 idx#40 ] +Uplifting [assertType] best 632 combination zp ZP_BYTE:3 [ assertType::t2#35 ] reg byte y [ assertType::t1#35 ] +Uplifting [main] best 632 combination +Attempting to uplift remaining variables inzp ZP_BYTE:3 [ assertType::t2#35 ] +Uplifting [assertType] best 632 combination zp ZP_BYTE:3 [ assertType::t2#35 ] +Allocated (was zp ZP_BYTE:3) zp ZP_BYTE:2 [ assertType::t2#35 ] + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 File Comments +// Tests conversion of numbers to correct int types +// See https://gitlab.com/camelot/kickc/issues/181 +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_SIGNED_DWORD = 6 + .const TYPEID_BYTE = 1 + .const TYPEID_WORD = 3 + .const TYPEID_DWORD = 5 + .const RED = 2 + .const GREEN = 5 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG9 @end +bend: +//SEG10 main +main: { + //SEG11 [5] call assertType + //SEG12 [75] phi from main to assertType [phi:main->assertType] + assertType_from_main: + //SEG13 [75] phi (byte) idx#79 = (byte) 0 [phi:main->assertType#0] -- vbuxx=vbuc1 + ldx #0 + //SEG14 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG15 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_BYTE + jsr assertType + //SEG16 [6] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + jmp b1 + //SEG17 main::@1 + b1: + //SEG18 [7] call assertType + //SEG19 [75] phi from main::@1 to assertType [phi:main::@1->assertType] + assertType_from_b1: + //SEG20 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@1->assertType#0] -- register_copy + //SEG21 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG22 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG23 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + jmp b2 + //SEG24 main::@2 + b2: + //SEG25 [9] call assertType + //SEG26 [75] phi from main::@2 to assertType [phi:main::@2->assertType] + assertType_from_b2: + //SEG27 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@2->assertType#0] -- register_copy + //SEG28 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG29 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG30 [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + b3_from_b2: + jmp b3 + //SEG31 main::@3 + b3: + //SEG32 [11] call assertType + //SEG33 [75] phi from main::@3 to assertType [phi:main::@3->assertType] + assertType_from_b3: + //SEG34 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@3->assertType#0] -- register_copy + //SEG35 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG36 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG37 [12] phi from main::@3 to main::@4 [phi:main::@3->main::@4] + b4_from_b3: + jmp b4 + //SEG38 main::@4 + b4: + //SEG39 [13] call assertType + //SEG40 [75] phi from main::@4 to assertType [phi:main::@4->assertType] + assertType_from_b4: + //SEG41 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@4->assertType#0] -- register_copy + //SEG42 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG43 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_WORD + jsr assertType + //SEG44 [14] phi from main::@4 to main::@5 [phi:main::@4->main::@5] + b5_from_b4: + jmp b5 + //SEG45 main::@5 + b5: + //SEG46 [15] call assertType + //SEG47 [75] phi from main::@5 to assertType [phi:main::@5->assertType] + assertType_from_b5: + //SEG48 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@5->assertType#0] -- register_copy + //SEG49 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG50 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG51 [16] phi from main::@5 to main::@6 [phi:main::@5->main::@6] + b6_from_b5: + jmp b6 + //SEG52 main::@6 + b6: + //SEG53 [17] call assertType + //SEG54 [75] phi from main::@6 to assertType [phi:main::@6->assertType] + assertType_from_b6: + //SEG55 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@6->assertType#0] -- register_copy + //SEG56 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG57 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG58 [18] phi from main::@6 to main::@7 [phi:main::@6->main::@7] + b7_from_b6: + jmp b7 + //SEG59 main::@7 + b7: + //SEG60 [19] call assertType + //SEG61 [75] phi from main::@7 to assertType [phi:main::@7->assertType] + assertType_from_b7: + //SEG62 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@7->assertType#0] -- register_copy + //SEG63 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG64 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG65 [20] phi from main::@7 to main::@8 [phi:main::@7->main::@8] + b8_from_b7: + jmp b8 + //SEG66 main::@8 + b8: + //SEG67 [21] call assertType + //SEG68 [75] phi from main::@8 to assertType [phi:main::@8->assertType] + assertType_from_b8: + //SEG69 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@8->assertType#0] -- register_copy + //SEG70 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG71 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG72 [22] phi from main::@8 to main::@9 [phi:main::@8->main::@9] + b9_from_b8: + jmp b9 + //SEG73 main::@9 + b9: + //SEG74 [23] call assertType + //SEG75 [75] phi from main::@9 to assertType [phi:main::@9->assertType] + assertType_from_b9: + //SEG76 [75] phi (byte) idx#79 = (byte) $28 [phi:main::@9->assertType#0] -- vbuxx=vbuc1 + ldx #$28 + //SEG77 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG78 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG79 [24] phi from main::@9 to main::@10 [phi:main::@9->main::@10] + b10_from_b9: + jmp b10 + //SEG80 main::@10 + b10: + //SEG81 [25] call assertType + //SEG82 [75] phi from main::@10 to assertType [phi:main::@10->assertType] + assertType_from_b10: + //SEG83 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@10->assertType#0] -- register_copy + //SEG84 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG85 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG86 [26] phi from main::@10 to main::@11 [phi:main::@10->main::@11] + b11_from_b10: + jmp b11 + //SEG87 main::@11 + b11: + //SEG88 [27] call assertType + //SEG89 [75] phi from main::@11 to assertType [phi:main::@11->assertType] + assertType_from_b11: + //SEG90 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@11->assertType#0] -- register_copy + //SEG91 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG92 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG93 [28] phi from main::@11 to main::@12 [phi:main::@11->main::@12] + b12_from_b11: + jmp b12 + //SEG94 main::@12 + b12: + //SEG95 [29] call assertType + //SEG96 [75] phi from main::@12 to assertType [phi:main::@12->assertType] + assertType_from_b12: + //SEG97 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@12->assertType#0] -- register_copy + //SEG98 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG99 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG100 [30] phi from main::@12 to main::@13 [phi:main::@12->main::@13] + b13_from_b12: + jmp b13 + //SEG101 main::@13 + b13: + //SEG102 [31] call assertType + //SEG103 [75] phi from main::@13 to assertType [phi:main::@13->assertType] + assertType_from_b13: + //SEG104 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@13->assertType#0] -- register_copy + //SEG105 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG106 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG107 [32] phi from main::@13 to main::@14 [phi:main::@13->main::@14] + b14_from_b13: + jmp b14 + //SEG108 main::@14 + b14: + //SEG109 [33] call assertType + //SEG110 [75] phi from main::@14 to assertType [phi:main::@14->assertType] + assertType_from_b14: + //SEG111 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@14->assertType#0] -- register_copy + //SEG112 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG113 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG114 [34] phi from main::@14 to main::@15 [phi:main::@14->main::@15] + b15_from_b14: + jmp b15 + //SEG115 main::@15 + b15: + //SEG116 [35] call assertType + //SEG117 [75] phi from main::@15 to assertType [phi:main::@15->assertType] + assertType_from_b15: + //SEG118 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@15->assertType#0] -- register_copy + //SEG119 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG120 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG121 [36] phi from main::@15 to main::@16 [phi:main::@15->main::@16] + b16_from_b15: + jmp b16 + //SEG122 main::@16 + b16: + //SEG123 [37] call assertType + //SEG124 [75] phi from main::@16 to assertType [phi:main::@16->assertType] + assertType_from_b16: + //SEG125 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@16->assertType#0] -- register_copy + //SEG126 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG127 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG128 [38] phi from main::@16 to main::@17 [phi:main::@16->main::@17] + b17_from_b16: + jmp b17 + //SEG129 main::@17 + b17: + //SEG130 [39] call assertType + //SEG131 [75] phi from main::@17 to assertType [phi:main::@17->assertType] + assertType_from_b17: + //SEG132 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@17->assertType#0] -- register_copy + //SEG133 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG134 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG135 [40] phi from main::@17 to main::@18 [phi:main::@17->main::@18] + b18_from_b17: + jmp b18 + //SEG136 main::@18 + b18: + //SEG137 [41] call assertType + //SEG138 [75] phi from main::@18 to assertType [phi:main::@18->assertType] + assertType_from_b18: + //SEG139 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@18->assertType#0] -- register_copy + //SEG140 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG141 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG142 [42] phi from main::@18 to main::@19 [phi:main::@18->main::@19] + b19_from_b18: + jmp b19 + //SEG143 main::@19 + b19: + //SEG144 [43] call assertType + //SEG145 [75] phi from main::@19 to assertType [phi:main::@19->assertType] + assertType_from_b19: + //SEG146 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@19->assertType#0] -- register_copy + //SEG147 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG148 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG149 [44] phi from main::@19 to main::@20 [phi:main::@19->main::@20] + b20_from_b19: + jmp b20 + //SEG150 main::@20 + b20: + //SEG151 [45] call assertType + //SEG152 [75] phi from main::@20 to assertType [phi:main::@20->assertType] + assertType_from_b20: + //SEG153 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@20->assertType#0] -- register_copy + //SEG154 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG155 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG156 [46] phi from main::@20 to main::@21 [phi:main::@20->main::@21] + b21_from_b20: + jmp b21 + //SEG157 main::@21 + b21: + //SEG158 [47] call assertType + //SEG159 [75] phi from main::@21 to assertType [phi:main::@21->assertType] + assertType_from_b21: + //SEG160 [75] phi (byte) idx#79 = (byte) $50 [phi:main::@21->assertType#0] -- vbuxx=vbuc1 + ldx #$50 + //SEG161 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG162 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG163 [48] phi from main::@21 to main::@22 [phi:main::@21->main::@22] + b22_from_b21: + jmp b22 + //SEG164 main::@22 + b22: + //SEG165 [49] call assertType + //SEG166 [75] phi from main::@22 to assertType [phi:main::@22->assertType] + assertType_from_b22: + //SEG167 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@22->assertType#0] -- register_copy + //SEG168 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG169 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG170 [50] phi from main::@22 to main::@23 [phi:main::@22->main::@23] + b23_from_b22: + jmp b23 + //SEG171 main::@23 + b23: + //SEG172 [51] call assertType + //SEG173 [75] phi from main::@23 to assertType [phi:main::@23->assertType] + assertType_from_b23: + //SEG174 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@23->assertType#0] -- register_copy + //SEG175 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG176 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_BYTE + jsr assertType + //SEG177 [52] phi from main::@23 to main::@24 [phi:main::@23->main::@24] + b24_from_b23: + jmp b24 + //SEG178 main::@24 + b24: + //SEG179 [53] call assertType + //SEG180 [75] phi from main::@24 to assertType [phi:main::@24->assertType] + assertType_from_b24: + //SEG181 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@24->assertType#0] -- register_copy + //SEG182 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG183 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG184 [54] phi from main::@24 to main::@25 [phi:main::@24->main::@25] + b25_from_b24: + jmp b25 + //SEG185 main::@25 + b25: + //SEG186 [55] call assertType + //SEG187 [75] phi from main::@25 to assertType [phi:main::@25->assertType] + assertType_from_b25: + //SEG188 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@25->assertType#0] -- register_copy + //SEG189 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG190 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG191 [56] phi from main::@25 to main::@26 [phi:main::@25->main::@26] + b26_from_b25: + jmp b26 + //SEG192 main::@26 + b26: + //SEG193 [57] call assertType + //SEG194 [75] phi from main::@26 to assertType [phi:main::@26->assertType] + assertType_from_b26: + //SEG195 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@26->assertType#0] -- register_copy + //SEG196 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG197 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG198 [58] phi from main::@26 to main::@27 [phi:main::@26->main::@27] + b27_from_b26: + jmp b27 + //SEG199 main::@27 + b27: + //SEG200 [59] call assertType + //SEG201 [75] phi from main::@27 to assertType [phi:main::@27->assertType] + assertType_from_b27: + //SEG202 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@27->assertType#0] -- register_copy + //SEG203 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG204 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG205 [60] phi from main::@27 to main::@28 [phi:main::@27->main::@28] + b28_from_b27: + jmp b28 + //SEG206 main::@28 + b28: + //SEG207 [61] call assertType + //SEG208 [75] phi from main::@28 to assertType [phi:main::@28->assertType] + assertType_from_b28: + //SEG209 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@28->assertType#0] -- register_copy + //SEG210 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG211 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG212 [62] phi from main::@28 to main::@29 [phi:main::@28->main::@29] + b29_from_b28: + jmp b29 + //SEG213 main::@29 + b29: + //SEG214 [63] call assertType + //SEG215 [75] phi from main::@29 to assertType [phi:main::@29->assertType] + assertType_from_b29: + //SEG216 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@29->assertType#0] -- register_copy + //SEG217 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG218 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_WORD + jsr assertType + //SEG219 [64] phi from main::@29 to main::@30 [phi:main::@29->main::@30] + b30_from_b29: + jmp b30 + //SEG220 main::@30 + b30: + //SEG221 [65] call assertType + //SEG222 [75] phi from main::@30 to assertType [phi:main::@30->assertType] + assertType_from_b30: + //SEG223 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@30->assertType#0] -- register_copy + //SEG224 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG225 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG226 [66] phi from main::@30 to main::@31 [phi:main::@30->main::@31] + b31_from_b30: + jmp b31 + //SEG227 main::@31 + b31: + //SEG228 [67] call assertType + //SEG229 [75] phi from main::@31 to assertType [phi:main::@31->assertType] + assertType_from_b31: + //SEG230 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@31->assertType#0] -- register_copy + //SEG231 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG232 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG233 [68] phi from main::@31 to main::@32 [phi:main::@31->main::@32] + b32_from_b31: + jmp b32 + //SEG234 main::@32 + b32: + //SEG235 [69] call assertType + //SEG236 [75] phi from main::@32 to assertType [phi:main::@32->assertType] + assertType_from_b32: + //SEG237 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@32->assertType#0] -- register_copy + //SEG238 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG239 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG240 [70] phi from main::@32 to main::@33 [phi:main::@32->main::@33] + b33_from_b32: + jmp b33 + //SEG241 main::@33 + b33: + //SEG242 [71] call assertType + //SEG243 [75] phi from main::@33 to assertType [phi:main::@33->assertType] + assertType_from_b33: + //SEG244 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@33->assertType#0] -- register_copy + //SEG245 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG246 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_DWORD + jsr assertType + //SEG247 [72] phi from main::@33 to main::@34 [phi:main::@33->main::@34] + b34_from_b33: + jmp b34 + //SEG248 main::@34 + b34: + //SEG249 [73] call assertType + //SEG250 [75] phi from main::@34 to assertType [phi:main::@34->assertType] + assertType_from_b34: + //SEG251 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@34->assertType#0] -- register_copy + //SEG252 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@34->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG253 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@34->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + jmp breturn + //SEG254 main::@return + breturn: + //SEG255 [74] return + rts +} +//SEG256 assertType +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte register(Y) t1, byte zeropage(2) t2) +assertType: { + .label t2 = 2 + //SEG257 [76] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 + tya + cmp t2 + beq b1 + jmp b3 + //SEG258 assertType::@3 + b3: + //SEG259 [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #RED + sta $d800,x + jmp b2 + //SEG260 assertType::@2 + b2: + //SEG261 [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 -- pbuc1_derefidx_vbuxx=vbuyy + tya + sta $400,x + //SEG262 [79] (byte) idx#40 ← ++ (byte) idx#79 -- vbuxx=_inc_vbuxx + inx + jmp breturn + //SEG263 assertType::@return + breturn: + //SEG264 [80] return + rts + //SEG265 assertType::@1 + b1: + //SEG266 [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #GREEN + sta $d800,x + jmp b2 +} + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp b3 +Removing instruction jmp b4 +Removing instruction jmp b5 +Removing instruction jmp b6 +Removing instruction jmp b7 +Removing instruction jmp b8 +Removing instruction jmp b9 +Removing instruction jmp b10 +Removing instruction jmp b11 +Removing instruction jmp b12 +Removing instruction jmp b13 +Removing instruction jmp b14 +Removing instruction jmp b15 +Removing instruction jmp b16 +Removing instruction jmp b17 +Removing instruction jmp b18 +Removing instruction jmp b19 +Removing instruction jmp b20 +Removing instruction jmp b21 +Removing instruction jmp b22 +Removing instruction jmp b23 +Removing instruction jmp b24 +Removing instruction jmp b25 +Removing instruction jmp b26 +Removing instruction jmp b27 +Removing instruction jmp b28 +Removing instruction jmp b29 +Removing instruction jmp b30 +Removing instruction jmp b31 +Removing instruction jmp b32 +Removing instruction jmp b33 +Removing instruction jmp b34 +Removing instruction jmp breturn +Removing instruction jmp b3 +Removing instruction jmp b2 +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing instruction ldy #TYPEID_SIGNED_BYTE with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_BYTE with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_WORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Replacing instruction ldy #TYPEID_DWORD with TAY +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Removing instruction b1_from_main: +Removing instruction assertType_from_b1: +Removing instruction b2_from_b1: +Removing instruction assertType_from_b2: +Removing instruction b3_from_b2: +Removing instruction assertType_from_b3: +Removing instruction b4_from_b3: +Removing instruction assertType_from_b4: +Removing instruction b5_from_b4: +Removing instruction assertType_from_b5: +Removing instruction b6_from_b5: +Removing instruction assertType_from_b6: +Removing instruction b7_from_b6: +Removing instruction assertType_from_b7: +Removing instruction b8_from_b7: +Removing instruction assertType_from_b8: +Removing instruction b9_from_b8: +Removing instruction assertType_from_b9: +Removing instruction b10_from_b9: +Removing instruction assertType_from_b10: +Removing instruction b11_from_b10: +Removing instruction assertType_from_b11: +Removing instruction b12_from_b11: +Removing instruction assertType_from_b12: +Removing instruction b13_from_b12: +Removing instruction assertType_from_b13: +Removing instruction b14_from_b13: +Removing instruction assertType_from_b14: +Removing instruction b15_from_b14: +Removing instruction assertType_from_b15: +Removing instruction b16_from_b15: +Removing instruction assertType_from_b16: +Removing instruction b17_from_b16: +Removing instruction assertType_from_b17: +Removing instruction b18_from_b17: +Removing instruction assertType_from_b18: +Removing instruction b19_from_b18: +Removing instruction assertType_from_b19: +Removing instruction b20_from_b19: +Removing instruction assertType_from_b20: +Removing instruction b21_from_b20: +Removing instruction assertType_from_b21: +Removing instruction b22_from_b21: +Removing instruction assertType_from_b22: +Removing instruction b23_from_b22: +Removing instruction assertType_from_b23: +Removing instruction b24_from_b23: +Removing instruction assertType_from_b24: +Removing instruction b25_from_b24: +Removing instruction assertType_from_b25: +Removing instruction b26_from_b25: +Removing instruction assertType_from_b26: +Removing instruction b27_from_b26: +Removing instruction assertType_from_b27: +Removing instruction b28_from_b27: +Removing instruction assertType_from_b28: +Removing instruction b29_from_b28: +Removing instruction assertType_from_b29: +Removing instruction b30_from_b29: +Removing instruction assertType_from_b30: +Removing instruction b31_from_b30: +Removing instruction assertType_from_b31: +Removing instruction b32_from_b31: +Removing instruction assertType_from_b32: +Removing instruction b33_from_b32: +Removing instruction assertType_from_b33: +Removing instruction b34_from_b33: +Removing instruction assertType_from_b34: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction assertType_from_main: +Removing instruction b1: +Removing instruction b2: +Removing instruction b3: +Removing instruction b4: +Removing instruction b5: +Removing instruction b6: +Removing instruction b7: +Removing instruction b8: +Removing instruction b9: +Removing instruction b10: +Removing instruction b11: +Removing instruction b12: +Removing instruction b13: +Removing instruction b14: +Removing instruction b15: +Removing instruction b16: +Removing instruction b17: +Removing instruction b18: +Removing instruction b19: +Removing instruction b20: +Removing instruction b21: +Removing instruction b22: +Removing instruction b23: +Removing instruction b24: +Removing instruction b25: +Removing instruction b26: +Removing instruction b27: +Removing instruction b28: +Removing instruction b29: +Removing instruction b30: +Removing instruction b31: +Removing instruction b32: +Removing instruction b33: +Removing instruction b34: +Removing instruction breturn: +Removing instruction 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 +(byte*) COLS +(byte) GREEN +(const byte) GREEN#0 GREEN = (byte) 5 +(byte) RED +(const byte) RED#0 RED = (byte) 2 +(byte*) SCREEN +(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1 +(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5 +(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2 +(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6 +(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4 +(const byte) TYPEID_WORD TYPEID_WORD = (number) 3 +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(label) assertType::@1 +(label) assertType::@2 +(label) assertType::@3 +(label) assertType::@return +(byte) assertType::t1 +(byte) assertType::t1#35 reg byte y 1.0 +(byte) assertType::t2 +(byte) assertType::t2#35 t2 zp ZP_BYTE:2 2.0 +(byte) idx +(byte) idx#40 reg byte x 0.9999999999999993 +(byte) idx#79 reg byte x 14.400000000000007 +(void()) main() +(label) main::@1 +(label) main::@10 +(label) main::@11 +(label) main::@12 +(label) main::@13 +(label) main::@14 +(label) main::@15 +(label) main::@16 +(label) main::@17 +(label) main::@18 +(label) main::@19 +(label) main::@2 +(label) main::@20 +(label) main::@21 +(label) main::@22 +(label) main::@23 +(label) main::@24 +(label) main::@25 +(label) main::@26 +(label) main::@27 +(label) main::@28 +(label) main::@29 +(label) main::@3 +(label) main::@30 +(label) main::@31 +(label) main::@32 +(label) main::@33 +(label) main::@34 +(label) main::@4 +(label) main::@5 +(label) main::@6 +(label) main::@7 +(label) main::@8 +(label) main::@9 +(label) main::@return + +reg byte y [ assertType::t1#35 ] +zp ZP_BYTE:2 [ assertType::t2#35 ] +reg byte x [ idx#79 idx#40 ] + + +FINAL ASSEMBLER +Score: 506 + +//SEG0 File Comments +// Tests conversion of numbers to correct int types +// See https://gitlab.com/camelot/kickc/issues/181 +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const TYPEID_SIGNED_BYTE = 2 + .const TYPEID_SIGNED_WORD = 4 + .const TYPEID_SIGNED_DWORD = 6 + .const TYPEID_BYTE = 1 + .const TYPEID_WORD = 3 + .const TYPEID_DWORD = 5 + .const RED = 2 + .const GREEN = 5 +//SEG3 @begin +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +//SEG5 @1 +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +//SEG9 @end +//SEG10 main +main: { + //SEG11 [5] call assertType + //SEG12 [75] phi from main to assertType [phi:main->assertType] + //SEG13 [75] phi (byte) idx#79 = (byte) 0 [phi:main->assertType#0] -- vbuxx=vbuc1 + ldx #0 + //SEG14 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_BYTE + sta assertType.t2 + //SEG15 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG16 [6] phi from main to main::@1 [phi:main->main::@1] + //SEG17 main::@1 + //SEG18 [7] call assertType + //SEG19 [75] phi from main::@1 to assertType [phi:main::@1->assertType] + //SEG20 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@1->assertType#0] -- register_copy + //SEG21 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG22 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG23 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + //SEG24 main::@2 + //SEG25 [9] call assertType + //SEG26 [75] phi from main::@2 to assertType [phi:main::@2->assertType] + //SEG27 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@2->assertType#0] -- register_copy + //SEG28 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG29 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG30 [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + //SEG31 main::@3 + //SEG32 [11] call assertType + //SEG33 [75] phi from main::@3 to assertType [phi:main::@3->assertType] + //SEG34 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@3->assertType#0] -- register_copy + //SEG35 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG36 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG37 [12] phi from main::@3 to main::@4 [phi:main::@3->main::@4] + //SEG38 main::@4 + //SEG39 [13] call assertType + //SEG40 [75] phi from main::@4 to assertType [phi:main::@4->assertType] + //SEG41 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@4->assertType#0] -- register_copy + //SEG42 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_WORD + sta assertType.t2 + //SEG43 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG44 [14] phi from main::@4 to main::@5 [phi:main::@4->main::@5] + //SEG45 main::@5 + //SEG46 [15] call assertType + //SEG47 [75] phi from main::@5 to assertType [phi:main::@5->assertType] + //SEG48 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@5->assertType#0] -- register_copy + //SEG49 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG50 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG51 [16] phi from main::@5 to main::@6 [phi:main::@5->main::@6] + //SEG52 main::@6 + //SEG53 [17] call assertType + //SEG54 [75] phi from main::@6 to assertType [phi:main::@6->assertType] + //SEG55 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@6->assertType#0] -- register_copy + //SEG56 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG57 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG58 [18] phi from main::@6 to main::@7 [phi:main::@6->main::@7] + //SEG59 main::@7 + //SEG60 [19] call assertType + //SEG61 [75] phi from main::@7 to assertType [phi:main::@7->assertType] + //SEG62 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@7->assertType#0] -- register_copy + //SEG63 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG64 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG65 [20] phi from main::@7 to main::@8 [phi:main::@7->main::@8] + //SEG66 main::@8 + //SEG67 [21] call assertType + //SEG68 [75] phi from main::@8 to assertType [phi:main::@8->assertType] + //SEG69 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@8->assertType#0] -- register_copy + //SEG70 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_SIGNED_DWORD + sta assertType.t2 + //SEG71 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG72 [22] phi from main::@8 to main::@9 [phi:main::@8->main::@9] + //SEG73 main::@9 + //SEG74 [23] call assertType + //SEG75 [75] phi from main::@9 to assertType [phi:main::@9->assertType] + //SEG76 [75] phi (byte) idx#79 = (byte) $28 [phi:main::@9->assertType#0] -- vbuxx=vbuc1 + ldx #$28 + //SEG77 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG78 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG79 [24] phi from main::@9 to main::@10 [phi:main::@9->main::@10] + //SEG80 main::@10 + //SEG81 [25] call assertType + //SEG82 [75] phi from main::@10 to assertType [phi:main::@10->assertType] + //SEG83 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@10->assertType#0] -- register_copy + //SEG84 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG85 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG86 [26] phi from main::@10 to main::@11 [phi:main::@10->main::@11] + //SEG87 main::@11 + //SEG88 [27] call assertType + //SEG89 [75] phi from main::@11 to assertType [phi:main::@11->assertType] + //SEG90 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@11->assertType#0] -- register_copy + //SEG91 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG92 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG93 [28] phi from main::@11 to main::@12 [phi:main::@11->main::@12] + //SEG94 main::@12 + //SEG95 [29] call assertType + //SEG96 [75] phi from main::@12 to assertType [phi:main::@12->assertType] + //SEG97 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@12->assertType#0] -- register_copy + //SEG98 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG99 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG100 [30] phi from main::@12 to main::@13 [phi:main::@12->main::@13] + //SEG101 main::@13 + //SEG102 [31] call assertType + //SEG103 [75] phi from main::@13 to assertType [phi:main::@13->assertType] + //SEG104 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@13->assertType#0] -- register_copy + //SEG105 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG106 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG107 [32] phi from main::@13 to main::@14 [phi:main::@13->main::@14] + //SEG108 main::@14 + //SEG109 [33] call assertType + //SEG110 [75] phi from main::@14 to assertType [phi:main::@14->assertType] + //SEG111 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@14->assertType#0] -- register_copy + //SEG112 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG113 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG114 [34] phi from main::@14 to main::@15 [phi:main::@14->main::@15] + //SEG115 main::@15 + //SEG116 [35] call assertType + //SEG117 [75] phi from main::@15 to assertType [phi:main::@15->assertType] + //SEG118 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@15->assertType#0] -- register_copy + //SEG119 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG120 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG121 [36] phi from main::@15 to main::@16 [phi:main::@15->main::@16] + //SEG122 main::@16 + //SEG123 [37] call assertType + //SEG124 [75] phi from main::@16 to assertType [phi:main::@16->assertType] + //SEG125 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@16->assertType#0] -- register_copy + //SEG126 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG127 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG128 [38] phi from main::@16 to main::@17 [phi:main::@16->main::@17] + //SEG129 main::@17 + //SEG130 [39] call assertType + //SEG131 [75] phi from main::@17 to assertType [phi:main::@17->assertType] + //SEG132 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@17->assertType#0] -- register_copy + //SEG133 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG134 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG135 [40] phi from main::@17 to main::@18 [phi:main::@17->main::@18] + //SEG136 main::@18 + //SEG137 [41] call assertType + //SEG138 [75] phi from main::@18 to assertType [phi:main::@18->assertType] + //SEG139 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@18->assertType#0] -- register_copy + //SEG140 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG141 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG142 [42] phi from main::@18 to main::@19 [phi:main::@18->main::@19] + //SEG143 main::@19 + //SEG144 [43] call assertType + //SEG145 [75] phi from main::@19 to assertType [phi:main::@19->assertType] + //SEG146 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@19->assertType#0] -- register_copy + //SEG147 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG148 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG149 [44] phi from main::@19 to main::@20 [phi:main::@19->main::@20] + //SEG150 main::@20 + //SEG151 [45] call assertType + //SEG152 [75] phi from main::@20 to assertType [phi:main::@20->assertType] + //SEG153 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@20->assertType#0] -- register_copy + //SEG154 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG155 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG156 [46] phi from main::@20 to main::@21 [phi:main::@20->main::@21] + //SEG157 main::@21 + //SEG158 [47] call assertType + //SEG159 [75] phi from main::@21 to assertType [phi:main::@21->assertType] + //SEG160 [75] phi (byte) idx#79 = (byte) $50 [phi:main::@21->assertType#0] -- vbuxx=vbuc1 + ldx #$50 + //SEG161 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG162 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG163 [48] phi from main::@21 to main::@22 [phi:main::@21->main::@22] + //SEG164 main::@22 + //SEG165 [49] call assertType + //SEG166 [75] phi from main::@22 to assertType [phi:main::@22->assertType] + //SEG167 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@22->assertType#0] -- register_copy + //SEG168 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG169 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG170 [50] phi from main::@22 to main::@23 [phi:main::@22->main::@23] + //SEG171 main::@23 + //SEG172 [51] call assertType + //SEG173 [75] phi from main::@23 to assertType [phi:main::@23->assertType] + //SEG174 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@23->assertType#0] -- register_copy + //SEG175 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_BYTE + sta assertType.t2 + //SEG176 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG177 [52] phi from main::@23 to main::@24 [phi:main::@23->main::@24] + //SEG178 main::@24 + //SEG179 [53] call assertType + //SEG180 [75] phi from main::@24 to assertType [phi:main::@24->assertType] + //SEG181 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@24->assertType#0] -- register_copy + //SEG182 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG183 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG184 [54] phi from main::@24 to main::@25 [phi:main::@24->main::@25] + //SEG185 main::@25 + //SEG186 [55] call assertType + //SEG187 [75] phi from main::@25 to assertType [phi:main::@25->assertType] + //SEG188 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@25->assertType#0] -- register_copy + //SEG189 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG190 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG191 [56] phi from main::@25 to main::@26 [phi:main::@25->main::@26] + //SEG192 main::@26 + //SEG193 [57] call assertType + //SEG194 [75] phi from main::@26 to assertType [phi:main::@26->assertType] + //SEG195 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@26->assertType#0] -- register_copy + //SEG196 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG197 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG198 [58] phi from main::@26 to main::@27 [phi:main::@26->main::@27] + //SEG199 main::@27 + //SEG200 [59] call assertType + //SEG201 [75] phi from main::@27 to assertType [phi:main::@27->assertType] + //SEG202 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@27->assertType#0] -- register_copy + //SEG203 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG204 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG205 [60] phi from main::@27 to main::@28 [phi:main::@27->main::@28] + //SEG206 main::@28 + //SEG207 [61] call assertType + //SEG208 [75] phi from main::@28 to assertType [phi:main::@28->assertType] + //SEG209 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@28->assertType#0] -- register_copy + //SEG210 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG211 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG212 [62] phi from main::@28 to main::@29 [phi:main::@28->main::@29] + //SEG213 main::@29 + //SEG214 [63] call assertType + //SEG215 [75] phi from main::@29 to assertType [phi:main::@29->assertType] + //SEG216 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@29->assertType#0] -- register_copy + //SEG217 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_WORD + sta assertType.t2 + //SEG218 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG219 [64] phi from main::@29 to main::@30 [phi:main::@29->main::@30] + //SEG220 main::@30 + //SEG221 [65] call assertType + //SEG222 [75] phi from main::@30 to assertType [phi:main::@30->assertType] + //SEG223 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@30->assertType#0] -- register_copy + //SEG224 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG225 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG226 [66] phi from main::@30 to main::@31 [phi:main::@30->main::@31] + //SEG227 main::@31 + //SEG228 [67] call assertType + //SEG229 [75] phi from main::@31 to assertType [phi:main::@31->assertType] + //SEG230 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@31->assertType#0] -- register_copy + //SEG231 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG232 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG233 [68] phi from main::@31 to main::@32 [phi:main::@31->main::@32] + //SEG234 main::@32 + //SEG235 [69] call assertType + //SEG236 [75] phi from main::@32 to assertType [phi:main::@32->assertType] + //SEG237 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@32->assertType#0] -- register_copy + //SEG238 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG239 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG240 [70] phi from main::@32 to main::@33 [phi:main::@32->main::@33] + //SEG241 main::@33 + //SEG242 [71] call assertType + //SEG243 [75] phi from main::@33 to assertType [phi:main::@33->assertType] + //SEG244 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@33->assertType#0] -- register_copy + //SEG245 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG246 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#2] -- vbuyy=vbuc1 + tay + jsr assertType + //SEG247 [72] phi from main::@33 to main::@34 [phi:main::@33->main::@34] + //SEG248 main::@34 + //SEG249 [73] call assertType + //SEG250 [75] phi from main::@34 to assertType [phi:main::@34->assertType] + //SEG251 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@34->assertType#0] -- register_copy + //SEG252 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@34->assertType#1] -- vbuz1=vbuc1 + lda #TYPEID_DWORD + sta assertType.t2 + //SEG253 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@34->assertType#2] -- vbuyy=vbuc1 + ldy #TYPEID_SIGNED_DWORD + jsr assertType + //SEG254 main::@return + //SEG255 [74] return + rts +} +//SEG256 assertType +// Check that the two passed type IDs are equal. +// Shows a letter symbolizing t1 +// If they are equal the letter is green - if not it is red. +// assertType(byte register(Y) t1, byte zeropage(2) t2) +assertType: { + .label t2 = 2 + //SEG257 [76] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 + tya + cmp t2 + beq b1 + //SEG258 assertType::@3 + //SEG259 [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #RED + sta $d800,x + //SEG260 assertType::@2 + b2: + //SEG261 [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 -- pbuc1_derefidx_vbuxx=vbuyy + tya + sta $400,x + //SEG262 [79] (byte) idx#40 ← ++ (byte) idx#79 -- vbuxx=_inc_vbuxx + inx + //SEG263 assertType::@return + //SEG264 [80] return + rts + //SEG265 assertType::@1 + b1: + //SEG266 [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 + lda #GREEN + sta $d800,x + jmp b2 +} + diff --git a/src/test/ref/number-conversion.sym b/src/test/ref/number-conversion.sym new file mode 100644 index 000000000..78d7bc585 --- /dev/null +++ b/src/test/ref/number-conversion.sym @@ -0,0 +1,67 @@ +(label) @1 +(label) @begin +(label) @end +(byte*) COLS +(byte) GREEN +(const byte) GREEN#0 GREEN = (byte) 5 +(byte) RED +(const byte) RED#0 RED = (byte) 2 +(byte*) SCREEN +(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1 +(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5 +(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2 +(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6 +(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4 +(const byte) TYPEID_WORD TYPEID_WORD = (number) 3 +(void()) assertType((byte) assertType::t1 , (byte) assertType::t2) +(label) assertType::@1 +(label) assertType::@2 +(label) assertType::@3 +(label) assertType::@return +(byte) assertType::t1 +(byte) assertType::t1#35 reg byte y 1.0 +(byte) assertType::t2 +(byte) assertType::t2#35 t2 zp ZP_BYTE:2 2.0 +(byte) idx +(byte) idx#40 reg byte x 0.9999999999999993 +(byte) idx#79 reg byte x 14.400000000000007 +(void()) main() +(label) main::@1 +(label) main::@10 +(label) main::@11 +(label) main::@12 +(label) main::@13 +(label) main::@14 +(label) main::@15 +(label) main::@16 +(label) main::@17 +(label) main::@18 +(label) main::@19 +(label) main::@2 +(label) main::@20 +(label) main::@21 +(label) main::@22 +(label) main::@23 +(label) main::@24 +(label) main::@25 +(label) main::@26 +(label) main::@27 +(label) main::@28 +(label) main::@29 +(label) main::@3 +(label) main::@30 +(label) main::@31 +(label) main::@32 +(label) main::@33 +(label) main::@34 +(label) main::@4 +(label) main::@5 +(label) main::@6 +(label) main::@7 +(label) main::@8 +(label) main::@9 +(label) main::@return + +reg byte y [ assertType::t1#35 ] +zp ZP_BYTE:2 [ assertType::t2#35 ] +reg byte x [ idx#79 idx#40 ] diff --git a/src/test/ref/number-type.asm b/src/test/ref/number-type.asm new file mode 100644 index 000000000..8944e6dbf --- /dev/null +++ b/src/test/ref/number-type.asm @@ -0,0 +1,69 @@ +// Tests the number type used for constant expressions +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + jsr testBytes + jsr testSBytes + rts +} +testSBytes: { + // Constant values resolvable to signed bytes + .label SCREEN = $428 + lda #-$c + sta SCREEN + lda #-6-6 + sta SCREEN+1 + lda #-$12+6 + sta SCREEN+2 + lda #-$714+$708 + sta SCREEN+3 + lda #-1-2-3-6 + sta SCREEN+4 + lda #-2*6 + sta SCREEN+5 + lda #-3<<2 + sta SCREEN+6 + lda #-$18>>1 + sta SCREEN+7 + lda #-4&-9 + sta SCREEN+8 + lda #-$10|-$fc + sta SCREEN+9 + lda #(-2-2)*$f/5 + sta SCREEN+$a + lda #$ff&$1000-$c + sta SCREEN+$b + rts +} +testBytes: { + // Constant values resolvable to bytes + .label SCREEN = $400 + lda #$c + sta SCREEN + lda #6+6 + sta SCREEN+1 + lda #$12-6 + sta SCREEN+2 + lda #$714-$708 + sta SCREEN+3 + lda #1+2+3+6 + sta SCREEN+4 + lda #2*6 + sta SCREEN+5 + lda #3<<2 + sta SCREEN+6 + lda #$18>>1 + sta SCREEN+7 + lda #$f&$1c + sta SCREEN+8 + lda #4|8 + sta SCREEN+9 + lda #5^9 + sta SCREEN+$a + lda #(2+2)*$f/5 + sta SCREEN+$b + lda #$ff&$1000+$c + sta SCREEN+$c + rts +} diff --git a/src/test/ref/number-type.cfg b/src/test/ref/number-type.cfg new file mode 100644 index 000000000..11a77d0ae --- /dev/null +++ b/src/test/ref/number-type.cfg @@ -0,0 +1,55 @@ +@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 testBytes + to:main::@1 +main::@1: scope:[main] from main + [6] phi() + [7] call testSBytes + to:main::@return +main::@return: scope:[main] from main::@1 + [8] return + to:@return +testSBytes: scope:[testSBytes] from main::@1 + [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c + [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6 + [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6 + [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708 + [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6 + [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6 + [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2 + [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1 + [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9 + [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc + [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5 + [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c + to:testSBytes::@return +testSBytes::@return: scope:[testSBytes] from testSBytes + [21] return + to:@return +testBytes: scope:[testBytes] from main + [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c + [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6 + [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6 + [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708 + [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6 + [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6 + [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2 + [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1 + [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c + [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8 + [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9 + [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5 + [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c + to:testBytes::@return +testBytes::@return: scope:[testBytes] from testBytes + [35] return + to:@return diff --git a/src/test/ref/number-type.log b/src/test/ref/number-type.log new file mode 100644 index 000000000..55a8e6375 --- /dev/null +++ b/src/test/ref/number-type.log @@ -0,0 +1,1204 @@ +Adding pointer type conversion cast (byte*) testBytes::SCREEN in (byte*) testBytes::SCREEN ← (number) $400 +Adding pointer type conversion cast (signed byte*) testSBytes::SCREEN in (signed byte*) testSBytes::SCREEN ← (number) $428 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@3 +main: scope:[main] from @3 + call testBytes + to:main::@1 +main::@1: scope:[main] from main + call testSBytes + to:main::@2 +main::@2: scope:[main] from main::@1 + to:main::@return +main::@return: scope:[main] from main::@2 + return + to:@return +testBytes: scope:[testBytes] from main + (number) testBytes::$17 ← (number) $400 + (byte*) testBytes::SCREEN#0 ← ((byte*)) (number) testBytes::$17 + (byte) testBytes::idx#0 ← (number) 0 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#0) ← (number) $c + (byte) testBytes::idx#1 ← ++ (byte) testBytes::idx#0 + (number~) testBytes::$0 ← (number) 6 + (number) 6 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#1) ← (number~) testBytes::$0 + (byte) testBytes::idx#2 ← ++ (byte) testBytes::idx#1 + (number~) testBytes::$1 ← (number) $12 - (number) 6 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#2) ← (number~) testBytes::$1 + (byte) testBytes::idx#3 ← ++ (byte) testBytes::idx#2 + (number~) testBytes::$2 ← (number) $714 - (number) $708 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#3) ← (number~) testBytes::$2 + (byte) testBytes::idx#4 ← ++ (byte) testBytes::idx#3 + (number~) testBytes::$3 ← (number) 1 + (number) 2 + (number~) testBytes::$4 ← (number~) testBytes::$3 + (number) 3 + (number~) testBytes::$5 ← (number~) testBytes::$4 + (number) 6 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#4) ← (number~) testBytes::$5 + (byte) testBytes::idx#5 ← ++ (byte) testBytes::idx#4 + (number~) testBytes::$6 ← (number) 2 * (number) 6 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#5) ← (number~) testBytes::$6 + (byte) testBytes::idx#6 ← ++ (byte) testBytes::idx#5 + (number~) testBytes::$7 ← (number) 3 << (number) 2 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#6) ← (number~) testBytes::$7 + (byte) testBytes::idx#7 ← ++ (byte) testBytes::idx#6 + (number~) testBytes::$8 ← (number) $18 >> (number) 1 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#7) ← (number~) testBytes::$8 + (byte) testBytes::idx#8 ← ++ (byte) testBytes::idx#7 + (number~) testBytes::$9 ← (number) $f & (number) $1c + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#8) ← (number~) testBytes::$9 + (byte) testBytes::idx#9 ← ++ (byte) testBytes::idx#8 + (number~) testBytes::$10 ← (number) 4 | (number) 8 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#9) ← (number~) testBytes::$10 + (byte) testBytes::idx#10 ← ++ (byte) testBytes::idx#9 + (number~) testBytes::$11 ← (number) 5 ^ (number) 9 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#10) ← (number~) testBytes::$11 + (byte) testBytes::idx#11 ← ++ (byte) testBytes::idx#10 + (number~) testBytes::$12 ← (number) 2 + (number) 2 + (number~) testBytes::$13 ← (number) $f / (number) 5 + (number~) testBytes::$14 ← (number~) testBytes::$12 * (number~) testBytes::$13 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#11) ← (number~) testBytes::$14 + (byte) testBytes::idx#12 ← ++ (byte) testBytes::idx#11 + (number~) testBytes::$15 ← (number) $1000 + (number) $c + (byte~) testBytes::$16 ← ((byte)) (number~) testBytes::$15 + *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#12) ← (byte~) testBytes::$16 + (byte) testBytes::idx#13 ← ++ (byte) testBytes::idx#12 + to:testBytes::@return +testBytes::@return: scope:[testBytes] from testBytes + return + to:@return +testSBytes: scope:[testSBytes] from main::@1 + (number) testSBytes::$29 ← (number) $428 + (signed byte*) testSBytes::SCREEN#0 ← ((signed byte*)) (number) testSBytes::$29 + (byte) testSBytes::idx#0 ← (number) 0 + (number~) testSBytes::$0 ← - (number) $c + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#0) ← (number~) testSBytes::$0 + (byte) testSBytes::idx#1 ← ++ (byte) testSBytes::idx#0 + (number~) testSBytes::$1 ← - (number) 6 + (number~) testSBytes::$2 ← (number~) testSBytes::$1 - (number) 6 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#1) ← (number~) testSBytes::$2 + (byte) testSBytes::idx#2 ← ++ (byte) testSBytes::idx#1 + (number~) testSBytes::$3 ← - (number) $12 + (number~) testSBytes::$4 ← (number~) testSBytes::$3 + (number) 6 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#2) ← (number~) testSBytes::$4 + (byte) testSBytes::idx#3 ← ++ (byte) testSBytes::idx#2 + (number~) testSBytes::$5 ← - (number) $714 + (number~) testSBytes::$6 ← (number~) testSBytes::$5 + (number) $708 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#3) ← (number~) testSBytes::$6 + (byte) testSBytes::idx#4 ← ++ (byte) testSBytes::idx#3 + (number~) testSBytes::$7 ← - (number) 1 + (number~) testSBytes::$8 ← (number~) testSBytes::$7 - (number) 2 + (number~) testSBytes::$9 ← (number~) testSBytes::$8 - (number) 3 + (number~) testSBytes::$10 ← (number~) testSBytes::$9 - (number) 6 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#4) ← (number~) testSBytes::$10 + (byte) testSBytes::idx#5 ← ++ (byte) testSBytes::idx#4 + (number~) testSBytes::$11 ← - (number) 2 + (number~) testSBytes::$12 ← (number~) testSBytes::$11 * (number) 6 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#5) ← (number~) testSBytes::$12 + (byte) testSBytes::idx#6 ← ++ (byte) testSBytes::idx#5 + (number~) testSBytes::$13 ← - (number) 3 + (number~) testSBytes::$14 ← (number~) testSBytes::$13 << (number) 2 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#6) ← (number~) testSBytes::$14 + (byte) testSBytes::idx#7 ← ++ (byte) testSBytes::idx#6 + (number~) testSBytes::$15 ← - (number) $18 + (number~) testSBytes::$16 ← (number~) testSBytes::$15 >> (number) 1 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#7) ← (number~) testSBytes::$16 + (byte) testSBytes::idx#8 ← ++ (byte) testSBytes::idx#7 + (number~) testSBytes::$17 ← - (number) 4 + (number~) testSBytes::$18 ← - (number) 9 + (number~) testSBytes::$19 ← (number~) testSBytes::$17 & (number~) testSBytes::$18 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#8) ← (number~) testSBytes::$19 + (byte) testSBytes::idx#9 ← ++ (byte) testSBytes::idx#8 + (number~) testSBytes::$20 ← - (number) $10 + (number~) testSBytes::$21 ← - (number) $fc + (number~) testSBytes::$22 ← (number~) testSBytes::$20 | (number~) testSBytes::$21 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#9) ← (number~) testSBytes::$22 + (byte) testSBytes::idx#10 ← ++ (byte) testSBytes::idx#9 + (number~) testSBytes::$23 ← - (number) 2 + (number~) testSBytes::$24 ← (number~) testSBytes::$23 - (number) 2 + (number~) testSBytes::$25 ← (number) $f / (number) 5 + (number~) testSBytes::$26 ← (number~) testSBytes::$24 * (number~) testSBytes::$25 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#10) ← (number~) testSBytes::$26 + (byte) testSBytes::idx#11 ← ++ (byte) testSBytes::idx#10 + (number~) testSBytes::$27 ← (number) $1000 - (number) $c + (signed byte~) testSBytes::$28 ← ((signed byte)) (number~) testSBytes::$27 + *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#11) ← (signed byte~) testSBytes::$28 + (byte) testSBytes::idx#12 ← ++ (byte) testSBytes::idx#11 + to:testSBytes::@return +testSBytes::@return: scope:[testSBytes] from testSBytes + 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::@2 +(label) main::@return +(void()) testBytes() +(number~) testBytes::$0 +(number~) testBytes::$1 +(number~) testBytes::$10 +(number~) testBytes::$11 +(number~) testBytes::$12 +(number~) testBytes::$13 +(number~) testBytes::$14 +(number~) testBytes::$15 +(byte~) testBytes::$16 +(number) testBytes::$17 +(number~) testBytes::$2 +(number~) testBytes::$3 +(number~) testBytes::$4 +(number~) testBytes::$5 +(number~) testBytes::$6 +(number~) testBytes::$7 +(number~) testBytes::$8 +(number~) testBytes::$9 +(label) testBytes::@return +(byte*) testBytes::SCREEN +(byte*) testBytes::SCREEN#0 +(byte) testBytes::idx +(byte) testBytes::idx#0 +(byte) testBytes::idx#1 +(byte) testBytes::idx#10 +(byte) testBytes::idx#11 +(byte) testBytes::idx#12 +(byte) testBytes::idx#13 +(byte) testBytes::idx#2 +(byte) testBytes::idx#3 +(byte) testBytes::idx#4 +(byte) testBytes::idx#5 +(byte) testBytes::idx#6 +(byte) testBytes::idx#7 +(byte) testBytes::idx#8 +(byte) testBytes::idx#9 +(void()) testSBytes() +(number~) testSBytes::$0 +(number~) testSBytes::$1 +(number~) testSBytes::$10 +(number~) testSBytes::$11 +(number~) testSBytes::$12 +(number~) testSBytes::$13 +(number~) testSBytes::$14 +(number~) testSBytes::$15 +(number~) testSBytes::$16 +(number~) testSBytes::$17 +(number~) testSBytes::$18 +(number~) testSBytes::$19 +(number~) testSBytes::$2 +(number~) testSBytes::$20 +(number~) testSBytes::$21 +(number~) testSBytes::$22 +(number~) testSBytes::$23 +(number~) testSBytes::$24 +(number~) testSBytes::$25 +(number~) testSBytes::$26 +(number~) testSBytes::$27 +(signed byte~) testSBytes::$28 +(number) testSBytes::$29 +(number~) testSBytes::$3 +(number~) testSBytes::$4 +(number~) testSBytes::$5 +(number~) testSBytes::$6 +(number~) testSBytes::$7 +(number~) testSBytes::$8 +(number~) testSBytes::$9 +(label) testSBytes::@return +(signed byte*) testSBytes::SCREEN +(signed byte*) testSBytes::SCREEN#0 +(byte) testSBytes::idx +(byte) testSBytes::idx#0 +(byte) testSBytes::idx#1 +(byte) testSBytes::idx#10 +(byte) testSBytes::idx#11 +(byte) testSBytes::idx#12 +(byte) testSBytes::idx#2 +(byte) testSBytes::idx#3 +(byte) testSBytes::idx#4 +(byte) testSBytes::idx#5 +(byte) testSBytes::idx#6 +(byte) testSBytes::idx#7 +(byte) testSBytes::idx#8 +(byte) testSBytes::idx#9 + +Adding number conversion cast (byte) 0 in (byte) testBytes::idx#0 ← (number) 0 +Adding number conversion cast (byte) $c in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#0) ← (number) $c +Adding number conversion cast (byte) 0 in (byte) testSBytes::idx#0 ← (number) 0 +Culled Empty Block (label) main::@2 +Culled Empty Block (label) @4 +Successful SSA optimization Pass2CullEmptyBlocks +Constant right-side identified [5] (byte) testBytes::idx#0 ← ((byte)) (number) 0 +Constant right-side identified [6] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#0) ← ((byte)) (number) $c +Constant right-side identified [8] (number~) testBytes::$0 ← (number) 6 + (number) 6 +Constant right-side identified [11] (number~) testBytes::$1 ← (number) $12 - (number) 6 +Constant right-side identified [14] (number~) testBytes::$2 ← (number) $714 - (number) $708 +Constant right-side identified [17] (number~) testBytes::$3 ← (number) 1 + (number) 2 +Constant right-side identified [22] (number~) testBytes::$6 ← (number) 2 * (number) 6 +Constant right-side identified [25] (number~) testBytes::$7 ← (number) 3 << (number) 2 +Constant right-side identified [28] (number~) testBytes::$8 ← (number) $18 >> (number) 1 +Constant right-side identified [31] (number~) testBytes::$9 ← (number) $f & (number) $1c +Constant right-side identified [34] (number~) testBytes::$10 ← (number) 4 | (number) 8 +Constant right-side identified [37] (number~) testBytes::$11 ← (number) 5 ^ (number) 9 +Constant right-side identified [40] (number~) testBytes::$12 ← (number) 2 + (number) 2 +Constant right-side identified [41] (number~) testBytes::$13 ← (number) $f / (number) 5 +Constant right-side identified [45] (number~) testBytes::$15 ← (number) $1000 + (number) $c +Constant right-side identified [52] (byte) testSBytes::idx#0 ← ((byte)) (number) 0 +Constant right-side identified [53] (number~) testSBytes::$0 ← - (number) $c +Constant right-side identified [56] (number~) testSBytes::$1 ← - (number) 6 +Constant right-side identified [60] (number~) testSBytes::$3 ← - (number) $12 +Constant right-side identified [64] (number~) testSBytes::$5 ← - (number) $714 +Constant right-side identified [68] (number~) testSBytes::$7 ← - (number) 1 +Constant right-side identified [74] (number~) testSBytes::$11 ← - (number) 2 +Constant right-side identified [78] (number~) testSBytes::$13 ← - (number) 3 +Constant right-side identified [82] (number~) testSBytes::$15 ← - (number) $18 +Constant right-side identified [86] (number~) testSBytes::$17 ← - (number) 4 +Constant right-side identified [87] (number~) testSBytes::$18 ← - (number) 9 +Constant right-side identified [91] (number~) testSBytes::$20 ← - (number) $10 +Constant right-side identified [92] (number~) testSBytes::$21 ← - (number) $fc +Constant right-side identified [96] (number~) testSBytes::$23 ← - (number) 2 +Constant right-side identified [98] (number~) testSBytes::$25 ← (number) $f / (number) 5 +Constant right-side identified [102] (number~) testSBytes::$27 ← (number) $1000 - (number) $c +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const number) testBytes::$17 = $400 +Constant (const byte) testBytes::idx#0 = ((byte))0 +Constant (const number) testBytes::$0 = 6+6 +Constant (const number) testBytes::$1 = $12-6 +Constant (const number) testBytes::$2 = $714-$708 +Constant (const number) testBytes::$3 = 1+2 +Constant (const number) testBytes::$6 = 2*6 +Constant (const number) testBytes::$7 = 3<<2 +Constant (const number) testBytes::$8 = $18>>1 +Constant (const number) testBytes::$9 = $f&$1c +Constant (const number) testBytes::$10 = 4|8 +Constant (const number) testBytes::$11 = 5^9 +Constant (const number) testBytes::$12 = 2+2 +Constant (const number) testBytes::$13 = $f/5 +Constant (const number) testBytes::$15 = $1000+$c +Constant (const number) testSBytes::$29 = $428 +Constant (const byte) testSBytes::idx#0 = ((byte))0 +Constant (const number) testSBytes::$0 = -$c +Constant (const number) testSBytes::$1 = -6 +Constant (const number) testSBytes::$3 = -$12 +Constant (const number) testSBytes::$5 = -$714 +Constant (const number) testSBytes::$7 = -1 +Constant (const number) testSBytes::$11 = -2 +Constant (const number) testSBytes::$13 = -3 +Constant (const number) testSBytes::$15 = -$18 +Constant (const number) testSBytes::$17 = -4 +Constant (const number) testSBytes::$18 = -9 +Constant (const number) testSBytes::$20 = -$10 +Constant (const number) testSBytes::$21 = -$fc +Constant (const number) testSBytes::$23 = -2 +Constant (const number) testSBytes::$25 = $f/5 +Constant (const number) testSBytes::$27 = $1000-$c +Successful SSA optimization Pass2ConstantIdentification +Eliminating unused variable (byte) testBytes::idx#13 and assignment [33] (byte) testBytes::idx#13 ← ++ (byte) testBytes::idx#12 +Eliminating unused variable (byte) testSBytes::idx#12 and assignment [73] (byte) testSBytes::idx#12 ← ++ (byte) testSBytes::idx#11 +Successful SSA optimization PassNEliminateUnusedVars +Simplifying constant integer cast $c +Adding number conversion cast (byte) testBytes::$0 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#1) ← (const number) testBytes::$0 +Adding number conversion cast (byte) testBytes::$1 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#2) ← (const number) testBytes::$1 +Adding number conversion cast (byte) testBytes::$2 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#3) ← (const number) testBytes::$2 +Adding number conversion cast (byte) testBytes::$6 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#5) ← (const number) testBytes::$6 +Adding number conversion cast (byte) testBytes::$7 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#6) ← (const number) testBytes::$7 +Adding number conversion cast (byte) testBytes::$8 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#7) ← (const number) testBytes::$8 +Adding number conversion cast (byte) testBytes::$9 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#8) ← (const number) testBytes::$9 +Adding number conversion cast (byte) testBytes::$10 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#9) ← (const number) testBytes::$10 +Adding number conversion cast (byte) testBytes::$11 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#10) ← (const number) testBytes::$11 +Adding number conversion cast (signed byte) testSBytes::$0 in *((signed byte*) testSBytes::SCREEN#0 + (const byte) testSBytes::idx#0) ← (const number) testSBytes::$0 +Constant right-side identified [3] (byte*) testBytes::SCREEN#0 ← ((byte*)) (const number) testBytes::$17 +Constant right-side identified [5] (byte) testBytes::idx#1 ← ++ (const byte) testBytes::idx#0 +Constant right-side identified [6] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#1) ← ((byte)) (const number) testBytes::$0 +Constant right-side identified [8] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#2) ← ((byte)) (const number) testBytes::$1 +Constant right-side identified [10] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#3) ← ((byte)) (const number) testBytes::$2 +Constant right-side identified [12] (number~) testBytes::$4 ← (const number) testBytes::$3 + (number) 3 +Constant right-side identified [16] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#5) ← ((byte)) (const number) testBytes::$6 +Constant right-side identified [18] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#6) ← ((byte)) (const number) testBytes::$7 +Constant right-side identified [20] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#7) ← ((byte)) (const number) testBytes::$8 +Constant right-side identified [22] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#8) ← ((byte)) (const number) testBytes::$9 +Constant right-side identified [24] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#9) ← ((byte)) (const number) testBytes::$10 +Constant right-side identified [26] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#10) ← ((byte)) (const number) testBytes::$11 +Constant right-side identified [28] (number~) testBytes::$14 ← (const number) testBytes::$12 * (const number) testBytes::$13 +Constant right-side identified [31] (byte~) testBytes::$16 ← ((byte)) (const number) testBytes::$15 +Constant right-side identified [34] (signed byte*) testSBytes::SCREEN#0 ← ((signed byte*)) (const number) testSBytes::$29 +Constant right-side identified [35] *((signed byte*) testSBytes::SCREEN#0 + (const byte) testSBytes::idx#0) ← ((signed byte)) (const number) testSBytes::$0 +Constant right-side identified [36] (byte) testSBytes::idx#1 ← ++ (const byte) testSBytes::idx#0 +Constant right-side identified [37] (number~) testSBytes::$2 ← (const number) testSBytes::$1 - (number) 6 +Constant right-side identified [40] (number~) testSBytes::$4 ← (const number) testSBytes::$3 + (number) 6 +Constant right-side identified [43] (number~) testSBytes::$6 ← (const number) testSBytes::$5 + (number) $708 +Constant right-side identified [46] (number~) testSBytes::$8 ← (const number) testSBytes::$7 - (number) 2 +Constant right-side identified [51] (number~) testSBytes::$12 ← (const number) testSBytes::$11 * (number) 6 +Constant right-side identified [54] (number~) testSBytes::$14 ← (const number) testSBytes::$13 << (number) 2 +Constant right-side identified [57] (number~) testSBytes::$16 ← (const number) testSBytes::$15 >> (number) 1 +Constant right-side identified [60] (number~) testSBytes::$19 ← (const number) testSBytes::$17 & (const number) testSBytes::$18 +Constant right-side identified [63] (number~) testSBytes::$22 ← (const number) testSBytes::$20 | (const number) testSBytes::$21 +Constant right-side identified [66] (number~) testSBytes::$24 ← (const number) testSBytes::$23 - (number) 2 +Constant right-side identified [70] (signed byte~) testSBytes::$28 ← ((signed byte)) (const number) testSBytes::$27 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte*) testBytes::SCREEN#0 = ((byte*))testBytes::$17 +Constant (const byte) testBytes::idx#1 = ++testBytes::idx#0 +Constant (const number) testBytes::$4 = testBytes::$3+3 +Constant (const number) testBytes::$14 = testBytes::$12*testBytes::$13 +Constant (const byte) testBytes::$16 = ((byte))testBytes::$15 +Constant (const signed byte*) testSBytes::SCREEN#0 = ((signed byte*))testSBytes::$29 +Constant (const byte) testSBytes::idx#1 = ++testSBytes::idx#0 +Constant (const number) testSBytes::$2 = testSBytes::$1-6 +Constant (const number) testSBytes::$4 = testSBytes::$3+6 +Constant (const number) testSBytes::$6 = testSBytes::$5+$708 +Constant (const number) testSBytes::$8 = testSBytes::$7-2 +Constant (const number) testSBytes::$12 = testSBytes::$11*6 +Constant (const number) testSBytes::$14 = testSBytes::$13<<2 +Constant (const number) testSBytes::$16 = testSBytes::$15>>1 +Constant (const number) testSBytes::$19 = testSBytes::$17&testSBytes::$18 +Constant (const number) testSBytes::$22 = testSBytes::$20|testSBytes::$21 +Constant (const number) testSBytes::$24 = testSBytes::$23-2 +Constant (const signed byte) testSBytes::$28 = ((signed byte))testSBytes::$27 +Successful SSA optimization Pass2ConstantIdentification +Adding number conversion cast (byte) testBytes::$14 in *((const byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#11) ← (const number) testBytes::$14 +Adding number conversion cast (signed byte) testSBytes::$2 in *((const signed byte*) testSBytes::SCREEN#0 + (const byte) testSBytes::idx#1) ← (const number) testSBytes::$2 +Adding number conversion cast (signed byte) testSBytes::$4 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#2) ← (const number) testSBytes::$4 +Adding number conversion cast (signed byte) testSBytes::$6 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#3) ← (const number) testSBytes::$6 +Adding number conversion cast (signed byte) testSBytes::$12 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#5) ← (const number) testSBytes::$12 +Adding number conversion cast (signed byte) testSBytes::$14 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#6) ← (const number) testSBytes::$14 +Adding number conversion cast (signed byte) testSBytes::$16 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#7) ← (const number) testSBytes::$16 +Adding number conversion cast (signed byte) testSBytes::$19 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#8) ← (const number) testSBytes::$19 +Adding number conversion cast (signed byte) testSBytes::$22 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#9) ← (const number) testSBytes::$22 +Constant right-side identified [5] (byte) testBytes::idx#2 ← ++ (const byte) testBytes::idx#1 +Constant right-side identified [10] (number~) testBytes::$5 ← (const number) testBytes::$4 + (number) 6 +Constant right-side identified [25] *((const byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#11) ← ((byte)) (const number) testBytes::$14 +Constant right-side identified [30] *((const signed byte*) testSBytes::SCREEN#0 + (const byte) testSBytes::idx#1) ← ((signed byte)) (const number) testSBytes::$2 +Constant right-side identified [31] (byte) testSBytes::idx#2 ← ++ (const byte) testSBytes::idx#1 +Constant right-side identified [32] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#2) ← ((signed byte)) (const number) testSBytes::$4 +Constant right-side identified [34] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#3) ← ((signed byte)) (const number) testSBytes::$6 +Constant right-side identified [36] (number~) testSBytes::$9 ← (const number) testSBytes::$8 - (number) 3 +Constant right-side identified [40] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#5) ← ((signed byte)) (const number) testSBytes::$12 +Constant right-side identified [42] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#6) ← ((signed byte)) (const number) testSBytes::$14 +Constant right-side identified [44] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#7) ← ((signed byte)) (const number) testSBytes::$16 +Constant right-side identified [46] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#8) ← ((signed byte)) (const number) testSBytes::$19 +Constant right-side identified [48] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#9) ← ((signed byte)) (const number) testSBytes::$22 +Constant right-side identified [50] (number~) testSBytes::$26 ← (const number) testSBytes::$24 * (const number) testSBytes::$25 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#2 = ++testBytes::idx#1 +Constant (const number) testBytes::$5 = testBytes::$4+6 +Constant (const byte) testSBytes::idx#2 = ++testSBytes::idx#1 +Constant (const number) testSBytes::$9 = testSBytes::$8-3 +Constant (const number) testSBytes::$26 = testSBytes::$24*testSBytes::$25 +Successful SSA optimization Pass2ConstantIdentification +Adding number conversion cast (byte) testBytes::$5 in *((const byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#4) ← (const number) testBytes::$5 +Adding number conversion cast (signed byte) testSBytes::$26 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#10) ← (const number) testSBytes::$26 +Constant right-side identified [6] (byte) testBytes::idx#3 ← ++ (const byte) testBytes::idx#2 +Constant right-side identified [9] *((const byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#4) ← ((byte)) (const number) testBytes::$5 +Constant right-side identified [30] (byte) testSBytes::idx#3 ← ++ (const byte) testSBytes::idx#2 +Constant right-side identified [33] (number~) testSBytes::$10 ← (const number) testSBytes::$9 - (number) 6 +Constant right-side identified [46] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#10) ← ((signed byte)) (const number) testSBytes::$26 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#3 = ++testBytes::idx#2 +Constant (const byte) testSBytes::idx#3 = ++testSBytes::idx#2 +Constant (const number) testSBytes::$10 = testSBytes::$9-6 +Successful SSA optimization Pass2ConstantIdentification +Adding number conversion cast (signed byte) testSBytes::$10 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#4) ← (const number) testSBytes::$10 +Constant right-side identified [7] (byte) testBytes::idx#4 ← ++ (const byte) testBytes::idx#3 +Constant right-side identified [30] (byte) testSBytes::idx#4 ← ++ (const byte) testSBytes::idx#3 +Constant right-side identified [31] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#4) ← ((signed byte)) (const number) testSBytes::$10 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#4 = ++testBytes::idx#3 +Constant (const byte) testSBytes::idx#4 = ++testSBytes::idx#3 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [8] (byte) testBytes::idx#5 ← ++ (const byte) testBytes::idx#4 +Constant right-side identified [30] (byte) testSBytes::idx#5 ← ++ (const byte) testSBytes::idx#4 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#5 = ++testBytes::idx#4 +Constant (const byte) testSBytes::idx#5 = ++testSBytes::idx#4 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [9] (byte) testBytes::idx#6 ← ++ (const byte) testBytes::idx#5 +Constant right-side identified [30] (byte) testSBytes::idx#6 ← ++ (const byte) testSBytes::idx#5 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#6 = ++testBytes::idx#5 +Constant (const byte) testSBytes::idx#6 = ++testSBytes::idx#5 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [10] (byte) testBytes::idx#7 ← ++ (const byte) testBytes::idx#6 +Constant right-side identified [30] (byte) testSBytes::idx#7 ← ++ (const byte) testSBytes::idx#6 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#7 = ++testBytes::idx#6 +Constant (const byte) testSBytes::idx#7 = ++testSBytes::idx#6 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [11] (byte) testBytes::idx#8 ← ++ (const byte) testBytes::idx#7 +Constant right-side identified [30] (byte) testSBytes::idx#8 ← ++ (const byte) testSBytes::idx#7 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#8 = ++testBytes::idx#7 +Constant (const byte) testSBytes::idx#8 = ++testSBytes::idx#7 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [12] (byte) testBytes::idx#9 ← ++ (const byte) testBytes::idx#8 +Constant right-side identified [30] (byte) testSBytes::idx#9 ← ++ (const byte) testSBytes::idx#8 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#9 = ++testBytes::idx#8 +Constant (const byte) testSBytes::idx#9 = ++testSBytes::idx#8 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [13] (byte) testBytes::idx#10 ← ++ (const byte) testBytes::idx#9 +Constant right-side identified [30] (byte) testSBytes::idx#10 ← ++ (const byte) testSBytes::idx#9 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#10 = ++testBytes::idx#9 +Constant (const byte) testSBytes::idx#10 = ++testSBytes::idx#9 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [14] (byte) testBytes::idx#11 ← ++ (const byte) testBytes::idx#10 +Constant right-side identified [30] (byte) testSBytes::idx#11 ← ++ (const byte) testSBytes::idx#10 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#11 = ++testBytes::idx#10 +Constant (const byte) testSBytes::idx#11 = ++testSBytes::idx#10 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [15] (byte) testBytes::idx#12 ← ++ (const byte) testBytes::idx#11 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) testBytes::idx#12 = ++testBytes::idx#11 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with different constant siblings (const byte) testBytes::idx#0 +Inlining constant with different constant siblings (const byte) testBytes::idx#1 +Inlining constant with different constant siblings (const byte) testBytes::idx#2 +Inlining constant with different constant siblings (const byte) testBytes::idx#3 +Inlining constant with different constant siblings (const byte) testBytes::idx#4 +Inlining constant with different constant siblings (const byte) testBytes::idx#5 +Inlining constant with different constant siblings (const byte) testBytes::idx#6 +Inlining constant with different constant siblings (const byte) testBytes::idx#7 +Inlining constant with different constant siblings (const byte) testBytes::idx#8 +Inlining constant with different constant siblings (const byte) testBytes::idx#9 +Inlining constant with different constant siblings (const byte) testBytes::idx#10 +Inlining constant with different constant siblings (const byte) testBytes::idx#11 +Inlining constant with different constant siblings (const byte) testBytes::idx#12 +Inlining constant with different constant siblings (const byte) testSBytes::idx#0 +Inlining constant with different constant siblings (const byte) testSBytes::idx#1 +Inlining constant with different constant siblings (const byte) testSBytes::idx#2 +Inlining constant with different constant siblings (const byte) testSBytes::idx#3 +Inlining constant with different constant siblings (const byte) testSBytes::idx#4 +Inlining constant with different constant siblings (const byte) testSBytes::idx#5 +Inlining constant with different constant siblings (const byte) testSBytes::idx#6 +Inlining constant with different constant siblings (const byte) testSBytes::idx#7 +Inlining constant with different constant siblings (const byte) testSBytes::idx#8 +Inlining constant with different constant siblings (const byte) testSBytes::idx#9 +Inlining constant with different constant siblings (const byte) testSBytes::idx#10 +Inlining constant with different constant siblings (const byte) testSBytes::idx#11 +Constant inlined testBytes::idx#5 = ++++++++++((byte))(number) 0 +Constant inlined testBytes::idx#6 = ++++++++++++((byte))(number) 0 +Constant inlined testBytes::idx#3 = ++++++((byte))(number) 0 +Constant inlined testBytes::idx#4 = ++++++++((byte))(number) 0 +Constant inlined testBytes::idx#1 = ++((byte))(number) 0 +Constant inlined testBytes::idx#2 = ++++((byte))(number) 0 +Constant inlined testBytes::idx#0 = ((byte))(number) 0 +Constant inlined testBytes::idx#9 = ++++++++++++++++++((byte))(number) 0 +Constant inlined testBytes::idx#7 = ++++++++++++++((byte))(number) 0 +Constant inlined testBytes::idx#8 = ++++++++++++++++((byte))(number) 0 +Constant inlined testSBytes::$28 = ((signed byte))(number) $1000-(number) $c +Constant inlined testSBytes::$29 = (number) $428 +Constant inlined testSBytes::$7 = -(number) 1 +Constant inlined testSBytes::$6 = -(number) $714+(number) $708 +Constant inlined testSBytes::$9 = -(number) 1-(number) 2-(number) 3 +Constant inlined testSBytes::$8 = -(number) 1-(number) 2 +Constant inlined testSBytes::$3 = -(number) $12 +Constant inlined testSBytes::$2 = -(number) 6-(number) 6 +Constant inlined testSBytes::$5 = -(number) $714 +Constant inlined testSBytes::$4 = -(number) $12+(number) 6 +Constant inlined testSBytes::$1 = -(number) 6 +Constant inlined testSBytes::$0 = -(number) $c +Constant inlined testSBytes::$13 = -(number) 3 +Constant inlined testSBytes::$14 = -(number) 3<<(number) 2 +Constant inlined testSBytes::$15 = -(number) $18 +Constant inlined testSBytes::$16 = -(number) $18>>(number) 1 +Constant inlined testSBytes::$10 = -(number) 1-(number) 2-(number) 3-(number) 6 +Constant inlined testSBytes::$11 = -(number) 2 +Constant inlined testSBytes::$12 = -(number) 2*(number) 6 +Constant inlined testBytes::idx#12 = ++++++++++++++++++++++++((byte))(number) 0 +Constant inlined testBytes::$2 = (number) $714-(number) $708 +Constant inlined testBytes::$14 = (number) 2+(number) 2*(number) $f/(number) 5 +Constant inlined testSBytes::$24 = -(number) 2-(number) 2 +Constant inlined testBytes::idx#11 = ++++++++++++++++++++++((byte))(number) 0 +Constant inlined testBytes::$1 = (number) $12-(number) 6 +Constant inlined testBytes::$15 = (number) $1000+(number) $c +Constant inlined testSBytes::$25 = (number) $f/(number) 5 +Constant inlined testBytes::idx#10 = ++++++++++++++++++++((byte))(number) 0 +Constant inlined testBytes::$0 = (number) 6+(number) 6 +Constant inlined testBytes::$12 = (number) 2+(number) 2 +Constant inlined testSBytes::$26 = -(number) 2-(number) 2*(number) $f/(number) 5 +Constant inlined testBytes::$13 = (number) $f/(number) 5 +Constant inlined testSBytes::$27 = (number) $1000-(number) $c +Constant inlined testBytes::$10 = (number) 4|(number) 8 +Constant inlined testSBytes::$20 = -(number) $10 +Constant inlined testBytes::$11 = (number) 5^(number) 9 +Constant inlined testSBytes::$21 = -(number) $fc +Constant inlined testSBytes::$22 = -(number) $10|-(number) $fc +Constant inlined testSBytes::$23 = -(number) 2 +Constant inlined testBytes::$9 = (number) $f&(number) $1c +Constant inlined testBytes::$8 = (number) $18>>(number) 1 +Constant inlined testBytes::$7 = (number) 3<<(number) 2 +Constant inlined testSBytes::idx#10 = ++++++++++++++++++++((byte))(number) 0 +Constant inlined testBytes::$6 = (number) 2*(number) 6 +Constant inlined testBytes::$5 = (number) 1+(number) 2+(number) 3+(number) 6 +Constant inlined testBytes::$4 = (number) 1+(number) 2+(number) 3 +Constant inlined testBytes::$3 = (number) 1+(number) 2 +Constant inlined testSBytes::idx#9 = ++++++++++++++++++((byte))(number) 0 +Constant inlined testSBytes::idx#11 = ++++++++++++++++++++++((byte))(number) 0 +Constant inlined testSBytes::idx#8 = ++++++++++++++++((byte))(number) 0 +Constant inlined testSBytes::idx#5 = ++++++++++((byte))(number) 0 +Constant inlined testSBytes::idx#4 = ++++++++((byte))(number) 0 +Constant inlined testSBytes::idx#7 = ++++++++++++++((byte))(number) 0 +Constant inlined testSBytes::idx#6 = ++++++++++++((byte))(number) 0 +Constant inlined testSBytes::$17 = -(number) 4 +Constant inlined testSBytes::idx#1 = ++((byte))(number) 0 +Constant inlined testSBytes::$18 = -(number) 9 +Constant inlined testSBytes::idx#0 = ((byte))(number) 0 +Constant inlined testBytes::$16 = ((byte))(number) $1000+(number) $c +Constant inlined testSBytes::$19 = -(number) 4&-(number) 9 +Constant inlined testSBytes::idx#3 = ++++++((byte))(number) 0 +Constant inlined testBytes::$17 = (number) $400 +Constant inlined testSBytes::idx#2 = ++++((byte))(number) 0 +Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(testBytes::SCREEN#0+((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++++++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++++++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++++++++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++++++++++((byte))0) +Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++++++++++++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++++++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++++++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++++++++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++++++++++((byte))0) +Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++++++++++++((byte))0) +Successful SSA optimization Pass2ConstantAdditionElimination +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant plus zero testBytes::SCREEN#0+0 +Simplifying constant integer increment ++0 +Simplifying constant integer increment ++0 +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++2 +Simplifying constant integer increment ++3 +Simplifying constant integer increment ++4 +Simplifying constant integer increment ++5 +Simplifying constant integer increment ++6 +Simplifying constant integer increment ++7 +Simplifying constant integer increment ++8 +Simplifying constant integer increment ++9 +Simplifying constant integer increment ++$a +Simplifying constant plus zero testSBytes::SCREEN#0+0 +Simplifying constant integer increment ++0 +Simplifying constant integer increment ++0 +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++2 +Simplifying constant integer increment ++3 +Simplifying constant integer increment ++4 +Simplifying constant integer increment ++5 +Simplifying constant integer increment ++6 +Simplifying constant integer increment ++7 +Simplifying constant integer increment ++8 +Simplifying constant integer increment ++9 +Successful SSA optimization Pass2ConstantSimplification +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++2 +Simplifying constant integer increment ++3 +Simplifying constant integer increment ++4 +Simplifying constant integer increment ++5 +Simplifying constant integer increment ++6 +Simplifying constant integer increment ++7 +Simplifying constant integer increment ++8 +Simplifying constant integer increment ++9 +Simplifying constant integer increment ++$a +Simplifying constant integer increment ++$b +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++2 +Simplifying constant integer increment ++3 +Simplifying constant integer increment ++4 +Simplifying constant integer increment ++5 +Simplifying constant integer increment ++6 +Simplifying constant integer increment ++7 +Simplifying constant integer increment ++8 +Simplifying constant integer increment ++9 +Simplifying constant integer increment ++$a +Successful SSA optimization Pass2ConstantSimplification +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @3 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@1 +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to testBytes:5 testSBytes:7 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Renumbering block @3 to @1 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@1 + +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 testBytes + to:main::@1 +main::@1: scope:[main] from main + [6] phi() + [7] call testSBytes + to:main::@return +main::@return: scope:[main] from main::@1 + [8] return + to:@return +testSBytes: scope:[testSBytes] from main::@1 + [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c + [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6 + [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6 + [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708 + [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6 + [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6 + [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2 + [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1 + [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9 + [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc + [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5 + [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c + to:testSBytes::@return +testSBytes::@return: scope:[testSBytes] from testSBytes + [21] return + to:@return +testBytes: scope:[testBytes] from main + [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c + [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6 + [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6 + [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708 + [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6 + [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6 + [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2 + [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1 + [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c + [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8 + [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9 + [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5 + [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c + to:testBytes::@return +testBytes::@return: scope:[testBytes] from testBytes + [35] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(void()) main() +(void()) testBytes() +(byte*) testBytes::SCREEN +(byte) testBytes::idx +(void()) testSBytes() +(signed byte*) testSBytes::SCREEN +(byte) testSBytes::idx + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +//SEG0 File Comments +// Tests the number type used for constant expressions +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG9 @end +bend: +//SEG10 main +main: { + //SEG11 [5] call testBytes + jsr testBytes + //SEG12 [6] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + jmp b1 + //SEG13 main::@1 + b1: + //SEG14 [7] call testSBytes + jsr testSBytes + jmp breturn + //SEG15 main::@return + breturn: + //SEG16 [8] return + rts +} +//SEG17 testSBytes +testSBytes: { + // Constant values resolvable to signed bytes + .label SCREEN = $428 + //SEG18 [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c -- _deref_pbsc1=vbsc2 + lda #-$c + sta SCREEN + //SEG19 [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6 -- _deref_pbsc1=vbsc2 + lda #-6-6 + sta SCREEN+1 + //SEG20 [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6 -- _deref_pbsc1=vbsc2 + lda #-$12+6 + sta SCREEN+2 + //SEG21 [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708 -- _deref_pbsc1=vbsc2 + lda #-$714+$708 + sta SCREEN+3 + //SEG22 [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6 -- _deref_pbsc1=vbsc2 + lda #-1-2-3-6 + sta SCREEN+4 + //SEG23 [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6 -- _deref_pbsc1=vbsc2 + lda #-2*6 + sta SCREEN+5 + //SEG24 [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2 -- _deref_pbsc1=vbsc2 + lda #-3<<2 + sta SCREEN+6 + //SEG25 [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1 -- _deref_pbsc1=vbsc2 + lda #-$18>>1 + sta SCREEN+7 + //SEG26 [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9 -- _deref_pbsc1=vbsc2 + lda #-4&-9 + sta SCREEN+8 + //SEG27 [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc -- _deref_pbsc1=vbsc2 + lda #-$10|-$fc + sta SCREEN+9 + //SEG28 [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5 -- _deref_pbsc1=vbsc2 + lda #(-2-2)*$f/5 + sta SCREEN+$a + //SEG29 [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c -- _deref_pbsc1=vbsc2 + lda #$ff&$1000-$c + sta SCREEN+$b + jmp breturn + //SEG30 testSBytes::@return + breturn: + //SEG31 [21] return + rts +} +//SEG32 testBytes +testBytes: { + // Constant values resolvable to bytes + .label SCREEN = $400 + //SEG33 [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c -- _deref_pbuc1=vbuc2 + lda #$c + sta SCREEN + //SEG34 [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6 -- _deref_pbuc1=vbuc2 + lda #6+6 + sta SCREEN+1 + //SEG35 [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6 -- _deref_pbuc1=vbuc2 + lda #$12-6 + sta SCREEN+2 + //SEG36 [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708 -- _deref_pbuc1=vbuc2 + lda #$714-$708 + sta SCREEN+3 + //SEG37 [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6 -- _deref_pbuc1=vbuc2 + lda #1+2+3+6 + sta SCREEN+4 + //SEG38 [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6 -- _deref_pbuc1=vbuc2 + lda #2*6 + sta SCREEN+5 + //SEG39 [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2 -- _deref_pbuc1=vbuc2 + lda #3<<2 + sta SCREEN+6 + //SEG40 [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1 -- _deref_pbuc1=vbuc2 + lda #$18>>1 + sta SCREEN+7 + //SEG41 [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c -- _deref_pbuc1=vbuc2 + lda #$f&$1c + sta SCREEN+8 + //SEG42 [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8 -- _deref_pbuc1=vbuc2 + lda #4|8 + sta SCREEN+9 + //SEG43 [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9 -- _deref_pbuc1=vbuc2 + lda #5^9 + sta SCREEN+$a + //SEG44 [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5 -- _deref_pbuc1=vbuc2 + lda #(2+2)*$f/5 + sta SCREEN+$b + //SEG45 [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c -- _deref_pbuc1=vbuc2 + lda #$ff&$1000+$c + sta SCREEN+$c + jmp breturn + //SEG46 testBytes::@return + breturn: + //SEG47 [35] return + rts +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a +Statement [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a +Statement [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [testBytes] +Uplift Scope [testSBytes] +Uplift Scope [] + +Uplifting [main] best 204 combination +Uplifting [testBytes] best 204 combination +Uplifting [testSBytes] best 204 combination +Uplifting [] best 204 combination + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 File Comments +// Tests the number type used for constant expressions +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG9 @end +bend: +//SEG10 main +main: { + //SEG11 [5] call testBytes + jsr testBytes + //SEG12 [6] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + jmp b1 + //SEG13 main::@1 + b1: + //SEG14 [7] call testSBytes + jsr testSBytes + jmp breturn + //SEG15 main::@return + breturn: + //SEG16 [8] return + rts +} +//SEG17 testSBytes +testSBytes: { + // Constant values resolvable to signed bytes + .label SCREEN = $428 + //SEG18 [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c -- _deref_pbsc1=vbsc2 + lda #-$c + sta SCREEN + //SEG19 [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6 -- _deref_pbsc1=vbsc2 + lda #-6-6 + sta SCREEN+1 + //SEG20 [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6 -- _deref_pbsc1=vbsc2 + lda #-$12+6 + sta SCREEN+2 + //SEG21 [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708 -- _deref_pbsc1=vbsc2 + lda #-$714+$708 + sta SCREEN+3 + //SEG22 [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6 -- _deref_pbsc1=vbsc2 + lda #-1-2-3-6 + sta SCREEN+4 + //SEG23 [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6 -- _deref_pbsc1=vbsc2 + lda #-2*6 + sta SCREEN+5 + //SEG24 [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2 -- _deref_pbsc1=vbsc2 + lda #-3<<2 + sta SCREEN+6 + //SEG25 [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1 -- _deref_pbsc1=vbsc2 + lda #-$18>>1 + sta SCREEN+7 + //SEG26 [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9 -- _deref_pbsc1=vbsc2 + lda #-4&-9 + sta SCREEN+8 + //SEG27 [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc -- _deref_pbsc1=vbsc2 + lda #-$10|-$fc + sta SCREEN+9 + //SEG28 [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5 -- _deref_pbsc1=vbsc2 + lda #(-2-2)*$f/5 + sta SCREEN+$a + //SEG29 [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c -- _deref_pbsc1=vbsc2 + lda #$ff&$1000-$c + sta SCREEN+$b + jmp breturn + //SEG30 testSBytes::@return + breturn: + //SEG31 [21] return + rts +} +//SEG32 testBytes +testBytes: { + // Constant values resolvable to bytes + .label SCREEN = $400 + //SEG33 [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c -- _deref_pbuc1=vbuc2 + lda #$c + sta SCREEN + //SEG34 [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6 -- _deref_pbuc1=vbuc2 + lda #6+6 + sta SCREEN+1 + //SEG35 [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6 -- _deref_pbuc1=vbuc2 + lda #$12-6 + sta SCREEN+2 + //SEG36 [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708 -- _deref_pbuc1=vbuc2 + lda #$714-$708 + sta SCREEN+3 + //SEG37 [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6 -- _deref_pbuc1=vbuc2 + lda #1+2+3+6 + sta SCREEN+4 + //SEG38 [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6 -- _deref_pbuc1=vbuc2 + lda #2*6 + sta SCREEN+5 + //SEG39 [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2 -- _deref_pbuc1=vbuc2 + lda #3<<2 + sta SCREEN+6 + //SEG40 [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1 -- _deref_pbuc1=vbuc2 + lda #$18>>1 + sta SCREEN+7 + //SEG41 [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c -- _deref_pbuc1=vbuc2 + lda #$f&$1c + sta SCREEN+8 + //SEG42 [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8 -- _deref_pbuc1=vbuc2 + lda #4|8 + sta SCREEN+9 + //SEG43 [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9 -- _deref_pbuc1=vbuc2 + lda #5^9 + sta SCREEN+$a + //SEG44 [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5 -- _deref_pbuc1=vbuc2 + lda #(2+2)*$f/5 + sta SCREEN+$b + //SEG45 [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c -- _deref_pbuc1=vbuc2 + lda #$ff&$1000+$c + sta SCREEN+$c + jmp breturn + //SEG46 testBytes::@return + breturn: + //SEG47 [35] return + rts +} + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp breturn +Removing instruction jmp breturn +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Removing instruction b1_from_main: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction b1: +Removing instruction breturn: +Removing instruction breturn: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@return +(void()) testBytes() +(label) testBytes::@return +(byte*) testBytes::SCREEN +(const byte*) testBytes::SCREEN#0 SCREEN = ((byte*))(number) $400 +(byte) testBytes::idx +(void()) testSBytes() +(label) testSBytes::@return +(signed byte*) testSBytes::SCREEN +(const signed byte*) testSBytes::SCREEN#0 SCREEN = ((signed byte*))(number) $428 +(byte) testSBytes::idx + + + +FINAL ASSEMBLER +Score: 180 + +//SEG0 File Comments +// Tests the number type used for constant expressions +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG2 Global Constants & labels +//SEG3 @begin +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +//SEG5 @1 +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +//SEG9 @end +//SEG10 main +main: { + //SEG11 [5] call testBytes + jsr testBytes + //SEG12 [6] phi from main to main::@1 [phi:main->main::@1] + //SEG13 main::@1 + //SEG14 [7] call testSBytes + jsr testSBytes + //SEG15 main::@return + //SEG16 [8] return + rts +} +//SEG17 testSBytes +testSBytes: { + // Constant values resolvable to signed bytes + .label SCREEN = $428 + //SEG18 [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c -- _deref_pbsc1=vbsc2 + lda #-$c + sta SCREEN + //SEG19 [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6 -- _deref_pbsc1=vbsc2 + lda #-6-6 + sta SCREEN+1 + //SEG20 [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6 -- _deref_pbsc1=vbsc2 + lda #-$12+6 + sta SCREEN+2 + //SEG21 [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708 -- _deref_pbsc1=vbsc2 + lda #-$714+$708 + sta SCREEN+3 + //SEG22 [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6 -- _deref_pbsc1=vbsc2 + lda #-1-2-3-6 + sta SCREEN+4 + //SEG23 [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6 -- _deref_pbsc1=vbsc2 + lda #-2*6 + sta SCREEN+5 + //SEG24 [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2 -- _deref_pbsc1=vbsc2 + lda #-3<<2 + sta SCREEN+6 + //SEG25 [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1 -- _deref_pbsc1=vbsc2 + lda #-$18>>1 + sta SCREEN+7 + //SEG26 [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9 -- _deref_pbsc1=vbsc2 + lda #-4&-9 + sta SCREEN+8 + //SEG27 [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc -- _deref_pbsc1=vbsc2 + lda #-$10|-$fc + sta SCREEN+9 + //SEG28 [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5 -- _deref_pbsc1=vbsc2 + lda #(-2-2)*$f/5 + sta SCREEN+$a + //SEG29 [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c -- _deref_pbsc1=vbsc2 + lda #$ff&$1000-$c + sta SCREEN+$b + //SEG30 testSBytes::@return + //SEG31 [21] return + rts +} +//SEG32 testBytes +testBytes: { + // Constant values resolvable to bytes + .label SCREEN = $400 + //SEG33 [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c -- _deref_pbuc1=vbuc2 + lda #$c + sta SCREEN + //SEG34 [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6 -- _deref_pbuc1=vbuc2 + lda #6+6 + sta SCREEN+1 + //SEG35 [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6 -- _deref_pbuc1=vbuc2 + lda #$12-6 + sta SCREEN+2 + //SEG36 [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708 -- _deref_pbuc1=vbuc2 + lda #$714-$708 + sta SCREEN+3 + //SEG37 [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6 -- _deref_pbuc1=vbuc2 + lda #1+2+3+6 + sta SCREEN+4 + //SEG38 [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6 -- _deref_pbuc1=vbuc2 + lda #2*6 + sta SCREEN+5 + //SEG39 [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2 -- _deref_pbuc1=vbuc2 + lda #3<<2 + sta SCREEN+6 + //SEG40 [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1 -- _deref_pbuc1=vbuc2 + lda #$18>>1 + sta SCREEN+7 + //SEG41 [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c -- _deref_pbuc1=vbuc2 + lda #$f&$1c + sta SCREEN+8 + //SEG42 [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8 -- _deref_pbuc1=vbuc2 + lda #4|8 + sta SCREEN+9 + //SEG43 [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9 -- _deref_pbuc1=vbuc2 + lda #5^9 + sta SCREEN+$a + //SEG44 [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5 -- _deref_pbuc1=vbuc2 + lda #(2+2)*$f/5 + sta SCREEN+$b + //SEG45 [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c -- _deref_pbuc1=vbuc2 + lda #$ff&$1000+$c + sta SCREEN+$c + //SEG46 testBytes::@return + //SEG47 [35] return + rts +} + diff --git a/src/test/ref/number-type.sym b/src/test/ref/number-type.sym new file mode 100644 index 000000000..fa464be74 --- /dev/null +++ b/src/test/ref/number-type.sym @@ -0,0 +1,17 @@ +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@return +(void()) testBytes() +(label) testBytes::@return +(byte*) testBytes::SCREEN +(const byte*) testBytes::SCREEN#0 SCREEN = ((byte*))(number) $400 +(byte) testBytes::idx +(void()) testSBytes() +(label) testSBytes::@return +(signed byte*) testSBytes::SCREEN +(const signed byte*) testSBytes::SCREEN#0 SCREEN = ((signed byte*))(number) $428 +(byte) testSBytes::idx + From b097b5c2c51a962d261979a523d8b230d01f4bcf Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 7 May 2019 01:46:23 +0200 Subject: [PATCH 10/93] Working on fixing test errors. --- .../iterator/ProgramExpressionBinary.java | 28 +++++++++++-------- .../iterator/ProgramExpressionIterator.java | 2 ++ .../kickc/model/values/ConstantPointer.java | 8 ++---- .../Pass2ConstantCastSimplification.java | 17 +++++++---- .../kickc/passes/Pass2InlineDerefIdx.java | 2 +- src/test/kc/bitwise-not.kc | 2 +- 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java index 655ca17e4..aac9a3cb5 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java @@ -44,12 +44,14 @@ public interface ProgramExpressionBinary extends ProgramExpression { /** * Adds a cast to the left operand + * * @param toType The toType to cast to */ void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols); /** * Adds a cast to the right operand + * * @param toType The toType to cast to */ void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols); @@ -135,7 +137,7 @@ public interface ProgramExpressionBinary extends ProgramExpression { @Override public RValue getRight() { - if(assignment.getrValue1()==null && assignment.getOperator()==null) { + if(assignment.getrValue1() == null && assignment.getOperator() == null) { return assignment.getrValue2(); } else { return new AssignmentRValue(assignment); @@ -160,13 +162,9 @@ public interface ProgramExpressionBinary extends ProgramExpression { @Override public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { - if(assignment.getrValue1()==null && assignment.getOperator()==null) { - //if(assignment.getrValue2() instanceof ConstantInteger) { - // ((ConstantInteger) assignment.getrValue2()).setType(toType); - //} else { - assignment.setOperator(Operators.getCastUnary(toType)); - //} - } else { + if(assignment.getrValue1() == null && assignment.getOperator() == null) { + assignment.setOperator(Operators.getCastUnary(toType)); + } else { throw new InternalError("Not implemented!"); } } @@ -205,12 +203,20 @@ public interface ProgramExpressionBinary extends ProgramExpression { @Override public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { - throw new InternalError("Not implemented!"); + if(conditionalJump.getrValue1() instanceof ConstantValue) { + conditionalJump.setrValue1(new ConstantCastValue(toType, (ConstantValue) conditionalJump.getrValue1())); + } else { + throw new InternalError("Not implemented!"); + } } @Override public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { - throw new InternalError("Not implemented!"); + if(conditionalJump.getrValue2() instanceof ConstantValue) { + conditionalJump.setrValue2(new ConstantCastValue(toType, (ConstantValue) conditionalJump.getrValue2())); + } else { + throw new InternalError("Not implemented!"); + } } @@ -226,7 +232,7 @@ public interface ProgramExpressionBinary extends ProgramExpression { } public ConstantBinary getConstantBinary() { - return (ConstantBinary)programValue.get(); + return (ConstantBinary) programValue.get(); } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java index a8ae53aca..e525c101f 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java @@ -28,6 +28,8 @@ public class ProgramExpressionIterator { ProgramValueIterator.execute(program.getScope(), (programValue, currentStmt, stmtIt, currentBlock) -> { if(programValue.get() instanceof ConstantBinary) { handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), null, null, null); + } else if(programValue.get() instanceof ConstantUnary) { + handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), null, null, null); } }); diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantPointer.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantPointer.java index 452f3331c..dd8bf3940 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantPointer.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantPointer.java @@ -5,7 +5,7 @@ import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -/** Constant pointer (meaning it points to a constant location)*/ +/** Constant pointer (meaning it points to a constant location) */ public class ConstantPointer implements ConstantEnumerable<Long> { /** The memory location pointed to. */ @@ -52,11 +52,7 @@ public class ConstantPointer implements ConstantEnumerable<Long> { @Override public String toString(Program program) { - if(program == null) { - return Long.toString(location); - } else { - return "(" + getType(program.getScope()).getTypeName() + ") " + Long.toString(location); - } + return "(" + getType().getTypeName() + ") " + Long.toString(location); } @Override diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java index a40c02fd0..14f4f1028 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java @@ -1,13 +1,14 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.iterator.ProgramExpression; import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary; import dk.camelot64.kickc.model.operators.OperatorCast; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; +import dk.camelot64.kickc.model.types.SymbolTypePointer; import dk.camelot64.kickc.model.values.ConstantInteger; -import dk.camelot64.kickc.model.values.ConstantValue; +import dk.camelot64.kickc.model.values.ConstantPointer; import java.util.concurrent.atomic.AtomicBoolean; @@ -29,9 +30,15 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization { ConstantInteger constantInteger = (ConstantInteger) unary.getOperand(); if(constantInteger.getType().equals(SymbolType.NUMBER)) { SymbolType castType = operatorCast.getToType(); - ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); - programExpression.set(newConstInt); - getLog().append("Simplifying constant integer cast "+newConstInt); + if(castType instanceof SymbolTypeIntegerFixed ) { + ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); + programExpression.set(newConstInt); + getLog().append("Simplifying constant integer cast " + newConstInt.toString()); + } else if(castType instanceof SymbolTypePointer) { + ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType()); + programExpression.set(newConstPointer); + getLog().append("Simplifying constant pointer cast " + newConstPointer.toString()); + } } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java index dd7b0a85e..795d55117 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java @@ -83,7 +83,7 @@ public class Pass2InlineDerefIdx extends Pass2SsaOptimization { } else if(derefAssignment.getOperator()==null) { return attemptInlineDeref(derefAssignment.getrValue2()); } else if(derefAssignment.getOperator() instanceof OperatorCastPtr) { - throw new CompileError("Not implemented!"); + //throw new CompileError("Not implemented!"); //return attemptInlineDeref(derefAssignment.getrValue2()); } return null; diff --git a/src/test/kc/bitwise-not.kc b/src/test/kc/bitwise-not.kc index 282da557c..1da5f5af6 100644 --- a/src/test/kc/bitwise-not.kc +++ b/src/test/kc/bitwise-not.kc @@ -1,7 +1,7 @@ void main() { byte* SCREEN = $400; - *SCREEN = ~1; + *SCREEN = ~1ub; for(byte c : 1..26) { SCREEN[c] = ~c; From 87e6fecb8f02f9c439465b09ce6d189d0acedaef Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 7 May 2019 09:19:50 +0200 Subject: [PATCH 11/93] Working on fixing test errors. --- .../kickc/passes/Pass2AssertTypeMatch.java | 13 ++++++++++--- .../java/dk/camelot64/kickc/test/TestPrograms.java | 11 ++++++++--- src/test/kc/helloworld0.kc | 8 ++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 src/test/kc/helloworld0.kc diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java index 466599cf3..999188209 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java @@ -1,12 +1,15 @@ package dk.camelot64.kickc.passes; -import dk.camelot64.kickc.model.*; -import dk.camelot64.kickc.model.statements.StatementConditionalJump; -import dk.camelot64.kickc.model.values.LValue; +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.statements.StatementConditionalJump; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.types.SymbolTypePointer; +import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.RValue; /** @@ -55,6 +58,10 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion { // L-value is still a number - constants are probably not done being identified & typed return; } + if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) { + // String value can be assigned into a pointer + return; + } // Types do not match getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false)); throw new CompileError("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource()); diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index b77d09e82..29f794fb5 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,6 +32,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testHelloWorld0() throws IOException, URISyntaxException { + compileAndCompare("helloworld0", log()); + } + @Test public void testNumberConversion() throws IOException, URISyntaxException { compileAndCompare("number-conversion"); @@ -1879,9 +1884,9 @@ public class TestPrograms { boolean success = true; ReferenceHelper helper = new ReferenceHelperFolder(refPath); success &= helper.testOutput(fileName, ".asm", program.getAsm().toString(false)); - success &= helper.testOutput(fileName, ".sym", program.getScope().getSymbolTableContents(program)); - success &= helper.testOutput(fileName, ".cfg", program.getGraph().toString(program)); - success &= helper.testOutput(fileName, ".log", program.getLog().toString()); + //success &= helper.testOutput(fileName, ".sym", program.getScope().getSymbolTableContents(program)); + //success &= helper.testOutput(fileName, ".cfg", program.getGraph().toString(program)); + //success &= helper.testOutput(fileName, ".log", program.getLog().toString()); if(!success) { //System.out.println("\nCOMPILE LOG"); //System.out.println(program.getLog().toString()); diff --git a/src/test/kc/helloworld0.kc b/src/test/kc/helloworld0.kc new file mode 100644 index 000000000..a70b62201 --- /dev/null +++ b/src/test/kc/helloworld0.kc @@ -0,0 +1,8 @@ +// Tests minimal hello world + +byte[] msg = "hello world"; +byte* SCREEN = 0x0400; + +void main() { + for( byte i: 0..11) SCREEN[i] = msg[i]; +} \ No newline at end of file From 47aa623f2525fea8585a20a4381eb3fd3555d14d Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 7 May 2019 18:52:01 +0200 Subject: [PATCH 12/93] Working on fixing test errors. --- .../model/types/SymbolTypeConversion.java | 17 +++++----- .../kickc/model/types/SymbolTypeMatch.java | 31 +++++++++++++++++++ .../kickc/passes/Pass2AssertTypeMatch.java | 14 ++------- .../passes/Pass2ConstantIdentification.java | 16 +++++----- .../Pass2ConstantRValueConsolidation.java | 2 +- .../passes/Pass2SizeOfSimplification.java | 5 +-- .../dk/camelot64/kickc/test/TestPrograms.java | 2 +- src/test/kc/helloworld0.kc | 2 +- 8 files changed, 55 insertions(+), 34 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index 7b93fa1de..239f64417 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -11,11 +11,10 @@ import dk.camelot64.kickc.model.values.RValue; /** * Rules for converting integer types. - * + * <p> * Integer conversion implements C99 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70 - * + * <p> * The special number type is converted as described here https://gitlab.com/camelot/kickc/issues/181 - * */ public class SymbolTypeConversion { @@ -37,19 +36,19 @@ public class SymbolTypeConversion { if(type1.equals(type2)) return type1; // C99 6.3.1.8 b. If both are signed or both are unsigned then the smallest type is converted to the size of the large type (byte->word->sword, sbyte->sword->sdword) - if(fixed1.isSigned()==fixed2.isSigned()) - return (fixed1.getBits()>fixed2.getBits()) ? fixed1 : fixed2; + if(fixed1.isSigned() == fixed2.isSigned()) + return (fixed1.getBits() > fixed2.getBits()) ? fixed1 : fixed2; // C99 6.3.1.8 c. One is signed and one unsigned. // If the signed type can contain all values of the unsigned type then the unsigned value is converted to the signed type. (byte->sword, byte->sdword, word->sdword). SymbolTypeIntegerFixed typeS, typeU; if(fixed1.isSigned()) { typeS = fixed1; typeU = fixed2; - } else { + } else { typeS = fixed2; typeU = fixed1; } - if(typeS.getBits()>typeU.getBits()) + if(typeS.getBits() > typeU.getBits()) return typeS; // C99 6.3.1.8 d. The unsigned type is the same size as or larger than the signed type. // The signed value is first converted to the size of the unsigned type and then converted to unsigned changing the sign and the value @@ -59,6 +58,7 @@ public class SymbolTypeConversion { /** * Find the integer type that results from a binary operator according to the special number type conversion https://gitlab.com/camelot/kickc/issues/181 + * * @param left The left value * @param right The right value * @param symbols The program scope symbols (used for looking up symbols and constants) @@ -92,7 +92,8 @@ public class SymbolTypeConversion { fixedType = (SymbolTypeIntegerFixed) leftType; } else { // Binary operator combining number and non-integer - throw new CompileError("Error! Incompatible operands " + left.toString() + " and " + right.toString(), currentStmt); + return null; + //throw new CompileError("Error! Incompatible operands " + left.toString() + " and " + right.toString(), currentStmt); } if(numberVal instanceof ConstantValue) { diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java new file mode 100644 index 000000000..b058abbb2 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java @@ -0,0 +1,31 @@ +package dk.camelot64.kickc.model.types; + +/** Container for function checking if types of an assignment match up */ +public class SymbolTypeMatch { + + /** + * Determines if the types of an assignment match up properly + * @param lValueType The type of the LValue + * @param rValueType The type of the RValue + * @return true if the types match up + */ + public static boolean assignmentTypeMatch(SymbolType lValueType, SymbolType rValueType) { + if(lValueType.equals(rValueType)) { + return true; + } + if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) { + // L-value is still a number - constants are probably not done being identified & typed + return true; + } + if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) { + // String value can be assigned into a pointer + return true; + } + if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && assignmentTypeMatch(((SymbolTypePointer) lValueType).getElementType(), ((SymbolTypePointer) rValueType).getElementType())) { + // Pointer types assigned from each other + // TODO: Maybe handle sizes + return true; + } + return false; + } +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java index 999188209..82c5fce43 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java @@ -8,7 +8,7 @@ import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementConditionalJump; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypePointer; +import dk.camelot64.kickc.model.types.SymbolTypeMatch; import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.RValue; @@ -51,17 +51,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion { LValue lValue = statement.getlValue(); SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue); SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), statement); - if(lValueType.equals(rValueType)) { - return; - } - if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) { - // L-value is still a number - constants are probably not done being identified & typed - return; - } - if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) { - // String value can be assigned into a pointer - return; - } + if(SymbolTypeMatch.assignmentTypeMatch(lValueType, rValueType)) return; // Types do not match getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false)); throw new CompileError("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java index 0cde91c25..95e8e0229 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java @@ -15,11 +15,14 @@ import dk.camelot64.kickc.model.symbols.ProgramScope; 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.SymbolTypeArray; import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.types.SymbolTypeMatch; import dk.camelot64.kickc.model.values.*; -import java.util.*; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; /** * Compiler Pass propagating constants in expressions eliminating constant variables @@ -69,24 +72,19 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { ConstantValue constVal = constVarVal.getConstantValue(); SymbolType valueType = SymbolTypeInference.inferType(getScope(), constVal); SymbolType variableType = variable.getType(); - SymbolType constType = variableType; - if(!valueType.equals(variableType)) { - if(variableType.equals(valueType)) { - constType = variableType; - } else { + if(!SymbolTypeMatch.assignmentTypeMatch(variableType, valueType)) { throw new CompileError( "Constant variable has a non-matching type \n variable: " + variable.toString(getProgram()) + "\n value: (" + valueType.toString() + ") " + constVal.calculateLiteral(getScope()) + "\n value definition: " + constVal.toString(getProgram()) ); - } } ConstantVar constantVar = new ConstantVar( variable.getName(), constScope, - constType, + variableType, constVal); constantVar.setDeclaredAlignment(variable.getDeclaredAlignment()); constantVar.setDeclaredRegister(variable.getDeclaredRegister()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java index a473bd5f8..eed062e60 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java @@ -16,7 +16,7 @@ import java.util.ArrayList; import java.util.List; /** - * Compiler Pass consolidating L-values that are constant into a single {@link ConstantValue} + * Compiler Pass consolidating R-values that are constant into a single {@link ConstantValue} */ public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java index e2c1e6f2c..3121da890 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java @@ -76,12 +76,12 @@ public class Pass2SizeOfSimplification extends Pass2SsaOptimization { SymbolTypeArray arrayType = (SymbolTypeArray) symbolType; RValue arraySize = arrayType.getSize(); if(arraySize instanceof ConstantValue) { - getLog().append("Resolving sizeof() " + unary.toString(getProgram())); + getLog().append("Resolving array sizeof() " + unary.toString(getProgram())); ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType()); programValue.set(new ConstantBinary((ConstantValue) arraySize, Operators.MULTIPLY, sizeOfConstantVar)); modified.set(true); } else if(constant.getValue() instanceof ConstantArrayList) { - getLog().append("Resolving sizeof() " + unary.toString(getProgram())); + getLog().append("Resolving array sizeof() " + unary.toString(getProgram())); int size = ((ConstantArrayList) constant.getValue()).getElements().size(); ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType()); programValue.set(new ConstantBinary(new ConstantInteger((long) size), Operators.MULTIPLY, sizeOfConstantVar)); @@ -97,6 +97,7 @@ public class Pass2SizeOfSimplification extends Pass2SsaOptimization { if(stringLiteral instanceof ConstantString) { ConstantString constString = (ConstantString) stringLiteral; int length = constString.getString().length(); + getLog().append("Resolving string sizeof() " + unary.toString(getProgram())); ConstantRef sizeOfChar = OperatorSizeOf.getSizeOfConstantVar(getScope(), SymbolType.BYTE); programValue.set(new ConstantBinary(new ConstantInteger((long) length), Operators.MULTIPLY, sizeOfChar)); modified.set(true); diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 29f794fb5..422890f99 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -34,7 +34,7 @@ public class TestPrograms { @Test public void testHelloWorld0() throws IOException, URISyntaxException { - compileAndCompare("helloworld0", log()); + compileAndCompare("helloworld0"); } @Test diff --git a/src/test/kc/helloworld0.kc b/src/test/kc/helloworld0.kc index a70b62201..b3136af56 100644 --- a/src/test/kc/helloworld0.kc +++ b/src/test/kc/helloworld0.kc @@ -1,6 +1,6 @@ // Tests minimal hello world -byte[] msg = "hello world"; +byte[] msg = "hello world!"; byte* SCREEN = 0x0400; void main() { From 82729cb4d9488a0ebc2f80eaf5667015dddb319d Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 7 May 2019 21:03:26 +0200 Subject: [PATCH 13/93] Working on fixing test errors - 196/350 working. --- .../model/types/SymbolTypeConversion.java | 9 +++++- .../Pass2ConstantCastSimplification.java | 29 ++++++++++++++++++- .../passes/Pass2ConstantIdentification.java | 6 ++++ .../passes/PassNAddNumberTypeConversions.java | 6 ++-- .../dk/camelot64/kickc/test/TestPrograms.java | 5 ++++ src/test/kc/const-int-cast-problem.kc | 8 +++++ 6 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 src/test/kc/const-int-cast-problem.kc diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index 239f64417..15c35ad73 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -90,10 +90,17 @@ public class SymbolTypeConversion { // Right is the number type - left is the fixed type numberVal = right; fixedType = (SymbolTypeIntegerFixed) leftType; + } else if(SymbolType.NUMBER.equals(leftType) && rightType instanceof SymbolTypePointer) { + // Left is the number type - right is a pointer (effectively unsigned word) + numberVal = left; + fixedType = SymbolType.WORD; + } else if(SymbolType.NUMBER.equals(rightType) && leftType instanceof SymbolTypePointer) { + // Right is the number type - left is a pointer (effectively unsigned word) + numberVal = right; + fixedType = SymbolType.WORD; } else { // Binary operator combining number and non-integer return null; - //throw new CompileError("Error! Incompatible operands " + left.toString() + " and " + right.toString(), currentStmt); } if(numberVal instanceof ConstantValue) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java index 14f4f1028..893003447 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java @@ -3,10 +3,12 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary; +import dk.camelot64.kickc.model.iterator.ProgramValueIterator; import dk.camelot64.kickc.model.operators.OperatorCast; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; import dk.camelot64.kickc.model.types.SymbolTypePointer; +import dk.camelot64.kickc.model.values.ConstantCastValue; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantPointer; @@ -28,21 +30,46 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization { ProgramExpressionUnary unary = (ProgramExpressionUnary) programExpression; if(unary.getOperand() instanceof ConstantInteger) { ConstantInteger constantInteger = (ConstantInteger) unary.getOperand(); - if(constantInteger.getType().equals(SymbolType.NUMBER)) { + if(SymbolType.NUMBER.equals(constantInteger.getType())) { SymbolType castType = operatorCast.getToType(); if(castType instanceof SymbolTypeIntegerFixed ) { ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); programExpression.set(newConstInt); getLog().append("Simplifying constant integer cast " + newConstInt.toString()); + optimized.set(true); } else if(castType instanceof SymbolTypePointer) { ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType()); programExpression.set(newConstPointer); getLog().append("Simplifying constant pointer cast " + newConstPointer.toString()); + optimized.set(true); } } } } }); + ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> { + if(programValue.get() instanceof ConstantCastValue) { + ConstantCastValue constantCastValue = (ConstantCastValue) programValue.get(); + if(constantCastValue.getValue() instanceof ConstantInteger) { + ConstantInteger constantInteger = (ConstantInteger) constantCastValue.getValue(); + if(SymbolType.NUMBER.equals(constantInteger.getType())) { + SymbolType castType = constantCastValue.getToType(); + if(castType instanceof SymbolTypeIntegerFixed ) { + ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); + programValue.set(newConstInt); + getLog().append("Simplifying constant integer cast " + newConstInt.toString()); + optimized.set(true); + } else if(castType instanceof SymbolTypePointer) { + ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType()); + programValue.set(newConstPointer); + getLog().append("Simplifying constant pointer cast " + newConstPointer.toString()); + optimized.set(true); + } + } + } + } + + }); return optimized.get(); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java index 95e8e0229..d4df53443 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java @@ -73,6 +73,12 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { SymbolType valueType = SymbolTypeInference.inferType(getScope(), constVal); SymbolType variableType = variable.getType(); + if(!variableType.equals(SymbolType.NUMBER) && valueType.equals(SymbolType.NUMBER)) { + // Value is number - wait til it is cast to a proper type + constants.remove(constRef); + continue; + } + if(!SymbolTypeMatch.assignmentTypeMatch(variableType, valueType)) { throw new CompileError( "Constant variable has a non-matching type \n variable: " + variable.toString(getProgram()) + diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java index 39d15dc0c..16688948f 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java @@ -6,6 +6,7 @@ import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeConversion; import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.types.SymbolTypePointer; import dk.camelot64.kickc.model.values.RValue; /** @@ -28,12 +29,12 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization { if(conversionType != null) { // Convert both left and right to the found type SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left); - if(!leftType.equals(conversionType)) { + if(!leftType.equals(conversionType) && !(leftType instanceof SymbolTypePointer)) { getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false)); binary.addLeftCast(conversionType, stmtIt, currentBlock.getScope(), getScope()); } SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right); - if(!rightType.equals(conversionType)) { + if(!rightType.equals(conversionType) && !(rightType instanceof SymbolTypePointer)) { getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false)); binary.addRightCast(conversionType, stmtIt, currentBlock.getScope(), getScope()); } @@ -43,5 +44,4 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization { return false; } - } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 422890f99..f9a125777 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -103,6 +103,11 @@ public class TestPrograms { compileAndCompare("type-signed"); } + @Test + public void testConstIntCastProblem() throws IOException, URISyntaxException { + compileAndCompare("const-int-cast-problem"); + } + @Test public void testPointerPlus0() throws IOException, URISyntaxException { compileAndCompare("pointer-plus-0"); diff --git a/src/test/kc/const-int-cast-problem.kc b/src/test/kc/const-int-cast-problem.kc new file mode 100644 index 000000000..01a8dea74 --- /dev/null +++ b/src/test/kc/const-int-cast-problem.kc @@ -0,0 +1,8 @@ +// Test a problem with converting casted constant numbers to fixed type constant integers +const byte* SCREEN = $0400; + +void main() { + for( byte i: 121..122) { + SCREEN[i] = i>>4; + } +} From 44e9cff722d07a89dc389855ac059ba571b6f7f7 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 7 May 2019 21:53:08 +0200 Subject: [PATCH 14/93] Working on fixing test errors - 198/350 working. --- .../kickc/model/operators/OperatorGetHigh.java | 2 ++ .../kickc/model/operators/OperatorGetLow.java | 2 ++ .../model/operators/OperatorShiftLeft.java | 8 +++++++- .../model/operators/OperatorShiftRight.java | 8 +++++++- .../model/types/SymbolTypeNumberInference.java | 18 ++++++++++++++---- .../kickc/model/values/ConstantBinary.java | 6 +++++- .../kickc/model/values/ConstantUnary.java | 6 +++++- .../dk/camelot64/kickc/test/TestPrograms.java | 5 +++++ .../kc/examples/sinsprites/sinus-sprites.kc | 2 +- src/test/kc/inline-kasm-resource.kc | 2 +- src/test/kc/tod018-problem.kc | 9 +++++++++ 11 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 src/test/kc/tod018-problem.kc diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java index 2a76c569b..81aad2e0e 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java @@ -43,6 +43,8 @@ public class OperatorGetHigh extends OperatorUnary { return SymbolType.WORD; } else if(SymbolType.STRING.equals(operandType)) { return SymbolType.BYTE; + } else if(SymbolType.NUMBER.equals(operandType)) { + return SymbolType.NUMBER; } throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java index bd8d030f3..81fc490c0 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java @@ -43,6 +43,8 @@ public class OperatorGetLow extends OperatorUnary { return SymbolType.WORD; } else if(SymbolType.STRING.equals(operandType)) { return SymbolType.BYTE; + } else if(SymbolType.NUMBER.equals(operandType)) { + return SymbolType.NUMBER; } throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java index bb14a9cd1..c6c7f3f72 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java @@ -2,6 +2,8 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeConversion; +import dk.camelot64.kickc.model.types.SymbolTypeInteger; import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantInteger; @@ -24,7 +26,11 @@ public class OperatorShiftLeft extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { - return left; + if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { + return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right); + } else { + return left; + } } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java index 6b3adb2b7..dc9c66a69 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java @@ -2,6 +2,8 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeConversion; +import dk.camelot64.kickc.model.types.SymbolTypeInteger; import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +25,11 @@ public class OperatorShiftRight extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { - return left; + if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { + return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right); + } else { + return left; + } } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java index 4967f0bfa..acef7130b 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java @@ -48,8 +48,13 @@ public class SymbolTypeNumberInference { // Calculate resulting constant literal ConstantLiteral leftLiteral = leftValue.calculateLiteral(programScope); ConstantLiteral rightLiteral = rightValue.calculateLiteral(programScope); - ConstantLiteral constantLiteral = operator.calculateLiteral(leftLiteral, rightLiteral); - return inferTypes(programScope, constantLiteral); + ConstantLiteral literal = operator.calculateLiteral(leftLiteral, rightLiteral); + if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) { + SymbolType literalType = SymbolTypeInference.inferType(programScope, leftValue, operator, rightValue); + ((ConstantInteger) literal).setType(literalType); + throw new InternalError("Unexpected advanced literal type calculation!"); + } + return inferTypes(programScope, literal); } else { throw new InternalError("Both operands must be number type."); } @@ -64,8 +69,13 @@ public class SymbolTypeNumberInference { if(SymbolType.NUMBER.equals(constantValue.getType(programScope))) { // Calculate resulting constant literal ConstantLiteral operandLiteral = constantValue.calculateLiteral(programScope); - ConstantLiteral constantLiteral = operator.calculateLiteral(operandLiteral, programScope); - return inferTypes(programScope, constantLiteral); + ConstantLiteral literal = operator.calculateLiteral(operandLiteral, programScope); + if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) { + SymbolType literalType = SymbolTypeInference.inferType(programScope, operator, constantValue); + ((ConstantInteger) literal).setType(literalType); + throw new InternalError("Unexpected advanced literal type calculation!"); + } + return inferTypes(programScope, literal); } else { throw new InternalError("Operand must be number type."); } diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java index e15ed558a..df51994a4 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java @@ -50,7 +50,11 @@ public class ConstantBinary implements ConstantValue { @Override public ConstantLiteral calculateLiteral(ProgramScope scope) { - return operator.calculateLiteral(left.calculateLiteral(scope), right.calculateLiteral(scope)); + ConstantLiteral literal = operator.calculateLiteral(left.calculateLiteral(scope), right.calculateLiteral(scope)); + if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(scope))) { + ((ConstantInteger) literal).setType(getType(scope)); + } + return literal; } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java index 80fc32871..a111b9c07 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java @@ -38,7 +38,11 @@ public class ConstantUnary implements ConstantValue { @Override public ConstantLiteral calculateLiteral(ProgramScope scope) { - return operator.calculateLiteral(operand.calculateLiteral(scope), scope); + ConstantLiteral literal = operator.calculateLiteral(operand.calculateLiteral(scope), scope); + if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(scope))) { + ((ConstantInteger) literal).setType(getType(scope)); + } + return literal; } @Override diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index f9a125777..6a0063197 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,6 +32,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testToD018Problem() throws IOException, URISyntaxException { + compileAndCompare("tod018-problem", log()); + } + @Test public void testHelloWorld0() throws IOException, URISyntaxException { compileAndCompare("helloworld0"); diff --git a/src/test/kc/examples/sinsprites/sinus-sprites.kc b/src/test/kc/examples/sinsprites/sinus-sprites.kc index d27f76bb9..a81055760 100644 --- a/src/test/kc/examples/sinsprites/sinus-sprites.kc +++ b/src/test/kc/examples/sinsprites/sinus-sprites.kc @@ -104,7 +104,7 @@ void place_sprites() { *SPRITES_EXPAND_X = %01111111; *SPRITES_EXPAND_Y = %01111111; byte* sprites_ptr = SCREEN+$3f8; - byte spr_id = (byte)(sprites/$40); + byte spr_id = (byte)((word)sprites/$40); byte spr_x = 60; byte j2 = 0; byte col = $5; diff --git a/src/test/kc/inline-kasm-resource.kc b/src/test/kc/inline-kasm-resource.kc index 6b7bf9b32..a0d9b8593 100644 --- a/src/test/kc/inline-kasm-resource.kc +++ b/src/test/kc/inline-kasm-resource.kc @@ -14,7 +14,7 @@ const byte* SPRITES_XPOS = $d000; const byte* SPRITES_YPOS = $d001; void main() { - *(SCREEN+$3f8) = (byte)(SPRITE/$40); + *(SCREEN+$3f8) = (byte)((word)SPRITE/$40); *SPRITES_ENABLE = 1; *SPRITES_XPOS = 100; *SPRITES_YPOS = 100; diff --git a/src/test/kc/tod018-problem.kc b/src/test/kc/tod018-problem.kc new file mode 100644 index 000000000..cb6b2e5c7 --- /dev/null +++ b/src/test/kc/tod018-problem.kc @@ -0,0 +1,9 @@ +// Tests a problem with tod018 not calculating types correctly + +void main() { + const byte *D018 = 0xd018; + const byte* screen = 0x0400; + byte d018val = >((word)screen&$3fff); + *D018 = d018val; +} + From cab95b6ba547a9204022ccfbb851676a797192f1 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 7 May 2019 22:08:59 +0200 Subject: [PATCH 15/93] Working on fixing test errors - 198/350 working. --- src/main/fragment/vduz1=_dword_vbuaa.asm | 5 +++++ src/main/fragment/vduz1=vduc1_plus_vduz2.asm | 13 +++++++++++++ src/main/fragment/vduz1=vduz1_plus_vduz2.asm | 3 +-- src/main/fragment/vduz1=vduz2_plus_vwuc1.asm | 3 +-- .../model/iterator/ProgramExpressionBinary.java | 4 ++++ 5 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 src/main/fragment/vduz1=_dword_vbuaa.asm create mode 100644 src/main/fragment/vduz1=vduc1_plus_vduz2.asm diff --git a/src/main/fragment/vduz1=_dword_vbuaa.asm b/src/main/fragment/vduz1=_dword_vbuaa.asm new file mode 100644 index 000000000..e1a56bd93 --- /dev/null +++ b/src/main/fragment/vduz1=_dword_vbuaa.asm @@ -0,0 +1,5 @@ +sta {z1} +lda #0 +sta {z1}+1 +sta {z1}+2 +sta {z1}+3 diff --git a/src/main/fragment/vduz1=vduc1_plus_vduz2.asm b/src/main/fragment/vduz1=vduc1_plus_vduz2.asm new file mode 100644 index 000000000..aee9842f5 --- /dev/null +++ b/src/main/fragment/vduz1=vduc1_plus_vduz2.asm @@ -0,0 +1,13 @@ +lda {z2} +clc +adc #<{c1} +sta {z1} +lda {z2}+1 +adc #>{c1} +sta {z1}+1 +lda {z2}+2 +adc #0 +sta {z1}+2 +lda {z2}+3 +adc #0 +sta {z1}+3 \ No newline at end of file diff --git a/src/main/fragment/vduz1=vduz1_plus_vduz2.asm b/src/main/fragment/vduz1=vduz1_plus_vduz2.asm index 3574d1e24..973a718d1 100644 --- a/src/main/fragment/vduz1=vduz1_plus_vduz2.asm +++ b/src/main/fragment/vduz1=vduz1_plus_vduz2.asm @@ -10,5 +10,4 @@ adc {z2}+2 sta {z1}+2 lda {z1}+3 adc {z2}+3 -sta {z1}+3 - +sta {z1}+3 \ No newline at end of file diff --git a/src/main/fragment/vduz1=vduz2_plus_vwuc1.asm b/src/main/fragment/vduz1=vduz2_plus_vwuc1.asm index ff2fb6d2d..aee9842f5 100644 --- a/src/main/fragment/vduz1=vduz2_plus_vwuc1.asm +++ b/src/main/fragment/vduz1=vduz2_plus_vwuc1.asm @@ -10,5 +10,4 @@ adc #0 sta {z1}+2 lda {z2}+3 adc #0 -sta {z1}+3 - +sta {z1}+3 \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java index aac9a3cb5..d10a28ec4 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java @@ -98,7 +98,9 @@ public interface ProgramExpressionBinary extends ProgramExpression { tmpVar.setType(toType); StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue1(), assignment.getSource(), Comment.NO_COMMENTS); assignment.setrValue1(tmpVar.getRef()); + stmtIt.previous(); stmtIt.add(newAssignment); + stmtIt.next(); } } @@ -112,7 +114,9 @@ public interface ProgramExpressionBinary extends ProgramExpression { tmpVar.setType(toType); StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue2(), assignment.getSource(), Comment.NO_COMMENTS); assignment.setrValue2(tmpVar.getRef()); + stmtIt.previous(); stmtIt.add(newAssignment); + stmtIt.next(); } } } From 21b3114b58c63d5d55615082445d65b7234206fc Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 7 May 2019 23:39:57 +0200 Subject: [PATCH 16/93] Working on fixing test errors - 202/350 working. --- src/test/ref/const-int-cast-problem.asm | 19 +++++++++++++++++++ src/test/ref/helloworld0.asm | 16 ++++++++++++++++ src/test/ref/tod018-problem.asm | 12 ++++++++++++ src/test/ref/typeid-plus-byte-problem.asm | 12 ++++++++++++ src/test/ref/typemismatch.asm | 7 +++++++ 5 files changed, 66 insertions(+) create mode 100644 src/test/ref/const-int-cast-problem.asm create mode 100644 src/test/ref/helloworld0.asm create mode 100644 src/test/ref/tod018-problem.asm create mode 100644 src/test/ref/typeid-plus-byte-problem.asm create mode 100644 src/test/ref/typemismatch.asm diff --git a/src/test/ref/const-int-cast-problem.asm b/src/test/ref/const-int-cast-problem.asm new file mode 100644 index 000000000..10377d0e9 --- /dev/null +++ b/src/test/ref/const-int-cast-problem.asm @@ -0,0 +1,19 @@ +// Test a problem with converting casted constant numbers to fixed type constant integers +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label SCREEN = $400 +main: { + ldx #$79 + b1: + txa + lsr + lsr + lsr + lsr + sta SCREEN,x + inx + cpx #$7b + bne b1 + rts +} diff --git a/src/test/ref/helloworld0.asm b/src/test/ref/helloworld0.asm new file mode 100644 index 000000000..4d3606742 --- /dev/null +++ b/src/test/ref/helloworld0.asm @@ -0,0 +1,16 @@ +// Tests minimal hello world +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label SCREEN = $400 +main: { + ldx #0 + b1: + lda msg,x + sta SCREEN,x + inx + cpx #$c + bne b1 + rts +} + msg: .text "hello world!@" diff --git a/src/test/ref/tod018-problem.asm b/src/test/ref/tod018-problem.asm new file mode 100644 index 000000000..abe4cf7a9 --- /dev/null +++ b/src/test/ref/tod018-problem.asm @@ -0,0 +1,12 @@ +// Tests a problem with tod018 not calculating types correctly +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label D018 = $d018 + .label screen = $400 + .const d018val = >screen&$3fff + lda #d018val + sta D018 + rts +} diff --git a/src/test/ref/typeid-plus-byte-problem.asm b/src/test/ref/typeid-plus-byte-problem.asm new file mode 100644 index 000000000..d92b22c23 --- /dev/null +++ b/src/test/ref/typeid-plus-byte-problem.asm @@ -0,0 +1,12 @@ +// Test that byte+byte creates a byte - even when there is a value overflow +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label SCREEN = $400 +main: { + .const ubc2 = $fa + .const ubc1 = $c+$d+$e + lda #ubc1+ubc2 + sta SCREEN + rts +} diff --git a/src/test/ref/typemismatch.asm b/src/test/ref/typemismatch.asm new file mode 100644 index 000000000..29ae868a1 --- /dev/null +++ b/src/test/ref/typemismatch.asm @@ -0,0 +1,7 @@ +// Type mismatch - should fail gracefully +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + rts +} From 64a8389e6ea860db3079de2fdca9b5c9b9630eca Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Wed, 8 May 2019 00:11:33 +0200 Subject: [PATCH 17/93] Working on fixing test errors - 228/350 working. --- .../dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java index fd47ffd3c..0b1199cd6 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java @@ -29,7 +29,7 @@ public class PassNAddTypeConversionsNew extends Pass2SsaOptimization { // Special handling of assigning a pointer from an unsigned word if((programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue) && (leftType instanceof SymbolTypePointer) && SymbolType.isInteger(rightType)) { getLog().append("Adding pointer type conversion cast (" + leftType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false)); - binary.addLeftCast(leftType, stmtIt, currentBlock.getScope(), getScope()); + binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope()); } if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) { From ea990b5e87b2d4cabd8ff01d06191cc367dbacac Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Wed, 8 May 2019 23:24:48 +0200 Subject: [PATCH 18/93] Working on fixing test errors - fixed pointer-dereference-indexed - 228/350 working. --- .../iterator/ProgramExpressionBinary.java | 56 +++++++++++++++++++ .../iterator/ProgramExpressionIterator.java | 17 +++--- .../passes/PassNAddNumberTypeConversions.java | 8 +-- 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java index d10a28ec4..ff1a8b9e0 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java @@ -269,4 +269,60 @@ public interface ProgramExpressionBinary extends ProgramExpression { getConstantBinary().setRight(new ConstantCastValue(toType, getConstantBinary().getRight())); } } + + /** Binary expression that is an indexed dereference of a pointer eg. ptr[i] or *(ptr+i). */ + class ProgramExpressionBinaryPointerDereferenceIndexed implements ProgramExpressionBinary { + /** A program value containing a {@link ConstantBinary}. */ + private ProgramValue programValue; + + public ProgramExpressionBinaryPointerDereferenceIndexed(ProgramValue programValue) { + this.programValue = programValue; + } + + public PointerDereferenceIndexed getPointerDereferenceIndexed() { + return (PointerDereferenceIndexed) programValue.get(); + } + + @Override + public RValue getLeft() { + return getPointerDereferenceIndexed().getPointer(); + } + + @Override + public OperatorBinary getOperator() { + return Operators.PLUS; + } + + @Override + public RValue getRight() { + return getPointerDereferenceIndexed().getIndex(); + } + + @Override + public void set(Value value) { + programValue.set(value); + } + + @Override + public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + if(getPointerDereferenceIndexed().getPointer() instanceof ConstantValue) { + getPointerDereferenceIndexed().setPointer(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getPointer())); + } else { + // Try to use CastValue - may later have to be supported! + getPointerDereferenceIndexed().setPointer(new CastValue(toType, getPointerDereferenceIndexed().getPointer())); + } + } + + @Override + public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + if(getPointerDereferenceIndexed().getIndex() instanceof ConstantValue) { + getPointerDereferenceIndexed().setIndex(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getIndex())); + } else { + // Try to use CastValue - may later have to be supported! + getPointerDereferenceIndexed().setIndex(new CastValue(toType, getPointerDereferenceIndexed().getIndex())); + } + } + } + + } diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java index e525c101f..c109a3001 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java @@ -7,6 +7,7 @@ import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementConditionalJump; import dk.camelot64.kickc.model.values.ConstantBinary; import dk.camelot64.kickc.model.values.ConstantUnary; +import dk.camelot64.kickc.model.values.PointerDereferenceIndexed; import java.util.ListIterator; @@ -25,13 +26,16 @@ public class ProgramExpressionIterator { */ public static void execute(Program program, ProgramExpressionHandler handler) { // Iterate all symbols - ProgramValueIterator.execute(program.getScope(), (programValue, currentStmt, stmtIt, currentBlock) -> { + ProgramValueHandler programValueHandler = (programValue, currentStmt, stmtIt, currentBlock) -> { if(programValue.get() instanceof ConstantBinary) { handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), null, null, null); } else if(programValue.get() instanceof ConstantUnary) { handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), null, null, null); + } else if(programValue.get() instanceof PointerDereferenceIndexed) { + handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), null, null, null); } - }); + }; + ProgramValueIterator.execute(program.getScope(), programValueHandler); // Iterate all blocks/statements for(ControlFlowBlock block : program.getGraph().getAllBlocks()) { @@ -53,14 +57,7 @@ public class ProgramExpressionIterator { } } // Iterate all statement values - ProgramValueIterator.execute(stmt, (programValue, currentStmt, stmtIt1, currentBlock) -> { - if(programValue.get() instanceof ConstantBinary) { - handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), stmt, stmtIt, block); - } else if(programValue.get() instanceof ConstantUnary) { - handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), stmt, stmtIt, block); - } - - }, stmtIt, block); + ProgramValueIterator.execute(stmt, programValueHandler, stmtIt, block); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java index 16688948f..6854e09b0 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java @@ -30,13 +30,13 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization { // Convert both left and right to the found type SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left); if(!leftType.equals(conversionType) && !(leftType instanceof SymbolTypePointer)) { - getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false)); - binary.addLeftCast(conversionType, stmtIt, currentBlock.getScope(), getScope()); + getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + (currentStmt==null?"":currentStmt.toString(getProgram(), false))); + binary.addLeftCast(conversionType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope()); } SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right); if(!rightType.equals(conversionType) && !(rightType instanceof SymbolTypePointer)) { - getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false)); - binary.addRightCast(conversionType, stmtIt, currentBlock.getScope(), getScope()); + getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false))); + binary.addRightCast(conversionType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope()); } } } From f6f25e728b8bf535aca33eb040dc4851717a8e6e Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 9 May 2019 07:43:47 +0200 Subject: [PATCH 19/93] Working on special word+byte downgrade. - down to 190/351. --- .../java/dk/camelot64/kickc/Compiler.java | 1 + .../passes/PassNAddTypeConversionsNew.java | 8 ++ .../passes/PassNDowngradeBytePlusWord.java | 91 +++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 74445a9ff..362b19c25 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -233,6 +233,7 @@ public class Compiler { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); optimizations.add(new PassNAddTypeConversionsNew(program)); optimizations.add(new PassNAddNumberTypeConversions(program)); + optimizations.add(new PassNDowngradeBytePlusWord(program)); optimizations.add(new PassNTypeInference(program)); optimizations.add(new PassNTypeIdSimplification(program)); optimizations.add(new Pass2CullEmptyBlocks(program)); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java index 0b1199cd6..4f4e3d1b6 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java @@ -35,6 +35,14 @@ public class PassNAddTypeConversionsNew extends Pass2SsaOptimization { if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) { SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType); if(conversionType != null && !SymbolType.NUMBER.equals(conversionType)) { + // If byte-like + word-like - skip!! + if(leftType.equals(SymbolType.WORD) && rightType.equals(SymbolType.BYTE)) { + return; + } + if(rightType.equals(SymbolType.WORD) && leftType.equals(SymbolType.BYTE)) { + return; + } + // Convert both left and right to the found type if(!leftType.equals(conversionType)) { getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false)); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java new file mode 100644 index 000000000..34182438b --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java @@ -0,0 +1,91 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; +import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.types.SymbolTypePointer; +import dk.camelot64.kickc.model.values.*; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Downgrade any number expression cast that are part of a WORD+NUMBER expression to BYTE if the number is small enough to fit in the byte. + */ +public class PassNDowngradeBytePlusWord extends Pass2SsaOptimization { + + public PassNDowngradeBytePlusWord(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean modified = new AtomicBoolean(false); + ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> { + if(binaryExpression instanceof ProgramExpressionBinary) { + ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression; + RValue left = binary.getLeft(); + RValue right = binary.getRight(); + if(isConstantWord(left) && isWordLike(right) && isByteLike((ConstantValue) left)) { + getLog().append("Downgrading number conversion cast to (byte) " + binary.getLeft().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); + binary.addLeftCast(SymbolType.BYTE, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); + modified.set(true); + } else if(isConstantWord(right) && isWordLike(left) && isByteLike((ConstantValue) right)) { + getLog().append("Downgrading number conversion cast to (byte) " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); + binary.addRightCast(SymbolType.BYTE, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); + modified.set(true); + } + + } + }); + return modified.get(); + } + + + /** + * Determines if a constant value is a byte-like value (can be represented inside a BYTE) + * + * @param constantValue The value to examine + * @return true if the value is a byte-like value + */ + public boolean isByteLike(ConstantValue constantValue) { + ConstantLiteral constantLiteral = (constantValue).calculateLiteral(getScope()); + if(constantLiteral instanceof ConstantInteger) { + ConstantInteger constantInteger = (ConstantInteger) constantLiteral; + Long value = constantInteger.getValue(); + if(SymbolType.BYTE.contains(value)) { + return true; + } + } + return false; + } + + /** + * Determines if a value is a word-like value (WORD or Pointer) + * + * @param rValue The value to examine + * @return true if the value is a word-like value + */ + public boolean isWordLike(RValue rValue) { + SymbolType symbolType = SymbolTypeInference.inferType(getProgram().getScope(), rValue); + return symbolType.equals(SymbolType.WORD) || symbolType instanceof SymbolTypePointer; + } + + + /** + * Determines if the passed value is a constant cast to WORD + * + * @param rValue The value to examine + * @return true if the value is a constant cast to word + */ + public boolean isConstantWord(RValue rValue) { + if(rValue instanceof ConstantInteger && ((ConstantInteger) rValue).getType().equals(SymbolType.WORD)) { + return true; + } + if((rValue instanceof ConstantCastValue) && ((ConstantCastValue) rValue).getToType().equals(SymbolType.WORD)) + return true; + return false; + } + +} From 51c10d29c38742152e99901a5e3cdfc0a3e4f729 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Fri, 10 May 2019 11:20:37 +0200 Subject: [PATCH 20/93] Working on fixing type conversion casting. Still a work in progress! --- .../model/types/SymbolTypeConversion.java | 12 +++++++--- .../passes/Pass2ConstantSimplification.java | 8 +++---- .../passes/PassNAddNumberTypeConversions.java | 24 +++++++++++-------- .../passes/PassNAddTypeConversionsNew.java | 2 ++ 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index 15c35ad73..9e136c58b 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -27,6 +27,7 @@ public class SymbolTypeConversion { * @return The type resulting from a binary operator performed on the two parameters */ public static SymbolType convertedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) { + // If any of the two types are unresolved - return an unresolved result if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) { return SymbolType.NUMBER; } @@ -57,7 +58,7 @@ public class SymbolTypeConversion { } /** - * Find the integer type that results from a binary operator according to the special number type conversion https://gitlab.com/camelot/kickc/issues/181 + * Find the integer type that a number operand in a binary operator should be converted/cast to according to number type conversion https://gitlab.com/camelot/kickc/issues/181 * * @param left The left value * @param right The right value @@ -65,7 +66,7 @@ public class SymbolTypeConversion { * @param currentStmt The current statement (used only for exception context) * @return a non-null fixed integer type if a number type conversion is relevant. */ - public static SymbolType convertedNumberType(RValue left, RValue right, ProgramScope symbols, Statement currentStmt) { + public static SymbolType getNumberCastType(RValue left, RValue right, ProgramScope symbols, Statement currentStmt) { SymbolType leftType = SymbolTypeInference.inferType(symbols, left); SymbolType rightType = SymbolTypeInference.inferType(symbols, right); @@ -80,6 +81,10 @@ public class SymbolTypeConversion { return null; } + // Treat pointers like WORD + if(leftType instanceof SymbolTypePointer) leftType = SymbolType.WORD; + if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD; + RValue numberVal; SymbolTypeIntegerFixed fixedType; if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) { @@ -125,7 +130,8 @@ public class SymbolTypeConversion { } else { smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value); } - return smallestUnsignedType.getBits() > fixedType.getBits() ? smallestUnsignedType : fixedType; + return smallestUnsignedType; + //return smallestUnsignedType.getBits() > fixedType.getBits() ? smallestUnsignedType : fixedType; } } else { throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java index 8b748d28e..cb4490626 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java @@ -29,13 +29,13 @@ public class Pass2ConstantSimplification extends Pass2SsaOptimization { // Found a candidate!! ConstantInteger intOperand = (ConstantInteger) unary.getOperand(); getLog().append("Simplifying constant integer increment "+unary); - programValue.set(new ConstantInteger(intOperand.getValue()+1)); + programValue.set(new ConstantInteger(intOperand.getValue()+1, intOperand.getType())); optimized[0] = true; } else if(Operators.DECREMENT.equals(unary.getOperator()) && unary.getOperand() instanceof ConstantInteger) { // Found a candidate!! ConstantInteger intOperand = (ConstantInteger) unary.getOperand(); getLog().append("Simplifying constant integer decrement "+unary); - programValue.set(new ConstantInteger(intOperand.getValue()+1)); + programValue.set(new ConstantInteger(intOperand.getValue()-1, intOperand.getType())); optimized[0] = true; } } else if(programValue.get() instanceof ConstantBinary) { @@ -43,10 +43,10 @@ public class Pass2ConstantSimplification extends Pass2SsaOptimization { if(Operators.MULTIPLY.equals(binary.getOperator())) { if(binary.getLeft() instanceof ConstantInteger && ((ConstantInteger) binary.getLeft()).getValue() == 0) { getLog().append("Simplifying constant multiply by zero " + binary); - programValue.set(new ConstantInteger(0L)); + programValue.set(new ConstantInteger(0L, binary.getType(getScope()))); } else if(binary.getRight() instanceof ConstantInteger && ((ConstantInteger) binary.getRight()).getValue() == 0) { getLog().append("Simplifying constant multiply by zero " + binary); - programValue.set(new ConstantInteger(0L)); + programValue.set(new ConstantInteger(0L, binary.getType(getScope()))); } } else if(Operators.PLUS.equals(binary.getOperator())) { if(binary.getLeft() instanceof ConstantInteger && ((ConstantInteger) binary.getLeft()).getValue() == 0) { diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java index 6854e09b0..7a69f1fd4 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java @@ -6,9 +6,10 @@ import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeConversion; import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypePointer; import dk.camelot64.kickc.model.values.RValue; +import java.util.concurrent.atomic.AtomicBoolean; + /** * Add casts to {@link SymbolType#NUMBER} expressions that meet a typed value in a binary expression (including assignment) */ @@ -20,28 +21,31 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization { @Override public boolean step() { + AtomicBoolean modified = new AtomicBoolean(false); ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> { if(binaryExpression instanceof ProgramExpressionBinary) { ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression; RValue left = binary.getLeft(); RValue right = binary.getRight(); - SymbolType conversionType = SymbolTypeConversion.convertedNumberType(left, right, getScope(), currentStmt); - if(conversionType != null) { + SymbolType castType = SymbolTypeConversion.getNumberCastType(left, right, getScope(), currentStmt); + if(castType != null) { // Convert both left and right to the found type SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left); - if(!leftType.equals(conversionType) && !(leftType instanceof SymbolTypePointer)) { - getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + (currentStmt==null?"":currentStmt.toString(getProgram(), false))); - binary.addLeftCast(conversionType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope()); + if(SymbolType.NUMBER.equals(leftType)) { + getLog().append("Adding number conversion cast (" + castType + ") " + binary.getLeft().toString() + " in " + (currentStmt==null?"":currentStmt.toString(getProgram(), false))); + binary.addLeftCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope()); + modified.set(true); } SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right); - if(!rightType.equals(conversionType) && !(rightType instanceof SymbolTypePointer)) { - getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false))); - binary.addRightCast(conversionType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope()); + if(rightType.equals(SymbolType.NUMBER)) { + getLog().append("Adding number conversion cast (" + castType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false))); + binary.addRightCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope()); + modified.set(true); } } } }); - return false; + return modified.get(); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java index 4f4e3d1b6..ee10bd5c5 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java @@ -32,6 +32,7 @@ public class PassNAddTypeConversionsNew extends Pass2SsaOptimization { binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope()); } + /* if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) { SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType); if(conversionType != null && !SymbolType.NUMBER.equals(conversionType)) { @@ -54,6 +55,7 @@ public class PassNAddTypeConversionsNew extends Pass2SsaOptimization { } } } + */ } }); return false; From 3c8845d6a6a751e314f52d5c60ca6e9db9dec536 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Sat, 11 May 2019 19:55:03 +0200 Subject: [PATCH 21/93] Added alias elimination to constant optimization phase. 255/351. --- src/main/java/dk/camelot64/kickc/Compiler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 362b19c25..9492c763b 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -299,6 +299,7 @@ public class Compiler { private void pass2InlineConstants() { // Constant inlining optimizations - as the last step to ensure that constant identification has been completed List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>(); + constantOptimizations.add(new Pass2AliasElimination(program)); constantOptimizations.add(new Pass2ConstantInlining(program)); constantOptimizations.add(new Pass2ConstantStringConsolidation(program)); constantOptimizations.add(new Pass2IdenticalPhiElimination(program)); From bd6ece561b3bf66a266380db6874f03bc7be2d09 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Sat, 11 May 2019 20:14:14 +0200 Subject: [PATCH 22/93] Fixed multiply to shift. 260/351. --- .../kickc/passes/Pass2MultiplyToShiftRewriting.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java b/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java index 123efd721..cad43daf9 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java @@ -6,14 +6,7 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; -import dk.camelot64.kickc.model.statements.StatementCall; -import dk.camelot64.kickc.model.statements.StatementCallPointer; -import dk.camelot64.kickc.model.symbols.ConstantVar; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeProcedure; import dk.camelot64.kickc.model.values.*; -import kickass.pass.expressions.expr.Constant; import java.util.ListIterator; @@ -34,7 +27,8 @@ public class Pass2MultiplyToShiftRewriting extends Pass2SsaOptimization { if(statement instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) statement; if(Operators.MULTIPLY.equals(assignment.getOperator()) || Operators.DIVIDE.equals(assignment.getOperator())) { - ConstantLiteral constantLiteral = getConstantLiteral(assignment); + if(assignment.getrValue1() instanceof ConstantValue) continue; + ConstantLiteral constantLiteral = getConstantLiteral2(assignment); if(constantLiteral instanceof ConstantInteger) { Long constantInt = ((ConstantInteger)constantLiteral).getInteger(); double power2 = Math.log(constantInt) / Math.log(2); @@ -72,7 +66,7 @@ public class Pass2MultiplyToShiftRewriting extends Pass2SsaOptimization { * @param assignment The Assignment * @return The constant literal value for RValue2 (or null) */ - private ConstantLiteral getConstantLiteral(StatementAssignment assignment) { + private ConstantLiteral getConstantLiteral2(StatementAssignment assignment) { if(assignment.getrValue2() instanceof ConstantValue) { ConstantValue constantValue = (ConstantValue) assignment.getrValue2(); try { From e56e66acd8d7b96b73e1f072d53fe473d63b6891 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Sat, 11 May 2019 23:16:03 +0200 Subject: [PATCH 23/93] Working on multiply/divide. --- .../dk/camelot64/kickc/model/operators/OperatorDivide.java | 3 +-- .../camelot64/kickc/model/operators/OperatorMultiply.java | 7 +++++++ .../kickc/passes/Pass0GenerateStatementSequence.java | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java index 3ce383230..f36dfdaca 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java @@ -29,11 +29,10 @@ public class OperatorDivide extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { if(left instanceof SymbolTypePointer) { - if(SymbolType.isByte(right) || SymbolType.isWord(right)) { + if(right.equals(SymbolType.BYTE) || right.equals(SymbolType.WORD)|| right.equals(SymbolType.NUMBER)) { return left; } else { throw new NoMatchingType("Cannot divide pointer by "+right.toString()); - } } // Handle numeric types through proper promotion diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java index 76bb36ec6..a4a98d455 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java @@ -22,6 +22,13 @@ public class OperatorMultiply extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + if(left instanceof SymbolTypePointer) { + if(right.equals(SymbolType.BYTE) || right.equals(SymbolType.WORD)|| right.equals(SymbolType.NUMBER)) { + return left; + } else { + throw new NoMatchingType("Cannot multiply pointer by "+right.toString()); + } + } // Handle numeric types through proper promotion if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 65afaf38f..34533b203 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -501,7 +501,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { } else { if(type instanceof SymbolTypeIntegerFixed) { // Add an zero value initializer - ConstantInteger zero = new ConstantInteger(0L); + ConstantInteger zero = new ConstantInteger(0L, type); Statement stmt = new StatementAssignment(lValue.getRef(), zero, new StatementSource(ctx), ensureUnusedComments(comments)); sequence.addStatement(stmt); } else if(type instanceof SymbolTypeArray) { From 6e566852bafe362e65782b00ace46e978476da49 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 12 May 2019 12:27:48 +0200 Subject: [PATCH 24/93] Fixed assignment type conversions and unnecesary byte/word casts. 269/351 --- .../java/dk/camelot64/kickc/Compiler.java | 4 +- .../model/types/SymbolTypeConversion.java | 46 +++++++++---- .../kickc/model/types/SymbolTypeMatch.java | 31 --------- .../kickc/passes/Pass2AssertTypeMatch.java | 4 +- .../Pass2ConstantCastSimplification.java | 20 +++++- .../passes/Pass2ConstantIdentification.java | 4 +- .../PassNAddTypeConversionAssignment.java | 57 ++++++++++++++++ .../passes/PassNAddTypeConversionsNew.java | 65 ------------------- .../passes/PassNDowngradeBytePlusWord.java | 1 - 9 files changed, 115 insertions(+), 117 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java delete mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 9492c763b..2e73baad4 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -165,7 +165,7 @@ public class Compiler { new Pass1FixLValuesLoHi(program).execute(); new Pass1AssertNoLValueIntermediate(program).execute(); new Pass1PointerSizeofFix(program).execute(); - new PassNAddTypeConversionsNew(program).execute(); + new PassNAddTypeConversionAssignment(program).execute(); new Pass1EarlyConstantIdentification(program).execute(); new PassNStatementIndices(program).step(); new PassNCallGraphAnalysis(program).step(); @@ -231,7 +231,7 @@ public class Compiler { private void pass2Optimize() { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); - optimizations.add(new PassNAddTypeConversionsNew(program)); + optimizations.add(new PassNAddTypeConversionAssignment(program)); optimizations.add(new PassNAddNumberTypeConversions(program)); optimizations.add(new PassNDowngradeBytePlusWord(program)); optimizations.add(new PassNTypeInference(program)); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index 9e136c58b..f1663a6b8 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -85,6 +85,7 @@ public class SymbolTypeConversion { if(leftType instanceof SymbolTypePointer) leftType = SymbolType.WORD; if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD; + // Identify which of the two operands is a number and which is a fixed type RValue numberVal; SymbolTypeIntegerFixed fixedType; if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) { @@ -95,19 +96,12 @@ public class SymbolTypeConversion { // Right is the number type - left is the fixed type numberVal = right; fixedType = (SymbolTypeIntegerFixed) leftType; - } else if(SymbolType.NUMBER.equals(leftType) && rightType instanceof SymbolTypePointer) { - // Left is the number type - right is a pointer (effectively unsigned word) - numberVal = left; - fixedType = SymbolType.WORD; - } else if(SymbolType.NUMBER.equals(rightType) && leftType instanceof SymbolTypePointer) { - // Right is the number type - left is a pointer (effectively unsigned word) - numberVal = right; - fixedType = SymbolType.WORD; } else { // Binary operator combining number and non-integer return null; } + // Find the cast type if possible if(numberVal instanceof ConstantValue) { ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols); if(constantLiteral instanceof ConstantInteger) { @@ -115,14 +109,14 @@ public class SymbolTypeConversion { if(SymbolType.NUMBER.equals(constantInteger.getType())) { Long value = constantInteger.getValue(); if(fixedType.isSigned()) { - // b) If one operand is a signed type and the other a number they are both converted to the smallest signed type that can hold the values. + // b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values. SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value); if(smallestSignedType == null) { throw new CompileError("Number constant has value that cannot be represented by a signed type " + value, currentStmt); } - return smallestSignedType.getBits() > fixedType.getBits() ? smallestSignedType : fixedType; + return smallestSignedType; } else { - // c) If one operand is an unsigned type and the other a number they are both converted to the smallest unsigned type that can hold the values. + // b) If one operand is a signed type and the other a number the number is converted to the smallest unsigned type that can hold its values. // If the number value is negative it is converted to unsigned using two's complement. SymbolTypeIntegerFixed smallestUnsignedType; if(value < 0) { @@ -131,7 +125,6 @@ public class SymbolTypeConversion { smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value); } return smallestUnsignedType; - //return smallestUnsignedType.getBits() > fixedType.getBits() ? smallestUnsignedType : fixedType; } } else { throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt); @@ -145,4 +138,33 @@ public class SymbolTypeConversion { // No number conversion return null; } + + /** + * Determines if the types of an assignment match up properly + * @param lValueType The type of the LValue + * @param rValueType The type of the RValue + * @return true if the types match up + */ + public static boolean assignmentTypeMatch(SymbolType lValueType, SymbolType rValueType) { + if(lValueType.equals(rValueType)) + return true; + if(lValueType.equals(SymbolType.WORD) && rValueType.equals(SymbolType.BYTE)) + return true; + if(lValueType.equals(SymbolType.SWORD) && rValueType.equals(SymbolType.SBYTE)) + return true; + if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) { + // L-value is still a number - constants are probably not done being identified & typed + return true; + } + if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) { + // String value can be assigned into a pointer + return true; + } + if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && assignmentTypeMatch(((SymbolTypePointer) lValueType).getElementType(), ((SymbolTypePointer) rValueType).getElementType())) { + // Pointer types assigned from each other + // TODO: Maybe handle sizes + return true; + } + return false; + } } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java deleted file mode 100644 index b058abbb2..000000000 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java +++ /dev/null @@ -1,31 +0,0 @@ -package dk.camelot64.kickc.model.types; - -/** Container for function checking if types of an assignment match up */ -public class SymbolTypeMatch { - - /** - * Determines if the types of an assignment match up properly - * @param lValueType The type of the LValue - * @param rValueType The type of the RValue - * @return true if the types match up - */ - public static boolean assignmentTypeMatch(SymbolType lValueType, SymbolType rValueType) { - if(lValueType.equals(rValueType)) { - return true; - } - if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) { - // L-value is still a number - constants are probably not done being identified & typed - return true; - } - if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) { - // String value can be assigned into a pointer - return true; - } - if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && assignmentTypeMatch(((SymbolTypePointer) lValueType).getElementType(), ((SymbolTypePointer) rValueType).getElementType())) { - // Pointer types assigned from each other - // TODO: Maybe handle sizes - return true; - } - return false; - } -} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java index 82c5fce43..5e9e3157d 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java @@ -7,8 +7,8 @@ import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementConditionalJump; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeConversion; import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypeMatch; import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.RValue; @@ -51,7 +51,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion { LValue lValue = statement.getlValue(); SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue); SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), statement); - if(SymbolTypeMatch.assignmentTypeMatch(lValueType, rValueType)) return; + if(SymbolTypeConversion.assignmentTypeMatch(lValueType, rValueType)) return; // Types do not match getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false)); throw new CompileError("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java index 893003447..b8daf00a8 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java @@ -28,10 +28,10 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization { if(programExpression.getOperator() instanceof OperatorCast) { OperatorCast operatorCast = (OperatorCast) programExpression.getOperator(); ProgramExpressionUnary unary = (ProgramExpressionUnary) programExpression; + SymbolType castType = operatorCast.getToType(); if(unary.getOperand() instanceof ConstantInteger) { ConstantInteger constantInteger = (ConstantInteger) unary.getOperand(); if(SymbolType.NUMBER.equals(constantInteger.getType())) { - SymbolType castType = operatorCast.getToType(); if(castType instanceof SymbolTypeIntegerFixed ) { ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); programExpression.set(newConstInt); @@ -43,6 +43,14 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization { getLog().append("Simplifying constant pointer cast " + newConstPointer.toString()); optimized.set(true); } + } else if(castType instanceof SymbolTypeIntegerFixed) { + if(((SymbolTypeIntegerFixed) castType).contains(constantInteger.getValue())) { + // Cast type contains the value - cast not needed + ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); + programExpression.set(newConstInt); + getLog().append("Simplifying constant integer cast " + newConstInt.toString()); + optimized.set(true); + } } } } @@ -52,8 +60,8 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization { ConstantCastValue constantCastValue = (ConstantCastValue) programValue.get(); if(constantCastValue.getValue() instanceof ConstantInteger) { ConstantInteger constantInteger = (ConstantInteger) constantCastValue.getValue(); + SymbolType castType = constantCastValue.getToType(); if(SymbolType.NUMBER.equals(constantInteger.getType())) { - SymbolType castType = constantCastValue.getToType(); if(castType instanceof SymbolTypeIntegerFixed ) { ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); programValue.set(newConstInt); @@ -65,6 +73,14 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization { getLog().append("Simplifying constant pointer cast " + newConstPointer.toString()); optimized.set(true); } + } else if(castType instanceof SymbolTypeIntegerFixed) { + if(((SymbolTypeIntegerFixed) castType).contains(constantInteger.getValue())) { + // Cast type contains the value - cast not needed + ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); + programValue.set(newConstInt); + getLog().append("Simplifying constant integer cast " + newConstInt.toString()); + optimized.set(true); + } } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java index d4df53443..be3634d84 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java @@ -15,8 +15,8 @@ import dk.camelot64.kickc.model.symbols.ProgramScope; 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.SymbolTypeConversion; import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypeMatch; import dk.camelot64.kickc.model.values.*; import java.util.LinkedHashMap; @@ -79,7 +79,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { continue; } - if(!SymbolTypeMatch.assignmentTypeMatch(variableType, valueType)) { + if(!SymbolTypeConversion.assignmentTypeMatch(variableType, valueType)) { throw new CompileError( "Constant variable has a non-matching type \n variable: " + variable.toString(getProgram()) + "\n value: (" + valueType.toString() + ") " + constVal.calculateLiteral(getScope()) + diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java new file mode 100644 index 000000000..e2f2049c0 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java @@ -0,0 +1,57 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; +import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; +import dk.camelot64.kickc.model.types.*; +import dk.camelot64.kickc.model.values.RValue; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Add a cast a variable is assigned something of a convertible type. + * Also allows pointers to be assigned integer values. + */ +public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization { + + public PassNAddTypeConversionAssignment(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean modified = new AtomicBoolean(false); + ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> { + if(programExpression instanceof ProgramExpressionBinary) { + ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression; + RValue left = binary.getLeft(); + RValue right = binary.getRight(); + SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left); + SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right); + + if(!SymbolTypeConversion.assignmentTypeMatch(leftType, rightType)) { + // Assigning a pointer from an unsigned word + if(programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue) { + if((leftType instanceof SymbolTypePointer) && SymbolType.isInteger(rightType)) { + getLog().append("Adding pointer type conversion cast (" + leftType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false)); + binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope()); + modified.set(true); + } + } + if(leftType instanceof SymbolTypeIntegerFixed && SymbolType.isInteger(rightType)) { + SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType); + // Add cast to the right Type if needed + if(leftType.equals(conversionType) && !rightType.equals(conversionType)) { + getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); + binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); + modified.set(true); + } + } + } + } + }); + return modified.get(); + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java deleted file mode 100644 index ee10bd5c5..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java +++ /dev/null @@ -1,65 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; -import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; -import dk.camelot64.kickc.model.types.*; -import dk.camelot64.kickc.model.values.RValue; - -/** - * Add casts in binary expressions where left/right types are not equal according to the C99 type conversion rules - * 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70. - */ -public class PassNAddTypeConversionsNew extends Pass2SsaOptimization { - - public PassNAddTypeConversionsNew(Program program) { - super(program); - } - - @Override - public boolean step() { - ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> { - if(programExpression instanceof ProgramExpressionBinary) { - ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression; - RValue left = binary.getLeft(); - RValue right = binary.getRight(); - SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left); - SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right); - - // Special handling of assigning a pointer from an unsigned word - if((programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue) && (leftType instanceof SymbolTypePointer) && SymbolType.isInteger(rightType)) { - getLog().append("Adding pointer type conversion cast (" + leftType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false)); - binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope()); - } - - /* - if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) { - SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType); - if(conversionType != null && !SymbolType.NUMBER.equals(conversionType)) { - // If byte-like + word-like - skip!! - if(leftType.equals(SymbolType.WORD) && rightType.equals(SymbolType.BYTE)) { - return; - } - if(rightType.equals(SymbolType.WORD) && leftType.equals(SymbolType.BYTE)) { - return; - } - - // Convert both left and right to the found type - if(!leftType.equals(conversionType)) { - getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false)); - binary.addLeftCast(conversionType, stmtIt, currentBlock.getScope(), getScope()); - } - if(!rightType.equals(conversionType)) { - getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false)); - binary.addRightCast(conversionType, stmtIt, currentBlock.getScope(), getScope()); - } - } - } - */ - } - }); - return false; - } - - -} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java index 34182438b..b3f819d53 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java @@ -42,7 +42,6 @@ public class PassNDowngradeBytePlusWord extends Pass2SsaOptimization { return modified.get(); } - /** * Determines if a constant value is a byte-like value (can be represented inside a BYTE) * From e09d81cd132b50c0ed75ef55d3818082cc76fb76 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 12 May 2019 12:59:47 +0200 Subject: [PATCH 25/93] Improved no-cast detection. 271/351 --- .../camelot64/kickc/fragment/AsmFormat.java | 46 +++++++++++-------- .../Pass2ConstantCastSimplification.java | 4 +- .../dk/camelot64/kickc/test/TestPrograms.java | 2 +- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java index 895e806a8..26db72078 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java @@ -114,12 +114,14 @@ public class AsmFormat { // No cast needed return getAsmConstant(program, operand, outerPrecedence, codeScope); } - if(SymbolType.NUMBER.equals(operandType)) { - List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand); - if(operandInferedTypes.contains(SymbolType.BYTE) || operandInferedTypes.contains(SymbolType.SBYTE)) { - // No cast needed - return getAsmConstant(program, operand, outerPrecedence, codeScope); - } + ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope()); + if(constantLiteral instanceof ConstantInteger && Operators.CAST_BYTE.equals(operator) && SymbolType.BYTE.contains(((ConstantInteger) constantLiteral).getValue())) { + // No cast needed + return getAsmConstant(program, operand, outerPrecedence, codeScope); + } + if(constantLiteral instanceof ConstantInteger && Operators.CAST_SBYTE.equals(operator) && SymbolType.SBYTE.contains(((ConstantInteger) constantLiteral).getValue())) { + // No cast needed + return getAsmConstant(program, operand, outerPrecedence, codeScope); } // Cast is needed return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xff), Operators.BOOL_AND, operand), outerPrecedence, codeScope); @@ -129,12 +131,18 @@ public class AsmFormat { // No cast needed return getAsmConstant(program, operand, outerPrecedence, codeScope); } - if(SymbolType.NUMBER.equals(operandType)) { - List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand); - if(operandInferedTypes.contains(SymbolType.WORD) || operandInferedTypes.contains(SymbolType.SWORD)) { - // No cast needed - return getAsmConstant(program, operand, outerPrecedence, codeScope); - } + ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope()); + if(constantLiteral instanceof ConstantInteger && Operators.CAST_WORD.equals(operator)&& SymbolType.WORD.contains(((ConstantInteger) constantLiteral).getValue())) { + // No cast needed + return getAsmConstant(program, operand, outerPrecedence, codeScope); + } + if(constantLiteral instanceof ConstantInteger && Operators.CAST_SWORD.equals(operator)&& SymbolType.SWORD.contains(((ConstantInteger) constantLiteral).getValue())) { + // No cast needed + return getAsmConstant(program, operand, outerPrecedence, codeScope); + } + if(constantLiteral instanceof ConstantInteger && (operator instanceof OperatorCastPtr) && SymbolType.WORD.contains(((ConstantInteger) constantLiteral).getValue())) { + // No cast needed + return getAsmConstant(program, operand, outerPrecedence, codeScope); } // Cast is needed return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffff), Operators.BOOL_AND, operand), outerPrecedence, codeScope); @@ -144,12 +152,14 @@ public class AsmFormat { // No cast needed return getAsmConstant(program, operand, outerPrecedence, codeScope); } - if(SymbolType.NUMBER.equals(operandType)) { - List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand); - if(operandInferedTypes.contains(SymbolType.DWORD) || operandInferedTypes.contains(SymbolType.SDWORD)) { - // No cast needed - return getAsmConstant(program, operand, outerPrecedence, codeScope); - } + ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope()); + if(constantLiteral instanceof ConstantInteger && Operators.CAST_DWORD.equals(operator)&& SymbolType.DWORD.contains(((ConstantInteger) constantLiteral).getValue())) { + // No cast needed + return getAsmConstant(program, operand, outerPrecedence, codeScope); + } + if(constantLiteral instanceof ConstantInteger && Operators.CAST_SDWORD.equals(operator)&& SymbolType.SDWORD.contains(((ConstantInteger) constantLiteral).getValue())) { + // No cast needed + return getAsmConstant(program, operand, outerPrecedence, codeScope); } // Cast is needed return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffffffffL), Operators.BOOL_AND, operand), outerPrecedence, codeScope); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java index b8daf00a8..0d516f99e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java @@ -8,9 +8,7 @@ import dk.camelot64.kickc.model.operators.OperatorCast; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.values.ConstantCastValue; -import dk.camelot64.kickc.model.values.ConstantInteger; -import dk.camelot64.kickc.model.values.ConstantPointer; +import dk.camelot64.kickc.model.values.*; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 6a0063197..100a0e868 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -49,7 +49,7 @@ public class TestPrograms { @Test public void testNumberType() throws IOException, URISyntaxException { - compileAndCompare("number-type", log()); + compileAndCompare("number-type"); } @Test From 8db7736830746b2f5999ecfc9cea4169fa3b67ac Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 12 May 2019 13:51:36 +0200 Subject: [PATCH 26/93] Improved no-cast detection. 273/351 --- .../camelot64/kickc/model/types/SymbolTypeConversion.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index f1663a6b8..88dd99c38 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -150,8 +150,16 @@ public class SymbolTypeConversion { return true; if(lValueType.equals(SymbolType.WORD) && rValueType.equals(SymbolType.BYTE)) return true; + if(lValueType.equals(SymbolType.DWORD) && rValueType.equals(SymbolType.BYTE)) + return true; + if(lValueType.equals(SymbolType.DWORD) && rValueType.equals(SymbolType.WORD)) + return true; if(lValueType.equals(SymbolType.SWORD) && rValueType.equals(SymbolType.SBYTE)) return true; + if(lValueType.equals(SymbolType.SDWORD) && rValueType.equals(SymbolType.SBYTE)) + return true; + if(lValueType.equals(SymbolType.SDWORD) && rValueType.equals(SymbolType.SWORD)) + return true; if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) { // L-value is still a number - constants are probably not done being identified & typed return true; From ef05cc8c3bd1ecbe52a13ab33f8356534024d7df Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 12 May 2019 13:56:04 +0200 Subject: [PATCH 27/93] Eliminating SymbolTypeMulti - 273/351 --- .../kickc/model/types/SymbolType.java | 48 +++---------------- .../kickc/model/types/SymbolTypeMulti.java | 1 - 2 files changed, 6 insertions(+), 43 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java index 2d6c20a6b..71e41be30 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java @@ -113,13 +113,7 @@ public interface SymbolType { * @return true if the type is BYTE compatible */ static boolean isByte(SymbolType type) { - if(BYTE.equals(type)) { - return true; - } else if(type instanceof SymbolTypeMulti) { - return ((SymbolTypeMulti) type).isByte(); - } else { - return false; - } + return BYTE.equals(type); } /** @@ -129,13 +123,7 @@ public interface SymbolType { * @return true if the type is SBYTE compatible */ static boolean isSByte(SymbolType type) { - if(SBYTE.equals(type)) { - return true; - } else if(type instanceof SymbolTypeMulti) { - return ((SymbolTypeMulti) type).isSByte(); - } else { - return false; - } + return SBYTE.equals(type); } /** @@ -145,13 +133,7 @@ public interface SymbolType { * @return true if the type is WORD compatible */ static boolean isWord(SymbolType type) { - if(WORD.equals(type)) { - return true; - } else if(type instanceof SymbolTypeMulti) { - return ((SymbolTypeMulti) type).isWord(); - } else { - return false; - } + return WORD.equals(type); } /** @@ -161,13 +143,7 @@ public interface SymbolType { * @return true if the type is SWORD compatible */ static boolean isSWord(SymbolType type) { - if(SWORD.equals(type)) { - return true; - } else if(type instanceof SymbolTypeMulti) { - return ((SymbolTypeMulti) type).isSWord(); - } else { - return false; - } + return SWORD.equals(type); } /** @@ -177,13 +153,7 @@ public interface SymbolType { * @return true if the type is DWORD compatible */ static boolean isDWord(SymbolType type) { - if(DWORD.equals(type)) { - return true; - } else if(type instanceof SymbolTypeMulti) { - return ((SymbolTypeMulti) type).isDWord(); - } else { - return false; - } + return DWORD.equals(type); } /** @@ -193,13 +163,7 @@ public interface SymbolType { * @return true if the type is SDWORD compatible */ static boolean isSDWord(SymbolType type) { - if(SDWORD.equals(type)) { - return true; - } else if(type instanceof SymbolTypeMulti) { - return ((SymbolTypeMulti) type).isSWord(); - } else { - return false; - } + return SDWORD.equals(type); } /** diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java index f3438573e..9c0b8924e 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java @@ -1,6 +1,5 @@ package dk.camelot64.kickc.model.types; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; From 7767c1216b8910003b3d8baac2eb3fc05a51db01 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 12 May 2019 14:32:16 +0200 Subject: [PATCH 28/93] Added missing fragment - 274/351 --- src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm | 6 +++++ .../fragment/AsmFragmentInstanceSpec.java | 26 +++++++++---------- .../types/SymbolTypeNumberInference.java | 25 +++++++++++------- 3 files changed, 35 insertions(+), 22 deletions(-) create mode 100644 src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm diff --git a/src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm b/src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm new file mode 100644 index 000000000..92a07250f --- /dev/null +++ b/src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm @@ -0,0 +1,6 @@ +sec +sbc #{c1} +bvc !+ +eor #$80 +!: +bmi {la1} diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java index 539207338..09d9be44f 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java @@ -3,11 +3,9 @@ package dk.camelot64.kickc.fragment; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypeMulti; -import dk.camelot64.kickc.model.values.ConstantValue; -import dk.camelot64.kickc.model.values.ScopeRef; -import dk.camelot64.kickc.model.values.Value; +import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; +import dk.camelot64.kickc.model.types.SymbolTypeNumberInference; +import dk.camelot64.kickc.model.values.*; import java.util.*; @@ -38,6 +36,7 @@ public class AsmFragmentInstanceSpec { /** * Creates an asm fragment instance specification. + * * @param program The symbol table * @param signature The fragment signature. * @param bindings Binding of named values in the fragment to values (constants, variables, ...) @@ -70,7 +69,7 @@ public class AsmFragmentInstanceSpec { private ConstantValue variationConstant; /** When iterating variations this is iterates the potential types for the constant value. */ - private Iterator<SymbolType> variationIterator; + private Iterator<SymbolTypeIntegerFixed> variationIterator; /** The name of the current variation in the bindings. */ private String variationCurrentName; @@ -82,10 +81,11 @@ public class AsmFragmentInstanceSpec { * Does any more variations of the ASM fragment instance specification exist? * Variations are used for finding the right fragment to use for constant numbers. * For instance the number 1000 can be represented as several different types (unsigned/signed word/dword). + * * @return true if more variations exits */ public boolean hasNextVariation() { - if(variationIterator==null) { + if(variationIterator == null) { // Look for variations // TODO Currently only one iterable constant value is handled - add support for multiple iterable constant values! for(String name : bindings.keySet()) { @@ -93,9 +93,9 @@ public class AsmFragmentInstanceSpec { // Found a constant value that may be multi-typed Value value = bindings.get(name); if(value instanceof ConstantValue) { - SymbolType symbolType = SymbolTypeInference.inferType(program.getScope(), (ConstantValue) value); - if(symbolType instanceof SymbolTypeMulti) { - Collection<SymbolType> types = ((SymbolTypeMulti) symbolType).getTypes(); + ConstantLiteral constantLiteral = ((ConstantValue) value).calculateLiteral(program.getScope()); + if(constantLiteral instanceof ConstantInteger) { + List<SymbolTypeIntegerFixed> types = SymbolTypeNumberInference.inferTypes(((ConstantInteger) constantLiteral).getValue()); if(types.size() > 1) { // Found constant value with multiple types variationConstant = (ConstantValue) value; @@ -111,7 +111,7 @@ public class AsmFragmentInstanceSpec { } // If no variations exist add empty iterator if(variationIterator == null) { - List<SymbolType> empty = new ArrayList<>(); + List<SymbolTypeIntegerFixed> empty = new ArrayList<>(); variationIterator = empty.iterator(); } } @@ -126,7 +126,7 @@ public class AsmFragmentInstanceSpec { if(hasNextVariation()) { SymbolType nextVariationValue = variationIterator.next(); // Find the next name - String variationConstName = "c"+variationCurrentName.substring(variationCurrentName.length() - 1); + String variationConstName = "c" + variationCurrentName.substring(variationCurrentName.length() - 1); String variationNextName = AsmFragmentInstanceSpecFactory.getTypePrefix(nextVariationValue) + variationConstName; // Update bindings Value constValue = bindings.get(variationCurrentName); @@ -136,7 +136,7 @@ public class AsmFragmentInstanceSpec { this.signature = signature.replace(variationCurrentName, variationNextName); variationCurrentName = variationNextName; variationCurrentValue = nextVariationValue; - } else { + } else { this.signature = "no-more-variations"; this.bindings = new LinkedHashMap<>(); } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java index acef7130b..983e6a21f 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java @@ -97,18 +97,25 @@ public class SymbolTypeNumberInference { */ public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantLiteral literal) { if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) { - ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>(); - ConstantInteger constantInteger = (ConstantInteger) literal; - Long number = constantInteger.getValue(); - for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) { - if(typeInteger.contains(number)) { - potentialTypes.add(typeInteger); - } - } - return potentialTypes; + return inferTypes(((ConstantInteger) literal).getValue()); } else { throw new InternalError("Literal must number type."); } } + /** + * Find any fixed integer types that can contain the passed integer value + * @param value the value to examine + * @return All fixed size integer types capable of representing the passed value + */ + public static List<SymbolTypeIntegerFixed> inferTypes(Long value) { + ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>(); + for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) { + if(typeInteger.contains(value)) { + potentialTypes.add(typeInteger); + } + } + return potentialTypes; + } + } From 07b67efb7ce4c7bd5ed24b14f7bc6c3ed8f72a8d Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 12 May 2019 14:42:41 +0200 Subject: [PATCH 29/93] Eliminating SymbolTypeMulti - 274/351 --- .../camelot64/kickc/fragment/AsmFormat.java | 20 +++---- .../kickc/fragment/AsmFragmentInstance.java | 2 +- .../AsmFragmentInstanceSpecFactory.java | 24 ++++---- .../kickc/model/operators/OperatorDWord.java | 6 +- .../model/operators/OperatorGetHigh.java | 8 +-- .../kickc/model/operators/OperatorGetLow.java | 8 +-- .../kickc/model/operators/OperatorPlus.java | 6 +- .../model/operators/OperatorSetHigh.java | 12 ++-- .../kickc/model/operators/OperatorSetLow.java | 8 +-- .../kickc/model/operators/OperatorSizeOf.java | 15 ++--- .../kickc/model/operators/OperatorTypeId.java | 36 +---------- .../kickc/model/operators/OperatorWord.java | 3 +- .../kickc/model/types/SymbolType.java | 60 ------------------- .../model/types/SymbolTypeInference.java | 4 +- .../passes/Pass2FixInlineConstructors.java | 4 +- .../kickc/passes/Pass2NopCastElimination.java | 10 ++-- .../kickc/passes/Pass4CodeGeneration.java | 18 +++--- .../kickc/passes/Pass4RegistersFinalize.java | 12 ++-- 18 files changed, 79 insertions(+), 177 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java index 26db72078..331c51337 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java @@ -10,8 +10,6 @@ import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.*; -import java.util.List; - /** Formatting of numbers, constants, names and more for KickAssembler */ public class AsmFormat { @@ -165,22 +163,22 @@ public class AsmFormat { return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffffffffL), Operators.BOOL_AND, operand), outerPrecedence, codeScope); } else if(Operators.LOWBYTE.equals(operator)) { SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand); - if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) { + if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) { return getAsmConstant(program, operand, outerPrecedence, codeScope); - } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) { + } else if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) { return "<" + getAsmConstant(program, operand, outerPrecedence, codeScope); - } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) { + } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) { return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_AND, new ConstantInteger((long) 0xffff)), outerPrecedence, codeScope); } else { throw new CompileError("Unhandled type " + operand); } } else if(Operators.HIBYTE.equals(operator)) { SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand); - if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) { + if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) { return getAsmConstant(program, new ConstantInteger(0l), outerPrecedence, codeScope); - } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) { + } else if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) { return ">" + getAsmConstant(program, operand, outerPrecedence, codeScope); - } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) { + } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) { return getAsmConstant(program, new ConstantBinary(operand, Operators.SHIFT_RIGHT, new ConstantInteger((long) 16)), outerPrecedence, codeScope); } else { throw new CompileError("Unhandled type " + operand); @@ -191,11 +189,11 @@ public class AsmFormat { return getAsmConstant(program, new ConstantBinary(operand, Operators.MINUS, new ConstantInteger((long) 1)), outerPrecedence, codeScope); } else if(Operators.BOOL_NOT.equals(operator)) { SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand); - if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) { + if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) { return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xff)), outerPrecedence, codeScope); - } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) { + } else if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) { return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xffff)), outerPrecedence, codeScope); - } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) { + } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) { return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xffffffff)), outerPrecedence, codeScope); } else { throw new CompileError("Unhandled type " + operand); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java index 9a34ffe2a..53793f4c9 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java @@ -301,7 +301,7 @@ public class AsmFragmentInstance { public AsmParameter visitAsmExprInt(KickCParser.AsmExprIntContext ctx) { Number number = NumberParser.parseLiteral(ctx.NUMBER().getText()); ConstantInteger intVal = new ConstantInteger(number.longValue()); - boolean isZp = SymbolType.isByte(intVal.getType()) || SymbolType.isSByte(intVal.getType()); + boolean isZp = SymbolType.BYTE.equals(intVal.getType()) || SymbolType.SBYTE.equals(intVal.getType()); String param = AsmFormat.getAsmNumber(number); return new AsmParameter(param, isZp); } diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java index 396ec781e..de00e8edf 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java @@ -288,17 +288,17 @@ public class AsmFragmentInstanceSpecFactory { * @return The type name */ static String getTypePrefix(SymbolType type) { - if(SymbolType.isByte(type)) { + if(SymbolType.BYTE.equals(type)) { return "vbu"; - } else if(SymbolType.isSByte(type)) { + } else if(SymbolType.SBYTE.equals(type)) { return "vbs"; - } else if(SymbolType.isWord(type)) { + } else if(SymbolType.WORD.equals(type)) { return "vwu"; - } else if(SymbolType.isSWord(type)) { + } else if(SymbolType.SWORD.equals(type)) { return "vws"; - } else if(SymbolType.isDWord(type)) { + } else if(SymbolType.DWORD.equals(type)) { return "vdu"; - } else if(SymbolType.isSDWord(type)) { + } else if(SymbolType.SDWORD.equals(type)) { return "vds"; } else if(SymbolType.STRING.equals(type)) { return "pbu"; @@ -306,17 +306,17 @@ public class AsmFragmentInstanceSpecFactory { return "vbo"; } else if(type instanceof SymbolTypePointer) { SymbolType elementType = ((SymbolTypePointer) type).getElementType(); - if(SymbolType.isByte(elementType)) { + if(SymbolType.BYTE.equals(elementType)) { return "pbu"; - } else if(SymbolType.isSByte(elementType)) { + } else if(SymbolType.SBYTE.equals(elementType)) { return "pbs"; - } else if(SymbolType.isWord(elementType)) { + } else if(SymbolType.WORD.equals(elementType)) { return "pwu"; - } else if(SymbolType.isSWord(elementType)) { + } else if(SymbolType.SWORD.equals(elementType)) { return "pws"; - } else if(SymbolType.isDWord(elementType)) { + } else if(SymbolType.DWORD.equals(elementType)) { return "pdu"; - } else if(SymbolType.isSDWord(elementType)) { + } else if(SymbolType.SDWORD.equals(elementType)) { return "pds"; } else if(SymbolType.BOOLEAN.equals(elementType)) { return "pbo"; diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java index c713d3255..b0e06378c 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java @@ -32,13 +32,13 @@ public class OperatorDWord extends OperatorBinary { if(right instanceof SymbolTypePointer) { right = SymbolType.WORD; } - if(SymbolType.isByte(left)) { + if(SymbolType.BYTE.equals(left)) { left = SymbolType.WORD; } - if(SymbolType.isByte(right)) { + if(SymbolType.BYTE.equals(right)) { right = SymbolType.WORD; } - if(SymbolType.isWord(left) && SymbolType.isWord(right)) { + if(SymbolType.WORD.equals(left) && SymbolType.WORD.equals(right)) { return SymbolType.DWORD; } throw new NoMatchingType("DWord constructor cannot use " + left + " " + getOperator() + " " + right); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java index 81aad2e0e..d28f2f49f 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java @@ -22,9 +22,9 @@ public class OperatorGetHigh extends OperatorUnary { public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { if(operand instanceof ConstantInteger) { ConstantInteger operandInt = (ConstantInteger) operand; - if(SymbolType.isWord(operandInt.getType()) || SymbolType.isSWord(operandInt.getType())) { + if(SymbolType.WORD.equals(operandInt.getType()) || SymbolType.SWORD.equals(operandInt.getType())) { return new ConstantInteger(operandInt.getInteger()>>8); - } else if(SymbolType.isDWord(operandInt.getType()) || SymbolType.isSDWord(operandInt.getType())) { + } else if(SymbolType.DWORD.equals(operandInt.getType()) || SymbolType.SDWORD.equals(operandInt.getType())) { return new ConstantInteger(operandInt.getInteger()>>16); } } else if(operand instanceof ConstantPointer) { @@ -37,9 +37,9 @@ public class OperatorGetHigh extends OperatorUnary { @Override public SymbolType inferType(SymbolTypeSimple operandType) { - if(operandType instanceof SymbolTypePointer || SymbolType.isWord(operandType) || SymbolType.isSWord(operandType)) { + if(operandType instanceof SymbolTypePointer || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType)) { return SymbolType.BYTE; - } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) { + } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) { return SymbolType.WORD; } else if(SymbolType.STRING.equals(operandType)) { return SymbolType.BYTE; diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java index 81fc490c0..c05e748d4 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java @@ -22,9 +22,9 @@ public class OperatorGetLow extends OperatorUnary { public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { if(operand instanceof ConstantInteger) { ConstantInteger operandInt = (ConstantInteger) operand; - if(SymbolType.isWord(operandInt.getType()) || SymbolType.isSWord(operandInt.getType())) { + if(SymbolType.WORD.equals(operandInt.getType()) || SymbolType.SWORD.equals(operandInt.getType())) { return new ConstantInteger(operandInt.getInteger()&0xff); - } else if(SymbolType.isDWord(operandInt.getType()) || SymbolType.isSDWord(operandInt.getType())) { + } else if(SymbolType.DWORD.equals(operandInt.getType()) || SymbolType.SDWORD.equals(operandInt.getType())) { return new ConstantInteger(operandInt.getInteger()&0xffff); } } else if(operand instanceof ConstantPointer) { @@ -37,9 +37,9 @@ public class OperatorGetLow extends OperatorUnary { @Override public SymbolType inferType(SymbolTypeSimple operandType) { - if(operandType instanceof SymbolTypePointer || SymbolType.isWord(operandType) || SymbolType.isSWord(operandType)) { + if(operandType instanceof SymbolTypePointer || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType)) { return SymbolType.BYTE; - } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) { + } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) { return SymbolType.WORD; } else if(SymbolType.STRING.equals(operandType)) { return SymbolType.BYTE; diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java index 00844a779..0cb8ec7b8 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java @@ -23,7 +23,7 @@ public class OperatorPlus extends OperatorBinary { return new ConstantString(((ConstantString) left).getString() + ((ConstantString) right).getString()); } else if(left instanceof ConstantString && right instanceof ConstantChar) { return new ConstantString(((ConstantString) left).getString() + ((ConstantChar) right).getChar()); - } else if(left instanceof ConstantString && right instanceof ConstantInteger && SymbolType.isByte(((ConstantInteger) right).getType())) { + } else if(left instanceof ConstantString && right instanceof ConstantInteger && SymbolType.BYTE.equals(((ConstantInteger) right).getType())) { Character character = (char) ((ConstantInteger) right).getInteger().byteValue(); return new ConstantString(((ConstantString) left).getString() + character); } else if(left instanceof ConstantPointer && right instanceof ConstantInteger) { @@ -62,9 +62,9 @@ public class OperatorPlus extends OperatorBinary { private boolean isStringLike(SymbolTypeSimple type) { if(SymbolType.STRING.equals(type)) { return true; - } else if(SymbolType.isByte(type)) { + } else if(SymbolType.BYTE.equals(type)) { return true; - } else if(type instanceof SymbolTypeArray && SymbolType.isByte(((SymbolTypeArray) type).getElementType())) { + } else if(type instanceof SymbolTypeArray && SymbolType.BYTE.equals(((SymbolTypeArray) type).getElementType())) { return true; } return false; diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java index e5218c3bd..19662e139 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java @@ -22,17 +22,17 @@ public class OperatorSetHigh extends OperatorBinary { public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { if(left instanceof SymbolTypePointer) { return left; - } else if(SymbolType.isByte(left)) { + } else if(SymbolType.BYTE.equals(left)) { return SymbolType.WORD; - } else if(SymbolType.isSByte(left)) { + } else if(SymbolType.SBYTE.equals(left)) { return SymbolType.WORD; - } else if(SymbolType.isWord(left)) { + } else if(SymbolType.WORD.equals(left)) { return SymbolType.WORD; - } else if(SymbolType.isSWord(left)) { + } else if(SymbolType.SWORD.equals(left)) { return SymbolType.SWORD; - } else if(SymbolType.isDWord(left)) { + } else if(SymbolType.DWORD.equals(left)) { return SymbolType.DWORD; - } else if(SymbolType.isSDWord(left)) { + } else if(SymbolType.SDWORD.equals(left)) { return SymbolType.SDWORD; } throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java index 12e3d486f..bd4cd763a 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java @@ -23,13 +23,13 @@ public class OperatorSetLow extends OperatorBinary { if(left instanceof SymbolTypePointer) { return left; } - if(SymbolType.isWord(left)) { + if(SymbolType.WORD.equals(left)) { return SymbolType.WORD; - } else if(SymbolType.isSWord(left)) { + } else if(SymbolType.SWORD.equals(left)) { return SymbolType.SWORD; - } else if(SymbolType.isDWord(left)) { + } else if(SymbolType.DWORD.equals(left)) { return SymbolType.DWORD; - } else if(SymbolType.isSDWord(left)) { + } else if(SymbolType.SDWORD.equals(left)) { return SymbolType.SDWORD; } throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java index 02d3e51e8..6300140e1 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.symbols.ConstantVar; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeMulti; import dk.camelot64.kickc.model.types.SymbolTypePointer; import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; @@ -20,7 +19,7 @@ public class OperatorSizeOf extends OperatorUnary { @Override public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { SymbolType type = operand.getType(scope); - return new ConstantInteger((long)type.getSizeBytes()); + return new ConstantInteger((long) type.getSizeBytes()); } @Override @@ -30,6 +29,7 @@ public class OperatorSizeOf extends OperatorUnary { /** * Get the constant variable containing the size of a specific type + * * @param programScope The program scope (used for finding/adding the constant). * @param type The type to get the variable for * @return The constant variable @@ -37,7 +37,7 @@ public class OperatorSizeOf extends OperatorUnary { public static ConstantRef getSizeOfConstantVar(ProgramScope programScope, SymbolType type) { String typeConstName = getSizeofConstantName(type); ConstantVar typeSizeConstant = programScope.getConstant(typeConstName); - if(typeSizeConstant ==null) { + if(typeSizeConstant == null) { // Constant not found - create it long typeSize = type.getSizeBytes(); typeSizeConstant = new ConstantVar(typeConstName, programScope, SymbolType.BYTE, new ConstantInteger(typeSize)); @@ -48,18 +48,15 @@ public class OperatorSizeOf extends OperatorUnary { /** * Get the name of the constant variable containing the size of a specific type + * * @param type The type to get the variable for * @return The name of the constant */ public static String getSizeofConstantName(SymbolType type) { - if(type instanceof SymbolTypeMulti) { - // Grab the first sub-type. It will be the smallest - SymbolType subType = OperatorTypeId.getSubTypeToUse((SymbolTypeMulti) type); - return getSizeofConstantName(subType); - } else if(type instanceof SymbolTypePointer) { + if(type instanceof SymbolTypePointer) { return "SIZEOF_POINTER"; } else { - return "SIZEOF_"+type.getTypeName().toUpperCase().replace(" ", "_"); + return "SIZEOF_" + type.getTypeName().toUpperCase().replace(" ", "_"); } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java index df22fc60d..c5dca47db 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java @@ -36,7 +36,7 @@ public class OperatorTypeId extends OperatorUnary { * @return The constant variable */ public static ConstantRef getTypeIdConstantVar(ProgramScope programScope, SymbolType type) { - String typeConstName = "TYPEID_"+getTypeIdConstantName(type); + String typeConstName = "TYPEID_" + getTypeIdConstantName(type); ConstantVar typeIdConstant = programScope.getConstant(typeConstName); if(typeIdConstant == null) { // Constant not found - create it @@ -54,15 +54,7 @@ public class OperatorTypeId extends OperatorUnary { * @return The name of the constant */ private static String getTypeIdConstantName(SymbolType type) { - if(type instanceof SymbolTypeMulti) { - // Grab the first sub-type. It will be the smallest - SymbolType subType = getSubTypeToUse((SymbolTypeMulti) type); - if(subType==null) { - return "VOID"; - } else { - return getTypeIdConstantName(subType); - } - } else if(type instanceof SymbolTypeProcedure) { + if(type instanceof SymbolTypeProcedure) { return "PROCEDURE"; } else if(type instanceof SymbolTypePointer) { return "POINTER_" + getTypeIdConstantName(((SymbolTypePointer) type).getElementType()); @@ -113,33 +105,9 @@ public class OperatorTypeId extends OperatorUnary { return 0x0f; } else if(type instanceof SymbolTypePointer) { return 0x10 + getTypeId(((SymbolTypePointer) type).getElementType()); - } else if(type instanceof SymbolTypeMulti) { - // Return the smallest type ID - SymbolType useType = getSubTypeToUse((SymbolTypeMulti) type); - if(useType==null) return 0; - return getTypeId(useType); } else { return 0; } } - /** - * Find the sub-type to use for typeid() - * @param type The multi type - * @return The sub-type to use - */ - public static SymbolType getSubTypeToUse(SymbolTypeMulti type) { - SymbolType useType = null; - Integer useID = null; - for(SymbolType subType : type.getTypes()) { - int subId = getTypeId(subType); - if(useType==null || subId < useID) { - useType = subType; - useID = subId; - } - } - return useType; - } - - } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java index 1ddc3a770..c84710823 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.NoMatchingType; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypePointer; import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -25,7 +24,7 @@ public class OperatorWord extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { - if(SymbolType.isByte(left) && SymbolType.isByte(right)) { + if(SymbolType.BYTE.equals(left) && SymbolType.BYTE.equals(right)) { return SymbolType.WORD; } throw new NoMatchingType("Word constructor cannot use " + left + " " + getOperator() + " " + right); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java index 71e41be30..34747ed97 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java @@ -106,66 +106,6 @@ public interface SymbolType { */ int getSizeBytes(); - /** - * Is the type {@link #BYTE} or compatible {@link SymbolTypeMulti} - * - * @param type The type to examine - * @return true if the type is BYTE compatible - */ - static boolean isByte(SymbolType type) { - return BYTE.equals(type); - } - - /** - * Is the type {@link #SBYTE} or compatible {@link SymbolTypeMulti} - * - * @param type The type to examine - * @return true if the type is SBYTE compatible - */ - static boolean isSByte(SymbolType type) { - return SBYTE.equals(type); - } - - /** - * Is the type {@link #WORD} or compatible {@link SymbolTypeMulti} - * - * @param type The type to examine - * @return true if the type is WORD compatible - */ - static boolean isWord(SymbolType type) { - return WORD.equals(type); - } - - /** - * Is the type {@link #SWORD} or compatible {@link SymbolTypeMulti} - * - * @param type The type to examine - * @return true if the type is SWORD compatible - */ - static boolean isSWord(SymbolType type) { - return SWORD.equals(type); - } - - /** - * Is the type {@link #DWORD} or compatible {@link SymbolTypeMulti} - * - * @param type The type to examine - * @return true if the type is DWORD compatible - */ - static boolean isDWord(SymbolType type) { - return DWORD.equals(type); - } - - /** - * Is the type {@link #SDWORD} or compatible {@link SymbolTypeMulti} - * - * @param type The type to examine - * @return true if the type is SDWORD compatible - */ - static boolean isSDWord(SymbolType type) { - return SDWORD.equals(type); - } - /** * Is the type an integer type (including {@link #NUMBER}) * diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index 31bf4b7a9..100244aca 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -148,13 +148,13 @@ public class SymbolTypeInference { } } if(elmType != null) { - if((list.getList().size() == 2 && SymbolType.isByte(elmType) || SymbolType.isSByte(elmType))) { + if((list.getList().size() == 2 && SymbolType.BYTE.equals(elmType) || SymbolType.SBYTE.equals(elmType))) { // Potentially a word constructor - return a composite type ArrayList<SymbolType> types = new ArrayList<>(); types.add(new SymbolTypeArray(elmType)); types.add(SymbolType.WORD); return new SymbolTypeMulti(types); - } else if((list.getList().size() == 2 && SymbolType.isWord(elmType))) { + } else if((list.getList().size() == 2 && SymbolType.WORD.equals(elmType))) { // Potentially a dword constructor - return a composite type ArrayList<SymbolType> types = new ArrayList<>(); types.add(new SymbolTypeArray(elmType)); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java index 49b6afce4..e13b30941 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java @@ -49,7 +49,7 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization { @Override protected boolean isSubType(SymbolType elmType) { - return SymbolType.isByte(elmType); + return SymbolType.BYTE.equals(elmType); } } @@ -62,7 +62,7 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization { @Override protected boolean isSubType(SymbolType elmType) { - return SymbolType.isWord(elmType); + return SymbolType.WORD.equals(elmType); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java index a298ad251..b66de4df4 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java @@ -40,19 +40,19 @@ public class Pass2NopCastElimination extends Pass2SsaOptimization { SymbolType rValType = SymbolTypeInference.inferType(getScope(), assignment.getrValue2()); boolean isNopCast = false; SymbolType toType = null; - if(SymbolType.isByte(rValType) && Operators.CAST_SBYTE.equals(assignment.getOperator())) { + if(SymbolType.BYTE.equals(rValType) && Operators.CAST_SBYTE.equals(assignment.getOperator())) { isNopCast = true; toType = SymbolType.SBYTE; - } else if(SymbolType.isSByte(rValType) && Operators.CAST_BYTE.equals(assignment.getOperator())) { + } else if(SymbolType.SBYTE.equals(rValType) && Operators.CAST_BYTE.equals(assignment.getOperator())) { isNopCast = true; toType = SymbolType.BYTE; - } else if(SymbolType.isWord(rValType) && Operators.CAST_SWORD.equals(assignment.getOperator())) { + } else if(SymbolType.WORD.equals(rValType) && Operators.CAST_SWORD.equals(assignment.getOperator())) { isNopCast = true; toType = SymbolType.SWORD; - } else if(SymbolType.isSWord(rValType) && Operators.CAST_WORD.equals(assignment.getOperator())) { + } else if(SymbolType.SWORD.equals(rValType) && Operators.CAST_WORD.equals(assignment.getOperator())) { isNopCast = true; toType = SymbolType.WORD; - } else if(SymbolType.isWord(rValType) && assignment.getOperator() instanceof OperatorCastPtr) { + } else if(SymbolType.WORD.equals(rValType) && assignment.getOperator() instanceof OperatorCastPtr) { isNopCast = true; OperatorCastPtr castOperator = (OperatorCastPtr) (assignment.getOperator()); toType = new SymbolTypePointer(castOperator.getElementType()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 630581697..e758eb361 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -387,13 +387,13 @@ public class Pass4CodeGeneration { String asmElement = AsmFormat.getAsmConstant(program, element, 99, scopeRef); asmElements.add(asmElement); } - if(SymbolType.isByte(elementType) || SymbolType.isSByte(elementType)) { + if(SymbolType.BYTE.equals(elementType) || SymbolType.SBYTE.equals(elementType)) { asm.addDataNumeric(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.BYTE, asmElements); added.add(asmName); - } else if(SymbolType.isWord(elementType) || SymbolType.isSWord(elementType)) { + } else if(SymbolType.WORD.equals(elementType) || SymbolType.SWORD.equals(elementType)) { asm.addDataNumeric(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmElements); added.add(asmName); - } else if(SymbolType.isDWord(elementType) || SymbolType.isSDWord(elementType)) { + } else if(SymbolType.DWORD.equals(elementType) || SymbolType.SDWORD.equals(elementType)) { asm.addDataNumeric(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.DWORD, asmElements); added.add(asmName); } else if(elementType instanceof SymbolTypePointer) { @@ -410,27 +410,27 @@ public class Pass4CodeGeneration { throw new Pass2SsaAssertion.AssertionFailed("Error! Array size is not constant integer " + constantVar.toString(program)); } int size = ((ConstantInteger) arraySizeConst).getInteger().intValue(); - if(SymbolType.isByte(constantArrayFilled.getElementType())) { + if(SymbolType.BYTE.equals(constantArrayFilled.getElementType())) { String asmSize = AsmFormat.getAsmConstant(program, arraySize, 99, scopeRef); asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.BYTE, asmSize, size, "0"); added.add(asmName); - } else if(SymbolType.isSByte(constantArrayFilled.getElementType())) { + } else if(SymbolType.SBYTE.equals(constantArrayFilled.getElementType())) { String asmSize = AsmFormat.getAsmConstant(program, arraySize, 99, scopeRef); asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.BYTE, asmSize, size, "0"); added.add(asmName); - } else if(SymbolType.isWord(constantArrayFilled.getElementType())) { + } else if(SymbolType.WORD.equals(constantArrayFilled.getElementType())) { String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(2L), Operators.MULTIPLY, arraySize), 99, scopeRef); asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmSize, size, "0"); added.add(asmName); - } else if(SymbolType.isSWord(constantArrayFilled.getElementType())) { + } else if(SymbolType.SWORD.equals(constantArrayFilled.getElementType())) { String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(2L), Operators.MULTIPLY, arraySize), 99, scopeRef); asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmSize, size, "0"); added.add(asmName); - } else if(SymbolType.isDWord(constantArrayFilled.getElementType())) { + } else if(SymbolType.DWORD.equals(constantArrayFilled.getElementType())) { String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(4L), Operators.MULTIPLY, arraySize), 99, scopeRef); asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.DWORD, asmSize, size, "0"); added.add(asmName); - } else if(SymbolType.isSDWord(constantArrayFilled.getElementType())) { + } else if(SymbolType.SDWORD.equals(constantArrayFilled.getElementType())) { String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(4L), Operators.MULTIPLY, arraySize), 99, scopeRef); asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.DWORD, asmSize, size, "0"); added.add(asmName); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java index 157b04ca7..e36e1348a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java @@ -195,23 +195,23 @@ public class Pass4RegistersFinalize extends Pass2Base { */ private Registers.Register allocateNewRegisterZp(Variable variable) { SymbolType varType = variable.getType(); - if(SymbolType.isByte(varType)) { + if(SymbolType.BYTE.equals(varType)) { return new Registers.RegisterZpByte(allocateZp((1))); - } else if(SymbolType.isSByte(varType)) { + } else if(SymbolType.SBYTE.equals(varType)) { return new Registers.RegisterZpByte(allocateZp(1)); - } else if(SymbolType.isWord(varType)) { + } else if(SymbolType.WORD.equals(varType)) { Registers.RegisterZpWord registerZpWord = new Registers.RegisterZpWord(allocateZp(2)); return registerZpWord; - } else if(SymbolType.isSWord(varType)) { + } else if(SymbolType.SWORD.equals(varType)) { Registers.RegisterZpWord registerZpWord = new Registers.RegisterZpWord(allocateZp(2)); return registerZpWord; - } else if(SymbolType.isDWord(varType)) { + } else if(SymbolType.DWORD.equals(varType)) { Registers.RegisterZpDWord registerZpDWord = new Registers.RegisterZpDWord(allocateZp(4)); return registerZpDWord; - } else if(SymbolType.isSDWord(varType)) { + } else if(SymbolType.SDWORD.equals(varType)) { Registers.RegisterZpDWord registerZpDWord = new Registers.RegisterZpDWord(allocateZp(4)); return registerZpDWord; From fe60b31f73113438f9aa780c44f82ff8d5719660 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 12 May 2019 21:18:55 +0200 Subject: [PATCH 30/93] New literal word constructor handling - 277/354 --- .../java/dk/camelot64/kickc/Compiler.java | 1 + .../iterator/ProgramExpressionIterator.java | 6 +- .../iterator/ProgramExpressionUnary.java | 37 ++++++++- .../kickc/model/types/SymbolTypeArray.java | 6 +- .../model/types/SymbolTypeInference.java | 81 ++----------------- .../kickc/model/values/ValueList.java | 4 + .../Pass2ConstantCastSimplification.java | 31 ------- .../passes/Pass2FixInlineConstructorsNew.java | 69 ++++++++++++++++ .../PassNAddTypeConversionAssignment.java | 19 +++++ .../dk/camelot64/kickc/test/TestPrograms.java | 15 ++++ src/test/kc/inline-word-0.kc | 7 ++ src/test/kc/inline-word-1.kc | 7 ++ src/test/kc/inline-word-2.kc | 7 ++ 13 files changed, 174 insertions(+), 116 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java create mode 100644 src/test/kc/inline-word-0.kc create mode 100644 src/test/kc/inline-word-1.kc create mode 100644 src/test/kc/inline-word-2.kc diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 2e73baad4..4d524e483 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -254,6 +254,7 @@ public class Compiler { optimizations.add(new Pass2ConstantIfs(program)); optimizations.add(new Pass2ConstantStringConsolidation(program)); optimizations.add(new Pass2FixInlineConstructors(program)); + optimizations.add(new Pass2FixInlineConstructorsNew(program)); optimizations.add(new Pass2TypeInference(program)); optimizations.add(new PassNEliminateUnusedVars(program, true)); optimizations.add(new Pass2EliminateRedundantCasts(program)); diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java index c109a3001..6a6d9c3dc 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java @@ -5,9 +5,7 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementConditionalJump; -import dk.camelot64.kickc.model.values.ConstantBinary; -import dk.camelot64.kickc.model.values.ConstantUnary; -import dk.camelot64.kickc.model.values.PointerDereferenceIndexed; +import dk.camelot64.kickc.model.values.*; import java.util.ListIterator; @@ -33,6 +31,8 @@ public class ProgramExpressionIterator { handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), null, null, null); } else if(programValue.get() instanceof PointerDereferenceIndexed) { handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), null, null, null); + } else if(programValue.get() instanceof ConstantCastValue) { + handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryCast(programValue), null, null, null); } }; ProgramValueIterator.execute(program.getScope(), programValueHandler); diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java index a2795032d..fdcdeb4a0 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java @@ -1,7 +1,9 @@ package dk.camelot64.kickc.model.iterator; import dk.camelot64.kickc.model.operators.OperatorUnary; +import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.values.ConstantCastValue; import dk.camelot64.kickc.model.values.ConstantUnary; import dk.camelot64.kickc.model.values.RValue; import dk.camelot64.kickc.model.values.Value; @@ -52,7 +54,7 @@ public interface ProgramExpressionUnary extends ProgramExpression { /** Unary expression as part of a constant expression. */ class ProgramExpressionUnaryConstant implements ProgramExpressionUnary { - + /** A ProgramValue containing a {@link ConstantUnary}. */ private ProgramValue programValue; @@ -81,4 +83,37 @@ public interface ProgramExpressionUnary extends ProgramExpression { } + /** Unary cast expression {@link ConstantCastValue} as part of a constant expression. */ + class ProgramExpressionUnaryCast implements ProgramExpressionUnary { + + /** A ProgramValue containing a {@link ConstantCastValue}. */ + private ProgramValue programValue; + + ProgramExpressionUnaryCast(ProgramValue programValue) { + this.programValue = programValue; + } + + public ConstantCastValue getConstantUnary() { + return (ConstantCastValue) programValue.get(); + } + + @Override + public OperatorUnary getOperator() { + return Operators.getCastUnary(getConstantUnary().getToType()); + } + + @Override + public RValue getOperand() { + return getConstantUnary().getValue(); + } + + @Override + public void set(Value value) { + programValue.set(value); + } + + } + + + } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeArray.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeArray.java index 738b40754..7aaa8fce2 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeArray.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeArray.java @@ -31,11 +31,7 @@ public class SymbolTypeArray extends SymbolTypePointer { @Override public String getTypeName() { SymbolType elementType = getElementType(); - if(elementType instanceof SymbolTypeMulti) { - return "(" + elementType.getTypeName() + ")" + "[" + (size == null ? "" : size.toString()) + "]"; - } else { - return elementType.getTypeName() + "[" + (size == null ? "" : size.toString()) + "]"; - } + return elementType.getTypeName() + "[" + (size == null ? "" : size.toString()) + "]"; } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index 100244aca..d512f96e7 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -9,10 +9,6 @@ import dk.camelot64.kickc.model.statements.*; import dk.camelot64.kickc.model.symbols.*; import dk.camelot64.kickc.model.values.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - /** * Type inference of expressions (rValues & unary/binary operators) */ @@ -126,7 +122,7 @@ public class SymbolTypeInference { } else if(rValue instanceof ProcedureRef) { Procedure procedure = symbols.getProcedure((ProcedureRef) rValue); return procedure.getType(); - } else if(rValue instanceof AssignmentRValue) { + } else if(rValue instanceof AssignmentRValue) { return inferTypeRValue(symbols, ((AssignmentRValue) rValue).getAssignment()); } if(type == null) { @@ -148,21 +144,8 @@ public class SymbolTypeInference { } } if(elmType != null) { - if((list.getList().size() == 2 && SymbolType.BYTE.equals(elmType) || SymbolType.SBYTE.equals(elmType))) { - // Potentially a word constructor - return a composite type - ArrayList<SymbolType> types = new ArrayList<>(); - types.add(new SymbolTypeArray(elmType)); - types.add(SymbolType.WORD); - return new SymbolTypeMulti(types); - } else if((list.getList().size() == 2 && SymbolType.WORD.equals(elmType))) { - // Potentially a dword constructor - return a composite type - ArrayList<SymbolType> types = new ArrayList<>(); - types.add(new SymbolTypeArray(elmType)); - types.add(SymbolType.DWORD); - return new SymbolTypeMulti(types); - } else { - return new SymbolTypeArray(elmType); - } + long size = list.getList().size(); + return new SymbolTypeArray(elmType, new ConstantInteger(size, size<256?SymbolType.BYTE:SymbolType.WORD)); } else { throw new RuntimeException("Cannot infer list element type " + list.toString()); } @@ -223,13 +206,8 @@ public class SymbolTypeInference { SymbolType valueType = inferType(programScope, rValue); if(type == null) { type = valueType; - } else { - SymbolType newType = intersectTypes(type, valueType); - if(newType == null) { - throw new CompileError("Types not compatible " + type + " and " + valueType); - } - type = newType; - } + } else if(!type.equals(valueType)) + throw new CompileError("Types not compatible " + type + " and " + valueType); } if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) { program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program)); @@ -295,53 +273,4 @@ public class SymbolTypeInference { } } - /** - * Find the symbol type that is the intersection between the two passed types. - * Handles SymbolTypeMulti by intersecting the sub type lists. - * - * @param type1 The first type - * @param type2 The second type - * @return The intersection between the two types (handling multi-types) - */ - public static SymbolType intersectTypes(SymbolType type1, SymbolType type2) { - List<SymbolType> newSubTypes = new ArrayList<>(); - if(type1 instanceof SymbolTypeMulti) { - Collection<SymbolType> subTypes1 = ((SymbolTypeMulti) type1).getTypes(); - if(type2 instanceof SymbolTypeMulti) { - Collection<SymbolType> subTypes2 = ((SymbolTypeMulti) type2).getTypes(); - for(SymbolType subType1 : subTypes1) { - if(subTypes2.contains(subType1)) { - newSubTypes.add(subType1); - } - } - } else { - // Element type is not multi - check if the list type contains it - if(subTypes1.contains(type2)) { - newSubTypes.add(type2); - } - } - } else { - // List-type not multi - check if the element type contains it - if(type2 instanceof SymbolTypeMulti) { - Collection<SymbolType> subTypes2 = ((SymbolTypeMulti) type2).getTypes(); - if(subTypes2.contains(type1)) { - newSubTypes.add(type1); - } - } else { - // Element type is not multi - check if the list type is the same - if(type1.equals(type2)) { - newSubTypes.add(type1); - } - } - } - if(newSubTypes.size() == 0) { - return null; - } else if(newSubTypes.size() == 1) { - // A single type matching - use it - return newSubTypes.get(0); - } else { - // Multiple matches was found - use them - return new SymbolTypeMulti(newSubTypes); - } - } } diff --git a/src/main/java/dk/camelot64/kickc/model/values/ValueList.java b/src/main/java/dk/camelot64/kickc/model/values/ValueList.java index fd704486a..a81adb58a 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ValueList.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ValueList.java @@ -38,4 +38,8 @@ public class ValueList implements RValue { return out.toString(); } + @Override + public String toString() { + return toString(null); + } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java index 0d516f99e..467e386ca 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java @@ -53,37 +53,6 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization { } } }); - ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> { - if(programValue.get() instanceof ConstantCastValue) { - ConstantCastValue constantCastValue = (ConstantCastValue) programValue.get(); - if(constantCastValue.getValue() instanceof ConstantInteger) { - ConstantInteger constantInteger = (ConstantInteger) constantCastValue.getValue(); - SymbolType castType = constantCastValue.getToType(); - if(SymbolType.NUMBER.equals(constantInteger.getType())) { - if(castType instanceof SymbolTypeIntegerFixed ) { - ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); - programValue.set(newConstInt); - getLog().append("Simplifying constant integer cast " + newConstInt.toString()); - optimized.set(true); - } else if(castType instanceof SymbolTypePointer) { - ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType()); - programValue.set(newConstPointer); - getLog().append("Simplifying constant pointer cast " + newConstPointer.toString()); - optimized.set(true); - } - } else if(castType instanceof SymbolTypeIntegerFixed) { - if(((SymbolTypeIntegerFixed) castType).contains(constantInteger.getValue())) { - // Cast type contains the value - cast not needed - ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); - programValue.set(newConstInt); - getLog().append("Simplifying constant integer cast " + newConstInt.toString()); - optimized.set(true); - } - } - } - } - - }); return optimized.get(); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java new file mode 100644 index 000000000..edd754321 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java @@ -0,0 +1,69 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.Comment; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; +import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary; +import dk.camelot64.kickc.model.operators.OperatorBinary; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.symbols.Scope; +import dk.camelot64.kickc.model.symbols.VariableIntermediate; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.CastValue; +import dk.camelot64.kickc.model.values.RValue; +import dk.camelot64.kickc.model.values.ValueList; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Identifies word constructors <code> (word) { b1, b2 }</code> and replaces + * them with a binary operator <code>word w = b1 w= b2 ;</code> + */ +public class Pass2FixInlineConstructorsNew extends Pass2SsaOptimization { + + public Pass2FixInlineConstructorsNew(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean optimized = new AtomicBoolean(false); + ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> { + if(programExpression instanceof ProgramExpressionUnary) { + if(programExpression.getOperator().equals(Operators.CAST_WORD)) { + if(((ProgramExpressionUnary) programExpression).getOperand() instanceof ValueList) { + ValueList list = (ValueList) ((ProgramExpressionUnary) programExpression).getOperand(); + List<RValue> listValues = list.getList(); + if(listValues.size()==2) { + + OperatorBinary constructOperator = Operators.WORD; + SymbolType constructType = SymbolType.WORD; + + // Convert list to a word constructor in a new tmp variable + Scope currentScope = Pass2FixInlineConstructorsNew.this.getScope().getScope(currentBlock.getScope()); + VariableIntermediate tmpVar = currentScope.addVariableIntermediate(); + tmpVar.setTypeInferred(constructType); + // Move backward - to insert before the current statement + stmtIt.previous(); + // Add assignment of the new tmpVar + StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), new CastValue(SymbolType.BYTE, listValues.get(0)), constructOperator, new CastValue(SymbolType.BYTE, listValues.get(1)), currentStmt.getSource(), Comment.NO_COMMENTS); + stmtIt.add(assignment); + // Move back before the current statement + stmtIt.next(); + // Replace current value with the reference + programExpression.set(tmpVar.getRef()); + Pass2FixInlineConstructorsNew.this.getLog().append("Fixing inline constructor with " + assignment.toString()); + optimized.set(true); + } + } + } + } + }); + return optimized.get(); + + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java index e2f2049c0..908cb0587 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java @@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; import dk.camelot64.kickc.model.types.*; +import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.RValue; import java.util.concurrent.atomic.AtomicBoolean; @@ -37,6 +38,15 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization { binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope()); modified.set(true); } + + // Detect word literal constructor + if(leftType.equals(SymbolType.WORD) && isLiteralWordCandidate(rightType)) { + SymbolType conversionType = SymbolType.WORD; + getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); + binary.addRightCast(SymbolType.WORD, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); + modified.set(true); + } + } if(leftType instanceof SymbolTypeIntegerFixed && SymbolType.isInteger(rightType)) { SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType); @@ -53,5 +63,14 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization { return modified.get(); } + public static boolean isLiteralWordCandidate(SymbolType rightType) { + if(rightType instanceof SymbolTypeArray) { + SymbolTypeArray rightArray = (SymbolTypeArray) rightType; + if(new ConstantInteger(2L, SymbolType.BYTE).equals(rightArray.getSize())) + if(SymbolType.BYTE.equals(rightArray.getElementType()) || SymbolType.NUMBER.equals(rightArray.getElementType())) + return true; + } + return false; + } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 100a0e868..3bb2350d3 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -1359,6 +1359,21 @@ public class TestPrograms { compileAndCompare("inline-assignment"); } + @Test + public void testInlineWord0() throws IOException, URISyntaxException { + compileAndCompare("inline-word-0"); + } + + @Test + public void testInlineWord1() throws IOException, URISyntaxException { + compileAndCompare("inline-word-1"); + } + + @Test + public void testInlineWord2() throws IOException, URISyntaxException { + compileAndCompare("inline-word-2"); + } + @Test public void testInlineWord() throws IOException, URISyntaxException { compileAndCompare("inline-word"); diff --git a/src/test/kc/inline-word-0.kc b/src/test/kc/inline-word-0.kc new file mode 100644 index 000000000..e4ef83c7c --- /dev/null +++ b/src/test/kc/inline-word-0.kc @@ -0,0 +1,7 @@ +// Tests minimal inline word + +void main() { + word w = { 0x02ub, 0x01ub }; + word* screen = 0x0400; + screen[0] = w; +} \ No newline at end of file diff --git a/src/test/kc/inline-word-1.kc b/src/test/kc/inline-word-1.kc new file mode 100644 index 000000000..9154746f8 --- /dev/null +++ b/src/test/kc/inline-word-1.kc @@ -0,0 +1,7 @@ +// Tests minimal inline word + +void main() { + word w = { 0x01, 0x02 }; + word* screen = 0x0400; + screen[0] = w; +} \ No newline at end of file diff --git a/src/test/kc/inline-word-2.kc b/src/test/kc/inline-word-2.kc new file mode 100644 index 000000000..9cff6751a --- /dev/null +++ b/src/test/kc/inline-word-2.kc @@ -0,0 +1,7 @@ +// Tests minimal inline word + +void main() { + word w = { 0x01, 0x02ub }; + word* screen = 0x0400; + screen[0] = w; +} \ No newline at end of file From 3d56f3705a8fd725943667f3c760905725f2fe85 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Mon, 13 May 2019 09:17:30 +0200 Subject: [PATCH 31/93] Array initializer with number handling - 278/358 --- .../java/dk/camelot64/kickc/Compiler.java | 4 +- .../iterator/ProgramExpressionBinary.java | 8 ++- .../model/types/SymbolTypeInference.java | 8 ++- .../Pass2ConstantRValueConsolidation.java | 2 +- .../passes/Pass2FixInlineConstructorsNew.java | 71 +++++++++++++------ .../PassNAddArrayNumberTypeConversions.java | 63 ++++++++++++++++ .../PassNAddTypeConversionAssignment.java | 19 ++++- .../dk/camelot64/kickc/test/TestPrograms.java | 22 +++++- src/test/kc/inline-pointer-0.kc | 6 ++ src/test/kc/inline-pointer-1.kc | 11 +++ src/test/kc/inline-pointer-2.kc | 6 ++ src/test/kc/mixed-array-0.kc | 9 +++ src/test/kc/true-inline-words.kc | 2 +- 13 files changed, 200 insertions(+), 31 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddArrayNumberTypeConversions.java create mode 100644 src/test/kc/inline-pointer-0.kc create mode 100644 src/test/kc/inline-pointer-1.kc create mode 100644 src/test/kc/inline-pointer-2.kc create mode 100644 src/test/kc/mixed-array-0.kc diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 4d524e483..6440f0256 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -233,6 +233,7 @@ public class Compiler { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); optimizations.add(new PassNAddTypeConversionAssignment(program)); optimizations.add(new PassNAddNumberTypeConversions(program)); + optimizations.add(new PassNAddArrayNumberTypeConversions(program)); optimizations.add(new PassNDowngradeBytePlusWord(program)); optimizations.add(new PassNTypeInference(program)); optimizations.add(new PassNTypeIdSimplification(program)); @@ -253,8 +254,9 @@ public class Compiler { //optimizations.add(new Pass2ConstantAdditionElimination(program)); optimizations.add(new Pass2ConstantIfs(program)); optimizations.add(new Pass2ConstantStringConsolidation(program)); - optimizations.add(new Pass2FixInlineConstructors(program)); + //optimizations.add(new Pass2FixInlineConstructors(program)); optimizations.add(new Pass2FixInlineConstructorsNew(program)); + optimizations.add(new PassNAddTypeConversionAssignment(program)); optimizations.add(new Pass2TypeInference(program)); optimizations.add(new PassNEliminateUnusedVars(program, true)); optimizations.add(new Pass2EliminateRedundantCasts(program)); diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java index ff1a8b9e0..f23553a71 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java @@ -169,7 +169,13 @@ public interface ProgramExpressionBinary extends ProgramExpression { if(assignment.getrValue1() == null && assignment.getOperator() == null) { assignment.setOperator(Operators.getCastUnary(toType)); } else { - throw new InternalError("Not implemented!"); + Scope blockScope = symbols.getScope(currentScope); + VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); + SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight()); + tmpVar.setType(rightType); + StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS); + assignment.setlValue(tmpVar.getRef()); + stmtIt.add(newAssignment); } } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index d512f96e7..8944b1cfa 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -139,7 +139,13 @@ public class SymbolTypeInference { elmType = type; } else { if(!elmType.equals(type)) { - throw new RuntimeException("Array element has type mismatch " + elm.toString() + " not matching type " + elmType.getTypeName()); + if(SymbolType.NUMBER.equals(elmType) && SymbolType.isInteger(type)) { + elmType = SymbolType.NUMBER; + } else if(SymbolType.isInteger(elmType) && SymbolType.NUMBER.equals(type)) { + elmType = SymbolType.NUMBER; + } else { + throw new CompileError("Array element has type mismatch "+elm.toString() + " not matching type " + elmType.getTypeName()); + } } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java index eed062e60..edf2a49c3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java @@ -98,7 +98,7 @@ public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization { } else { if(!listType.equals(elmType)) { // No overlap between list type and element type - throw new RuntimeException("Array type " + listType + " does not match element type" + elmType + ". Array: " + valueList.toString(getProgram())); + throw new RuntimeException("Array type " + listType + " does not match element type " + elmType + ". Array: " + valueList.toString(getProgram())); } } elements.add(constantValue); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java index edd754321..e8c83cf29 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java @@ -1,11 +1,15 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.Comment; +import dk.camelot64.kickc.model.ControlFlowBlock; import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramExpression; import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary; import dk.camelot64.kickc.model.operators.OperatorBinary; +import dk.camelot64.kickc.model.operators.OperatorCastPtr; import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.symbols.Scope; import dk.camelot64.kickc.model.symbols.VariableIntermediate; @@ -15,6 +19,7 @@ import dk.camelot64.kickc.model.values.RValue; import dk.camelot64.kickc.model.values.ValueList; import java.util.List; +import java.util.ListIterator; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -32,29 +37,19 @@ public class Pass2FixInlineConstructorsNew extends Pass2SsaOptimization { AtomicBoolean optimized = new AtomicBoolean(false); ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> { if(programExpression instanceof ProgramExpressionUnary) { - if(programExpression.getOperator().equals(Operators.CAST_WORD)) { - if(((ProgramExpressionUnary) programExpression).getOperand() instanceof ValueList) { - ValueList list = (ValueList) ((ProgramExpressionUnary) programExpression).getOperand(); - List<RValue> listValues = list.getList(); - if(listValues.size()==2) { - - OperatorBinary constructOperator = Operators.WORD; - SymbolType constructType = SymbolType.WORD; - - // Convert list to a word constructor in a new tmp variable - Scope currentScope = Pass2FixInlineConstructorsNew.this.getScope().getScope(currentBlock.getScope()); - VariableIntermediate tmpVar = currentScope.addVariableIntermediate(); - tmpVar.setTypeInferred(constructType); - // Move backward - to insert before the current statement - stmtIt.previous(); - // Add assignment of the new tmpVar - StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), new CastValue(SymbolType.BYTE, listValues.get(0)), constructOperator, new CastValue(SymbolType.BYTE, listValues.get(1)), currentStmt.getSource(), Comment.NO_COMMENTS); - stmtIt.add(assignment); - // Move back before the current statement - stmtIt.next(); - // Replace current value with the reference - programExpression.set(tmpVar.getRef()); - Pass2FixInlineConstructorsNew.this.getLog().append("Fixing inline constructor with " + assignment.toString()); + if(((ProgramExpressionUnary) programExpression).getOperand() instanceof ValueList) { + ValueList list = (ValueList) ((ProgramExpressionUnary) programExpression).getOperand(); + List<RValue> listValues = list.getList(); + if(listValues.size() == 2) { + if(programExpression.getOperator().equals(Operators.CAST_WORD)) { + addLiteralWordConstructor(Operators.WORD, SymbolType.WORD, SymbolType.BYTE, programExpression, listValues, currentStmt, stmtIt, currentBlock); + optimized.set(true); + } else if(programExpression.getOperator() instanceof OperatorCastPtr) { + SymbolType castType = ((OperatorCastPtr) programExpression.getOperator()).getToType(); + addLiteralWordConstructor(Operators.WORD, castType, SymbolType.BYTE, programExpression, listValues, currentStmt, stmtIt, currentBlock); + optimized.set(true); + } else if(programExpression.getOperator().equals(Operators.CAST_DWORD)) { + addLiteralWordConstructor(Operators.DWORD, SymbolType.DWORD, SymbolType.WORD, programExpression, listValues, currentStmt, stmtIt, currentBlock); optimized.set(true); } } @@ -65,5 +60,35 @@ public class Pass2FixInlineConstructorsNew extends Pass2SsaOptimization { } + /** + * Add a literal word/dword constructor. + * Converts a cast value-list with 2 items to a word/dword constructor. + * (word) { 1, 2 } -> 1 =w 2 + * @param constructOperator The operator to add + * @param constructType The type being constructed + * @param subType The sub-type + * @param programExpression The program expression containing the cast value list + * @param listValues + * @param currentStmt + * @param stmtIt + * @param currentBlock + */ + public void addLiteralWordConstructor(OperatorBinary constructOperator, SymbolType constructType, SymbolType subType, ProgramExpression programExpression, List<RValue> listValues, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) { + // Convert list to a word constructor in a new tmp variable + Scope currentScope = Pass2FixInlineConstructorsNew.this.getScope().getScope(currentBlock.getScope()); + VariableIntermediate tmpVar = currentScope.addVariableIntermediate(); + tmpVar.setTypeInferred(constructType); + // Move backward - to insert before the current statement + stmtIt.previous(); + // Add assignment of the new tmpVar + StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), new CastValue(subType, listValues.get(0)), constructOperator, new CastValue(subType, listValues.get(1)), currentStmt.getSource(), Comment.NO_COMMENTS); + stmtIt.add(assignment); + // Move back before the current statement + stmtIt.next(); + // Replace current value with the reference + programExpression.set(tmpVar.getRef()); + Pass2FixInlineConstructorsNew.this.getLog().append("Fixing inline constructor with " + assignment.toString()); + } + } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddArrayNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddArrayNumberTypeConversions.java new file mode 100644 index 000000000..fb3599b09 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddArrayNumberTypeConversions.java @@ -0,0 +1,63 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; +import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeArray; +import dk.camelot64.kickc.model.types.SymbolTypeConversion; +import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.values.*; + +import java.util.ListIterator; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Add casts to {@link SymbolType#NUMBER} expressions that are inside array initializers based on the type of the array + */ +public class PassNAddArrayNumberTypeConversions extends Pass2SsaOptimization { + + public PassNAddArrayNumberTypeConversions(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean modified = new AtomicBoolean(false); + ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> { + if(binaryExpression instanceof ProgramExpressionBinary) { + ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression; + RValue left = binary.getLeft(); + RValue right = binary.getRight(); + SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left); + if(leftType instanceof SymbolTypeArray && right instanceof ValueList) { + SymbolType declaredElmType = ((SymbolTypeArray) leftType).getElementType(); + ListIterator<RValue> elmIterator = ((ValueList) right).getList().listIterator(); + while(elmIterator.hasNext()) { + RValue elm = elmIterator.next(); + SymbolType elmType = SymbolTypeInference.inferType(getProgram().getScope(), elm); + if(SymbolType.NUMBER.equals(elmType)) { + // Add a cast - if the value fits. + if(!SymbolTypeConversion.assignmentTypeMatch(declaredElmType, elmType)) { + throw new CompileError("Array type " + declaredElmType + " does not match element type " + elmType , currentStmt); + } + // TODO: Test if the value matches the declared type! + if(elm instanceof ConstantValue) { + elmIterator.set(new ConstantCastValue(declaredElmType, (ConstantValue) elm)); + } else { + elmIterator.set(new CastValue(declaredElmType, elm)); + } + modified.set(true); + } + } + if(modified.get()) { + getLog().append("Adding number conversion cast (" + declaredElmType+ ") to elements in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); + } + } + } + }); + return modified.get(); + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java index 908cb0587..3fde76260 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java @@ -43,7 +43,22 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization { if(leftType.equals(SymbolType.WORD) && isLiteralWordCandidate(rightType)) { SymbolType conversionType = SymbolType.WORD; getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); - binary.addRightCast(SymbolType.WORD, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); + binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); + modified.set(true); + } + // Detect word literal constructor + if(leftType instanceof SymbolTypePointer && isLiteralWordCandidate(rightType)) { + SymbolType conversionType = SymbolType.WORD; + getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); + binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); + modified.set(true); + } + + // Detect dword literal constructor + if(leftType.equals(SymbolType.DWORD) && isLiteralWordCandidate(rightType)) { + SymbolType conversionType = SymbolType.DWORD; + getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); + binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); modified.set(true); } @@ -67,7 +82,7 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization { if(rightType instanceof SymbolTypeArray) { SymbolTypeArray rightArray = (SymbolTypeArray) rightType; if(new ConstantInteger(2L, SymbolType.BYTE).equals(rightArray.getSize())) - if(SymbolType.BYTE.equals(rightArray.getElementType()) || SymbolType.NUMBER.equals(rightArray.getElementType())) + if(SymbolType.isInteger(rightArray.getElementType())) return true; } return false; diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 3bb2350d3..ca909666e 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,9 +32,29 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testMixedArray0() throws IOException, URISyntaxException { + compileAndCompare("mixed-array-0"); + } + + @Test + public void testInlinePointer2() throws IOException, URISyntaxException { + compileAndCompare("inline-pointer-2"); + } + + @Test + public void testInlinePointer1() throws IOException, URISyntaxException { + compileAndCompare("inline-pointer-1"); + } + + @Test + public void testInlinePointer0() throws IOException, URISyntaxException { + compileAndCompare("inline-pointer-0"); + } + @Test public void testToD018Problem() throws IOException, URISyntaxException { - compileAndCompare("tod018-problem", log()); + compileAndCompare("tod018-problem"); } @Test diff --git a/src/test/kc/inline-pointer-0.kc b/src/test/kc/inline-pointer-0.kc new file mode 100644 index 000000000..6f60ecd49 --- /dev/null +++ b/src/test/kc/inline-pointer-0.kc @@ -0,0 +1,6 @@ +// Tests creating a literal pointer from two bytes + +void main() { + byte* screen = (byte*) { 4, 0 }; + *screen = 'a'; +} \ No newline at end of file diff --git a/src/test/kc/inline-pointer-1.kc b/src/test/kc/inline-pointer-1.kc new file mode 100644 index 000000000..bb1523bbc --- /dev/null +++ b/src/test/kc/inline-pointer-1.kc @@ -0,0 +1,11 @@ +// Tests creating a literal pointer from two bytes + +void main() { + puta(4, 0x00); + puta(5, 0x18); +} + +void puta(byte ph, byte pl) { + byte* screen = (byte*) { ph, pl }; + *screen = 'a'; +} \ No newline at end of file diff --git a/src/test/kc/inline-pointer-2.kc b/src/test/kc/inline-pointer-2.kc new file mode 100644 index 000000000..7bfdfdfe6 --- /dev/null +++ b/src/test/kc/inline-pointer-2.kc @@ -0,0 +1,6 @@ +// Tests creating a literal pointer from two bytes + +void main() { + byte* screen = (byte*){ 4, 0 } + (word){ 0, 40 }; + *screen = 'a'; +} \ No newline at end of file diff --git a/src/test/kc/mixed-array-0.kc b/src/test/kc/mixed-array-0.kc new file mode 100644 index 000000000..7065854c7 --- /dev/null +++ b/src/test/kc/mixed-array-0.kc @@ -0,0 +1,9 @@ +// Test an array with mixed byte/number types + +void main() { + byte[] msg = { 1ub, 2, 3 }; + byte* SCREEN = 0x400; + SCREEN[0] = msg[0]; + SCREEN[1] = msg[1]; + SCREEN[2] = msg[2]; +} \ No newline at end of file diff --git a/src/test/kc/true-inline-words.kc b/src/test/kc/true-inline-words.kc index b9d96a0b6..cc701f1e0 100644 --- a/src/test/kc/true-inline-words.kc +++ b/src/test/kc/true-inline-words.kc @@ -3,7 +3,7 @@ void main() { byte[] bs = { 'c', 'm' }; // constant byte array byte b = 4; // constant byte word w = { b, 0 }; // constant inline word - word w2 = { 1, 1 } + w + { 0, 0 }; // constant inline words inside expression + word w2 = (word){ 1, 1 } + w + (word){ 0, 0 }; // constant inline words inside expression byte* sc = w2; // implicit cast to (byte*) *sc = bs[1]; // In the end $501 is set to 'c' From 6e0b665423f1106220dcbb0bed8f909414411e82 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Mon, 13 May 2019 09:24:23 +0200 Subject: [PATCH 32/93] Added an array initializer with negative values. --- src/test/java/dk/camelot64/kickc/test/TestPrograms.java | 5 +++++ src/test/kc/mixed-array-1.kc | 9 +++++++++ 2 files changed, 14 insertions(+) create mode 100644 src/test/kc/mixed-array-1.kc diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index ca909666e..83498d3aa 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,6 +32,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testMixedArray1() throws IOException, URISyntaxException { + compileAndCompare("mixed-array-1", log()); + } + @Test public void testMixedArray0() throws IOException, URISyntaxException { compileAndCompare("mixed-array-0"); diff --git a/src/test/kc/mixed-array-1.kc b/src/test/kc/mixed-array-1.kc new file mode 100644 index 000000000..b3c7880b6 --- /dev/null +++ b/src/test/kc/mixed-array-1.kc @@ -0,0 +1,9 @@ +// Test an array with mixed byte/number types + +void main() { + signed byte[] msg = { -1, 0, 1 }; + signed byte* SCREEN = 0x400; + SCREEN[0] = msg[0]; + SCREEN[1] = msg[1]; + SCREEN[2] = msg[2]; +} \ No newline at end of file From 6cfa5c750cd7e27972052fdfda3533d8b53b6ca4 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 14 May 2019 00:16:17 +0200 Subject: [PATCH 33/93] Implemented cast constant identification. 282/359 --- .../java/dk/camelot64/kickc/Compiler.java | 2 ++ .../kickc/passes/Pass2ConstantValues.java | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2ConstantValues.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 6440f0256..a2fac8fe0 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -249,6 +249,7 @@ public class Compiler { optimizations.add(new Pass2ConditionalAndOrRewriting(program)); optimizations.add(new Pass2ConstantRValueConsolidation(program)); optimizations.add(new Pass2ConstantIdentification(program)); + optimizations.add(new Pass2ConstantValues(program)); optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNVariableReferenceInfos(program)); //optimizations.add(new Pass2ConstantAdditionElimination(program)); @@ -308,6 +309,7 @@ public class Compiler { constantOptimizations.add(new Pass2IdenticalPhiElimination(program)); constantOptimizations.add(new Pass2ConstantRValueConsolidation(program)); constantOptimizations.add(new Pass2ConstantIdentification(program)); + constantOptimizations.add(new Pass2ConstantValues(program)); constantOptimizations.add(new Pass2ConstantAdditionElimination(program)); constantOptimizations.add(new Pass2ConstantSimplification(program)); constantOptimizations.add(new Pass2ConstantCastSimplification(program)); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantValues.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantValues.java new file mode 100644 index 000000000..e81c7b10b --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantValues.java @@ -0,0 +1,36 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramValueIterator; +import dk.camelot64.kickc.model.values.*; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Compiler Pass identifying constants values + */ +public class Pass2ConstantValues extends Pass2SsaOptimization { + + public Pass2ConstantValues(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean modified = new AtomicBoolean(false); + + ProgramValueIterator.execute(getProgram().getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> { + Value value = programValue.get(); + if((value instanceof RValue) && !(value instanceof ConstantValue)) { + ConstantValue constant = Pass2ConstantIdentification.getConstant((RValue) value); + if(constant!=null) { + programValue.set(constant); + getLog().append("Constant value identified " + value+ " in "+ (currentStmt==null?"":currentStmt.toString(getProgram(), false))); + modified.set(true); + } + } + }); + return modified.get(); + } + +} From 17a0db4472644bd6ce68556283dec94b3a53f73b Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Thu, 16 May 2019 08:51:14 +0200 Subject: [PATCH 34/93] Minor fixes --- src/main/fragment/vwuz1=vbuaa_rol_1.asm | 5 +++++ src/main/java/dk/camelot64/kickc/NumberParser.java | 2 +- .../camelot64/kickc/model/types/SymbolTypeInference.java | 6 +++++- src/test/java/dk/camelot64/kickc/test/TestPrograms.java | 5 +++++ src/test/kc/sandbox.kc | 4 ++-- src/test/kc/type-inference.kc | 9 +++++++++ 6 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 src/main/fragment/vwuz1=vbuaa_rol_1.asm create mode 100644 src/test/kc/type-inference.kc diff --git a/src/main/fragment/vwuz1=vbuaa_rol_1.asm b/src/main/fragment/vwuz1=vbuaa_rol_1.asm new file mode 100644 index 000000000..9c3c7c279 --- /dev/null +++ b/src/main/fragment/vwuz1=vbuaa_rol_1.asm @@ -0,0 +1,5 @@ +asl +sta {z1} +lda #0 +rol +sta {z1}+1 \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/NumberParser.java b/src/main/java/dk/camelot64/kickc/NumberParser.java index 4f222860d..e72a28df8 100644 --- a/src/main/java/dk/camelot64/kickc/NumberParser.java +++ b/src/main/java/dk/camelot64/kickc/NumberParser.java @@ -13,7 +13,7 @@ public class NumberParser { throw new NumberFormatException("Not Implemented: non-integer parsing. " + literal); } - SymbolType type = null; + SymbolType type = SymbolType.NUMBER; if(literal.endsWith("ub") || literal.endsWith("uc")) { type = SymbolType.BYTE; literal = literal.substring(0, literal.length()-2); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index 8944b1cfa..e0517349f 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -213,7 +213,11 @@ public class SymbolTypeInference { if(type == null) { type = valueType; } else if(!type.equals(valueType)) - throw new CompileError("Types not compatible " + type + " and " + valueType); + if(valueType instanceof SymbolTypeInteger && type instanceof SymbolTypeInteger) { + type = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) valueType, (SymbolTypeInteger) type); + } else { + throw new CompileError("Phi value has type mismatch "+phiRValue.toString() + " not matching type " + type.getTypeName()); + } } if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) { program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program)); diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 83498d3aa..4235009d8 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,6 +32,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testTypeInference() throws IOException, URISyntaxException { + compileAndCompare("type-inference", log().verboseSSAOptimize()); + } + @Test public void testMixedArray1() throws IOException, URISyntaxException { compileAndCompare("mixed-array-1", log()); diff --git a/src/test/kc/sandbox.kc b/src/test/kc/sandbox.kc index 403776835..9cf4f4229 100644 --- a/src/test/kc/sandbox.kc +++ b/src/test/kc/sandbox.kc @@ -47,9 +47,9 @@ byte myprintf(byte *dst, byte *str, word w1, word w2, word w3) { for (digit = 0; digit < b; ++digit) dst[bLen++] = buf6[digit]; if (bTrailing != 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = ' '; } else if (b == 'x' || b == 'X'){ // hex - b = (w >> 4) & 0xF; + b = ((byte)w >> 4) & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b; // "('a' - 10)" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/184 [FIXED] - b = w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b; + b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b; } bFormat = 0; continue; diff --git a/src/test/kc/type-inference.kc b/src/test/kc/type-inference.kc new file mode 100644 index 000000000..968ecdf1d --- /dev/null +++ b/src/test/kc/type-inference.kc @@ -0,0 +1,9 @@ +// Test inference of integer types in expressions + +void main() { + const word* screen = 0x0400; + for( byte b: 0..20) { + screen[b] = -0x30+b; + } +} + From 71cedd4d292a89db36026aaa17da7f86008f6e9e Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Fri, 17 May 2019 01:07:47 +0200 Subject: [PATCH 35/93] Working on fixing casts. --- src/main/fragment/_deref_pduc1=vduz1.asm | 8 +++ src/main/fragment/pbuz1=_ptr_vwuz2.asm | 4 ++ ...vbuxx=pwsc1_derefidx_vbuxx_minus_vwsz1.asm | 7 ++ ...vbuyy=pwsc1_derefidx_vbuyy_minus_vwsz1.asm | 7 ++ src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm | 3 + src/main/fragment/vwsz1=_sword_vbuaa.asm | 3 + .../java/dk/camelot64/kickc/Compiler.java | 6 +- .../AsmFragmentInstanceSpecFactory.java | 14 ++-- .../iterator/ProgramExpressionBinary.java | 52 +++++++++++++++ .../iterator/ProgramExpressionIterator.java | 9 +++ .../iterator/ProgramExpressionUnary.java | 39 +++++++++-- .../kickc/model/operators/OperatorSizeOf.java | 2 +- .../model/types/SymbolTypeConversion.java | 19 ++++++ .../kickc/passes/Pass3AddAssignmentCasts.java | 41 ++++++++++++ ...tion.java => PassNCastSimplification.java} | 29 +++++--- .../dk/camelot64/kickc/test/TestPrograms.java | 66 +++++++++++-------- src/test/kc/fragment-variations.kc | 16 +++++ src/test/kc/sizeof-expr.kc | 4 +- 18 files changed, 277 insertions(+), 52 deletions(-) create mode 100644 src/main/fragment/_deref_pduc1=vduz1.asm create mode 100644 src/main/fragment/pbuz1=_ptr_vwuz2.asm create mode 100644 src/main/fragment/pwsc1_derefidx_vbuxx=pwsc1_derefidx_vbuxx_minus_vwsz1.asm create mode 100644 src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vwsz1.asm create mode 100644 src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm create mode 100644 src/main/fragment/vwsz1=_sword_vbuaa.asm create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java rename src/main/java/dk/camelot64/kickc/passes/{Pass2ConstantCastSimplification.java => PassNCastSimplification.java} (71%) create mode 100644 src/test/kc/fragment-variations.kc diff --git a/src/main/fragment/_deref_pduc1=vduz1.asm b/src/main/fragment/_deref_pduc1=vduz1.asm new file mode 100644 index 000000000..7b88fe56a --- /dev/null +++ b/src/main/fragment/_deref_pduc1=vduz1.asm @@ -0,0 +1,8 @@ +lda {z1} +sta {c1} +lda {z1}+1 +sta {c1}+1 +lda {z1}+2 +sta {c1}+2 +lda {z1}+3 +sta {c1}+3 diff --git a/src/main/fragment/pbuz1=_ptr_vwuz2.asm b/src/main/fragment/pbuz1=_ptr_vwuz2.asm new file mode 100644 index 000000000..5b8ff5c26 --- /dev/null +++ b/src/main/fragment/pbuz1=_ptr_vwuz2.asm @@ -0,0 +1,4 @@ +lda {z2} +sta {z1} +lda {z2}+1 +sta {z1}+1 diff --git a/src/main/fragment/pwsc1_derefidx_vbuxx=pwsc1_derefidx_vbuxx_minus_vwsz1.asm b/src/main/fragment/pwsc1_derefidx_vbuxx=pwsc1_derefidx_vbuxx_minus_vwsz1.asm new file mode 100644 index 000000000..574b6dc27 --- /dev/null +++ b/src/main/fragment/pwsc1_derefidx_vbuxx=pwsc1_derefidx_vbuxx_minus_vwsz1.asm @@ -0,0 +1,7 @@ +lda {c1},x +sec +sbc {z1} +sta {c1},x +lda {c1}+1,x +sbc {z1}+1 +sta {c1}+1,x \ No newline at end of file diff --git a/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vwsz1.asm b/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vwsz1.asm new file mode 100644 index 000000000..856be16de --- /dev/null +++ b/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vwsz1.asm @@ -0,0 +1,7 @@ +lda {c1},y +sec +sbc {z1} +sta {c1},y +lda {c1}+1,y +sbc {z1}+1 +sta {c1}+1,y \ No newline at end of file diff --git a/src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm b/src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm new file mode 100644 index 000000000..9c8b937fb --- /dev/null +++ b/src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm @@ -0,0 +1,3 @@ +eor #$ff +clc +adc #$01 \ No newline at end of file diff --git a/src/main/fragment/vwsz1=_sword_vbuaa.asm b/src/main/fragment/vwsz1=_sword_vbuaa.asm new file mode 100644 index 000000000..e87d75da4 --- /dev/null +++ b/src/main/fragment/vwsz1=_sword_vbuaa.asm @@ -0,0 +1,3 @@ +sta {z1} +lda #0 +sta {z1}+1 \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index a2fac8fe0..19d962e42 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -270,7 +270,7 @@ public class Compiler { optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new Pass2InlineDerefIdx(program)); optimizations.add(new Pass2DeInlineWordDerefIdx(program)); - optimizations.add(new Pass2ConstantCastSimplification(program)); + optimizations.add(new PassNCastSimplification(program)); pass2Execute(optimizations); } @@ -312,7 +312,7 @@ public class Compiler { constantOptimizations.add(new Pass2ConstantValues(program)); constantOptimizations.add(new Pass2ConstantAdditionElimination(program)); constantOptimizations.add(new Pass2ConstantSimplification(program)); - constantOptimizations.add(new Pass2ConstantCastSimplification(program)); + constantOptimizations.add(new PassNCastSimplification(program)); constantOptimizations.add(new Pass2ConstantIfs(program)); pass2Execute(constantOptimizations); @@ -373,6 +373,8 @@ public class Compiler { new Pass3AssertConstants(program).check(); new Pass3AssertArrayLengths(program).check(); new Pass3AssertNoMulDivMod(program).check(); + new Pass3AddAssignmentCasts(program).execute(); + new PassNCastSimplification(program).execute(); new PassNBlockSequencePlanner(program).step(); // Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes new Pass3PhiLifting(program).perform(); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java index de00e8edf..bf197e32e 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java @@ -5,6 +5,8 @@ import dk.camelot64.kickc.model.ControlFlowGraph; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.Registers; import dk.camelot64.kickc.model.operators.Operator; +import dk.camelot64.kickc.model.operators.OperatorUnary; +import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementConditionalJump; @@ -228,13 +230,15 @@ public class AsmFragmentInstanceSpecFactory { if(value instanceof CastValue) { CastValue castVal = (CastValue) value; SymbolType toType = castVal.getToType(); - value = castVal.getValue(); - return bind(value, toType); + OperatorUnary castUnary = Operators.getCastUnary(toType); + return getOperatorFragmentName(castUnary) + bind(castVal.getValue()); } else if(value instanceof ConstantCastValue) { ConstantCastValue castVal = (ConstantCastValue) value; - SymbolType toType = castVal.getToType(); - value = castVal.getValue(); - return bind(value, toType); + if(castType==null) { + return bind(castVal.getValue(), castVal.getToType()); + } else { + return bind(castVal.getValue(), castType); + } } else if(value instanceof PointerDereference) { PointerDereference deref = (PointerDereference) value; SymbolType ptrType = null; diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java index f23553a71..e0b959796 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java @@ -7,6 +7,7 @@ import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementConditionalJump; +import dk.camelot64.kickc.model.statements.StatementPhiBlock; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.symbols.Scope; import dk.camelot64.kickc.model.symbols.VariableIntermediate; @@ -331,4 +332,55 @@ public interface ProgramExpressionBinary extends ProgramExpression { } + /** Assignment of a phi value to a phi variable. */ + class ProgramExpressionBinaryPhiValueAssignemnt implements ProgramExpressionBinary { + + private final StatementPhiBlock.PhiVariable phiVariable; + private final StatementPhiBlock.PhiRValue value; + + public ProgramExpressionBinaryPhiValueAssignemnt(StatementPhiBlock.PhiVariable phiVariable, StatementPhiBlock.PhiRValue value) { + this.phiVariable = phiVariable; + this.value = value; + } + + @Override + public RValue getLeft() { + return phiVariable.getVariable(); + } + + @Override + public OperatorBinary getOperator() { + return Operators.ASSIGNMENT; + } + + @Override + public RValue getRight() { + return value.getrValue(); + } + + @Override + public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + throw new InternalError("Not supported!"); + } + + @Override + public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { + if(getRight() instanceof ConstantValue) { + value.setrValue(new ConstantCastValue(toType, (ConstantValue) getRight())); + } else { + // Try to use CastValue - may later have to be supported! + value.setrValue(new CastValue(toType, getRight())); + } + } + + @Override + public void set(Value value) { + throw new InternalError("Not supported!"); + } + } + + + + + } diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java index 6a6d9c3dc..1995dbf5e 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java @@ -5,6 +5,7 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementConditionalJump; +import dk.camelot64.kickc.model.statements.StatementPhiBlock; import dk.camelot64.kickc.model.values.*; import java.util.ListIterator; @@ -32,6 +33,8 @@ public class ProgramExpressionIterator { } else if(programValue.get() instanceof PointerDereferenceIndexed) { handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), null, null, null); } else if(programValue.get() instanceof ConstantCastValue) { + handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstantCast(programValue), null, null, null); + } else if(programValue.get() instanceof CastValue) { handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryCast(programValue), null, null, null); } }; @@ -55,6 +58,12 @@ public class ProgramExpressionIterator { if(condJump.getrValue1() != null && condJump.getOperator() != null && condJump.getrValue2() != null) { handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConditionalJump(condJump), stmt, stmtIt, block); } + } else if(stmt instanceof StatementPhiBlock) { + for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) stmt).getPhiVariables()) { + for(StatementPhiBlock.PhiRValue value : phiVariable.getValues()) { + handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPhiValueAssignemnt(phiVariable, value), stmt, stmtIt, block); + } + } } // Iterate all statement values ProgramValueIterator.execute(stmt, programValueHandler, stmtIt, block); diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java index fdcdeb4a0..5b0fe07d9 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java @@ -3,10 +3,7 @@ package dk.camelot64.kickc.model.iterator; import dk.camelot64.kickc.model.operators.OperatorUnary; import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.StatementAssignment; -import dk.camelot64.kickc.model.values.ConstantCastValue; -import dk.camelot64.kickc.model.values.ConstantUnary; -import dk.camelot64.kickc.model.values.RValue; -import dk.camelot64.kickc.model.values.Value; +import dk.camelot64.kickc.model.values.*; /** * A binary expression in the program being iterated by {@link ProgramExpressionIterator} @@ -84,12 +81,12 @@ public interface ProgramExpressionUnary extends ProgramExpression { } /** Unary cast expression {@link ConstantCastValue} as part of a constant expression. */ - class ProgramExpressionUnaryCast implements ProgramExpressionUnary { + class ProgramExpressionUnaryConstantCast implements ProgramExpressionUnary { /** A ProgramValue containing a {@link ConstantCastValue}. */ private ProgramValue programValue; - ProgramExpressionUnaryCast(ProgramValue programValue) { + ProgramExpressionUnaryConstantCast(ProgramValue programValue) { this.programValue = programValue; } @@ -114,6 +111,36 @@ public interface ProgramExpressionUnary extends ProgramExpression { } + /** Unary cast expression {@link CastValue} as part of a constant expression. */ + class ProgramExpressionUnaryCast implements ProgramExpressionUnary { + + /** A ProgramValue containing a {@link CastValue}. */ + private ProgramValue programValue; + + ProgramExpressionUnaryCast(ProgramValue programValue) { + this.programValue = programValue; + } + + public CastValue getConstantUnary() { + return (CastValue) programValue.get(); + } + + @Override + public OperatorUnary getOperator() { + return Operators.getCastUnary(getConstantUnary().getToType()); + } + + @Override + public RValue getOperand() { + return getConstantUnary().getValue(); + } + + @Override + public void set(Value value) { + programValue.set(value); + } + + } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java index 6300140e1..11fa1b0a1 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java @@ -40,7 +40,7 @@ public class OperatorSizeOf extends OperatorUnary { if(typeSizeConstant == null) { // Constant not found - create it long typeSize = type.getSizeBytes(); - typeSizeConstant = new ConstantVar(typeConstName, programScope, SymbolType.BYTE, new ConstantInteger(typeSize)); + typeSizeConstant = new ConstantVar(typeConstName, programScope, SymbolType.BYTE, new ConstantInteger(typeSize&0xff, SymbolType.BYTE)); programScope.add(typeSizeConstant); } return typeSizeConstant.getRef(); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index 88dd99c38..6326a145b 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -175,4 +175,23 @@ public class SymbolTypeConversion { } return false; } + + /** + * Determines if the left side of an assignment needs a cast to be assigned to the right side + * @param lValueType The type of the LValue + * @param rValueType The type of the RValue + * @return true if the left side needs a cast + */ + public static boolean assignmentCastNeeded(SymbolType lValueType, SymbolType rValueType) { + if(lValueType.equals(rValueType)) + return false; + else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer) + return false; + else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType)) + return false; + else + return true; + + } + } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java new file mode 100644 index 000000000..aee315662 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java @@ -0,0 +1,41 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; +import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeConversion; +import dk.camelot64.kickc.model.types.SymbolTypeInference; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Add casts to assignments where the lvalue and rvalue have different matching types. + */ +public class Pass3AddAssignmentCasts extends Pass2SsaOptimization { + + public Pass3AddAssignmentCasts(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean modified = new AtomicBoolean(false); + ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> { + if(programExpression instanceof ProgramExpressionBinary) { + if(Operators.ASSIGNMENT.equals(programExpression.getOperator())) { + ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression; + SymbolType leftType = SymbolTypeInference.inferType(getScope(), binary.getLeft()); + SymbolType rightType = SymbolTypeInference.inferType(getScope(), binary.getRight()); + if(SymbolTypeConversion.assignmentTypeMatch(leftType, rightType) && SymbolTypeConversion.assignmentCastNeeded(leftType, rightType)) { + binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope()); + getLog().append("Adding assignment cast to " + currentStmt.toString(getProgram(), false)); + modified.set(true); + } + } + } + }); + return modified.get(); + } +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java similarity index 71% rename from src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java rename to src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java index 467e386ca..5661a8624 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java @@ -3,19 +3,21 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary; -import dk.camelot64.kickc.model.iterator.ProgramValueIterator; import dk.camelot64.kickc.model.operators.OperatorCast; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; -import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.values.*; +import dk.camelot64.kickc.model.types.*; +import dk.camelot64.kickc.model.values.ConstantInteger; +import dk.camelot64.kickc.model.values.ConstantPointer; +import dk.camelot64.kickc.model.values.RValue; import java.util.concurrent.atomic.AtomicBoolean; -/** Simplifies casts of (number) constants to a type. */ -public class Pass2ConstantCastSimplification extends Pass2SsaOptimization { +/** Simplifies casts + * - Inlines casts of (number) constants + * - Removes unnecessary casts + * */ +public class PassNCastSimplification extends Pass2SsaOptimization { - public Pass2ConstantCastSimplification(Program program) { + public PassNCastSimplification(Program program) { super(program); } @@ -27,8 +29,15 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization { OperatorCast operatorCast = (OperatorCast) programExpression.getOperator(); ProgramExpressionUnary unary = (ProgramExpressionUnary) programExpression; SymbolType castType = operatorCast.getToType(); - if(unary.getOperand() instanceof ConstantInteger) { - ConstantInteger constantInteger = (ConstantInteger) unary.getOperand(); + SymbolType operandType = SymbolTypeInference.inferType(getScope(), ((ProgramExpressionUnary) programExpression).getOperand()); + RValue unaryOperand = unary.getOperand(); + if(!SymbolTypeConversion.assignmentCastNeeded(castType, operandType)) { + // Cast Not needed + programExpression.set(unaryOperand); + getLog().append("Simplifying constant integer cast " + unaryOperand.toString(getProgram())); + optimized.set(true); + } else if(unaryOperand instanceof ConstantInteger) { + ConstantInteger constantInteger = (ConstantInteger) unaryOperand; if(SymbolType.NUMBER.equals(constantInteger.getType())) { if(castType instanceof SymbolTypeIntegerFixed ) { ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 4235009d8..4c242b507 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,14 +32,52 @@ public class TestPrograms { public TestPrograms() { } + /* + * Avaiting String concatenation + + @Test + public void testLiterals() throws IOException, URISyntaxException { + compileAndCompare("literals"); + } + + + @Test + public void testConstantStringConcat() throws IOException, URISyntaxException { + compileAndCompare("constant-string-concat"); + } + + @Test + public void testConcatChar() throws IOException, URISyntaxException { + compileAndCompare("concat-char"); + } + + @Test + public void testC64DtvGfxModes() throws IOException, URISyntaxException { + compileAndCompare("c64dtv-gfxmodes", 10); + } + + @Test + public void testC64DtvGfxExplorer() throws IOException, URISyntaxException { + compileAndCompare("c64dtv-gfxexplorer", 10); + } + + */ + + + + @Test + public void testFragmentVariations() throws IOException, URISyntaxException { + compileAndCompare("fragment-variations"); + } + @Test public void testTypeInference() throws IOException, URISyntaxException { - compileAndCompare("type-inference", log().verboseSSAOptimize()); + compileAndCompare("type-inference"); } @Test public void testMixedArray1() throws IOException, URISyntaxException { - compileAndCompare("mixed-array-1", log()); + compileAndCompare("mixed-array-1"); } @Test @@ -1059,11 +1097,6 @@ public class TestPrograms { compileAndCompare("assignment-chained"); } - @Test - public void testConcatChar() throws IOException, URISyntaxException { - compileAndCompare("concat-char"); - } - @Test public void testConstMultDiv() throws IOException, URISyntaxException { compileAndCompare("const-mult-div"); @@ -1184,11 +1217,6 @@ public class TestPrograms { compileAndCompare("c64dtv-8bppcharstretch"); } - @Test - public void testC64DtvGfxExplorer() throws IOException, URISyntaxException { - compileAndCompare("c64dtv-gfxexplorer", 10); - } - @Test public void testInlineString2() throws IOException, URISyntaxException { compileAndCompare("inline-string-2"); @@ -1209,11 +1237,6 @@ public class TestPrograms { compileAndCompare("keyboard-glitch"); } - @Test - public void testC64DtvGfxModes() throws IOException, URISyntaxException { - compileAndCompare("c64dtv-gfxmodes", 10); - } - @Test public void testNoromCharset() throws IOException, URISyntaxException { compileAndCompare("norom-charset"); @@ -1359,11 +1382,6 @@ public class TestPrograms { compileAndCompare("arrays-init"); } - @Test - public void testConstantStringConcat() throws IOException, URISyntaxException { - compileAndCompare("constant-string-concat"); - } - @Test public void testTrueInlineWords() throws IOException, URISyntaxException { compileAndCompare("true-inline-words"); @@ -1579,10 +1597,6 @@ public class TestPrograms { compileAndCompare("halfscii"); } - @Test - public void testLiterals() throws IOException, URISyntaxException { - compileAndCompare("literals"); - } @Test public void testScroll() throws IOException, URISyntaxException { diff --git a/src/test/kc/fragment-variations.kc b/src/test/kc/fragment-variations.kc new file mode 100644 index 000000000..ded7edfd4 --- /dev/null +++ b/src/test/kc/fragment-variations.kc @@ -0,0 +1,16 @@ +// Tests that ASM fragment variations works +// ASM fragment variations "cast" constants to different types + +void main() { + dword* screen = 0x400; + word w = 10; + screen[0] = mul16u(w, w); + w = 1000; + screen[1] = mul16u(w, w); +} + +dword mul16u(word b, word a) { + dword mb = b; + return mb+a; +} + diff --git a/src/test/kc/sizeof-expr.kc b/src/test/kc/sizeof-expr.kc index d48116db5..adc8538ac 100644 --- a/src/test/kc/sizeof-expr.kc +++ b/src/test/kc/sizeof-expr.kc @@ -19,7 +19,7 @@ void main() { byte[] bc = { 1, 2, 3, 4 }; // Strings byte[] sa = "camelot"; - byte[] sb = "cml"+" "+"rules"; + //byte[] sb = { 'a', 'b', 'c', 0}; SCREEN[idx++] = '0'+sizeof(0); SCREEN[idx++] = '0'+sizeof(idx); @@ -37,6 +37,6 @@ void main() { SCREEN[idx++] = '0'+sizeof(bb); SCREEN[idx++] = '0'+sizeof(bc); SCREEN[idx++] = '0'+sizeof(sa); - SCREEN[idx++] = '0'+sizeof(sb); + //SCREEN[idx++] = '0'+sizeof(sb); } \ No newline at end of file From 0876603ca750eedf122d5d6c4145b1c9c8d34a86 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Fri, 17 May 2019 08:55:04 +0200 Subject: [PATCH 36/93] Working on casts --- src/main/java/dk/camelot64/kickc/Compiler.java | 4 ++-- .../camelot64/kickc/model/operators/OperatorShiftLeft.java | 4 ---- .../camelot64/kickc/model/operators/OperatorShiftRight.java | 4 ---- .../kickc/passes/Pass2MultiplyToShiftRewriting.java | 5 +++-- src/test/java/dk/camelot64/kickc/test/TestPrograms.java | 2 +- 5 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 19d962e42..577463f7f 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -261,12 +261,11 @@ public class Compiler { optimizations.add(new Pass2TypeInference(program)); optimizations.add(new PassNEliminateUnusedVars(program, true)); optimizations.add(new Pass2EliminateRedundantCasts(program)); - optimizations.add(new Pass2NopCastElimination(program)); + //optimizations.add(new Pass2NopCastElimination(program)); optimizations.add(new Pass2EliminateUnusedBlocks(program)); optimizations.add(new Pass2RangeResolving(program)); optimizations.add(new Pass2ComparisonOptimization(program)); optimizations.add(new Pass2ConstantCallPointerIdentification(program)); - optimizations.add(new Pass2MultiplyToShiftRewriting(program)); optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new Pass2InlineDerefIdx(program)); optimizations.add(new Pass2DeInlineWordDerefIdx(program)); @@ -303,6 +302,7 @@ public class Compiler { private void pass2InlineConstants() { // Constant inlining optimizations - as the last step to ensure that constant identification has been completed List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>(); + constantOptimizations.add(new Pass2MultiplyToShiftRewriting(program)); constantOptimizations.add(new Pass2AliasElimination(program)); constantOptimizations.add(new Pass2ConstantInlining(program)); constantOptimizations.add(new Pass2ConstantStringConsolidation(program)); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java index c6c7f3f72..3350f82f7 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java @@ -26,11 +26,7 @@ public class OperatorShiftLeft extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { - if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { - return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right); - } else { return left; - } } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java index dc9c66a69..2f8a9dca0 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java @@ -25,11 +25,7 @@ public class OperatorShiftRight extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { - if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { - return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right); - } else { return left; - } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java b/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java index cad43daf9..5664593e6 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java @@ -6,6 +6,7 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.values.*; import java.util.ListIterator; @@ -44,12 +45,12 @@ public class Pass2MultiplyToShiftRewriting extends Pass2SsaOptimization { if(Operators.MULTIPLY.equals(assignment.getOperator())) { getLog().append("Rewriting multiplication to use shift "+statement.toString(getProgram(), false)); assignment.setOperator(Operators.SHIFT_LEFT); - assignment.setrValue2(new ConstantInteger((long)power2)); + assignment.setrValue2(new ConstantInteger((long)power2, SymbolType.BYTE)); optimized = true; } else if(Operators.DIVIDE.equals(assignment.getOperator())) { getLog().append("Rewriting division to use shift "+statement.toString(getProgram(), false)); assignment.setOperator(Operators.SHIFT_RIGHT); - assignment.setrValue2(new ConstantInteger((long)power2)); + assignment.setrValue2(new ConstantInteger((long)power2, SymbolType.BYTE)); optimized = true; } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 4c242b507..66978362f 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -333,7 +333,7 @@ public class TestPrograms { @Test public void testPointerCast2() throws IOException, URISyntaxException { - compileAndCompare("pointer-cast-2"); + compileAndCompare("pointer-cast-2", log()); } @Test From c200eaa53518ecbbb0557252eaba2d85cc8d8da4 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Sat, 18 May 2019 00:37:09 +0200 Subject: [PATCH 37/93] Working on casts --- .../java/dk/camelot64/kickc/Compiler.java | 1 + .../AsmFragmentInstanceSpecFactory.java | 14 +++++-- .../model/types/SymbolTypeConversion.java | 4 +- .../kickc/passes/Pass2InlineCast.java | 39 +++++++++++++++++++ .../dk/camelot64/kickc/test/TestPrograms.java | 4 +- src/test/kc/number-type.kc | 26 ++++++------- 6 files changed, 68 insertions(+), 20 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 577463f7f..eb8f14abf 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -268,6 +268,7 @@ public class Compiler { optimizations.add(new Pass2ConstantCallPointerIdentification(program)); optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new Pass2InlineDerefIdx(program)); + optimizations.add(new Pass2InlineCast(program)); optimizations.add(new Pass2DeInlineWordDerefIdx(program)); optimizations.add(new PassNCastSimplification(program)); pass2Execute(optimizations); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java index bf197e32e..caf298e42 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java @@ -228,13 +228,21 @@ public class AsmFragmentInstanceSpecFactory { public String bind(Value value, SymbolType castType) { if(value instanceof CastValue) { - CastValue castVal = (CastValue) value; - SymbolType toType = castVal.getToType(); + CastValue cast = (CastValue) value; + SymbolType toType = cast.getToType(); OperatorUnary castUnary = Operators.getCastUnary(toType); - return getOperatorFragmentName(castUnary) + bind(castVal.getValue()); + RValue castValue = cast.getValue(); + SymbolType castValueType = SymbolTypeInference.inferType(this.program.getScope(), castValue); + if(castValueType.getSizeBytes()==toType.getSizeBytes()) { + return bind(castValue, toType); + } else { + return getOperatorFragmentName(castUnary) + bind(castValue); + } } else if(value instanceof ConstantCastValue) { ConstantCastValue castVal = (ConstantCastValue) value; if(castType==null) { + // TODO: If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff ) + return bind(castVal.getValue(), castVal.getToType()); } else { return bind(castVal.getValue(), castType); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index 6326a145b..b82e23e76 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -185,9 +185,9 @@ public class SymbolTypeConversion { public static boolean assignmentCastNeeded(SymbolType lValueType, SymbolType rValueType) { if(lValueType.equals(rValueType)) return false; - else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer) + else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(((SymbolTypePointer) rValueType).getElementType())) return false; - else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType)) + else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) return false; else return true; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java new file mode 100644 index 000000000..2ba632bed --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java @@ -0,0 +1,39 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.operators.OperatorCast; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.CastValue; + +/** Identify unary casts */ +public class Pass2InlineCast extends Pass2SsaOptimization { + + public Pass2InlineCast(Program program) { + super(program); + } + + @Override + public boolean step() { + boolean optimized = false; + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementAssignment) { + StatementAssignment assignment = (StatementAssignment) statement; + if(assignment.getrValue1()==null && assignment.getOperator() instanceof OperatorCast) { + SymbolType toType = ((OperatorCast) assignment.getOperator()).getToType(); + assignment.setrValue2(new CastValue(toType, assignment.getrValue2())); + assignment.setOperator(null); + getLog().append("Inlining cast "+assignment.toString(getProgram(), false)); + optimized = true; + } + } + } + } + return optimized; + } + + +} diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 66978362f..ec6380462 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -117,7 +117,7 @@ public class TestPrograms { @Test public void testNumberType() throws IOException, URISyntaxException { - compileAndCompare("number-type"); + compileAndCompare("number-type", log()); } @Test @@ -333,7 +333,7 @@ public class TestPrograms { @Test public void testPointerCast2() throws IOException, URISyntaxException { - compileAndCompare("pointer-cast-2", log()); + compileAndCompare("pointer-cast-2"); } @Test diff --git a/src/test/kc/number-type.kc b/src/test/kc/number-type.kc index 74f270661..2ce2a2ca2 100644 --- a/src/test/kc/number-type.kc +++ b/src/test/kc/number-type.kc @@ -3,25 +3,25 @@ void main() { testBytes(); - testSBytes(); + //testSBytes(); } void testBytes() { // Constant values resolvable to bytes const byte* SCREEN = 0x0400; byte idx = 0; - SCREEN[idx++] = 12; - SCREEN[idx++] = 6+6; - SCREEN[idx++] = 18-6; - SCREEN[idx++] = 1812-1800; - SCREEN[idx++] = 1+2+3+6; - SCREEN[idx++] = 2*6; - SCREEN[idx++] = 3<<2; - SCREEN[idx++] = 24>>1; - SCREEN[idx++] = 15&28; - SCREEN[idx++] = 4|8; - SCREEN[idx++] = 5^9; - SCREEN[idx++] = (2+2)*(15/5); + //SCREEN[idx++] = 12; + //SCREEN[idx++] = 6+6; + //SCREEN[idx++] = 18-6; + //SCREEN[idx++] = 1812-1800; + //SCREEN[idx++] = 1+2+3+6; + //SCREEN[idx++] = 2*6; + //SCREEN[idx++] = 3<<2; + //SCREEN[idx++] = 24>>1; + //SCREEN[idx++] = 15&28; + //SCREEN[idx++] = 4|8; + //SCREEN[idx++] = 5^9; + //SCREEN[idx++] = (2+2)*(15/5); SCREEN[idx++] = (byte)(4096+12); } From 9f27006540778c8ff4bf619b69482622bd9cc426 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 18 May 2019 08:14:34 +0200 Subject: [PATCH 38/93] Working on casts --- .../AsmFragmentInstanceSpecFactory.java | 34 +++++++++++++------ .../dk/camelot64/kickc/test/TestPrograms.java | 4 +-- .../kc/examples/sinplotter/sine-plotter.kc | 2 +- src/test/kc/number-type.kc | 26 +++++++------- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java index caf298e42..5030079a3 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java @@ -14,10 +14,7 @@ import dk.camelot64.kickc.model.symbols.ConstantVar; import dk.camelot64.kickc.model.symbols.Label; import dk.camelot64.kickc.model.symbols.Symbol; import dk.camelot64.kickc.model.symbols.Variable; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeProcedure; +import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.*; import java.util.LinkedHashMap; @@ -89,6 +86,7 @@ public class AsmFragmentInstanceSpecFactory { /** * Get the created ASM fragment instance specification + * * @return The ASM fragment instance specification */ public AsmFragmentInstanceSpec getAsmFragmentInstanceSpec() { @@ -233,19 +231,35 @@ public class AsmFragmentInstanceSpecFactory { OperatorUnary castUnary = Operators.getCastUnary(toType); RValue castValue = cast.getValue(); SymbolType castValueType = SymbolTypeInference.inferType(this.program.getScope(), castValue); - if(castValueType.getSizeBytes()==toType.getSizeBytes()) { + if(castValueType.getSizeBytes() == toType.getSizeBytes()) { return bind(castValue, toType); } else { return getOperatorFragmentName(castUnary) + bind(castValue); } } else if(value instanceof ConstantCastValue) { ConstantCastValue castVal = (ConstantCastValue) value; - if(castType==null) { - // TODO: If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff ) + ConstantValue val = castVal.getValue(); + if(castType == null) { + SymbolType toType = castVal.getToType(); + // If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff ) + ConstantLiteral constantLiteral = val.calculateLiteral(program.getScope()); + if(constantLiteral instanceof ConstantInteger) { + if(toType instanceof SymbolTypeIntegerFixed) { + if(!((SymbolTypeIntegerFixed) toType).contains(((ConstantInteger) constantLiteral).getValue())) { + if(toType.getSizeBytes() == 1) { + val = new ConstantBinary(new ConstantInteger(0xffL, SymbolType.BYTE), Operators.BOOL_AND, val); + } else if(toType.getSizeBytes() == 2) { + val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val); + } else { + throw new InternalError("Not implemented!"); + } + } + } + } - return bind(castVal.getValue(), castVal.getToType()); + return bind(val, toType); } else { - return bind(castVal.getValue(), castType); + return bind(val, castType); } } else if(value instanceof PointerDereference) { PointerDereference deref = (PointerDereference) value; @@ -357,7 +371,7 @@ public class AsmFragmentInstanceSpecFactory { Registers.RegisterType.ZP_BYTE.equals(register.getType()) || Registers.RegisterType.ZP_WORD.equals(register.getType()) || Registers.RegisterType.ZP_DWORD.equals(register.getType()) - ) { + ) { // Examine if the ZP register is already bound Registers.RegisterZp registerZp = (Registers.RegisterZp) register; String zpNameIdx = null; diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index ec6380462..d7455e9d6 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,8 +63,6 @@ public class TestPrograms { */ - - @Test public void testFragmentVariations() throws IOException, URISyntaxException { compileAndCompare("fragment-variations"); @@ -117,7 +115,7 @@ public class TestPrograms { @Test public void testNumberType() throws IOException, URISyntaxException { - compileAndCompare("number-type", log()); + compileAndCompare("number-type"); } @Test diff --git a/src/test/kc/examples/sinplotter/sine-plotter.kc b/src/test/kc/examples/sinplotter/sine-plotter.kc index a46eb11c2..300f5591c 100644 --- a/src/test/kc/examples/sinplotter/sine-plotter.kc +++ b/src/test/kc/examples/sinplotter/sine-plotter.kc @@ -12,7 +12,7 @@ const word SIN_SIZE = 512; signed word[512] align($100) sin; -signed word* sin2 = $1400; +signed word* sin2 = $1500; kickasm(pc sin2) {{ .for(var i=0; i<512; i++) { diff --git a/src/test/kc/number-type.kc b/src/test/kc/number-type.kc index 2ce2a2ca2..74f270661 100644 --- a/src/test/kc/number-type.kc +++ b/src/test/kc/number-type.kc @@ -3,25 +3,25 @@ void main() { testBytes(); - //testSBytes(); + testSBytes(); } void testBytes() { // Constant values resolvable to bytes const byte* SCREEN = 0x0400; byte idx = 0; - //SCREEN[idx++] = 12; - //SCREEN[idx++] = 6+6; - //SCREEN[idx++] = 18-6; - //SCREEN[idx++] = 1812-1800; - //SCREEN[idx++] = 1+2+3+6; - //SCREEN[idx++] = 2*6; - //SCREEN[idx++] = 3<<2; - //SCREEN[idx++] = 24>>1; - //SCREEN[idx++] = 15&28; - //SCREEN[idx++] = 4|8; - //SCREEN[idx++] = 5^9; - //SCREEN[idx++] = (2+2)*(15/5); + SCREEN[idx++] = 12; + SCREEN[idx++] = 6+6; + SCREEN[idx++] = 18-6; + SCREEN[idx++] = 1812-1800; + SCREEN[idx++] = 1+2+3+6; + SCREEN[idx++] = 2*6; + SCREEN[idx++] = 3<<2; + SCREEN[idx++] = 24>>1; + SCREEN[idx++] = 15&28; + SCREEN[idx++] = 4|8; + SCREEN[idx++] = 5^9; + SCREEN[idx++] = (2+2)*(15/5); SCREEN[idx++] = (byte)(4096+12); } From 855434afa91f35ef0c75d72cbeb7e7c207398933 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 18 May 2019 08:51:22 +0200 Subject: [PATCH 39/93] Added missing fragment and ternary type inference test --- src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm | 11 +++++++++++ .../java/dk/camelot64/kickc/test/TestPrograms.java | 5 +++++ src/test/kc/ternary-inference.kc | 10 ++++++++++ 3 files changed, 26 insertions(+) create mode 100644 src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm create mode 100644 src/test/kc/ternary-inference.kc diff --git a/src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm b/src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm new file mode 100644 index 000000000..1d0b489df --- /dev/null +++ b/src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm @@ -0,0 +1,11 @@ +tax +clc +adc #<{c1} +sta {z1} +txa +ora #$7f +bmi !+ +lda #0 +!: +adc #>{c1} +sta {z1}+1 diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index d7455e9d6..e7a351b6a 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,6 +63,11 @@ public class TestPrograms { */ + @Test + public void testTernaryInference() throws IOException, URISyntaxException { + compileAndCompare("ternary-inference"); + } + @Test public void testFragmentVariations() throws IOException, URISyntaxException { compileAndCompare("fragment-variations"); diff --git a/src/test/kc/ternary-inference.kc b/src/test/kc/ternary-inference.kc new file mode 100644 index 000000000..47e22265d --- /dev/null +++ b/src/test/kc/ternary-inference.kc @@ -0,0 +1,10 @@ +// Type inference into the ternary operator + +void main() { + + const byte* screen = 0x400; + for(byte i: 0..10) { + screen[i] = (i<5?0x57:'0')+i; + } + +} \ No newline at end of file From 13cc9e453cdaed1a265015d6be5412e8e1ed3cf6 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 18 May 2019 12:23:13 +0200 Subject: [PATCH 40/93] Fixed a few tests. +0 in derefidx and rangenext() on signed words. --- .../fragment/pptz1_derefidx_vbuc1=pbuz2.asm | 6 ++++++ .../fragment/pptz1_derefidx_vbuc1=pwuz2.asm | 6 ++++++ .../fragment/pptz1_derefidx_vbuyy=pbuz2.asm | 5 +++++ .../fragment/pptz1_derefidx_vbuyy=pwuz2.asm | 5 +++++ .../camelot64/kickc/fragment/AsmFormat.java | 6 +++++- .../model/types/SymbolTypeInference.java | 2 +- .../Pass0GenerateStatementSequence.java | 19 ++++++++++++++----- .../Pass2ConstantAdditionElimination.java | 7 +++++++ .../dk/camelot64/kickc/test/TestPrograms.java | 2 +- 9 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 src/main/fragment/pptz1_derefidx_vbuc1=pbuz2.asm create mode 100644 src/main/fragment/pptz1_derefidx_vbuc1=pwuz2.asm create mode 100644 src/main/fragment/pptz1_derefidx_vbuyy=pbuz2.asm create mode 100644 src/main/fragment/pptz1_derefidx_vbuyy=pwuz2.asm diff --git a/src/main/fragment/pptz1_derefidx_vbuc1=pbuz2.asm b/src/main/fragment/pptz1_derefidx_vbuc1=pbuz2.asm new file mode 100644 index 000000000..d59fe6a79 --- /dev/null +++ b/src/main/fragment/pptz1_derefidx_vbuc1=pbuz2.asm @@ -0,0 +1,6 @@ +ldy #{c1} +lda {z2} +sta ({z1}),y +iny +lda {z2}+1 +sta ({z1}),y diff --git a/src/main/fragment/pptz1_derefidx_vbuc1=pwuz2.asm b/src/main/fragment/pptz1_derefidx_vbuc1=pwuz2.asm new file mode 100644 index 000000000..d59fe6a79 --- /dev/null +++ b/src/main/fragment/pptz1_derefidx_vbuc1=pwuz2.asm @@ -0,0 +1,6 @@ +ldy #{c1} +lda {z2} +sta ({z1}),y +iny +lda {z2}+1 +sta ({z1}),y diff --git a/src/main/fragment/pptz1_derefidx_vbuyy=pbuz2.asm b/src/main/fragment/pptz1_derefidx_vbuyy=pbuz2.asm new file mode 100644 index 000000000..54ae1d53c --- /dev/null +++ b/src/main/fragment/pptz1_derefidx_vbuyy=pbuz2.asm @@ -0,0 +1,5 @@ +lda {z2} +sta ({z1}),y +iny +lda {z2}+1 +sta ({z1}),y \ No newline at end of file diff --git a/src/main/fragment/pptz1_derefidx_vbuyy=pwuz2.asm b/src/main/fragment/pptz1_derefidx_vbuyy=pwuz2.asm new file mode 100644 index 000000000..54ae1d53c --- /dev/null +++ b/src/main/fragment/pptz1_derefidx_vbuyy=pwuz2.asm @@ -0,0 +1,5 @@ +lda {z2} +sta ({z1}),y +iny +lda {z2}+1 +sta ({z1}),y \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java index 331c51337..3e0c94f69 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java @@ -230,7 +230,11 @@ public class AsmFormat { if(number.longValue() >= 0L && number.longValue() <= 255L) { return SHORT_ASM_NUMBERS[number.intValue()]; } else { - return String.format("$%x", number.longValue()); + if(number.longValue()<0) { + return String.format("-$%x", -number.longValue()); + } else { + return String.format("$%x", number.longValue()); + } } } throw new RuntimeException("Unsupported number type " + number); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index e0517349f..75ef3d7e5 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -118,7 +118,7 @@ public class SymbolTypeInference { } else if(rValue instanceof RangeComparison) { return ((RangeComparison) rValue).getType(); } else if(rValue instanceof RangeNext) { - return SymbolType.BYTE; + return inferType(symbols, ((RangeNext) rValue).getRangeFirst()); } else if(rValue instanceof ProcedureRef) { Procedure procedure = symbols.getProcedure((ProcedureRef) rValue); return procedure.getType(); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 34533b203..3426efd3c 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -907,6 +907,10 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { // Assign loop variable with first value RValue rangeLastValue = (RValue) visit(rangeLastCtx); RValue rangeFirstValue = (RValue) visit(rangeFirstCtx); + if(varType!=null) { + if(rangeFirstValue instanceof ConstantInteger) ((ConstantInteger) rangeFirstValue).setType(varType); + if(rangeLastValue instanceof ConstantInteger) ((ConstantInteger) rangeLastValue).setType(varType); + } Statement stmtInit = new StatementAssignment(lValue.getRef(), rangeFirstValue, new StatementSource(ctx), Comment.NO_COMMENTS); sequence.addStatement(stmtInit); // Add label @@ -1348,11 +1352,16 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { RValue child = (RValue) this.visit(ctx.expr()); String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText(); Operator operator = Operators.getUnary(op); - VariableIntermediate tmpVar = getCurrentScope().addVariableIntermediate(); - VariableRef tmpVarRef = tmpVar.getRef(); - Statement stmt = new StatementAssignment(tmpVarRef, operator, child, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx))); - sequence.addStatement(stmt); - return tmpVarRef; + // Special handling of negative literal number + if(child instanceof ConstantInteger && operator.equals(Operators.NEG)) { + return new ConstantInteger(-((ConstantInteger) child).getInteger(), ((ConstantInteger) child).getType()); + } else { + VariableIntermediate tmpVar = getCurrentScope().addVariableIntermediate(); + VariableRef tmpVarRef = tmpVar.getRef(); + Statement stmt = new StatementAssignment(tmpVarRef, operator, child, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx))); + sequence.addStatement(stmt); + return tmpVarRef; + } } @Override diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java index 0c5f23010..15dc207c3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java @@ -93,6 +93,13 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { return true; } } + if(pointerDereferenceIndexed.getIndex() instanceof ConstantInteger ) { + if(((ConstantInteger)pointerDereferenceIndexed.getIndex()).getValue()==0L) { + value.set(new PointerDereferenceSimple(pointerDereferenceIndexed.getPointer())); + getLog().append("Simplified zero-index dereference" + value.get().toString()); + return true; + } + } return false; } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index e7a351b6a..d14adcd43 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -65,7 +65,7 @@ public class TestPrograms { @Test public void testTernaryInference() throws IOException, URISyntaxException { - compileAndCompare("ternary-inference"); + compileAndCompare("ternary-inference", log()); } @Test From 06aed186e2d053c8aa4e092b56e3fc2ebf5f17a5 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 18 May 2019 12:43:13 +0200 Subject: [PATCH 41/93] Fixed type inference for rangenext --- .../camelot64/kickc/model/types/SymbolTypeInference.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index 75ef3d7e5..4a244cbdb 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -118,7 +118,12 @@ public class SymbolTypeInference { } else if(rValue instanceof RangeComparison) { return ((RangeComparison) rValue).getType(); } else if(rValue instanceof RangeNext) { - return inferType(symbols, ((RangeNext) rValue).getRangeFirst()); + SymbolType rangedType = inferType(symbols, ((RangeNext) rValue).getRangeFirst()); + if(SymbolType.SBYTE.equals(rangedType) || SymbolType.SWORD.equals(rangedType) || SymbolType.SDWORD.equals(rangedType)) { + return SymbolType.SBYTE; + } else { + return SymbolType.BYTE; + } } else if(rValue instanceof ProcedureRef) { Procedure procedure = symbols.getProcedure((ProcedureRef) rValue); return procedure.getType(); From fe41c2ba4290007cb662fa13eda837d1bec5df2f Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 18 May 2019 13:58:26 +0200 Subject: [PATCH 42/93] Fixed array indexing using word-size indices --- .../java/dk/camelot64/kickc/Compiler.java | 9 +++-- .../kickc/model/VariableReferenceInfos.java | 36 +++++++++++-------- .../dk/camelot64/kickc/test/TestPrograms.java | 25 ++++++++++--- src/test/kc/derefidx-word-0.kc | 10 ++++++ src/test/kc/derefidx-word-1.kc | 7 ++++ src/test/kc/derefidx-word-2.kc | 9 +++++ 6 files changed, 75 insertions(+), 21 deletions(-) create mode 100644 src/test/kc/derefidx-word-0.kc create mode 100644 src/test/kc/derefidx-word-1.kc create mode 100644 src/test/kc/derefidx-word-2.kc diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index eb8f14abf..3aa809b1b 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -267,10 +267,10 @@ public class Compiler { optimizations.add(new Pass2ComparisonOptimization(program)); optimizations.add(new Pass2ConstantCallPointerIdentification(program)); optimizations.add(new Pass2SizeOfSimplification(program)); - optimizations.add(new Pass2InlineDerefIdx(program)); optimizations.add(new Pass2InlineCast(program)); - optimizations.add(new Pass2DeInlineWordDerefIdx(program)); optimizations.add(new PassNCastSimplification(program)); + optimizations.add(new Pass2InlineDerefIdx(program)); + optimizations.add(new Pass2DeInlineWordDerefIdx(program)); pass2Execute(optimizations); } @@ -303,6 +303,8 @@ public class Compiler { private void pass2InlineConstants() { // Constant inlining optimizations - as the last step to ensure that constant identification has been completed List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>(); + constantOptimizations.add(new PassNStatementIndices(program)); + constantOptimizations.add(new PassNVariableReferenceInfos(program)); constantOptimizations.add(new Pass2MultiplyToShiftRewriting(program)); constantOptimizations.add(new Pass2AliasElimination(program)); constantOptimizations.add(new Pass2ConstantInlining(program)); @@ -315,6 +317,9 @@ public class Compiler { constantOptimizations.add(new Pass2ConstantSimplification(program)); constantOptimizations.add(new PassNCastSimplification(program)); constantOptimizations.add(new Pass2ConstantIfs(program)); + constantOptimizations.add(new Pass2InlineDerefIdx(program)); + constantOptimizations.add(new PassNEliminateUnusedVars(program, true)); + pass2Execute(constantOptimizations); } diff --git a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java index fec6f0316..a799b28bd 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java @@ -224,9 +224,11 @@ public class VariableReferenceInfos { public Collection<Integer> getConstRefStatements(ConstantRef constRef) { Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef); LinkedHashSet<Integer> stmts = new LinkedHashSet<>(); - refs.stream() - .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) - .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx())); + if(refs!=null) { + refs.stream() + .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) + .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx())); + } return stmts; } @@ -239,9 +241,11 @@ public class VariableReferenceInfos { public Collection<Integer> getVarRefStatements(VariableRef varRef) { Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef); LinkedHashSet<Integer> stmts = new LinkedHashSet<>(); - refs.stream() - .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) - .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx())); + if(refs!=null) { + refs.stream() + .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) + .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx())); + } return stmts; } @@ -254,10 +258,12 @@ public class VariableReferenceInfos { public Collection<Integer> getVarUseStatements(VariableRef varRef) { Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef); LinkedHashSet<Integer> stmts = new LinkedHashSet<>(); - refs.stream() - .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) - .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE == referenceToSymbolVar.getReferenceType()) - .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx())); + if(refs!=null) { + refs.stream() + .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) + .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE == referenceToSymbolVar.getReferenceType()) + .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx())); + } return stmts; } @@ -271,10 +277,12 @@ public class VariableReferenceInfos { public Collection<SymbolVariableRef> getSymbolRefConsts(ConstantRef constRef) { Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef); LinkedHashSet<SymbolVariableRef> constRefs = new LinkedHashSet<>(); - refs.stream() - .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType())) - .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol) - .forEach(referenceToSymbolVar -> constRefs.add(((ReferenceInSymbol) referenceToSymbolVar).getReferencingSymbol())); + if(refs!=null) { + refs.stream() + .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType())) + .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol) + .forEach(referenceToSymbolVar -> constRefs.add(((ReferenceInSymbol) referenceToSymbolVar).getReferencingSymbol())); + } return constRefs; } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index d14adcd43..9f56c9b5e 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,6 +63,26 @@ public class TestPrograms { */ + @Test + public void testDoubleIndexingArrays() throws IOException, URISyntaxException { + compileAndCompare("double-indexing-arrays"); + } + + @Test + public void testDerefidxWord2() throws IOException, URISyntaxException { + compileAndCompare("derefidx-word-2"); + } + + @Test + public void testDerefidxWord1() throws IOException, URISyntaxException { + compileAndCompare("derefidx-word-1"); + } + + @Test + public void testDerefidxWord0() throws IOException, URISyntaxException { + compileAndCompare("derefidx-word-0"); + } + @Test public void testTernaryInference() throws IOException, URISyntaxException { compileAndCompare("ternary-inference", log()); @@ -574,11 +594,6 @@ public class TestPrograms { compileAndCompare("irq-idx-problem"); } - @Test - public void testDoubleIndexingArrays() throws IOException, URISyntaxException { - compileAndCompare("double-indexing-arrays"); - } - @Test public void testInlineKickAsmClobber() throws IOException, URISyntaxException { compileAndCompare("inline-kasm-clobber"); diff --git a/src/test/kc/derefidx-word-0.kc b/src/test/kc/derefidx-word-0.kc new file mode 100644 index 000000000..7b5117853 --- /dev/null +++ b/src/test/kc/derefidx-word-0.kc @@ -0,0 +1,10 @@ +// Tests that array-indexing by a word variable is turned into pointer addition + +void main() { + const byte* screen = 0x0400; + for( word i=0;i<1000;i+=40) { + screen[i] = 'a'; + } + +} + diff --git a/src/test/kc/derefidx-word-1.kc b/src/test/kc/derefidx-word-1.kc new file mode 100644 index 000000000..5124674fa --- /dev/null +++ b/src/test/kc/derefidx-word-1.kc @@ -0,0 +1,7 @@ +// Tests that array-indexing by a constant word is turned into a constant pointer + +void main() { + const byte* screen = 0x0400; + screen[40*10] = 'a'; +} + diff --git a/src/test/kc/derefidx-word-2.kc b/src/test/kc/derefidx-word-2.kc new file mode 100644 index 000000000..af8417918 --- /dev/null +++ b/src/test/kc/derefidx-word-2.kc @@ -0,0 +1,9 @@ +// Tests that array-indexing by a word variable that is a sum of a constant word and a byte is turned back into derefidx + +void main() { + const byte* screen = 0x0400; + for( byte i : 0..39) { + screen[40*10+i] = 'a'; + } +} + From 9cec38d0754a38044605a314b94d96230321c845 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 18 May 2019 21:37:34 +0200 Subject: [PATCH 43/93] Fixed negative numbers, zero-addition, zero inlining. --- .../java/dk/camelot64/kickc/Compiler.java | 7 + .../camelot64/kickc/fragment/AsmFormat.java | 2 +- .../kickc/fragment/AsmFragmentInstance.java | 3 +- .../AsmFragmentInstanceSpecFactory.java | 43 ++++-- .../model/operators/OperatorBitwiseAnd.java | 5 +- .../model/operators/OperatorGetHigh.java | 6 + .../kickc/model/operators/OperatorGetLow.java | 8 +- .../model/types/SymbolTypeConversion.java | 15 +- .../kickc/passes/Pass2InlineDerefIdx.java | 6 + .../passes/Pass4RegisterUpliftRemains.java | 7 +- .../passes/PassNSimplifyConstantZero.java | 44 ++++++ .../PassNSimplifyExpressionWithZero.java | 58 ++++++++ .../dk/camelot64/kickc/test/TestPrograms.java | 7 +- .../kc/examples/sinplotter/sine-plotter.kc | 2 +- src/test/kc/gfxbank.kc | 8 + src/test/ref/bresenhamarr.asm | 3 +- src/test/ref/c64dtv-8bppcharstretch.asm | 7 +- src/test/ref/c64dtv-8bppchunkystretch.asm | 10 +- src/test/ref/c64dtv-blittermin.asm | 7 +- src/test/ref/cast-not-needed-2.asm | 6 +- src/test/ref/cast-not-needed-3.asm | 6 +- src/test/ref/cast-precedence-problem.asm | 2 +- src/test/ref/complex/tetris/test-sprites.asm | 2 +- src/test/ref/complex/tetris/tetris.asm | 46 +++--- src/test/ref/consolidate-constant-problem.asm | 4 +- src/test/ref/const-signed-promotion.asm | 1 - src/test/ref/constantmin.asm | 3 +- src/test/ref/constants.asm | 2 +- src/test/ref/derefidx-word-0.asm | 39 +++++ src/test/ref/derefidx-word-1.asm | 10 ++ src/test/ref/derefidx-word-2.asm | 15 ++ src/test/ref/examples/3d/3d.asm | 51 +++---- src/test/ref/examples/3d/perspective.asm | 6 +- .../examples/bresenham/bitmap-bresenham.asm | 11 +- .../ref/examples/chargen/chargen-analysis.asm | 5 +- .../examples/fastmultiply/fastmultiply8.asm | 7 +- src/test/ref/examples/fire/fire.asm | 2 +- .../multiplexer/simple-multiplexer.asm | 8 +- .../ref/examples/plasma/plasma-unroll.asm | 2 +- src/test/ref/examples/plasma/plasma.asm | 2 +- src/test/ref/examples/rotate/rotate.asm | 80 +++++----- .../ref/examples/scrolllogo/scrolllogo.asm | 133 +++++++++-------- .../ref/examples/sinplotter/sine-plotter.asm | 137 ++++++++++-------- .../ref/examples/sinsprites/sinus-sprites.asm | 6 +- src/test/ref/forrangedwords.asm | 2 +- src/test/ref/fragment-variations.asm | 74 ++++++++++ src/test/ref/gfxbank.asm | 16 ++ src/test/ref/halfscii.asm | 28 ++-- src/test/ref/inline-function-if.asm | 4 +- src/test/ref/inline-kasm-resource.asm | 2 +- src/test/ref/inline-pointer-0.asm | 10 ++ src/test/ref/inline-pointer-1.asm | 24 +++ src/test/ref/inline-pointer-2.asm | 9 ++ src/test/ref/inline-string-3.asm | 9 +- src/test/ref/inline-word-0.asm | 13 ++ src/test/ref/inline-word-1.asm | 13 ++ src/test/ref/inline-word-2.asm | 13 ++ src/test/ref/inline-word.asm | 3 +- src/test/ref/int-literals.asm | 16 +- src/test/ref/line-anim.asm | 84 ++++++----- src/test/ref/linegen.asm | 16 +- src/test/ref/liverange-call-problem.asm | 4 +- src/test/ref/min-fmul-16.asm | 2 +- src/test/ref/mixed-array-0.asm | 15 ++ src/test/ref/mixed-array-1.asm | 15 ++ .../simple-multiplexer-irq.asm | 8 +- src/test/ref/number-conversion.asm | 8 +- src/test/ref/operator-lohi-problem.asm | 6 +- src/test/ref/ptr-complex.asm | 3 +- src/test/ref/roll-sprite-msb.asm | 6 +- src/test/ref/scan-desire-problem.asm | 5 +- src/test/ref/semi-struct-2.asm | 5 +- src/test/ref/signed-indexed-subtract.asm | 53 ++++--- src/test/ref/signed-words.asm | 36 +++-- src/test/ref/sinus-basic.asm | 4 +- src/test/ref/sinusgen16.asm | 65 +++++---- src/test/ref/sinusgen16b.asm | 124 +++++++++------- src/test/ref/sinusgen8.asm | 25 ++-- src/test/ref/sinusgen8b.asm | 83 ++++++----- src/test/ref/sinusgenscale8.asm | 28 ++-- src/test/ref/sizeof-expr.asm | 10 +- src/test/ref/test-comparisons-sword.asm | 6 +- src/test/ref/test-division.asm | 65 ++++----- src/test/ref/test-multiply-16bit.asm | 99 +++++++++---- src/test/ref/test-multiply-8bit.asm | 65 ++++++--- src/test/ref/test-scroll-up.asm | 4 +- src/test/ref/test-signed-word-minus-byte.asm | 28 +++- src/test/ref/test-word-size-arrays.asm | 2 +- src/test/ref/true-inline-words.asm | 6 +- src/test/ref/type-inference.asm | 23 +++ src/test/ref/type-mix.asm | 15 +- src/test/ref/typeid-plus-bytes.asm | 113 +++++++++++++-- src/test/ref/uninitialized.asm | 7 +- src/test/ref/valuelist-error.asm | 10 ++ 94 files changed, 1441 insertions(+), 677 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNSimplifyConstantZero.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNSimplifyExpressionWithZero.java create mode 100644 src/test/kc/gfxbank.kc create mode 100644 src/test/ref/derefidx-word-0.asm create mode 100644 src/test/ref/derefidx-word-1.asm create mode 100644 src/test/ref/derefidx-word-2.asm create mode 100644 src/test/ref/fragment-variations.asm create mode 100644 src/test/ref/gfxbank.asm create mode 100644 src/test/ref/inline-pointer-0.asm create mode 100644 src/test/ref/inline-pointer-1.asm create mode 100644 src/test/ref/inline-pointer-2.asm create mode 100644 src/test/ref/inline-word-0.asm create mode 100644 src/test/ref/inline-word-1.asm create mode 100644 src/test/ref/inline-word-2.asm create mode 100644 src/test/ref/mixed-array-0.asm create mode 100644 src/test/ref/mixed-array-1.asm create mode 100644 src/test/ref/type-inference.asm create mode 100644 src/test/ref/valuelist-error.asm diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 3aa809b1b..b5dd695b3 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -269,8 +269,12 @@ public class Compiler { optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new Pass2InlineCast(program)); optimizations.add(new PassNCastSimplification(program)); + optimizations.add(new PassNStatementIndices(program)); + optimizations.add(new PassNVariableReferenceInfos(program)); optimizations.add(new Pass2InlineDerefIdx(program)); optimizations.add(new Pass2DeInlineWordDerefIdx(program)); + optimizations.add(new PassNSimplifyConstantZero(program)); + optimizations.add(new PassNSimplifyExpressionWithZero(program)); pass2Execute(optimizations); } @@ -319,6 +323,9 @@ public class Compiler { constantOptimizations.add(new Pass2ConstantIfs(program)); constantOptimizations.add(new Pass2InlineDerefIdx(program)); constantOptimizations.add(new PassNEliminateUnusedVars(program, true)); + constantOptimizations.add(new PassNSimplifyConstantZero(program)); + constantOptimizations.add(new PassNSimplifyExpressionWithZero(program)); + pass2Execute(constantOptimizations); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java index 3e0c94f69..edd3e0899 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java @@ -231,7 +231,7 @@ public class AsmFormat { return SHORT_ASM_NUMBERS[number.intValue()]; } else { if(number.longValue()<0) { - return String.format("-$%x", -number.longValue()); + return "-"+getAsmNumber(-number.longValue()); } else { return String.format("$%x", number.longValue()); } diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java index 53793f4c9..21f9e65f3 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java @@ -300,8 +300,7 @@ public class AsmFragmentInstance { @Override public AsmParameter visitAsmExprInt(KickCParser.AsmExprIntContext ctx) { Number number = NumberParser.parseLiteral(ctx.NUMBER().getText()); - ConstantInteger intVal = new ConstantInteger(number.longValue()); - boolean isZp = SymbolType.BYTE.equals(intVal.getType()) || SymbolType.SBYTE.equals(intVal.getType()); + boolean isZp = SymbolType.BYTE.contains(number.longValue()) || SymbolType.SBYTE.contains(number.longValue()); String param = AsmFormat.getAsmNumber(number); return new AsmParameter(param, isZp); } diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java index 5030079a3..f3e3624c4 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java @@ -1,9 +1,6 @@ package dk.camelot64.kickc.fragment; -import dk.camelot64.kickc.model.ControlFlowBlock; -import dk.camelot64.kickc.model.ControlFlowGraph; -import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.Registers; +import dk.camelot64.kickc.model.*; import dk.camelot64.kickc.model.operators.Operator; import dk.camelot64.kickc.model.operators.OperatorUnary; import dk.camelot64.kickc.model.operators.Operators; @@ -17,6 +14,7 @@ import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.*; +import java.lang.InternalError; import java.util.LinkedHashMap; import java.util.Map; @@ -242,17 +240,32 @@ public class AsmFragmentInstanceSpecFactory { if(castType == null) { SymbolType toType = castVal.getToType(); // If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff ) - ConstantLiteral constantLiteral = val.calculateLiteral(program.getScope()); - if(constantLiteral instanceof ConstantInteger) { - if(toType instanceof SymbolTypeIntegerFixed) { - if(!((SymbolTypeIntegerFixed) toType).contains(((ConstantInteger) constantLiteral).getValue())) { - if(toType.getSizeBytes() == 1) { - val = new ConstantBinary(new ConstantInteger(0xffL, SymbolType.BYTE), Operators.BOOL_AND, val); - } else if(toType.getSizeBytes() == 2) { - val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val); - } else { - throw new InternalError("Not implemented!"); - } + + if(toType instanceof SymbolTypeIntegerFixed) { + SymbolTypeIntegerFixed integerFixed = (SymbolTypeIntegerFixed) toType; + ConstantLiteral constantLiteral; + Long integerValue; + try { + constantLiteral = val.calculateLiteral(program.getScope()); + if(constantLiteral instanceof ConstantInteger) { + integerValue = ((ConstantInteger) constantLiteral).getValue(); + } else if(constantLiteral instanceof ConstantPointer) { + integerValue = ((ConstantPointer) constantLiteral).getValue(); + } else { + throw new InternalError("Not implemented "+constantLiteral); + } + } catch (ConstantNotLiteral e) { + // Assume it is a word + integerValue = 0xffffL; + } + + if(!integerFixed.contains(integerValue)) { + if(toType.getSizeBytes() == 1) { + val = new ConstantBinary(new ConstantInteger(0xffL, SymbolType.BYTE), Operators.BOOL_AND, val); + } else if(toType.getSizeBytes() == 2) { + val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val); + } else { + throw new InternalError("Not implemented "+toType); } } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java index e7906ff6f..931576215 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java @@ -31,7 +31,10 @@ public class OperatorBitwiseAnd extends OperatorBinary { } // Handle numeric types if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) { - return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2); + if(type1.getSizeBytes()<type2.getSizeBytes()) + return type1; + else + return type2; } throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java index d28f2f49f..79902c0c2 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java @@ -26,6 +26,10 @@ public class OperatorGetHigh extends OperatorUnary { return new ConstantInteger(operandInt.getInteger()>>8); } else if(SymbolType.DWORD.equals(operandInt.getType()) || SymbolType.SDWORD.equals(operandInt.getType())) { return new ConstantInteger(operandInt.getInteger()>>16); + } else if(SymbolType.BYTE.equals(operandInt.getType()) || SymbolType.SBYTE.equals(operandInt.getType())) { + return new ConstantInteger(0L, SymbolType.BYTE); + } else if(SymbolType.NUMBER.equals(operandInt.getType())) { + throw new ConstantNotLiteral("Operand not resolved "+operand); } } else if(operand instanceof ConstantPointer) { return new ConstantInteger(((ConstantPointer) operand).getLocation()>>8); @@ -41,6 +45,8 @@ public class OperatorGetHigh extends OperatorUnary { return SymbolType.BYTE; } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) { return SymbolType.WORD; + } else if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) { + return SymbolType.BYTE; } else if(SymbolType.STRING.equals(operandType)) { return SymbolType.BYTE; } else if(SymbolType.NUMBER.equals(operandType)) { diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java index c05e748d4..7542903f6 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java @@ -26,13 +26,17 @@ public class OperatorGetLow extends OperatorUnary { return new ConstantInteger(operandInt.getInteger()&0xff); } else if(SymbolType.DWORD.equals(operandInt.getType()) || SymbolType.SDWORD.equals(operandInt.getType())) { return new ConstantInteger(operandInt.getInteger()&0xffff); + } else if(SymbolType.BYTE.equals(operandInt.getType()) || SymbolType.SBYTE.equals(operandInt.getType())) { + return operandInt; + } else if(SymbolType.NUMBER.equals(operandInt.getType())) { + throw new ConstantNotLiteral("Operand not resolved "+operand); } } else if(operand instanceof ConstantPointer) { return new ConstantInteger(((ConstantPointer) operand).getLocation()&0xff); } else if(operand instanceof ConstantString) { throw new ConstantNotLiteral("address of string is not literal"); } - throw new CompileError("Calculation not implemented " + getOperator() + " " + operand ); + throw new ConstantNotLiteral("Calculation not implemented " + getOperator() + " " + operand ); } @Override @@ -41,6 +45,8 @@ public class OperatorGetLow extends OperatorUnary { return SymbolType.BYTE; } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) { return SymbolType.WORD; + } else if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) { + return SymbolType.BYTE; } else if(SymbolType.STRING.equals(operandType)) { return SymbolType.BYTE; } else if(SymbolType.NUMBER.equals(operandType)) { diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index b82e23e76..df8ec8b90 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -1,6 +1,7 @@ package dk.camelot64.kickc.model.types; import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.InternalError; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.symbols.ProgramScope; @@ -103,7 +104,13 @@ public class SymbolTypeConversion { // Find the cast type if possible if(numberVal instanceof ConstantValue) { - ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols); + ConstantLiteral constantLiteral; + try { + constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols); + } catch( ConstantNotLiteral e) { + // Postpone til later! + return null; + } if(constantLiteral instanceof ConstantInteger) { ConstantInteger constantInteger = (ConstantInteger) constantLiteral; if(SymbolType.NUMBER.equals(constantInteger.getType())) { @@ -161,7 +168,11 @@ public class SymbolTypeConversion { if(lValueType.equals(SymbolType.SDWORD) && rValueType.equals(SymbolType.SWORD)) return true; if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) { - // L-value is still a number - constants are probably not done being identified & typed + // R-value is still a number - constants are probably not done being identified & typed + return true; + } + if(SymbolType.NUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) { + // R-value is still a number - constants are probably not done being identified & typed return true; } if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java index 795d55117..3a8146be7 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java @@ -12,6 +12,7 @@ import dk.camelot64.kickc.model.types.SymbolTypeInference; import dk.camelot64.kickc.model.types.SymbolTypePointer; import dk.camelot64.kickc.model.values.*; +import java.util.Collection; import java.util.concurrent.atomic.AtomicBoolean; /** Identify derefs of pointers that are defined as pointer + value - and inline them as derefidx instead */ @@ -71,6 +72,11 @@ public class Pass2InlineDerefIdx extends Pass2SsaOptimization { public RValue attemptInlineDeref(StatementAssignment derefAssignment) { + VariableRef derefVar = (VariableRef) derefAssignment.getlValue(); + Collection<Integer> varUseStatements = getProgram().getVariableReferenceInfos().getVarUseStatements(derefVar); + if(varUseStatements.size()>2) { + return null; + } if(Operators.PLUS.equals(derefAssignment.getOperator())) { SymbolType derefLeftType = SymbolTypeInference.inferType(getScope(), derefAssignment.getrValue1()); if(derefLeftType instanceof SymbolTypePointer) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java index 6e023bbb0..7e4f48ee0 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java @@ -18,12 +18,7 @@ public class Pass4RegisterUpliftRemains extends Pass2Base { LiveRangeEquivalenceClassSet equivalenceClassSet = getProgram().getLiveRangeEquivalenceClassSet(); List<LiveRangeEquivalenceClass> equivalenceClasses = new ArrayList<>(equivalenceClassSet.getEquivalenceClasses()); final VariableRegisterWeights registerWeights = getProgram().getVariableRegisterWeights(); - Collections.sort(equivalenceClasses, new Comparator<LiveRangeEquivalenceClass>() { - @Override - public int compare(LiveRangeEquivalenceClass o1, LiveRangeEquivalenceClass o2) { - return Double.compare(registerWeights.getTotalWeight(o2), registerWeights.getTotalWeight(o1)); - } - }); + Collections.sort(equivalenceClasses, (o1, o2) -> Double.compare(registerWeights.getTotalWeight(o2), registerWeights.getTotalWeight(o1))); Set<String> unknownFragments = new LinkedHashSet<>(); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyConstantZero.java b/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyConstantZero.java new file mode 100644 index 000000000..6b01d695d --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyConstantZero.java @@ -0,0 +1,44 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.ConstantNotLiteral; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramValueIterator; +import dk.camelot64.kickc.model.values.*; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Simplify any constant expression evaluating to zero + */ +public class PassNSimplifyConstantZero extends Pass2SsaOptimization { + + public PassNSimplifyConstantZero(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean modified = new AtomicBoolean(false); + + ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> { + Value value = programValue.get(); + if(value instanceof ConstantValue && !(value instanceof ConstantInteger) &&!(value instanceof ConstantRef)) { + ConstantLiteral literal; + try { + literal = ((ConstantValue) value).calculateLiteral(getProgram().getScope()); + } catch( ConstantNotLiteral e) { + return; + } + if(literal instanceof ConstantInteger) { + if(((ConstantInteger) literal).getInteger()==0L) { + getLog().append("Simplifying constant evaluating to zero "+value.toString(getProgram()) + " in "+(currentStmt==null?"":currentStmt.toString(getProgram(), false))); + programValue.set(new ConstantInteger(0L, ((ConstantInteger) literal).getType())); + modified.set(true); + } + } + } + }); + return modified.get(); + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyExpressionWithZero.java b/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyExpressionWithZero.java new file mode 100644 index 000000000..c59ea0bd1 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyExpressionWithZero.java @@ -0,0 +1,58 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; +import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; +import dk.camelot64.kickc.model.operators.Operator; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.values.ConstantInteger; +import dk.camelot64.kickc.model.values.PointerDereferenceSimple; +import dk.camelot64.kickc.model.values.RValue; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Simplify any binary expression containing a zero value (if possible + */ +public class PassNSimplifyExpressionWithZero extends Pass2SsaOptimization { + + public PassNSimplifyExpressionWithZero(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean modified = new AtomicBoolean(false); + + ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> { + if(programExpression instanceof ProgramExpressionBinary) { + ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression; + RValue left = binary.getLeft(); + RValue right = binary.getRight(); + Operator operator = programExpression.getOperator(); + if(Operators.PLUS.equals(operator) || Operators.MINUS.equals(operator) || Operators.BOOL_OR.equals(operator) || Operators.BOOL_XOR.equals(operator)) { + if(left instanceof ConstantInteger && ((ConstantInteger) left).getInteger() == 0) { + getLog().append("Simplifying expression containing zero " + binary.getRight().toString()+ " in "+ (currentStmt==null?"":currentStmt.toString(getProgram(), false))); + if(programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed) { + programExpression.set(new PointerDereferenceSimple(binary.getRight())); + } else { + programExpression.set(binary.getRight()); + } + modified.set(true); + } else if(right instanceof ConstantInteger && ((ConstantInteger) right).getInteger() == 0) { + getLog().append("Simplifying expression containing zero " + binary.getLeft().toString()+ " in "+ (currentStmt==null?"":currentStmt.toString(getProgram(), false))); + if(programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed) { + programExpression.set(new PointerDereferenceSimple(binary.getLeft())); + } else { + programExpression.set(binary.getLeft()); + } + modified.set(true); + } + } + } + }); + + return modified.get(); + } + +} diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 9f56c9b5e..7a4ea6db5 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,6 +63,11 @@ public class TestPrograms { */ + @Test + public void testGfxBankOptimization() throws IOException, URISyntaxException { + compileAndCompare("gfxbank"); + } + @Test public void testDoubleIndexingArrays() throws IOException, URISyntaxException { compileAndCompare("double-indexing-arrays"); @@ -1743,7 +1748,7 @@ public class TestPrograms { @Test public void testForClassicMin() throws IOException, URISyntaxException { - compileAndCompare("forclassicmin", log()); + compileAndCompare("forclassicmin"); } @Test diff --git a/src/test/kc/examples/sinplotter/sine-plotter.kc b/src/test/kc/examples/sinplotter/sine-plotter.kc index 300f5591c..a46eb11c2 100644 --- a/src/test/kc/examples/sinplotter/sine-plotter.kc +++ b/src/test/kc/examples/sinplotter/sine-plotter.kc @@ -12,7 +12,7 @@ const word SIN_SIZE = 512; signed word[512] align($100) sin; -signed word* sin2 = $1500; +signed word* sin2 = $1400; kickasm(pc sin2) {{ .for(var i=0; i<512; i++) { diff --git a/src/test/kc/gfxbank.kc b/src/test/kc/gfxbank.kc new file mode 100644 index 000000000..990aaa585 --- /dev/null +++ b/src/test/kc/gfxbank.kc @@ -0,0 +1,8 @@ +// Test minimization of constants + +import "c64" + +void main() { + const byte* PLAYFIELD_CHARSET = $2800; + vicSelectGfxBank(PLAYFIELD_CHARSET); +} diff --git a/src/test/ref/bresenhamarr.asm b/src/test/ref/bresenhamarr.asm index 7c3c586de..6f5b47054 100644 --- a/src/test/ref/bresenhamarr.asm +++ b/src/test/ref/bresenhamarr.asm @@ -19,9 +19,8 @@ main: { ldx #yd/2 lda #x0 sta x - lda #x0+y0*$28 + lda #<0 sta idx - lda #0 sta idx+1 b1: lda idx diff --git a/src/test/ref/c64dtv-8bppcharstretch.asm b/src/test/ref/c64dtv-8bppcharstretch.asm index 0e1316723..4cb9bf646 100644 --- a/src/test/ref/c64dtv-8bppcharstretch.asm +++ b/src/test/ref/c64dtv-8bppcharstretch.asm @@ -77,7 +77,7 @@ main: { lda #VIC_MCM|VIC_CSEL sta VIC_CONTROL2 // Plane A: SCREEN - lda #<SCREEN + lda #0 sta DTV_PLANEA_START_LO lda #>SCREEN sta DTV_PLANEA_START_MI @@ -89,7 +89,6 @@ main: { sta DTV_PLANEA_MODULO_LO sta DTV_PLANEA_MODULO_HI // Plane B: CHARSET8 - lda #<CHARSET8 sta DTV_PLANEB_START_LO lda #>CHARSET8 sta DTV_PLANEB_START_MI @@ -233,9 +232,9 @@ gfx_init_plane_charset8: { lda #0 sta ch sta col - lda #<$4000+(CHARSET8&$3fff) + lda #<$4000 sta gfxa - lda #>$4000+(CHARSET8&$3fff) + lda #>$4000 sta gfxa+1 lda #<CHARGEN+1 sta chargen diff --git a/src/test/ref/c64dtv-8bppchunkystretch.asm b/src/test/ref/c64dtv-8bppchunkystretch.asm index 47a9811aa..350dbd2a5 100644 --- a/src/test/ref/c64dtv-8bppchunkystretch.asm +++ b/src/test/ref/c64dtv-8bppchunkystretch.asm @@ -65,7 +65,7 @@ main: { lda #VIC_MCM|VIC_CSEL sta VIC_CONTROL2 // Plane B: CHUNKY - lda #<CHUNKY + lda #0 sta DTV_PLANEB_START_LO lda #>CHUNKY sta DTV_PLANEB_START_MI @@ -84,9 +84,9 @@ main: { sta CIA2_PORT_A // Set VIC Bank // VIC memory - lda #(CHUNKY&$3fff)/$40|(0)/4 + lda #0 sta VIC_MEMORY - ldx #0 + tax // DTV Palette - Grey Tones b1: txa @@ -195,7 +195,7 @@ gfx_init_chunky: { .label gfxb = 5 .label x = 3 .label y = 2 - lda #$ff&CHUNKY/$4000 + lda #CHUNKY/$4000 jsr dtvSetCpuBankSegment1 ldx #($ff&CHUNKY/$4000)+1 lda #0 @@ -205,7 +205,7 @@ gfx_init_chunky: { lda #>$4000 sta gfxb+1 b1: - lda #0 + lda #<0 sta x sta x+1 b2: diff --git a/src/test/ref/c64dtv-blittermin.asm b/src/test/ref/c64dtv-blittermin.asm index b74c1966c..b7e126dea 100644 --- a/src/test/ref/c64dtv-blittermin.asm +++ b/src/test/ref/c64dtv-blittermin.asm @@ -85,9 +85,9 @@ main: { sta DTV_BLITTER_SRCA_HI sta DTV_BLITTER_SRCA_MOD_LO sta DTV_BLITTER_SRCA_MOD_HI - lda #<$100 + lda #<$80 sta DTV_BLITTER_SRCA_LIN_LO - lda #>$100 + lda #0 sta DTV_BLITTER_SRCA_LIN_HI lda #$10 sta DTV_BLITTER_SRCA_STEP @@ -100,14 +100,12 @@ main: { sta DTV_BLITTER_SRCB_HI sta DTV_BLITTER_SRCB_MOD_LO sta DTV_BLITTER_SRCB_MOD_HI - lda #<$100 sta DTV_BLITTER_SRCB_LIN_LO lda #>$100 sta DTV_BLITTER_SRCB_LIN_HI lda #0 sta DTV_BLITTER_SRCB_STEP // Step 0.0 - lda #<SCREEN sta DTV_BLITTER_DEST_LO lda #>SCREEN sta DTV_BLITTER_DEST_MI @@ -115,7 +113,6 @@ main: { sta DTV_BLITTER_DEST_HI sta DTV_BLITTER_DEST_MOD_LO sta DTV_BLITTER_DEST_MOD_HI - lda #<$100 sta DTV_BLITTER_DEST_LIN_LO lda #>$100 sta DTV_BLITTER_DEST_LIN_HI diff --git a/src/test/ref/cast-not-needed-2.asm b/src/test/ref/cast-not-needed-2.asm index c91a7229a..f6c04cf1c 100644 --- a/src/test/ref/cast-not-needed-2.asm +++ b/src/test/ref/cast-not-needed-2.asm @@ -2,14 +2,12 @@ .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" - .const SIZEOF_POINTER = 2 main: { - .const getScreen1_id = 0 .label getScreen1_return = 2 .label spritePtr1_return = 2 - lda screens+getScreen1_id*SIZEOF_POINTER + lda screens sta getScreen1_return - lda screens+getScreen1_id*SIZEOF_POINTER+1 + lda screens+1 sta getScreen1_return+1 clc lda spritePtr1_return diff --git a/src/test/ref/cast-not-needed-3.asm b/src/test/ref/cast-not-needed-3.asm index 4a3ee07b6..c57565015 100644 --- a/src/test/ref/cast-not-needed-3.asm +++ b/src/test/ref/cast-not-needed-3.asm @@ -2,15 +2,13 @@ .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" - .const SIZEOF_POINTER = 2 main: { .label DSP = $400 - .const getScreen1_id = 0 .label getScreen1_return = 2 .label spritePtr1__0 = 2 - lda screens+getScreen1_id*SIZEOF_POINTER + lda screens sta getScreen1_return - lda screens+getScreen1_id*SIZEOF_POINTER+1 + lda screens+1 sta getScreen1_return+1 clc lda spritePtr1__0 diff --git a/src/test/ref/cast-precedence-problem.asm b/src/test/ref/cast-precedence-problem.asm index d0d46735c..18f118178 100644 --- a/src/test/ref/cast-precedence-problem.asm +++ b/src/test/ref/cast-precedence-problem.asm @@ -7,8 +7,8 @@ main: { .const min = $a .const max = $c8 .label BGCOL = $d021 - .const sumb = min+max .const sumw = min+max + .const sumb = min+max .const midb = (sumb>>1)+1 .const midw = (sumw>>1)+1 lda #midw diff --git a/src/test/ref/complex/tetris/test-sprites.asm b/src/test/ref/complex/tetris/test-sprites.asm index a35164dc2..61571e8bb 100644 --- a/src/test/ref/complex/tetris/test-sprites.asm +++ b/src/test/ref/complex/tetris/test-sprites.asm @@ -84,7 +84,7 @@ bbegin: rts main: { .const toSpritePtr2_return = SIN_SPRITE/$40 - .const vicSelectGfxBank1_toDd001_return = 3^(>PLAYFIELD_SCREEN_1)/$40 + .const vicSelectGfxBank1_toDd001_return = 3 .const toD0181_return = (>(PLAYFIELD_SCREEN_1&$3fff)*4)|(>PLAYFIELD_CHARSET)/4&$f .label xpos = 2 .label ypos = 3 diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm index 889a3b29e..5787e8dbe 100644 --- a/src/test/ref/complex/tetris/tetris.asm +++ b/src/test/ref/complex/tetris/tetris.asm @@ -205,18 +205,20 @@ main: { ldx play_spawn_current.piece_idx lda #$20 jsr render_next - ldy play_spawn_current._7 - lda PIECES,y + lda current_piece_gfx sta current_piece - lda PIECES+1,y + lda current_piece_gfx+1 sta current_piece+1 lda #0 sta level_bcd sta level sta score_bcd sta score_bcd+1 + lda #<0>>$10 sta score_bcd+2 + lda #>0>>$10 sta score_bcd+3 + lda #<0 sta lines_bcd sta lines_bcd+1 sta current_movedown_counter @@ -308,16 +310,16 @@ render_score: { jsr render_bcd ldx score_bytes+1 ldy #0 - lda #score_offset+2 + lda #<score_offset+2 sta render_bcd.offset - tya + lda #>score_offset+2 sta render_bcd.offset+1 jsr render_bcd ldx score_bytes ldy #0 - lda #score_offset+4 + lda #<score_offset+4 sta render_bcd.offset - tya + lda #>score_offset+4 sta render_bcd.offset+1 jsr render_bcd lda lines_bcd+1 @@ -331,9 +333,9 @@ render_score: { lda lines_bcd tax ldy #0 - lda #lines_offset+1 + lda #<lines_offset+1 sta render_bcd.offset - tya + lda #>lines_offset+1 sta render_bcd.offset+1 jsr render_bcd ldx level_bcd @@ -390,8 +392,8 @@ render_bcd: { // Render the next tetromino in the "next" area render_next: { .const next_area_offset = $28*$c+$18+4 - .label next_piece_char = $a .label next_piece_gfx = 5 + .label next_piece_char = $a .label screen_next_area = 7 .label l = 9 cmp #0 @@ -409,13 +411,14 @@ render_next: { b1: txa asl + // Render the next piece tay - lda PIECES_NEXT_CHARS,x - sta next_piece_char lda PIECES,y sta next_piece_gfx lda PIECES+1,y sta next_piece_gfx+1 + lda PIECES_NEXT_CHARS,x + sta next_piece_char lda #0 sta l b3: @@ -816,10 +819,9 @@ play_move_down: { tax jsr play_update_score jsr play_spawn_current - ldy play_spawn_current._7 - lda PIECES,y + lda current_piece_gfx sta current_piece - lda PIECES+1,y + lda current_piece_gfx+1 sta current_piece+1 lda #0 sta current_orientation @@ -838,20 +840,18 @@ play_move_down: { // Spawn a new piece // Moves the next piece into the current and spawns a new next piece play_spawn_current: { - .label _7 = 4 .label piece_idx = $21 // Move next piece into current ldx next_piece_idx txa asl - sta _7 - lda PIECES_CHARS,x - sta current_piece_char - ldy _7 + tay lda PIECES,y sta current_piece_gfx lda PIECES+1,y sta current_piece_gfx+1 + lda PIECES_CHARS,x + sta current_piece_char lda PIECES_START_X,x sta current_xpos lda PIECES_START_Y,x @@ -860,9 +860,9 @@ play_spawn_current: { sta play_collision.xpos lda current_ypos sta play_collision.ypos - lda PIECES,y + lda current_piece_gfx sta current_piece_104 - lda PIECES+1,y + lda current_piece_gfx+1 sta current_piece_104+1 ldx #0 jsr play_collision @@ -1378,7 +1378,7 @@ sprites_init: { } // Initialize rendering render_init: { - .const vicSelectGfxBank1_toDd001_return = 3^(>PLAYFIELD_CHARSET)/$40 + .const vicSelectGfxBank1_toDd001_return = 3 .label li_1 = 5 .label li_2 = 7 lda #3 diff --git a/src/test/ref/consolidate-constant-problem.asm b/src/test/ref/consolidate-constant-problem.asm index f8146c526..be6c8721f 100644 --- a/src/test/ref/consolidate-constant-problem.asm +++ b/src/test/ref/consolidate-constant-problem.asm @@ -6,7 +6,7 @@ main: { lda #0 sta screen+$27 sta screen+$26 - sta $28*1+screen+$27 - sta screen+$26+$28*1 + sta screen+$28*1+$27 + sta screen+$28*1+$26 rts } diff --git a/src/test/ref/const-signed-promotion.asm b/src/test/ref/const-signed-promotion.asm index 90042051c..fbe66dba9 100644 --- a/src/test/ref/const-signed-promotion.asm +++ b/src/test/ref/const-signed-promotion.asm @@ -2,7 +2,6 @@ .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" - .const SIZEOF_SIGNED_WORD = 2 main: { .label screen = $400 ldx #0 diff --git a/src/test/ref/constantmin.asm b/src/test/ref/constantmin.asm index 4832ff399..5fc98d7cf 100644 --- a/src/test/ref/constantmin.asm +++ b/src/test/ref/constantmin.asm @@ -5,12 +5,11 @@ .const STAR = $51 .label VIC = $d000 .const RED = 2 - .label BGCOL = VIC+$10*2+1 main: { lda #STAR sta SCREEN lda #RED - sta BGCOL + sta VIC+$10*2+1 ldx #$28 b1: lda #STAR+1 diff --git a/src/test/ref/constants.asm b/src/test/ref/constants.asm index e49be31e1..7d603723c 100644 --- a/src/test/ref/constants.asm +++ b/src/test/ref/constants.asm @@ -18,8 +18,8 @@ main: { test_sbytes: { .const bb = 0 .const bc = bb+2 - .const bd = bc-4 .const bf = $ff&-$7f-$7f + .const bd = bc-4 .const be = -bd lda #0 sta assert_sbyte.c diff --git a/src/test/ref/derefidx-word-0.asm b/src/test/ref/derefidx-word-0.asm new file mode 100644 index 000000000..a893d8fe3 --- /dev/null +++ b/src/test/ref/derefidx-word-0.asm @@ -0,0 +1,39 @@ +// Tests that array-indexing by a word variable is turned into pointer addition +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + .label i = 2 + .label _1 = 4 + lda #<0 + sta i + sta i+1 + b1: + lda i + clc + adc #<screen + sta _1 + lda i+1 + adc #>screen + sta _1+1 + lda #'a' + ldy #0 + sta (_1),y + lda #$28 + clc + adc i + sta i + bcc !+ + inc i+1 + !: + lda i+1 + cmp #>$3e8 + bcc b1 + bne !+ + lda i + cmp #<$3e8 + bcc b1 + !: + rts +} diff --git a/src/test/ref/derefidx-word-1.asm b/src/test/ref/derefidx-word-1.asm new file mode 100644 index 000000000..631845860 --- /dev/null +++ b/src/test/ref/derefidx-word-1.asm @@ -0,0 +1,10 @@ +// Tests that array-indexing by a constant word is turned into a constant pointer +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + lda #'a' + sta screen+$28*$a + rts +} diff --git a/src/test/ref/derefidx-word-2.asm b/src/test/ref/derefidx-word-2.asm new file mode 100644 index 000000000..44af2978a --- /dev/null +++ b/src/test/ref/derefidx-word-2.asm @@ -0,0 +1,15 @@ +// Tests that array-indexing by a word variable that is a sum of a constant word and a byte is turned back into derefidx +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + ldx #0 + b1: + lda #'a' + sta screen+$28*$a,x + inx + cpx #$28 + bne b1 + rts +} diff --git a/src/test/ref/examples/3d/3d.asm b/src/test/ref/examples/3d/3d.asm index 0dcdcb236..c555981f4 100644 --- a/src/test/ref/examples/3d/3d.asm +++ b/src/test/ref/examples/3d/3d.asm @@ -129,13 +129,13 @@ anim: { tya asl tax - lda #$80 + lda xp clc - adc xp + adc #$80 sta SPRITES_XPOS,x - lda #$80 + lda yp clc - adc yp + adc #$80 sta SPRITES_YPOS,x inc i lda #8 @@ -149,10 +149,9 @@ anim: { // Increment angles inc sx inc sx - lda sy - sec - sbc #3 - sta sy + lax sy + axs #3 + stx sy jmp b2 } debug_print: { @@ -336,8 +335,7 @@ print_sbyte_at: { .label at = 6 cpx #0 bmi b1 - lda #' ' - sta print_char_at.ch + ldy #' ' jsr print_char_at b2: inc print_byte_at.at @@ -347,8 +345,7 @@ print_sbyte_at: { jsr print_byte_at rts b1: - lda #'-' - sta print_char_at.ch + ldy #'-' jsr print_char_at txa eor #$ff @@ -358,17 +355,16 @@ print_sbyte_at: { jmp b2 } // Print a single char -// print_char_at(byte zeropage(8) ch, byte* zeropage(6) at) +// print_char_at(byte register(Y) ch, byte* zeropage(6) at) print_char_at: { .label at = 6 - .label ch = 8 - lda ch + tya ldy #0 sta (at),y rts } // Print a byte as HEX at a specific position -// print_byte_at(byte* zeropage(6) at) +// print_byte_at(byte register(X) b, byte* zeropage(6) at) print_byte_at: { .label at = 6 txa @@ -378,7 +374,7 @@ print_byte_at: { lsr tay lda print_hextab,y - sta print_char_at.ch + tay jsr print_char_at lda #$f axs #0 @@ -386,8 +382,7 @@ print_byte_at: { bne !+ inc print_char_at.at+1 !: - lda print_hextab,x - sta print_char_at.ch + ldy print_hextab,x jsr print_char_at rts } @@ -395,10 +390,10 @@ print_byte_at: { // The rotation matrix is prepared by calling prepare_matrix() // The passed points must be in the interval [-$3f;$3f]. // Implemented in assembler to utilize seriously fast multiplication -// rotate_matrix(signed byte register(X) x, signed byte zeropage(5) y, signed byte zeropage(8) z) +// rotate_matrix(signed byte register(X) x, signed byte zeropage(5) y, signed byte zeropage($a) z) rotate_matrix: { .label y = 5 - .label z = 8 + .label z = $a txa sta xr lda y @@ -543,7 +538,7 @@ calculate_matrix: { .label sy = 3 .label t1 = 4 .label t3 = 5 - .label t4 = 8 + .label t4 = $a .label t5 = $b .label t6 = $c .label t7 = $d @@ -959,9 +954,9 @@ debug_print_init: { str11: .text "yp@" } // Print a string at a specific screen position -// print_str_at(byte* zeropage(6) str, byte* zeropage(9) at) +// print_str_at(byte* zeropage(6) str, byte* zeropage(8) at) print_str_at: { - .label at = 9 + .label at = 8 .label str = 6 b1: ldy #0 @@ -1014,7 +1009,7 @@ sprites_init: { sta SPRITES_ENABLE ldx #0 b1: - lda #$ff&SPRITE/$40 + lda #SPRITE/$40 sta sprites_ptr,x lda #GREEN sta SPRITES_COLS,x @@ -1024,6 +1019,9 @@ sprites_init: { rts } print_hextab: .text "0123456789abcdef" + // Positions to rotate + xs: .byte -$34, -$34, -$34, 0, 0, $34, $34, $34 + ys: .byte -$34, 0, $34, -$34, $34, -$34, 0, $34 zs: .byte $34, $34, $34, $34, $34, $34, $34, $34 // Rotated positions xrs: .fill 8, 0 @@ -1036,9 +1034,6 @@ sprites_init: { yps: .fill 8, 0 // The rotation matrix rotation_matrix: .fill 9, 0 - // Positions to rotate - xs: .byte -$34, -$34, -$34, 0, 0, $34, $34, $34 - ys: .byte -$34, 0, $34, -$34, $34, -$34, 0, $34 .pc = mulf_sqr1 "mulf_sqr1" .for(var i=0;i<$200;i++) { .if(i<=159) { .byte round((i*i)/256) } diff --git a/src/test/ref/examples/3d/perspective.asm b/src/test/ref/examples/3d/perspective.asm index 7dea6c315..db564e9c2 100644 --- a/src/test/ref/examples/3d/perspective.asm +++ b/src/test/ref/examples/3d/perspective.asm @@ -32,8 +32,8 @@ main: { rts } do_perspective: { - .label y = -$47 .label x = $39 + .label y = -$47 .label z = $36 lda #<$400 sta print_char_cursor @@ -240,9 +240,9 @@ mulf_init: { .label val = 6 .label sqr = 2 .label add = 4 - lda #1 + lda #<1 sta add - lda #0 + lda #>1 sta add+1 tax sta sqr diff --git a/src/test/ref/examples/bresenham/bitmap-bresenham.asm b/src/test/ref/examples/bresenham/bitmap-bresenham.asm index a5ee012ff..9c513d6a8 100644 --- a/src/test/ref/examples/bresenham/bitmap-bresenham.asm +++ b/src/test/ref/examples/bresenham/bitmap-bresenham.asm @@ -187,6 +187,7 @@ bitmap_plot: { .label _0 = 9 .label plotter_x = 9 .label plotter_y = $b + .label plotter = 9 lda bitmap_plot_xhi,x sta plotter_x+1 lda bitmap_plot_xlo,x @@ -204,8 +205,8 @@ bitmap_plot: { sta _0+1 lda bitmap_plot_bit,x ldy #0 - ora (_0),y - sta (_0),y + ora (plotter),y + sta (plotter),y rts } // bitmap_line_ydxi(byte zeropage(7) y, byte register(X) x, byte zeropage(6) y1, byte zeropage(3) yd, byte zeropage(4) xd) @@ -335,11 +336,11 @@ init_screen: { bitmap_clear: { .label bitmap = 9 .label y = 2 - .label _3 = 9 + .label _4 = 9 lda bitmap_plot_xlo - sta _3 + sta _4 lda bitmap_plot_xhi - sta _3+1 + sta _4+1 lda #0 sta y b1: diff --git a/src/test/ref/examples/chargen/chargen-analysis.asm b/src/test/ref/examples/chargen/chargen-analysis.asm index 3acea7f3d..9a4f94c32 100644 --- a/src/test/ref/examples/chargen/chargen-analysis.asm +++ b/src/test/ref/examples/chargen/chargen-analysis.asm @@ -312,10 +312,11 @@ mul8u: { .label mb = $b .label res = 9 .label return = 9 - lda #b + lda #<b sta mb - lda #0 + lda #>b sta mb+1 + lda #<0 sta res sta res+1 b1: diff --git a/src/test/ref/examples/fastmultiply/fastmultiply8.asm b/src/test/ref/examples/fastmultiply/fastmultiply8.asm index 1ca0be223..b01b2b3b8 100644 --- a/src/test/ref/examples/fastmultiply/fastmultiply8.asm +++ b/src/test/ref/examples/fastmultiply/fastmultiply8.asm @@ -145,10 +145,11 @@ print_char_at: { rts } // Print a byte as HEX at a specific position -// print_byte_at(byte* zeropage(8) at) +// print_byte_at(byte zeropage($a) b, byte* zeropage(8) at) print_byte_at: { + .label b = $a .label at = 8 - lda print_sbyte_at.b + lda b lsr lsr lsr @@ -158,7 +159,7 @@ print_byte_at: { sta print_char_at.ch jsr print_char_at lda #$f - and print_sbyte_at.b + and b tay inc print_char_at.at bne !+ diff --git a/src/test/ref/examples/fire/fire.asm b/src/test/ref/examples/fire/fire.asm index d14cf06e3..e6481db83 100644 --- a/src/test/ref/examples/fire/fire.asm +++ b/src/test/ref/examples/fire/fire.asm @@ -307,7 +307,7 @@ sid_rnd_init: { fillscreen: { .label screen = 2 .label i = 4 - lda #0 + lda #<0 sta i sta i+1 b1: diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm index 449776ef4..0b59051e7 100644 --- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm +++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm @@ -219,13 +219,13 @@ init: { lda #VIC_DEN|VIC_RSEL|3 sta D011 jsr plexInit - lda #$20 + lda #<$20 sta xp - lda #0 + lda #>$20 sta xp+1 - tax + ldx #0 b1: - lda #$ff&SPRITE/$40 + lda #SPRITE/$40 sta PLEX_PTR,x txa asl diff --git a/src/test/ref/examples/plasma/plasma-unroll.asm b/src/test/ref/examples/plasma/plasma-unroll.asm index 6ac675a5a..761f2a967 100644 --- a/src/test/ref/examples/plasma/plasma-unroll.asm +++ b/src/test/ref/examples/plasma/plasma-unroll.asm @@ -254,7 +254,7 @@ makecharset: { sta print_char_cursor lda #>print_line_cursor sta print_char_cursor+1 - lda #0 + lda #<0 sta c sta c+1 b1: diff --git a/src/test/ref/examples/plasma/plasma.asm b/src/test/ref/examples/plasma/plasma.asm index 5bdbc6470..f0b03b983 100644 --- a/src/test/ref/examples/plasma/plasma.asm +++ b/src/test/ref/examples/plasma/plasma.asm @@ -190,7 +190,7 @@ makecharset: { sta print_char_cursor lda #>print_line_cursor sta print_char_cursor+1 - lda #0 + lda #<0 sta c sta c+1 b1: diff --git a/src/test/ref/examples/rotate/rotate.asm b/src/test/ref/examples/rotate/rotate.asm index e96371907..89dbfc313 100644 --- a/src/test/ref/examples/rotate/rotate.asm +++ b/src/test/ref/examples/rotate/rotate.asm @@ -27,14 +27,16 @@ main: { rts } anim: { - .label _4 = 7 - .label _6 = 9 + .label _4 = 5 + .label _6 = 5 .label _9 = 5 .label _10 = 5 .label _11 = 5 .label _12 = 5 - .label x = $b - .label y = $c + .label cos_a = $b + .label sin_a = $c + .label x = $d + .label y = $e .label xr = 7 .label yr = 9 .label xpos = 5 @@ -48,6 +50,11 @@ anim: { cmp RASTER bne b2 inc BORDERCOL + ldy angle + lda COS,y + sta cos_a + lda SIN,y + sta sin_a lda #0 sta sprite_msb sta i @@ -58,27 +65,25 @@ anim: { // signed fixed[7.0] lda ys,y sta y - ldy angle - lda COS,y + lda cos_a jsr mulf8u_prepare ldy x jsr mulf8s_prepared - lda mulf8s_prepared.return - sta _4 - lda mulf8s_prepared.return+1 - sta _4+1 - asl xr - rol xr+1 + lda _4 + asl + sta xr + lda _4+1 + rol + sta xr+1 ldy y jsr mulf8s_prepared - lda mulf8s_prepared.return - sta _6 - lda mulf8s_prepared.return+1 - sta _6+1 - asl yr - rol yr+1 - ldy angle - lda SIN,y + lda _6 + asl + sta yr + lda _6+1 + rol + sta yr+1 + lda sin_a jsr mulf8u_prepare ldy y jsr mulf8s_prepared @@ -104,18 +109,16 @@ anim: { adc _12+1 sta yr+1 lda xr+1 + tax + clc + adc #<$18+$95 sta xpos + txa ora #$7f bmi !+ lda #0 !: - sta xpos+1 - lda xpos - clc - adc #$18+$95 - sta xpos - lda xpos+1 - adc #0 + adc #>$18+$95 sta xpos+1 lsr sprite_msb cmp #0 @@ -153,35 +156,44 @@ anim: { // mulf8s_prepared(signed byte register(Y) b) mulf8s_prepared: { .label memA = $fd + .label _8 = $f + .label _12 = $f .label m = 5 .label return = 5 + tya jsr mulf8u_prepared lda memA cmp #0 bpl b1 lda m+1 - sty $ff + sta _8 + tya + eor #$ff sec - sbc $ff + adc _8 sta m+1 b1: cpy #0 bpl b2 lda m+1 + sta _12 + lda memA + eor #$ff sec - sbc memA + adc _12 sta m+1 b2: rts } // Calculate fast multiply with a prepared unsigned byte to a word result // The prepared number is set by calling mulf8u_prepare(byte a) +// mulf8u_prepared(byte register(A) b) mulf8u_prepared: { .label resL = $fe .label memB = $ff .label return = 5 - sty memB - ldx memB + sta memB + tax sec sm1: lda mulf_sqr1_lo,x @@ -218,7 +230,7 @@ init: { sta SPRITES_ENABLE ldx #0 b1: - lda #$ff&SPRITE/$40 + lda #SPRITE/$40 sta sprites_ptr,x lda #GREEN sta SPRITES_COLS,x @@ -246,7 +258,7 @@ mulf_init: { sta sqr1_lo lda #>mulf_sqr1_lo+1 sta sqr1_lo+1 - lda #0 + lda #<0 sta sqr sta sqr+1 tax diff --git a/src/test/ref/examples/scrolllogo/scrolllogo.asm b/src/test/ref/examples/scrolllogo/scrolllogo.asm index 638b1528c..bd40df77b 100644 --- a/src/test/ref/examples/scrolllogo/scrolllogo.asm +++ b/src/test/ref/examples/scrolllogo/scrolllogo.asm @@ -68,7 +68,7 @@ loop: { .label _1 = 9 .label _5 = 9 .label xpos = 9 - lda #0 + lda #<0 sta xsin_idx sta xsin_idx+1 b1: @@ -109,7 +109,7 @@ loop: { lda xsin_idx cmp #<XSIN_SIZE bne b4 - lda #0 + lda #<0 sta xsin_idx sta xsin_idx+1 b4: @@ -120,8 +120,8 @@ loop: { render_logo: { .label _3 = $f .label xpos = 9 - .label x_char = 4 .label logo_idx = 4 + .label logo_start = 4 lda xpos and #7 ora #VIC_MCM @@ -142,20 +142,21 @@ render_logo: { ror _3+1 ror _3 lda _3 - sta x_char + tax lda xpos+1 bmi b1 + stx logo_start ldy #0 - b2: - cpy x_char - bne b3 + b3: + cpy logo_start + bne b4 lda #0 sta logo_idx - b5: - cpy #$28 - bne b6 - rts b6: + cpy #$28 + bne b7 + rts + b7: lda logo_idx sta SCREEN,y lda #$28*1 @@ -180,8 +181,8 @@ render_logo: { sta SCREEN+$28*5,y iny inc logo_idx - jmp b5 - b3: + jmp b6 + b4: lda #0 sta SCREEN,y sta SCREEN+$28*1,y @@ -190,23 +191,23 @@ render_logo: { sta SCREEN+$28*4,y sta SCREEN+$28*5,y iny - jmp b2 + jmp b3 b1: - lda x_char + txa eor #$ff clc adc #1 sta logo_idx ldy #0 - b8: + b9: lda #$28 cmp logo_idx - bne b9 - b11: - cpy #$28 - bne b12 - rts + bne b10 b12: + cpy #$28 + bne b13 + rts + b13: lda #0 sta SCREEN,y sta SCREEN+$28*1,y @@ -215,8 +216,8 @@ render_logo: { sta SCREEN+$28*4,y sta SCREEN+$28*5,y iny - jmp b11 - b9: + jmp b12 + b10: lda logo_idx sta SCREEN,y lda #$28*1 @@ -241,7 +242,7 @@ render_logo: { sta SCREEN+$28*5,y iny inc logo_idx - jmp b8 + jmp b9 } // Generate signed word sinus table - with values in the range min-max. // sintab - the table to generate into @@ -254,22 +255,24 @@ sin16s_gen2: { .label _5 = $b .label _6 = $f .label _8 = $f - .label step = $1b + .label step = $19 .label sintab = 2 .label x = 5 .label i = 9 jsr div32u16u - lda #0 + lda #<0 sta i sta i+1 lda #<xsin sta sintab lda #>xsin sta sintab+1 - lda #0 + lda #<0 sta x sta x+1 + lda #<0>>$10 sta x+2 + lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -329,21 +332,25 @@ sin16s_gen2: { } // Multiply of two signed words to a signed double word // Fixes offsets introduced by using unsigned multiplication -// mul16s(signed word zeropage($17) a) +// mul16s(signed word zeropage($15) a) mul16s: { .label _9 = $f .label _16 = $f .label m = $b .label return = $b - .label a = $17 + .label a = $15 lda a sta mul16u.a lda a+1 sta mul16u.a+1 lda #<sin16s_gen2.ampl - sta mul16u.b + sta mul16u.mb lda #>sin16s_gen2.ampl - sta mul16u.b+1 + sta mul16u.mb+1 + lda #<sin16s_gen2.ampl>>$10 + sta mul16u.mb+2 + lda #>sin16s_gen2.ampl>>$10 + sta mul16u.mb+3 jsr mul16u lda a+1 bpl b2 @@ -366,23 +373,19 @@ mul16s: { rts } // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word -// mul16u(word zeropage($11) a, word zeropage($f) b) +// mul16u(word zeropage($f) a, word zeropage($17) b) mul16u: { - .label mb = $13 - .label a = $11 + .label mb = $11 + .label a = $f .label res = $b .label return = $b - .label b = $f - lda b - sta mb - lda b+1 - sta mb+1 - lda #0 - sta mb+2 - sta mb+3 + .label b = $17 + lda #<0 sta res sta res+1 + lda #<0>>$10 sta res+2 + lda #>0>>$10 sta res+3 b1: lda a @@ -424,17 +427,18 @@ mul16u: { // sin16s(dword zeropage($b) x) sin16s: { .label _4 = $b + .label _20 = $15 .label x = $b - .label return = $17 - .label x1 = $1f - .label x2 = $19 - .label x3 = $19 + .label return = $15 + .label x1 = $1d + .label x2 = $15 + .label x3 = $15 .label x3_6 = $f - .label usinx = $17 - .label x4 = $19 + .label usinx = $1f + .label x4 = $15 .label x5 = $f .label x5_128 = $f - .label sinx = $17 + .label sinx = $15 .label isUpper = 4 lda x+3 cmp #>PI_u4f28>>$10 @@ -580,9 +584,17 @@ sin16s: { lda usinx+1 adc x5_128+1 sta usinx+1 + lda usinx + sta sinx + lda usinx+1 + sta sinx+1 lda isUpper cmp #0 beq b3 + lda usinx + sta _20 + lda usinx+1 + sta _20+1 sec lda sinx eor #$ff @@ -597,19 +609,26 @@ sin16s: { } // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result. // The select parameter indicates how many of the highest bits of the 32-bit result to skip -// mulu16_sel(word zeropage($19) v1, word zeropage($f) v2, byte register(X) select) +// mulu16_sel(word zeropage($15) v1, word zeropage($17) v2, byte register(X) select) mulu16_sel: { .label _0 = $b .label _1 = $b - .label v1 = $19 - .label v2 = $f + .label v1 = $15 + .label v2 = $17 .label return = $f - .label return_1 = $19 - .label return_10 = $19 + .label return_1 = $15 + .label return_10 = $15 lda v1 sta mul16u.a lda v1+1 sta mul16u.a+1 + lda mul16u.b + sta mul16u.mb + lda mul16u.b+1 + sta mul16u.mb+1 + lda #0 + sta mul16u.mb+2 + sta mul16u.mb+3 jsr mul16u cpx #0 beq !e+ @@ -630,14 +649,14 @@ mulu16_sel: { // Divide unsigned 32-bit dword dividend with a 16-bit word divisor // The 16-bit word remainder can be found in rem16u after the division div32u16u: { - .label quotient_hi = $11 + .label quotient_hi = $15 .label quotient_lo = $f - .label return = $1b + .label return = $19 lda #<PI2_u4f28>>$10 sta divr16u.dividend lda #>PI2_u4f28>>$10 sta divr16u.dividend+1 - lda #0 + lda #<0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u diff --git a/src/test/ref/examples/sinplotter/sine-plotter.asm b/src/test/ref/examples/sinplotter/sine-plotter.asm index 76895de72..951d02189 100644 --- a/src/test/ref/examples/sinplotter/sine-plotter.asm +++ b/src/test/ref/examples/sinplotter/sine-plotter.asm @@ -36,7 +36,7 @@ .label sin2 = $1400 .label rem16u = 2 main: { - .const vicSelectGfxBank1_toDd001_return = 3^(>SCREEN)/$40 + .const vicSelectGfxBank1_toDd001_return = 3 .const toD0181_return = (>(SCREEN&$3fff)*4)|(>BITMAP)/4&$f sei // Disable normal interrupt @@ -73,7 +73,7 @@ render_sine: { .label sin2_val = 6 .label xpos = 4 .label sin_idx = 2 - lda #0 + lda #<0 sta xpos sta xpos+1 sta sin_idx @@ -149,7 +149,7 @@ render_sine: { lda xpos cmp #<$140 bne b2 - lda #0 + lda #<0 sta xpos sta xpos+1 b2: @@ -174,33 +174,34 @@ render_sine: { // Plot a single dot in the bitmap // bitmap_plot(word zeropage(4) x, byte register(X) y) bitmap_plot: { - .label _1 = $10 + .label _1 = $15 .label plotter = 6 + .label plotter_1 = $15 .label x = 4 - .label _3 = 6 + .label _4 = 6 lda bitmap_plot_yhi,x - sta _3+1 + sta _4+1 lda bitmap_plot_ylo,x - sta _3 + sta _4 lda x and #<$fff8 sta _1 lda x+1 and #>$fff8 sta _1+1 - lda plotter + lda plotter_1 clc - adc _1 - sta plotter - lda plotter+1 - adc _1+1 - sta plotter+1 + adc plotter + sta plotter_1 + lda plotter_1+1 + adc plotter+1 + sta plotter_1+1 lda x tay lda bitmap_plot_bit,y ldy #0 - ora (plotter),y - sta (plotter),y + ora (plotter_1),y + sta (plotter_1),y rts } // wrap_y(signed word zeropage(6) y) @@ -230,13 +231,13 @@ wrap_y: { sta y+1 jmp b3 b2: - sec lda y - sbc #$c8 + sec + sbc #<$c8 sta y - bcs !+ - dec y+1 - !: + lda y+1 + sbc #>$c8 + sta y+1 jmp b1 } // Generate signed word sinus table - with values in the range min-max. @@ -250,22 +251,24 @@ sin16s_gen2: { .label _5 = $c .label _6 = 6 .label _8 = 6 - .label step = $1b + .label step = $19 .label sintab = 2 .label x = 8 .label i = 4 jsr div32u16u - lda #0 + lda #<0 sta i sta i+1 lda #<sin sta sintab lda #>sin sta sintab+1 - lda #0 + lda #<0 sta x sta x+1 + lda #<0>>$10 sta x+2 + lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -325,21 +328,25 @@ sin16s_gen2: { } // Multiply of two signed words to a signed double word // Fixes offsets introduced by using unsigned multiplication -// mul16s(signed word zeropage($17) a) +// mul16s(signed word zeropage($15) a) mul16s: { .label _9 = 6 .label _16 = 6 .label m = $c .label return = $c - .label a = $17 + .label a = $15 lda a sta mul16u.a lda a+1 sta mul16u.a+1 lda #<sin16s_gen2.ampl - sta mul16u.b + sta mul16u.mb lda #>sin16s_gen2.ampl - sta mul16u.b+1 + sta mul16u.mb+1 + lda #<sin16s_gen2.ampl>>$10 + sta mul16u.mb+2 + lda #>sin16s_gen2.ampl>>$10 + sta mul16u.mb+3 jsr mul16u lda a+1 bpl b2 @@ -362,23 +369,19 @@ mul16s: { rts } // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word -// mul16u(word zeropage($10) a, word zeropage(6) b) +// mul16u(word zeropage(6) a, word zeropage($17) b) mul16u: { - .label mb = $12 - .label a = $10 + .label mb = $10 + .label a = 6 .label res = $c .label return = $c - .label b = 6 - lda b - sta mb - lda b+1 - sta mb+1 - lda #0 - sta mb+2 - sta mb+3 + .label b = $17 + lda #<0 sta res sta res+1 + lda #<0>>$10 sta res+2 + lda #>0>>$10 sta res+3 b1: lda a @@ -420,18 +423,19 @@ mul16u: { // sin16s(dword zeropage($c) x) sin16s: { .label _4 = $c + .label _20 = $15 .label x = $c - .label return = $17 - .label x1 = $1f - .label x2 = $19 - .label x3 = $19 + .label return = $15 + .label x1 = $1d + .label x2 = $15 + .label x3 = $15 .label x3_6 = 6 - .label usinx = $17 - .label x4 = $19 + .label usinx = $1f + .label x4 = $15 .label x5 = 6 .label x5_128 = 6 - .label sinx = $17 - .label isUpper = $16 + .label sinx = $15 + .label isUpper = $14 lda x+3 cmp #>PI_u4f28>>$10 bcc b4 @@ -576,9 +580,17 @@ sin16s: { lda usinx+1 adc x5_128+1 sta usinx+1 + lda usinx + sta sinx + lda usinx+1 + sta sinx+1 lda isUpper cmp #0 beq b3 + lda usinx + sta _20 + lda usinx+1 + sta _20+1 sec lda sinx eor #$ff @@ -593,19 +605,26 @@ sin16s: { } // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result. // The select parameter indicates how many of the highest bits of the 32-bit result to skip -// mulu16_sel(word zeropage($19) v1, word zeropage(6) v2, byte register(X) select) +// mulu16_sel(word zeropage($15) v1, word zeropage($17) v2, byte register(X) select) mulu16_sel: { .label _0 = $c .label _1 = $c - .label v1 = $19 - .label v2 = 6 + .label v1 = $15 + .label v2 = $17 .label return = 6 - .label return_1 = $19 - .label return_10 = $19 + .label return_1 = $15 + .label return_10 = $15 lda v1 sta mul16u.a lda v1+1 sta mul16u.a+1 + lda mul16u.b + sta mul16u.mb + lda mul16u.b+1 + sta mul16u.mb+1 + lda #0 + sta mul16u.mb+2 + sta mul16u.mb+3 jsr mul16u cpx #0 beq !e+ @@ -626,14 +645,14 @@ mulu16_sel: { // Divide unsigned 32-bit dword dividend with a 16-bit word divisor // The 16-bit word remainder can be found in rem16u after the division div32u16u: { - .label quotient_hi = $10 + .label quotient_hi = $15 .label quotient_lo = 6 - .label return = $1b + .label return = $19 lda #<PI2_u4f28>>$10 sta divr16u.dividend lda #>PI2_u4f28>>$10 sta divr16u.dividend+1 - lda #0 + lda #<0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u @@ -713,12 +732,12 @@ divr16u: { // Clear all graphics on the bitmap bitmap_clear: { .label bitmap = 2 - .label y = $16 - .label _3 = 2 + .label y = $14 + .label _4 = 2 lda bitmap_plot_ylo - sta _3 + sta _4 lda bitmap_plot_yhi - sta _3+1 + sta _4+1 lda #0 sta y b1: @@ -742,7 +761,7 @@ bitmap_clear: { } // Initialize bitmap plotting tables bitmap_init: { - .label _3 = $16 + .label _3 = $14 .label yoffs = 2 ldx #0 lda #$80 diff --git a/src/test/ref/examples/sinsprites/sinus-sprites.asm b/src/test/ref/examples/sinsprites/sinus-sprites.asm index 6d699fc87..81a9c2d21 100644 --- a/src/test/ref/examples/sinsprites/sinus-sprites.asm +++ b/src/test/ref/examples/sinsprites/sinus-sprites.asm @@ -228,9 +228,9 @@ gen_sintab: { lda #>f_amp sta setMEMtoFAC.mem+1 jsr setMEMtoFAC - lda #2 + lda #<2 sta setFAC.w - lda #0 + lda #>2 sta setFAC.w+1 jsr setFAC lda #<f_amp @@ -596,7 +596,7 @@ place_sprites: { sta spr_x lda #0 sta j - lda #$ff&sprites/$40 + lda #sprites/$40 sta spr_id b1: lda spr_id diff --git a/src/test/ref/forrangedwords.asm b/src/test/ref/forrangedwords.asm index 8716f7084..60b793ab1 100644 --- a/src/test/ref/forrangedwords.asm +++ b/src/test/ref/forrangedwords.asm @@ -5,7 +5,7 @@ main: { .label SCREEN = $400 .label w = 2 .label sw = 2 - lda #0 + lda #<0 sta w sta w+1 b1: diff --git a/src/test/ref/fragment-variations.asm b/src/test/ref/fragment-variations.asm new file mode 100644 index 000000000..451bee711 --- /dev/null +++ b/src/test/ref/fragment-variations.asm @@ -0,0 +1,74 @@ +// Tests that ASM fragment variations works +// ASM fragment variations "cast" constants to different types +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const SIZEOF_DWORD = 4 +main: { + .label screen = $400 + .label _0 = 2 + .label _1 = 2 + lda #<$a + sta mul16u.a + lda #>$a + sta mul16u.a+1 + lda #<$a + sta mul16u.mb + lda #>$a + sta mul16u.mb+1 + lda #<$a>>$10 + sta mul16u.mb+2 + lda #>$a>>$10 + sta mul16u.mb+3 + jsr mul16u + lda _0 + sta screen + lda _0+1 + sta screen+1 + lda _0+2 + sta screen+2 + lda _0+3 + sta screen+3 + lda #<$3e8 + sta mul16u.a + lda #>$3e8 + sta mul16u.a+1 + lda #<$3e8 + sta mul16u.mb + lda #>$3e8 + sta mul16u.mb+1 + lda #<$3e8>>$10 + sta mul16u.mb+2 + lda #>$3e8>>$10 + sta mul16u.mb+3 + jsr mul16u + lda _1 + sta screen+1*SIZEOF_DWORD + lda _1+1 + sta screen+1*SIZEOF_DWORD+1 + lda _1+2 + sta screen+1*SIZEOF_DWORD+2 + lda _1+3 + sta screen+1*SIZEOF_DWORD+3 + rts +} +// mul16u(word zeropage(6) a) +mul16u: { + .label return = 2 + .label mb = 2 + .label a = 6 + lda return + clc + adc a + sta return + lda return+1 + adc a+1 + sta return+1 + lda return+2 + adc #0 + sta return+2 + lda return+3 + adc #0 + sta return+3 + rts +} diff --git a/src/test/ref/gfxbank.asm b/src/test/ref/gfxbank.asm new file mode 100644 index 000000000..54c84cffb --- /dev/null +++ b/src/test/ref/gfxbank.asm @@ -0,0 +1,16 @@ +// Test minimization of constants +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // CIA#2 Port A: Serial bus, RS-232, VIC memory bank + .label CIA2_PORT_A = $dd00 + // CIA #2 Port A data direction register. + .label CIA2_PORT_A_DDR = $dd02 +main: { + .const vicSelectGfxBank1_toDd001_return = 3 + lda #3 + sta CIA2_PORT_A_DDR + lda #vicSelectGfxBank1_toDd001_return + sta CIA2_PORT_A + rts +} diff --git a/src/test/ref/halfscii.asm b/src/test/ref/halfscii.asm index 179529db1..b452a7471 100644 --- a/src/test/ref/halfscii.asm +++ b/src/test/ref/halfscii.asm @@ -7,10 +7,11 @@ .label D018 = $d018 .label CHARSET4 = $2800 main: { - .label _1 = 6 - .label _11 = 6 - .label _21 = 6 - .label _30 = 6 + .label _1 = 8 + .label _11 = 8 + .label _21 = 8 + .label _30 = 8 + .label chargen1 = 6 .label charset4 = 4 .label chargen = 2 sei @@ -25,13 +26,19 @@ main: { lda #>CHARGEN sta chargen+1 b1: + lda chargen + clc + adc #1 + sta chargen1 + lda chargen+1 + adc #0 + sta chargen1+1 lda #$60 ldy #0 and (chargen),y sta _1 lda #$60 - ldy #1 - and (chargen),y + and (chargen1),y lsr lsr ora _1 @@ -54,8 +61,7 @@ main: { and (chargen),y sta _11 lda #$18 - ldy #1 - and (chargen),y + and (chargen1),y lsr lsr ora _11 @@ -75,8 +81,7 @@ main: { asl sta _21 lda #6 - ldy #1 - and (chargen),y + and (chargen1),y lsr ora _21 tay @@ -95,8 +100,7 @@ main: { asl sta _30 lda #1 - tay - and (chargen),y + and (chargen1),y ora _30 tay lda bits_count,y diff --git a/src/test/ref/inline-function-if.asm b/src/test/ref/inline-function-if.asm index 8f77a44d9..d5729668a 100644 --- a/src/test/ref/inline-function-if.asm +++ b/src/test/ref/inline-function-if.asm @@ -6,8 +6,8 @@ main: { .const toUpper1_ch = 'c' .const toUpper2_ch = 'm' - .const toUpper1_res = toUpper1_ch+$40 - lda #toUpper1_res + .const toUpper1_return = toUpper1_ch+$40 + lda #toUpper1_return sta screen lda #toUpper2_ch sta screen+1 diff --git a/src/test/ref/inline-kasm-resource.asm b/src/test/ref/inline-kasm-resource.asm index f54a110c8..54b571824 100644 --- a/src/test/ref/inline-kasm-resource.asm +++ b/src/test/ref/inline-kasm-resource.asm @@ -8,7 +8,7 @@ .label SPRITES_XPOS = $d000 .label SPRITES_YPOS = $d001 main: { - lda #$ff&SPRITE/$40 + lda #SPRITE/$40 sta SCREEN+$3f8 lda #1 sta SPRITES_ENABLE diff --git a/src/test/ref/inline-pointer-0.asm b/src/test/ref/inline-pointer-0.asm new file mode 100644 index 000000000..3e2b5610f --- /dev/null +++ b/src/test/ref/inline-pointer-0.asm @@ -0,0 +1,10 @@ +// Tests creating a literal pointer from two bytes +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = 4*$100 + lda #'a' + sta screen + rts +} diff --git a/src/test/ref/inline-pointer-1.asm b/src/test/ref/inline-pointer-1.asm new file mode 100644 index 000000000..4da10ae54 --- /dev/null +++ b/src/test/ref/inline-pointer-1.asm @@ -0,0 +1,24 @@ +// Tests creating a literal pointer from two bytes +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + ldx #0 + lda #4 + jsr puta + ldx #$18 + lda #5 + jsr puta + rts +} +// puta(byte register(A) ph, byte register(X) pl) +puta: { + .label screen = 2 + .label _2 = 2 + sta _2+1 + stx _2 + lda #'a' + ldy #0 + sta (screen),y + rts +} diff --git a/src/test/ref/inline-pointer-2.asm b/src/test/ref/inline-pointer-2.asm new file mode 100644 index 000000000..32a924a78 --- /dev/null +++ b/src/test/ref/inline-pointer-2.asm @@ -0,0 +1,9 @@ +// Tests creating a literal pointer from two bytes +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + lda #'a' + sta 4*$100+$28 + rts +} diff --git a/src/test/ref/inline-string-3.asm b/src/test/ref/inline-string-3.asm index aaf848ee9..1e2abba8f 100644 --- a/src/test/ref/inline-string-3.asm +++ b/src/test/ref/inline-string-3.asm @@ -7,17 +7,18 @@ main: { .label PTR = $9ffe .label SCREEN = $400 - .label _6 = 2 + .label ptr = 2 + .label _7 = 2 lda #<STRING sta PTR lda #>STRING sta PTR+1 lda PTR - sta _6 + sta _7 lda PTR+1 - sta _6+1 + sta _7+1 ldy #0 - lda (_6),y + lda (ptr),y sta SCREEN rts STRING: .text "camelot" diff --git a/src/test/ref/inline-word-0.asm b/src/test/ref/inline-word-0.asm new file mode 100644 index 000000000..d1161c334 --- /dev/null +++ b/src/test/ref/inline-word-0.asm @@ -0,0 +1,13 @@ +// Tests minimal inline word +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + .const w = 2*$100+1 + lda #<w + sta screen + lda #>w + sta screen+1 + rts +} diff --git a/src/test/ref/inline-word-1.asm b/src/test/ref/inline-word-1.asm new file mode 100644 index 000000000..bb6135dcc --- /dev/null +++ b/src/test/ref/inline-word-1.asm @@ -0,0 +1,13 @@ +// Tests minimal inline word +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + .const w = 1*$100+2 + lda #<w + sta screen + lda #>w + sta screen+1 + rts +} diff --git a/src/test/ref/inline-word-2.asm b/src/test/ref/inline-word-2.asm new file mode 100644 index 000000000..bb6135dcc --- /dev/null +++ b/src/test/ref/inline-word-2.asm @@ -0,0 +1,13 @@ +// Tests minimal inline word +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + .const w = 1*$100+2 + lda #<w + sta screen + lda #>w + sta screen+1 + rts +} diff --git a/src/test/ref/inline-word.asm b/src/test/ref/inline-word.asm index 505c1ebc1..7b80c88b1 100644 --- a/src/test/ref/inline-word.asm +++ b/src/test/ref/inline-word.asm @@ -4,6 +4,7 @@ .label SCREEN = $400 main: { .label w = 3 + .label sc = 3 .label h = 2 lda #0 sta h @@ -17,7 +18,7 @@ main: { stx w lda #'*' ldy #0 - sta (w),y + sta (sc),y inx cpx #8 bne b2 diff --git a/src/test/ref/int-literals.asm b/src/test/ref/int-literals.asm index 8f7755754..dc02bae1d 100644 --- a/src/test/ref/int-literals.asm +++ b/src/test/ref/int-literals.asm @@ -10,11 +10,13 @@ .const TYPEID_SIGNED_DWORD = 6 .const RED = 2 .const GREEN = 5 + .label SCREEN = $400 + .label COLS = $d800 main: { .label s = 2 - lda #<$400 + lda #<SCREEN sta s - lda #>$400 + lda #>SCREEN sta s+1 b1: lda #' ' @@ -25,11 +27,11 @@ main: { inc s+1 !: lda s+1 - cmp #>$400+$3e8 + cmp #>SCREEN+$3e8 bcc b1 bne !+ lda s - cmp #<$400+$3e8 + cmp #<SCREEN+$3e8 bcc b1 !: jsr testSimpleTypes @@ -109,14 +111,14 @@ assertType: { cmp t2 beq b1 lda #RED - sta $d800,x + sta COLS,x b2: tya - sta $400,x + sta SCREEN,x inx rts b1: lda #GREEN - sta $d800,x + sta COLS,x jmp b2 } diff --git a/src/test/ref/line-anim.asm b/src/test/ref/line-anim.asm index 7f9b1338f..bd6739ae0 100644 --- a/src/test/ref/line-anim.asm +++ b/src/test/ref/line-anim.asm @@ -80,35 +80,38 @@ bitmap_plot: { .label _1 = 7 .label x = 3 .label plotter = 5 - .label _3 = 5 + .label plotter_1 = 7 + .label _4 = 5 lda bitmap_plot_yhi,x - sta _3+1 + sta _4+1 lda bitmap_plot_ylo,x - sta _3 + sta _4 lda x and #<$fff8 sta _1 lda x+1 and #>$fff8 sta _1+1 - lda plotter + lda plotter_1 clc - adc _1 - sta plotter - lda plotter+1 - adc _1+1 - sta plotter+1 + adc plotter + sta plotter_1 + lda plotter_1+1 + adc plotter+1 + sta plotter_1+1 lda x tay lda bitmap_plot_bit,y ldy #0 - ora (plotter),y - sta (plotter),y + ora (plotter_1),y + sta (plotter_1),y rts } // Initialize the points to be animated // point_init(byte zeropage(2) point_idx) point_init: { + .label _0 = 9 + .label _1 = 3 .label _3 = 7 .label _4 = 3 .label _9 = 3 @@ -120,20 +123,28 @@ point_init: { .label abs16s1_return = 3 .label abs16s2__2 = 5 .label abs16s2_return = 5 - .label x_stepf = 5 + .label x_stepf = 3 .label x_diff = 9 lda point_idx asl - tax + tay + lda x_end,y + sta _0 + lda x_end+1,y + sta _0+1 lda point_idx asl tay + lda x_start,y + sta _1 + lda x_start+1,y + sta _1+1 + lda x_diff sec - lda x_end,x - sbc x_start,y + sbc _1 sta x_diff - lda x_end+1,x - sbc x_start+1,y + lda x_diff+1 + sbc _1+1 sta x_diff+1 ldy point_idx lda y_end,y @@ -229,8 +240,8 @@ point_init: { lda x_diff+1 bmi b4 // x add = 1.0 - ldy point_idx lda #$10 + ldy point_idx sta x_add,y b5: jsr divr16s @@ -278,23 +289,18 @@ point_init: { // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.5.5 // divr16s(signed word zeropage(9) divisor, signed word zeropage(7) rem) divr16s: { - .const dividend = 0 .label _10 = 7 .label _13 = 9 - .label resultu = 5 - .label return = 5 + .label _18 = 3 + .label remu = 7 + .label divisoru = 9 + .label resultu = 3 + .label return = 3 .label divisor = 9 .label rem = 7 - .label dividendu = 3 - .label divisoru = 9 - .label remu = 7 lda rem+1 bmi b1 - lda #dividend - sta dividendu - lda #0 - sta dividendu+1 - tay + ldy #0 b2: lda divisor+1 bmi b3 @@ -337,10 +343,6 @@ divr16s: { eor #$ff adc #0 sta _10+1 - lda #-dividend - sta dividendu - lda #0 - sta dividendu+1 ldy #1 jmp b2 } @@ -348,17 +350,19 @@ divr16s: { // Returns the quotient dividend/divisor. // The final remainder will be set into the global variable rem16u // Implemented using simple binary division -// divr16u(word zeropage(3) dividend, word zeropage(9) divisor, word zeropage(7) rem) +// divr16u(word zeropage(5) dividend, word zeropage(9) divisor, word zeropage(7) rem) divr16u: { .label rem = 7 - .label dividend = 3 - .label quotient = 5 - .label return = 5 + .label dividend = 5 + .label quotient = 3 + .label return = 3 .label divisor = 9 ldx #0 txa sta quotient sta quotient+1 + sta dividend + sta dividend+1 b1: asl rem rol rem+1 @@ -434,11 +438,11 @@ screen_fill: { bitmap_clear: { .label bitmap = 3 .label y = 2 - .label _3 = 3 + .label _4 = 3 lda bitmap_plot_ylo - sta _3 + sta _4 lda bitmap_plot_yhi - sta _3+1 + sta _4+1 lda #0 sta y b1: diff --git a/src/test/ref/linegen.asm b/src/test/ref/linegen.asm index 4cbd79681..825a7fc29 100644 --- a/src/test/ref/linegen.asm +++ b/src/test/ref/linegen.asm @@ -38,7 +38,7 @@ main: { sta lin16u_gen.lintab lda #>lintab3 sta lin16u_gen.lintab+1 - lda #0 + lda #<0 sta lin16u_gen.min sta lin16u_gen.min+1 lda #<$6488 @@ -76,7 +76,7 @@ main: { lda #>str1 sta print_str.str+1 jsr print_str - lda #0 + lda #<0 sta print_word.w sta print_word.w+1 jsr print_word @@ -309,10 +309,11 @@ lin16u_gen: { lda ampl+1 sbc min+1 sta ampl+1 - lda #$14-1 + lda #<$14-1 sta divr16u.divisor - lda #0 + lda #>$14-1 sta divr16u.divisor+1 + lda #<0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u @@ -320,10 +321,11 @@ lin16u_gen: { sta stepi lda divr16u.return+1 sta stepi+1 - lda #$14-1 + lda #<$14-1 sta divr16u.divisor - lda #0 + lda #>$14-1 sta divr16u.divisor+1 + lda #<0 sta divr16u.dividend sta divr16u.dividend+1 jsr divr16u @@ -342,7 +344,7 @@ lin16u_gen: { sta val+2 lda min+1 sta val+3 - lda #0 + lda #<0 sta i sta i+1 b1: diff --git a/src/test/ref/liverange-call-problem.asm b/src/test/ref/liverange-call-problem.asm index ff5e1ea3d..933c49ae1 100644 --- a/src/test/ref/liverange-call-problem.asm +++ b/src/test/ref/liverange-call-problem.asm @@ -8,11 +8,11 @@ .label w2 = 2 main: { .label SCREEN = $400 - lda #0 + lda #<0 sta w1 sta w1+1 jsr incw1 - lda #0 + lda #<0 sta w2 sta w2+1 jsr incw2 diff --git a/src/test/ref/min-fmul-16.asm b/src/test/ref/min-fmul-16.asm index dc431ade4..ef4553748 100644 --- a/src/test/ref/min-fmul-16.asm +++ b/src/test/ref/min-fmul-16.asm @@ -226,7 +226,7 @@ mulf_init: { sta sqr1_lo lda #>mulf_sqr1_lo+1 sta sqr1_lo+1 - lda #0 + lda #<0 sta sqr sta sqr+1 tax diff --git a/src/test/ref/mixed-array-0.asm b/src/test/ref/mixed-array-0.asm new file mode 100644 index 000000000..3e2175924 --- /dev/null +++ b/src/test/ref/mixed-array-0.asm @@ -0,0 +1,15 @@ +// Test an array with mixed byte/number types +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label SCREEN = $400 + lda msg + sta SCREEN + lda msg+1 + sta SCREEN+1 + lda msg+2 + sta SCREEN+2 + rts + msg: .byte 1, 2, 3 +} diff --git a/src/test/ref/mixed-array-1.asm b/src/test/ref/mixed-array-1.asm new file mode 100644 index 000000000..2d92feb78 --- /dev/null +++ b/src/test/ref/mixed-array-1.asm @@ -0,0 +1,15 @@ +// Test an array with mixed byte/number types +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label SCREEN = $400 + lda msg + sta SCREEN + lda msg+1 + sta SCREEN+1 + lda msg+2 + sta SCREEN+2 + rts + msg: .byte -1, 0, 1 +} diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm index b3658492e..f9d6d5695 100644 --- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm +++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm @@ -167,13 +167,13 @@ init: { lda #VIC_DEN|VIC_RSEL|3 sta D011 jsr plexInit - lda #$20 + lda #<$20 sta xp - lda #0 + lda #>$20 sta xp+1 - tax + ldx #0 b1: - lda #$ff&SPRITE/$40 + lda #SPRITE/$40 sta PLEX_PTR,x txa asl diff --git a/src/test/ref/number-conversion.asm b/src/test/ref/number-conversion.asm index 17df64b44..412553a64 100644 --- a/src/test/ref/number-conversion.asm +++ b/src/test/ref/number-conversion.asm @@ -11,6 +11,8 @@ .const TYPEID_DWORD = 5 .const RED = 2 .const GREEN = 5 + .label SCREEN = $400 + .label COLS = $d800 main: { ldx #0 lda #TYPEID_SIGNED_BYTE @@ -167,14 +169,14 @@ assertType: { cmp t2 beq b1 lda #RED - sta $d800,x + sta COLS,x b2: tya - sta $400,x + sta SCREEN,x inx rts b1: lda #GREEN - sta $d800,x + sta COLS,x jmp b2 } diff --git a/src/test/ref/operator-lohi-problem.asm b/src/test/ref/operator-lohi-problem.asm index 83e1032ff..332ca079f 100644 --- a/src/test/ref/operator-lohi-problem.asm +++ b/src/test/ref/operator-lohi-problem.asm @@ -9,11 +9,9 @@ .label SCREEN = $400 main: { .const dw = $2000 - .const w1 = dw&$ffff - .const w2 = <dw+1 - lda #<w1 + .const w2 = dw+1&$ffff + lda #0 sta SCREEN - lda #>w1 sta SCREEN+1 lda #<w2 sta SCREEN+3 diff --git a/src/test/ref/ptr-complex.asm b/src/test/ref/ptr-complex.asm index 214144b95..e8ef78d97 100644 --- a/src/test/ref/ptr-complex.asm +++ b/src/test/ref/ptr-complex.asm @@ -7,7 +7,6 @@ main: { .label screen = $400 // Increment on a const named pointer .label BGCOL = $d020 - .label sc2 = screen+$51 ldx #0 // RValue pointer expression (variable) b1: @@ -17,7 +16,7 @@ main: { cpx #$b bne b1 lda screen+$79 - sta sc2 + sta screen+$51 // LValue pointer expression (constant - directly) lda screen+$7a sta screen+$52 diff --git a/src/test/ref/roll-sprite-msb.asm b/src/test/ref/roll-sprite-msb.asm index 80b22ddde..18ab37b56 100644 --- a/src/test/ref/roll-sprite-msb.asm +++ b/src/test/ref/roll-sprite-msb.asm @@ -7,11 +7,11 @@ .label SPRITES_XMSB = $d010 main: { .label xpos = 2 - lda #$c8 + lda #<$c8 sta xpos - lda #0 + lda #>$c8 sta xpos+1 - tax + ldx #0 b1: stx position_sprite.spriteno jsr position_sprite diff --git a/src/test/ref/scan-desire-problem.asm b/src/test/ref/scan-desire-problem.asm index 248cffd38..377b83bf5 100644 --- a/src/test/ref/scan-desire-problem.asm +++ b/src/test/ref/scan-desire-problem.asm @@ -172,10 +172,11 @@ mul8u: { .label mb = 6 .label res = 4 .label return = 4 - lda #b + lda #<b sta mb - lda #0 + lda #>b sta mb+1 + lda #<0 sta res sta res+1 b1: diff --git a/src/test/ref/semi-struct-2.asm b/src/test/ref/semi-struct-2.asm index 0429bcc2f..d54d7ac9c 100644 --- a/src/test/ref/semi-struct-2.asm +++ b/src/test/ref/semi-struct-2.asm @@ -730,10 +730,11 @@ mul8u: { .label mb = 2 .label res = 8 .label return = 8 - lda #SIZEOF_ENTRY + lda #<SIZEOF_ENTRY sta mb - lda #0 + lda #>SIZEOF_ENTRY sta mb+1 + lda #<0 sta res sta res+1 b1: diff --git a/src/test/ref/signed-indexed-subtract.asm b/src/test/ref/signed-indexed-subtract.asm index e82d13764..7ca3ce033 100644 --- a/src/test/ref/signed-indexed-subtract.asm +++ b/src/test/ref/signed-indexed-subtract.asm @@ -2,22 +2,25 @@ .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" - .label print_line_cursor = 2 + .label print_line_cursor = 3 .label print_char_cursor = 7 main: { - ldy #0 + .label i = 2 + lda #0 + sta i b1: - tya + lda i ldx #$80 jsr sub - tya + lda i ldx #$40 jsr sub - tya + lda i ldx #$40 jsr sub - iny - cpy #9 + inc i + lda #9 + cmp i bne b1 jsr print_cls lda #<$400 @@ -71,9 +74,9 @@ print_ln: { rts } // Print a signed word as HEX -// print_sword(signed word zeropage(4) w) +// print_sword(signed word zeropage(5) w) print_sword: { - .label w = 4 + .label w = 5 lda w+1 bpl b1 lda #'-' @@ -92,19 +95,21 @@ print_sword: { rts } // Print a word as HEX +// print_word(word zeropage(5) w) print_word: { - lda print_sword.w+1 + .label w = 5 + lda w+1 sta print_byte.b jsr print_byte - lda print_sword.w + lda w sta print_byte.b jsr print_byte rts } // Print a byte as HEX -// print_byte(byte zeropage(6) b) +// print_byte(byte zeropage(2) b) print_byte: { - .label b = 6 + .label b = 2 lda b lsr lsr @@ -133,7 +138,7 @@ print_char: { } // Clear the screen. Also resets current line/char cursor. print_cls: { - .label sc = 2 + .label sc = 3 lda #<$400 sta sc lda #>$400 @@ -156,16 +161,20 @@ print_cls: { } // sub(byte register(A) idx, byte register(X) s) sub: { + .label _1 = 3 asl + tay + txa + sta _1 + lda #0 + sta _1+1 + lda words,y sec - stx $ff - tax - lda words,x - sbc $ff - sta words,x - bcs !+ - dec words+1,x - !: + sbc _1 + sta words,y + lda words+1,y + sbc _1+1 + sta words+1,y rts } print_hextab: .text "0123456789abcdef" diff --git a/src/test/ref/signed-words.asm b/src/test/ref/signed-words.asm index e85a5777d..9a92c64eb 100644 --- a/src/test/ref/signed-words.asm +++ b/src/test/ref/signed-words.asm @@ -25,21 +25,22 @@ .label yvel_22 = 6 main: { jsr init - lda #$64 + lda #<$64 sta yvel_init - lda #0 + lda #>$64 sta yvel_init+1 - lda #$c8 + lda #<$c8 sta xvel - lda #0 + lda #>$c8 sta xvel+1 + lda #<0 sta ypos sta ypos+1 sta xpos sta xpos+1 - lda #$64 + lda #<$64 sta yvel_12 - lda #0 + lda #>$64 sta yvel_12+1 b1: lda #$ff @@ -64,13 +65,20 @@ anim: { eor #$ff adc #0 sta xvel+1 + lda #$a + sta $fe + ora #$7f + bmi !+ + lda #0 + !: + sta $ff sec lda yvel_init - sbc #$a + sbc $fe sta yvel_init - bcs !+ - dec yvel_init+1 - !: + lda yvel_init+1 + sbc $ff + sta yvel_init+1 lda yvel_init cmp #<-$c8 lda yvel_init+1 @@ -79,16 +87,16 @@ anim: { eor #$80 !: bpl b3 - lda #$c8 + lda #<$c8 sta yvel - lda #0 + lda #>$c8 sta yvel+1 b3: lda yvel sta yvel_22 lda yvel+1 sta yvel_22+1 - lda #0 + lda #<0 sta ypos sta ypos+1 sta xpos @@ -182,7 +190,7 @@ init: { sta SPRITES_YPOS lda #WHITE sta SPRITES_COLS - lda #$ff&SPRITE/$40 + lda #SPRITE/$40 sta SPRITES_PTR lda #<SCREEN sta sc diff --git a/src/test/ref/sinus-basic.asm b/src/test/ref/sinus-basic.asm index bf19ef5b9..9e8385227 100644 --- a/src/test/ref/sinus-basic.asm +++ b/src/test/ref/sinus-basic.asm @@ -46,9 +46,9 @@ main: { lda #>f_i sta setMEMtoFAC.mem+1 jsr setMEMtoFAC - lda #$19 + lda #<$19 sta setFAC.w - lda #0 + lda #>$19 sta setFAC.w+1 jsr setFAC jsr divMEMbyFAC diff --git a/src/test/ref/sinusgen16.asm b/src/test/ref/sinusgen16.asm index f9d538a19..380d92e7c 100644 --- a/src/test/ref/sinusgen16.asm +++ b/src/test/ref/sinusgen16.asm @@ -112,11 +112,13 @@ print_sword: { rts } // Print a word as HEX +// print_word(word zeropage(6) w) print_word: { - lda print_sword.w+1 + .label w = 6 + lda w+1 tax jsr print_byte - lda print_sword.w + lda w tax jsr print_byte rts @@ -178,22 +180,24 @@ print_cls: { // sin16s_gen(signed word* zeropage(2) sintab) sin16s_gen: { .label _1 = 6 - .label step = $1b + .label step = $19 .label sintab = 2 .label x = $a .label i = 4 jsr div32u16u - lda #0 + lda #<0 sta i sta i+1 lda #<main.sintab1 sta sintab lda #>main.sintab1 sta sintab+1 - lda #0 + lda #<0 sta x sta x+1 + lda #<0>>$10 sta x+2 + lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -252,16 +256,17 @@ sin16s_gen: { // sin16s(dword zeropage($f) x) sin16s: { .label _4 = $f + .label _20 = 6 .label x = $f .label return = 6 - .label x1 = $1f - .label x2 = 8 - .label x3 = 8 - .label x3_6 = $13 - .label usinx = 6 - .label x4 = 8 - .label x5 = $13 - .label x5_128 = $13 + .label x1 = $1d + .label x2 = 6 + .label x3 = 6 + .label x3_6 = 8 + .label usinx = $1f + .label x4 = 6 + .label x5 = 8 + .label x5_128 = 8 .label sinx = 6 .label isUpper = $e lda x+3 @@ -408,9 +413,17 @@ sin16s: { lda usinx+1 adc x5_128+1 sta usinx+1 + lda usinx + sta sinx + lda usinx+1 + sta sinx+1 lda isUpper cmp #0 beq b3 + lda usinx + sta _20 + lda usinx+1 + sta _20+1 sec lda sinx eor #$ff @@ -425,15 +438,15 @@ sin16s: { } // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result. // The select parameter indicates how many of the highest bits of the 32-bit result to skip -// mulu16_sel(word zeropage(8) v1, word zeropage($13) v2, byte register(X) select) +// mulu16_sel(word zeropage(6) v1, word zeropage(8) v2, byte register(X) select) mulu16_sel: { .label _0 = $f .label _1 = $f - .label v1 = 8 - .label v2 = $13 - .label return = $13 - .label return_1 = 8 - .label return_10 = 8 + .label v1 = 6 + .label v2 = 8 + .label return = 8 + .label return_1 = 6 + .label return_10 = 6 lda v1 sta mul16u.a lda v1+1 @@ -456,12 +469,12 @@ mulu16_sel: { rts } // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word -// mul16u(word zeropage($15) a, word zeropage($13) b) +// mul16u(word zeropage($13) a, word zeropage(8) b) mul16u: { - .label mb = $17 - .label a = $15 + .label a = $13 + .label mb = $15 .label res = $f - .label b = $13 + .label b = 8 .label return = $f lda b sta mb @@ -472,7 +485,9 @@ mul16u: { sta mb+3 sta res sta res+1 + lda #<0>>$10 sta res+2 + lda #>0>>$10 sta res+3 b1: lda a @@ -513,12 +528,12 @@ mul16u: { div32u16u: { .label quotient_hi = 8 .label quotient_lo = 6 - .label return = $1b + .label return = $19 lda #<PI2_u4f28>>$10 sta divr16u.dividend lda #>PI2_u4f28>>$10 sta divr16u.dividend+1 - lda #0 + lda #<0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u diff --git a/src/test/ref/sinusgen16b.asm b/src/test/ref/sinusgen16b.asm index c99639748..b5f324cfa 100644 --- a/src/test/ref/sinusgen16b.asm +++ b/src/test/ref/sinusgen16b.asm @@ -129,11 +129,13 @@ print_sword: { rts } // Print a word as HEX +// print_word(word zeropage(8) w) print_word: { - lda print_sword.w+1 + .label w = 8 + lda w+1 sta print_byte.b jsr print_byte - lda print_sword.w + lda w sta print_byte.b jsr print_byte rts @@ -196,23 +198,25 @@ print_cls: { // wavelength - the number of sinus points in a total sinus wavelength (the size of the table) // sin16s_genb(signed word* zeropage(2) sintab) sin16s_genb: { - .label _2 = 8 - .label step = $1d + .label _2 = 6 + .label step = $1b .label sintab = 2 .label x = $d .label i = 4 jsr div32u16u - lda #0 + lda #<0 sta i sta i+1 lda #<main.sintab2 sta sintab lda #>main.sintab2 sta sintab+1 - lda #0 + lda #<0 sta x sta x+1 + lda #<0>>$10 sta x+2 + lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -266,17 +270,18 @@ sin16s_genb: { // result: signed word sin(x) s[0.15] - using the full range -$7fff - $7fff // sin16sb(word zeropage(6) x) sin16sb: { + .label _19 = 6 .label x = 6 - .label return = 8 + .label return = 6 .label x1 = 6 - .label x2 = $b - .label x3 = $b - .label x3_6 = $11 - .label usinx = 8 - .label x4 = $b - .label x5 = $11 - .label x5_128 = $11 - .label sinx = 8 + .label x2 = 8 + .label x3 = 8 + .label x3_6 = $b + .label usinx = $1f + .label x4 = 8 + .label x5 = $b + .label x5_128 = $b + .label sinx = 6 .label isUpper = $a lda x+1 cmp #>PI_u4f12 @@ -388,9 +393,17 @@ sin16sb: { lda usinx+1 adc x5_128+1 sta usinx+1 + lda usinx + sta sinx + lda usinx+1 + sta sinx+1 lda isUpper cmp #0 beq b3 + lda usinx + sta _19 + lda usinx+1 + sta _19+1 sec lda sinx eor #$ff @@ -405,19 +418,19 @@ sin16sb: { } // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result. // The select parameter indicates how many of the highest bits of the 32-bit result to skip -// mulu16_sel(word zeropage($b) v1, word zeropage($11) v2, byte register(X) select) +// mulu16_sel(word zeropage(8) v1, word zeropage($b) v2, byte register(X) select) mulu16_sel: { - .label _0 = $15 - .label _1 = $15 - .label v1 = $b - .label v2 = $11 - .label return = $b - .label return_11 = $11 - .label return_14 = $11 - .label return_16 = $11 - .label return_17 = $11 - .label return_18 = $11 - .label return_20 = $11 + .label _0 = $13 + .label _1 = $13 + .label v1 = 8 + .label v2 = $b + .label return = 8 + .label return_11 = $b + .label return_14 = $b + .label return_16 = $b + .label return_17 = $b + .label return_18 = $b + .label return_20 = $b lda v1 sta mul16u.a lda v1+1 @@ -440,13 +453,13 @@ mulu16_sel: { rts } // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word -// mul16u(word zeropage($13) a, word zeropage($11) b) +// mul16u(word zeropage($11) a, word zeropage($b) b) mul16u: { - .label mb = $19 - .label a = $13 - .label res = $15 - .label b = $11 - .label return = $15 + .label a = $11 + .label mb = $17 + .label res = $13 + .label b = $b + .label return = $13 lda b sta mb lda b+1 @@ -456,7 +469,9 @@ mul16u: { sta mb+3 sta res sta res+1 + lda #<0>>$10 sta res+2 + lda #>0>>$10 sta res+3 b1: lda a @@ -497,12 +512,12 @@ mul16u: { div32u16u: { .label quotient_hi = 8 .label quotient_lo = 6 - .label return = $1d + .label return = $1b lda #<PI2_u4f28>>$10 sta divr16u.dividend lda #>PI2_u4f28>>$10 sta divr16u.dividend+1 - lda #0 + lda #<0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u @@ -585,22 +600,24 @@ divr16u: { // sin16s_gen(signed word* zeropage(2) sintab) sin16s_gen: { .label _1 = 6 - .label step = $1d + .label step = $1b .label sintab = 2 .label x = $d .label i = 4 jsr div32u16u - lda #0 + lda #<0 sta i sta i+1 lda #<main.sintab1 sta sintab lda #>main.sintab1 sta sintab+1 - lda #0 + lda #<0 sta x sta x+1 + lda #<0>>$10 sta x+2 + lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -656,19 +673,20 @@ sin16s_gen: { // Calculate signed word sinus sin(x) // x: unsigned dword input u[4.28] in the interval $00000000 - PI2_u4f28 // result: signed word sin(x) s[0.15] - using the full range -$7fff - $7fff -// sin16s(dword zeropage($15) x) +// sin16s(dword zeropage($13) x) sin16s: { - .label _4 = $15 - .label x = $15 + .label _4 = $13 + .label _20 = 6 + .label x = $13 .label return = 6 - .label x1 = 8 - .label x2 = $b - .label x3 = $b - .label x3_6 = $11 - .label usinx = 6 - .label x4 = $b - .label x5 = $11 - .label x5_128 = $11 + .label x1 = 6 + .label x2 = 8 + .label x3 = 8 + .label x3_6 = $b + .label usinx = $1f + .label x4 = 8 + .label x5 = $b + .label x5_128 = $b .label sinx = 6 .label isUpper = $a lda x+3 @@ -815,9 +833,17 @@ sin16s: { lda usinx+1 adc x5_128+1 sta usinx+1 + lda usinx + sta sinx + lda usinx+1 + sta sinx+1 lda isUpper cmp #0 beq b3 + lda usinx + sta _20 + lda usinx+1 + sta _20+1 sec lda sinx eor #$ff diff --git a/src/test/ref/sinusgen8.asm b/src/test/ref/sinusgen8.asm index 9c3cdd67e..0c037f3c0 100644 --- a/src/test/ref/sinusgen8.asm +++ b/src/test/ref/sinusgen8.asm @@ -11,6 +11,7 @@ .label print_char_cursor = 5 main: { .label wavelength = $c0 + .label _2 = 4 .label sb = 4 jsr sin8s_gen jsr print_cls @@ -20,9 +21,11 @@ main: { sta print_char_cursor+1 ldx #0 b1: + lda sintabref,x + sta _2 lda sintab2,x sec - sbc sintabref,x + sbc sb sta sb bmi b2 lda #<str1 @@ -104,8 +107,10 @@ print_char: { rts } // Print a byte as HEX +// print_byte(byte zeropage(4) b) print_byte: { - lda print_sbyte.b + .label b = 4 + lda b lsr lsr lsr @@ -114,7 +119,7 @@ print_byte: { lda print_hextab,y jsr print_char lda #$f - and print_sbyte.b + and b tay lda print_hextab,y jsr print_char @@ -153,14 +158,14 @@ sin8s_gen: { .label x = 2 .label i = 7 jsr div16u - lda #0 + lda #<0 sta i sta i+1 lda #<main.sintab2 sta sintab lda #>main.sintab2 sta sintab+1 - lda #0 + lda #<0 sta x sta x+1 // u[4.12] @@ -170,6 +175,7 @@ sin8s_gen: { lda x+1 sta sin8s.x+1 jsr sin8s + tya ldy #0 sta (sintab),y inc sintab @@ -297,16 +303,17 @@ sin8s: { bcc b3 dex b3: + txa + tay lda isUpper cmp #0 - beq b14 + beq b4 txa eor #$ff clc adc #1 - rts - b14: - txa + tay + b4: rts } // Calculate val*val for two unsigned byte values - the result is 8 selected bits of the 16-bit result. diff --git a/src/test/ref/sinusgen8b.asm b/src/test/ref/sinusgen8b.asm index 7ab3110de..e9cafe49a 100644 --- a/src/test/ref/sinusgen8b.asm +++ b/src/test/ref/sinusgen8b.asm @@ -129,8 +129,10 @@ print_char: { rts } // Print a byte as HEX +// print_byte(byte zeropage(4) b) print_byte: { - lda print_sbyte.b + .label b = 4 + lda b lsr lsr lsr @@ -139,7 +141,7 @@ print_byte: { lda print_hextab,y jsr print_char lda #$f - and print_sbyte.b + and b tay lda print_hextab,y jsr print_char @@ -179,17 +181,19 @@ sin16s_gen: { .label x = 7 .label i = 5 jsr div32u16u - lda #0 + lda #<0 sta i sta i+1 lda #<main.sintabw sta sintab lda #>main.sintabw sta sintab+1 - lda #0 + lda #<0 sta x sta x+1 + lda #<0>>$10 sta x+2 + lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -248,16 +252,17 @@ sin16s_gen: { // sin16s(dword zeropage($b) x) sin16s: { .label _4 = $b + .label _20 = $f .label x = $b .label return = $f - .label x1 = $20 - .label x2 = $11 - .label x3 = $11 - .label x3_6 = $13 - .label usinx = $f - .label x4 = $11 - .label x5 = $13 - .label x5_128 = $13 + .label x1 = $1a + .label x2 = $f + .label x3 = $f + .label x3_6 = $11 + .label usinx = $20 + .label x4 = $f + .label x5 = $11 + .label x5_128 = $11 .label sinx = $f .label isUpper = 4 lda x+3 @@ -404,9 +409,17 @@ sin16s: { lda usinx+1 adc x5_128+1 sta usinx+1 + lda usinx + sta sinx + lda usinx+1 + sta sinx+1 lda isUpper cmp #0 beq b3 + lda usinx + sta _20 + lda usinx+1 + sta _20+1 sec lda sinx eor #$ff @@ -421,15 +434,15 @@ sin16s: { } // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result. // The select parameter indicates how many of the highest bits of the 32-bit result to skip -// mulu16_sel(word zeropage($11) v1, word zeropage($13) v2, byte register(X) select) +// mulu16_sel(word zeropage($f) v1, word zeropage($11) v2, byte register(X) select) mulu16_sel: { .label _0 = $b .label _1 = $b - .label v1 = $11 - .label v2 = $13 - .label return = $13 - .label return_1 = $11 - .label return_10 = $11 + .label v1 = $f + .label v2 = $11 + .label return = $11 + .label return_1 = $f + .label return_10 = $f lda v1 sta mul16u.a lda v1+1 @@ -452,12 +465,12 @@ mulu16_sel: { rts } // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word -// mul16u(word zeropage($15) a, word zeropage($13) b) +// mul16u(word zeropage($13) a, word zeropage($11) b) mul16u: { - .label mb = $17 - .label a = $15 + .label a = $13 + .label mb = $15 .label res = $b - .label b = $13 + .label b = $11 .label return = $b lda b sta mb @@ -468,7 +481,9 @@ mul16u: { sta mb+3 sta res sta res+1 + lda #<0>>$10 sta res+2 + lda #>0>>$10 sta res+3 b1: lda a @@ -514,7 +529,7 @@ div32u16u: { sta divr16u.dividend lda #>PI2_u4f28>>$10 sta divr16u.dividend+1 - lda #0 + lda #<0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u @@ -601,14 +616,14 @@ sin8s_gen: { .label x = 2 .label i = $11 jsr div16u - lda #0 + lda #<0 sta i sta i+1 lda #<main.sintabb sta sintab lda #>main.sintabb sta sintab+1 - lda #0 + lda #<0 sta x sta x+1 // u[4.12] @@ -618,6 +633,7 @@ sin8s_gen: { lda x+1 sta sin8s.x+1 jsr sin8s + tya ldy #0 sta (sintab),y inc sintab @@ -745,25 +761,26 @@ sin8s: { bcc b3 dex b3: + txa + tay lda isUpper cmp #0 - beq b14 + beq b4 txa eor #$ff clc adc #1 - rts - b14: - txa + tay + b4: rts } // Calculate val*val for two unsigned byte values - the result is 8 selected bits of the 16-bit result. // The select parameter indicates how many of the highest bits of the 16-bit result to skip -// mulu8_sel(byte register(X) v1, byte register(Y) v2, byte zeropage($1b) select) +// mulu8_sel(byte register(X) v1, byte register(Y) v2, byte zeropage($19) select) mulu8_sel: { .label _0 = $13 .label _1 = $13 - .label select = $1b + .label select = $19 tya jsr mul8u ldy select @@ -780,7 +797,7 @@ mulu8_sel: { // Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word // mul8u(byte register(X) a, byte register(A) b) mul8u: { - .label mb = $15 + .label mb = $1a .label res = $13 .label return = $13 sta mb @@ -822,7 +839,7 @@ div16u: { sta divr16u.dividend lda #>PI2_u4f12 sta divr16u.dividend+1 - lda #0 + lda #<0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u diff --git a/src/test/ref/sinusgenscale8.asm b/src/test/ref/sinusgenscale8.asm index 7cbff336f..792e19135 100644 --- a/src/test/ref/sinusgenscale8.asm +++ b/src/test/ref/sinusgenscale8.asm @@ -86,14 +86,14 @@ sin8u_table: { lda #>$400 sta print_line_cursor+1 jsr print_ln - lda #0 + lda #<0 sta i sta i+1 lda #<main.sintab sta sintab lda #>main.sintab sta sintab+1 - lda #0 + lda #<0 sta x sta x+1 // u[4.12] @@ -103,8 +103,7 @@ sin8u_table: { lda x+1 sta sin8s.x+1 jsr sin8s - sta sinx - tay + sty sinx jsr mul8su lda sinx_sc+1 tax @@ -327,7 +326,10 @@ mul8su: { .label return = $f tya tax - lda #b + lda #<b + sta mul8u.mb + lda #>b + sta mul8u.mb+1 jsr mul8u cpy #0 bpl b1 @@ -344,9 +346,7 @@ mul8u: { .label mb = $b .label res = $f .label return = $f - sta mb - lda #0 - sta mb+1 + lda #<0 sta res sta res+1 b1: @@ -473,16 +473,17 @@ sin8s: { bcc b3 dex b3: + txa + tay lda isUpper cmp #0 - beq b14 + beq b4 txa eor #$ff clc adc #1 - rts - b14: - txa + tay + b4: rts } // Calculate val*val for two unsigned byte values - the result is 8 selected bits of the 16-bit result. @@ -493,6 +494,9 @@ mulu8_sel: { .label _1 = $f .label select = $11 tya + sta mul8u.mb + lda #0 + sta mul8u.mb+1 jsr mul8u ldy select beq !e+ diff --git a/src/test/ref/sizeof-expr.asm b/src/test/ref/sizeof-expr.asm index 1749feae1..5720d470d 100644 --- a/src/test/ref/sizeof-expr.asm +++ b/src/test/ref/sizeof-expr.asm @@ -6,6 +6,7 @@ .const SIZEOF_BYTE = 1 .const SIZEOF_WORD = 2 .const SIZEOF_POINTER = 2 + .const SIZEOF_NUMBER = $ff main: { .const sz = $f .label b = 2 @@ -15,13 +16,16 @@ main: { sta b sta w sta w+1 - lda #'0'+SIZEOF_BYTE + //byte[] sb = { 'a', 'b', 'c', 0}; + lda #'0'+SIZEOF_NUMBER sta SCREEN + lda #'0'+SIZEOF_BYTE sta SCREEN+1 sta SCREEN+2 sta SCREEN+3 - lda #'0'+SIZEOF_WORD + lda #'0'+SIZEOF_NUMBER sta SCREEN+5 + lda #'0'+SIZEOF_WORD sta SCREEN+6 lda #'0'+SIZEOF_POINTER sta SCREEN+8 @@ -36,7 +40,5 @@ main: { sta SCREEN+$e lda #'0'+8*SIZEOF_BYTE sta SCREEN+$f - lda #'0'+$c*SIZEOF_BYTE - sta SCREEN+$10 rts } diff --git a/src/test/ref/test-comparisons-sword.asm b/src/test/ref/test-comparisons-sword.asm index 426dacc95..7040fecd8 100644 --- a/src/test/ref/test-comparisons-sword.asm +++ b/src/test/ref/test-comparisons-sword.asm @@ -323,11 +323,13 @@ print_sword: { rts } // Print a word as HEX +// print_word(word zeropage($a) w) print_word: { - lda print_sword.w+1 + .label w = $a + lda w+1 sta print_byte.b jsr print_byte - lda print_sword.w + lda w sta print_byte.b jsr print_byte rts diff --git a/src/test/ref/test-division.asm b/src/test/ref/test-division.asm index 6f74de8b7..d7b963748 100644 --- a/src/test/ref/test-division.asm +++ b/src/test/ref/test-division.asm @@ -4,8 +4,8 @@ .pc = $80d "Program" .label print_char_cursor = 8 .label print_line_cursor = 3 - .label rem16u = $a - .label rem16s = $a + .label rem16u = $e + .label rem16s = $e main: { jsr print_cls jsr test_8u @@ -17,7 +17,7 @@ main: { test_16s: { .label dividend = 5 .label divisor = $13 - .label res = $e + .label res = $c .label i = 2 lda #0 sta i @@ -198,7 +198,7 @@ print_str: { // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.5.5 // div16s(signed word zeropage(5) dividend, signed word zeropage($13) divisor) div16s: { - .label return = $e + .label return = $c .label dividend = 5 .label divisor = $13 lda dividend @@ -217,25 +217,21 @@ div16s: { // Implemented using simple binary division // Follows the C99 standard by truncating toward zero on negative results. // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.5.5 -// divr16s(signed word zeropage(8) dividend, signed word zeropage($c) divisor) +// divr16s(signed word zeropage(8) dividend, signed word zeropage($a) divisor) divr16s: { - .const rem = 0 .label _8 = 8 - .label _13 = $c - .label resultu = $e - .label return = $e - .label dividend = 8 - .label divisor = $c + .label _13 = $a + .label _16 = $e + .label _18 = $c .label dividendu = 8 - .label divisoru = $c - .label remu = $a + .label divisoru = $a + .label resultu = $c + .label return = $c + .label dividend = 8 + .label divisor = $a lda dividend+1 bmi b1 - lda #rem - sta remu - lda #0 - sta remu+1 - tay + ldy #0 b2: lda divisor+1 bmi b3 @@ -287,10 +283,6 @@ divr16s: { eor #$ff adc #0 sta _8+1 - lda #-rem - sta remu - lda #0 - sta remu+1 ldy #1 jmp b2 } @@ -298,17 +290,19 @@ divr16s: { // Returns the quotient dividend/divisor. // The final remainder will be set into the global variable rem16u // Implemented using simple binary division -// divr16u(word zeropage(8) dividend, word zeropage($c) divisor, word zeropage($a) rem) +// divr16u(word zeropage(8) dividend, word zeropage($a) divisor, word zeropage($e) rem) divr16u: { - .label rem = $a + .label rem = $e .label dividend = 8 - .label quotient = $e - .label return = $e - .label divisor = $c + .label quotient = $c + .label return = $c + .label divisor = $a ldx #0 txa sta quotient sta quotient+1 + sta rem + sta rem+1 b1: asl rem rol rem+1 @@ -446,7 +440,7 @@ div8s: { tay lda neg cmp #0 - beq b9 + beq b5 txa eor #$ff clc @@ -457,7 +451,7 @@ div8s: { clc adc #1 rts - b9: + b5: tya rts b3: @@ -537,8 +531,8 @@ divr8u: { } test_16u: { .label dividend = 5 - .label divisor = $c - .label res = $e + .label divisor = $a + .label res = $c .label i = 2 lda #0 sta i @@ -606,18 +600,15 @@ test_16u: { // Returns the quotient dividend/divisor. // The remainder will be set into the global variable rem16u // Implemented using simple binary division -// div16u(word zeropage(5) dividend, word zeropage($c) divisor) +// div16u(word zeropage(5) dividend, word zeropage($a) divisor) div16u: { - .label return = $e + .label return = $c .label dividend = 5 - .label divisor = $c + .label divisor = $a lda dividend sta divr16u.dividend lda dividend+1 sta divr16u.dividend+1 - lda #0 - sta divr16u.rem - sta divr16u.rem+1 jsr divr16u rts } diff --git a/src/test/ref/test-multiply-16bit.asm b/src/test/ref/test-multiply-16bit.asm index e5701b8c6..e9858cdce 100644 --- a/src/test/ref/test-multiply-16bit.asm +++ b/src/test/ref/test-multiply-16bit.asm @@ -340,7 +340,9 @@ print_sword: { // mulf16s(signed word zeropage(3) a, signed word zeropage(5) b) mulf16s: { .label _9 = 9 + .label _10 = $15 .label _13 = 9 + .label _14 = $15 .label _16 = 9 .label _17 = 9 .label m = $11 @@ -362,12 +364,16 @@ mulf16s: { sta _9 lda m+3 sta _9+1 + lda b + sta _10 + lda b+1 + sta _10+1 lda _16 sec - sbc b + sbc _10 sta _16 lda _16+1 - sbc b+1 + sbc _10+1 sta _16+1 lda _16 sta m+2 @@ -380,12 +386,16 @@ mulf16s: { sta _13 lda m+3 sta _13+1 + lda a + sta _14 + lda a+1 + sta _14+1 lda _17 sec - sbc a + sbc _14 sta _17 lda _17+1 - sbc a+1 + sbc _14+1 sta _17+1 lda _17 sta m+2 @@ -519,21 +529,30 @@ mulf16u: { // mul16s(signed word zeropage(3) a, signed word zeropage(5) b) mul16s: { .label _9 = 9 + .label _10 = $15 .label _13 = 9 + .label _14 = $15 .label _16 = 9 .label _17 = 9 .label m = $19 .label return = $19 .label a = 3 .label b = 5 - lda b - sta mul16u.b - lda b+1 - sta mul16u.b+1 lda a sta mul16u.a lda a+1 sta mul16u.a+1 + lda b + sta mul16u.b + lda b+1 + sta mul16u.b+1 + lda mul16u.b + sta mul16u.mb + lda mul16u.b+1 + sta mul16u.mb+1 + lda #0 + sta mul16u.mb+2 + sta mul16u.mb+3 jsr mul16u lda a+1 bpl b1 @@ -541,12 +560,16 @@ mul16s: { sta _9 lda m+3 sta _9+1 + lda b + sta _10 + lda b+1 + sta _10+1 lda _16 sec - sbc b + sbc _10 sta _16 lda _16+1 - sbc b+1 + sbc _10+1 sta _16+1 lda _16 sta m+2 @@ -559,12 +582,16 @@ mul16s: { sta _13 lda m+3 sta _13+1 + lda a + sta _14 + lda a+1 + sta _14+1 lda _17 sec - sbc a + sbc _14 sta _17 lda _17+1 - sbc a+1 + sbc _14+1 sta _17+1 lda _17 sta m+2 @@ -574,23 +601,20 @@ mul16s: { rts } // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word -// mul16u(word zeropage(9) a, word zeropage($17) b) +// mul16u(word zeropage(9) a, word zeropage($15) b) mul16u: { .label mb = $11 .label a = 9 .label res = $19 + .label b = $15 .label return = $19 - .label b = $17 - lda b - sta mb - lda b+1 - sta mb+1 - lda #0 - sta mb+2 - sta mb+3 + .label b_1 = $17 + lda #<0 sta res sta res+1 + lda #<0>>$10 sta res+2 + lda #>0>>$10 sta res+3 b1: lda a @@ -643,12 +667,14 @@ muls16s: { lda a beq b5 !: - lda #0 + lda #<0 sta j sta j+1 sta m sta m+1 + lda #<0>>$10 sta m+2 + lda #>0>>$10 sta m+3 b3: lda b+1 @@ -682,19 +708,23 @@ muls16s: { bne b3 rts b5: - lda #0 + lda #<0 sta return sta return+1 + lda #<0>>$10 sta return+2 + lda #>0>>$10 sta return+3 rts b6: - lda #0 + lda #<0 sta i sta i+1 sta m sta m+1 + lda #<0>>$10 sta m+2 + lda #>0>>$10 sta m+3 b4: lda b+1 @@ -774,6 +804,13 @@ mul16u_compare: { sta mul16u.a lda a+1 sta mul16u.a+1 + lda mul16u.b_1 + sta mul16u.mb + lda mul16u.b_1+1 + sta mul16u.mb+1 + lda #0 + sta mul16u.mb+2 + sta mul16u.mb+3 jsr mul16u jsr mulf16u lda ms @@ -822,7 +859,9 @@ mul16u_compare: { b5: iny cpy #$10 - bne b2 + beq !b2+ + jmp b2 + !b2: inc i lda #$10 cmp i @@ -926,12 +965,14 @@ muls16u: { lda a+1 beq b3 !: - lda #0 + lda #<0 sta i sta i+1 sta m sta m+1 + lda #<0>>$10 sta m+2 + lda #>0>>$10 sta m+3 b2: lda m @@ -959,10 +1000,12 @@ muls16u: { bne b2 rts b3: - lda #0 + lda #<0 sta return sta return+1 + lda #<0>>$10 sta return+2 + lda #>0>>$10 sta return+3 rts } @@ -985,7 +1028,7 @@ mulf_init: { sta sqr1_lo lda #>mulf_sqr1_lo+1 sta sqr1_lo+1 - lda #0 + lda #<0 sta sqr sta sqr+1 tax diff --git a/src/test/ref/test-multiply-8bit.asm b/src/test/ref/test-multiply-8bit.asm index 92b5ae098..5cf013274 100644 --- a/src/test/ref/test-multiply-8bit.asm +++ b/src/test/ref/test-multiply-8bit.asm @@ -267,26 +267,36 @@ print_sbyte: { // Fixes offsets introduced by using unsigned multiplication // mul8s(signed byte zeropage(2) a, signed byte register(Y) b) mul8s: { + .label _9 = $10 + .label _13 = $10 .label m = $c - .label a = 2 .label return = $c - tya + .label a = 2 ldx a + tya + sta mul8u.mb + lda #0 + sta mul8u.mb+1 jsr mul8u lda a cmp #0 bpl b1 lda m+1 - sty $ff + sta _9 + tya + eor #$ff sec - sbc $ff + adc _9 sta m+1 b1: cpy #0 bpl b2 lda m+1 + sta _13 + lda a + eor #$ff sec - sbc a + adc _13 sta m+1 b2: rts @@ -297,9 +307,7 @@ mul8u: { .label mb = 6 .label res = $c .label return = $c - sta mb - lda #0 - sta mb+1 + lda #<0 sta res sta res+1 b1: @@ -331,34 +339,42 @@ mul8u: { mulf8s: { .label return = $e jsr mulf8u_prepare - stx mulf8s_prepared.b + txa + tay jsr mulf8s_prepared rts } // Calculate fast multiply with a prepared unsigned byte to a word result // The prepared number is set by calling mulf8s_prepare(byte a) -// mulf8s_prepared(signed byte zeropage(3) b) +// mulf8s_prepared(signed byte register(Y) b) mulf8s_prepared: { .label memA = $fd + .label _8 = $10 + .label _12 = $10 .label m = $e - .label b = 3 .label return = $e - ldx b + tya + tax jsr mulf8u_prepared lda memA cmp #0 bpl b1 lda m+1 + sta _8 + tya + eor #$ff sec - sbc b + adc _8 sta m+1 b1: - lda b - cmp #0 + cpy #0 bpl b2 lda m+1 + sta _12 + lda memA + eor #$ff sec - sbc memA + adc _12 sta m+1 b2: rts @@ -411,8 +427,8 @@ muls8s: { bmi b6 cmp #1 bmi b5 - lda #0 - tay + ldy #0 + tya sta m sta m+1 b3: @@ -435,13 +451,13 @@ muls8s: { bne b3 rts b5: - lda #0 + lda #<0 sta return sta return+1 rts b6: - lda #0 - tay + ldy #0 + tya sta m sta m+1 b4: @@ -484,6 +500,9 @@ mul8u_compare: { jsr mulf8u ldx a lda b + sta mul8u.mb + lda #0 + sta mul8u.mb+1 jsr mul8u lda ms cmp mf @@ -615,7 +634,7 @@ muls8u: { bne b2 rts b3: - lda #0 + lda #<0 sta return sta return+1 rts @@ -777,7 +796,7 @@ mulf_init: { sta sqr1_lo lda #>mulf_sqr1_lo+1 sta sqr1_lo+1 - lda #0 + lda #<0 sta sqr sta sqr+1 tax diff --git a/src/test/ref/test-scroll-up.asm b/src/test/ref/test-scroll-up.asm index 15c85f776..3f11d2fd0 100644 --- a/src/test/ref/test-scroll-up.asm +++ b/src/test/ref/test-scroll-up.asm @@ -17,7 +17,7 @@ scrollup3: { .label _4 = 7 .label _5 = 9 .label l2_4 = 4 - lda #0 + lda #<0 sta l2 sta l2+1 b1: @@ -111,7 +111,7 @@ scrollup1: { .label line = 2 .label _6 = 7 .label _7 = 4 - lda #0 + lda #<0 sta line sta line+1 b1: diff --git a/src/test/ref/test-signed-word-minus-byte.asm b/src/test/ref/test-signed-word-minus-byte.asm index 7323f8d14..44e686934 100644 --- a/src/test/ref/test-signed-word-minus-byte.asm +++ b/src/test/ref/test-signed-word-minus-byte.asm @@ -22,19 +22,33 @@ main: { lda #>$4d2 sta w1+1 b1: + lda #$5b + sta $fe + ora #$7f + bmi !+ + lda #0 + !: + sta $ff sec lda w1 - sbc #$5b + sbc $fe sta w2 lda w1+1 - sbc #0 + sbc $ff sta w2+1 + lda #$29 + sta $fe + ora #$7f + bmi !+ + lda #0 + !: + sta $ff sec lda w2 - sbc #$29 + sbc $fe sta w1 lda w2+1 - sbc #0 + sbc $ff sta w1+1 lda w1 sta print_sword.w @@ -102,11 +116,13 @@ print_sword: { rts } // Print a word as HEX +// print_word(word zeropage(6) w) print_word: { - lda print_sword.w+1 + .label w = 6 + lda w+1 sta print_byte.b jsr print_byte - lda print_sword.w + lda w sta print_byte.b jsr print_byte rts diff --git a/src/test/ref/test-word-size-arrays.asm b/src/test/ref/test-word-size-arrays.asm index 34f29fa59..7a768dfdd 100644 --- a/src/test/ref/test-word-size-arrays.asm +++ b/src/test/ref/test-word-size-arrays.asm @@ -10,7 +10,7 @@ main: { .label _8 = 6 .label _9 = 4 .label _10 = 4 - lda #0 + lda #<0 sta line sta line+1 b1: diff --git a/src/test/ref/true-inline-words.asm b/src/test/ref/true-inline-words.asm index 4dd088582..f8a2b1d7e 100644 --- a/src/test/ref/true-inline-words.asm +++ b/src/test/ref/true-inline-words.asm @@ -8,10 +8,12 @@ main: { .label pos = $501 .label bgcol = $d021 .const w = b*$100 - .const w2 = 1*$100+1+w+0 + .const w2 = 1*$100+1+w + // constant inline words inside expression + .label sc = w2 // implicit cast to (byte*) lda bs+1 - sta w2 + sta sc lda #'m' cmp pos beq b1 diff --git a/src/test/ref/type-inference.asm b/src/test/ref/type-inference.asm new file mode 100644 index 000000000..50476c017 --- /dev/null +++ b/src/test/ref/type-inference.asm @@ -0,0 +1,23 @@ +// Test inference of integer types in expressions +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + .label b = 2 + lda #0 + sta b + b1: + lax b + axs #-[-$30] + lda b + asl + tay + txa + sta screen,y + inc b + lda #$15 + cmp b + bne b1 + rts +} diff --git a/src/test/ref/type-mix.asm b/src/test/ref/type-mix.asm index 8a32fe08f..f9d20ad6c 100644 --- a/src/test/ref/type-mix.asm +++ b/src/test/ref/type-mix.asm @@ -10,13 +10,20 @@ main: { sta w sta w+1 b1: + lda #$c + sta $fe + ora #$7f + bmi !+ + lda #0 + !: + sta $ff sec lda w - sbc #$c + sbc $fe sta w - bcs !+ - dec w+1 - !: + lda w+1 + sbc $ff + sta w+1 lda w sta SCREEN,x inx diff --git a/src/test/ref/typeid-plus-bytes.asm b/src/test/ref/typeid-plus-bytes.asm index 3678d2e5c..5bd605bdd 100644 --- a/src/test/ref/typeid-plus-bytes.asm +++ b/src/test/ref/typeid-plus-bytes.asm @@ -5,36 +5,125 @@ .const TYPEID_BYTE = 1 .const TYPEID_SIGNED_BYTE = 2 .label SCREEN = $400 + .label SSCREEN = $400 main: { jsr testUnsigned + jsr testUnsignedVals jsr testSigned + jsr testSignedVals + rts +} +testSignedVals: { + .const sbc1 = -$78 + .label sbv1 = 5 + lda #-$78 + sta sbv1 + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28 + lda #sbc1 + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1 + lda sbv1 + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1 + lda #-$46+-$32 + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1 + lda #sbc1+-$78 + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1 + lda #-$78+sbc1 + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1 + lda #-$78 + clc + adc sbv1 + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1 + lda #-$78 + clc + adc sbv1 + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1 + lda #sbc1 + clc + adc sbv1 + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1 + lda #sbc1 + clc + adc sbv1 + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1 + lda sbv1 + asl + sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1 rts } testSigned: { - .label sbv1 = 3 - lda #$13 + .label sbv1 = 4 + lda #-$78 sta sbv1 + lda #0 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28 lda #TYPEID_SIGNED_BYTE - sta SCREEN+$28 - sta SCREEN+$29 - sta SCREEN+$2a - sta SCREEN+$2b - sta SCREEN+$2c - sta SCREEN+$2d - sta SCREEN+$2e - sta SCREEN+$2f + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1 + lda #0 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1 + lda #TYPEID_SIGNED_BYTE + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1 + rts +} +testUnsignedVals: { + .const ubc1 = $fa + .label ubv1 = 3 + lda #$fa + sta ubv1 + sta SCREEN+$b+$28 + lda #ubc1 + sta SCREEN+$b+$28+1 + lda ubv1 + sta SCREEN+$b+$28+1+1 + lda #$78+$82 + sta SCREEN+$b+$28+1+1+1 + lda #ubc1+$fa + sta SCREEN+$b+$28+1+1+1+1 + lda #$fa+ubc1 + sta SCREEN+$b+$28+1+1+1+1+1 + lax ubv1 + axs #-[$fa] + stx SCREEN+$b+$28+1+1+1+1+1+1 + lax ubv1 + axs #-[$fa] + stx SCREEN+$b+$28+1+1+1+1+1+1+1 + lda #ubc1 + clc + adc ubv1 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1 + lda #ubc1 + clc + adc ubv1 + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1 + lda ubv1 + asl + sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1 rts } testUnsigned: { .label ubv1 = 2 - lda #$5b + lda #$fa sta ubv1 - lda #TYPEID_BYTE + lda #0 sta SCREEN + lda #TYPEID_BYTE sta SCREEN+1 sta SCREEN+2 + lda #0 sta SCREEN+3 + lda #TYPEID_BYTE sta SCREEN+4 sta SCREEN+5 + sta SCREEN+6 + sta SCREEN+7 + sta SCREEN+8 + sta SCREEN+9 + sta SCREEN+$a rts } diff --git a/src/test/ref/uninitialized.asm b/src/test/ref/uninitialized.asm index dd22c0239..24dc22e36 100644 --- a/src/test/ref/uninitialized.asm +++ b/src/test/ref/uninitialized.asm @@ -3,19 +3,14 @@ :BasicUpstart(main) .pc = $80d "Program" .const b = 0 - .const w = 0 - .label ptr = 0 .label SCREEN = $400 main: { lda #b sta SCREEN - lda #<w + lda #0 sta SCREEN+2 - lda #>w sta SCREEN+3 - lda #<ptr sta SCREEN+5 - lda #>ptr sta SCREEN+5 rts } diff --git a/src/test/ref/valuelist-error.asm b/src/test/ref/valuelist-error.asm new file mode 100644 index 000000000..eb9744a46 --- /dev/null +++ b/src/test/ref/valuelist-error.asm @@ -0,0 +1,10 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + .const w = -1*$100+-1 + lda #<w + sta screen + rts +} From eed40184501664cb80f5b147525cd42716504ba8 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 18 May 2019 22:07:16 +0200 Subject: [PATCH 44/93] Added a blitter box --- .../dk/camelot64/kickc/test/TestPrograms.java | 5 ++ src/test/kc/c64dtv-blitter-box.kc | 57 +++++++++++++++++++ src/test/kc/c64dtv-blittermin.kc | 12 ++-- 3 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 src/test/kc/c64dtv-blitter-box.kc diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 7a4ea6db5..508e25cee 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -1230,6 +1230,11 @@ public class TestPrograms { compileAndCompare("c64dtv-blittermin"); } + @Test + public void testC64DtvBlitterBox() throws IOException, URISyntaxException { + compileAndCompare("c64dtv-blitter-box"); + } + @Test public void testC64Dtv8bppChunkyStretch() throws IOException, URISyntaxException { compileAndCompare("c64dtv-8bppchunkystretch"); diff --git a/src/test/kc/c64dtv-blitter-box.kc b/src/test/kc/c64dtv-blitter-box.kc new file mode 100644 index 000000000..df9ab614f --- /dev/null +++ b/src/test/kc/c64dtv-blitter-box.kc @@ -0,0 +1,57 @@ +// Fill a box on the screen using the blitter + +import "c64dtv.kc" + +const byte* SCREEN = $400; +const byte[] SRCA = "camelot rules!"; +const byte[] SRCB = { $80 }; + +void main() { + + *DTV_FEATURE = DTV_FEATURE_ENABLE; + + // Instruct blitter not to continue previous blit + *DTV_BLITTER_CONTROL2 = DTV_BLIT_CLEAR_IRQ; + + *DTV_BLITTER_SRCA_LO = <SRCA; + *DTV_BLITTER_SRCA_MI = >SRCA; + *DTV_BLITTER_SRCA_HI = 0; + *DTV_BLITTER_SRCA_MOD_LO = 0; + *DTV_BLITTER_SRCA_MOD_HI = 0; + *DTV_BLITTER_SRCA_LIN_LO = <$100uw; + *DTV_BLITTER_SRCA_LIN_HI = >$100uw; + *DTV_BLITTER_SRCA_STEP = 01; // Step 0.0 + + *DTV_BLITTER_SRCB_LO = <SRCB; + *DTV_BLITTER_SRCB_MI = >SRCB; + *DTV_BLITTER_SRCB_HI = 0; + *DTV_BLITTER_SRCB_MOD_LO = 0; + *DTV_BLITTER_SRCB_MOD_HI = 0; + *DTV_BLITTER_SRCB_LIN_LO = <$100uw; + *DTV_BLITTER_SRCB_LIN_HI = >$100uw; + *DTV_BLITTER_SRCB_STEP = $00; // Step 0.0 + + *DTV_BLITTER_DEST_LO = <SCREEN+40+5; + *DTV_BLITTER_DEST_MI = >SCREEN+40+5; + *DTV_BLITTER_DEST_HI = 0; + *DTV_BLITTER_DEST_MOD_LO = <21uw; + *DTV_BLITTER_DEST_MOD_HI = >21uw; + *DTV_BLITTER_DEST_LIN_LO = <19uw; + *DTV_BLITTER_DEST_LIN_HI = >19uw; + *DTV_BLITTER_DEST_STEP = $10; // Step 1.0 + + *DTV_BLITTER_LEN_LO = <20*10uw; + *DTV_BLITTER_LEN_HI = >20*10uw; + + *DTV_BLITTER_ALU = DTV_BLIT_ADD; + *DTV_BLITTER_TRANSPARANCY = DTV_BLIT_TRANSPARANCY_NONE; + + // Start blitter + *DTV_BLITTER_CONTROL = DTV_BLIT_FORCE_START | DTV_BLIT_SRCA_FWD | DTV_BLIT_SRCB_FWD| DTV_BLIT_DEST_FWD; + // Instruct blitter to continue at DEST and restart SRC A/B + *DTV_BLITTER_CONTROL2 = DTV_BLIT_DEST_CONT; + + // wait til blitter is ready + do {} while((*DTV_BLITTER_CONTROL2 & DTV_BLIT_STATUS_BUSY)!=0); + +} \ No newline at end of file diff --git a/src/test/kc/c64dtv-blittermin.kc b/src/test/kc/c64dtv-blittermin.kc index ee0002776..ffc43fa90 100644 --- a/src/test/kc/c64dtv-blittermin.kc +++ b/src/test/kc/c64dtv-blittermin.kc @@ -17,8 +17,8 @@ void main() { *DTV_BLITTER_SRCA_HI = 0; *DTV_BLITTER_SRCA_MOD_LO = 0; *DTV_BLITTER_SRCA_MOD_HI = 0; - *DTV_BLITTER_SRCA_LIN_LO = <$100; - *DTV_BLITTER_SRCA_LIN_HI = >$100; + *DTV_BLITTER_SRCA_LIN_LO = <$100uw; + *DTV_BLITTER_SRCA_LIN_HI = >$100uw; *DTV_BLITTER_SRCA_STEP = $10; // Step 1.0 *DTV_BLITTER_SRCB_LO = <SRCB; @@ -26,8 +26,8 @@ void main() { *DTV_BLITTER_SRCB_HI = 0; *DTV_BLITTER_SRCB_MOD_LO = 0; *DTV_BLITTER_SRCB_MOD_HI = 0; - *DTV_BLITTER_SRCB_LIN_LO = <$100; - *DTV_BLITTER_SRCB_LIN_HI = >$100; + *DTV_BLITTER_SRCB_LIN_LO = <$100uw; + *DTV_BLITTER_SRCB_LIN_HI = >$100uw; *DTV_BLITTER_SRCB_STEP = $00; // Step 0.0 *DTV_BLITTER_DEST_LO = <SCREEN; @@ -35,8 +35,8 @@ void main() { *DTV_BLITTER_DEST_HI = 0; *DTV_BLITTER_DEST_MOD_LO = 0; *DTV_BLITTER_DEST_MOD_HI = 0; - *DTV_BLITTER_DEST_LIN_LO = <$100; - *DTV_BLITTER_DEST_LIN_HI = >$100; + *DTV_BLITTER_DEST_LIN_LO = <$100uw; + *DTV_BLITTER_DEST_LIN_HI = >$100uw; *DTV_BLITTER_DEST_STEP = $10; // Step 1.0 *DTV_BLITTER_LEN_LO = SRCA_LEN; From abfa6f875f640f337abdcb51bbc8716c7b4ce348 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 18 May 2019 22:40:46 +0200 Subject: [PATCH 45/93] Added a few tests --- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/number-inference-sum.kc | 16 ++ src/test/ref/c64dtv-blitter-box.asm | 148 ++++++++++++++++++ src/test/ref/number-inference-sum.asm | 20 +++ 4 files changed, 189 insertions(+) create mode 100644 src/test/kc/number-inference-sum.kc create mode 100644 src/test/ref/c64dtv-blitter-box.asm create mode 100644 src/test/ref/number-inference-sum.asm diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 508e25cee..112535fab 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,6 +63,11 @@ public class TestPrograms { */ + @Test + public void testNumberInferenceSum() throws IOException, URISyntaxException { + compileAndCompare("number-inference-sum"); + } + @Test public void testGfxBankOptimization() throws IOException, URISyntaxException { compileAndCompare("gfxbank"); diff --git a/src/test/kc/number-inference-sum.kc b/src/test/kc/number-inference-sum.kc new file mode 100644 index 000000000..b0aa72f6a --- /dev/null +++ b/src/test/kc/number-inference-sum.kc @@ -0,0 +1,16 @@ +// Test inference of number types using a long sum +// Currently fails - because the compiler does not handle byte+byte correctly (not truncating the result to 8 bits) + +void main() { + const word* screen = 0x0400; + const byte* bgcol = 0xd020; + const byte RED = 2; + + byte b1 = 250; + byte b2 = b1+250; + word w = b2+1; + screen[0] = w; + + if((w)>255) *bgcol = RED; + +} \ No newline at end of file diff --git a/src/test/ref/c64dtv-blitter-box.asm b/src/test/ref/c64dtv-blitter-box.asm new file mode 100644 index 000000000..36d9a9a77 --- /dev/null +++ b/src/test/ref/c64dtv-blitter-box.asm @@ -0,0 +1,148 @@ +// Fill a box on the screen using the blitter +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Feature enables or disables the extra C64 DTV features + .label DTV_FEATURE = $d03f + .const DTV_FEATURE_ENABLE = 1 + // Blitter Source A Start + .label DTV_BLITTER_SRCA_LO = $d320 + .label DTV_BLITTER_SRCA_MI = $d321 + .label DTV_BLITTER_SRCA_HI = $d322 + // Blitter Source A Modulo + .label DTV_BLITTER_SRCA_MOD_LO = $d323 + .label DTV_BLITTER_SRCA_MOD_HI = $d324 + // Blitter Source A Line Length + .label DTV_BLITTER_SRCA_LIN_LO = $d325 + .label DTV_BLITTER_SRCA_LIN_HI = $d326 + // Blitter Source A Step ([7:4] integral part, [3:0] fractional part) + .label DTV_BLITTER_SRCA_STEP = $d327 + // Blitter Source B Start + .label DTV_BLITTER_SRCB_LO = $d328 + .label DTV_BLITTER_SRCB_MI = $d329 + .label DTV_BLITTER_SRCB_HI = $d32a + // Blitter Source B Modulo + .label DTV_BLITTER_SRCB_MOD_LO = $d32b + .label DTV_BLITTER_SRCB_MOD_HI = $d32c + // Blitter Source B Line Length + .label DTV_BLITTER_SRCB_LIN_LO = $d32d + .label DTV_BLITTER_SRCB_LIN_HI = $d32e + // Blitter Source B Step ([7:4] integral part, [3:0] fractional part) + .label DTV_BLITTER_SRCB_STEP = $d32f + // Blitter Destination Start + .label DTV_BLITTER_DEST_LO = $d330 + .label DTV_BLITTER_DEST_MI = $d331 + .label DTV_BLITTER_DEST_HI = $d332 + // Blitter Source B Modulo + .label DTV_BLITTER_DEST_MOD_LO = $d333 + .label DTV_BLITTER_DEST_MOD_HI = $d334 + // Blitter Source B Line Length + .label DTV_BLITTER_DEST_LIN_LO = $d335 + .label DTV_BLITTER_DEST_LIN_HI = $d336 + // Blitter Source B Step ([7:4] integral part, [3:0] fractional part) + .label DTV_BLITTER_DEST_STEP = $d337 + // Blitter Blit Length + .label DTV_BLITTER_LEN_LO = $d338 + .label DTV_BLITTER_LEN_HI = $d339 + // Blitter Control + .label DTV_BLITTER_CONTROL = $d33a + // Bit[0] Force Start Strobe when set + .const DTV_BLIT_FORCE_START = 1 + // Bit[1] Source A Direction Positive when set + .const DTV_BLIT_SRCA_FWD = 2 + // Bit[2] Source B Direction Positive when set + .const DTV_BLIT_SRCB_FWD = 4 + // Bit[3] Destination Direction Positive when set + .const DTV_BLIT_DEST_FWD = 8 + // Blitter Transparency + .label DTV_BLITTER_TRANSPARANCY = $d33b + // No transparancy + // Bit[2]==Bit[1]==0: write in any case + .const DTV_BLIT_TRANSPARANCY_NONE = 0 + // Controls the ALU operation + .label DTV_BLITTER_ALU = $d33e + .const DTV_BLIT_ADD = $30 + // Blitter Control 2 + .label DTV_BLITTER_CONTROL2 = $d33f + // Bit[0] Clear Blitter IRQ + .const DTV_BLIT_CLEAR_IRQ = 1 + // Bit[3] Destination Continue + .const DTV_BLIT_DEST_CONT = 8 + // Bit[0] Busy when set (When reading) + .const DTV_BLIT_STATUS_BUSY = 1 + .label SCREEN = $400 +main: { + lda #DTV_FEATURE_ENABLE + sta DTV_FEATURE + // Instruct blitter not to continue previous blit + lda #DTV_BLIT_CLEAR_IRQ + sta DTV_BLITTER_CONTROL2 + lda #<SRCA + sta DTV_BLITTER_SRCA_LO + lda #>SRCA + sta DTV_BLITTER_SRCA_MI + lda #0 + sta DTV_BLITTER_SRCA_HI + sta DTV_BLITTER_SRCA_MOD_LO + sta DTV_BLITTER_SRCA_MOD_HI + sta DTV_BLITTER_SRCA_LIN_LO + lda #>$100 + sta DTV_BLITTER_SRCA_LIN_HI + lda #1 + sta DTV_BLITTER_SRCA_STEP + // Step 0.0 + lda #<SRCB + sta DTV_BLITTER_SRCB_LO + lda #>SRCB + sta DTV_BLITTER_SRCB_MI + lda #0 + sta DTV_BLITTER_SRCB_HI + sta DTV_BLITTER_SRCB_MOD_LO + sta DTV_BLITTER_SRCB_MOD_HI + sta DTV_BLITTER_SRCB_LIN_LO + lda #>$100 + sta DTV_BLITTER_SRCB_LIN_HI + lda #0 + sta DTV_BLITTER_SRCB_STEP + // Step 0.0 + lda #<SCREEN+$28+5 + sta DTV_BLITTER_DEST_LO + lda #>SCREEN+$28+5 + sta DTV_BLITTER_DEST_MI + lda #0 + sta DTV_BLITTER_DEST_HI + lda #<$15 + sta DTV_BLITTER_DEST_MOD_LO + lda #0 + sta DTV_BLITTER_DEST_MOD_HI + lda #<$13 + sta DTV_BLITTER_DEST_LIN_LO + lda #0 + sta DTV_BLITTER_DEST_LIN_HI + lda #$10 + sta DTV_BLITTER_DEST_STEP + // Step 1.0 + lda #<$14*$a + sta DTV_BLITTER_LEN_LO + lda #0 + sta DTV_BLITTER_LEN_HI + lda #DTV_BLIT_ADD + sta DTV_BLITTER_ALU + lda #DTV_BLIT_TRANSPARANCY_NONE + sta DTV_BLITTER_TRANSPARANCY + // Start blitter + lda #DTV_BLIT_FORCE_START|DTV_BLIT_SRCA_FWD|DTV_BLIT_SRCB_FWD|DTV_BLIT_DEST_FWD + sta DTV_BLITTER_CONTROL + // Instruct blitter to continue at DEST and restart SRC A/B + lda #DTV_BLIT_DEST_CONT + sta DTV_BLITTER_CONTROL2 + // wait til blitter is ready + b1: + lda #DTV_BLIT_STATUS_BUSY + and DTV_BLITTER_CONTROL2 + cmp #0 + bne b1 + rts +} + SRCA: .text "camelot rules!@" + SRCB: .byte $80 diff --git a/src/test/ref/number-inference-sum.asm b/src/test/ref/number-inference-sum.asm new file mode 100644 index 000000000..9715ba4f5 --- /dev/null +++ b/src/test/ref/number-inference-sum.asm @@ -0,0 +1,20 @@ +// Test inference of number types using a long sum +// Currently fails - because the compiler does not handle byte+byte correctly (not truncating the result to 8 bits) +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + .label bgcol = $d020 + .const RED = 2 + .const b1 = $fa + .const b2 = b1+$fa + .const w = b2+1 + lda #<w + sta screen + lda #>w + sta screen+1 + lda #RED + sta bgcol + rts +} From b5a9d4747233210c3c68eef3f7622d14ca3351d1 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 18 May 2019 23:58:04 +0200 Subject: [PATCH 46/93] Improved code by avoiding unnecesary casts --- ...uxx.asm => pwuc1_derefidx_vbuaa=vbuxx.asm} | 0 ...uaa.asm => pwuc1_derefidx_vbuxx=vbuaa.asm} | 0 .../fragment/pwuc1_derefidx_vbuyy=vbuaa.asm | 3 + src/main/fragment/vduz1=vwuz2.asm | 7 + .../java/dk/camelot64/kickc/Compiler.java | 4 - .../model/types/SymbolTypeConversion.java | 3 +- .../passes/Pass2FixInlineConstructors.java | 132 ------------------ .../kickc/passes/Pass2NopCastElimination.java | 87 ------------ .../kickc/passes/Pass3AddAssignmentCasts.java | 41 ------ .../kickc/passes/Pass3PhiMemCoalesce.java | 13 +- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/mul8u-min.kc | 14 ++ src/test/ref/bresenhamarr.asm | 2 +- src/test/ref/c64dtv-8bppchunkystretch.asm | 2 +- src/test/ref/c64dtv-blittermin.asm | 3 +- src/test/ref/complex/tetris/tetris.asm | 3 - src/test/ref/derefidx-word-0.asm | 2 +- src/test/ref/examples/3d/perspective.asm | 4 +- .../ref/examples/chargen/chargen-analysis.asm | 5 +- src/test/ref/examples/fire/fire.asm | 2 +- .../multiplexer/simple-multiplexer.asm | 6 +- .../ref/examples/plasma/plasma-unroll.asm | 2 +- src/test/ref/examples/plasma/plasma.asm | 2 +- src/test/ref/examples/rotate/rotate.asm | 2 +- .../ref/examples/scrolllogo/scrolllogo.asm | 52 ++++--- .../ref/examples/sinplotter/sine-plotter.asm | 62 ++++---- .../ref/examples/sinsprites/sinus-sprites.asm | 4 +- src/test/ref/forrangedwords.asm | 2 +- src/test/ref/fragment-variations.asm | 10 +- src/test/ref/linegen.asm | 16 +-- src/test/ref/liverange-call-problem.asm | 4 +- src/test/ref/min-fmul-16.asm | 2 +- .../simple-multiplexer-irq.asm | 6 +- src/test/ref/roll-sprite-msb.asm | 6 +- src/test/ref/scan-desire-problem.asm | 6 +- src/test/ref/semi-struct-2.asm | 5 +- src/test/ref/signed-words.asm | 12 +- src/test/ref/sinus-basic.asm | 4 +- src/test/ref/sinusgen16.asm | 10 +- src/test/ref/sinusgen16b.asm | 16 +-- src/test/ref/sinusgen8.asm | 4 +- src/test/ref/sinusgen8b.asm | 16 +-- src/test/ref/sinusgenscale8.asm | 10 +- src/test/ref/test-multiply-16bit.asm | 32 ++--- src/test/ref/test-multiply-8bit.asm | 8 +- src/test/ref/test-scroll-up.asm | 4 +- src/test/ref/test-word-size-arrays.asm | 2 +- 47 files changed, 185 insertions(+), 452 deletions(-) rename src/main/fragment/{pwuc1_derefidx_vbuaa=_word_vbuxx.asm => pwuc1_derefidx_vbuaa=vbuxx.asm} (100%) rename src/main/fragment/{pwuc1_derefidx_vbuxx=_word_vbuaa.asm => pwuc1_derefidx_vbuxx=vbuaa.asm} (100%) create mode 100644 src/main/fragment/pwuc1_derefidx_vbuyy=vbuaa.asm create mode 100644 src/main/fragment/vduz1=vwuz2.asm delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java create mode 100644 src/test/kc/mul8u-min.kc diff --git a/src/main/fragment/pwuc1_derefidx_vbuaa=_word_vbuxx.asm b/src/main/fragment/pwuc1_derefidx_vbuaa=vbuxx.asm similarity index 100% rename from src/main/fragment/pwuc1_derefidx_vbuaa=_word_vbuxx.asm rename to src/main/fragment/pwuc1_derefidx_vbuaa=vbuxx.asm diff --git a/src/main/fragment/pwuc1_derefidx_vbuxx=_word_vbuaa.asm b/src/main/fragment/pwuc1_derefidx_vbuxx=vbuaa.asm similarity index 100% rename from src/main/fragment/pwuc1_derefidx_vbuxx=_word_vbuaa.asm rename to src/main/fragment/pwuc1_derefidx_vbuxx=vbuaa.asm diff --git a/src/main/fragment/pwuc1_derefidx_vbuyy=vbuaa.asm b/src/main/fragment/pwuc1_derefidx_vbuyy=vbuaa.asm new file mode 100644 index 000000000..355a5914f --- /dev/null +++ b/src/main/fragment/pwuc1_derefidx_vbuyy=vbuaa.asm @@ -0,0 +1,3 @@ +sta {c1},y +lda #0 +sta {c1}+1,y diff --git a/src/main/fragment/vduz1=vwuz2.asm b/src/main/fragment/vduz1=vwuz2.asm new file mode 100644 index 000000000..7d25095ee --- /dev/null +++ b/src/main/fragment/vduz1=vwuz2.asm @@ -0,0 +1,7 @@ +lda {z2} +sta {z1} +lda {z2}+1 +sta {z1}+1 +lda #0 +sta {z1}+2 +sta {z1}+3 \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index b5dd695b3..4dc3c79f5 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -252,16 +252,13 @@ public class Compiler { optimizations.add(new Pass2ConstantValues(program)); optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNVariableReferenceInfos(program)); - //optimizations.add(new Pass2ConstantAdditionElimination(program)); optimizations.add(new Pass2ConstantIfs(program)); optimizations.add(new Pass2ConstantStringConsolidation(program)); - //optimizations.add(new Pass2FixInlineConstructors(program)); optimizations.add(new Pass2FixInlineConstructorsNew(program)); optimizations.add(new PassNAddTypeConversionAssignment(program)); optimizations.add(new Pass2TypeInference(program)); optimizations.add(new PassNEliminateUnusedVars(program, true)); optimizations.add(new Pass2EliminateRedundantCasts(program)); - //optimizations.add(new Pass2NopCastElimination(program)); optimizations.add(new Pass2EliminateUnusedBlocks(program)); optimizations.add(new Pass2RangeResolving(program)); optimizations.add(new Pass2ComparisonOptimization(program)); @@ -386,7 +383,6 @@ public class Compiler { new Pass3AssertConstants(program).check(); new Pass3AssertArrayLengths(program).check(); new Pass3AssertNoMulDivMod(program).check(); - new Pass3AddAssignmentCasts(program).execute(); new PassNCastSimplification(program).execute(); new PassNBlockSequencePlanner(program).step(); // Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index df8ec8b90..02b96b28c 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -202,7 +202,8 @@ public class SymbolTypeConversion { return false; else return true; - } + + } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java deleted file mode 100644 index e13b30941..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java +++ /dev/null @@ -1,132 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.Comment; -import dk.camelot64.kickc.model.ControlFlowBlock; -import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.iterator.ProgramValue; -import dk.camelot64.kickc.model.iterator.ProgramValueHandler; -import dk.camelot64.kickc.model.iterator.ProgramValueIterator; -import dk.camelot64.kickc.model.operators.Operator; -import dk.camelot64.kickc.model.operators.Operators; -import dk.camelot64.kickc.model.statements.Statement; -import dk.camelot64.kickc.model.statements.StatementAssignment; -import dk.camelot64.kickc.model.symbols.Scope; -import dk.camelot64.kickc.model.symbols.VariableIntermediate; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeArray; -import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; -import dk.camelot64.kickc.model.values.Value; -import dk.camelot64.kickc.model.values.ValueList; - -import java.util.ListIterator; - -/** - * Identifies word constructors <code>{ b1, b2 }</code> and replaces - * them with a binary operator <code>word w = b1 w= b2 ;</code> - */ -public class Pass2FixInlineConstructors extends Pass2SsaOptimization { - - public Pass2FixInlineConstructors(Program program) { - super(program); - } - - @Override - public boolean step() { - WordConstructor wordConstructor = new WordConstructor(); - ProgramValueIterator.execute(getGraph(), wordConstructor); - DWordConstructor dwordConstructor = new DWordConstructor(); - ProgramValueIterator.execute(getGraph(), dwordConstructor); - return wordConstructor.isOptimized() || dwordConstructor.isOptimized(); - } - - /** Replaces { b1, b2 } with a w= operator */ - private class WordConstructor extends InlineConstructor { - - public WordConstructor() { - super(SymbolType.WORD, Operators.WORD); - } - - @Override - protected boolean isSubType(SymbolType elmType) { - return SymbolType.BYTE.equals(elmType); - } - } - - /** Replaces { w1, w2 } with a dw= operator */ - private class DWordConstructor extends InlineConstructor { - - public DWordConstructor() { - super(SymbolType.DWORD, Operators.DWORD); - } - - @Override - protected boolean isSubType(SymbolType elmType) { - return SymbolType.WORD.equals(elmType); - } - } - - - private abstract class InlineConstructor implements ProgramValueHandler { - private SymbolTypeIntegerFixed constructType; - private Operator constructOperator; - private boolean optimized; - - public InlineConstructor(SymbolTypeIntegerFixed constructType, Operator constructOperator) { - this.constructType = constructType; - this.constructOperator = constructOperator; - } - - protected abstract boolean isSubType(SymbolType elmType); - - public boolean isOptimized() { - return optimized; - } - - @Override - public void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) { - Value rValue = programValue.get(); - if(rValue instanceof ValueList) { - ValueList list = (ValueList) rValue; - if(list.getList().size() == 2) { - // We have a simple assignment of a length 2 value list to a variable - SymbolType elmType1 = SymbolTypeInference.inferType(Pass2FixInlineConstructors.this.getScope(), list.getList().get(0)); - SymbolType elmType2 = SymbolTypeInference.inferType(Pass2FixInlineConstructors.this.getScope(), list.getList().get(1)); - if(isSubType(elmType1) && isSubType(elmType2)) { - // We have a 2-element list { byte, byte } - - // Check if we are assigning into a declared byte array - if(currentStmt instanceof StatementAssignment) { - StatementAssignment assignment = (StatementAssignment) currentStmt; - if(assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2().equals(rValue)) { - SymbolType lType = SymbolTypeInference.inferType(Pass2FixInlineConstructors.this.getScope(), assignment.getlValue()); - if(lType instanceof SymbolTypeArray && isSubType(((SymbolTypeArray) lType).getElementType())) { - // We are assigning into a declared byte array - do not convert! - return; - } - } - } - - // Convert list to a word constructor in a new tmp variable - Scope currentScope = Pass2FixInlineConstructors.this.getScope().getScope(currentBlock.getScope()); - VariableIntermediate tmpVar = currentScope.addVariableIntermediate(); - tmpVar.setTypeInferred(constructType); - // Move backward - to insert before the current statement - stmtIt.previous(); - // Add assignment of the new tmpVar - StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), list.getList().get(0), constructOperator, list.getList().get(1), currentStmt.getSource(), Comment.NO_COMMENTS); - stmtIt.add(assignment); - // Move back before the current statement - stmtIt.next(); - // Replace current value with the reference - programValue.set(tmpVar.getRef()); - Pass2FixInlineConstructors.this.getLog().append("Fixing inline constructor with " + assignment.toString()); - optimized = true; - } - } - } - } - } - - -} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java deleted file mode 100644 index b66de4df4..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java +++ /dev/null @@ -1,87 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.*; -import dk.camelot64.kickc.model.operators.OperatorCastPtr; -import dk.camelot64.kickc.model.operators.Operators; -import dk.camelot64.kickc.model.values.*; -import dk.camelot64.kickc.model.statements.Statement; -import dk.camelot64.kickc.model.statements.StatementAssignment; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypePointer; - -import java.util.LinkedHashMap; -import java.util.ListIterator; - -/** - * Compiler Pass eliminating cast assignments that has no effect (byte to/from signed byte, word to/from signed word) - */ -public class Pass2NopCastElimination extends Pass2SsaOptimization { - - public Pass2NopCastElimination(Program program) { - super(program); - } - - /** - * Eliminate cast assignments that has no effect (byte to/from signed byte, word to/from signed word) - */ - @Override - public boolean step() { - LinkedHashMap<SymbolRef, RValue> castAliasses = new LinkedHashMap<>(); - - for(ControlFlowBlock block : getGraph().getAllBlocks()) { - ListIterator<Statement> stmtIt = block.getStatements().listIterator(); - while(stmtIt.hasNext()) { - Statement stmt = stmtIt.next(); - if(stmt instanceof StatementAssignment) { - StatementAssignment assignment = (StatementAssignment) stmt; - if(assignment.getlValue() instanceof VariableRef && assignment.getrValue1()==null && assignment.getOperator()!=null ) { - // It is a simple cast assignment - check if it is no-op - SymbolType rValType = SymbolTypeInference.inferType(getScope(), assignment.getrValue2()); - boolean isNopCast = false; - SymbolType toType = null; - if(SymbolType.BYTE.equals(rValType) && Operators.CAST_SBYTE.equals(assignment.getOperator())) { - isNopCast = true; - toType = SymbolType.SBYTE; - } else if(SymbolType.SBYTE.equals(rValType) && Operators.CAST_BYTE.equals(assignment.getOperator())) { - isNopCast = true; - toType = SymbolType.BYTE; - } else if(SymbolType.WORD.equals(rValType) && Operators.CAST_SWORD.equals(assignment.getOperator())) { - isNopCast = true; - toType = SymbolType.SWORD; - } else if(SymbolType.SWORD.equals(rValType) && Operators.CAST_WORD.equals(assignment.getOperator())) { - isNopCast = true; - toType = SymbolType.WORD; - } else if(SymbolType.WORD.equals(rValType) && assignment.getOperator() instanceof OperatorCastPtr) { - isNopCast = true; - OperatorCastPtr castOperator = (OperatorCastPtr) (assignment.getOperator()); - toType = new SymbolTypePointer(castOperator.getElementType()); - } else if(rValType instanceof SymbolTypePointer && Operators.CAST_WORD.equals(assignment.getOperator())) { - isNopCast = true; - toType = SymbolType.WORD; - } else if(rValType instanceof SymbolTypePointer && assignment.getOperator() instanceof OperatorCastPtr) { - isNopCast = true; - toType = new SymbolTypePointer(((OperatorCastPtr) assignment.getOperator()).getElementType()); - } - if(isNopCast) { - getLog().append("Eliminating Noop Cast "+assignment.toString(getProgram(), false)); - // Add the alias for replacement - if(assignment.getrValue2() instanceof ConstantValue) { - castAliasses.put((VariableRef) assignment.getlValue(), new ConstantCastValue(toType, (ConstantValue) assignment.getrValue2())); - } else { - castAliasses.put((VariableRef) assignment.getlValue(), new CastValue(toType, assignment.getrValue2())); - } - // Remove the assignment - stmtIt.remove(); - } - } - } - } - } - replaceVariables(castAliasses); - deleteSymbols(getScope(), castAliasses.keySet()); - return (castAliasses.size() > 0); - } - - -} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java deleted file mode 100644 index aee315662..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java +++ /dev/null @@ -1,41 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; -import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; -import dk.camelot64.kickc.model.operators.Operators; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeConversion; -import dk.camelot64.kickc.model.types.SymbolTypeInference; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Add casts to assignments where the lvalue and rvalue have different matching types. - */ -public class Pass3AddAssignmentCasts extends Pass2SsaOptimization { - - public Pass3AddAssignmentCasts(Program program) { - super(program); - } - - @Override - public boolean step() { - AtomicBoolean modified = new AtomicBoolean(false); - ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> { - if(programExpression instanceof ProgramExpressionBinary) { - if(Operators.ASSIGNMENT.equals(programExpression.getOperator())) { - ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression; - SymbolType leftType = SymbolTypeInference.inferType(getScope(), binary.getLeft()); - SymbolType rightType = SymbolTypeInference.inferType(getScope(), binary.getRight()); - if(SymbolTypeConversion.assignmentTypeMatch(leftType, rightType) && SymbolTypeConversion.assignmentCastNeeded(leftType, rightType)) { - binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope()); - getLog().append("Adding assignment cast to " + currentStmt.toString(getProgram(), false)); - modified.set(true); - } - } - } - }); - return modified.get(); - } -} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java index 65b5fae89..7a4876a5e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java @@ -1,6 +1,8 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.*; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeConversion; import dk.camelot64.kickc.model.values.ConstantValue; import dk.camelot64.kickc.model.values.VariableRef; import dk.camelot64.kickc.model.statements.StatementAssignment; @@ -49,9 +51,12 @@ public class Pass3PhiMemCoalesce extends Pass2SsaOptimization { */ public static class EquivalenceClassPhiInitializer extends ControlFlowGraphBaseVisitor<Void> { + private Program program; + private LiveRangeEquivalenceClassSet phiEquivalenceClasses; public EquivalenceClassPhiInitializer(Program program) { + this.program = program; this.phiEquivalenceClasses = new LiveRangeEquivalenceClassSet(program); } @@ -65,7 +70,13 @@ public class Pass3PhiMemCoalesce extends Pass2SsaOptimization { VariableRef phiRVar = (VariableRef) phiRValue.getrValue(); LiveRangeEquivalenceClass rValEquivalenceClass = phiEquivalenceClasses.getOrCreateEquivalenceClass(phiRVar); if(!rValEquivalenceClass.equals(equivalenceClass)) { - phiEquivalenceClasses.consolidate(equivalenceClass, rValEquivalenceClass); + SymbolType varType = program.getScope().getVariable(variable).getType(); + SymbolType rVarType = program.getScope().getVariable(phiRVar).getType(); + if(varType.getSizeBytes()==rVarType.getSizeBytes()) { + phiEquivalenceClasses.consolidate(equivalenceClass, rValEquivalenceClass); + } else { + program.getLog().append("Not consolidating phi with different size "+variable.toString()+" "+phiRVar.toString()); + } } } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 112535fab..e0d216b07 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,6 +63,11 @@ public class TestPrograms { */ + @Test + public void testMul8uMin() throws IOException, URISyntaxException { + compileAndCompare("mul8u-min"); + } + @Test public void testNumberInferenceSum() throws IOException, URISyntaxException { compileAndCompare("number-inference-sum"); diff --git a/src/test/kc/mul8u-min.kc b/src/test/kc/mul8u-min.kc new file mode 100644 index 000000000..83f0668cb --- /dev/null +++ b/src/test/kc/mul8u-min.kc @@ -0,0 +1,14 @@ +// Minimal test of mul8u + +import "multiply" + +void main() { + + const word* screen = 0x0400; + byte i = 0; + + for(byte a: 0..5) + for (byte b: 0..5) + screen[i++] = mul8u(a,b); + +} \ No newline at end of file diff --git a/src/test/ref/bresenhamarr.asm b/src/test/ref/bresenhamarr.asm index 6f5b47054..27134b6fd 100644 --- a/src/test/ref/bresenhamarr.asm +++ b/src/test/ref/bresenhamarr.asm @@ -19,7 +19,7 @@ main: { ldx #yd/2 lda #x0 sta x - lda #<0 + lda #0 sta idx sta idx+1 b1: diff --git a/src/test/ref/c64dtv-8bppchunkystretch.asm b/src/test/ref/c64dtv-8bppchunkystretch.asm index 350dbd2a5..5d6615f06 100644 --- a/src/test/ref/c64dtv-8bppchunkystretch.asm +++ b/src/test/ref/c64dtv-8bppchunkystretch.asm @@ -205,7 +205,7 @@ gfx_init_chunky: { lda #>$4000 sta gfxb+1 b1: - lda #<0 + lda #0 sta x sta x+1 b2: diff --git a/src/test/ref/c64dtv-blittermin.asm b/src/test/ref/c64dtv-blittermin.asm index b7e126dea..0628deace 100644 --- a/src/test/ref/c64dtv-blittermin.asm +++ b/src/test/ref/c64dtv-blittermin.asm @@ -85,9 +85,8 @@ main: { sta DTV_BLITTER_SRCA_HI sta DTV_BLITTER_SRCA_MOD_LO sta DTV_BLITTER_SRCA_MOD_HI - lda #<$80 sta DTV_BLITTER_SRCA_LIN_LO - lda #0 + lda #>$100 sta DTV_BLITTER_SRCA_LIN_HI lda #$10 sta DTV_BLITTER_SRCA_STEP diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm index 5787e8dbe..2ffbfb4d9 100644 --- a/src/test/ref/complex/tetris/tetris.asm +++ b/src/test/ref/complex/tetris/tetris.asm @@ -214,11 +214,8 @@ main: { sta level sta score_bcd sta score_bcd+1 - lda #<0>>$10 sta score_bcd+2 - lda #>0>>$10 sta score_bcd+3 - lda #<0 sta lines_bcd sta lines_bcd+1 sta current_movedown_counter diff --git a/src/test/ref/derefidx-word-0.asm b/src/test/ref/derefidx-word-0.asm index a893d8fe3..95ea7045b 100644 --- a/src/test/ref/derefidx-word-0.asm +++ b/src/test/ref/derefidx-word-0.asm @@ -6,7 +6,7 @@ main: { .label screen = $400 .label i = 2 .label _1 = 4 - lda #<0 + lda #0 sta i sta i+1 b1: diff --git a/src/test/ref/examples/3d/perspective.asm b/src/test/ref/examples/3d/perspective.asm index db564e9c2..313e08cfb 100644 --- a/src/test/ref/examples/3d/perspective.asm +++ b/src/test/ref/examples/3d/perspective.asm @@ -240,9 +240,9 @@ mulf_init: { .label val = 6 .label sqr = 2 .label add = 4 - lda #<1 + lda #1 sta add - lda #>1 + lda #0 sta add+1 tax sta sqr diff --git a/src/test/ref/examples/chargen/chargen-analysis.asm b/src/test/ref/examples/chargen/chargen-analysis.asm index 9a4f94c32..3acea7f3d 100644 --- a/src/test/ref/examples/chargen/chargen-analysis.asm +++ b/src/test/ref/examples/chargen/chargen-analysis.asm @@ -312,11 +312,10 @@ mul8u: { .label mb = $b .label res = 9 .label return = 9 - lda #<b + lda #b sta mb - lda #>b + lda #0 sta mb+1 - lda #<0 sta res sta res+1 b1: diff --git a/src/test/ref/examples/fire/fire.asm b/src/test/ref/examples/fire/fire.asm index e6481db83..d14cf06e3 100644 --- a/src/test/ref/examples/fire/fire.asm +++ b/src/test/ref/examples/fire/fire.asm @@ -307,7 +307,7 @@ sid_rnd_init: { fillscreen: { .label screen = 2 .label i = 4 - lda #<0 + lda #0 sta i sta i+1 b1: diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm index 0b59051e7..c581edf00 100644 --- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm +++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm @@ -219,11 +219,11 @@ init: { lda #VIC_DEN|VIC_RSEL|3 sta D011 jsr plexInit - lda #<$20 + lda #$20 sta xp - lda #>$20 + lda #0 sta xp+1 - ldx #0 + tax b1: lda #SPRITE/$40 sta PLEX_PTR,x diff --git a/src/test/ref/examples/plasma/plasma-unroll.asm b/src/test/ref/examples/plasma/plasma-unroll.asm index 761f2a967..6ac675a5a 100644 --- a/src/test/ref/examples/plasma/plasma-unroll.asm +++ b/src/test/ref/examples/plasma/plasma-unroll.asm @@ -254,7 +254,7 @@ makecharset: { sta print_char_cursor lda #>print_line_cursor sta print_char_cursor+1 - lda #<0 + lda #0 sta c sta c+1 b1: diff --git a/src/test/ref/examples/plasma/plasma.asm b/src/test/ref/examples/plasma/plasma.asm index f0b03b983..5bdbc6470 100644 --- a/src/test/ref/examples/plasma/plasma.asm +++ b/src/test/ref/examples/plasma/plasma.asm @@ -190,7 +190,7 @@ makecharset: { sta print_char_cursor lda #>print_line_cursor sta print_char_cursor+1 - lda #<0 + lda #0 sta c sta c+1 b1: diff --git a/src/test/ref/examples/rotate/rotate.asm b/src/test/ref/examples/rotate/rotate.asm index 89dbfc313..21947b062 100644 --- a/src/test/ref/examples/rotate/rotate.asm +++ b/src/test/ref/examples/rotate/rotate.asm @@ -258,7 +258,7 @@ mulf_init: { sta sqr1_lo lda #>mulf_sqr1_lo+1 sta sqr1_lo+1 - lda #<0 + lda #0 sta sqr sta sqr+1 tax diff --git a/src/test/ref/examples/scrolllogo/scrolllogo.asm b/src/test/ref/examples/scrolllogo/scrolllogo.asm index bd40df77b..46983d01e 100644 --- a/src/test/ref/examples/scrolllogo/scrolllogo.asm +++ b/src/test/ref/examples/scrolllogo/scrolllogo.asm @@ -68,7 +68,7 @@ loop: { .label _1 = 9 .label _5 = 9 .label xpos = 9 - lda #<0 + lda #0 sta xsin_idx sta xsin_idx+1 b1: @@ -109,7 +109,7 @@ loop: { lda xsin_idx cmp #<XSIN_SIZE bne b4 - lda #<0 + lda #0 sta xsin_idx sta xsin_idx+1 b4: @@ -260,19 +260,17 @@ sin16s_gen2: { .label x = 5 .label i = 9 jsr div32u16u - lda #<0 + lda #0 sta i sta i+1 lda #<xsin sta sintab lda #>xsin sta sintab+1 - lda #<0 + lda #0 sta x sta x+1 - lda #<0>>$10 sta x+2 - lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -332,13 +330,13 @@ sin16s_gen2: { } // Multiply of two signed words to a signed double word // Fixes offsets introduced by using unsigned multiplication -// mul16s(signed word zeropage($15) a) +// mul16s(signed word zeropage($f) a) mul16s: { .label _9 = $f .label _16 = $f .label m = $b .label return = $b - .label a = $15 + .label a = $f lda a sta mul16u.a lda a+1 @@ -373,19 +371,17 @@ mul16s: { rts } // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word -// mul16u(word zeropage($f) a, word zeropage($17) b) +// mul16u(word zeropage($11) a, word zeropage($f) b) mul16u: { - .label mb = $11 - .label a = $f + .label mb = $13 + .label a = $11 .label res = $b .label return = $b - .label b = $17 - lda #<0 + .label b = $f + lda #0 sta res sta res+1 - lda #<0>>$10 sta res+2 - lda #>0>>$10 sta res+3 b1: lda a @@ -427,18 +423,18 @@ mul16u: { // sin16s(dword zeropage($b) x) sin16s: { .label _4 = $b - .label _20 = $15 + .label _20 = $f .label x = $b - .label return = $15 + .label return = $f .label x1 = $1d - .label x2 = $15 - .label x3 = $15 + .label x2 = $17 + .label x3 = $17 .label x3_6 = $f .label usinx = $1f - .label x4 = $15 + .label x4 = $17 .label x5 = $f .label x5_128 = $f - .label sinx = $15 + .label sinx = $f .label isUpper = 4 lda x+3 cmp #>PI_u4f28>>$10 @@ -609,15 +605,15 @@ sin16s: { } // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result. // The select parameter indicates how many of the highest bits of the 32-bit result to skip -// mulu16_sel(word zeropage($15) v1, word zeropage($17) v2, byte register(X) select) +// mulu16_sel(word zeropage($17) v1, word zeropage($f) v2, byte register(X) select) mulu16_sel: { .label _0 = $b .label _1 = $b - .label v1 = $15 - .label v2 = $17 + .label v1 = $17 + .label v2 = $f .label return = $f - .label return_1 = $15 - .label return_10 = $15 + .label return_1 = $17 + .label return_10 = $17 lda v1 sta mul16u.a lda v1+1 @@ -649,14 +645,14 @@ mulu16_sel: { // Divide unsigned 32-bit dword dividend with a 16-bit word divisor // The 16-bit word remainder can be found in rem16u after the division div32u16u: { - .label quotient_hi = $15 + .label quotient_hi = $11 .label quotient_lo = $f .label return = $19 lda #<PI2_u4f28>>$10 sta divr16u.dividend lda #>PI2_u4f28>>$10 sta divr16u.dividend+1 - lda #<0 + lda #0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u diff --git a/src/test/ref/examples/sinplotter/sine-plotter.asm b/src/test/ref/examples/sinplotter/sine-plotter.asm index 951d02189..341d95d20 100644 --- a/src/test/ref/examples/sinplotter/sine-plotter.asm +++ b/src/test/ref/examples/sinplotter/sine-plotter.asm @@ -73,7 +73,7 @@ render_sine: { .label sin2_val = 6 .label xpos = 4 .label sin_idx = 2 - lda #<0 + lda #0 sta xpos sta xpos+1 sta sin_idx @@ -149,7 +149,7 @@ render_sine: { lda xpos cmp #<$140 bne b2 - lda #<0 + lda #0 sta xpos sta xpos+1 b2: @@ -174,9 +174,9 @@ render_sine: { // Plot a single dot in the bitmap // bitmap_plot(word zeropage(4) x, byte register(X) y) bitmap_plot: { - .label _1 = $15 + .label _1 = $10 .label plotter = 6 - .label plotter_1 = $15 + .label plotter_1 = $10 .label x = 4 .label _4 = 6 lda bitmap_plot_yhi,x @@ -256,19 +256,17 @@ sin16s_gen2: { .label x = 8 .label i = 4 jsr div32u16u - lda #<0 + lda #0 sta i sta i+1 lda #<sin sta sintab lda #>sin sta sintab+1 - lda #<0 + lda #0 sta x sta x+1 - lda #<0>>$10 sta x+2 - lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -328,13 +326,13 @@ sin16s_gen2: { } // Multiply of two signed words to a signed double word // Fixes offsets introduced by using unsigned multiplication -// mul16s(signed word zeropage($15) a) +// mul16s(signed word zeropage(6) a) mul16s: { .label _9 = 6 .label _16 = 6 .label m = $c .label return = $c - .label a = $15 + .label a = 6 lda a sta mul16u.a lda a+1 @@ -369,19 +367,17 @@ mul16s: { rts } // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word -// mul16u(word zeropage(6) a, word zeropage($17) b) +// mul16u(word zeropage($10) a, word zeropage(6) b) mul16u: { - .label mb = $10 - .label a = 6 + .label mb = $12 + .label a = $10 .label res = $c .label return = $c - .label b = $17 - lda #<0 + .label b = 6 + lda #0 sta res sta res+1 - lda #<0>>$10 sta res+2 - lda #>0>>$10 sta res+3 b1: lda a @@ -423,19 +419,19 @@ mul16u: { // sin16s(dword zeropage($c) x) sin16s: { .label _4 = $c - .label _20 = $15 + .label _20 = 6 .label x = $c - .label return = $15 + .label return = 6 .label x1 = $1d - .label x2 = $15 - .label x3 = $15 + .label x2 = $17 + .label x3 = $17 .label x3_6 = 6 .label usinx = $1f - .label x4 = $15 + .label x4 = $17 .label x5 = 6 .label x5_128 = 6 - .label sinx = $15 - .label isUpper = $14 + .label sinx = 6 + .label isUpper = $16 lda x+3 cmp #>PI_u4f28>>$10 bcc b4 @@ -605,15 +601,15 @@ sin16s: { } // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result. // The select parameter indicates how many of the highest bits of the 32-bit result to skip -// mulu16_sel(word zeropage($15) v1, word zeropage($17) v2, byte register(X) select) +// mulu16_sel(word zeropage($17) v1, word zeropage(6) v2, byte register(X) select) mulu16_sel: { .label _0 = $c .label _1 = $c - .label v1 = $15 - .label v2 = $17 + .label v1 = $17 + .label v2 = 6 .label return = 6 - .label return_1 = $15 - .label return_10 = $15 + .label return_1 = $17 + .label return_10 = $17 lda v1 sta mul16u.a lda v1+1 @@ -645,14 +641,14 @@ mulu16_sel: { // Divide unsigned 32-bit dword dividend with a 16-bit word divisor // The 16-bit word remainder can be found in rem16u after the division div32u16u: { - .label quotient_hi = $15 + .label quotient_hi = $10 .label quotient_lo = 6 .label return = $19 lda #<PI2_u4f28>>$10 sta divr16u.dividend lda #>PI2_u4f28>>$10 sta divr16u.dividend+1 - lda #<0 + lda #0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u @@ -732,7 +728,7 @@ divr16u: { // Clear all graphics on the bitmap bitmap_clear: { .label bitmap = 2 - .label y = $14 + .label y = $16 .label _4 = 2 lda bitmap_plot_ylo sta _4 @@ -761,7 +757,7 @@ bitmap_clear: { } // Initialize bitmap plotting tables bitmap_init: { - .label _3 = $14 + .label _3 = $16 .label yoffs = 2 ldx #0 lda #$80 diff --git a/src/test/ref/examples/sinsprites/sinus-sprites.asm b/src/test/ref/examples/sinsprites/sinus-sprites.asm index 81a9c2d21..eddb6422e 100644 --- a/src/test/ref/examples/sinsprites/sinus-sprites.asm +++ b/src/test/ref/examples/sinsprites/sinus-sprites.asm @@ -228,9 +228,9 @@ gen_sintab: { lda #>f_amp sta setMEMtoFAC.mem+1 jsr setMEMtoFAC - lda #<2 + lda #2 sta setFAC.w - lda #>2 + lda #0 sta setFAC.w+1 jsr setFAC lda #<f_amp diff --git a/src/test/ref/forrangedwords.asm b/src/test/ref/forrangedwords.asm index 60b793ab1..8716f7084 100644 --- a/src/test/ref/forrangedwords.asm +++ b/src/test/ref/forrangedwords.asm @@ -5,7 +5,7 @@ main: { .label SCREEN = $400 .label w = 2 .label sw = 2 - lda #<0 + lda #0 sta w sta w+1 b1: diff --git a/src/test/ref/fragment-variations.asm b/src/test/ref/fragment-variations.asm index 451bee711..4fea75dc1 100644 --- a/src/test/ref/fragment-variations.asm +++ b/src/test/ref/fragment-variations.asm @@ -8,17 +8,15 @@ main: { .label screen = $400 .label _0 = 2 .label _1 = 2 - lda #<$a + lda #$a sta mul16u.a - lda #>$a + lda #0 sta mul16u.a+1 - lda #<$a + lda #$a sta mul16u.mb - lda #>$a + lda #0 sta mul16u.mb+1 - lda #<$a>>$10 sta mul16u.mb+2 - lda #>$a>>$10 sta mul16u.mb+3 jsr mul16u lda _0 diff --git a/src/test/ref/linegen.asm b/src/test/ref/linegen.asm index 825a7fc29..4cbd79681 100644 --- a/src/test/ref/linegen.asm +++ b/src/test/ref/linegen.asm @@ -38,7 +38,7 @@ main: { sta lin16u_gen.lintab lda #>lintab3 sta lin16u_gen.lintab+1 - lda #<0 + lda #0 sta lin16u_gen.min sta lin16u_gen.min+1 lda #<$6488 @@ -76,7 +76,7 @@ main: { lda #>str1 sta print_str.str+1 jsr print_str - lda #<0 + lda #0 sta print_word.w sta print_word.w+1 jsr print_word @@ -309,11 +309,10 @@ lin16u_gen: { lda ampl+1 sbc min+1 sta ampl+1 - lda #<$14-1 + lda #$14-1 sta divr16u.divisor - lda #>$14-1 + lda #0 sta divr16u.divisor+1 - lda #<0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u @@ -321,11 +320,10 @@ lin16u_gen: { sta stepi lda divr16u.return+1 sta stepi+1 - lda #<$14-1 + lda #$14-1 sta divr16u.divisor - lda #>$14-1 + lda #0 sta divr16u.divisor+1 - lda #<0 sta divr16u.dividend sta divr16u.dividend+1 jsr divr16u @@ -344,7 +342,7 @@ lin16u_gen: { sta val+2 lda min+1 sta val+3 - lda #<0 + lda #0 sta i sta i+1 b1: diff --git a/src/test/ref/liverange-call-problem.asm b/src/test/ref/liverange-call-problem.asm index 933c49ae1..ff5e1ea3d 100644 --- a/src/test/ref/liverange-call-problem.asm +++ b/src/test/ref/liverange-call-problem.asm @@ -8,11 +8,11 @@ .label w2 = 2 main: { .label SCREEN = $400 - lda #<0 + lda #0 sta w1 sta w1+1 jsr incw1 - lda #<0 + lda #0 sta w2 sta w2+1 jsr incw2 diff --git a/src/test/ref/min-fmul-16.asm b/src/test/ref/min-fmul-16.asm index ef4553748..dc431ade4 100644 --- a/src/test/ref/min-fmul-16.asm +++ b/src/test/ref/min-fmul-16.asm @@ -226,7 +226,7 @@ mulf_init: { sta sqr1_lo lda #>mulf_sqr1_lo+1 sta sqr1_lo+1 - lda #<0 + lda #0 sta sqr sta sqr+1 tax diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm index f9d6d5695..8b97b383b 100644 --- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm +++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm @@ -167,11 +167,11 @@ init: { lda #VIC_DEN|VIC_RSEL|3 sta D011 jsr plexInit - lda #<$20 + lda #$20 sta xp - lda #>$20 + lda #0 sta xp+1 - ldx #0 + tax b1: lda #SPRITE/$40 sta PLEX_PTR,x diff --git a/src/test/ref/roll-sprite-msb.asm b/src/test/ref/roll-sprite-msb.asm index 18ab37b56..80b22ddde 100644 --- a/src/test/ref/roll-sprite-msb.asm +++ b/src/test/ref/roll-sprite-msb.asm @@ -7,11 +7,11 @@ .label SPRITES_XMSB = $d010 main: { .label xpos = 2 - lda #<$c8 + lda #$c8 sta xpos - lda #>$c8 + lda #0 sta xpos+1 - ldx #0 + tax b1: stx position_sprite.spriteno jsr position_sprite diff --git a/src/test/ref/scan-desire-problem.asm b/src/test/ref/scan-desire-problem.asm index 377b83bf5..2cd3d41b5 100644 --- a/src/test/ref/scan-desire-problem.asm +++ b/src/test/ref/scan-desire-problem.asm @@ -76,6 +76,7 @@ draw_block: { asl sta x1 lda #0 + rol sta x1+1 txa asl @@ -172,11 +173,10 @@ mul8u: { .label mb = 6 .label res = 4 .label return = 4 - lda #<b + lda #b sta mb - lda #>b + lda #0 sta mb+1 - lda #<0 sta res sta res+1 b1: diff --git a/src/test/ref/semi-struct-2.asm b/src/test/ref/semi-struct-2.asm index d54d7ac9c..0429bcc2f 100644 --- a/src/test/ref/semi-struct-2.asm +++ b/src/test/ref/semi-struct-2.asm @@ -730,11 +730,10 @@ mul8u: { .label mb = 2 .label res = 8 .label return = 8 - lda #<SIZEOF_ENTRY + lda #SIZEOF_ENTRY sta mb - lda #>SIZEOF_ENTRY + lda #0 sta mb+1 - lda #<0 sta res sta res+1 b1: diff --git a/src/test/ref/signed-words.asm b/src/test/ref/signed-words.asm index 9a92c64eb..1f3826b81 100644 --- a/src/test/ref/signed-words.asm +++ b/src/test/ref/signed-words.asm @@ -25,22 +25,22 @@ .label yvel_22 = 6 main: { jsr init - lda #<$64 + lda #$64 sta yvel_init - lda #>$64 + lda #0 sta yvel_init+1 lda #<$c8 sta xvel lda #>$c8 sta xvel+1 - lda #<0 + lda #0 sta ypos sta ypos+1 sta xpos sta xpos+1 - lda #<$64 + lda #$64 sta yvel_12 - lda #>$64 + lda #0 sta yvel_12+1 b1: lda #$ff @@ -96,7 +96,7 @@ anim: { sta yvel_22 lda yvel+1 sta yvel_22+1 - lda #<0 + lda #0 sta ypos sta ypos+1 sta xpos diff --git a/src/test/ref/sinus-basic.asm b/src/test/ref/sinus-basic.asm index 9e8385227..bf19ef5b9 100644 --- a/src/test/ref/sinus-basic.asm +++ b/src/test/ref/sinus-basic.asm @@ -46,9 +46,9 @@ main: { lda #>f_i sta setMEMtoFAC.mem+1 jsr setMEMtoFAC - lda #<$19 + lda #$19 sta setFAC.w - lda #>$19 + lda #0 sta setFAC.w+1 jsr setFAC jsr divMEMbyFAC diff --git a/src/test/ref/sinusgen16.asm b/src/test/ref/sinusgen16.asm index 380d92e7c..bdca50e5c 100644 --- a/src/test/ref/sinusgen16.asm +++ b/src/test/ref/sinusgen16.asm @@ -185,19 +185,17 @@ sin16s_gen: { .label x = $a .label i = 4 jsr div32u16u - lda #<0 + lda #0 sta i sta i+1 lda #<main.sintab1 sta sintab lda #>main.sintab1 sta sintab+1 - lda #<0 + lda #0 sta x sta x+1 - lda #<0>>$10 sta x+2 - lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -485,9 +483,7 @@ mul16u: { sta mb+3 sta res sta res+1 - lda #<0>>$10 sta res+2 - lda #>0>>$10 sta res+3 b1: lda a @@ -533,7 +529,7 @@ div32u16u: { sta divr16u.dividend lda #>PI2_u4f28>>$10 sta divr16u.dividend+1 - lda #<0 + lda #0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u diff --git a/src/test/ref/sinusgen16b.asm b/src/test/ref/sinusgen16b.asm index b5f324cfa..299b22494 100644 --- a/src/test/ref/sinusgen16b.asm +++ b/src/test/ref/sinusgen16b.asm @@ -204,19 +204,17 @@ sin16s_genb: { .label x = $d .label i = 4 jsr div32u16u - lda #<0 + lda #0 sta i sta i+1 lda #<main.sintab2 sta sintab lda #>main.sintab2 sta sintab+1 - lda #<0 + lda #0 sta x sta x+1 - lda #<0>>$10 sta x+2 - lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -469,9 +467,7 @@ mul16u: { sta mb+3 sta res sta res+1 - lda #<0>>$10 sta res+2 - lda #>0>>$10 sta res+3 b1: lda a @@ -517,7 +513,7 @@ div32u16u: { sta divr16u.dividend lda #>PI2_u4f28>>$10 sta divr16u.dividend+1 - lda #<0 + lda #0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u @@ -605,19 +601,17 @@ sin16s_gen: { .label x = $d .label i = 4 jsr div32u16u - lda #<0 + lda #0 sta i sta i+1 lda #<main.sintab1 sta sintab lda #>main.sintab1 sta sintab+1 - lda #<0 + lda #0 sta x sta x+1 - lda #<0>>$10 sta x+2 - lda #>0>>$10 sta x+3 // u[4.28] b1: diff --git a/src/test/ref/sinusgen8.asm b/src/test/ref/sinusgen8.asm index 0c037f3c0..5e117690a 100644 --- a/src/test/ref/sinusgen8.asm +++ b/src/test/ref/sinusgen8.asm @@ -158,14 +158,14 @@ sin8s_gen: { .label x = 2 .label i = 7 jsr div16u - lda #<0 + lda #0 sta i sta i+1 lda #<main.sintab2 sta sintab lda #>main.sintab2 sta sintab+1 - lda #<0 + lda #0 sta x sta x+1 // u[4.12] diff --git a/src/test/ref/sinusgen8b.asm b/src/test/ref/sinusgen8b.asm index e9cafe49a..67172c57e 100644 --- a/src/test/ref/sinusgen8b.asm +++ b/src/test/ref/sinusgen8b.asm @@ -181,19 +181,17 @@ sin16s_gen: { .label x = 7 .label i = 5 jsr div32u16u - lda #<0 + lda #0 sta i sta i+1 lda #<main.sintabw sta sintab lda #>main.sintabw sta sintab+1 - lda #<0 + lda #0 sta x sta x+1 - lda #<0>>$10 sta x+2 - lda #>0>>$10 sta x+3 // u[4.28] b1: @@ -481,9 +479,7 @@ mul16u: { sta mb+3 sta res sta res+1 - lda #<0>>$10 sta res+2 - lda #>0>>$10 sta res+3 b1: lda a @@ -529,7 +525,7 @@ div32u16u: { sta divr16u.dividend lda #>PI2_u4f28>>$10 sta divr16u.dividend+1 - lda #<0 + lda #0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u @@ -616,14 +612,14 @@ sin8s_gen: { .label x = 2 .label i = $11 jsr div16u - lda #<0 + lda #0 sta i sta i+1 lda #<main.sintabb sta sintab lda #>main.sintabb sta sintab+1 - lda #<0 + lda #0 sta x sta x+1 // u[4.12] @@ -839,7 +835,7 @@ div16u: { sta divr16u.dividend lda #>PI2_u4f12 sta divr16u.dividend+1 - lda #<0 + lda #0 sta divr16u.rem sta divr16u.rem+1 jsr divr16u diff --git a/src/test/ref/sinusgenscale8.asm b/src/test/ref/sinusgenscale8.asm index 792e19135..ba40b7df7 100644 --- a/src/test/ref/sinusgenscale8.asm +++ b/src/test/ref/sinusgenscale8.asm @@ -86,14 +86,14 @@ sin8u_table: { lda #>$400 sta print_line_cursor+1 jsr print_ln - lda #<0 + lda #0 sta i sta i+1 lda #<main.sintab sta sintab lda #>main.sintab sta sintab+1 - lda #<0 + lda #0 sta x sta x+1 // u[4.12] @@ -326,9 +326,9 @@ mul8su: { .label return = $f tya tax - lda #<b + lda #b sta mul8u.mb - lda #>b + lda #0 sta mul8u.mb+1 jsr mul8u cpy #0 @@ -346,7 +346,7 @@ mul8u: { .label mb = $b .label res = $f .label return = $f - lda #<0 + lda #0 sta res sta res+1 b1: diff --git a/src/test/ref/test-multiply-16bit.asm b/src/test/ref/test-multiply-16bit.asm index e9858cdce..4b1b9e166 100644 --- a/src/test/ref/test-multiply-16bit.asm +++ b/src/test/ref/test-multiply-16bit.asm @@ -601,20 +601,18 @@ mul16s: { rts } // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word -// mul16u(word zeropage(9) a, word zeropage($15) b) +// mul16u(word zeropage($1d) a, word zeropage(9) b) mul16u: { .label mb = $11 - .label a = 9 + .label a = $1d .label res = $19 - .label b = $15 + .label b = 9 .label return = $19 .label b_1 = $17 - lda #<0 + lda #0 sta res sta res+1 - lda #<0>>$10 sta res+2 - lda #>0>>$10 sta res+3 b1: lda a @@ -667,14 +665,12 @@ muls16s: { lda a beq b5 !: - lda #<0 + lda #0 sta j sta j+1 sta m sta m+1 - lda #<0>>$10 sta m+2 - lda #>0>>$10 sta m+3 b3: lda b+1 @@ -708,23 +704,19 @@ muls16s: { bne b3 rts b5: - lda #<0 + lda #0 sta return sta return+1 - lda #<0>>$10 sta return+2 - lda #>0>>$10 sta return+3 rts b6: - lda #<0 + lda #0 sta i sta i+1 sta m sta m+1 - lda #<0>>$10 sta m+2 - lda #>0>>$10 sta m+3 b4: lda b+1 @@ -965,14 +957,12 @@ muls16u: { lda a+1 beq b3 !: - lda #<0 + lda #0 sta i sta i+1 sta m sta m+1 - lda #<0>>$10 sta m+2 - lda #>0>>$10 sta m+3 b2: lda m @@ -1000,12 +990,10 @@ muls16u: { bne b2 rts b3: - lda #<0 + lda #0 sta return sta return+1 - lda #<0>>$10 sta return+2 - lda #>0>>$10 sta return+3 rts } @@ -1028,7 +1016,7 @@ mulf_init: { sta sqr1_lo lda #>mulf_sqr1_lo+1 sta sqr1_lo+1 - lda #<0 + lda #0 sta sqr sta sqr+1 tax diff --git a/src/test/ref/test-multiply-8bit.asm b/src/test/ref/test-multiply-8bit.asm index 5cf013274..195dda466 100644 --- a/src/test/ref/test-multiply-8bit.asm +++ b/src/test/ref/test-multiply-8bit.asm @@ -307,7 +307,7 @@ mul8u: { .label mb = 6 .label res = $c .label return = $c - lda #<0 + lda #0 sta res sta res+1 b1: @@ -451,7 +451,7 @@ muls8s: { bne b3 rts b5: - lda #<0 + lda #0 sta return sta return+1 rts @@ -634,7 +634,7 @@ muls8u: { bne b2 rts b3: - lda #<0 + lda #0 sta return sta return+1 rts @@ -796,7 +796,7 @@ mulf_init: { sta sqr1_lo lda #>mulf_sqr1_lo+1 sta sqr1_lo+1 - lda #<0 + lda #0 sta sqr sta sqr+1 tax diff --git a/src/test/ref/test-scroll-up.asm b/src/test/ref/test-scroll-up.asm index 3f11d2fd0..15c85f776 100644 --- a/src/test/ref/test-scroll-up.asm +++ b/src/test/ref/test-scroll-up.asm @@ -17,7 +17,7 @@ scrollup3: { .label _4 = 7 .label _5 = 9 .label l2_4 = 4 - lda #<0 + lda #0 sta l2 sta l2+1 b1: @@ -111,7 +111,7 @@ scrollup1: { .label line = 2 .label _6 = 7 .label _7 = 4 - lda #<0 + lda #0 sta line sta line+1 b1: diff --git a/src/test/ref/test-word-size-arrays.asm b/src/test/ref/test-word-size-arrays.asm index 7a768dfdd..34f29fa59 100644 --- a/src/test/ref/test-word-size-arrays.asm +++ b/src/test/ref/test-word-size-arrays.asm @@ -10,7 +10,7 @@ main: { .label _8 = 6 .label _9 = 4 .label _10 = 4 - lda #<0 + lda #0 sta line sta line+1 b1: From fa6e54fb876dcb68af5ec25826e178052641669e Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sat, 18 May 2019 23:58:24 +0200 Subject: [PATCH 47/93] Added test ref --- src/test/ref/mul8u-min.asm | 70 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/test/ref/mul8u-min.asm diff --git a/src/test/ref/mul8u-min.asm b/src/test/ref/mul8u-min.asm new file mode 100644 index 000000000..88d7cb90b --- /dev/null +++ b/src/test/ref/mul8u-min.asm @@ -0,0 +1,70 @@ +// Minimal test of mul8u +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + .label _0 = 4 + .label i = 3 + .label a = 2 + lda #0 + sta i + sta a + b1: + ldy #0 + b2: + ldx a + tya + jsr mul8u + lda i + asl + tax + lda _0 + sta screen,x + lda _0+1 + sta screen+1,x + inc i + iny + cpy #6 + bne b2 + inc a + lda #6 + cmp a + bne b1 + rts +} +// Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word +// mul8u(byte register(X) a, byte register(A) b) +mul8u: { + .label mb = 6 + .label res = 4 + .label return = 4 + sta mb + lda #0 + sta mb+1 + sta res + sta res+1 + b1: + cpx #0 + bne b2 + rts + b2: + txa + and #1 + cmp #0 + beq b3 + lda res + clc + adc mb + sta res + lda res+1 + adc mb+1 + sta res+1 + b3: + txa + lsr + tax + asl mb + rol mb+1 + jmp b1 +} From f31dc244b52e991a55cbc535c069104e4a14bb46 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 19 May 2019 00:07:52 +0200 Subject: [PATCH 48/93] fixed tests --- src/test/java/dk/camelot64/kickc/test/TestPrograms.java | 5 ----- src/test/kc/typemismatch.kc | 2 ++ src/test/kc/valuelist-error.kc | 5 ----- 3 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 src/test/kc/valuelist-error.kc diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index e0d216b07..bb0078a74 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -1831,11 +1831,6 @@ public class TestPrograms { assertError("invalid-consttype", "Constant variable has a non-matching type", false); } - @Test - public void testValueListError() throws IOException, URISyntaxException { - assertError("valuelist-error", "Value list not resolved to word constructor"); - } - @Test public void testArrayUninitialized() throws IOException, URISyntaxException { assertError("array-uninitialized", "Array has no declared size."); diff --git a/src/test/kc/typemismatch.kc b/src/test/kc/typemismatch.kc index d4d1f8b7c..d391e89a0 100644 --- a/src/test/kc/typemismatch.kc +++ b/src/test/kc/typemismatch.kc @@ -2,4 +2,6 @@ void main() { word w = 5000; byte b = w; + const byte* screen = 0x0400; + screen[0] = b; } \ No newline at end of file diff --git a/src/test/kc/valuelist-error.kc b/src/test/kc/valuelist-error.kc deleted file mode 100644 index 4463c8ebd..000000000 --- a/src/test/kc/valuelist-error.kc +++ /dev/null @@ -1,5 +0,0 @@ -void main() { - word w = { -1, -1}; - byte* screen = $400; - *screen = <w; -} \ No newline at end of file From 624687153869af255c021b53ebfe6a1887086c8b Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 19 May 2019 01:16:12 +0200 Subject: [PATCH 49/93] Fixed tests --- .../java/dk/camelot64/kickc/Compiler.java | 1 - .../kickc/model/types/SymbolTypeMulti.java | 137 ------------------ .../dk/camelot64/kickc/test/TestPrograms.java | 12 +- src/test/kc/sandbox.kc | 6 +- src/test/kc/ternary-inference.kc | 4 +- src/test/ref/sandbox.asm | 60 ++++---- src/test/ref/ternary-inference.asm | 24 +++ 7 files changed, 62 insertions(+), 182 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java create mode 100644 src/test/ref/ternary-inference.asm diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 4dc3c79f5..d7e23c9c2 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -323,7 +323,6 @@ public class Compiler { constantOptimizations.add(new PassNSimplifyConstantZero(program)); constantOptimizations.add(new PassNSimplifyExpressionWithZero(program)); - pass2Execute(constantOptimizations); } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java deleted file mode 100644 index 9c0b8924e..000000000 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java +++ /dev/null @@ -1,137 +0,0 @@ -package dk.camelot64.kickc.model.types; - -import java.util.Arrays; -import java.util.Collection; - -/** - * Symbol Type of an inline expression. Inline expressions can match multiple types depending on the actual value, - * eg. the value 27 matches both byte and signed byte (which can in turn be promoted to word/signed word, dword/signed dword), while the value -252 only matches signed word or signed dword. - */ -public class SymbolTypeMulti implements SymbolType { - - /** All numeric types. */ - public static final SymbolTypeMulti NUMERIC = new SymbolTypeMulti(Arrays.asList(BYTE, SBYTE, WORD, SWORD, DWORD, SDWORD)); - - /** - * All potential types for the inline constant. - */ - private Collection<SymbolType> types; - - public SymbolTypeMulti(Collection<SymbolType> types) { - this.types = types; - } - - public Collection<SymbolType> getTypes() { - return types; - } - - @Override - public int getSizeBytes() { - // Find the minimal sizeof - and return that - Integer size = null; - for(SymbolType type : types) { - if(size==null) { - size = type.getSizeBytes(); - } else if(size>type.getSizeBytes()) { - size = type.getSizeBytes(); - } - } - if(size==null) { - return -1; - } - return size; - } - - @Override - public String getTypeName() { - StringBuilder name = new StringBuilder(); - boolean first = true; - for(SymbolType type : types) { - if(first) { - first = false; - } else { - name.append("/"); - } - name.append(type); - } - return name.toString(); - } - - @Override - public boolean equals(Object o) { - if(this == o) { - return true; - } - if(o == null || getClass() != o.getClass()) { - return false; - } - SymbolTypeMulti that = (SymbolTypeMulti) o; - return types != null ? types.equals(that.types) : that.types == null; - } - - @Override - public int hashCode() { - return types != null ? types.hashCode() : 0; - } - - @Override - public String toString() { - return getTypeName(); - } - - /** - * Is unsigned byte one of the potential types - * - * @return true if unsigned byte is a potential type - */ - public boolean isByte() { - return types.contains(BYTE); - } - - /** - * Is signed byte one of the potential types - * - * @return true if signed byte is a potential type - */ - public boolean isSByte() { - return types.contains(SBYTE); - } - - /** - * Is unsigned word one of the potential types - * - * @return true if unsigned word is a potential type - */ - public boolean isWord() { - return types.contains(WORD); - } - - /** - * Is signed word one of the potential types - * - * @return true if signed word is a potential type - */ - public boolean isSWord() { - return types.contains(SWORD); - } - - /** - * Is unsigned dword one of the potential types - * - * @return true if unsigned dword is a potential type - */ - public boolean isDWord() { - return types.contains(DWORD); - } - - /** - * Is signed dword one of the potential types - * - * @return true if signed dword is a potential type - */ - public boolean isSDWord() { - return types.contains(SDWORD); - } - - -} diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index bb0078a74..0fc59583b 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,6 +63,12 @@ public class TestPrograms { */ + + @Test + public void testTernaryInference() throws IOException, URISyntaxException { + compileAndCompare("ternary-inference"); + } + @Test public void testMul8uMin() throws IOException, URISyntaxException { compileAndCompare("mul8u-min"); @@ -98,11 +104,6 @@ public class TestPrograms { compileAndCompare("derefidx-word-0"); } - @Test - public void testTernaryInference() throws IOException, URISyntaxException { - compileAndCompare("ternary-inference", log()); - } - @Test public void testFragmentVariations() throws IOException, URISyntaxException { compileAndCompare("fragment-variations"); @@ -188,7 +189,6 @@ public class TestPrograms { compileAndCompare("sandbox"); } - //@Test //public void testPointerCast3() throws IOException, URISyntaxException { // compileAndCompare("pointer-cast-3"); diff --git a/src/test/kc/sandbox.kc b/src/test/kc/sandbox.kc index 9cf4f4229..3ff3ae112 100644 --- a/src/test/kc/sandbox.kc +++ b/src/test/kc/sandbox.kc @@ -48,8 +48,10 @@ byte myprintf(byte *dst, byte *str, word w1, word w2, word w3) { if (bTrailing != 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = ' '; } else if (b == 'x' || b == 'X'){ // hex b = ((byte)w >> 4) & 0xF; - dst[bLen++] = (b < 10 ? '0' : 0x57) + b; // "('a' - 10)" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/184 [FIXED] - b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b; + dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b; + // "('a' - 10)" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/184 [FIXED] + // (b < 10 ? '0' : 0x57) not supported + b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b; } bFormat = 0; continue; diff --git a/src/test/kc/ternary-inference.kc b/src/test/kc/ternary-inference.kc index 47e22265d..4f6e29973 100644 --- a/src/test/kc/ternary-inference.kc +++ b/src/test/kc/ternary-inference.kc @@ -1,10 +1,8 @@ // Type inference into the ternary operator void main() { - const byte* screen = 0x400; for(byte i: 0..10) { - screen[i] = (i<5?0x57:'0')+i; + screen[i] = (i<5?0x57ub:'0')+i; } - } \ No newline at end of file diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm index 83029cccc..559fa3c11 100644 --- a/src/test/ref/sandbox.asm +++ b/src/test/ref/sandbox.asm @@ -152,11 +152,10 @@ Print: { } // myprintf(byte* zeropage(8) str, word zeropage(2) w1, word zeropage(4) w2, word zeropage(6) w3) myprintf: { - .label _17 = $12 .label str = 8 .label bDigits = $11 .label bLen = $10 - .label digit = $a + .label b = $a .label bArg = $b .label return = $10 .label w1 = 2 @@ -228,19 +227,13 @@ myprintf: { sta bFormat jmp b27 b26: - lda w+1 - sta _17+1 lda w - sta _17 - ldy #4 - !: - lsr _17+1 - ror _17 - dey - bne !- - lda _17 - and #$f - tax + lsr + lsr + lsr + lsr + ldx #$f + axs #0 cpx #$a bcc b8 lda #$57 @@ -255,8 +248,8 @@ myprintf: { sta strTemp,y iny lda w - and #$f - tax + ldx #$f + axs #0 cpx #$a bcc b10 lda #$57 @@ -277,35 +270,33 @@ myprintf: { lda w+1 sta utoa.value+1 jsr utoa - ldx #1 + lda #1 + sta b b12: - lda buf6,x + ldy b + lda buf6,y cmp #0 bne b13 lda bTrailing cmp #0 beq b39 b15: - lda #0 - sta digit + ldx #0 b19: - ldy digit - lda buf6,y + lda buf6,x ldy bLen sta strTemp,y inc bLen - inc digit - txa - cmp digit - beq !+ - bcs b19 - !: + inx + cpx b + bcc b19 lda bTrailing cmp #0 bne b40 jmp b22 b40: - cpx bDigits + lda b + cmp bDigits bcc b21 jmp b22 b21: @@ -314,11 +305,13 @@ myprintf: { sta strTemp,y inc bLen dec bDigits - cpx bDigits + lda b + cmp bDigits bcc b21 jmp b22 b39: - cpx bDigits + lda b + cmp bDigits bcc b16 jmp b15 b16: @@ -334,11 +327,12 @@ myprintf: { sta strTemp,y inc bLen dec bDigits - cpx bDigits + lda b + cmp bDigits bcc b16 jmp b15 b13: - inx + inc b jmp b12 b6: lda w diff --git a/src/test/ref/ternary-inference.asm b/src/test/ref/ternary-inference.asm new file mode 100644 index 000000000..90df7b35e --- /dev/null +++ b/src/test/ref/ternary-inference.asm @@ -0,0 +1,24 @@ +// Type inference into the ternary operator +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = $400 + ldx #0 + b1: + cpx #5 + bcc b2 + lda #'0' + jmp b3 + b2: + lda #$57 + b3: + stx $ff + clc + adc $ff + sta screen,x + inx + cpx #$b + bne b1 + rts +} From 2ec68d6fd5d71af6c5b5be7fb21beb91f6ea901e Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Sun, 19 May 2019 09:31:12 +0200 Subject: [PATCH 50/93] added hex2dec test --- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/hex2dec.kc | 56 ++++ src/test/ref/hex2dec.asm | 282 ++++++++++++++++++ 3 files changed, 343 insertions(+) create mode 100644 src/test/kc/hex2dec.kc create mode 100644 src/test/ref/hex2dec.asm diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 0fc59583b..c4a10ab7a 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -64,6 +64,11 @@ public class TestPrograms { */ + @Test + public void testHex2Dec() throws IOException, URISyntaxException { + compileAndCompare("hex2dec"); + } + @Test public void testTernaryInference() throws IOException, URISyntaxException { compileAndCompare("ternary-inference"); diff --git a/src/test/kc/hex2dec.kc b/src/test/kc/hex2dec.kc new file mode 100644 index 000000000..d1d838356 --- /dev/null +++ b/src/test/kc/hex2dec.kc @@ -0,0 +1,56 @@ +// Testing hex to decimal conversion + +const unsigned char *control = 0xd011; +const unsigned char *raster = 0xd012; +const unsigned char *bordercol = 0xd020; + +void main() { + asm { sei } + cls(); + while(true) { + do { + unsigned char rst = (*control&0x80)|(*raster>>1); + } while (rst!=0x30); + unsigned char *screen = 0x0400; + *bordercol = 1; + utoa(00000, screen); (*bordercol)++; screen += 40; + utoa(01234, screen); (*bordercol)++; screen += 40; + utoa(05678, screen); (*bordercol)++; screen += 40; + utoa(09999, screen); (*bordercol)++; screen += 40; + utoa(59999, screen); + *bordercol = 0; + } + +} + +void cls() { + unsigned char *screen = 0x0400; + for( unsigned char *sc: screen..screen+999) *sc=' '; +} + +unsigned char[] DIGITS = "0123456789abcdef"; +const unsigned char RADIX_BINARY = 2; +const unsigned char RADIX_OCTAL = 8; +const unsigned char RADIX_DECIMAL = 10; +const unsigned char RADIX_HEX = 16; + + + +// simple 'utoa' without using multiply or divide +unsigned int append(unsigned char *dst, unsigned int value, unsigned int sub){ + *dst = '0'; + unsigned int sub3 = sub*2+sub; + while (value >= sub3){ *dst += 3; value -= sub3; } + while (value >= sub){ ++*dst; value -= sub; } + return value; +} + +void utoa(unsigned int value, unsigned char *dst){ + unsigned char bStarted = 0; + if (bStarted == 1 || value >= 10000){ value = append(dst++, value, 10000); bStarted = 1; } + if (bStarted == 1 || value >= 1000){ value = append(dst++, value, 1000); bStarted = 1; } + if (bStarted == 1 || value >= 100){ value = append(dst++, value, 100); bStarted = 1; } + if (bStarted == 1 || value >= 10){ value = append(dst++, value, 10); bStarted = 1; } + *dst++ = '0' + (unsigned char) value; + *dst = 0; +} diff --git a/src/test/ref/hex2dec.asm b/src/test/ref/hex2dec.asm new file mode 100644 index 000000000..b080e5c44 --- /dev/null +++ b/src/test/ref/hex2dec.asm @@ -0,0 +1,282 @@ +// Testing hex to decimal conversion +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label control = $d011 + .label raster = $d012 + .label bordercol = $d020 +main: { + .label _1 = 8 + sei + jsr cls + b1: + lda #$80 + and control + sta _1 + lda raster + lsr + ora _1 + cmp #$30 + bne b1 + lda #1 + sta bordercol + lda #<$400 + sta utoa.dst + lda #>$400 + sta utoa.dst+1 + lda #0 + sta utoa.value + sta utoa.value+1 + jsr utoa + inc bordercol + lda #<$400+$28 + sta utoa.dst + lda #>$400+$28 + sta utoa.dst+1 + lda #<$4d2 + sta utoa.value + lda #>$4d2 + sta utoa.value+1 + jsr utoa + inc bordercol + lda #<$400+$28+$28 + sta utoa.dst + lda #>$400+$28+$28 + sta utoa.dst+1 + lda #<$162e + sta utoa.value + lda #>$162e + sta utoa.value+1 + jsr utoa + inc bordercol + lda #<$400+$28+$28+$28 + sta utoa.dst + lda #>$400+$28+$28+$28 + sta utoa.dst+1 + lda #<$270f + sta utoa.value + lda #>$270f + sta utoa.value+1 + jsr utoa + inc bordercol + lda #<$400+$28+$28+$28+$28 + sta utoa.dst + lda #>$400+$28+$28+$28+$28 + sta utoa.dst+1 + lda #<$ea5f + sta utoa.value + lda #>$ea5f + sta utoa.value+1 + jsr utoa + lda #0 + sta bordercol + jmp b1 +} +// utoa(word zeropage(2) value, byte* zeropage(4) dst) +utoa: { + .label value = 2 + .label dst = 4 + lda value+1 + cmp #>$2710 + bcc !+ + beq !b5+ + jmp b5 + !b5: + lda value + cmp #<$2710 + bcc !b5+ + jmp b5 + !b5: + !: + ldx #0 + b1: + cpx #1 + beq b6 + lda value+1 + cmp #>$3e8 + bcc !+ + bne b6 + lda value + cmp #<$3e8 + bcs b6 + !: + b2: + cpx #1 + beq b7 + lda value+1 + cmp #>$64 + bcc !+ + bne b7 + lda value + cmp #<$64 + bcs b7 + !: + b3: + cpx #1 + beq b8 + lda value+1 + cmp #>$a + bcc !+ + bne b8 + lda value + cmp #<$a + bcs b8 + !: + b4: + lda value + clc + adc #'0' + ldy #0 + sta (dst),y + inc dst + bne !+ + inc dst+1 + !: + lda #0 + tay + sta (dst),y + rts + b8: + lda #$a + sta append.sub + lda #0 + sta append.sub+1 + jsr append + inc dst + bne !+ + inc dst+1 + !: + jmp b4 + b7: + lda #$64 + sta append.sub + lda #0 + sta append.sub+1 + jsr append + inc dst + bne !+ + inc dst+1 + !: + ldx #1 + jmp b3 + b6: + lda #<$3e8 + sta append.sub + lda #>$3e8 + sta append.sub+1 + jsr append + inc dst + bne !+ + inc dst+1 + !: + ldx #1 + jmp b2 + b5: + lda #<$2710 + sta append.sub + lda #>$2710 + sta append.sub+1 + jsr append + inc dst + bne !+ + inc dst+1 + !: + ldx #1 + jmp b1 +} +// simple 'utoa' without using multiply or divide +// append(byte* zeropage(4) dst, word zeropage(2) value, word zeropage(6) sub) +append: { + .label _0 = 9 + .label sub3 = 9 + .label value = 2 + .label dst = 4 + .label return = 2 + .label sub = 6 + lda #'0' + ldy #0 + sta (dst),y + lda sub + asl + sta _0 + lda sub+1 + rol + sta _0+1 + lda sub3 + clc + adc sub + sta sub3 + lda sub3+1 + adc sub+1 + sta sub3+1 + b1: + lda sub3+1 + cmp value+1 + bne !+ + lda sub3 + cmp value + !: + bcc b2 + beq b2 + b3: + lda sub+1 + cmp value+1 + bne !+ + lda sub + cmp value + !: + bcc b4 + beq b4 + rts + b4: + ldy #0 + lda (dst),y + clc + adc #1 + sta (dst),y + lda value + sec + sbc sub + sta value + lda value+1 + sbc sub+1 + sta value+1 + jmp b3 + b2: + lda #3 + clc + ldy #0 + adc (dst),y + sta (dst),y + lda value + sec + sbc sub3 + sta value + lda value+1 + sbc sub3+1 + sta value+1 + jmp b1 +} +cls: { + .label screen = $400 + .label sc = 2 + lda #<screen + sta sc + lda #>screen + sta sc+1 + b1: + lda #' ' + ldy #0 + sta (sc),y + inc sc + bne !+ + inc sc+1 + !: + lda sc+1 + cmp #>screen+$3e7+1 + bne b1 + lda sc + cmp #<screen+$3e7+1 + bne b1 + rts +} From 9864995afb799046a72a13b4d28923b8a0b2615f Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Sun, 19 May 2019 21:17:39 +0200 Subject: [PATCH 51/93] Created utoa10 with smaller memory footprint. --- ...pwuc1_derefidx_vbuxx_le_vwuz1_then_la1.asm | 8 + ...pwuc1_derefidx_vbuyy_le_vwuz1_then_la1.asm | 8 + ...vwuz1=vwuz1_minus_pwuc1_derefidx_vbuxx.asm | 7 + ...vwuz1=vwuz1_minus_pwuc1_derefidx_vbuyy.asm | 7 + src/main/fragment/vwuz1_le_vwuz2_then_la1.asm | 2 +- src/test/kc/hex2dec.kc | 82 ++++- src/test/ref/hex2dec.asm | 305 +++++++----------- 7 files changed, 208 insertions(+), 211 deletions(-) create mode 100644 src/main/fragment/pwuc1_derefidx_vbuxx_le_vwuz1_then_la1.asm create mode 100644 src/main/fragment/pwuc1_derefidx_vbuyy_le_vwuz1_then_la1.asm create mode 100644 src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuxx.asm create mode 100644 src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuyy.asm diff --git a/src/main/fragment/pwuc1_derefidx_vbuxx_le_vwuz1_then_la1.asm b/src/main/fragment/pwuc1_derefidx_vbuxx_le_vwuz1_then_la1.asm new file mode 100644 index 000000000..ef873ab36 --- /dev/null +++ b/src/main/fragment/pwuc1_derefidx_vbuxx_le_vwuz1_then_la1.asm @@ -0,0 +1,8 @@ +lda {c1}+1,x +cmp {z1}+1 +bne !+ +lda {c1},x +cmp {z1} +beq {la1} +!: +bcc {la1} diff --git a/src/main/fragment/pwuc1_derefidx_vbuyy_le_vwuz1_then_la1.asm b/src/main/fragment/pwuc1_derefidx_vbuyy_le_vwuz1_then_la1.asm new file mode 100644 index 000000000..427b691bd --- /dev/null +++ b/src/main/fragment/pwuc1_derefidx_vbuyy_le_vwuz1_then_la1.asm @@ -0,0 +1,8 @@ +lda {c1}+1,y +cmp {z1}+1 +bne !+ +lda {c1},y +cmp {z1} +beq {la1} +!: +bcc {la1} diff --git a/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuxx.asm b/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuxx.asm new file mode 100644 index 000000000..0b9a494d5 --- /dev/null +++ b/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuxx.asm @@ -0,0 +1,7 @@ +sec +lda {z1} +sbc {c1},x +sta {z1} +lda {z1}+1 +sbc {c1}+1,x +sta {z1}+1 diff --git a/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuyy.asm b/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuyy.asm new file mode 100644 index 000000000..001c5e74d --- /dev/null +++ b/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuyy.asm @@ -0,0 +1,7 @@ +sec +lda {z1} +sbc {c1},y +sta {z1} +lda {z1}+1 +sbc {c1}+1,y +sta {z1}+1 diff --git a/src/main/fragment/vwuz1_le_vwuz2_then_la1.asm b/src/main/fragment/vwuz1_le_vwuz2_then_la1.asm index 54a02388d..cc7e71a71 100644 --- a/src/main/fragment/vwuz1_le_vwuz2_then_la1.asm +++ b/src/main/fragment/vwuz1_le_vwuz2_then_la1.asm @@ -3,6 +3,6 @@ cmp {z2}+1 bne !+ lda {z1} cmp {z2} +beq {la1} !: bcc {la1} -beq {la1} \ No newline at end of file diff --git a/src/test/kc/hex2dec.kc b/src/test/kc/hex2dec.kc index d1d838356..f27a6e7d4 100644 --- a/src/test/kc/hex2dec.kc +++ b/src/test/kc/hex2dec.kc @@ -13,12 +13,19 @@ void main() { } while (rst!=0x30); unsigned char *screen = 0x0400; *bordercol = 1; - utoa(00000, screen); (*bordercol)++; screen += 40; - utoa(01234, screen); (*bordercol)++; screen += 40; - utoa(05678, screen); (*bordercol)++; screen += 40; - utoa(09999, screen); (*bordercol)++; screen += 40; - utoa(59999, screen); + unsigned char time_start = *raster; + utoa10b(00000, screen); (*bordercol)++; screen += 40; + utoa10b(01234, screen); (*bordercol)++; screen += 40; + utoa10b(05678, screen); (*bordercol)++; screen += 40; + utoa10b(09999, screen); (*bordercol)++; screen += 40; + utoa10b(58888, screen); + unsigned char time_end = *raster; *bordercol = 0; + unsigned char time = time_end - time_start; + utoa10b((unsigned int)time, screen+80); + byte[] msg = "raster lines"; + for( byte i=0; msg[i]!=0; i++ ) (screen+80+3)[i] = msg[i]; + //for( byte* m="lines", s=screen+80+6 ;*m!=0;m++,s++) *s = *m; } } @@ -28,29 +35,70 @@ void cls() { for( unsigned char *sc: screen..screen+999) *sc=' '; } -unsigned char[] DIGITS = "0123456789abcdef"; const unsigned char RADIX_BINARY = 2; const unsigned char RADIX_OCTAL = 8; const unsigned char RADIX_DECIMAL = 10; const unsigned char RADIX_HEX = 16; - - // simple 'utoa' without using multiply or divide -unsigned int append(unsigned char *dst, unsigned int value, unsigned int sub){ - *dst = '0'; +unsigned int utoa_digit(unsigned char *dst, unsigned int value, unsigned int sub){ + unsigned char digit = 0; unsigned int sub3 = sub*2+sub; - while (value >= sub3){ *dst += 3; value -= sub3; } - while (value >= sub){ ++*dst; value -= sub; } + while (value >= sub3){ digit += 3; value -= sub3; } + while (value >= sub){ ++digit; value -= sub; } + *dst = DIGITS[digit]; return value; } void utoa(unsigned int value, unsigned char *dst){ unsigned char bStarted = 0; - if (bStarted == 1 || value >= 10000){ value = append(dst++, value, 10000); bStarted = 1; } - if (bStarted == 1 || value >= 1000){ value = append(dst++, value, 1000); bStarted = 1; } - if (bStarted == 1 || value >= 100){ value = append(dst++, value, 100); bStarted = 1; } - if (bStarted == 1 || value >= 10){ value = append(dst++, value, 10); bStarted = 1; } + if (bStarted == 1 || value >= 10000){ value = utoa_digit(dst++, value, 10000); bStarted = 1; } + if (bStarted == 1 || value >= 1000){ value = utoa_digit(dst++, value, 1000); bStarted = 1; } + if (bStarted == 1 || value >= 100){ value = utoa_digit(dst++, value, 100); bStarted = 1; } + if (bStarted == 1 || value >= 10){ value = utoa_digit(dst++, value, 10); bStarted = 1; } *dst++ = '0' + (unsigned char) value; - *dst = 0; + //*dst = 0; } + +unsigned char[] DIGITS = "0123456789abcdef"; +unsigned int[] SUB3 = { 30000, 3000, 300, 30 }; +unsigned int[] SUB1 = { 10000, 1000, 100, 10 }; + +// Simple decimal utoa() without using multiply or divide +void utoa10(unsigned int value, unsigned char* dst) { + unsigned char bStarted = 0; + for( unsigned char i: 0..3) { + unsigned char digit = 0; + unsigned int sub1 = SUB1[i]; + if(value>=sub1) { + unsigned int sub3 = SUB3[i]; + while(value>=sub3) { digit += 3; value -= sub3; bStarted = 1; } + while(value>=sub1) { digit += 1; value -= sub1; bStarted = 1; } + } + if(bStarted!=0) { + *dst++ = DIGITS[digit]; + } + } + *dst++ = DIGITS[(unsigned char) value]; + //*dst = 0; +} + +unsigned int[] SUB = { 30000, 10000, 3000, 1000, 300, 100, 30, 10 }; +unsigned char[] VAL = { 3, 1, 3, 1, 3, 1, 3, 1 }; + +// Decimal utoa() without using multiply or divide +void utoa10b(unsigned int value, unsigned char* dst) { + unsigned char bStarted = 0; + unsigned char digit = 0; + for( unsigned char i: 0..7) { + while(value>=SUB[i]) { digit += VAL[i]; value -= SUB[i]; bStarted = 1; } + if((i&1)!=0) { + if(bStarted!=0) { + *dst++ = DIGITS[digit]; + } + digit = 0; + } + } + *dst++ = DIGITS[(unsigned char) value]; + *dst = 0; +} \ No newline at end of file diff --git a/src/test/ref/hex2dec.asm b/src/test/ref/hex2dec.asm index b080e5c44..4fbbca239 100644 --- a/src/test/ref/hex2dec.asm +++ b/src/test/ref/hex2dec.asm @@ -6,7 +6,8 @@ .label raster = $d012 .label bordercol = $d020 main: { - .label _1 = 8 + .label _1 = 4 + .label time_start = 8 sei jsr cls b1: @@ -20,112 +21,129 @@ main: { bne b1 lda #1 sta bordercol + lda raster + sta time_start lda #<$400 - sta utoa.dst + sta utoa10b.dst lda #>$400 - sta utoa.dst+1 + sta utoa10b.dst+1 lda #0 - sta utoa.value - sta utoa.value+1 - jsr utoa + sta utoa10b.value + sta utoa10b.value+1 + jsr utoa10b inc bordercol lda #<$400+$28 - sta utoa.dst + sta utoa10b.dst lda #>$400+$28 - sta utoa.dst+1 + sta utoa10b.dst+1 lda #<$4d2 - sta utoa.value + sta utoa10b.value lda #>$4d2 - sta utoa.value+1 - jsr utoa + sta utoa10b.value+1 + jsr utoa10b inc bordercol lda #<$400+$28+$28 - sta utoa.dst + sta utoa10b.dst lda #>$400+$28+$28 - sta utoa.dst+1 + sta utoa10b.dst+1 lda #<$162e - sta utoa.value + sta utoa10b.value lda #>$162e - sta utoa.value+1 - jsr utoa + sta utoa10b.value+1 + jsr utoa10b inc bordercol lda #<$400+$28+$28+$28 - sta utoa.dst + sta utoa10b.dst lda #>$400+$28+$28+$28 - sta utoa.dst+1 + sta utoa10b.dst+1 lda #<$270f - sta utoa.value + sta utoa10b.value lda #>$270f - sta utoa.value+1 - jsr utoa + sta utoa10b.value+1 + jsr utoa10b inc bordercol lda #<$400+$28+$28+$28+$28 - sta utoa.dst + sta utoa10b.dst lda #>$400+$28+$28+$28+$28 - sta utoa.dst+1 - lda #<$ea5f - sta utoa.value - lda #>$ea5f - sta utoa.value+1 - jsr utoa + sta utoa10b.dst+1 + lda #<$e608 + sta utoa10b.value + lda #>$e608 + sta utoa10b.value+1 + jsr utoa10b + ldx raster lda #0 sta bordercol - jmp b1 -} -// utoa(word zeropage(2) value, byte* zeropage(4) dst) -utoa: { - .label value = 2 - .label dst = 4 - lda value+1 - cmp #>$2710 - bcc !+ - beq !b5+ - jmp b5 - !b5: - lda value - cmp #<$2710 - bcc !b5+ - jmp b5 - !b5: - !: + txa + sec + sbc time_start + sta utoa10b.value + lda #0 + sta utoa10b.value+1 + lda #<$400+$28+$28+$28+$28+$50 + sta utoa10b.dst + lda #>$400+$28+$28+$28+$28+$50 + sta utoa10b.dst+1 + jsr utoa10b ldx #0 - b1: - cpx #1 - beq b6 - lda value+1 - cmp #>$3e8 - bcc !+ - bne b6 - lda value - cmp #<$3e8 - bcs b6 - !: - b2: - cpx #1 - beq b7 - lda value+1 - cmp #>$64 - bcc !+ - bne b7 - lda value - cmp #<$64 - bcs b7 - !: b3: - cpx #1 - beq b8 - lda value+1 - cmp #>$a - bcc !+ - bne b8 - lda value - cmp #<$a - bcs b8 + lda msg,x + sta $400+$28+$28+$28+$28+$50+3,x + inx + lda msg,x + cmp #0 + bne b3 + jmp b1 + msg: .text "raster lines@" +} +// Decimal utoa() without using multiply or divide +// utoa10b(word zeropage(2) value, byte* zeropage(6) dst) +utoa10b: { + .label value = 2 + .label digit = 4 + .label dst = 6 + .label bStarted = 5 + lda #0 + sta bStarted + sta digit + tax + b1: + txa + asl + tay + lda SUB+1,y + cmp value+1 + bne !+ + lda SUB,y + cmp value + beq b2 !: - b4: + bcc b2 + txa + and #1 + cmp #0 + beq b6 + lda bStarted + cmp #0 + beq b7 + ldy digit + lda DIGITS,y + ldy #0 + sta (dst),y + inc dst + bne !+ + inc dst+1 + !: + b7: + lda #0 + sta digit + b6: + inx + cpx #8 + bne b1 lda value - clc - adc #'0' + tay + lda DIGITS,y ldy #0 sta (dst),y inc dst @@ -136,125 +154,23 @@ utoa: { tay sta (dst),y rts - b8: - lda #$a - sta append.sub - lda #0 - sta append.sub+1 - jsr append - inc dst - bne !+ - inc dst+1 - !: - jmp b4 - b7: - lda #$64 - sta append.sub - lda #0 - sta append.sub+1 - jsr append - inc dst - bne !+ - inc dst+1 - !: - ldx #1 - jmp b3 - b6: - lda #<$3e8 - sta append.sub - lda #>$3e8 - sta append.sub+1 - jsr append - inc dst - bne !+ - inc dst+1 - !: - ldx #1 - jmp b2 - b5: - lda #<$2710 - sta append.sub - lda #>$2710 - sta append.sub+1 - jsr append - inc dst - bne !+ - inc dst+1 - !: - ldx #1 - jmp b1 -} -// simple 'utoa' without using multiply or divide -// append(byte* zeropage(4) dst, word zeropage(2) value, word zeropage(6) sub) -append: { - .label _0 = 9 - .label sub3 = 9 - .label value = 2 - .label dst = 4 - .label return = 2 - .label sub = 6 - lda #'0' - ldy #0 - sta (dst),y - lda sub - asl - sta _0 - lda sub+1 - rol - sta _0+1 - lda sub3 - clc - adc sub - sta sub3 - lda sub3+1 - adc sub+1 - sta sub3+1 - b1: - lda sub3+1 - cmp value+1 - bne !+ - lda sub3 - cmp value - !: - bcc b2 - beq b2 - b3: - lda sub+1 - cmp value+1 - bne !+ - lda sub - cmp value - !: - bcc b4 - beq b4 - rts - b4: - ldy #0 - lda (dst),y - clc - adc #1 - sta (dst),y - lda value - sec - sbc sub - sta value - lda value+1 - sbc sub+1 - sta value+1 - jmp b3 b2: - lda #3 + lda VAL,x clc - ldy #0 - adc (dst),y - sta (dst),y - lda value + adc digit + sta digit + txa + asl + tay sec - sbc sub3 + lda value + sbc SUB,y sta value lda value+1 - sbc sub3+1 + sbc SUB+1,y sta value+1 + lda #1 + sta bStarted jmp b1 } cls: { @@ -280,3 +196,6 @@ cls: { bne b1 rts } + DIGITS: .text "0123456789abcdef@" + SUB: .word $7530, $2710, $bb8, $3e8, $12c, $64, $1e, $a + VAL: .byte 3, 1, 3, 1, 3, 1, 3, 1 From 5d988dd859a1169fc4faaeabeb6fc04f6c6c8ceb Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Mon, 20 May 2019 10:36:58 +0200 Subject: [PATCH 52/93] Rafactoring pass 2 --- .../java/dk/camelot64/kickc/Compiler.java | 9 +-- .../dk/camelot64/kickc/test/TestPrograms.java | 1 - src/test/ref/pointer-plus-0.asm | 8 +- src/test/ref/sandbox.asm | 2 +- src/test/ref/semi-struct-1.asm | 16 ++-- src/test/ref/semi-struct-2.asm | 74 +++++++++---------- src/test/ref/sizeof-expr.asm | 2 +- src/test/ref/test-comparisons-word.asm | 4 +- 8 files changed, 55 insertions(+), 61 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index d7e23c9c2..ca1139264 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -231,12 +231,12 @@ public class Compiler { private void pass2Optimize() { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); - optimizations.add(new PassNAddTypeConversionAssignment(program)); optimizations.add(new PassNAddNumberTypeConversions(program)); optimizations.add(new PassNAddArrayNumberTypeConversions(program)); optimizations.add(new PassNDowngradeBytePlusWord(program)); optimizations.add(new PassNTypeInference(program)); optimizations.add(new PassNTypeIdSimplification(program)); + optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new Pass2CullEmptyBlocks(program)); optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNVariableReferenceInfos(program)); @@ -257,21 +257,18 @@ public class Compiler { optimizations.add(new Pass2FixInlineConstructorsNew(program)); optimizations.add(new PassNAddTypeConversionAssignment(program)); optimizations.add(new Pass2TypeInference(program)); - optimizations.add(new PassNEliminateUnusedVars(program, true)); optimizations.add(new Pass2EliminateRedundantCasts(program)); - optimizations.add(new Pass2EliminateUnusedBlocks(program)); optimizations.add(new Pass2RangeResolving(program)); optimizations.add(new Pass2ComparisonOptimization(program)); optimizations.add(new Pass2ConstantCallPointerIdentification(program)); - optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new Pass2InlineCast(program)); optimizations.add(new PassNCastSimplification(program)); - optimizations.add(new PassNStatementIndices(program)); - optimizations.add(new PassNVariableReferenceInfos(program)); optimizations.add(new Pass2InlineDerefIdx(program)); optimizations.add(new Pass2DeInlineWordDerefIdx(program)); optimizations.add(new PassNSimplifyConstantZero(program)); optimizations.add(new PassNSimplifyExpressionWithZero(program)); + optimizations.add(new PassNEliminateUnusedVars(program, true)); + optimizations.add(new Pass2EliminateUnusedBlocks(program)); pass2Execute(optimizations); } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index c4a10ab7a..39ac64c0b 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,7 +63,6 @@ public class TestPrograms { */ - @Test public void testHex2Dec() throws IOException, URISyntaxException { compileAndCompare("hex2dec"); diff --git a/src/test/ref/pointer-plus-0.asm b/src/test/ref/pointer-plus-0.asm index 3670d3426..8fc352c78 100644 --- a/src/test/ref/pointer-plus-0.asm +++ b/src/test/ref/pointer-plus-0.asm @@ -4,15 +4,15 @@ .pc = $80d "Program" main: { .label SCREEN = $400 - .label _1 = 2 - .label _3 = 2 + .label _0 = 2 + .label _2 = 2 lda #<msg1 sta first.msg lda #>msg1 sta first.msg+1 jsr first ldy #0 - lda (_1),y + lda (_0),y sta SCREEN lda #<msg2 sta first.msg @@ -20,7 +20,7 @@ main: { sta first.msg+1 jsr first ldy #0 - lda (_3),y + lda (_2),y sta SCREEN+1 rts } diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm index 559fa3c11..7abbd0312 100644 --- a/src/test/ref/sandbox.asm +++ b/src/test/ref/sandbox.asm @@ -545,9 +545,9 @@ append: { bne !+ lda sub cmp value + beq b2 !: bcc b2 - beq b2 rts b2: ldy #0 diff --git a/src/test/ref/semi-struct-1.asm b/src/test/ref/semi-struct-1.asm index 77e06cc4d..981c26588 100644 --- a/src/test/ref/semi-struct-1.asm +++ b/src/test/ref/semi-struct-1.asm @@ -22,7 +22,7 @@ main: { } // Print points print_points: { - .label pointXpos1__0 = 9 + .label point = 9 .label i = 2 jsr print_cls lda #<$400 @@ -42,15 +42,15 @@ print_points: { tya clc adc #<points - sta pointXpos1__0 + sta point lda #>points adc #0 - sta pointXpos1__0+1 + sta point+1 ldx points,y jsr print_byte jsr print_str ldy #1 - lda (pointXpos1__0),y + lda (point),y tax jsr print_byte jsr print_ln @@ -168,7 +168,7 @@ print_cls: { } // Initialize points init_points: { - .label pointXpos1__0 = 3 + .label getPoint1_return = 3 .label pos = 2 lda #$a sta pos @@ -180,17 +180,17 @@ init_points: { tya clc adc #<points - sta pointXpos1__0 + sta getPoint1_return lda #>points adc #0 - sta pointXpos1__0+1 + sta getPoint1_return+1 lda pos sta points,y lda #$a clc adc pos ldy #1 - sta (pointXpos1__0),y + sta (getPoint1_return),y clc adc #$a sta pos diff --git a/src/test/ref/semi-struct-2.asm b/src/test/ref/semi-struct-2.asm index 0429bcc2f..03cc33c2c 100644 --- a/src/test/ref/semi-struct-2.asm +++ b/src/test/ref/semi-struct-2.asm @@ -301,7 +301,6 @@ print_ln: { // printEntry(byte* zeropage(4) entry) printEntry: { .label entry = 4 - .label entryBufDisk1__0 = 4 lda print_line_cursor sta print_char_cursor lda print_line_cursor+1 @@ -312,10 +311,10 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #0 - lda (entryBufDisk1__0),y + lda (entry),y sta print_word.w iny - lda (entryBufDisk1__0),y + lda (entry),y sta print_word.w+1 jsr print_word lda print_line_cursor @@ -333,10 +332,10 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #2 - lda (entryBufDisk1__0),y + lda (entry),y sta print_word.w iny - lda (entryBufDisk1__0),y + lda (entry),y sta print_word.w+1 jsr print_word lda print_line_cursor @@ -354,10 +353,10 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #4 - lda (entryBufDisk1__0),y + lda (entry),y sta print_word.w iny - lda (entryBufDisk1__0),y + lda (entry),y sta print_word.w+1 jsr print_word lda print_line_cursor @@ -375,10 +374,10 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #6 - lda (entryBufDisk1__0),y + lda (entry),y sta print_word.w iny - lda (entryBufDisk1__0),y + lda (entry),y sta print_word.w+1 jsr print_word lda print_line_cursor @@ -396,7 +395,7 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #8 - lda (entryBufDisk1__0),y + lda (entry),y tax jsr print_byte lda print_line_cursor @@ -414,7 +413,7 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #9 - lda (entryBufDisk1__0),y + lda (entry),y tax jsr print_byte lda print_line_cursor @@ -432,7 +431,7 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #$a - lda (entryBufDisk1__0),y + lda (entry),y tax jsr print_byte lda print_line_cursor @@ -450,7 +449,7 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #$b - lda (entryBufDisk1__0),y + lda (entry),y tax jsr print_byte lda print_line_cursor @@ -468,10 +467,10 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #$c - lda (entryBufDisk1__0),y + lda (entry),y sta print_word.w iny - lda (entryBufDisk1__0),y + lda (entry),y sta print_word.w+1 jsr print_word lda print_line_cursor @@ -489,7 +488,7 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #$e - lda (entryBufDisk1__0),y + lda (entry),y tax jsr print_byte lda print_line_cursor @@ -507,7 +506,7 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #$f - lda (entryBufDisk1__0),y + lda (entry),y tax jsr print_byte lda print_line_cursor @@ -525,7 +524,7 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #$10 - lda (entryBufDisk1__0),y + lda (entry),y tax jsr print_byte lda print_line_cursor @@ -543,7 +542,7 @@ printEntry: { sta print_str.str+1 jsr print_str ldy #$11 - lda (entryBufDisk1__0),y + lda (entry),y tax jsr print_byte lda print_line_cursor @@ -616,7 +615,6 @@ initEntry: { .label _7 = 6 .label _17 = 6 .label entry = 2 - .label entryBufDisk1__0 = 2 txa clc adc #<$1111 @@ -626,10 +624,10 @@ initEntry: { sta _1+1 ldy #0 lda _1 - sta (entryBufDisk1__0),y + sta (entry),y iny lda _1+1 - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #<$2222 @@ -639,10 +637,10 @@ initEntry: { sta _3+1 ldy #2 lda _3 - sta (entryBufDisk1__0),y + sta (entry),y iny lda _3+1 - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #<$3333 @@ -652,10 +650,10 @@ initEntry: { sta _5+1 ldy #4 lda _5 - sta (entryBufDisk1__0),y + sta (entry),y iny lda _5+1 - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #<$4444 @@ -665,30 +663,30 @@ initEntry: { sta _7+1 ldy #6 lda _7 - sta (entryBufDisk1__0),y + sta (entry),y iny lda _7+1 - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #$55 ldy #8 - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #$66 ldy #9 - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #$77 ldy #$a - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #$88 ldy #$b - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #<$9999 @@ -698,30 +696,30 @@ initEntry: { sta _17+1 ldy #$c lda _17 - sta (entryBufDisk1__0),y + sta (entry),y iny lda _17+1 - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #$aa ldy #$e - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #$bb ldy #$f - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #$cc ldy #$10 - sta (entryBufDisk1__0),y + sta (entry),y txa clc adc #$dd ldy #$11 - sta (entryBufDisk1__0),y + sta (entry),y rts } // Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word diff --git a/src/test/ref/sizeof-expr.asm b/src/test/ref/sizeof-expr.asm index 5720d470d..06f2d6a54 100644 --- a/src/test/ref/sizeof-expr.asm +++ b/src/test/ref/sizeof-expr.asm @@ -2,10 +2,10 @@ .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" - .label SCREEN = $400 .const SIZEOF_BYTE = 1 .const SIZEOF_WORD = 2 .const SIZEOF_POINTER = 2 + .label SCREEN = $400 .const SIZEOF_NUMBER = $ff main: { .const sz = $f diff --git a/src/test/ref/test-comparisons-word.asm b/src/test/ref/test-comparisons-word.asm index 05ed548ab..fed328414 100644 --- a/src/test/ref/test-comparisons-word.asm +++ b/src/test/ref/test-comparisons-word.asm @@ -205,9 +205,9 @@ compare: { bne !+ lda w1 cmp w2 + beq b11 !: bcc b11 - beq b11 lda #TT sta r jmp b22 @@ -247,9 +247,9 @@ compare: { bne !+ lda w2 cmp w1 + beq b13 !: bcc b13 - beq b13 lda #TT sta r jmp b24 From 77d24eddc654032b0a5899526a733ea708c7c80a Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Mon, 20 May 2019 10:47:53 +0200 Subject: [PATCH 53/93] Rafactoring pass 2 --- .../java/dk/camelot64/kickc/Compiler.java | 1 - .../kickc/passes/Pass2TypeInference.java | 33 ------------------- src/test/ref/inline-pointer-2.asm | 3 +- 3 files changed, 2 insertions(+), 35 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2TypeInference.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index ca1139264..d988613f4 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -256,7 +256,6 @@ public class Compiler { optimizations.add(new Pass2ConstantStringConsolidation(program)); optimizations.add(new Pass2FixInlineConstructorsNew(program)); optimizations.add(new PassNAddTypeConversionAssignment(program)); - optimizations.add(new Pass2TypeInference(program)); optimizations.add(new Pass2EliminateRedundantCasts(program)); optimizations.add(new Pass2RangeResolving(program)); optimizations.add(new Pass2ComparisonOptimization(program)); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2TypeInference.java b/src/main/java/dk/camelot64/kickc/passes/Pass2TypeInference.java deleted file mode 100644 index b59532300..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2TypeInference.java +++ /dev/null @@ -1,33 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.ControlFlowBlock; -import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.statements.Statement; -import dk.camelot64.kickc.model.statements.StatementAssignment; -import dk.camelot64.kickc.model.statements.StatementCall; -import dk.camelot64.kickc.model.types.SymbolTypeInference; - -/** - * Pass through the all statements (re-)inferring types of variables. - */ -public class Pass2TypeInference extends Pass2SsaOptimization { - - public Pass2TypeInference(Program program) { - super(program); - } - - @Override - public boolean step() { - for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { - for(Statement statement : block.getStatements()) { - if(statement instanceof StatementAssignment) { - SymbolTypeInference.inferAssignmentLValue(getProgram(), (StatementAssignment) statement, true); - } else if(statement instanceof StatementCall) { - SymbolTypeInference.inferCallLValue(getProgram(), (StatementCall) statement, true); - } - } - } - return false; - } - -} diff --git a/src/test/ref/inline-pointer-2.asm b/src/test/ref/inline-pointer-2.asm index 32a924a78..8cd4e7021 100644 --- a/src/test/ref/inline-pointer-2.asm +++ b/src/test/ref/inline-pointer-2.asm @@ -3,7 +3,8 @@ :BasicUpstart(main) .pc = $80d "Program" main: { + .label screen = 4*$100+$28 lda #'a' - sta 4*$100+$28 + sta screen rts } From 27c6c3fb8651a72a63928746b6e96a83f4fc770c Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Mon, 20 May 2019 10:54:06 +0200 Subject: [PATCH 54/93] Rafactoring pass 2 --- src/main/java/dk/camelot64/kickc/Compiler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index d988613f4..252e07f27 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -250,16 +250,16 @@ public class Compiler { optimizations.add(new Pass2ConstantRValueConsolidation(program)); optimizations.add(new Pass2ConstantIdentification(program)); optimizations.add(new Pass2ConstantValues(program)); - optimizations.add(new PassNStatementIndices(program)); - optimizations.add(new PassNVariableReferenceInfos(program)); + optimizations.add(new Pass2ConstantCallPointerIdentification(program)); optimizations.add(new Pass2ConstantIfs(program)); optimizations.add(new Pass2ConstantStringConsolidation(program)); + optimizations.add(new PassNStatementIndices(program)); + optimizations.add(new PassNVariableReferenceInfos(program)); optimizations.add(new Pass2FixInlineConstructorsNew(program)); optimizations.add(new PassNAddTypeConversionAssignment(program)); optimizations.add(new Pass2EliminateRedundantCasts(program)); optimizations.add(new Pass2RangeResolving(program)); optimizations.add(new Pass2ComparisonOptimization(program)); - optimizations.add(new Pass2ConstantCallPointerIdentification(program)); optimizations.add(new Pass2InlineCast(program)); optimizations.add(new PassNCastSimplification(program)); optimizations.add(new Pass2InlineDerefIdx(program)); From 2b26c813d989907f0ead3bed66e975c0b0aebfca Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Mon, 20 May 2019 11:01:58 +0200 Subject: [PATCH 55/93] Rafactoring pass 2 --- src/main/fragment/vduz1=vwuz2_dword_vbuc1.asm | 8 ++++---- src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm | 8 ++++++++ src/main/java/dk/camelot64/kickc/Compiler.java | 2 +- ...rd.java => PassNDowngradeConstantTypeConversions.java} | 4 ++-- src/test/ref/linegen.asm | 5 ++--- 5 files changed, 17 insertions(+), 10 deletions(-) create mode 100644 src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm rename src/main/java/dk/camelot64/kickc/passes/{PassNDowngradeBytePlusWord.java => PassNDowngradeConstantTypeConversions.java} (96%) diff --git a/src/main/fragment/vduz1=vwuz2_dword_vbuc1.asm b/src/main/fragment/vduz1=vwuz2_dword_vbuc1.asm index a704a0e79..ee4169530 100644 --- a/src/main/fragment/vduz1=vwuz2_dword_vbuc1.asm +++ b/src/main/fragment/vduz1=vwuz2_dword_vbuc1.asm @@ -1,8 +1,8 @@ -lda #<{c1} -sta {z1} -lda #>{c1} -sta {z1}+1 lda {z2} sta {z1}+2 lda {z2}+1 sta {z1}+3 +lda #{c1} +sta {z1} +lda #0 +sta {z1}+1 diff --git a/src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm b/src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm new file mode 100644 index 000000000..a704a0e79 --- /dev/null +++ b/src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm @@ -0,0 +1,8 @@ +lda #<{c1} +sta {z1} +lda #>{c1} +sta {z1}+1 +lda {z2} +sta {z1}+2 +lda {z2}+1 +sta {z1}+3 diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 252e07f27..5c86cc61e 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -233,7 +233,7 @@ public class Compiler { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); optimizations.add(new PassNAddNumberTypeConversions(program)); optimizations.add(new PassNAddArrayNumberTypeConversions(program)); - optimizations.add(new PassNDowngradeBytePlusWord(program)); + optimizations.add(new PassNDowngradeConstantTypeConversions(program)); optimizations.add(new PassNTypeInference(program)); optimizations.add(new PassNTypeIdSimplification(program)); optimizations.add(new Pass2SizeOfSimplification(program)); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java similarity index 96% rename from src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java rename to src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java index b3f819d53..85a6db2cb 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java @@ -13,9 +13,9 @@ import java.util.concurrent.atomic.AtomicBoolean; /** * Downgrade any number expression cast that are part of a WORD+NUMBER expression to BYTE if the number is small enough to fit in the byte. */ -public class PassNDowngradeBytePlusWord extends Pass2SsaOptimization { +public class PassNDowngradeConstantTypeConversions extends Pass2SsaOptimization { - public PassNDowngradeBytePlusWord(Program program) { + public PassNDowngradeConstantTypeConversions(Program program) { super(program); } diff --git a/src/test/ref/linegen.asm b/src/test/ref/linegen.asm index 4cbd79681..4b4fcd8a9 100644 --- a/src/test/ref/linegen.asm +++ b/src/test/ref/linegen.asm @@ -335,14 +335,13 @@ lin16u_gen: { sta step lda stepf+1 sta step+1 - lda #<0 - sta val - sta val+1 lda min sta val+2 lda min+1 sta val+3 lda #0 + sta val + sta val+1 sta i sta i+1 b1: From bc699a9e2727f26f84e0b3612265fc6101cf3092 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Mon, 20 May 2019 23:41:58 +0200 Subject: [PATCH 56/93] Added utoa16(). Fixed early constant identification not taking procedure parameters into account. --- .../Pass1EarlyConstantIdentification.java | 46 +++-- src/test/kc/hex2dec.kc | 91 ++++------ src/test/ref/hex2dec.asm | 166 ++++++++++++------ 3 files changed, 187 insertions(+), 116 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1EarlyConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass1EarlyConstantIdentification.java index faceeca37..8c8339dd9 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1EarlyConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1EarlyConstantIdentification.java @@ -6,12 +6,15 @@ import dk.camelot64.kickc.model.operators.OperatorCastPtr; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementLValue; +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.values.ConstantValue; import dk.camelot64.kickc.model.values.VariableRef; import java.util.ArrayList; import java.util.Collection; +import java.util.List; /** Identify any variable that are clearly constant. */ public class Pass1EarlyConstantIdentification extends Pass1Base { @@ -26,18 +29,20 @@ public class Pass1EarlyConstantIdentification extends Pass1Base { for(Variable variable : getProgram().getScope().getAllVariables(true)) { VariableRef variableRef = variable.getRef(); if(!variable.isDeclaredConstant() && !variable.isDeclaredVolatile() && !variableRef.isIntermediate()) { - Collection<StatementLValue> assignments = getAssignments(variable); - if(assignments.size() == 1) { - if(!Pass2ConstantIdentification.isAddressOfUsed(variableRef, getProgram())) { - StatementLValue assignment = assignments.iterator().next(); - if(assignment instanceof StatementAssignment) { - StatementAssignment assign = (StatementAssignment) assignment; - if(assign.getrValue1() == null && assign.getOperator() == null && assign.getrValue2() instanceof ConstantValue) { - getLog().append("Identified constant variable " + variable.toString(getProgram())); - earlyConstants.add(variableRef); - } else if(assign.getrValue1() == null && assign.getOperator() instanceof OperatorCastPtr && assign.getrValue2() instanceof ConstantValue) { - getLog().append("Identified constant variable " + variable.toString(getProgram())); - earlyConstants.add(variableRef); + if(!isParameter(variableRef)) { + Collection<StatementLValue> assignments = getAssignments(variable); + if(assignments.size() == 1) { + if(!Pass2ConstantIdentification.isAddressOfUsed(variableRef, getProgram())) { + StatementLValue assignment = assignments.iterator().next(); + if(assignment instanceof StatementAssignment) { + StatementAssignment assign = (StatementAssignment) assignment; + if(assign.getrValue1() == null && assign.getOperator() == null && assign.getrValue2() instanceof ConstantValue) { + getLog().append("Identified constant variable " + variable.toString(getProgram())); + earlyConstants.add(variableRef); + } else if(assign.getrValue1() == null && assign.getOperator() instanceof OperatorCastPtr && assign.getrValue2() instanceof ConstantValue) { + getLog().append("Identified constant variable " + variable.toString(getProgram())); + earlyConstants.add(variableRef); + } } } } @@ -48,6 +53,23 @@ public class Pass1EarlyConstantIdentification extends Pass1Base { return false; } + /** + * Examines whether a variale is a procedure parameter + * @param variableRef The variable + * @return true if the variable is a procedure parameter + */ + public boolean isParameter(VariableRef variableRef) { + Variable var = getScope().getVariable(variableRef); + Scope varScope = var.getScope(); + if(varScope instanceof Procedure) { + List<Variable> parameters = ((Procedure) varScope).getParameters(); + if(parameters.contains(var)) + return true; + + } + return false; + } + /** * Find all assignments of a variable. * diff --git a/src/test/kc/hex2dec.kc b/src/test/kc/hex2dec.kc index f27a6e7d4..d44d936df 100644 --- a/src/test/kc/hex2dec.kc +++ b/src/test/kc/hex2dec.kc @@ -14,15 +14,15 @@ void main() { unsigned char *screen = 0x0400; *bordercol = 1; unsigned char time_start = *raster; - utoa10b(00000, screen); (*bordercol)++; screen += 40; - utoa10b(01234, screen); (*bordercol)++; screen += 40; - utoa10b(05678, screen); (*bordercol)++; screen += 40; - utoa10b(09999, screen); (*bordercol)++; screen += 40; - utoa10b(58888, screen); + utoa16w(00000, screen); (*bordercol)++; screen += 40; + utoa16w(01234, screen); (*bordercol)++; screen += 40; + utoa16w(05678, screen); (*bordercol)++; screen += 40; + utoa16w(09999, screen); (*bordercol)++; screen += 40; + utoa16w(58888, screen); unsigned char time_end = *raster; *bordercol = 0; unsigned char time = time_end - time_start; - utoa10b((unsigned int)time, screen+80); + utoa10w((unsigned int)time, screen+80); byte[] msg = "raster lines"; for( byte i=0; msg[i]!=0; i++ ) (screen+80+3)[i] = msg[i]; //for( byte* m="lines", s=screen+80+6 ;*m!=0;m++,s++) *s = *m; @@ -40,58 +40,20 @@ const unsigned char RADIX_OCTAL = 8; const unsigned char RADIX_DECIMAL = 10; const unsigned char RADIX_HEX = 16; -// simple 'utoa' without using multiply or divide -unsigned int utoa_digit(unsigned char *dst, unsigned int value, unsigned int sub){ - unsigned char digit = 0; - unsigned int sub3 = sub*2+sub; - while (value >= sub3){ digit += 3; value -= sub3; } - while (value >= sub){ ++digit; value -= sub; } - *dst = DIGITS[digit]; - return value; -} - -void utoa(unsigned int value, unsigned char *dst){ - unsigned char bStarted = 0; - if (bStarted == 1 || value >= 10000){ value = utoa_digit(dst++, value, 10000); bStarted = 1; } - if (bStarted == 1 || value >= 1000){ value = utoa_digit(dst++, value, 1000); bStarted = 1; } - if (bStarted == 1 || value >= 100){ value = utoa_digit(dst++, value, 100); bStarted = 1; } - if (bStarted == 1 || value >= 10){ value = utoa_digit(dst++, value, 10); bStarted = 1; } - *dst++ = '0' + (unsigned char) value; - //*dst = 0; -} - +// Digits used for utoa() unsigned char[] DIGITS = "0123456789abcdef"; -unsigned int[] SUB3 = { 30000, 3000, 300, 30 }; -unsigned int[] SUB1 = { 10000, 1000, 100, 10 }; -// Simple decimal utoa() without using multiply or divide -void utoa10(unsigned int value, unsigned char* dst) { - unsigned char bStarted = 0; - for( unsigned char i: 0..3) { - unsigned char digit = 0; - unsigned int sub1 = SUB1[i]; - if(value>=sub1) { - unsigned int sub3 = SUB3[i]; - while(value>=sub3) { digit += 3; value -= sub3; bStarted = 1; } - while(value>=sub1) { digit += 1; value -= sub1; bStarted = 1; } - } - if(bStarted!=0) { - *dst++ = DIGITS[digit]; - } - } - *dst++ = DIGITS[(unsigned char) value]; - //*dst = 0; -} - -unsigned int[] SUB = { 30000, 10000, 3000, 1000, 300, 100, 30, 10 }; -unsigned char[] VAL = { 3, 1, 3, 1, 3, 1, 3, 1 }; +// Subtraction values used for decimal utoa() +unsigned int[] UTOA10_SUB = { 30000, 10000, 3000, 1000, 300, 100, 30, 10 }; +// Digit addition values used for decimal utoa() +unsigned char[] UTOA10_VAL = { 3, 1, 3, 1, 3, 1, 3, 1 }; // Decimal utoa() without using multiply or divide -void utoa10b(unsigned int value, unsigned char* dst) { +void utoa10w(unsigned int value, unsigned char* dst) { unsigned char bStarted = 0; unsigned char digit = 0; for( unsigned char i: 0..7) { - while(value>=SUB[i]) { digit += VAL[i]; value -= SUB[i]; bStarted = 1; } + while(value>=UTOA10_SUB[i]) { digit += UTOA10_VAL[i]; value -= UTOA10_SUB[i]; bStarted = 1; } if((i&1)!=0) { if(bStarted!=0) { *dst++ = DIGITS[digit]; @@ -101,4 +63,29 @@ void utoa10b(unsigned int value, unsigned char* dst) { } *dst++ = DIGITS[(unsigned char) value]; *dst = 0; -} \ No newline at end of file +} + +// Holds the destination address for the hexadecimal utoa() +unsigned char* utoa16_dst; +// Holds whether the hexadecimal utoa() has started outputting digits +unsigned char utoa16_started; + +// Hexadecimal utoa() for an unsigned int (16bits) +void utoa16w(unsigned int value, unsigned char* dst) { + utoa16_dst = dst; + utoa16_started = 0; + utoa16n((>value)>>4); + utoa16n((>value)&0x0f); + utoa16n((<value)>>4); + utoa16_started = 1; + utoa16n((<value)&0x0f); + *utoa16_dst = 0; +} + +// Hexadecimal utoa() for a single nybble +void utoa16n(unsigned char nybble) { + if(nybble!=0) utoa16_started=1; + if(utoa16_started!=0) { + *utoa16_dst++ = DIGITS[nybble]; + } +} diff --git a/src/test/ref/hex2dec.asm b/src/test/ref/hex2dec.asm index 4fbbca239..373a47ff5 100644 --- a/src/test/ref/hex2dec.asm +++ b/src/test/ref/hex2dec.asm @@ -5,9 +5,11 @@ .label control = $d011 .label raster = $d012 .label bordercol = $d020 + .label utoa16_dst = 2 + .label utoa16_started = 4 main: { .label _1 = 4 - .label time_start = 8 + .label time_start = 5 sei jsr cls b1: @@ -23,68 +25,64 @@ main: { sta bordercol lda raster sta time_start - lda #<$400 - sta utoa10b.dst - lda #>$400 - sta utoa10b.dst+1 lda #0 - sta utoa10b.value - sta utoa10b.value+1 - jsr utoa10b + sta utoa16w.value + sta utoa16w.value+1 + lda #<$400 + sta utoa16w.dst + lda #>$400 + sta utoa16w.dst+1 + jsr utoa16w inc bordercol - lda #<$400+$28 - sta utoa10b.dst - lda #>$400+$28 - sta utoa10b.dst+1 lda #<$4d2 - sta utoa10b.value + sta utoa16w.value lda #>$4d2 - sta utoa10b.value+1 - jsr utoa10b + sta utoa16w.value+1 + lda #<$400+$28 + sta utoa16w.dst + lda #>$400+$28 + sta utoa16w.dst+1 + jsr utoa16w inc bordercol - lda #<$400+$28+$28 - sta utoa10b.dst - lda #>$400+$28+$28 - sta utoa10b.dst+1 lda #<$162e - sta utoa10b.value + sta utoa16w.value lda #>$162e - sta utoa10b.value+1 - jsr utoa10b + sta utoa16w.value+1 + lda #<$400+$28+$28 + sta utoa16w.dst + lda #>$400+$28+$28 + sta utoa16w.dst+1 + jsr utoa16w inc bordercol - lda #<$400+$28+$28+$28 - sta utoa10b.dst - lda #>$400+$28+$28+$28 - sta utoa10b.dst+1 lda #<$270f - sta utoa10b.value + sta utoa16w.value lda #>$270f - sta utoa10b.value+1 - jsr utoa10b + sta utoa16w.value+1 + lda #<$400+$28+$28+$28 + sta utoa16w.dst + lda #>$400+$28+$28+$28 + sta utoa16w.dst+1 + jsr utoa16w inc bordercol - lda #<$400+$28+$28+$28+$28 - sta utoa10b.dst - lda #>$400+$28+$28+$28+$28 - sta utoa10b.dst+1 lda #<$e608 - sta utoa10b.value + sta utoa16w.value lda #>$e608 - sta utoa10b.value+1 - jsr utoa10b + sta utoa16w.value+1 + lda #<$400+$28+$28+$28+$28 + sta utoa16w.dst + lda #>$400+$28+$28+$28+$28 + sta utoa16w.dst+1 + jsr utoa16w ldx raster lda #0 sta bordercol txa sec sbc time_start - sta utoa10b.value + sta utoa10w.value lda #0 - sta utoa10b.value+1 - lda #<$400+$28+$28+$28+$28+$50 - sta utoa10b.dst - lda #>$400+$28+$28+$28+$28+$50 - sta utoa10b.dst+1 - jsr utoa10b + sta utoa10w.value+1 + jsr utoa10w ldx #0 b3: lda msg,x @@ -97,12 +95,16 @@ main: { msg: .text "raster lines@" } // Decimal utoa() without using multiply or divide -// utoa10b(word zeropage(2) value, byte* zeropage(6) dst) -utoa10b: { +// utoa10w(word zeropage(2) value, byte* zeropage(6) dst) +utoa10w: { .label value = 2 .label digit = 4 .label dst = 6 .label bStarted = 5 + lda #<$400+$28+$28+$28+$28+$50 + sta dst + lda #>$400+$28+$28+$28+$28+$50 + sta dst+1 lda #0 sta bStarted sta digit @@ -111,10 +113,10 @@ utoa10b: { txa asl tay - lda SUB+1,y + lda UTOA10_SUB+1,y cmp value+1 bne !+ - lda SUB,y + lda UTOA10_SUB,y cmp value beq b2 !: @@ -155,7 +157,7 @@ utoa10b: { sta (dst),y rts b2: - lda VAL,x + lda UTOA10_VAL,x clc adc digit sta digit @@ -164,15 +166,72 @@ utoa10b: { tay sec lda value - sbc SUB,y + sbc UTOA10_SUB,y sta value lda value+1 - sbc SUB+1,y + sbc UTOA10_SUB+1,y sta value+1 lda #1 sta bStarted jmp b1 } +// Hexadecimal utoa() for an unsigned int (16bits) +// utoa16w(word zeropage(6) value, byte* zeropage(2) dst) +utoa16w: { + .label dst = 2 + .label value = 6 + lda value+1 + lsr + lsr + lsr + lsr + tax + lda #0 + sta utoa16_started + jsr utoa16n + lda value+1 + ldx #$f + axs #0 + jsr utoa16n + lda value + lsr + lsr + lsr + lsr + tax + jsr utoa16n + lda value + ldx #$f + axs #0 + lda #1 + sta utoa16_started + jsr utoa16n + lda #0 + tay + sta (utoa16_dst),y + rts +} +// Hexadecimal utoa() for a single nybble +// utoa16n(byte register(X) nybble) +utoa16n: { + cpx #0 + beq b1 + lda #1 + sta utoa16_started + b1: + lda utoa16_started + cmp #0 + beq breturn + lda DIGITS,x + ldy #0 + sta (utoa16_dst),y + inc utoa16_dst + bne !+ + inc utoa16_dst+1 + !: + breturn: + rts +} cls: { .label screen = $400 .label sc = 2 @@ -196,6 +255,9 @@ cls: { bne b1 rts } + // Digits used for utoa() DIGITS: .text "0123456789abcdef@" - SUB: .word $7530, $2710, $bb8, $3e8, $12c, $64, $1e, $a - VAL: .byte 3, 1, 3, 1, 3, 1, 3, 1 + // Subtraction values used for decimal utoa() + UTOA10_SUB: .word $7530, $2710, $bb8, $3e8, $12c, $64, $1e, $a + // Digit addition values used for decimal utoa() + UTOA10_VAL: .byte 3, 1, 3, 1, 3, 1, 3, 1 From b3041e326d2654b21a362019062aa709859f0e89 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 21 May 2019 00:05:17 +0200 Subject: [PATCH 57/93] Optimizing compiler passes --- src/main/java/dk/camelot64/kickc/Compiler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 5c86cc61e..67ca190b1 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -378,7 +378,6 @@ public class Compiler { new Pass3AssertConstants(program).check(); new Pass3AssertArrayLengths(program).check(); new Pass3AssertNoMulDivMod(program).check(); - new PassNCastSimplification(program).execute(); new PassNBlockSequencePlanner(program).step(); // Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes new Pass3PhiLifting(program).perform(); From 3132790ab5a3450bdc064ec7de9ec42f2e0e3c8a Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 21 May 2019 00:33:36 +0200 Subject: [PATCH 58/93] Added very naive heap implementation. --- .../dk/camelot64/kickc/test/TestPrograms.java | 5 ++ src/test/kc/memory-heap.kc | 34 ++++++++++ src/test/ref/memory-heap.asm | 66 +++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 src/test/kc/memory-heap.kc create mode 100644 src/test/ref/memory-heap.asm diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 39ac64c0b..4a2357ddc 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -68,6 +68,11 @@ public class TestPrograms { compileAndCompare("hex2dec"); } + @Test + public void testMemoryHeap() throws IOException, URISyntaxException { + compileAndCompare("memory-heap"); + } + @Test public void testTernaryInference() throws IOException, URISyntaxException { compileAndCompare("ternary-inference"); diff --git a/src/test/kc/memory-heap.kc b/src/test/kc/memory-heap.kc new file mode 100644 index 000000000..2fa915342 --- /dev/null +++ b/src/test/kc/memory-heap.kc @@ -0,0 +1,34 @@ +// Experiments with malloc() + +void main() { + unsigned char* buf1 = (unsigned char*) malloc(100); + unsigned char* buf2 = (unsigned char*) malloc(100); + for(unsigned char i:0..99) { + buf1[i] = i; + buf2[i] = 255-i; + } + free(buf1); + free(buf2); + unsigned char* screen = 0x0400; + screen[0] = *buf1; + screen[1] = *buf2; +} + +// Start of the heap used by malloc() +unsigned char* HEAP_START = 0xc000; + +// Head of the heap. Moved forward for each malloc() +unsigned char* heap_head = HEAP_START; + +// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block. +// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values. +unsigned char* malloc(unsigned int size) { + unsigned char* mem = heap_head; + heap_head+= size; + return mem; +} + +// A block of memory previously allocated by a call to malloc is deallocated, making it available again for further allocations. +// If ptr is a null pointer, the function does nothing. +void free(unsigned char* ptr) { +} \ No newline at end of file diff --git a/src/test/ref/memory-heap.asm b/src/test/ref/memory-heap.asm new file mode 100644 index 000000000..769942503 --- /dev/null +++ b/src/test/ref/memory-heap.asm @@ -0,0 +1,66 @@ +// Experiments with malloc() +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Start of the heap used by malloc() + .label HEAP_START = $c000 + .label heap_head = 2 +main: { + .label screen = $400 + .label buf1 = 4 + .label buf2 = 6 + lda #<HEAP_START + sta heap_head + lda #>HEAP_START + sta heap_head+1 + jsr malloc + lda malloc.return_2 + sta malloc.return + lda malloc.return_2+1 + sta malloc.return+1 + jsr malloc + ldy #0 + b1: + tya + sta (buf1),y + tya + eor #$ff + clc + adc #$ff+1 + sta (buf2),y + iny + cpy #$64 + bne b1 + jsr free + jsr free + ldy #0 + lda (buf1),y + sta screen + lda (buf2),y + sta screen+1 + rts +} +// A block of memory previously allocated by a call to malloc is deallocated, making it available again for further allocations. +// If ptr is a null pointer, the function does nothing. +free: { + rts +} +// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block. +// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values. +malloc: { + .label return = 4 + .label return_1 = 6 + .label return_2 = 6 + lda heap_head + sta return_2 + lda heap_head+1 + sta return_2+1 + lda #$64 + clc + adc heap_head + sta heap_head + bcc !+ + inc heap_head+1 + !: + rts +} From fd259fe47e6c0c7d438913d6e41b417863af80f2 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 21 May 2019 01:45:32 +0200 Subject: [PATCH 59/93] Added pointer to pointer test. --- ...eref__deref_pptz1=pbuc1_derefidx_vbuxx.asm | 5 + .../_deref_pptz1=_inc__deref_pptz1.asm | 5 + .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/hex2dec-ptrptr.kc | 38 ++++ src/test/ref/hex2dec-ptrptr.asm | 163 ++++++++++++++++++ 5 files changed, 216 insertions(+) create mode 100644 src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm create mode 100644 src/main/fragment/_deref_pptz1=_inc__deref_pptz1.asm create mode 100644 src/test/kc/hex2dec-ptrptr.kc create mode 100644 src/test/ref/hex2dec-ptrptr.asm diff --git a/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm b/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm new file mode 100644 index 000000000..8f14bd50e --- /dev/null +++ b/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm @@ -0,0 +1,5 @@ +ldy #0 +lda {z1} +sta !+ +1 +lda {c1},x +!: sta ({z1}),y diff --git a/src/main/fragment/_deref_pptz1=_inc__deref_pptz1.asm b/src/main/fragment/_deref_pptz1=_inc__deref_pptz1.asm new file mode 100644 index 000000000..d066e7dc9 --- /dev/null +++ b/src/main/fragment/_deref_pptz1=_inc__deref_pptz1.asm @@ -0,0 +1,5 @@ +ldy #0 +lda ({z1}),y +clc +adc #1 +sta ({z1}),y \ No newline at end of file diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 4a2357ddc..319f189f0 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,6 +63,11 @@ public class TestPrograms { */ + @Test + public void testHex2DecPtrPtr() throws IOException, URISyntaxException { + compileAndCompare("hex2dec-ptrptr"); + } + @Test public void testHex2Dec() throws IOException, URISyntaxException { compileAndCompare("hex2dec"); diff --git a/src/test/kc/hex2dec-ptrptr.kc b/src/test/kc/hex2dec-ptrptr.kc new file mode 100644 index 000000000..18665be48 --- /dev/null +++ b/src/test/kc/hex2dec-ptrptr.kc @@ -0,0 +1,38 @@ +// Testing binary to hex conversion using pointer to pointer + +void main() { + cls(); + unsigned char *screen = 0x0400; + utoa16w(00000, screen); screen += 40; + utoa16w(01234, screen); screen += 40; + utoa16w(05678, screen); screen += 40; + utoa16w(09999, screen); screen += 40; + utoa16w(58888, screen); +} + +void cls() { + unsigned char *screen = 0x0400; + for( unsigned char *sc: screen..screen+999) *sc=' '; +} + +// Digits used for utoa() +unsigned char[] DIGITS = "0123456789abcdef"; + +// Hexadecimal utoa() for an unsigned int (16bits) +void utoa16w(unsigned int value, unsigned char* dst) { + unsigned char started = 0; + started = utoa16n((>value)>>4, &dst, started); + started = utoa16n((>value)&0x0f, &dst, started); + started = utoa16n((<value)>>4, &dst, started); + utoa16n((<value)&0x0f, &dst, 1); + *dst = 0; +} + +// Hexadecimal utoa() for a single nybble +unsigned char utoa16n(unsigned char nybble, unsigned **dst, unsigned char started) { + if(nybble!=0) started=1; + if(started!=0) { + *(*dst)++ = DIGITS[nybble]; + } + return started; +} diff --git a/src/test/ref/hex2dec-ptrptr.asm b/src/test/ref/hex2dec-ptrptr.asm new file mode 100644 index 000000000..6dcb61501 --- /dev/null +++ b/src/test/ref/hex2dec-ptrptr.asm @@ -0,0 +1,163 @@ +// Testing binary to hex conversion using pointer to pointer +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + jsr cls + lda #<$400 + sta utoa16w.dst + lda #>$400 + sta utoa16w.dst+1 + lda #0 + sta utoa16w.value + sta utoa16w.value+1 + jsr utoa16w + lda #<$400+$28 + sta utoa16w.dst + lda #>$400+$28 + sta utoa16w.dst+1 + lda #<$4d2 + sta utoa16w.value + lda #>$4d2 + sta utoa16w.value+1 + jsr utoa16w + lda #<$400+$28+$28 + sta utoa16w.dst + lda #>$400+$28+$28 + sta utoa16w.dst+1 + lda #<$162e + sta utoa16w.value + lda #>$162e + sta utoa16w.value+1 + jsr utoa16w + lda #<$400+$28+$28+$28 + sta utoa16w.dst + lda #>$400+$28+$28+$28 + sta utoa16w.dst+1 + lda #<$270f + sta utoa16w.value + lda #>$270f + sta utoa16w.value+1 + jsr utoa16w + lda #<$400+$28+$28+$28+$28 + sta utoa16w.dst + lda #>$400+$28+$28+$28+$28 + sta utoa16w.dst+1 + lda #<$e608 + sta utoa16w.value + lda #>$e608 + sta utoa16w.value+1 + jsr utoa16w + rts +} +// Hexadecimal utoa() for an unsigned int (16bits) +// utoa16w(word zeropage(2) value, byte* zeropage(4) dst) +utoa16w: { + .label value = 2 + .label dst = 4 + lda value+1 + lsr + lsr + lsr + lsr + tax + lda #<dst + sta utoa16n.dst + lda #>dst + sta utoa16n.dst+1 + lda #0 + sta utoa16n.started + jsr utoa16n + lda utoa16n.return + tay + lda value+1 + ldx #$f + axs #0 + sty utoa16n.started + lda #<dst + sta utoa16n.dst + lda #>dst + sta utoa16n.dst+1 + jsr utoa16n + lda utoa16n.return + tay + lda value + lsr + lsr + lsr + lsr + tax + sty utoa16n.started + lda #<dst + sta utoa16n.dst + lda #>dst + sta utoa16n.dst+1 + jsr utoa16n + lda value + ldx #$f + axs #0 + lda #<dst + sta utoa16n.dst + lda #>dst + sta utoa16n.dst+1 + lda #1 + sta utoa16n.started + jsr utoa16n + lda #0 + tay + sta (dst),y + rts +} +// Hexadecimal utoa() for a single nybble +// utoa16n(byte register(X) nybble, word** zeropage(6) dst, byte zeropage(8) started) +utoa16n: { + .label started = 8 + .label return = 8 + .label dst = 6 + cpx #0 + beq b1 + lda #1 + sta return + b1: + lda return + cmp #0 + beq breturn + ldy #0 + lda dst + sta !++1 + lda DIGITS,x + !: + sta (dst),y + ldy #0 + lda (dst),y + clc + adc #1 + sta (dst),y + breturn: + rts +} +cls: { + .label screen = $400 + .label sc = 2 + lda #<screen + sta sc + lda #>screen + sta sc+1 + b1: + lda #' ' + ldy #0 + sta (sc),y + inc sc + bne !+ + inc sc+1 + !: + lda sc+1 + cmp #>screen+$3e7+1 + bne b1 + lda sc + cmp #<screen+$3e7+1 + bne b1 + rts +} + // Digits used for utoa() + DIGITS: .text "0123456789abcdef@" From 5f2b798a8aeb763034e0b63b744a13302f322e03 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 21 May 2019 10:23:39 +0200 Subject: [PATCH 60/93] Added test for pointer-to-pointer optimization. --- .../fragment/_deref__deref_pptc1=vbuaa.asm | 2 + ...eref__deref_pptz1=pbuc1_derefidx_vbuxx.asm | 2 +- .../fragment/_deref__deref_pptz1=vbuaa.asm | 4 ++ .../_deref_pptc1=_inc__deref_pptc1.asm | 4 ++ .../dk/camelot64/kickc/test/TestPrograms.java | 20 ++++++ src/test/kc/ptrptr-optimize-0.kc | 8 +++ src/test/kc/ptrptr-optimize-1.kc | 11 ++++ src/test/kc/ptrptr-optimize-2.kc | 11 ++++ src/test/kc/subexpr-optimize-0.kc | 10 +++ src/test/ref/hex2dec-ptrptr.asm | 62 ++++++++----------- src/test/ref/ptrptr-optimize-0.asm | 23 +++++++ src/test/ref/ptrptr-optimize-1.asm | 27 ++++++++ src/test/ref/ptrptr-optimize-2.asm | 41 ++++++++++++ src/test/ref/subexpr-optimize-0.asm | 38 ++++++++++++ 14 files changed, 225 insertions(+), 38 deletions(-) create mode 100644 src/main/fragment/_deref__deref_pptc1=vbuaa.asm create mode 100644 src/main/fragment/_deref__deref_pptz1=vbuaa.asm create mode 100644 src/main/fragment/_deref_pptc1=_inc__deref_pptc1.asm create mode 100644 src/test/kc/ptrptr-optimize-0.kc create mode 100644 src/test/kc/ptrptr-optimize-1.kc create mode 100644 src/test/kc/ptrptr-optimize-2.kc create mode 100644 src/test/kc/subexpr-optimize-0.kc create mode 100644 src/test/ref/ptrptr-optimize-0.asm create mode 100644 src/test/ref/ptrptr-optimize-1.asm create mode 100644 src/test/ref/ptrptr-optimize-2.asm create mode 100644 src/test/ref/subexpr-optimize-0.asm diff --git a/src/main/fragment/_deref__deref_pptc1=vbuaa.asm b/src/main/fragment/_deref__deref_pptc1=vbuaa.asm new file mode 100644 index 000000000..a674d8937 --- /dev/null +++ b/src/main/fragment/_deref__deref_pptc1=vbuaa.asm @@ -0,0 +1,2 @@ +ldy #0 +sta ({c1}),y diff --git a/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm b/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm index 8f14bd50e..1d22175ee 100644 --- a/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm +++ b/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm @@ -2,4 +2,4 @@ ldy #0 lda {z1} sta !+ +1 lda {c1},x -!: sta ({z1}),y +!: sta ($ff),y diff --git a/src/main/fragment/_deref__deref_pptz1=vbuaa.asm b/src/main/fragment/_deref__deref_pptz1=vbuaa.asm new file mode 100644 index 000000000..6516b7db1 --- /dev/null +++ b/src/main/fragment/_deref__deref_pptz1=vbuaa.asm @@ -0,0 +1,4 @@ +ldy {z1} +sty !+ +1 +ldy #0 +!: sta ($ff),y diff --git a/src/main/fragment/_deref_pptc1=_inc__deref_pptc1.asm b/src/main/fragment/_deref_pptc1=_inc__deref_pptc1.asm new file mode 100644 index 000000000..39191f06b --- /dev/null +++ b/src/main/fragment/_deref_pptc1=_inc__deref_pptc1.asm @@ -0,0 +1,4 @@ +inc {c1} +bne !+ +inc {c1}+1 +!: \ No newline at end of file diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 319f189f0..2b81406b6 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,6 +63,26 @@ public class TestPrograms { */ + @Test + public void testSubExprOptimize0() throws IOException, URISyntaxException { + compileAndCompare("subexpr-optimize-0"); + } + + @Test + public void testPtrPtrOptimize2() throws IOException, URISyntaxException { + compileAndCompare("ptrptr-optimize-2"); + } + + @Test + public void testPtrPtrOptimize1() throws IOException, URISyntaxException { + compileAndCompare("ptrptr-optimize-1"); + } + + @Test + public void testPtrPtrOptimize0() throws IOException, URISyntaxException { + compileAndCompare("ptrptr-optimize-0"); + } + @Test public void testHex2DecPtrPtr() throws IOException, URISyntaxException { compileAndCompare("hex2dec-ptrptr"); diff --git a/src/test/kc/ptrptr-optimize-0.kc b/src/test/kc/ptrptr-optimize-0.kc new file mode 100644 index 000000000..c615190e5 --- /dev/null +++ b/src/test/kc/ptrptr-optimize-0.kc @@ -0,0 +1,8 @@ +// Tests optimization of constant pointers to pointers +void main() { + byte* screen = 0x400; + byte** pscreen = &screen; + **pscreen = 'a'; + (*pscreen)++; + **pscreen = 'b'; +} \ No newline at end of file diff --git a/src/test/kc/ptrptr-optimize-1.kc b/src/test/kc/ptrptr-optimize-1.kc new file mode 100644 index 000000000..5e78562a3 --- /dev/null +++ b/src/test/kc/ptrptr-optimize-1.kc @@ -0,0 +1,11 @@ +// Tests optimization of constant pointers to pointers +void main() { + byte* screen = 0x400; + byte** pscreen = &screen; + sub('a',pscreen); + sub('b',pscreen); +} + +void sub(unsigned char ch, unsigned char **dst) { + *(*dst)++ = ch; +} diff --git a/src/test/kc/ptrptr-optimize-2.kc b/src/test/kc/ptrptr-optimize-2.kc new file mode 100644 index 000000000..5b76ac29e --- /dev/null +++ b/src/test/kc/ptrptr-optimize-2.kc @@ -0,0 +1,11 @@ +// Tests (non-)optimization of constant pointers to pointers +// The two examples of &screen is not detected as identical leading to ASM that could be optimized more +void main() { + byte* screen = 0x400; + sub('a',&screen); + sub('b',&screen); +} + +void sub(unsigned char ch, unsigned char **dst) { + *(*dst)++ = ch; +} diff --git a/src/test/kc/subexpr-optimize-0.kc b/src/test/kc/subexpr-optimize-0.kc new file mode 100644 index 000000000..52588128f --- /dev/null +++ b/src/test/kc/subexpr-optimize-0.kc @@ -0,0 +1,10 @@ +// Tests (non-)optimization of identical sub-expressions +// The two examples of i+1 is not detected as identical leading to ASM that could be optimized more +void main() { + byte* screen = 0x400; + for( byte i: 0..2) { + *screen++ = i+1; + *screen++ = i+1; + } +} + diff --git a/src/test/ref/hex2dec-ptrptr.asm b/src/test/ref/hex2dec-ptrptr.asm index 6dcb61501..3c58ffe2c 100644 --- a/src/test/ref/hex2dec-ptrptr.asm +++ b/src/test/ref/hex2dec-ptrptr.asm @@ -60,48 +60,40 @@ utoa16w: { lsr lsr lsr - tax + tay lda #<dst sta utoa16n.dst lda #>dst sta utoa16n.dst+1 - lda #0 - sta utoa16n.started + ldx #0 jsr utoa16n - lda utoa16n.return - tay lda value+1 - ldx #$f - axs #0 - sty utoa16n.started - lda #<dst - sta utoa16n.dst - lda #>dst - sta utoa16n.dst+1 - jsr utoa16n - lda utoa16n.return + and #$f tay - lda value - lsr - lsr - lsr - lsr - tax - sty utoa16n.started lda #<dst sta utoa16n.dst lda #>dst sta utoa16n.dst+1 jsr utoa16n lda value - ldx #$f - axs #0 + lsr + lsr + lsr + lsr + tay lda #<dst sta utoa16n.dst lda #>dst sta utoa16n.dst+1 - lda #1 - sta utoa16n.started + jsr utoa16n + lda value + and #$f + tay + lda #<dst + sta utoa16n.dst + lda #>dst + sta utoa16n.dst+1 + ldx #1 jsr utoa16n lda #0 tay @@ -109,25 +101,21 @@ utoa16w: { rts } // Hexadecimal utoa() for a single nybble -// utoa16n(byte register(X) nybble, word** zeropage(6) dst, byte zeropage(8) started) +// utoa16n(byte register(Y) nybble, word** zeropage(6) dst, byte register(X) started) utoa16n: { - .label started = 8 - .label return = 8 .label dst = 6 - cpx #0 + cpy #0 beq b1 - lda #1 - sta return + ldx #1 b1: - lda return - cmp #0 + cpx #0 beq breturn + lda DIGITS,y + ldy dst + sty !++1 ldy #0 - lda dst - sta !++1 - lda DIGITS,x !: - sta (dst),y + sta ($ff),y ldy #0 lda (dst),y clc diff --git a/src/test/ref/ptrptr-optimize-0.asm b/src/test/ref/ptrptr-optimize-0.asm new file mode 100644 index 000000000..bcfea43c8 --- /dev/null +++ b/src/test/ref/ptrptr-optimize-0.asm @@ -0,0 +1,23 @@ +// Tests optimization of constant pointers to pointers +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label pscreen = screen + .label screen = 2 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + lda #'a' + ldy #0 + sta (pscreen),y + inc pscreen + bne !+ + inc pscreen+1 + !: + lda #'b' + ldy #0 + sta (pscreen),y + rts +} diff --git a/src/test/ref/ptrptr-optimize-1.asm b/src/test/ref/ptrptr-optimize-1.asm new file mode 100644 index 000000000..5bb1ace96 --- /dev/null +++ b/src/test/ref/ptrptr-optimize-1.asm @@ -0,0 +1,27 @@ +// Tests optimization of constant pointers to pointers +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label pscreen = screen + .label screen = 2 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + lda #'a' + jsr sub + lda #'b' + jsr sub + rts +} +// sub(byte register(A) ch) +sub: { + ldy #0 + sta (main.pscreen),y + inc main.pscreen + bne !+ + inc main.pscreen+1 + !: + rts +} diff --git a/src/test/ref/ptrptr-optimize-2.asm b/src/test/ref/ptrptr-optimize-2.asm new file mode 100644 index 000000000..0105bd47d --- /dev/null +++ b/src/test/ref/ptrptr-optimize-2.asm @@ -0,0 +1,41 @@ +// Tests (non-)optimization of constant pointers to pointers +// The two examples of &screen is not detected as identical leading to ASM that could be optimized more +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = 2 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + lda #<screen + sta sub.dst + lda #>screen + sta sub.dst+1 + ldx #'a' + jsr sub + lda #<screen + sta sub.dst + lda #>screen + sta sub.dst+1 + ldx #'b' + jsr sub + rts +} +// sub(byte register(X) ch, byte** zeropage(2) dst) +sub: { + .label dst = 2 + txa + ldy dst + sty !++1 + ldy #0 + !: + sta ($ff),y + ldy #0 + lda (dst),y + clc + adc #1 + sta (dst),y + rts +} diff --git a/src/test/ref/subexpr-optimize-0.asm b/src/test/ref/subexpr-optimize-0.asm new file mode 100644 index 000000000..c282ef851 --- /dev/null +++ b/src/test/ref/subexpr-optimize-0.asm @@ -0,0 +1,38 @@ +// Tests (non-)optimization of identical sub-expressions +// The two examples of i+1 is not detected as identical leading to ASM that could be optimized more +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = 2 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + ldx #0 + b1: + txa + tay + iny + tya + ldy #0 + sta (screen),y + inc screen + bne !+ + inc screen+1 + !: + txa + tay + iny + tya + ldy #0 + sta (screen),y + inc screen + bne !+ + inc screen+1 + !: + inx + cpx #3 + bne b1 + rts +} From c1213f4d55d116ba6f6f831afbd975dfdfac78b2 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Tue, 21 May 2019 23:06:13 +0200 Subject: [PATCH 61/93] Added right side duplicate identification. --- .../java/dk/camelot64/kickc/Compiler.java | 1 + .../kickc/model/iterator/ProgramValue.java | 4 +- .../Pass2DuplicateRValueIdentification.java | 132 ++++++++++++++++++ 3 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 67ca190b1..8449ab3f8 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -268,6 +268,7 @@ public class Compiler { optimizations.add(new PassNSimplifyExpressionWithZero(program)); optimizations.add(new PassNEliminateUnusedVars(program, true)); optimizations.add(new Pass2EliminateUnusedBlocks(program)); + optimizations.add(new Pass2DuplicateRValueIdentification(program)); pass2Execute(optimizations); } diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java index 551863bf9..0477f39ef 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java @@ -23,7 +23,7 @@ public interface ProgramValue { class RValue1 implements ProgramValue { private final StatementAssignment statement; - RValue1(StatementAssignment statement) { + public RValue1(StatementAssignment statement) { this.statement = statement; } @@ -41,7 +41,7 @@ public interface ProgramValue { class RValue2 implements ProgramValue { private final StatementAssignment statement; - RValue2(StatementAssignment statement) { + public RValue2(StatementAssignment statement) { this.statement = statement; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java new file mode 100644 index 000000000..2abdb07f0 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java @@ -0,0 +1,132 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramValue; +import dk.camelot64.kickc.model.iterator.ProgramValueHandler; +import dk.camelot64.kickc.model.iterator.ProgramValueIterator; +import dk.camelot64.kickc.model.operators.Operator; +import dk.camelot64.kickc.model.operators.OperatorCast; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.symbols.Variable; +import dk.camelot64.kickc.model.values.ConstantValue; +import dk.camelot64.kickc.model.values.PointerDereference; +import dk.camelot64.kickc.model.values.RValue; +import dk.camelot64.kickc.model.values.VariableRef; + +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Compiler Pass identifying R-values that are duplicates of each other - and consolidates them to a single RValue. + */ +public class Pass2DuplicateRValueIdentification extends Pass2SsaOptimization { + + public Pass2DuplicateRValueIdentification(Program program) { + super(program); + } + + @Override + public boolean step() { + boolean modified = false; + + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + Set<AssignmentRValue> rValues = new HashSet<>(); + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementAssignment) { + StatementAssignment assignment = (StatementAssignment) statement; + AssignmentRValue assignmentRValue = new AssignmentRValue(assignment, block); + if(!assignmentRValue.isConstant() && !assignmentRValue.isTrivial() && !assignmentRValue.isVolatile()) { + if(rValues.contains(assignmentRValue)) { + AssignmentRValue firstAssignment = rValues.stream().filter(assignmentRValue1 -> assignmentRValue1.equals(assignmentRValue)).findFirst().get(); + if(firstAssignment.assignment.getlValue() instanceof VariableRef) { + getLog().append("Identified duplicate assignment right side "+assignment.toString(getProgram(), false)); + assignment.setrValue1(null); + assignment.setOperator(null); + assignment.setrValue2(firstAssignment.assignment.getlValue()); + modified = true; + } else { + throw new InternalError("Complex lValue for duplicate rvalue "+firstAssignment.assignment.toString(getProgram(), false)); + } + } else { + rValues.add(assignmentRValue); + } + } + } + } + } + return modified; + } + + + /** + * Represents an RValue of an assignment. + * Implements equals() and hashcode() to allow identification of duplicate RValues + */ + private class AssignmentRValue { + private ControlFlowBlock block; + private StatementAssignment assignment; + private RValue rValue1; + private Operator operator; + private RValue rValue2; + + public AssignmentRValue(StatementAssignment assignment, ControlFlowBlock block) { + this.block = block; + this.assignment = assignment; + this.rValue1 = assignment.getrValue1(); + this.operator = assignment.getOperator(); + this.rValue2 = assignment.getrValue2(); + } + + private boolean isConstant() { + if(rValue1 != null && !(rValue1 instanceof ConstantValue)) + return false; + if(rValue2 != null && !(rValue2 instanceof ConstantValue)) + return false; + return true; + } + + private boolean isVolatile() { + AtomicBoolean isVol = new AtomicBoolean(false); + ProgramValueHandler identifyVolatiles = (programValue, currentStmt, stmtIt, currentBlock) -> { + if(programValue.get() instanceof PointerDereference) + isVol.set(true); + if(programValue.get() instanceof VariableRef) { + Variable variable = getScope().getVariable((VariableRef) programValue.get()); + if(variable.isDeclaredVolatile()) + isVol.set(true); + } + }; + ProgramValueIterator.execute(new ProgramValue.RValue1(assignment), identifyVolatiles, assignment, null, null); + ProgramValueIterator.execute(new ProgramValue.RValue2(assignment), identifyVolatiles, assignment, null, null); + if(Operators.DEREF.equals(operator) || Operators.DEREF_IDX.equals(operator)) + isVol.set(true); + return isVol.get(); + } + + private boolean isTrivial() { + if(operator == null) return true; + if(operator instanceof OperatorCast) return true; + return false; + } + + + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + AssignmentRValue that = (AssignmentRValue) o; + return Objects.equals(rValue1, that.rValue1) && + Objects.equals(operator, that.operator) && + Objects.equals(rValue2, that.rValue2); + } + + @Override + public int hashCode() { + return Objects.hash(rValue1, operator, rValue2); + } + + } +} From 2c808e59d6a9a6a2589ab4d379c24641710f017d Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Wed, 22 May 2019 08:06:54 +0200 Subject: [PATCH 62/93] Added tests for duplicate assignment right side optimization. --- .../Pass2DuplicateRValueIdentification.java | 13 +++++ .../dk/camelot64/kickc/test/TestPrograms.java | 5 ++ src/test/kc/subexpr-optimize-0.kc | 4 +- src/test/kc/subexpr-optimize-1.kc | 12 +++++ src/test/ref/complex/tetris/tetris.asm | 21 ++++----- src/test/ref/examples/3d/perspective.asm | 47 ++++++++----------- .../multiplexer/simple-multiplexer.asm | 12 ++--- src/test/ref/line-anim.asm | 34 +++++--------- .../simple-multiplexer-irq.asm | 12 ++--- src/test/ref/roll-sprite-msb.asm | 3 -- src/test/ref/subexpr-optimize-0.asm | 11 ++--- src/test/ref/subexpr-optimize-1.asm | 21 +++++++++ src/test/ref/test-division.asm | 30 +++++------- 13 files changed, 117 insertions(+), 108 deletions(-) create mode 100644 src/test/kc/subexpr-optimize-1.kc create mode 100644 src/test/ref/subexpr-optimize-1.asm diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java index 2abdb07f0..3e3a5ebe3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java @@ -109,6 +109,19 @@ public class Pass2DuplicateRValueIdentification extends Pass2SsaOptimization { private boolean isTrivial() { if(operator == null) return true; if(operator instanceof OperatorCast) return true; + if(operator.equals(Operators.PLUS)) return true; + if(operator.equals(Operators.MINUS)) return true; + if(operator.equals(Operators.BOOL_AND)) return true; + if(operator.equals(Operators.BOOL_OR)) return true; + if(operator.equals(Operators.BOOL_XOR)) return true; + if(operator.equals(Operators.BOOL_NOT)) return true; + if(operator.equals(Operators.LE)) return true; + if(operator.equals(Operators.LT)) return true; + if(operator.equals(Operators.GE)) return true; + if(operator.equals(Operators.GT)) return true; + if(operator.equals(Operators.EQ)) return true; + if(operator.equals(Operators.NEQ)) return true; + if(operator.equals(Operators.LOGIC_NOT)) return true; return false; } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 2b81406b6..338a622e5 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,6 +63,11 @@ public class TestPrograms { */ + @Test + public void testSubExprOptimize1() throws IOException, URISyntaxException { + compileAndCompare("subexpr-optimize-1"); + } + @Test public void testSubExprOptimize0() throws IOException, URISyntaxException { compileAndCompare("subexpr-optimize-0"); diff --git a/src/test/kc/subexpr-optimize-0.kc b/src/test/kc/subexpr-optimize-0.kc index 52588128f..78ec0430f 100644 --- a/src/test/kc/subexpr-optimize-0.kc +++ b/src/test/kc/subexpr-optimize-0.kc @@ -3,8 +3,8 @@ void main() { byte* screen = 0x400; for( byte i: 0..2) { - *screen++ = i+1; - *screen++ = i+1; + *screen++ = i*2; + *screen++ = i*2; } } diff --git a/src/test/kc/subexpr-optimize-1.kc b/src/test/kc/subexpr-optimize-1.kc new file mode 100644 index 000000000..4fdabcfce --- /dev/null +++ b/src/test/kc/subexpr-optimize-1.kc @@ -0,0 +1,12 @@ +// A sub-expression that should not be optimized (+1 to a pointer) + +void main() { + byte* SCREEN = 0x0400; + for(byte i: 0..38) { + SCREEN[i] = SCREEN[i+1]; + (SCREEN+40)[i] = (SCREEN+40)[i+1]; + (SCREEN+80)[i] = (SCREEN+80)[i+1]; + (SCREEN+120)[i] = (SCREEN+120)[i+1]; + } + +} \ No newline at end of file diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm index 2ffbfb4d9..663c44f97 100644 --- a/src/test/ref/complex/tetris/tetris.asm +++ b/src/test/ref/complex/tetris/tetris.asm @@ -1412,22 +1412,19 @@ render_init: { sta li_1 lda #>PLAYFIELD_SCREEN_1+2*$28+$10 sta li_1+1 - ldx #0 + ldy #0 b1: - txa + tya asl - tay + tax lda li_1 - sta screen_lines_1,y + sta screen_lines_1,x lda li_1+1 - sta screen_lines_1+1,y - txa - asl - tay + sta screen_lines_1+1,x lda li_2 - sta screen_lines_2,y + sta screen_lines_2,x lda li_2+1 - sta screen_lines_2+1,y + sta screen_lines_2+1,x lda #$28 clc adc li_1 @@ -1442,8 +1439,8 @@ render_init: { bcc !+ inc li_2+1 !: - inx - cpx #PLAYFIELD_LINES-1+1 + iny + cpy #PLAYFIELD_LINES-1+1 bne b1 rts } diff --git a/src/test/ref/examples/3d/perspective.asm b/src/test/ref/examples/3d/perspective.asm index 313e08cfb..878c3f046 100644 --- a/src/test/ref/examples/3d/perspective.asm +++ b/src/test/ref/examples/3d/perspective.asm @@ -244,42 +244,35 @@ mulf_init: { sta add lda #0 sta add+1 - tax + tay sta sqr sta sqr+1 b1: lda sqr+1 sta val + sta mulf_sqr1,y + sta mulf_sqr1+$100,y + tya + eor #$ff + tax + inx + lda val sta mulf_sqr1,x sta mulf_sqr1+$100,x - txa + sta mulf_sqr2+1,y + sta mulf_sqr2+$100+1,y + tya eor #$ff - tay - iny + tax + axs #1+1 lda val - sta mulf_sqr1,y - txa + sta mulf_sqr2,x + tya eor #$ff - tay - iny + tax + axs #1+1 lda val - sta mulf_sqr1+$100,y - sta mulf_sqr2+1,x - sta mulf_sqr2+$100+1,x - txa - eor #$ff - clc - adc #1+1 - tay - lda val - sta mulf_sqr2,y - txa - eor #$ff - clc - adc #1+1 - tay - lda val - sta mulf_sqr2+$100,y + sta mulf_sqr2+$100,x lda sqr clc adc add @@ -294,8 +287,8 @@ mulf_init: { bcc !+ inc add+1 !: - inx - cpx #$81 + iny + cpy #$81 bne b1 rts } diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm index c581edf00..ab1e3bf7b 100644 --- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm +++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm @@ -120,17 +120,13 @@ plexShowSprite: { ldx plex_sprite_idx sta PLEX_SCREEN_PTR,x ldy plex_show_idx - ldx PLEX_SORTED_IDX,y - txa + lda PLEX_SORTED_IDX,y asl - tay - lda PLEX_XPOS,y + tax + lda PLEX_XPOS,x ldy plex_sprite_idx2 sta SPRITES_XPOS,y - txa - asl - tay - lda PLEX_XPOS+1,y + lda PLEX_XPOS+1,x cmp #0 bne b1 lda #$ff diff --git a/src/test/ref/line-anim.asm b/src/test/ref/line-anim.asm index bd6739ae0..796e154ef 100644 --- a/src/test/ref/line-anim.asm +++ b/src/test/ref/line-anim.asm @@ -127,17 +127,14 @@ point_init: { .label x_diff = 9 lda point_idx asl - tay - lda x_end,y + tax + lda x_end,x sta _0 - lda x_end+1,y + lda x_end+1,x sta _0+1 - lda point_idx - asl - tay - lda x_start,y + lda x_start,x sta _1 - lda x_start+1,y + lda x_start+1,x sta _1+1 lda x_diff sec @@ -191,10 +188,10 @@ point_init: { b2: lda point_idx asl - tay - lda x_start,y + tax + lda x_start,x sta _9 - lda x_start+1,y + lda x_start+1,x sta _9+1 asl _9 rol _9+1 @@ -204,13 +201,10 @@ point_init: { rol _9+1 asl _9 rol _9+1 - lda point_idx - asl - tay lda _9 - sta x_cur,y + sta x_cur,x lda _9+1 - sta x_cur+1,y + sta x_cur+1,x ldy point_idx lda y_start,y sta _10 @@ -224,15 +218,11 @@ point_init: { rol _11+1 asl _11 rol _11+1 - tya - asl - tay lda _11 - sta y_cur,y + sta y_cur,x lda _11+1 - sta y_cur+1,y + sta y_cur+1,x lda #DELAY - ldy point_idx sta delay,y rts b1: diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm index 8b97b383b..32a1fc283 100644 --- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm +++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm @@ -290,17 +290,13 @@ plexShowSprite: { ldx plex_sprite_idx sta PLEX_SCREEN_PTR,x ldy plex_show_idx - ldx PLEX_SORTED_IDX,y - txa + lda PLEX_SORTED_IDX,y asl - tay - lda PLEX_XPOS,y + tax + lda PLEX_XPOS,x ldy plex_sprite_idx2 sta SPRITES_XPOS,y - txa - asl - tay - lda PLEX_XPOS+1,y + lda PLEX_XPOS+1,x cmp #0 bne b1 lda #$ff diff --git a/src/test/ref/roll-sprite-msb.asm b/src/test/ref/roll-sprite-msb.asm index 80b22ddde..e338a5605 100644 --- a/src/test/ref/roll-sprite-msb.asm +++ b/src/test/ref/roll-sprite-msb.asm @@ -37,9 +37,6 @@ position_sprite: { tay lda #y sta SPRITES_YPOS,y - lda spriteno - asl - tay lda x sta SPRITES_XPOS,y lda x+1 diff --git a/src/test/ref/subexpr-optimize-0.asm b/src/test/ref/subexpr-optimize-0.asm index c282ef851..dd03a4605 100644 --- a/src/test/ref/subexpr-optimize-0.asm +++ b/src/test/ref/subexpr-optimize-0.asm @@ -4,6 +4,7 @@ :BasicUpstart(main) .pc = $80d "Program" main: { + .label _1 = 4 .label screen = 2 lda #<$400 sta screen @@ -12,19 +13,15 @@ main: { ldx #0 b1: txa - tay - iny - tya + asl + sta _1 ldy #0 sta (screen),y inc screen bne !+ inc screen+1 !: - txa - tay - iny - tya + lda _1 ldy #0 sta (screen),y inc screen diff --git a/src/test/ref/subexpr-optimize-1.asm b/src/test/ref/subexpr-optimize-1.asm new file mode 100644 index 000000000..df54827e6 --- /dev/null +++ b/src/test/ref/subexpr-optimize-1.asm @@ -0,0 +1,21 @@ +// A sub-expression that should not be optimized (+1 to a pointer) +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label SCREEN = $400 + ldx #0 + b1: + lda SCREEN+1,x + sta SCREEN,x + lda SCREEN+$28+1,x + sta SCREEN+$28,x + lda SCREEN+$50+1,x + sta SCREEN+$50,x + lda SCREEN+$78+1,x + sta SCREEN+$78,x + inx + cpx #$27 + bne b1 + rts +} diff --git a/src/test/ref/test-division.asm b/src/test/ref/test-division.asm index d7b963748..cd75806a1 100644 --- a/src/test/ref/test-division.asm +++ b/src/test/ref/test-division.asm @@ -24,17 +24,14 @@ test_16s: { b1: lda i asl - tay - lda dividends,y + tax + lda dividends,x sta dividend - lda dividends+1,y + lda dividends+1,x sta dividend+1 - lda i - asl - tay - lda divisors,y + lda divisors,x sta divisor - lda divisors+1,y + lda divisors+1,x sta divisor+1 jsr div16s lda print_line_cursor @@ -76,9 +73,7 @@ test_16s: { inc i lda #6 cmp i - beq !b1+ - jmp b1 - !b1: + bne b1 rts dividends: .word $7fff, $7fff, -$7fff, -$7fff, $7fff, -$7fff divisors: .word 5, -7, $b, -$d, -$11, $13 @@ -539,17 +534,14 @@ test_16u: { b1: lda i asl - tay - lda dividends,y + tax + lda dividends,x sta dividend - lda dividends+1,y + lda dividends+1,x sta dividend+1 - lda i - asl - tay - lda divisors,y + lda divisors,x sta divisor - lda divisors+1,y + lda divisors+1,x sta divisor+1 jsr div16u lda print_line_cursor From 67db0f0f6f13df48edc56950758f0bd19ca06c3d Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Wed, 22 May 2019 08:19:43 +0200 Subject: [PATCH 63/93] Improved duplicate assignment right side optimization slightly. --- .../Pass2DuplicateRValueIdentification.java | 6 ++---- src/test/ref/bitmap-plotter.asm | 11 +++++----- src/test/ref/bool-ifs.asm | 21 ++++++++----------- .../examples/bresenham/bitmap-bresenham.asm | 11 +++++----- .../ref/examples/sinplotter/sine-plotter.asm | 11 +++++----- src/test/ref/line-anim.asm | 11 +++++----- 6 files changed, 31 insertions(+), 40 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java index 3e3a5ebe3..09f8fa690 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java @@ -111,10 +111,6 @@ public class Pass2DuplicateRValueIdentification extends Pass2SsaOptimization { if(operator instanceof OperatorCast) return true; if(operator.equals(Operators.PLUS)) return true; if(operator.equals(Operators.MINUS)) return true; - if(operator.equals(Operators.BOOL_AND)) return true; - if(operator.equals(Operators.BOOL_OR)) return true; - if(operator.equals(Operators.BOOL_XOR)) return true; - if(operator.equals(Operators.BOOL_NOT)) return true; if(operator.equals(Operators.LE)) return true; if(operator.equals(Operators.LT)) return true; if(operator.equals(Operators.GE)) return true; @@ -122,6 +118,8 @@ public class Pass2DuplicateRValueIdentification extends Pass2SsaOptimization { if(operator.equals(Operators.EQ)) return true; if(operator.equals(Operators.NEQ)) return true; if(operator.equals(Operators.LOGIC_NOT)) return true; + if(operator.equals(Operators.LOGIC_AND)) return true; + if(operator.equals(Operators.LOGIC_OR)) return true; return false; } diff --git a/src/test/ref/bitmap-plotter.asm b/src/test/ref/bitmap-plotter.asm index 4554d3c63..7762f5817 100644 --- a/src/test/ref/bitmap-plotter.asm +++ b/src/test/ref/bitmap-plotter.asm @@ -81,7 +81,7 @@ plot: { rts } init_plot_tables: { - .label _6 = 4 + .label _10 = 4 .label yoffs = 2 ldy #$80 ldx #0 @@ -109,15 +109,14 @@ init_plot_tables: { tax b3: lda #7 - sax _6 + sax _10 lda yoffs - ora _6 + ora _10 sta plot_ylo,x lda yoffs+1 sta plot_yhi,x - txa - and #7 - cmp #7 + lda #7 + cmp _10 bne b4 clc lda yoffs diff --git a/src/test/ref/bool-ifs.asm b/src/test/ref/bool-ifs.asm index c5dacee64..0fc00115b 100644 --- a/src/test/ref/bool-ifs.asm +++ b/src/test/ref/bool-ifs.asm @@ -11,34 +11,31 @@ main: { } bool_complex: { .label screen = $478 - ldy #0 + ldx #0 b1: - ldx #1 - tya - axs #0 - tya + txa and #1 - cpy #$a + cpx #$a bcc b6 b5: - cpy #$a + cpx #$a bcc b4 cmp #0 beq b4 b2: lda #'*' - sta screen,y + sta screen,x b3: - iny - cpy #$15 + inx + cpx #$15 bne b1 rts b4: lda #' ' - sta screen,y + sta screen,x jmp b3 b6: - cpx #0 + cmp #0 beq b2 jmp b5 } diff --git a/src/test/ref/examples/bresenham/bitmap-bresenham.asm b/src/test/ref/examples/bresenham/bitmap-bresenham.asm index 9c513d6a8..c6f38704b 100644 --- a/src/test/ref/examples/bresenham/bitmap-bresenham.asm +++ b/src/test/ref/examples/bresenham/bitmap-bresenham.asm @@ -364,7 +364,7 @@ bitmap_clear: { } // Initialize the bitmap plotter tables for a specific bitmap bitmap_init: { - .label _6 = 2 + .label _10 = 2 .label yoffs = 9 ldy #$80 ldx #0 @@ -392,15 +392,14 @@ bitmap_init: { tax b3: lda #7 - sax _6 + sax _10 lda yoffs - ora _6 + ora _10 sta bitmap_plot_ylo,x lda yoffs+1 sta bitmap_plot_yhi,x - txa - and #7 - cmp #7 + lda #7 + cmp _10 bne b4 clc lda yoffs diff --git a/src/test/ref/examples/sinplotter/sine-plotter.asm b/src/test/ref/examples/sinplotter/sine-plotter.asm index 341d95d20..e86b7ba4e 100644 --- a/src/test/ref/examples/sinplotter/sine-plotter.asm +++ b/src/test/ref/examples/sinplotter/sine-plotter.asm @@ -757,7 +757,7 @@ bitmap_clear: { } // Initialize bitmap plotting tables bitmap_init: { - .label _3 = $16 + .label _7 = $16 .label yoffs = 2 ldx #0 lda #$80 @@ -778,15 +778,14 @@ bitmap_init: { ldx #0 b3: lda #7 - sax _3 + sax _7 lda yoffs - ora _3 + ora _7 sta bitmap_plot_ylo,x lda yoffs+1 sta bitmap_plot_yhi,x - txa - and #7 - cmp #7 + lda #7 + cmp _7 bne b4 clc lda yoffs diff --git a/src/test/ref/line-anim.asm b/src/test/ref/line-anim.asm index 796e154ef..e787357ed 100644 --- a/src/test/ref/line-anim.asm +++ b/src/test/ref/line-anim.asm @@ -455,7 +455,7 @@ bitmap_clear: { rts } bitmap_init: { - .label _3 = 2 + .label _7 = 2 .label yoffs = 3 ldx #0 lda #$80 @@ -476,15 +476,14 @@ bitmap_init: { ldx #0 b3: lda #7 - sax _3 + sax _7 lda yoffs - ora _3 + ora _7 sta bitmap_plot_ylo,x lda yoffs+1 sta bitmap_plot_yhi,x - txa - and #7 - cmp #7 + lda #7 + cmp _7 bne b4 clc lda yoffs From 39c4f0d6b4d1a24bf76b8d5d3d048b7cb244e3f8 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Wed, 22 May 2019 15:29:47 +0200 Subject: [PATCH 64/93] Fixed identification of identical Phi RValues that are constant pointers to symbols. --- src/main/fragment/_deref_pptc1=pbuz1.asm | 4 ++ .../model/values/ConstantSymbolPointer.java | 16 ++++++++ src/test/ref/hex2dec-ptrptr.asm | 38 ++++--------------- src/test/ref/pointer-pointer-3.asm | 19 ++-------- src/test/ref/ptrptr-optimize-2.asm | 28 ++++---------- 5 files changed, 38 insertions(+), 67 deletions(-) create mode 100644 src/main/fragment/_deref_pptc1=pbuz1.asm diff --git a/src/main/fragment/_deref_pptc1=pbuz1.asm b/src/main/fragment/_deref_pptc1=pbuz1.asm new file mode 100644 index 000000000..0e0382e79 --- /dev/null +++ b/src/main/fragment/_deref_pptc1=pbuz1.asm @@ -0,0 +1,4 @@ +lda {z1} +sta {c1} +lda {z1}+1 +sta {c1}+1 \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantSymbolPointer.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantSymbolPointer.java index 4474cb416..4f7c079a9 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantSymbolPointer.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantSymbolPointer.java @@ -6,6 +6,8 @@ import dk.camelot64.kickc.model.symbols.Symbol; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; +import java.util.Objects; + /** A pointer to a symbol (variable or procedure) */ public class ConstantSymbolPointer implements ConstantValue { @@ -44,4 +46,18 @@ public class ConstantSymbolPointer implements ConstantValue { public String toString() { return toString(null); } + + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + ConstantSymbolPointer that = (ConstantSymbolPointer) o; + return Objects.equals(toSymbol, that.toSymbol); + } + + @Override + public int hashCode() { + + return Objects.hash(toSymbol); + } } diff --git a/src/test/ref/hex2dec-ptrptr.asm b/src/test/ref/hex2dec-ptrptr.asm index 3c58ffe2c..af42a6775 100644 --- a/src/test/ref/hex2dec-ptrptr.asm +++ b/src/test/ref/hex2dec-ptrptr.asm @@ -60,39 +60,19 @@ utoa16w: { lsr lsr lsr - tay - lda #<dst - sta utoa16n.dst - lda #>dst - sta utoa16n.dst+1 ldx #0 jsr utoa16n lda value+1 and #$f - tay - lda #<dst - sta utoa16n.dst - lda #>dst - sta utoa16n.dst+1 jsr utoa16n lda value lsr lsr lsr lsr - tay - lda #<dst - sta utoa16n.dst - lda #>dst - sta utoa16n.dst+1 jsr utoa16n lda value and #$f - tay - lda #<dst - sta utoa16n.dst - lda #>dst - sta utoa16n.dst+1 ldx #1 jsr utoa16n lda #0 @@ -101,26 +81,22 @@ utoa16w: { rts } // Hexadecimal utoa() for a single nybble -// utoa16n(byte register(Y) nybble, word** zeropage(6) dst, byte register(X) started) +// utoa16n(byte register(A) nybble, byte register(X) started) utoa16n: { - .label dst = 6 - cpy #0 + cmp #0 beq b1 ldx #1 b1: cpx #0 beq breturn + tay lda DIGITS,y - ldy dst - sty !++1 ldy #0 + sta (utoa16w.dst),y + inc utoa16w.dst + bne !+ + inc utoa16w.dst+1 !: - sta ($ff),y - ldy #0 - lda (dst),y - clc - adc #1 - sta (dst),y breturn: rts } diff --git a/src/test/ref/pointer-pointer-3.asm b/src/test/ref/pointer-pointer-3.asm index 8d95438d3..079d897cf 100644 --- a/src/test/ref/pointer-pointer-3.asm +++ b/src/test/ref/pointer-pointer-3.asm @@ -4,7 +4,7 @@ .pc = $80d "Program" .label screen1 = $400 .label screen2 = $400+$28 - .label screen = 6 + .label screen = 4 bbegin: lda #<$400 sta screen @@ -13,10 +13,6 @@ bbegin: jsr main rts main: { - lda #<screen - sta setscreen.screen - lda #>screen - sta setscreen.screen+1 lda #<screen1 sta setscreen.val lda #>screen1 @@ -25,10 +21,6 @@ main: { lda #'a' ldy #0 sta (screen),y - lda #<screen - sta setscreen.screen - lda #>screen - sta setscreen.screen+1 lda #<screen2 sta setscreen.val lda #>screen2 @@ -39,15 +31,12 @@ main: { sta (screen),y rts } -// setscreen(byte** zeropage(4) screen, byte* zeropage(2) val) +// setscreen(byte* zeropage(2) val) setscreen: { .label val = 2 - .label screen = 4 - ldy #0 lda val - sta (screen),y - iny + sta screen lda val+1 - sta (screen),y + sta screen+1 rts } diff --git a/src/test/ref/ptrptr-optimize-2.asm b/src/test/ref/ptrptr-optimize-2.asm index 0105bd47d..afc340a19 100644 --- a/src/test/ref/ptrptr-optimize-2.asm +++ b/src/test/ref/ptrptr-optimize-2.asm @@ -9,33 +9,19 @@ main: { sta screen lda #>$400 sta screen+1 - lda #<screen - sta sub.dst - lda #>screen - sta sub.dst+1 - ldx #'a' + lda #'a' jsr sub - lda #<screen - sta sub.dst - lda #>screen - sta sub.dst+1 - ldx #'b' + lda #'b' jsr sub rts } -// sub(byte register(X) ch, byte** zeropage(2) dst) +// sub(byte register(A) ch) sub: { - .label dst = 2 - txa - ldy dst - sty !++1 ldy #0 + sta (main.screen),y + inc main.screen + bne !+ + inc main.screen+1 !: - sta ($ff),y - ldy #0 - lda (dst),y - clc - adc #1 - sta (dst),y rts } From ff7e4bff2a197521311d1289b503fc400f3e22a0 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Wed, 22 May 2019 15:32:42 +0200 Subject: [PATCH 65/93] Removed duplicate compiler step. --- .../java/dk/camelot64/kickc/Compiler.java | 1 - .../passes/Pass2RedundantPhiElimination.java | 75 ------------------- 2 files changed, 76 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 8449ab3f8..c1616481a 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -243,7 +243,6 @@ public class Compiler { optimizations.add(new Pass2UnaryNotSimplification(program)); optimizations.add(new Pass2AliasElimination(program)); optimizations.add(new Pass2SelfPhiElimination(program)); - optimizations.add(new Pass2RedundantPhiElimination(program)); optimizations.add(new Pass2IdenticalPhiElimination(program)); optimizations.add(new Pass2ConditionalJumpSimplification(program)); optimizations.add(new Pass2ConditionalAndOrRewriting(program)); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java deleted file mode 100644 index 74371da2e..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java +++ /dev/null @@ -1,75 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.*; -import dk.camelot64.kickc.model.values.LValue; -import dk.camelot64.kickc.model.values.RValue; -import dk.camelot64.kickc.model.values.VariableRef; -import dk.camelot64.kickc.model.statements.StatementPhiBlock; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** Compiler Pass eliminating redundant phi functions */ -public class Pass2RedundantPhiElimination extends Pass2SsaOptimization { - - public Pass2RedundantPhiElimination(Program program) { - super(program); - } - - /** - * Eliminate alias assignments replacing them with the aliased variable. - */ - @Override - public boolean step() { - final Map<VariableRef, RValue> aliases = findRedundantPhis(); - removeAssignments(getGraph(), aliases.keySet()); - replaceVariables(aliases); - for(VariableRef var : aliases.keySet()) { - RValue alias = aliases.get(var); - getLog().append("Redundant Phi " + var.toString(getProgram()) + " " + alias.toString(getProgram())); - } - deleteSymbols(getScope(), aliases.keySet()); - return aliases.size() > 0; - } - - /** - * Find phi variables where all previous symbols are identical. - * - * @return Map from (phi) Variable to the previous value - */ - private Map<VariableRef, RValue> findRedundantPhis() { - final Map<VariableRef, RValue> aliases = new LinkedHashMap<>(); - ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() { - - @Override - public Void visitPhiBlock(StatementPhiBlock phi) { - for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) { - boolean found = true; - RValue rValue = null; - for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { - if(rValue == null) { - rValue = phiRValue.getrValue(); - } else { - if(!rValue.equals(phiRValue.getrValue())) { - found = false; - break; - } - } - } - if(found) { - VariableRef variable = phiVariable.getVariable(); - if(rValue == null) { - rValue = LValue.VOID; - } - aliases.put(variable, rValue); - } - } - return null; - } - - }; - visitor.visitGraph(getGraph()); - return aliases; - } - -} From aaf556abe166efa2d0942dd55182efcf8520b22d Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Wed, 22 May 2019 15:42:00 +0200 Subject: [PATCH 66/93] Improved utoa16 implementation using pointer to pointer. --- src/test/kc/hex2dec.kc | 30 ++++++-------- src/test/ref/hex2dec.asm | 85 ++++++++++++++++++---------------------- 2 files changed, 50 insertions(+), 65 deletions(-) diff --git a/src/test/kc/hex2dec.kc b/src/test/kc/hex2dec.kc index d44d936df..d2642974c 100644 --- a/src/test/kc/hex2dec.kc +++ b/src/test/kc/hex2dec.kc @@ -65,27 +65,21 @@ void utoa10w(unsigned int value, unsigned char* dst) { *dst = 0; } -// Holds the destination address for the hexadecimal utoa() -unsigned char* utoa16_dst; -// Holds whether the hexadecimal utoa() has started outputting digits -unsigned char utoa16_started; - // Hexadecimal utoa() for an unsigned int (16bits) void utoa16w(unsigned int value, unsigned char* dst) { - utoa16_dst = dst; - utoa16_started = 0; - utoa16n((>value)>>4); - utoa16n((>value)&0x0f); - utoa16n((<value)>>4); - utoa16_started = 1; - utoa16n((<value)&0x0f); - *utoa16_dst = 0; + unsigned char started = 0; + started = utoa16n((>value)>>4, &dst, started); + started = utoa16n((>value)&0x0f, &dst, started); + started = utoa16n((<value)>>4, &dst, started); + utoa16n((<value)&0x0f, &dst, 1); + *dst = 0; } // Hexadecimal utoa() for a single nybble -void utoa16n(unsigned char nybble) { - if(nybble!=0) utoa16_started=1; - if(utoa16_started!=0) { - *utoa16_dst++ = DIGITS[nybble]; +unsigned char utoa16n(unsigned char nybble, unsigned **dst, unsigned char started) { + if(nybble!=0) started=1; + if(started!=0) { + *(*dst)++ = DIGITS[nybble]; } -} + return started; +} \ No newline at end of file diff --git a/src/test/ref/hex2dec.asm b/src/test/ref/hex2dec.asm index 373a47ff5..1ff955992 100644 --- a/src/test/ref/hex2dec.asm +++ b/src/test/ref/hex2dec.asm @@ -5,11 +5,9 @@ .label control = $d011 .label raster = $d012 .label bordercol = $d020 - .label utoa16_dst = 2 - .label utoa16_started = 4 main: { .label _1 = 4 - .label time_start = 5 + .label time_start = 4 sei jsr cls b1: @@ -25,53 +23,53 @@ main: { sta bordercol lda raster sta time_start - lda #0 - sta utoa16w.value - sta utoa16w.value+1 lda #<$400 sta utoa16w.dst lda #>$400 sta utoa16w.dst+1 + lda #0 + sta utoa16w.value + sta utoa16w.value+1 jsr utoa16w inc bordercol - lda #<$4d2 - sta utoa16w.value - lda #>$4d2 - sta utoa16w.value+1 lda #<$400+$28 sta utoa16w.dst lda #>$400+$28 sta utoa16w.dst+1 + lda #<$4d2 + sta utoa16w.value + lda #>$4d2 + sta utoa16w.value+1 jsr utoa16w inc bordercol - lda #<$162e - sta utoa16w.value - lda #>$162e - sta utoa16w.value+1 lda #<$400+$28+$28 sta utoa16w.dst lda #>$400+$28+$28 sta utoa16w.dst+1 + lda #<$162e + sta utoa16w.value + lda #>$162e + sta utoa16w.value+1 jsr utoa16w inc bordercol - lda #<$270f - sta utoa16w.value - lda #>$270f - sta utoa16w.value+1 lda #<$400+$28+$28+$28 sta utoa16w.dst lda #>$400+$28+$28+$28 sta utoa16w.dst+1 + lda #<$270f + sta utoa16w.value + lda #>$270f + sta utoa16w.value+1 jsr utoa16w inc bordercol - lda #<$e608 - sta utoa16w.value - lda #>$e608 - sta utoa16w.value+1 lda #<$400+$28+$28+$28+$28 sta utoa16w.dst lda #>$400+$28+$28+$28+$28 sta utoa16w.dst+1 + lda #<$e608 + sta utoa16w.value + lda #>$e608 + sta utoa16w.value+1 jsr utoa16w ldx raster lda #0 @@ -176,58 +174,51 @@ utoa10w: { jmp b1 } // Hexadecimal utoa() for an unsigned int (16bits) -// utoa16w(word zeropage(6) value, byte* zeropage(2) dst) +// utoa16w(word zeropage(2) value, byte* zeropage(6) dst) utoa16w: { - .label dst = 2 - .label value = 6 + .label value = 2 + .label dst = 6 lda value+1 lsr lsr lsr lsr - tax - lda #0 - sta utoa16_started + ldx #0 jsr utoa16n lda value+1 - ldx #$f - axs #0 + and #$f jsr utoa16n lda value lsr lsr lsr lsr - tax jsr utoa16n lda value - ldx #$f - axs #0 - lda #1 - sta utoa16_started + and #$f + ldx #1 jsr utoa16n lda #0 tay - sta (utoa16_dst),y + sta (dst),y rts } // Hexadecimal utoa() for a single nybble -// utoa16n(byte register(X) nybble) +// utoa16n(byte register(A) nybble, byte register(X) started) utoa16n: { - cpx #0 - beq b1 - lda #1 - sta utoa16_started - b1: - lda utoa16_started cmp #0 + beq b1 + ldx #1 + b1: + cpx #0 beq breturn - lda DIGITS,x + tay + lda DIGITS,y ldy #0 - sta (utoa16_dst),y - inc utoa16_dst + sta (utoa16w.dst),y + inc utoa16w.dst bne !+ - inc utoa16_dst+1 + inc utoa16w.dst+1 !: breturn: rts From 9636e261914fbc8ff0a8f749b5c51782dab37ebc Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Wed, 22 May 2019 15:53:48 +0200 Subject: [PATCH 67/93] Changed all type comparisons to use SymbolType.XXX.equals() --- .../kickc/model/operators/OperatorDivide.java | 2 +- .../kickc/model/operators/OperatorMultiply.java | 2 +- .../kickc/model/types/SymbolTypeConversion.java | 16 ++++++++-------- .../passes/Pass2ConstantIdentification.java | 2 +- .../passes/PassNAddNumberTypeConversions.java | 2 +- .../passes/PassNAddTypeConversionAssignment.java | 4 ++-- .../PassNDowngradeConstantTypeConversions.java | 6 +++--- .../kickc/passes/PassNTypeIdSimplification.java | 2 +- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java index f36dfdaca..e145eb480 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java @@ -29,7 +29,7 @@ public class OperatorDivide extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { if(left instanceof SymbolTypePointer) { - if(right.equals(SymbolType.BYTE) || right.equals(SymbolType.WORD)|| right.equals(SymbolType.NUMBER)) { + if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) { return left; } else { throw new NoMatchingType("Cannot divide pointer by "+right.toString()); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java index a4a98d455..48b4cf2d4 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java @@ -23,7 +23,7 @@ public class OperatorMultiply extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { if(left instanceof SymbolTypePointer) { - if(right.equals(SymbolType.BYTE) || right.equals(SymbolType.WORD)|| right.equals(SymbolType.NUMBER)) { + if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) { return left; } else { throw new NoMatchingType("Cannot multiply pointer by "+right.toString()); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index 02b96b28c..b2f8c2356 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -155,17 +155,17 @@ public class SymbolTypeConversion { public static boolean assignmentTypeMatch(SymbolType lValueType, SymbolType rValueType) { if(lValueType.equals(rValueType)) return true; - if(lValueType.equals(SymbolType.WORD) && rValueType.equals(SymbolType.BYTE)) + if(SymbolType.WORD.equals(lValueType) && SymbolType.BYTE.equals(rValueType)) return true; - if(lValueType.equals(SymbolType.DWORD) && rValueType.equals(SymbolType.BYTE)) + if(SymbolType.DWORD.equals(lValueType) && SymbolType.BYTE.equals(rValueType)) return true; - if(lValueType.equals(SymbolType.DWORD) && rValueType.equals(SymbolType.WORD)) + if(SymbolType.DWORD.equals(lValueType) && SymbolType.WORD.equals(rValueType)) return true; - if(lValueType.equals(SymbolType.SWORD) && rValueType.equals(SymbolType.SBYTE)) + if(SymbolType.SWORD.equals(lValueType) && SymbolType.SBYTE.equals(rValueType)) return true; - if(lValueType.equals(SymbolType.SDWORD) && rValueType.equals(SymbolType.SBYTE)) + if(SymbolType.SDWORD.equals(lValueType) && SymbolType.SBYTE.equals(rValueType)) return true; - if(lValueType.equals(SymbolType.SDWORD) && rValueType.equals(SymbolType.SWORD)) + if(SymbolType.SDWORD.equals(lValueType) && SymbolType.SWORD.equals(rValueType)) return true; if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) { // R-value is still a number - constants are probably not done being identified & typed @@ -175,7 +175,7 @@ public class SymbolTypeConversion { // R-value is still a number - constants are probably not done being identified & typed return true; } - if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) { + if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType())) { // String value can be assigned into a pointer return true; } @@ -198,7 +198,7 @@ public class SymbolTypeConversion { return false; else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(((SymbolTypePointer) rValueType).getElementType())) return false; - else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) + else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType())) return false; else return true; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java index be3634d84..76affac0d 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java @@ -73,7 +73,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { SymbolType valueType = SymbolTypeInference.inferType(getScope(), constVal); SymbolType variableType = variable.getType(); - if(!variableType.equals(SymbolType.NUMBER) && valueType.equals(SymbolType.NUMBER)) { + if(!SymbolType.NUMBER.equals(variableType) && SymbolType.NUMBER.equals(valueType)) { // Value is number - wait til it is cast to a proper type constants.remove(constRef); continue; diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java index 7a69f1fd4..dcc576213 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java @@ -37,7 +37,7 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization { modified.set(true); } SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right); - if(rightType.equals(SymbolType.NUMBER)) { + if(SymbolType.NUMBER.equals(rightType)) { getLog().append("Adding number conversion cast (" + castType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false))); binary.addRightCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope()); modified.set(true); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java index 3fde76260..4b74e0e9c 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java @@ -40,7 +40,7 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization { } // Detect word literal constructor - if(leftType.equals(SymbolType.WORD) && isLiteralWordCandidate(rightType)) { + if(SymbolType.WORD.equals(leftType) && isLiteralWordCandidate(rightType)) { SymbolType conversionType = SymbolType.WORD; getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); @@ -55,7 +55,7 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization { } // Detect dword literal constructor - if(leftType.equals(SymbolType.DWORD) && isLiteralWordCandidate(rightType)) { + if(SymbolType.DWORD.equals(leftType) && isLiteralWordCandidate(rightType)) { SymbolType conversionType = SymbolType.DWORD; getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java index 85a6db2cb..e87e6e748 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java @@ -68,7 +68,7 @@ public class PassNDowngradeConstantTypeConversions extends Pass2SsaOptimization */ public boolean isWordLike(RValue rValue) { SymbolType symbolType = SymbolTypeInference.inferType(getProgram().getScope(), rValue); - return symbolType.equals(SymbolType.WORD) || symbolType instanceof SymbolTypePointer; + return SymbolType.WORD.equals(symbolType) || symbolType instanceof SymbolTypePointer; } @@ -79,10 +79,10 @@ public class PassNDowngradeConstantTypeConversions extends Pass2SsaOptimization * @return true if the value is a constant cast to word */ public boolean isConstantWord(RValue rValue) { - if(rValue instanceof ConstantInteger && ((ConstantInteger) rValue).getType().equals(SymbolType.WORD)) { + if(rValue instanceof ConstantInteger && SymbolType.WORD.equals(((ConstantInteger) rValue).getType())) { return true; } - if((rValue instanceof ConstantCastValue) && ((ConstantCastValue) rValue).getToType().equals(SymbolType.WORD)) + if((rValue instanceof ConstantCastValue) && SymbolType.WORD.equals(((ConstantCastValue) rValue).getToType())) return true; return false; } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java index 43d47670d..1b110077d 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java @@ -30,7 +30,7 @@ public class PassNTypeIdSimplification extends Pass2SsaOptimization { if(Operators.TYPEID.equals(unary.getOperator())) { RValue rValue = unary.getOperand(); SymbolType symbolType = SymbolTypeInference.inferType(getScope(), rValue); - if(symbolType.equals(SymbolType.VAR) || symbolType.equals(SymbolType.NUMBER)) { + if(SymbolType.VAR.equals(symbolType) || SymbolType.NUMBER.equals(symbolType)) { } else { getLog().append("Resolving typeid() " + currentStmt.toString(getProgram(), false)); From 2fb9a5baf3b33b9775864c301be18b5409964d1e Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Wed, 22 May 2019 23:38:34 +0200 Subject: [PATCH 68/93] Moved symbol table update functions to PassNTypeInference (cleaning up SymbolTypeInference). --- .../kickc/model/types/SymbolType.java | 6 +- .../model/types/SymbolTypeInference.java | 110 ------------- .../kickc/passes/Pass1FixLValuesLoHi.java | 3 +- .../kickc/passes/PassNTypeInference.java | 149 +++++++++++++++--- 4 files changed, 135 insertions(+), 133 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java index 34747ed97..bff9cc686 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java @@ -15,8 +15,12 @@ public interface SymbolType { SymbolTypeIntegerFixed DWORD = new SymbolTypeIntegerFixed("dword", 0, 4_294_967_296L, false, 32); /** Signed double word (4 bytes, 32 bits). */ SymbolTypeIntegerFixed SDWORD = new SymbolTypeIntegerFixed("signed dword", -2_147_483_648, 2_147_483_647, true, 32); - /** Integer with unknown size (used for constant expressions). */ + /** Integer with unknown size and unknown signedness (used for constant expressions). */ SymbolTypeIntegerAuto NUMBER = new SymbolTypeIntegerAuto("number"); + /** Unsigned integer with unknown size (used for constant expressions). */ + SymbolTypeIntegerAuto UNUMBER = new SymbolTypeIntegerAuto("unumber"); + /** Signed integer with unknown size (used for constant expressions). */ + SymbolTypeIntegerAuto SNUMBER = new SymbolTypeIntegerAuto("snumber"); /** String value (treated like byte* ). */ SymbolTypeNamed STRING = new SymbolTypeNamed("string", 99); /** Boolean value. */ diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index 4a244cbdb..6c308eec4 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -178,114 +178,4 @@ public class SymbolTypeInference { return rValueType; } - public static void inferCallLValue(Program program, StatementCall call, boolean reinfer) { - ProgramScope programScope = program.getScope(); - LValue lValue = call.getlValue(); - if(lValue instanceof VariableRef) { - Variable symbol = programScope.getVariable((VariableRef) lValue); - if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { - Procedure procedure = programScope.getProcedure(call.getProcedure()); - SymbolType type = procedure.getReturnType(); - setInferedType(program, call, symbol, type); - } - } - } - - public static void inferCallPointerLValue(Program program, StatementCallPointer call, boolean reinfer) { - ProgramScope programScope = program.getScope(); - LValue lValue = call.getlValue(); - if(lValue instanceof VariableRef) { - Variable symbol = programScope.getVariable((VariableRef) lValue); - if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { - SymbolType procedureType = inferType(programScope, call.getProcedure()); - if(procedureType instanceof SymbolTypeProcedure) { - SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType(); - setInferedType(program, call, symbol, returnType); - } - } - } - } - - public static void inferPhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable, boolean reinfer) { - ProgramScope programScope = program.getScope(); - - Variable symbol = programScope.getVariable(phiVariable.getVariable()); - if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { - SymbolType type = null; - for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { - RValue rValue = phiRValue.getrValue(); - SymbolType valueType = inferType(programScope, rValue); - if(type == null) { - type = valueType; - } else if(!type.equals(valueType)) - if(valueType instanceof SymbolTypeInteger && type instanceof SymbolTypeInteger) { - type = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) valueType, (SymbolTypeInteger) type); - } else { - throw new CompileError("Phi value has type mismatch "+phiRValue.toString() + " not matching type " + type.getTypeName()); - } - } - if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) { - program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program)); - } - symbol.setTypeInferred(type); - } - } - - public static void inferAssignmentLValue(Program program, StatementAssignment assignment, boolean reinfer) { - ProgramScope programScope = program.getScope(); - LValue lValue = assignment.getlValue(); - if(lValue instanceof VariableRef) { - Variable symbol = programScope.getVariable((VariableRef) lValue); - if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) { - // Unresolved symbol - perform inference - Operator operator = assignment.getOperator(); - if(assignment.getrValue1() == null && operator == null) { - // Copy operation - RValue rValue = assignment.getrValue2(); - SymbolType type = inferType(programScope, rValue); - setInferedType(program, assignment, symbol, type); - } else if(assignment.getrValue1() == null && operator instanceof OperatorUnary) { - // Unary operation - RValue rValue = assignment.getrValue2(); - SymbolType type = inferType(programScope, (OperatorUnary) operator, rValue); - setInferedType(program, assignment, symbol, type); - } else if(operator instanceof OperatorBinary) { - // Binary operation - SymbolType type = inferType( - programScope, assignment.getrValue1(), - (OperatorBinary) assignment.getOperator(), - assignment.getrValue2()); - setInferedType(program, assignment, symbol, type); - } else { - throw new CompileError("Cannot infer type of " + assignment); - } - // If the type is an array or a string the symbol is constant - if(symbol.getType() instanceof SymbolTypeArray) { - symbol.setDeclaredConstant(true); - } else if(SymbolType.STRING.equals(symbol.getType())) { - symbol.setDeclaredConstant(true); - } - } - } - } - - private static void setInferedType(Program program, Statement statement, Variable symbol, SymbolType type) { - if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) { - program.getLog().append("Inferred type updated to " + type + " in " + statement.toString(program, false)); - } - symbol.setTypeInferred(type); - } - - public static void inferLValue(Program program, StatementLValue statementLValue, boolean reinfer) { - if(statementLValue instanceof StatementAssignment) { - inferAssignmentLValue(program, (StatementAssignment) statementLValue, reinfer); - } else if(statementLValue instanceof StatementCall) { - inferCallLValue(program, (StatementCall) statementLValue, reinfer); - } else if(statementLValue instanceof StatementCallPointer) { - inferCallPointerLValue(program, (StatementCallPointer) statementLValue, reinfer); - } else { - throw new RuntimeException("LValue statement not implemented " + statementLValue); - } - } - } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java index 1b2f990e8..68d13d0e3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java @@ -12,7 +12,6 @@ import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.symbols.Scope; import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.symbols.VariableIntermediate; -import dk.camelot64.kickc.model.types.SymbolTypeInference; import java.util.ArrayList; import java.util.List; @@ -80,7 +79,7 @@ public class Pass1FixLValuesLoHi extends Pass1Base { VariableIntermediate tmpVar = currentScope.addVariableIntermediate(); VariableRef tmpVarRef = tmpVar.getRef(); statementLValue.setlValue(tmpVarRef); - SymbolTypeInference.inferLValue(getProgram(), statementLValue, false); + PassNTypeInference.inferLValue(getProgram(), statementLValue); // Insert an extra "set low" assignment statement Statement setLoHiAssignment = new StatementAssignment(loHiVar, loHiVar, loHiOperator, tmpVarRef, statementLValue.getSource(), new ArrayList<>()); statementsIt.add(setLoHiAssignment); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java index d4baa4e7d..d37114431 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java @@ -3,10 +3,17 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.ControlFlowBlock; import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.operators.Operator; +import dk.camelot64.kickc.model.operators.OperatorBinary; +import dk.camelot64.kickc.model.operators.OperatorUnary; import dk.camelot64.kickc.model.statements.*; import dk.camelot64.kickc.model.symbols.Procedure; -import dk.camelot64.kickc.model.symbols.Scope; -import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.symbols.ProgramScope; +import dk.camelot64.kickc.model.symbols.Variable; +import dk.camelot64.kickc.model.types.*; +import dk.camelot64.kickc.model.values.LValue; +import dk.camelot64.kickc.model.values.RValue; +import dk.camelot64.kickc.model.values.VariableRef; /** * Pass through the generated statements inferring types of unresolved variables. @@ -18,34 +25,136 @@ public class PassNTypeInference extends Pass2SsaOptimization { super(program); } + @Override public boolean step() { for(ControlFlowBlock block : getGraph().getAllBlocks()) { for(Statement statement : block.getStatements()) { - if(statement instanceof StatementAssignment) { - StatementAssignment assignment = (StatementAssignment) statement; - try { - SymbolTypeInference.inferAssignmentLValue(getProgram(), assignment, false); - } catch(CompileError e) { - throw new CompileError(e.getMessage(), statement.getSource()); - } - } else if(statement instanceof StatementPhiBlock) { - for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) { - try { - SymbolTypeInference.inferPhiVariable(getProgram(), phiVariable, false); - } catch(CompileError e) { - throw new CompileError(e.getMessage(), statement.getSource()); + try { + if(statement instanceof StatementLValue) { + inferLValue(getProgram(), (StatementLValue) statement); + } else if(statement instanceof StatementPhiBlock) { + for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) { + inferPhiVariable(getProgram(), phiVariable); } } - } else if(statement instanceof StatementCall) { - SymbolTypeInference.inferCallLValue(getProgram(), (StatementCall) statement, false); - } else if(statement instanceof StatementCallPointer) { - SymbolTypeInference.inferCallPointerLValue(getProgram(), (StatementCallPointer) statement, false); + } catch(CompileError e) { + throw new CompileError(e.getMessage(), statement.getSource()); } - } } return false; } + public static void inferLValue(Program program, StatementLValue statementLValue) { + if(statementLValue instanceof StatementAssignment) { + inferAssignmentLValue(program, (StatementAssignment) statementLValue); + } else if(statementLValue instanceof StatementCall) { + inferCallLValue(program, (StatementCall) statementLValue); + } else if(statementLValue instanceof StatementCallPointer) { + inferCallPointerLValue(program, (StatementCallPointer) statementLValue); + } else { + throw new RuntimeException("LValue statement not implemented " + statementLValue); + } + } + + + private static void inferCallLValue(Program program, StatementCall call) { + ProgramScope programScope = program.getScope(); + LValue lValue = call.getlValue(); + if(lValue instanceof VariableRef) { + Variable symbol = programScope.getVariable((VariableRef) lValue); + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { + Procedure procedure = programScope.getProcedure(call.getProcedure()); + SymbolType type = procedure.getReturnType(); + setInferedType(program, call, symbol, type); + } + } + } + + private static void inferCallPointerLValue(Program program, StatementCallPointer call) { + ProgramScope programScope = program.getScope(); + LValue lValue = call.getlValue(); + if(lValue instanceof VariableRef) { + Variable symbol = programScope.getVariable((VariableRef) lValue); + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { + SymbolType procedureType = SymbolTypeInference.inferType(programScope, call.getProcedure()); + if(procedureType instanceof SymbolTypeProcedure) { + SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType(); + setInferedType(program, call, symbol, returnType); + } + } + } + } + + private static void inferPhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) { + ProgramScope programScope = program.getScope(); + Variable symbol = programScope.getVariable(phiVariable.getVariable()); + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { + SymbolType type = null; + for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { + RValue rValue = phiRValue.getrValue(); + SymbolType valueType = SymbolTypeInference.inferType(programScope, rValue); + if(type == null) { + type = valueType; + } else if(!type.equals(valueType)) + if(valueType instanceof SymbolTypeInteger && type instanceof SymbolTypeInteger) { + type = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) valueType, (SymbolTypeInteger) type); + } else { + throw new CompileError("Phi value has type mismatch " + phiRValue.toString() + " not matching type " + type.getTypeName()); + } + } + if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) { + program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program)); + } + symbol.setTypeInferred(type); + } + } + + private static void inferAssignmentLValue(Program program, StatementAssignment assignment) { + ProgramScope programScope = program.getScope(); + LValue lValue = assignment.getlValue(); + if(lValue instanceof VariableRef) { + Variable symbol = programScope.getVariable((VariableRef) lValue); + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { + // Unresolved symbol - perform inference + Operator operator = assignment.getOperator(); + if(assignment.getrValue1() == null && operator == null) { + // Copy operation + RValue rValue = assignment.getrValue2(); + SymbolType type = SymbolTypeInference.inferType(programScope, rValue); + setInferedType(program, assignment, symbol, type); + } else if(assignment.getrValue1() == null && operator instanceof OperatorUnary) { + // Unary operation + RValue rValue = assignment.getrValue2(); + SymbolType type = SymbolTypeInference.inferType(programScope, (OperatorUnary) operator, rValue); + setInferedType(program, assignment, symbol, type); + } else if(operator instanceof OperatorBinary) { + // Binary operation + SymbolType type = SymbolTypeInference.inferType( + programScope, assignment.getrValue1(), + (OperatorBinary) assignment.getOperator(), + assignment.getrValue2()); + setInferedType(program, assignment, symbol, type); + } else { + throw new CompileError("Cannot infer type of " + assignment); + } + // If the type is an array or a string the symbol is constant + if(symbol.getType() instanceof SymbolTypeArray) { + symbol.setDeclaredConstant(true); + } else if(SymbolType.STRING.equals(symbol.getType())) { + symbol.setDeclaredConstant(true); + } + } + } + } + + private static void setInferedType(Program program, Statement statement, Variable symbol, SymbolType type) { + if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) { + program.getLog().append("Inferred type updated to " + type + " in " + statement.toString(program, false)); + } + symbol.setTypeInferred(type); + } + + } From 864b993f143845ef3538dc883322e6588f9339e8 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Wed, 22 May 2019 23:50:50 +0200 Subject: [PATCH 69/93] Eliminated SymbolTypeSimple. Eliminated SymbolTypeInference.infer(type, ...). Eliminiated most of SymbolTypeNumberInference. --- .../model/operators/OperatorAddressOf.java | 3 +- .../model/operators/OperatorAssignment.java | 4 +- .../kickc/model/operators/OperatorBinary.java | 3 +- .../model/operators/OperatorBitwiseAnd.java | 2 +- .../model/operators/OperatorBitwiseNot.java | 3 +- .../model/operators/OperatorBitwiseOr.java | 2 +- .../model/operators/OperatorBitwiseXor.java | 2 +- .../model/operators/OperatorCastBool.java | 3 +- .../model/operators/OperatorCastByte.java | 3 +- .../model/operators/OperatorCastDWord.java | 3 +- .../model/operators/OperatorCastPtr.java | 3 +- .../model/operators/OperatorCastSByte.java | 3 +- .../model/operators/OperatorCastSDWord.java | 3 +- .../model/operators/OperatorCastSWord.java | 3 +- .../model/operators/OperatorCastWord.java | 3 +- .../kickc/model/operators/OperatorDWord.java | 3 +- .../model/operators/OperatorDecrement.java | 3 +- .../kickc/model/operators/OperatorDeref.java | 3 +- .../model/operators/OperatorDerefIdx.java | 3 +- .../kickc/model/operators/OperatorDivide.java | 2 +- .../kickc/model/operators/OperatorEqual.java | 3 +- .../model/operators/OperatorGetHigh.java | 3 +- .../kickc/model/operators/OperatorGetLow.java | 3 +- .../model/operators/OperatorGreaterThan.java | 3 +- .../operators/OperatorGreaterThanEqual.java | 3 +- .../model/operators/OperatorIncrement.java | 3 +- .../model/operators/OperatorLessThan.java | 3 +- .../operators/OperatorLessThanEqual.java | 3 +- .../model/operators/OperatorLogicAnd.java | 3 +- .../model/operators/OperatorLogicNot.java | 3 +- .../model/operators/OperatorLogicOr.java | 3 +- .../kickc/model/operators/OperatorMinus.java | 2 +- .../kickc/model/operators/OperatorModulo.java | 2 +- .../model/operators/OperatorMultiply.java | 2 +- .../kickc/model/operators/OperatorNeg.java | 3 +- .../model/operators/OperatorNotEqual.java | 3 +- .../kickc/model/operators/OperatorPlus.java | 4 +- .../kickc/model/operators/OperatorPos.java | 3 +- .../model/operators/OperatorSetHigh.java | 3 +- .../kickc/model/operators/OperatorSetLow.java | 3 +- .../model/operators/OperatorShiftLeft.java | 6 +- .../model/operators/OperatorShiftRight.java | 5 +- .../kickc/model/operators/OperatorSizeOf.java | 3 +- .../kickc/model/operators/OperatorTypeId.java | 2 +- .../kickc/model/operators/OperatorUnary.java | 3 +- .../kickc/model/operators/OperatorWord.java | 3 +- .../model/types/SymbolTypeBlockScope.java | 2 +- .../model/types/SymbolTypeInference.java | 29 +----- .../kickc/model/types/SymbolTypeInteger.java | 2 +- .../kickc/model/types/SymbolTypeNamed.java | 2 +- .../types/SymbolTypeNumberInference.java | 94 ------------------- .../kickc/model/types/SymbolTypePointer.java | 2 +- .../model/types/SymbolTypeProcedure.java | 2 +- .../kickc/model/types/SymbolTypeProgram.java | 2 +- .../kickc/model/types/SymbolTypeSimple.java | 5 - 55 files changed, 55 insertions(+), 222 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeSimple.java diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAddressOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAddressOf.java index 5b3c998dd..f0da75fec 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAddressOf.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAddressOf.java @@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantLiteral; /** Unary Address-of Operator (&p) */ @@ -20,7 +19,7 @@ public class OperatorAddressOf extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return new SymbolTypePointer(operandType); } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java index b42c177eb..9e84e1b3d 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java @@ -2,8 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; -import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantLiteral; /** Binary assignment operator ( x = y ) */ @@ -19,7 +17,7 @@ public class OperatorAssignment extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return left; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBinary.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBinary.java index 0ae783a25..9a6a79d30 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBinary.java @@ -1,7 +1,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantLiteral; /** A binary expression operator */ @@ -25,6 +24,6 @@ public abstract class OperatorBinary extends Operator { * @param right The type of the right operand * @return The type resulting from applying the operator to the operands */ - public abstract SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right); + public abstract SymbolType inferType(SymbolType left, SymbolType right); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java index 931576215..84af74049 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java @@ -21,7 +21,7 @@ public class OperatorBitwiseAnd extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) { + public SymbolType inferType(SymbolType type1, SymbolType type2) { // Handle pointers as words if(type1 instanceof SymbolTypePointer) { type1 = SymbolType.WORD; diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseNot.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseNot.java index 3ef8aac69..690067238 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseNot.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseNot.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorBitwiseNot extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return operandType; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java index 3e6a46208..9a0309952 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java @@ -21,7 +21,7 @@ public class OperatorBitwiseOr extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) { + public SymbolType inferType(SymbolType type1, SymbolType type2) { // Handle pointers as words if(type1 instanceof SymbolTypePointer) { type1 = SymbolType.WORD; diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java index 2d614f2ab..8c4d71d4a 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java @@ -21,7 +21,7 @@ public class OperatorBitwiseXor extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) { + public SymbolType inferType(SymbolType type1, SymbolType type2) { // Handle pointers as words if(type1 instanceof SymbolTypePointer) { type1 = SymbolType.WORD; diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java index 24b02a921..f0b17f0f6 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; @@ -26,7 +25,7 @@ public class OperatorCastBool extends OperatorCast { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return SymbolType.BOOLEAN; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java index b00ba311a..7b843b4c0 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; @@ -26,7 +25,7 @@ public class OperatorCastByte extends OperatorCast { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return SymbolType.BYTE; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java index 111b94b7a..54cb2efc7 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; @@ -28,7 +27,7 @@ public class OperatorCastDWord extends OperatorCast { @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return SymbolType.DWORD; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java index 142ecc533..041089cd9 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java @@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; @@ -33,7 +32,7 @@ public class OperatorCastPtr extends OperatorCast { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return new SymbolTypePointer(elementType); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java index 9487eae97..7d020c032 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorCastSByte extends OperatorCast { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return SymbolType.SBYTE; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java index 6ec765ca7..bea05b604 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorCastSDWord extends OperatorCast { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return SymbolType.SDWORD; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java index b8a618979..7954d4243 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorCastSWord extends OperatorCast { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return SymbolType.SWORD; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java index 0b1097086..aa0b6c1b6 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; @@ -27,7 +26,7 @@ public class OperatorCastWord extends OperatorCast { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return SymbolType.WORD; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java index b0e06378c..9ef7fc18d 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java @@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.NoMatchingType; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -24,7 +23,7 @@ public class OperatorDWord extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { // Handle pointers as words if(left instanceof SymbolTypePointer) { left = SymbolType.WORD; diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java index 76dbf6087..5dfd1a7a4 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorDecrement extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return operandType; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDeref.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDeref.java index c8a524b31..f14f87a66 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDeref.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDeref.java @@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantLiteral; /** Unary Pointer Dereference Operator (*p) */ @@ -20,7 +19,7 @@ public class OperatorDeref extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { if(operandType instanceof SymbolTypePointer) { return ((SymbolTypePointer) operandType).getElementType(); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDerefIdx.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDerefIdx.java index c4cf2b56f..834e5c66b 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDerefIdx.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDerefIdx.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantLiteral; /** Binary Pointer Dereference with an index Operator ( p[i] / *(p+i) ) */ @@ -19,7 +18,7 @@ public class OperatorDerefIdx extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { if(left instanceof SymbolTypePointer) { return ((SymbolTypePointer) left).getElementType(); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java index e145eb480..eb3be39a8 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java @@ -27,7 +27,7 @@ public class OperatorDivide extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { if(left instanceof SymbolTypePointer) { if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) { return left; diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorEqual.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorEqual.java index 08777da59..cc990790f 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorEqual.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorEqual.java @@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -25,7 +24,7 @@ public class OperatorEqual extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return SymbolType.BOOLEAN; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java index 79902c0c2..e7ad53157 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java @@ -5,7 +5,6 @@ import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; @@ -40,7 +39,7 @@ public class OperatorGetHigh extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { if(operandType instanceof SymbolTypePointer || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType)) { return SymbolType.BYTE; } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) { diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java index 7542903f6..6d8e03c03 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java @@ -5,7 +5,6 @@ import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; @@ -40,7 +39,7 @@ public class OperatorGetLow extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { if(operandType instanceof SymbolTypePointer || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType)) { return SymbolType.BYTE; } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) { diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThan.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThan.java index fcf503c84..f1614c0be 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThan.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThan.java @@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorGreaterThan extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return SymbolType.BOOLEAN; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThanEqual.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThanEqual.java index b195f1e40..2ce48f329 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThanEqual.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThanEqual.java @@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorGreaterThanEqual extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return SymbolType.BOOLEAN; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java index 70671914f..a7532ff7a 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantPointer; @@ -26,7 +25,7 @@ public class OperatorIncrement extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return operandType; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThan.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThan.java index a3d0c379f..ad61da0e8 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThan.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThan.java @@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorLessThan extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return SymbolType.BOOLEAN; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThanEqual.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThanEqual.java index af07b0378..cbf042583 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThanEqual.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThanEqual.java @@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorLessThanEqual extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return SymbolType.BOOLEAN; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicAnd.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicAnd.java index d755616a3..0088ec944 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicAnd.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicAnd.java @@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -22,7 +21,7 @@ public class OperatorLogicAnd extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return SymbolType.BOOLEAN; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicNot.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicNot.java index 740f1ce01..990cab0f1 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicNot.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicNot.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorLogicNot extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return operandType; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicOr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicOr.java index 5c838560a..5d5b92e68 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicOr.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicOr.java @@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -22,7 +21,7 @@ public class OperatorLogicOr extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return SymbolType.BOOLEAN; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java index ce472ffd7..50c1fb6f7 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java @@ -29,7 +29,7 @@ public class OperatorMinus extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) { + public SymbolType inferType(SymbolType type1, SymbolType type2) { // Handle pointer types if(type1 instanceof SymbolTypePointer && SymbolType.isInteger(type2)) { return new SymbolTypePointer(((SymbolTypePointer) type1).getElementType()); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java index 4fc0a3388..7235c3fdc 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java @@ -24,7 +24,7 @@ public class OperatorModulo extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { // Handle numeric types through proper promotion if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java index 48b4cf2d4..a32595647 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java @@ -21,7 +21,7 @@ public class OperatorMultiply extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { if(left instanceof SymbolTypePointer) { if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) { return left; diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorNeg.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorNeg.java index ce736a9d1..2e777f4f1 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorNeg.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorNeg.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorNeg extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return operandType; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorNotEqual.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorNotEqual.java index 8b995c59e..7aba1389b 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorNotEqual.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorNotEqual.java @@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -29,7 +28,7 @@ public class OperatorNotEqual extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return SymbolType.BOOLEAN; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java index 0cb8ec7b8..7df7c77bd 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java @@ -37,7 +37,7 @@ public class OperatorPlus extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) { + public SymbolType inferType(SymbolType type1, SymbolType type2) { // Handle all non-numeric types if(SymbolType.isInteger(type1) && type2 instanceof SymbolTypePointer) { return new SymbolTypePointer(((SymbolTypePointer) type2).getElementType()); @@ -59,7 +59,7 @@ public class OperatorPlus extends OperatorBinary { * @param type The type to check * @return true if the type is string like */ - private boolean isStringLike(SymbolTypeSimple type) { + private boolean isStringLike(SymbolType type) { if(SymbolType.STRING.equals(type)) { return true; } else if(SymbolType.BYTE.equals(type)) { diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPos.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPos.java index 03acd3465..507bba6fc 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPos.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPos.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorPos extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return operandType; } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java index 19662e139..041322a18 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantLiteral; /** Binary SetHighByte Operator ( w hi= b ) */ @@ -19,7 +18,7 @@ public class OperatorSetHigh extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { if(left instanceof SymbolTypePointer) { return left; } else if(SymbolType.BYTE.equals(left)) { diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java index bd4cd763a..180b4b5bd 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantLiteral; /** Binary SetLowByte Operator ( w lo= b ) */ @@ -19,7 +18,7 @@ public class OperatorSetLow extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { if(left instanceof SymbolTypePointer) { return left; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java index 3350f82f7..5d84970ef 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java @@ -2,10 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeConversion; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; -import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -25,7 +21,7 @@ public class OperatorShiftLeft extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return left; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java index 2f8a9dca0..352dae6d5 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java @@ -2,9 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeConversion; -import dk.camelot64.kickc.model.types.SymbolTypeInteger; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -24,7 +21,7 @@ public class OperatorShiftRight extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { return left; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java index 11fa1b0a1..422f6a4c2 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java @@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.symbols.ConstantVar; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; import dk.camelot64.kickc.model.values.ConstantRef; @@ -23,7 +22,7 @@ public class OperatorSizeOf extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return SymbolType.BYTE; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java index c5dca47db..0d09c75e9 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java @@ -24,7 +24,7 @@ public class OperatorTypeId extends OperatorUnary { } @Override - public SymbolType inferType(SymbolTypeSimple operandType) { + public SymbolType inferType(SymbolType operandType) { return SymbolType.BYTE; } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorUnary.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorUnary.java index d9efd026f..2c1775de7 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorUnary.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorUnary.java @@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantLiteral; /** A unary expression operator */ @@ -25,6 +24,6 @@ public abstract class OperatorUnary extends Operator { * @param operandType The type of the operand * @return The type resulting from applying the operator to the operand */ - public abstract SymbolType inferType(SymbolTypeSimple operandType); + public abstract SymbolType inferType(SymbolType operandType); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java index c84710823..01f96476c 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.NoMatchingType; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +22,7 @@ public class OperatorWord extends OperatorBinary { } @Override - public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { + public SymbolType inferType(SymbolType left, SymbolType right) { if(SymbolType.BYTE.equals(left) && SymbolType.BYTE.equals(right)) { return SymbolType.WORD; } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeBlockScope.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeBlockScope.java index 8d5b113f4..4fc97f3cb 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeBlockScope.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeBlockScope.java @@ -1,7 +1,7 @@ package dk.camelot64.kickc.model.types; /** A block scope */ -public class SymbolTypeBlockScope implements SymbolTypeSimple { +public class SymbolTypeBlockScope implements SymbolType { public SymbolTypeBlockScope() { diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index 6c308eec4..f2af3c947 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -1,8 +1,6 @@ package dk.camelot64.kickc.model.types; import dk.camelot64.kickc.model.CompileError; -import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.operators.Operator; import dk.camelot64.kickc.model.operators.OperatorBinary; import dk.camelot64.kickc.model.operators.OperatorUnary; import dk.camelot64.kickc.model.statements.*; @@ -24,22 +22,7 @@ public class SymbolTypeInference { */ public static SymbolType inferType(ProgramScope programScope, OperatorUnary operator, RValue rValue) { SymbolType valueType = inferType(programScope, rValue); - return inferType(operator, valueType); - } - - /** - * Infer the type of a unary operator on an operand type - * - * @param operator The unary operator - * @param operandType The operand type - * @return The type of the result from applying the operator on the operand - */ - public static SymbolType inferType(OperatorUnary operator, SymbolType operandType) { - if(operandType instanceof SymbolTypeSimple) { - return operator.inferType((SymbolTypeSimple) operandType); - } else { - throw new RuntimeException("Not implemented!"); - } + return operator.inferType(valueType); } /** @@ -54,15 +37,7 @@ public class SymbolTypeInference { public static SymbolType inferType(ProgramScope programScope, RValue left, OperatorBinary operator, RValue right) { SymbolType leftType = inferType(programScope, left); SymbolType rightType = inferType(programScope, right); - return inferType(leftType, operator, rightType); - } - - public static SymbolType inferType(SymbolType left, OperatorBinary operator, SymbolType right) { - if(left instanceof SymbolTypeSimple && right instanceof SymbolTypeSimple) { - return operator.inferType((SymbolTypeSimple) left, (SymbolTypeSimple) right); - } else { - throw new RuntimeException("Not implemented!"); - } + return operator.inferType(leftType, rightType); } public static SymbolType inferType(ProgramScope symbols, RValue rValue) { diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java index 2a4cdfa7f..9a64e214d 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java @@ -1,6 +1,6 @@ package dk.camelot64.kickc.model.types; /** Integer type marker interface. */ -public interface SymbolTypeInteger extends SymbolTypeSimple { +public interface SymbolTypeInteger extends SymbolType { } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNamed.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNamed.java index fce17747e..5578a24bf 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNamed.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNamed.java @@ -1,7 +1,7 @@ package dk.camelot64.kickc.model.types; /** Basic named (string, char, ...) Symbol Types */ -public class SymbolTypeNamed implements SymbolTypeSimple { +public class SymbolTypeNamed implements SymbolType { private String typeName; diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java index 983e6a21f..9a1519369 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java @@ -1,15 +1,5 @@ package dk.camelot64.kickc.model.types; -import dk.camelot64.kickc.model.InternalError; -import dk.camelot64.kickc.model.operators.OperatorBinary; -import dk.camelot64.kickc.model.operators.OperatorUnary; -import dk.camelot64.kickc.model.statements.StatementAssignment; -import dk.camelot64.kickc.model.symbols.ProgramScope; -import dk.camelot64.kickc.model.values.ConstantInteger; -import dk.camelot64.kickc.model.values.ConstantLiteral; -import dk.camelot64.kickc.model.values.ConstantValue; -import dk.camelot64.kickc.model.values.RValue; - import java.util.ArrayList; import java.util.List; @@ -19,90 +9,6 @@ import java.util.List; */ public class SymbolTypeNumberInference { - /** - * Infer the potential types for an RValue with {@link SymbolType#NUMBER} type - * - * @return The potential types - */ - public static List<SymbolTypeIntegerFixed> inferTypesRValue(ProgramScope symbols, StatementAssignment assignment) { - RValue rValue1 = assignment.getrValue1(); - RValue rValue2 = assignment.getrValue2(); - if(assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof ConstantValue) { - return inferTypes(symbols, (ConstantValue) rValue2); - } else if(assignment.getrValue1() == null && assignment.getOperator() instanceof OperatorUnary && assignment.getrValue2() instanceof ConstantValue) { - return inferTypes(symbols, (OperatorUnary) assignment.getOperator(), (ConstantValue) rValue2); - } else if(assignment.getOperator() instanceof OperatorBinary && assignment.getrValue1() instanceof ConstantValue && assignment.getrValue2() instanceof ConstantValue) { - return inferTypes(symbols, (ConstantValue) rValue1, (OperatorBinary) assignment.getOperator(), (ConstantValue) rValue2); - } else { - return new ArrayList<>(); - } - } - - /** - * Infer the potential types for a binary operator with {@link SymbolType#NUMBER} type - * - * @return The potential types - */ - public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantValue leftValue, OperatorBinary operator, ConstantValue rightValue) { - if(SymbolType.NUMBER.equals(leftValue.getType(programScope)) && SymbolType.NUMBER.equals(rightValue.getType(programScope))) { - // Calculate resulting constant literal - ConstantLiteral leftLiteral = leftValue.calculateLiteral(programScope); - ConstantLiteral rightLiteral = rightValue.calculateLiteral(programScope); - ConstantLiteral literal = operator.calculateLiteral(leftLiteral, rightLiteral); - if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) { - SymbolType literalType = SymbolTypeInference.inferType(programScope, leftValue, operator, rightValue); - ((ConstantInteger) literal).setType(literalType); - throw new InternalError("Unexpected advanced literal type calculation!"); - } - return inferTypes(programScope, literal); - } else { - throw new InternalError("Both operands must be number type."); - } - } - - /** - * Infer the potential types for a unary operator with {@link SymbolType#NUMBER} type - * - * @return The potential types - */ - public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, OperatorUnary operator, ConstantValue constantValue) { - if(SymbolType.NUMBER.equals(constantValue.getType(programScope))) { - // Calculate resulting constant literal - ConstantLiteral operandLiteral = constantValue.calculateLiteral(programScope); - ConstantLiteral literal = operator.calculateLiteral(operandLiteral, programScope); - if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) { - SymbolType literalType = SymbolTypeInference.inferType(programScope, operator, constantValue); - ((ConstantInteger) literal).setType(literalType); - throw new InternalError("Unexpected advanced literal type calculation!"); - } - return inferTypes(programScope, literal); - } else { - throw new InternalError("Operand must be number type."); - } - } - - /** - * Infer the potential types for a constant value with {@link SymbolType#NUMBER} type - * - * @return The potential types - */ - public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantValue constantValue) { - // Calculate resulting constant literal - ConstantLiteral constantLiteral = constantValue.calculateLiteral(programScope); - return inferTypes(programScope, constantLiteral); - } - - /** - * Infer the potential types for a constant literal with {@link SymbolType#NUMBER} type - */ - public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantLiteral literal) { - if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) { - return inferTypes(((ConstantInteger) literal).getValue()); - } else { - throw new InternalError("Literal must number type."); - } - } - /** * Find any fixed integer types that can contain the passed integer value * @param value the value to examine diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java index 8be80416d..451b04e87 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java @@ -1,7 +1,7 @@ package dk.camelot64.kickc.model.types; /** A pointer */ -public class SymbolTypePointer implements SymbolTypeSimple { +public class SymbolTypePointer implements SymbolType { /** The number of bytes needed to represent a pointer in memory. */ public static final int SIZE_BYTES = 2; diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java index e97924672..30f9e25bd 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java @@ -3,7 +3,7 @@ package dk.camelot64.kickc.model.types; import java.util.Objects; /** A function returning another type */ -public class SymbolTypeProcedure implements SymbolTypeSimple { +public class SymbolTypeProcedure implements SymbolType { private SymbolType returnType; diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProgram.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProgram.java index 489f81cc8..186ba98b5 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProgram.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProgram.java @@ -1,7 +1,7 @@ package dk.camelot64.kickc.model.types; /** A program */ -public class SymbolTypeProgram implements SymbolTypeSimple { +public class SymbolTypeProgram implements SymbolType { public SymbolTypeProgram() { diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeSimple.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeSimple.java deleted file mode 100644 index ea306056a..000000000 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeSimple.java +++ /dev/null @@ -1,5 +0,0 @@ -package dk.camelot64.kickc.model.types; - -/** Marker interface for simple symbol types - ie. not a multi-type */ -public interface SymbolTypeSimple extends SymbolType { -} From 669064bd37dae72f3aa3e851b388263f865c020d Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Wed, 22 May 2019 23:59:43 +0200 Subject: [PATCH 70/93] Eliminated SymbolTypeNumberInference. --- .../fragment/AsmFragmentInstanceSpec.java | 20 ++++++++++++-- .../types/SymbolTypeNumberInference.java | 27 ------------------- .../passes/PassNTypeIdSimplification.java | 25 ----------------- 3 files changed, 18 insertions(+), 54 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java index 09d9be44f..9a003f18b 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java @@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed; -import dk.camelot64.kickc.model.types.SymbolTypeNumberInference; import dk.camelot64.kickc.model.values.*; import java.util.*; @@ -49,6 +48,7 @@ public class AsmFragmentInstanceSpec { this.codeScopeRef = codeScopeRef; } + public String getSignature() { return signature; } @@ -95,7 +95,7 @@ public class AsmFragmentInstanceSpec { if(value instanceof ConstantValue) { ConstantLiteral constantLiteral = ((ConstantValue) value).calculateLiteral(program.getScope()); if(constantLiteral instanceof ConstantInteger) { - List<SymbolTypeIntegerFixed> types = SymbolTypeNumberInference.inferTypes(((ConstantInteger) constantLiteral).getValue()); + List<SymbolTypeIntegerFixed> types = getVariationTypes(((ConstantInteger) constantLiteral).getValue()); if(types.size() > 1) { // Found constant value with multiple types variationConstant = (ConstantValue) value; @@ -118,6 +118,22 @@ public class AsmFragmentInstanceSpec { return variationIterator.hasNext(); } + /** + * Find any fixed integer types that can contain the passed integer value + * @param value the value to examine + * @return All fixed size integer types capable of representing the passed value + */ + public static List<SymbolTypeIntegerFixed> getVariationTypes(Long value) { + ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>(); + for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) { + if(typeInteger.contains(value)) { + potentialTypes.add(typeInteger); + } + } + return potentialTypes; + } + + /** * Updates the ASM fragment instance specification to the next available variation. * If no more variations exist the ASM fragment instance specification will become unusable. diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java deleted file mode 100644 index 9a1519369..000000000 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java +++ /dev/null @@ -1,27 +0,0 @@ -package dk.camelot64.kickc.model.types; - -import java.util.ArrayList; -import java.util.List; - -/** - * Interference of possible types for constant expressions with the {@link SymbolType#NUMBER} type. - * This is done by evaluating the constant expression to find the literal value. - */ -public class SymbolTypeNumberInference { - - /** - * Find any fixed integer types that can contain the passed integer value - * @param value the value to examine - * @return All fixed size integer types capable of representing the passed value - */ - public static List<SymbolTypeIntegerFixed> inferTypes(Long value) { - ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>(); - for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) { - if(typeInteger.contains(value)) { - potentialTypes.add(typeInteger); - } - } - return potentialTypes; - } - -} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java index 1b110077d..1e6b5ffd0 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java @@ -42,31 +42,6 @@ public class PassNTypeIdSimplification extends Pass2SsaOptimization { } }); - /* - for(ControlFlowBlock block : getGraph().getAllBlocks()) { - for(Statement statement : block.getStatements()) { - if(statement instanceof StatementAssignment) { - StatementAssignment assignment = (StatementAssignment) statement; - if(Operators.TYPEID.equals(assignment.getOperator())) { - RValue rValue = assignment.getrValue2(); - SymbolType symbolType = SymbolTypeInference.inferType(getSymbols(), rValue); - if(SymbolType.NUMBER.equals(symbolType)) { - if(rValue instanceof ConstantValue) { - List<SymbolTypeIntegerFixed> fixedTypes = SymbolTypeNumberInference.inferTypes(getSymbols(), (ConstantLiteral) rValue); - throw new InternalError("TODO: Implement typeof(const)!"); - } - } else { - getLog().append("Resolving typeid() " + assignment.toString(getProgram(), false)); - ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getSymbols(), symbolType); - assignment.setrValue2(typeIDConstantVar); - assignment.setOperator(null); - modified = true; - } - } - } - } - } - */ return modified.get(); } } From 49a61ecbdd4f27957596ce2e7156a8e887d80471 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 00:28:34 +0200 Subject: [PATCH 71/93] Cleaning up type inference. --- .../model/types/SymbolTypeInference.java | 2 +- .../kickc/passes/Pass2AssertTypeMatch.java | 3 +- .../kickc/passes/PassNTypeInference.java | 28 ++----------------- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index f2af3c947..6cb623454 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -137,7 +137,7 @@ public class SymbolTypeInference { } } - public static SymbolType inferTypeRValue(ProgramScope symbols, StatementAssignment assignment) { + private static SymbolType inferTypeRValue(ProgramScope symbols, StatementAssignment assignment) { SymbolType rValueType; RValue rValue1 = assignment.getrValue1(); RValue rValue2 = assignment.getrValue2(); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java index 5e9e3157d..2a1e626af 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java @@ -9,6 +9,7 @@ import dk.camelot64.kickc.model.statements.StatementConditionalJump; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeConversion; import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.values.AssignmentRValue; import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.RValue; @@ -50,7 +51,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion { private void checkAssignment(StatementAssignment statement) { LValue lValue = statement.getlValue(); SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue); - SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), statement); + SymbolType rValueType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(statement)); if(SymbolTypeConversion.assignmentTypeMatch(lValueType, rValueType)) return; // Types do not match getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false)); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java index d37114431..365829e6a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java @@ -3,14 +3,12 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.ControlFlowBlock; import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.operators.Operator; -import dk.camelot64.kickc.model.operators.OperatorBinary; -import dk.camelot64.kickc.model.operators.OperatorUnary; import dk.camelot64.kickc.model.statements.*; import dk.camelot64.kickc.model.symbols.Procedure; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.types.*; +import dk.camelot64.kickc.model.values.AssignmentRValue; import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.RValue; import dk.camelot64.kickc.model.values.VariableRef; @@ -117,28 +115,8 @@ public class PassNTypeInference extends Pass2SsaOptimization { if(lValue instanceof VariableRef) { Variable symbol = programScope.getVariable((VariableRef) lValue); if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { - // Unresolved symbol - perform inference - Operator operator = assignment.getOperator(); - if(assignment.getrValue1() == null && operator == null) { - // Copy operation - RValue rValue = assignment.getrValue2(); - SymbolType type = SymbolTypeInference.inferType(programScope, rValue); - setInferedType(program, assignment, symbol, type); - } else if(assignment.getrValue1() == null && operator instanceof OperatorUnary) { - // Unary operation - RValue rValue = assignment.getrValue2(); - SymbolType type = SymbolTypeInference.inferType(programScope, (OperatorUnary) operator, rValue); - setInferedType(program, assignment, symbol, type); - } else if(operator instanceof OperatorBinary) { - // Binary operation - SymbolType type = SymbolTypeInference.inferType( - programScope, assignment.getrValue1(), - (OperatorBinary) assignment.getOperator(), - assignment.getrValue2()); - setInferedType(program, assignment, symbol, type); - } else { - throw new CompileError("Cannot infer type of " + assignment); - } + SymbolType type = SymbolTypeInference.inferType(programScope, new AssignmentRValue(assignment)); + setInferedType(program, assignment, symbol, type); // If the type is an array or a string the symbol is constant if(symbol.getType() instanceof SymbolTypeArray) { symbol.setDeclaredConstant(true); From 65c92716f03500a4e2aeaa59e6055ec811d679a2 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 00:38:35 +0200 Subject: [PATCH 72/93] Cleaning up type inference. --- .../model/types/SymbolTypeInference.java | 76 +++++++------------ .../kickc/model/values/ConstantBinary.java | 4 +- .../kickc/model/values/ConstantUnary.java | 3 +- .../passes/Pass2DeInlineWordDerefIdx.java | 8 +- 4 files changed, 37 insertions(+), 54 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index 6cb623454..c2875ef15 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -3,43 +3,15 @@ package dk.camelot64.kickc.model.types; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.operators.OperatorBinary; import dk.camelot64.kickc.model.operators.OperatorUnary; -import dk.camelot64.kickc.model.statements.*; +import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.symbols.*; import dk.camelot64.kickc.model.values.*; /** - * Type inference of expressions (rValues & unary/binary operators) + * Type inference of an RValue */ public class SymbolTypeInference { - /** - * Infer the type of a unary operator on a value - * - * @param programScope The program scope usable for accessing the symbol table - * @param operator The unary operator - * @param rValue The value - * @return The type of the resulting value - */ - public static SymbolType inferType(ProgramScope programScope, OperatorUnary operator, RValue rValue) { - SymbolType valueType = inferType(programScope, rValue); - return operator.inferType(valueType); - } - - /** - * Infer the type of a binary operator on a value - * - * @param programScope The program scope usable for accessing the symbol table - * @param left The left value - * @param operator The binary operator - * @param rValue The right value - * @return The type of the resulting value - */ - public static SymbolType inferType(ProgramScope programScope, RValue left, OperatorBinary operator, RValue right) { - SymbolType leftType = inferType(programScope, left); - SymbolType rightType = inferType(programScope, right); - return operator.inferType(leftType, rightType); - } - public static SymbolType inferType(ProgramScope symbols, RValue rValue) { SymbolType type = null; if(rValue instanceof VariableRef) { @@ -61,10 +33,13 @@ public class SymbolTypeInference { type = SymbolType.BOOLEAN; } else if(rValue instanceof ConstantUnary) { ConstantUnary constUnary = (ConstantUnary) rValue; - return inferType(symbols, constUnary.getOperator(), constUnary.getOperand()); + SymbolType valueType = inferType(symbols, constUnary.getOperand()); + return constUnary.getOperator().inferType(valueType); } else if(rValue instanceof ConstantBinary) { ConstantBinary constBin = (ConstantBinary) rValue; - return inferType(symbols, constBin.getLeft(), constBin.getOperator(), constBin.getRight()); + SymbolType leftType = inferType(symbols, constBin.getLeft()); + SymbolType rightType = inferType(symbols, constBin.getRight()); + return constBin.getOperator().inferType(leftType, rightType); } else if(rValue instanceof ValueList) { type = inferTypeList(symbols, (ValueList) rValue); } else if(rValue instanceof PointerDereference) { @@ -103,7 +78,26 @@ public class SymbolTypeInference { Procedure procedure = symbols.getProcedure((ProcedureRef) rValue); return procedure.getType(); } else if(rValue instanceof AssignmentRValue) { - return inferTypeRValue(symbols, ((AssignmentRValue) rValue).getAssignment()); + StatementAssignment assignment = ((AssignmentRValue) rValue).getAssignment(); + SymbolType rValueType; + RValue rValue1 = assignment.getrValue1(); + RValue rValue2 = assignment.getrValue2(); + if(assignment.getrValue1() == null && assignment.getOperator() == null) { + // Copy assignment + rValueType = inferType(symbols, rValue2); + } else if(assignment.getrValue1() == null && assignment.getOperator() instanceof OperatorUnary) { + // Unary operation assignment + SymbolType valueType = inferType(symbols, rValue2); + rValueType = ((OperatorUnary) assignment.getOperator()).inferType(valueType); + } else if(assignment.getOperator() instanceof OperatorBinary) { + // Binary operation assignment + SymbolType leftType = inferType(symbols, rValue1); + SymbolType rightType = inferType(symbols, rValue2); + rValueType = ((OperatorBinary) assignment.getOperator()).inferType(leftType, rightType); + } else { + throw new CompileError("Cannot infer type of " + assignment.toString()); + } + return rValueType; } if(type == null) { throw new RuntimeException("Cannot infer type for " + rValue.toString()); @@ -137,20 +131,4 @@ public class SymbolTypeInference { } } - private static SymbolType inferTypeRValue(ProgramScope symbols, StatementAssignment assignment) { - SymbolType rValueType; - RValue rValue1 = assignment.getrValue1(); - RValue rValue2 = assignment.getrValue2(); - if(assignment.getrValue1() == null && assignment.getOperator() == null) { - rValueType = inferType(symbols, rValue2); - } else if(assignment.getrValue1() == null && assignment.getOperator() instanceof OperatorUnary) { - rValueType = inferType(symbols, (OperatorUnary) assignment.getOperator(), rValue2); - } else if(assignment.getOperator() instanceof OperatorBinary) { - rValueType = inferType(symbols, rValue1, (OperatorBinary) assignment.getOperator(), rValue2); - } else { - throw new CompileError("Cannot infer type of " + assignment.toString()); - } - return rValueType; - } - } diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java index df51994a4..90896ad5e 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java @@ -59,7 +59,9 @@ public class ConstantBinary implements ConstantValue { @Override public SymbolType getType(ProgramScope scope) { - return SymbolTypeInference.inferType(scope, left, operator, right); + SymbolType leftType = SymbolTypeInference.inferType(scope, left); + SymbolType rightType = SymbolTypeInference.inferType(scope, right); + return operator.inferType(leftType, rightType); } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java index a111b9c07..d6ca0a7f9 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java @@ -47,7 +47,8 @@ public class ConstantUnary implements ConstantValue { @Override public SymbolType getType(ProgramScope scope) { - return SymbolTypeInference.inferType(scope, operator, operand); + SymbolType valueType = SymbolTypeInference.inferType(scope, operand); + return operator.inferType(valueType); } @Override diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java index 4bfcbac8a..2b0b96cce 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java @@ -9,6 +9,7 @@ import dk.camelot64.kickc.model.symbols.Scope; import dk.camelot64.kickc.model.symbols.VariableIntermediate; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.values.AssignmentRValue; import dk.camelot64.kickc.model.values.PointerDereferenceIndexed; import dk.camelot64.kickc.model.values.PointerDereferenceSimple; import dk.camelot64.kickc.model.values.RValue; @@ -35,12 +36,13 @@ public class Pass2DeInlineWordDerefIdx extends Pass2SsaOptimization { getLog().append("De-inlining pointer[w] to *(pointer+w) "+currentStmt.toString(getProgram(), false)); Scope currentScope = getScope().getScope(currentBlock.getScope()); VariableIntermediate tmpVar = currentScope.addVariableIntermediate(); - SymbolType pointerType = SymbolTypeInference.inferType(getScope(), dereferenceIndexed.getPointer(), Operators.PLUS, indexValue); - tmpVar.setType(pointerType); stmtIt.previous(); - stmtIt.add(new StatementAssignment(tmpVar.getRef(), dereferenceIndexed.getPointer(), Operators.PLUS, indexValue, currentStmt.getSource(), Comment.NO_COMMENTS)); + StatementAssignment tmpVarAssignment = new StatementAssignment(tmpVar.getRef(), dereferenceIndexed.getPointer(), Operators.PLUS, indexValue, currentStmt.getSource(), Comment.NO_COMMENTS); + stmtIt.add(tmpVarAssignment); stmtIt.next(); programValue.set(new PointerDereferenceSimple(tmpVar.getRef())); + SymbolType pointerType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(tmpVarAssignment)); + tmpVar.setType(pointerType); optimized.set(true); } } From 2a146714966bd978a6097d41ab8a2eefebc7b69c Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 00:46:43 +0200 Subject: [PATCH 73/93] Renamed for clarity --- .../kickc/passes/Pass1FixLValuesLoHi.java | 2 +- .../kickc/passes/PassNTypeInference.java | 22 +++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java index 68d13d0e3..1e65038e9 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java @@ -79,7 +79,7 @@ public class Pass1FixLValuesLoHi extends Pass1Base { VariableIntermediate tmpVar = currentScope.addVariableIntermediate(); VariableRef tmpVarRef = tmpVar.getRef(); statementLValue.setlValue(tmpVarRef); - PassNTypeInference.inferLValue(getProgram(), statementLValue); + PassNTypeInference.updateInferedTypeLValue(getProgram(), statementLValue); // Insert an extra "set low" assignment statement Statement setLoHiAssignment = new StatementAssignment(loHiVar, loHiVar, loHiOperator, tmpVarRef, statementLValue.getSource(), new ArrayList<>()); statementsIt.add(setLoHiAssignment); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java index 365829e6a..4e135e916 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java @@ -15,7 +15,6 @@ import dk.camelot64.kickc.model.values.VariableRef; /** * Pass through the generated statements inferring types of unresolved variables. - * Also updates procedure calls to point to the actual procedure called. */ public class PassNTypeInference extends Pass2SsaOptimization { @@ -23,17 +22,16 @@ public class PassNTypeInference extends Pass2SsaOptimization { super(program); } - @Override public boolean step() { for(ControlFlowBlock block : getGraph().getAllBlocks()) { for(Statement statement : block.getStatements()) { try { if(statement instanceof StatementLValue) { - inferLValue(getProgram(), (StatementLValue) statement); + updateInferedTypeLValue(getProgram(), (StatementLValue) statement); } else if(statement instanceof StatementPhiBlock) { for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) { - inferPhiVariable(getProgram(), phiVariable); + updateInferedTypePhiVariable(getProgram(), phiVariable); } } } catch(CompileError e) { @@ -44,20 +42,20 @@ public class PassNTypeInference extends Pass2SsaOptimization { return false; } - public static void inferLValue(Program program, StatementLValue statementLValue) { + static void updateInferedTypeLValue(Program program, StatementLValue statementLValue) { if(statementLValue instanceof StatementAssignment) { - inferAssignmentLValue(program, (StatementAssignment) statementLValue); + updateInferedTypeAssignmentLValue(program, (StatementAssignment) statementLValue); } else if(statementLValue instanceof StatementCall) { - inferCallLValue(program, (StatementCall) statementLValue); + updateInferedTypeCallLValue(program, (StatementCall) statementLValue); } else if(statementLValue instanceof StatementCallPointer) { - inferCallPointerLValue(program, (StatementCallPointer) statementLValue); + updateInferedTypeCallPointerLValue(program, (StatementCallPointer) statementLValue); } else { throw new RuntimeException("LValue statement not implemented " + statementLValue); } } - private static void inferCallLValue(Program program, StatementCall call) { + private static void updateInferedTypeCallLValue(Program program, StatementCall call) { ProgramScope programScope = program.getScope(); LValue lValue = call.getlValue(); if(lValue instanceof VariableRef) { @@ -70,7 +68,7 @@ public class PassNTypeInference extends Pass2SsaOptimization { } } - private static void inferCallPointerLValue(Program program, StatementCallPointer call) { + private static void updateInferedTypeCallPointerLValue(Program program, StatementCallPointer call) { ProgramScope programScope = program.getScope(); LValue lValue = call.getlValue(); if(lValue instanceof VariableRef) { @@ -85,7 +83,7 @@ public class PassNTypeInference extends Pass2SsaOptimization { } } - private static void inferPhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) { + private static void updateInferedTypePhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) { ProgramScope programScope = program.getScope(); Variable symbol = programScope.getVariable(phiVariable.getVariable()); if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { @@ -109,7 +107,7 @@ public class PassNTypeInference extends Pass2SsaOptimization { } } - private static void inferAssignmentLValue(Program program, StatementAssignment assignment) { + private static void updateInferedTypeAssignmentLValue(Program program, StatementAssignment assignment) { ProgramScope programScope = program.getScope(); LValue lValue = assignment.getlValue(); if(lValue instanceof VariableRef) { From 009b141ef161423303ea1621d71c1d5c1d7128f7 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 01:07:59 +0200 Subject: [PATCH 74/93] Eliminated PassNDowngradeConstantTypeConversion. Simplified PassNAddTypeConversionAssignment. --- .../java/dk/camelot64/kickc/Compiler.java | 1 - .../Pass0GenerateStatementSequence.java | 4 +- .../PassNAddTypeConversionAssignment.java | 9 -- ...PassNDowngradeConstantTypeConversions.java | 90 ------------------- src/test/ref/linegen.asm | 5 +- src/test/ref/signed-indexed-subtract.asm | 51 +++++------ 6 files changed, 27 insertions(+), 133 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index c1616481a..b6217ad15 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -233,7 +233,6 @@ public class Compiler { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); optimizations.add(new PassNAddNumberTypeConversions(program)); optimizations.add(new PassNAddArrayNumberTypeConversions(program)); - optimizations.add(new PassNDowngradeConstantTypeConversions(program)); optimizations.add(new PassNTypeInference(program)); optimizations.add(new PassNTypeIdSimplification(program)); optimizations.add(new Pass2SizeOfSimplification(program)); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 3426efd3c..2a5e5faea 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -908,8 +908,8 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { RValue rangeLastValue = (RValue) visit(rangeLastCtx); RValue rangeFirstValue = (RValue) visit(rangeFirstCtx); if(varType!=null) { - if(rangeFirstValue instanceof ConstantInteger) ((ConstantInteger) rangeFirstValue).setType(varType); - if(rangeLastValue instanceof ConstantInteger) ((ConstantInteger) rangeLastValue).setType(varType); + if(rangeFirstValue instanceof ConstantInteger) ((ConstantInteger) rangeFirstValue).setType(SymbolType.NUMBER); + if(rangeLastValue instanceof ConstantInteger) ((ConstantInteger) rangeLastValue).setType(SymbolType.NUMBER); } Statement stmtInit = new StatementAssignment(lValue.getRef(), rangeFirstValue, new StatementSource(ctx), Comment.NO_COMMENTS); sequence.addStatement(stmtInit); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java index 4b74e0e9c..d34690762 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java @@ -63,15 +63,6 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization { } } - if(leftType instanceof SymbolTypeIntegerFixed && SymbolType.isInteger(rightType)) { - SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType); - // Add cast to the right Type if needed - if(leftType.equals(conversionType) && !rightType.equals(conversionType)) { - getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); - binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); - modified.set(true); - } - } } } }); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java deleted file mode 100644 index e87e6e748..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java +++ /dev/null @@ -1,90 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary; -import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.values.*; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Downgrade any number expression cast that are part of a WORD+NUMBER expression to BYTE if the number is small enough to fit in the byte. - */ -public class PassNDowngradeConstantTypeConversions extends Pass2SsaOptimization { - - public PassNDowngradeConstantTypeConversions(Program program) { - super(program); - } - - @Override - public boolean step() { - AtomicBoolean modified = new AtomicBoolean(false); - ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> { - if(binaryExpression instanceof ProgramExpressionBinary) { - ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression; - RValue left = binary.getLeft(); - RValue right = binary.getRight(); - if(isConstantWord(left) && isWordLike(right) && isByteLike((ConstantValue) left)) { - getLog().append("Downgrading number conversion cast to (byte) " + binary.getLeft().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); - binary.addLeftCast(SymbolType.BYTE, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); - modified.set(true); - } else if(isConstantWord(right) && isWordLike(left) && isByteLike((ConstantValue) right)) { - getLog().append("Downgrading number conversion cast to (byte) " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false))); - binary.addRightCast(SymbolType.BYTE, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope()); - modified.set(true); - } - - } - }); - return modified.get(); - } - - /** - * Determines if a constant value is a byte-like value (can be represented inside a BYTE) - * - * @param constantValue The value to examine - * @return true if the value is a byte-like value - */ - public boolean isByteLike(ConstantValue constantValue) { - ConstantLiteral constantLiteral = (constantValue).calculateLiteral(getScope()); - if(constantLiteral instanceof ConstantInteger) { - ConstantInteger constantInteger = (ConstantInteger) constantLiteral; - Long value = constantInteger.getValue(); - if(SymbolType.BYTE.contains(value)) { - return true; - } - } - return false; - } - - /** - * Determines if a value is a word-like value (WORD or Pointer) - * - * @param rValue The value to examine - * @return true if the value is a word-like value - */ - public boolean isWordLike(RValue rValue) { - SymbolType symbolType = SymbolTypeInference.inferType(getProgram().getScope(), rValue); - return SymbolType.WORD.equals(symbolType) || symbolType instanceof SymbolTypePointer; - } - - - /** - * Determines if the passed value is a constant cast to WORD - * - * @param rValue The value to examine - * @return true if the value is a constant cast to word - */ - public boolean isConstantWord(RValue rValue) { - if(rValue instanceof ConstantInteger && SymbolType.WORD.equals(((ConstantInteger) rValue).getType())) { - return true; - } - if((rValue instanceof ConstantCastValue) && SymbolType.WORD.equals(((ConstantCastValue) rValue).getToType())) - return true; - return false; - } - -} diff --git a/src/test/ref/linegen.asm b/src/test/ref/linegen.asm index 4b4fcd8a9..4cbd79681 100644 --- a/src/test/ref/linegen.asm +++ b/src/test/ref/linegen.asm @@ -335,13 +335,14 @@ lin16u_gen: { sta step lda stepf+1 sta step+1 + lda #<0 + sta val + sta val+1 lda min sta val+2 lda min+1 sta val+3 lda #0 - sta val - sta val+1 sta i sta i+1 b1: diff --git a/src/test/ref/signed-indexed-subtract.asm b/src/test/ref/signed-indexed-subtract.asm index 7ca3ce033..8904aed68 100644 --- a/src/test/ref/signed-indexed-subtract.asm +++ b/src/test/ref/signed-indexed-subtract.asm @@ -2,25 +2,22 @@ .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" - .label print_line_cursor = 3 + .label print_line_cursor = 2 .label print_char_cursor = 7 main: { - .label i = 2 - lda #0 - sta i + ldy #0 b1: - lda i + tya ldx #$80 jsr sub - lda i + tya ldx #$40 jsr sub - lda i + tya ldx #$40 jsr sub - inc i - lda #9 - cmp i + iny + cpy #9 bne b1 jsr print_cls lda #<$400 @@ -74,9 +71,9 @@ print_ln: { rts } // Print a signed word as HEX -// print_sword(signed word zeropage(5) w) +// print_sword(signed word zeropage(4) w) print_sword: { - .label w = 5 + .label w = 4 lda w+1 bpl b1 lda #'-' @@ -95,9 +92,9 @@ print_sword: { rts } // Print a word as HEX -// print_word(word zeropage(5) w) +// print_word(word zeropage(4) w) print_word: { - .label w = 5 + .label w = 4 lda w+1 sta print_byte.b jsr print_byte @@ -107,9 +104,9 @@ print_word: { rts } // Print a byte as HEX -// print_byte(byte zeropage(2) b) +// print_byte(byte zeropage(6) b) print_byte: { - .label b = 2 + .label b = 6 lda b lsr lsr @@ -138,7 +135,7 @@ print_char: { } // Clear the screen. Also resets current line/char cursor. print_cls: { - .label sc = 3 + .label sc = 2 lda #<$400 sta sc lda #>$400 @@ -161,20 +158,16 @@ print_cls: { } // sub(byte register(A) idx, byte register(X) s) sub: { - .label _1 = 3 asl - tay - txa - sta _1 - lda #0 - sta _1+1 - lda words,y sec - sbc _1 - sta words,y - lda words+1,y - sbc _1+1 - sta words+1,y + stx $ff + tax + lda words,x + sbc $ff + sta words,x + bcs !+ + dec words+1,x + !: rts } print_hextab: .text "0123456789abcdef" From fdbfa68c1c202c20961bd36d978f190e3a928f5a Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 07:12:52 +0200 Subject: [PATCH 75/93] Eliminated Pass2EliminateRedundantCasts. --- .../java/dk/camelot64/kickc/Compiler.java | 1 - .../passes/Pass2EliminateRedundantCasts.java | 75 ------------------- 2 files changed, 76 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2EliminateRedundantCasts.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index b6217ad15..6e35e5a99 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -255,7 +255,6 @@ public class Compiler { optimizations.add(new PassNVariableReferenceInfos(program)); optimizations.add(new Pass2FixInlineConstructorsNew(program)); optimizations.add(new PassNAddTypeConversionAssignment(program)); - optimizations.add(new Pass2EliminateRedundantCasts(program)); optimizations.add(new Pass2RangeResolving(program)); optimizations.add(new Pass2ComparisonOptimization(program)); optimizations.add(new Pass2InlineCast(program)); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2EliminateRedundantCasts.java b/src/main/java/dk/camelot64/kickc/passes/Pass2EliminateRedundantCasts.java deleted file mode 100644 index 40731c99a..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2EliminateRedundantCasts.java +++ /dev/null @@ -1,75 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.ControlFlowBlock; -import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.operators.OperatorCastPtr; -import dk.camelot64.kickc.model.operators.Operators; -import dk.camelot64.kickc.model.statements.Statement; -import dk.camelot64.kickc.model.statements.StatementAssignment; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeInference; -import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.values.RValue; - -/** - * Eliminate casts that are not necessary - */ -public class Pass2EliminateRedundantCasts extends Pass2SsaOptimization { - - public Pass2EliminateRedundantCasts(Program program) { - super(program); - } - - @Override - public boolean step() { - boolean modified = false; - for(ControlFlowBlock block : getGraph().getAllBlocks()) { - for(Statement statement : block.getStatements()) { - if(statement instanceof StatementAssignment) { - StatementAssignment assignment = (StatementAssignment) statement; - if(isRedundantCast(assignment)) { - // Redundant cast - getLog().append("Removing redundant cast " + statement.toString(getProgram(), false)); - assignment.setOperator(null); - modified = true; - } - } - } - } - return modified; - } - - /** - * Determines if the assignment is a redundant cast - * - * @param assignment The assignment to examine - * @return true if is is a redundant cast - */ - private boolean isRedundantCast(StatementAssignment assignment) { - RValue rValue2 = assignment.getrValue2(); - SymbolType rValue2Type = SymbolTypeInference.inferType(getScope(), rValue2); - if(Operators.CAST_BYTE.equals(assignment.getOperator()) && SymbolType.BYTE.equals(rValue2Type)) { - return true; - } else if(Operators.CAST_SBYTE.equals(assignment.getOperator()) && SymbolType.SBYTE.equals(rValue2Type)) { - return true; - } else if(Operators.CAST_WORD.equals(assignment.getOperator()) && SymbolType.WORD.equals(rValue2Type)) { - return true; - } else if(Operators.CAST_SWORD.equals(assignment.getOperator()) && SymbolType.SWORD.equals(rValue2Type)) { - return true; - } else if(Operators.CAST_DWORD.equals(assignment.getOperator()) && SymbolType.DWORD.equals(rValue2Type)) { - return true; - } else if(Operators.CAST_SDWORD.equals(assignment.getOperator()) && SymbolType.SDWORD.equals(rValue2Type)) { - return true; - } else if(Operators.CAST_BOOL.equals(assignment.getOperator()) && SymbolType.BOOLEAN.equals(rValue2Type)) { - return true; - } else if(assignment.getOperator() instanceof OperatorCastPtr) { - // Casting to a pointer - OperatorCastPtr operatorCastPtr = (OperatorCastPtr) assignment.getOperator(); - if(rValue2Type.equals(new SymbolTypePointer(operatorCastPtr.getElementType()))) { - return true; - } - } - return false; - } - -} From 1df77d5ded1fc5b5de4988b85e4f907bbb30b94d Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 07:39:10 +0200 Subject: [PATCH 76/93] Collected all type inference in pass2 together. --- src/main/java/dk/camelot64/kickc/Compiler.java | 13 ++++++++----- .../model/iterator/ProgramExpressionIterator.java | 10 +++++----- .../kickc/passes/Pass2FixInlineConstructorsNew.java | 2 +- .../ref/examples/bresenham/bitmap-bresenham.asm | 6 +++--- src/test/ref/examples/sinplotter/sine-plotter.asm | 12 ++++++------ src/test/ref/inline-pointer-1.asm | 6 +++--- src/test/ref/inline-string-3.asm | 6 +++--- src/test/ref/line-anim.asm | 12 ++++++------ src/test/ref/pointer-plus-0.asm | 10 ++++------ 9 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 6e35e5a99..0aff5a280 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -231,9 +231,16 @@ public class Compiler { private void pass2Optimize() { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); + + optimizations.add(new Pass2FixInlineConstructorsNew(program)); + optimizations.add(new PassNAddNumberTypeConversions(program)); optimizations.add(new PassNAddArrayNumberTypeConversions(program)); optimizations.add(new PassNTypeInference(program)); + optimizations.add(new PassNAddTypeConversionAssignment(program)); + optimizations.add(new Pass2InlineCast(program)); + optimizations.add(new PassNCastSimplification(program)); + optimizations.add(new PassNTypeIdSimplification(program)); optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new Pass2CullEmptyBlocks(program)); @@ -243,6 +250,7 @@ public class Compiler { optimizations.add(new Pass2AliasElimination(program)); optimizations.add(new Pass2SelfPhiElimination(program)); optimizations.add(new Pass2IdenticalPhiElimination(program)); + optimizations.add(new Pass2DuplicateRValueIdentification(program)); optimizations.add(new Pass2ConditionalJumpSimplification(program)); optimizations.add(new Pass2ConditionalAndOrRewriting(program)); optimizations.add(new Pass2ConstantRValueConsolidation(program)); @@ -253,19 +261,14 @@ public class Compiler { optimizations.add(new Pass2ConstantStringConsolidation(program)); optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNVariableReferenceInfos(program)); - optimizations.add(new Pass2FixInlineConstructorsNew(program)); - optimizations.add(new PassNAddTypeConversionAssignment(program)); optimizations.add(new Pass2RangeResolving(program)); optimizations.add(new Pass2ComparisonOptimization(program)); - optimizations.add(new Pass2InlineCast(program)); - optimizations.add(new PassNCastSimplification(program)); optimizations.add(new Pass2InlineDerefIdx(program)); optimizations.add(new Pass2DeInlineWordDerefIdx(program)); optimizations.add(new PassNSimplifyConstantZero(program)); optimizations.add(new PassNSimplifyExpressionWithZero(program)); optimizations.add(new PassNEliminateUnusedVars(program, true)); optimizations.add(new Pass2EliminateUnusedBlocks(program)); - optimizations.add(new Pass2DuplicateRValueIdentification(program)); pass2Execute(optimizations); } diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java index 1995dbf5e..4411ffd80 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java @@ -27,15 +27,15 @@ public class ProgramExpressionIterator { // Iterate all symbols ProgramValueHandler programValueHandler = (programValue, currentStmt, stmtIt, currentBlock) -> { if(programValue.get() instanceof ConstantBinary) { - handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), null, null, null); + handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), currentStmt, stmtIt, currentBlock); } else if(programValue.get() instanceof ConstantUnary) { - handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), null, null, null); + handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), currentStmt, stmtIt, currentBlock); } else if(programValue.get() instanceof PointerDereferenceIndexed) { - handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), null, null, null); + handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), currentStmt, stmtIt, currentBlock); } else if(programValue.get() instanceof ConstantCastValue) { - handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstantCast(programValue), null, null, null); + handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstantCast(programValue), currentStmt, stmtIt, currentBlock); } else if(programValue.get() instanceof CastValue) { - handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryCast(programValue), null, null, null); + handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryCast(programValue), currentStmt, stmtIt, currentBlock); } }; ProgramValueIterator.execute(program.getScope(), programValueHandler); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java index e8c83cf29..9bb996f01 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java @@ -77,7 +77,7 @@ public class Pass2FixInlineConstructorsNew extends Pass2SsaOptimization { // Convert list to a word constructor in a new tmp variable Scope currentScope = Pass2FixInlineConstructorsNew.this.getScope().getScope(currentBlock.getScope()); VariableIntermediate tmpVar = currentScope.addVariableIntermediate(); - tmpVar.setTypeInferred(constructType); + //tmpVar.setTypeInferred(constructType); // Move backward - to insert before the current statement stmtIt.previous(); // Add assignment of the new tmpVar diff --git a/src/test/ref/examples/bresenham/bitmap-bresenham.asm b/src/test/ref/examples/bresenham/bitmap-bresenham.asm index c6f38704b..5c7a99cac 100644 --- a/src/test/ref/examples/bresenham/bitmap-bresenham.asm +++ b/src/test/ref/examples/bresenham/bitmap-bresenham.asm @@ -336,11 +336,11 @@ init_screen: { bitmap_clear: { .label bitmap = 9 .label y = 2 - .label _4 = 9 + .label _3 = 9 lda bitmap_plot_xlo - sta _4 + sta _3 lda bitmap_plot_xhi - sta _4+1 + sta _3+1 lda #0 sta y b1: diff --git a/src/test/ref/examples/sinplotter/sine-plotter.asm b/src/test/ref/examples/sinplotter/sine-plotter.asm index e86b7ba4e..a7f77bdfb 100644 --- a/src/test/ref/examples/sinplotter/sine-plotter.asm +++ b/src/test/ref/examples/sinplotter/sine-plotter.asm @@ -178,11 +178,11 @@ bitmap_plot: { .label plotter = 6 .label plotter_1 = $10 .label x = 4 - .label _4 = 6 + .label _3 = 6 lda bitmap_plot_yhi,x - sta _4+1 + sta _3+1 lda bitmap_plot_ylo,x - sta _4 + sta _3 lda x and #<$fff8 sta _1 @@ -729,11 +729,11 @@ divr16u: { bitmap_clear: { .label bitmap = 2 .label y = $16 - .label _4 = 2 + .label _3 = 2 lda bitmap_plot_ylo - sta _4 + sta _3 lda bitmap_plot_yhi - sta _4+1 + sta _3+1 lda #0 sta y b1: diff --git a/src/test/ref/inline-pointer-1.asm b/src/test/ref/inline-pointer-1.asm index 4da10ae54..3bf16934c 100644 --- a/src/test/ref/inline-pointer-1.asm +++ b/src/test/ref/inline-pointer-1.asm @@ -14,9 +14,9 @@ main: { // puta(byte register(A) ph, byte register(X) pl) puta: { .label screen = 2 - .label _2 = 2 - sta _2+1 - stx _2 + .label _1 = 2 + sta _1+1 + stx _1 lda #'a' ldy #0 sta (screen),y diff --git a/src/test/ref/inline-string-3.asm b/src/test/ref/inline-string-3.asm index 1e2abba8f..1881a03a3 100644 --- a/src/test/ref/inline-string-3.asm +++ b/src/test/ref/inline-string-3.asm @@ -8,15 +8,15 @@ main: { .label PTR = $9ffe .label SCREEN = $400 .label ptr = 2 - .label _7 = 2 + .label _6 = 2 lda #<STRING sta PTR lda #>STRING sta PTR+1 lda PTR - sta _7 + sta _6 lda PTR+1 - sta _7+1 + sta _6+1 ldy #0 lda (ptr),y sta SCREEN diff --git a/src/test/ref/line-anim.asm b/src/test/ref/line-anim.asm index e787357ed..862d9a41b 100644 --- a/src/test/ref/line-anim.asm +++ b/src/test/ref/line-anim.asm @@ -81,11 +81,11 @@ bitmap_plot: { .label x = 3 .label plotter = 5 .label plotter_1 = 7 - .label _4 = 5 + .label _3 = 5 lda bitmap_plot_yhi,x - sta _4+1 + sta _3+1 lda bitmap_plot_ylo,x - sta _4 + sta _3 lda x and #<$fff8 sta _1 @@ -428,11 +428,11 @@ screen_fill: { bitmap_clear: { .label bitmap = 3 .label y = 2 - .label _4 = 3 + .label _3 = 3 lda bitmap_plot_ylo - sta _4 + sta _3 lda bitmap_plot_yhi - sta _4+1 + sta _3+1 lda #0 sta y b1: diff --git a/src/test/ref/pointer-plus-0.asm b/src/test/ref/pointer-plus-0.asm index 8fc352c78..999a7535a 100644 --- a/src/test/ref/pointer-plus-0.asm +++ b/src/test/ref/pointer-plus-0.asm @@ -7,27 +7,25 @@ main: { .label _0 = 2 .label _2 = 2 lda #<msg1 - sta first.msg + sta first.return lda #>msg1 - sta first.msg+1 + sta first.return+1 jsr first ldy #0 lda (_0),y sta SCREEN lda #<msg2 - sta first.msg + sta first.return lda #>msg2 - sta first.msg+1 + sta first.return+1 jsr first ldy #0 lda (_2),y sta SCREEN+1 rts } -// first(byte* zeropage(2) msg) first: { .label return = 2 - .label msg = 2 rts } msg1: .text "hello world!@" From d5ebe81c218655a24511669ee8494eb6d3088c0b Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 07:41:18 +0200 Subject: [PATCH 77/93] Eliminated two redundant pass2 steps --- src/main/java/dk/camelot64/kickc/Compiler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 0aff5a280..84bd51381 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -259,8 +259,6 @@ public class Compiler { optimizations.add(new Pass2ConstantCallPointerIdentification(program)); optimizations.add(new Pass2ConstantIfs(program)); optimizations.add(new Pass2ConstantStringConsolidation(program)); - optimizations.add(new PassNStatementIndices(program)); - optimizations.add(new PassNVariableReferenceInfos(program)); optimizations.add(new Pass2RangeResolving(program)); optimizations.add(new Pass2ComparisonOptimization(program)); optimizations.add(new Pass2InlineDerefIdx(program)); From 01e833681ac100297288fc1e8c1c59236f9ce816 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 12:02:52 +0200 Subject: [PATCH 78/93] Improved planned sequence for A->B->C sequences where B is conditional successor of A. --- .../java/dk/camelot64/kickc/Compiler.java | 2 +- .../passes/PassNBlockSequencePlanner.java | 22 ++++++-- src/test/ref/bool-ifs.asm | 16 +++--- src/test/ref/bool-vars.asm | 18 +++---- src/test/ref/complex-conditional-problem.asm | 6 +-- src/test/ref/complex/tetris/tetris.asm | 54 +++++++++---------- .../multiplexer/simple-multiplexer.asm | 17 +++--- src/test/ref/loop-break-continue.asm | 12 ++--- src/test/ref/loop-break-nested.asm | 14 ++--- src/test/ref/loop-continue.asm | 6 +-- .../simple-multiplexer-irq.asm | 20 +++---- src/test/ref/no-recursion-heavy.asm | 3 ++ src/test/ref/sandbox.asm | 48 +++++++++-------- src/test/ref/signed-words.asm | 6 +-- src/test/ref/travis1.asm | 22 ++++---- 15 files changed, 143 insertions(+), 123 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 84bd51381..ae353382c 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -377,7 +377,7 @@ public class Compiler { new Pass3AssertConstants(program).check(); new Pass3AssertArrayLengths(program).check(); new Pass3AssertNoMulDivMod(program).check(); - new PassNBlockSequencePlanner(program).step(); + //new PassNBlockSequencePlanner(program).step(); // Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes new Pass3PhiLifting(program).perform(); new PassNBlockSequencePlanner(program).step(); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNBlockSequencePlanner.java b/src/main/java/dk/camelot64/kickc/passes/PassNBlockSequencePlanner.java index 810de150a..f020476a6 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNBlockSequencePlanner.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNBlockSequencePlanner.java @@ -39,11 +39,25 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization { if(block.getCallSuccessor() != null) { pushTodo(getGraph().getCallSuccessor(block)); } - if(block.getConditionalSuccessor() != null) { + ControlFlowBlock conditionalSuccessor = getGraph().getConditionalSuccessor(block); + ControlFlowBlock defaultSuccessor = getGraph().getDefaultSuccessor(block); + if(conditionalSuccessor != null && defaultSuccessor != null) { + // Both conditional and default successor + if(conditionalSuccessor.getDefaultSuccessor().equals(defaultSuccessor.getLabel())) { + // Best sequence is cond->default (resulting in better code locality) + pushTodo(defaultSuccessor); + pushTodo(getGraph().getConditionalSuccessor(block)); + } else { + // Best sequence is default->cond + pushTodo(getGraph().getConditionalSuccessor(block)); + pushTodo(defaultSuccessor); + } + } else if(conditionalSuccessor != null) { + // Only a conditional successor pushTodo(getGraph().getConditionalSuccessor(block)); - } - if(getGraph().getDefaultSuccessor(block) != null) { - pushTodo(getGraph().getDefaultSuccessor(block)); + } else if(defaultSuccessor != null) { + // Only a default successor + pushTodo(defaultSuccessor); } } diff --git a/src/test/ref/bool-ifs.asm b/src/test/ref/bool-ifs.asm index 0fc00115b..ef375b6fe 100644 --- a/src/test/ref/bool-ifs.asm +++ b/src/test/ref/bool-ifs.asm @@ -17,6 +17,10 @@ bool_complex: { and #1 cpx #$a bcc b6 + jmp b5 + b6: + cmp #0 + beq b2 b5: cpx #$a bcc b4 @@ -34,10 +38,6 @@ bool_complex: { lda #' ' sta screen,x jmp b3 - b6: - cmp #0 - beq b2 - jmp b5 } bool_not: { .label screen = $450 @@ -91,6 +91,10 @@ bool_and: { and #1 cpx #$a bcc b5 + jmp b4 + b5: + cmp #0 + beq b2 b4: lda #' ' sta screen,x @@ -99,10 +103,6 @@ bool_and: { cpx #$15 bne b1 rts - b5: - cmp #0 - beq b2 - jmp b4 b2: lda #'*' sta screen,x diff --git a/src/test/ref/bool-vars.asm b/src/test/ref/bool-vars.asm index 8d19ed6d0..65d8b579c 100644 --- a/src/test/ref/bool-vars.asm +++ b/src/test/ref/bool-vars.asm @@ -31,6 +31,11 @@ bool_complex: { lda o1 cmp #0 bne b6 + jmp b5 + b6: + lda o2 + cmp #0 + bne b2 b5: lda o1 cmp #0 @@ -50,11 +55,6 @@ bool_complex: { lda #' ' sta screen,x jmp b3 - b6: - lda o2 - cmp #0 - bne b2 - jmp b5 } bool_not: { .label screen = $450 @@ -108,6 +108,10 @@ bool_and: { and #1 cpx #$a bcc b5 + jmp b4 + b5: + cmp #0 + beq b2 b4: lda #' ' sta screen,x @@ -116,10 +120,6 @@ bool_and: { cpx #$15 bne b1 rts - b5: - cmp #0 - beq b2 - jmp b4 b2: lda #'*' sta screen,x diff --git a/src/test/ref/complex-conditional-problem.asm b/src/test/ref/complex-conditional-problem.asm index ec0d49551..46436158b 100644 --- a/src/test/ref/complex-conditional-problem.asm +++ b/src/test/ref/complex-conditional-problem.asm @@ -11,10 +11,10 @@ main: { bcs b3 cmp #$40 bcc b3 + jmp b2 + b3: + lda #0 b2: sta SCREEN jmp b1 - b3: - lda #0 - jmp b2 } diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm index 663c44f97..f0383be1a 100644 --- a/src/test/ref/complex/tetris/tetris.asm +++ b/src/test/ref/complex/tetris/tetris.asm @@ -145,18 +145,18 @@ .label current_xpos_59 = $a .label current_piece_gfx_64 = 5 .label current_piece_char_68 = $b - .label render_screen_render_69 = 9 - .label current_xpos_130 = $a - .label current_xpos_131 = $a - .label current_piece_gfx_120 = 5 - .label current_piece_gfx_121 = 5 - .label current_piece_char_108 = $b - .label current_piece_char_109 = $b - .label current_piece_100 = 5 + .label render_screen_render_68 = 9 + .label current_xpos_127 = $a + .label current_xpos_128 = $a + .label current_piece_gfx_117 = 5 + .label current_piece_gfx_118 = 5 + .label current_piece_char_105 = $b + .label current_piece_char_106 = $b .label current_piece_101 = 5 .label current_piece_102 = 5 .label current_piece_103 = 5 .label current_piece_104 = 5 + .label current_piece_105 = 5 bbegin: // The screen currently being showed to the user. $00 for screen 1 / $20 for screen 2. lda #0 @@ -192,13 +192,13 @@ main: { jsr render_playfield ldx current_ypos lda current_xpos - sta current_xpos_130 + sta current_xpos_127 lda current_piece_gfx - sta current_piece_gfx_120 + sta current_piece_gfx_117 lda current_piece_gfx+1 - sta current_piece_gfx_120+1 + sta current_piece_gfx_117+1 lda current_piece_char - sta current_piece_char_108 + sta current_piece_char_105 lda #$20 sta render_screen_render_33 jsr render_moving @@ -250,15 +250,15 @@ main: { jsr render_playfield ldx current_ypos lda render_screen_render - sta render_screen_render_69 + sta render_screen_render_68 lda current_xpos - sta current_xpos_131 + sta current_xpos_128 lda current_piece_gfx - sta current_piece_gfx_121 + sta current_piece_gfx_118 lda current_piece_gfx+1 - sta current_piece_gfx_121+1 + sta current_piece_gfx_118+1 lda current_piece_char - sta current_piece_char_109 + sta current_piece_char_106 jsr render_moving lda render_screen_render ldx next_piece_idx @@ -608,9 +608,9 @@ play_move_rotate: { sta play_collision.ypos ldx orientation lda current_piece - sta current_piece_103 + sta current_piece_104 lda current_piece+1 - sta current_piece_103+1 + sta current_piece_104+1 jsr play_collision cmp #COLLISION_NONE bne b4 @@ -738,9 +738,9 @@ play_move_leftright: { sta play_collision.ypos ldx current_orientation lda current_piece - sta current_piece_102 + sta current_piece_103 lda current_piece+1 - sta current_piece_102+1 + sta current_piece_103+1 jsr play_collision cmp #COLLISION_NONE bne b3 @@ -759,9 +759,9 @@ play_move_leftright: { sta play_collision.ypos ldx current_orientation lda current_piece - sta current_piece_101 + sta current_piece_102 lda current_piece+1 - sta current_piece_101+1 + sta current_piece_102+1 jsr play_collision cmp #COLLISION_NONE bne b3 @@ -804,9 +804,9 @@ play_move_down: { sta play_collision.xpos ldx current_orientation lda current_piece - sta current_piece_100 + sta current_piece_101 lda current_piece+1 - sta current_piece_100+1 + sta current_piece_101+1 jsr play_collision cmp #COLLISION_NONE beq b10 @@ -858,9 +858,9 @@ play_spawn_current: { lda current_ypos sta play_collision.ypos lda current_piece_gfx - sta current_piece_104 + sta current_piece_105 lda current_piece_gfx+1 - sta current_piece_104+1 + sta current_piece_105+1 ldx #0 jsr play_collision cmp #COLLISION_PLAYFIELD diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm index ab1e3bf7b..cfcef75d5 100644 --- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm +++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm @@ -142,10 +142,11 @@ plexShowSprite: { asl plex_sprite_msb lda plex_sprite_msb cmp #0 - bne breturn + bne b5 lda #1 sta plex_sprite_msb - breturn: + rts + b5: rts b1: lda SPRITES_XMSB @@ -185,6 +186,12 @@ plexSort: { dex cpx #$ff bne b5 + jmp b4 + b5: + lda nxt_y + ldy PLEX_SORTED_IDX,x + cmp PLEX_YPOS,y + bcc b3 b4: inx lda nxt_idx @@ -202,12 +209,6 @@ plexSort: { cpx #8 bne plexFreePrepare1_b1 rts - b5: - lda nxt_y - ldy PLEX_SORTED_IDX,x - cmp PLEX_YPOS,y - bcc b3 - jmp b4 } // Initialize the program init: { diff --git a/src/test/ref/loop-break-continue.asm b/src/test/ref/loop-break-continue.asm index 1ff20050e..c7a50bd37 100644 --- a/src/test/ref/loop-break-continue.asm +++ b/src/test/ref/loop-break-continue.asm @@ -19,11 +19,7 @@ main: { lda str,x cmp #' ' bne b3 - b4: - inx - cpx #0 - bne b1 - rts + jmp b4 b3: lda str,x ldy #0 @@ -32,6 +28,10 @@ main: { bne !+ inc screen+1 !: - jmp b4 + b4: + inx + cpx #0 + bne b1 + rts str: .text "hello brave new world@" } diff --git a/src/test/ref/loop-break-nested.asm b/src/test/ref/loop-break-nested.asm index 86284b28d..eb7d4bbcc 100644 --- a/src/test/ref/loop-break-nested.asm +++ b/src/test/ref/loop-break-nested.asm @@ -20,6 +20,13 @@ main: { lda (line),y cmp #'a' bne b3 + jmp b4 + b3: + lda #'a' + sta (line),y + iny + cpy #$28 + bne b2 b4: lda #$28 clc @@ -37,11 +44,4 @@ main: { bcc b1 !: rts - b3: - lda #'a' - sta (line),y - iny - cpy #$28 - bne b2 - jmp b4 } diff --git a/src/test/ref/loop-continue.asm b/src/test/ref/loop-continue.asm index c5abdab71..fe08e6e87 100644 --- a/src/test/ref/loop-continue.asm +++ b/src/test/ref/loop-continue.asm @@ -9,12 +9,12 @@ main: { lda SCREEN,x cmp #' ' bne b2 + jmp b3 + b2: + inc SCREEN,x b3: inx cpx #$28*6+1 bne b1 rts - b2: - inc SCREEN,x - jmp b3 } diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm index 32a1fc283..d8dee23c8 100644 --- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm +++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm @@ -130,6 +130,12 @@ plexSort: { dex cpx #$ff bne b6 + jmp b4 + b6: + lda nxt_y + ldy PLEX_SORTED_IDX,x + cmp PLEX_YPOS,y + bcc b3 b4: inx lda nxt_idx @@ -154,12 +160,6 @@ plexSort: { bne plexFreePrepare1_b1 sta plex_free_next rts - b6: - lda nxt_y - ldy PLEX_SORTED_IDX,x - cmp PLEX_YPOS,y - bcc b3 - jmp b4 } // Initialize the program init: { @@ -242,6 +242,10 @@ plex_irq: { lda plex_show_idx cmp #PLEX_COUNT bcc b7 + jmp b4 + b7: + cpx _4 + bcc b3 b4: lda #IRQ_RASTER sta IRQ_STATUS @@ -257,10 +261,6 @@ plex_irq: { b1: stx RASTER jmp b2 - b7: - cpx _4 - bcc b3 - jmp b4 } // Show the next sprite. // plexSort() prepares showing the sprites diff --git a/src/test/ref/no-recursion-heavy.asm b/src/test/ref/no-recursion-heavy.asm index 9b94f1c33..a64e0d602 100644 --- a/src/test/ref/no-recursion-heavy.asm +++ b/src/test/ref/no-recursion-heavy.asm @@ -270,5 +270,8 @@ fc: { cmp #7 cmp #8 cmp #9 + bne b10 + rts + b10: rts } diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm index 7abbd0312..0c0bcc277 100644 --- a/src/test/ref/sandbox.asm +++ b/src/test/ref/sandbox.asm @@ -202,9 +202,16 @@ myprintf: { rts b3: cpx #'1' - bcc !b37+ - jmp b37 - !b37: + bcs b37 + jmp b4 + b37: + cpx #'9' + bcs !b23+ + jmp b23 + !b23: + bne !b23+ + jmp b23 + !b23: b4: cpx #'-' bne b5 @@ -280,6 +287,11 @@ myprintf: { lda bTrailing cmp #0 beq b39 + jmp b15 + b39: + lda b + cmp bDigits + bcc b16 b15: ldx #0 b19: @@ -309,18 +321,13 @@ myprintf: { cmp bDigits bcc b21 jmp b22 - b39: - lda b - cmp bDigits - bcc b16 - jmp b15 b16: lda bLeadZero cmp #0 - beq b14 + beq b17 lda #'0' jmp b18 - b14: + b17: lda #' ' b18: ldy bLen @@ -341,11 +348,6 @@ myprintf: { sta strTemp,y inc bLen jmp b22 - b37: - cpx #'9' - bcc b23 - beq b23 - jmp b4 b23: txa axs #'0' @@ -392,13 +394,7 @@ myprintf: { b28: cpx #$41 bcs b41 - b30: - // swap 0x41 / 0x61 when in lower case mode - ldy bLen - txa - sta strTemp,y - inc bLen - jmp b27 + jmp b30 b41: cpx #$5a+1 bcc b35 @@ -406,7 +402,13 @@ myprintf: { b35: txa axs #-[$20] - jmp b30 + b30: + // swap 0x41 / 0x61 when in lower case mode + ldy bLen + txa + sta strTemp,y + inc bLen + jmp b27 buf6: .fill 6, 0 } // utoa(word zeropage($12) value, byte* zeropage($14) dst) diff --git a/src/test/ref/signed-words.asm b/src/test/ref/signed-words.asm index 1f3826b81..cd5577b6e 100644 --- a/src/test/ref/signed-words.asm +++ b/src/test/ref/signed-words.asm @@ -22,7 +22,7 @@ .label yvel_10 = 6 .label xvel = 2 .label yvel_12 = 6 - .label yvel_22 = 6 + .label yvel_21 = 6 main: { jsr init lda #$64 @@ -93,9 +93,9 @@ anim: { sta yvel+1 b3: lda yvel - sta yvel_22 + sta yvel_21 lda yvel+1 - sta yvel_22+1 + sta yvel_21+1 lda #0 sta ypos sta ypos+1 diff --git a/src/test/ref/travis1.asm b/src/test/ref/travis1.asm index a73fc4f30..12531614c 100644 --- a/src/test/ref/travis1.asm +++ b/src/test/ref/travis1.asm @@ -22,6 +22,17 @@ main: { jsr game_ready cmp #0 bne b3 + jmp b2 + b3: + lda print_line_cursor + sta print_char_cursor + lda print_line_cursor+1 + sta print_char_cursor+1 + lda #<str + sta print_str_ln.str + lda #>str + sta print_str_ln.str+1 + jsr print_str_ln b2: inc i lda #6 @@ -34,17 +45,6 @@ main: { lda print_line_cursor+1 sta print_char_cursor+1 jmp b1 - b3: - lda print_line_cursor - sta print_char_cursor - lda print_line_cursor+1 - sta print_char_cursor+1 - lda #<str - sta print_str_ln.str - lda #>str - sta print_str_ln.str+1 - jsr print_str_ln - jmp b2 str: .text "ready!@" } // Print a zero-terminated string followed by a newline From 682d007ba8b9349ad81f7cb615f4afeae62ff854 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 12:19:20 +0200 Subject: [PATCH 79/93] Replaced Pass1EliminiateEmptyBlocks with PassNCullEmptyBlocks (which was removed from pass 2). --- .../java/dk/camelot64/kickc/Compiler.java | 6 +- .../passes/Pass1EliminateEmptyBlocks.java | 66 -------------- ...yBlocks.java => PassNCullEmptyBlocks.java} | 4 +- src/test/ref/complex/tetris/tetris.asm | 86 +++++++++---------- .../ref/examples/chargen/chargen-analysis.asm | 24 +++--- .../multiplexer/simple-multiplexer.asm | 6 +- src/test/ref/function-pointer-noarg-3.asm | 8 +- .../ref/function-pointer-noarg-call-2.asm | 8 +- src/test/ref/function-pointer-return.asm | 8 +- src/test/ref/inline-string-2.asm | 8 +- .../simple-multiplexer-irq.asm | 4 +- src/test/ref/no-recursion-heavy.asm | 23 +++-- src/test/ref/sandbox-ternary-error.asm | 8 +- src/test/ref/sandbox.asm | 40 ++++----- src/test/ref/semi-struct-2.asm | 76 ++++++++-------- src/test/ref/signed-words.asm | 6 +- src/test/ref/test-comparisons-sword.asm | 5 +- src/test/ref/test-comparisons-word.asm | 5 +- 18 files changed, 161 insertions(+), 230 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java rename src/main/java/dk/camelot64/kickc/passes/{Pass2CullEmptyBlocks.java => PassNCullEmptyBlocks.java} (97%) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index ae353382c..ac82bc58f 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -183,7 +183,7 @@ public class Compiler { new Pass1EliminateUncalledProcedures(program).execute(); new PassNEliminateUnusedVars(program, false).execute(); new Pass1ExtractInlineStrings(program).execute(); - new Pass1EliminateEmptyBlocks(program).execute(); + new PassNCullEmptyBlocks(program).execute(); new Pass1ModifiedVarsAnalysis(program).execute(); if(getLog().isVerbosePass1CreateSsa()) { @@ -243,7 +243,6 @@ public class Compiler { optimizations.add(new PassNTypeIdSimplification(program)); optimizations.add(new Pass2SizeOfSimplification(program)); - optimizations.add(new Pass2CullEmptyBlocks(program)); optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNVariableReferenceInfos(program)); optimizations.add(new Pass2UnaryNotSimplification(program)); @@ -377,7 +376,6 @@ public class Compiler { new Pass3AssertConstants(program).check(); new Pass3AssertArrayLengths(program).check(); new Pass3AssertNoMulDivMod(program).check(); - //new PassNBlockSequencePlanner(program).step(); // Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes new Pass3PhiLifting(program).perform(); new PassNBlockSequencePlanner(program).step(); @@ -404,7 +402,7 @@ public class Compiler { // Phi mem coalesce removes as many variables introduced by phi lifting as possible - as long as their live ranges do not overlap new Pass3PhiMemCoalesce(program).step(); - new Pass2CullEmptyBlocks(program).step(); + new PassNCullEmptyBlocks(program).step(); new PassNRenumberLabels(program).execute(); new PassNBlockSequencePlanner(program).step(); new Pass3AddNopBeforeCallOns(program).generate(); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java b/src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java deleted file mode 100644 index 9cfc9095d..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java +++ /dev/null @@ -1,66 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.CompileLog; -import dk.camelot64.kickc.model.*; -import dk.camelot64.kickc.model.symbols.Label; -import dk.camelot64.kickc.model.symbols.Symbol; -import dk.camelot64.kickc.model.values.LabelRef; -import dk.camelot64.kickc.model.values.SymbolRef; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Eliminate empty blocks in pass 1 (before creating SSA) - */ -public class Pass1EliminateEmptyBlocks extends Pass1Base { - - public Pass1EliminateEmptyBlocks(Program program) { - super(program); - } - - @Override - public boolean step() { - CompileLog log = getLog(); - ControlFlowGraph graph = getProgram().getGraph(); - Collection<ControlFlowBlock> blocks = graph.getAllBlocks(); - List<LabelRef> removeList = new ArrayList<>(); - for(ControlFlowBlock block : blocks) { - if(block.getLabel().getFullName().equals(SymbolRef.END_BLOCK_NAME)) { - continue; - } else if(block.getLabel().getFullName().equals(SymbolRef.BEGIN_BLOCK_NAME)) { - continue; - } - if(block.getStatements().isEmpty()) { - List<ControlFlowBlock> predecessors = graph.getPredecessors(block); - boolean remove = true; - for(ControlFlowBlock predecessor : predecessors) { - if(predecessor.getDefaultSuccessor().equals(block.getLabel())) { - predecessor.setDefaultSuccessor(block.getDefaultSuccessor()); - } else { - remove = false; - } - } - if(remove) { - removeList.add(block.getLabel()); - } - } - } - boolean modified = false; - for(LabelRef labelRef : removeList) { - Symbol removeSymbol = getScope().getSymbol(labelRef); - if(removeSymbol instanceof Label) { - Label label = (Label) removeSymbol; - graph.remove(labelRef); - label.getScope().remove(label); - if(log.isVerbosePass1CreateSsa()) { - log.append("Removing empty block " + labelRef); - } - modified = true; - } - } - return modified; - } - -} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java b/src/main/java/dk/camelot64/kickc/passes/PassNCullEmptyBlocks.java similarity index 97% rename from src/main/java/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java rename to src/main/java/dk/camelot64/kickc/passes/PassNCullEmptyBlocks.java index 679d87eb3..c9c067215 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNCullEmptyBlocks.java @@ -12,9 +12,9 @@ import java.util.List; import java.util.Map; /** Pass that culls empty control flow blocks from the program */ -public class Pass2CullEmptyBlocks extends Pass2SsaOptimization { +public class PassNCullEmptyBlocks extends Pass2SsaOptimization { - public Pass2CullEmptyBlocks(Program program) { + public PassNCullEmptyBlocks(Program program) { super(program); } diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm index f0383be1a..df178a3ac 100644 --- a/src/test/ref/complex/tetris/tetris.asm +++ b/src/test/ref/complex/tetris/tetris.asm @@ -145,18 +145,18 @@ .label current_xpos_59 = $a .label current_piece_gfx_64 = 5 .label current_piece_char_68 = $b - .label render_screen_render_68 = 9 - .label current_xpos_127 = $a - .label current_xpos_128 = $a - .label current_piece_gfx_117 = 5 - .label current_piece_gfx_118 = 5 - .label current_piece_char_105 = $b - .label current_piece_char_106 = $b - .label current_piece_101 = 5 - .label current_piece_102 = 5 - .label current_piece_103 = 5 - .label current_piece_104 = 5 - .label current_piece_105 = 5 + .label render_screen_render_65 = 9 + .label current_xpos_119 = $a + .label current_xpos_120 = $a + .label current_piece_gfx_112 = 5 + .label current_piece_gfx_113 = 5 + .label current_piece_char_100 = $b + .label current_piece_char_101 = $b + .label current_piece_96 = 5 + .label current_piece_97 = 5 + .label current_piece_98 = 5 + .label current_piece_99 = 5 + .label current_piece_100 = 5 bbegin: // The screen currently being showed to the user. $00 for screen 1 / $20 for screen 2. lda #0 @@ -192,13 +192,13 @@ main: { jsr render_playfield ldx current_ypos lda current_xpos - sta current_xpos_127 + sta current_xpos_119 lda current_piece_gfx - sta current_piece_gfx_117 + sta current_piece_gfx_112 lda current_piece_gfx+1 - sta current_piece_gfx_117+1 + sta current_piece_gfx_112+1 lda current_piece_char - sta current_piece_char_105 + sta current_piece_char_100 lda #$20 sta render_screen_render_33 jsr render_moving @@ -250,15 +250,15 @@ main: { jsr render_playfield ldx current_ypos lda render_screen_render - sta render_screen_render_68 + sta render_screen_render_65 lda current_xpos - sta current_xpos_128 + sta current_xpos_120 lda current_piece_gfx - sta current_piece_gfx_118 + sta current_piece_gfx_113 lda current_piece_gfx+1 - sta current_piece_gfx_118+1 + sta current_piece_gfx_113+1 lda current_piece_char - sta current_piece_char_106 + sta current_piece_char_101 jsr render_moving lda render_screen_render ldx next_piece_idx @@ -286,18 +286,18 @@ render_score: { .label screen = 5 lda render_screen_render cmp #0 - beq b2 + beq b1 lda #<PLAYFIELD_SCREEN_2 sta screen lda #>PLAYFIELD_SCREEN_2 sta screen+1 - jmp b1 - b2: + jmp b2 + b1: lda #<PLAYFIELD_SCREEN_1 sta screen lda #>PLAYFIELD_SCREEN_1 sta screen+1 - b1: + b2: ldx score_bytes+2 ldy #0 lda #<score_offset @@ -394,18 +394,18 @@ render_next: { .label screen_next_area = 7 .label l = 9 cmp #0 - beq b2 + beq b1 lda #<PLAYFIELD_SCREEN_2+next_area_offset sta screen_next_area lda #>PLAYFIELD_SCREEN_2+next_area_offset sta screen_next_area+1 - jmp b1 - b2: + jmp b2 + b1: lda #<PLAYFIELD_SCREEN_1+next_area_offset sta screen_next_area lda #>PLAYFIELD_SCREEN_1+next_area_offset sta screen_next_area+1 - b1: + b2: txa asl // Render the next piece @@ -608,9 +608,9 @@ play_move_rotate: { sta play_collision.ypos ldx orientation lda current_piece - sta current_piece_104 + sta current_piece_99 lda current_piece+1 - sta current_piece_104+1 + sta current_piece_99+1 jsr play_collision cmp #COLLISION_NONE bne b4 @@ -645,8 +645,8 @@ play_collision: { .label l = $d .label i_2 = $e .label i_3 = $e - .label i_11 = $e - .label i_13 = $e + .label i_10 = $e + .label i_12 = $e txa clc adc piece_gfx @@ -715,11 +715,11 @@ play_collision: { rts b9: lda i - sta i_11 + sta i_10 jmp b1 b10: lda i - sta i_13 + sta i_12 jmp b2 } // Move left/right or rotate the current piece @@ -738,9 +738,9 @@ play_move_leftright: { sta play_collision.ypos ldx current_orientation lda current_piece - sta current_piece_103 + sta current_piece_98 lda current_piece+1 - sta current_piece_103+1 + sta current_piece_98+1 jsr play_collision cmp #COLLISION_NONE bne b3 @@ -759,9 +759,9 @@ play_move_leftright: { sta play_collision.ypos ldx current_orientation lda current_piece - sta current_piece_102 + sta current_piece_97 lda current_piece+1 - sta current_piece_102+1 + sta current_piece_97+1 jsr play_collision cmp #COLLISION_NONE bne b3 @@ -804,9 +804,9 @@ play_move_down: { sta play_collision.xpos ldx current_orientation lda current_piece - sta current_piece_101 + sta current_piece_96 lda current_piece+1 - sta current_piece_101+1 + sta current_piece_96+1 jsr play_collision cmp #COLLISION_NONE beq b10 @@ -858,9 +858,9 @@ play_spawn_current: { lda current_ypos sta play_collision.ypos lda current_piece_gfx - sta current_piece_105 + sta current_piece_100 lda current_piece_gfx+1 - sta current_piece_105+1 + sta current_piece_100+1 ldx #0 jsr play_collision cmp #COLLISION_PLAYFIELD diff --git a/src/test/ref/examples/chargen/chargen-analysis.asm b/src/test/ref/examples/chargen/chargen-analysis.asm index 3acea7f3d..591a0f78e 100644 --- a/src/test/ref/examples/chargen/chargen-analysis.asm +++ b/src/test/ref/examples/chargen/chargen-analysis.asm @@ -174,39 +174,39 @@ main: { ldx #KEY_LSHIFT jsr keyboard_key_pressed cmp #0 - bne b2 + bne b9 lda #0 sta shift - jmp b9 - b2: + jmp b10 + b9: lda #1 sta shift - b9: + b10: lda #0 sta ch // Check for key presses - and plot char if found - b10: + b11: ldx ch jsr keyboard_get_keycode cmp #$3f - beq b13 + beq b2 tax jsr keyboard_key_pressed - jmp b11 - b13: + jmp b12 + b2: lda #0 - b11: + b12: cmp #0 - beq b12 + beq b13 ldy cur_pos lda ch ldx shift jsr plot_chargen - b12: + b13: inc ch lda #$40 cmp ch - bne b10 + bne b11 jmp b4 str: .text "f1@" str1: .text "f3@" diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm index cfcef75d5..6016bd1d2 100644 --- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm +++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm @@ -23,10 +23,10 @@ .label SPRITE = $2000 .label YSIN = $2100 .label PLEX_SCREEN_PTR = SCREEN+$3f8 + .label plex_sprite_msb = 6 .label plex_free_next = 3 .label plex_sprite_idx = 4 .label plex_show_idx = 5 - .label plex_sprite_msb = 6 main: { sei jsr init @@ -185,9 +185,9 @@ plexSort: { sta PLEX_SORTED_IDX+1,x dex cpx #$ff - bne b5 + bne b6 jmp b4 - b5: + b6: lda nxt_y ldy PLEX_SORTED_IDX,x cmp PLEX_YPOS,y diff --git a/src/test/ref/function-pointer-noarg-3.asm b/src/test/ref/function-pointer-noarg-3.asm index a5efe51f9..6ef9b4501 100644 --- a/src/test/ref/function-pointer-noarg-3.asm +++ b/src/test/ref/function-pointer-noarg-3.asm @@ -13,18 +13,18 @@ main: { txa and #1 cmp #0 - beq b1 + beq b3 lda #<fn2 sta f lda #>fn2 sta f+1 - jmp b3 - b1: + jmp b4 + b3: lda #<fn1 sta f lda #>fn1 sta f+1 - b3: + b4: jsr ff jmp b2 diff --git a/src/test/ref/function-pointer-noarg-call-2.asm b/src/test/ref/function-pointer-noarg-call-2.asm index f751aa759..9d047951b 100644 --- a/src/test/ref/function-pointer-noarg-call-2.asm +++ b/src/test/ref/function-pointer-noarg-call-2.asm @@ -12,18 +12,18 @@ main: { lda #1 and i cmp #0 - beq b1 + beq b3 lda #<fn2 sta f lda #>fn2 sta f+1 - jmp b3 - b1: + jmp b4 + b3: lda #<fn1 sta f lda #>fn1 sta f+1 - b3: + b4: jsr bi_f jmp b2 bi_f: diff --git a/src/test/ref/function-pointer-return.asm b/src/test/ref/function-pointer-return.asm index 13febb158..c244eb54d 100644 --- a/src/test/ref/function-pointer-return.asm +++ b/src/test/ref/function-pointer-return.asm @@ -11,18 +11,18 @@ main: { txa and #1 cmp #0 - beq b1 + beq b3 lda #<fn2 sta f lda #>fn2 sta f+1 - jmp b3 - b1: + jmp b4 + b3: lda #<fn1 sta f lda #>fn1 sta f+1 - b3: + b4: lda f sta SCREEN jmp b2 diff --git a/src/test/ref/inline-string-2.asm b/src/test/ref/inline-string-2.asm index 9f5927b68..0bbdcd2b0 100644 --- a/src/test/ref/inline-string-2.asm +++ b/src/test/ref/inline-string-2.asm @@ -18,18 +18,18 @@ main: { print_msg: { .label msg = 4 cpx #1 - beq b2 + beq b1 lda #<msg_2 sta msg lda #>msg_2 sta msg+1 - jmp b1 - b2: + jmp b2 + b1: lda #<msg_1 sta msg lda #>msg_1 sta msg+1 - b1: + b2: jsr print rts msg_1: .text "Hello @" diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm index d8dee23c8..52e162f4a 100644 --- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm +++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm @@ -129,9 +129,9 @@ plexSort: { sta PLEX_SORTED_IDX+1,x dex cpx #$ff - bne b6 + bne b7 jmp b4 - b6: + b7: lda nxt_y ldy PLEX_SORTED_IDX,x cmp PLEX_YPOS,y diff --git a/src/test/ref/no-recursion-heavy.asm b/src/test/ref/no-recursion-heavy.asm index a64e0d602..ec7449e53 100644 --- a/src/test/ref/no-recursion-heavy.asm +++ b/src/test/ref/no-recursion-heavy.asm @@ -5,6 +5,7 @@ .label bb = 3 .label bb_27 = 4 .label bc = 5 + .label bb_100 = 4 .label bb_101 = 4 .label bb_102 = 4 .label bb_103 = 4 @@ -13,7 +14,6 @@ .label bb_106 = 4 .label bb_107 = 4 .label bb_108 = 4 - .label bb_109 = 4 main: { lda #0 sta ba @@ -31,7 +31,7 @@ f0: { bne b1 inc bb lda bb - sta bb_101 + sta bb_100 jsr fa b1: lda #1 @@ -39,7 +39,7 @@ f0: { bne b2 inc bb lda bb - sta bb_102 + sta bb_101 jsr fa b2: lda #2 @@ -47,7 +47,7 @@ f0: { bne b3 inc bb lda bb - sta bb_103 + sta bb_102 jsr fa b3: lda #3 @@ -55,7 +55,7 @@ f0: { bne b4 inc bb lda bb - sta bb_104 + sta bb_103 jsr fa b4: lda #4 @@ -63,7 +63,7 @@ f0: { bne b5 inc bb lda bb - sta bb_105 + sta bb_104 jsr fa b5: lda #5 @@ -71,7 +71,7 @@ f0: { bne b6 inc bb lda bb - sta bb_106 + sta bb_105 jsr fa b6: lda #6 @@ -79,7 +79,7 @@ f0: { bne b7 inc bb lda bb - sta bb_107 + sta bb_106 jsr fa b7: lda #7 @@ -87,7 +87,7 @@ f0: { bne b8 inc bb lda bb - sta bb_108 + sta bb_107 jsr fa b8: lda #8 @@ -95,7 +95,7 @@ f0: { bne b9 inc bb lda bb - sta bb_109 + sta bb_108 jsr fa b9: lda #9 @@ -270,8 +270,5 @@ fc: { cmp #7 cmp #8 cmp #9 - bne b10 - rts - b10: rts } diff --git a/src/test/ref/sandbox-ternary-error.asm b/src/test/ref/sandbox-ternary-error.asm index cf9c393e2..a599c7f2c 100644 --- a/src/test/ref/sandbox-ternary-error.asm +++ b/src/test/ref/sandbox-ternary-error.asm @@ -7,15 +7,15 @@ main: { ldx #0 b1: cpx #0 - beq b4 - cpx #1 beq b2 + cpx #1 + beq b4 lda #'c' jmp b3 - b2: + b4: lda #'b' jmp b3 - b4: + b2: lda #'a' b3: sta SCREEN diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm index 0c0bcc277..3597c7029 100644 --- a/src/test/ref/sandbox.asm +++ b/src/test/ref/sandbox.asm @@ -202,9 +202,9 @@ myprintf: { rts b3: cpx #'1' - bcs b37 + bcs b39 jmp b4 - b37: + b39: cpx #'9' bcs !b23+ jmp b23 @@ -286,9 +286,9 @@ myprintf: { bne b13 lda bTrailing cmp #0 - beq b39 + beq b41 jmp b15 - b39: + b41: lda b cmp bDigits bcc b16 @@ -304,9 +304,9 @@ myprintf: { bcc b19 lda bTrailing cmp #0 - bne b40 + bne b42 jmp b22 - b40: + b42: lda b cmp bDigits bcc b21 @@ -360,15 +360,15 @@ myprintf: { //w = (bArg == 0) ? w1 : ((bArg == 1) ? w2 : w3); -- "?" is the normal way, but error "sequence does not contain all blocks" -- https://gitlab.com/camelot/kickc/issues/185 [FIXED] lda bArg cmp #0 - beq b42 + beq b29 lda #1 cmp bArg - beq b43 + beq b30 lda w3 sta w lda w3+1 sta w+1 - b29: + b31: inc bArg lda #0 sta bLeadZero @@ -379,30 +379,30 @@ myprintf: { lda #1 sta bFormat jmp b27 - b43: + b30: lda w2 sta w lda w2+1 sta w+1 - jmp b29 - b42: + jmp b31 + b29: lda w1 sta w lda w1+1 sta w+1 - jmp b29 + jmp b31 b28: cpx #$41 - bcs b41 - jmp b30 - b41: + bcs b43 + jmp b32 + b43: cpx #$5a+1 - bcc b35 - jmp b30 - b35: + bcc b37 + jmp b32 + b37: txa axs #-[$20] - b30: + b32: // swap 0x41 / 0x61 when in lower case mode ldy bLen txa diff --git a/src/test/ref/semi-struct-2.asm b/src/test/ref/semi-struct-2.asm index 03cc33c2c..6d4e8534f 100644 --- a/src/test/ref/semi-struct-2.asm +++ b/src/test/ref/semi-struct-2.asm @@ -37,6 +37,8 @@ .label print_line_cursor = $a .label print_line_cursor_32 = 2 .label print_line_cursor_63 = 2 + .label print_line_cursor_157 = 2 + .label print_line_cursor_158 = 2 .label print_line_cursor_159 = 2 .label print_line_cursor_160 = 2 .label print_line_cursor_161 = 2 @@ -52,9 +54,7 @@ .label print_line_cursor_171 = 2 .label print_line_cursor_172 = 2 .label print_line_cursor_173 = 2 - .label print_line_cursor_174 = 2 .label print_line_cursor_175 = 2 - .label print_line_cursor_177 = 2 // Initialize 2 file entries and print them main: { .const fileEntry1_idx = 1 @@ -114,9 +114,9 @@ main: { sta print_line_cursor_63+1 jsr print_ln lda print_line_cursor - sta print_line_cursor_159 + sta print_line_cursor_157 lda print_line_cursor+1 - sta print_line_cursor_159+1 + sta print_line_cursor_157+1 lda print_line_cursor sta print_char_cursor lda print_line_cursor+1 @@ -124,9 +124,9 @@ main: { jsr print_ln jsr printEntry lda print_line_cursor - sta print_line_cursor_160 + sta print_line_cursor_158 lda print_line_cursor+1 - sta print_line_cursor_160+1 + sta print_line_cursor_158+1 lda print_line_cursor sta print_char_cursor lda print_line_cursor+1 @@ -161,9 +161,9 @@ main: { sta print_line_cursor_63+1 jsr print_ln lda print_line_cursor - sta print_line_cursor_161 + sta print_line_cursor_159 lda print_line_cursor+1 - sta print_line_cursor_161+1 + sta print_line_cursor_159+1 lda print_line_cursor sta print_char_cursor lda print_line_cursor+1 @@ -175,9 +175,9 @@ main: { sta printEntry.entry+1 jsr printEntry lda print_line_cursor - sta print_line_cursor_162 + sta print_line_cursor_160 lda print_line_cursor+1 - sta print_line_cursor_162+1 + sta print_line_cursor_160+1 lda print_line_cursor sta print_char_cursor lda print_line_cursor+1 @@ -292,9 +292,9 @@ print_ln: { rts b2: lda print_line_cursor - sta print_line_cursor_177 + sta print_line_cursor_175 lda print_line_cursor+1 - sta print_line_cursor_177+1 + sta print_line_cursor_175+1 jmp b1 } // Print the contents of a file entry @@ -318,9 +318,9 @@ printEntry: { sta print_word.w+1 jsr print_word lda print_line_cursor - sta print_line_cursor_163 + sta print_line_cursor_161 lda print_line_cursor+1 - sta print_line_cursor_163+1 + sta print_line_cursor_161+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -339,9 +339,9 @@ printEntry: { sta print_word.w+1 jsr print_word lda print_line_cursor - sta print_line_cursor_164 + sta print_line_cursor_162 lda print_line_cursor+1 - sta print_line_cursor_164+1 + sta print_line_cursor_162+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -360,9 +360,9 @@ printEntry: { sta print_word.w+1 jsr print_word lda print_line_cursor - sta print_line_cursor_165 + sta print_line_cursor_163 lda print_line_cursor+1 - sta print_line_cursor_165+1 + sta print_line_cursor_163+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -381,9 +381,9 @@ printEntry: { sta print_word.w+1 jsr print_word lda print_line_cursor - sta print_line_cursor_166 + sta print_line_cursor_164 lda print_line_cursor+1 - sta print_line_cursor_166+1 + sta print_line_cursor_164+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -399,9 +399,9 @@ printEntry: { tax jsr print_byte lda print_line_cursor - sta print_line_cursor_167 + sta print_line_cursor_165 lda print_line_cursor+1 - sta print_line_cursor_167+1 + sta print_line_cursor_165+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -417,9 +417,9 @@ printEntry: { tax jsr print_byte lda print_line_cursor - sta print_line_cursor_168 + sta print_line_cursor_166 lda print_line_cursor+1 - sta print_line_cursor_168+1 + sta print_line_cursor_166+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -435,9 +435,9 @@ printEntry: { tax jsr print_byte lda print_line_cursor - sta print_line_cursor_169 + sta print_line_cursor_167 lda print_line_cursor+1 - sta print_line_cursor_169+1 + sta print_line_cursor_167+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -453,9 +453,9 @@ printEntry: { tax jsr print_byte lda print_line_cursor - sta print_line_cursor_170 + sta print_line_cursor_168 lda print_line_cursor+1 - sta print_line_cursor_170+1 + sta print_line_cursor_168+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -474,9 +474,9 @@ printEntry: { sta print_word.w+1 jsr print_word lda print_line_cursor - sta print_line_cursor_171 + sta print_line_cursor_169 lda print_line_cursor+1 - sta print_line_cursor_171+1 + sta print_line_cursor_169+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -492,9 +492,9 @@ printEntry: { tax jsr print_byte lda print_line_cursor - sta print_line_cursor_172 + sta print_line_cursor_170 lda print_line_cursor+1 - sta print_line_cursor_172+1 + sta print_line_cursor_170+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -510,9 +510,9 @@ printEntry: { tax jsr print_byte lda print_line_cursor - sta print_line_cursor_173 + sta print_line_cursor_171 lda print_line_cursor+1 - sta print_line_cursor_173+1 + sta print_line_cursor_171+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -528,9 +528,9 @@ printEntry: { tax jsr print_byte lda print_line_cursor - sta print_line_cursor_174 + sta print_line_cursor_172 lda print_line_cursor+1 - sta print_line_cursor_174+1 + sta print_line_cursor_172+1 jsr print_ln lda print_line_cursor sta print_char_cursor @@ -546,9 +546,9 @@ printEntry: { tax jsr print_byte lda print_line_cursor - sta print_line_cursor_175 + sta print_line_cursor_173 lda print_line_cursor+1 - sta print_line_cursor_175+1 + sta print_line_cursor_173+1 jsr print_ln rts str: .text "bufdisk @" diff --git a/src/test/ref/signed-words.asm b/src/test/ref/signed-words.asm index cd5577b6e..765fcee02 100644 --- a/src/test/ref/signed-words.asm +++ b/src/test/ref/signed-words.asm @@ -22,7 +22,7 @@ .label yvel_10 = 6 .label xvel = 2 .label yvel_12 = 6 - .label yvel_21 = 6 + .label yvel_20 = 6 main: { jsr init lda #$64 @@ -93,9 +93,9 @@ anim: { sta yvel+1 b3: lda yvel - sta yvel_21 + sta yvel_20 lda yvel+1 - sta yvel_21+1 + sta yvel_20+1 lda #0 sta ypos sta ypos+1 diff --git a/src/test/ref/test-comparisons-sword.asm b/src/test/ref/test-comparisons-sword.asm index 7040fecd8..243347b6b 100644 --- a/src/test/ref/test-comparisons-sword.asm +++ b/src/test/ref/test-comparisons-sword.asm @@ -80,8 +80,9 @@ main: { inc i cmp i bne b1 - b8: - jmp b8 + b5: + // loop forever + jmp b5 } // Print a newline print_ln: { diff --git a/src/test/ref/test-comparisons-word.asm b/src/test/ref/test-comparisons-word.asm index fed328414..3b0d79f32 100644 --- a/src/test/ref/test-comparisons-word.asm +++ b/src/test/ref/test-comparisons-word.asm @@ -73,8 +73,9 @@ main: { inc i cmp i bne b1 - b8: - jmp b8 + b5: + // loop forever + jmp b5 } // Print a newline print_ln: { From 430c128cc3c4664e999e735a2032e5ab78e6ce50 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 12:33:15 +0200 Subject: [PATCH 80/93] Simplified constant inlining pass2 --- .../java/dk/camelot64/kickc/Compiler.java | 25 ++++++------------- .../ref/function-pointer-noarg-call-8.asm | 7 +++--- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index ac82bc58f..8d964707d 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -230,17 +230,19 @@ public class Compiler { } private void pass2Optimize() { + List<Pass2SsaOptimization> optimizations = getPass2Optimizations(); + pass2Execute(optimizations); + } + + private List<Pass2SsaOptimization> getPass2Optimizations() { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); - optimizations.add(new Pass2FixInlineConstructorsNew(program)); - optimizations.add(new PassNAddNumberTypeConversions(program)); optimizations.add(new PassNAddArrayNumberTypeConversions(program)); optimizations.add(new PassNTypeInference(program)); optimizations.add(new PassNAddTypeConversionAssignment(program)); optimizations.add(new Pass2InlineCast(program)); optimizations.add(new PassNCastSimplification(program)); - optimizations.add(new PassNTypeIdSimplification(program)); optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new PassNStatementIndices(program)); @@ -266,7 +268,7 @@ public class Compiler { optimizations.add(new PassNSimplifyExpressionWithZero(program)); optimizations.add(new PassNEliminateUnusedVars(program, true)); optimizations.add(new Pass2EliminateUnusedBlocks(program)); - pass2Execute(optimizations); + return optimizations; } private void pass2UnrollLoops() { @@ -297,26 +299,15 @@ public class Compiler { private void pass2InlineConstants() { // Constant inlining optimizations - as the last step to ensure that constant identification has been completed + List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>(); constantOptimizations.add(new PassNStatementIndices(program)); constantOptimizations.add(new PassNVariableReferenceInfos(program)); constantOptimizations.add(new Pass2MultiplyToShiftRewriting(program)); - constantOptimizations.add(new Pass2AliasElimination(program)); constantOptimizations.add(new Pass2ConstantInlining(program)); - constantOptimizations.add(new Pass2ConstantStringConsolidation(program)); - constantOptimizations.add(new Pass2IdenticalPhiElimination(program)); - constantOptimizations.add(new Pass2ConstantRValueConsolidation(program)); - constantOptimizations.add(new Pass2ConstantIdentification(program)); - constantOptimizations.add(new Pass2ConstantValues(program)); constantOptimizations.add(new Pass2ConstantAdditionElimination(program)); constantOptimizations.add(new Pass2ConstantSimplification(program)); - constantOptimizations.add(new PassNCastSimplification(program)); - constantOptimizations.add(new Pass2ConstantIfs(program)); - constantOptimizations.add(new Pass2InlineDerefIdx(program)); - constantOptimizations.add(new PassNEliminateUnusedVars(program, true)); - constantOptimizations.add(new PassNSimplifyConstantZero(program)); - constantOptimizations.add(new PassNSimplifyExpressionWithZero(program)); - + constantOptimizations.addAll(getPass2Optimizations()); pass2Execute(constantOptimizations); } diff --git a/src/test/ref/function-pointer-noarg-call-8.asm b/src/test/ref/function-pointer-noarg-call-8.asm index 6ea60224a..c90b2daa7 100644 --- a/src/test/ref/function-pointer-noarg-call-8.asm +++ b/src/test/ref/function-pointer-noarg-call-8.asm @@ -3,8 +3,8 @@ :BasicUpstart(bbegin) .pc = $80d "Program" .label SCREEN = $400 - .label msg = 4 - .label idx = 3 + .label msg = 3 + .label idx = 5 bbegin: lda #<0 sta msg @@ -13,7 +13,6 @@ bbegin: jsr main rts main: { - .label f = hello lda #<msg1 sta msg lda #>msg1 @@ -31,7 +30,7 @@ do10: { lda #0 sta i b1: - jsr main.f + jsr hello inc i lda #$a cmp i From 06147e2634bf189a207bc9844c3b4fe6135db8fa Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 15:48:34 +0200 Subject: [PATCH 81/93] Moved malloc/free trivial implementations to stdlib --- .../java/dk/camelot64/kickc/Compiler.java | 11 +++++----- src/main/kc/stdlib/stdlib.kc | 20 ++++++++++++++++++ src/test/kc/memory-heap.kc | 21 ++----------------- src/test/ref/memory-heap.asm | 17 +++++++-------- 4 files changed, 35 insertions(+), 34 deletions(-) create mode 100644 src/main/kc/stdlib/stdlib.kc diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 8d964707d..667ad696e 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -229,11 +229,6 @@ public class Compiler { } } - private void pass2Optimize() { - List<Pass2SsaOptimization> optimizations = getPass2Optimizations(); - pass2Execute(optimizations); - } - private List<Pass2SsaOptimization> getPass2Optimizations() { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); optimizations.add(new Pass2FixInlineConstructorsNew(program)); @@ -271,6 +266,11 @@ public class Compiler { return optimizations; } + private void pass2Optimize() { + List<Pass2SsaOptimization> optimizations = getPass2Optimizations(); + pass2Execute(optimizations); + } + private void pass2UnrollLoops() { List<Pass2SsaOptimization> loopUnrolling = new ArrayList<>(); loopUnrolling.add(new PassNStatementIndices(program)); @@ -299,7 +299,6 @@ public class Compiler { private void pass2InlineConstants() { // Constant inlining optimizations - as the last step to ensure that constant identification has been completed - List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>(); constantOptimizations.add(new PassNStatementIndices(program)); constantOptimizations.add(new PassNVariableReferenceInfos(program)); diff --git a/src/main/kc/stdlib/stdlib.kc b/src/main/kc/stdlib/stdlib.kc new file mode 100644 index 000000000..bd6686a8f --- /dev/null +++ b/src/main/kc/stdlib/stdlib.kc @@ -0,0 +1,20 @@ +// Implementation of functions found int C stdlib.h / stdlib.c + +// Start of the heap used by malloc() +unsigned char* HEAP_START = 0xc000; + +// Head of the heap. Moved forward for each malloc() +unsigned char* heap_head = HEAP_START; + +// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block. +// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values. +unsigned char* malloc(unsigned int size) { + unsigned char* mem = heap_head; + heap_head+= size; + return mem; +} + +// A block of memory previously allocated by a call to malloc is deallocated, making it available again for further allocations. +// If ptr is a null pointer, the function does nothing. +void free(unsigned char* ptr) { +} \ No newline at end of file diff --git a/src/test/kc/memory-heap.kc b/src/test/kc/memory-heap.kc index 2fa915342..5c62db2fd 100644 --- a/src/test/kc/memory-heap.kc +++ b/src/test/kc/memory-heap.kc @@ -1,5 +1,7 @@ // Experiments with malloc() +import "stdlib" + void main() { unsigned char* buf1 = (unsigned char*) malloc(100); unsigned char* buf2 = (unsigned char*) malloc(100); @@ -13,22 +15,3 @@ void main() { screen[0] = *buf1; screen[1] = *buf2; } - -// Start of the heap used by malloc() -unsigned char* HEAP_START = 0xc000; - -// Head of the heap. Moved forward for each malloc() -unsigned char* heap_head = HEAP_START; - -// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block. -// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values. -unsigned char* malloc(unsigned int size) { - unsigned char* mem = heap_head; - heap_head+= size; - return mem; -} - -// A block of memory previously allocated by a call to malloc is deallocated, making it available again for further allocations. -// If ptr is a null pointer, the function does nothing. -void free(unsigned char* ptr) { -} \ No newline at end of file diff --git a/src/test/ref/memory-heap.asm b/src/test/ref/memory-heap.asm index 769942503..c07e8c978 100644 --- a/src/test/ref/memory-heap.asm +++ b/src/test/ref/memory-heap.asm @@ -14,10 +14,10 @@ main: { lda #>HEAP_START sta heap_head+1 jsr malloc - lda malloc.return_2 - sta malloc.return - lda malloc.return_2+1 - sta malloc.return+1 + lda malloc.return + sta malloc.return_2 + lda malloc.return+1 + sta malloc.return_2+1 jsr malloc ldy #0 b1: @@ -48,13 +48,12 @@ free: { // Allocates a block of size bytes of memory, returning a pointer to the beginning of the block. // The content of the newly allocated block of memory is not initialized, remaining with indeterminate values. malloc: { - .label return = 4 - .label return_1 = 6 - .label return_2 = 6 + .label return = 6 + .label return_2 = 4 lda heap_head - sta return_2 + sta return lda heap_head+1 - sta return_2+1 + sta return+1 lda #$64 clc adc heap_head From 9ef7c69c3e0d836f8c2ba1ba213fcf4db18bfe4f Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Thu, 23 May 2019 17:50:44 +0200 Subject: [PATCH 82/93] Improved comparisons to avoid branch/jmp sequences by negating comparisons. --- src/main/fragment/vbuaa_le_0_then_la1.asm | 2 + src/main/fragment/vbuxx_le_0_then_la1.asm | 2 + src/main/fragment/vbuyy_le_0_then_la1.asm | 2 + src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm | 7 ++ .../java/dk/camelot64/kickc/Compiler.java | 1 + .../model/operators/OperatorDecrement.java | 3 +- .../model/operators/OperatorIncrement.java | 4 +- ...ss2ConditionalJumpSequenceImprovement.java | 79 +++++++++++++++++++ .../dk/camelot64/kickc/test/TestPrograms.java | 5 ++ src/test/kc/statement-sequence-1.kc | 15 ++++ src/test/ref/bool-ifs.asm | 8 +- src/test/ref/bool-vars.asm | 4 +- src/test/ref/complex-conditional-problem.asm | 3 +- src/test/ref/duplicate-loop-problem.asm | 4 +- .../multiplexer/simple-multiplexer.asm | 4 +- src/test/ref/keyboard-glitch.asm | 4 +- src/test/ref/loop-break-continue.asm | 9 +-- src/test/ref/loop-break-nested.asm | 17 ++-- src/test/ref/loop-break.asm | 5 +- src/test/ref/loop-continue.asm | 4 +- src/test/ref/loop-while-continue.asm | 4 +- .../simple-multiplexer-irq.asm | 8 +- src/test/ref/sandbox.asm | 25 +++--- src/test/ref/statement-sequence-1.asm | 27 +++++++ 24 files changed, 180 insertions(+), 66 deletions(-) create mode 100644 src/main/fragment/vbuaa_le_0_then_la1.asm create mode 100644 src/main/fragment/vbuxx_le_0_then_la1.asm create mode 100644 src/main/fragment/vbuyy_le_0_then_la1.asm create mode 100644 src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSequenceImprovement.java create mode 100644 src/test/kc/statement-sequence-1.kc create mode 100644 src/test/ref/statement-sequence-1.asm diff --git a/src/main/fragment/vbuaa_le_0_then_la1.asm b/src/main/fragment/vbuaa_le_0_then_la1.asm new file mode 100644 index 000000000..118295957 --- /dev/null +++ b/src/main/fragment/vbuaa_le_0_then_la1.asm @@ -0,0 +1,2 @@ +cmp #0 +beq {la1} \ No newline at end of file diff --git a/src/main/fragment/vbuxx_le_0_then_la1.asm b/src/main/fragment/vbuxx_le_0_then_la1.asm new file mode 100644 index 000000000..d1d800f7b --- /dev/null +++ b/src/main/fragment/vbuxx_le_0_then_la1.asm @@ -0,0 +1,2 @@ +cpx #0 +beq {la1} \ No newline at end of file diff --git a/src/main/fragment/vbuyy_le_0_then_la1.asm b/src/main/fragment/vbuyy_le_0_then_la1.asm new file mode 100644 index 000000000..9af1697e9 --- /dev/null +++ b/src/main/fragment/vbuyy_le_0_then_la1.asm @@ -0,0 +1,2 @@ +cpy #0 +beq {la1} \ No newline at end of file diff --git a/src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm b/src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm new file mode 100644 index 000000000..5afd41846 --- /dev/null +++ b/src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm @@ -0,0 +1,7 @@ +lda {z1} +cmp #<{c1} +bne !+ +lda {z1}+1 +cmp #>{c1} +beq {la1} +!: \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 667ad696e..fd5051bd2 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -249,6 +249,7 @@ public class Compiler { optimizations.add(new Pass2DuplicateRValueIdentification(program)); optimizations.add(new Pass2ConditionalJumpSimplification(program)); optimizations.add(new Pass2ConditionalAndOrRewriting(program)); + optimizations.add(new Pass2ConditionalJumpSequenceImprovement(program)); optimizations.add(new Pass2ConstantRValueConsolidation(program)); optimizations.add(new Pass2ConstantIdentification(program)); optimizations.add(new Pass2ConstantValues(program)); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java index 5dfd1a7a4..1ea0a32b1 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java @@ -1,6 +1,7 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.values.ConstantInteger; @@ -18,7 +19,7 @@ public class OperatorDecrement extends OperatorUnary { if(operand instanceof ConstantInteger ) { return new ConstantInteger(((ConstantInteger) operand).getInteger() -1); } - throw new CompileError("Calculation not implemented " + getOperator() + " " + operand ); + throw new ConstantNotLiteral("Calculation not literal " + getOperator() + " " + operand ); } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java index a7532ff7a..bd63496d0 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java @@ -1,6 +1,6 @@ package dk.camelot64.kickc.model.operators; -import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.values.ConstantInteger; @@ -21,7 +21,7 @@ public class OperatorIncrement extends OperatorUnary { } else if(operand instanceof ConstantPointer) { return new ConstantPointer(((ConstantPointer) operand).getLocation()+1, ((ConstantPointer) operand).getElementType()); } - throw new CompileError("Calculation not implemented " + getOperator() + " " + operand ); + throw new ConstantNotLiteral("Calculation not literal " + getOperator() + " " + operand ); } @Override diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSequenceImprovement.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSequenceImprovement.java new file mode 100644 index 000000000..0bbd1fd33 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSequenceImprovement.java @@ -0,0 +1,79 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.operators.Operator; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementConditionalJump; +import dk.camelot64.kickc.model.values.LabelRef; + +// If a conditional (on block A) jumps to a block (B) that has the same default successor (C) as the current block (A) then +// negate the conditional to ensure sequence A->B->C, which generates optimal ASM. +public class Pass2ConditionalJumpSequenceImprovement extends Pass2SsaOptimization { + + public Pass2ConditionalJumpSequenceImprovement(Program program) { + super(program); + } + + @Override + public boolean step() { + boolean modified = false; + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + ControlFlowBlock conditionalSuccessor = getGraph().getConditionalSuccessor(block); + ControlFlowBlock defaultSuccessor = getGraph().getDefaultSuccessor(block); + if(conditionalSuccessor != null && defaultSuccessor != null) { + if(conditionalSuccessor.getDefaultSuccessor().equals(defaultSuccessor.getLabel())) { + if(conditionalSuccessor.equals(block)) continue; + // conditional successor is current blocks default successor + // Negate condition and swap conditional/default successor. + modified = negateCondition(block); + } + + } + } + return modified; + } + + private boolean negateCondition(ControlFlowBlock block) { + LabelRef defaultSuccessor = block.getDefaultSuccessor(); + LabelRef conditionalSuccessor = block.getConditionalSuccessor(); + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementConditionalJump) { + StatementConditionalJump conditionalJump = (StatementConditionalJump) statement; + if(negateOperator(conditionalJump.getOperator()) != null) { + Operator negatedOperator = negateOperator(conditionalJump.getOperator()); + conditionalJump.setOperator(negatedOperator); + conditionalJump.setDestination(defaultSuccessor); + block.setConditionalSuccessor(defaultSuccessor); + block.setDefaultSuccessor(conditionalSuccessor); + getLog().append("Negating conditional jump and destination " + conditionalJump.toString(getProgram(), false)); + return true; + } + } + } + return false; + } + + /** + * Find the logic operator that returns the opposite result + * + * @param operator The operator to negate + * @return The opposite logic operator. Null if not found. + */ + private Operator negateOperator(Operator operator) { + if(Operators.EQ.equals(operator)) + return Operators.NEQ; + if(Operators.NEQ.equals(operator)) + return Operators.EQ; + if(Operators.LT.equals(operator)) + return Operators.GE; + if(Operators.LE.equals(operator)) + return Operators.GT; + if(Operators.GT.equals(operator)) + return Operators.LE; + if(Operators.GE.equals(operator)) + return Operators.LT; + return null; + } +} diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 338a622e5..23c2cc2b7 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -63,6 +63,11 @@ public class TestPrograms { */ + @Test + public void testStatementSequence1() throws IOException, URISyntaxException { + compileAndCompare("statement-sequence-1"); + } + @Test public void testSubExprOptimize1() throws IOException, URISyntaxException { compileAndCompare("subexpr-optimize-1"); diff --git a/src/test/kc/statement-sequence-1.kc b/src/test/kc/statement-sequence-1.kc new file mode 100644 index 000000000..396b7b3cf --- /dev/null +++ b/src/test/kc/statement-sequence-1.kc @@ -0,0 +1,15 @@ +// Tests statement sequence generation + +void main() { + + const byte* SCREEN = 0x0400; + + for(byte i: 0..10) { + byte c = i+5; + if((i&1)==0 || i>5) + c++; + SCREEN[i] = c; + } + + +} diff --git a/src/test/ref/bool-ifs.asm b/src/test/ref/bool-ifs.asm index ef375b6fe..8b9c1b158 100644 --- a/src/test/ref/bool-ifs.asm +++ b/src/test/ref/bool-ifs.asm @@ -16,9 +16,7 @@ bool_complex: { txa and #1 cpx #$a - bcc b6 - jmp b5 - b6: + bcs b5 cmp #0 beq b2 b5: @@ -90,9 +88,7 @@ bool_and: { txa and #1 cpx #$a - bcc b5 - jmp b4 - b5: + bcs b4 cmp #0 beq b2 b4: diff --git a/src/test/ref/bool-vars.asm b/src/test/ref/bool-vars.asm index 65d8b579c..e4b28d49a 100644 --- a/src/test/ref/bool-vars.asm +++ b/src/test/ref/bool-vars.asm @@ -107,9 +107,7 @@ bool_and: { txa and #1 cpx #$a - bcc b5 - jmp b4 - b5: + bcs b4 cmp #0 beq b2 b4: diff --git a/src/test/ref/complex-conditional-problem.asm b/src/test/ref/complex-conditional-problem.asm index 46436158b..12fdbcac5 100644 --- a/src/test/ref/complex-conditional-problem.asm +++ b/src/test/ref/complex-conditional-problem.asm @@ -10,8 +10,7 @@ main: { cmp #$20+1 bcs b3 cmp #$40 - bcc b3 - jmp b2 + bcs b2 b3: lda #0 b2: diff --git a/src/test/ref/duplicate-loop-problem.asm b/src/test/ref/duplicate-loop-problem.asm index d2dc774fa..0a2aa7631 100644 --- a/src/test/ref/duplicate-loop-problem.asm +++ b/src/test/ref/duplicate-loop-problem.asm @@ -10,9 +10,7 @@ main: { txa and #$1f cpx #0 - beq b3 - jmp b1 - b3: + bne b1 cmp #$1f beq b1 jmp b1 diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm index 6016bd1d2..b0ac841db 100644 --- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm +++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm @@ -185,9 +185,7 @@ plexSort: { sta PLEX_SORTED_IDX+1,x dex cpx #$ff - bne b6 - jmp b4 - b6: + beq b4 lda nxt_y ldy PLEX_SORTED_IDX,x cmp PLEX_YPOS,y diff --git a/src/test/ref/keyboard-glitch.asm b/src/test/ref/keyboard-glitch.asm index e557715bc..e9466358d 100644 --- a/src/test/ref/keyboard-glitch.asm +++ b/src/test/ref/keyboard-glitch.asm @@ -95,7 +95,9 @@ pressed: { ldx #KEY_SPACE jsr keyboard_key_pressed cmp #0 - beq b1 + bne breturn + jmp b1 + breturn: rts } // Keyboard row bitmask as expected by CIA#1 Port A when reading a specific keyboard matrix row (rows are numbered 0-7) diff --git a/src/test/ref/loop-break-continue.asm b/src/test/ref/loop-break-continue.asm index c7a50bd37..66faad93f 100644 --- a/src/test/ref/loop-break-continue.asm +++ b/src/test/ref/loop-break-continue.asm @@ -14,13 +14,12 @@ main: { lda str,x cmp #'@' bne b2 + breturn: rts b2: lda str,x cmp #' ' - bne b3 - jmp b4 - b3: + beq b4 lda str,x ldy #0 sta (screen),y @@ -31,7 +30,7 @@ main: { b4: inx cpx #0 - bne b1 - rts + beq breturn + jmp b1 str: .text "hello brave new world@" } diff --git a/src/test/ref/loop-break-nested.asm b/src/test/ref/loop-break-nested.asm index eb7d4bbcc..9de10c039 100644 --- a/src/test/ref/loop-break-nested.asm +++ b/src/test/ref/loop-break-nested.asm @@ -12,16 +12,15 @@ main: { ldy #0 lda (line),y cmp #'a' - bne b5 + bne b3 + breturn: rts - b5: + b3: ldy #0 b2: lda (line),y cmp #'a' - bne b3 - jmp b4 - b3: + beq b4 lda #'a' sta (line),y iny @@ -37,11 +36,11 @@ main: { !: lda line+1 cmp #>$400+$28*$19 - bcc b1 - bne !+ + bcc !+ + bne breturn lda line cmp #<$400+$28*$19 - bcc b1 + bcs breturn !: - rts + jmp b1 } diff --git a/src/test/ref/loop-break.asm b/src/test/ref/loop-break.asm index e1e305c19..9be966560 100644 --- a/src/test/ref/loop-break.asm +++ b/src/test/ref/loop-break.asm @@ -8,13 +8,12 @@ main: { b1: lda SCREEN,x cmp #'a' - bne b2 - rts - b2: + beq breturn lda #'a' sta SCREEN,x inx cpx #$28*6+1 bne b1 + breturn: rts } diff --git a/src/test/ref/loop-continue.asm b/src/test/ref/loop-continue.asm index fe08e6e87..bd86c60aa 100644 --- a/src/test/ref/loop-continue.asm +++ b/src/test/ref/loop-continue.asm @@ -8,9 +8,7 @@ main: { b1: lda SCREEN,x cmp #' ' - bne b2 - jmp b3 - b2: + beq b3 inc SCREEN,x b3: inx diff --git a/src/test/ref/loop-while-continue.asm b/src/test/ref/loop-while-continue.asm index 1424862f5..8529f855a 100644 --- a/src/test/ref/loop-while-continue.asm +++ b/src/test/ref/loop-while-continue.asm @@ -13,9 +13,7 @@ main: { b2: lda SCREEN,x cmp #' ' - bne b3 - jmp b1 - b3: + beq b1 inc SCREEN,x jmp b1 } diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm index 52e162f4a..64cf59ca2 100644 --- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm +++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm @@ -129,9 +129,7 @@ plexSort: { sta PLEX_SORTED_IDX+1,x dex cpx #$ff - bne b7 - jmp b4 - b7: + beq b4 lda nxt_y ldy PLEX_SORTED_IDX,x cmp PLEX_YPOS,y @@ -241,9 +239,7 @@ plex_irq: { sta _4 lda plex_show_idx cmp #PLEX_COUNT - bcc b7 - jmp b4 - b7: + bcs b4 cpx _4 bcc b3 b4: diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm index 3597c7029..c3437f972 100644 --- a/src/test/ref/sandbox.asm +++ b/src/test/ref/sandbox.asm @@ -202,9 +202,7 @@ myprintf: { rts b3: cpx #'1' - bcs b39 - jmp b4 - b39: + bcc b4 cpx #'9' bcs !b23+ jmp b23 @@ -286,10 +284,8 @@ myprintf: { bne b13 lda bTrailing cmp #0 - beq b41 - jmp b15 - b41: - lda b + bne b15 + tya cmp bDigits bcc b16 b15: @@ -304,13 +300,14 @@ myprintf: { bcc b19 lda bTrailing cmp #0 - bne b42 + bne !b22+ jmp b22 - b42: + !b22: lda b cmp bDigits - bcc b21 + bcc !b22+ jmp b22 + !b22: b21: lda #' ' ldy bLen @@ -393,13 +390,9 @@ myprintf: { jmp b31 b28: cpx #$41 - bcs b43 - jmp b32 - b43: + bcc b32 cpx #$5a+1 - bcc b37 - jmp b32 - b37: + bcs b32 txa axs #-[$20] b32: diff --git a/src/test/ref/statement-sequence-1.asm b/src/test/ref/statement-sequence-1.asm new file mode 100644 index 000000000..4ba57981e --- /dev/null +++ b/src/test/ref/statement-sequence-1.asm @@ -0,0 +1,27 @@ +// Tests statement sequence generation +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label SCREEN = $400 + ldy #0 + b1: + tya + tax + axs #-[5] + tya + and #1 + cmp #0 + beq b3 + cpy #5+1 + bcc b2 + b3: + inx + b2: + txa + sta SCREEN,y + iny + cpy #$b + bne b1 + rts +} From f574bb676c467717d9710b99268deb075d997952 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Fri, 24 May 2019 00:50:48 +0200 Subject: [PATCH 83/93] Working in unumber/snumber. Only few failing tests. --- .../java/dk/camelot64/kickc/Compiler.java | 7 +- .../iterator/ProgramExpressionBinary.java | 58 +++++--- .../model/operators/OperatorCastSNumber.java | 27 ++++ .../model/operators/OperatorCastUNumber.java | 28 ++++ .../kickc/model/operators/OperatorDivide.java | 2 +- .../model/operators/OperatorGetHigh.java | 4 + .../kickc/model/operators/OperatorGetLow.java | 4 + .../kickc/model/operators/Operators.java | 6 + .../kickc/model/symbols/VariableVersion.java | 1 + .../kickc/model/types/SymbolType.java | 2 +- .../model/types/SymbolTypeConversion.java | 129 ++++++++++++------ .../kickc/passes/Pass1PointerSizeofFix.java | 4 +- .../passes/Pass2ConstantIdentification.java | 1 + .../kickc/passes/Pass2ConstantInlining.java | 3 +- .../passes/Pass2DeInlineWordDerefIdx.java | 2 +- .../passes/PassNAddNumberTypeConversions.java | 1 + .../kickc/passes/PassNCastSimplification.java | 9 +- .../PassNFinalizeNumberTypeConversions.java | 65 +++++++++ .../kickc/passes/PassNTypeInference.java | 8 +- src/test/kc/sandbox.kc | 4 +- src/test/kc/ternary-inference.kc | 2 +- 21 files changed, 290 insertions(+), 77 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSNumber.java create mode 100644 src/main/java/dk/camelot64/kickc/model/operators/OperatorCastUNumber.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index fd5051bd2..fcfc80bcb 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -232,12 +232,15 @@ public class Compiler { private List<Pass2SsaOptimization> getPass2Optimizations() { List<Pass2SsaOptimization> optimizations = new ArrayList<>(); optimizations.add(new Pass2FixInlineConstructorsNew(program)); + optimizations.add(new PassNAddNumberTypeConversions(program)); optimizations.add(new PassNAddArrayNumberTypeConversions(program)); - optimizations.add(new PassNTypeInference(program)); - optimizations.add(new PassNAddTypeConversionAssignment(program)); optimizations.add(new Pass2InlineCast(program)); optimizations.add(new PassNCastSimplification(program)); + optimizations.add(new PassNFinalizeNumberTypeConversions(program)); + optimizations.add(new PassNTypeInference(program)); + optimizations.add(new PassNAddTypeConversionAssignment(program)); + optimizations.add(new PassNTypeIdSimplification(program)); optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new PassNStatementIndices(program)); diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java index e0b959796..f21ea8348 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java @@ -10,6 +10,7 @@ import dk.camelot64.kickc.model.statements.StatementConditionalJump; import dk.camelot64.kickc.model.statements.StatementPhiBlock; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.symbols.Scope; +import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.symbols.VariableIntermediate; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; @@ -96,7 +97,7 @@ public interface ProgramExpressionBinary extends ProgramExpression { } else { Scope blockScope = symbols.getScope(currentScope); VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); - tmpVar.setType(toType); + tmpVar.setTypeInferred(toType); StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue1(), assignment.getSource(), Comment.NO_COMMENTS); assignment.setrValue1(tmpVar.getRef()); stmtIt.previous(); @@ -112,7 +113,7 @@ public interface ProgramExpressionBinary extends ProgramExpression { } else { Scope blockScope = symbols.getScope(currentScope); VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); - tmpVar.setType(toType); + tmpVar.setTypeInferred(toType); StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue2(), assignment.getSource(), Comment.NO_COMMENTS); assignment.setrValue2(tmpVar.getRef()); stmtIt.previous(); @@ -156,13 +157,21 @@ public interface ProgramExpressionBinary extends ProgramExpression { @Override public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { - Scope blockScope = symbols.getScope(currentScope); - VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); - SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight()); - tmpVar.setType(rightType); - StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS); - assignment.setlValue(tmpVar.getRef()); - stmtIt.add(newAssignment); + if(assignment.getlValue() instanceof VariableRef) { + Variable variable = symbols.getVariable((VariableRef) assignment.getlValue()); + if(variable.isInferredType()) + variable.setTypeInferred(toType); + else + throw new InternalError("Cannot cast declared type!" + variable.toString()); + } else { + Scope blockScope = symbols.getScope(currentScope); + VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); + SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight()); + tmpVar.setTypeInferred(rightType); + StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS); + assignment.setlValue(tmpVar.getRef()); + stmtIt.add(newAssignment); + } } @Override @@ -173,7 +182,7 @@ public interface ProgramExpressionBinary extends ProgramExpression { Scope blockScope = symbols.getScope(currentScope); VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight()); - tmpVar.setType(rightType); + tmpVar.setTypeInferred(rightType); StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS); assignment.setlValue(tmpVar.getRef()); stmtIt.add(newAssignment); @@ -314,7 +323,7 @@ public interface ProgramExpressionBinary extends ProgramExpression { public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { if(getPointerDereferenceIndexed().getPointer() instanceof ConstantValue) { getPointerDereferenceIndexed().setPointer(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getPointer())); - } else { + } else { // Try to use CastValue - may later have to be supported! getPointerDereferenceIndexed().setPointer(new CastValue(toType, getPointerDereferenceIndexed().getPointer())); } @@ -324,7 +333,14 @@ public interface ProgramExpressionBinary extends ProgramExpression { public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { if(getPointerDereferenceIndexed().getIndex() instanceof ConstantValue) { getPointerDereferenceIndexed().setIndex(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getIndex())); - } else { + } else if( getPointerDereferenceIndexed().getIndex() instanceof VariableRef) { + Variable variable = symbols.getVariable((VariableRef) getPointerDereferenceIndexed().getIndex()); + if(variable.isInferredType()) + variable.setTypeInferred(toType); + else + throw new InternalError("Cannot cast declared type!" + variable.toString()); + + } else { // Try to use CastValue - may later have to be supported! getPointerDereferenceIndexed().setIndex(new CastValue(toType, getPointerDereferenceIndexed().getIndex())); } @@ -360,15 +376,22 @@ public interface ProgramExpressionBinary extends ProgramExpression { @Override public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { - throw new InternalError("Not supported!"); + Variable variable = symbols.getVariable(phiVariable.getVariable()); + if(variable.isInferredType()) + variable.setTypeInferred(toType); + else + throw new InternalError("Cannot cast declared type!" + variable.toString()); } @Override public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { - if(getRight() instanceof ConstantValue) { + if(getRight() instanceof VariableRef) { + Variable variable = symbols.getVariable((VariableRef) getRight()); + if(variable.isInferredType()) + variable.setTypeInferred(toType); + } else if(getRight() instanceof ConstantValue) { value.setrValue(new ConstantCastValue(toType, (ConstantValue) getRight())); - } else { - // Try to use CastValue - may later have to be supported! + } else { value.setrValue(new CastValue(toType, getRight())); } } @@ -380,7 +403,4 @@ public interface ProgramExpressionBinary extends ProgramExpression { } - - - } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSNumber.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSNumber.java new file mode 100644 index 000000000..f63a5c264 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSNumber.java @@ -0,0 +1,27 @@ +package dk.camelot64.kickc.model.operators; + +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.symbols.ProgramScope; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.ConstantInteger; +import dk.camelot64.kickc.model.values.ConstantLiteral; + +/** Unary Cast to signed number operator ( (snumber) x ) */ +public class OperatorCastSNumber extends OperatorCast { + + public OperatorCastSNumber(int precedence) { + super("((snumber))", "_snumber_", precedence, SymbolType.SNUMBER); + } + + @Override + public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { + if(value instanceof ConstantInteger) + return new ConstantInteger(((ConstantInteger) value).getValue(), SymbolType.SNUMBER); + throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); + } + + @Override + public SymbolType inferType(SymbolType operandType) { + return SymbolType.SNUMBER; + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastUNumber.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastUNumber.java new file mode 100644 index 000000000..d6ea9e832 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastUNumber.java @@ -0,0 +1,28 @@ +package dk.camelot64.kickc.model.operators; + +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.symbols.ProgramScope; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.ConstantInteger; +import dk.camelot64.kickc.model.values.ConstantLiteral; +import dk.camelot64.kickc.model.values.ConstantPointer; + +/** Unary Cast to unsigned number operator ( (unumber) x ) */ +public class OperatorCastUNumber extends OperatorCast { + + public OperatorCastUNumber(int precedence) { + super("((unumber))", "_unumber_", precedence, SymbolType.UNUMBER); + } + + @Override + public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { + if(value instanceof ConstantInteger) + return new ConstantInteger(((ConstantInteger) value).getValue(), SymbolType.UNUMBER); + throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); + } + + @Override + public SymbolType inferType(SymbolType operandType) { + return SymbolType.UNUMBER; + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java index eb3be39a8..e771d3bb4 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java @@ -29,7 +29,7 @@ public class OperatorDivide extends OperatorBinary { @Override public SymbolType inferType(SymbolType left, SymbolType right) { if(left instanceof SymbolTypePointer) { - if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) { + if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)|| SymbolType.UNUMBER.equals(right)|| SymbolType.SNUMBER.equals(right)) { return left; } else { throw new NoMatchingType("Cannot divide pointer by "+right.toString()); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java index e7ad53157..82367f396 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java @@ -50,6 +50,10 @@ public class OperatorGetHigh extends OperatorUnary { return SymbolType.BYTE; } else if(SymbolType.NUMBER.equals(operandType)) { return SymbolType.NUMBER; + } else if(SymbolType.UNUMBER.equals(operandType)) { + return SymbolType.UNUMBER; + } else if(SymbolType.SNUMBER.equals(operandType)) { + return SymbolType.UNUMBER; } throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java index 6d8e03c03..e162f4d0d 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java @@ -50,6 +50,10 @@ public class OperatorGetLow extends OperatorUnary { return SymbolType.BYTE; } else if(SymbolType.NUMBER.equals(operandType)) { return SymbolType.NUMBER; + } else if(SymbolType.UNUMBER.equals(operandType)) { + return SymbolType.UNUMBER; + } else if(SymbolType.SNUMBER.equals(operandType)) { + return SymbolType.UNUMBER; } throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java index 173ab0e8c..0afad2224 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java @@ -26,6 +26,8 @@ public class Operators { public static final OperatorUnary CAST_DWORD = new OperatorCastDWord(2); public static final OperatorUnary CAST_SDWORD = new OperatorCastSDWord(2); public static final OperatorUnary CAST_BOOL= new OperatorCastBool(2); + public static final OperatorUnary CAST_UNUMBER = new OperatorCastUNumber(2); + public static final OperatorUnary CAST_SNUMBER = new OperatorCastSNumber(2); public static final OperatorUnary SIZEOF = new OperatorSizeOf(2); public static final OperatorUnary TYPEID = new OperatorTypeId(2); public static final OperatorBinary MULTIPLY = new OperatorMultiply(3); @@ -149,6 +151,10 @@ public class Operators { return CAST_DWORD; } else if(SymbolType.SDWORD.equals(castType)) { return CAST_SDWORD; + } else if(SymbolType.UNUMBER.equals(castType)) { + return CAST_UNUMBER; + } else if(SymbolType.SNUMBER.equals(castType)) { + return CAST_SNUMBER; } else if(SymbolType.BOOLEAN.equals(castType)) { return CAST_BOOL; } else if(castType instanceof SymbolTypePointer) { diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/VariableVersion.java b/src/main/java/dk/camelot64/kickc/model/symbols/VariableVersion.java index 7aca0fd3a..47c67dc0f 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/VariableVersion.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/VariableVersion.java @@ -12,6 +12,7 @@ public class VariableVersion extends Variable { this.setDeclaredAlignment(versionOf.getDeclaredAlignment()); this.setDeclaredRegister(versionOf.getDeclaredRegister()); this.setDeclaredVolatile(versionOf.isDeclaredVolatile()); + this.setInferredType(versionOf.isInferredType()); this.versionOfName = versionOf.getLocalName(); this.setComments(versionOf.getComments()); } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java index bff9cc686..c0abe5d1b 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java @@ -117,7 +117,7 @@ public interface SymbolType { * @return true if the type is integer */ static boolean isInteger(SymbolType type) { - return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type); + return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type)|| UNUMBER.equals(type)|| SNUMBER.equals(type); } } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index b2f8c2356..e37c240d9 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -32,6 +32,16 @@ public class SymbolTypeConversion { if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) { return SymbolType.NUMBER; } + // If any of the two types are unresolved unsigned - return an unresolved unsigned result + if(SymbolType.UNUMBER.equals(type1) || SymbolType.UNUMBER.equals(type2)) { + return SymbolType.UNUMBER; + } + // If any of the two types are unresolved signed - return an unresolved signed result + if(SymbolType.SNUMBER.equals(type1) || SymbolType.SNUMBER.equals(type2)) { + return SymbolType.SNUMBER; + } + + // Both types are resolved (fixed) integer types SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1; SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2; // C99 6.3.1.8 a. If two operands have the same type no conversion is performed @@ -82,6 +92,13 @@ public class SymbolTypeConversion { return null; } + // a) If any the two operands are unsigned numbers the result is an unsigned number + if(SymbolType.UNUMBER.equals(leftType) || SymbolType.UNUMBER.equals(rightType)) + return SymbolType.UNUMBER; + // a) If any the two operands are signed numbers the result is an signed number + if(SymbolType.SNUMBER.equals(leftType) || SymbolType.SNUMBER.equals(rightType)) + return SymbolType.SNUMBER; + // Treat pointers like WORD if(leftType instanceof SymbolTypePointer) leftType = SymbolType.WORD; if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD; @@ -102,52 +119,70 @@ public class SymbolTypeConversion { return null; } - // Find the cast type if possible - if(numberVal instanceof ConstantValue) { - ConstantLiteral constantLiteral; - try { - constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols); - } catch( ConstantNotLiteral e) { - // Postpone til later! - return null; - } - if(constantLiteral instanceof ConstantInteger) { - ConstantInteger constantInteger = (ConstantInteger) constantLiteral; - if(SymbolType.NUMBER.equals(constantInteger.getType())) { - Long value = constantInteger.getValue(); - if(fixedType.isSigned()) { - // b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values. - SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value); - if(smallestSignedType == null) { - throw new CompileError("Number constant has value that cannot be represented by a signed type " + value, currentStmt); - } - return smallestSignedType; - } else { - // b) If one operand is a signed type and the other a number the number is converted to the smallest unsigned type that can hold its values. - // If the number value is negative it is converted to unsigned using two's complement. - SymbolTypeIntegerFixed smallestUnsignedType; - if(value < 0) { - smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(-value); - } else { - smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value); - } - return smallestUnsignedType; - } - } else { - throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt); - } - } + if(fixedType.isSigned()) { + return SymbolType.SNUMBER; } else { - // Postpone til later! - return null; + return SymbolType.UNUMBER; } } + // No number conversion return null; + + } + + + public static SymbolType getSmallestSignedFixedIntegerType(ConstantValue constantValue, ProgramScope symbols) { + ConstantLiteral constantLiteral; + try { + constantLiteral = constantValue.calculateLiteral(symbols); + } catch(ConstantNotLiteral e) { + // Postpone til later! + return null; + } + if(constantLiteral instanceof ConstantInteger) { + Long value = ((ConstantInteger) constantLiteral).getValue(); + // b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values. + SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value); + if(smallestSignedType == null) { + throw new CompileError("Number constant has value that cannot be represented by a signed type " + constantValue.toString()); + } + return smallestSignedType; + } + // Postpone til later! + return null; } + public static SymbolType getSmallestUnsignedFixedIntegerType(ConstantValue constantValue, ProgramScope symbols) { + ConstantLiteral constantLiteral; + try { + constantLiteral = constantValue.calculateLiteral(symbols); + } catch(ConstantNotLiteral e) { + // Postpone til later! + return null; + } + if(constantLiteral instanceof ConstantInteger) { + Long value = ((ConstantInteger) constantLiteral).getValue(); + // b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values. + SymbolTypeIntegerFixed smallestUnsignedType; + if(value < 0) { + smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(-value); + } else { + smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value); + } + if(smallestUnsignedType == null) { + throw new CompileError("Number constant has value that cannot be represented by a unsigned type " + constantValue.toString()); + } + return smallestUnsignedType; + } + // Postpone til later! + return null; + } + + /** * Determines if the types of an assignment match up properly + * * @param lValueType The type of the LValue * @param rValueType The type of the RValue * @return true if the types match up @@ -171,10 +206,26 @@ public class SymbolTypeConversion { // R-value is still a number - constants are probably not done being identified & typed return true; } + if(SymbolType.UNUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) { + // R-value is still a number - constants are probably not done being identified & typed + return true; + } + if(SymbolType.SNUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) { + // R-value is still a number - constants are probably not done being identified & typed + return true; + } if(SymbolType.NUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) { // R-value is still a number - constants are probably not done being identified & typed return true; } + if(SymbolType.UNUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) { + // R-value is still a number - constants are probably not done being identified & typed + return true; + } + if(SymbolType.SNUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) { + // R-value is still a number - constants are probably not done being identified & typed + return true; + } if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType())) { // String value can be assigned into a pointer return true; @@ -189,6 +240,7 @@ public class SymbolTypeConversion { /** * Determines if the left side of an assignment needs a cast to be assigned to the right side + * * @param lValueType The type of the LValue * @param rValueType The type of the RValue * @return true if the left side needs a cast @@ -201,9 +253,8 @@ public class SymbolTypeConversion { else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType())) return false; else - return true; + return true; } - } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java b/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java index 9a840e3b4..c4caba00d 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java @@ -64,7 +64,7 @@ public class Pass1PointerSizeofFix extends Pass1Base { VariableRef idx2VarRef = handled.getOrDefault(currentStmt, new LinkedHashMap<>()).get(deref.getIndex()); if(idx2VarRef==null) { VariableIntermediate idx2Var = getScope().getScope(currentBlock.getScope()).addVariableIntermediate(); - idx2Var.setType(SymbolTypeInference.inferType(getScope(), deref.getIndex())); + idx2Var.setTypeInferred(SymbolTypeInference.inferType(getScope(), deref.getIndex())); ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()); StatementAssignment idx2 = new StatementAssignment(idx2Var.getRef(), deref.getIndex(), Operators.MULTIPLY, sizeOfTargetType, currentStmt.getSource(), Comment.NO_COMMENTS); stmtIt.previous(); @@ -100,7 +100,7 @@ public class Pass1PointerSizeofFix extends Pass1Base { // Adding to a pointer - multiply by sizeof() getLog().append("Fixing pointer addition " + assignment.toString(getProgram(), false)); VariableIntermediate tmpVar = getScope().getScope(block.getScope()).addVariableIntermediate(); - tmpVar.setType(SymbolTypeInference.inferType(getScope(), assignment.getrValue2())); + tmpVar.setTypeInferred(SymbolTypeInference.inferType(getScope(), assignment.getrValue2())); stmtIt.remove(); ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()); stmtIt.add(new StatementAssignment(tmpVar.getRef(), assignment.getrValue2(), Operators.MULTIPLY, sizeOfTargetType, assignment.getSource(), Comment.NO_COMMENTS)); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java index 76affac0d..58cbc1719 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java @@ -92,6 +92,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { constScope, variableType, constVal); + constantVar.setInferredType(variable.isInferredType()); constantVar.setDeclaredAlignment(variable.getDeclaredAlignment()); constantVar.setDeclaredRegister(variable.getDeclaredRegister()); if(variable.getComments().size() > 0) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java index 4686b3df3..801a63bb4 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java @@ -33,8 +33,9 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization { @Override public boolean step() { Map<ConstantRef, ConstantValue> inline = new HashMap<>(); + Map<ConstantRef, ConstantValue> aliasConstants = findAliasConstants(); + inline.putAll(aliasConstants); inline.putAll(findUnnamedConstants()); - inline.putAll(findAliasConstants()); inline.putAll(findConstVarVersions()); // Remove all string constants diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java index 2b0b96cce..267a085ab 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java @@ -42,7 +42,7 @@ public class Pass2DeInlineWordDerefIdx extends Pass2SsaOptimization { stmtIt.next(); programValue.set(new PointerDereferenceSimple(tmpVar.getRef())); SymbolType pointerType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(tmpVarAssignment)); - tmpVar.setType(pointerType); + tmpVar.setTypeInferred(pointerType); optimized.set(true); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java index dcc576213..7f05fe4f3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java @@ -40,6 +40,7 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization { if(SymbolType.NUMBER.equals(rightType)) { getLog().append("Adding number conversion cast (" + castType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false))); binary.addRightCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope()); + modified.set(true); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java index 5661a8624..743d7cfe1 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java @@ -11,10 +11,11 @@ import dk.camelot64.kickc.model.values.RValue; import java.util.concurrent.atomic.AtomicBoolean; -/** Simplifies casts +/** + * Simplifies casts * - Inlines casts of (number) constants * - Removes unnecessary casts - * */ + */ public class PassNCastSimplification extends Pass2SsaOptimization { public PassNCastSimplification(Program program) { @@ -39,12 +40,12 @@ public class PassNCastSimplification extends Pass2SsaOptimization { } else if(unaryOperand instanceof ConstantInteger) { ConstantInteger constantInteger = (ConstantInteger) unaryOperand; if(SymbolType.NUMBER.equals(constantInteger.getType())) { - if(castType instanceof SymbolTypeIntegerFixed ) { + if(castType instanceof SymbolTypeIntegerFixed || SymbolType.UNUMBER.equals(castType) || SymbolType.SNUMBER.equals(castType)) { ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); programExpression.set(newConstInt); getLog().append("Simplifying constant integer cast " + newConstInt.toString()); optimized.set(true); - } else if(castType instanceof SymbolTypePointer) { + } else if(castType instanceof SymbolTypePointer) { ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType()); programExpression.set(newConstPointer); getLog().append("Simplifying constant pointer cast " + newConstPointer.toString()); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java new file mode 100644 index 000000000..76b2b33a3 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java @@ -0,0 +1,65 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.InternalError; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramValueIterator; +import dk.camelot64.kickc.model.symbols.ConstantVar; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeConversion; +import dk.camelot64.kickc.model.values.*; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Finalize any constant integers to the smallest fixed size signed/unsigned type - if they have been resolved as snumber/unumber. + */ +public class PassNFinalizeNumberTypeConversions extends Pass2SsaOptimization { + + public PassNFinalizeNumberTypeConversions(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean modified = new AtomicBoolean(false); + ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> { + if(programValue.get() instanceof ConstantInteger) { + ConstantInteger constantInteger = (ConstantInteger) programValue.get(); + if(SymbolType.UNUMBER.equals(constantInteger.getType())) { + SymbolType integerType = SymbolTypeConversion.getSmallestUnsignedFixedIntegerType(constantInteger, getScope()); + programValue.set(new ConstantInteger(constantInteger.getValue(), integerType)); + getLog().append("Finalized unsigned number type "+programValue.get().toString(getProgram())); + modified.set(true); + } else if(SymbolType.SNUMBER.equals(constantInteger.getType())) { + SymbolType integerType = SymbolTypeConversion.getSmallestSignedFixedIntegerType(constantInteger, getScope()); + programValue.set(new ConstantInteger(constantInteger.getValue(), integerType)); + getLog().append("Finalized signed number type "+programValue.get().toString(getProgram())); + modified.set(true); + } + } else if(programValue.get() instanceof ConstantCastValue) { + ConstantCastValue constantCastValue = (ConstantCastValue) programValue.get(); + SymbolType toType = constantCastValue.getToType(); + if(SymbolType.UNUMBER.equals(toType)) { + if(constantCastValue.getValue() instanceof ConstantRef) { + ConstantRef constRef = (ConstantRef) constantCastValue.getValue(); + ConstantVar constant = getScope().getConstant(constRef); + if(constant.isInferredType()) + constant.setTypeInferred(toType); + else + throw new InternalError("Cannot cast declared type!" + constant.toString()); + } else { + ConstantLiteral constantLiteral = constantCastValue.getValue().calculateLiteral(getProgram().getScope()); + SymbolType smallestUnsigned = SymbolTypeConversion.getSmallestUnsignedFixedIntegerType(constantLiteral, getScope()); + if(smallestUnsigned!=null) { + constantCastValue.setToType(smallestUnsigned); + } + } + } + if(SymbolType.SNUMBER.equals(toType)) + throw new InternalError("TODO: Finalize ConstantCast"); + } + }); + return modified.get(); + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java index 4e135e916..39c586a4e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java @@ -60,7 +60,7 @@ public class PassNTypeInference extends Pass2SsaOptimization { LValue lValue = call.getlValue(); if(lValue instanceof VariableRef) { Variable symbol = programScope.getVariable((VariableRef) lValue); - if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) { Procedure procedure = programScope.getProcedure(call.getProcedure()); SymbolType type = procedure.getReturnType(); setInferedType(program, call, symbol, type); @@ -73,7 +73,7 @@ public class PassNTypeInference extends Pass2SsaOptimization { LValue lValue = call.getlValue(); if(lValue instanceof VariableRef) { Variable symbol = programScope.getVariable((VariableRef) lValue); - if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) { SymbolType procedureType = SymbolTypeInference.inferType(programScope, call.getProcedure()); if(procedureType instanceof SymbolTypeProcedure) { SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType(); @@ -86,7 +86,7 @@ public class PassNTypeInference extends Pass2SsaOptimization { private static void updateInferedTypePhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) { ProgramScope programScope = program.getScope(); Variable symbol = programScope.getVariable(phiVariable.getVariable()); - if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) { SymbolType type = null; for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { RValue rValue = phiRValue.getrValue(); @@ -112,7 +112,7 @@ public class PassNTypeInference extends Pass2SsaOptimization { LValue lValue = assignment.getlValue(); if(lValue instanceof VariableRef) { Variable symbol = programScope.getVariable((VariableRef) lValue); - if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { + if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType()) || SymbolType.SNUMBER.equals(symbol.getType())) { SymbolType type = SymbolTypeInference.inferType(programScope, new AssignmentRValue(assignment)); setInferedType(program, assignment, symbol, type); // If the type is an array or a string the symbol is constant diff --git a/src/test/kc/sandbox.kc b/src/test/kc/sandbox.kc index 3ff3ae112..d84bb18f5 100644 --- a/src/test/kc/sandbox.kc +++ b/src/test/kc/sandbox.kc @@ -48,10 +48,10 @@ byte myprintf(byte *dst, byte *str, word w1, word w2, word w3) { if (bTrailing != 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = ' '; } else if (b == 'x' || b == 'X'){ // hex b = ((byte)w >> 4) & 0xF; - dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b; + dst[bLen++] = (b < 10 ? '0' : 0x57) + b; // "('a' - 10)" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/184 [FIXED] // (b < 10 ? '0' : 0x57) not supported - b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b; + b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b; } bFormat = 0; continue; diff --git a/src/test/kc/ternary-inference.kc b/src/test/kc/ternary-inference.kc index 4f6e29973..30b892c79 100644 --- a/src/test/kc/ternary-inference.kc +++ b/src/test/kc/ternary-inference.kc @@ -3,6 +3,6 @@ void main() { const byte* screen = 0x400; for(byte i: 0..10) { - screen[i] = (i<5?0x57ub:'0')+i; + screen[i] = (i<5?0x57:'0')+i; } } \ No newline at end of file From c42156c4e982b6f5862a306299435d98b1975212 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Fri, 24 May 2019 00:52:30 +0200 Subject: [PATCH 84/93] Working in unumber/snumber. Updated test files. --- src/test/ref/complex/tetris/tetris.asm | 1 + src/test/ref/examples/fire/fire.asm | 12 ++++---- src/test/ref/test-scroll-up.asm | 42 +++++++++++++------------- src/test/ref/test-word-size-arrays.asm | 36 +++++++++++----------- 4 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm index df178a3ac..ce2a47921 100644 --- a/src/test/ref/complex/tetris/tetris.asm +++ b/src/test/ref/complex/tetris/tetris.asm @@ -388,6 +388,7 @@ render_bcd: { } // Render the next tetromino in the "next" area render_next: { + // Find the screen area .const next_area_offset = $28*$c+$18+4 .label next_piece_gfx = 5 .label next_piece_char = $a diff --git a/src/test/ref/examples/fire/fire.asm b/src/test/ref/examples/fire/fire.asm index d14cf06e3..77c8919c1 100644 --- a/src/test/ref/examples/fire/fire.asm +++ b/src/test/ref/examples/fire/fire.asm @@ -182,7 +182,7 @@ makecharset: { .label ii = $a .label i = 9 .label c = 8 - .label _22 = 2 + .label _26 = 2 lda #<CHARSET sta font lda #>CHARSET @@ -272,15 +272,15 @@ makecharset: { inc _19+1 !: clc - lda _22 + lda _26 adc #<CHARSET+1*8 - sta _22 - lda _22+1 + sta _26 + lda _26+1 adc #>CHARSET+1*8 - sta _22+1 + sta _26+1 tya ldy #0 - sta (_22),y + sta (_26),y inc i lda i cmp #8 diff --git a/src/test/ref/test-scroll-up.asm b/src/test/ref/test-scroll-up.asm index 15c85f776..7e9d7c1b9 100644 --- a/src/test/ref/test-scroll-up.asm +++ b/src/test/ref/test-scroll-up.asm @@ -14,8 +14,8 @@ scrollup3: { .label l2_1 = 4 .label line = 2 .label l2_2 = 4 - .label _4 = 7 - .label _5 = 9 + .label _5 = 7 + .label _6 = 9 .label l2_4 = 4 lda #0 sta l2 @@ -30,20 +30,20 @@ scrollup3: { lda l2_2 clc adc #<screen+$28 - sta _4 + sta _5 lda l2_2+1 adc #>screen+$28 - sta _4+1 + sta _5+1 lda l2_2 clc adc #<screen - sta _5 + sta _6 lda l2_2+1 adc #>screen - sta _5+1 + sta _6+1 ldy #0 - lda (_4),y - sta (_5),y + lda (_5),y + sta (_6),y inc l2_1 bne !+ inc l2_1+1 @@ -109,8 +109,8 @@ scrollup1: { .label _0 = 4 .label _2 = 7 .label line = 2 - .label _6 = 7 - .label _7 = 4 + .label _7 = 7 + .label _8 = 4 lda #0 sta line sta line+1 @@ -132,22 +132,22 @@ scrollup1: { adc line+1 sta _2+1 clc - lda _6 - adc #<screen+$28 - sta _6 - lda _6+1 - adc #>screen+$28 - sta _6+1 - clc lda _7 - adc #<screen + adc #<screen+$28 sta _7 lda _7+1 - adc #>screen + adc #>screen+$28 sta _7+1 + clc + lda _8 + adc #<screen + sta _8 + lda _8+1 + adc #>screen + sta _8+1 ldy #0 - lda (_6),y - sta (_7),y + lda (_7),y + sta (_8),y inx cpx #$28 bcc b2 diff --git a/src/test/ref/test-word-size-arrays.asm b/src/test/ref/test-word-size-arrays.asm index 34f29fa59..93a40e061 100644 --- a/src/test/ref/test-word-size-arrays.asm +++ b/src/test/ref/test-word-size-arrays.asm @@ -7,9 +7,9 @@ main: { .label _2 = 6 .label _6 = 4 .label line = 2 - .label _8 = 6 - .label _9 = 4 + .label _9 = 6 .label _10 = 4 + .label _11 = 4 lda #0 sta line sta line+1 @@ -31,22 +31,22 @@ main: { adc line+1 sta _2+1 clc - lda _8 - adc #<screen+$28 - sta _8 - lda _8+1 - adc #>screen+$28 - sta _8+1 - clc lda _9 - adc #<screen + adc #<screen+$28 sta _9 lda _9+1 - adc #>screen + adc #>screen+$28 sta _9+1 + clc + lda _10 + adc #<screen + sta _10 + lda _10+1 + adc #>screen + sta _10+1 ldy #0 - lda (_8),y - sta (_9),y + lda (_9),y + sta (_10),y inx cpx #$28 bcc b2 @@ -76,15 +76,15 @@ main: { adc line+1 sta _6+1 clc - lda _10 + lda _11 adc #<screen - sta _10 - lda _10+1 + sta _11 + lda _11+1 adc #>screen - sta _10+1 + sta _11+1 lda #' ' ldy #0 - sta (_10),y + sta (_11),y inx cpx #$28 bcc b4 From 999afdcbc725809dca40b77ae6e4d3d7fca75365 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Fri, 24 May 2019 09:02:31 +0200 Subject: [PATCH 85/93] Fixed 2/3. One remaining! --- .../PassNFinalizeNumberTypeConversions.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java index 76b2b33a3..b4f45b8f9 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java @@ -54,9 +54,22 @@ public class PassNFinalizeNumberTypeConversions extends Pass2SsaOptimization { constantCastValue.setToType(smallestUnsigned); } } + } else if(SymbolType.SNUMBER.equals(toType)) { + if(constantCastValue.getValue() instanceof ConstantRef) { + ConstantRef constRef = (ConstantRef) constantCastValue.getValue(); + ConstantVar constant = getScope().getConstant(constRef); + if(constant.isInferredType()) + constant.setTypeInferred(toType); + else + throw new InternalError("Cannot cast declared type!" + constant.toString()); + } else { + ConstantLiteral constantLiteral = constantCastValue.getValue().calculateLiteral(getProgram().getScope()); + SymbolType smallestSigned = SymbolTypeConversion.getSmallestSignedFixedIntegerType(constantLiteral, getScope()); + if(smallestSigned!=null) { + constantCastValue.setToType(smallestSigned); + } + } } - if(SymbolType.SNUMBER.equals(toType)) - throw new InternalError("TODO: Finalize ConstantCast"); } }); return modified.get(); From 3376a462fc80e4cc70c22223dec56a07fcdb47d3 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Fri, 24 May 2019 18:02:42 +0200 Subject: [PATCH 86/93] Fixed number range test --- src/test/kc/invalid-consttype.kc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/kc/invalid-consttype.kc b/src/test/kc/invalid-consttype.kc index 3fcef26c4..fb4c21b72 100644 --- a/src/test/kc/invalid-consttype.kc +++ b/src/test/kc/invalid-consttype.kc @@ -1,5 +1,5 @@ void main() { - signed byte b = -127-127; + signed byte b = -400; byte* SCREEN = $0400; *SCREEN = (byte)b; } \ No newline at end of file From e46fd03ec57bf60923bd7683ba03699beb3806f7 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Fri, 24 May 2019 20:57:43 +0200 Subject: [PATCH 87/93] Added support for string concatenation C style (using simple space separation). Fixed tests. --- .../java/dk/camelot64/kickc/parser/KickC.g4 | 2 +- .../kickc/parser/KickCBaseListener.java | 2 +- .../kickc/parser/KickCBaseVisitor.java | 2 +- .../dk/camelot64/kickc/parser/KickCLexer.java | 2 +- .../camelot64/kickc/parser/KickCListener.java | 2 +- .../camelot64/kickc/parser/KickCParser.java | 773 +++++++++--------- .../camelot64/kickc/parser/KickCVisitor.java | 2 +- .../Pass0GenerateStatementSequence.java | 18 +- .../dk/camelot64/kickc/test/TestPrograms.java | 33 +- src/test/kc/c64dtv-gfxexplorer.kc | 66 +- src/test/kc/c64dtv-gfxmodes.kc | 43 +- src/test/kc/concat-char.kc | 10 - src/test/kc/constant-string-concat-0.kc | 8 + src/test/kc/constant-string-concat.kc | 11 +- src/test/kc/literals.kc | 2 +- src/test/ref/c64dtv-gfxexplorer.asm | 601 +++++++------- src/test/ref/c64dtv-gfxmodes.asm | 94 +-- src/test/ref/concat-char.asm | 16 - src/test/ref/concat-char.cfg | 21 - src/test/ref/concat-char.log | 338 -------- src/test/ref/concat-char.sym | 16 - src/test/ref/constant-string-concat-0.asm | 17 + src/test/ref/constant-string-concat.asm | 7 +- src/test/ref/literals.asm | 2 +- 24 files changed, 848 insertions(+), 1240 deletions(-) delete mode 100644 src/test/kc/concat-char.kc create mode 100644 src/test/kc/constant-string-concat-0.kc delete mode 100644 src/test/ref/concat-char.asm delete mode 100644 src/test/ref/concat-char.cfg delete mode 100644 src/test/ref/concat-char.log delete mode 100644 src/test/ref/concat-char.sym create mode 100644 src/test/ref/constant-string-concat-0.asm diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 index 9c0cbfe03..a30ea0b67 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 +++ b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 @@ -146,7 +146,7 @@ expr | '{' expr (',' expr )* '}' #initList | NAME #exprId | NUMBER #exprNumber - | STRING #exprString + | STRING+ #exprString | CHAR #exprChar | BOOLEAN #exprBool ; diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java index 64996623d..02bba947a 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java @@ -1,4 +1,4 @@ -// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7 +// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7 package dk.camelot64.kickc.parser; import org.antlr.v4.runtime.ParserRuleContext; diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java index 984232061..709766578 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java @@ -1,4 +1,4 @@ -// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7 +// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7 package dk.camelot64.kickc.parser; import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java index 4b9fc4407..951b0e72e 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java @@ -1,4 +1,4 @@ -// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7 +// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7 package dk.camelot64.kickc.parser; import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.CharStream; diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java index aef2c95a7..54517c054 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java @@ -1,4 +1,4 @@ -// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7 +// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7 package dk.camelot64.kickc.parser; import org.antlr.v4.runtime.tree.ParseTreeListener; diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java index 383fd8a0a..807940f33 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java @@ -1,4 +1,4 @@ -// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7 +// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7 package dk.camelot64.kickc.parser; import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.dfa.DFA; @@ -2820,7 +2820,10 @@ public class KickCParser extends Parser { } } public static class ExprStringContext extends ExprContext { - public TerminalNode STRING() { return getToken(KickCParser.STRING, 0); } + public List<TerminalNode> STRING() { return getTokens(KickCParser.STRING); } + public TerminalNode STRING(int i) { + return getToken(KickCParser.STRING, i); + } public ExprStringContext(ExprContext ctx) { copyFrom(ctx); } @Override public void enterRule(ParseTreeListener listener) { @@ -2975,9 +2978,9 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(388); + setState(392); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,37,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,38,_ctx) ) { case 1: { _localctx = new ExprParContext(_localctx); @@ -3185,8 +3188,26 @@ public class KickCParser extends Parser { _localctx = new ExprStringContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(385); - match(STRING); + setState(386); + _errHandler.sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + setState(385); + match(STRING); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(388); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,37,_ctx); + } while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); } break; case 13: @@ -3194,7 +3215,7 @@ public class KickCParser extends Parser { _localctx = new ExprCharContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(386); + setState(390); match(CHAR); } break; @@ -3203,30 +3224,30 @@ public class KickCParser extends Parser { _localctx = new ExprBoolContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(387); + setState(391); match(BOOLEAN); } break; } _ctx.stop = _input.LT(-1); - setState(444); + setState(448); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,40,_ctx); + _alt = getInterpreter().adaptivePredict(_input,41,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(442); + setState(446); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,39,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) { case 1: { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(390); + setState(394); if (!(precpred(_ctx, 19))) throw new FailedPredicateException(this, "precpred(_ctx, 19)"); - setState(391); + setState(395); _la = _input.LA(1); if ( !(_la==T__41 || _la==T__42) ) { _errHandler.recoverInline(this); @@ -3236,7 +3257,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(392); + setState(396); expr(20); } break; @@ -3244,9 +3265,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(393); + setState(397); if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)"); - setState(394); + setState(398); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__29) | (1L << T__43) | (1L << T__44))) != 0)) ) { _errHandler.recoverInline(this); @@ -3256,7 +3277,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(395); + setState(399); expr(19); } break; @@ -3264,9 +3285,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(396); + setState(400); if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)"); - setState(397); + setState(401); _la = _input.LA(1); if ( !(_la==T__36 || _la==T__37) ) { _errHandler.recoverInline(this); @@ -3276,7 +3297,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(398); + setState(402); expr(18); } break; @@ -3284,9 +3305,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(399); + setState(403); if (!(precpred(_ctx, 15))) throw new FailedPredicateException(this, "precpred(_ctx, 15)"); - setState(400); + setState(404); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__45) | (1L << T__46) | (1L << T__47) | (1L << T__48) | (1L << T__49) | (1L << T__50))) != 0)) ) { _errHandler.recoverInline(this); @@ -3296,7 +3317,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(401); + setState(405); expr(16); } break; @@ -3304,13 +3325,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(402); + setState(406); if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)"); { - setState(403); + setState(407); match(T__39); } - setState(404); + setState(408); expr(15); } break; @@ -3318,13 +3339,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(405); + setState(409); if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); { - setState(406); + setState(410); match(T__51); } - setState(407); + setState(411); expr(14); } break; @@ -3332,13 +3353,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(408); + setState(412); if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); { - setState(409); + setState(413); match(T__52); } - setState(410); + setState(414); expr(13); } break; @@ -3346,13 +3367,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(411); + setState(415); if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); { - setState(412); + setState(416); match(T__53); } - setState(413); + setState(417); expr(12); } break; @@ -3360,13 +3381,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(414); + setState(418); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); { - setState(415); + setState(419); match(T__54); } - setState(416); + setState(420); expr(11); } break; @@ -3374,15 +3395,15 @@ public class KickCParser extends Parser { { _localctx = new ExprTernaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(417); - if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(418); - match(T__55); - setState(419); - expr(0); - setState(420); - match(T__25); setState(421); + if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); + setState(422); + match(T__55); + setState(423); + expr(0); + setState(424); + match(T__25); + setState(425); expr(10); } break; @@ -3390,11 +3411,11 @@ public class KickCParser extends Parser { { _localctx = new ExprAssignmentContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(423); + setState(427); if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); - setState(424); + setState(428); match(T__3); - setState(425); + setState(429); expr(8); } break; @@ -3402,9 +3423,9 @@ public class KickCParser extends Parser { { _localctx = new ExprAssignmentCompoundContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(426); + setState(430); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(427); + setState(431); _la = _input.LA(1); if ( !(((((_la - 57)) & ~0x3f) == 0 && ((1L << (_la - 57)) & ((1L << (T__56 - 57)) | (1L << (T__57 - 57)) | (1L << (T__58 - 57)) | (1L << (T__59 - 57)) | (1L << (T__60 - 57)) | (1L << (T__61 - 57)) | (1L << (T__62 - 57)) | (1L << (T__63 - 57)) | (1L << (T__64 - 57)) | (1L << (T__65 - 57)))) != 0)) ) { _errHandler.recoverInline(this); @@ -3414,7 +3435,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(428); + setState(432); expr(7); } break; @@ -3422,21 +3443,21 @@ public class KickCParser extends Parser { { _localctx = new ExprCallContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(429); + setState(433); if (!(precpred(_ctx, 28))) throw new FailedPredicateException(this, "precpred(_ctx, 28)"); - setState(430); + setState(434); match(T__4); - setState(432); + setState(436); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (STRING - 80)) | (1L << (CHAR - 80)) | (1L << (BOOLEAN - 80)) | (1L << (NUMBER - 80)) | (1L << (NAME - 80)))) != 0)) { { - setState(431); + setState(435); parameterList(); } } - setState(434); + setState(438); match(T__5); } break; @@ -3444,13 +3465,13 @@ public class KickCParser extends Parser { { _localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(435); + setState(439); if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)"); - setState(436); + setState(440); match(T__30); - setState(437); + setState(441); commaExpr(0); - setState(438); + setState(442); match(T__31); } break; @@ -3458,9 +3479,9 @@ public class KickCParser extends Parser { { _localctx = new ExprPostModContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(440); + setState(444); if (!(precpred(_ctx, 22))) throw new FailedPredicateException(this, "precpred(_ctx, 22)"); - setState(441); + setState(445); _la = _input.LA(1); if ( !(_la==T__34 || _la==T__35) ) { _errHandler.recoverInline(this); @@ -3475,9 +3496,9 @@ public class KickCParser extends Parser { } } } - setState(446); + setState(450); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,40,_ctx); + _alt = getInterpreter().adaptivePredict(_input,41,_ctx); } } } @@ -3525,21 +3546,21 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(447); + setState(451); expr(0); - setState(452); + setState(456); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(448); + setState(452); match(T__2); - setState(449); + setState(453); expr(0); } } - setState(454); + setState(458); _errHandler.sync(this); _la = _input.LA(1); } @@ -3587,19 +3608,19 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(455); + setState(459); match(T__66); - setState(457); + setState(461); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__4) { { - setState(456); + setState(460); asmDirectives(); } } - setState(459); + setState(463); match(KICKASM); } } @@ -3647,27 +3668,27 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(461); + setState(465); match(T__4); - setState(462); + setState(466); asmDirective(); - setState(467); + setState(471); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(463); + setState(467); match(T__2); - setState(464); + setState(468); asmDirective(); } } - setState(469); + setState(473); _errHandler.sync(this); _la = _input.LA(1); } - setState(470); + setState(474); match(T__5); } } @@ -3806,16 +3827,16 @@ public class KickCParser extends Parser { AsmDirectiveContext _localctx = new AsmDirectiveContext(_ctx, getState()); enterRule(_localctx, 52, RULE_asmDirective); try { - setState(487); + setState(491); _errHandler.sync(this); switch (_input.LA(1)) { case T__67: _localctx = new AsmDirectiveResourceContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(472); + setState(476); match(T__67); - setState(473); + setState(477); match(STRING); } break; @@ -3823,9 +3844,9 @@ public class KickCParser extends Parser { _localctx = new AsmDirectiveUsesContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(474); + setState(478); match(T__68); - setState(475); + setState(479); match(NAME); } break; @@ -3833,9 +3854,9 @@ public class KickCParser extends Parser { _localctx = new AsmDirectiveClobberContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(476); + setState(480); match(T__69); - setState(477); + setState(481); match(STRING); } break; @@ -3843,9 +3864,9 @@ public class KickCParser extends Parser { _localctx = new AsmDirectiveBytesContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(478); + setState(482); match(T__70); - setState(479); + setState(483); expr(0); } break; @@ -3853,9 +3874,9 @@ public class KickCParser extends Parser { _localctx = new AsmDirectiveCyclesContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(480); + setState(484); match(T__71); - setState(481); + setState(485); expr(0); } break; @@ -3863,14 +3884,14 @@ public class KickCParser extends Parser { _localctx = new AsmDirectiveAddressContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(482); + setState(486); match(T__72); - setState(485); + setState(489); _errHandler.sync(this); switch (_input.LA(1)) { case T__12: { - setState(483); + setState(487); match(T__12); } break; @@ -3894,7 +3915,7 @@ public class KickCParser extends Parser { case NUMBER: case NAME: { - setState(484); + setState(488); expr(0); } break; @@ -3951,17 +3972,17 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(492); + setState(496); _errHandler.sync(this); _la = _input.LA(1); while (((((_la - 39)) & ~0x3f) == 0 && ((1L << (_la - 39)) & ((1L << (T__38 - 39)) | (1L << (T__73 - 39)) | (1L << (MNEMONIC - 39)) | (1L << (NAME - 39)))) != 0)) { { { - setState(489); + setState(493); asmLine(); } } - setState(494); + setState(498); _errHandler.sync(this); _la = _input.LA(1); } @@ -4011,28 +4032,28 @@ public class KickCParser extends Parser { AsmLineContext _localctx = new AsmLineContext(_ctx, getState()); enterRule(_localctx, 56, RULE_asmLine); try { - setState(498); + setState(502); _errHandler.sync(this); switch (_input.LA(1)) { case T__38: case NAME: enterOuterAlt(_localctx, 1); { - setState(495); + setState(499); asmLabel(); } break; case MNEMONIC: enterOuterAlt(_localctx, 2); { - setState(496); + setState(500); asmInstruction(); } break; case T__73: enterOuterAlt(_localctx, 3); { - setState(497); + setState(501); asmBytes(); } break; @@ -4102,16 +4123,16 @@ public class KickCParser extends Parser { enterRule(_localctx, 58, RULE_asmLabel); int _la; try { - setState(507); + setState(511); _errHandler.sync(this); switch (_input.LA(1)) { case NAME: _localctx = new AsmLabelNameContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(500); + setState(504); match(NAME); - setState(501); + setState(505); match(T__25); } break; @@ -4119,19 +4140,19 @@ public class KickCParser extends Parser { _localctx = new AsmLabelMultiContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(502); + setState(506); match(T__38); - setState(504); + setState(508); _errHandler.sync(this); _la = _input.LA(1); if (_la==NAME) { { - setState(503); + setState(507); match(NAME); } } - setState(506); + setState(510); match(T__25); } break; @@ -4180,14 +4201,14 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(509); + setState(513); match(MNEMONIC); - setState(511); + setState(515); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,50,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { case 1: { - setState(510); + setState(514); asmParamMode(); } break; @@ -4238,23 +4259,23 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(513); + setState(517); match(T__73); - setState(514); + setState(518); asmExpr(0); - setState(519); + setState(523); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(515); + setState(519); match(T__2); - setState(516); + setState(520); asmExpr(0); } } - setState(521); + setState(525); _errHandler.sync(this); _la = _input.LA(1); } @@ -4404,14 +4425,14 @@ public class KickCParser extends Parser { AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState()); enterRule(_localctx, 64, RULE_asmParamMode); try { - setState(545); + setState(549); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,52,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) { case 1: _localctx = new AsmModeAbsContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(522); + setState(526); asmExpr(0); } break; @@ -4419,9 +4440,9 @@ public class KickCParser extends Parser { _localctx = new AsmModeImmContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(523); + setState(527); match(T__74); - setState(524); + setState(528); asmExpr(0); } break; @@ -4429,11 +4450,11 @@ public class KickCParser extends Parser { _localctx = new AsmModeAbsXYContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(525); + setState(529); asmExpr(0); - setState(526); + setState(530); match(T__2); - setState(527); + setState(531); match(NAME); } break; @@ -4441,15 +4462,15 @@ public class KickCParser extends Parser { _localctx = new AsmModeIndIdxXYContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(529); - match(T__4); - setState(530); - asmExpr(0); - setState(531); - match(T__5); - setState(532); - match(T__2); setState(533); + match(T__4); + setState(534); + asmExpr(0); + setState(535); + match(T__5); + setState(536); + match(T__2); + setState(537); match(NAME); } break; @@ -4457,15 +4478,15 @@ public class KickCParser extends Parser { _localctx = new AsmModeIdxIndXYContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(535); - match(T__4); - setState(536); - asmExpr(0); - setState(537); - match(T__2); - setState(538); - match(NAME); setState(539); + match(T__4); + setState(540); + asmExpr(0); + setState(541); + match(T__2); + setState(542); + match(NAME); + setState(543); match(T__5); } break; @@ -4473,11 +4494,11 @@ public class KickCParser extends Parser { _localctx = new AsmModeIndContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(541); + setState(545); match(T__4); - setState(542); + setState(546); asmExpr(0); - setState(543); + setState(547); match(T__5); } break; @@ -4667,7 +4688,7 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(561); + setState(565); _errHandler.sync(this); switch (_input.LA(1)) { case T__30: @@ -4676,11 +4697,11 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(548); + setState(552); match(T__30); - setState(549); + setState(553); asmExpr(0); - setState(550); + setState(554); match(T__31); } break; @@ -4692,7 +4713,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(552); + setState(556); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__36) | (1L << T__37) | (1L << T__45) | (1L << T__46))) != 0)) ) { _errHandler.recoverInline(this); @@ -4702,7 +4723,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(553); + setState(557); asmExpr(8); } break; @@ -4711,7 +4732,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprLabelContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(554); + setState(558); match(NAME); } break; @@ -4720,7 +4741,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprLabelRelContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(555); + setState(559); match(ASMREL); } break; @@ -4729,11 +4750,11 @@ public class KickCParser extends Parser { _localctx = new AsmExprReplaceContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(556); + setState(560); match(T__6); - setState(557); + setState(561); match(NAME); - setState(558); + setState(562); match(T__7); } break; @@ -4742,7 +4763,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprIntContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(559); + setState(563); match(NUMBER); } break; @@ -4751,7 +4772,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprCharContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(560); + setState(564); match(CHAR); } break; @@ -4759,28 +4780,28 @@ public class KickCParser extends Parser { throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(577); + setState(581); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,55,_ctx); + _alt = getInterpreter().adaptivePredict(_input,56,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(575); + setState(579); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,54,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) { case 1: { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(563); + setState(567); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); { - setState(564); + setState(568); match(T__75); } - setState(565); + setState(569); asmExpr(11); } break; @@ -4788,9 +4809,9 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(566); + setState(570); if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(567); + setState(571); _la = _input.LA(1); if ( !(_la==T__41 || _la==T__42) ) { _errHandler.recoverInline(this); @@ -4800,7 +4821,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(568); + setState(572); asmExpr(10); } break; @@ -4808,9 +4829,9 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(569); + setState(573); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(570); + setState(574); _la = _input.LA(1); if ( !(_la==T__29 || _la==T__43) ) { _errHandler.recoverInline(this); @@ -4820,7 +4841,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(571); + setState(575); asmExpr(8); } break; @@ -4828,9 +4849,9 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(572); + setState(576); if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); - setState(573); + setState(577); _la = _input.LA(1); if ( !(_la==T__36 || _la==T__37) ) { _errHandler.recoverInline(this); @@ -4840,16 +4861,16 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(574); + setState(578); asmExpr(7); } break; } } } - setState(579); + setState(583); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,55,_ctx); + _alt = getInterpreter().adaptivePredict(_input,56,_ctx); } } } @@ -4954,7 +4975,7 @@ public class KickCParser extends Parser { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3b\u0247\4\2\t\2\4"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3b\u024b\4\2\t\2\4"+ "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ "\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -4984,203 +5005,205 @@ public class KickCParser extends Parser { "\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u015e\n\30\3\30\3\30"+ "\3\30\3\30\3\30\3\30\5\30\u0166\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+ "\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u017b"+ - "\n\30\f\30\16\30\u017e\13\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u0187"+ - "\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+ - "\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+ - "\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+ - "\3\30\5\30\u01b3\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u01bd"+ - "\n\30\f\30\16\30\u01c0\13\30\3\31\3\31\3\31\7\31\u01c5\n\31\f\31\16\31"+ - "\u01c8\13\31\3\32\3\32\5\32\u01cc\n\32\3\32\3\32\3\33\3\33\3\33\3\33\7"+ - "\33\u01d4\n\33\f\33\16\33\u01d7\13\33\3\33\3\33\3\34\3\34\3\34\3\34\3"+ - "\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\5\34\u01e8\n\34\5\34\u01ea"+ - "\n\34\3\35\7\35\u01ed\n\35\f\35\16\35\u01f0\13\35\3\36\3\36\3\36\5\36"+ - "\u01f5\n\36\3\37\3\37\3\37\3\37\5\37\u01fb\n\37\3\37\5\37\u01fe\n\37\3"+ - " \3 \5 \u0202\n \3!\3!\3!\3!\7!\u0208\n!\f!\16!\u020b\13!\3\"\3\"\3\""+ - "\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3"+ - "\"\3\"\3\"\5\"\u0224\n\"\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\5#"+ - "\u0234\n#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\7#\u0242\n#\f#\16#\u0245"+ - "\13#\3#\2\7\22*,.D$\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60"+ - "\62\64\668:<>@BD\2\r\3\2\36\37\3\2%&\3\2\'+\3\2\60\61\3\2,-\4\2 ./\3"+ - "\2\'(\3\2\60\65\3\2;D\4\2\'(\60\61\4\2 ..\2\u0299\2F\3\2\2\2\4J\3\2\2"+ - "\2\6P\3\2\2\2\bS\3\2\2\2\nW\3\2\2\2\fa\3\2\2\2\16f\3\2\2\2\20p\3\2\2\2"+ - "\22s\3\2\2\2\24~\3\2\2\2\26\u0083\3\2\2\2\30\u0090\3\2\2\2\32\u009c\3"+ - "\2\2\2\34\u009e\3\2\2\2\36\u00b4\3\2\2\2 \u00b6\3\2\2\2\"\u00c3\3\2\2"+ - "\2$\u0113\3\2\2\2&\u0125\3\2\2\2(\u012b\3\2\2\2*\u0137\3\2\2\2,\u0149"+ - "\3\2\2\2.\u0186\3\2\2\2\60\u01c1\3\2\2\2\62\u01c9\3\2\2\2\64\u01cf\3\2"+ - "\2\2\66\u01e9\3\2\2\28\u01ee\3\2\2\2:\u01f4\3\2\2\2<\u01fd\3\2\2\2>\u01ff"+ - "\3\2\2\2@\u0203\3\2\2\2B\u0223\3\2\2\2D\u0233\3\2\2\2FG\5\6\4\2GH\5\n"+ - "\6\2HI\7\2\2\3I\3\3\2\2\2JK\58\35\2KL\7\2\2\3L\5\3\2\2\2MO\5\b\5\2NM\3"+ - "\2\2\2OR\3\2\2\2PN\3\2\2\2PQ\3\2\2\2Q\7\3\2\2\2RP\3\2\2\2ST\7\3\2\2TU"+ - "\7R\2\2U\t\3\2\2\2VX\5\f\7\2WV\3\2\2\2XY\3\2\2\2YW\3\2\2\2YZ\3\2\2\2Z"+ - "\13\3\2\2\2[\\\5\20\t\2\\]\7\4\2\2]b\3\2\2\2^b\5\26\f\2_b\5\62\32\2`b"+ - "\5\34\17\2a[\3\2\2\2a^\3\2\2\2a_\3\2\2\2a`\3\2\2\2b\r\3\2\2\2ce\5\36\20"+ - "\2dc\3\2\2\2eh\3\2\2\2fd\3\2\2\2fg\3\2\2\2gi\3\2\2\2hf\3\2\2\2im\5*\26"+ - "\2jl\5\36\20\2kj\3\2\2\2lo\3\2\2\2mk\3\2\2\2mn\3\2\2\2n\17\3\2\2\2om\3"+ - "\2\2\2pq\5\16\b\2qr\5\22\n\2r\21\3\2\2\2st\b\n\1\2tu\5\24\13\2u{\3\2\2"+ - "\2vw\f\3\2\2wx\7\5\2\2xz\5\24\13\2yv\3\2\2\2z}\3\2\2\2{y\3\2\2\2{|\3\2"+ - "\2\2|\23\3\2\2\2}{\3\2\2\2~\u0081\7^\2\2\177\u0080\7\6\2\2\u0080\u0082"+ - "\5.\30\2\u0081\177\3\2\2\2\u0081\u0082\3\2\2\2\u0082\25\3\2\2\2\u0083"+ - "\u0084\5\16\b\2\u0084\u0085\7^\2\2\u0085\u0087\7\7\2\2\u0086\u0088\5\30"+ - "\r\2\u0087\u0086\3\2\2\2\u0087\u0088\3\2\2\2\u0088\u0089\3\2\2\2\u0089"+ - "\u008a\7\b\2\2\u008a\u008c\7\t\2\2\u008b\u008d\5\"\22\2\u008c\u008b\3"+ - "\2\2\2\u008c\u008d\3\2\2\2\u008d\u008e\3\2\2\2\u008e\u008f\7\n\2\2\u008f"+ - "\27\3\2\2\2\u0090\u0095\5\32\16\2\u0091\u0092\7\5\2\2\u0092\u0094\5\32"+ - "\16\2\u0093\u0091\3\2\2\2\u0094\u0097\3\2\2\2\u0095\u0093\3\2\2\2\u0095"+ - "\u0096\3\2\2\2\u0096\31\3\2\2\2\u0097\u0095\3\2\2\2\u0098\u0099\5\16\b"+ - "\2\u0099\u009a\7^\2\2\u009a\u009d\3\2\2\2\u009b\u009d\7Q\2\2\u009c\u0098"+ - "\3\2\2\2\u009c\u009b\3\2\2\2\u009d\33\3\2\2\2\u009e\u009f\5 \21\2\u009f"+ - "\u00a0\7\4\2\2\u00a0\35\3\2\2\2\u00a1\u00b5\7\13\2\2\u00a2\u00b5\7\f\2"+ - "\2\u00a3\u00a4\7\r\2\2\u00a4\u00a5\7\7\2\2\u00a5\u00a6\7U\2\2\u00a6\u00b5"+ - "\7\b\2\2\u00a7\u00a8\7\16\2\2\u00a8\u00a9\7\7\2\2\u00a9\u00aa\7^\2\2\u00aa"+ - "\u00b5\7\b\2\2\u00ab\u00b5\7\17\2\2\u00ac\u00b5\7\20\2\2\u00ad\u00b1\7"+ - "\21\2\2\u00ae\u00af\7\7\2\2\u00af\u00b0\7^\2\2\u00b0\u00b2\7\b\2\2\u00b1"+ - "\u00ae\3\2\2\2\u00b1\u00b2\3\2\2\2\u00b2\u00b5\3\2\2\2\u00b3\u00b5\5 "+ - "\21\2\u00b4\u00a1\3\2\2\2\u00b4\u00a2\3\2\2\2\u00b4\u00a3\3\2\2\2\u00b4"+ - "\u00a7\3\2\2\2\u00b4\u00ab\3\2\2\2\u00b4\u00ac\3\2\2\2\u00b4\u00ad\3\2"+ - "\2\2\u00b4\u00b3\3\2\2\2\u00b5\37\3\2\2\2\u00b6\u00b7\7\22\2\2\u00b7\u00b8"+ - "\7\7\2\2\u00b8\u00bd\7U\2\2\u00b9\u00ba\7\5\2\2\u00ba\u00bc\7U\2\2\u00bb"+ - "\u00b9\3\2\2\2\u00bc\u00bf\3\2\2\2\u00bd\u00bb\3\2\2\2\u00bd\u00be\3\2"+ - "\2\2\u00be\u00c0\3\2\2\2\u00bf\u00bd\3\2\2\2\u00c0\u00c1\7\b\2\2\u00c1"+ - "!\3\2\2\2\u00c2\u00c4\5$\23\2\u00c3\u00c2\3\2\2\2\u00c4\u00c5\3\2\2\2"+ - "\u00c5\u00c3\3\2\2\2\u00c5\u00c6\3\2\2\2\u00c6#\3\2\2\2\u00c7\u00c8\5"+ - "\20\t\2\u00c8\u00c9\7\4\2\2\u00c9\u0114\3\2\2\2\u00ca\u00cc\7\t\2\2\u00cb"+ - "\u00cd\5\"\22\2\u00cc\u00cb\3\2\2\2\u00cc\u00cd\3\2\2\2\u00cd\u00ce\3"+ - "\2\2\2\u00ce\u0114\7\n\2\2\u00cf\u00d0\5,\27\2\u00d0\u00d1\7\4\2\2\u00d1"+ - "\u0114\3\2\2\2\u00d2\u00d3\7\23\2\2\u00d3\u00d4\7\7\2\2\u00d4\u00d5\5"+ - ",\27\2\u00d5\u00d6\7\b\2\2\u00d6\u00d9\5$\23\2\u00d7\u00d8\7\24\2\2\u00d8"+ - "\u00da\5$\23\2\u00d9\u00d7\3\2\2\2\u00d9\u00da\3\2\2\2\u00da\u0114\3\2"+ - "\2\2\u00db\u00dd\5\36\20\2\u00dc\u00db\3\2\2\2\u00dd\u00e0\3\2\2\2\u00de"+ - "\u00dc\3\2\2\2\u00de\u00df\3\2\2\2\u00df\u00e1\3\2\2\2\u00e0\u00de\3\2"+ - "\2\2\u00e1\u00e2\7\25\2\2\u00e2\u00e3\7\7\2\2\u00e3\u00e4\5,\27\2\u00e4"+ - "\u00e5\7\b\2\2\u00e5\u00e6\5$\23\2\u00e6\u0114\3\2\2\2\u00e7\u00e9\5\36"+ - "\20\2\u00e8\u00e7\3\2\2\2\u00e9\u00ec\3\2\2\2\u00ea\u00e8\3\2\2\2\u00ea"+ - "\u00eb\3\2\2\2\u00eb\u00ed\3\2\2\2\u00ec\u00ea\3\2\2\2\u00ed\u00ee\7\26"+ - "\2\2\u00ee\u00ef\5$\23\2\u00ef\u00f0\7\25\2\2\u00f0\u00f1\7\7\2\2\u00f1"+ - "\u00f2\5,\27\2\u00f2\u00f3\7\b\2\2\u00f3\u00f4\7\4\2\2\u00f4\u0114\3\2"+ - "\2\2\u00f5\u00f7\5\36\20\2\u00f6\u00f5\3\2\2\2\u00f7\u00fa\3\2\2\2\u00f8"+ - "\u00f6\3\2\2\2\u00f8\u00f9\3\2\2\2\u00f9\u00fb\3\2\2\2\u00fa\u00f8\3\2"+ - "\2\2\u00fb\u00fc\7\27\2\2\u00fc\u00fd\7\7\2\2\u00fd\u00fe\5&\24\2\u00fe"+ - "\u00ff\7\b\2\2\u00ff\u0100\5$\23\2\u0100\u0114\3\2\2\2\u0101\u0103\7\30"+ - "\2\2\u0102\u0104\5,\27\2\u0103\u0102\3\2\2\2\u0103\u0104\3\2\2\2\u0104"+ - "\u0105\3\2\2\2\u0105\u0114\7\4\2\2\u0106\u0107\7\31\2\2\u0107\u0114\7"+ - "\4\2\2\u0108\u0109\7\32\2\2\u0109\u0114\7\4\2\2\u010a\u010c\7\33\2\2\u010b"+ - "\u010d\5\64\33\2\u010c\u010b\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3"+ - "\2\2\2\u010e\u010f\7\t\2\2\u010f\u0110\58\35\2\u0110\u0111\7\n\2\2\u0111"+ - "\u0114\3\2\2\2\u0112\u0114\5\62\32\2\u0113\u00c7\3\2\2\2\u0113\u00ca\3"+ - "\2\2\2\u0113\u00cf\3\2\2\2\u0113\u00d2\3\2\2\2\u0113\u00de\3\2\2\2\u0113"+ - "\u00ea\3\2\2\2\u0113\u00f8\3\2\2\2\u0113\u0101\3\2\2\2\u0113\u0106\3\2"+ - "\2\2\u0113\u0108\3\2\2\2\u0113\u010a\3\2\2\2\u0113\u0112\3\2\2\2\u0114"+ - "%\3\2\2\2\u0115\u0116\5(\25\2\u0116\u0117\7\4\2\2\u0117\u0118\5,\27\2"+ - "\u0118\u011a\7\4\2\2\u0119\u011b\5,\27\2\u011a\u0119\3\2\2\2\u011a\u011b"+ - "\3\2\2\2\u011b\u0126\3\2\2\2\u011c\u011e\5\16\b\2\u011d\u011c\3\2\2\2"+ - "\u011d\u011e\3\2\2\2\u011e\u011f\3\2\2\2\u011f\u0120\7^\2\2\u0120\u0121"+ - "\7\34\2\2\u0121\u0122\5.\30\2\u0122\u0123\7\35\2\2\u0123\u0124\5.\30\2"+ - "\u0124\u0126\3\2\2\2\u0125\u0115\3\2\2\2\u0125\u011d\3\2\2\2\u0126\'\3"+ - "\2\2\2\u0127\u0129\5\20\t\2\u0128\u0127\3\2\2\2\u0128\u0129\3\2\2\2\u0129"+ - "\u012c\3\2\2\2\u012a\u012c\5,\27\2\u012b\u0128\3\2\2\2\u012b\u012a\3\2"+ - "\2\2\u012c)\3\2\2\2\u012d\u012e\b\26\1\2\u012e\u012f\7\7\2\2\u012f\u0130"+ - "\5*\26\2\u0130\u0131\7\b\2\2\u0131\u0138\3\2\2\2\u0132\u0138\7Q\2\2\u0133"+ - "\u0135\t\2\2\2\u0134\u0136\7Q\2\2\u0135\u0134\3\2\2\2\u0135\u0136\3\2"+ - "\2\2\u0136\u0138\3\2\2\2\u0137\u012d\3\2\2\2\u0137\u0132\3\2\2\2\u0137"+ - "\u0133\3\2\2\2\u0138\u0146\3\2\2\2\u0139\u013a\f\5\2\2\u013a\u0145\7 "+ - "\2\2\u013b\u013c\f\4\2\2\u013c\u013e\7!\2\2\u013d\u013f\5.\30\2\u013e"+ - "\u013d\3\2\2\2\u013e\u013f\3\2\2\2\u013f\u0140\3\2\2\2\u0140\u0145\7\""+ - "\2\2\u0141\u0142\f\3\2\2\u0142\u0143\7\7\2\2\u0143\u0145\7\b\2\2\u0144"+ - "\u0139\3\2\2\2\u0144\u013b\3\2\2\2\u0144\u0141\3\2\2\2\u0145\u0148\3\2"+ - "\2\2\u0146\u0144\3\2\2\2\u0146\u0147\3\2\2\2\u0147+\3\2\2\2\u0148\u0146"+ - "\3\2\2\2\u0149\u014a\b\27\1\2\u014a\u014b\5.\30\2\u014b\u0151\3\2\2\2"+ - "\u014c\u014d\f\3\2\2\u014d\u014e\7\5\2\2\u014e\u0150\5.\30\2\u014f\u014c"+ - "\3\2\2\2\u0150\u0153\3\2\2\2\u0151\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152"+ - "-\3\2\2\2\u0153\u0151\3\2\2\2\u0154\u0155\b\30\1\2\u0155\u0156\7\7\2\2"+ - "\u0156\u0157\5,\27\2\u0157\u0158\7\b\2\2\u0158\u0187\3\2\2\2\u0159\u015a"+ - "\7#\2\2\u015a\u015d\7\7\2\2\u015b\u015e\5*\26\2\u015c\u015e\5.\30\2\u015d"+ - "\u015b\3\2\2\2\u015d\u015c\3\2\2\2\u015e\u015f\3\2\2\2\u015f\u0160\7\b"+ - "\2\2\u0160\u0187\3\2\2\2\u0161\u0162\7$\2\2\u0162\u0165\7\7\2\2\u0163"+ - "\u0166\5*\26\2\u0164\u0166\5.\30\2\u0165\u0163\3\2\2\2\u0165\u0164\3\2"+ - "\2\2\u0166\u0167\3\2\2\2\u0167\u0168\7\b\2\2\u0168\u0187\3\2\2\2\u0169"+ - "\u016a\7\7\2\2\u016a\u016b\5*\26\2\u016b\u016c\7\b\2\2\u016c\u016d\5."+ - "\30\32\u016d\u0187\3\2\2\2\u016e\u016f\t\3\2\2\u016f\u0187\5.\30\31\u0170"+ - "\u0171\7 \2\2\u0171\u0187\5.\30\27\u0172\u0173\t\4\2\2\u0173\u0187\5."+ - "\30\26\u0174\u0175\t\5\2\2\u0175\u0187\5.\30\22\u0176\u0177\7\t\2\2\u0177"+ - "\u017c\5.\30\2\u0178\u0179\7\5\2\2\u0179\u017b\5.\30\2\u017a\u0178\3\2"+ - "\2\2\u017b\u017e\3\2\2\2\u017c\u017a\3\2\2\2\u017c\u017d\3\2\2\2\u017d"+ - "\u017f\3\2\2\2\u017e\u017c\3\2\2\2\u017f\u0180\7\n\2\2\u0180\u0187\3\2"+ - "\2\2\u0181\u0187\7^\2\2\u0182\u0187\7U\2\2\u0183\u0187\7R\2\2\u0184\u0187"+ - "\7S\2\2\u0185\u0187\7T\2\2\u0186\u0154\3\2\2\2\u0186\u0159\3\2\2\2\u0186"+ - "\u0161\3\2\2\2\u0186\u0169\3\2\2\2\u0186\u016e\3\2\2\2\u0186\u0170\3\2"+ - "\2\2\u0186\u0172\3\2\2\2\u0186\u0174\3\2\2\2\u0186\u0176\3\2\2\2\u0186"+ - "\u0181\3\2\2\2\u0186\u0182\3\2\2\2\u0186\u0183\3\2\2\2\u0186\u0184\3\2"+ - "\2\2\u0186\u0185\3\2\2\2\u0187\u01be\3\2\2\2\u0188\u0189\f\25\2\2\u0189"+ - "\u018a\t\6\2\2\u018a\u01bd\5.\30\26\u018b\u018c\f\24\2\2\u018c\u018d\t"+ - "\7\2\2\u018d\u01bd\5.\30\25\u018e\u018f\f\23\2\2\u018f\u0190\t\b\2\2\u0190"+ - "\u01bd\5.\30\24\u0191\u0192\f\21\2\2\u0192\u0193\t\t\2\2\u0193\u01bd\5"+ - ".\30\22\u0194\u0195\f\20\2\2\u0195\u0196\7*\2\2\u0196\u01bd\5.\30\21\u0197"+ - "\u0198\f\17\2\2\u0198\u0199\7\66\2\2\u0199\u01bd\5.\30\20\u019a\u019b"+ - "\f\16\2\2\u019b\u019c\7\67\2\2\u019c\u01bd\5.\30\17\u019d\u019e\f\r\2"+ - "\2\u019e\u019f\78\2\2\u019f\u01bd\5.\30\16\u01a0\u01a1\f\f\2\2\u01a1\u01a2"+ - "\79\2\2\u01a2\u01bd\5.\30\r\u01a3\u01a4\f\13\2\2\u01a4\u01a5\7:\2\2\u01a5"+ - "\u01a6\5.\30\2\u01a6\u01a7\7\34\2\2\u01a7\u01a8\5.\30\f\u01a8\u01bd\3"+ - "\2\2\2\u01a9\u01aa\f\n\2\2\u01aa\u01ab\7\6\2\2\u01ab\u01bd\5.\30\n\u01ac"+ - "\u01ad\f\t\2\2\u01ad\u01ae\t\n\2\2\u01ae\u01bd\5.\30\t\u01af\u01b0\f\36"+ - "\2\2\u01b0\u01b2\7\7\2\2\u01b1\u01b3\5\60\31\2\u01b2\u01b1\3\2\2\2\u01b2"+ - "\u01b3\3\2\2\2\u01b3\u01b4\3\2\2\2\u01b4\u01bd\7\b\2\2\u01b5\u01b6\f\33"+ - "\2\2\u01b6\u01b7\7!\2\2\u01b7\u01b8\5,\27\2\u01b8\u01b9\7\"\2\2\u01b9"+ - "\u01bd\3\2\2\2\u01ba\u01bb\f\30\2\2\u01bb\u01bd\t\3\2\2\u01bc\u0188\3"+ - "\2\2\2\u01bc\u018b\3\2\2\2\u01bc\u018e\3\2\2\2\u01bc\u0191\3\2\2\2\u01bc"+ - "\u0194\3\2\2\2\u01bc\u0197\3\2\2\2\u01bc\u019a\3\2\2\2\u01bc\u019d\3\2"+ - "\2\2\u01bc\u01a0\3\2\2\2\u01bc\u01a3\3\2\2\2\u01bc\u01a9\3\2\2\2\u01bc"+ - "\u01ac\3\2\2\2\u01bc\u01af\3\2\2\2\u01bc\u01b5\3\2\2\2\u01bc\u01ba\3\2"+ - "\2\2\u01bd\u01c0\3\2\2\2\u01be\u01bc\3\2\2\2\u01be\u01bf\3\2\2\2\u01bf"+ - "/\3\2\2\2\u01c0\u01be\3\2\2\2\u01c1\u01c6\5.\30\2\u01c2\u01c3\7\5\2\2"+ - "\u01c3\u01c5\5.\30\2\u01c4\u01c2\3\2\2\2\u01c5\u01c8\3\2\2\2\u01c6\u01c4"+ - "\3\2\2\2\u01c6\u01c7\3\2\2\2\u01c7\61\3\2\2\2\u01c8\u01c6\3\2\2\2\u01c9"+ - "\u01cb\7E\2\2\u01ca\u01cc\5\64\33\2\u01cb\u01ca\3\2\2\2\u01cb\u01cc\3"+ - "\2\2\2\u01cc\u01cd\3\2\2\2\u01cd\u01ce\7P\2\2\u01ce\63\3\2\2\2\u01cf\u01d0"+ - "\7\7\2\2\u01d0\u01d5\5\66\34\2\u01d1\u01d2\7\5\2\2\u01d2\u01d4\5\66\34"+ - "\2\u01d3\u01d1\3\2\2\2\u01d4\u01d7\3\2\2\2\u01d5\u01d3\3\2\2\2\u01d5\u01d6"+ - "\3\2\2\2\u01d6\u01d8\3\2\2\2\u01d7\u01d5\3\2\2\2\u01d8\u01d9\7\b\2\2\u01d9"+ - "\65\3\2\2\2\u01da\u01db\7F\2\2\u01db\u01ea\7R\2\2\u01dc\u01dd\7G\2\2\u01dd"+ - "\u01ea\7^\2\2\u01de\u01df\7H\2\2\u01df\u01ea\7R\2\2\u01e0\u01e1\7I\2\2"+ - "\u01e1\u01ea\5.\30\2\u01e2\u01e3\7J\2\2\u01e3\u01ea\5.\30\2\u01e4\u01e7"+ - "\7K\2\2\u01e5\u01e8\7\17\2\2\u01e6\u01e8\5.\30\2\u01e7\u01e5\3\2\2\2\u01e7"+ - "\u01e6\3\2\2\2\u01e8\u01ea\3\2\2\2\u01e9\u01da\3\2\2\2\u01e9\u01dc\3\2"+ - "\2\2\u01e9\u01de\3\2\2\2\u01e9\u01e0\3\2\2\2\u01e9\u01e2\3\2\2\2\u01e9"+ - "\u01e4\3\2\2\2\u01ea\67\3\2\2\2\u01eb\u01ed\5:\36\2\u01ec\u01eb\3\2\2"+ - "\2\u01ed\u01f0\3\2\2\2\u01ee\u01ec\3\2\2\2\u01ee\u01ef\3\2\2\2\u01ef9"+ - "\3\2\2\2\u01f0\u01ee\3\2\2\2\u01f1\u01f5\5<\37\2\u01f2\u01f5\5> \2\u01f3"+ - "\u01f5\5@!\2\u01f4\u01f1\3\2\2\2\u01f4\u01f2\3\2\2\2\u01f4\u01f3\3\2\2"+ - "\2\u01f5;\3\2\2\2\u01f6\u01f7\7^\2\2\u01f7\u01fe\7\34\2\2\u01f8\u01fa"+ - "\7)\2\2\u01f9\u01fb\7^\2\2\u01fa\u01f9\3\2\2\2\u01fa\u01fb\3\2\2\2\u01fb"+ - "\u01fc\3\2\2\2\u01fc\u01fe\7\34\2\2\u01fd\u01f6\3\2\2\2\u01fd\u01f8\3"+ - "\2\2\2\u01fe=\3\2\2\2\u01ff\u0201\7O\2\2\u0200\u0202\5B\"\2\u0201\u0200"+ - "\3\2\2\2\u0201\u0202\3\2\2\2\u0202?\3\2\2\2\u0203\u0204\7L\2\2\u0204\u0209"+ - "\5D#\2\u0205\u0206\7\5\2\2\u0206\u0208\5D#\2\u0207\u0205\3\2\2\2\u0208"+ - "\u020b\3\2\2\2\u0209\u0207\3\2\2\2\u0209\u020a\3\2\2\2\u020aA\3\2\2\2"+ - "\u020b\u0209\3\2\2\2\u020c\u0224\5D#\2\u020d\u020e\7M\2\2\u020e\u0224"+ - "\5D#\2\u020f\u0210\5D#\2\u0210\u0211\7\5\2\2\u0211\u0212\7^\2\2\u0212"+ - "\u0224\3\2\2\2\u0213\u0214\7\7\2\2\u0214\u0215\5D#\2\u0215\u0216\7\b\2"+ - "\2\u0216\u0217\7\5\2\2\u0217\u0218\7^\2\2\u0218\u0224\3\2\2\2\u0219\u021a"+ - "\7\7\2\2\u021a\u021b\5D#\2\u021b\u021c\7\5\2\2\u021c\u021d\7^\2\2\u021d"+ - "\u021e\7\b\2\2\u021e\u0224\3\2\2\2\u021f\u0220\7\7\2\2\u0220\u0221\5D"+ - "#\2\u0221\u0222\7\b\2\2\u0222\u0224\3\2\2\2\u0223\u020c\3\2\2\2\u0223"+ - "\u020d\3\2\2\2\u0223\u020f\3\2\2\2\u0223\u0213\3\2\2\2\u0223\u0219\3\2"+ - "\2\2\u0223\u021f\3\2\2\2\u0224C\3\2\2\2\u0225\u0226\b#\1\2\u0226\u0227"+ - "\7!\2\2\u0227\u0228\5D#\2\u0228\u0229\7\"\2\2\u0229\u0234\3\2\2\2\u022a"+ - "\u022b\t\13\2\2\u022b\u0234\5D#\n\u022c\u0234\7^\2\2\u022d\u0234\7_\2"+ - "\2\u022e\u022f\7\t\2\2\u022f\u0230\7^\2\2\u0230\u0234\7\n\2\2\u0231\u0234"+ - "\7U\2\2\u0232\u0234\7S\2\2\u0233\u0225\3\2\2\2\u0233\u022a\3\2\2\2\u0233"+ - "\u022c\3\2\2\2\u0233\u022d\3\2\2\2\u0233\u022e\3\2\2\2\u0233\u0231\3\2"+ - "\2\2\u0233\u0232\3\2\2\2\u0234\u0243\3\2\2\2\u0235\u0236\f\f\2\2\u0236"+ - "\u0237\7N\2\2\u0237\u0242\5D#\r\u0238\u0239\f\13\2\2\u0239\u023a\t\6\2"+ - "\2\u023a\u0242\5D#\f\u023b\u023c\f\t\2\2\u023c\u023d\t\f\2\2\u023d\u0242"+ - "\5D#\n\u023e\u023f\f\b\2\2\u023f\u0240\t\b\2\2\u0240\u0242\5D#\t\u0241"+ - "\u0235\3\2\2\2\u0241\u0238\3\2\2\2\u0241\u023b\3\2\2\2\u0241\u023e\3\2"+ - "\2\2\u0242\u0245\3\2\2\2\u0243\u0241\3\2\2\2\u0243\u0244\3\2\2\2\u0244"+ - "E\3\2\2\2\u0245\u0243\3\2\2\2:PYafm{\u0081\u0087\u008c\u0095\u009c\u00b1"+ + "\n\30\f\30\16\30\u017e\13\30\3\30\3\30\3\30\3\30\3\30\6\30\u0185\n\30"+ + "\r\30\16\30\u0186\3\30\3\30\5\30\u018b\n\30\3\30\3\30\3\30\3\30\3\30\3"+ + "\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3"+ + "\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3"+ + "\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u01b7\n\30\3\30\3\30"+ + "\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u01c1\n\30\f\30\16\30\u01c4\13\30"+ + "\3\31\3\31\3\31\7\31\u01c9\n\31\f\31\16\31\u01cc\13\31\3\32\3\32\5\32"+ + "\u01d0\n\32\3\32\3\32\3\33\3\33\3\33\3\33\7\33\u01d8\n\33\f\33\16\33\u01db"+ + "\13\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34"+ + "\3\34\3\34\5\34\u01ec\n\34\5\34\u01ee\n\34\3\35\7\35\u01f1\n\35\f\35\16"+ + "\35\u01f4\13\35\3\36\3\36\3\36\5\36\u01f9\n\36\3\37\3\37\3\37\3\37\5\37"+ + "\u01ff\n\37\3\37\5\37\u0202\n\37\3 \3 \5 \u0206\n \3!\3!\3!\3!\7!\u020c"+ + "\n!\f!\16!\u020f\13!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3"+ + "\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\5\"\u0228\n\"\3#\3#\3#\3#\3"+ + "#\3#\3#\3#\3#\3#\3#\3#\3#\3#\5#\u0238\n#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3"+ + "#\3#\3#\7#\u0246\n#\f#\16#\u0249\13#\3#\2\7\22*,.D$\2\4\6\b\n\f\16\20"+ + "\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BD\2\r\3\2\36\37\3\2%&"+ + "\3\2\'+\3\2\60\61\3\2,-\4\2 ./\3\2\'(\3\2\60\65\3\2;D\4\2\'(\60\61\4"+ + "\2 ..\2\u029e\2F\3\2\2\2\4J\3\2\2\2\6P\3\2\2\2\bS\3\2\2\2\nW\3\2\2\2"+ + "\fa\3\2\2\2\16f\3\2\2\2\20p\3\2\2\2\22s\3\2\2\2\24~\3\2\2\2\26\u0083\3"+ + "\2\2\2\30\u0090\3\2\2\2\32\u009c\3\2\2\2\34\u009e\3\2\2\2\36\u00b4\3\2"+ + "\2\2 \u00b6\3\2\2\2\"\u00c3\3\2\2\2$\u0113\3\2\2\2&\u0125\3\2\2\2(\u012b"+ + "\3\2\2\2*\u0137\3\2\2\2,\u0149\3\2\2\2.\u018a\3\2\2\2\60\u01c5\3\2\2\2"+ + "\62\u01cd\3\2\2\2\64\u01d3\3\2\2\2\66\u01ed\3\2\2\28\u01f2\3\2\2\2:\u01f8"+ + "\3\2\2\2<\u0201\3\2\2\2>\u0203\3\2\2\2@\u0207\3\2\2\2B\u0227\3\2\2\2D"+ + "\u0237\3\2\2\2FG\5\6\4\2GH\5\n\6\2HI\7\2\2\3I\3\3\2\2\2JK\58\35\2KL\7"+ + "\2\2\3L\5\3\2\2\2MO\5\b\5\2NM\3\2\2\2OR\3\2\2\2PN\3\2\2\2PQ\3\2\2\2Q\7"+ + "\3\2\2\2RP\3\2\2\2ST\7\3\2\2TU\7R\2\2U\t\3\2\2\2VX\5\f\7\2WV\3\2\2\2X"+ + "Y\3\2\2\2YW\3\2\2\2YZ\3\2\2\2Z\13\3\2\2\2[\\\5\20\t\2\\]\7\4\2\2]b\3\2"+ + "\2\2^b\5\26\f\2_b\5\62\32\2`b\5\34\17\2a[\3\2\2\2a^\3\2\2\2a_\3\2\2\2"+ + "a`\3\2\2\2b\r\3\2\2\2ce\5\36\20\2dc\3\2\2\2eh\3\2\2\2fd\3\2\2\2fg\3\2"+ + "\2\2gi\3\2\2\2hf\3\2\2\2im\5*\26\2jl\5\36\20\2kj\3\2\2\2lo\3\2\2\2mk\3"+ + "\2\2\2mn\3\2\2\2n\17\3\2\2\2om\3\2\2\2pq\5\16\b\2qr\5\22\n\2r\21\3\2\2"+ + "\2st\b\n\1\2tu\5\24\13\2u{\3\2\2\2vw\f\3\2\2wx\7\5\2\2xz\5\24\13\2yv\3"+ + "\2\2\2z}\3\2\2\2{y\3\2\2\2{|\3\2\2\2|\23\3\2\2\2}{\3\2\2\2~\u0081\7^\2"+ + "\2\177\u0080\7\6\2\2\u0080\u0082\5.\30\2\u0081\177\3\2\2\2\u0081\u0082"+ + "\3\2\2\2\u0082\25\3\2\2\2\u0083\u0084\5\16\b\2\u0084\u0085\7^\2\2\u0085"+ + "\u0087\7\7\2\2\u0086\u0088\5\30\r\2\u0087\u0086\3\2\2\2\u0087\u0088\3"+ + "\2\2\2\u0088\u0089\3\2\2\2\u0089\u008a\7\b\2\2\u008a\u008c\7\t\2\2\u008b"+ + "\u008d\5\"\22\2\u008c\u008b\3\2\2\2\u008c\u008d\3\2\2\2\u008d\u008e\3"+ + "\2\2\2\u008e\u008f\7\n\2\2\u008f\27\3\2\2\2\u0090\u0095\5\32\16\2\u0091"+ + "\u0092\7\5\2\2\u0092\u0094\5\32\16\2\u0093\u0091\3\2\2\2\u0094\u0097\3"+ + "\2\2\2\u0095\u0093\3\2\2\2\u0095\u0096\3\2\2\2\u0096\31\3\2\2\2\u0097"+ + "\u0095\3\2\2\2\u0098\u0099\5\16\b\2\u0099\u009a\7^\2\2\u009a\u009d\3\2"+ + "\2\2\u009b\u009d\7Q\2\2\u009c\u0098\3\2\2\2\u009c\u009b\3\2\2\2\u009d"+ + "\33\3\2\2\2\u009e\u009f\5 \21\2\u009f\u00a0\7\4\2\2\u00a0\35\3\2\2\2\u00a1"+ + "\u00b5\7\13\2\2\u00a2\u00b5\7\f\2\2\u00a3\u00a4\7\r\2\2\u00a4\u00a5\7"+ + "\7\2\2\u00a5\u00a6\7U\2\2\u00a6\u00b5\7\b\2\2\u00a7\u00a8\7\16\2\2\u00a8"+ + "\u00a9\7\7\2\2\u00a9\u00aa\7^\2\2\u00aa\u00b5\7\b\2\2\u00ab\u00b5\7\17"+ + "\2\2\u00ac\u00b5\7\20\2\2\u00ad\u00b1\7\21\2\2\u00ae\u00af\7\7\2\2\u00af"+ + "\u00b0\7^\2\2\u00b0\u00b2\7\b\2\2\u00b1\u00ae\3\2\2\2\u00b1\u00b2\3\2"+ + "\2\2\u00b2\u00b5\3\2\2\2\u00b3\u00b5\5 \21\2\u00b4\u00a1\3\2\2\2\u00b4"+ + "\u00a2\3\2\2\2\u00b4\u00a3\3\2\2\2\u00b4\u00a7\3\2\2\2\u00b4\u00ab\3\2"+ + "\2\2\u00b4\u00ac\3\2\2\2\u00b4\u00ad\3\2\2\2\u00b4\u00b3\3\2\2\2\u00b5"+ + "\37\3\2\2\2\u00b6\u00b7\7\22\2\2\u00b7\u00b8\7\7\2\2\u00b8\u00bd\7U\2"+ + "\2\u00b9\u00ba\7\5\2\2\u00ba\u00bc\7U\2\2\u00bb\u00b9\3\2\2\2\u00bc\u00bf"+ + "\3\2\2\2\u00bd\u00bb\3\2\2\2\u00bd\u00be\3\2\2\2\u00be\u00c0\3\2\2\2\u00bf"+ + "\u00bd\3\2\2\2\u00c0\u00c1\7\b\2\2\u00c1!\3\2\2\2\u00c2\u00c4\5$\23\2"+ + "\u00c3\u00c2\3\2\2\2\u00c4\u00c5\3\2\2\2\u00c5\u00c3\3\2\2\2\u00c5\u00c6"+ + "\3\2\2\2\u00c6#\3\2\2\2\u00c7\u00c8\5\20\t\2\u00c8\u00c9\7\4\2\2\u00c9"+ + "\u0114\3\2\2\2\u00ca\u00cc\7\t\2\2\u00cb\u00cd\5\"\22\2\u00cc\u00cb\3"+ + "\2\2\2\u00cc\u00cd\3\2\2\2\u00cd\u00ce\3\2\2\2\u00ce\u0114\7\n\2\2\u00cf"+ + "\u00d0\5,\27\2\u00d0\u00d1\7\4\2\2\u00d1\u0114\3\2\2\2\u00d2\u00d3\7\23"+ + "\2\2\u00d3\u00d4\7\7\2\2\u00d4\u00d5\5,\27\2\u00d5\u00d6\7\b\2\2\u00d6"+ + "\u00d9\5$\23\2\u00d7\u00d8\7\24\2\2\u00d8\u00da\5$\23\2\u00d9\u00d7\3"+ + "\2\2\2\u00d9\u00da\3\2\2\2\u00da\u0114\3\2\2\2\u00db\u00dd\5\36\20\2\u00dc"+ + "\u00db\3\2\2\2\u00dd\u00e0\3\2\2\2\u00de\u00dc\3\2\2\2\u00de\u00df\3\2"+ + "\2\2\u00df\u00e1\3\2\2\2\u00e0\u00de\3\2\2\2\u00e1\u00e2\7\25\2\2\u00e2"+ + "\u00e3\7\7\2\2\u00e3\u00e4\5,\27\2\u00e4\u00e5\7\b\2\2\u00e5\u00e6\5$"+ + "\23\2\u00e6\u0114\3\2\2\2\u00e7\u00e9\5\36\20\2\u00e8\u00e7\3\2\2\2\u00e9"+ + "\u00ec\3\2\2\2\u00ea\u00e8\3\2\2\2\u00ea\u00eb\3\2\2\2\u00eb\u00ed\3\2"+ + "\2\2\u00ec\u00ea\3\2\2\2\u00ed\u00ee\7\26\2\2\u00ee\u00ef\5$\23\2\u00ef"+ + "\u00f0\7\25\2\2\u00f0\u00f1\7\7\2\2\u00f1\u00f2\5,\27\2\u00f2\u00f3\7"+ + "\b\2\2\u00f3\u00f4\7\4\2\2\u00f4\u0114\3\2\2\2\u00f5\u00f7\5\36\20\2\u00f6"+ + "\u00f5\3\2\2\2\u00f7\u00fa\3\2\2\2\u00f8\u00f6\3\2\2\2\u00f8\u00f9\3\2"+ + "\2\2\u00f9\u00fb\3\2\2\2\u00fa\u00f8\3\2\2\2\u00fb\u00fc\7\27\2\2\u00fc"+ + "\u00fd\7\7\2\2\u00fd\u00fe\5&\24\2\u00fe\u00ff\7\b\2\2\u00ff\u0100\5$"+ + "\23\2\u0100\u0114\3\2\2\2\u0101\u0103\7\30\2\2\u0102\u0104\5,\27\2\u0103"+ + "\u0102\3\2\2\2\u0103\u0104\3\2\2\2\u0104\u0105\3\2\2\2\u0105\u0114\7\4"+ + "\2\2\u0106\u0107\7\31\2\2\u0107\u0114\7\4\2\2\u0108\u0109\7\32\2\2\u0109"+ + "\u0114\7\4\2\2\u010a\u010c\7\33\2\2\u010b\u010d\5\64\33\2\u010c\u010b"+ + "\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3\2\2\2\u010e\u010f\7\t\2\2\u010f"+ + "\u0110\58\35\2\u0110\u0111\7\n\2\2\u0111\u0114\3\2\2\2\u0112\u0114\5\62"+ + "\32\2\u0113\u00c7\3\2\2\2\u0113\u00ca\3\2\2\2\u0113\u00cf\3\2\2\2\u0113"+ + "\u00d2\3\2\2\2\u0113\u00de\3\2\2\2\u0113\u00ea\3\2\2\2\u0113\u00f8\3\2"+ + "\2\2\u0113\u0101\3\2\2\2\u0113\u0106\3\2\2\2\u0113\u0108\3\2\2\2\u0113"+ + "\u010a\3\2\2\2\u0113\u0112\3\2\2\2\u0114%\3\2\2\2\u0115\u0116\5(\25\2"+ + "\u0116\u0117\7\4\2\2\u0117\u0118\5,\27\2\u0118\u011a\7\4\2\2\u0119\u011b"+ + "\5,\27\2\u011a\u0119\3\2\2\2\u011a\u011b\3\2\2\2\u011b\u0126\3\2\2\2\u011c"+ + "\u011e\5\16\b\2\u011d\u011c\3\2\2\2\u011d\u011e\3\2\2\2\u011e\u011f\3"+ + "\2\2\2\u011f\u0120\7^\2\2\u0120\u0121\7\34\2\2\u0121\u0122\5.\30\2\u0122"+ + "\u0123\7\35\2\2\u0123\u0124\5.\30\2\u0124\u0126\3\2\2\2\u0125\u0115\3"+ + "\2\2\2\u0125\u011d\3\2\2\2\u0126\'\3\2\2\2\u0127\u0129\5\20\t\2\u0128"+ + "\u0127\3\2\2\2\u0128\u0129\3\2\2\2\u0129\u012c\3\2\2\2\u012a\u012c\5,"+ + "\27\2\u012b\u0128\3\2\2\2\u012b\u012a\3\2\2\2\u012c)\3\2\2\2\u012d\u012e"+ + "\b\26\1\2\u012e\u012f\7\7\2\2\u012f\u0130\5*\26\2\u0130\u0131\7\b\2\2"+ + "\u0131\u0138\3\2\2\2\u0132\u0138\7Q\2\2\u0133\u0135\t\2\2\2\u0134\u0136"+ + "\7Q\2\2\u0135\u0134\3\2\2\2\u0135\u0136\3\2\2\2\u0136\u0138\3\2\2\2\u0137"+ + "\u012d\3\2\2\2\u0137\u0132\3\2\2\2\u0137\u0133\3\2\2\2\u0138\u0146\3\2"+ + "\2\2\u0139\u013a\f\5\2\2\u013a\u0145\7 \2\2\u013b\u013c\f\4\2\2\u013c"+ + "\u013e\7!\2\2\u013d\u013f\5.\30\2\u013e\u013d\3\2\2\2\u013e\u013f\3\2"+ + "\2\2\u013f\u0140\3\2\2\2\u0140\u0145\7\"\2\2\u0141\u0142\f\3\2\2\u0142"+ + "\u0143\7\7\2\2\u0143\u0145\7\b\2\2\u0144\u0139\3\2\2\2\u0144\u013b\3\2"+ + "\2\2\u0144\u0141\3\2\2\2\u0145\u0148\3\2\2\2\u0146\u0144\3\2\2\2\u0146"+ + "\u0147\3\2\2\2\u0147+\3\2\2\2\u0148\u0146\3\2\2\2\u0149\u014a\b\27\1\2"+ + "\u014a\u014b\5.\30\2\u014b\u0151\3\2\2\2\u014c\u014d\f\3\2\2\u014d\u014e"+ + "\7\5\2\2\u014e\u0150\5.\30\2\u014f\u014c\3\2\2\2\u0150\u0153\3\2\2\2\u0151"+ + "\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152-\3\2\2\2\u0153\u0151\3\2\2\2"+ + "\u0154\u0155\b\30\1\2\u0155\u0156\7\7\2\2\u0156\u0157\5,\27\2\u0157\u0158"+ + "\7\b\2\2\u0158\u018b\3\2\2\2\u0159\u015a\7#\2\2\u015a\u015d\7\7\2\2\u015b"+ + "\u015e\5*\26\2\u015c\u015e\5.\30\2\u015d\u015b\3\2\2\2\u015d\u015c\3\2"+ + "\2\2\u015e\u015f\3\2\2\2\u015f\u0160\7\b\2\2\u0160\u018b\3\2\2\2\u0161"+ + "\u0162\7$\2\2\u0162\u0165\7\7\2\2\u0163\u0166\5*\26\2\u0164\u0166\5.\30"+ + "\2\u0165\u0163\3\2\2\2\u0165\u0164\3\2\2\2\u0166\u0167\3\2\2\2\u0167\u0168"+ + "\7\b\2\2\u0168\u018b\3\2\2\2\u0169\u016a\7\7\2\2\u016a\u016b\5*\26\2\u016b"+ + "\u016c\7\b\2\2\u016c\u016d\5.\30\32\u016d\u018b\3\2\2\2\u016e\u016f\t"+ + "\3\2\2\u016f\u018b\5.\30\31\u0170\u0171\7 \2\2\u0171\u018b\5.\30\27\u0172"+ + "\u0173\t\4\2\2\u0173\u018b\5.\30\26\u0174\u0175\t\5\2\2\u0175\u018b\5"+ + ".\30\22\u0176\u0177\7\t\2\2\u0177\u017c\5.\30\2\u0178\u0179\7\5\2\2\u0179"+ + "\u017b\5.\30\2\u017a\u0178\3\2\2\2\u017b\u017e\3\2\2\2\u017c\u017a\3\2"+ + "\2\2\u017c\u017d\3\2\2\2\u017d\u017f\3\2\2\2\u017e\u017c\3\2\2\2\u017f"+ + "\u0180\7\n\2\2\u0180\u018b\3\2\2\2\u0181\u018b\7^\2\2\u0182\u018b\7U\2"+ + "\2\u0183\u0185\7R\2\2\u0184\u0183\3\2\2\2\u0185\u0186\3\2\2\2\u0186\u0184"+ + "\3\2\2\2\u0186\u0187\3\2\2\2\u0187\u018b\3\2\2\2\u0188\u018b\7S\2\2\u0189"+ + "\u018b\7T\2\2\u018a\u0154\3\2\2\2\u018a\u0159\3\2\2\2\u018a\u0161\3\2"+ + "\2\2\u018a\u0169\3\2\2\2\u018a\u016e\3\2\2\2\u018a\u0170\3\2\2\2\u018a"+ + "\u0172\3\2\2\2\u018a\u0174\3\2\2\2\u018a\u0176\3\2\2\2\u018a\u0181\3\2"+ + "\2\2\u018a\u0182\3\2\2\2\u018a\u0184\3\2\2\2\u018a\u0188\3\2\2\2\u018a"+ + "\u0189\3\2\2\2\u018b\u01c2\3\2\2\2\u018c\u018d\f\25\2\2\u018d\u018e\t"+ + "\6\2\2\u018e\u01c1\5.\30\26\u018f\u0190\f\24\2\2\u0190\u0191\t\7\2\2\u0191"+ + "\u01c1\5.\30\25\u0192\u0193\f\23\2\2\u0193\u0194\t\b\2\2\u0194\u01c1\5"+ + ".\30\24\u0195\u0196\f\21\2\2\u0196\u0197\t\t\2\2\u0197\u01c1\5.\30\22"+ + "\u0198\u0199\f\20\2\2\u0199\u019a\7*\2\2\u019a\u01c1\5.\30\21\u019b\u019c"+ + "\f\17\2\2\u019c\u019d\7\66\2\2\u019d\u01c1\5.\30\20\u019e\u019f\f\16\2"+ + "\2\u019f\u01a0\7\67\2\2\u01a0\u01c1\5.\30\17\u01a1\u01a2\f\r\2\2\u01a2"+ + "\u01a3\78\2\2\u01a3\u01c1\5.\30\16\u01a4\u01a5\f\f\2\2\u01a5\u01a6\79"+ + "\2\2\u01a6\u01c1\5.\30\r\u01a7\u01a8\f\13\2\2\u01a8\u01a9\7:\2\2\u01a9"+ + "\u01aa\5.\30\2\u01aa\u01ab\7\34\2\2\u01ab\u01ac\5.\30\f\u01ac\u01c1\3"+ + "\2\2\2\u01ad\u01ae\f\n\2\2\u01ae\u01af\7\6\2\2\u01af\u01c1\5.\30\n\u01b0"+ + "\u01b1\f\t\2\2\u01b1\u01b2\t\n\2\2\u01b2\u01c1\5.\30\t\u01b3\u01b4\f\36"+ + "\2\2\u01b4\u01b6\7\7\2\2\u01b5\u01b7\5\60\31\2\u01b6\u01b5\3\2\2\2\u01b6"+ + "\u01b7\3\2\2\2\u01b7\u01b8\3\2\2\2\u01b8\u01c1\7\b\2\2\u01b9\u01ba\f\33"+ + "\2\2\u01ba\u01bb\7!\2\2\u01bb\u01bc\5,\27\2\u01bc\u01bd\7\"\2\2\u01bd"+ + "\u01c1\3\2\2\2\u01be\u01bf\f\30\2\2\u01bf\u01c1\t\3\2\2\u01c0\u018c\3"+ + "\2\2\2\u01c0\u018f\3\2\2\2\u01c0\u0192\3\2\2\2\u01c0\u0195\3\2\2\2\u01c0"+ + "\u0198\3\2\2\2\u01c0\u019b\3\2\2\2\u01c0\u019e\3\2\2\2\u01c0\u01a1\3\2"+ + "\2\2\u01c0\u01a4\3\2\2\2\u01c0\u01a7\3\2\2\2\u01c0\u01ad\3\2\2\2\u01c0"+ + "\u01b0\3\2\2\2\u01c0\u01b3\3\2\2\2\u01c0\u01b9\3\2\2\2\u01c0\u01be\3\2"+ + "\2\2\u01c1\u01c4\3\2\2\2\u01c2\u01c0\3\2\2\2\u01c2\u01c3\3\2\2\2\u01c3"+ + "/\3\2\2\2\u01c4\u01c2\3\2\2\2\u01c5\u01ca\5.\30\2\u01c6\u01c7\7\5\2\2"+ + "\u01c7\u01c9\5.\30\2\u01c8\u01c6\3\2\2\2\u01c9\u01cc\3\2\2\2\u01ca\u01c8"+ + "\3\2\2\2\u01ca\u01cb\3\2\2\2\u01cb\61\3\2\2\2\u01cc\u01ca\3\2\2\2\u01cd"+ + "\u01cf\7E\2\2\u01ce\u01d0\5\64\33\2\u01cf\u01ce\3\2\2\2\u01cf\u01d0\3"+ + "\2\2\2\u01d0\u01d1\3\2\2\2\u01d1\u01d2\7P\2\2\u01d2\63\3\2\2\2\u01d3\u01d4"+ + "\7\7\2\2\u01d4\u01d9\5\66\34\2\u01d5\u01d6\7\5\2\2\u01d6\u01d8\5\66\34"+ + "\2\u01d7\u01d5\3\2\2\2\u01d8\u01db\3\2\2\2\u01d9\u01d7\3\2\2\2\u01d9\u01da"+ + "\3\2\2\2\u01da\u01dc\3\2\2\2\u01db\u01d9\3\2\2\2\u01dc\u01dd\7\b\2\2\u01dd"+ + "\65\3\2\2\2\u01de\u01df\7F\2\2\u01df\u01ee\7R\2\2\u01e0\u01e1\7G\2\2\u01e1"+ + "\u01ee\7^\2\2\u01e2\u01e3\7H\2\2\u01e3\u01ee\7R\2\2\u01e4\u01e5\7I\2\2"+ + "\u01e5\u01ee\5.\30\2\u01e6\u01e7\7J\2\2\u01e7\u01ee\5.\30\2\u01e8\u01eb"+ + "\7K\2\2\u01e9\u01ec\7\17\2\2\u01ea\u01ec\5.\30\2\u01eb\u01e9\3\2\2\2\u01eb"+ + "\u01ea\3\2\2\2\u01ec\u01ee\3\2\2\2\u01ed\u01de\3\2\2\2\u01ed\u01e0\3\2"+ + "\2\2\u01ed\u01e2\3\2\2\2\u01ed\u01e4\3\2\2\2\u01ed\u01e6\3\2\2\2\u01ed"+ + "\u01e8\3\2\2\2\u01ee\67\3\2\2\2\u01ef\u01f1\5:\36\2\u01f0\u01ef\3\2\2"+ + "\2\u01f1\u01f4\3\2\2\2\u01f2\u01f0\3\2\2\2\u01f2\u01f3\3\2\2\2\u01f39"+ + "\3\2\2\2\u01f4\u01f2\3\2\2\2\u01f5\u01f9\5<\37\2\u01f6\u01f9\5> \2\u01f7"+ + "\u01f9\5@!\2\u01f8\u01f5\3\2\2\2\u01f8\u01f6\3\2\2\2\u01f8\u01f7\3\2\2"+ + "\2\u01f9;\3\2\2\2\u01fa\u01fb\7^\2\2\u01fb\u0202\7\34\2\2\u01fc\u01fe"+ + "\7)\2\2\u01fd\u01ff\7^\2\2\u01fe\u01fd\3\2\2\2\u01fe\u01ff\3\2\2\2\u01ff"+ + "\u0200\3\2\2\2\u0200\u0202\7\34\2\2\u0201\u01fa\3\2\2\2\u0201\u01fc\3"+ + "\2\2\2\u0202=\3\2\2\2\u0203\u0205\7O\2\2\u0204\u0206\5B\"\2\u0205\u0204"+ + "\3\2\2\2\u0205\u0206\3\2\2\2\u0206?\3\2\2\2\u0207\u0208\7L\2\2\u0208\u020d"+ + "\5D#\2\u0209\u020a\7\5\2\2\u020a\u020c\5D#\2\u020b\u0209\3\2\2\2\u020c"+ + "\u020f\3\2\2\2\u020d\u020b\3\2\2\2\u020d\u020e\3\2\2\2\u020eA\3\2\2\2"+ + "\u020f\u020d\3\2\2\2\u0210\u0228\5D#\2\u0211\u0212\7M\2\2\u0212\u0228"+ + "\5D#\2\u0213\u0214\5D#\2\u0214\u0215\7\5\2\2\u0215\u0216\7^\2\2\u0216"+ + "\u0228\3\2\2\2\u0217\u0218\7\7\2\2\u0218\u0219\5D#\2\u0219\u021a\7\b\2"+ + "\2\u021a\u021b\7\5\2\2\u021b\u021c\7^\2\2\u021c\u0228\3\2\2\2\u021d\u021e"+ + "\7\7\2\2\u021e\u021f\5D#\2\u021f\u0220\7\5\2\2\u0220\u0221\7^\2\2\u0221"+ + "\u0222\7\b\2\2\u0222\u0228\3\2\2\2\u0223\u0224\7\7\2\2\u0224\u0225\5D"+ + "#\2\u0225\u0226\7\b\2\2\u0226\u0228\3\2\2\2\u0227\u0210\3\2\2\2\u0227"+ + "\u0211\3\2\2\2\u0227\u0213\3\2\2\2\u0227\u0217\3\2\2\2\u0227\u021d\3\2"+ + "\2\2\u0227\u0223\3\2\2\2\u0228C\3\2\2\2\u0229\u022a\b#\1\2\u022a\u022b"+ + "\7!\2\2\u022b\u022c\5D#\2\u022c\u022d\7\"\2\2\u022d\u0238\3\2\2\2\u022e"+ + "\u022f\t\13\2\2\u022f\u0238\5D#\n\u0230\u0238\7^\2\2\u0231\u0238\7_\2"+ + "\2\u0232\u0233\7\t\2\2\u0233\u0234\7^\2\2\u0234\u0238\7\n\2\2\u0235\u0238"+ + "\7U\2\2\u0236\u0238\7S\2\2\u0237\u0229\3\2\2\2\u0237\u022e\3\2\2\2\u0237"+ + "\u0230\3\2\2\2\u0237\u0231\3\2\2\2\u0237\u0232\3\2\2\2\u0237\u0235\3\2"+ + "\2\2\u0237\u0236\3\2\2\2\u0238\u0247\3\2\2\2\u0239\u023a\f\f\2\2\u023a"+ + "\u023b\7N\2\2\u023b\u0246\5D#\r\u023c\u023d\f\13\2\2\u023d\u023e\t\6\2"+ + "\2\u023e\u0246\5D#\f\u023f\u0240\f\t\2\2\u0240\u0241\t\f\2\2\u0241\u0246"+ + "\5D#\n\u0242\u0243\f\b\2\2\u0243\u0244\t\b\2\2\u0244\u0246\5D#\t\u0245"+ + "\u0239\3\2\2\2\u0245\u023c\3\2\2\2\u0245\u023f\3\2\2\2\u0245\u0242\3\2"+ + "\2\2\u0246\u0249\3\2\2\2\u0247\u0245\3\2\2\2\u0247\u0248\3\2\2\2\u0248"+ + "E\3\2\2\2\u0249\u0247\3\2\2\2;PYafm{\u0081\u0087\u008c\u0095\u009c\u00b1"+ "\u00b4\u00bd\u00c5\u00cc\u00d9\u00de\u00ea\u00f8\u0103\u010c\u0113\u011a"+ "\u011d\u0125\u0128\u012b\u0135\u0137\u013e\u0144\u0146\u0151\u015d\u0165"+ - "\u017c\u0186\u01b2\u01bc\u01be\u01c6\u01cb\u01d5\u01e7\u01e9\u01ee\u01f4"+ - "\u01fa\u01fd\u0201\u0209\u0223\u0233\u0241\u0243"; + "\u017c\u0186\u018a\u01b6\u01c0\u01c2\u01ca\u01cf\u01d9\u01eb\u01ed\u01f2"+ + "\u01f8\u01fe\u0201\u0205\u020d\u0227\u0237\u0245\u0247"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java index 84d1ddcb7..98035b89e 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java @@ -1,4 +1,4 @@ -// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7 +// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7 package dk.camelot64.kickc.parser; import org.antlr.v4.runtime.tree.ParseTreeVisitor; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 2a5e5faea..63febda6c 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -1307,12 +1307,18 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { @Override public RValue visitExprString(KickCParser.ExprStringContext ctx) { - String text = ctx.getText(); - String stringValue; - if(text.endsWith("z")) { - stringValue = text.substring(1, text.length() - 2); - } else { - stringValue = text.substring(1, text.length() - 1)+"@"; + String stringValue =""; + String subText = ""; + for(TerminalNode stringNode : ctx.STRING()) { + subText = stringNode.getText(); + if(subText.endsWith("z")) { + stringValue += subText.substring(1, subText.length() - 2); + } else { + stringValue += subText.substring(1, subText.length() - 1); + } + } + if(!subText.endsWith("z")) { + stringValue += "@"; } return new ConstantString(stringValue); } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 23c2cc2b7..5fb692d96 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,23 +32,9 @@ public class TestPrograms { public TestPrograms() { } - /* - * Avaiting String concatenation - @Test - public void testLiterals() throws IOException, URISyntaxException { - compileAndCompare("literals"); - } - - - @Test - public void testConstantStringConcat() throws IOException, URISyntaxException { - compileAndCompare("constant-string-concat"); - } - - @Test - public void testConcatChar() throws IOException, URISyntaxException { - compileAndCompare("concat-char"); + public void testC64DtvGfxExplorer() throws IOException, URISyntaxException { + compileAndCompare("c64dtv-gfxexplorer", 10); } @Test @@ -57,11 +43,20 @@ public class TestPrograms { } @Test - public void testC64DtvGfxExplorer() throws IOException, URISyntaxException { - compileAndCompare("c64dtv-gfxexplorer", 10); + public void testConstantStringConcat0() throws IOException, URISyntaxException { + compileAndCompare("constant-string-concat-0", log().verboseParse().verboseStatementSequence().verboseCreateSsa()); } - */ + @Test + public void testLiterals() throws IOException, URISyntaxException { + compileAndCompare("literals"); + } + + + @Test + public void testConstantStringConcat() throws IOException, URISyntaxException { + compileAndCompare("constant-string-concat"); + } @Test public void testStatementSequence1() throws IOException, URISyntaxException { diff --git a/src/test/kc/c64dtv-gfxexplorer.kc b/src/test/kc/c64dtv-gfxexplorer.kc index 0eba729d9..6c35edfb6 100644 --- a/src/test/kc/c64dtv-gfxexplorer.kc +++ b/src/test/kc/c64dtv-gfxexplorer.kc @@ -115,40 +115,40 @@ const byte* FORM_SCREEN = $0400; const byte* FORM_CHARSET = $1800; // Charset ROM byte[] FORM_TEXT = - " C64 DTV Graphics Mode Explorer @"z + - " @"z + - " PRESET 0 Standard Charset @"z + - " @"z + - " CONTROL PLANE A VIC II @"z + - " bmm 0 pattern p0 screen s0 @"z + - " mcm 0 start 00 gfx g0 @"z + - " ecm 0 step 00 colors c0 @"z + - " hicolor 0 modulo 00 @"z + - " linear 0 COLORS @"z + - " color off 0 PLANE B palet 0 @"z + - " chunky 0 pattern p0 bgcol0 00 @"z + - " border off 0 start 00 bgcol1 00 @"z + - " overscan 0 step 00 bgcol2 00 @"z + - " modulo 00 bgcol3 00 @"z + - "@"z ; + " C64 DTV Graphics Mode Explorer @" + " @" + " PRESET 0 Standard Charset @" + " @" + " CONTROL PLANE A VIC II @" + " bmm 0 pattern p0 screen s0 @" + " mcm 0 start 00 gfx g0 @" + " ecm 0 step 00 colors c0 @" + " hicolor 0 modulo 00 @" + " linear 0 COLORS @" + " color off 0 PLANE B palet 0 @" + " chunky 0 pattern p0 bgcol0 00 @" + " border off 0 start 00 bgcol1 00 @" + " overscan 0 step 00 bgcol2 00 @" + " modulo 00 bgcol3 00 @" + ; byte[] FORM_COLS = - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@"z + - " @"z + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@"z + - " @"z + - " nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z + - " nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z + - " nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z + - " nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z + - " nnnnnnnnnnnn mmmmmmmmmm @"z + - " nnnnnnnnnnnn jjjjjjjjj @"z + - " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z + - " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z + - " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z + - " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z + - " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z + - " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z + - "@"z ; + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@" + " @" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@" + " @" + " nnnnnnnnnnnn mmmmmmmmmm ooooooooo @" + " nnnnnnnnnnnn mmmmmmmmmm ooooooooo @" + " nnnnnnnnnnnn mmmmmmmmmm ooooooooo @" + " nnnnnnnnnnnn mmmmmmmmmm ooooooooo @" + " nnnnnnnnnnnn mmmmmmmmmm @" + " nnnnnnnnnnnn jjjjjjjjj @" + " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" + " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" + " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" + " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" + " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" + " nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" + ; // Number of form fields byte form_fields_cnt = 36; diff --git a/src/test/kc/c64dtv-gfxmodes.kc b/src/test/kc/c64dtv-gfxmodes.kc index 79a3bd30c..87dcd7a88 100644 --- a/src/test/kc/c64dtv-gfxmodes.kc +++ b/src/test/kc/c64dtv-gfxmodes.kc @@ -18,27 +18,28 @@ void main() { } byte[] MENU_TEXT = - "C64DTV Graphics Modes CCLHBME@"z + - " OHIIMCC@"z + - " LUNCMMM@"z + - "----------------------------------------@"z + - "1. Standard Char (V) 0000000@"z + - "2. Extended Color Char (V) 0000001@"z + - "3. Multicolor Char (V) 0000010@"z + - "4. Standard Bitmap (V) 0000100@"z + - "5. Multicolor Bitmap (V) 0000110@"z + - "6. High Color Standard Char (H) 0001000@"z + - "7. High Extended Color Char (H) 0001001@"z + - "8. High Multicolor Char (H) 0001010@"z + - "9. High Multicolor Bitmap (H) 0001110@"z + - "a. Sixs Fred 2 (D) 0010111@"z + - "b. Two Plane Bitmap (D) 0011101@"z + - "c. Sixs Fred (2 Plane MC BM) (D) 0011111@"z + - "d. 8bpp Pixel Cell (D) 0111011@"z + - "e. Chunky 8bpp Bitmap (D) 1111011@"z + - "----------------------------------------@"z + - " (V) vicII (H) vicII+hicol (D) c64dtv@"z + - "@"z ; + "C64DTV Graphics Modes CCLHBME@" + " OHIIMCC@" + " LUNCMMM@" + "----------------------------------------@" + "1. Standard Char (V) 0000000@" + "2. Extended Color Char (V) 0000001@" + "3. Multicolor Char (V) 0000010@" + "4. Standard Bitmap (V) 0000100@" + "5. Multicolor Bitmap (V) 0000110@" + "6. High Color Standard Char (H) 0001000@" + "7. High Extended Color Char (H) 0001001@" + "8. High Multicolor Char (H) 0001010@" + "9. High Multicolor Bitmap (H) 0001110@" + "a. Sixs Fred 2 (D) 0010111@" + "b. Two Plane Bitmap (D) 0011101@" + "c. Sixs Fred (2 Plane MC BM) (D) 0011111@" + "d. 8bpp Pixel Cell (D) 0111011@" + "e. Chunky 8bpp Bitmap (D) 1111011@" + "----------------------------------------@" + " (V) vicII (H) vicII+hicol (D) c64dtv@" + ; + void menu() { const byte* SCREEN = $8000; diff --git a/src/test/kc/concat-char.kc b/src/test/kc/concat-char.kc deleted file mode 100644 index c51f6ae5c..000000000 --- a/src/test/kc/concat-char.kc +++ /dev/null @@ -1,10 +0,0 @@ -// Concatenate a char to a string - -void main() { - byte* screen = $400; - byte l = 'l'; - byte[] msg = "cm"z+l; - for( byte i: 0..2 ) { - screen[i] = msg[i]; - } -} \ No newline at end of file diff --git a/src/test/kc/constant-string-concat-0.kc b/src/test/kc/constant-string-concat-0.kc new file mode 100644 index 000000000..f3b35771b --- /dev/null +++ b/src/test/kc/constant-string-concat-0.kc @@ -0,0 +1,8 @@ +// Concatenates string constants in different ways +void main() { + byte[] msg = "camel" "ot"; + byte* SCREEN = 0x0400; + for( byte i=0;msg[i]!=0;i++) { + SCREEN[i] = msg[i]; + } +} \ No newline at end of file diff --git a/src/test/kc/constant-string-concat.kc b/src/test/kc/constant-string-concat.kc index 218825e62..0acbe2a1a 100644 --- a/src/test/kc/constant-string-concat.kc +++ b/src/test/kc/constant-string-concat.kc @@ -1,13 +1,10 @@ // Concatenates string constants in different ways void main() { - byte[] s = "e"z+"l"z; - byte[] s2 = s+'o'; - byte[] s3 = "cam"z+s2; - byte e = '!'; - byte[] s4 = ""z+'t'+ e; - byte[] s5 = s3+s4; + byte[] s = "c" + "ame" + "lot"; byte* SCREEN = $400; for( byte i: 0..7) { - SCREEN[i] = s5[i]; + SCREEN[i] = s[i]; } } \ No newline at end of file diff --git a/src/test/kc/literals.kc b/src/test/kc/literals.kc index e72097339..043c30658 100644 --- a/src/test/kc/literals.kc +++ b/src/test/kc/literals.kc @@ -2,7 +2,7 @@ byte* SCREEN = $0400; byte ch = 'a'; byte num = 1; -byte[] str = "bc"z+"d"z+'e'; +byte[] str = "bc" "d" "e"; byte[] nums = { 2, 3, 4, 5}; void main() { diff --git a/src/test/ref/c64dtv-gfxexplorer.asm b/src/test/ref/c64dtv-gfxexplorer.asm index a1a01b569..18ca5b0bb 100644 --- a/src/test/ref/c64dtv-gfxexplorer.asm +++ b/src/test/ref/c64dtv-gfxexplorer.asm @@ -130,41 +130,6 @@ .const FORM_CURSOR_BLINK = $28 // Any shift is pressed .const KEY_MODIFIER_SHIFT = KEY_MODIFIER_LSHIFT|KEY_MODIFIER_RSHIFT - .label form_ctrl_bmm = form_fields_val+1 - .label form_ctrl_mcm = form_fields_val+2 - .label form_ctrl_ecm = form_fields_val+3 - .label form_ctrl_hicol = form_fields_val+4 - .label form_ctrl_line = form_fields_val+5 - .label form_ctrl_colof = form_fields_val+6 - .label form_ctrl_chunk = form_fields_val+7 - .label form_ctrl_borof = form_fields_val+8 - .label form_ctrl_overs = form_fields_val+9 - .label form_a_pattern = form_fields_val+$a - .label form_a_start_hi = form_fields_val+$b - .label form_a_start_lo = form_fields_val+$c - .label form_a_step_hi = form_fields_val+$d - .label form_a_step_lo = form_fields_val+$e - .label form_a_mod_hi = form_fields_val+$f - .label form_a_mod_lo = form_fields_val+$10 - .label form_b_pattern = form_fields_val+$11 - .label form_b_start_hi = form_fields_val+$12 - .label form_b_start_lo = form_fields_val+$13 - .label form_b_step_hi = form_fields_val+$14 - .label form_b_step_lo = form_fields_val+$15 - .label form_b_mod_hi = form_fields_val+$16 - .label form_b_mod_lo = form_fields_val+$17 - .label form_vic_screen = form_fields_val+$18 - .label form_vic_gfx = form_fields_val+$19 - .label form_vic_cols = form_fields_val+$1a - .label form_dtv_palet = form_fields_val+$1b - .label form_vic_bg0_hi = form_fields_val+$1c - .label form_vic_bg0_lo = form_fields_val+$1d - .label form_vic_bg1_hi = form_fields_val+$1e - .label form_vic_bg1_lo = form_fields_val+$1f - .label form_vic_bg2_hi = form_fields_val+$20 - .label form_vic_bg2_lo = form_fields_val+$21 - .label form_vic_bg3_hi = form_fields_val+$22 - .label form_vic_bg3_lo = form_fields_val+$23 .label print_char_cursor = 5 .label print_line_cursor = $10 .label keyboard_events_size = 8 @@ -196,61 +161,61 @@ main: { // Change graphics mode to show the selected graphics mode gfx_mode: { .label _22 = 9 - .label _24 = 3 .label _26 = 3 .label _28 = 3 .label _36 = 9 - .label _38 = 3 .label _40 = 3 .label _42 = 3 .label _52 = 3 + .label _53 = 3 .label _54 = 3 .label _55 = 3 .label _56 = 2 .label _57 = 3 + .label _58 = 3 .label _59 = 3 .label plane_a = 9 .label plane_b = 9 .label vic_colors = 3 .label col = 5 .label cy = 2 - lda form_ctrl_line + lda form_fields_val+5 cmp #0 beq b10 - ldx #0|DTV_LINEAR + ldx #DTV_LINEAR jmp b1 b10: ldx #0 b1: - lda form_ctrl_borof + lda form_fields_val+8 cmp #0 beq b2 txa ora #DTV_BORDER_OFF tax b2: - lda form_ctrl_hicol + lda form_fields_val+4 cmp #0 beq b3 txa ora #DTV_HIGHCOLOR tax b3: - lda form_ctrl_overs + lda form_fields_val+9 cmp #0 beq b4 txa ora #DTV_OVERSCAN tax b4: - lda form_ctrl_colof + lda form_fields_val+6 cmp #0 beq b5 txa ora #DTV_COLORRAM_OFF tax b5: - lda form_ctrl_chunk + lda form_fields_val+7 cmp #0 beq b6 txa @@ -258,7 +223,7 @@ gfx_mode: { tax b6: stx DTV_CONTROL - lda form_ctrl_ecm + lda form_fields_val+3 cmp #0 beq b11 ldx #VIC_DEN|VIC_RSEL|3|VIC_ECM @@ -266,7 +231,7 @@ gfx_mode: { b11: ldx #VIC_DEN|VIC_RSEL|3 b7: - lda form_ctrl_bmm + lda form_fields_val+1 cmp #0 beq b8 txa @@ -274,7 +239,7 @@ gfx_mode: { tax b8: stx VIC_CONTROL - lda form_ctrl_mcm + lda form_fields_val+2 cmp #0 beq b12 lda #VIC_CSEL|VIC_MCM @@ -283,14 +248,14 @@ gfx_mode: { lda #VIC_CSEL b9: sta VIC_CONTROL2 - lda form_a_start_hi + lda form_fields_val+$b asl asl asl asl - ora form_a_start_lo + ora form_fields_val+$c tax - lda form_a_pattern + lda form_fields_val+$a jsr get_plane txa clc @@ -306,15 +271,12 @@ gfx_mode: { adc #0 sta plane_a+3 lda plane_a - sta _24 - lda plane_a+1 - sta _24+1 - lda _24 - sta DTV_PLANEA_START_LO - lda plane_a sta _26 lda plane_a+1 sta _26+1 + lda _26 + sta DTV_PLANEA_START_LO + lda _26+1 sta DTV_PLANEA_START_MI lda plane_a+2 sta _28 @@ -322,30 +284,30 @@ gfx_mode: { sta _28+1 lda _28 sta DTV_PLANEA_START_HI - lda form_a_step_hi + lda form_fields_val+$d asl asl asl asl - ora form_a_step_lo + ora form_fields_val+$e sta DTV_PLANEA_STEP - lda form_a_mod_hi + lda form_fields_val+$f asl asl asl asl - ora form_a_mod_lo + ora form_fields_val+$10 sta DTV_PLANEA_MODULO_LO lda #0 sta DTV_PLANEA_MODULO_HI - lda form_b_start_hi + lda form_fields_val+$12 asl asl asl asl - ora form_b_start_lo + ora form_fields_val+$13 tax - lda form_b_pattern + lda form_fields_val+$11 jsr get_plane txa clc @@ -361,15 +323,12 @@ gfx_mode: { adc #0 sta plane_b+3 lda plane_b - sta _38 - lda plane_b+1 - sta _38+1 - lda _38 - sta DTV_PLANEB_START_LO - lda plane_b sta _40 lda plane_b+1 sta _40+1 + lda _40 + sta DTV_PLANEB_START_LO + lda _40+1 sta DTV_PLANEB_START_MI lda plane_b+2 sta _42 @@ -377,19 +336,19 @@ gfx_mode: { sta _42+1 lda _42 sta DTV_PLANEB_START_HI - lda form_b_step_hi + lda form_fields_val+$14 asl asl asl asl - ora form_b_step_lo + ora form_fields_val+$15 sta DTV_PLANEB_STEP - lda form_b_mod_hi + lda form_fields_val+$16 asl asl asl asl - ora form_b_mod_lo + ora form_fields_val+$17 sta DTV_PLANEB_MODULO_LO lda #0 sta DTV_PLANEB_MODULO_HI @@ -399,7 +358,7 @@ gfx_mode: { // Set VIC Bank bits to output - all others to input lda #3^VIC_SCREEN0/$4000 sta CIA2_PORT_A - lda form_vic_screen + lda form_fields_val+$18 jsr get_vic_screen lda _54 and #<$3fff @@ -415,7 +374,7 @@ gfx_mode: { bne !- lda _55 sta _56 - lda form_vic_gfx + lda form_fields_val+$19 jsr get_vic_charset lda _59 and #<$3fff @@ -429,7 +388,7 @@ gfx_mode: { // Set VIC Bank // VIC memory sta VIC_MEMORY - lda form_vic_cols + lda form_fields_val+$1a jsr get_vic_screen lda #0 sta cy @@ -461,36 +420,36 @@ gfx_mode: { // Background colors lda #0 sta BORDERCOL - lda form_vic_bg0_hi + lda form_fields_val+$1c asl asl asl asl - ora form_vic_bg0_lo + ora form_fields_val+$1d sta BGCOL1 - lda form_vic_bg1_hi + lda form_fields_val+$1e asl asl asl asl - ora form_vic_bg1_lo + ora form_fields_val+$1f sta BGCOL2 - lda form_vic_bg2_hi + lda form_fields_val+$20 asl asl asl asl - ora form_vic_bg2_lo + ora form_fields_val+$21 sta BGCOL3 - lda form_vic_bg3_hi + lda form_fields_val+$22 asl asl asl asl - ora form_vic_bg3_lo + ora form_fields_val+$23 sta BGCOL4 // DTV Palette - lda form_dtv_palet + lda form_fields_val+$1b cmp #0 beq b13 ldx #0 @@ -508,7 +467,9 @@ gfx_mode: { jsr keyboard_event_scan jsr keyboard_event_get cmp #KEY_SPACE - bne b25 + beq breturn + jmp b25 + breturn: rts // DTV Palette - default b13: @@ -567,7 +528,7 @@ keyboard_event_scan: { jsr keyboard_event_pressed cmp #0 beq b4 - ldx #0|KEY_MODIFIER_LSHIFT + ldx #KEY_MODIFIER_LSHIFT jmp b1 b4: ldx #0 @@ -679,39 +640,39 @@ keyboard_matrix_read: { get_vic_screen: { .label return = 3 cmp #0 - beq b2 + beq b1 cmp #1 - beq b3 + beq b2 cmp #2 - beq b4 + beq b3 cmp #3 - beq b5 + beq b4 cmp #4 - bne b2 + bne b1 lda #<VIC_SCREEN4 sta return lda #>VIC_SCREEN4 sta return+1 rts - b2: + b1: lda #<VIC_SCREEN0 sta return lda #>VIC_SCREEN0 sta return+1 rts - b3: + b2: lda #<VIC_SCREEN1 sta return lda #>VIC_SCREEN1 sta return+1 rts - b4: + b3: lda #<VIC_SCREEN2 sta return lda #>VIC_SCREEN2 sta return+1 rts - b5: + b4: lda #<VIC_SCREEN3 sta return lda #>VIC_SCREEN3 @@ -723,15 +684,15 @@ get_vic_screen: { get_vic_charset: { .label return = 3 cmp #0 - beq b2 + beq b1 cmp #1 - bne b2 + bne b1 lda #<VIC_BITMAP sta return lda #>VIC_BITMAP sta return+1 rts - b2: + b1: lda #<VIC_CHARSET_ROM sta return lda #>VIC_CHARSET_ROM @@ -785,7 +746,7 @@ get_plane: { cmp #$c beq b6 cmp #$d - bne b2 + bne b1 lda #<PLANE_FULL sta return lda #>PLANE_FULL @@ -795,14 +756,24 @@ get_plane: { lda #>PLANE_FULL>>$10 sta return+3 rts - b2: - lda #<$ffffffff&VIC_SCREEN0 + b1: + lda #<VIC_SCREEN0 sta return - lda #>$ffffffff&VIC_SCREEN0 + lda #>VIC_SCREEN0 sta return+1 - lda #<$ffffffff&VIC_SCREEN0>>$10 + lda #<VIC_SCREEN0>>$10 sta return+2 - lda #>$ffffffff&VIC_SCREEN0>>$10 + lda #>VIC_SCREEN0>>$10 + sta return+3 + rts + b2: + lda #<VIC_SCREEN0 + sta return + lda #>VIC_SCREEN0 + sta return+1 + lda #<VIC_SCREEN0>>$10 + sta return+2 + lda #>VIC_SCREEN0>>$10 sta return+3 rts b3: @@ -846,53 +817,53 @@ get_plane: { sta return+3 rts b7: - lda #<$ffffffff&VIC_SCREEN1 + lda #<VIC_SCREEN1 sta return - lda #>$ffffffff&VIC_SCREEN1 + lda #>VIC_SCREEN1 sta return+1 - lda #<$ffffffff&VIC_SCREEN1>>$10 + lda #<VIC_SCREEN1>>$10 sta return+2 - lda #>$ffffffff&VIC_SCREEN1>>$10 + lda #>VIC_SCREEN1>>$10 sta return+3 rts b8: - lda #<$ffffffff&VIC_SCREEN2 + lda #<VIC_SCREEN2 sta return - lda #>$ffffffff&VIC_SCREEN2 + lda #>VIC_SCREEN2 sta return+1 - lda #<$ffffffff&VIC_SCREEN2>>$10 + lda #<VIC_SCREEN2>>$10 sta return+2 - lda #>$ffffffff&VIC_SCREEN2>>$10 + lda #>VIC_SCREEN2>>$10 sta return+3 rts b9: - lda #<$ffffffff&VIC_SCREEN3 + lda #<VIC_SCREEN3 sta return - lda #>$ffffffff&VIC_SCREEN3 + lda #>VIC_SCREEN3 sta return+1 - lda #<$ffffffff&VIC_SCREEN3>>$10 + lda #<VIC_SCREEN3>>$10 sta return+2 - lda #>$ffffffff&VIC_SCREEN3>>$10 + lda #>VIC_SCREEN3>>$10 sta return+3 rts b10: - lda #<$ffffffff&VIC_BITMAP + lda #<VIC_BITMAP sta return - lda #>$ffffffff&VIC_BITMAP + lda #>VIC_BITMAP sta return+1 - lda #<$ffffffff&VIC_BITMAP>>$10 + lda #<VIC_BITMAP>>$10 sta return+2 - lda #>$ffffffff&VIC_BITMAP>>$10 + lda #>VIC_BITMAP>>$10 sta return+3 rts b11: - lda #<$ffffffff&VIC_CHARSET_ROM + lda #<VIC_CHARSET_ROM sta return - lda #>$ffffffff&VIC_CHARSET_ROM + lda #>VIC_CHARSET_ROM sta return+1 - lda #<$ffffffff&VIC_CHARSET_ROM>>$10 + lda #<VIC_CHARSET_ROM>>$10 sta return+2 - lda #>$ffffffff&VIC_CHARSET_ROM>>$10 + lda #>VIC_CHARSET_ROM>>$10 sta return+3 rts b12: @@ -956,10 +927,10 @@ form_mode: { lda form_fields_val jsr render_preset_name // DTV Graphics Bank - lda #($ffffffff&FORM_CHARSET)/$10000 + lda #0 sta DTV_GRAPHICS_VIC_BANK // DTV Color Bank - lda #DTV_COLOR_BANK_DEFAULT/$400 + lda #<DTV_COLOR_BANK_DEFAULT/$400 sta DTV_COLOR_BANK_LO lda #0 sta DTV_COLOR_BANK_HI @@ -967,7 +938,6 @@ form_mode: { lda #3 sta CIA2_PORT_A_DDR // Set VIC Bank bits to output - all others to input - lda #3^FORM_CHARSET/$4000 sta CIA2_PORT_A // Set VIC Bank // DTV Graphics Mode @@ -982,7 +952,7 @@ form_mode: { lda #(FORM_SCREEN&$3fff)/$40|(FORM_CHARSET&$3fff)/$400 sta VIC_MEMORY // DTV Plane A to FORM_SCREEN also - lda #<FORM_SCREEN + lda #0 sta DTV_PLANEA_START_LO lda #>FORM_SCREEN sta DTV_PLANEA_START_MI @@ -1030,93 +1000,93 @@ form_mode: { render_preset_name: { .label name = 3 cmp #0 - beq b12 - cmp #1 - beq b4 - cmp #2 - beq b5 - cmp #3 - beq b6 - cmp #4 - beq b7 - cmp #5 - beq b8 - cmp #6 - beq b9 - cmp #7 - beq b10 - cmp #8 - beq b11 - cmp #9 - beq b2 - cmp #$a beq b3 - b12: + cmp #1 + beq b6 + cmp #2 + beq b7 + cmp #3 + beq b8 + cmp #4 + beq b9 + cmp #5 + beq b10 + cmp #6 + beq b11 + cmp #7 + beq b12 + cmp #8 + beq b4 + cmp #9 + beq b5 + cmp #$a + beq b1 + b3: lda #<name_1 sta name lda #>name_1 sta name+1 - jmp b1 - b2: - lda #<name_10 - sta name - lda #>name_10 - sta name+1 - jmp b1 - b3: + jmp b2 + b1: lda #<name_11 sta name lda #>name_11 sta name+1 - jmp b1 + jmp b2 b4: - lda #<name_2 - sta name - lda #>name_2 - sta name+1 - jmp b1 - b5: - lda #<name_3 - sta name - lda #>name_3 - sta name+1 - jmp b1 - b6: - lda #<name_4 - sta name - lda #>name_4 - sta name+1 - jmp b1 - b7: - lda #<name_5 - sta name - lda #>name_5 - sta name+1 - jmp b1 - b8: - lda #<name_6 - sta name - lda #>name_6 - sta name+1 - jmp b1 - b9: - lda #<name_7 - sta name - lda #>name_7 - sta name+1 - jmp b1 - b10: - lda #<name_8 - sta name - lda #>name_8 - sta name+1 - jmp b1 - b11: lda #<name_9 sta name lda #>name_9 sta name+1 - b1: + jmp b2 + b5: + lda #<name_10 + sta name + lda #>name_10 + sta name+1 + jmp b2 + b6: + lda #<name_2 + sta name + lda #>name_2 + sta name+1 + jmp b2 + b7: + lda #<name_3 + sta name + lda #>name_3 + sta name+1 + jmp b2 + b8: + lda #<name_4 + sta name + lda #>name_4 + sta name+1 + jmp b2 + b9: + lda #<name_5 + sta name + lda #>name_5 + sta name+1 + jmp b2 + b10: + lda #<name_6 + sta name + lda #>name_6 + sta name+1 + jmp b2 + b11: + lda #<name_7 + sta name + lda #>name_7 + sta name+1 + jmp b2 + b12: + lda #<name_8 + sta name + lda #>name_8 + sta name+1 + b2: jsr print_str_at rts name_1: .text "Standard Charset @" @@ -1168,7 +1138,7 @@ form_render_values: { ldy form_fields_val,x lda print_hextab,y ldy form_field_ptr.x - sta (form_field_ptr._2),y + sta (form_field_ptr.line),y inx cpx #form_fields_cnt bcc b1 @@ -1178,6 +1148,7 @@ form_render_values: { // field_idx is the index of the field to get the screen address for // form_field_ptr(byte register(X) field_idx) form_field_ptr: { + .label line = 3 .label x = $13 .label _2 = 3 lda form_fields_y,x @@ -1196,93 +1167,93 @@ form_field_ptr: { apply_preset: { .label preset = 3 cmp #0 - beq b12 - cmp #1 - beq b4 - cmp #2 - beq b5 - cmp #3 - beq b6 - cmp #4 - beq b7 - cmp #5 - beq b8 - cmp #6 - beq b9 - cmp #7 - beq b10 - cmp #8 - beq b11 - cmp #9 - beq b2 - cmp #$a beq b3 - b12: + cmp #1 + beq b6 + cmp #2 + beq b7 + cmp #3 + beq b8 + cmp #4 + beq b9 + cmp #5 + beq b10 + cmp #6 + beq b11 + cmp #7 + beq b12 + cmp #8 + beq b4 + cmp #9 + beq b5 + cmp #$a + beq b1 + b3: lda #<preset_stdchar sta preset lda #>preset_stdchar sta preset+1 - jmp b1 - b2: - lda #<preset_sixsfred2 - sta preset - lda #>preset_sixsfred2 - sta preset+1 - jmp b1 - b3: + jmp b2 + b1: lda #<preset_8bpppixelcell sta preset lda #>preset_8bpppixelcell sta preset+1 - jmp b1 + jmp b2 b4: - lda #<preset_ecmchar - sta preset - lda #>preset_ecmchar - sta preset+1 - jmp b1 - b5: - lda #<preset_stdbm - sta preset - lda #>preset_stdbm - sta preset+1 - jmp b1 - b6: - lda #<preset_mcbm - sta preset - lda #>preset_mcbm - sta preset+1 - jmp b1 - b7: - lda #<preset_hi_stdchar - sta preset - lda #>preset_hi_stdchar - sta preset+1 - jmp b1 - b8: - lda #<preset_hi_ecmchar - sta preset - lda #>preset_hi_ecmchar - sta preset+1 - jmp b1 - b9: - lda #<preset_twoplane - sta preset - lda #>preset_twoplane - sta preset+1 - jmp b1 - b10: - lda #<preset_chunky - sta preset - lda #>preset_chunky - sta preset+1 - jmp b1 - b11: lda #<preset_sixsfred sta preset lda #>preset_sixsfred sta preset+1 - b1: + jmp b2 + b5: + lda #<preset_sixsfred2 + sta preset + lda #>preset_sixsfred2 + sta preset+1 + jmp b2 + b6: + lda #<preset_ecmchar + sta preset + lda #>preset_ecmchar + sta preset+1 + jmp b2 + b7: + lda #<preset_stdbm + sta preset + lda #>preset_stdbm + sta preset+1 + jmp b2 + b8: + lda #<preset_mcbm + sta preset + lda #>preset_mcbm + sta preset+1 + jmp b2 + b9: + lda #<preset_hi_stdchar + sta preset + lda #>preset_hi_stdchar + sta preset+1 + jmp b2 + b10: + lda #<preset_hi_ecmchar + sta preset + lda #>preset_hi_ecmchar + sta preset+1 + jmp b2 + b11: + lda #<preset_twoplane + sta preset + lda #>preset_twoplane + sta preset+1 + jmp b2 + b12: + lda #<preset_chunky + sta preset + lda #>preset_chunky + sta preset+1 + b2: ldy #0 // Copy preset values into the fields b13: @@ -1316,8 +1287,8 @@ form_control: { !b2: lda #$7f ldy form_field_ptr.x - and (form_field_ptr._2),y - sta (form_field_ptr._2),y + and (form_field_ptr.line),y + sta (form_field_ptr.line),y b3: jsr keyboard_event_scan jsr keyboard_event_get @@ -1325,78 +1296,78 @@ form_control: { bne b4 lda #$7f ldy form_field_ptr.x - and (form_field_ptr._2),y + and (form_field_ptr.line),y // Unblink the cursor - sta (form_field_ptr._2),y + sta (form_field_ptr.line),y txa and #KEY_MODIFIER_SHIFT cmp #0 - beq b12 + beq b13 dec form_field_idx lda #$ff cmp form_field_idx - bne b13 + bne b14 lda #form_fields_cnt-1 sta form_field_idx - b13: + b14: lda #FORM_CURSOR_BLINK/2 sta form_cursor_count ldx #0 rts - b12: + b13: inc form_field_idx lda #form_fields_cnt cmp form_field_idx - bne b13 + bne b14 lda #0 sta form_field_idx - jmp b13 + jmp b14 b4: cmp #KEY_CRSR_RIGHT bne b5 txa and #KEY_MODIFIER_SHIFT cmp #0 - beq b14 + beq b15 ldx form_field_idx dec form_fields_val,x lda #$ff ldy form_field_idx cmp form_fields_val,y - bne b15 + bne b16 lda form_fields_max,y sta form_fields_val,y - b15: + b16: // Render field value ldx form_field_idx ldy form_fields_val,x lda print_hextab,y ldy form_field_ptr.x - sta (form_field_ptr._2),y - b6: + sta (form_field_ptr.line),y + b7: ldx #0 rts - b14: + b15: ldx form_field_idx inc form_fields_val,x ldy form_field_idx lda form_fields_val,y cmp form_fields_max,y - bcc b15 - beq b15 + bcc b16 + beq b16 lda #0 sta form_fields_val,y - jmp b15 + jmp b16 b5: cmp #KEY_SPACE - bne b6 + bne b7 ldx #$ff rts b2: lda #$80 ldy form_field_ptr.x - ora (form_field_ptr._2),y - sta (form_field_ptr._2),y + ora (form_field_ptr.line),y + sta (form_field_ptr.line),y jmp b3 } // Set the screen to use for the form. @@ -1680,9 +1651,9 @@ gfx_init_plane_horisontal2: { .label ay = 2 lda #gfxbCpuBank jsr dtvSetCpuBankSegment1 - lda #<$4000+(PLANE_HORISONTAL2&$3fff) + lda #<$4000 sta gfxa - lda #>$4000+(PLANE_HORISONTAL2&$3fff) + lda #>$4000 sta gfxa+1 lda #0 sta ay @@ -1753,9 +1724,9 @@ gfx_init_plane_horisontal: { .label ay = 2 lda #gfxbCpuBank jsr dtvSetCpuBankSegment1 - lda #<$4000+(PLANE_HORISONTAL&$3fff) + lda #<$4000 sta gfxa - lda #>$4000+(PLANE_HORISONTAL&$3fff) + lda #>$4000 sta gfxa+1 lda #0 sta ay @@ -1810,9 +1781,9 @@ gfx_init_plane_charset8: { lda #0 sta ch sta col - lda #<$4000+(PLANE_CHARSET8&$3fff) + lda #<$4000 sta gfxa - lda #>$4000+(PLANE_CHARSET8&$3fff) + lda #>$4000 sta gfxa+1 lda #<CHARGEN sta chargen @@ -2104,6 +2075,7 @@ bitmap_plot: { .label _0 = 3 .label plotter_x = 3 .label plotter_y = 5 + .label plotter = 3 lda bitmap_plot_xhi,x sta plotter_x+1 lda bitmap_plot_xlo,x @@ -2121,8 +2093,8 @@ bitmap_plot: { sta _0+1 lda bitmap_plot_bit,x ldy #0 - ora (_0),y - sta (_0),y + ora (plotter),y + sta (plotter),y rts } // bitmap_line_ydxi(byte zeropage($e) y, byte register(X) x, byte zeropage($12) y1, byte zeropage(7) yd, byte zeropage(8) xd) @@ -2260,7 +2232,7 @@ bitmap_clear: { } // Initialize the bitmap plotter tables for a specific bitmap bitmap_init: { - .label _6 = 2 + .label _10 = 2 .label yoffs = 3 ldy #$80 ldx #0 @@ -2288,15 +2260,14 @@ bitmap_init: { tax b3: lda #7 - sax _6 + sax _10 lda yoffs - ora _6 + ora _10 sta bitmap_plot_ylo,x lda yoffs+1 sta bitmap_plot_yhi,x - txa - and #7 - cmp #7 + lda #7 + cmp _10 bne b4 clc lda yoffs @@ -2563,6 +2534,9 @@ keyboard_init: { bitmap_plot_ylo: .fill $100, 0 bitmap_plot_yhi: .fill $100, 0 bitmap_plot_bit: .fill $100, 0 + // Charset ROM + FORM_TEXT: .text " C64 DTV Graphics Mode Explorer @ @ PRESET 0 Standard Charset @ @ CONTROL PLANE A VIC II @ bmm 0 pattern p0 screen s0 @ mcm 0 start 00 gfx g0 @ ecm 0 step 00 colors c0 @ hicolor 0 modulo 00 @ linear 0 COLORS @ color off 0 PLANE B palet 0 @ chunky 0 pattern p0 bgcol0 00 @ border off 0 start 00 bgcol1 00 @ overscan 0 step 00 bgcol2 00 @ modulo 00 bgcol3 00 @@" + FORM_COLS: .text "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@ @aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@ @ nnnnnnnnnnnn mmmmmmmmmm ooooooooo @ nnnnnnnnnnnn mmmmmmmmmm ooooooooo @ nnnnnnnnnnnn mmmmmmmmmm ooooooooo @ nnnnnnnnnnnn mmmmmmmmmm ooooooooo @ nnnnnnnnnnnn mmmmmmmmmm @ nnnnnnnnnnnn jjjjjjjjj @ nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @ nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @ nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @ nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @ nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @ nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @@" // Form fields x/y-positions form_fields_x: .byte 8, $c, $c, $c, $c, $c, $c, $c, $c, $c, $19, $18, $19, $18, $19, $18, $19, $19, $18, $19, $18, $19, $18, $19, $25, $25, $25, $25, $24, $25, $24, $25, $24, $25, $24, $25 form_fields_y: .byte 2, 5, 6, 7, 8, 9, $a, $b, $c, $d, 5, 6, 6, 7, 7, 8, 8, $b, $c, $c, $d, $d, $e, $e, 5, 6, 7, $a, $b, $b, $c, $c, $d, $d, $e, $e @@ -2595,6 +2569,3 @@ keyboard_init: { // Table with addresses of the y-lines of the form. The first line contains the address of the form screen. form_line_lo: .fill $19, 0 form_line_hi: .fill $19, 0 - // Charset ROM - FORM_TEXT: .text " C64 DTV Graphics Mode Explorer @"+" @"+" PRESET 0 Standard Charset @"+" @"+" CONTROL PLANE A VIC II @"+" bmm 0 pattern p0 screen s0 @"+" mcm 0 start 00 gfx g0 @"+" ecm 0 step 00 colors c0 @"+" hicolor 0 modulo 00 @"+" linear 0 COLORS @"+" color off 0 PLANE B palet 0 @"+" chunky 0 pattern p0 bgcol0 00 @"+" border off 0 start 00 bgcol1 00 @"+" overscan 0 step 00 bgcol2 00 @"+" modulo 00 bgcol3 00 @"+"@" - FORM_COLS: .text "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@"+" @"+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@"+" @"+" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"+" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"+" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"+" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"+" nnnnnnnnnnnn mmmmmmmmmm @"+" nnnnnnnnnnnn jjjjjjjjj @"+" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"+" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"+" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"+" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"+" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"+" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"+"@" diff --git a/src/test/ref/c64dtv-gfxmodes.asm b/src/test/ref/c64dtv-gfxmodes.asm index e496af02c..429e6c1c9 100644 --- a/src/test/ref/c64dtv-gfxmodes.asm +++ b/src/test/ref/c64dtv-gfxmodes.asm @@ -120,10 +120,10 @@ menu: { .label c = 2 // Charset ROM // DTV Graphics Bank - lda #($ffffffff&CHARSET)/$10000 + lda #0 sta DTV_GRAPHICS_VIC_BANK // DTV Color Bank - lda #DTV_COLOR_BANK_DEFAULT/$400 + lda #<DTV_COLOR_BANK_DEFAULT/$400 sta DTV_COLOR_BANK_LO lda #0 sta DTV_COLOR_BANK_HI @@ -142,7 +142,7 @@ menu: { lda #VIC_CSEL sta VIC_CONTROL2 // VIC Memory Pointers - lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400 + lda #(CHARSET&$3fff)/$400 sta VIC_MEMORY ldx #0 // DTV Palette - default @@ -286,11 +286,10 @@ mode_8bppchunkybmm: { lda #VIC_MCM|VIC_CSEL sta VIC_CONTROL2 // Linear Graphics Plane B Counter - lda #PLANEB&$ffff - sta DTV_PLANEB_START_LO lda #0 + sta DTV_PLANEB_START_LO sta DTV_PLANEB_START_MI - lda #PLANEB>>$10 + lda #<PLANEB>>$10 sta DTV_PLANEB_START_HI lda #8 sta DTV_PLANEB_STEP @@ -525,7 +524,7 @@ mode_8bpppixelcell: { lda #VIC_MCM|VIC_CSEL sta VIC_CONTROL2 // Linear Graphics Plane A Counter - lda #<PLANEA + lda #0 sta DTV_PLANEA_START_LO lda #>PLANEA sta DTV_PLANEA_START_MI @@ -537,7 +536,6 @@ mode_8bpppixelcell: { sta DTV_PLANEA_MODULO_LO sta DTV_PLANEA_MODULO_HI // Linear Graphics Plane B Counter - lda #<PLANEB sta DTV_PLANEB_START_LO lda #>PLANEB sta DTV_PLANEB_START_MI @@ -674,7 +672,7 @@ mode_sixsfred: { lda #VIC_MCM|VIC_CSEL sta VIC_CONTROL2 // Linear Graphics Plane A Counter - lda #<PLANEA + lda #0 sta DTV_PLANEA_START_LO lda #>PLANEA sta DTV_PLANEA_START_MI @@ -686,7 +684,6 @@ mode_sixsfred: { sta DTV_PLANEA_MODULO_LO sta DTV_PLANEA_MODULO_HI // Linear Graphics Plane B Counter - lda #<PLANEB sta DTV_PLANEB_START_LO lda #>PLANEB sta DTV_PLANEB_START_MI @@ -700,9 +697,9 @@ mode_sixsfred: { // DTV Color Bank lda #<COLORS/$400 sta DTV_COLOR_BANK_LO - lda #>COLORS/$400 + lda #0 sta DTV_COLOR_BANK_HI - ldx #0 + tax // DTV Palette - Grey Tones b1: txa @@ -823,7 +820,7 @@ mode_twoplanebitmap: { lda #VIC_CSEL sta VIC_CONTROL2 // Linear Graphics Plane A Counter - lda #<PLANEA + lda #0 sta DTV_PLANEA_START_LO lda #>PLANEA sta DTV_PLANEA_START_MI @@ -835,7 +832,6 @@ mode_twoplanebitmap: { sta DTV_PLANEA_MODULO_LO sta DTV_PLANEA_MODULO_HI // Linear Graphics Plane B Counter - lda #<PLANEB sta DTV_PLANEB_START_LO lda #>PLANEB sta DTV_PLANEB_START_MI @@ -849,9 +845,9 @@ mode_twoplanebitmap: { // DTV Color Bank lda #<COLORS/$400 sta DTV_COLOR_BANK_LO - lda #>COLORS/$400 + lda #0 sta DTV_COLOR_BANK_HI - ldx #0 + tax // DTV Palette - Grey Tones b1: txa @@ -989,7 +985,7 @@ mode_sixsfred2: { lda #VIC_MCM|VIC_CSEL sta VIC_CONTROL2 // Linear Graphics Plane A Counter - lda #<PLANEA + lda #0 sta DTV_PLANEA_START_LO lda #>PLANEA sta DTV_PLANEA_START_MI @@ -1001,7 +997,6 @@ mode_sixsfred2: { sta DTV_PLANEA_MODULO_LO sta DTV_PLANEA_MODULO_HI // Linear Graphics Plane B Counter - lda #<PLANEB sta DTV_PLANEB_START_LO lda #>PLANEB sta DTV_PLANEB_START_MI @@ -1015,9 +1010,9 @@ mode_sixsfred2: { // DTV Color Bank lda #<COLORS/$400 sta DTV_COLOR_BANK_LO - lda #>COLORS/$400 + lda #0 sta DTV_COLOR_BANK_HI - ldx #0 + tax // DTV Palette - Grey Tones b1: txa @@ -1138,10 +1133,10 @@ mode_hicolmcchar: { .label ch = 5 .label cy = 4 // DTV Graphics Bank - lda #($ffffffff&CHARSET)/$10000 + lda #0 sta DTV_GRAPHICS_VIC_BANK // DTV Color Bank - lda #COLORS/$400 + lda #<COLORS/$400 sta DTV_COLOR_BANK_LO lda #0 sta DTV_COLOR_BANK_HI @@ -1160,7 +1155,7 @@ mode_hicolmcchar: { lda #VIC_CSEL|VIC_MCM sta VIC_CONTROL2 // VIC Memory Pointers - lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400 + lda #(CHARSET&$3fff)/$400 sta VIC_MEMORY ldx #0 // DTV Palette - Grey Tones @@ -1247,10 +1242,10 @@ mode_hicolecmchar: { .label ch = 5 .label cy = 4 // DTV Graphics Bank - lda #($ffffffff&CHARSET)/$10000 + lda #0 sta DTV_GRAPHICS_VIC_BANK // DTV Color Bank - lda #COLORS/$400 + lda #<COLORS/$400 sta DTV_COLOR_BANK_LO lda #0 sta DTV_COLOR_BANK_HI @@ -1269,7 +1264,7 @@ mode_hicolecmchar: { lda #VIC_CSEL sta VIC_CONTROL2 // VIC Memory Pointers - lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400 + lda #(CHARSET&$3fff)/$400 sta VIC_MEMORY ldx #0 // DTV Palette - Grey Tones @@ -1354,10 +1349,10 @@ mode_hicolstdchar: { .label ch = 5 .label cy = 4 // DTV Graphics Bank - lda #($ffffffff&CHARSET)/$10000 + lda #0 sta DTV_GRAPHICS_VIC_BANK // DTV Color Bank - lda #COLORS/$400 + lda #<COLORS/$400 sta DTV_COLOR_BANK_LO lda #0 sta DTV_COLOR_BANK_HI @@ -1376,7 +1371,7 @@ mode_hicolstdchar: { lda #VIC_CSEL sta VIC_CONTROL2 // VIC Memory Pointers - lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400 + lda #(CHARSET&$3fff)/$400 sta VIC_MEMORY ldx #0 // DTV Palette - Grey Tones @@ -1453,9 +1448,8 @@ mode_stdbitmap: { .label cy = 4 .label l = 4 // DTV Graphics Bank - lda #($ffffffff&BITMAP)/$10000 - sta DTV_GRAPHICS_VIC_BANK lda #0 + sta DTV_GRAPHICS_VIC_BANK sta DTV_CONTROL // VIC Graphics Bank lda #3 @@ -1470,7 +1464,7 @@ mode_stdbitmap: { lda #VIC_CSEL sta VIC_CONTROL2 // VIC Memory Pointers - lda #(SCREEN&$3fff)/$40|(BITMAP&$3fff)/$400 + lda #(BITMAP&$3fff)/$400 sta VIC_MEMORY ldx #0 // DTV Palette - default @@ -1694,6 +1688,7 @@ bitmap_plot: { .label _0 = 2 .label plotter_x = 2 .label plotter_y = 5 + .label plotter = 2 lda bitmap_plot_xhi,x sta plotter_x+1 lda bitmap_plot_xlo,x @@ -1711,8 +1706,8 @@ bitmap_plot: { sta _0+1 lda bitmap_plot_bit,x ldy #0 - ora (_0),y - sta (_0),y + ora (plotter),y + sta (plotter),y rts } // bitmap_line_ydxi(byte zeropage($a) y, byte register(X) x, byte zeropage($c) y1, byte zeropage(7) yd, byte zeropage(8) xd) @@ -1850,7 +1845,7 @@ bitmap_clear: { } // Initialize the bitmap plotter tables for a specific bitmap bitmap_init: { - .label _6 = 4 + .label _10 = 4 .label yoffs = 2 ldy #$80 ldx #0 @@ -1878,15 +1873,14 @@ bitmap_init: { tax b3: lda #7 - sax _6 + sax _10 lda yoffs - ora _6 + ora _10 sta bitmap_plot_ylo,x lda yoffs+1 sta bitmap_plot_yhi,x - txa - and #7 - cmp #7 + lda #7 + cmp _10 bne b4 clc lda yoffs @@ -1923,10 +1917,10 @@ mode_mcchar: { .label ch = 5 .label cy = 4 // DTV Graphics Bank - lda #($ffffffff&CHARSET)/$10000 + lda #0 sta DTV_GRAPHICS_VIC_BANK // DTV Color Bank - lda #DTV_COLOR_BANK_DEFAULT/$400 + lda #<DTV_COLOR_BANK_DEFAULT/$400 sta DTV_COLOR_BANK_LO lda #0 sta DTV_COLOR_BANK_HI @@ -1944,7 +1938,7 @@ mode_mcchar: { lda #VIC_CSEL|VIC_MCM sta VIC_CONTROL2 // VIC Memory Pointers - lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400 + lda #(CHARSET&$3fff)/$400 sta VIC_MEMORY ldx #0 // DTV Palette - default @@ -2035,10 +2029,10 @@ mode_ecmchar: { .label ch = 5 .label cy = 4 // DTV Graphics Bank - lda #($ffffffff&CHARSET)/$10000 + lda #0 sta DTV_GRAPHICS_VIC_BANK // DTV Color Bank - lda #DTV_COLOR_BANK_DEFAULT/$400 + lda #<DTV_COLOR_BANK_DEFAULT/$400 sta DTV_COLOR_BANK_LO lda #0 sta DTV_COLOR_BANK_HI @@ -2056,7 +2050,7 @@ mode_ecmchar: { lda #VIC_CSEL sta VIC_CONTROL2 // VIC Memory Pointers - lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400 + lda #(CHARSET&$3fff)/$400 sta VIC_MEMORY ldx #0 // DTV Palette - default @@ -2144,10 +2138,10 @@ mode_stdchar: { .label ch = 5 .label cy = 4 // DTV Graphics Bank - lda #($ffffffff&CHARSET)/$10000 + lda #0 sta DTV_GRAPHICS_VIC_BANK // DTV Color Bank - lda #DTV_COLOR_BANK_DEFAULT/$400 + lda #<DTV_COLOR_BANK_DEFAULT/$400 sta DTV_COLOR_BANK_LO lda #0 sta DTV_COLOR_BANK_HI @@ -2165,7 +2159,7 @@ mode_stdchar: { lda #VIC_CSEL sta VIC_CONTROL2 // VIC Memory Pointers - lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400 + lda #(CHARSET&$3fff)/$400 sta VIC_MEMORY ldx #0 // DTV Palette - default @@ -2337,4 +2331,4 @@ print_set_screen: { bitmap_plot_ylo: .fill $100, 0 bitmap_plot_yhi: .fill $100, 0 bitmap_plot_bit: .fill $100, 0 - MENU_TEXT: .text "C64DTV Graphics Modes CCLHBME@"+" OHIIMCC@"+" LUNCMMM@"+"----------------------------------------@"+"1. Standard Char (V) 0000000@"+"2. Extended Color Char (V) 0000001@"+"3. Multicolor Char (V) 0000010@"+"4. Standard Bitmap (V) 0000100@"+"5. Multicolor Bitmap (V) 0000110@"+"6. High Color Standard Char (H) 0001000@"+"7. High Extended Color Char (H) 0001001@"+"8. High Multicolor Char (H) 0001010@"+"9. High Multicolor Bitmap (H) 0001110@"+"a. Sixs Fred 2 (D) 0010111@"+"b. Two Plane Bitmap (D) 0011101@"+"c. Sixs Fred (2 Plane MC BM) (D) 0011111@"+"d. 8bpp Pixel Cell (D) 0111011@"+"e. Chunky 8bpp Bitmap (D) 1111011@"+"----------------------------------------@"+" (V) vicII (H) vicII+hicol (D) c64dtv@"+"@" + MENU_TEXT: .text "C64DTV Graphics Modes CCLHBME@ OHIIMCC@ LUNCMMM@----------------------------------------@1. Standard Char (V) 0000000@2. Extended Color Char (V) 0000001@3. Multicolor Char (V) 0000010@4. Standard Bitmap (V) 0000100@5. Multicolor Bitmap (V) 0000110@6. High Color Standard Char (H) 0001000@7. High Extended Color Char (H) 0001001@8. High Multicolor Char (H) 0001010@9. High Multicolor Bitmap (H) 0001110@a. Sixs Fred 2 (D) 0010111@b. Two Plane Bitmap (D) 0011101@c. Sixs Fred (2 Plane MC BM) (D) 0011111@d. 8bpp Pixel Cell (D) 0111011@e. Chunky 8bpp Bitmap (D) 1111011@----------------------------------------@ (V) vicII (H) vicII+hicol (D) c64dtv@@" diff --git a/src/test/ref/concat-char.asm b/src/test/ref/concat-char.asm deleted file mode 100644 index 921520657..000000000 --- a/src/test/ref/concat-char.asm +++ /dev/null @@ -1,16 +0,0 @@ -// Concatenate a char to a string -.pc = $801 "Basic" -:BasicUpstart(main) -.pc = $80d "Program" -main: { - .label screen = $400 - ldx #0 - b1: - lda msg,x - sta screen,x - inx - cpx #3 - bne b1 - rts - msg: .text "cm"+'l' -} diff --git a/src/test/ref/concat-char.cfg b/src/test/ref/concat-char.cfg deleted file mode 100644 index d85c7528b..000000000 --- a/src/test/ref/concat-char.cfg +++ /dev/null @@ -1,21 +0,0 @@ -@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::@1 - [5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::i#1 ) - [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) - [7] (byte) main::i#1 ← ++ (byte) main::i#2 - [8] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 - to:main::@return -main::@return: scope:[main] from main::@1 - [9] return - to:@return diff --git a/src/test/ref/concat-char.log b/src/test/ref/concat-char.log deleted file mode 100644 index 492facbb5..000000000 --- a/src/test/ref/concat-char.log +++ /dev/null @@ -1,338 +0,0 @@ -Identified constant variable (byte*) main::screen -Identified constant variable (byte) main::l - -CONTROL FLOW GRAPH SSA -@begin: scope:[] from - to:@1 -main: scope:[main] from @1 - (byte*) main::screen#0 ← ((byte*)) (word/signed word/dword/signed dword) $400 - (byte) main::l#0 ← (byte) 'l' - (string~) main::$0 ← (const string) main::$2 + (byte) main::l#0 - (byte[]) main::msg#0 ← (string~) main::$0 - (byte) main::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 - to:main::@1 -main::@1: scope:[main] from main main::@1 - (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) - *((byte*) main::screen#0 + (byte) main::i#2) ← *((byte[]) main::msg#0 + (byte) main::i#2) - (byte) main::i#1 ← (byte) main::i#2 + rangenext(0,2) - (bool~) main::$1 ← (byte) main::i#1 != rangelast(0,2) - if((bool~) main::$1) goto main::@1 - to:main::@return -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 -(void()) main() -(string~) main::$0 -(bool~) main::$1 -(const string) main::$2 = (string) "cm" -(label) main::@1 -(label) main::@return -(byte) main::i -(byte) main::i#0 -(byte) main::i#1 -(byte) main::i#2 -(byte) main::l -(byte) main::l#0 -(byte[]) main::msg -(byte[]) main::msg#0 -(byte*) main::screen -(byte*) main::screen#0 - -Culled Empty Block (label) @2 -Successful SSA optimization Pass2CullEmptyBlocks -Alias (byte[]) main::msg#0 = (string~) main::$0 -Successful SSA optimization Pass2AliasElimination -Simple Condition (bool~) main::$1 [9] if((byte) main::i#1!=rangelast(0,2)) goto main::@1 -Successful SSA optimization Pass2ConditionalJumpSimplification -Constant (const byte*) main::screen#0 = ((byte*))$400 -Constant (const byte) main::l#0 = 'l' -Constant (const byte) main::i#0 = 0 -Successful SSA optimization Pass2ConstantIdentification -Constant (const byte[]) main::msg#0 = "cm"+'l' -Successful SSA optimization Pass2ConstantIdentification -Eliminating unused constant (const string) main::$2 -Eliminating unused constant (const byte) main::l#0 -Successful SSA optimization PassNEliminateUnusedVars -Resolved ranged next value main::i#1 ← ++ main::i#2 to ++ -Resolved ranged comparison value if(main::i#1!=rangelast(0,2)) goto main::@1 to (byte/signed byte/word/signed word/dword/signed dword) 3 -Inlining constant with var siblings (const byte) main::i#0 -Constant inlined main::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0 -Successful SSA optimization Pass2ConstantInlining -Added new block during phi lifting main::@3(between main::@1 and main::@1) -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 -CALL GRAPH -Calls in [] to main:2 - -Created 1 initial phi equivalence classes -Coalesced [10] main::i#3 ← main::i#1 -Coalesced down to 1 phi equivalence classes -Culled Empty Block (label) main::@3 -Adding NOP phi() at start of @begin -Adding NOP phi() at start of @1 -Adding NOP phi() at start of @end -Adding NOP phi() at start of main - -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::@1 - [5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::i#1 ) - [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) - [7] (byte) main::i#1 ← ++ (byte) main::i#2 - [8] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 - to:main::@return -main::@return: scope:[main] from main::@1 - [9] return - to:@return - - -VARIABLE REGISTER WEIGHTS -(void()) main() -(byte) main::i -(byte) main::i#1 16.5 -(byte) main::i#2 22.0 -(byte) main::l -(byte[]) main::msg -(byte*) main::screen - -Initial phi equivalence classes -[ main::i#2 main::i#1 ] -Complete equivalence classes -[ main::i#2 main::i#1 ] -Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ] - -INITIAL ASM -//SEG0 File Comments -// Concatenate a char to a string -//SEG1 Basic Upstart -.pc = $801 "Basic" -:BasicUpstart(bbegin) -.pc = $80d "Program" -//SEG2 Global Constants & labels -//SEG3 @begin -bbegin: -//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] -b1_from_bbegin: - jmp b1 -//SEG5 @1 -b1: -//SEG6 [2] call main -//SEG7 [4] phi from @1 to main [phi:@1->main] -main_from_b1: - jsr main -//SEG8 [3] phi from @1 to @end [phi:@1->@end] -bend_from_b1: - jmp bend -//SEG9 @end -bend: -//SEG10 main -main: { - .label screen = $400 - .label i = 2 - //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] - b1_from_main: - //SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 - lda #0 - sta i - jmp b1 - //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] - b1_from_b1: - //SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy - jmp b1 - //SEG15 main::@1 - b1: - //SEG16 [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz1 - ldy i - lda msg,y - sta screen,y - //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 - inc i - //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 - lda #3 - cmp i - bne b1_from_b1 - jmp breturn - //SEG19 main::@return - breturn: - //SEG20 [9] return - rts - msg: .text "cm"+'l' -} - -REGISTER UPLIFT POTENTIAL REGISTERS -Statement [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ] -Statement [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a -Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y , - -REGISTER UPLIFT SCOPES -Uplift Scope [main] 38.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] -Uplift Scope [] - -Uplifting [main] best 288 combination reg byte x [ main::i#2 main::i#1 ] -Uplifting [] best 288 combination - -ASSEMBLER BEFORE OPTIMIZATION -//SEG0 File Comments -// Concatenate a char to a string -//SEG1 Basic Upstart -.pc = $801 "Basic" -:BasicUpstart(bbegin) -.pc = $80d "Program" -//SEG2 Global Constants & labels -//SEG3 @begin -bbegin: -//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] -b1_from_bbegin: - jmp b1 -//SEG5 @1 -b1: -//SEG6 [2] call main -//SEG7 [4] phi from @1 to main [phi:@1->main] -main_from_b1: - jsr main -//SEG8 [3] phi from @1 to @end [phi:@1->@end] -bend_from_b1: - jmp bend -//SEG9 @end -bend: -//SEG10 main -main: { - .label screen = $400 - //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] - b1_from_main: - //SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 - ldx #0 - jmp b1 - //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] - b1_from_b1: - //SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy - jmp b1 - //SEG15 main::@1 - b1: - //SEG16 [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx - lda msg,x - sta screen,x - //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx - inx - //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 - cpx #3 - bne b1_from_b1 - jmp breturn - //SEG19 main::@return - breturn: - //SEG20 [9] return - rts - msg: .text "cm"+'l' -} - -ASSEMBLER OPTIMIZATIONS -Removing instruction jmp b1 -Removing instruction jmp bend -Removing instruction jmp b1 -Removing instruction jmp breturn -Succesful ASM optimization Pass5NextJumpElimination -Replacing label b1_from_b1 with b1 -Removing instruction b1_from_bbegin: -Removing instruction b1: -Removing instruction main_from_b1: -Removing instruction bend_from_b1: -Removing instruction b1_from_b1: -Succesful ASM optimization Pass5RedundantLabelElimination -Removing instruction bend: -Removing instruction b1_from_main: -Removing instruction breturn: -Succesful ASM optimization Pass5UnusedLabelElimination -Updating BasicUpstart to call main directly -Removing instruction jsr main -Succesful ASM optimization Pass5SkipBegin -Removing instruction jmp b1 -Succesful ASM optimization Pass5NextJumpElimination -Removing instruction bbegin: -Succesful ASM optimization Pass5UnusedLabelElimination - -FINAL SYMBOL TABLE -(label) @1 -(label) @begin -(label) @end -(void()) main() -(label) main::@1 -(label) main::@return -(byte) main::i -(byte) main::i#1 reg byte x 16.5 -(byte) main::i#2 reg byte x 22.0 -(byte) main::l -(byte[]) main::msg -(const byte[]) main::msg#0 msg = (string) "cm"+(byte) 'l' -(byte*) main::screen -(const byte*) main::screen#0 screen = ((byte*))(word/signed word/dword/signed dword) $400 - -reg byte x [ main::i#2 main::i#1 ] - - -FINAL ASSEMBLER -Score: 186 - -//SEG0 File Comments -// Concatenate a char to a string -//SEG1 Basic Upstart -.pc = $801 "Basic" -:BasicUpstart(main) -.pc = $80d "Program" -//SEG2 Global Constants & labels -//SEG3 @begin -//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] -//SEG5 @1 -//SEG6 [2] call main -//SEG7 [4] phi from @1 to main [phi:@1->main] -//SEG8 [3] phi from @1 to @end [phi:@1->@end] -//SEG9 @end -//SEG10 main -main: { - .label screen = $400 - //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] - //SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 - ldx #0 - //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] - //SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy - //SEG15 main::@1 - b1: - //SEG16 [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx - lda msg,x - sta screen,x - //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx - inx - //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 - cpx #3 - bne b1 - //SEG19 main::@return - //SEG20 [9] return - rts - msg: .text "cm"+'l' -} - diff --git a/src/test/ref/concat-char.sym b/src/test/ref/concat-char.sym deleted file mode 100644 index 118c86105..000000000 --- a/src/test/ref/concat-char.sym +++ /dev/null @@ -1,16 +0,0 @@ -(label) @1 -(label) @begin -(label) @end -(void()) main() -(label) main::@1 -(label) main::@return -(byte) main::i -(byte) main::i#1 reg byte x 16.5 -(byte) main::i#2 reg byte x 22.0 -(byte) main::l -(byte[]) main::msg -(const byte[]) main::msg#0 msg = (string) "cm"+(byte) 'l' -(byte*) main::screen -(const byte*) main::screen#0 screen = ((byte*))(word/signed word/dword/signed dword) $400 - -reg byte x [ main::i#2 main::i#1 ] diff --git a/src/test/ref/constant-string-concat-0.asm b/src/test/ref/constant-string-concat-0.asm new file mode 100644 index 000000000..7fff00ab2 --- /dev/null +++ b/src/test/ref/constant-string-concat-0.asm @@ -0,0 +1,17 @@ +// Concatenates string constants in different ways +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label SCREEN = $400 + ldx #0 + b1: + lda msg,x + sta SCREEN,x + inx + lda msg,x + cmp #0 + bne b1 + rts + msg: .text "camelot@" +} diff --git a/src/test/ref/constant-string-concat.asm b/src/test/ref/constant-string-concat.asm index 4fa0ed741..c832a5567 100644 --- a/src/test/ref/constant-string-concat.asm +++ b/src/test/ref/constant-string-concat.asm @@ -6,14 +6,11 @@ main: { .label SCREEN = $400 ldx #0 b1: - lda s5,x + lda s,x sta SCREEN,x inx cpx #8 bne b1 rts - s: .text "e"+"l" - s4: .text ""+'t'+'!' - s3: .text "cam"+s+'o' - s5: .text s3+s4 + s: .text "camelot@" } diff --git a/src/test/ref/literals.asm b/src/test/ref/literals.asm index 3ad59a6a7..31f1584a0 100644 --- a/src/test/ref/literals.asm +++ b/src/test/ref/literals.asm @@ -20,5 +20,5 @@ main: { bne b1 rts } + str: .text "bcde@" nums: .byte 2, 3, 4, 5 - str: .text "bc"+"d"+'e' From 75af42ad3f6c6e8c8d090fed2fb81a925d82290c Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Fri, 24 May 2019 23:00:13 +0200 Subject: [PATCH 88/93] Added struct syntax --- .../java/dk/camelot64/kickc/parser/KickC.g4 | 15 + .../dk/camelot64/kickc/parser/KickC.tokens | 130 +- .../kickc/parser/KickCBaseListener.java | 60 + .../kickc/parser/KickCBaseVisitor.java | 35 + .../dk/camelot64/kickc/parser/KickCLexer.java | 732 +++---- .../camelot64/kickc/parser/KickCLexer.tokens | 130 +- .../camelot64/kickc/parser/KickCListener.java | 54 + .../camelot64/kickc/parser/KickCParser.java | 1738 ++++++++++------- .../camelot64/kickc/parser/KickCVisitor.java | 32 + 9 files changed, 1687 insertions(+), 1239 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 index a30ea0b67..117fd6732 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 +++ b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 @@ -23,6 +23,7 @@ declSeq decl : declVariables ';' + | structDef ';' | declFunction | declKasm | globalDirective @@ -112,6 +113,20 @@ typeDecl | typeDecl '*' #typePtr | typeDecl '[' (expr)? ']' #typeArray | typeDecl '(' ')' #typeProcedure + | structDef #typeStructDef + | structRef #typeStructRef + ; + +structRef + : 'struct' NAME + ; + +structDef + : 'struct' NAME? '{' structMembers+ '}' + ; + +structMembers + : declVariables ';' ; commaExpr diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.tokens b/src/main/java/dk/camelot64/kickc/parser/KickC.tokens index c69744d23..a303b96fe 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickC.tokens +++ b/src/main/java/dk/camelot64/kickc/parser/KickC.tokens @@ -74,26 +74,27 @@ T__72=73 T__73=74 T__74=75 T__75=76 -MNEMONIC=77 -KICKASM=78 -SIMPLETYPE=79 -STRING=80 -CHAR=81 -BOOLEAN=82 -NUMBER=83 -NUMFLOAT=84 -BINFLOAT=85 -DECFLOAT=86 -HEXFLOAT=87 -NUMINT=88 -BININTEGER=89 -DECINTEGER=90 -HEXINTEGER=91 -NAME=92 -ASMREL=93 -WS=94 -COMMENT_LINE=95 -COMMENT_BLOCK=96 +T__76=77 +MNEMONIC=78 +KICKASM=79 +SIMPLETYPE=80 +STRING=81 +CHAR=82 +BOOLEAN=83 +NUMBER=84 +NUMFLOAT=85 +BINFLOAT=86 +DECFLOAT=87 +HEXFLOAT=88 +NUMINT=89 +BININTEGER=90 +DECINTEGER=91 +HEXINTEGER=92 +NAME=93 +ASMREL=94 +WS=95 +COMMENT_LINE=96 +COMMENT_BLOCK=97 'import'=1 ';'=2 ','=3 @@ -126,47 +127,48 @@ COMMENT_BLOCK=96 '*'=30 '['=31 ']'=32 -'sizeof'=33 -'typeid'=34 -'--'=35 -'++'=36 -'+'=37 -'-'=38 -'!'=39 -'&'=40 -'~'=41 -'>>'=42 -'<<'=43 -'/'=44 -'%'=45 -'<'=46 -'>'=47 -'=='=48 -'!='=49 -'<='=50 -'>='=51 -'^'=52 -'|'=53 -'&&'=54 -'||'=55 -'?'=56 -'+='=57 -'-='=58 -'*='=59 -'/='=60 -'%='=61 -'<<='=62 -'>>='=63 -'&='=64 -'|='=65 -'^='=66 -'kickasm'=67 -'resource'=68 -'uses'=69 -'clobbers'=70 -'bytes'=71 -'cycles'=72 -'pc'=73 -'.byte'=74 -'#'=75 -'.'=76 +'struct'=33 +'sizeof'=34 +'typeid'=35 +'--'=36 +'++'=37 +'+'=38 +'-'=39 +'!'=40 +'&'=41 +'~'=42 +'>>'=43 +'<<'=44 +'/'=45 +'%'=46 +'<'=47 +'>'=48 +'=='=49 +'!='=50 +'<='=51 +'>='=52 +'^'=53 +'|'=54 +'&&'=55 +'||'=56 +'?'=57 +'+='=58 +'-='=59 +'*='=60 +'/='=61 +'%='=62 +'<<='=63 +'>>='=64 +'&='=65 +'|='=66 +'^='=67 +'kickasm'=68 +'resource'=69 +'uses'=70 +'clobbers'=71 +'bytes'=72 +'cycles'=73 +'pc'=74 +'.byte'=75 +'#'=76 +'.'=77 diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java index 02bba947a..b8a02352a 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java @@ -551,6 +551,18 @@ public class KickCBaseListener implements KickCListener { * <p>The default implementation does nothing.</p> */ @Override public void exitTypeArray(KickCParser.TypeArrayContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void enterTypeStructRef(KickCParser.TypeStructRefContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void exitTypeStructRef(KickCParser.TypeStructRefContext ctx) { } /** * {@inheritDoc} * @@ -563,6 +575,18 @@ public class KickCBaseListener implements KickCListener { * <p>The default implementation does nothing.</p> */ @Override public void exitTypeSimple(KickCParser.TypeSimpleContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void enterTypeStructDef(KickCParser.TypeStructDefContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void exitTypeStructDef(KickCParser.TypeStructDefContext ctx) { } /** * {@inheritDoc} * @@ -575,6 +599,42 @@ public class KickCBaseListener implements KickCListener { * <p>The default implementation does nothing.</p> */ @Override public void exitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void enterStructRef(KickCParser.StructRefContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void exitStructRef(KickCParser.StructRefContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void enterStructDef(KickCParser.StructDefContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void exitStructDef(KickCParser.StructDefContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void enterStructMembers(KickCParser.StructMembersContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void exitStructMembers(KickCParser.StructMembersContext ctx) { } /** * {@inheritDoc} * diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java index 709766578..2cba0e61e 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java @@ -326,6 +326,13 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements * {@link #visitChildren} on {@code ctx}.</p> */ @Override public T visitTypeArray(KickCParser.TypeArrayContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + * <p>The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.</p> + */ + @Override public T visitTypeStructRef(KickCParser.TypeStructRefContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * @@ -333,6 +340,13 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements * {@link #visitChildren} on {@code ctx}.</p> */ @Override public T visitTypeSimple(KickCParser.TypeSimpleContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + * <p>The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.</p> + */ + @Override public T visitTypeStructDef(KickCParser.TypeStructDefContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * @@ -340,6 +354,27 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements * {@link #visitChildren} on {@code ctx}.</p> */ @Override public T visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + * <p>The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.</p> + */ + @Override public T visitStructRef(KickCParser.StructRefContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + * <p>The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.</p> + */ + @Override public T visitStructDef(KickCParser.StructDefContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + * <p>The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.</p> + */ + @Override public T visitStructMembers(KickCParser.StructMembersContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java index 951b0e72e..594b24209 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java @@ -27,10 +27,10 @@ public class KickCLexer extends Lexer { T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, - T__73=74, T__74=75, T__75=76, MNEMONIC=77, KICKASM=78, SIMPLETYPE=79, - STRING=80, CHAR=81, BOOLEAN=82, NUMBER=83, NUMFLOAT=84, BINFLOAT=85, DECFLOAT=86, - HEXFLOAT=87, NUMINT=88, BININTEGER=89, DECINTEGER=90, HEXINTEGER=91, NAME=92, - ASMREL=93, WS=94, COMMENT_LINE=95, COMMENT_BLOCK=96; + T__73=74, T__74=75, T__75=76, T__76=77, MNEMONIC=78, KICKASM=79, SIMPLETYPE=80, + STRING=81, CHAR=82, BOOLEAN=83, NUMBER=84, NUMFLOAT=85, BINFLOAT=86, DECFLOAT=87, + HEXFLOAT=88, NUMINT=89, BININTEGER=90, DECINTEGER=91, HEXINTEGER=92, NAME=93, + ASMREL=94, WS=95, COMMENT_LINE=96, COMMENT_BLOCK=97; public static String[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -49,11 +49,11 @@ public class KickCLexer extends Lexer { "T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56", "T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64", "T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "T__71", "T__72", - "T__73", "T__74", "T__75", "MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", - "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", - "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "BINDIGIT", "DECDIGIT", - "HEXDIGIT", "NAME", "NAME_START", "NAME_CHAR", "ASMREL", "WS", "COMMENT_LINE", - "COMMENT_BLOCK" + "T__73", "T__74", "T__75", "T__76", "MNEMONIC", "KICKASM", "SIMPLETYPE", + "STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", + "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "BINDIGIT", + "DECDIGIT", "HEXDIGIT", "NAME", "NAME_START", "NAME_CHAR", "ASMREL", "WS", + "COMMENT_LINE", "COMMENT_BLOCK" }; private static final String[] _LITERAL_NAMES = { @@ -61,12 +61,12 @@ public class KickCLexer extends Lexer { "'extern'", "'align'", "'register'", "'inline'", "'volatile'", "'interrupt'", "'reserve'", "'if'", "'else'", "'while'", "'do'", "'for'", "'return'", "'break'", "'continue'", "'asm'", "':'", "'..'", "'signed'", "'unsigned'", - "'*'", "'['", "']'", "'sizeof'", "'typeid'", "'--'", "'++'", "'+'", "'-'", - "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", "'>'", "'=='", - "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", "'+='", "'-='", - "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", "'^='", "'kickasm'", - "'resource'", "'uses'", "'clobbers'", "'bytes'", "'cycles'", "'pc'", "'.byte'", - "'#'", "'.'" + "'*'", "'['", "']'", "'struct'", "'sizeof'", "'typeid'", "'--'", "'++'", + "'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", + "'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", + "'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", + "'^='", "'kickasm'", "'resource'", "'uses'", "'clobbers'", "'bytes'", + "'cycles'", "'pc'", "'.byte'", "'#'", "'.'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null, null, @@ -75,10 +75,10 @@ public class KickCLexer extends Lexer { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", - "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", - "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "ASMREL", - "WS", "COMMENT_LINE", "COMMENT_BLOCK" + null, null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", + "STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", + "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", + "ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -138,7 +138,7 @@ public class KickCLexer extends Lexer { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2b\u03dc\b\1\4\2\t"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2c\u03e5\b\1\4\2\t"+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -149,350 +149,354 @@ public class KickCLexer extends Lexer { "\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+ "\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+ "\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+ - "`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3"+ - "\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\n\3\n"+ - "\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3"+ - "\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16"+ - "\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20"+ - "\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\22"+ - "\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\25"+ - "\3\25\3\25\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\30"+ - "\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31"+ - "\3\32\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\35"+ - "\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3 \3"+ - " \3!\3!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3#\3#\3#\3#\3#\3#\3#\3$\3$\3$\3%\3"+ - "%\3%\3&\3&\3\'\3\'\3(\3(\3)\3)\3*\3*\3+\3+\3+\3,\3,\3,\3-\3-\3.\3.\3/"+ - "\3/\3\60\3\60\3\61\3\61\3\61\3\62\3\62\3\62\3\63\3\63\3\63\3\64\3\64\3"+ - "\64\3\65\3\65\3\66\3\66\3\67\3\67\3\67\38\38\38\39\39\3:\3:\3:\3;\3;\3"+ - ";\3<\3<\3<\3=\3=\3=\3>\3>\3>\3?\3?\3?\3?\3@\3@\3@\3@\3A\3A\3A\3B\3B\3"+ - "B\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3E\3E\3F\3F\3"+ - "F\3F\3F\3G\3G\3G\3G\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3"+ - "I\3I\3J\3J\3J\3K\3K\3K\3K\3K\3K\3L\3L\3M\3M\3N\3N\3N\3N\3N\3N\3N\3N\3"+ - "N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+ - "N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+ - "N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+ - "N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+ - "N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+ - "N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+ - "N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+ - "N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+ - "N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+ - "N\3N\3N\3N\3N\3N\3N\5N\u02e6\nN\3O\3O\3O\3O\7O\u02ec\nO\fO\16O\u02ef\13"+ - "O\3O\3O\3O\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3"+ - "P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\5P\u0319\nP\3Q\3"+ - "Q\3Q\3Q\7Q\u031f\nQ\fQ\16Q\u0322\13Q\3Q\3Q\5Q\u0326\nQ\3R\3R\3R\3R\5R"+ - "\u032c\nR\3R\3R\3S\3S\3S\3S\3S\3S\3S\3S\3S\5S\u0339\nS\3T\3T\5T\u033d"+ - "\nT\3U\3U\3U\5U\u0342\nU\3V\3V\3V\3V\3V\5V\u0349\nV\3V\7V\u034c\nV\fV"+ - "\16V\u034f\13V\3V\3V\6V\u0353\nV\rV\16V\u0354\3W\7W\u0358\nW\fW\16W\u035b"+ - "\13W\3W\3W\6W\u035f\nW\rW\16W\u0360\3X\3X\3X\3X\3X\5X\u0368\nX\3X\7X\u036b"+ - "\nX\fX\16X\u036e\13X\3X\3X\6X\u0372\nX\rX\16X\u0373\3Y\3Y\3Y\5Y\u0379"+ - "\nY\3Y\3Y\3Y\5Y\u037e\nY\3Z\3Z\3Z\6Z\u0383\nZ\rZ\16Z\u0384\3Z\3Z\6Z\u0389"+ - "\nZ\rZ\16Z\u038a\5Z\u038d\nZ\3[\6[\u0390\n[\r[\16[\u0391\3\\\3\\\3\\\3"+ - "\\\3\\\5\\\u0399\n\\\3\\\6\\\u039c\n\\\r\\\16\\\u039d\3]\3]\3^\3^\3_\3"+ - "_\3`\3`\7`\u03a8\n`\f`\16`\u03ab\13`\3a\3a\3b\3b\3c\3c\7c\u03b3\nc\fc"+ - "\16c\u03b6\13c\3c\6c\u03b9\nc\rc\16c\u03ba\3d\6d\u03be\nd\rd\16d\u03bf"+ - "\3d\3d\3e\3e\3e\3e\7e\u03c8\ne\fe\16e\u03cb\13e\3e\3e\3f\3f\3f\3f\7f\u03d3"+ - "\nf\ff\16f\u03d6\13f\3f\3f\3f\3f\3f\4\u02ed\u03d4\2g\3\3\5\4\7\5\t\6\13"+ - "\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'"+ - "\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'"+ - "M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177"+ - "A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093"+ - "K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7"+ - "U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9\2\u00bb"+ - "\2\u00bd\2\u00bf^\u00c1\2\u00c3\2\u00c5_\u00c7`\u00c9a\u00cbb\3\2\17\3"+ - "\2$$\3\2))\4\2uuww\7\2dfkknnuuyy\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHc"+ - "h\5\2C\\aac|\6\2\62;C\\aac|\4\2--//\6\2\13\f\17\17\"\"\u00a2\u00a2\4\2"+ - "\f\f\17\17\2\u044b\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13"+ - "\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2"+ - "\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2"+ - "!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3"+ - "\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2"+ - "\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E"+ - "\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2"+ - "\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2"+ - "\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k"+ - "\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2"+ - "\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2"+ - "\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b"+ - "\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2"+ - "\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d"+ - "\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2"+ - "\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af"+ - "\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2"+ - "\2\2\u00bf\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb"+ - "\3\2\2\2\3\u00cd\3\2\2\2\5\u00d4\3\2\2\2\7\u00d6\3\2\2\2\t\u00d8\3\2\2"+ - "\2\13\u00da\3\2\2\2\r\u00dc\3\2\2\2\17\u00de\3\2\2\2\21\u00e0\3\2\2\2"+ - "\23\u00e2\3\2\2\2\25\u00e8\3\2\2\2\27\u00ef\3\2\2\2\31\u00f5\3\2\2\2\33"+ - "\u00fe\3\2\2\2\35\u0105\3\2\2\2\37\u010e\3\2\2\2!\u0118\3\2\2\2#\u0120"+ - "\3\2\2\2%\u0123\3\2\2\2\'\u0128\3\2\2\2)\u012e\3\2\2\2+\u0131\3\2\2\2"+ - "-\u0135\3\2\2\2/\u013c\3\2\2\2\61\u0142\3\2\2\2\63\u014b\3\2\2\2\65\u014f"+ - "\3\2\2\2\67\u0151\3\2\2\29\u0154\3\2\2\2;\u015b\3\2\2\2=\u0164\3\2\2\2"+ - "?\u0166\3\2\2\2A\u0168\3\2\2\2C\u016a\3\2\2\2E\u0171\3\2\2\2G\u0178\3"+ - "\2\2\2I\u017b\3\2\2\2K\u017e\3\2\2\2M\u0180\3\2\2\2O\u0182\3\2\2\2Q\u0184"+ - "\3\2\2\2S\u0186\3\2\2\2U\u0188\3\2\2\2W\u018b\3\2\2\2Y\u018e\3\2\2\2["+ - "\u0190\3\2\2\2]\u0192\3\2\2\2_\u0194\3\2\2\2a\u0196\3\2\2\2c\u0199\3\2"+ - "\2\2e\u019c\3\2\2\2g\u019f\3\2\2\2i\u01a2\3\2\2\2k\u01a4\3\2\2\2m\u01a6"+ - "\3\2\2\2o\u01a9\3\2\2\2q\u01ac\3\2\2\2s\u01ae\3\2\2\2u\u01b1\3\2\2\2w"+ - "\u01b4\3\2\2\2y\u01b7\3\2\2\2{\u01ba\3\2\2\2}\u01bd\3\2\2\2\177\u01c1"+ - "\3\2\2\2\u0081\u01c5\3\2\2\2\u0083\u01c8\3\2\2\2\u0085\u01cb\3\2\2\2\u0087"+ - "\u01ce\3\2\2\2\u0089\u01d6\3\2\2\2\u008b\u01df\3\2\2\2\u008d\u01e4\3\2"+ - "\2\2\u008f\u01ed\3\2\2\2\u0091\u01f3\3\2\2\2\u0093\u01fa\3\2\2\2\u0095"+ - "\u01fd\3\2\2\2\u0097\u0203\3\2\2\2\u0099\u0205\3\2\2\2\u009b\u02e5\3\2"+ - "\2\2\u009d\u02e7\3\2\2\2\u009f\u0318\3\2\2\2\u00a1\u031a\3\2\2\2\u00a3"+ - "\u0327\3\2\2\2\u00a5\u0338\3\2\2\2\u00a7\u033c\3\2\2\2\u00a9\u0341\3\2"+ - "\2\2\u00ab\u0348\3\2\2\2\u00ad\u0359\3\2\2\2\u00af\u0367\3\2\2\2\u00b1"+ - "\u0378\3\2\2\2\u00b3\u038c\3\2\2\2\u00b5\u038f\3\2\2\2\u00b7\u0398\3\2"+ - "\2\2\u00b9\u039f\3\2\2\2\u00bb\u03a1\3\2\2\2\u00bd\u03a3\3\2\2\2\u00bf"+ - "\u03a5\3\2\2\2\u00c1\u03ac\3\2\2\2\u00c3\u03ae\3\2\2\2\u00c5\u03b0\3\2"+ - "\2\2\u00c7\u03bd\3\2\2\2\u00c9\u03c3\3\2\2\2\u00cb\u03ce\3\2\2\2\u00cd"+ - "\u00ce\7k\2\2\u00ce\u00cf\7o\2\2\u00cf\u00d0\7r\2\2\u00d0\u00d1\7q\2\2"+ - "\u00d1\u00d2\7t\2\2\u00d2\u00d3\7v\2\2\u00d3\4\3\2\2\2\u00d4\u00d5\7="+ - "\2\2\u00d5\6\3\2\2\2\u00d6\u00d7\7.\2\2\u00d7\b\3\2\2\2\u00d8\u00d9\7"+ - "?\2\2\u00d9\n\3\2\2\2\u00da\u00db\7*\2\2\u00db\f\3\2\2\2\u00dc\u00dd\7"+ - "+\2\2\u00dd\16\3\2\2\2\u00de\u00df\7}\2\2\u00df\20\3\2\2\2\u00e0\u00e1"+ - "\7\177\2\2\u00e1\22\3\2\2\2\u00e2\u00e3\7e\2\2\u00e3\u00e4\7q\2\2\u00e4"+ - "\u00e5\7p\2\2\u00e5\u00e6\7u\2\2\u00e6\u00e7\7v\2\2\u00e7\24\3\2\2\2\u00e8"+ - "\u00e9\7g\2\2\u00e9\u00ea\7z\2\2\u00ea\u00eb\7v\2\2\u00eb\u00ec\7g\2\2"+ - "\u00ec\u00ed\7t\2\2\u00ed\u00ee\7p\2\2\u00ee\26\3\2\2\2\u00ef\u00f0\7"+ - "c\2\2\u00f0\u00f1\7n\2\2\u00f1\u00f2\7k\2\2\u00f2\u00f3\7i\2\2\u00f3\u00f4"+ - "\7p\2\2\u00f4\30\3\2\2\2\u00f5\u00f6\7t\2\2\u00f6\u00f7\7g\2\2\u00f7\u00f8"+ - "\7i\2\2\u00f8\u00f9\7k\2\2\u00f9\u00fa\7u\2\2\u00fa\u00fb\7v\2\2\u00fb"+ - "\u00fc\7g\2\2\u00fc\u00fd\7t\2\2\u00fd\32\3\2\2\2\u00fe\u00ff\7k\2\2\u00ff"+ - "\u0100\7p\2\2\u0100\u0101\7n\2\2\u0101\u0102\7k\2\2\u0102\u0103\7p\2\2"+ - "\u0103\u0104\7g\2\2\u0104\34\3\2\2\2\u0105\u0106\7x\2\2\u0106\u0107\7"+ - "q\2\2\u0107\u0108\7n\2\2\u0108\u0109\7c\2\2\u0109\u010a\7v\2\2\u010a\u010b"+ - "\7k\2\2\u010b\u010c\7n\2\2\u010c\u010d\7g\2\2\u010d\36\3\2\2\2\u010e\u010f"+ - "\7k\2\2\u010f\u0110\7p\2\2\u0110\u0111\7v\2\2\u0111\u0112\7g\2\2\u0112"+ - "\u0113\7t\2\2\u0113\u0114\7t\2\2\u0114\u0115\7w\2\2\u0115\u0116\7r\2\2"+ - "\u0116\u0117\7v\2\2\u0117 \3\2\2\2\u0118\u0119\7t\2\2\u0119\u011a\7g\2"+ - "\2\u011a\u011b\7u\2\2\u011b\u011c\7g\2\2\u011c\u011d\7t\2\2\u011d\u011e"+ - "\7x\2\2\u011e\u011f\7g\2\2\u011f\"\3\2\2\2\u0120\u0121\7k\2\2\u0121\u0122"+ - "\7h\2\2\u0122$\3\2\2\2\u0123\u0124\7g\2\2\u0124\u0125\7n\2\2\u0125\u0126"+ - "\7u\2\2\u0126\u0127\7g\2\2\u0127&\3\2\2\2\u0128\u0129\7y\2\2\u0129\u012a"+ - "\7j\2\2\u012a\u012b\7k\2\2\u012b\u012c\7n\2\2\u012c\u012d\7g\2\2\u012d"+ - "(\3\2\2\2\u012e\u012f\7f\2\2\u012f\u0130\7q\2\2\u0130*\3\2\2\2\u0131\u0132"+ - "\7h\2\2\u0132\u0133\7q\2\2\u0133\u0134\7t\2\2\u0134,\3\2\2\2\u0135\u0136"+ - "\7t\2\2\u0136\u0137\7g\2\2\u0137\u0138\7v\2\2\u0138\u0139\7w\2\2\u0139"+ - "\u013a\7t\2\2\u013a\u013b\7p\2\2\u013b.\3\2\2\2\u013c\u013d\7d\2\2\u013d"+ - "\u013e\7t\2\2\u013e\u013f\7g\2\2\u013f\u0140\7c\2\2\u0140\u0141\7m\2\2"+ - "\u0141\60\3\2\2\2\u0142\u0143\7e\2\2\u0143\u0144\7q\2\2\u0144\u0145\7"+ - "p\2\2\u0145\u0146\7v\2\2\u0146\u0147\7k\2\2\u0147\u0148\7p\2\2\u0148\u0149"+ - "\7w\2\2\u0149\u014a\7g\2\2\u014a\62\3\2\2\2\u014b\u014c\7c\2\2\u014c\u014d"+ - "\7u\2\2\u014d\u014e\7o\2\2\u014e\64\3\2\2\2\u014f\u0150\7<\2\2\u0150\66"+ - "\3\2\2\2\u0151\u0152\7\60\2\2\u0152\u0153\7\60\2\2\u01538\3\2\2\2\u0154"+ - "\u0155\7u\2\2\u0155\u0156\7k\2\2\u0156\u0157\7i\2\2\u0157\u0158\7p\2\2"+ - "\u0158\u0159\7g\2\2\u0159\u015a\7f\2\2\u015a:\3\2\2\2\u015b\u015c\7w\2"+ - "\2\u015c\u015d\7p\2\2\u015d\u015e\7u\2\2\u015e\u015f\7k\2\2\u015f\u0160"+ - "\7i\2\2\u0160\u0161\7p\2\2\u0161\u0162\7g\2\2\u0162\u0163\7f\2\2\u0163"+ - "<\3\2\2\2\u0164\u0165\7,\2\2\u0165>\3\2\2\2\u0166\u0167\7]\2\2\u0167@"+ - "\3\2\2\2\u0168\u0169\7_\2\2\u0169B\3\2\2\2\u016a\u016b\7u\2\2\u016b\u016c"+ - "\7k\2\2\u016c\u016d\7|\2\2\u016d\u016e\7g\2\2\u016e\u016f\7q\2\2\u016f"+ - "\u0170\7h\2\2\u0170D\3\2\2\2\u0171\u0172\7v\2\2\u0172\u0173\7{\2\2\u0173"+ - "\u0174\7r\2\2\u0174\u0175\7g\2\2\u0175\u0176\7k\2\2\u0176\u0177\7f\2\2"+ - "\u0177F\3\2\2\2\u0178\u0179\7/\2\2\u0179\u017a\7/\2\2\u017aH\3\2\2\2\u017b"+ - "\u017c\7-\2\2\u017c\u017d\7-\2\2\u017dJ\3\2\2\2\u017e\u017f\7-\2\2\u017f"+ - "L\3\2\2\2\u0180\u0181\7/\2\2\u0181N\3\2\2\2\u0182\u0183\7#\2\2\u0183P"+ - "\3\2\2\2\u0184\u0185\7(\2\2\u0185R\3\2\2\2\u0186\u0187\7\u0080\2\2\u0187"+ - "T\3\2\2\2\u0188\u0189\7@\2\2\u0189\u018a\7@\2\2\u018aV\3\2\2\2\u018b\u018c"+ - "\7>\2\2\u018c\u018d\7>\2\2\u018dX\3\2\2\2\u018e\u018f\7\61\2\2\u018fZ"+ - "\3\2\2\2\u0190\u0191\7\'\2\2\u0191\\\3\2\2\2\u0192\u0193\7>\2\2\u0193"+ - "^\3\2\2\2\u0194\u0195\7@\2\2\u0195`\3\2\2\2\u0196\u0197\7?\2\2\u0197\u0198"+ - "\7?\2\2\u0198b\3\2\2\2\u0199\u019a\7#\2\2\u019a\u019b\7?\2\2\u019bd\3"+ - "\2\2\2\u019c\u019d\7>\2\2\u019d\u019e\7?\2\2\u019ef\3\2\2\2\u019f\u01a0"+ - "\7@\2\2\u01a0\u01a1\7?\2\2\u01a1h\3\2\2\2\u01a2\u01a3\7`\2\2\u01a3j\3"+ - "\2\2\2\u01a4\u01a5\7~\2\2\u01a5l\3\2\2\2\u01a6\u01a7\7(\2\2\u01a7\u01a8"+ - "\7(\2\2\u01a8n\3\2\2\2\u01a9\u01aa\7~\2\2\u01aa\u01ab\7~\2\2\u01abp\3"+ - "\2\2\2\u01ac\u01ad\7A\2\2\u01adr\3\2\2\2\u01ae\u01af\7-\2\2\u01af\u01b0"+ - "\7?\2\2\u01b0t\3\2\2\2\u01b1\u01b2\7/\2\2\u01b2\u01b3\7?\2\2\u01b3v\3"+ - "\2\2\2\u01b4\u01b5\7,\2\2\u01b5\u01b6\7?\2\2\u01b6x\3\2\2\2\u01b7\u01b8"+ - "\7\61\2\2\u01b8\u01b9\7?\2\2\u01b9z\3\2\2\2\u01ba\u01bb\7\'\2\2\u01bb"+ - "\u01bc\7?\2\2\u01bc|\3\2\2\2\u01bd\u01be\7>\2\2\u01be\u01bf\7>\2\2\u01bf"+ - "\u01c0\7?\2\2\u01c0~\3\2\2\2\u01c1\u01c2\7@\2\2\u01c2\u01c3\7@\2\2\u01c3"+ - "\u01c4\7?\2\2\u01c4\u0080\3\2\2\2\u01c5\u01c6\7(\2\2\u01c6\u01c7\7?\2"+ - "\2\u01c7\u0082\3\2\2\2\u01c8\u01c9\7~\2\2\u01c9\u01ca\7?\2\2\u01ca\u0084"+ - "\3\2\2\2\u01cb\u01cc\7`\2\2\u01cc\u01cd\7?\2\2\u01cd\u0086\3\2\2\2\u01ce"+ - "\u01cf\7m\2\2\u01cf\u01d0\7k\2\2\u01d0\u01d1\7e\2\2\u01d1\u01d2\7m\2\2"+ - "\u01d2\u01d3\7c\2\2\u01d3\u01d4\7u\2\2\u01d4\u01d5\7o\2\2\u01d5\u0088"+ - "\3\2\2\2\u01d6\u01d7\7t\2\2\u01d7\u01d8\7g\2\2\u01d8\u01d9\7u\2\2\u01d9"+ - "\u01da\7q\2\2\u01da\u01db\7w\2\2\u01db\u01dc\7t\2\2\u01dc\u01dd\7e\2\2"+ - "\u01dd\u01de\7g\2\2\u01de\u008a\3\2\2\2\u01df\u01e0\7w\2\2\u01e0\u01e1"+ - "\7u\2\2\u01e1\u01e2\7g\2\2\u01e2\u01e3\7u\2\2\u01e3\u008c\3\2\2\2\u01e4"+ - "\u01e5\7e\2\2\u01e5\u01e6\7n\2\2\u01e6\u01e7\7q\2\2\u01e7\u01e8\7d\2\2"+ - "\u01e8\u01e9\7d\2\2\u01e9\u01ea\7g\2\2\u01ea\u01eb\7t\2\2\u01eb\u01ec"+ - "\7u\2\2\u01ec\u008e\3\2\2\2\u01ed\u01ee\7d\2\2\u01ee\u01ef\7{\2\2\u01ef"+ - "\u01f0\7v\2\2\u01f0\u01f1\7g\2\2\u01f1\u01f2\7u\2\2\u01f2\u0090\3\2\2"+ - "\2\u01f3\u01f4\7e\2\2\u01f4\u01f5\7{\2\2\u01f5\u01f6\7e\2\2\u01f6\u01f7"+ - "\7n\2\2\u01f7\u01f8\7g\2\2\u01f8\u01f9\7u\2\2\u01f9\u0092\3\2\2\2\u01fa"+ - "\u01fb\7r\2\2\u01fb\u01fc\7e\2\2\u01fc\u0094\3\2\2\2\u01fd\u01fe\7\60"+ - "\2\2\u01fe\u01ff\7d\2\2\u01ff\u0200\7{\2\2\u0200\u0201\7v\2\2\u0201\u0202"+ - "\7g\2\2\u0202\u0096\3\2\2\2\u0203\u0204\7%\2\2\u0204\u0098\3\2\2\2\u0205"+ - "\u0206\7\60\2\2\u0206\u009a\3\2\2\2\u0207\u0208\7d\2\2\u0208\u0209\7t"+ - "\2\2\u0209\u02e6\7m\2\2\u020a\u020b\7q\2\2\u020b\u020c\7t\2\2\u020c\u02e6"+ - "\7c\2\2\u020d\u020e\7m\2\2\u020e\u020f\7k\2\2\u020f\u02e6\7n\2\2\u0210"+ - "\u0211\7u\2\2\u0211\u0212\7n\2\2\u0212\u02e6\7q\2\2\u0213\u0214\7p\2\2"+ - "\u0214\u0215\7q\2\2\u0215\u02e6\7r\2\2\u0216\u0217\7c\2\2\u0217\u0218"+ - "\7u\2\2\u0218\u02e6\7n\2\2\u0219\u021a\7r\2\2\u021a\u021b\7j\2\2\u021b"+ - "\u02e6\7r\2\2\u021c\u021d\7c\2\2\u021d\u021e\7p\2\2\u021e\u02e6\7e\2\2"+ - "\u021f\u0220\7d\2\2\u0220\u0221\7r\2\2\u0221\u02e6\7n\2\2\u0222\u0223"+ - "\7e\2\2\u0223\u0224\7n\2\2\u0224\u02e6\7e\2\2\u0225\u0226\7l\2\2\u0226"+ - "\u0227\7u\2\2\u0227\u02e6\7t\2\2\u0228\u0229\7c\2\2\u0229\u022a\7p\2\2"+ - "\u022a\u02e6\7f\2\2\u022b\u022c\7t\2\2\u022c\u022d\7n\2\2\u022d\u02e6"+ - "\7c\2\2\u022e\u022f\7d\2\2\u022f\u0230\7k\2\2\u0230\u02e6\7v\2\2\u0231"+ - "\u0232\7t\2\2\u0232\u0233\7q\2\2\u0233\u02e6\7n\2\2\u0234\u0235\7r\2\2"+ - "\u0235\u0236\7n\2\2\u0236\u02e6\7c\2\2\u0237\u0238\7r\2\2\u0238\u0239"+ - "\7n\2\2\u0239\u02e6\7r\2\2\u023a\u023b\7d\2\2\u023b\u023c\7o\2\2\u023c"+ - "\u02e6\7k\2\2\u023d\u023e\7u\2\2\u023e\u023f\7g\2\2\u023f\u02e6\7e\2\2"+ - "\u0240\u0241\7t\2\2\u0241\u0242\7v\2\2\u0242\u02e6\7k\2\2\u0243\u0244"+ - "\7g\2\2\u0244\u0245\7q\2\2\u0245\u02e6\7t\2\2\u0246\u0247\7u\2\2\u0247"+ - "\u0248\7t\2\2\u0248\u02e6\7g\2\2\u0249\u024a\7n\2\2\u024a\u024b\7u\2\2"+ - "\u024b\u02e6\7t\2\2\u024c\u024d\7r\2\2\u024d\u024e\7j\2\2\u024e\u02e6"+ - "\7c\2\2\u024f\u0250\7c\2\2\u0250\u0251\7n\2\2\u0251\u02e6\7t\2\2\u0252"+ - "\u0253\7l\2\2\u0253\u0254\7o\2\2\u0254\u02e6\7r\2\2\u0255\u0256\7d\2\2"+ - "\u0256\u0257\7x\2\2\u0257\u02e6\7e\2\2\u0258\u0259\7e\2\2\u0259\u025a"+ - "\7n\2\2\u025a\u02e6\7k\2\2\u025b\u025c\7t\2\2\u025c\u025d\7v\2\2\u025d"+ - "\u02e6\7u\2\2\u025e\u025f\7c\2\2\u025f\u0260\7f\2\2\u0260\u02e6\7e\2\2"+ - "\u0261\u0262\7t\2\2\u0262\u0263\7t\2\2\u0263\u02e6\7c\2\2\u0264\u0265"+ - "\7d\2\2\u0265\u0266\7x\2\2\u0266\u02e6\7u\2\2\u0267\u0268\7u\2\2\u0268"+ - "\u0269\7g\2\2\u0269\u02e6\7k\2\2\u026a\u026b\7u\2\2\u026b\u026c\7c\2\2"+ - "\u026c\u02e6\7z\2\2\u026d\u026e\7u\2\2\u026e\u026f\7v\2\2\u026f\u02e6"+ - "\7{\2\2\u0270\u0271\7u\2\2\u0271\u0272\7v\2\2\u0272\u02e6\7c\2\2\u0273"+ - "\u0274\7u\2\2\u0274\u0275\7v\2\2\u0275\u02e6\7z\2\2\u0276\u0277\7f\2\2"+ - "\u0277\u0278\7g\2\2\u0278\u02e6\7{\2\2\u0279\u027a\7v\2\2\u027a\u027b"+ - "\7z\2\2\u027b\u02e6\7c\2\2\u027c\u027d\7z\2\2\u027d\u027e\7c\2\2\u027e"+ - "\u02e6\7c\2\2\u027f\u0280\7d\2\2\u0280\u0281\7e\2\2\u0281\u02e6\7e\2\2"+ - "\u0282\u0283\7c\2\2\u0283\u0284\7j\2\2\u0284\u02e6\7z\2\2\u0285\u0286"+ - "\7v\2\2\u0286\u0287\7{\2\2\u0287\u02e6\7c\2\2\u0288\u0289\7v\2\2\u0289"+ - "\u028a\7z\2\2\u028a\u02e6\7u\2\2\u028b\u028c\7v\2\2\u028c\u028d\7c\2\2"+ - "\u028d\u02e6\7u\2\2\u028e\u028f\7u\2\2\u028f\u0290\7j\2\2\u0290\u02e6"+ - "\7{\2\2\u0291\u0292\7u\2\2\u0292\u0293\7j\2\2\u0293\u02e6\7z\2\2\u0294"+ - "\u0295\7n\2\2\u0295\u0296\7f\2\2\u0296\u02e6\7{\2\2\u0297\u0298\7n\2\2"+ - "\u0298\u0299\7f\2\2\u0299\u02e6\7c\2\2\u029a\u029b\7n\2\2\u029b\u029c"+ - "\7f\2\2\u029c\u02e6\7z\2\2\u029d\u029e\7n\2\2\u029e\u029f\7c\2\2\u029f"+ - "\u02e6\7z\2\2\u02a0\u02a1\7v\2\2\u02a1\u02a2\7c\2\2\u02a2\u02e6\7{\2\2"+ - "\u02a3\u02a4\7v\2\2\u02a4\u02a5\7c\2\2\u02a5\u02e6\7z\2\2\u02a6\u02a7"+ - "\7d\2\2\u02a7\u02a8\7e\2\2\u02a8\u02e6\7u\2\2\u02a9\u02aa\7e\2\2\u02aa"+ - "\u02ab\7n\2\2\u02ab\u02e6\7x\2\2\u02ac\u02ad\7v\2\2\u02ad\u02ae\7u\2\2"+ - "\u02ae\u02e6\7z\2\2\u02af\u02b0\7n\2\2\u02b0\u02b1\7c\2\2\u02b1\u02e6"+ - "\7u\2\2\u02b2\u02b3\7e\2\2\u02b3\u02b4\7r\2\2\u02b4\u02e6\7{\2\2\u02b5"+ - "\u02b6\7e\2\2\u02b6\u02b7\7o\2\2\u02b7\u02e6\7r\2\2\u02b8\u02b9\7e\2\2"+ - "\u02b9\u02ba\7r\2\2\u02ba\u02e6\7z\2\2\u02bb\u02bc\7f\2\2\u02bc\u02bd"+ - "\7e\2\2\u02bd\u02e6\7r\2\2\u02be\u02bf\7f\2\2\u02bf\u02c0\7g\2\2\u02c0"+ - "\u02e6\7e\2\2\u02c1\u02c2\7k\2\2\u02c2\u02c3\7p\2\2\u02c3\u02e6\7e\2\2"+ - "\u02c4\u02c5\7c\2\2\u02c5\u02c6\7z\2\2\u02c6\u02e6\7u\2\2\u02c7\u02c8"+ - "\7d\2\2\u02c8\u02c9\7p\2\2\u02c9\u02e6\7g\2\2\u02ca\u02cb\7e\2\2\u02cb"+ - "\u02cc\7n\2\2\u02cc\u02e6\7f\2\2\u02cd\u02ce\7u\2\2\u02ce\u02cf\7d\2\2"+ - "\u02cf\u02e6\7e\2\2\u02d0\u02d1\7k\2\2\u02d1\u02d2\7u\2\2\u02d2\u02e6"+ - "\7e\2\2\u02d3\u02d4\7k\2\2\u02d4\u02d5\7p\2\2\u02d5\u02e6\7z\2\2\u02d6"+ - "\u02d7\7d\2\2\u02d7\u02d8\7g\2\2\u02d8\u02e6\7s\2\2\u02d9\u02da\7u\2\2"+ - "\u02da\u02db\7g\2\2\u02db\u02e6\7f\2\2\u02dc\u02dd\7f\2\2\u02dd\u02de"+ - "\7g\2\2\u02de\u02e6\7z\2\2\u02df\u02e0\7k\2\2\u02e0\u02e1\7p\2\2\u02e1"+ - "\u02e6\7{\2\2\u02e2\u02e3\7t\2\2\u02e3\u02e4\7q\2\2\u02e4\u02e6\7t\2\2"+ - "\u02e5\u0207\3\2\2\2\u02e5\u020a\3\2\2\2\u02e5\u020d\3\2\2\2\u02e5\u0210"+ - "\3\2\2\2\u02e5\u0213\3\2\2\2\u02e5\u0216\3\2\2\2\u02e5\u0219\3\2\2\2\u02e5"+ - "\u021c\3\2\2\2\u02e5\u021f\3\2\2\2\u02e5\u0222\3\2\2\2\u02e5\u0225\3\2"+ - "\2\2\u02e5\u0228\3\2\2\2\u02e5\u022b\3\2\2\2\u02e5\u022e\3\2\2\2\u02e5"+ - "\u0231\3\2\2\2\u02e5\u0234\3\2\2\2\u02e5\u0237\3\2\2\2\u02e5\u023a\3\2"+ - "\2\2\u02e5\u023d\3\2\2\2\u02e5\u0240\3\2\2\2\u02e5\u0243\3\2\2\2\u02e5"+ - "\u0246\3\2\2\2\u02e5\u0249\3\2\2\2\u02e5\u024c\3\2\2\2\u02e5\u024f\3\2"+ - "\2\2\u02e5\u0252\3\2\2\2\u02e5\u0255\3\2\2\2\u02e5\u0258\3\2\2\2\u02e5"+ - "\u025b\3\2\2\2\u02e5\u025e\3\2\2\2\u02e5\u0261\3\2\2\2\u02e5\u0264\3\2"+ - "\2\2\u02e5\u0267\3\2\2\2\u02e5\u026a\3\2\2\2\u02e5\u026d\3\2\2\2\u02e5"+ - "\u0270\3\2\2\2\u02e5\u0273\3\2\2\2\u02e5\u0276\3\2\2\2\u02e5\u0279\3\2"+ - "\2\2\u02e5\u027c\3\2\2\2\u02e5\u027f\3\2\2\2\u02e5\u0282\3\2\2\2\u02e5"+ - "\u0285\3\2\2\2\u02e5\u0288\3\2\2\2\u02e5\u028b\3\2\2\2\u02e5\u028e\3\2"+ - "\2\2\u02e5\u0291\3\2\2\2\u02e5\u0294\3\2\2\2\u02e5\u0297\3\2\2\2\u02e5"+ - "\u029a\3\2\2\2\u02e5\u029d\3\2\2\2\u02e5\u02a0\3\2\2\2\u02e5\u02a3\3\2"+ - "\2\2\u02e5\u02a6\3\2\2\2\u02e5\u02a9\3\2\2\2\u02e5\u02ac\3\2\2\2\u02e5"+ - "\u02af\3\2\2\2\u02e5\u02b2\3\2\2\2\u02e5\u02b5\3\2\2\2\u02e5\u02b8\3\2"+ - "\2\2\u02e5\u02bb\3\2\2\2\u02e5\u02be\3\2\2\2\u02e5\u02c1\3\2\2\2\u02e5"+ - "\u02c4\3\2\2\2\u02e5\u02c7\3\2\2\2\u02e5\u02ca\3\2\2\2\u02e5\u02cd\3\2"+ - "\2\2\u02e5\u02d0\3\2\2\2\u02e5\u02d3\3\2\2\2\u02e5\u02d6\3\2\2\2\u02e5"+ - "\u02d9\3\2\2\2\u02e5\u02dc\3\2\2\2\u02e5\u02df\3\2\2\2\u02e5\u02e2\3\2"+ - "\2\2\u02e6\u009c\3\2\2\2\u02e7\u02e8\7}\2\2\u02e8\u02e9\7}\2\2\u02e9\u02ed"+ - "\3\2\2\2\u02ea\u02ec\13\2\2\2\u02eb\u02ea\3\2\2\2\u02ec\u02ef\3\2\2\2"+ - "\u02ed\u02ee\3\2\2\2\u02ed\u02eb\3\2\2\2\u02ee\u02f0\3\2\2\2\u02ef\u02ed"+ - "\3\2\2\2\u02f0\u02f1\7\177\2\2\u02f1\u02f2\7\177\2\2\u02f2\u009e\3\2\2"+ - "\2\u02f3\u02f4\7d\2\2\u02f4\u02f5\7{\2\2\u02f5\u02f6\7v\2\2\u02f6\u0319"+ - "\7g\2\2\u02f7\u02f8\7y\2\2\u02f8\u02f9\7q\2\2\u02f9\u02fa\7t\2\2\u02fa"+ - "\u0319\7f\2\2\u02fb\u02fc\7f\2\2\u02fc\u02fd\7y\2\2\u02fd\u02fe\7q\2\2"+ - "\u02fe\u02ff\7t\2\2\u02ff\u0319\7f\2\2\u0300\u0301\7d\2\2\u0301\u0302"+ - "\7q\2\2\u0302\u0303\7q\2\2\u0303\u0319\7n\2\2\u0304\u0305\7e\2\2\u0305"+ - "\u0306\7j\2\2\u0306\u0307\7c\2\2\u0307\u0319\7t\2\2\u0308\u0309\7u\2\2"+ - "\u0309\u030a\7j\2\2\u030a\u030b\7q\2\2\u030b\u030c\7t\2\2\u030c\u0319"+ - "\7v\2\2\u030d\u030e\7k\2\2\u030e\u030f\7p\2\2\u030f\u0319\7v\2\2\u0310"+ - "\u0311\7n\2\2\u0311\u0312\7q\2\2\u0312\u0313\7p\2\2\u0313\u0319\7i\2\2"+ - "\u0314\u0315\7x\2\2\u0315\u0316\7q\2\2\u0316\u0317\7k\2\2\u0317\u0319"+ - "\7f\2\2\u0318\u02f3\3\2\2\2\u0318\u02f7\3\2\2\2\u0318\u02fb\3\2\2\2\u0318"+ - "\u0300\3\2\2\2\u0318\u0304\3\2\2\2\u0318\u0308\3\2\2\2\u0318\u030d\3\2"+ - "\2\2\u0318\u0310\3\2\2\2\u0318\u0314\3\2\2\2\u0319\u00a0\3\2\2\2\u031a"+ - "\u0320\7$\2\2\u031b\u031c\7^\2\2\u031c\u031f\7$\2\2\u031d\u031f\n\2\2"+ - "\2\u031e\u031b\3\2\2\2\u031e\u031d\3\2\2\2\u031f\u0322\3\2\2\2\u0320\u031e"+ - "\3\2\2\2\u0320\u0321\3\2\2\2\u0321\u0323\3\2\2\2\u0322\u0320\3\2\2\2\u0323"+ - "\u0325\7$\2\2\u0324\u0326\7|\2\2\u0325\u0324\3\2\2\2\u0325\u0326\3\2\2"+ - "\2\u0326\u00a2\3\2\2\2\u0327\u032b\7)\2\2\u0328\u0329\7^\2\2\u0329\u032c"+ - "\7)\2\2\u032a\u032c\n\3\2\2\u032b\u0328\3\2\2\2\u032b\u032a\3\2\2\2\u032c"+ - "\u032d\3\2\2\2\u032d\u032e\7)\2\2\u032e\u00a4\3\2\2\2\u032f\u0330\7v\2"+ - "\2\u0330\u0331\7t\2\2\u0331\u0332\7w\2\2\u0332\u0339\7g\2\2\u0333\u0334"+ - "\7h\2\2\u0334\u0335\7c\2\2\u0335\u0336\7n\2\2\u0336\u0337\7u\2\2\u0337"+ - "\u0339\7g\2\2\u0338\u032f\3\2\2\2\u0338\u0333\3\2\2\2\u0339\u00a6\3\2"+ - "\2\2\u033a\u033d\5\u00a9U\2\u033b\u033d\5\u00b1Y\2\u033c\u033a\3\2\2\2"+ - "\u033c\u033b\3\2\2\2\u033d\u00a8\3\2\2\2\u033e\u0342\5\u00abV\2\u033f"+ - "\u0342\5\u00adW\2\u0340\u0342\5\u00afX\2\u0341\u033e\3\2\2\2\u0341\u033f"+ - "\3\2\2\2\u0341\u0340\3\2\2\2\u0342\u00aa\3\2\2\2\u0343\u0349\7\'\2\2\u0344"+ - "\u0345\7\62\2\2\u0345\u0349\7d\2\2\u0346\u0347\7\62\2\2\u0347\u0349\7"+ - "D\2\2\u0348\u0343\3\2\2\2\u0348\u0344\3\2\2\2\u0348\u0346\3\2\2\2\u0349"+ - "\u034d\3\2\2\2\u034a\u034c\5\u00b9]\2\u034b\u034a\3\2\2\2\u034c\u034f"+ - "\3\2\2\2\u034d\u034b\3\2\2\2\u034d\u034e\3\2\2\2\u034e\u0350\3\2\2\2\u034f"+ - "\u034d\3\2\2\2\u0350\u0352\7\60\2\2\u0351\u0353\5\u00b9]\2\u0352\u0351"+ - "\3\2\2\2\u0353\u0354\3\2\2\2\u0354\u0352\3\2\2\2\u0354\u0355\3\2\2\2\u0355"+ - "\u00ac\3\2\2\2\u0356\u0358\5\u00bb^\2\u0357\u0356\3\2\2\2\u0358\u035b"+ - "\3\2\2\2\u0359\u0357\3\2\2\2\u0359\u035a\3\2\2\2\u035a\u035c\3\2\2\2\u035b"+ - "\u0359\3\2\2\2\u035c\u035e\7\60\2\2\u035d\u035f\5\u00bb^\2\u035e\u035d"+ - "\3\2\2\2\u035f\u0360\3\2\2\2\u0360\u035e\3\2\2\2\u0360\u0361\3\2\2\2\u0361"+ - "\u00ae\3\2\2\2\u0362\u0368\7&\2\2\u0363\u0364\7\62\2\2\u0364\u0368\7z"+ - "\2\2\u0365\u0366\7\62\2\2\u0366\u0368\7Z\2\2\u0367\u0362\3\2\2\2\u0367"+ - "\u0363\3\2\2\2\u0367\u0365\3\2\2\2\u0368\u036c\3\2\2\2\u0369\u036b\5\u00bd"+ - "_\2\u036a\u0369\3\2\2\2\u036b\u036e\3\2\2\2\u036c\u036a\3\2\2\2\u036c"+ - "\u036d\3\2\2\2\u036d\u036f\3\2\2\2\u036e\u036c\3\2\2\2\u036f\u0371\7\60"+ - "\2\2\u0370\u0372\5\u00bd_\2\u0371\u0370\3\2\2\2\u0372\u0373\3\2\2\2\u0373"+ - "\u0371\3\2\2\2\u0373\u0374\3\2\2\2\u0374\u00b0\3\2\2\2\u0375\u0379\5\u00b5"+ - "[\2\u0376\u0379\5\u00b7\\\2\u0377\u0379\5\u00b3Z\2\u0378\u0375\3\2\2\2"+ - "\u0378\u0376\3\2\2\2\u0378\u0377\3\2\2\2\u0379\u037d\3\2\2\2\u037a\u037b"+ - "\t\4\2\2\u037b\u037e\t\5\2\2\u037c\u037e\7n\2\2\u037d\u037a\3\2\2\2\u037d"+ - "\u037c\3\2\2\2\u037d\u037e\3\2\2\2\u037e\u00b2\3\2\2\2\u037f\u0380\7\62"+ - "\2\2\u0380\u0382\t\6\2\2\u0381\u0383\5\u00b9]\2\u0382\u0381\3\2\2\2\u0383"+ - "\u0384\3\2\2\2\u0384\u0382\3\2\2\2\u0384\u0385\3\2\2\2\u0385\u038d\3\2"+ - "\2\2\u0386\u0388\7\'\2\2\u0387\u0389\5\u00b9]\2\u0388\u0387\3\2\2\2\u0389"+ - "\u038a\3\2\2\2\u038a\u0388\3\2\2\2\u038a\u038b\3\2\2\2\u038b\u038d\3\2"+ - "\2\2\u038c\u037f\3\2\2\2\u038c\u0386\3\2\2\2\u038d\u00b4\3\2\2\2\u038e"+ - "\u0390\5\u00bb^\2\u038f\u038e\3\2\2\2\u0390\u0391\3\2\2\2\u0391\u038f"+ - "\3\2\2\2\u0391\u0392\3\2\2\2\u0392\u00b6\3\2\2\2\u0393\u0399\7&\2\2\u0394"+ - "\u0395\7\62\2\2\u0395\u0399\7z\2\2\u0396\u0397\7\62\2\2\u0397\u0399\7"+ - "Z\2\2\u0398\u0393\3\2\2\2\u0398\u0394\3\2\2\2\u0398\u0396\3\2\2\2\u0399"+ - "\u039b\3\2\2\2\u039a\u039c\5\u00bd_\2\u039b\u039a\3\2\2\2\u039c\u039d"+ - "\3\2\2\2\u039d\u039b\3\2\2\2\u039d\u039e\3\2\2\2\u039e\u00b8\3\2\2\2\u039f"+ - "\u03a0\t\7\2\2\u03a0\u00ba\3\2\2\2\u03a1\u03a2\t\b\2\2\u03a2\u00bc\3\2"+ - "\2\2\u03a3\u03a4\t\t\2\2\u03a4\u00be\3\2\2\2\u03a5\u03a9\5\u00c1a\2\u03a6"+ - "\u03a8\5\u00c3b\2\u03a7\u03a6\3\2\2\2\u03a8\u03ab\3\2\2\2\u03a9\u03a7"+ - "\3\2\2\2\u03a9\u03aa\3\2\2\2\u03aa\u00c0\3\2\2\2\u03ab\u03a9\3\2\2\2\u03ac"+ - "\u03ad\t\n\2\2\u03ad\u00c2\3\2\2\2\u03ae\u03af\t\13\2\2\u03af\u00c4\3"+ - "\2\2\2\u03b0\u03b4\7#\2\2\u03b1\u03b3\5\u00c3b\2\u03b2\u03b1\3\2\2\2\u03b3"+ - "\u03b6\3\2\2\2\u03b4\u03b2\3\2\2\2\u03b4\u03b5\3\2\2\2\u03b5\u03b8\3\2"+ - "\2\2\u03b6\u03b4\3\2\2\2\u03b7\u03b9\t\f\2\2\u03b8\u03b7\3\2\2\2\u03b9"+ - "\u03ba\3\2\2\2\u03ba\u03b8\3\2\2\2\u03ba\u03bb\3\2\2\2\u03bb\u00c6\3\2"+ - "\2\2\u03bc\u03be\t\r\2\2\u03bd\u03bc\3\2\2\2\u03be\u03bf\3\2\2\2\u03bf"+ - "\u03bd\3\2\2\2\u03bf\u03c0\3\2\2\2\u03c0\u03c1\3\2\2\2\u03c1\u03c2\bd"+ - "\2\2\u03c2\u00c8\3\2\2\2\u03c3\u03c4\7\61\2\2\u03c4\u03c5\7\61\2\2\u03c5"+ - "\u03c9\3\2\2\2\u03c6\u03c8\n\16\2\2\u03c7\u03c6\3\2\2\2\u03c8\u03cb\3"+ - "\2\2\2\u03c9\u03c7\3\2\2\2\u03c9\u03ca\3\2\2\2\u03ca\u03cc\3\2\2\2\u03cb"+ - "\u03c9\3\2\2\2\u03cc\u03cd\be\3\2\u03cd\u00ca\3\2\2\2\u03ce\u03cf\7\61"+ - "\2\2\u03cf\u03d0\7,\2\2\u03d0\u03d4\3\2\2\2\u03d1\u03d3\13\2\2\2\u03d2"+ - "\u03d1\3\2\2\2\u03d3\u03d6\3\2\2\2\u03d4\u03d5\3\2\2\2\u03d4\u03d2\3\2"+ - "\2\2\u03d5\u03d7\3\2\2\2\u03d6\u03d4\3\2\2\2\u03d7\u03d8\7,\2\2\u03d8"+ - "\u03d9\7\61\2\2\u03d9\u03da\3\2\2\2\u03da\u03db\bf\3\2\u03db\u00cc\3\2"+ - "\2\2#\2\u02e5\u02ed\u0318\u031e\u0320\u0325\u032b\u0338\u033c\u0341\u0348"+ - "\u034d\u0354\u0359\u0360\u0367\u036c\u0373\u0378\u037d\u0384\u038a\u038c"+ - "\u0391\u0398\u039d\u03a9\u03b4\u03ba\u03bf\u03c9\u03d4\4\2\3\2\2\4\2"; + "`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\3\2\3\2\3\2\3\2\3\2\3\2"+ + "\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3"+ + "\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f"+ + "\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16"+ + "\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20"+ + "\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+ + "\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24"+ + "\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27"+ + "\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31"+ + "\3\31\3\32\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\35"+ + "\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37"+ + "\3 \3 \3!\3!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3#\3#\3#\3#\3#\3#\3#\3$\3$\3"+ + "$\3$\3$\3$\3$\3%\3%\3%\3&\3&\3&\3\'\3\'\3(\3(\3)\3)\3*\3*\3+\3+\3,\3,"+ + "\3,\3-\3-\3-\3.\3.\3/\3/\3\60\3\60\3\61\3\61\3\62\3\62\3\62\3\63\3\63"+ + "\3\63\3\64\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\67\3\67\38\38\38\39\3"+ + "9\39\3:\3:\3;\3;\3;\3<\3<\3<\3=\3=\3=\3>\3>\3>\3?\3?\3?\3@\3@\3@\3@\3"+ + "A\3A\3A\3A\3B\3B\3B\3C\3C\3C\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3E\3F\3F\3"+ + "F\3F\3F\3F\3F\3F\3F\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3H\3H\3H\3I\3I\3"+ + "I\3I\3I\3I\3J\3J\3J\3J\3J\3J\3J\3K\3K\3K\3L\3L\3L\3L\3L\3L\3M\3M\3N\3"+ + "N\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ + "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ + "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ + "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ + "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ + "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ + "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ + "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ + "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ + "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\5O\u02ef\nO\3P\3P\3P\3"+ + "P\7P\u02f5\nP\fP\16P\u02f8\13P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q"+ + "\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q"+ + "\3Q\3Q\3Q\3Q\5Q\u0322\nQ\3R\3R\3R\3R\7R\u0328\nR\fR\16R\u032b\13R\3R\3"+ + "R\5R\u032f\nR\3S\3S\3S\3S\5S\u0335\nS\3S\3S\3T\3T\3T\3T\3T\3T\3T\3T\3"+ + "T\5T\u0342\nT\3U\3U\5U\u0346\nU\3V\3V\3V\5V\u034b\nV\3W\3W\3W\3W\3W\5"+ + "W\u0352\nW\3W\7W\u0355\nW\fW\16W\u0358\13W\3W\3W\6W\u035c\nW\rW\16W\u035d"+ + "\3X\7X\u0361\nX\fX\16X\u0364\13X\3X\3X\6X\u0368\nX\rX\16X\u0369\3Y\3Y"+ + "\3Y\3Y\3Y\5Y\u0371\nY\3Y\7Y\u0374\nY\fY\16Y\u0377\13Y\3Y\3Y\6Y\u037b\n"+ + "Y\rY\16Y\u037c\3Z\3Z\3Z\5Z\u0382\nZ\3Z\3Z\3Z\5Z\u0387\nZ\3[\3[\3[\6[\u038c"+ + "\n[\r[\16[\u038d\3[\3[\6[\u0392\n[\r[\16[\u0393\5[\u0396\n[\3\\\6\\\u0399"+ + "\n\\\r\\\16\\\u039a\3]\3]\3]\3]\3]\5]\u03a2\n]\3]\6]\u03a5\n]\r]\16]\u03a6"+ + "\3^\3^\3_\3_\3`\3`\3a\3a\7a\u03b1\na\fa\16a\u03b4\13a\3b\3b\3c\3c\3d\3"+ + "d\7d\u03bc\nd\fd\16d\u03bf\13d\3d\6d\u03c2\nd\rd\16d\u03c3\3e\6e\u03c7"+ + "\ne\re\16e\u03c8\3e\3e\3f\3f\3f\3f\7f\u03d1\nf\ff\16f\u03d4\13f\3f\3f"+ + "\3g\3g\3g\3g\7g\u03dc\ng\fg\16g\u03df\13g\3g\3g\3g\3g\3g\4\u02f6\u03dd"+ + "\2h\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35"+ + "\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36"+ + ";\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67"+ + "m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008d"+ + "H\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1"+ + "R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5"+ + "\\\u00b7]\u00b9^\u00bb\2\u00bd\2\u00bf\2\u00c1_\u00c3\2\u00c5\2\u00c7"+ + "`\u00c9a\u00cbb\u00cdc\3\2\17\3\2$$\3\2))\4\2uuww\7\2dfkknnuuyy\4\2DD"+ + "dd\3\2\62\63\3\2\62;\5\2\62;CHch\5\2C\\aac|\6\2\62;C\\aac|\4\2--//\6\2"+ + "\13\f\17\17\"\"\u00a2\u00a2\4\2\f\f\17\17\2\u0454\2\3\3\2\2\2\2\5\3\2"+ + "\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21"+ + "\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2"+ + "\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3"+ + "\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3"+ + "\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3"+ + "\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2"+ + "\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2"+ + "Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3"+ + "\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2"+ + "\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2"+ + "\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3"+ + "\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2"+ + "\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099"+ + "\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2"+ + "\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab"+ + "\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2"+ + "\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00c1\3\2\2\2\2\u00c7"+ + "\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\3\u00cf\3\2\2"+ + "\2\5\u00d6\3\2\2\2\7\u00d8\3\2\2\2\t\u00da\3\2\2\2\13\u00dc\3\2\2\2\r"+ + "\u00de\3\2\2\2\17\u00e0\3\2\2\2\21\u00e2\3\2\2\2\23\u00e4\3\2\2\2\25\u00ea"+ + "\3\2\2\2\27\u00f1\3\2\2\2\31\u00f7\3\2\2\2\33\u0100\3\2\2\2\35\u0107\3"+ + "\2\2\2\37\u0110\3\2\2\2!\u011a\3\2\2\2#\u0122\3\2\2\2%\u0125\3\2\2\2\'"+ + "\u012a\3\2\2\2)\u0130\3\2\2\2+\u0133\3\2\2\2-\u0137\3\2\2\2/\u013e\3\2"+ + "\2\2\61\u0144\3\2\2\2\63\u014d\3\2\2\2\65\u0151\3\2\2\2\67\u0153\3\2\2"+ + "\29\u0156\3\2\2\2;\u015d\3\2\2\2=\u0166\3\2\2\2?\u0168\3\2\2\2A\u016a"+ + "\3\2\2\2C\u016c\3\2\2\2E\u0173\3\2\2\2G\u017a\3\2\2\2I\u0181\3\2\2\2K"+ + "\u0184\3\2\2\2M\u0187\3\2\2\2O\u0189\3\2\2\2Q\u018b\3\2\2\2S\u018d\3\2"+ + "\2\2U\u018f\3\2\2\2W\u0191\3\2\2\2Y\u0194\3\2\2\2[\u0197\3\2\2\2]\u0199"+ + "\3\2\2\2_\u019b\3\2\2\2a\u019d\3\2\2\2c\u019f\3\2\2\2e\u01a2\3\2\2\2g"+ + "\u01a5\3\2\2\2i\u01a8\3\2\2\2k\u01ab\3\2\2\2m\u01ad\3\2\2\2o\u01af\3\2"+ + "\2\2q\u01b2\3\2\2\2s\u01b5\3\2\2\2u\u01b7\3\2\2\2w\u01ba\3\2\2\2y\u01bd"+ + "\3\2\2\2{\u01c0\3\2\2\2}\u01c3\3\2\2\2\177\u01c6\3\2\2\2\u0081\u01ca\3"+ + "\2\2\2\u0083\u01ce\3\2\2\2\u0085\u01d1\3\2\2\2\u0087\u01d4\3\2\2\2\u0089"+ + "\u01d7\3\2\2\2\u008b\u01df\3\2\2\2\u008d\u01e8\3\2\2\2\u008f\u01ed\3\2"+ + "\2\2\u0091\u01f6\3\2\2\2\u0093\u01fc\3\2\2\2\u0095\u0203\3\2\2\2\u0097"+ + "\u0206\3\2\2\2\u0099\u020c\3\2\2\2\u009b\u020e\3\2\2\2\u009d\u02ee\3\2"+ + "\2\2\u009f\u02f0\3\2\2\2\u00a1\u0321\3\2\2\2\u00a3\u0323\3\2\2\2\u00a5"+ + "\u0330\3\2\2\2\u00a7\u0341\3\2\2\2\u00a9\u0345\3\2\2\2\u00ab\u034a\3\2"+ + "\2\2\u00ad\u0351\3\2\2\2\u00af\u0362\3\2\2\2\u00b1\u0370\3\2\2\2\u00b3"+ + "\u0381\3\2\2\2\u00b5\u0395\3\2\2\2\u00b7\u0398\3\2\2\2\u00b9\u03a1\3\2"+ + "\2\2\u00bb\u03a8\3\2\2\2\u00bd\u03aa\3\2\2\2\u00bf\u03ac\3\2\2\2\u00c1"+ + "\u03ae\3\2\2\2\u00c3\u03b5\3\2\2\2\u00c5\u03b7\3\2\2\2\u00c7\u03b9\3\2"+ + "\2\2\u00c9\u03c6\3\2\2\2\u00cb\u03cc\3\2\2\2\u00cd\u03d7\3\2\2\2\u00cf"+ + "\u00d0\7k\2\2\u00d0\u00d1\7o\2\2\u00d1\u00d2\7r\2\2\u00d2\u00d3\7q\2\2"+ + "\u00d3\u00d4\7t\2\2\u00d4\u00d5\7v\2\2\u00d5\4\3\2\2\2\u00d6\u00d7\7="+ + "\2\2\u00d7\6\3\2\2\2\u00d8\u00d9\7.\2\2\u00d9\b\3\2\2\2\u00da\u00db\7"+ + "?\2\2\u00db\n\3\2\2\2\u00dc\u00dd\7*\2\2\u00dd\f\3\2\2\2\u00de\u00df\7"+ + "+\2\2\u00df\16\3\2\2\2\u00e0\u00e1\7}\2\2\u00e1\20\3\2\2\2\u00e2\u00e3"+ + "\7\177\2\2\u00e3\22\3\2\2\2\u00e4\u00e5\7e\2\2\u00e5\u00e6\7q\2\2\u00e6"+ + "\u00e7\7p\2\2\u00e7\u00e8\7u\2\2\u00e8\u00e9\7v\2\2\u00e9\24\3\2\2\2\u00ea"+ + "\u00eb\7g\2\2\u00eb\u00ec\7z\2\2\u00ec\u00ed\7v\2\2\u00ed\u00ee\7g\2\2"+ + "\u00ee\u00ef\7t\2\2\u00ef\u00f0\7p\2\2\u00f0\26\3\2\2\2\u00f1\u00f2\7"+ + "c\2\2\u00f2\u00f3\7n\2\2\u00f3\u00f4\7k\2\2\u00f4\u00f5\7i\2\2\u00f5\u00f6"+ + "\7p\2\2\u00f6\30\3\2\2\2\u00f7\u00f8\7t\2\2\u00f8\u00f9\7g\2\2\u00f9\u00fa"+ + "\7i\2\2\u00fa\u00fb\7k\2\2\u00fb\u00fc\7u\2\2\u00fc\u00fd\7v\2\2\u00fd"+ + "\u00fe\7g\2\2\u00fe\u00ff\7t\2\2\u00ff\32\3\2\2\2\u0100\u0101\7k\2\2\u0101"+ + "\u0102\7p\2\2\u0102\u0103\7n\2\2\u0103\u0104\7k\2\2\u0104\u0105\7p\2\2"+ + "\u0105\u0106\7g\2\2\u0106\34\3\2\2\2\u0107\u0108\7x\2\2\u0108\u0109\7"+ + "q\2\2\u0109\u010a\7n\2\2\u010a\u010b\7c\2\2\u010b\u010c\7v\2\2\u010c\u010d"+ + "\7k\2\2\u010d\u010e\7n\2\2\u010e\u010f\7g\2\2\u010f\36\3\2\2\2\u0110\u0111"+ + "\7k\2\2\u0111\u0112\7p\2\2\u0112\u0113\7v\2\2\u0113\u0114\7g\2\2\u0114"+ + "\u0115\7t\2\2\u0115\u0116\7t\2\2\u0116\u0117\7w\2\2\u0117\u0118\7r\2\2"+ + "\u0118\u0119\7v\2\2\u0119 \3\2\2\2\u011a\u011b\7t\2\2\u011b\u011c\7g\2"+ + "\2\u011c\u011d\7u\2\2\u011d\u011e\7g\2\2\u011e\u011f\7t\2\2\u011f\u0120"+ + "\7x\2\2\u0120\u0121\7g\2\2\u0121\"\3\2\2\2\u0122\u0123\7k\2\2\u0123\u0124"+ + "\7h\2\2\u0124$\3\2\2\2\u0125\u0126\7g\2\2\u0126\u0127\7n\2\2\u0127\u0128"+ + "\7u\2\2\u0128\u0129\7g\2\2\u0129&\3\2\2\2\u012a\u012b\7y\2\2\u012b\u012c"+ + "\7j\2\2\u012c\u012d\7k\2\2\u012d\u012e\7n\2\2\u012e\u012f\7g\2\2\u012f"+ + "(\3\2\2\2\u0130\u0131\7f\2\2\u0131\u0132\7q\2\2\u0132*\3\2\2\2\u0133\u0134"+ + "\7h\2\2\u0134\u0135\7q\2\2\u0135\u0136\7t\2\2\u0136,\3\2\2\2\u0137\u0138"+ + "\7t\2\2\u0138\u0139\7g\2\2\u0139\u013a\7v\2\2\u013a\u013b\7w\2\2\u013b"+ + "\u013c\7t\2\2\u013c\u013d\7p\2\2\u013d.\3\2\2\2\u013e\u013f\7d\2\2\u013f"+ + "\u0140\7t\2\2\u0140\u0141\7g\2\2\u0141\u0142\7c\2\2\u0142\u0143\7m\2\2"+ + "\u0143\60\3\2\2\2\u0144\u0145\7e\2\2\u0145\u0146\7q\2\2\u0146\u0147\7"+ + "p\2\2\u0147\u0148\7v\2\2\u0148\u0149\7k\2\2\u0149\u014a\7p\2\2\u014a\u014b"+ + "\7w\2\2\u014b\u014c\7g\2\2\u014c\62\3\2\2\2\u014d\u014e\7c\2\2\u014e\u014f"+ + "\7u\2\2\u014f\u0150\7o\2\2\u0150\64\3\2\2\2\u0151\u0152\7<\2\2\u0152\66"+ + "\3\2\2\2\u0153\u0154\7\60\2\2\u0154\u0155\7\60\2\2\u01558\3\2\2\2\u0156"+ + "\u0157\7u\2\2\u0157\u0158\7k\2\2\u0158\u0159\7i\2\2\u0159\u015a\7p\2\2"+ + "\u015a\u015b\7g\2\2\u015b\u015c\7f\2\2\u015c:\3\2\2\2\u015d\u015e\7w\2"+ + "\2\u015e\u015f\7p\2\2\u015f\u0160\7u\2\2\u0160\u0161\7k\2\2\u0161\u0162"+ + "\7i\2\2\u0162\u0163\7p\2\2\u0163\u0164\7g\2\2\u0164\u0165\7f\2\2\u0165"+ + "<\3\2\2\2\u0166\u0167\7,\2\2\u0167>\3\2\2\2\u0168\u0169\7]\2\2\u0169@"+ + "\3\2\2\2\u016a\u016b\7_\2\2\u016bB\3\2\2\2\u016c\u016d\7u\2\2\u016d\u016e"+ + "\7v\2\2\u016e\u016f\7t\2\2\u016f\u0170\7w\2\2\u0170\u0171\7e\2\2\u0171"+ + "\u0172\7v\2\2\u0172D\3\2\2\2\u0173\u0174\7u\2\2\u0174\u0175\7k\2\2\u0175"+ + "\u0176\7|\2\2\u0176\u0177\7g\2\2\u0177\u0178\7q\2\2\u0178\u0179\7h\2\2"+ + "\u0179F\3\2\2\2\u017a\u017b\7v\2\2\u017b\u017c\7{\2\2\u017c\u017d\7r\2"+ + "\2\u017d\u017e\7g\2\2\u017e\u017f\7k\2\2\u017f\u0180\7f\2\2\u0180H\3\2"+ + "\2\2\u0181\u0182\7/\2\2\u0182\u0183\7/\2\2\u0183J\3\2\2\2\u0184\u0185"+ + "\7-\2\2\u0185\u0186\7-\2\2\u0186L\3\2\2\2\u0187\u0188\7-\2\2\u0188N\3"+ + "\2\2\2\u0189\u018a\7/\2\2\u018aP\3\2\2\2\u018b\u018c\7#\2\2\u018cR\3\2"+ + "\2\2\u018d\u018e\7(\2\2\u018eT\3\2\2\2\u018f\u0190\7\u0080\2\2\u0190V"+ + "\3\2\2\2\u0191\u0192\7@\2\2\u0192\u0193\7@\2\2\u0193X\3\2\2\2\u0194\u0195"+ + "\7>\2\2\u0195\u0196\7>\2\2\u0196Z\3\2\2\2\u0197\u0198\7\61\2\2\u0198\\"+ + "\3\2\2\2\u0199\u019a\7\'\2\2\u019a^\3\2\2\2\u019b\u019c\7>\2\2\u019c`"+ + "\3\2\2\2\u019d\u019e\7@\2\2\u019eb\3\2\2\2\u019f\u01a0\7?\2\2\u01a0\u01a1"+ + "\7?\2\2\u01a1d\3\2\2\2\u01a2\u01a3\7#\2\2\u01a3\u01a4\7?\2\2\u01a4f\3"+ + "\2\2\2\u01a5\u01a6\7>\2\2\u01a6\u01a7\7?\2\2\u01a7h\3\2\2\2\u01a8\u01a9"+ + "\7@\2\2\u01a9\u01aa\7?\2\2\u01aaj\3\2\2\2\u01ab\u01ac\7`\2\2\u01acl\3"+ + "\2\2\2\u01ad\u01ae\7~\2\2\u01aen\3\2\2\2\u01af\u01b0\7(\2\2\u01b0\u01b1"+ + "\7(\2\2\u01b1p\3\2\2\2\u01b2\u01b3\7~\2\2\u01b3\u01b4\7~\2\2\u01b4r\3"+ + "\2\2\2\u01b5\u01b6\7A\2\2\u01b6t\3\2\2\2\u01b7\u01b8\7-\2\2\u01b8\u01b9"+ + "\7?\2\2\u01b9v\3\2\2\2\u01ba\u01bb\7/\2\2\u01bb\u01bc\7?\2\2\u01bcx\3"+ + "\2\2\2\u01bd\u01be\7,\2\2\u01be\u01bf\7?\2\2\u01bfz\3\2\2\2\u01c0\u01c1"+ + "\7\61\2\2\u01c1\u01c2\7?\2\2\u01c2|\3\2\2\2\u01c3\u01c4\7\'\2\2\u01c4"+ + "\u01c5\7?\2\2\u01c5~\3\2\2\2\u01c6\u01c7\7>\2\2\u01c7\u01c8\7>\2\2\u01c8"+ + "\u01c9\7?\2\2\u01c9\u0080\3\2\2\2\u01ca\u01cb\7@\2\2\u01cb\u01cc\7@\2"+ + "\2\u01cc\u01cd\7?\2\2\u01cd\u0082\3\2\2\2\u01ce\u01cf\7(\2\2\u01cf\u01d0"+ + "\7?\2\2\u01d0\u0084\3\2\2\2\u01d1\u01d2\7~\2\2\u01d2\u01d3\7?\2\2\u01d3"+ + "\u0086\3\2\2\2\u01d4\u01d5\7`\2\2\u01d5\u01d6\7?\2\2\u01d6\u0088\3\2\2"+ + "\2\u01d7\u01d8\7m\2\2\u01d8\u01d9\7k\2\2\u01d9\u01da\7e\2\2\u01da\u01db"+ + "\7m\2\2\u01db\u01dc\7c\2\2\u01dc\u01dd\7u\2\2\u01dd\u01de\7o\2\2\u01de"+ + "\u008a\3\2\2\2\u01df\u01e0\7t\2\2\u01e0\u01e1\7g\2\2\u01e1\u01e2\7u\2"+ + "\2\u01e2\u01e3\7q\2\2\u01e3\u01e4\7w\2\2\u01e4\u01e5\7t\2\2\u01e5\u01e6"+ + "\7e\2\2\u01e6\u01e7\7g\2\2\u01e7\u008c\3\2\2\2\u01e8\u01e9\7w\2\2\u01e9"+ + "\u01ea\7u\2\2\u01ea\u01eb\7g\2\2\u01eb\u01ec\7u\2\2\u01ec\u008e\3\2\2"+ + "\2\u01ed\u01ee\7e\2\2\u01ee\u01ef\7n\2\2\u01ef\u01f0\7q\2\2\u01f0\u01f1"+ + "\7d\2\2\u01f1\u01f2\7d\2\2\u01f2\u01f3\7g\2\2\u01f3\u01f4\7t\2\2\u01f4"+ + "\u01f5\7u\2\2\u01f5\u0090\3\2\2\2\u01f6\u01f7\7d\2\2\u01f7\u01f8\7{\2"+ + "\2\u01f8\u01f9\7v\2\2\u01f9\u01fa\7g\2\2\u01fa\u01fb\7u\2\2\u01fb\u0092"+ + "\3\2\2\2\u01fc\u01fd\7e\2\2\u01fd\u01fe\7{\2\2\u01fe\u01ff\7e\2\2\u01ff"+ + "\u0200\7n\2\2\u0200\u0201\7g\2\2\u0201\u0202\7u\2\2\u0202\u0094\3\2\2"+ + "\2\u0203\u0204\7r\2\2\u0204\u0205\7e\2\2\u0205\u0096\3\2\2\2\u0206\u0207"+ + "\7\60\2\2\u0207\u0208\7d\2\2\u0208\u0209\7{\2\2\u0209\u020a\7v\2\2\u020a"+ + "\u020b\7g\2\2\u020b\u0098\3\2\2\2\u020c\u020d\7%\2\2\u020d\u009a\3\2\2"+ + "\2\u020e\u020f\7\60\2\2\u020f\u009c\3\2\2\2\u0210\u0211\7d\2\2\u0211\u0212"+ + "\7t\2\2\u0212\u02ef\7m\2\2\u0213\u0214\7q\2\2\u0214\u0215\7t\2\2\u0215"+ + "\u02ef\7c\2\2\u0216\u0217\7m\2\2\u0217\u0218\7k\2\2\u0218\u02ef\7n\2\2"+ + "\u0219\u021a\7u\2\2\u021a\u021b\7n\2\2\u021b\u02ef\7q\2\2\u021c\u021d"+ + "\7p\2\2\u021d\u021e\7q\2\2\u021e\u02ef\7r\2\2\u021f\u0220\7c\2\2\u0220"+ + "\u0221\7u\2\2\u0221\u02ef\7n\2\2\u0222\u0223\7r\2\2\u0223\u0224\7j\2\2"+ + "\u0224\u02ef\7r\2\2\u0225\u0226\7c\2\2\u0226\u0227\7p\2\2\u0227\u02ef"+ + "\7e\2\2\u0228\u0229\7d\2\2\u0229\u022a\7r\2\2\u022a\u02ef\7n\2\2\u022b"+ + "\u022c\7e\2\2\u022c\u022d\7n\2\2\u022d\u02ef\7e\2\2\u022e\u022f\7l\2\2"+ + "\u022f\u0230\7u\2\2\u0230\u02ef\7t\2\2\u0231\u0232\7c\2\2\u0232\u0233"+ + "\7p\2\2\u0233\u02ef\7f\2\2\u0234\u0235\7t\2\2\u0235\u0236\7n\2\2\u0236"+ + "\u02ef\7c\2\2\u0237\u0238\7d\2\2\u0238\u0239\7k\2\2\u0239\u02ef\7v\2\2"+ + "\u023a\u023b\7t\2\2\u023b\u023c\7q\2\2\u023c\u02ef\7n\2\2\u023d\u023e"+ + "\7r\2\2\u023e\u023f\7n\2\2\u023f\u02ef\7c\2\2\u0240\u0241\7r\2\2\u0241"+ + "\u0242\7n\2\2\u0242\u02ef\7r\2\2\u0243\u0244\7d\2\2\u0244\u0245\7o\2\2"+ + "\u0245\u02ef\7k\2\2\u0246\u0247\7u\2\2\u0247\u0248\7g\2\2\u0248\u02ef"+ + "\7e\2\2\u0249\u024a\7t\2\2\u024a\u024b\7v\2\2\u024b\u02ef\7k\2\2\u024c"+ + "\u024d\7g\2\2\u024d\u024e\7q\2\2\u024e\u02ef\7t\2\2\u024f\u0250\7u\2\2"+ + "\u0250\u0251\7t\2\2\u0251\u02ef\7g\2\2\u0252\u0253\7n\2\2\u0253\u0254"+ + "\7u\2\2\u0254\u02ef\7t\2\2\u0255\u0256\7r\2\2\u0256\u0257\7j\2\2\u0257"+ + "\u02ef\7c\2\2\u0258\u0259\7c\2\2\u0259\u025a\7n\2\2\u025a\u02ef\7t\2\2"+ + "\u025b\u025c\7l\2\2\u025c\u025d\7o\2\2\u025d\u02ef\7r\2\2\u025e\u025f"+ + "\7d\2\2\u025f\u0260\7x\2\2\u0260\u02ef\7e\2\2\u0261\u0262\7e\2\2\u0262"+ + "\u0263\7n\2\2\u0263\u02ef\7k\2\2\u0264\u0265\7t\2\2\u0265\u0266\7v\2\2"+ + "\u0266\u02ef\7u\2\2\u0267\u0268\7c\2\2\u0268\u0269\7f\2\2\u0269\u02ef"+ + "\7e\2\2\u026a\u026b\7t\2\2\u026b\u026c\7t\2\2\u026c\u02ef\7c\2\2\u026d"+ + "\u026e\7d\2\2\u026e\u026f\7x\2\2\u026f\u02ef\7u\2\2\u0270\u0271\7u\2\2"+ + "\u0271\u0272\7g\2\2\u0272\u02ef\7k\2\2\u0273\u0274\7u\2\2\u0274\u0275"+ + "\7c\2\2\u0275\u02ef\7z\2\2\u0276\u0277\7u\2\2\u0277\u0278\7v\2\2\u0278"+ + "\u02ef\7{\2\2\u0279\u027a\7u\2\2\u027a\u027b\7v\2\2\u027b\u02ef\7c\2\2"+ + "\u027c\u027d\7u\2\2\u027d\u027e\7v\2\2\u027e\u02ef\7z\2\2\u027f\u0280"+ + "\7f\2\2\u0280\u0281\7g\2\2\u0281\u02ef\7{\2\2\u0282\u0283\7v\2\2\u0283"+ + "\u0284\7z\2\2\u0284\u02ef\7c\2\2\u0285\u0286\7z\2\2\u0286\u0287\7c\2\2"+ + "\u0287\u02ef\7c\2\2\u0288\u0289\7d\2\2\u0289\u028a\7e\2\2\u028a\u02ef"+ + "\7e\2\2\u028b\u028c\7c\2\2\u028c\u028d\7j\2\2\u028d\u02ef\7z\2\2\u028e"+ + "\u028f\7v\2\2\u028f\u0290\7{\2\2\u0290\u02ef\7c\2\2\u0291\u0292\7v\2\2"+ + "\u0292\u0293\7z\2\2\u0293\u02ef\7u\2\2\u0294\u0295\7v\2\2\u0295\u0296"+ + "\7c\2\2\u0296\u02ef\7u\2\2\u0297\u0298\7u\2\2\u0298\u0299\7j\2\2\u0299"+ + "\u02ef\7{\2\2\u029a\u029b\7u\2\2\u029b\u029c\7j\2\2\u029c\u02ef\7z\2\2"+ + "\u029d\u029e\7n\2\2\u029e\u029f\7f\2\2\u029f\u02ef\7{\2\2\u02a0\u02a1"+ + "\7n\2\2\u02a1\u02a2\7f\2\2\u02a2\u02ef\7c\2\2\u02a3\u02a4\7n\2\2\u02a4"+ + "\u02a5\7f\2\2\u02a5\u02ef\7z\2\2\u02a6\u02a7\7n\2\2\u02a7\u02a8\7c\2\2"+ + "\u02a8\u02ef\7z\2\2\u02a9\u02aa\7v\2\2\u02aa\u02ab\7c\2\2\u02ab\u02ef"+ + "\7{\2\2\u02ac\u02ad\7v\2\2\u02ad\u02ae\7c\2\2\u02ae\u02ef\7z\2\2\u02af"+ + "\u02b0\7d\2\2\u02b0\u02b1\7e\2\2\u02b1\u02ef\7u\2\2\u02b2\u02b3\7e\2\2"+ + "\u02b3\u02b4\7n\2\2\u02b4\u02ef\7x\2\2\u02b5\u02b6\7v\2\2\u02b6\u02b7"+ + "\7u\2\2\u02b7\u02ef\7z\2\2\u02b8\u02b9\7n\2\2\u02b9\u02ba\7c\2\2\u02ba"+ + "\u02ef\7u\2\2\u02bb\u02bc\7e\2\2\u02bc\u02bd\7r\2\2\u02bd\u02ef\7{\2\2"+ + "\u02be\u02bf\7e\2\2\u02bf\u02c0\7o\2\2\u02c0\u02ef\7r\2\2\u02c1\u02c2"+ + "\7e\2\2\u02c2\u02c3\7r\2\2\u02c3\u02ef\7z\2\2\u02c4\u02c5\7f\2\2\u02c5"+ + "\u02c6\7e\2\2\u02c6\u02ef\7r\2\2\u02c7\u02c8\7f\2\2\u02c8\u02c9\7g\2\2"+ + "\u02c9\u02ef\7e\2\2\u02ca\u02cb\7k\2\2\u02cb\u02cc\7p\2\2\u02cc\u02ef"+ + "\7e\2\2\u02cd\u02ce\7c\2\2\u02ce\u02cf\7z\2\2\u02cf\u02ef\7u\2\2\u02d0"+ + "\u02d1\7d\2\2\u02d1\u02d2\7p\2\2\u02d2\u02ef\7g\2\2\u02d3\u02d4\7e\2\2"+ + "\u02d4\u02d5\7n\2\2\u02d5\u02ef\7f\2\2\u02d6\u02d7\7u\2\2\u02d7\u02d8"+ + "\7d\2\2\u02d8\u02ef\7e\2\2\u02d9\u02da\7k\2\2\u02da\u02db\7u\2\2\u02db"+ + "\u02ef\7e\2\2\u02dc\u02dd\7k\2\2\u02dd\u02de\7p\2\2\u02de\u02ef\7z\2\2"+ + "\u02df\u02e0\7d\2\2\u02e0\u02e1\7g\2\2\u02e1\u02ef\7s\2\2\u02e2\u02e3"+ + "\7u\2\2\u02e3\u02e4\7g\2\2\u02e4\u02ef\7f\2\2\u02e5\u02e6\7f\2\2\u02e6"+ + "\u02e7\7g\2\2\u02e7\u02ef\7z\2\2\u02e8\u02e9\7k\2\2\u02e9\u02ea\7p\2\2"+ + "\u02ea\u02ef\7{\2\2\u02eb\u02ec\7t\2\2\u02ec\u02ed\7q\2\2\u02ed\u02ef"+ + "\7t\2\2\u02ee\u0210\3\2\2\2\u02ee\u0213\3\2\2\2\u02ee\u0216\3\2\2\2\u02ee"+ + "\u0219\3\2\2\2\u02ee\u021c\3\2\2\2\u02ee\u021f\3\2\2\2\u02ee\u0222\3\2"+ + "\2\2\u02ee\u0225\3\2\2\2\u02ee\u0228\3\2\2\2\u02ee\u022b\3\2\2\2\u02ee"+ + "\u022e\3\2\2\2\u02ee\u0231\3\2\2\2\u02ee\u0234\3\2\2\2\u02ee\u0237\3\2"+ + "\2\2\u02ee\u023a\3\2\2\2\u02ee\u023d\3\2\2\2\u02ee\u0240\3\2\2\2\u02ee"+ + "\u0243\3\2\2\2\u02ee\u0246\3\2\2\2\u02ee\u0249\3\2\2\2\u02ee\u024c\3\2"+ + "\2\2\u02ee\u024f\3\2\2\2\u02ee\u0252\3\2\2\2\u02ee\u0255\3\2\2\2\u02ee"+ + "\u0258\3\2\2\2\u02ee\u025b\3\2\2\2\u02ee\u025e\3\2\2\2\u02ee\u0261\3\2"+ + "\2\2\u02ee\u0264\3\2\2\2\u02ee\u0267\3\2\2\2\u02ee\u026a\3\2\2\2\u02ee"+ + "\u026d\3\2\2\2\u02ee\u0270\3\2\2\2\u02ee\u0273\3\2\2\2\u02ee\u0276\3\2"+ + "\2\2\u02ee\u0279\3\2\2\2\u02ee\u027c\3\2\2\2\u02ee\u027f\3\2\2\2\u02ee"+ + "\u0282\3\2\2\2\u02ee\u0285\3\2\2\2\u02ee\u0288\3\2\2\2\u02ee\u028b\3\2"+ + "\2\2\u02ee\u028e\3\2\2\2\u02ee\u0291\3\2\2\2\u02ee\u0294\3\2\2\2\u02ee"+ + "\u0297\3\2\2\2\u02ee\u029a\3\2\2\2\u02ee\u029d\3\2\2\2\u02ee\u02a0\3\2"+ + "\2\2\u02ee\u02a3\3\2\2\2\u02ee\u02a6\3\2\2\2\u02ee\u02a9\3\2\2\2\u02ee"+ + "\u02ac\3\2\2\2\u02ee\u02af\3\2\2\2\u02ee\u02b2\3\2\2\2\u02ee\u02b5\3\2"+ + "\2\2\u02ee\u02b8\3\2\2\2\u02ee\u02bb\3\2\2\2\u02ee\u02be\3\2\2\2\u02ee"+ + "\u02c1\3\2\2\2\u02ee\u02c4\3\2\2\2\u02ee\u02c7\3\2\2\2\u02ee\u02ca\3\2"+ + "\2\2\u02ee\u02cd\3\2\2\2\u02ee\u02d0\3\2\2\2\u02ee\u02d3\3\2\2\2\u02ee"+ + "\u02d6\3\2\2\2\u02ee\u02d9\3\2\2\2\u02ee\u02dc\3\2\2\2\u02ee\u02df\3\2"+ + "\2\2\u02ee\u02e2\3\2\2\2\u02ee\u02e5\3\2\2\2\u02ee\u02e8\3\2\2\2\u02ee"+ + "\u02eb\3\2\2\2\u02ef\u009e\3\2\2\2\u02f0\u02f1\7}\2\2\u02f1\u02f2\7}\2"+ + "\2\u02f2\u02f6\3\2\2\2\u02f3\u02f5\13\2\2\2\u02f4\u02f3\3\2\2\2\u02f5"+ + "\u02f8\3\2\2\2\u02f6\u02f7\3\2\2\2\u02f6\u02f4\3\2\2\2\u02f7\u02f9\3\2"+ + "\2\2\u02f8\u02f6\3\2\2\2\u02f9\u02fa\7\177\2\2\u02fa\u02fb\7\177\2\2\u02fb"+ + "\u00a0\3\2\2\2\u02fc\u02fd\7d\2\2\u02fd\u02fe\7{\2\2\u02fe\u02ff\7v\2"+ + "\2\u02ff\u0322\7g\2\2\u0300\u0301\7y\2\2\u0301\u0302\7q\2\2\u0302\u0303"+ + "\7t\2\2\u0303\u0322\7f\2\2\u0304\u0305\7f\2\2\u0305\u0306\7y\2\2\u0306"+ + "\u0307\7q\2\2\u0307\u0308\7t\2\2\u0308\u0322\7f\2\2\u0309\u030a\7d\2\2"+ + "\u030a\u030b\7q\2\2\u030b\u030c\7q\2\2\u030c\u0322\7n\2\2\u030d\u030e"+ + "\7e\2\2\u030e\u030f\7j\2\2\u030f\u0310\7c\2\2\u0310\u0322\7t\2\2\u0311"+ + "\u0312\7u\2\2\u0312\u0313\7j\2\2\u0313\u0314\7q\2\2\u0314\u0315\7t\2\2"+ + "\u0315\u0322\7v\2\2\u0316\u0317\7k\2\2\u0317\u0318\7p\2\2\u0318\u0322"+ + "\7v\2\2\u0319\u031a\7n\2\2\u031a\u031b\7q\2\2\u031b\u031c\7p\2\2\u031c"+ + "\u0322\7i\2\2\u031d\u031e\7x\2\2\u031e\u031f\7q\2\2\u031f\u0320\7k\2\2"+ + "\u0320\u0322\7f\2\2\u0321\u02fc\3\2\2\2\u0321\u0300\3\2\2\2\u0321\u0304"+ + "\3\2\2\2\u0321\u0309\3\2\2\2\u0321\u030d\3\2\2\2\u0321\u0311\3\2\2\2\u0321"+ + "\u0316\3\2\2\2\u0321\u0319\3\2\2\2\u0321\u031d\3\2\2\2\u0322\u00a2\3\2"+ + "\2\2\u0323\u0329\7$\2\2\u0324\u0325\7^\2\2\u0325\u0328\7$\2\2\u0326\u0328"+ + "\n\2\2\2\u0327\u0324\3\2\2\2\u0327\u0326\3\2\2\2\u0328\u032b\3\2\2\2\u0329"+ + "\u0327\3\2\2\2\u0329\u032a\3\2\2\2\u032a\u032c\3\2\2\2\u032b\u0329\3\2"+ + "\2\2\u032c\u032e\7$\2\2\u032d\u032f\7|\2\2\u032e\u032d\3\2\2\2\u032e\u032f"+ + "\3\2\2\2\u032f\u00a4\3\2\2\2\u0330\u0334\7)\2\2\u0331\u0332\7^\2\2\u0332"+ + "\u0335\7)\2\2\u0333\u0335\n\3\2\2\u0334\u0331\3\2\2\2\u0334\u0333\3\2"+ + "\2\2\u0335\u0336\3\2\2\2\u0336\u0337\7)\2\2\u0337\u00a6\3\2\2\2\u0338"+ + "\u0339\7v\2\2\u0339\u033a\7t\2\2\u033a\u033b\7w\2\2\u033b\u0342\7g\2\2"+ + "\u033c\u033d\7h\2\2\u033d\u033e\7c\2\2\u033e\u033f\7n\2\2\u033f\u0340"+ + "\7u\2\2\u0340\u0342\7g\2\2\u0341\u0338\3\2\2\2\u0341\u033c\3\2\2\2\u0342"+ + "\u00a8\3\2\2\2\u0343\u0346\5\u00abV\2\u0344\u0346\5\u00b3Z\2\u0345\u0343"+ + "\3\2\2\2\u0345\u0344\3\2\2\2\u0346\u00aa\3\2\2\2\u0347\u034b\5\u00adW"+ + "\2\u0348\u034b\5\u00afX\2\u0349\u034b\5\u00b1Y\2\u034a\u0347\3\2\2\2\u034a"+ + "\u0348\3\2\2\2\u034a\u0349\3\2\2\2\u034b\u00ac\3\2\2\2\u034c\u0352\7\'"+ + "\2\2\u034d\u034e\7\62\2\2\u034e\u0352\7d\2\2\u034f\u0350\7\62\2\2\u0350"+ + "\u0352\7D\2\2\u0351\u034c\3\2\2\2\u0351\u034d\3\2\2\2\u0351\u034f\3\2"+ + "\2\2\u0352\u0356\3\2\2\2\u0353\u0355\5\u00bb^\2\u0354\u0353\3\2\2\2\u0355"+ + "\u0358\3\2\2\2\u0356\u0354\3\2\2\2\u0356\u0357\3\2\2\2\u0357\u0359\3\2"+ + "\2\2\u0358\u0356\3\2\2\2\u0359\u035b\7\60\2\2\u035a\u035c\5\u00bb^\2\u035b"+ + "\u035a\3\2\2\2\u035c\u035d\3\2\2\2\u035d\u035b\3\2\2\2\u035d\u035e\3\2"+ + "\2\2\u035e\u00ae\3\2\2\2\u035f\u0361\5\u00bd_\2\u0360\u035f\3\2\2\2\u0361"+ + "\u0364\3\2\2\2\u0362\u0360\3\2\2\2\u0362\u0363\3\2\2\2\u0363\u0365\3\2"+ + "\2\2\u0364\u0362\3\2\2\2\u0365\u0367\7\60\2\2\u0366\u0368\5\u00bd_\2\u0367"+ + "\u0366\3\2\2\2\u0368\u0369\3\2\2\2\u0369\u0367\3\2\2\2\u0369\u036a\3\2"+ + "\2\2\u036a\u00b0\3\2\2\2\u036b\u0371\7&\2\2\u036c\u036d\7\62\2\2\u036d"+ + "\u0371\7z\2\2\u036e\u036f\7\62\2\2\u036f\u0371\7Z\2\2\u0370\u036b\3\2"+ + "\2\2\u0370\u036c\3\2\2\2\u0370\u036e\3\2\2\2\u0371\u0375\3\2\2\2\u0372"+ + "\u0374\5\u00bf`\2\u0373\u0372\3\2\2\2\u0374\u0377\3\2\2\2\u0375\u0373"+ + "\3\2\2\2\u0375\u0376\3\2\2\2\u0376\u0378\3\2\2\2\u0377\u0375\3\2\2\2\u0378"+ + "\u037a\7\60\2\2\u0379\u037b\5\u00bf`\2\u037a\u0379\3\2\2\2\u037b\u037c"+ + "\3\2\2\2\u037c\u037a\3\2\2\2\u037c\u037d\3\2\2\2\u037d\u00b2\3\2\2\2\u037e"+ + "\u0382\5\u00b7\\\2\u037f\u0382\5\u00b9]\2\u0380\u0382\5\u00b5[\2\u0381"+ + "\u037e\3\2\2\2\u0381\u037f\3\2\2\2\u0381\u0380\3\2\2\2\u0382\u0386\3\2"+ + "\2\2\u0383\u0384\t\4\2\2\u0384\u0387\t\5\2\2\u0385\u0387\7n\2\2\u0386"+ + "\u0383\3\2\2\2\u0386\u0385\3\2\2\2\u0386\u0387\3\2\2\2\u0387\u00b4\3\2"+ + "\2\2\u0388\u0389\7\62\2\2\u0389\u038b\t\6\2\2\u038a\u038c\5\u00bb^\2\u038b"+ + "\u038a\3\2\2\2\u038c\u038d\3\2\2\2\u038d\u038b\3\2\2\2\u038d\u038e\3\2"+ + "\2\2\u038e\u0396\3\2\2\2\u038f\u0391\7\'\2\2\u0390\u0392\5\u00bb^\2\u0391"+ + "\u0390\3\2\2\2\u0392\u0393\3\2\2\2\u0393\u0391\3\2\2\2\u0393\u0394\3\2"+ + "\2\2\u0394\u0396\3\2\2\2\u0395\u0388\3\2\2\2\u0395\u038f\3\2\2\2\u0396"+ + "\u00b6\3\2\2\2\u0397\u0399\5\u00bd_\2\u0398\u0397\3\2\2\2\u0399\u039a"+ + "\3\2\2\2\u039a\u0398\3\2\2\2\u039a\u039b\3\2\2\2\u039b\u00b8\3\2\2\2\u039c"+ + "\u03a2\7&\2\2\u039d\u039e\7\62\2\2\u039e\u03a2\7z\2\2\u039f\u03a0\7\62"+ + "\2\2\u03a0\u03a2\7Z\2\2\u03a1\u039c\3\2\2\2\u03a1\u039d\3\2\2\2\u03a1"+ + "\u039f\3\2\2\2\u03a2\u03a4\3\2\2\2\u03a3\u03a5\5\u00bf`\2\u03a4\u03a3"+ + "\3\2\2\2\u03a5\u03a6\3\2\2\2\u03a6\u03a4\3\2\2\2\u03a6\u03a7\3\2\2\2\u03a7"+ + "\u00ba\3\2\2\2\u03a8\u03a9\t\7\2\2\u03a9\u00bc\3\2\2\2\u03aa\u03ab\t\b"+ + "\2\2\u03ab\u00be\3\2\2\2\u03ac\u03ad\t\t\2\2\u03ad\u00c0\3\2\2\2\u03ae"+ + "\u03b2\5\u00c3b\2\u03af\u03b1\5\u00c5c\2\u03b0\u03af\3\2\2\2\u03b1\u03b4"+ + "\3\2\2\2\u03b2\u03b0\3\2\2\2\u03b2\u03b3\3\2\2\2\u03b3\u00c2\3\2\2\2\u03b4"+ + "\u03b2\3\2\2\2\u03b5\u03b6\t\n\2\2\u03b6\u00c4\3\2\2\2\u03b7\u03b8\t\13"+ + "\2\2\u03b8\u00c6\3\2\2\2\u03b9\u03bd\7#\2\2\u03ba\u03bc\5\u00c5c\2\u03bb"+ + "\u03ba\3\2\2\2\u03bc\u03bf\3\2\2\2\u03bd\u03bb\3\2\2\2\u03bd\u03be\3\2"+ + "\2\2\u03be\u03c1\3\2\2\2\u03bf\u03bd\3\2\2\2\u03c0\u03c2\t\f\2\2\u03c1"+ + "\u03c0\3\2\2\2\u03c2\u03c3\3\2\2\2\u03c3\u03c1\3\2\2\2\u03c3\u03c4\3\2"+ + "\2\2\u03c4\u00c8\3\2\2\2\u03c5\u03c7\t\r\2\2\u03c6\u03c5\3\2\2\2\u03c7"+ + "\u03c8\3\2\2\2\u03c8\u03c6\3\2\2\2\u03c8\u03c9\3\2\2\2\u03c9\u03ca\3\2"+ + "\2\2\u03ca\u03cb\be\2\2\u03cb\u00ca\3\2\2\2\u03cc\u03cd\7\61\2\2\u03cd"+ + "\u03ce\7\61\2\2\u03ce\u03d2\3\2\2\2\u03cf\u03d1\n\16\2\2\u03d0\u03cf\3"+ + "\2\2\2\u03d1\u03d4\3\2\2\2\u03d2\u03d0\3\2\2\2\u03d2\u03d3\3\2\2\2\u03d3"+ + "\u03d5\3\2\2\2\u03d4\u03d2\3\2\2\2\u03d5\u03d6\bf\3\2\u03d6\u00cc\3\2"+ + "\2\2\u03d7\u03d8\7\61\2\2\u03d8\u03d9\7,\2\2\u03d9\u03dd\3\2\2\2\u03da"+ + "\u03dc\13\2\2\2\u03db\u03da\3\2\2\2\u03dc\u03df\3\2\2\2\u03dd\u03de\3"+ + "\2\2\2\u03dd\u03db\3\2\2\2\u03de\u03e0\3\2\2\2\u03df\u03dd\3\2\2\2\u03e0"+ + "\u03e1\7,\2\2\u03e1\u03e2\7\61\2\2\u03e2\u03e3\3\2\2\2\u03e3\u03e4\bg"+ + "\3\2\u03e4\u00ce\3\2\2\2#\2\u02ee\u02f6\u0321\u0327\u0329\u032e\u0334"+ + "\u0341\u0345\u034a\u0351\u0356\u035d\u0362\u0369\u0370\u0375\u037c\u0381"+ + "\u0386\u038d\u0393\u0395\u039a\u03a1\u03a6\u03b2\u03bd\u03c3\u03c8\u03d2"+ + "\u03dd\4\2\3\2\2\4\2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens index c69744d23..a303b96fe 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens +++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens @@ -74,26 +74,27 @@ T__72=73 T__73=74 T__74=75 T__75=76 -MNEMONIC=77 -KICKASM=78 -SIMPLETYPE=79 -STRING=80 -CHAR=81 -BOOLEAN=82 -NUMBER=83 -NUMFLOAT=84 -BINFLOAT=85 -DECFLOAT=86 -HEXFLOAT=87 -NUMINT=88 -BININTEGER=89 -DECINTEGER=90 -HEXINTEGER=91 -NAME=92 -ASMREL=93 -WS=94 -COMMENT_LINE=95 -COMMENT_BLOCK=96 +T__76=77 +MNEMONIC=78 +KICKASM=79 +SIMPLETYPE=80 +STRING=81 +CHAR=82 +BOOLEAN=83 +NUMBER=84 +NUMFLOAT=85 +BINFLOAT=86 +DECFLOAT=87 +HEXFLOAT=88 +NUMINT=89 +BININTEGER=90 +DECINTEGER=91 +HEXINTEGER=92 +NAME=93 +ASMREL=94 +WS=95 +COMMENT_LINE=96 +COMMENT_BLOCK=97 'import'=1 ';'=2 ','=3 @@ -126,47 +127,48 @@ COMMENT_BLOCK=96 '*'=30 '['=31 ']'=32 -'sizeof'=33 -'typeid'=34 -'--'=35 -'++'=36 -'+'=37 -'-'=38 -'!'=39 -'&'=40 -'~'=41 -'>>'=42 -'<<'=43 -'/'=44 -'%'=45 -'<'=46 -'>'=47 -'=='=48 -'!='=49 -'<='=50 -'>='=51 -'^'=52 -'|'=53 -'&&'=54 -'||'=55 -'?'=56 -'+='=57 -'-='=58 -'*='=59 -'/='=60 -'%='=61 -'<<='=62 -'>>='=63 -'&='=64 -'|='=65 -'^='=66 -'kickasm'=67 -'resource'=68 -'uses'=69 -'clobbers'=70 -'bytes'=71 -'cycles'=72 -'pc'=73 -'.byte'=74 -'#'=75 -'.'=76 +'struct'=33 +'sizeof'=34 +'typeid'=35 +'--'=36 +'++'=37 +'+'=38 +'-'=39 +'!'=40 +'&'=41 +'~'=42 +'>>'=43 +'<<'=44 +'/'=45 +'%'=46 +'<'=47 +'>'=48 +'=='=49 +'!='=50 +'<='=51 +'>='=52 +'^'=53 +'|'=54 +'&&'=55 +'||'=56 +'?'=57 +'+='=58 +'-='=59 +'*='=60 +'/='=61 +'%='=62 +'<<='=63 +'>>='=64 +'&='=65 +'|='=66 +'^='=67 +'kickasm'=68 +'resource'=69 +'uses'=70 +'clobbers'=71 +'bytes'=72 +'cycles'=73 +'pc'=74 +'.byte'=75 +'#'=76 +'.'=77 diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java index 54517c054..950823cc9 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java @@ -517,6 +517,18 @@ public interface KickCListener extends ParseTreeListener { * @param ctx the parse tree */ void exitTypeArray(KickCParser.TypeArrayContext ctx); + /** + * Enter a parse tree produced by the {@code typeStructRef} + * labeled alternative in {@link KickCParser#typeDecl}. + * @param ctx the parse tree + */ + void enterTypeStructRef(KickCParser.TypeStructRefContext ctx); + /** + * Exit a parse tree produced by the {@code typeStructRef} + * labeled alternative in {@link KickCParser#typeDecl}. + * @param ctx the parse tree + */ + void exitTypeStructRef(KickCParser.TypeStructRefContext ctx); /** * Enter a parse tree produced by the {@code typeSimple} * labeled alternative in {@link KickCParser#typeDecl}. @@ -529,6 +541,18 @@ public interface KickCListener extends ParseTreeListener { * @param ctx the parse tree */ void exitTypeSimple(KickCParser.TypeSimpleContext ctx); + /** + * Enter a parse tree produced by the {@code typeStructDef} + * labeled alternative in {@link KickCParser#typeDecl}. + * @param ctx the parse tree + */ + void enterTypeStructDef(KickCParser.TypeStructDefContext ctx); + /** + * Exit a parse tree produced by the {@code typeStructDef} + * labeled alternative in {@link KickCParser#typeDecl}. + * @param ctx the parse tree + */ + void exitTypeStructDef(KickCParser.TypeStructDefContext ctx); /** * Enter a parse tree produced by the {@code typeSignedSimple} * labeled alternative in {@link KickCParser#typeDecl}. @@ -541,6 +565,36 @@ public interface KickCListener extends ParseTreeListener { * @param ctx the parse tree */ void exitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx); + /** + * Enter a parse tree produced by {@link KickCParser#structRef}. + * @param ctx the parse tree + */ + void enterStructRef(KickCParser.StructRefContext ctx); + /** + * Exit a parse tree produced by {@link KickCParser#structRef}. + * @param ctx the parse tree + */ + void exitStructRef(KickCParser.StructRefContext ctx); + /** + * Enter a parse tree produced by {@link KickCParser#structDef}. + * @param ctx the parse tree + */ + void enterStructDef(KickCParser.StructDefContext ctx); + /** + * Exit a parse tree produced by {@link KickCParser#structDef}. + * @param ctx the parse tree + */ + void exitStructDef(KickCParser.StructDefContext ctx); + /** + * Enter a parse tree produced by {@link KickCParser#structMembers}. + * @param ctx the parse tree + */ + void enterStructMembers(KickCParser.StructMembersContext ctx); + /** + * Exit a parse tree produced by {@link KickCParser#structMembers}. + * @param ctx the parse tree + */ + void exitStructMembers(KickCParser.StructMembersContext ctx); /** * Enter a parse tree produced by the {@code commaNone} * labeled alternative in {@link KickCParser#commaExpr}. diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java index 807940f33..02a84e4b0 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java @@ -27,29 +27,30 @@ public class KickCParser extends Parser { T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, - T__73=74, T__74=75, T__75=76, MNEMONIC=77, KICKASM=78, SIMPLETYPE=79, - STRING=80, CHAR=81, BOOLEAN=82, NUMBER=83, NUMFLOAT=84, BINFLOAT=85, DECFLOAT=86, - HEXFLOAT=87, NUMINT=88, BININTEGER=89, DECINTEGER=90, HEXINTEGER=91, NAME=92, - ASMREL=93, WS=94, COMMENT_LINE=95, COMMENT_BLOCK=96; + T__73=74, T__74=75, T__75=76, T__76=77, MNEMONIC=78, KICKASM=79, SIMPLETYPE=80, + STRING=81, CHAR=82, BOOLEAN=83, NUMBER=84, NUMFLOAT=85, BINFLOAT=86, DECFLOAT=87, + HEXFLOAT=88, NUMINT=89, BININTEGER=90, DECINTEGER=91, HEXINTEGER=92, NAME=93, + ASMREL=94, WS=95, COMMENT_LINE=96, COMMENT_BLOCK=97; public static final int RULE_file = 0, RULE_asmFile = 1, RULE_importSeq = 2, RULE_importDecl = 3, RULE_declSeq = 4, RULE_decl = 5, RULE_declTypes = 6, RULE_declVariables = 7, RULE_declVariableList = 8, RULE_declVariableInit = 9, RULE_declFunction = 10, RULE_parameterListDecl = 11, RULE_parameterDecl = 12, RULE_globalDirective = 13, RULE_directive = 14, RULE_directiveReserve = 15, RULE_stmtSeq = 16, RULE_stmt = 17, - RULE_forLoop = 18, RULE_forClassicInit = 19, RULE_typeDecl = 20, RULE_commaExpr = 21, - RULE_expr = 22, RULE_parameterList = 23, RULE_declKasm = 24, RULE_asmDirectives = 25, - RULE_asmDirective = 26, RULE_asmLines = 27, RULE_asmLine = 28, RULE_asmLabel = 29, - RULE_asmInstruction = 30, RULE_asmBytes = 31, RULE_asmParamMode = 32, - RULE_asmExpr = 33; + RULE_forLoop = 18, RULE_forClassicInit = 19, RULE_typeDecl = 20, RULE_structRef = 21, + RULE_structDef = 22, RULE_structMembers = 23, RULE_commaExpr = 24, RULE_expr = 25, + RULE_parameterList = 26, RULE_declKasm = 27, RULE_asmDirectives = 28, + RULE_asmDirective = 29, RULE_asmLines = 30, RULE_asmLine = 31, RULE_asmLabel = 32, + RULE_asmInstruction = 33, RULE_asmBytes = 34, RULE_asmParamMode = 35, + RULE_asmExpr = 36; public static final String[] ruleNames = { "file", "asmFile", "importSeq", "importDecl", "declSeq", "decl", "declTypes", "declVariables", "declVariableList", "declVariableInit", "declFunction", "parameterListDecl", "parameterDecl", "globalDirective", "directive", "directiveReserve", "stmtSeq", "stmt", "forLoop", "forClassicInit", "typeDecl", - "commaExpr", "expr", "parameterList", "declKasm", "asmDirectives", "asmDirective", - "asmLines", "asmLine", "asmLabel", "asmInstruction", "asmBytes", "asmParamMode", - "asmExpr" + "structRef", "structDef", "structMembers", "commaExpr", "expr", "parameterList", + "declKasm", "asmDirectives", "asmDirective", "asmLines", "asmLine", "asmLabel", + "asmInstruction", "asmBytes", "asmParamMode", "asmExpr" }; private static final String[] _LITERAL_NAMES = { @@ -57,12 +58,12 @@ public class KickCParser extends Parser { "'extern'", "'align'", "'register'", "'inline'", "'volatile'", "'interrupt'", "'reserve'", "'if'", "'else'", "'while'", "'do'", "'for'", "'return'", "'break'", "'continue'", "'asm'", "':'", "'..'", "'signed'", "'unsigned'", - "'*'", "'['", "']'", "'sizeof'", "'typeid'", "'--'", "'++'", "'+'", "'-'", - "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", "'>'", "'=='", - "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", "'+='", "'-='", - "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", "'^='", "'kickasm'", - "'resource'", "'uses'", "'clobbers'", "'bytes'", "'cycles'", "'pc'", "'.byte'", - "'#'", "'.'" + "'*'", "'['", "']'", "'struct'", "'sizeof'", "'typeid'", "'--'", "'++'", + "'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", + "'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", + "'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", + "'^='", "'kickasm'", "'resource'", "'uses'", "'clobbers'", "'bytes'", + "'cycles'", "'pc'", "'.byte'", "'#'", "'.'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null, null, @@ -71,10 +72,10 @@ public class KickCParser extends Parser { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", - "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", - "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "ASMREL", - "WS", "COMMENT_LINE", "COMMENT_BLOCK" + null, null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", + "STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", + "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", + "ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -158,11 +159,11 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(68); + setState(74); importSeq(); - setState(69); + setState(75); declSeq(); - setState(70); + setState(76); match(EOF); } } @@ -207,9 +208,9 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(72); + setState(78); asmLines(); - setState(73); + setState(79); match(EOF); } } @@ -257,17 +258,17 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(78); + setState(84); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__0) { { { - setState(75); + setState(81); importDecl(); } } - setState(80); + setState(86); _errHandler.sync(this); _la = _input.LA(1); } @@ -311,9 +312,9 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(81); + setState(87); match(T__0); - setState(82); + setState(88); match(STRING); } } @@ -361,20 +362,20 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(85); + setState(91); _errHandler.sync(this); _la = _input.LA(1); do { { { - setState(84); + setState(90); decl(); } } - setState(87); + setState(93); _errHandler.sync(this); _la = _input.LA(1); - } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28))) != 0) || _la==T__66 || _la==SIMPLETYPE ); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==T__67 || _la==SIMPLETYPE ); } } catch (RecognitionException re) { @@ -392,6 +393,9 @@ public class KickCParser extends Parser { public DeclVariablesContext declVariables() { return getRuleContext(DeclVariablesContext.class,0); } + public StructDefContext structDef() { + return getRuleContext(StructDefContext.class,0); + } public DeclFunctionContext declFunction() { return getRuleContext(DeclFunctionContext.class,0); } @@ -424,36 +428,45 @@ public class KickCParser extends Parser { DeclContext _localctx = new DeclContext(_ctx, getState()); enterRule(_localctx, 10, RULE_decl); try { - setState(95); + setState(104); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(89); + setState(95); declVariables(); - setState(90); + setState(96); match(T__1); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(92); - declFunction(); + setState(98); + structDef(); + setState(99); + match(T__1); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(93); - declKasm(); + setState(101); + declFunction(); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(94); + setState(102); + declKasm(); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(103); globalDirective(); } break; @@ -506,33 +519,33 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(100); + setState(109); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) { { { - setState(97); + setState(106); directive(); } } - setState(102); + setState(111); _errHandler.sync(this); _la = _input.LA(1); } - setState(103); + setState(112); typeDecl(0); - setState(107); + setState(116); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) { { { - setState(104); + setState(113); directive(); } } - setState(109); + setState(118); _errHandler.sync(this); _la = _input.LA(1); } @@ -581,9 +594,9 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(110); + setState(119); declTypes(); - setState(111); + setState(120); declVariableList(0); } } @@ -640,11 +653,11 @@ public class KickCParser extends Parser { enterOuterAlt(_localctx, 1); { { - setState(114); + setState(123); declVariableInit(); } _ctx.stop = _input.LT(-1); - setState(121); + setState(130); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,5,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -655,16 +668,16 @@ public class KickCParser extends Parser { { _localctx = new DeclVariableListContext(_parentctx, _parentState); pushNewRecursionContext(_localctx, _startState, RULE_declVariableList); - setState(116); + setState(125); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(117); + setState(126); match(T__2); - setState(118); + setState(127); declVariableInit(); } } } - setState(123); + setState(132); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,5,_ctx); } @@ -711,16 +724,16 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(124); + setState(133); match(NAME); - setState(127); + setState(136); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { case 1: { - setState(125); + setState(134); match(T__3); - setState(126); + setState(135); expr(0); } break; @@ -775,37 +788,37 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(129); + setState(138); declTypes(); - setState(130); + setState(139); match(NAME); - setState(131); + setState(140); match(T__4); - setState(133); + setState(142); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28))) != 0) || _la==SIMPLETYPE) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==SIMPLETYPE) { { - setState(132); + setState(141); parameterListDecl(); } } - setState(135); + setState(144); match(T__5); - setState(136); + setState(145); match(T__6); - setState(138); + setState(147); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & ((1L << (T__66 - 67)) | (1L << (SIMPLETYPE - 67)) | (1L << (STRING - 67)) | (1L << (CHAR - 67)) | (1L << (BOOLEAN - 67)) | (1L << (NUMBER - 67)) | (1L << (NAME - 67)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0)) { { - setState(137); + setState(146); stmtSeq(); } } - setState(140); + setState(149); match(T__7); } } @@ -853,21 +866,21 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(142); + setState(151); parameterDecl(); - setState(147); + setState(156); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(143); + setState(152); match(T__2); - setState(144); + setState(153); parameterDecl(); } } - setState(149); + setState(158); _errHandler.sync(this); _la = _input.LA(1); } @@ -937,16 +950,16 @@ public class KickCParser extends Parser { ParameterDeclContext _localctx = new ParameterDeclContext(_ctx, getState()); enterRule(_localctx, 24, RULE_parameterDecl); try { - setState(154); + setState(163); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) { case 1: _localctx = new ParameterDeclTypeContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(150); + setState(159); declTypes(); - setState(151); + setState(160); match(NAME); } break; @@ -954,7 +967,7 @@ public class KickCParser extends Parser { _localctx = new ParameterDeclVoidContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(153); + setState(162); match(SIMPLETYPE); } break; @@ -1000,9 +1013,9 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(156); + setState(165); directiveReserve(); - setState(157); + setState(166); match(T__1); } } @@ -1167,14 +1180,14 @@ public class KickCParser extends Parser { DirectiveContext _localctx = new DirectiveContext(_ctx, getState()); enterRule(_localctx, 28, RULE_directive); try { - setState(178); + setState(187); _errHandler.sync(this); switch (_input.LA(1)) { case T__8: _localctx = new DirectiveConstContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(159); + setState(168); match(T__8); } break; @@ -1182,7 +1195,7 @@ public class KickCParser extends Parser { _localctx = new DirectiveExternContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(160); + setState(169); match(T__9); } break; @@ -1190,13 +1203,13 @@ public class KickCParser extends Parser { _localctx = new DirectiveAlignContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(161); + setState(170); match(T__10); - setState(162); + setState(171); match(T__4); - setState(163); + setState(172); match(NUMBER); - setState(164); + setState(173); match(T__5); } break; @@ -1204,13 +1217,13 @@ public class KickCParser extends Parser { _localctx = new DirectiveRegisterContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(165); + setState(174); match(T__11); - setState(166); + setState(175); match(T__4); - setState(167); + setState(176); match(NAME); - setState(168); + setState(177); match(T__5); } break; @@ -1218,7 +1231,7 @@ public class KickCParser extends Parser { _localctx = new DirectiveInlineContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(169); + setState(178); match(T__12); } break; @@ -1226,7 +1239,7 @@ public class KickCParser extends Parser { _localctx = new DirectiveVolatileContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(170); + setState(179); match(T__13); } break; @@ -1234,18 +1247,18 @@ public class KickCParser extends Parser { _localctx = new DirectiveInterruptContext(_localctx); enterOuterAlt(_localctx, 7); { - setState(171); + setState(180); match(T__14); - setState(175); + setState(184); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) { case 1: { - setState(172); + setState(181); match(T__4); - setState(173); + setState(182); match(NAME); - setState(174); + setState(183); match(T__5); } break; @@ -1256,7 +1269,7 @@ public class KickCParser extends Parser { _localctx = new DirectiveReserveZpContext(_localctx); enterOuterAlt(_localctx, 8); { - setState(177); + setState(186); directiveReserve(); } break; @@ -1306,29 +1319,29 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(180); + setState(189); match(T__15); - setState(181); + setState(190); match(T__4); - setState(182); + setState(191); match(NUMBER); - setState(187); + setState(196); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(183); + setState(192); match(T__2); - setState(184); + setState(193); match(NUMBER); } } - setState(189); + setState(198); _errHandler.sync(this); _la = _input.LA(1); } - setState(190); + setState(199); match(T__5); } } @@ -1376,20 +1389,20 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(193); + setState(202); _errHandler.sync(this); _la = _input.LA(1); do { { { - setState(192); + setState(201); stmt(); } } - setState(195); + setState(204); _errHandler.sync(this); _la = _input.LA(1); - } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & ((1L << (T__66 - 67)) | (1L << (SIMPLETYPE - 67)) | (1L << (STRING - 67)) | (1L << (CHAR - 67)) | (1L << (BOOLEAN - 67)) | (1L << (NUMBER - 67)) | (1L << (NAME - 67)))) != 0) ); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0) ); } } catch (RecognitionException re) { @@ -1678,16 +1691,16 @@ public class KickCParser extends Parser { enterRule(_localctx, 34, RULE_stmt); int _la; try { - setState(273); + setState(282); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,22,_ctx) ) { case 1: _localctx = new StmtDeclVarContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(197); + setState(206); declVariables(); - setState(198); + setState(207); match(T__1); } break; @@ -1695,19 +1708,19 @@ public class KickCParser extends Parser { _localctx = new StmtBlockContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(200); + setState(209); match(T__6); - setState(202); + setState(211); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & ((1L << (T__66 - 67)) | (1L << (SIMPLETYPE - 67)) | (1L << (STRING - 67)) | (1L << (CHAR - 67)) | (1L << (BOOLEAN - 67)) | (1L << (NUMBER - 67)) | (1L << (NAME - 67)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0)) { { - setState(201); + setState(210); stmtSeq(); } } - setState(204); + setState(213); match(T__7); } break; @@ -1715,9 +1728,9 @@ public class KickCParser extends Parser { _localctx = new StmtExprContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(205); + setState(214); commaExpr(0); - setState(206); + setState(215); match(T__1); } break; @@ -1725,24 +1738,24 @@ public class KickCParser extends Parser { _localctx = new StmtIfElseContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(208); + setState(217); match(T__16); - setState(209); + setState(218); match(T__4); - setState(210); + setState(219); commaExpr(0); - setState(211); + setState(220); match(T__5); - setState(212); + setState(221); stmt(); - setState(215); + setState(224); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,16,_ctx) ) { case 1: { - setState(213); + setState(222); match(T__17); - setState(214); + setState(223); stmt(); } break; @@ -1753,29 +1766,29 @@ public class KickCParser extends Parser { _localctx = new StmtWhileContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(220); + setState(229); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) { { { - setState(217); + setState(226); directive(); } } - setState(222); + setState(231); _errHandler.sync(this); _la = _input.LA(1); } - setState(223); + setState(232); match(T__18); - setState(224); + setState(233); match(T__4); - setState(225); + setState(234); commaExpr(0); - setState(226); + setState(235); match(T__5); - setState(227); + setState(236); stmt(); } break; @@ -1783,33 +1796,33 @@ public class KickCParser extends Parser { _localctx = new StmtDoWhileContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(232); + setState(241); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) { { { - setState(229); + setState(238); directive(); } } - setState(234); + setState(243); _errHandler.sync(this); _la = _input.LA(1); } - setState(235); + setState(244); match(T__19); - setState(236); + setState(245); stmt(); - setState(237); + setState(246); match(T__18); - setState(238); + setState(247); match(T__4); - setState(239); + setState(248); commaExpr(0); - setState(240); + setState(249); match(T__5); - setState(241); + setState(250); match(T__1); } break; @@ -1817,29 +1830,29 @@ public class KickCParser extends Parser { _localctx = new StmtForContext(_localctx); enterOuterAlt(_localctx, 7); { - setState(246); + setState(255); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) { { { - setState(243); + setState(252); directive(); } } - setState(248); + setState(257); _errHandler.sync(this); _la = _input.LA(1); } - setState(249); + setState(258); match(T__20); - setState(250); + setState(259); match(T__4); - setState(251); + setState(260); forLoop(); - setState(252); + setState(261); match(T__5); - setState(253); + setState(262); stmt(); } break; @@ -1847,19 +1860,19 @@ public class KickCParser extends Parser { _localctx = new StmtReturnContext(_localctx); enterOuterAlt(_localctx, 8); { - setState(255); + setState(264); match(T__21); - setState(257); + setState(266); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (STRING - 80)) | (1L << (CHAR - 80)) | (1L << (BOOLEAN - 80)) | (1L << (NUMBER - 80)) | (1L << (NAME - 80)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) { { - setState(256); + setState(265); commaExpr(0); } } - setState(259); + setState(268); match(T__1); } break; @@ -1867,9 +1880,9 @@ public class KickCParser extends Parser { _localctx = new StmtBreakContext(_localctx); enterOuterAlt(_localctx, 9); { - setState(260); + setState(269); match(T__22); - setState(261); + setState(270); match(T__1); } break; @@ -1877,9 +1890,9 @@ public class KickCParser extends Parser { _localctx = new StmtContinueContext(_localctx); enterOuterAlt(_localctx, 10); { - setState(262); + setState(271); match(T__23); - setState(263); + setState(272); match(T__1); } break; @@ -1887,23 +1900,23 @@ public class KickCParser extends Parser { _localctx = new StmtAsmContext(_localctx); enterOuterAlt(_localctx, 11); { - setState(264); + setState(273); match(T__24); - setState(266); + setState(275); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__4) { { - setState(265); + setState(274); asmDirectives(); } } - setState(268); + setState(277); match(T__6); - setState(269); + setState(278); asmLines(); - setState(270); + setState(279); match(T__7); } break; @@ -1911,7 +1924,7 @@ public class KickCParser extends Parser { _localctx = new StmtDeclKasmContext(_localctx); enterOuterAlt(_localctx, 12); { - setState(272); + setState(281); declKasm(); } break; @@ -1996,27 +2009,27 @@ public class KickCParser extends Parser { enterRule(_localctx, 36, RULE_forLoop); int _la; try { - setState(291); + setState(300); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,25,_ctx) ) { case 1: _localctx = new ForClassicContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(275); + setState(284); forClassicInit(); - setState(276); + setState(285); match(T__1); - setState(277); + setState(286); commaExpr(0); - setState(278); + setState(287); match(T__1); - setState(280); + setState(289); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (STRING - 80)) | (1L << (CHAR - 80)) | (1L << (BOOLEAN - 80)) | (1L << (NUMBER - 80)) | (1L << (NAME - 80)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) { { - setState(279); + setState(288); commaExpr(0); } } @@ -2027,27 +2040,27 @@ public class KickCParser extends Parser { _localctx = new ForRangeContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(283); + setState(292); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28))) != 0) || _la==SIMPLETYPE) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==SIMPLETYPE) { { - setState(282); + setState(291); declTypes(); } } - setState(285); + setState(294); match(NAME); - setState(286); + setState(295); match(T__25); - setState(287); + setState(296); expr(0); { - setState(288); + setState(297); match(T__26); } - setState(289); + setState(298); expr(0); } break; @@ -2119,19 +2132,19 @@ public class KickCParser extends Parser { enterRule(_localctx, 38, RULE_forClassicInit); int _la; try { - setState(297); + setState(306); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) { case 1: _localctx = new ForClassicInitDeclContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(294); + setState(303); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28))) != 0) || _la==SIMPLETYPE) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==SIMPLETYPE) { { - setState(293); + setState(302); declVariables(); } } @@ -2142,7 +2155,7 @@ public class KickCParser extends Parser { _localctx = new ForClassicInitExprContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(296); + setState(305); commaExpr(0); } break; @@ -2249,6 +2262,25 @@ public class KickCParser extends Parser { else return visitor.visitChildren(this); } } + public static class TypeStructRefContext extends TypeDeclContext { + public StructRefContext structRef() { + return getRuleContext(StructRefContext.class,0); + } + public TypeStructRefContext(TypeDeclContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).enterTypeStructRef(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).exitTypeStructRef(this); + } + @Override + public <T> T accept(ParseTreeVisitor<? extends T> visitor) { + if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitTypeStructRef(this); + else return visitor.visitChildren(this); + } + } public static class TypeSimpleContext extends TypeDeclContext { public TerminalNode SIMPLETYPE() { return getToken(KickCParser.SIMPLETYPE, 0); } public TypeSimpleContext(TypeDeclContext ctx) { copyFrom(ctx); } @@ -2266,6 +2298,25 @@ public class KickCParser extends Parser { else return visitor.visitChildren(this); } } + public static class TypeStructDefContext extends TypeDeclContext { + public StructDefContext structDef() { + return getRuleContext(StructDefContext.class,0); + } + public TypeStructDefContext(TypeDeclContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).enterTypeStructDef(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).exitTypeStructDef(this); + } + @Override + public <T> T accept(ParseTreeVisitor<? extends T> visitor) { + if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitTypeStructDef(this); + else return visitor.visitChildren(this); + } + } public static class TypeSignedSimpleContext extends TypeDeclContext { public TerminalNode SIMPLETYPE() { return getToken(KickCParser.SIMPLETYPE, 0); } public TypeSignedSimpleContext(TypeDeclContext ctx) { copyFrom(ctx); } @@ -2300,39 +2351,38 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(309); + setState(320); _errHandler.sync(this); - switch (_input.LA(1)) { - case T__4: + switch ( getInterpreter().adaptivePredict(_input,29,_ctx) ) { + case 1: { _localctx = new TypeParContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(300); + setState(309); match(T__4); - setState(301); + setState(310); typeDecl(0); - setState(302); + setState(311); match(T__5); } break; - case SIMPLETYPE: + case 2: { _localctx = new TypeSimpleContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(304); + setState(313); match(SIMPLETYPE); } break; - case T__27: - case T__28: + case 3: { _localctx = new TypeSignedSimpleContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(305); + setState(314); _la = _input.LA(1); if ( !(_la==T__27 || _la==T__28) ) { _errHandler.recoverInline(this); @@ -2342,23 +2392,39 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(307); + setState(316); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,28,_ctx) ) { case 1: { - setState(306); + setState(315); match(SIMPLETYPE); } break; } } break; - default: - throw new NoViableAltException(this); + case 4: + { + _localctx = new TypeStructDefContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(318); + structDef(); + } + break; + case 5: + { + _localctx = new TypeStructRefContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(319); + structRef(); + } + break; } _ctx.stop = _input.LT(-1); - setState(324); + setState(335); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,32,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -2366,16 +2432,16 @@ public class KickCParser extends Parser { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(322); + setState(333); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,31,_ctx) ) { case 1: { _localctx = new TypePtrContext(new TypeDeclContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_typeDecl); - setState(311); - if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); - setState(312); + setState(322); + if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); + setState(323); match(T__29); } break; @@ -2383,21 +2449,21 @@ public class KickCParser extends Parser { { _localctx = new TypeArrayContext(new TypeDeclContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_typeDecl); - setState(313); - if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(314); + setState(324); + if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)"); + setState(325); match(T__30); - setState(316); + setState(327); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (STRING - 80)) | (1L << (CHAR - 80)) | (1L << (BOOLEAN - 80)) | (1L << (NUMBER - 80)) | (1L << (NAME - 80)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) { { - setState(315); + setState(326); expr(0); } } - setState(318); + setState(329); match(T__31); } break; @@ -2405,18 +2471,18 @@ public class KickCParser extends Parser { { _localctx = new TypeProcedureContext(new TypeDeclContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_typeDecl); - setState(319); - if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(320); + setState(330); + if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); + setState(331); match(T__4); - setState(321); + setState(332); match(T__5); } break; } } } - setState(326); + setState(337); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,32,_ctx); } @@ -2433,6 +2499,173 @@ public class KickCParser extends Parser { return _localctx; } + public static class StructRefContext extends ParserRuleContext { + public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); } + public StructRefContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_structRef; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).enterStructRef(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).exitStructRef(this); + } + @Override + public <T> T accept(ParseTreeVisitor<? extends T> visitor) { + if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitStructRef(this); + else return visitor.visitChildren(this); + } + } + + public final StructRefContext structRef() throws RecognitionException { + StructRefContext _localctx = new StructRefContext(_ctx, getState()); + enterRule(_localctx, 42, RULE_structRef); + try { + enterOuterAlt(_localctx, 1); + { + setState(338); + match(T__32); + setState(339); + match(NAME); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class StructDefContext extends ParserRuleContext { + public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); } + public List<StructMembersContext> structMembers() { + return getRuleContexts(StructMembersContext.class); + } + public StructMembersContext structMembers(int i) { + return getRuleContext(StructMembersContext.class,i); + } + public StructDefContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_structDef; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).enterStructDef(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).exitStructDef(this); + } + @Override + public <T> T accept(ParseTreeVisitor<? extends T> visitor) { + if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitStructDef(this); + else return visitor.visitChildren(this); + } + } + + public final StructDefContext structDef() throws RecognitionException { + StructDefContext _localctx = new StructDefContext(_ctx, getState()); + enterRule(_localctx, 44, RULE_structDef); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(341); + match(T__32); + setState(343); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==NAME) { + { + setState(342); + match(NAME); + } + } + + setState(345); + match(T__6); + setState(347); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(346); + structMembers(); + } + } + setState(349); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==SIMPLETYPE ); + setState(351); + match(T__7); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class StructMembersContext extends ParserRuleContext { + public DeclVariablesContext declVariables() { + return getRuleContext(DeclVariablesContext.class,0); + } + public StructMembersContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_structMembers; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).enterStructMembers(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).exitStructMembers(this); + } + @Override + public <T> T accept(ParseTreeVisitor<? extends T> visitor) { + if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitStructMembers(this); + else return visitor.visitChildren(this); + } + } + + public final StructMembersContext structMembers() throws RecognitionException { + StructMembersContext _localctx = new StructMembersContext(_ctx, getState()); + enterRule(_localctx, 46, RULE_structMembers); + try { + enterOuterAlt(_localctx, 1); + { + setState(353); + declVariables(); + setState(354); + match(T__1); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + public static class CommaExprContext extends ParserRuleContext { public CommaExprContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); @@ -2495,8 +2728,8 @@ public class KickCParser extends Parser { int _parentState = getState(); CommaExprContext _localctx = new CommaExprContext(_ctx, _parentState); CommaExprContext _prevctx = _localctx; - int _startState = 42; - enterRecursionRule(_localctx, 42, RULE_commaExpr, _p); + int _startState = 48; + enterRecursionRule(_localctx, 48, RULE_commaExpr, _p); try { int _alt; enterOuterAlt(_localctx, 1); @@ -2506,13 +2739,13 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(328); + setState(357); expr(0); } _ctx.stop = _input.LT(-1); - setState(335); + setState(364); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,33,_ctx); + _alt = getInterpreter().adaptivePredict(_input,35,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); @@ -2521,18 +2754,18 @@ public class KickCParser extends Parser { { _localctx = new CommaSimpleContext(new CommaExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_commaExpr); - setState(330); + setState(359); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(331); + setState(360); match(T__2); - setState(332); + setState(361); expr(0); } } } - setState(337); + setState(366); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,33,_ctx); + _alt = getInterpreter().adaptivePredict(_input,35,_ctx); } } } @@ -2971,27 +3204,27 @@ public class KickCParser extends Parser { int _parentState = getState(); ExprContext _localctx = new ExprContext(_ctx, _parentState); ExprContext _prevctx = _localctx; - int _startState = 44; - enterRecursionRule(_localctx, 44, RULE_expr, _p); + int _startState = 50; + enterRecursionRule(_localctx, 50, RULE_expr, _p); int _la; try { int _alt; enterOuterAlt(_localctx, 1); { - setState(392); + setState(421); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,38,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) { case 1: { _localctx = new ExprParContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(339); + setState(368); match(T__4); - setState(340); + setState(369); commaExpr(0); - setState(341); + setState(370); match(T__5); } break; @@ -3000,27 +3233,27 @@ public class KickCParser extends Parser { _localctx = new ExprSizeOfContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(343); - match(T__32); - setState(344); + setState(372); + match(T__33); + setState(373); match(T__4); - setState(347); + setState(376); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,34,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,36,_ctx) ) { case 1: { - setState(345); + setState(374); typeDecl(0); } break; case 2: { - setState(346); + setState(375); expr(0); } break; } - setState(349); + setState(378); match(T__5); } break; @@ -3029,27 +3262,27 @@ public class KickCParser extends Parser { _localctx = new ExprTypeIdContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(351); - match(T__33); - setState(352); + setState(380); + match(T__34); + setState(381); match(T__4); - setState(355); + setState(384); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,35,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,37,_ctx) ) { case 1: { - setState(353); + setState(382); typeDecl(0); } break; case 2: { - setState(354); + setState(383); expr(0); } break; } - setState(357); + setState(386); match(T__5); } break; @@ -3058,13 +3291,13 @@ public class KickCParser extends Parser { _localctx = new ExprCastContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(359); + setState(388); match(T__4); - setState(360); + setState(389); typeDecl(0); - setState(361); + setState(390); match(T__5); - setState(362); + setState(391); expr(24); } break; @@ -3073,9 +3306,9 @@ public class KickCParser extends Parser { _localctx = new ExprPreModContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(364); + setState(393); _la = _input.LA(1); - if ( !(_la==T__34 || _la==T__35) ) { + if ( !(_la==T__35 || _la==T__36) ) { _errHandler.recoverInline(this); } else { @@ -3083,7 +3316,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(365); + setState(394); expr(23); } break; @@ -3092,9 +3325,9 @@ public class KickCParser extends Parser { _localctx = new ExprPtrContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(366); + setState(395); match(T__29); - setState(367); + setState(396); expr(21); } break; @@ -3103,9 +3336,9 @@ public class KickCParser extends Parser { _localctx = new ExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(368); + setState(397); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -3113,7 +3346,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(369); + setState(398); expr(20); } break; @@ -3122,9 +3355,9 @@ public class KickCParser extends Parser { _localctx = new ExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(370); + setState(399); _la = _input.LA(1); - if ( !(_la==T__45 || _la==T__46) ) { + if ( !(_la==T__46 || _la==T__47) ) { _errHandler.recoverInline(this); } else { @@ -3132,7 +3365,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(371); + setState(400); expr(16); } break; @@ -3141,27 +3374,27 @@ public class KickCParser extends Parser { _localctx = new InitListContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(372); + setState(401); match(T__6); - setState(373); + setState(402); expr(0); - setState(378); + setState(407); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(374); + setState(403); match(T__2); - setState(375); + setState(404); expr(0); } } - setState(380); + setState(409); _errHandler.sync(this); _la = _input.LA(1); } - setState(381); + setState(410); match(T__7); } break; @@ -3170,7 +3403,7 @@ public class KickCParser extends Parser { _localctx = new ExprIdContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(383); + setState(412); match(NAME); } break; @@ -3179,7 +3412,7 @@ public class KickCParser extends Parser { _localctx = new ExprNumberContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(384); + setState(413); match(NUMBER); } break; @@ -3188,7 +3421,7 @@ public class KickCParser extends Parser { _localctx = new ExprStringContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(386); + setState(415); _errHandler.sync(this); _alt = 1; do { @@ -3196,7 +3429,7 @@ public class KickCParser extends Parser { case 1: { { - setState(385); + setState(414); match(STRING); } } @@ -3204,9 +3437,9 @@ public class KickCParser extends Parser { default: throw new NoViableAltException(this); } - setState(388); + setState(417); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,37,_ctx); + _alt = getInterpreter().adaptivePredict(_input,39,_ctx); } while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); } break; @@ -3215,7 +3448,7 @@ public class KickCParser extends Parser { _localctx = new ExprCharContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(390); + setState(419); match(CHAR); } break; @@ -3224,32 +3457,32 @@ public class KickCParser extends Parser { _localctx = new ExprBoolContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(391); + setState(420); match(BOOLEAN); } break; } _ctx.stop = _input.LT(-1); - setState(448); + setState(477); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,41,_ctx); + _alt = getInterpreter().adaptivePredict(_input,43,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(446); + setState(475); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,42,_ctx) ) { case 1: { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(394); + setState(423); if (!(precpred(_ctx, 19))) throw new FailedPredicateException(this, "precpred(_ctx, 19)"); - setState(395); + setState(424); _la = _input.LA(1); - if ( !(_la==T__41 || _la==T__42) ) { + if ( !(_la==T__42 || _la==T__43) ) { _errHandler.recoverInline(this); } else { @@ -3257,7 +3490,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(396); + setState(425); expr(20); } break; @@ -3265,11 +3498,11 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(397); + setState(426); if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)"); - setState(398); + setState(427); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__29) | (1L << T__43) | (1L << T__44))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__29) | (1L << T__44) | (1L << T__45))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -3277,7 +3510,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(399); + setState(428); expr(19); } break; @@ -3285,11 +3518,11 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(400); + setState(429); if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)"); - setState(401); + setState(430); _la = _input.LA(1); - if ( !(_la==T__36 || _la==T__37) ) { + if ( !(_la==T__37 || _la==T__38) ) { _errHandler.recoverInline(this); } else { @@ -3297,7 +3530,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(402); + setState(431); expr(18); } break; @@ -3305,11 +3538,11 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(403); + setState(432); if (!(precpred(_ctx, 15))) throw new FailedPredicateException(this, "precpred(_ctx, 15)"); - setState(404); + setState(433); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__45) | (1L << T__46) | (1L << T__47) | (1L << T__48) | (1L << T__49) | (1L << T__50))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__46) | (1L << T__47) | (1L << T__48) | (1L << T__49) | (1L << T__50) | (1L << T__51))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -3317,7 +3550,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(405); + setState(434); expr(16); } break; @@ -3325,13 +3558,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(406); + setState(435); if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)"); { - setState(407); - match(T__39); + setState(436); + match(T__40); } - setState(408); + setState(437); expr(15); } break; @@ -3339,13 +3572,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(409); + setState(438); if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); { - setState(410); - match(T__51); + setState(439); + match(T__52); } - setState(411); + setState(440); expr(14); } break; @@ -3353,13 +3586,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(412); + setState(441); if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); { - setState(413); - match(T__52); + setState(442); + match(T__53); } - setState(414); + setState(443); expr(13); } break; @@ -3367,13 +3600,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(415); + setState(444); if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); { - setState(416); - match(T__53); + setState(445); + match(T__54); } - setState(417); + setState(446); expr(12); } break; @@ -3381,13 +3614,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(418); + setState(447); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); { - setState(419); - match(T__54); + setState(448); + match(T__55); } - setState(420); + setState(449); expr(11); } break; @@ -3395,15 +3628,15 @@ public class KickCParser extends Parser { { _localctx = new ExprTernaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(421); + setState(450); if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(422); - match(T__55); - setState(423); + setState(451); + match(T__56); + setState(452); expr(0); - setState(424); + setState(453); match(T__25); - setState(425); + setState(454); expr(10); } break; @@ -3411,11 +3644,11 @@ public class KickCParser extends Parser { { _localctx = new ExprAssignmentContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(427); + setState(456); if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); - setState(428); + setState(457); match(T__3); - setState(429); + setState(458); expr(8); } break; @@ -3423,11 +3656,11 @@ public class KickCParser extends Parser { { _localctx = new ExprAssignmentCompoundContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(430); + setState(459); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(431); + setState(460); _la = _input.LA(1); - if ( !(((((_la - 57)) & ~0x3f) == 0 && ((1L << (_la - 57)) & ((1L << (T__56 - 57)) | (1L << (T__57 - 57)) | (1L << (T__58 - 57)) | (1L << (T__59 - 57)) | (1L << (T__60 - 57)) | (1L << (T__61 - 57)) | (1L << (T__62 - 57)) | (1L << (T__63 - 57)) | (1L << (T__64 - 57)) | (1L << (T__65 - 57)))) != 0)) ) { + if ( !(((((_la - 58)) & ~0x3f) == 0 && ((1L << (_la - 58)) & ((1L << (T__57 - 58)) | (1L << (T__58 - 58)) | (1L << (T__59 - 58)) | (1L << (T__60 - 58)) | (1L << (T__61 - 58)) | (1L << (T__62 - 58)) | (1L << (T__63 - 58)) | (1L << (T__64 - 58)) | (1L << (T__65 - 58)) | (1L << (T__66 - 58)))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -3435,7 +3668,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(432); + setState(461); expr(7); } break; @@ -3443,21 +3676,21 @@ public class KickCParser extends Parser { { _localctx = new ExprCallContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(433); + setState(462); if (!(precpred(_ctx, 28))) throw new FailedPredicateException(this, "precpred(_ctx, 28)"); - setState(434); + setState(463); match(T__4); - setState(436); + setState(465); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (STRING - 80)) | (1L << (CHAR - 80)) | (1L << (BOOLEAN - 80)) | (1L << (NUMBER - 80)) | (1L << (NAME - 80)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) { { - setState(435); + setState(464); parameterList(); } } - setState(438); + setState(467); match(T__5); } break; @@ -3465,13 +3698,13 @@ public class KickCParser extends Parser { { _localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(439); + setState(468); if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)"); - setState(440); + setState(469); match(T__30); - setState(441); + setState(470); commaExpr(0); - setState(442); + setState(471); match(T__31); } break; @@ -3479,11 +3712,11 @@ public class KickCParser extends Parser { { _localctx = new ExprPostModContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(444); + setState(473); if (!(precpred(_ctx, 22))) throw new FailedPredicateException(this, "precpred(_ctx, 22)"); - setState(445); + setState(474); _la = _input.LA(1); - if ( !(_la==T__34 || _la==T__35) ) { + if ( !(_la==T__35 || _la==T__36) ) { _errHandler.recoverInline(this); } else { @@ -3496,9 +3729,9 @@ public class KickCParser extends Parser { } } } - setState(450); + setState(479); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,41,_ctx); + _alt = getInterpreter().adaptivePredict(_input,43,_ctx); } } } @@ -3541,26 +3774,26 @@ public class KickCParser extends Parser { public final ParameterListContext parameterList() throws RecognitionException { ParameterListContext _localctx = new ParameterListContext(_ctx, getState()); - enterRule(_localctx, 46, RULE_parameterList); + enterRule(_localctx, 52, RULE_parameterList); int _la; try { enterOuterAlt(_localctx, 1); { - setState(451); + setState(480); expr(0); - setState(456); + setState(485); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(452); + setState(481); match(T__2); - setState(453); + setState(482); expr(0); } } - setState(458); + setState(487); _errHandler.sync(this); _la = _input.LA(1); } @@ -3603,24 +3836,24 @@ public class KickCParser extends Parser { public final DeclKasmContext declKasm() throws RecognitionException { DeclKasmContext _localctx = new DeclKasmContext(_ctx, getState()); - enterRule(_localctx, 48, RULE_declKasm); + enterRule(_localctx, 54, RULE_declKasm); int _la; try { enterOuterAlt(_localctx, 1); { - setState(459); - match(T__66); - setState(461); + setState(488); + match(T__67); + setState(490); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__4) { { - setState(460); + setState(489); asmDirectives(); } } - setState(463); + setState(492); match(KICKASM); } } @@ -3663,32 +3896,32 @@ public class KickCParser extends Parser { public final AsmDirectivesContext asmDirectives() throws RecognitionException { AsmDirectivesContext _localctx = new AsmDirectivesContext(_ctx, getState()); - enterRule(_localctx, 50, RULE_asmDirectives); + enterRule(_localctx, 56, RULE_asmDirectives); int _la; try { enterOuterAlt(_localctx, 1); { - setState(465); + setState(494); match(T__4); - setState(466); + setState(495); asmDirective(); - setState(471); + setState(500); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(467); + setState(496); match(T__2); - setState(468); + setState(497); asmDirective(); } } - setState(473); + setState(502); _errHandler.sync(this); _la = _input.LA(1); } - setState(474); + setState(503); match(T__5); } } @@ -3825,80 +4058,79 @@ public class KickCParser extends Parser { public final AsmDirectiveContext asmDirective() throws RecognitionException { AsmDirectiveContext _localctx = new AsmDirectiveContext(_ctx, getState()); - enterRule(_localctx, 52, RULE_asmDirective); + enterRule(_localctx, 58, RULE_asmDirective); try { - setState(491); + setState(520); _errHandler.sync(this); switch (_input.LA(1)) { - case T__67: + case T__68: _localctx = new AsmDirectiveResourceContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(476); - match(T__67); - setState(477); - match(STRING); - } - break; - case T__68: - _localctx = new AsmDirectiveUsesContext(_localctx); - enterOuterAlt(_localctx, 2); - { - setState(478); + setState(505); match(T__68); - setState(479); - match(NAME); + setState(506); + match(STRING); } break; case T__69: - _localctx = new AsmDirectiveClobberContext(_localctx); - enterOuterAlt(_localctx, 3); + _localctx = new AsmDirectiveUsesContext(_localctx); + enterOuterAlt(_localctx, 2); { - setState(480); + setState(507); match(T__69); - setState(481); - match(STRING); + setState(508); + match(NAME); } break; case T__70: - _localctx = new AsmDirectiveBytesContext(_localctx); - enterOuterAlt(_localctx, 4); + _localctx = new AsmDirectiveClobberContext(_localctx); + enterOuterAlt(_localctx, 3); { - setState(482); + setState(509); match(T__70); - setState(483); - expr(0); + setState(510); + match(STRING); } break; case T__71: - _localctx = new AsmDirectiveCyclesContext(_localctx); - enterOuterAlt(_localctx, 5); + _localctx = new AsmDirectiveBytesContext(_localctx); + enterOuterAlt(_localctx, 4); { - setState(484); + setState(511); match(T__71); - setState(485); + setState(512); expr(0); } break; case T__72: + _localctx = new AsmDirectiveCyclesContext(_localctx); + enterOuterAlt(_localctx, 5); + { + setState(513); + match(T__72); + setState(514); + expr(0); + } + break; + case T__73: _localctx = new AsmDirectiveAddressContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(486); - match(T__72); - setState(489); + setState(515); + match(T__73); + setState(518); _errHandler.sync(this); switch (_input.LA(1)) { case T__12: { - setState(487); + setState(516); match(T__12); } break; case T__4: case T__6: case T__29: - case T__32: case T__33: case T__34: case T__35: @@ -3907,15 +4139,16 @@ public class KickCParser extends Parser { case T__38: case T__39: case T__40: - case T__45: + case T__41: case T__46: + case T__47: case STRING: case CHAR: case BOOLEAN: case NUMBER: case NAME: { - setState(488); + setState(517); expr(0); } break; @@ -3967,22 +4200,22 @@ public class KickCParser extends Parser { public final AsmLinesContext asmLines() throws RecognitionException { AsmLinesContext _localctx = new AsmLinesContext(_ctx, getState()); - enterRule(_localctx, 54, RULE_asmLines); + enterRule(_localctx, 60, RULE_asmLines); int _la; try { enterOuterAlt(_localctx, 1); { - setState(496); + setState(525); _errHandler.sync(this); _la = _input.LA(1); - while (((((_la - 39)) & ~0x3f) == 0 && ((1L << (_la - 39)) & ((1L << (T__38 - 39)) | (1L << (T__73 - 39)) | (1L << (MNEMONIC - 39)) | (1L << (NAME - 39)))) != 0)) { + while (((((_la - 40)) & ~0x3f) == 0 && ((1L << (_la - 40)) & ((1L << (T__39 - 40)) | (1L << (T__74 - 40)) | (1L << (MNEMONIC - 40)) | (1L << (NAME - 40)))) != 0)) { { { - setState(493); + setState(522); asmLine(); } } - setState(498); + setState(527); _errHandler.sync(this); _la = _input.LA(1); } @@ -4030,30 +4263,30 @@ public class KickCParser extends Parser { public final AsmLineContext asmLine() throws RecognitionException { AsmLineContext _localctx = new AsmLineContext(_ctx, getState()); - enterRule(_localctx, 56, RULE_asmLine); + enterRule(_localctx, 62, RULE_asmLine); try { - setState(502); + setState(531); _errHandler.sync(this); switch (_input.LA(1)) { - case T__38: + case T__39: case NAME: enterOuterAlt(_localctx, 1); { - setState(499); + setState(528); asmLabel(); } break; case MNEMONIC: enterOuterAlt(_localctx, 2); { - setState(500); + setState(529); asmInstruction(); } break; - case T__73: + case T__74: enterOuterAlt(_localctx, 3); { - setState(501); + setState(530); asmBytes(); } break; @@ -4120,39 +4353,39 @@ public class KickCParser extends Parser { public final AsmLabelContext asmLabel() throws RecognitionException { AsmLabelContext _localctx = new AsmLabelContext(_ctx, getState()); - enterRule(_localctx, 58, RULE_asmLabel); + enterRule(_localctx, 64, RULE_asmLabel); int _la; try { - setState(511); + setState(540); _errHandler.sync(this); switch (_input.LA(1)) { case NAME: _localctx = new AsmLabelNameContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(504); + setState(533); match(NAME); - setState(505); + setState(534); match(T__25); } break; - case T__38: + case T__39: _localctx = new AsmLabelMultiContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(506); - match(T__38); - setState(508); + setState(535); + match(T__39); + setState(537); _errHandler.sync(this); _la = _input.LA(1); if (_la==NAME) { { - setState(507); + setState(536); match(NAME); } } - setState(510); + setState(539); match(T__25); } break; @@ -4197,18 +4430,18 @@ public class KickCParser extends Parser { public final AsmInstructionContext asmInstruction() throws RecognitionException { AsmInstructionContext _localctx = new AsmInstructionContext(_ctx, getState()); - enterRule(_localctx, 60, RULE_asmInstruction); + enterRule(_localctx, 66, RULE_asmInstruction); try { enterOuterAlt(_localctx, 1); { - setState(513); + setState(542); match(MNEMONIC); - setState(515); + setState(544); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) { case 1: { - setState(514); + setState(543); asmParamMode(); } break; @@ -4254,28 +4487,28 @@ public class KickCParser extends Parser { public final AsmBytesContext asmBytes() throws RecognitionException { AsmBytesContext _localctx = new AsmBytesContext(_ctx, getState()); - enterRule(_localctx, 62, RULE_asmBytes); + enterRule(_localctx, 68, RULE_asmBytes); int _la; try { enterOuterAlt(_localctx, 1); { - setState(517); - match(T__73); - setState(518); + setState(546); + match(T__74); + setState(547); asmExpr(0); - setState(523); + setState(552); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(519); + setState(548); match(T__2); - setState(520); + setState(549); asmExpr(0); } } - setState(525); + setState(554); _errHandler.sync(this); _la = _input.LA(1); } @@ -4423,16 +4656,16 @@ public class KickCParser extends Parser { public final AsmParamModeContext asmParamMode() throws RecognitionException { AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState()); - enterRule(_localctx, 64, RULE_asmParamMode); + enterRule(_localctx, 70, RULE_asmParamMode); try { - setState(549); + setState(578); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) { case 1: _localctx = new AsmModeAbsContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(526); + setState(555); asmExpr(0); } break; @@ -4440,9 +4673,9 @@ public class KickCParser extends Parser { _localctx = new AsmModeImmContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(527); - match(T__74); - setState(528); + setState(556); + match(T__75); + setState(557); asmExpr(0); } break; @@ -4450,11 +4683,11 @@ public class KickCParser extends Parser { _localctx = new AsmModeAbsXYContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(529); + setState(558); asmExpr(0); - setState(530); + setState(559); match(T__2); - setState(531); + setState(560); match(NAME); } break; @@ -4462,15 +4695,15 @@ public class KickCParser extends Parser { _localctx = new AsmModeIndIdxXYContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(533); + setState(562); match(T__4); - setState(534); + setState(563); asmExpr(0); - setState(535); + setState(564); match(T__5); - setState(536); + setState(565); match(T__2); - setState(537); + setState(566); match(NAME); } break; @@ -4478,15 +4711,15 @@ public class KickCParser extends Parser { _localctx = new AsmModeIdxIndXYContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(539); + setState(568); match(T__4); - setState(540); + setState(569); asmExpr(0); - setState(541); + setState(570); match(T__2); - setState(542); + setState(571); match(NAME); - setState(543); + setState(572); match(T__5); } break; @@ -4494,11 +4727,11 @@ public class KickCParser extends Parser { _localctx = new AsmModeIndContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(545); + setState(574); match(T__4); - setState(546); + setState(575); asmExpr(0); - setState(547); + setState(576); match(T__5); } break; @@ -4681,14 +4914,14 @@ public class KickCParser extends Parser { int _parentState = getState(); AsmExprContext _localctx = new AsmExprContext(_ctx, _parentState); AsmExprContext _prevctx = _localctx; - int _startState = 66; - enterRecursionRule(_localctx, 66, RULE_asmExpr, _p); + int _startState = 72; + enterRecursionRule(_localctx, 72, RULE_asmExpr, _p); int _la; try { int _alt; enterOuterAlt(_localctx, 1); { - setState(565); + setState(594); _errHandler.sync(this); switch (_input.LA(1)) { case T__30: @@ -4697,25 +4930,25 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(552); + setState(581); match(T__30); - setState(553); + setState(582); asmExpr(0); - setState(554); + setState(583); match(T__31); } break; - case T__36: case T__37: - case T__45: + case T__38: case T__46: + case T__47: { _localctx = new AsmExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(556); + setState(585); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__36) | (1L << T__37) | (1L << T__45) | (1L << T__46))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__37) | (1L << T__38) | (1L << T__46) | (1L << T__47))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -4723,7 +4956,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(557); + setState(586); asmExpr(8); } break; @@ -4732,7 +4965,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprLabelContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(558); + setState(587); match(NAME); } break; @@ -4741,7 +4974,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprLabelRelContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(559); + setState(588); match(ASMREL); } break; @@ -4750,11 +4983,11 @@ public class KickCParser extends Parser { _localctx = new AsmExprReplaceContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(560); + setState(589); match(T__6); - setState(561); + setState(590); match(NAME); - setState(562); + setState(591); match(T__7); } break; @@ -4763,7 +4996,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprIntContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(563); + setState(592); match(NUMBER); } break; @@ -4772,7 +5005,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprCharContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(564); + setState(593); match(CHAR); } break; @@ -4780,28 +5013,28 @@ public class KickCParser extends Parser { throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(581); + setState(610); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,56,_ctx); + _alt = getInterpreter().adaptivePredict(_input,58,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(579); + setState(608); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,57,_ctx) ) { case 1: { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(567); + setState(596); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); { - setState(568); - match(T__75); + setState(597); + match(T__76); } - setState(569); + setState(598); asmExpr(11); } break; @@ -4809,11 +5042,11 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(570); + setState(599); if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(571); + setState(600); _la = _input.LA(1); - if ( !(_la==T__41 || _la==T__42) ) { + if ( !(_la==T__42 || _la==T__43) ) { _errHandler.recoverInline(this); } else { @@ -4821,7 +5054,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(572); + setState(601); asmExpr(10); } break; @@ -4829,11 +5062,11 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(573); + setState(602); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(574); + setState(603); _la = _input.LA(1); - if ( !(_la==T__29 || _la==T__43) ) { + if ( !(_la==T__29 || _la==T__44) ) { _errHandler.recoverInline(this); } else { @@ -4841,7 +5074,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(575); + setState(604); asmExpr(8); } break; @@ -4849,11 +5082,11 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(576); + setState(605); if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); - setState(577); + setState(606); _la = _input.LA(1); - if ( !(_la==T__36 || _la==T__37) ) { + if ( !(_la==T__37 || _la==T__38) ) { _errHandler.recoverInline(this); } else { @@ -4861,16 +5094,16 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(578); + setState(607); asmExpr(7); } break; } } } - setState(583); + setState(612); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,56,_ctx); + _alt = getInterpreter().adaptivePredict(_input,58,_ctx); } } } @@ -4891,11 +5124,11 @@ public class KickCParser extends Parser { return declVariableList_sempred((DeclVariableListContext)_localctx, predIndex); case 20: return typeDecl_sempred((TypeDeclContext)_localctx, predIndex); - case 21: + case 24: return commaExpr_sempred((CommaExprContext)_localctx, predIndex); - case 22: + case 25: return expr_sempred((ExprContext)_localctx, predIndex); - case 33: + case 36: return asmExpr_sempred((AsmExprContext)_localctx, predIndex); } return true; @@ -4910,11 +5143,11 @@ public class KickCParser extends Parser { private boolean typeDecl_sempred(TypeDeclContext _localctx, int predIndex) { switch (predIndex) { case 1: - return precpred(_ctx, 3); + return precpred(_ctx, 5); case 2: - return precpred(_ctx, 2); + return precpred(_ctx, 4); case 3: - return precpred(_ctx, 1); + return precpred(_ctx, 3); } return true; } @@ -4975,235 +5208,246 @@ public class KickCParser extends Parser { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3b\u024b\4\2\t\2\4"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3c\u0268\4\2\t\2\4"+ "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ "\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ - "\t!\4\"\t\"\4#\t#\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\4\7\4O\n\4\f\4\16\4R\13"+ - "\4\3\5\3\5\3\5\3\6\6\6X\n\6\r\6\16\6Y\3\7\3\7\3\7\3\7\3\7\3\7\5\7b\n\7"+ - "\3\b\7\be\n\b\f\b\16\bh\13\b\3\b\3\b\7\bl\n\b\f\b\16\bo\13\b\3\t\3\t\3"+ - "\t\3\n\3\n\3\n\3\n\3\n\3\n\7\nz\n\n\f\n\16\n}\13\n\3\13\3\13\3\13\5\13"+ - "\u0082\n\13\3\f\3\f\3\f\3\f\5\f\u0088\n\f\3\f\3\f\3\f\5\f\u008d\n\f\3"+ - "\f\3\f\3\r\3\r\3\r\7\r\u0094\n\r\f\r\16\r\u0097\13\r\3\16\3\16\3\16\3"+ - "\16\5\16\u009d\n\16\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+ - "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\5\20\u00b2\n\20\3\20\5\20"+ - "\u00b5\n\20\3\21\3\21\3\21\3\21\3\21\7\21\u00bc\n\21\f\21\16\21\u00bf"+ - "\13\21\3\21\3\21\3\22\6\22\u00c4\n\22\r\22\16\22\u00c5\3\23\3\23\3\23"+ - "\3\23\3\23\5\23\u00cd\n\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23"+ - "\3\23\3\23\5\23\u00da\n\23\3\23\7\23\u00dd\n\23\f\23\16\23\u00e0\13\23"+ - "\3\23\3\23\3\23\3\23\3\23\3\23\3\23\7\23\u00e9\n\23\f\23\16\23\u00ec\13"+ - "\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\7\23\u00f7\n\23\f\23"+ - "\16\23\u00fa\13\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u0104"+ - "\n\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u010d\n\23\3\23\3\23\3\23"+ - "\3\23\3\23\5\23\u0114\n\23\3\24\3\24\3\24\3\24\3\24\5\24\u011b\n\24\3"+ - "\24\5\24\u011e\n\24\3\24\3\24\3\24\3\24\3\24\3\24\5\24\u0126\n\24\3\25"+ - "\5\25\u0129\n\25\3\25\5\25\u012c\n\25\3\26\3\26\3\26\3\26\3\26\3\26\3"+ - "\26\3\26\5\26\u0136\n\26\5\26\u0138\n\26\3\26\3\26\3\26\3\26\3\26\5\26"+ - "\u013f\n\26\3\26\3\26\3\26\3\26\7\26\u0145\n\26\f\26\16\26\u0148\13\26"+ - "\3\27\3\27\3\27\3\27\3\27\3\27\7\27\u0150\n\27\f\27\16\27\u0153\13\27"+ - "\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u015e\n\30\3\30\3\30"+ - "\3\30\3\30\3\30\3\30\5\30\u0166\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+ - "\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u017b"+ - "\n\30\f\30\16\30\u017e\13\30\3\30\3\30\3\30\3\30\3\30\6\30\u0185\n\30"+ - "\r\30\16\30\u0186\3\30\3\30\5\30\u018b\n\30\3\30\3\30\3\30\3\30\3\30\3"+ - "\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3"+ - "\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3"+ - "\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u01b7\n\30\3\30\3\30"+ - "\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u01c1\n\30\f\30\16\30\u01c4\13\30"+ - "\3\31\3\31\3\31\7\31\u01c9\n\31\f\31\16\31\u01cc\13\31\3\32\3\32\5\32"+ - "\u01d0\n\32\3\32\3\32\3\33\3\33\3\33\3\33\7\33\u01d8\n\33\f\33\16\33\u01db"+ - "\13\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34"+ - "\3\34\3\34\5\34\u01ec\n\34\5\34\u01ee\n\34\3\35\7\35\u01f1\n\35\f\35\16"+ - "\35\u01f4\13\35\3\36\3\36\3\36\5\36\u01f9\n\36\3\37\3\37\3\37\3\37\5\37"+ - "\u01ff\n\37\3\37\5\37\u0202\n\37\3 \3 \5 \u0206\n \3!\3!\3!\3!\7!\u020c"+ - "\n!\f!\16!\u020f\13!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3"+ - "\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\5\"\u0228\n\"\3#\3#\3#\3#\3"+ - "#\3#\3#\3#\3#\3#\3#\3#\3#\3#\5#\u0238\n#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3"+ - "#\3#\3#\7#\u0246\n#\f#\16#\u0249\13#\3#\2\7\22*,.D$\2\4\6\b\n\f\16\20"+ - "\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BD\2\r\3\2\36\37\3\2%&"+ - "\3\2\'+\3\2\60\61\3\2,-\4\2 ./\3\2\'(\3\2\60\65\3\2;D\4\2\'(\60\61\4"+ - "\2 ..\2\u029e\2F\3\2\2\2\4J\3\2\2\2\6P\3\2\2\2\bS\3\2\2\2\nW\3\2\2\2"+ - "\fa\3\2\2\2\16f\3\2\2\2\20p\3\2\2\2\22s\3\2\2\2\24~\3\2\2\2\26\u0083\3"+ - "\2\2\2\30\u0090\3\2\2\2\32\u009c\3\2\2\2\34\u009e\3\2\2\2\36\u00b4\3\2"+ - "\2\2 \u00b6\3\2\2\2\"\u00c3\3\2\2\2$\u0113\3\2\2\2&\u0125\3\2\2\2(\u012b"+ - "\3\2\2\2*\u0137\3\2\2\2,\u0149\3\2\2\2.\u018a\3\2\2\2\60\u01c5\3\2\2\2"+ - "\62\u01cd\3\2\2\2\64\u01d3\3\2\2\2\66\u01ed\3\2\2\28\u01f2\3\2\2\2:\u01f8"+ - "\3\2\2\2<\u0201\3\2\2\2>\u0203\3\2\2\2@\u0207\3\2\2\2B\u0227\3\2\2\2D"+ - "\u0237\3\2\2\2FG\5\6\4\2GH\5\n\6\2HI\7\2\2\3I\3\3\2\2\2JK\58\35\2KL\7"+ - "\2\2\3L\5\3\2\2\2MO\5\b\5\2NM\3\2\2\2OR\3\2\2\2PN\3\2\2\2PQ\3\2\2\2Q\7"+ - "\3\2\2\2RP\3\2\2\2ST\7\3\2\2TU\7R\2\2U\t\3\2\2\2VX\5\f\7\2WV\3\2\2\2X"+ - "Y\3\2\2\2YW\3\2\2\2YZ\3\2\2\2Z\13\3\2\2\2[\\\5\20\t\2\\]\7\4\2\2]b\3\2"+ - "\2\2^b\5\26\f\2_b\5\62\32\2`b\5\34\17\2a[\3\2\2\2a^\3\2\2\2a_\3\2\2\2"+ - "a`\3\2\2\2b\r\3\2\2\2ce\5\36\20\2dc\3\2\2\2eh\3\2\2\2fd\3\2\2\2fg\3\2"+ - "\2\2gi\3\2\2\2hf\3\2\2\2im\5*\26\2jl\5\36\20\2kj\3\2\2\2lo\3\2\2\2mk\3"+ - "\2\2\2mn\3\2\2\2n\17\3\2\2\2om\3\2\2\2pq\5\16\b\2qr\5\22\n\2r\21\3\2\2"+ - "\2st\b\n\1\2tu\5\24\13\2u{\3\2\2\2vw\f\3\2\2wx\7\5\2\2xz\5\24\13\2yv\3"+ - "\2\2\2z}\3\2\2\2{y\3\2\2\2{|\3\2\2\2|\23\3\2\2\2}{\3\2\2\2~\u0081\7^\2"+ - "\2\177\u0080\7\6\2\2\u0080\u0082\5.\30\2\u0081\177\3\2\2\2\u0081\u0082"+ - "\3\2\2\2\u0082\25\3\2\2\2\u0083\u0084\5\16\b\2\u0084\u0085\7^\2\2\u0085"+ - "\u0087\7\7\2\2\u0086\u0088\5\30\r\2\u0087\u0086\3\2\2\2\u0087\u0088\3"+ - "\2\2\2\u0088\u0089\3\2\2\2\u0089\u008a\7\b\2\2\u008a\u008c\7\t\2\2\u008b"+ - "\u008d\5\"\22\2\u008c\u008b\3\2\2\2\u008c\u008d\3\2\2\2\u008d\u008e\3"+ - "\2\2\2\u008e\u008f\7\n\2\2\u008f\27\3\2\2\2\u0090\u0095\5\32\16\2\u0091"+ - "\u0092\7\5\2\2\u0092\u0094\5\32\16\2\u0093\u0091\3\2\2\2\u0094\u0097\3"+ - "\2\2\2\u0095\u0093\3\2\2\2\u0095\u0096\3\2\2\2\u0096\31\3\2\2\2\u0097"+ - "\u0095\3\2\2\2\u0098\u0099\5\16\b\2\u0099\u009a\7^\2\2\u009a\u009d\3\2"+ - "\2\2\u009b\u009d\7Q\2\2\u009c\u0098\3\2\2\2\u009c\u009b\3\2\2\2\u009d"+ - "\33\3\2\2\2\u009e\u009f\5 \21\2\u009f\u00a0\7\4\2\2\u00a0\35\3\2\2\2\u00a1"+ - "\u00b5\7\13\2\2\u00a2\u00b5\7\f\2\2\u00a3\u00a4\7\r\2\2\u00a4\u00a5\7"+ - "\7\2\2\u00a5\u00a6\7U\2\2\u00a6\u00b5\7\b\2\2\u00a7\u00a8\7\16\2\2\u00a8"+ - "\u00a9\7\7\2\2\u00a9\u00aa\7^\2\2\u00aa\u00b5\7\b\2\2\u00ab\u00b5\7\17"+ - "\2\2\u00ac\u00b5\7\20\2\2\u00ad\u00b1\7\21\2\2\u00ae\u00af\7\7\2\2\u00af"+ - "\u00b0\7^\2\2\u00b0\u00b2\7\b\2\2\u00b1\u00ae\3\2\2\2\u00b1\u00b2\3\2"+ - "\2\2\u00b2\u00b5\3\2\2\2\u00b3\u00b5\5 \21\2\u00b4\u00a1\3\2\2\2\u00b4"+ - "\u00a2\3\2\2\2\u00b4\u00a3\3\2\2\2\u00b4\u00a7\3\2\2\2\u00b4\u00ab\3\2"+ - "\2\2\u00b4\u00ac\3\2\2\2\u00b4\u00ad\3\2\2\2\u00b4\u00b3\3\2\2\2\u00b5"+ - "\37\3\2\2\2\u00b6\u00b7\7\22\2\2\u00b7\u00b8\7\7\2\2\u00b8\u00bd\7U\2"+ - "\2\u00b9\u00ba\7\5\2\2\u00ba\u00bc\7U\2\2\u00bb\u00b9\3\2\2\2\u00bc\u00bf"+ - "\3\2\2\2\u00bd\u00bb\3\2\2\2\u00bd\u00be\3\2\2\2\u00be\u00c0\3\2\2\2\u00bf"+ - "\u00bd\3\2\2\2\u00c0\u00c1\7\b\2\2\u00c1!\3\2\2\2\u00c2\u00c4\5$\23\2"+ - "\u00c3\u00c2\3\2\2\2\u00c4\u00c5\3\2\2\2\u00c5\u00c3\3\2\2\2\u00c5\u00c6"+ - "\3\2\2\2\u00c6#\3\2\2\2\u00c7\u00c8\5\20\t\2\u00c8\u00c9\7\4\2\2\u00c9"+ - "\u0114\3\2\2\2\u00ca\u00cc\7\t\2\2\u00cb\u00cd\5\"\22\2\u00cc\u00cb\3"+ - "\2\2\2\u00cc\u00cd\3\2\2\2\u00cd\u00ce\3\2\2\2\u00ce\u0114\7\n\2\2\u00cf"+ - "\u00d0\5,\27\2\u00d0\u00d1\7\4\2\2\u00d1\u0114\3\2\2\2\u00d2\u00d3\7\23"+ - "\2\2\u00d3\u00d4\7\7\2\2\u00d4\u00d5\5,\27\2\u00d5\u00d6\7\b\2\2\u00d6"+ - "\u00d9\5$\23\2\u00d7\u00d8\7\24\2\2\u00d8\u00da\5$\23\2\u00d9\u00d7\3"+ - "\2\2\2\u00d9\u00da\3\2\2\2\u00da\u0114\3\2\2\2\u00db\u00dd\5\36\20\2\u00dc"+ - "\u00db\3\2\2\2\u00dd\u00e0\3\2\2\2\u00de\u00dc\3\2\2\2\u00de\u00df\3\2"+ - "\2\2\u00df\u00e1\3\2\2\2\u00e0\u00de\3\2\2\2\u00e1\u00e2\7\25\2\2\u00e2"+ - "\u00e3\7\7\2\2\u00e3\u00e4\5,\27\2\u00e4\u00e5\7\b\2\2\u00e5\u00e6\5$"+ - "\23\2\u00e6\u0114\3\2\2\2\u00e7\u00e9\5\36\20\2\u00e8\u00e7\3\2\2\2\u00e9"+ - "\u00ec\3\2\2\2\u00ea\u00e8\3\2\2\2\u00ea\u00eb\3\2\2\2\u00eb\u00ed\3\2"+ - "\2\2\u00ec\u00ea\3\2\2\2\u00ed\u00ee\7\26\2\2\u00ee\u00ef\5$\23\2\u00ef"+ - "\u00f0\7\25\2\2\u00f0\u00f1\7\7\2\2\u00f1\u00f2\5,\27\2\u00f2\u00f3\7"+ - "\b\2\2\u00f3\u00f4\7\4\2\2\u00f4\u0114\3\2\2\2\u00f5\u00f7\5\36\20\2\u00f6"+ - "\u00f5\3\2\2\2\u00f7\u00fa\3\2\2\2\u00f8\u00f6\3\2\2\2\u00f8\u00f9\3\2"+ - "\2\2\u00f9\u00fb\3\2\2\2\u00fa\u00f8\3\2\2\2\u00fb\u00fc\7\27\2\2\u00fc"+ - "\u00fd\7\7\2\2\u00fd\u00fe\5&\24\2\u00fe\u00ff\7\b\2\2\u00ff\u0100\5$"+ - "\23\2\u0100\u0114\3\2\2\2\u0101\u0103\7\30\2\2\u0102\u0104\5,\27\2\u0103"+ - "\u0102\3\2\2\2\u0103\u0104\3\2\2\2\u0104\u0105\3\2\2\2\u0105\u0114\7\4"+ - "\2\2\u0106\u0107\7\31\2\2\u0107\u0114\7\4\2\2\u0108\u0109\7\32\2\2\u0109"+ - "\u0114\7\4\2\2\u010a\u010c\7\33\2\2\u010b\u010d\5\64\33\2\u010c\u010b"+ - "\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3\2\2\2\u010e\u010f\7\t\2\2\u010f"+ - "\u0110\58\35\2\u0110\u0111\7\n\2\2\u0111\u0114\3\2\2\2\u0112\u0114\5\62"+ - "\32\2\u0113\u00c7\3\2\2\2\u0113\u00ca\3\2\2\2\u0113\u00cf\3\2\2\2\u0113"+ - "\u00d2\3\2\2\2\u0113\u00de\3\2\2\2\u0113\u00ea\3\2\2\2\u0113\u00f8\3\2"+ - "\2\2\u0113\u0101\3\2\2\2\u0113\u0106\3\2\2\2\u0113\u0108\3\2\2\2\u0113"+ - "\u010a\3\2\2\2\u0113\u0112\3\2\2\2\u0114%\3\2\2\2\u0115\u0116\5(\25\2"+ - "\u0116\u0117\7\4\2\2\u0117\u0118\5,\27\2\u0118\u011a\7\4\2\2\u0119\u011b"+ - "\5,\27\2\u011a\u0119\3\2\2\2\u011a\u011b\3\2\2\2\u011b\u0126\3\2\2\2\u011c"+ - "\u011e\5\16\b\2\u011d\u011c\3\2\2\2\u011d\u011e\3\2\2\2\u011e\u011f\3"+ - "\2\2\2\u011f\u0120\7^\2\2\u0120\u0121\7\34\2\2\u0121\u0122\5.\30\2\u0122"+ - "\u0123\7\35\2\2\u0123\u0124\5.\30\2\u0124\u0126\3\2\2\2\u0125\u0115\3"+ - "\2\2\2\u0125\u011d\3\2\2\2\u0126\'\3\2\2\2\u0127\u0129\5\20\t\2\u0128"+ - "\u0127\3\2\2\2\u0128\u0129\3\2\2\2\u0129\u012c\3\2\2\2\u012a\u012c\5,"+ - "\27\2\u012b\u0128\3\2\2\2\u012b\u012a\3\2\2\2\u012c)\3\2\2\2\u012d\u012e"+ - "\b\26\1\2\u012e\u012f\7\7\2\2\u012f\u0130\5*\26\2\u0130\u0131\7\b\2\2"+ - "\u0131\u0138\3\2\2\2\u0132\u0138\7Q\2\2\u0133\u0135\t\2\2\2\u0134\u0136"+ - "\7Q\2\2\u0135\u0134\3\2\2\2\u0135\u0136\3\2\2\2\u0136\u0138\3\2\2\2\u0137"+ - "\u012d\3\2\2\2\u0137\u0132\3\2\2\2\u0137\u0133\3\2\2\2\u0138\u0146\3\2"+ - "\2\2\u0139\u013a\f\5\2\2\u013a\u0145\7 \2\2\u013b\u013c\f\4\2\2\u013c"+ - "\u013e\7!\2\2\u013d\u013f\5.\30\2\u013e\u013d\3\2\2\2\u013e\u013f\3\2"+ - "\2\2\u013f\u0140\3\2\2\2\u0140\u0145\7\"\2\2\u0141\u0142\f\3\2\2\u0142"+ - "\u0143\7\7\2\2\u0143\u0145\7\b\2\2\u0144\u0139\3\2\2\2\u0144\u013b\3\2"+ - "\2\2\u0144\u0141\3\2\2\2\u0145\u0148\3\2\2\2\u0146\u0144\3\2\2\2\u0146"+ - "\u0147\3\2\2\2\u0147+\3\2\2\2\u0148\u0146\3\2\2\2\u0149\u014a\b\27\1\2"+ - "\u014a\u014b\5.\30\2\u014b\u0151\3\2\2\2\u014c\u014d\f\3\2\2\u014d\u014e"+ - "\7\5\2\2\u014e\u0150\5.\30\2\u014f\u014c\3\2\2\2\u0150\u0153\3\2\2\2\u0151"+ - "\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152-\3\2\2\2\u0153\u0151\3\2\2\2"+ - "\u0154\u0155\b\30\1\2\u0155\u0156\7\7\2\2\u0156\u0157\5,\27\2\u0157\u0158"+ - "\7\b\2\2\u0158\u018b\3\2\2\2\u0159\u015a\7#\2\2\u015a\u015d\7\7\2\2\u015b"+ - "\u015e\5*\26\2\u015c\u015e\5.\30\2\u015d\u015b\3\2\2\2\u015d\u015c\3\2"+ - "\2\2\u015e\u015f\3\2\2\2\u015f\u0160\7\b\2\2\u0160\u018b\3\2\2\2\u0161"+ - "\u0162\7$\2\2\u0162\u0165\7\7\2\2\u0163\u0166\5*\26\2\u0164\u0166\5.\30"+ - "\2\u0165\u0163\3\2\2\2\u0165\u0164\3\2\2\2\u0166\u0167\3\2\2\2\u0167\u0168"+ - "\7\b\2\2\u0168\u018b\3\2\2\2\u0169\u016a\7\7\2\2\u016a\u016b\5*\26\2\u016b"+ - "\u016c\7\b\2\2\u016c\u016d\5.\30\32\u016d\u018b\3\2\2\2\u016e\u016f\t"+ - "\3\2\2\u016f\u018b\5.\30\31\u0170\u0171\7 \2\2\u0171\u018b\5.\30\27\u0172"+ - "\u0173\t\4\2\2\u0173\u018b\5.\30\26\u0174\u0175\t\5\2\2\u0175\u018b\5"+ - ".\30\22\u0176\u0177\7\t\2\2\u0177\u017c\5.\30\2\u0178\u0179\7\5\2\2\u0179"+ - "\u017b\5.\30\2\u017a\u0178\3\2\2\2\u017b\u017e\3\2\2\2\u017c\u017a\3\2"+ - "\2\2\u017c\u017d\3\2\2\2\u017d\u017f\3\2\2\2\u017e\u017c\3\2\2\2\u017f"+ - "\u0180\7\n\2\2\u0180\u018b\3\2\2\2\u0181\u018b\7^\2\2\u0182\u018b\7U\2"+ - "\2\u0183\u0185\7R\2\2\u0184\u0183\3\2\2\2\u0185\u0186\3\2\2\2\u0186\u0184"+ - "\3\2\2\2\u0186\u0187\3\2\2\2\u0187\u018b\3\2\2\2\u0188\u018b\7S\2\2\u0189"+ - "\u018b\7T\2\2\u018a\u0154\3\2\2\2\u018a\u0159\3\2\2\2\u018a\u0161\3\2"+ - "\2\2\u018a\u0169\3\2\2\2\u018a\u016e\3\2\2\2\u018a\u0170\3\2\2\2\u018a"+ - "\u0172\3\2\2\2\u018a\u0174\3\2\2\2\u018a\u0176\3\2\2\2\u018a\u0181\3\2"+ - "\2\2\u018a\u0182\3\2\2\2\u018a\u0184\3\2\2\2\u018a\u0188\3\2\2\2\u018a"+ - "\u0189\3\2\2\2\u018b\u01c2\3\2\2\2\u018c\u018d\f\25\2\2\u018d\u018e\t"+ - "\6\2\2\u018e\u01c1\5.\30\26\u018f\u0190\f\24\2\2\u0190\u0191\t\7\2\2\u0191"+ - "\u01c1\5.\30\25\u0192\u0193\f\23\2\2\u0193\u0194\t\b\2\2\u0194\u01c1\5"+ - ".\30\24\u0195\u0196\f\21\2\2\u0196\u0197\t\t\2\2\u0197\u01c1\5.\30\22"+ - "\u0198\u0199\f\20\2\2\u0199\u019a\7*\2\2\u019a\u01c1\5.\30\21\u019b\u019c"+ - "\f\17\2\2\u019c\u019d\7\66\2\2\u019d\u01c1\5.\30\20\u019e\u019f\f\16\2"+ - "\2\u019f\u01a0\7\67\2\2\u01a0\u01c1\5.\30\17\u01a1\u01a2\f\r\2\2\u01a2"+ - "\u01a3\78\2\2\u01a3\u01c1\5.\30\16\u01a4\u01a5\f\f\2\2\u01a5\u01a6\79"+ - "\2\2\u01a6\u01c1\5.\30\r\u01a7\u01a8\f\13\2\2\u01a8\u01a9\7:\2\2\u01a9"+ - "\u01aa\5.\30\2\u01aa\u01ab\7\34\2\2\u01ab\u01ac\5.\30\f\u01ac\u01c1\3"+ - "\2\2\2\u01ad\u01ae\f\n\2\2\u01ae\u01af\7\6\2\2\u01af\u01c1\5.\30\n\u01b0"+ - "\u01b1\f\t\2\2\u01b1\u01b2\t\n\2\2\u01b2\u01c1\5.\30\t\u01b3\u01b4\f\36"+ - "\2\2\u01b4\u01b6\7\7\2\2\u01b5\u01b7\5\60\31\2\u01b6\u01b5\3\2\2\2\u01b6"+ - "\u01b7\3\2\2\2\u01b7\u01b8\3\2\2\2\u01b8\u01c1\7\b\2\2\u01b9\u01ba\f\33"+ - "\2\2\u01ba\u01bb\7!\2\2\u01bb\u01bc\5,\27\2\u01bc\u01bd\7\"\2\2\u01bd"+ - "\u01c1\3\2\2\2\u01be\u01bf\f\30\2\2\u01bf\u01c1\t\3\2\2\u01c0\u018c\3"+ - "\2\2\2\u01c0\u018f\3\2\2\2\u01c0\u0192\3\2\2\2\u01c0\u0195\3\2\2\2\u01c0"+ - "\u0198\3\2\2\2\u01c0\u019b\3\2\2\2\u01c0\u019e\3\2\2\2\u01c0\u01a1\3\2"+ - "\2\2\u01c0\u01a4\3\2\2\2\u01c0\u01a7\3\2\2\2\u01c0\u01ad\3\2\2\2\u01c0"+ - "\u01b0\3\2\2\2\u01c0\u01b3\3\2\2\2\u01c0\u01b9\3\2\2\2\u01c0\u01be\3\2"+ - "\2\2\u01c1\u01c4\3\2\2\2\u01c2\u01c0\3\2\2\2\u01c2\u01c3\3\2\2\2\u01c3"+ - "/\3\2\2\2\u01c4\u01c2\3\2\2\2\u01c5\u01ca\5.\30\2\u01c6\u01c7\7\5\2\2"+ - "\u01c7\u01c9\5.\30\2\u01c8\u01c6\3\2\2\2\u01c9\u01cc\3\2\2\2\u01ca\u01c8"+ - "\3\2\2\2\u01ca\u01cb\3\2\2\2\u01cb\61\3\2\2\2\u01cc\u01ca\3\2\2\2\u01cd"+ - "\u01cf\7E\2\2\u01ce\u01d0\5\64\33\2\u01cf\u01ce\3\2\2\2\u01cf\u01d0\3"+ - "\2\2\2\u01d0\u01d1\3\2\2\2\u01d1\u01d2\7P\2\2\u01d2\63\3\2\2\2\u01d3\u01d4"+ - "\7\7\2\2\u01d4\u01d9\5\66\34\2\u01d5\u01d6\7\5\2\2\u01d6\u01d8\5\66\34"+ - "\2\u01d7\u01d5\3\2\2\2\u01d8\u01db\3\2\2\2\u01d9\u01d7\3\2\2\2\u01d9\u01da"+ - "\3\2\2\2\u01da\u01dc\3\2\2\2\u01db\u01d9\3\2\2\2\u01dc\u01dd\7\b\2\2\u01dd"+ - "\65\3\2\2\2\u01de\u01df\7F\2\2\u01df\u01ee\7R\2\2\u01e0\u01e1\7G\2\2\u01e1"+ - "\u01ee\7^\2\2\u01e2\u01e3\7H\2\2\u01e3\u01ee\7R\2\2\u01e4\u01e5\7I\2\2"+ - "\u01e5\u01ee\5.\30\2\u01e6\u01e7\7J\2\2\u01e7\u01ee\5.\30\2\u01e8\u01eb"+ - "\7K\2\2\u01e9\u01ec\7\17\2\2\u01ea\u01ec\5.\30\2\u01eb\u01e9\3\2\2\2\u01eb"+ - "\u01ea\3\2\2\2\u01ec\u01ee\3\2\2\2\u01ed\u01de\3\2\2\2\u01ed\u01e0\3\2"+ - "\2\2\u01ed\u01e2\3\2\2\2\u01ed\u01e4\3\2\2\2\u01ed\u01e6\3\2\2\2\u01ed"+ - "\u01e8\3\2\2\2\u01ee\67\3\2\2\2\u01ef\u01f1\5:\36\2\u01f0\u01ef\3\2\2"+ - "\2\u01f1\u01f4\3\2\2\2\u01f2\u01f0\3\2\2\2\u01f2\u01f3\3\2\2\2\u01f39"+ - "\3\2\2\2\u01f4\u01f2\3\2\2\2\u01f5\u01f9\5<\37\2\u01f6\u01f9\5> \2\u01f7"+ - "\u01f9\5@!\2\u01f8\u01f5\3\2\2\2\u01f8\u01f6\3\2\2\2\u01f8\u01f7\3\2\2"+ - "\2\u01f9;\3\2\2\2\u01fa\u01fb\7^\2\2\u01fb\u0202\7\34\2\2\u01fc\u01fe"+ - "\7)\2\2\u01fd\u01ff\7^\2\2\u01fe\u01fd\3\2\2\2\u01fe\u01ff\3\2\2\2\u01ff"+ - "\u0200\3\2\2\2\u0200\u0202\7\34\2\2\u0201\u01fa\3\2\2\2\u0201\u01fc\3"+ - "\2\2\2\u0202=\3\2\2\2\u0203\u0205\7O\2\2\u0204\u0206\5B\"\2\u0205\u0204"+ - "\3\2\2\2\u0205\u0206\3\2\2\2\u0206?\3\2\2\2\u0207\u0208\7L\2\2\u0208\u020d"+ - "\5D#\2\u0209\u020a\7\5\2\2\u020a\u020c\5D#\2\u020b\u0209\3\2\2\2\u020c"+ - "\u020f\3\2\2\2\u020d\u020b\3\2\2\2\u020d\u020e\3\2\2\2\u020eA\3\2\2\2"+ - "\u020f\u020d\3\2\2\2\u0210\u0228\5D#\2\u0211\u0212\7M\2\2\u0212\u0228"+ - "\5D#\2\u0213\u0214\5D#\2\u0214\u0215\7\5\2\2\u0215\u0216\7^\2\2\u0216"+ - "\u0228\3\2\2\2\u0217\u0218\7\7\2\2\u0218\u0219\5D#\2\u0219\u021a\7\b\2"+ - "\2\u021a\u021b\7\5\2\2\u021b\u021c\7^\2\2\u021c\u0228\3\2\2\2\u021d\u021e"+ - "\7\7\2\2\u021e\u021f\5D#\2\u021f\u0220\7\5\2\2\u0220\u0221\7^\2\2\u0221"+ - "\u0222\7\b\2\2\u0222\u0228\3\2\2\2\u0223\u0224\7\7\2\2\u0224\u0225\5D"+ - "#\2\u0225\u0226\7\b\2\2\u0226\u0228\3\2\2\2\u0227\u0210\3\2\2\2\u0227"+ - "\u0211\3\2\2\2\u0227\u0213\3\2\2\2\u0227\u0217\3\2\2\2\u0227\u021d\3\2"+ - "\2\2\u0227\u0223\3\2\2\2\u0228C\3\2\2\2\u0229\u022a\b#\1\2\u022a\u022b"+ - "\7!\2\2\u022b\u022c\5D#\2\u022c\u022d\7\"\2\2\u022d\u0238\3\2\2\2\u022e"+ - "\u022f\t\13\2\2\u022f\u0238\5D#\n\u0230\u0238\7^\2\2\u0231\u0238\7_\2"+ - "\2\u0232\u0233\7\t\2\2\u0233\u0234\7^\2\2\u0234\u0238\7\n\2\2\u0235\u0238"+ - "\7U\2\2\u0236\u0238\7S\2\2\u0237\u0229\3\2\2\2\u0237\u022e\3\2\2\2\u0237"+ - "\u0230\3\2\2\2\u0237\u0231\3\2\2\2\u0237\u0232\3\2\2\2\u0237\u0235\3\2"+ - "\2\2\u0237\u0236\3\2\2\2\u0238\u0247\3\2\2\2\u0239\u023a\f\f\2\2\u023a"+ - "\u023b\7N\2\2\u023b\u0246\5D#\r\u023c\u023d\f\13\2\2\u023d\u023e\t\6\2"+ - "\2\u023e\u0246\5D#\f\u023f\u0240\f\t\2\2\u0240\u0241\t\f\2\2\u0241\u0246"+ - "\5D#\n\u0242\u0243\f\b\2\2\u0243\u0244\t\b\2\2\u0244\u0246\5D#\t\u0245"+ - "\u0239\3\2\2\2\u0245\u023c\3\2\2\2\u0245\u023f\3\2\2\2\u0245\u0242\3\2"+ - "\2\2\u0246\u0249\3\2\2\2\u0247\u0245\3\2\2\2\u0247\u0248\3\2\2\2\u0248"+ - "E\3\2\2\2\u0249\u0247\3\2\2\2;PYafm{\u0081\u0087\u008c\u0095\u009c\u00b1"+ - "\u00b4\u00bd\u00c5\u00cc\u00d9\u00de\u00ea\u00f8\u0103\u010c\u0113\u011a"+ - "\u011d\u0125\u0128\u012b\u0135\u0137\u013e\u0144\u0146\u0151\u015d\u0165"+ - "\u017c\u0186\u018a\u01b6\u01c0\u01c2\u01ca\u01cf\u01d9\u01eb\u01ed\u01f2"+ - "\u01f8\u01fe\u0201\u0205\u020d\u0227\u0237\u0245\u0247"; + "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\4\7"+ + "\4U\n\4\f\4\16\4X\13\4\3\5\3\5\3\5\3\6\6\6^\n\6\r\6\16\6_\3\7\3\7\3\7"+ + "\3\7\3\7\3\7\3\7\3\7\3\7\5\7k\n\7\3\b\7\bn\n\b\f\b\16\bq\13\b\3\b\3\b"+ + "\7\bu\n\b\f\b\16\bx\13\b\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\7\n\u0083"+ + "\n\n\f\n\16\n\u0086\13\n\3\13\3\13\3\13\5\13\u008b\n\13\3\f\3\f\3\f\3"+ + "\f\5\f\u0091\n\f\3\f\3\f\3\f\5\f\u0096\n\f\3\f\3\f\3\r\3\r\3\r\7\r\u009d"+ + "\n\r\f\r\16\r\u00a0\13\r\3\16\3\16\3\16\3\16\5\16\u00a6\n\16\3\17\3\17"+ + "\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+ + "\3\20\3\20\3\20\5\20\u00bb\n\20\3\20\5\20\u00be\n\20\3\21\3\21\3\21\3"+ + "\21\3\21\7\21\u00c5\n\21\f\21\16\21\u00c8\13\21\3\21\3\21\3\22\6\22\u00cd"+ + "\n\22\r\22\16\22\u00ce\3\23\3\23\3\23\3\23\3\23\5\23\u00d6\n\23\3\23\3"+ + "\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u00e3\n\23\3\23"+ + "\7\23\u00e6\n\23\f\23\16\23\u00e9\13\23\3\23\3\23\3\23\3\23\3\23\3\23"+ + "\3\23\7\23\u00f2\n\23\f\23\16\23\u00f5\13\23\3\23\3\23\3\23\3\23\3\23"+ + "\3\23\3\23\3\23\3\23\7\23\u0100\n\23\f\23\16\23\u0103\13\23\3\23\3\23"+ + "\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u010d\n\23\3\23\3\23\3\23\3\23\3\23"+ + "\3\23\3\23\5\23\u0116\n\23\3\23\3\23\3\23\3\23\3\23\5\23\u011d\n\23\3"+ + "\24\3\24\3\24\3\24\3\24\5\24\u0124\n\24\3\24\5\24\u0127\n\24\3\24\3\24"+ + "\3\24\3\24\3\24\3\24\5\24\u012f\n\24\3\25\5\25\u0132\n\25\3\25\5\25\u0135"+ + "\n\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\5\26\u013f\n\26\3\26\3\26"+ + "\5\26\u0143\n\26\3\26\3\26\3\26\3\26\3\26\5\26\u014a\n\26\3\26\3\26\3"+ + "\26\3\26\7\26\u0150\n\26\f\26\16\26\u0153\13\26\3\27\3\27\3\27\3\30\3"+ + "\30\5\30\u015a\n\30\3\30\3\30\6\30\u015e\n\30\r\30\16\30\u015f\3\30\3"+ + "\30\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\7\32\u016d\n\32\f\32"+ + "\16\32\u0170\13\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u017b"+ + "\n\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u0183\n\33\3\33\3\33\3\33\3\33"+ + "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+ + "\3\33\7\33\u0198\n\33\f\33\16\33\u019b\13\33\3\33\3\33\3\33\3\33\3\33"+ + "\6\33\u01a2\n\33\r\33\16\33\u01a3\3\33\3\33\5\33\u01a8\n\33\3\33\3\33"+ + "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+ + "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+ + "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u01d4"+ + "\n\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\7\33\u01de\n\33\f\33\16"+ + "\33\u01e1\13\33\3\34\3\34\3\34\7\34\u01e6\n\34\f\34\16\34\u01e9\13\34"+ + "\3\35\3\35\5\35\u01ed\n\35\3\35\3\35\3\36\3\36\3\36\3\36\7\36\u01f5\n"+ + "\36\f\36\16\36\u01f8\13\36\3\36\3\36\3\37\3\37\3\37\3\37\3\37\3\37\3\37"+ + "\3\37\3\37\3\37\3\37\3\37\3\37\5\37\u0209\n\37\5\37\u020b\n\37\3 \7 \u020e"+ + "\n \f \16 \u0211\13 \3!\3!\3!\5!\u0216\n!\3\"\3\"\3\"\3\"\5\"\u021c\n"+ + "\"\3\"\5\"\u021f\n\"\3#\3#\5#\u0223\n#\3$\3$\3$\3$\7$\u0229\n$\f$\16$"+ + "\u022c\13$\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3"+ + "%\3%\3%\3%\5%\u0245\n%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\5&\u0255"+ + "\n&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\7&\u0263\n&\f&\16&\u0266\13&\3"+ + "&\2\7\22*\62\64J\'\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60"+ + "\62\64\668:<>@BDFHJ\2\r\3\2\36\37\3\2&\'\3\2(,\3\2\61\62\3\2-.\4\2 /"+ + "\60\3\2()\3\2\61\66\3\2<E\4\2()\61\62\4\2 //\2\u02bd\2L\3\2\2\2\4P\3"+ + "\2\2\2\6V\3\2\2\2\bY\3\2\2\2\n]\3\2\2\2\fj\3\2\2\2\16o\3\2\2\2\20y\3\2"+ + "\2\2\22|\3\2\2\2\24\u0087\3\2\2\2\26\u008c\3\2\2\2\30\u0099\3\2\2\2\32"+ + "\u00a5\3\2\2\2\34\u00a7\3\2\2\2\36\u00bd\3\2\2\2 \u00bf\3\2\2\2\"\u00cc"+ + "\3\2\2\2$\u011c\3\2\2\2&\u012e\3\2\2\2(\u0134\3\2\2\2*\u0142\3\2\2\2,"+ + "\u0154\3\2\2\2.\u0157\3\2\2\2\60\u0163\3\2\2\2\62\u0166\3\2\2\2\64\u01a7"+ + "\3\2\2\2\66\u01e2\3\2\2\28\u01ea\3\2\2\2:\u01f0\3\2\2\2<\u020a\3\2\2\2"+ + ">\u020f\3\2\2\2@\u0215\3\2\2\2B\u021e\3\2\2\2D\u0220\3\2\2\2F\u0224\3"+ + "\2\2\2H\u0244\3\2\2\2J\u0254\3\2\2\2LM\5\6\4\2MN\5\n\6\2NO\7\2\2\3O\3"+ + "\3\2\2\2PQ\5> \2QR\7\2\2\3R\5\3\2\2\2SU\5\b\5\2TS\3\2\2\2UX\3\2\2\2VT"+ + "\3\2\2\2VW\3\2\2\2W\7\3\2\2\2XV\3\2\2\2YZ\7\3\2\2Z[\7S\2\2[\t\3\2\2\2"+ + "\\^\5\f\7\2]\\\3\2\2\2^_\3\2\2\2_]\3\2\2\2_`\3\2\2\2`\13\3\2\2\2ab\5\20"+ + "\t\2bc\7\4\2\2ck\3\2\2\2de\5.\30\2ef\7\4\2\2fk\3\2\2\2gk\5\26\f\2hk\5"+ + "8\35\2ik\5\34\17\2ja\3\2\2\2jd\3\2\2\2jg\3\2\2\2jh\3\2\2\2ji\3\2\2\2k"+ + "\r\3\2\2\2ln\5\36\20\2ml\3\2\2\2nq\3\2\2\2om\3\2\2\2op\3\2\2\2pr\3\2\2"+ + "\2qo\3\2\2\2rv\5*\26\2su\5\36\20\2ts\3\2\2\2ux\3\2\2\2vt\3\2\2\2vw\3\2"+ + "\2\2w\17\3\2\2\2xv\3\2\2\2yz\5\16\b\2z{\5\22\n\2{\21\3\2\2\2|}\b\n\1\2"+ + "}~\5\24\13\2~\u0084\3\2\2\2\177\u0080\f\3\2\2\u0080\u0081\7\5\2\2\u0081"+ + "\u0083\5\24\13\2\u0082\177\3\2\2\2\u0083\u0086\3\2\2\2\u0084\u0082\3\2"+ + "\2\2\u0084\u0085\3\2\2\2\u0085\23\3\2\2\2\u0086\u0084\3\2\2\2\u0087\u008a"+ + "\7_\2\2\u0088\u0089\7\6\2\2\u0089\u008b\5\64\33\2\u008a\u0088\3\2\2\2"+ + "\u008a\u008b\3\2\2\2\u008b\25\3\2\2\2\u008c\u008d\5\16\b\2\u008d\u008e"+ + "\7_\2\2\u008e\u0090\7\7\2\2\u008f\u0091\5\30\r\2\u0090\u008f\3\2\2\2\u0090"+ + "\u0091\3\2\2\2\u0091\u0092\3\2\2\2\u0092\u0093\7\b\2\2\u0093\u0095\7\t"+ + "\2\2\u0094\u0096\5\"\22\2\u0095\u0094\3\2\2\2\u0095\u0096\3\2\2\2\u0096"+ + "\u0097\3\2\2\2\u0097\u0098\7\n\2\2\u0098\27\3\2\2\2\u0099\u009e\5\32\16"+ + "\2\u009a\u009b\7\5\2\2\u009b\u009d\5\32\16\2\u009c\u009a\3\2\2\2\u009d"+ + "\u00a0\3\2\2\2\u009e\u009c\3\2\2\2\u009e\u009f\3\2\2\2\u009f\31\3\2\2"+ + "\2\u00a0\u009e\3\2\2\2\u00a1\u00a2\5\16\b\2\u00a2\u00a3\7_\2\2\u00a3\u00a6"+ + "\3\2\2\2\u00a4\u00a6\7R\2\2\u00a5\u00a1\3\2\2\2\u00a5\u00a4\3\2\2\2\u00a6"+ + "\33\3\2\2\2\u00a7\u00a8\5 \21\2\u00a8\u00a9\7\4\2\2\u00a9\35\3\2\2\2\u00aa"+ + "\u00be\7\13\2\2\u00ab\u00be\7\f\2\2\u00ac\u00ad\7\r\2\2\u00ad\u00ae\7"+ + "\7\2\2\u00ae\u00af\7V\2\2\u00af\u00be\7\b\2\2\u00b0\u00b1\7\16\2\2\u00b1"+ + "\u00b2\7\7\2\2\u00b2\u00b3\7_\2\2\u00b3\u00be\7\b\2\2\u00b4\u00be\7\17"+ + "\2\2\u00b5\u00be\7\20\2\2\u00b6\u00ba\7\21\2\2\u00b7\u00b8\7\7\2\2\u00b8"+ + "\u00b9\7_\2\2\u00b9\u00bb\7\b\2\2\u00ba\u00b7\3\2\2\2\u00ba\u00bb\3\2"+ + "\2\2\u00bb\u00be\3\2\2\2\u00bc\u00be\5 \21\2\u00bd\u00aa\3\2\2\2\u00bd"+ + "\u00ab\3\2\2\2\u00bd\u00ac\3\2\2\2\u00bd\u00b0\3\2\2\2\u00bd\u00b4\3\2"+ + "\2\2\u00bd\u00b5\3\2\2\2\u00bd\u00b6\3\2\2\2\u00bd\u00bc\3\2\2\2\u00be"+ + "\37\3\2\2\2\u00bf\u00c0\7\22\2\2\u00c0\u00c1\7\7\2\2\u00c1\u00c6\7V\2"+ + "\2\u00c2\u00c3\7\5\2\2\u00c3\u00c5\7V\2\2\u00c4\u00c2\3\2\2\2\u00c5\u00c8"+ + "\3\2\2\2\u00c6\u00c4\3\2\2\2\u00c6\u00c7\3\2\2\2\u00c7\u00c9\3\2\2\2\u00c8"+ + "\u00c6\3\2\2\2\u00c9\u00ca\7\b\2\2\u00ca!\3\2\2\2\u00cb\u00cd\5$\23\2"+ + "\u00cc\u00cb\3\2\2\2\u00cd\u00ce\3\2\2\2\u00ce\u00cc\3\2\2\2\u00ce\u00cf"+ + "\3\2\2\2\u00cf#\3\2\2\2\u00d0\u00d1\5\20\t\2\u00d1\u00d2\7\4\2\2\u00d2"+ + "\u011d\3\2\2\2\u00d3\u00d5\7\t\2\2\u00d4\u00d6\5\"\22\2\u00d5\u00d4\3"+ + "\2\2\2\u00d5\u00d6\3\2\2\2\u00d6\u00d7\3\2\2\2\u00d7\u011d\7\n\2\2\u00d8"+ + "\u00d9\5\62\32\2\u00d9\u00da\7\4\2\2\u00da\u011d\3\2\2\2\u00db\u00dc\7"+ + "\23\2\2\u00dc\u00dd\7\7\2\2\u00dd\u00de\5\62\32\2\u00de\u00df\7\b\2\2"+ + "\u00df\u00e2\5$\23\2\u00e0\u00e1\7\24\2\2\u00e1\u00e3\5$\23\2\u00e2\u00e0"+ + "\3\2\2\2\u00e2\u00e3\3\2\2\2\u00e3\u011d\3\2\2\2\u00e4\u00e6\5\36\20\2"+ + "\u00e5\u00e4\3\2\2\2\u00e6\u00e9\3\2\2\2\u00e7\u00e5\3\2\2\2\u00e7\u00e8"+ + "\3\2\2\2\u00e8\u00ea\3\2\2\2\u00e9\u00e7\3\2\2\2\u00ea\u00eb\7\25\2\2"+ + "\u00eb\u00ec\7\7\2\2\u00ec\u00ed\5\62\32\2\u00ed\u00ee\7\b\2\2\u00ee\u00ef"+ + "\5$\23\2\u00ef\u011d\3\2\2\2\u00f0\u00f2\5\36\20\2\u00f1\u00f0\3\2\2\2"+ + "\u00f2\u00f5\3\2\2\2\u00f3\u00f1\3\2\2\2\u00f3\u00f4\3\2\2\2\u00f4\u00f6"+ + "\3\2\2\2\u00f5\u00f3\3\2\2\2\u00f6\u00f7\7\26\2\2\u00f7\u00f8\5$\23\2"+ + "\u00f8\u00f9\7\25\2\2\u00f9\u00fa\7\7\2\2\u00fa\u00fb\5\62\32\2\u00fb"+ + "\u00fc\7\b\2\2\u00fc\u00fd\7\4\2\2\u00fd\u011d\3\2\2\2\u00fe\u0100\5\36"+ + "\20\2\u00ff\u00fe\3\2\2\2\u0100\u0103\3\2\2\2\u0101\u00ff\3\2\2\2\u0101"+ + "\u0102\3\2\2\2\u0102\u0104\3\2\2\2\u0103\u0101\3\2\2\2\u0104\u0105\7\27"+ + "\2\2\u0105\u0106\7\7\2\2\u0106\u0107\5&\24\2\u0107\u0108\7\b\2\2\u0108"+ + "\u0109\5$\23\2\u0109\u011d\3\2\2\2\u010a\u010c\7\30\2\2\u010b\u010d\5"+ + "\62\32\2\u010c\u010b\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3\2\2\2\u010e"+ + "\u011d\7\4\2\2\u010f\u0110\7\31\2\2\u0110\u011d\7\4\2\2\u0111\u0112\7"+ + "\32\2\2\u0112\u011d\7\4\2\2\u0113\u0115\7\33\2\2\u0114\u0116\5:\36\2\u0115"+ + "\u0114\3\2\2\2\u0115\u0116\3\2\2\2\u0116\u0117\3\2\2\2\u0117\u0118\7\t"+ + "\2\2\u0118\u0119\5> \2\u0119\u011a\7\n\2\2\u011a\u011d\3\2\2\2\u011b\u011d"+ + "\58\35\2\u011c\u00d0\3\2\2\2\u011c\u00d3\3\2\2\2\u011c\u00d8\3\2\2\2\u011c"+ + "\u00db\3\2\2\2\u011c\u00e7\3\2\2\2\u011c\u00f3\3\2\2\2\u011c\u0101\3\2"+ + "\2\2\u011c\u010a\3\2\2\2\u011c\u010f\3\2\2\2\u011c\u0111\3\2\2\2\u011c"+ + "\u0113\3\2\2\2\u011c\u011b\3\2\2\2\u011d%\3\2\2\2\u011e\u011f\5(\25\2"+ + "\u011f\u0120\7\4\2\2\u0120\u0121\5\62\32\2\u0121\u0123\7\4\2\2\u0122\u0124"+ + "\5\62\32\2\u0123\u0122\3\2\2\2\u0123\u0124\3\2\2\2\u0124\u012f\3\2\2\2"+ + "\u0125\u0127\5\16\b\2\u0126\u0125\3\2\2\2\u0126\u0127\3\2\2\2\u0127\u0128"+ + "\3\2\2\2\u0128\u0129\7_\2\2\u0129\u012a\7\34\2\2\u012a\u012b\5\64\33\2"+ + "\u012b\u012c\7\35\2\2\u012c\u012d\5\64\33\2\u012d\u012f\3\2\2\2\u012e"+ + "\u011e\3\2\2\2\u012e\u0126\3\2\2\2\u012f\'\3\2\2\2\u0130\u0132\5\20\t"+ + "\2\u0131\u0130\3\2\2\2\u0131\u0132\3\2\2\2\u0132\u0135\3\2\2\2\u0133\u0135"+ + "\5\62\32\2\u0134\u0131\3\2\2\2\u0134\u0133\3\2\2\2\u0135)\3\2\2\2\u0136"+ + "\u0137\b\26\1\2\u0137\u0138\7\7\2\2\u0138\u0139\5*\26\2\u0139\u013a\7"+ + "\b\2\2\u013a\u0143\3\2\2\2\u013b\u0143\7R\2\2\u013c\u013e\t\2\2\2\u013d"+ + "\u013f\7R\2\2\u013e\u013d\3\2\2\2\u013e\u013f\3\2\2\2\u013f\u0143\3\2"+ + "\2\2\u0140\u0143\5.\30\2\u0141\u0143\5,\27\2\u0142\u0136\3\2\2\2\u0142"+ + "\u013b\3\2\2\2\u0142\u013c\3\2\2\2\u0142\u0140\3\2\2\2\u0142\u0141\3\2"+ + "\2\2\u0143\u0151\3\2\2\2\u0144\u0145\f\7\2\2\u0145\u0150\7 \2\2\u0146"+ + "\u0147\f\6\2\2\u0147\u0149\7!\2\2\u0148\u014a\5\64\33\2\u0149\u0148\3"+ + "\2\2\2\u0149\u014a\3\2\2\2\u014a\u014b\3\2\2\2\u014b\u0150\7\"\2\2\u014c"+ + "\u014d\f\5\2\2\u014d\u014e\7\7\2\2\u014e\u0150\7\b\2\2\u014f\u0144\3\2"+ + "\2\2\u014f\u0146\3\2\2\2\u014f\u014c\3\2\2\2\u0150\u0153\3\2\2\2\u0151"+ + "\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152+\3\2\2\2\u0153\u0151\3\2\2\2"+ + "\u0154\u0155\7#\2\2\u0155\u0156\7_\2\2\u0156-\3\2\2\2\u0157\u0159\7#\2"+ + "\2\u0158\u015a\7_\2\2\u0159\u0158\3\2\2\2\u0159\u015a\3\2\2\2\u015a\u015b"+ + "\3\2\2\2\u015b\u015d\7\t\2\2\u015c\u015e\5\60\31\2\u015d\u015c\3\2\2\2"+ + "\u015e\u015f\3\2\2\2\u015f\u015d\3\2\2\2\u015f\u0160\3\2\2\2\u0160\u0161"+ + "\3\2\2\2\u0161\u0162\7\n\2\2\u0162/\3\2\2\2\u0163\u0164\5\20\t\2\u0164"+ + "\u0165\7\4\2\2\u0165\61\3\2\2\2\u0166\u0167\b\32\1\2\u0167\u0168\5\64"+ + "\33\2\u0168\u016e\3\2\2\2\u0169\u016a\f\3\2\2\u016a\u016b\7\5\2\2\u016b"+ + "\u016d\5\64\33\2\u016c\u0169\3\2\2\2\u016d\u0170\3\2\2\2\u016e\u016c\3"+ + "\2\2\2\u016e\u016f\3\2\2\2\u016f\63\3\2\2\2\u0170\u016e\3\2\2\2\u0171"+ + "\u0172\b\33\1\2\u0172\u0173\7\7\2\2\u0173\u0174\5\62\32\2\u0174\u0175"+ + "\7\b\2\2\u0175\u01a8\3\2\2\2\u0176\u0177\7$\2\2\u0177\u017a\7\7\2\2\u0178"+ + "\u017b\5*\26\2\u0179\u017b\5\64\33\2\u017a\u0178\3\2\2\2\u017a\u0179\3"+ + "\2\2\2\u017b\u017c\3\2\2\2\u017c\u017d\7\b\2\2\u017d\u01a8\3\2\2\2\u017e"+ + "\u017f\7%\2\2\u017f\u0182\7\7\2\2\u0180\u0183\5*\26\2\u0181\u0183\5\64"+ + "\33\2\u0182\u0180\3\2\2\2\u0182\u0181\3\2\2\2\u0183\u0184\3\2\2\2\u0184"+ + "\u0185\7\b\2\2\u0185\u01a8\3\2\2\2\u0186\u0187\7\7\2\2\u0187\u0188\5*"+ + "\26\2\u0188\u0189\7\b\2\2\u0189\u018a\5\64\33\32\u018a\u01a8\3\2\2\2\u018b"+ + "\u018c\t\3\2\2\u018c\u01a8\5\64\33\31\u018d\u018e\7 \2\2\u018e\u01a8\5"+ + "\64\33\27\u018f\u0190\t\4\2\2\u0190\u01a8\5\64\33\26\u0191\u0192\t\5\2"+ + "\2\u0192\u01a8\5\64\33\22\u0193\u0194\7\t\2\2\u0194\u0199\5\64\33\2\u0195"+ + "\u0196\7\5\2\2\u0196\u0198\5\64\33\2\u0197\u0195\3\2\2\2\u0198\u019b\3"+ + "\2\2\2\u0199\u0197\3\2\2\2\u0199\u019a\3\2\2\2\u019a\u019c\3\2\2\2\u019b"+ + "\u0199\3\2\2\2\u019c\u019d\7\n\2\2\u019d\u01a8\3\2\2\2\u019e\u01a8\7_"+ + "\2\2\u019f\u01a8\7V\2\2\u01a0\u01a2\7S\2\2\u01a1\u01a0\3\2\2\2\u01a2\u01a3"+ + "\3\2\2\2\u01a3\u01a1\3\2\2\2\u01a3\u01a4\3\2\2\2\u01a4\u01a8\3\2\2\2\u01a5"+ + "\u01a8\7T\2\2\u01a6\u01a8\7U\2\2\u01a7\u0171\3\2\2\2\u01a7\u0176\3\2\2"+ + "\2\u01a7\u017e\3\2\2\2\u01a7\u0186\3\2\2\2\u01a7\u018b\3\2\2\2\u01a7\u018d"+ + "\3\2\2\2\u01a7\u018f\3\2\2\2\u01a7\u0191\3\2\2\2\u01a7\u0193\3\2\2\2\u01a7"+ + "\u019e\3\2\2\2\u01a7\u019f\3\2\2\2\u01a7\u01a1\3\2\2\2\u01a7\u01a5\3\2"+ + "\2\2\u01a7\u01a6\3\2\2\2\u01a8\u01df\3\2\2\2\u01a9\u01aa\f\25\2\2\u01aa"+ + "\u01ab\t\6\2\2\u01ab\u01de\5\64\33\26\u01ac\u01ad\f\24\2\2\u01ad\u01ae"+ + "\t\7\2\2\u01ae\u01de\5\64\33\25\u01af\u01b0\f\23\2\2\u01b0\u01b1\t\b\2"+ + "\2\u01b1\u01de\5\64\33\24\u01b2\u01b3\f\21\2\2\u01b3\u01b4\t\t\2\2\u01b4"+ + "\u01de\5\64\33\22\u01b5\u01b6\f\20\2\2\u01b6\u01b7\7+\2\2\u01b7\u01de"+ + "\5\64\33\21\u01b8\u01b9\f\17\2\2\u01b9\u01ba\7\67\2\2\u01ba\u01de\5\64"+ + "\33\20\u01bb\u01bc\f\16\2\2\u01bc\u01bd\78\2\2\u01bd\u01de\5\64\33\17"+ + "\u01be\u01bf\f\r\2\2\u01bf\u01c0\79\2\2\u01c0\u01de\5\64\33\16\u01c1\u01c2"+ + "\f\f\2\2\u01c2\u01c3\7:\2\2\u01c3\u01de\5\64\33\r\u01c4\u01c5\f\13\2\2"+ + "\u01c5\u01c6\7;\2\2\u01c6\u01c7\5\64\33\2\u01c7\u01c8\7\34\2\2\u01c8\u01c9"+ + "\5\64\33\f\u01c9\u01de\3\2\2\2\u01ca\u01cb\f\n\2\2\u01cb\u01cc\7\6\2\2"+ + "\u01cc\u01de\5\64\33\n\u01cd\u01ce\f\t\2\2\u01ce\u01cf\t\n\2\2\u01cf\u01de"+ + "\5\64\33\t\u01d0\u01d1\f\36\2\2\u01d1\u01d3\7\7\2\2\u01d2\u01d4\5\66\34"+ + "\2\u01d3\u01d2\3\2\2\2\u01d3\u01d4\3\2\2\2\u01d4\u01d5\3\2\2\2\u01d5\u01de"+ + "\7\b\2\2\u01d6\u01d7\f\33\2\2\u01d7\u01d8\7!\2\2\u01d8\u01d9\5\62\32\2"+ + "\u01d9\u01da\7\"\2\2\u01da\u01de\3\2\2\2\u01db\u01dc\f\30\2\2\u01dc\u01de"+ + "\t\3\2\2\u01dd\u01a9\3\2\2\2\u01dd\u01ac\3\2\2\2\u01dd\u01af\3\2\2\2\u01dd"+ + "\u01b2\3\2\2\2\u01dd\u01b5\3\2\2\2\u01dd\u01b8\3\2\2\2\u01dd\u01bb\3\2"+ + "\2\2\u01dd\u01be\3\2\2\2\u01dd\u01c1\3\2\2\2\u01dd\u01c4\3\2\2\2\u01dd"+ + "\u01ca\3\2\2\2\u01dd\u01cd\3\2\2\2\u01dd\u01d0\3\2\2\2\u01dd\u01d6\3\2"+ + "\2\2\u01dd\u01db\3\2\2\2\u01de\u01e1\3\2\2\2\u01df\u01dd\3\2\2\2\u01df"+ + "\u01e0\3\2\2\2\u01e0\65\3\2\2\2\u01e1\u01df\3\2\2\2\u01e2\u01e7\5\64\33"+ + "\2\u01e3\u01e4\7\5\2\2\u01e4\u01e6\5\64\33\2\u01e5\u01e3\3\2\2\2\u01e6"+ + "\u01e9\3\2\2\2\u01e7\u01e5\3\2\2\2\u01e7\u01e8\3\2\2\2\u01e8\67\3\2\2"+ + "\2\u01e9\u01e7\3\2\2\2\u01ea\u01ec\7F\2\2\u01eb\u01ed\5:\36\2\u01ec\u01eb"+ + "\3\2\2\2\u01ec\u01ed\3\2\2\2\u01ed\u01ee\3\2\2\2\u01ee\u01ef\7Q\2\2\u01ef"+ + "9\3\2\2\2\u01f0\u01f1\7\7\2\2\u01f1\u01f6\5<\37\2\u01f2\u01f3\7\5\2\2"+ + "\u01f3\u01f5\5<\37\2\u01f4\u01f2\3\2\2\2\u01f5\u01f8\3\2\2\2\u01f6\u01f4"+ + "\3\2\2\2\u01f6\u01f7\3\2\2\2\u01f7\u01f9\3\2\2\2\u01f8\u01f6\3\2\2\2\u01f9"+ + "\u01fa\7\b\2\2\u01fa;\3\2\2\2\u01fb\u01fc\7G\2\2\u01fc\u020b\7S\2\2\u01fd"+ + "\u01fe\7H\2\2\u01fe\u020b\7_\2\2\u01ff\u0200\7I\2\2\u0200\u020b\7S\2\2"+ + "\u0201\u0202\7J\2\2\u0202\u020b\5\64\33\2\u0203\u0204\7K\2\2\u0204\u020b"+ + "\5\64\33\2\u0205\u0208\7L\2\2\u0206\u0209\7\17\2\2\u0207\u0209\5\64\33"+ + "\2\u0208\u0206\3\2\2\2\u0208\u0207\3\2\2\2\u0209\u020b\3\2\2\2\u020a\u01fb"+ + "\3\2\2\2\u020a\u01fd\3\2\2\2\u020a\u01ff\3\2\2\2\u020a\u0201\3\2\2\2\u020a"+ + "\u0203\3\2\2\2\u020a\u0205\3\2\2\2\u020b=\3\2\2\2\u020c\u020e\5@!\2\u020d"+ + "\u020c\3\2\2\2\u020e\u0211\3\2\2\2\u020f\u020d\3\2\2\2\u020f\u0210\3\2"+ + "\2\2\u0210?\3\2\2\2\u0211\u020f\3\2\2\2\u0212\u0216\5B\"\2\u0213\u0216"+ + "\5D#\2\u0214\u0216\5F$\2\u0215\u0212\3\2\2\2\u0215\u0213\3\2\2\2\u0215"+ + "\u0214\3\2\2\2\u0216A\3\2\2\2\u0217\u0218\7_\2\2\u0218\u021f\7\34\2\2"+ + "\u0219\u021b\7*\2\2\u021a\u021c\7_\2\2\u021b\u021a\3\2\2\2\u021b\u021c"+ + "\3\2\2\2\u021c\u021d\3\2\2\2\u021d\u021f\7\34\2\2\u021e\u0217\3\2\2\2"+ + "\u021e\u0219\3\2\2\2\u021fC\3\2\2\2\u0220\u0222\7P\2\2\u0221\u0223\5H"+ + "%\2\u0222\u0221\3\2\2\2\u0222\u0223\3\2\2\2\u0223E\3\2\2\2\u0224\u0225"+ + "\7M\2\2\u0225\u022a\5J&\2\u0226\u0227\7\5\2\2\u0227\u0229\5J&\2\u0228"+ + "\u0226\3\2\2\2\u0229\u022c\3\2\2\2\u022a\u0228\3\2\2\2\u022a\u022b\3\2"+ + "\2\2\u022bG\3\2\2\2\u022c\u022a\3\2\2\2\u022d\u0245\5J&\2\u022e\u022f"+ + "\7N\2\2\u022f\u0245\5J&\2\u0230\u0231\5J&\2\u0231\u0232\7\5\2\2\u0232"+ + "\u0233\7_\2\2\u0233\u0245\3\2\2\2\u0234\u0235\7\7\2\2\u0235\u0236\5J&"+ + "\2\u0236\u0237\7\b\2\2\u0237\u0238\7\5\2\2\u0238\u0239\7_\2\2\u0239\u0245"+ + "\3\2\2\2\u023a\u023b\7\7\2\2\u023b\u023c\5J&\2\u023c\u023d\7\5\2\2\u023d"+ + "\u023e\7_\2\2\u023e\u023f\7\b\2\2\u023f\u0245\3\2\2\2\u0240\u0241\7\7"+ + "\2\2\u0241\u0242\5J&\2\u0242\u0243\7\b\2\2\u0243\u0245\3\2\2\2\u0244\u022d"+ + "\3\2\2\2\u0244\u022e\3\2\2\2\u0244\u0230\3\2\2\2\u0244\u0234\3\2\2\2\u0244"+ + "\u023a\3\2\2\2\u0244\u0240\3\2\2\2\u0245I\3\2\2\2\u0246\u0247\b&\1\2\u0247"+ + "\u0248\7!\2\2\u0248\u0249\5J&\2\u0249\u024a\7\"\2\2\u024a\u0255\3\2\2"+ + "\2\u024b\u024c\t\13\2\2\u024c\u0255\5J&\n\u024d\u0255\7_\2\2\u024e\u0255"+ + "\7`\2\2\u024f\u0250\7\t\2\2\u0250\u0251\7_\2\2\u0251\u0255\7\n\2\2\u0252"+ + "\u0255\7V\2\2\u0253\u0255\7T\2\2\u0254\u0246\3\2\2\2\u0254\u024b\3\2\2"+ + "\2\u0254\u024d\3\2\2\2\u0254\u024e\3\2\2\2\u0254\u024f\3\2\2\2\u0254\u0252"+ + "\3\2\2\2\u0254\u0253\3\2\2\2\u0255\u0264\3\2\2\2\u0256\u0257\f\f\2\2\u0257"+ + "\u0258\7O\2\2\u0258\u0263\5J&\r\u0259\u025a\f\13\2\2\u025a\u025b\t\6\2"+ + "\2\u025b\u0263\5J&\f\u025c\u025d\f\t\2\2\u025d\u025e\t\f\2\2\u025e\u0263"+ + "\5J&\n\u025f\u0260\f\b\2\2\u0260\u0261\t\b\2\2\u0261\u0263\5J&\t\u0262"+ + "\u0256\3\2\2\2\u0262\u0259\3\2\2\2\u0262\u025c\3\2\2\2\u0262\u025f\3\2"+ + "\2\2\u0263\u0266\3\2\2\2\u0264\u0262\3\2\2\2\u0264\u0265\3\2\2\2\u0265"+ + "K\3\2\2\2\u0266\u0264\3\2\2\2=V_jov\u0084\u008a\u0090\u0095\u009e\u00a5"+ + "\u00ba\u00bd\u00c6\u00ce\u00d5\u00e2\u00e7\u00f3\u0101\u010c\u0115\u011c"+ + "\u0123\u0126\u012e\u0131\u0134\u013e\u0142\u0149\u014f\u0151\u0159\u015f"+ + "\u016e\u017a\u0182\u0199\u01a3\u01a7\u01d3\u01dd\u01df\u01e7\u01ec\u01f6"+ + "\u0208\u020a\u020f\u0215\u021b\u021e\u0222\u022a\u0244\u0254\u0262\u0264"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java index 98035b89e..edb044629 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java @@ -310,6 +310,13 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> { * @return the visitor result */ T visitTypeArray(KickCParser.TypeArrayContext ctx); + /** + * Visit a parse tree produced by the {@code typeStructRef} + * labeled alternative in {@link KickCParser#typeDecl}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTypeStructRef(KickCParser.TypeStructRefContext ctx); /** * Visit a parse tree produced by the {@code typeSimple} * labeled alternative in {@link KickCParser#typeDecl}. @@ -317,6 +324,13 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> { * @return the visitor result */ T visitTypeSimple(KickCParser.TypeSimpleContext ctx); + /** + * Visit a parse tree produced by the {@code typeStructDef} + * labeled alternative in {@link KickCParser#typeDecl}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTypeStructDef(KickCParser.TypeStructDefContext ctx); /** * Visit a parse tree produced by the {@code typeSignedSimple} * labeled alternative in {@link KickCParser#typeDecl}. @@ -324,6 +338,24 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> { * @return the visitor result */ T visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx); + /** + * Visit a parse tree produced by {@link KickCParser#structRef}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitStructRef(KickCParser.StructRefContext ctx); + /** + * Visit a parse tree produced by {@link KickCParser#structDef}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitStructDef(KickCParser.StructDefContext ctx); + /** + * Visit a parse tree produced by {@link KickCParser#structMembers}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitStructMembers(KickCParser.StructMembersContext ctx); /** * Visit a parse tree produced by the {@code commaNone} * labeled alternative in {@link KickCParser#commaExpr}. From 30d6878ade5d5739ec9fd150b9a1c66c52b414a1 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Mon, 27 May 2019 08:39:59 +0200 Subject: [PATCH 89/93] Minimalistic struct example working with several shortcuts in the code. --- .../fragment/_deref_pbuc1=vssz1_mbr_0.asm | 2 + .../fragment/_deref_pbuc1=vssz1_mbr_1.asm | 2 + src/main/fragment/vssz1=vssf2.asm | 3 + src/main/fragment/vssz1_mbr_0=vbuc1.asm | 2 + src/main/fragment/vssz1_mbr_1=vbuc1.asm | 2 + .../AsmFragmentInstanceSpecFactory.java | 30 +- .../dk/camelot64/kickc/model/Registers.java | 14 + .../kickc/model/iterator/ProgramValue.java | 22 + .../model/iterator/ProgramValueIterator.java | 3 + .../camelot64/kickc/model/symbols/Scope.java | 43 +- .../kickc/model/symbols/StructDefinition.java | 25 + .../model/types/SymbolTypeInference.java | 17 + .../kickc/model/types/SymbolTypePointer.java | 4 +- .../kickc/model/types/SymbolTypeStruct.java | 60 ++ .../kickc/model/values/StructMemberRef.java | 45 + .../kickc/model/values/StructZero.java | 25 + .../java/dk/camelot64/kickc/parser/KickC.g4 | 2 + .../dk/camelot64/kickc/parser/KickC.tokens | 130 +-- .../kickc/parser/KickCBaseListener.java | 24 + .../kickc/parser/KickCBaseVisitor.java | 14 + .../dk/camelot64/kickc/parser/KickCLexer.java | 723 ++++++------- .../camelot64/kickc/parser/KickCLexer.tokens | 130 +-- .../camelot64/kickc/parser/KickCListener.java | 24 + .../camelot64/kickc/parser/KickCParser.java | 975 ++++++++++-------- .../camelot64/kickc/parser/KickCVisitor.java | 14 + .../Pass0GenerateStatementSequence.java | 42 + .../kickc/passes/Pass2AssertSymbols.java | 2 + .../kickc/passes/Pass4RegistersFinalize.java | 5 + .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/struct-0.kc | 14 + src/test/ref/struct-0.asm | 23 + 31 files changed, 1455 insertions(+), 971 deletions(-) create mode 100644 src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm create mode 100644 src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm create mode 100644 src/main/fragment/vssz1=vssf2.asm create mode 100644 src/main/fragment/vssz1_mbr_0=vbuc1.asm create mode 100644 src/main/fragment/vssz1_mbr_1=vbuc1.asm create mode 100644 src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java create mode 100644 src/main/java/dk/camelot64/kickc/model/values/StructMemberRef.java create mode 100644 src/main/java/dk/camelot64/kickc/model/values/StructZero.java create mode 100644 src/test/kc/struct-0.kc create mode 100644 src/test/ref/struct-0.asm diff --git a/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm b/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm new file mode 100644 index 000000000..f235c1aee --- /dev/null +++ b/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm @@ -0,0 +1,2 @@ +lda {z1}+0 +sta {c1} \ No newline at end of file diff --git a/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm b/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm new file mode 100644 index 000000000..59a255b43 --- /dev/null +++ b/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm @@ -0,0 +1,2 @@ +lda {z1}+1 +sta {c1} \ No newline at end of file diff --git a/src/main/fragment/vssz1=vssf2.asm b/src/main/fragment/vssz1=vssf2.asm new file mode 100644 index 000000000..5a5c14b91 --- /dev/null +++ b/src/main/fragment/vssz1=vssf2.asm @@ -0,0 +1,3 @@ +lda #0 +sta {z1} +sta {z1}+1 \ No newline at end of file diff --git a/src/main/fragment/vssz1_mbr_0=vbuc1.asm b/src/main/fragment/vssz1_mbr_0=vbuc1.asm new file mode 100644 index 000000000..cdbf628d1 --- /dev/null +++ b/src/main/fragment/vssz1_mbr_0=vbuc1.asm @@ -0,0 +1,2 @@ +lda #{c1} +sta {z1}+0 \ No newline at end of file diff --git a/src/main/fragment/vssz1_mbr_1=vbuc1.asm b/src/main/fragment/vssz1_mbr_1=vbuc1.asm new file mode 100644 index 000000000..540828c77 --- /dev/null +++ b/src/main/fragment/vssz1_mbr_1=vbuc1.asm @@ -0,0 +1,2 @@ +lda #{c1} +sta {z1}+1 \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java index f3e3624c4..760674038 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java @@ -7,10 +7,7 @@ import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementConditionalJump; -import dk.camelot64.kickc.model.symbols.ConstantVar; -import dk.camelot64.kickc.model.symbols.Label; -import dk.camelot64.kickc.model.symbols.Symbol; -import dk.camelot64.kickc.model.symbols.Variable; +import dk.camelot64.kickc.model.symbols.*; import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.*; @@ -306,6 +303,26 @@ public class AsmFragmentInstanceSpecFactory { String name = "la" + nextLabelIdx++; bind(name, value); return name; + } else if(value instanceof StructZero) { + return "vssf"+((StructZero) value).getTypeStruct().getSizeBytes(); + } else if(value instanceof StructMemberRef) { + StructMemberRef structMemberRef = (StructMemberRef) value; + RValue struct = structMemberRef.getStruct(); + String memberName = structMemberRef.getMemberName(); + SymbolType symbolType = SymbolTypeInference.inferType(program.getScope(), struct); + byte idx = 0; + if(symbolType instanceof SymbolTypeStruct) { + String structTypeName = ((SymbolTypeStruct) symbolType).getStructTypeName(); + StructDefinition structDefinition = program.getScope().getStructDefinition(structTypeName); + for(Variable structMember : structDefinition.getAllVariables(false)) { + if(structMember.getLocalName().equals(memberName)) { + break; + } else { + idx += structMember.getType().getSizeBytes(); + } + } + } + return bind(struct)+"_mbr_"+ idx; } throw new RuntimeException("Binding of value type not supported " + value); } @@ -343,6 +360,8 @@ public class AsmFragmentInstanceSpecFactory { return "pbu"; } else if(SymbolType.BOOLEAN.equals(type)) { return "vbo"; + } else if(type instanceof SymbolTypeStruct) { + return "vss"; } else if(type instanceof SymbolTypePointer) { SymbolType elementType = ((SymbolTypePointer) type).getElementType(); if(SymbolType.BYTE.equals(elementType)) { @@ -383,7 +402,8 @@ public class AsmFragmentInstanceSpecFactory { Registers.RegisterType.ZP_BOOL.equals(register.getType()) || Registers.RegisterType.ZP_BYTE.equals(register.getType()) || Registers.RegisterType.ZP_WORD.equals(register.getType()) || - Registers.RegisterType.ZP_DWORD.equals(register.getType()) + Registers.RegisterType.ZP_DWORD.equals(register.getType()) || + Registers.RegisterType.ZP_STRUCT.equals(register.getType()) ) { // Examine if the ZP register is already bound Registers.RegisterZp registerZp = (Registers.RegisterZp) register; diff --git a/src/main/java/dk/camelot64/kickc/model/Registers.java b/src/main/java/dk/camelot64/kickc/model/Registers.java index b889d62bd..7e2075931 100644 --- a/src/main/java/dk/camelot64/kickc/model/Registers.java +++ b/src/main/java/dk/camelot64/kickc/model/Registers.java @@ -45,6 +45,7 @@ public class Registers { ZP_BYTE, ZP_WORD, ZP_DWORD, + ZP_STRUCT, ZP_BOOL, CONSTANT } @@ -150,6 +151,19 @@ public class Registers { } + /** Zero page addresses used as a register for a struct variable. */ + public static class RegisterZpStruct extends RegisterZp { + + public RegisterZpStruct(int zp) { + super(zp); + } + + @Override + public RegisterType getType() { + return RegisterType.ZP_STRUCT; + } + + } /** A zero page address used as a register for a boolean variable. */ public static class RegisterZpBool extends RegisterZp { diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java index 0477f39ef..c6d75927a 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java @@ -748,6 +748,28 @@ public interface ProgramValue { } + /** + * Struct expression inside a struct member reference. + */ + class ProgramValueStruct implements ProgramValue { + private final StructMemberRef structMemberRef; + + public ProgramValueStruct(StructMemberRef structMemberRef) { + this.structMemberRef = structMemberRef; + } + + @Override + public Value get() { + return structMemberRef.getStruct(); + } + + @Override + public void set(Value val) { + structMemberRef.setStruct((RValue) val); + } + + } + /** * Pointer index inside a indexed pointer dererence value. */ diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java index 6fe274204..a1984c1a8 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java @@ -186,6 +186,8 @@ public class ProgramValueIterator { subValues.add(new ProgramValue.ProgramValuePointerIndex((PointerDereferenceIndexed) value)); } else if(value instanceof PointerDereferenceSimple) { subValues.add(new ProgramValue.ProgramValuePointer((PointerDereference) value)); + } else if(value instanceof StructMemberRef) { + subValues.add(new ProgramValue.ProgramValueStruct((StructMemberRef) value)); } else if(value instanceof ValueList) { ValueList valueList = (ValueList) value; int size = valueList.getList().size(); @@ -223,6 +225,7 @@ public class ProgramValueIterator { value instanceof ProcedureRef || value instanceof ConstantLiteral || value instanceof ConstantRef || + value instanceof StructZero || value instanceof LabelRef ) { // No sub values diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java index 3070e188f..d7d55166b 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java @@ -82,7 +82,7 @@ public abstract class Scope implements Symbol { } } - public Symbol add(Symbol symbol) { + public <T extends Symbol> T add(T symbol) { if(symbols.get(symbol.getLocalName()) != null) { throw new CompileError("Symbol already declared " + symbol.getLocalName()); } @@ -95,16 +95,12 @@ public abstract class Scope implements Symbol { } public VariableUnversioned addVariable(String name, SymbolType type) { - VariableUnversioned symbol = new VariableUnversioned(name, this, type); - add(symbol); - return symbol; + return add(new VariableUnversioned(name, this, type)); } public VariableIntermediate addVariableIntermediate() { String name = allocateIntermediateVariableName(); - VariableIntermediate symbol = new VariableIntermediate(name, this, SymbolType.VAR); - add(symbol); - return symbol; + return add(new VariableIntermediate(name, this, SymbolType.VAR)); } /** @@ -254,16 +250,12 @@ public abstract class Scope implements Symbol { public Label addLabel(String name) { - Label symbol = new Label(name, this, false); - add(symbol); - return symbol; + return add(new Label(name, this, false)); } public Label addLabelIntermediate() { String name = "@" + intermediateLabelCount++; - Label symbol = new Label(name, this, true); - add(symbol); - return symbol; + return add(new Label(name, this, true)); } public Label getLabel(String name) { @@ -276,9 +268,7 @@ public abstract class Scope implements Symbol { public BlockScope addBlockScope() { String name = ":" + blockCount++; - BlockScope blockScope = new BlockScope(name, this); - add(blockScope); - return blockScope; + return add(new BlockScope(name, this)); } public BlockScope getBlockScope(String name) { @@ -286,13 +276,7 @@ public abstract class Scope implements Symbol { } public Procedure addProcedure(String name, SymbolType type) { - Symbol symbol = symbols.get(name); - if(symbol != null) { - throw new RuntimeException("Error! Symbol already defined " + symbol); - } - Procedure procedure = new Procedure(name, type, this); - add(procedure); - return procedure; + return add(new Procedure(name, type, this)); } public Procedure getProcedure(String name) { @@ -304,6 +288,19 @@ public abstract class Scope implements Symbol { } } + /** + * Add a struct definition. + * The name can be either defined in the program or an intermediate name. + * @param name + */ + public StructDefinition addStructDefinition(String name) { + return add(new StructDefinition(name, this)); + } + + public StructDefinition getStructDefinition(String name) { + return (StructDefinition) getSymbol(name); + } + public Scope getScope(ScopeRef scopeRef) { if(scopeRef.getFullName().equals("") && this instanceof ProgramScope) { // Special case for the outer program scope diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java b/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java new file mode 100644 index 000000000..165980096 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java @@ -0,0 +1,25 @@ +package dk.camelot64.kickc.model.symbols; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeStruct; + +/** + * A struct definition containing a set of variables. + */ +public class StructDefinition extends Scope { + + public StructDefinition(String name, Scope parentScope) { + super(name, parentScope); + } + + @Override + public SymbolType getType() { + return new SymbolTypeStruct(this); + } + + @Override + public String toString(Program program) { + return "block-"+getFullName(); + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index c2875ef15..3506dfadd 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -1,6 +1,8 @@ package dk.camelot64.kickc.model.types; +import dk.camelot64.kickc.fragment.AsmFragmentInstanceSpec; import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.operators.OperatorBinary; import dk.camelot64.kickc.model.operators.OperatorUnary; import dk.camelot64.kickc.model.statements.StatementAssignment; @@ -98,6 +100,21 @@ public class SymbolTypeInference { throw new CompileError("Cannot infer type of " + assignment.toString()); } return rValueType; + } else if(rValue instanceof StructMemberRef) { + StructMemberRef structMemberRef = (StructMemberRef) rValue; + SymbolType structType = inferType(symbols, structMemberRef.getStruct()); + if(structType instanceof SymbolTypeStruct) { + String typeName = ((SymbolTypeStruct) structType).getStructTypeName(); + StructDefinition structDefinition = symbols.getStructDefinition(typeName); + Variable structMember = structDefinition.getVariable(structMemberRef.getMemberName()); + return structMember.getType(); + } else { + AsmFragmentInstanceSpec asmFragmentInstanceSpec = null; + Program program = asmFragmentInstanceSpec.getProgram(); + throw new CompileError("Dot applied to non-struct "+ structMemberRef.getStruct().toString(program)); + } + } else if(rValue instanceof StructZero) { + return ((StructZero)rValue).getTypeStruct(); } if(type == null) { throw new RuntimeException("Cannot infer type for " + rValue.toString()); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java index 451b04e87..b9bedcb87 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java @@ -4,7 +4,7 @@ package dk.camelot64.kickc.model.types; public class SymbolTypePointer implements SymbolType { /** The number of bytes needed to represent a pointer in memory. */ - public static final int SIZE_BYTES = 2; + public static final int SIZE_POINTER_BYTES = 2; private SymbolType elementType; @@ -28,7 +28,7 @@ public class SymbolTypePointer implements SymbolType { @Override public int getSizeBytes() { - return SIZE_BYTES; + return SIZE_POINTER_BYTES; } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java new file mode 100644 index 000000000..558f73708 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java @@ -0,0 +1,60 @@ +package dk.camelot64.kickc.model.types; + +import dk.camelot64.kickc.model.symbols.StructDefinition; +import dk.camelot64.kickc.model.symbols.Variable; + +import java.util.Objects; + +/** A struct */ +public class SymbolTypeStruct implements SymbolType { + + /** Name of the struct type. */ + private String name; + + /** Size of the struct in bytes. */ + private int sizeBytes; + + public SymbolTypeStruct(StructDefinition structDefinition) { + this.name = structDefinition.getLocalName(); + int sizeBytes = 0; + for(Variable member : structDefinition.getAllVariables(false)) { + sizeBytes += member.getType().getSizeBytes(); + } + this.sizeBytes = sizeBytes; + } + + @Override + public String getTypeName() { + return "struct " + name; + } + + public String getStructTypeName() { + return name; + } + + @Override + public int getSizeBytes() { + return sizeBytes; + } + + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + SymbolTypeStruct that = (SymbolTypeStruct) o; + return sizeBytes == that.sizeBytes && + Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + + return Objects.hash(name, sizeBytes); + } + + @Override + public String toString() { + return getTypeName(); + } + +} diff --git a/src/main/java/dk/camelot64/kickc/model/values/StructMemberRef.java b/src/main/java/dk/camelot64/kickc/model/values/StructMemberRef.java new file mode 100644 index 000000000..a171bf582 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/values/StructMemberRef.java @@ -0,0 +1,45 @@ +package dk.camelot64.kickc.model.values; + +import dk.camelot64.kickc.model.Program; + +/** A reference to a struct member */ +public class StructMemberRef implements LValue { + + /** Expression evaluating to a struct. */ + private RValue struct; + + /** Name of the referenced member. */ + private String memberName; + + public StructMemberRef(RValue struct, String memberName) { + this.struct = struct; + this.memberName = memberName; + } + + public RValue getStruct() { + return struct; + } + + public void setStruct(RValue struct) { + this.struct = struct; + } + + public String getMemberName() { + return memberName; + } + + public void setMemberName(String memberName) { + this.memberName = memberName; + } + + @Override + public String toString() { + return toString(null); + } + + @Override + public String toString(Program program) { + return struct.toString(program) + "." + memberName ; + } + +} diff --git a/src/main/java/dk/camelot64/kickc/model/values/StructZero.java b/src/main/java/dk/camelot64/kickc/model/values/StructZero.java new file mode 100644 index 000000000..9d6798d6e --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/values/StructZero.java @@ -0,0 +1,25 @@ +package dk.camelot64.kickc.model.values; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.types.SymbolTypeStruct; + +/** + * An zero-filled struct. + */ +public class StructZero implements RValue { + + private SymbolTypeStruct typeStruct; + + public StructZero(SymbolTypeStruct typeStruct) { + this.typeStruct = typeStruct; + } + + public SymbolTypeStruct getTypeStruct() { + return typeStruct; + } + + @Override + public String toString(Program program) { + return "{}"; + } +} diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 index 117fd6732..a604ccb24 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 +++ b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 @@ -136,6 +136,8 @@ commaExpr expr : '(' commaExpr ')' #exprPar + | expr '.' NAME #exprDot + | expr '->' NAME #exprArrow | expr '(' parameterList? ')' #exprCall | 'sizeof' '(' ( typeDecl | expr ) ')' #exprSizeOf | 'typeid' '(' ( typeDecl | expr ) ')' #exprTypeId diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.tokens b/src/main/java/dk/camelot64/kickc/parser/KickC.tokens index a303b96fe..42dfa728a 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickC.tokens +++ b/src/main/java/dk/camelot64/kickc/parser/KickC.tokens @@ -75,26 +75,27 @@ T__73=74 T__74=75 T__75=76 T__76=77 -MNEMONIC=78 -KICKASM=79 -SIMPLETYPE=80 -STRING=81 -CHAR=82 -BOOLEAN=83 -NUMBER=84 -NUMFLOAT=85 -BINFLOAT=86 -DECFLOAT=87 -HEXFLOAT=88 -NUMINT=89 -BININTEGER=90 -DECINTEGER=91 -HEXINTEGER=92 -NAME=93 -ASMREL=94 -WS=95 -COMMENT_LINE=96 -COMMENT_BLOCK=97 +T__77=78 +MNEMONIC=79 +KICKASM=80 +SIMPLETYPE=81 +STRING=82 +CHAR=83 +BOOLEAN=84 +NUMBER=85 +NUMFLOAT=86 +BINFLOAT=87 +DECFLOAT=88 +HEXFLOAT=89 +NUMINT=90 +BININTEGER=91 +DECINTEGER=92 +HEXINTEGER=93 +NAME=94 +ASMREL=95 +WS=96 +COMMENT_LINE=97 +COMMENT_BLOCK=98 'import'=1 ';'=2 ','=3 @@ -128,47 +129,48 @@ COMMENT_BLOCK=97 '['=31 ']'=32 'struct'=33 -'sizeof'=34 -'typeid'=35 -'--'=36 -'++'=37 -'+'=38 -'-'=39 -'!'=40 -'&'=41 -'~'=42 -'>>'=43 -'<<'=44 -'/'=45 -'%'=46 -'<'=47 -'>'=48 -'=='=49 -'!='=50 -'<='=51 -'>='=52 -'^'=53 -'|'=54 -'&&'=55 -'||'=56 -'?'=57 -'+='=58 -'-='=59 -'*='=60 -'/='=61 -'%='=62 -'<<='=63 -'>>='=64 -'&='=65 -'|='=66 -'^='=67 -'kickasm'=68 -'resource'=69 -'uses'=70 -'clobbers'=71 -'bytes'=72 -'cycles'=73 -'pc'=74 -'.byte'=75 -'#'=76 -'.'=77 +'.'=34 +'->'=35 +'sizeof'=36 +'typeid'=37 +'--'=38 +'++'=39 +'+'=40 +'-'=41 +'!'=42 +'&'=43 +'~'=44 +'>>'=45 +'<<'=46 +'/'=47 +'%'=48 +'<'=49 +'>'=50 +'=='=51 +'!='=52 +'<='=53 +'>='=54 +'^'=55 +'|'=56 +'&&'=57 +'||'=58 +'?'=59 +'+='=60 +'-='=61 +'*='=62 +'/='=63 +'%='=64 +'<<='=65 +'>>='=66 +'&='=67 +'|='=68 +'^='=69 +'kickasm'=70 +'resource'=71 +'uses'=72 +'clobbers'=73 +'bytes'=74 +'cycles'=75 +'pc'=76 +'.byte'=77 +'#'=78 diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java index b8a02352a..ba4d3501e 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java @@ -755,6 +755,30 @@ public class KickCBaseListener implements KickCListener { * <p>The default implementation does nothing.</p> */ @Override public void exitExprChar(KickCParser.ExprCharContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void enterExprArrow(KickCParser.ExprArrowContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void exitExprArrow(KickCParser.ExprArrowContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void enterExprDot(KickCParser.ExprDotContext ctx) { } + /** + * {@inheritDoc} + * + * <p>The default implementation does nothing.</p> + */ + @Override public void exitExprDot(KickCParser.ExprDotContext ctx) { } /** * {@inheritDoc} * diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java index 2cba0e61e..111fc9a36 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java @@ -445,6 +445,20 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements * {@link #visitChildren} on {@code ctx}.</p> */ @Override public T visitExprChar(KickCParser.ExprCharContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + * <p>The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.</p> + */ + @Override public T visitExprArrow(KickCParser.ExprArrowContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + * <p>The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.</p> + */ + @Override public T visitExprDot(KickCParser.ExprDotContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java index 594b24209..c8c2c2b66 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java @@ -27,10 +27,10 @@ public class KickCLexer extends Lexer { T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, - T__73=74, T__74=75, T__75=76, T__76=77, MNEMONIC=78, KICKASM=79, SIMPLETYPE=80, - STRING=81, CHAR=82, BOOLEAN=83, NUMBER=84, NUMFLOAT=85, BINFLOAT=86, DECFLOAT=87, - HEXFLOAT=88, NUMINT=89, BININTEGER=90, DECINTEGER=91, HEXINTEGER=92, NAME=93, - ASMREL=94, WS=95, COMMENT_LINE=96, COMMENT_BLOCK=97; + T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, MNEMONIC=79, KICKASM=80, + SIMPLETYPE=81, STRING=82, CHAR=83, BOOLEAN=84, NUMBER=85, NUMFLOAT=86, + BINFLOAT=87, DECFLOAT=88, HEXFLOAT=89, NUMINT=90, BININTEGER=91, DECINTEGER=92, + HEXINTEGER=93, NAME=94, ASMREL=95, WS=96, COMMENT_LINE=97, COMMENT_BLOCK=98; public static String[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -49,7 +49,7 @@ public class KickCLexer extends Lexer { "T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56", "T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64", "T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "T__71", "T__72", - "T__73", "T__74", "T__75", "T__76", "MNEMONIC", "KICKASM", "SIMPLETYPE", + "T__73", "T__74", "T__75", "T__76", "T__77", "MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "BINDIGIT", "DECDIGIT", "HEXDIGIT", "NAME", "NAME_START", "NAME_CHAR", "ASMREL", "WS", @@ -61,12 +61,12 @@ public class KickCLexer extends Lexer { "'extern'", "'align'", "'register'", "'inline'", "'volatile'", "'interrupt'", "'reserve'", "'if'", "'else'", "'while'", "'do'", "'for'", "'return'", "'break'", "'continue'", "'asm'", "':'", "'..'", "'signed'", "'unsigned'", - "'*'", "'['", "']'", "'struct'", "'sizeof'", "'typeid'", "'--'", "'++'", - "'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", - "'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", - "'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", - "'^='", "'kickasm'", "'resource'", "'uses'", "'clobbers'", "'bytes'", - "'cycles'", "'pc'", "'.byte'", "'#'", "'.'" + "'*'", "'['", "']'", "'struct'", "'.'", "'->'", "'sizeof'", "'typeid'", + "'--'", "'++'", "'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", + "'%'", "'<'", "'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", + "'||'", "'?'", "'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", + "'&='", "'|='", "'^='", "'kickasm'", "'resource'", "'uses'", "'clobbers'", + "'bytes'", "'cycles'", "'pc'", "'.byte'", "'#'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null, null, @@ -75,7 +75,7 @@ public class KickCLexer extends Lexer { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", + null, null, null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK" @@ -138,7 +138,7 @@ public class KickCLexer extends Lexer { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2c\u03e5\b\1\4\2\t"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2d\u03ea\b\1\4\2\t"+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -149,354 +149,355 @@ public class KickCLexer extends Lexer { "\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+ "\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+ "\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+ - "`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\3\2\3\2\3\2\3\2\3\2\3\2"+ - "\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3"+ - "\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f"+ - "\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16"+ - "\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20"+ - "\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+ - "\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24"+ - "\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27"+ - "\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31"+ - "\3\31\3\32\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\35"+ - "\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37"+ - "\3 \3 \3!\3!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3#\3#\3#\3#\3#\3#\3#\3$\3$\3"+ - "$\3$\3$\3$\3$\3%\3%\3%\3&\3&\3&\3\'\3\'\3(\3(\3)\3)\3*\3*\3+\3+\3,\3,"+ - "\3,\3-\3-\3-\3.\3.\3/\3/\3\60\3\60\3\61\3\61\3\62\3\62\3\62\3\63\3\63"+ - "\3\63\3\64\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\67\3\67\38\38\38\39\3"+ - "9\39\3:\3:\3;\3;\3;\3<\3<\3<\3=\3=\3=\3>\3>\3>\3?\3?\3?\3@\3@\3@\3@\3"+ - "A\3A\3A\3A\3B\3B\3B\3C\3C\3C\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3E\3F\3F\3"+ - "F\3F\3F\3F\3F\3F\3F\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3H\3H\3H\3I\3I\3"+ - "I\3I\3I\3I\3J\3J\3J\3J\3J\3J\3J\3K\3K\3K\3L\3L\3L\3L\3L\3L\3M\3M\3N\3"+ - "N\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\5O\u02ef\nO\3P\3P\3P\3"+ - "P\7P\u02f5\nP\fP\16P\u02f8\13P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q"+ - "\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q"+ - "\3Q\3Q\3Q\3Q\5Q\u0322\nQ\3R\3R\3R\3R\7R\u0328\nR\fR\16R\u032b\13R\3R\3"+ - "R\5R\u032f\nR\3S\3S\3S\3S\5S\u0335\nS\3S\3S\3T\3T\3T\3T\3T\3T\3T\3T\3"+ - "T\5T\u0342\nT\3U\3U\5U\u0346\nU\3V\3V\3V\5V\u034b\nV\3W\3W\3W\3W\3W\5"+ - "W\u0352\nW\3W\7W\u0355\nW\fW\16W\u0358\13W\3W\3W\6W\u035c\nW\rW\16W\u035d"+ - "\3X\7X\u0361\nX\fX\16X\u0364\13X\3X\3X\6X\u0368\nX\rX\16X\u0369\3Y\3Y"+ - "\3Y\3Y\3Y\5Y\u0371\nY\3Y\7Y\u0374\nY\fY\16Y\u0377\13Y\3Y\3Y\6Y\u037b\n"+ - "Y\rY\16Y\u037c\3Z\3Z\3Z\5Z\u0382\nZ\3Z\3Z\3Z\5Z\u0387\nZ\3[\3[\3[\6[\u038c"+ - "\n[\r[\16[\u038d\3[\3[\6[\u0392\n[\r[\16[\u0393\5[\u0396\n[\3\\\6\\\u0399"+ - "\n\\\r\\\16\\\u039a\3]\3]\3]\3]\3]\5]\u03a2\n]\3]\6]\u03a5\n]\r]\16]\u03a6"+ - "\3^\3^\3_\3_\3`\3`\3a\3a\7a\u03b1\na\fa\16a\u03b4\13a\3b\3b\3c\3c\3d\3"+ - "d\7d\u03bc\nd\fd\16d\u03bf\13d\3d\6d\u03c2\nd\rd\16d\u03c3\3e\6e\u03c7"+ - "\ne\re\16e\u03c8\3e\3e\3f\3f\3f\3f\7f\u03d1\nf\ff\16f\u03d4\13f\3f\3f"+ - "\3g\3g\3g\3g\7g\u03dc\ng\fg\16g\u03df\13g\3g\3g\3g\3g\3g\4\u02f6\u03dd"+ - "\2h\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35"+ - "\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36"+ - ";\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67"+ - "m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008d"+ - "H\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1"+ - "R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5"+ - "\\\u00b7]\u00b9^\u00bb\2\u00bd\2\u00bf\2\u00c1_\u00c3\2\u00c5\2\u00c7"+ - "`\u00c9a\u00cbb\u00cdc\3\2\17\3\2$$\3\2))\4\2uuww\7\2dfkknnuuyy\4\2DD"+ - "dd\3\2\62\63\3\2\62;\5\2\62;CHch\5\2C\\aac|\6\2\62;C\\aac|\4\2--//\6\2"+ - "\13\f\17\17\"\"\u00a2\u00a2\4\2\f\f\17\17\2\u0454\2\3\3\2\2\2\2\5\3\2"+ - "\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21"+ - "\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2"+ - "\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3"+ - "\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3"+ - "\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3"+ - "\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2"+ - "\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2"+ - "Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3"+ - "\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2"+ - "\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2"+ - "\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3"+ - "\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2"+ - "\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099"+ - "\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2"+ - "\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab"+ - "\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2"+ - "\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00c1\3\2\2\2\2\u00c7"+ - "\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\3\u00cf\3\2\2"+ - "\2\5\u00d6\3\2\2\2\7\u00d8\3\2\2\2\t\u00da\3\2\2\2\13\u00dc\3\2\2\2\r"+ - "\u00de\3\2\2\2\17\u00e0\3\2\2\2\21\u00e2\3\2\2\2\23\u00e4\3\2\2\2\25\u00ea"+ - "\3\2\2\2\27\u00f1\3\2\2\2\31\u00f7\3\2\2\2\33\u0100\3\2\2\2\35\u0107\3"+ - "\2\2\2\37\u0110\3\2\2\2!\u011a\3\2\2\2#\u0122\3\2\2\2%\u0125\3\2\2\2\'"+ - "\u012a\3\2\2\2)\u0130\3\2\2\2+\u0133\3\2\2\2-\u0137\3\2\2\2/\u013e\3\2"+ - "\2\2\61\u0144\3\2\2\2\63\u014d\3\2\2\2\65\u0151\3\2\2\2\67\u0153\3\2\2"+ - "\29\u0156\3\2\2\2;\u015d\3\2\2\2=\u0166\3\2\2\2?\u0168\3\2\2\2A\u016a"+ - "\3\2\2\2C\u016c\3\2\2\2E\u0173\3\2\2\2G\u017a\3\2\2\2I\u0181\3\2\2\2K"+ - "\u0184\3\2\2\2M\u0187\3\2\2\2O\u0189\3\2\2\2Q\u018b\3\2\2\2S\u018d\3\2"+ - "\2\2U\u018f\3\2\2\2W\u0191\3\2\2\2Y\u0194\3\2\2\2[\u0197\3\2\2\2]\u0199"+ - "\3\2\2\2_\u019b\3\2\2\2a\u019d\3\2\2\2c\u019f\3\2\2\2e\u01a2\3\2\2\2g"+ - "\u01a5\3\2\2\2i\u01a8\3\2\2\2k\u01ab\3\2\2\2m\u01ad\3\2\2\2o\u01af\3\2"+ - "\2\2q\u01b2\3\2\2\2s\u01b5\3\2\2\2u\u01b7\3\2\2\2w\u01ba\3\2\2\2y\u01bd"+ - "\3\2\2\2{\u01c0\3\2\2\2}\u01c3\3\2\2\2\177\u01c6\3\2\2\2\u0081\u01ca\3"+ - "\2\2\2\u0083\u01ce\3\2\2\2\u0085\u01d1\3\2\2\2\u0087\u01d4\3\2\2\2\u0089"+ - "\u01d7\3\2\2\2\u008b\u01df\3\2\2\2\u008d\u01e8\3\2\2\2\u008f\u01ed\3\2"+ - "\2\2\u0091\u01f6\3\2\2\2\u0093\u01fc\3\2\2\2\u0095\u0203\3\2\2\2\u0097"+ - "\u0206\3\2\2\2\u0099\u020c\3\2\2\2\u009b\u020e\3\2\2\2\u009d\u02ee\3\2"+ - "\2\2\u009f\u02f0\3\2\2\2\u00a1\u0321\3\2\2\2\u00a3\u0323\3\2\2\2\u00a5"+ - "\u0330\3\2\2\2\u00a7\u0341\3\2\2\2\u00a9\u0345\3\2\2\2\u00ab\u034a\3\2"+ - "\2\2\u00ad\u0351\3\2\2\2\u00af\u0362\3\2\2\2\u00b1\u0370\3\2\2\2\u00b3"+ - "\u0381\3\2\2\2\u00b5\u0395\3\2\2\2\u00b7\u0398\3\2\2\2\u00b9\u03a1\3\2"+ - "\2\2\u00bb\u03a8\3\2\2\2\u00bd\u03aa\3\2\2\2\u00bf\u03ac\3\2\2\2\u00c1"+ - "\u03ae\3\2\2\2\u00c3\u03b5\3\2\2\2\u00c5\u03b7\3\2\2\2\u00c7\u03b9\3\2"+ - "\2\2\u00c9\u03c6\3\2\2\2\u00cb\u03cc\3\2\2\2\u00cd\u03d7\3\2\2\2\u00cf"+ - "\u00d0\7k\2\2\u00d0\u00d1\7o\2\2\u00d1\u00d2\7r\2\2\u00d2\u00d3\7q\2\2"+ - "\u00d3\u00d4\7t\2\2\u00d4\u00d5\7v\2\2\u00d5\4\3\2\2\2\u00d6\u00d7\7="+ - "\2\2\u00d7\6\3\2\2\2\u00d8\u00d9\7.\2\2\u00d9\b\3\2\2\2\u00da\u00db\7"+ - "?\2\2\u00db\n\3\2\2\2\u00dc\u00dd\7*\2\2\u00dd\f\3\2\2\2\u00de\u00df\7"+ - "+\2\2\u00df\16\3\2\2\2\u00e0\u00e1\7}\2\2\u00e1\20\3\2\2\2\u00e2\u00e3"+ - "\7\177\2\2\u00e3\22\3\2\2\2\u00e4\u00e5\7e\2\2\u00e5\u00e6\7q\2\2\u00e6"+ - "\u00e7\7p\2\2\u00e7\u00e8\7u\2\2\u00e8\u00e9\7v\2\2\u00e9\24\3\2\2\2\u00ea"+ - "\u00eb\7g\2\2\u00eb\u00ec\7z\2\2\u00ec\u00ed\7v\2\2\u00ed\u00ee\7g\2\2"+ - "\u00ee\u00ef\7t\2\2\u00ef\u00f0\7p\2\2\u00f0\26\3\2\2\2\u00f1\u00f2\7"+ - "c\2\2\u00f2\u00f3\7n\2\2\u00f3\u00f4\7k\2\2\u00f4\u00f5\7i\2\2\u00f5\u00f6"+ - "\7p\2\2\u00f6\30\3\2\2\2\u00f7\u00f8\7t\2\2\u00f8\u00f9\7g\2\2\u00f9\u00fa"+ - "\7i\2\2\u00fa\u00fb\7k\2\2\u00fb\u00fc\7u\2\2\u00fc\u00fd\7v\2\2\u00fd"+ - "\u00fe\7g\2\2\u00fe\u00ff\7t\2\2\u00ff\32\3\2\2\2\u0100\u0101\7k\2\2\u0101"+ - "\u0102\7p\2\2\u0102\u0103\7n\2\2\u0103\u0104\7k\2\2\u0104\u0105\7p\2\2"+ - "\u0105\u0106\7g\2\2\u0106\34\3\2\2\2\u0107\u0108\7x\2\2\u0108\u0109\7"+ - "q\2\2\u0109\u010a\7n\2\2\u010a\u010b\7c\2\2\u010b\u010c\7v\2\2\u010c\u010d"+ - "\7k\2\2\u010d\u010e\7n\2\2\u010e\u010f\7g\2\2\u010f\36\3\2\2\2\u0110\u0111"+ - "\7k\2\2\u0111\u0112\7p\2\2\u0112\u0113\7v\2\2\u0113\u0114\7g\2\2\u0114"+ - "\u0115\7t\2\2\u0115\u0116\7t\2\2\u0116\u0117\7w\2\2\u0117\u0118\7r\2\2"+ - "\u0118\u0119\7v\2\2\u0119 \3\2\2\2\u011a\u011b\7t\2\2\u011b\u011c\7g\2"+ - "\2\u011c\u011d\7u\2\2\u011d\u011e\7g\2\2\u011e\u011f\7t\2\2\u011f\u0120"+ - "\7x\2\2\u0120\u0121\7g\2\2\u0121\"\3\2\2\2\u0122\u0123\7k\2\2\u0123\u0124"+ - "\7h\2\2\u0124$\3\2\2\2\u0125\u0126\7g\2\2\u0126\u0127\7n\2\2\u0127\u0128"+ - "\7u\2\2\u0128\u0129\7g\2\2\u0129&\3\2\2\2\u012a\u012b\7y\2\2\u012b\u012c"+ - "\7j\2\2\u012c\u012d\7k\2\2\u012d\u012e\7n\2\2\u012e\u012f\7g\2\2\u012f"+ - "(\3\2\2\2\u0130\u0131\7f\2\2\u0131\u0132\7q\2\2\u0132*\3\2\2\2\u0133\u0134"+ - "\7h\2\2\u0134\u0135\7q\2\2\u0135\u0136\7t\2\2\u0136,\3\2\2\2\u0137\u0138"+ - "\7t\2\2\u0138\u0139\7g\2\2\u0139\u013a\7v\2\2\u013a\u013b\7w\2\2\u013b"+ - "\u013c\7t\2\2\u013c\u013d\7p\2\2\u013d.\3\2\2\2\u013e\u013f\7d\2\2\u013f"+ - "\u0140\7t\2\2\u0140\u0141\7g\2\2\u0141\u0142\7c\2\2\u0142\u0143\7m\2\2"+ - "\u0143\60\3\2\2\2\u0144\u0145\7e\2\2\u0145\u0146\7q\2\2\u0146\u0147\7"+ - "p\2\2\u0147\u0148\7v\2\2\u0148\u0149\7k\2\2\u0149\u014a\7p\2\2\u014a\u014b"+ - "\7w\2\2\u014b\u014c\7g\2\2\u014c\62\3\2\2\2\u014d\u014e\7c\2\2\u014e\u014f"+ - "\7u\2\2\u014f\u0150\7o\2\2\u0150\64\3\2\2\2\u0151\u0152\7<\2\2\u0152\66"+ - "\3\2\2\2\u0153\u0154\7\60\2\2\u0154\u0155\7\60\2\2\u01558\3\2\2\2\u0156"+ - "\u0157\7u\2\2\u0157\u0158\7k\2\2\u0158\u0159\7i\2\2\u0159\u015a\7p\2\2"+ - "\u015a\u015b\7g\2\2\u015b\u015c\7f\2\2\u015c:\3\2\2\2\u015d\u015e\7w\2"+ - "\2\u015e\u015f\7p\2\2\u015f\u0160\7u\2\2\u0160\u0161\7k\2\2\u0161\u0162"+ - "\7i\2\2\u0162\u0163\7p\2\2\u0163\u0164\7g\2\2\u0164\u0165\7f\2\2\u0165"+ - "<\3\2\2\2\u0166\u0167\7,\2\2\u0167>\3\2\2\2\u0168\u0169\7]\2\2\u0169@"+ - "\3\2\2\2\u016a\u016b\7_\2\2\u016bB\3\2\2\2\u016c\u016d\7u\2\2\u016d\u016e"+ - "\7v\2\2\u016e\u016f\7t\2\2\u016f\u0170\7w\2\2\u0170\u0171\7e\2\2\u0171"+ - "\u0172\7v\2\2\u0172D\3\2\2\2\u0173\u0174\7u\2\2\u0174\u0175\7k\2\2\u0175"+ - "\u0176\7|\2\2\u0176\u0177\7g\2\2\u0177\u0178\7q\2\2\u0178\u0179\7h\2\2"+ - "\u0179F\3\2\2\2\u017a\u017b\7v\2\2\u017b\u017c\7{\2\2\u017c\u017d\7r\2"+ - "\2\u017d\u017e\7g\2\2\u017e\u017f\7k\2\2\u017f\u0180\7f\2\2\u0180H\3\2"+ - "\2\2\u0181\u0182\7/\2\2\u0182\u0183\7/\2\2\u0183J\3\2\2\2\u0184\u0185"+ - "\7-\2\2\u0185\u0186\7-\2\2\u0186L\3\2\2\2\u0187\u0188\7-\2\2\u0188N\3"+ - "\2\2\2\u0189\u018a\7/\2\2\u018aP\3\2\2\2\u018b\u018c\7#\2\2\u018cR\3\2"+ - "\2\2\u018d\u018e\7(\2\2\u018eT\3\2\2\2\u018f\u0190\7\u0080\2\2\u0190V"+ - "\3\2\2\2\u0191\u0192\7@\2\2\u0192\u0193\7@\2\2\u0193X\3\2\2\2\u0194\u0195"+ - "\7>\2\2\u0195\u0196\7>\2\2\u0196Z\3\2\2\2\u0197\u0198\7\61\2\2\u0198\\"+ - "\3\2\2\2\u0199\u019a\7\'\2\2\u019a^\3\2\2\2\u019b\u019c\7>\2\2\u019c`"+ - "\3\2\2\2\u019d\u019e\7@\2\2\u019eb\3\2\2\2\u019f\u01a0\7?\2\2\u01a0\u01a1"+ - "\7?\2\2\u01a1d\3\2\2\2\u01a2\u01a3\7#\2\2\u01a3\u01a4\7?\2\2\u01a4f\3"+ - "\2\2\2\u01a5\u01a6\7>\2\2\u01a6\u01a7\7?\2\2\u01a7h\3\2\2\2\u01a8\u01a9"+ - "\7@\2\2\u01a9\u01aa\7?\2\2\u01aaj\3\2\2\2\u01ab\u01ac\7`\2\2\u01acl\3"+ - "\2\2\2\u01ad\u01ae\7~\2\2\u01aen\3\2\2\2\u01af\u01b0\7(\2\2\u01b0\u01b1"+ - "\7(\2\2\u01b1p\3\2\2\2\u01b2\u01b3\7~\2\2\u01b3\u01b4\7~\2\2\u01b4r\3"+ - "\2\2\2\u01b5\u01b6\7A\2\2\u01b6t\3\2\2\2\u01b7\u01b8\7-\2\2\u01b8\u01b9"+ - "\7?\2\2\u01b9v\3\2\2\2\u01ba\u01bb\7/\2\2\u01bb\u01bc\7?\2\2\u01bcx\3"+ - "\2\2\2\u01bd\u01be\7,\2\2\u01be\u01bf\7?\2\2\u01bfz\3\2\2\2\u01c0\u01c1"+ - "\7\61\2\2\u01c1\u01c2\7?\2\2\u01c2|\3\2\2\2\u01c3\u01c4\7\'\2\2\u01c4"+ - "\u01c5\7?\2\2\u01c5~\3\2\2\2\u01c6\u01c7\7>\2\2\u01c7\u01c8\7>\2\2\u01c8"+ - "\u01c9\7?\2\2\u01c9\u0080\3\2\2\2\u01ca\u01cb\7@\2\2\u01cb\u01cc\7@\2"+ - "\2\u01cc\u01cd\7?\2\2\u01cd\u0082\3\2\2\2\u01ce\u01cf\7(\2\2\u01cf\u01d0"+ - "\7?\2\2\u01d0\u0084\3\2\2\2\u01d1\u01d2\7~\2\2\u01d2\u01d3\7?\2\2\u01d3"+ - "\u0086\3\2\2\2\u01d4\u01d5\7`\2\2\u01d5\u01d6\7?\2\2\u01d6\u0088\3\2\2"+ - "\2\u01d7\u01d8\7m\2\2\u01d8\u01d9\7k\2\2\u01d9\u01da\7e\2\2\u01da\u01db"+ - "\7m\2\2\u01db\u01dc\7c\2\2\u01dc\u01dd\7u\2\2\u01dd\u01de\7o\2\2\u01de"+ - "\u008a\3\2\2\2\u01df\u01e0\7t\2\2\u01e0\u01e1\7g\2\2\u01e1\u01e2\7u\2"+ - "\2\u01e2\u01e3\7q\2\2\u01e3\u01e4\7w\2\2\u01e4\u01e5\7t\2\2\u01e5\u01e6"+ - "\7e\2\2\u01e6\u01e7\7g\2\2\u01e7\u008c\3\2\2\2\u01e8\u01e9\7w\2\2\u01e9"+ - "\u01ea\7u\2\2\u01ea\u01eb\7g\2\2\u01eb\u01ec\7u\2\2\u01ec\u008e\3\2\2"+ - "\2\u01ed\u01ee\7e\2\2\u01ee\u01ef\7n\2\2\u01ef\u01f0\7q\2\2\u01f0\u01f1"+ - "\7d\2\2\u01f1\u01f2\7d\2\2\u01f2\u01f3\7g\2\2\u01f3\u01f4\7t\2\2\u01f4"+ - "\u01f5\7u\2\2\u01f5\u0090\3\2\2\2\u01f6\u01f7\7d\2\2\u01f7\u01f8\7{\2"+ - "\2\u01f8\u01f9\7v\2\2\u01f9\u01fa\7g\2\2\u01fa\u01fb\7u\2\2\u01fb\u0092"+ - "\3\2\2\2\u01fc\u01fd\7e\2\2\u01fd\u01fe\7{\2\2\u01fe\u01ff\7e\2\2\u01ff"+ - "\u0200\7n\2\2\u0200\u0201\7g\2\2\u0201\u0202\7u\2\2\u0202\u0094\3\2\2"+ - "\2\u0203\u0204\7r\2\2\u0204\u0205\7e\2\2\u0205\u0096\3\2\2\2\u0206\u0207"+ - "\7\60\2\2\u0207\u0208\7d\2\2\u0208\u0209\7{\2\2\u0209\u020a\7v\2\2\u020a"+ - "\u020b\7g\2\2\u020b\u0098\3\2\2\2\u020c\u020d\7%\2\2\u020d\u009a\3\2\2"+ - "\2\u020e\u020f\7\60\2\2\u020f\u009c\3\2\2\2\u0210\u0211\7d\2\2\u0211\u0212"+ - "\7t\2\2\u0212\u02ef\7m\2\2\u0213\u0214\7q\2\2\u0214\u0215\7t\2\2\u0215"+ - "\u02ef\7c\2\2\u0216\u0217\7m\2\2\u0217\u0218\7k\2\2\u0218\u02ef\7n\2\2"+ - "\u0219\u021a\7u\2\2\u021a\u021b\7n\2\2\u021b\u02ef\7q\2\2\u021c\u021d"+ - "\7p\2\2\u021d\u021e\7q\2\2\u021e\u02ef\7r\2\2\u021f\u0220\7c\2\2\u0220"+ - "\u0221\7u\2\2\u0221\u02ef\7n\2\2\u0222\u0223\7r\2\2\u0223\u0224\7j\2\2"+ - "\u0224\u02ef\7r\2\2\u0225\u0226\7c\2\2\u0226\u0227\7p\2\2\u0227\u02ef"+ - "\7e\2\2\u0228\u0229\7d\2\2\u0229\u022a\7r\2\2\u022a\u02ef\7n\2\2\u022b"+ - "\u022c\7e\2\2\u022c\u022d\7n\2\2\u022d\u02ef\7e\2\2\u022e\u022f\7l\2\2"+ - "\u022f\u0230\7u\2\2\u0230\u02ef\7t\2\2\u0231\u0232\7c\2\2\u0232\u0233"+ - "\7p\2\2\u0233\u02ef\7f\2\2\u0234\u0235\7t\2\2\u0235\u0236\7n\2\2\u0236"+ - "\u02ef\7c\2\2\u0237\u0238\7d\2\2\u0238\u0239\7k\2\2\u0239\u02ef\7v\2\2"+ - "\u023a\u023b\7t\2\2\u023b\u023c\7q\2\2\u023c\u02ef\7n\2\2\u023d\u023e"+ - "\7r\2\2\u023e\u023f\7n\2\2\u023f\u02ef\7c\2\2\u0240\u0241\7r\2\2\u0241"+ - "\u0242\7n\2\2\u0242\u02ef\7r\2\2\u0243\u0244\7d\2\2\u0244\u0245\7o\2\2"+ - "\u0245\u02ef\7k\2\2\u0246\u0247\7u\2\2\u0247\u0248\7g\2\2\u0248\u02ef"+ - "\7e\2\2\u0249\u024a\7t\2\2\u024a\u024b\7v\2\2\u024b\u02ef\7k\2\2\u024c"+ - "\u024d\7g\2\2\u024d\u024e\7q\2\2\u024e\u02ef\7t\2\2\u024f\u0250\7u\2\2"+ - "\u0250\u0251\7t\2\2\u0251\u02ef\7g\2\2\u0252\u0253\7n\2\2\u0253\u0254"+ - "\7u\2\2\u0254\u02ef\7t\2\2\u0255\u0256\7r\2\2\u0256\u0257\7j\2\2\u0257"+ - "\u02ef\7c\2\2\u0258\u0259\7c\2\2\u0259\u025a\7n\2\2\u025a\u02ef\7t\2\2"+ - "\u025b\u025c\7l\2\2\u025c\u025d\7o\2\2\u025d\u02ef\7r\2\2\u025e\u025f"+ - "\7d\2\2\u025f\u0260\7x\2\2\u0260\u02ef\7e\2\2\u0261\u0262\7e\2\2\u0262"+ - "\u0263\7n\2\2\u0263\u02ef\7k\2\2\u0264\u0265\7t\2\2\u0265\u0266\7v\2\2"+ - "\u0266\u02ef\7u\2\2\u0267\u0268\7c\2\2\u0268\u0269\7f\2\2\u0269\u02ef"+ - "\7e\2\2\u026a\u026b\7t\2\2\u026b\u026c\7t\2\2\u026c\u02ef\7c\2\2\u026d"+ - "\u026e\7d\2\2\u026e\u026f\7x\2\2\u026f\u02ef\7u\2\2\u0270\u0271\7u\2\2"+ - "\u0271\u0272\7g\2\2\u0272\u02ef\7k\2\2\u0273\u0274\7u\2\2\u0274\u0275"+ - "\7c\2\2\u0275\u02ef\7z\2\2\u0276\u0277\7u\2\2\u0277\u0278\7v\2\2\u0278"+ - "\u02ef\7{\2\2\u0279\u027a\7u\2\2\u027a\u027b\7v\2\2\u027b\u02ef\7c\2\2"+ - "\u027c\u027d\7u\2\2\u027d\u027e\7v\2\2\u027e\u02ef\7z\2\2\u027f\u0280"+ - "\7f\2\2\u0280\u0281\7g\2\2\u0281\u02ef\7{\2\2\u0282\u0283\7v\2\2\u0283"+ - "\u0284\7z\2\2\u0284\u02ef\7c\2\2\u0285\u0286\7z\2\2\u0286\u0287\7c\2\2"+ - "\u0287\u02ef\7c\2\2\u0288\u0289\7d\2\2\u0289\u028a\7e\2\2\u028a\u02ef"+ - "\7e\2\2\u028b\u028c\7c\2\2\u028c\u028d\7j\2\2\u028d\u02ef\7z\2\2\u028e"+ - "\u028f\7v\2\2\u028f\u0290\7{\2\2\u0290\u02ef\7c\2\2\u0291\u0292\7v\2\2"+ - "\u0292\u0293\7z\2\2\u0293\u02ef\7u\2\2\u0294\u0295\7v\2\2\u0295\u0296"+ - "\7c\2\2\u0296\u02ef\7u\2\2\u0297\u0298\7u\2\2\u0298\u0299\7j\2\2\u0299"+ - "\u02ef\7{\2\2\u029a\u029b\7u\2\2\u029b\u029c\7j\2\2\u029c\u02ef\7z\2\2"+ - "\u029d\u029e\7n\2\2\u029e\u029f\7f\2\2\u029f\u02ef\7{\2\2\u02a0\u02a1"+ - "\7n\2\2\u02a1\u02a2\7f\2\2\u02a2\u02ef\7c\2\2\u02a3\u02a4\7n\2\2\u02a4"+ - "\u02a5\7f\2\2\u02a5\u02ef\7z\2\2\u02a6\u02a7\7n\2\2\u02a7\u02a8\7c\2\2"+ - "\u02a8\u02ef\7z\2\2\u02a9\u02aa\7v\2\2\u02aa\u02ab\7c\2\2\u02ab\u02ef"+ - "\7{\2\2\u02ac\u02ad\7v\2\2\u02ad\u02ae\7c\2\2\u02ae\u02ef\7z\2\2\u02af"+ - "\u02b0\7d\2\2\u02b0\u02b1\7e\2\2\u02b1\u02ef\7u\2\2\u02b2\u02b3\7e\2\2"+ - "\u02b3\u02b4\7n\2\2\u02b4\u02ef\7x\2\2\u02b5\u02b6\7v\2\2\u02b6\u02b7"+ - "\7u\2\2\u02b7\u02ef\7z\2\2\u02b8\u02b9\7n\2\2\u02b9\u02ba\7c\2\2\u02ba"+ - "\u02ef\7u\2\2\u02bb\u02bc\7e\2\2\u02bc\u02bd\7r\2\2\u02bd\u02ef\7{\2\2"+ - "\u02be\u02bf\7e\2\2\u02bf\u02c0\7o\2\2\u02c0\u02ef\7r\2\2\u02c1\u02c2"+ - "\7e\2\2\u02c2\u02c3\7r\2\2\u02c3\u02ef\7z\2\2\u02c4\u02c5\7f\2\2\u02c5"+ - "\u02c6\7e\2\2\u02c6\u02ef\7r\2\2\u02c7\u02c8\7f\2\2\u02c8\u02c9\7g\2\2"+ - "\u02c9\u02ef\7e\2\2\u02ca\u02cb\7k\2\2\u02cb\u02cc\7p\2\2\u02cc\u02ef"+ - "\7e\2\2\u02cd\u02ce\7c\2\2\u02ce\u02cf\7z\2\2\u02cf\u02ef\7u\2\2\u02d0"+ - "\u02d1\7d\2\2\u02d1\u02d2\7p\2\2\u02d2\u02ef\7g\2\2\u02d3\u02d4\7e\2\2"+ - "\u02d4\u02d5\7n\2\2\u02d5\u02ef\7f\2\2\u02d6\u02d7\7u\2\2\u02d7\u02d8"+ - "\7d\2\2\u02d8\u02ef\7e\2\2\u02d9\u02da\7k\2\2\u02da\u02db\7u\2\2\u02db"+ - "\u02ef\7e\2\2\u02dc\u02dd\7k\2\2\u02dd\u02de\7p\2\2\u02de\u02ef\7z\2\2"+ - "\u02df\u02e0\7d\2\2\u02e0\u02e1\7g\2\2\u02e1\u02ef\7s\2\2\u02e2\u02e3"+ - "\7u\2\2\u02e3\u02e4\7g\2\2\u02e4\u02ef\7f\2\2\u02e5\u02e6\7f\2\2\u02e6"+ - "\u02e7\7g\2\2\u02e7\u02ef\7z\2\2\u02e8\u02e9\7k\2\2\u02e9\u02ea\7p\2\2"+ - "\u02ea\u02ef\7{\2\2\u02eb\u02ec\7t\2\2\u02ec\u02ed\7q\2\2\u02ed\u02ef"+ - "\7t\2\2\u02ee\u0210\3\2\2\2\u02ee\u0213\3\2\2\2\u02ee\u0216\3\2\2\2\u02ee"+ - "\u0219\3\2\2\2\u02ee\u021c\3\2\2\2\u02ee\u021f\3\2\2\2\u02ee\u0222\3\2"+ - "\2\2\u02ee\u0225\3\2\2\2\u02ee\u0228\3\2\2\2\u02ee\u022b\3\2\2\2\u02ee"+ - "\u022e\3\2\2\2\u02ee\u0231\3\2\2\2\u02ee\u0234\3\2\2\2\u02ee\u0237\3\2"+ - "\2\2\u02ee\u023a\3\2\2\2\u02ee\u023d\3\2\2\2\u02ee\u0240\3\2\2\2\u02ee"+ - "\u0243\3\2\2\2\u02ee\u0246\3\2\2\2\u02ee\u0249\3\2\2\2\u02ee\u024c\3\2"+ - "\2\2\u02ee\u024f\3\2\2\2\u02ee\u0252\3\2\2\2\u02ee\u0255\3\2\2\2\u02ee"+ - "\u0258\3\2\2\2\u02ee\u025b\3\2\2\2\u02ee\u025e\3\2\2\2\u02ee\u0261\3\2"+ - "\2\2\u02ee\u0264\3\2\2\2\u02ee\u0267\3\2\2\2\u02ee\u026a\3\2\2\2\u02ee"+ - "\u026d\3\2\2\2\u02ee\u0270\3\2\2\2\u02ee\u0273\3\2\2\2\u02ee\u0276\3\2"+ - "\2\2\u02ee\u0279\3\2\2\2\u02ee\u027c\3\2\2\2\u02ee\u027f\3\2\2\2\u02ee"+ - "\u0282\3\2\2\2\u02ee\u0285\3\2\2\2\u02ee\u0288\3\2\2\2\u02ee\u028b\3\2"+ - "\2\2\u02ee\u028e\3\2\2\2\u02ee\u0291\3\2\2\2\u02ee\u0294\3\2\2\2\u02ee"+ - "\u0297\3\2\2\2\u02ee\u029a\3\2\2\2\u02ee\u029d\3\2\2\2\u02ee\u02a0\3\2"+ - "\2\2\u02ee\u02a3\3\2\2\2\u02ee\u02a6\3\2\2\2\u02ee\u02a9\3\2\2\2\u02ee"+ - "\u02ac\3\2\2\2\u02ee\u02af\3\2\2\2\u02ee\u02b2\3\2\2\2\u02ee\u02b5\3\2"+ - "\2\2\u02ee\u02b8\3\2\2\2\u02ee\u02bb\3\2\2\2\u02ee\u02be\3\2\2\2\u02ee"+ - "\u02c1\3\2\2\2\u02ee\u02c4\3\2\2\2\u02ee\u02c7\3\2\2\2\u02ee\u02ca\3\2"+ - "\2\2\u02ee\u02cd\3\2\2\2\u02ee\u02d0\3\2\2\2\u02ee\u02d3\3\2\2\2\u02ee"+ - "\u02d6\3\2\2\2\u02ee\u02d9\3\2\2\2\u02ee\u02dc\3\2\2\2\u02ee\u02df\3\2"+ - "\2\2\u02ee\u02e2\3\2\2\2\u02ee\u02e5\3\2\2\2\u02ee\u02e8\3\2\2\2\u02ee"+ - "\u02eb\3\2\2\2\u02ef\u009e\3\2\2\2\u02f0\u02f1\7}\2\2\u02f1\u02f2\7}\2"+ - "\2\u02f2\u02f6\3\2\2\2\u02f3\u02f5\13\2\2\2\u02f4\u02f3\3\2\2\2\u02f5"+ - "\u02f8\3\2\2\2\u02f6\u02f7\3\2\2\2\u02f6\u02f4\3\2\2\2\u02f7\u02f9\3\2"+ - "\2\2\u02f8\u02f6\3\2\2\2\u02f9\u02fa\7\177\2\2\u02fa\u02fb\7\177\2\2\u02fb"+ - "\u00a0\3\2\2\2\u02fc\u02fd\7d\2\2\u02fd\u02fe\7{\2\2\u02fe\u02ff\7v\2"+ - "\2\u02ff\u0322\7g\2\2\u0300\u0301\7y\2\2\u0301\u0302\7q\2\2\u0302\u0303"+ - "\7t\2\2\u0303\u0322\7f\2\2\u0304\u0305\7f\2\2\u0305\u0306\7y\2\2\u0306"+ - "\u0307\7q\2\2\u0307\u0308\7t\2\2\u0308\u0322\7f\2\2\u0309\u030a\7d\2\2"+ - "\u030a\u030b\7q\2\2\u030b\u030c\7q\2\2\u030c\u0322\7n\2\2\u030d\u030e"+ - "\7e\2\2\u030e\u030f\7j\2\2\u030f\u0310\7c\2\2\u0310\u0322\7t\2\2\u0311"+ - "\u0312\7u\2\2\u0312\u0313\7j\2\2\u0313\u0314\7q\2\2\u0314\u0315\7t\2\2"+ - "\u0315\u0322\7v\2\2\u0316\u0317\7k\2\2\u0317\u0318\7p\2\2\u0318\u0322"+ - "\7v\2\2\u0319\u031a\7n\2\2\u031a\u031b\7q\2\2\u031b\u031c\7p\2\2\u031c"+ - "\u0322\7i\2\2\u031d\u031e\7x\2\2\u031e\u031f\7q\2\2\u031f\u0320\7k\2\2"+ - "\u0320\u0322\7f\2\2\u0321\u02fc\3\2\2\2\u0321\u0300\3\2\2\2\u0321\u0304"+ - "\3\2\2\2\u0321\u0309\3\2\2\2\u0321\u030d\3\2\2\2\u0321\u0311\3\2\2\2\u0321"+ - "\u0316\3\2\2\2\u0321\u0319\3\2\2\2\u0321\u031d\3\2\2\2\u0322\u00a2\3\2"+ - "\2\2\u0323\u0329\7$\2\2\u0324\u0325\7^\2\2\u0325\u0328\7$\2\2\u0326\u0328"+ - "\n\2\2\2\u0327\u0324\3\2\2\2\u0327\u0326\3\2\2\2\u0328\u032b\3\2\2\2\u0329"+ - "\u0327\3\2\2\2\u0329\u032a\3\2\2\2\u032a\u032c\3\2\2\2\u032b\u0329\3\2"+ - "\2\2\u032c\u032e\7$\2\2\u032d\u032f\7|\2\2\u032e\u032d\3\2\2\2\u032e\u032f"+ - "\3\2\2\2\u032f\u00a4\3\2\2\2\u0330\u0334\7)\2\2\u0331\u0332\7^\2\2\u0332"+ - "\u0335\7)\2\2\u0333\u0335\n\3\2\2\u0334\u0331\3\2\2\2\u0334\u0333\3\2"+ - "\2\2\u0335\u0336\3\2\2\2\u0336\u0337\7)\2\2\u0337\u00a6\3\2\2\2\u0338"+ - "\u0339\7v\2\2\u0339\u033a\7t\2\2\u033a\u033b\7w\2\2\u033b\u0342\7g\2\2"+ - "\u033c\u033d\7h\2\2\u033d\u033e\7c\2\2\u033e\u033f\7n\2\2\u033f\u0340"+ - "\7u\2\2\u0340\u0342\7g\2\2\u0341\u0338\3\2\2\2\u0341\u033c\3\2\2\2\u0342"+ - "\u00a8\3\2\2\2\u0343\u0346\5\u00abV\2\u0344\u0346\5\u00b3Z\2\u0345\u0343"+ - "\3\2\2\2\u0345\u0344\3\2\2\2\u0346\u00aa\3\2\2\2\u0347\u034b\5\u00adW"+ - "\2\u0348\u034b\5\u00afX\2\u0349\u034b\5\u00b1Y\2\u034a\u0347\3\2\2\2\u034a"+ - "\u0348\3\2\2\2\u034a\u0349\3\2\2\2\u034b\u00ac\3\2\2\2\u034c\u0352\7\'"+ - "\2\2\u034d\u034e\7\62\2\2\u034e\u0352\7d\2\2\u034f\u0350\7\62\2\2\u0350"+ - "\u0352\7D\2\2\u0351\u034c\3\2\2\2\u0351\u034d\3\2\2\2\u0351\u034f\3\2"+ - "\2\2\u0352\u0356\3\2\2\2\u0353\u0355\5\u00bb^\2\u0354\u0353\3\2\2\2\u0355"+ - "\u0358\3\2\2\2\u0356\u0354\3\2\2\2\u0356\u0357\3\2\2\2\u0357\u0359\3\2"+ - "\2\2\u0358\u0356\3\2\2\2\u0359\u035b\7\60\2\2\u035a\u035c\5\u00bb^\2\u035b"+ - "\u035a\3\2\2\2\u035c\u035d\3\2\2\2\u035d\u035b\3\2\2\2\u035d\u035e\3\2"+ - "\2\2\u035e\u00ae\3\2\2\2\u035f\u0361\5\u00bd_\2\u0360\u035f\3\2\2\2\u0361"+ - "\u0364\3\2\2\2\u0362\u0360\3\2\2\2\u0362\u0363\3\2\2\2\u0363\u0365\3\2"+ - "\2\2\u0364\u0362\3\2\2\2\u0365\u0367\7\60\2\2\u0366\u0368\5\u00bd_\2\u0367"+ - "\u0366\3\2\2\2\u0368\u0369\3\2\2\2\u0369\u0367\3\2\2\2\u0369\u036a\3\2"+ - "\2\2\u036a\u00b0\3\2\2\2\u036b\u0371\7&\2\2\u036c\u036d\7\62\2\2\u036d"+ - "\u0371\7z\2\2\u036e\u036f\7\62\2\2\u036f\u0371\7Z\2\2\u0370\u036b\3\2"+ - "\2\2\u0370\u036c\3\2\2\2\u0370\u036e\3\2\2\2\u0371\u0375\3\2\2\2\u0372"+ - "\u0374\5\u00bf`\2\u0373\u0372\3\2\2\2\u0374\u0377\3\2\2\2\u0375\u0373"+ - "\3\2\2\2\u0375\u0376\3\2\2\2\u0376\u0378\3\2\2\2\u0377\u0375\3\2\2\2\u0378"+ - "\u037a\7\60\2\2\u0379\u037b\5\u00bf`\2\u037a\u0379\3\2\2\2\u037b\u037c"+ - "\3\2\2\2\u037c\u037a\3\2\2\2\u037c\u037d\3\2\2\2\u037d\u00b2\3\2\2\2\u037e"+ - "\u0382\5\u00b7\\\2\u037f\u0382\5\u00b9]\2\u0380\u0382\5\u00b5[\2\u0381"+ - "\u037e\3\2\2\2\u0381\u037f\3\2\2\2\u0381\u0380\3\2\2\2\u0382\u0386\3\2"+ - "\2\2\u0383\u0384\t\4\2\2\u0384\u0387\t\5\2\2\u0385\u0387\7n\2\2\u0386"+ - "\u0383\3\2\2\2\u0386\u0385\3\2\2\2\u0386\u0387\3\2\2\2\u0387\u00b4\3\2"+ - "\2\2\u0388\u0389\7\62\2\2\u0389\u038b\t\6\2\2\u038a\u038c\5\u00bb^\2\u038b"+ - "\u038a\3\2\2\2\u038c\u038d\3\2\2\2\u038d\u038b\3\2\2\2\u038d\u038e\3\2"+ - "\2\2\u038e\u0396\3\2\2\2\u038f\u0391\7\'\2\2\u0390\u0392\5\u00bb^\2\u0391"+ - "\u0390\3\2\2\2\u0392\u0393\3\2\2\2\u0393\u0391\3\2\2\2\u0393\u0394\3\2"+ - "\2\2\u0394\u0396\3\2\2\2\u0395\u0388\3\2\2\2\u0395\u038f\3\2\2\2\u0396"+ - "\u00b6\3\2\2\2\u0397\u0399\5\u00bd_\2\u0398\u0397\3\2\2\2\u0399\u039a"+ - "\3\2\2\2\u039a\u0398\3\2\2\2\u039a\u039b\3\2\2\2\u039b\u00b8\3\2\2\2\u039c"+ - "\u03a2\7&\2\2\u039d\u039e\7\62\2\2\u039e\u03a2\7z\2\2\u039f\u03a0\7\62"+ - "\2\2\u03a0\u03a2\7Z\2\2\u03a1\u039c\3\2\2\2\u03a1\u039d\3\2\2\2\u03a1"+ - "\u039f\3\2\2\2\u03a2\u03a4\3\2\2\2\u03a3\u03a5\5\u00bf`\2\u03a4\u03a3"+ - "\3\2\2\2\u03a5\u03a6\3\2\2\2\u03a6\u03a4\3\2\2\2\u03a6\u03a7\3\2\2\2\u03a7"+ - "\u00ba\3\2\2\2\u03a8\u03a9\t\7\2\2\u03a9\u00bc\3\2\2\2\u03aa\u03ab\t\b"+ - "\2\2\u03ab\u00be\3\2\2\2\u03ac\u03ad\t\t\2\2\u03ad\u00c0\3\2\2\2\u03ae"+ - "\u03b2\5\u00c3b\2\u03af\u03b1\5\u00c5c\2\u03b0\u03af\3\2\2\2\u03b1\u03b4"+ - "\3\2\2\2\u03b2\u03b0\3\2\2\2\u03b2\u03b3\3\2\2\2\u03b3\u00c2\3\2\2\2\u03b4"+ - "\u03b2\3\2\2\2\u03b5\u03b6\t\n\2\2\u03b6\u00c4\3\2\2\2\u03b7\u03b8\t\13"+ - "\2\2\u03b8\u00c6\3\2\2\2\u03b9\u03bd\7#\2\2\u03ba\u03bc\5\u00c5c\2\u03bb"+ - "\u03ba\3\2\2\2\u03bc\u03bf\3\2\2\2\u03bd\u03bb\3\2\2\2\u03bd\u03be\3\2"+ - "\2\2\u03be\u03c1\3\2\2\2\u03bf\u03bd\3\2\2\2\u03c0\u03c2\t\f\2\2\u03c1"+ - "\u03c0\3\2\2\2\u03c2\u03c3\3\2\2\2\u03c3\u03c1\3\2\2\2\u03c3\u03c4\3\2"+ - "\2\2\u03c4\u00c8\3\2\2\2\u03c5\u03c7\t\r\2\2\u03c6\u03c5\3\2\2\2\u03c7"+ - "\u03c8\3\2\2\2\u03c8\u03c6\3\2\2\2\u03c8\u03c9\3\2\2\2\u03c9\u03ca\3\2"+ - "\2\2\u03ca\u03cb\be\2\2\u03cb\u00ca\3\2\2\2\u03cc\u03cd\7\61\2\2\u03cd"+ - "\u03ce\7\61\2\2\u03ce\u03d2\3\2\2\2\u03cf\u03d1\n\16\2\2\u03d0\u03cf\3"+ - "\2\2\2\u03d1\u03d4\3\2\2\2\u03d2\u03d0\3\2\2\2\u03d2\u03d3\3\2\2\2\u03d3"+ - "\u03d5\3\2\2\2\u03d4\u03d2\3\2\2\2\u03d5\u03d6\bf\3\2\u03d6\u00cc\3\2"+ - "\2\2\u03d7\u03d8\7\61\2\2\u03d8\u03d9\7,\2\2\u03d9\u03dd\3\2\2\2\u03da"+ - "\u03dc\13\2\2\2\u03db\u03da\3\2\2\2\u03dc\u03df\3\2\2\2\u03dd\u03de\3"+ - "\2\2\2\u03dd\u03db\3\2\2\2\u03de\u03e0\3\2\2\2\u03df\u03dd\3\2\2\2\u03e0"+ - "\u03e1\7,\2\2\u03e1\u03e2\7\61\2\2\u03e2\u03e3\3\2\2\2\u03e3\u03e4\bg"+ - "\3\2\u03e4\u00ce\3\2\2\2#\2\u02ee\u02f6\u0321\u0327\u0329\u032e\u0334"+ - "\u0341\u0345\u034a\u0351\u0356\u035d\u0362\u0369\u0370\u0375\u037c\u0381"+ - "\u0386\u038d\u0393\u0395\u039a\u03a1\u03a6\u03b2\u03bd\u03c3\u03c8\u03d2"+ - "\u03dd\4\2\3\2\2\4\2"; + "`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\3\2\3\2\3\2\3\2\3"+ + "\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n"+ + "\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3"+ + "\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16"+ + "\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20"+ + "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+ + "\3\21\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24"+ + "\3\24\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27"+ + "\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31"+ + "\3\31\3\31\3\32\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35"+ + "\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\37"+ + "\3\37\3 \3 \3!\3!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3#\3#\3$\3$\3$\3%\3%\3%"+ + "\3%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3&\3\'\3\'\3\'\3(\3(\3(\3)\3)\3*\3*\3+"+ + "\3+\3,\3,\3-\3-\3.\3.\3.\3/\3/\3/\3\60\3\60\3\61\3\61\3\62\3\62\3\63\3"+ + "\63\3\64\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\66\3\67\3\67\3\67\38\38"+ + "\39\39\3:\3:\3:\3;\3;\3;\3<\3<\3=\3=\3=\3>\3>\3>\3?\3?\3?\3@\3@\3@\3A"+ + "\3A\3A\3B\3B\3B\3B\3C\3C\3C\3C\3D\3D\3D\3E\3E\3E\3F\3F\3F\3G\3G\3G\3G"+ + "\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3J\3J\3J\3J\3J"+ + "\3J\3J\3J\3J\3K\3K\3K\3K\3K\3K\3L\3L\3L\3L\3L\3L\3L\3M\3M\3M\3N\3N\3N"+ + "\3N\3N\3N\3O\3O\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\5P\u02f4"+ + "\nP\3Q\3Q\3Q\3Q\7Q\u02fa\nQ\fQ\16Q\u02fd\13Q\3Q\3Q\3Q\3R\3R\3R\3R\3R\3"+ + "R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3"+ + "R\3R\3R\3R\3R\3R\3R\3R\3R\5R\u0327\nR\3S\3S\3S\3S\7S\u032d\nS\fS\16S\u0330"+ + "\13S\3S\3S\5S\u0334\nS\3T\3T\3T\3T\5T\u033a\nT\3T\3T\3U\3U\3U\3U\3U\3"+ + "U\3U\3U\3U\5U\u0347\nU\3V\3V\5V\u034b\nV\3W\3W\3W\5W\u0350\nW\3X\3X\3"+ + "X\3X\3X\5X\u0357\nX\3X\7X\u035a\nX\fX\16X\u035d\13X\3X\3X\6X\u0361\nX"+ + "\rX\16X\u0362\3Y\7Y\u0366\nY\fY\16Y\u0369\13Y\3Y\3Y\6Y\u036d\nY\rY\16"+ + "Y\u036e\3Z\3Z\3Z\3Z\3Z\5Z\u0376\nZ\3Z\7Z\u0379\nZ\fZ\16Z\u037c\13Z\3Z"+ + "\3Z\6Z\u0380\nZ\rZ\16Z\u0381\3[\3[\3[\5[\u0387\n[\3[\3[\3[\5[\u038c\n"+ + "[\3\\\3\\\3\\\6\\\u0391\n\\\r\\\16\\\u0392\3\\\3\\\6\\\u0397\n\\\r\\\16"+ + "\\\u0398\5\\\u039b\n\\\3]\6]\u039e\n]\r]\16]\u039f\3^\3^\3^\3^\3^\5^\u03a7"+ + "\n^\3^\6^\u03aa\n^\r^\16^\u03ab\3_\3_\3`\3`\3a\3a\3b\3b\7b\u03b6\nb\f"+ + "b\16b\u03b9\13b\3c\3c\3d\3d\3e\3e\7e\u03c1\ne\fe\16e\u03c4\13e\3e\6e\u03c7"+ + "\ne\re\16e\u03c8\3f\6f\u03cc\nf\rf\16f\u03cd\3f\3f\3g\3g\3g\3g\7g\u03d6"+ + "\ng\fg\16g\u03d9\13g\3g\3g\3h\3h\3h\3h\7h\u03e1\nh\fh\16h\u03e4\13h\3"+ + "h\3h\3h\3h\3h\4\u02fb\u03e2\2i\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13"+ + "\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61"+ + "\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61"+ + "a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087"+ + "E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009b"+ + "O\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00af"+ + "Y\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd\2\u00bf\2\u00c1\2\u00c3"+ + "`\u00c5\2\u00c7\2\u00c9a\u00cbb\u00cdc\u00cfd\3\2\17\3\2$$\3\2))\4\2u"+ + "uww\7\2dfkknnuuyy\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHch\5\2C\\aac|\6\2"+ + "\62;C\\aac|\4\2--//\6\2\13\f\17\17\"\"\u00a2\u00a2\4\2\f\f\17\17\2\u0459"+ + "\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2"+ + "\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2"+ + "\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2"+ + "\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2"+ + "\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3"+ + "\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2"+ + "\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2"+ + "U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3"+ + "\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2"+ + "\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2"+ + "{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085"+ + "\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2"+ + "\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097"+ + "\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2"+ + "\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9"+ + "\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2"+ + "\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb"+ + "\3\2\2\2\2\u00c3\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2"+ + "\2\2\u00cf\3\2\2\2\3\u00d1\3\2\2\2\5\u00d8\3\2\2\2\7\u00da\3\2\2\2\t\u00dc"+ + "\3\2\2\2\13\u00de\3\2\2\2\r\u00e0\3\2\2\2\17\u00e2\3\2\2\2\21\u00e4\3"+ + "\2\2\2\23\u00e6\3\2\2\2\25\u00ec\3\2\2\2\27\u00f3\3\2\2\2\31\u00f9\3\2"+ + "\2\2\33\u0102\3\2\2\2\35\u0109\3\2\2\2\37\u0112\3\2\2\2!\u011c\3\2\2\2"+ + "#\u0124\3\2\2\2%\u0127\3\2\2\2\'\u012c\3\2\2\2)\u0132\3\2\2\2+\u0135\3"+ + "\2\2\2-\u0139\3\2\2\2/\u0140\3\2\2\2\61\u0146\3\2\2\2\63\u014f\3\2\2\2"+ + "\65\u0153\3\2\2\2\67\u0155\3\2\2\29\u0158\3\2\2\2;\u015f\3\2\2\2=\u0168"+ + "\3\2\2\2?\u016a\3\2\2\2A\u016c\3\2\2\2C\u016e\3\2\2\2E\u0175\3\2\2\2G"+ + "\u0177\3\2\2\2I\u017a\3\2\2\2K\u0181\3\2\2\2M\u0188\3\2\2\2O\u018b\3\2"+ + "\2\2Q\u018e\3\2\2\2S\u0190\3\2\2\2U\u0192\3\2\2\2W\u0194\3\2\2\2Y\u0196"+ + "\3\2\2\2[\u0198\3\2\2\2]\u019b\3\2\2\2_\u019e\3\2\2\2a\u01a0\3\2\2\2c"+ + "\u01a2\3\2\2\2e\u01a4\3\2\2\2g\u01a6\3\2\2\2i\u01a9\3\2\2\2k\u01ac\3\2"+ + "\2\2m\u01af\3\2\2\2o\u01b2\3\2\2\2q\u01b4\3\2\2\2s\u01b6\3\2\2\2u\u01b9"+ + "\3\2\2\2w\u01bc\3\2\2\2y\u01be\3\2\2\2{\u01c1\3\2\2\2}\u01c4\3\2\2\2\177"+ + "\u01c7\3\2\2\2\u0081\u01ca\3\2\2\2\u0083\u01cd\3\2\2\2\u0085\u01d1\3\2"+ + "\2\2\u0087\u01d5\3\2\2\2\u0089\u01d8\3\2\2\2\u008b\u01db\3\2\2\2\u008d"+ + "\u01de\3\2\2\2\u008f\u01e6\3\2\2\2\u0091\u01ef\3\2\2\2\u0093\u01f4\3\2"+ + "\2\2\u0095\u01fd\3\2\2\2\u0097\u0203\3\2\2\2\u0099\u020a\3\2\2\2\u009b"+ + "\u020d\3\2\2\2\u009d\u0213\3\2\2\2\u009f\u02f3\3\2\2\2\u00a1\u02f5\3\2"+ + "\2\2\u00a3\u0326\3\2\2\2\u00a5\u0328\3\2\2\2\u00a7\u0335\3\2\2\2\u00a9"+ + "\u0346\3\2\2\2\u00ab\u034a\3\2\2\2\u00ad\u034f\3\2\2\2\u00af\u0356\3\2"+ + "\2\2\u00b1\u0367\3\2\2\2\u00b3\u0375\3\2\2\2\u00b5\u0386\3\2\2\2\u00b7"+ + "\u039a\3\2\2\2\u00b9\u039d\3\2\2\2\u00bb\u03a6\3\2\2\2\u00bd\u03ad\3\2"+ + "\2\2\u00bf\u03af\3\2\2\2\u00c1\u03b1\3\2\2\2\u00c3\u03b3\3\2\2\2\u00c5"+ + "\u03ba\3\2\2\2\u00c7\u03bc\3\2\2\2\u00c9\u03be\3\2\2\2\u00cb\u03cb\3\2"+ + "\2\2\u00cd\u03d1\3\2\2\2\u00cf\u03dc\3\2\2\2\u00d1\u00d2\7k\2\2\u00d2"+ + "\u00d3\7o\2\2\u00d3\u00d4\7r\2\2\u00d4\u00d5\7q\2\2\u00d5\u00d6\7t\2\2"+ + "\u00d6\u00d7\7v\2\2\u00d7\4\3\2\2\2\u00d8\u00d9\7=\2\2\u00d9\6\3\2\2\2"+ + "\u00da\u00db\7.\2\2\u00db\b\3\2\2\2\u00dc\u00dd\7?\2\2\u00dd\n\3\2\2\2"+ + "\u00de\u00df\7*\2\2\u00df\f\3\2\2\2\u00e0\u00e1\7+\2\2\u00e1\16\3\2\2"+ + "\2\u00e2\u00e3\7}\2\2\u00e3\20\3\2\2\2\u00e4\u00e5\7\177\2\2\u00e5\22"+ + "\3\2\2\2\u00e6\u00e7\7e\2\2\u00e7\u00e8\7q\2\2\u00e8\u00e9\7p\2\2\u00e9"+ + "\u00ea\7u\2\2\u00ea\u00eb\7v\2\2\u00eb\24\3\2\2\2\u00ec\u00ed\7g\2\2\u00ed"+ + "\u00ee\7z\2\2\u00ee\u00ef\7v\2\2\u00ef\u00f0\7g\2\2\u00f0\u00f1\7t\2\2"+ + "\u00f1\u00f2\7p\2\2\u00f2\26\3\2\2\2\u00f3\u00f4\7c\2\2\u00f4\u00f5\7"+ + "n\2\2\u00f5\u00f6\7k\2\2\u00f6\u00f7\7i\2\2\u00f7\u00f8\7p\2\2\u00f8\30"+ + "\3\2\2\2\u00f9\u00fa\7t\2\2\u00fa\u00fb\7g\2\2\u00fb\u00fc\7i\2\2\u00fc"+ + "\u00fd\7k\2\2\u00fd\u00fe\7u\2\2\u00fe\u00ff\7v\2\2\u00ff\u0100\7g\2\2"+ + "\u0100\u0101\7t\2\2\u0101\32\3\2\2\2\u0102\u0103\7k\2\2\u0103\u0104\7"+ + "p\2\2\u0104\u0105\7n\2\2\u0105\u0106\7k\2\2\u0106\u0107\7p\2\2\u0107\u0108"+ + "\7g\2\2\u0108\34\3\2\2\2\u0109\u010a\7x\2\2\u010a\u010b\7q\2\2\u010b\u010c"+ + "\7n\2\2\u010c\u010d\7c\2\2\u010d\u010e\7v\2\2\u010e\u010f\7k\2\2\u010f"+ + "\u0110\7n\2\2\u0110\u0111\7g\2\2\u0111\36\3\2\2\2\u0112\u0113\7k\2\2\u0113"+ + "\u0114\7p\2\2\u0114\u0115\7v\2\2\u0115\u0116\7g\2\2\u0116\u0117\7t\2\2"+ + "\u0117\u0118\7t\2\2\u0118\u0119\7w\2\2\u0119\u011a\7r\2\2\u011a\u011b"+ + "\7v\2\2\u011b \3\2\2\2\u011c\u011d\7t\2\2\u011d\u011e\7g\2\2\u011e\u011f"+ + "\7u\2\2\u011f\u0120\7g\2\2\u0120\u0121\7t\2\2\u0121\u0122\7x\2\2\u0122"+ + "\u0123\7g\2\2\u0123\"\3\2\2\2\u0124\u0125\7k\2\2\u0125\u0126\7h\2\2\u0126"+ + "$\3\2\2\2\u0127\u0128\7g\2\2\u0128\u0129\7n\2\2\u0129\u012a\7u\2\2\u012a"+ + "\u012b\7g\2\2\u012b&\3\2\2\2\u012c\u012d\7y\2\2\u012d\u012e\7j\2\2\u012e"+ + "\u012f\7k\2\2\u012f\u0130\7n\2\2\u0130\u0131\7g\2\2\u0131(\3\2\2\2\u0132"+ + "\u0133\7f\2\2\u0133\u0134\7q\2\2\u0134*\3\2\2\2\u0135\u0136\7h\2\2\u0136"+ + "\u0137\7q\2\2\u0137\u0138\7t\2\2\u0138,\3\2\2\2\u0139\u013a\7t\2\2\u013a"+ + "\u013b\7g\2\2\u013b\u013c\7v\2\2\u013c\u013d\7w\2\2\u013d\u013e\7t\2\2"+ + "\u013e\u013f\7p\2\2\u013f.\3\2\2\2\u0140\u0141\7d\2\2\u0141\u0142\7t\2"+ + "\2\u0142\u0143\7g\2\2\u0143\u0144\7c\2\2\u0144\u0145\7m\2\2\u0145\60\3"+ + "\2\2\2\u0146\u0147\7e\2\2\u0147\u0148\7q\2\2\u0148\u0149\7p\2\2\u0149"+ + "\u014a\7v\2\2\u014a\u014b\7k\2\2\u014b\u014c\7p\2\2\u014c\u014d\7w\2\2"+ + "\u014d\u014e\7g\2\2\u014e\62\3\2\2\2\u014f\u0150\7c\2\2\u0150\u0151\7"+ + "u\2\2\u0151\u0152\7o\2\2\u0152\64\3\2\2\2\u0153\u0154\7<\2\2\u0154\66"+ + "\3\2\2\2\u0155\u0156\7\60\2\2\u0156\u0157\7\60\2\2\u01578\3\2\2\2\u0158"+ + "\u0159\7u\2\2\u0159\u015a\7k\2\2\u015a\u015b\7i\2\2\u015b\u015c\7p\2\2"+ + "\u015c\u015d\7g\2\2\u015d\u015e\7f\2\2\u015e:\3\2\2\2\u015f\u0160\7w\2"+ + "\2\u0160\u0161\7p\2\2\u0161\u0162\7u\2\2\u0162\u0163\7k\2\2\u0163\u0164"+ + "\7i\2\2\u0164\u0165\7p\2\2\u0165\u0166\7g\2\2\u0166\u0167\7f\2\2\u0167"+ + "<\3\2\2\2\u0168\u0169\7,\2\2\u0169>\3\2\2\2\u016a\u016b\7]\2\2\u016b@"+ + "\3\2\2\2\u016c\u016d\7_\2\2\u016dB\3\2\2\2\u016e\u016f\7u\2\2\u016f\u0170"+ + "\7v\2\2\u0170\u0171\7t\2\2\u0171\u0172\7w\2\2\u0172\u0173\7e\2\2\u0173"+ + "\u0174\7v\2\2\u0174D\3\2\2\2\u0175\u0176\7\60\2\2\u0176F\3\2\2\2\u0177"+ + "\u0178\7/\2\2\u0178\u0179\7@\2\2\u0179H\3\2\2\2\u017a\u017b\7u\2\2\u017b"+ + "\u017c\7k\2\2\u017c\u017d\7|\2\2\u017d\u017e\7g\2\2\u017e\u017f\7q\2\2"+ + "\u017f\u0180\7h\2\2\u0180J\3\2\2\2\u0181\u0182\7v\2\2\u0182\u0183\7{\2"+ + "\2\u0183\u0184\7r\2\2\u0184\u0185\7g\2\2\u0185\u0186\7k\2\2\u0186\u0187"+ + "\7f\2\2\u0187L\3\2\2\2\u0188\u0189\7/\2\2\u0189\u018a\7/\2\2\u018aN\3"+ + "\2\2\2\u018b\u018c\7-\2\2\u018c\u018d\7-\2\2\u018dP\3\2\2\2\u018e\u018f"+ + "\7-\2\2\u018fR\3\2\2\2\u0190\u0191\7/\2\2\u0191T\3\2\2\2\u0192\u0193\7"+ + "#\2\2\u0193V\3\2\2\2\u0194\u0195\7(\2\2\u0195X\3\2\2\2\u0196\u0197\7\u0080"+ + "\2\2\u0197Z\3\2\2\2\u0198\u0199\7@\2\2\u0199\u019a\7@\2\2\u019a\\\3\2"+ + "\2\2\u019b\u019c\7>\2\2\u019c\u019d\7>\2\2\u019d^\3\2\2\2\u019e\u019f"+ + "\7\61\2\2\u019f`\3\2\2\2\u01a0\u01a1\7\'\2\2\u01a1b\3\2\2\2\u01a2\u01a3"+ + "\7>\2\2\u01a3d\3\2\2\2\u01a4\u01a5\7@\2\2\u01a5f\3\2\2\2\u01a6\u01a7\7"+ + "?\2\2\u01a7\u01a8\7?\2\2\u01a8h\3\2\2\2\u01a9\u01aa\7#\2\2\u01aa\u01ab"+ + "\7?\2\2\u01abj\3\2\2\2\u01ac\u01ad\7>\2\2\u01ad\u01ae\7?\2\2\u01ael\3"+ + "\2\2\2\u01af\u01b0\7@\2\2\u01b0\u01b1\7?\2\2\u01b1n\3\2\2\2\u01b2\u01b3"+ + "\7`\2\2\u01b3p\3\2\2\2\u01b4\u01b5\7~\2\2\u01b5r\3\2\2\2\u01b6\u01b7\7"+ + "(\2\2\u01b7\u01b8\7(\2\2\u01b8t\3\2\2\2\u01b9\u01ba\7~\2\2\u01ba\u01bb"+ + "\7~\2\2\u01bbv\3\2\2\2\u01bc\u01bd\7A\2\2\u01bdx\3\2\2\2\u01be\u01bf\7"+ + "-\2\2\u01bf\u01c0\7?\2\2\u01c0z\3\2\2\2\u01c1\u01c2\7/\2\2\u01c2\u01c3"+ + "\7?\2\2\u01c3|\3\2\2\2\u01c4\u01c5\7,\2\2\u01c5\u01c6\7?\2\2\u01c6~\3"+ + "\2\2\2\u01c7\u01c8\7\61\2\2\u01c8\u01c9\7?\2\2\u01c9\u0080\3\2\2\2\u01ca"+ + "\u01cb\7\'\2\2\u01cb\u01cc\7?\2\2\u01cc\u0082\3\2\2\2\u01cd\u01ce\7>\2"+ + "\2\u01ce\u01cf\7>\2\2\u01cf\u01d0\7?\2\2\u01d0\u0084\3\2\2\2\u01d1\u01d2"+ + "\7@\2\2\u01d2\u01d3\7@\2\2\u01d3\u01d4\7?\2\2\u01d4\u0086\3\2\2\2\u01d5"+ + "\u01d6\7(\2\2\u01d6\u01d7\7?\2\2\u01d7\u0088\3\2\2\2\u01d8\u01d9\7~\2"+ + "\2\u01d9\u01da\7?\2\2\u01da\u008a\3\2\2\2\u01db\u01dc\7`\2\2\u01dc\u01dd"+ + "\7?\2\2\u01dd\u008c\3\2\2\2\u01de\u01df\7m\2\2\u01df\u01e0\7k\2\2\u01e0"+ + "\u01e1\7e\2\2\u01e1\u01e2\7m\2\2\u01e2\u01e3\7c\2\2\u01e3\u01e4\7u\2\2"+ + "\u01e4\u01e5\7o\2\2\u01e5\u008e\3\2\2\2\u01e6\u01e7\7t\2\2\u01e7\u01e8"+ + "\7g\2\2\u01e8\u01e9\7u\2\2\u01e9\u01ea\7q\2\2\u01ea\u01eb\7w\2\2\u01eb"+ + "\u01ec\7t\2\2\u01ec\u01ed\7e\2\2\u01ed\u01ee\7g\2\2\u01ee\u0090\3\2\2"+ + "\2\u01ef\u01f0\7w\2\2\u01f0\u01f1\7u\2\2\u01f1\u01f2\7g\2\2\u01f2\u01f3"+ + "\7u\2\2\u01f3\u0092\3\2\2\2\u01f4\u01f5\7e\2\2\u01f5\u01f6\7n\2\2\u01f6"+ + "\u01f7\7q\2\2\u01f7\u01f8\7d\2\2\u01f8\u01f9\7d\2\2\u01f9\u01fa\7g\2\2"+ + "\u01fa\u01fb\7t\2\2\u01fb\u01fc\7u\2\2\u01fc\u0094\3\2\2\2\u01fd\u01fe"+ + "\7d\2\2\u01fe\u01ff\7{\2\2\u01ff\u0200\7v\2\2\u0200\u0201\7g\2\2\u0201"+ + "\u0202\7u\2\2\u0202\u0096\3\2\2\2\u0203\u0204\7e\2\2\u0204\u0205\7{\2"+ + "\2\u0205\u0206\7e\2\2\u0206\u0207\7n\2\2\u0207\u0208\7g\2\2\u0208\u0209"+ + "\7u\2\2\u0209\u0098\3\2\2\2\u020a\u020b\7r\2\2\u020b\u020c\7e\2\2\u020c"+ + "\u009a\3\2\2\2\u020d\u020e\7\60\2\2\u020e\u020f\7d\2\2\u020f\u0210\7{"+ + "\2\2\u0210\u0211\7v\2\2\u0211\u0212\7g\2\2\u0212\u009c\3\2\2\2\u0213\u0214"+ + "\7%\2\2\u0214\u009e\3\2\2\2\u0215\u0216\7d\2\2\u0216\u0217\7t\2\2\u0217"+ + "\u02f4\7m\2\2\u0218\u0219\7q\2\2\u0219\u021a\7t\2\2\u021a\u02f4\7c\2\2"+ + "\u021b\u021c\7m\2\2\u021c\u021d\7k\2\2\u021d\u02f4\7n\2\2\u021e\u021f"+ + "\7u\2\2\u021f\u0220\7n\2\2\u0220\u02f4\7q\2\2\u0221\u0222\7p\2\2\u0222"+ + "\u0223\7q\2\2\u0223\u02f4\7r\2\2\u0224\u0225\7c\2\2\u0225\u0226\7u\2\2"+ + "\u0226\u02f4\7n\2\2\u0227\u0228\7r\2\2\u0228\u0229\7j\2\2\u0229\u02f4"+ + "\7r\2\2\u022a\u022b\7c\2\2\u022b\u022c\7p\2\2\u022c\u02f4\7e\2\2\u022d"+ + "\u022e\7d\2\2\u022e\u022f\7r\2\2\u022f\u02f4\7n\2\2\u0230\u0231\7e\2\2"+ + "\u0231\u0232\7n\2\2\u0232\u02f4\7e\2\2\u0233\u0234\7l\2\2\u0234\u0235"+ + "\7u\2\2\u0235\u02f4\7t\2\2\u0236\u0237\7c\2\2\u0237\u0238\7p\2\2\u0238"+ + "\u02f4\7f\2\2\u0239\u023a\7t\2\2\u023a\u023b\7n\2\2\u023b\u02f4\7c\2\2"+ + "\u023c\u023d\7d\2\2\u023d\u023e\7k\2\2\u023e\u02f4\7v\2\2\u023f\u0240"+ + "\7t\2\2\u0240\u0241\7q\2\2\u0241\u02f4\7n\2\2\u0242\u0243\7r\2\2\u0243"+ + "\u0244\7n\2\2\u0244\u02f4\7c\2\2\u0245\u0246\7r\2\2\u0246\u0247\7n\2\2"+ + "\u0247\u02f4\7r\2\2\u0248\u0249\7d\2\2\u0249\u024a\7o\2\2\u024a\u02f4"+ + "\7k\2\2\u024b\u024c\7u\2\2\u024c\u024d\7g\2\2\u024d\u02f4\7e\2\2\u024e"+ + "\u024f\7t\2\2\u024f\u0250\7v\2\2\u0250\u02f4\7k\2\2\u0251\u0252\7g\2\2"+ + "\u0252\u0253\7q\2\2\u0253\u02f4\7t\2\2\u0254\u0255\7u\2\2\u0255\u0256"+ + "\7t\2\2\u0256\u02f4\7g\2\2\u0257\u0258\7n\2\2\u0258\u0259\7u\2\2\u0259"+ + "\u02f4\7t\2\2\u025a\u025b\7r\2\2\u025b\u025c\7j\2\2\u025c\u02f4\7c\2\2"+ + "\u025d\u025e\7c\2\2\u025e\u025f\7n\2\2\u025f\u02f4\7t\2\2\u0260\u0261"+ + "\7l\2\2\u0261\u0262\7o\2\2\u0262\u02f4\7r\2\2\u0263\u0264\7d\2\2\u0264"+ + "\u0265\7x\2\2\u0265\u02f4\7e\2\2\u0266\u0267\7e\2\2\u0267\u0268\7n\2\2"+ + "\u0268\u02f4\7k\2\2\u0269\u026a\7t\2\2\u026a\u026b\7v\2\2\u026b\u02f4"+ + "\7u\2\2\u026c\u026d\7c\2\2\u026d\u026e\7f\2\2\u026e\u02f4\7e\2\2\u026f"+ + "\u0270\7t\2\2\u0270\u0271\7t\2\2\u0271\u02f4\7c\2\2\u0272\u0273\7d\2\2"+ + "\u0273\u0274\7x\2\2\u0274\u02f4\7u\2\2\u0275\u0276\7u\2\2\u0276\u0277"+ + "\7g\2\2\u0277\u02f4\7k\2\2\u0278\u0279\7u\2\2\u0279\u027a\7c\2\2\u027a"+ + "\u02f4\7z\2\2\u027b\u027c\7u\2\2\u027c\u027d\7v\2\2\u027d\u02f4\7{\2\2"+ + "\u027e\u027f\7u\2\2\u027f\u0280\7v\2\2\u0280\u02f4\7c\2\2\u0281\u0282"+ + "\7u\2\2\u0282\u0283\7v\2\2\u0283\u02f4\7z\2\2\u0284\u0285\7f\2\2\u0285"+ + "\u0286\7g\2\2\u0286\u02f4\7{\2\2\u0287\u0288\7v\2\2\u0288\u0289\7z\2\2"+ + "\u0289\u02f4\7c\2\2\u028a\u028b\7z\2\2\u028b\u028c\7c\2\2\u028c\u02f4"+ + "\7c\2\2\u028d\u028e\7d\2\2\u028e\u028f\7e\2\2\u028f\u02f4\7e\2\2\u0290"+ + "\u0291\7c\2\2\u0291\u0292\7j\2\2\u0292\u02f4\7z\2\2\u0293\u0294\7v\2\2"+ + "\u0294\u0295\7{\2\2\u0295\u02f4\7c\2\2\u0296\u0297\7v\2\2\u0297\u0298"+ + "\7z\2\2\u0298\u02f4\7u\2\2\u0299\u029a\7v\2\2\u029a\u029b\7c\2\2\u029b"+ + "\u02f4\7u\2\2\u029c\u029d\7u\2\2\u029d\u029e\7j\2\2\u029e\u02f4\7{\2\2"+ + "\u029f\u02a0\7u\2\2\u02a0\u02a1\7j\2\2\u02a1\u02f4\7z\2\2\u02a2\u02a3"+ + "\7n\2\2\u02a3\u02a4\7f\2\2\u02a4\u02f4\7{\2\2\u02a5\u02a6\7n\2\2\u02a6"+ + "\u02a7\7f\2\2\u02a7\u02f4\7c\2\2\u02a8\u02a9\7n\2\2\u02a9\u02aa\7f\2\2"+ + "\u02aa\u02f4\7z\2\2\u02ab\u02ac\7n\2\2\u02ac\u02ad\7c\2\2\u02ad\u02f4"+ + "\7z\2\2\u02ae\u02af\7v\2\2\u02af\u02b0\7c\2\2\u02b0\u02f4\7{\2\2\u02b1"+ + "\u02b2\7v\2\2\u02b2\u02b3\7c\2\2\u02b3\u02f4\7z\2\2\u02b4\u02b5\7d\2\2"+ + "\u02b5\u02b6\7e\2\2\u02b6\u02f4\7u\2\2\u02b7\u02b8\7e\2\2\u02b8\u02b9"+ + "\7n\2\2\u02b9\u02f4\7x\2\2\u02ba\u02bb\7v\2\2\u02bb\u02bc\7u\2\2\u02bc"+ + "\u02f4\7z\2\2\u02bd\u02be\7n\2\2\u02be\u02bf\7c\2\2\u02bf\u02f4\7u\2\2"+ + "\u02c0\u02c1\7e\2\2\u02c1\u02c2\7r\2\2\u02c2\u02f4\7{\2\2\u02c3\u02c4"+ + "\7e\2\2\u02c4\u02c5\7o\2\2\u02c5\u02f4\7r\2\2\u02c6\u02c7\7e\2\2\u02c7"+ + "\u02c8\7r\2\2\u02c8\u02f4\7z\2\2\u02c9\u02ca\7f\2\2\u02ca\u02cb\7e\2\2"+ + "\u02cb\u02f4\7r\2\2\u02cc\u02cd\7f\2\2\u02cd\u02ce\7g\2\2\u02ce\u02f4"+ + "\7e\2\2\u02cf\u02d0\7k\2\2\u02d0\u02d1\7p\2\2\u02d1\u02f4\7e\2\2\u02d2"+ + "\u02d3\7c\2\2\u02d3\u02d4\7z\2\2\u02d4\u02f4\7u\2\2\u02d5\u02d6\7d\2\2"+ + "\u02d6\u02d7\7p\2\2\u02d7\u02f4\7g\2\2\u02d8\u02d9\7e\2\2\u02d9\u02da"+ + "\7n\2\2\u02da\u02f4\7f\2\2\u02db\u02dc\7u\2\2\u02dc\u02dd\7d\2\2\u02dd"+ + "\u02f4\7e\2\2\u02de\u02df\7k\2\2\u02df\u02e0\7u\2\2\u02e0\u02f4\7e\2\2"+ + "\u02e1\u02e2\7k\2\2\u02e2\u02e3\7p\2\2\u02e3\u02f4\7z\2\2\u02e4\u02e5"+ + "\7d\2\2\u02e5\u02e6\7g\2\2\u02e6\u02f4\7s\2\2\u02e7\u02e8\7u\2\2\u02e8"+ + "\u02e9\7g\2\2\u02e9\u02f4\7f\2\2\u02ea\u02eb\7f\2\2\u02eb\u02ec\7g\2\2"+ + "\u02ec\u02f4\7z\2\2\u02ed\u02ee\7k\2\2\u02ee\u02ef\7p\2\2\u02ef\u02f4"+ + "\7{\2\2\u02f0\u02f1\7t\2\2\u02f1\u02f2\7q\2\2\u02f2\u02f4\7t\2\2\u02f3"+ + "\u0215\3\2\2\2\u02f3\u0218\3\2\2\2\u02f3\u021b\3\2\2\2\u02f3\u021e\3\2"+ + "\2\2\u02f3\u0221\3\2\2\2\u02f3\u0224\3\2\2\2\u02f3\u0227\3\2\2\2\u02f3"+ + "\u022a\3\2\2\2\u02f3\u022d\3\2\2\2\u02f3\u0230\3\2\2\2\u02f3\u0233\3\2"+ + "\2\2\u02f3\u0236\3\2\2\2\u02f3\u0239\3\2\2\2\u02f3\u023c\3\2\2\2\u02f3"+ + "\u023f\3\2\2\2\u02f3\u0242\3\2\2\2\u02f3\u0245\3\2\2\2\u02f3\u0248\3\2"+ + "\2\2\u02f3\u024b\3\2\2\2\u02f3\u024e\3\2\2\2\u02f3\u0251\3\2\2\2\u02f3"+ + "\u0254\3\2\2\2\u02f3\u0257\3\2\2\2\u02f3\u025a\3\2\2\2\u02f3\u025d\3\2"+ + "\2\2\u02f3\u0260\3\2\2\2\u02f3\u0263\3\2\2\2\u02f3\u0266\3\2\2\2\u02f3"+ + "\u0269\3\2\2\2\u02f3\u026c\3\2\2\2\u02f3\u026f\3\2\2\2\u02f3\u0272\3\2"+ + "\2\2\u02f3\u0275\3\2\2\2\u02f3\u0278\3\2\2\2\u02f3\u027b\3\2\2\2\u02f3"+ + "\u027e\3\2\2\2\u02f3\u0281\3\2\2\2\u02f3\u0284\3\2\2\2\u02f3\u0287\3\2"+ + "\2\2\u02f3\u028a\3\2\2\2\u02f3\u028d\3\2\2\2\u02f3\u0290\3\2\2\2\u02f3"+ + "\u0293\3\2\2\2\u02f3\u0296\3\2\2\2\u02f3\u0299\3\2\2\2\u02f3\u029c\3\2"+ + "\2\2\u02f3\u029f\3\2\2\2\u02f3\u02a2\3\2\2\2\u02f3\u02a5\3\2\2\2\u02f3"+ + "\u02a8\3\2\2\2\u02f3\u02ab\3\2\2\2\u02f3\u02ae\3\2\2\2\u02f3\u02b1\3\2"+ + "\2\2\u02f3\u02b4\3\2\2\2\u02f3\u02b7\3\2\2\2\u02f3\u02ba\3\2\2\2\u02f3"+ + "\u02bd\3\2\2\2\u02f3\u02c0\3\2\2\2\u02f3\u02c3\3\2\2\2\u02f3\u02c6\3\2"+ + "\2\2\u02f3\u02c9\3\2\2\2\u02f3\u02cc\3\2\2\2\u02f3\u02cf\3\2\2\2\u02f3"+ + "\u02d2\3\2\2\2\u02f3\u02d5\3\2\2\2\u02f3\u02d8\3\2\2\2\u02f3\u02db\3\2"+ + "\2\2\u02f3\u02de\3\2\2\2\u02f3\u02e1\3\2\2\2\u02f3\u02e4\3\2\2\2\u02f3"+ + "\u02e7\3\2\2\2\u02f3\u02ea\3\2\2\2\u02f3\u02ed\3\2\2\2\u02f3\u02f0\3\2"+ + "\2\2\u02f4\u00a0\3\2\2\2\u02f5\u02f6\7}\2\2\u02f6\u02f7\7}\2\2\u02f7\u02fb"+ + "\3\2\2\2\u02f8\u02fa\13\2\2\2\u02f9\u02f8\3\2\2\2\u02fa\u02fd\3\2\2\2"+ + "\u02fb\u02fc\3\2\2\2\u02fb\u02f9\3\2\2\2\u02fc\u02fe\3\2\2\2\u02fd\u02fb"+ + "\3\2\2\2\u02fe\u02ff\7\177\2\2\u02ff\u0300\7\177\2\2\u0300\u00a2\3\2\2"+ + "\2\u0301\u0302\7d\2\2\u0302\u0303\7{\2\2\u0303\u0304\7v\2\2\u0304\u0327"+ + "\7g\2\2\u0305\u0306\7y\2\2\u0306\u0307\7q\2\2\u0307\u0308\7t\2\2\u0308"+ + "\u0327\7f\2\2\u0309\u030a\7f\2\2\u030a\u030b\7y\2\2\u030b\u030c\7q\2\2"+ + "\u030c\u030d\7t\2\2\u030d\u0327\7f\2\2\u030e\u030f\7d\2\2\u030f\u0310"+ + "\7q\2\2\u0310\u0311\7q\2\2\u0311\u0327\7n\2\2\u0312\u0313\7e\2\2\u0313"+ + "\u0314\7j\2\2\u0314\u0315\7c\2\2\u0315\u0327\7t\2\2\u0316\u0317\7u\2\2"+ + "\u0317\u0318\7j\2\2\u0318\u0319\7q\2\2\u0319\u031a\7t\2\2\u031a\u0327"+ + "\7v\2\2\u031b\u031c\7k\2\2\u031c\u031d\7p\2\2\u031d\u0327\7v\2\2\u031e"+ + "\u031f\7n\2\2\u031f\u0320\7q\2\2\u0320\u0321\7p\2\2\u0321\u0327\7i\2\2"+ + "\u0322\u0323\7x\2\2\u0323\u0324\7q\2\2\u0324\u0325\7k\2\2\u0325\u0327"+ + "\7f\2\2\u0326\u0301\3\2\2\2\u0326\u0305\3\2\2\2\u0326\u0309\3\2\2\2\u0326"+ + "\u030e\3\2\2\2\u0326\u0312\3\2\2\2\u0326\u0316\3\2\2\2\u0326\u031b\3\2"+ + "\2\2\u0326\u031e\3\2\2\2\u0326\u0322\3\2\2\2\u0327\u00a4\3\2\2\2\u0328"+ + "\u032e\7$\2\2\u0329\u032a\7^\2\2\u032a\u032d\7$\2\2\u032b\u032d\n\2\2"+ + "\2\u032c\u0329\3\2\2\2\u032c\u032b\3\2\2\2\u032d\u0330\3\2\2\2\u032e\u032c"+ + "\3\2\2\2\u032e\u032f\3\2\2\2\u032f\u0331\3\2\2\2\u0330\u032e\3\2\2\2\u0331"+ + "\u0333\7$\2\2\u0332\u0334\7|\2\2\u0333\u0332\3\2\2\2\u0333\u0334\3\2\2"+ + "\2\u0334\u00a6\3\2\2\2\u0335\u0339\7)\2\2\u0336\u0337\7^\2\2\u0337\u033a"+ + "\7)\2\2\u0338\u033a\n\3\2\2\u0339\u0336\3\2\2\2\u0339\u0338\3\2\2\2\u033a"+ + "\u033b\3\2\2\2\u033b\u033c\7)\2\2\u033c\u00a8\3\2\2\2\u033d\u033e\7v\2"+ + "\2\u033e\u033f\7t\2\2\u033f\u0340\7w\2\2\u0340\u0347\7g\2\2\u0341\u0342"+ + "\7h\2\2\u0342\u0343\7c\2\2\u0343\u0344\7n\2\2\u0344\u0345\7u\2\2\u0345"+ + "\u0347\7g\2\2\u0346\u033d\3\2\2\2\u0346\u0341\3\2\2\2\u0347\u00aa\3\2"+ + "\2\2\u0348\u034b\5\u00adW\2\u0349\u034b\5\u00b5[\2\u034a\u0348\3\2\2\2"+ + "\u034a\u0349\3\2\2\2\u034b\u00ac\3\2\2\2\u034c\u0350\5\u00afX\2\u034d"+ + "\u0350\5\u00b1Y\2\u034e\u0350\5\u00b3Z\2\u034f\u034c\3\2\2\2\u034f\u034d"+ + "\3\2\2\2\u034f\u034e\3\2\2\2\u0350\u00ae\3\2\2\2\u0351\u0357\7\'\2\2\u0352"+ + "\u0353\7\62\2\2\u0353\u0357\7d\2\2\u0354\u0355\7\62\2\2\u0355\u0357\7"+ + "D\2\2\u0356\u0351\3\2\2\2\u0356\u0352\3\2\2\2\u0356\u0354\3\2\2\2\u0357"+ + "\u035b\3\2\2\2\u0358\u035a\5\u00bd_\2\u0359\u0358\3\2\2\2\u035a\u035d"+ + "\3\2\2\2\u035b\u0359\3\2\2\2\u035b\u035c\3\2\2\2\u035c\u035e\3\2\2\2\u035d"+ + "\u035b\3\2\2\2\u035e\u0360\7\60\2\2\u035f\u0361\5\u00bd_\2\u0360\u035f"+ + "\3\2\2\2\u0361\u0362\3\2\2\2\u0362\u0360\3\2\2\2\u0362\u0363\3\2\2\2\u0363"+ + "\u00b0\3\2\2\2\u0364\u0366\5\u00bf`\2\u0365\u0364\3\2\2\2\u0366\u0369"+ + "\3\2\2\2\u0367\u0365\3\2\2\2\u0367\u0368\3\2\2\2\u0368\u036a\3\2\2\2\u0369"+ + "\u0367\3\2\2\2\u036a\u036c\7\60\2\2\u036b\u036d\5\u00bf`\2\u036c\u036b"+ + "\3\2\2\2\u036d\u036e\3\2\2\2\u036e\u036c\3\2\2\2\u036e\u036f\3\2\2\2\u036f"+ + "\u00b2\3\2\2\2\u0370\u0376\7&\2\2\u0371\u0372\7\62\2\2\u0372\u0376\7z"+ + "\2\2\u0373\u0374\7\62\2\2\u0374\u0376\7Z\2\2\u0375\u0370\3\2\2\2\u0375"+ + "\u0371\3\2\2\2\u0375\u0373\3\2\2\2\u0376\u037a\3\2\2\2\u0377\u0379\5\u00c1"+ + "a\2\u0378\u0377\3\2\2\2\u0379\u037c\3\2\2\2\u037a\u0378\3\2\2\2\u037a"+ + "\u037b\3\2\2\2\u037b\u037d\3\2\2\2\u037c\u037a\3\2\2\2\u037d\u037f\7\60"+ + "\2\2\u037e\u0380\5\u00c1a\2\u037f\u037e\3\2\2\2\u0380\u0381\3\2\2\2\u0381"+ + "\u037f\3\2\2\2\u0381\u0382\3\2\2\2\u0382\u00b4\3\2\2\2\u0383\u0387\5\u00b9"+ + "]\2\u0384\u0387\5\u00bb^\2\u0385\u0387\5\u00b7\\\2\u0386\u0383\3\2\2\2"+ + "\u0386\u0384\3\2\2\2\u0386\u0385\3\2\2\2\u0387\u038b\3\2\2\2\u0388\u0389"+ + "\t\4\2\2\u0389\u038c\t\5\2\2\u038a\u038c\7n\2\2\u038b\u0388\3\2\2\2\u038b"+ + "\u038a\3\2\2\2\u038b\u038c\3\2\2\2\u038c\u00b6\3\2\2\2\u038d\u038e\7\62"+ + "\2\2\u038e\u0390\t\6\2\2\u038f\u0391\5\u00bd_\2\u0390\u038f\3\2\2\2\u0391"+ + "\u0392\3\2\2\2\u0392\u0390\3\2\2\2\u0392\u0393\3\2\2\2\u0393\u039b\3\2"+ + "\2\2\u0394\u0396\7\'\2\2\u0395\u0397\5\u00bd_\2\u0396\u0395\3\2\2\2\u0397"+ + "\u0398\3\2\2\2\u0398\u0396\3\2\2\2\u0398\u0399\3\2\2\2\u0399\u039b\3\2"+ + "\2\2\u039a\u038d\3\2\2\2\u039a\u0394\3\2\2\2\u039b\u00b8\3\2\2\2\u039c"+ + "\u039e\5\u00bf`\2\u039d\u039c\3\2\2\2\u039e\u039f\3\2\2\2\u039f\u039d"+ + "\3\2\2\2\u039f\u03a0\3\2\2\2\u03a0\u00ba\3\2\2\2\u03a1\u03a7\7&\2\2\u03a2"+ + "\u03a3\7\62\2\2\u03a3\u03a7\7z\2\2\u03a4\u03a5\7\62\2\2\u03a5\u03a7\7"+ + "Z\2\2\u03a6\u03a1\3\2\2\2\u03a6\u03a2\3\2\2\2\u03a6\u03a4\3\2\2\2\u03a7"+ + "\u03a9\3\2\2\2\u03a8\u03aa\5\u00c1a\2\u03a9\u03a8\3\2\2\2\u03aa\u03ab"+ + "\3\2\2\2\u03ab\u03a9\3\2\2\2\u03ab\u03ac\3\2\2\2\u03ac\u00bc\3\2\2\2\u03ad"+ + "\u03ae\t\7\2\2\u03ae\u00be\3\2\2\2\u03af\u03b0\t\b\2\2\u03b0\u00c0\3\2"+ + "\2\2\u03b1\u03b2\t\t\2\2\u03b2\u00c2\3\2\2\2\u03b3\u03b7\5\u00c5c\2\u03b4"+ + "\u03b6\5\u00c7d\2\u03b5\u03b4\3\2\2\2\u03b6\u03b9\3\2\2\2\u03b7\u03b5"+ + "\3\2\2\2\u03b7\u03b8\3\2\2\2\u03b8\u00c4\3\2\2\2\u03b9\u03b7\3\2\2\2\u03ba"+ + "\u03bb\t\n\2\2\u03bb\u00c6\3\2\2\2\u03bc\u03bd\t\13\2\2\u03bd\u00c8\3"+ + "\2\2\2\u03be\u03c2\7#\2\2\u03bf\u03c1\5\u00c7d\2\u03c0\u03bf\3\2\2\2\u03c1"+ + "\u03c4\3\2\2\2\u03c2\u03c0\3\2\2\2\u03c2\u03c3\3\2\2\2\u03c3\u03c6\3\2"+ + "\2\2\u03c4\u03c2\3\2\2\2\u03c5\u03c7\t\f\2\2\u03c6\u03c5\3\2\2\2\u03c7"+ + "\u03c8\3\2\2\2\u03c8\u03c6\3\2\2\2\u03c8\u03c9\3\2\2\2\u03c9\u00ca\3\2"+ + "\2\2\u03ca\u03cc\t\r\2\2\u03cb\u03ca\3\2\2\2\u03cc\u03cd\3\2\2\2\u03cd"+ + "\u03cb\3\2\2\2\u03cd\u03ce\3\2\2\2\u03ce\u03cf\3\2\2\2\u03cf\u03d0\bf"+ + "\2\2\u03d0\u00cc\3\2\2\2\u03d1\u03d2\7\61\2\2\u03d2\u03d3\7\61\2\2\u03d3"+ + "\u03d7\3\2\2\2\u03d4\u03d6\n\16\2\2\u03d5\u03d4\3\2\2\2\u03d6\u03d9\3"+ + "\2\2\2\u03d7\u03d5\3\2\2\2\u03d7\u03d8\3\2\2\2\u03d8\u03da\3\2\2\2\u03d9"+ + "\u03d7\3\2\2\2\u03da\u03db\bg\3\2\u03db\u00ce\3\2\2\2\u03dc\u03dd\7\61"+ + "\2\2\u03dd\u03de\7,\2\2\u03de\u03e2\3\2\2\2\u03df\u03e1\13\2\2\2\u03e0"+ + "\u03df\3\2\2\2\u03e1\u03e4\3\2\2\2\u03e2\u03e3\3\2\2\2\u03e2\u03e0\3\2"+ + "\2\2\u03e3\u03e5\3\2\2\2\u03e4\u03e2\3\2\2\2\u03e5\u03e6\7,\2\2\u03e6"+ + "\u03e7\7\61\2\2\u03e7\u03e8\3\2\2\2\u03e8\u03e9\bh\3\2\u03e9\u00d0\3\2"+ + "\2\2#\2\u02f3\u02fb\u0326\u032c\u032e\u0333\u0339\u0346\u034a\u034f\u0356"+ + "\u035b\u0362\u0367\u036e\u0375\u037a\u0381\u0386\u038b\u0392\u0398\u039a"+ + "\u039f\u03a6\u03ab\u03b7\u03c2\u03c8\u03cd\u03d7\u03e2\4\2\3\2\2\4\2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens index a303b96fe..42dfa728a 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens +++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens @@ -75,26 +75,27 @@ T__73=74 T__74=75 T__75=76 T__76=77 -MNEMONIC=78 -KICKASM=79 -SIMPLETYPE=80 -STRING=81 -CHAR=82 -BOOLEAN=83 -NUMBER=84 -NUMFLOAT=85 -BINFLOAT=86 -DECFLOAT=87 -HEXFLOAT=88 -NUMINT=89 -BININTEGER=90 -DECINTEGER=91 -HEXINTEGER=92 -NAME=93 -ASMREL=94 -WS=95 -COMMENT_LINE=96 -COMMENT_BLOCK=97 +T__77=78 +MNEMONIC=79 +KICKASM=80 +SIMPLETYPE=81 +STRING=82 +CHAR=83 +BOOLEAN=84 +NUMBER=85 +NUMFLOAT=86 +BINFLOAT=87 +DECFLOAT=88 +HEXFLOAT=89 +NUMINT=90 +BININTEGER=91 +DECINTEGER=92 +HEXINTEGER=93 +NAME=94 +ASMREL=95 +WS=96 +COMMENT_LINE=97 +COMMENT_BLOCK=98 'import'=1 ';'=2 ','=3 @@ -128,47 +129,48 @@ COMMENT_BLOCK=97 '['=31 ']'=32 'struct'=33 -'sizeof'=34 -'typeid'=35 -'--'=36 -'++'=37 -'+'=38 -'-'=39 -'!'=40 -'&'=41 -'~'=42 -'>>'=43 -'<<'=44 -'/'=45 -'%'=46 -'<'=47 -'>'=48 -'=='=49 -'!='=50 -'<='=51 -'>='=52 -'^'=53 -'|'=54 -'&&'=55 -'||'=56 -'?'=57 -'+='=58 -'-='=59 -'*='=60 -'/='=61 -'%='=62 -'<<='=63 -'>>='=64 -'&='=65 -'|='=66 -'^='=67 -'kickasm'=68 -'resource'=69 -'uses'=70 -'clobbers'=71 -'bytes'=72 -'cycles'=73 -'pc'=74 -'.byte'=75 -'#'=76 -'.'=77 +'.'=34 +'->'=35 +'sizeof'=36 +'typeid'=37 +'--'=38 +'++'=39 +'+'=40 +'-'=41 +'!'=42 +'&'=43 +'~'=44 +'>>'=45 +'<<'=46 +'/'=47 +'%'=48 +'<'=49 +'>'=50 +'=='=51 +'!='=52 +'<='=53 +'>='=54 +'^'=55 +'|'=56 +'&&'=57 +'||'=58 +'?'=59 +'+='=60 +'-='=61 +'*='=62 +'/='=63 +'%='=64 +'<<='=65 +'>>='=66 +'&='=67 +'|='=68 +'^='=69 +'kickasm'=70 +'resource'=71 +'uses'=72 +'clobbers'=73 +'bytes'=74 +'cycles'=75 +'pc'=76 +'.byte'=77 +'#'=78 diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java index 950823cc9..24069cabb 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java @@ -715,6 +715,30 @@ public interface KickCListener extends ParseTreeListener { * @param ctx the parse tree */ void exitExprChar(KickCParser.ExprCharContext ctx); + /** + * Enter a parse tree produced by the {@code exprArrow} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + */ + void enterExprArrow(KickCParser.ExprArrowContext ctx); + /** + * Exit a parse tree produced by the {@code exprArrow} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + */ + void exitExprArrow(KickCParser.ExprArrowContext ctx); + /** + * Enter a parse tree produced by the {@code exprDot} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + */ + void enterExprDot(KickCParser.ExprDotContext ctx); + /** + * Exit a parse tree produced by the {@code exprDot} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + */ + void exitExprDot(KickCParser.ExprDotContext ctx); /** * Enter a parse tree produced by the {@code initList} * labeled alternative in {@link KickCParser#expr}. diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java index 02a84e4b0..57be1778b 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java @@ -27,10 +27,10 @@ public class KickCParser extends Parser { T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, - T__73=74, T__74=75, T__75=76, T__76=77, MNEMONIC=78, KICKASM=79, SIMPLETYPE=80, - STRING=81, CHAR=82, BOOLEAN=83, NUMBER=84, NUMFLOAT=85, BINFLOAT=86, DECFLOAT=87, - HEXFLOAT=88, NUMINT=89, BININTEGER=90, DECINTEGER=91, HEXINTEGER=92, NAME=93, - ASMREL=94, WS=95, COMMENT_LINE=96, COMMENT_BLOCK=97; + T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, MNEMONIC=79, KICKASM=80, + SIMPLETYPE=81, STRING=82, CHAR=83, BOOLEAN=84, NUMBER=85, NUMFLOAT=86, + BINFLOAT=87, DECFLOAT=88, HEXFLOAT=89, NUMINT=90, BININTEGER=91, DECINTEGER=92, + HEXINTEGER=93, NAME=94, ASMREL=95, WS=96, COMMENT_LINE=97, COMMENT_BLOCK=98; public static final int RULE_file = 0, RULE_asmFile = 1, RULE_importSeq = 2, RULE_importDecl = 3, RULE_declSeq = 4, RULE_decl = 5, RULE_declTypes = 6, RULE_declVariables = 7, @@ -58,12 +58,12 @@ public class KickCParser extends Parser { "'extern'", "'align'", "'register'", "'inline'", "'volatile'", "'interrupt'", "'reserve'", "'if'", "'else'", "'while'", "'do'", "'for'", "'return'", "'break'", "'continue'", "'asm'", "':'", "'..'", "'signed'", "'unsigned'", - "'*'", "'['", "']'", "'struct'", "'sizeof'", "'typeid'", "'--'", "'++'", - "'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", - "'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", - "'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", - "'^='", "'kickasm'", "'resource'", "'uses'", "'clobbers'", "'bytes'", - "'cycles'", "'pc'", "'.byte'", "'#'", "'.'" + "'*'", "'['", "']'", "'struct'", "'.'", "'->'", "'sizeof'", "'typeid'", + "'--'", "'++'", "'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", + "'%'", "'<'", "'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", + "'||'", "'?'", "'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", + "'&='", "'|='", "'^='", "'kickasm'", "'resource'", "'uses'", "'clobbers'", + "'bytes'", "'cycles'", "'pc'", "'.byte'", "'#'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null, null, @@ -72,7 +72,7 @@ public class KickCParser extends Parser { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", + null, null, null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK" @@ -375,7 +375,7 @@ public class KickCParser extends Parser { setState(93); _errHandler.sync(this); _la = _input.LA(1); - } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==T__67 || _la==SIMPLETYPE ); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==T__69 || _la==SIMPLETYPE ); } } catch (RecognitionException re) { @@ -811,7 +811,7 @@ public class KickCParser extends Parser { setState(147); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 70)) & ~0x3f) == 0 && ((1L << (_la - 70)) & ((1L << (T__69 - 70)) | (1L << (SIMPLETYPE - 70)) | (1L << (STRING - 70)) | (1L << (CHAR - 70)) | (1L << (BOOLEAN - 70)) | (1L << (NUMBER - 70)) | (1L << (NAME - 70)))) != 0)) { { setState(146); stmtSeq(); @@ -1402,7 +1402,7 @@ public class KickCParser extends Parser { setState(204); _errHandler.sync(this); _la = _input.LA(1); - } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0) ); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 70)) & ~0x3f) == 0 && ((1L << (_la - 70)) & ((1L << (T__69 - 70)) | (1L << (SIMPLETYPE - 70)) | (1L << (STRING - 70)) | (1L << (CHAR - 70)) | (1L << (BOOLEAN - 70)) | (1L << (NUMBER - 70)) | (1L << (NAME - 70)))) != 0) ); } } catch (RecognitionException re) { @@ -1713,7 +1713,7 @@ public class KickCParser extends Parser { setState(211); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 70)) & ~0x3f) == 0 && ((1L << (_la - 70)) & ((1L << (T__69 - 70)) | (1L << (SIMPLETYPE - 70)) | (1L << (STRING - 70)) | (1L << (CHAR - 70)) | (1L << (BOOLEAN - 70)) | (1L << (NUMBER - 70)) | (1L << (NAME - 70)))) != 0)) { { setState(210); stmtSeq(); @@ -1865,7 +1865,7 @@ public class KickCParser extends Parser { setState(266); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 82)) & ~0x3f) == 0 && ((1L << (_la - 82)) & ((1L << (STRING - 82)) | (1L << (CHAR - 82)) | (1L << (BOOLEAN - 82)) | (1L << (NUMBER - 82)) | (1L << (NAME - 82)))) != 0)) { { setState(265); commaExpr(0); @@ -2027,7 +2027,7 @@ public class KickCParser extends Parser { setState(289); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 82)) & ~0x3f) == 0 && ((1L << (_la - 82)) & ((1L << (STRING - 82)) | (1L << (CHAR - 82)) | (1L << (BOOLEAN - 82)) | (1L << (NUMBER - 82)) | (1L << (NAME - 82)))) != 0)) { { setState(288); commaExpr(0); @@ -2456,7 +2456,7 @@ public class KickCParser extends Parser { setState(327); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 82)) & ~0x3f) == 0 && ((1L << (_la - 82)) & ((1L << (STRING - 82)) | (1L << (CHAR - 82)) | (1L << (BOOLEAN - 82)) | (1L << (NUMBER - 82)) | (1L << (NAME - 82)))) != 0)) { { setState(326); expr(0); @@ -2945,6 +2945,46 @@ public class KickCParser extends Parser { else return visitor.visitChildren(this); } } + public static class ExprArrowContext extends ExprContext { + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); + } + public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); } + public ExprArrowContext(ExprContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).enterExprArrow(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).exitExprArrow(this); + } + @Override + public <T> T accept(ParseTreeVisitor<? extends T> visitor) { + if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitExprArrow(this); + else return visitor.visitChildren(this); + } + } + public static class ExprDotContext extends ExprContext { + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); + } + public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); } + public ExprDotContext(ExprContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).enterExprDot(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).exitExprDot(this); + } + @Override + public <T> T accept(ParseTreeVisitor<? extends T> visitor) { + if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitExprDot(this); + else return visitor.visitChildren(this); + } + } public static class InitListContext extends ExprContext { public List<ExprContext> expr() { return getRuleContexts(ExprContext.class); @@ -3234,7 +3274,7 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; setState(372); - match(T__33); + match(T__35); setState(373); match(T__4); setState(376); @@ -3263,7 +3303,7 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; setState(380); - match(T__34); + match(T__36); setState(381); match(T__4); setState(384); @@ -3308,7 +3348,7 @@ public class KickCParser extends Parser { _prevctx = _localctx; setState(393); _la = _input.LA(1); - if ( !(_la==T__35 || _la==T__36) ) { + if ( !(_la==T__37 || _la==T__38) ) { _errHandler.recoverInline(this); } else { @@ -3338,7 +3378,7 @@ public class KickCParser extends Parser { _prevctx = _localctx; setState(397); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -3357,7 +3397,7 @@ public class KickCParser extends Parser { _prevctx = _localctx; setState(399); _la = _input.LA(1); - if ( !(_la==T__46 || _la==T__47) ) { + if ( !(_la==T__48 || _la==T__49) ) { _errHandler.recoverInline(this); } else { @@ -3463,7 +3503,7 @@ public class KickCParser extends Parser { break; } _ctx.stop = _input.LT(-1); - setState(477); + setState(483); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,43,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -3471,7 +3511,7 @@ public class KickCParser extends Parser { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(475); + setState(481); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,42,_ctx) ) { case 1: @@ -3482,7 +3522,7 @@ public class KickCParser extends Parser { if (!(precpred(_ctx, 19))) throw new FailedPredicateException(this, "precpred(_ctx, 19)"); setState(424); _la = _input.LA(1); - if ( !(_la==T__42 || _la==T__43) ) { + if ( !(_la==T__44 || _la==T__45) ) { _errHandler.recoverInline(this); } else { @@ -3502,7 +3542,7 @@ public class KickCParser extends Parser { if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)"); setState(427); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__29) | (1L << T__44) | (1L << T__45))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__29) | (1L << T__46) | (1L << T__47))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -3522,7 +3562,7 @@ public class KickCParser extends Parser { if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)"); setState(430); _la = _input.LA(1); - if ( !(_la==T__37 || _la==T__38) ) { + if ( !(_la==T__39 || _la==T__40) ) { _errHandler.recoverInline(this); } else { @@ -3542,7 +3582,7 @@ public class KickCParser extends Parser { if (!(precpred(_ctx, 15))) throw new FailedPredicateException(this, "precpred(_ctx, 15)"); setState(433); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__46) | (1L << T__47) | (1L << T__48) | (1L << T__49) | (1L << T__50) | (1L << T__51))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__48) | (1L << T__49) | (1L << T__50) | (1L << T__51) | (1L << T__52) | (1L << T__53))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -3562,7 +3602,7 @@ public class KickCParser extends Parser { if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)"); { setState(436); - match(T__40); + match(T__42); } setState(437); expr(15); @@ -3576,7 +3616,7 @@ public class KickCParser extends Parser { if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); { setState(439); - match(T__52); + match(T__54); } setState(440); expr(14); @@ -3590,7 +3630,7 @@ public class KickCParser extends Parser { if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); { setState(442); - match(T__53); + match(T__55); } setState(443); expr(13); @@ -3604,7 +3644,7 @@ public class KickCParser extends Parser { if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); { setState(445); - match(T__54); + match(T__56); } setState(446); expr(12); @@ -3618,7 +3658,7 @@ public class KickCParser extends Parser { if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); { setState(448); - match(T__55); + match(T__57); } setState(449); expr(11); @@ -3631,7 +3671,7 @@ public class KickCParser extends Parser { setState(450); if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); setState(451); - match(T__56); + match(T__58); setState(452); expr(0); setState(453); @@ -3660,7 +3700,7 @@ public class KickCParser extends Parser { if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); setState(460); _la = _input.LA(1); - if ( !(((((_la - 58)) & ~0x3f) == 0 && ((1L << (_la - 58)) & ((1L << (T__57 - 58)) | (1L << (T__58 - 58)) | (1L << (T__59 - 58)) | (1L << (T__60 - 58)) | (1L << (T__61 - 58)) | (1L << (T__62 - 58)) | (1L << (T__63 - 58)) | (1L << (T__64 - 58)) | (1L << (T__65 - 58)) | (1L << (T__66 - 58)))) != 0)) ) { + if ( !(((((_la - 60)) & ~0x3f) == 0 && ((1L << (_la - 60)) & ((1L << (T__59 - 60)) | (1L << (T__60 - 60)) | (1L << (T__61 - 60)) | (1L << (T__62 - 60)) | (1L << (T__63 - 60)) | (1L << (T__64 - 60)) | (1L << (T__65 - 60)) | (1L << (T__66 - 60)) | (1L << (T__67 - 60)) | (1L << (T__68 - 60)))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -3674,49 +3714,73 @@ public class KickCParser extends Parser { break; case 13: { - _localctx = new ExprCallContext(new ExprContext(_parentctx, _parentState)); + _localctx = new ExprDotContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); setState(462); - if (!(precpred(_ctx, 28))) throw new FailedPredicateException(this, "precpred(_ctx, 28)"); + if (!(precpred(_ctx, 30))) throw new FailedPredicateException(this, "precpred(_ctx, 30)"); setState(463); - match(T__4); - setState(465); - _errHandler.sync(this); - _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) { - { - setState(464); - parameterList(); - } - } - - setState(467); - match(T__5); + match(T__33); + setState(464); + match(NAME); } break; case 14: { - _localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState)); + _localctx = new ExprArrowContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(468); - if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)"); - setState(469); - match(T__30); - setState(470); - commaExpr(0); - setState(471); - match(T__31); + setState(465); + if (!(precpred(_ctx, 29))) throw new FailedPredicateException(this, "precpred(_ctx, 29)"); + setState(466); + match(T__34); + setState(467); + match(NAME); } break; case 15: + { + _localctx = new ExprCallContext(new ExprContext(_parentctx, _parentState)); + pushNewRecursionContext(_localctx, _startState, RULE_expr); + setState(468); + if (!(precpred(_ctx, 28))) throw new FailedPredicateException(this, "precpred(_ctx, 28)"); + setState(469); + match(T__4); + setState(471); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 82)) & ~0x3f) == 0 && ((1L << (_la - 82)) & ((1L << (STRING - 82)) | (1L << (CHAR - 82)) | (1L << (BOOLEAN - 82)) | (1L << (NUMBER - 82)) | (1L << (NAME - 82)))) != 0)) { + { + setState(470); + parameterList(); + } + } + + setState(473); + match(T__5); + } + break; + case 16: + { + _localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState)); + pushNewRecursionContext(_localctx, _startState, RULE_expr); + setState(474); + if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)"); + setState(475); + match(T__30); + setState(476); + commaExpr(0); + setState(477); + match(T__31); + } + break; + case 17: { _localctx = new ExprPostModContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(473); + setState(479); if (!(precpred(_ctx, 22))) throw new FailedPredicateException(this, "precpred(_ctx, 22)"); - setState(474); + setState(480); _la = _input.LA(1); - if ( !(_la==T__35 || _la==T__36) ) { + if ( !(_la==T__37 || _la==T__38) ) { _errHandler.recoverInline(this); } else { @@ -3729,7 +3793,7 @@ public class KickCParser extends Parser { } } } - setState(479); + setState(485); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,43,_ctx); } @@ -3779,21 +3843,21 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(480); + setState(486); expr(0); - setState(485); + setState(491); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(481); + setState(487); match(T__2); - setState(482); + setState(488); expr(0); } } - setState(487); + setState(493); _errHandler.sync(this); _la = _input.LA(1); } @@ -3841,19 +3905,19 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(488); - match(T__67); - setState(490); + setState(494); + match(T__69); + setState(496); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__4) { { - setState(489); + setState(495); asmDirectives(); } } - setState(492); + setState(498); match(KICKASM); } } @@ -3901,27 +3965,27 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(494); - match(T__4); - setState(495); - asmDirective(); setState(500); + match(T__4); + setState(501); + asmDirective(); + setState(506); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(496); + setState(502); match(T__2); - setState(497); + setState(503); asmDirective(); } } - setState(502); + setState(508); _errHandler.sync(this); _la = _input.LA(1); } - setState(503); + setState(509); match(T__5); } } @@ -4060,79 +4124,77 @@ public class KickCParser extends Parser { AsmDirectiveContext _localctx = new AsmDirectiveContext(_ctx, getState()); enterRule(_localctx, 58, RULE_asmDirective); try { - setState(520); + setState(526); _errHandler.sync(this); switch (_input.LA(1)) { - case T__68: + case T__70: _localctx = new AsmDirectiveResourceContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(505); - match(T__68); - setState(506); - match(STRING); - } - break; - case T__69: - _localctx = new AsmDirectiveUsesContext(_localctx); - enterOuterAlt(_localctx, 2); - { - setState(507); - match(T__69); - setState(508); - match(NAME); - } - break; - case T__70: - _localctx = new AsmDirectiveClobberContext(_localctx); - enterOuterAlt(_localctx, 3); - { - setState(509); + setState(511); match(T__70); - setState(510); + setState(512); match(STRING); } break; case T__71: - _localctx = new AsmDirectiveBytesContext(_localctx); - enterOuterAlt(_localctx, 4); + _localctx = new AsmDirectiveUsesContext(_localctx); + enterOuterAlt(_localctx, 2); { - setState(511); + setState(513); match(T__71); - setState(512); - expr(0); + setState(514); + match(NAME); } break; case T__72: - _localctx = new AsmDirectiveCyclesContext(_localctx); - enterOuterAlt(_localctx, 5); + _localctx = new AsmDirectiveClobberContext(_localctx); + enterOuterAlt(_localctx, 3); { - setState(513); + setState(515); match(T__72); - setState(514); - expr(0); + setState(516); + match(STRING); } break; case T__73: + _localctx = new AsmDirectiveBytesContext(_localctx); + enterOuterAlt(_localctx, 4); + { + setState(517); + match(T__73); + setState(518); + expr(0); + } + break; + case T__74: + _localctx = new AsmDirectiveCyclesContext(_localctx); + enterOuterAlt(_localctx, 5); + { + setState(519); + match(T__74); + setState(520); + expr(0); + } + break; + case T__75: _localctx = new AsmDirectiveAddressContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(515); - match(T__73); - setState(518); + setState(521); + match(T__75); + setState(524); _errHandler.sync(this); switch (_input.LA(1)) { case T__12: { - setState(516); + setState(522); match(T__12); } break; case T__4: case T__6: case T__29: - case T__33: - case T__34: case T__35: case T__36: case T__37: @@ -4140,15 +4202,17 @@ public class KickCParser extends Parser { case T__39: case T__40: case T__41: - case T__46: - case T__47: + case T__42: + case T__43: + case T__48: + case T__49: case STRING: case CHAR: case BOOLEAN: case NUMBER: case NAME: { - setState(517); + setState(523); expr(0); } break; @@ -4205,17 +4269,17 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(525); + setState(531); _errHandler.sync(this); _la = _input.LA(1); - while (((((_la - 40)) & ~0x3f) == 0 && ((1L << (_la - 40)) & ((1L << (T__39 - 40)) | (1L << (T__74 - 40)) | (1L << (MNEMONIC - 40)) | (1L << (NAME - 40)))) != 0)) { + while (((((_la - 42)) & ~0x3f) == 0 && ((1L << (_la - 42)) & ((1L << (T__41 - 42)) | (1L << (T__76 - 42)) | (1L << (MNEMONIC - 42)) | (1L << (NAME - 42)))) != 0)) { { { - setState(522); + setState(528); asmLine(); } } - setState(527); + setState(533); _errHandler.sync(this); _la = _input.LA(1); } @@ -4265,28 +4329,28 @@ public class KickCParser extends Parser { AsmLineContext _localctx = new AsmLineContext(_ctx, getState()); enterRule(_localctx, 62, RULE_asmLine); try { - setState(531); + setState(537); _errHandler.sync(this); switch (_input.LA(1)) { - case T__39: + case T__41: case NAME: enterOuterAlt(_localctx, 1); { - setState(528); + setState(534); asmLabel(); } break; case MNEMONIC: enterOuterAlt(_localctx, 2); { - setState(529); + setState(535); asmInstruction(); } break; - case T__74: + case T__76: enterOuterAlt(_localctx, 3); { - setState(530); + setState(536); asmBytes(); } break; @@ -4356,36 +4420,36 @@ public class KickCParser extends Parser { enterRule(_localctx, 64, RULE_asmLabel); int _la; try { - setState(540); + setState(546); _errHandler.sync(this); switch (_input.LA(1)) { case NAME: _localctx = new AsmLabelNameContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(533); + setState(539); match(NAME); - setState(534); + setState(540); match(T__25); } break; - case T__39: + case T__41: _localctx = new AsmLabelMultiContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(535); - match(T__39); - setState(537); + setState(541); + match(T__41); + setState(543); _errHandler.sync(this); _la = _input.LA(1); if (_la==NAME) { { - setState(536); + setState(542); match(NAME); } } - setState(539); + setState(545); match(T__25); } break; @@ -4434,14 +4498,14 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(542); + setState(548); match(MNEMONIC); - setState(544); + setState(550); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) { case 1: { - setState(543); + setState(549); asmParamMode(); } break; @@ -4492,23 +4556,23 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(546); - match(T__74); - setState(547); - asmExpr(0); setState(552); + match(T__76); + setState(553); + asmExpr(0); + setState(558); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(548); + setState(554); match(T__2); - setState(549); + setState(555); asmExpr(0); } } - setState(554); + setState(560); _errHandler.sync(this); _la = _input.LA(1); } @@ -4658,14 +4722,14 @@ public class KickCParser extends Parser { AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState()); enterRule(_localctx, 70, RULE_asmParamMode); try { - setState(578); + setState(584); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) { case 1: _localctx = new AsmModeAbsContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(555); + setState(561); asmExpr(0); } break; @@ -4673,9 +4737,9 @@ public class KickCParser extends Parser { _localctx = new AsmModeImmContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(556); - match(T__75); - setState(557); + setState(562); + match(T__77); + setState(563); asmExpr(0); } break; @@ -4683,11 +4747,11 @@ public class KickCParser extends Parser { _localctx = new AsmModeAbsXYContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(558); + setState(564); asmExpr(0); - setState(559); + setState(565); match(T__2); - setState(560); + setState(566); match(NAME); } break; @@ -4695,15 +4759,15 @@ public class KickCParser extends Parser { _localctx = new AsmModeIndIdxXYContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(562); + setState(568); match(T__4); - setState(563); + setState(569); asmExpr(0); - setState(564); + setState(570); match(T__5); - setState(565); + setState(571); match(T__2); - setState(566); + setState(572); match(NAME); } break; @@ -4711,15 +4775,15 @@ public class KickCParser extends Parser { _localctx = new AsmModeIdxIndXYContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(568); + setState(574); match(T__4); - setState(569); + setState(575); asmExpr(0); - setState(570); + setState(576); match(T__2); - setState(571); + setState(577); match(NAME); - setState(572); + setState(578); match(T__5); } break; @@ -4727,11 +4791,11 @@ public class KickCParser extends Parser { _localctx = new AsmModeIndContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(574); + setState(580); match(T__4); - setState(575); + setState(581); asmExpr(0); - setState(576); + setState(582); match(T__5); } break; @@ -4921,7 +4985,7 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(594); + setState(600); _errHandler.sync(this); switch (_input.LA(1)) { case T__30: @@ -4930,25 +4994,25 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(581); + setState(587); match(T__30); - setState(582); + setState(588); asmExpr(0); - setState(583); + setState(589); match(T__31); } break; - case T__37: - case T__38: - case T__46: - case T__47: + case T__39: + case T__40: + case T__48: + case T__49: { _localctx = new AsmExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(585); + setState(591); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__37) | (1L << T__38) | (1L << T__46) | (1L << T__47))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__39) | (1L << T__40) | (1L << T__48) | (1L << T__49))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -4956,7 +5020,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(586); + setState(592); asmExpr(8); } break; @@ -4965,7 +5029,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprLabelContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(587); + setState(593); match(NAME); } break; @@ -4974,7 +5038,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprLabelRelContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(588); + setState(594); match(ASMREL); } break; @@ -4983,11 +5047,11 @@ public class KickCParser extends Parser { _localctx = new AsmExprReplaceContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(589); + setState(595); match(T__6); - setState(590); + setState(596); match(NAME); - setState(591); + setState(597); match(T__7); } break; @@ -4996,7 +5060,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprIntContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(592); + setState(598); match(NUMBER); } break; @@ -5005,7 +5069,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprCharContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(593); + setState(599); match(CHAR); } break; @@ -5013,7 +5077,7 @@ public class KickCParser extends Parser { throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(610); + setState(616); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,58,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -5021,72 +5085,32 @@ public class KickCParser extends Parser { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(608); + setState(614); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,57,_ctx) ) { case 1: { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(596); + setState(602); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); { - setState(597); - match(T__76); + setState(603); + match(T__33); } - setState(598); + setState(604); asmExpr(11); } break; case 2: - { - _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); - pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(599); - if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(600); - _la = _input.LA(1); - if ( !(_la==T__42 || _la==T__43) ) { - _errHandler.recoverInline(this); - } - else { - if ( _input.LA(1)==Token.EOF ) matchedEOF = true; - _errHandler.reportMatch(this); - consume(); - } - setState(601); - asmExpr(10); - } - break; - case 3: - { - _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); - pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(602); - if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(603); - _la = _input.LA(1); - if ( !(_la==T__29 || _la==T__44) ) { - _errHandler.recoverInline(this); - } - else { - if ( _input.LA(1)==Token.EOF ) matchedEOF = true; - _errHandler.reportMatch(this); - consume(); - } - setState(604); - asmExpr(8); - } - break; - case 4: { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); setState(605); - if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); + if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); setState(606); _la = _input.LA(1); - if ( !(_la==T__37 || _la==T__38) ) { + if ( !(_la==T__44 || _la==T__45) ) { _errHandler.recoverInline(this); } else { @@ -5095,13 +5119,53 @@ public class KickCParser extends Parser { consume(); } setState(607); + asmExpr(10); + } + break; + case 3: + { + _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); + pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); + setState(608); + if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); + setState(609); + _la = _input.LA(1); + if ( !(_la==T__29 || _la==T__46) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(610); + asmExpr(8); + } + break; + case 4: + { + _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); + pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); + setState(611); + if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); + setState(612); + _la = _input.LA(1); + if ( !(_la==T__39 || _la==T__40) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(613); asmExpr(7); } break; } } } - setState(612); + setState(618); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,58,_ctx); } @@ -5185,30 +5249,34 @@ public class KickCParser extends Parser { case 16: return precpred(_ctx, 7); case 17: - return precpred(_ctx, 28); + return precpred(_ctx, 30); case 18: - return precpred(_ctx, 25); + return precpred(_ctx, 29); case 19: + return precpred(_ctx, 28); + case 20: + return precpred(_ctx, 25); + case 21: return precpred(_ctx, 22); } return true; } private boolean asmExpr_sempred(AsmExprContext _localctx, int predIndex) { switch (predIndex) { - case 20: - return precpred(_ctx, 10); - case 21: - return precpred(_ctx, 9); case 22: - return precpred(_ctx, 7); + return precpred(_ctx, 10); case 23: + return precpred(_ctx, 9); + case 24: + return precpred(_ctx, 7); + case 25: return precpred(_ctx, 6); } return true; } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3c\u0268\4\2\t\2\4"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3d\u026e\4\2\t\2\4"+ "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ "\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -5244,210 +5312,213 @@ public class KickCParser extends Parser { "\6\33\u01a2\n\33\r\33\16\33\u01a3\3\33\3\33\5\33\u01a8\n\33\3\33\3\33"+ "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+ "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+ - "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u01d4"+ - "\n\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\7\33\u01de\n\33\f\33\16"+ - "\33\u01e1\13\33\3\34\3\34\3\34\7\34\u01e6\n\34\f\34\16\34\u01e9\13\34"+ - "\3\35\3\35\5\35\u01ed\n\35\3\35\3\35\3\36\3\36\3\36\3\36\7\36\u01f5\n"+ - "\36\f\36\16\36\u01f8\13\36\3\36\3\36\3\37\3\37\3\37\3\37\3\37\3\37\3\37"+ - "\3\37\3\37\3\37\3\37\3\37\3\37\5\37\u0209\n\37\5\37\u020b\n\37\3 \7 \u020e"+ - "\n \f \16 \u0211\13 \3!\3!\3!\5!\u0216\n!\3\"\3\"\3\"\3\"\5\"\u021c\n"+ - "\"\3\"\5\"\u021f\n\"\3#\3#\5#\u0223\n#\3$\3$\3$\3$\7$\u0229\n$\f$\16$"+ - "\u022c\13$\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3"+ - "%\3%\3%\3%\5%\u0245\n%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\5&\u0255"+ - "\n&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\7&\u0263\n&\f&\16&\u0266\13&\3"+ - "&\2\7\22*\62\64J\'\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60"+ - "\62\64\668:<>@BDFHJ\2\r\3\2\36\37\3\2&\'\3\2(,\3\2\61\62\3\2-.\4\2 /"+ - "\60\3\2()\3\2\61\66\3\2<E\4\2()\61\62\4\2 //\2\u02bd\2L\3\2\2\2\4P\3"+ - "\2\2\2\6V\3\2\2\2\bY\3\2\2\2\n]\3\2\2\2\fj\3\2\2\2\16o\3\2\2\2\20y\3\2"+ - "\2\2\22|\3\2\2\2\24\u0087\3\2\2\2\26\u008c\3\2\2\2\30\u0099\3\2\2\2\32"+ - "\u00a5\3\2\2\2\34\u00a7\3\2\2\2\36\u00bd\3\2\2\2 \u00bf\3\2\2\2\"\u00cc"+ - "\3\2\2\2$\u011c\3\2\2\2&\u012e\3\2\2\2(\u0134\3\2\2\2*\u0142\3\2\2\2,"+ - "\u0154\3\2\2\2.\u0157\3\2\2\2\60\u0163\3\2\2\2\62\u0166\3\2\2\2\64\u01a7"+ - "\3\2\2\2\66\u01e2\3\2\2\28\u01ea\3\2\2\2:\u01f0\3\2\2\2<\u020a\3\2\2\2"+ - ">\u020f\3\2\2\2@\u0215\3\2\2\2B\u021e\3\2\2\2D\u0220\3\2\2\2F\u0224\3"+ - "\2\2\2H\u0244\3\2\2\2J\u0254\3\2\2\2LM\5\6\4\2MN\5\n\6\2NO\7\2\2\3O\3"+ - "\3\2\2\2PQ\5> \2QR\7\2\2\3R\5\3\2\2\2SU\5\b\5\2TS\3\2\2\2UX\3\2\2\2VT"+ - "\3\2\2\2VW\3\2\2\2W\7\3\2\2\2XV\3\2\2\2YZ\7\3\2\2Z[\7S\2\2[\t\3\2\2\2"+ - "\\^\5\f\7\2]\\\3\2\2\2^_\3\2\2\2_]\3\2\2\2_`\3\2\2\2`\13\3\2\2\2ab\5\20"+ - "\t\2bc\7\4\2\2ck\3\2\2\2de\5.\30\2ef\7\4\2\2fk\3\2\2\2gk\5\26\f\2hk\5"+ - "8\35\2ik\5\34\17\2ja\3\2\2\2jd\3\2\2\2jg\3\2\2\2jh\3\2\2\2ji\3\2\2\2k"+ - "\r\3\2\2\2ln\5\36\20\2ml\3\2\2\2nq\3\2\2\2om\3\2\2\2op\3\2\2\2pr\3\2\2"+ - "\2qo\3\2\2\2rv\5*\26\2su\5\36\20\2ts\3\2\2\2ux\3\2\2\2vt\3\2\2\2vw\3\2"+ - "\2\2w\17\3\2\2\2xv\3\2\2\2yz\5\16\b\2z{\5\22\n\2{\21\3\2\2\2|}\b\n\1\2"+ - "}~\5\24\13\2~\u0084\3\2\2\2\177\u0080\f\3\2\2\u0080\u0081\7\5\2\2\u0081"+ - "\u0083\5\24\13\2\u0082\177\3\2\2\2\u0083\u0086\3\2\2\2\u0084\u0082\3\2"+ - "\2\2\u0084\u0085\3\2\2\2\u0085\23\3\2\2\2\u0086\u0084\3\2\2\2\u0087\u008a"+ - "\7_\2\2\u0088\u0089\7\6\2\2\u0089\u008b\5\64\33\2\u008a\u0088\3\2\2\2"+ - "\u008a\u008b\3\2\2\2\u008b\25\3\2\2\2\u008c\u008d\5\16\b\2\u008d\u008e"+ - "\7_\2\2\u008e\u0090\7\7\2\2\u008f\u0091\5\30\r\2\u0090\u008f\3\2\2\2\u0090"+ - "\u0091\3\2\2\2\u0091\u0092\3\2\2\2\u0092\u0093\7\b\2\2\u0093\u0095\7\t"+ - "\2\2\u0094\u0096\5\"\22\2\u0095\u0094\3\2\2\2\u0095\u0096\3\2\2\2\u0096"+ - "\u0097\3\2\2\2\u0097\u0098\7\n\2\2\u0098\27\3\2\2\2\u0099\u009e\5\32\16"+ - "\2\u009a\u009b\7\5\2\2\u009b\u009d\5\32\16\2\u009c\u009a\3\2\2\2\u009d"+ - "\u00a0\3\2\2\2\u009e\u009c\3\2\2\2\u009e\u009f\3\2\2\2\u009f\31\3\2\2"+ - "\2\u00a0\u009e\3\2\2\2\u00a1\u00a2\5\16\b\2\u00a2\u00a3\7_\2\2\u00a3\u00a6"+ - "\3\2\2\2\u00a4\u00a6\7R\2\2\u00a5\u00a1\3\2\2\2\u00a5\u00a4\3\2\2\2\u00a6"+ - "\33\3\2\2\2\u00a7\u00a8\5 \21\2\u00a8\u00a9\7\4\2\2\u00a9\35\3\2\2\2\u00aa"+ - "\u00be\7\13\2\2\u00ab\u00be\7\f\2\2\u00ac\u00ad\7\r\2\2\u00ad\u00ae\7"+ - "\7\2\2\u00ae\u00af\7V\2\2\u00af\u00be\7\b\2\2\u00b0\u00b1\7\16\2\2\u00b1"+ - "\u00b2\7\7\2\2\u00b2\u00b3\7_\2\2\u00b3\u00be\7\b\2\2\u00b4\u00be\7\17"+ - "\2\2\u00b5\u00be\7\20\2\2\u00b6\u00ba\7\21\2\2\u00b7\u00b8\7\7\2\2\u00b8"+ - "\u00b9\7_\2\2\u00b9\u00bb\7\b\2\2\u00ba\u00b7\3\2\2\2\u00ba\u00bb\3\2"+ - "\2\2\u00bb\u00be\3\2\2\2\u00bc\u00be\5 \21\2\u00bd\u00aa\3\2\2\2\u00bd"+ - "\u00ab\3\2\2\2\u00bd\u00ac\3\2\2\2\u00bd\u00b0\3\2\2\2\u00bd\u00b4\3\2"+ - "\2\2\u00bd\u00b5\3\2\2\2\u00bd\u00b6\3\2\2\2\u00bd\u00bc\3\2\2\2\u00be"+ - "\37\3\2\2\2\u00bf\u00c0\7\22\2\2\u00c0\u00c1\7\7\2\2\u00c1\u00c6\7V\2"+ - "\2\u00c2\u00c3\7\5\2\2\u00c3\u00c5\7V\2\2\u00c4\u00c2\3\2\2\2\u00c5\u00c8"+ - "\3\2\2\2\u00c6\u00c4\3\2\2\2\u00c6\u00c7\3\2\2\2\u00c7\u00c9\3\2\2\2\u00c8"+ - "\u00c6\3\2\2\2\u00c9\u00ca\7\b\2\2\u00ca!\3\2\2\2\u00cb\u00cd\5$\23\2"+ - "\u00cc\u00cb\3\2\2\2\u00cd\u00ce\3\2\2\2\u00ce\u00cc\3\2\2\2\u00ce\u00cf"+ - "\3\2\2\2\u00cf#\3\2\2\2\u00d0\u00d1\5\20\t\2\u00d1\u00d2\7\4\2\2\u00d2"+ - "\u011d\3\2\2\2\u00d3\u00d5\7\t\2\2\u00d4\u00d6\5\"\22\2\u00d5\u00d4\3"+ - "\2\2\2\u00d5\u00d6\3\2\2\2\u00d6\u00d7\3\2\2\2\u00d7\u011d\7\n\2\2\u00d8"+ - "\u00d9\5\62\32\2\u00d9\u00da\7\4\2\2\u00da\u011d\3\2\2\2\u00db\u00dc\7"+ - "\23\2\2\u00dc\u00dd\7\7\2\2\u00dd\u00de\5\62\32\2\u00de\u00df\7\b\2\2"+ - "\u00df\u00e2\5$\23\2\u00e0\u00e1\7\24\2\2\u00e1\u00e3\5$\23\2\u00e2\u00e0"+ - "\3\2\2\2\u00e2\u00e3\3\2\2\2\u00e3\u011d\3\2\2\2\u00e4\u00e6\5\36\20\2"+ - "\u00e5\u00e4\3\2\2\2\u00e6\u00e9\3\2\2\2\u00e7\u00e5\3\2\2\2\u00e7\u00e8"+ - "\3\2\2\2\u00e8\u00ea\3\2\2\2\u00e9\u00e7\3\2\2\2\u00ea\u00eb\7\25\2\2"+ - "\u00eb\u00ec\7\7\2\2\u00ec\u00ed\5\62\32\2\u00ed\u00ee\7\b\2\2\u00ee\u00ef"+ - "\5$\23\2\u00ef\u011d\3\2\2\2\u00f0\u00f2\5\36\20\2\u00f1\u00f0\3\2\2\2"+ - "\u00f2\u00f5\3\2\2\2\u00f3\u00f1\3\2\2\2\u00f3\u00f4\3\2\2\2\u00f4\u00f6"+ - "\3\2\2\2\u00f5\u00f3\3\2\2\2\u00f6\u00f7\7\26\2\2\u00f7\u00f8\5$\23\2"+ - "\u00f8\u00f9\7\25\2\2\u00f9\u00fa\7\7\2\2\u00fa\u00fb\5\62\32\2\u00fb"+ - "\u00fc\7\b\2\2\u00fc\u00fd\7\4\2\2\u00fd\u011d\3\2\2\2\u00fe\u0100\5\36"+ - "\20\2\u00ff\u00fe\3\2\2\2\u0100\u0103\3\2\2\2\u0101\u00ff\3\2\2\2\u0101"+ - "\u0102\3\2\2\2\u0102\u0104\3\2\2\2\u0103\u0101\3\2\2\2\u0104\u0105\7\27"+ - "\2\2\u0105\u0106\7\7\2\2\u0106\u0107\5&\24\2\u0107\u0108\7\b\2\2\u0108"+ - "\u0109\5$\23\2\u0109\u011d\3\2\2\2\u010a\u010c\7\30\2\2\u010b\u010d\5"+ - "\62\32\2\u010c\u010b\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3\2\2\2\u010e"+ - "\u011d\7\4\2\2\u010f\u0110\7\31\2\2\u0110\u011d\7\4\2\2\u0111\u0112\7"+ - "\32\2\2\u0112\u011d\7\4\2\2\u0113\u0115\7\33\2\2\u0114\u0116\5:\36\2\u0115"+ - "\u0114\3\2\2\2\u0115\u0116\3\2\2\2\u0116\u0117\3\2\2\2\u0117\u0118\7\t"+ - "\2\2\u0118\u0119\5> \2\u0119\u011a\7\n\2\2\u011a\u011d\3\2\2\2\u011b\u011d"+ - "\58\35\2\u011c\u00d0\3\2\2\2\u011c\u00d3\3\2\2\2\u011c\u00d8\3\2\2\2\u011c"+ - "\u00db\3\2\2\2\u011c\u00e7\3\2\2\2\u011c\u00f3\3\2\2\2\u011c\u0101\3\2"+ - "\2\2\u011c\u010a\3\2\2\2\u011c\u010f\3\2\2\2\u011c\u0111\3\2\2\2\u011c"+ - "\u0113\3\2\2\2\u011c\u011b\3\2\2\2\u011d%\3\2\2\2\u011e\u011f\5(\25\2"+ - "\u011f\u0120\7\4\2\2\u0120\u0121\5\62\32\2\u0121\u0123\7\4\2\2\u0122\u0124"+ - "\5\62\32\2\u0123\u0122\3\2\2\2\u0123\u0124\3\2\2\2\u0124\u012f\3\2\2\2"+ - "\u0125\u0127\5\16\b\2\u0126\u0125\3\2\2\2\u0126\u0127\3\2\2\2\u0127\u0128"+ - "\3\2\2\2\u0128\u0129\7_\2\2\u0129\u012a\7\34\2\2\u012a\u012b\5\64\33\2"+ - "\u012b\u012c\7\35\2\2\u012c\u012d\5\64\33\2\u012d\u012f\3\2\2\2\u012e"+ - "\u011e\3\2\2\2\u012e\u0126\3\2\2\2\u012f\'\3\2\2\2\u0130\u0132\5\20\t"+ - "\2\u0131\u0130\3\2\2\2\u0131\u0132\3\2\2\2\u0132\u0135\3\2\2\2\u0133\u0135"+ - "\5\62\32\2\u0134\u0131\3\2\2\2\u0134\u0133\3\2\2\2\u0135)\3\2\2\2\u0136"+ - "\u0137\b\26\1\2\u0137\u0138\7\7\2\2\u0138\u0139\5*\26\2\u0139\u013a\7"+ - "\b\2\2\u013a\u0143\3\2\2\2\u013b\u0143\7R\2\2\u013c\u013e\t\2\2\2\u013d"+ - "\u013f\7R\2\2\u013e\u013d\3\2\2\2\u013e\u013f\3\2\2\2\u013f\u0143\3\2"+ - "\2\2\u0140\u0143\5.\30\2\u0141\u0143\5,\27\2\u0142\u0136\3\2\2\2\u0142"+ - "\u013b\3\2\2\2\u0142\u013c\3\2\2\2\u0142\u0140\3\2\2\2\u0142\u0141\3\2"+ - "\2\2\u0143\u0151\3\2\2\2\u0144\u0145\f\7\2\2\u0145\u0150\7 \2\2\u0146"+ - "\u0147\f\6\2\2\u0147\u0149\7!\2\2\u0148\u014a\5\64\33\2\u0149\u0148\3"+ - "\2\2\2\u0149\u014a\3\2\2\2\u014a\u014b\3\2\2\2\u014b\u0150\7\"\2\2\u014c"+ - "\u014d\f\5\2\2\u014d\u014e\7\7\2\2\u014e\u0150\7\b\2\2\u014f\u0144\3\2"+ - "\2\2\u014f\u0146\3\2\2\2\u014f\u014c\3\2\2\2\u0150\u0153\3\2\2\2\u0151"+ - "\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152+\3\2\2\2\u0153\u0151\3\2\2\2"+ - "\u0154\u0155\7#\2\2\u0155\u0156\7_\2\2\u0156-\3\2\2\2\u0157\u0159\7#\2"+ - "\2\u0158\u015a\7_\2\2\u0159\u0158\3\2\2\2\u0159\u015a\3\2\2\2\u015a\u015b"+ - "\3\2\2\2\u015b\u015d\7\t\2\2\u015c\u015e\5\60\31\2\u015d\u015c\3\2\2\2"+ - "\u015e\u015f\3\2\2\2\u015f\u015d\3\2\2\2\u015f\u0160\3\2\2\2\u0160\u0161"+ - "\3\2\2\2\u0161\u0162\7\n\2\2\u0162/\3\2\2\2\u0163\u0164\5\20\t\2\u0164"+ - "\u0165\7\4\2\2\u0165\61\3\2\2\2\u0166\u0167\b\32\1\2\u0167\u0168\5\64"+ - "\33\2\u0168\u016e\3\2\2\2\u0169\u016a\f\3\2\2\u016a\u016b\7\5\2\2\u016b"+ - "\u016d\5\64\33\2\u016c\u0169\3\2\2\2\u016d\u0170\3\2\2\2\u016e\u016c\3"+ - "\2\2\2\u016e\u016f\3\2\2\2\u016f\63\3\2\2\2\u0170\u016e\3\2\2\2\u0171"+ - "\u0172\b\33\1\2\u0172\u0173\7\7\2\2\u0173\u0174\5\62\32\2\u0174\u0175"+ - "\7\b\2\2\u0175\u01a8\3\2\2\2\u0176\u0177\7$\2\2\u0177\u017a\7\7\2\2\u0178"+ - "\u017b\5*\26\2\u0179\u017b\5\64\33\2\u017a\u0178\3\2\2\2\u017a\u0179\3"+ - "\2\2\2\u017b\u017c\3\2\2\2\u017c\u017d\7\b\2\2\u017d\u01a8\3\2\2\2\u017e"+ - "\u017f\7%\2\2\u017f\u0182\7\7\2\2\u0180\u0183\5*\26\2\u0181\u0183\5\64"+ - "\33\2\u0182\u0180\3\2\2\2\u0182\u0181\3\2\2\2\u0183\u0184\3\2\2\2\u0184"+ - "\u0185\7\b\2\2\u0185\u01a8\3\2\2\2\u0186\u0187\7\7\2\2\u0187\u0188\5*"+ - "\26\2\u0188\u0189\7\b\2\2\u0189\u018a\5\64\33\32\u018a\u01a8\3\2\2\2\u018b"+ - "\u018c\t\3\2\2\u018c\u01a8\5\64\33\31\u018d\u018e\7 \2\2\u018e\u01a8\5"+ - "\64\33\27\u018f\u0190\t\4\2\2\u0190\u01a8\5\64\33\26\u0191\u0192\t\5\2"+ - "\2\u0192\u01a8\5\64\33\22\u0193\u0194\7\t\2\2\u0194\u0199\5\64\33\2\u0195"+ - "\u0196\7\5\2\2\u0196\u0198\5\64\33\2\u0197\u0195\3\2\2\2\u0198\u019b\3"+ - "\2\2\2\u0199\u0197\3\2\2\2\u0199\u019a\3\2\2\2\u019a\u019c\3\2\2\2\u019b"+ - "\u0199\3\2\2\2\u019c\u019d\7\n\2\2\u019d\u01a8\3\2\2\2\u019e\u01a8\7_"+ - "\2\2\u019f\u01a8\7V\2\2\u01a0\u01a2\7S\2\2\u01a1\u01a0\3\2\2\2\u01a2\u01a3"+ - "\3\2\2\2\u01a3\u01a1\3\2\2\2\u01a3\u01a4\3\2\2\2\u01a4\u01a8\3\2\2\2\u01a5"+ - "\u01a8\7T\2\2\u01a6\u01a8\7U\2\2\u01a7\u0171\3\2\2\2\u01a7\u0176\3\2\2"+ - "\2\u01a7\u017e\3\2\2\2\u01a7\u0186\3\2\2\2\u01a7\u018b\3\2\2\2\u01a7\u018d"+ - "\3\2\2\2\u01a7\u018f\3\2\2\2\u01a7\u0191\3\2\2\2\u01a7\u0193\3\2\2\2\u01a7"+ - "\u019e\3\2\2\2\u01a7\u019f\3\2\2\2\u01a7\u01a1\3\2\2\2\u01a7\u01a5\3\2"+ - "\2\2\u01a7\u01a6\3\2\2\2\u01a8\u01df\3\2\2\2\u01a9\u01aa\f\25\2\2\u01aa"+ - "\u01ab\t\6\2\2\u01ab\u01de\5\64\33\26\u01ac\u01ad\f\24\2\2\u01ad\u01ae"+ - "\t\7\2\2\u01ae\u01de\5\64\33\25\u01af\u01b0\f\23\2\2\u01b0\u01b1\t\b\2"+ - "\2\u01b1\u01de\5\64\33\24\u01b2\u01b3\f\21\2\2\u01b3\u01b4\t\t\2\2\u01b4"+ - "\u01de\5\64\33\22\u01b5\u01b6\f\20\2\2\u01b6\u01b7\7+\2\2\u01b7\u01de"+ - "\5\64\33\21\u01b8\u01b9\f\17\2\2\u01b9\u01ba\7\67\2\2\u01ba\u01de\5\64"+ - "\33\20\u01bb\u01bc\f\16\2\2\u01bc\u01bd\78\2\2\u01bd\u01de\5\64\33\17"+ - "\u01be\u01bf\f\r\2\2\u01bf\u01c0\79\2\2\u01c0\u01de\5\64\33\16\u01c1\u01c2"+ - "\f\f\2\2\u01c2\u01c3\7:\2\2\u01c3\u01de\5\64\33\r\u01c4\u01c5\f\13\2\2"+ - "\u01c5\u01c6\7;\2\2\u01c6\u01c7\5\64\33\2\u01c7\u01c8\7\34\2\2\u01c8\u01c9"+ - "\5\64\33\f\u01c9\u01de\3\2\2\2\u01ca\u01cb\f\n\2\2\u01cb\u01cc\7\6\2\2"+ - "\u01cc\u01de\5\64\33\n\u01cd\u01ce\f\t\2\2\u01ce\u01cf\t\n\2\2\u01cf\u01de"+ - "\5\64\33\t\u01d0\u01d1\f\36\2\2\u01d1\u01d3\7\7\2\2\u01d2\u01d4\5\66\34"+ - "\2\u01d3\u01d2\3\2\2\2\u01d3\u01d4\3\2\2\2\u01d4\u01d5\3\2\2\2\u01d5\u01de"+ - "\7\b\2\2\u01d6\u01d7\f\33\2\2\u01d7\u01d8\7!\2\2\u01d8\u01d9\5\62\32\2"+ - "\u01d9\u01da\7\"\2\2\u01da\u01de\3\2\2\2\u01db\u01dc\f\30\2\2\u01dc\u01de"+ - "\t\3\2\2\u01dd\u01a9\3\2\2\2\u01dd\u01ac\3\2\2\2\u01dd\u01af\3\2\2\2\u01dd"+ - "\u01b2\3\2\2\2\u01dd\u01b5\3\2\2\2\u01dd\u01b8\3\2\2\2\u01dd\u01bb\3\2"+ - "\2\2\u01dd\u01be\3\2\2\2\u01dd\u01c1\3\2\2\2\u01dd\u01c4\3\2\2\2\u01dd"+ - "\u01ca\3\2\2\2\u01dd\u01cd\3\2\2\2\u01dd\u01d0\3\2\2\2\u01dd\u01d6\3\2"+ - "\2\2\u01dd\u01db\3\2\2\2\u01de\u01e1\3\2\2\2\u01df\u01dd\3\2\2\2\u01df"+ - "\u01e0\3\2\2\2\u01e0\65\3\2\2\2\u01e1\u01df\3\2\2\2\u01e2\u01e7\5\64\33"+ - "\2\u01e3\u01e4\7\5\2\2\u01e4\u01e6\5\64\33\2\u01e5\u01e3\3\2\2\2\u01e6"+ - "\u01e9\3\2\2\2\u01e7\u01e5\3\2\2\2\u01e7\u01e8\3\2\2\2\u01e8\67\3\2\2"+ - "\2\u01e9\u01e7\3\2\2\2\u01ea\u01ec\7F\2\2\u01eb\u01ed\5:\36\2\u01ec\u01eb"+ - "\3\2\2\2\u01ec\u01ed\3\2\2\2\u01ed\u01ee\3\2\2\2\u01ee\u01ef\7Q\2\2\u01ef"+ - "9\3\2\2\2\u01f0\u01f1\7\7\2\2\u01f1\u01f6\5<\37\2\u01f2\u01f3\7\5\2\2"+ - "\u01f3\u01f5\5<\37\2\u01f4\u01f2\3\2\2\2\u01f5\u01f8\3\2\2\2\u01f6\u01f4"+ - "\3\2\2\2\u01f6\u01f7\3\2\2\2\u01f7\u01f9\3\2\2\2\u01f8\u01f6\3\2\2\2\u01f9"+ - "\u01fa\7\b\2\2\u01fa;\3\2\2\2\u01fb\u01fc\7G\2\2\u01fc\u020b\7S\2\2\u01fd"+ - "\u01fe\7H\2\2\u01fe\u020b\7_\2\2\u01ff\u0200\7I\2\2\u0200\u020b\7S\2\2"+ - "\u0201\u0202\7J\2\2\u0202\u020b\5\64\33\2\u0203\u0204\7K\2\2\u0204\u020b"+ - "\5\64\33\2\u0205\u0208\7L\2\2\u0206\u0209\7\17\2\2\u0207\u0209\5\64\33"+ - "\2\u0208\u0206\3\2\2\2\u0208\u0207\3\2\2\2\u0209\u020b\3\2\2\2\u020a\u01fb"+ - "\3\2\2\2\u020a\u01fd\3\2\2\2\u020a\u01ff\3\2\2\2\u020a\u0201\3\2\2\2\u020a"+ - "\u0203\3\2\2\2\u020a\u0205\3\2\2\2\u020b=\3\2\2\2\u020c\u020e\5@!\2\u020d"+ - "\u020c\3\2\2\2\u020e\u0211\3\2\2\2\u020f\u020d\3\2\2\2\u020f\u0210\3\2"+ - "\2\2\u0210?\3\2\2\2\u0211\u020f\3\2\2\2\u0212\u0216\5B\"\2\u0213\u0216"+ - "\5D#\2\u0214\u0216\5F$\2\u0215\u0212\3\2\2\2\u0215\u0213\3\2\2\2\u0215"+ - "\u0214\3\2\2\2\u0216A\3\2\2\2\u0217\u0218\7_\2\2\u0218\u021f\7\34\2\2"+ - "\u0219\u021b\7*\2\2\u021a\u021c\7_\2\2\u021b\u021a\3\2\2\2\u021b\u021c"+ - "\3\2\2\2\u021c\u021d\3\2\2\2\u021d\u021f\7\34\2\2\u021e\u0217\3\2\2\2"+ - "\u021e\u0219\3\2\2\2\u021fC\3\2\2\2\u0220\u0222\7P\2\2\u0221\u0223\5H"+ - "%\2\u0222\u0221\3\2\2\2\u0222\u0223\3\2\2\2\u0223E\3\2\2\2\u0224\u0225"+ - "\7M\2\2\u0225\u022a\5J&\2\u0226\u0227\7\5\2\2\u0227\u0229\5J&\2\u0228"+ - "\u0226\3\2\2\2\u0229\u022c\3\2\2\2\u022a\u0228\3\2\2\2\u022a\u022b\3\2"+ - "\2\2\u022bG\3\2\2\2\u022c\u022a\3\2\2\2\u022d\u0245\5J&\2\u022e\u022f"+ - "\7N\2\2\u022f\u0245\5J&\2\u0230\u0231\5J&\2\u0231\u0232\7\5\2\2\u0232"+ - "\u0233\7_\2\2\u0233\u0245\3\2\2\2\u0234\u0235\7\7\2\2\u0235\u0236\5J&"+ - "\2\u0236\u0237\7\b\2\2\u0237\u0238\7\5\2\2\u0238\u0239\7_\2\2\u0239\u0245"+ - "\3\2\2\2\u023a\u023b\7\7\2\2\u023b\u023c\5J&\2\u023c\u023d\7\5\2\2\u023d"+ - "\u023e\7_\2\2\u023e\u023f\7\b\2\2\u023f\u0245\3\2\2\2\u0240\u0241\7\7"+ - "\2\2\u0241\u0242\5J&\2\u0242\u0243\7\b\2\2\u0243\u0245\3\2\2\2\u0244\u022d"+ - "\3\2\2\2\u0244\u022e\3\2\2\2\u0244\u0230\3\2\2\2\u0244\u0234\3\2\2\2\u0244"+ - "\u023a\3\2\2\2\u0244\u0240\3\2\2\2\u0245I\3\2\2\2\u0246\u0247\b&\1\2\u0247"+ - "\u0248\7!\2\2\u0248\u0249\5J&\2\u0249\u024a\7\"\2\2\u024a\u0255\3\2\2"+ - "\2\u024b\u024c\t\13\2\2\u024c\u0255\5J&\n\u024d\u0255\7_\2\2\u024e\u0255"+ - "\7`\2\2\u024f\u0250\7\t\2\2\u0250\u0251\7_\2\2\u0251\u0255\7\n\2\2\u0252"+ - "\u0255\7V\2\2\u0253\u0255\7T\2\2\u0254\u0246\3\2\2\2\u0254\u024b\3\2\2"+ - "\2\u0254\u024d\3\2\2\2\u0254\u024e\3\2\2\2\u0254\u024f\3\2\2\2\u0254\u0252"+ - "\3\2\2\2\u0254\u0253\3\2\2\2\u0255\u0264\3\2\2\2\u0256\u0257\f\f\2\2\u0257"+ - "\u0258\7O\2\2\u0258\u0263\5J&\r\u0259\u025a\f\13\2\2\u025a\u025b\t\6\2"+ - "\2\u025b\u0263\5J&\f\u025c\u025d\f\t\2\2\u025d\u025e\t\f\2\2\u025e\u0263"+ - "\5J&\n\u025f\u0260\f\b\2\2\u0260\u0261\t\b\2\2\u0261\u0263\5J&\t\u0262"+ - "\u0256\3\2\2\2\u0262\u0259\3\2\2\2\u0262\u025c\3\2\2\2\u0262\u025f\3\2"+ - "\2\2\u0263\u0266\3\2\2\2\u0264\u0262\3\2\2\2\u0264\u0265\3\2\2\2\u0265"+ - "K\3\2\2\2\u0266\u0264\3\2\2\2=V_jov\u0084\u008a\u0090\u0095\u009e\u00a5"+ + "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+ + "\3\33\3\33\3\33\3\33\5\33\u01da\n\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+ + "\3\33\7\33\u01e4\n\33\f\33\16\33\u01e7\13\33\3\34\3\34\3\34\7\34\u01ec"+ + "\n\34\f\34\16\34\u01ef\13\34\3\35\3\35\5\35\u01f3\n\35\3\35\3\35\3\36"+ + "\3\36\3\36\3\36\7\36\u01fb\n\36\f\36\16\36\u01fe\13\36\3\36\3\36\3\37"+ + "\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\5\37\u020f"+ + "\n\37\5\37\u0211\n\37\3 \7 \u0214\n \f \16 \u0217\13 \3!\3!\3!\5!\u021c"+ + "\n!\3\"\3\"\3\"\3\"\5\"\u0222\n\"\3\"\5\"\u0225\n\"\3#\3#\5#\u0229\n#"+ + "\3$\3$\3$\3$\7$\u022f\n$\f$\16$\u0232\13$\3%\3%\3%\3%\3%\3%\3%\3%\3%\3"+ + "%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\5%\u024b\n%\3&\3&\3&\3&\3&\3"+ + "&\3&\3&\3&\3&\3&\3&\3&\3&\5&\u025b\n&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3"+ + "&\3&\7&\u0269\n&\f&\16&\u026c\13&\3&\2\7\22*\62\64J\'\2\4\6\b\n\f\16\20"+ + "\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BDFHJ\2\r\3\2\36\37\3\2"+ + "()\3\2*.\3\2\63\64\3\2/\60\4\2 \61\62\3\2*+\3\2\638\3\2>G\4\2*+\63\64"+ + "\4\2 \61\61\2\u02c5\2L\3\2\2\2\4P\3\2\2\2\6V\3\2\2\2\bY\3\2\2\2\n]\3"+ + "\2\2\2\fj\3\2\2\2\16o\3\2\2\2\20y\3\2\2\2\22|\3\2\2\2\24\u0087\3\2\2\2"+ + "\26\u008c\3\2\2\2\30\u0099\3\2\2\2\32\u00a5\3\2\2\2\34\u00a7\3\2\2\2\36"+ + "\u00bd\3\2\2\2 \u00bf\3\2\2\2\"\u00cc\3\2\2\2$\u011c\3\2\2\2&\u012e\3"+ + "\2\2\2(\u0134\3\2\2\2*\u0142\3\2\2\2,\u0154\3\2\2\2.\u0157\3\2\2\2\60"+ + "\u0163\3\2\2\2\62\u0166\3\2\2\2\64\u01a7\3\2\2\2\66\u01e8\3\2\2\28\u01f0"+ + "\3\2\2\2:\u01f6\3\2\2\2<\u0210\3\2\2\2>\u0215\3\2\2\2@\u021b\3\2\2\2B"+ + "\u0224\3\2\2\2D\u0226\3\2\2\2F\u022a\3\2\2\2H\u024a\3\2\2\2J\u025a\3\2"+ + "\2\2LM\5\6\4\2MN\5\n\6\2NO\7\2\2\3O\3\3\2\2\2PQ\5> \2QR\7\2\2\3R\5\3\2"+ + "\2\2SU\5\b\5\2TS\3\2\2\2UX\3\2\2\2VT\3\2\2\2VW\3\2\2\2W\7\3\2\2\2XV\3"+ + "\2\2\2YZ\7\3\2\2Z[\7T\2\2[\t\3\2\2\2\\^\5\f\7\2]\\\3\2\2\2^_\3\2\2\2_"+ + "]\3\2\2\2_`\3\2\2\2`\13\3\2\2\2ab\5\20\t\2bc\7\4\2\2ck\3\2\2\2de\5.\30"+ + "\2ef\7\4\2\2fk\3\2\2\2gk\5\26\f\2hk\58\35\2ik\5\34\17\2ja\3\2\2\2jd\3"+ + "\2\2\2jg\3\2\2\2jh\3\2\2\2ji\3\2\2\2k\r\3\2\2\2ln\5\36\20\2ml\3\2\2\2"+ + "nq\3\2\2\2om\3\2\2\2op\3\2\2\2pr\3\2\2\2qo\3\2\2\2rv\5*\26\2su\5\36\20"+ + "\2ts\3\2\2\2ux\3\2\2\2vt\3\2\2\2vw\3\2\2\2w\17\3\2\2\2xv\3\2\2\2yz\5\16"+ + "\b\2z{\5\22\n\2{\21\3\2\2\2|}\b\n\1\2}~\5\24\13\2~\u0084\3\2\2\2\177\u0080"+ + "\f\3\2\2\u0080\u0081\7\5\2\2\u0081\u0083\5\24\13\2\u0082\177\3\2\2\2\u0083"+ + "\u0086\3\2\2\2\u0084\u0082\3\2\2\2\u0084\u0085\3\2\2\2\u0085\23\3\2\2"+ + "\2\u0086\u0084\3\2\2\2\u0087\u008a\7`\2\2\u0088\u0089\7\6\2\2\u0089\u008b"+ + "\5\64\33\2\u008a\u0088\3\2\2\2\u008a\u008b\3\2\2\2\u008b\25\3\2\2\2\u008c"+ + "\u008d\5\16\b\2\u008d\u008e\7`\2\2\u008e\u0090\7\7\2\2\u008f\u0091\5\30"+ + "\r\2\u0090\u008f\3\2\2\2\u0090\u0091\3\2\2\2\u0091\u0092\3\2\2\2\u0092"+ + "\u0093\7\b\2\2\u0093\u0095\7\t\2\2\u0094\u0096\5\"\22\2\u0095\u0094\3"+ + "\2\2\2\u0095\u0096\3\2\2\2\u0096\u0097\3\2\2\2\u0097\u0098\7\n\2\2\u0098"+ + "\27\3\2\2\2\u0099\u009e\5\32\16\2\u009a\u009b\7\5\2\2\u009b\u009d\5\32"+ + "\16\2\u009c\u009a\3\2\2\2\u009d\u00a0\3\2\2\2\u009e\u009c\3\2\2\2\u009e"+ + "\u009f\3\2\2\2\u009f\31\3\2\2\2\u00a0\u009e\3\2\2\2\u00a1\u00a2\5\16\b"+ + "\2\u00a2\u00a3\7`\2\2\u00a3\u00a6\3\2\2\2\u00a4\u00a6\7S\2\2\u00a5\u00a1"+ + "\3\2\2\2\u00a5\u00a4\3\2\2\2\u00a6\33\3\2\2\2\u00a7\u00a8\5 \21\2\u00a8"+ + "\u00a9\7\4\2\2\u00a9\35\3\2\2\2\u00aa\u00be\7\13\2\2\u00ab\u00be\7\f\2"+ + "\2\u00ac\u00ad\7\r\2\2\u00ad\u00ae\7\7\2\2\u00ae\u00af\7W\2\2\u00af\u00be"+ + "\7\b\2\2\u00b0\u00b1\7\16\2\2\u00b1\u00b2\7\7\2\2\u00b2\u00b3\7`\2\2\u00b3"+ + "\u00be\7\b\2\2\u00b4\u00be\7\17\2\2\u00b5\u00be\7\20\2\2\u00b6\u00ba\7"+ + "\21\2\2\u00b7\u00b8\7\7\2\2\u00b8\u00b9\7`\2\2\u00b9\u00bb\7\b\2\2\u00ba"+ + "\u00b7\3\2\2\2\u00ba\u00bb\3\2\2\2\u00bb\u00be\3\2\2\2\u00bc\u00be\5 "+ + "\21\2\u00bd\u00aa\3\2\2\2\u00bd\u00ab\3\2\2\2\u00bd\u00ac\3\2\2\2\u00bd"+ + "\u00b0\3\2\2\2\u00bd\u00b4\3\2\2\2\u00bd\u00b5\3\2\2\2\u00bd\u00b6\3\2"+ + "\2\2\u00bd\u00bc\3\2\2\2\u00be\37\3\2\2\2\u00bf\u00c0\7\22\2\2\u00c0\u00c1"+ + "\7\7\2\2\u00c1\u00c6\7W\2\2\u00c2\u00c3\7\5\2\2\u00c3\u00c5\7W\2\2\u00c4"+ + "\u00c2\3\2\2\2\u00c5\u00c8\3\2\2\2\u00c6\u00c4\3\2\2\2\u00c6\u00c7\3\2"+ + "\2\2\u00c7\u00c9\3\2\2\2\u00c8\u00c6\3\2\2\2\u00c9\u00ca\7\b\2\2\u00ca"+ + "!\3\2\2\2\u00cb\u00cd\5$\23\2\u00cc\u00cb\3\2\2\2\u00cd\u00ce\3\2\2\2"+ + "\u00ce\u00cc\3\2\2\2\u00ce\u00cf\3\2\2\2\u00cf#\3\2\2\2\u00d0\u00d1\5"+ + "\20\t\2\u00d1\u00d2\7\4\2\2\u00d2\u011d\3\2\2\2\u00d3\u00d5\7\t\2\2\u00d4"+ + "\u00d6\5\"\22\2\u00d5\u00d4\3\2\2\2\u00d5\u00d6\3\2\2\2\u00d6\u00d7\3"+ + "\2\2\2\u00d7\u011d\7\n\2\2\u00d8\u00d9\5\62\32\2\u00d9\u00da\7\4\2\2\u00da"+ + "\u011d\3\2\2\2\u00db\u00dc\7\23\2\2\u00dc\u00dd\7\7\2\2\u00dd\u00de\5"+ + "\62\32\2\u00de\u00df\7\b\2\2\u00df\u00e2\5$\23\2\u00e0\u00e1\7\24\2\2"+ + "\u00e1\u00e3\5$\23\2\u00e2\u00e0\3\2\2\2\u00e2\u00e3\3\2\2\2\u00e3\u011d"+ + "\3\2\2\2\u00e4\u00e6\5\36\20\2\u00e5\u00e4\3\2\2\2\u00e6\u00e9\3\2\2\2"+ + "\u00e7\u00e5\3\2\2\2\u00e7\u00e8\3\2\2\2\u00e8\u00ea\3\2\2\2\u00e9\u00e7"+ + "\3\2\2\2\u00ea\u00eb\7\25\2\2\u00eb\u00ec\7\7\2\2\u00ec\u00ed\5\62\32"+ + "\2\u00ed\u00ee\7\b\2\2\u00ee\u00ef\5$\23\2\u00ef\u011d\3\2\2\2\u00f0\u00f2"+ + "\5\36\20\2\u00f1\u00f0\3\2\2\2\u00f2\u00f5\3\2\2\2\u00f3\u00f1\3\2\2\2"+ + "\u00f3\u00f4\3\2\2\2\u00f4\u00f6\3\2\2\2\u00f5\u00f3\3\2\2\2\u00f6\u00f7"+ + "\7\26\2\2\u00f7\u00f8\5$\23\2\u00f8\u00f9\7\25\2\2\u00f9\u00fa\7\7\2\2"+ + "\u00fa\u00fb\5\62\32\2\u00fb\u00fc\7\b\2\2\u00fc\u00fd\7\4\2\2\u00fd\u011d"+ + "\3\2\2\2\u00fe\u0100\5\36\20\2\u00ff\u00fe\3\2\2\2\u0100\u0103\3\2\2\2"+ + "\u0101\u00ff\3\2\2\2\u0101\u0102\3\2\2\2\u0102\u0104\3\2\2\2\u0103\u0101"+ + "\3\2\2\2\u0104\u0105\7\27\2\2\u0105\u0106\7\7\2\2\u0106\u0107\5&\24\2"+ + "\u0107\u0108\7\b\2\2\u0108\u0109\5$\23\2\u0109\u011d\3\2\2\2\u010a\u010c"+ + "\7\30\2\2\u010b\u010d\5\62\32\2\u010c\u010b\3\2\2\2\u010c\u010d\3\2\2"+ + "\2\u010d\u010e\3\2\2\2\u010e\u011d\7\4\2\2\u010f\u0110\7\31\2\2\u0110"+ + "\u011d\7\4\2\2\u0111\u0112\7\32\2\2\u0112\u011d\7\4\2\2\u0113\u0115\7"+ + "\33\2\2\u0114\u0116\5:\36\2\u0115\u0114\3\2\2\2\u0115\u0116\3\2\2\2\u0116"+ + "\u0117\3\2\2\2\u0117\u0118\7\t\2\2\u0118\u0119\5> \2\u0119\u011a\7\n\2"+ + "\2\u011a\u011d\3\2\2\2\u011b\u011d\58\35\2\u011c\u00d0\3\2\2\2\u011c\u00d3"+ + "\3\2\2\2\u011c\u00d8\3\2\2\2\u011c\u00db\3\2\2\2\u011c\u00e7\3\2\2\2\u011c"+ + "\u00f3\3\2\2\2\u011c\u0101\3\2\2\2\u011c\u010a\3\2\2\2\u011c\u010f\3\2"+ + "\2\2\u011c\u0111\3\2\2\2\u011c\u0113\3\2\2\2\u011c\u011b\3\2\2\2\u011d"+ + "%\3\2\2\2\u011e\u011f\5(\25\2\u011f\u0120\7\4\2\2\u0120\u0121\5\62\32"+ + "\2\u0121\u0123\7\4\2\2\u0122\u0124\5\62\32\2\u0123\u0122\3\2\2\2\u0123"+ + "\u0124\3\2\2\2\u0124\u012f\3\2\2\2\u0125\u0127\5\16\b\2\u0126\u0125\3"+ + "\2\2\2\u0126\u0127\3\2\2\2\u0127\u0128\3\2\2\2\u0128\u0129\7`\2\2\u0129"+ + "\u012a\7\34\2\2\u012a\u012b\5\64\33\2\u012b\u012c\7\35\2\2\u012c\u012d"+ + "\5\64\33\2\u012d\u012f\3\2\2\2\u012e\u011e\3\2\2\2\u012e\u0126\3\2\2\2"+ + "\u012f\'\3\2\2\2\u0130\u0132\5\20\t\2\u0131\u0130\3\2\2\2\u0131\u0132"+ + "\3\2\2\2\u0132\u0135\3\2\2\2\u0133\u0135\5\62\32\2\u0134\u0131\3\2\2\2"+ + "\u0134\u0133\3\2\2\2\u0135)\3\2\2\2\u0136\u0137\b\26\1\2\u0137\u0138\7"+ + "\7\2\2\u0138\u0139\5*\26\2\u0139\u013a\7\b\2\2\u013a\u0143\3\2\2\2\u013b"+ + "\u0143\7S\2\2\u013c\u013e\t\2\2\2\u013d\u013f\7S\2\2\u013e\u013d\3\2\2"+ + "\2\u013e\u013f\3\2\2\2\u013f\u0143\3\2\2\2\u0140\u0143\5.\30\2\u0141\u0143"+ + "\5,\27\2\u0142\u0136\3\2\2\2\u0142\u013b\3\2\2\2\u0142\u013c\3\2\2\2\u0142"+ + "\u0140\3\2\2\2\u0142\u0141\3\2\2\2\u0143\u0151\3\2\2\2\u0144\u0145\f\7"+ + "\2\2\u0145\u0150\7 \2\2\u0146\u0147\f\6\2\2\u0147\u0149\7!\2\2\u0148\u014a"+ + "\5\64\33\2\u0149\u0148\3\2\2\2\u0149\u014a\3\2\2\2\u014a\u014b\3\2\2\2"+ + "\u014b\u0150\7\"\2\2\u014c\u014d\f\5\2\2\u014d\u014e\7\7\2\2\u014e\u0150"+ + "\7\b\2\2\u014f\u0144\3\2\2\2\u014f\u0146\3\2\2\2\u014f\u014c\3\2\2\2\u0150"+ + "\u0153\3\2\2\2\u0151\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152+\3\2\2\2"+ + "\u0153\u0151\3\2\2\2\u0154\u0155\7#\2\2\u0155\u0156\7`\2\2\u0156-\3\2"+ + "\2\2\u0157\u0159\7#\2\2\u0158\u015a\7`\2\2\u0159\u0158\3\2\2\2\u0159\u015a"+ + "\3\2\2\2\u015a\u015b\3\2\2\2\u015b\u015d\7\t\2\2\u015c\u015e\5\60\31\2"+ + "\u015d\u015c\3\2\2\2\u015e\u015f\3\2\2\2\u015f\u015d\3\2\2\2\u015f\u0160"+ + "\3\2\2\2\u0160\u0161\3\2\2\2\u0161\u0162\7\n\2\2\u0162/\3\2\2\2\u0163"+ + "\u0164\5\20\t\2\u0164\u0165\7\4\2\2\u0165\61\3\2\2\2\u0166\u0167\b\32"+ + "\1\2\u0167\u0168\5\64\33\2\u0168\u016e\3\2\2\2\u0169\u016a\f\3\2\2\u016a"+ + "\u016b\7\5\2\2\u016b\u016d\5\64\33\2\u016c\u0169\3\2\2\2\u016d\u0170\3"+ + "\2\2\2\u016e\u016c\3\2\2\2\u016e\u016f\3\2\2\2\u016f\63\3\2\2\2\u0170"+ + "\u016e\3\2\2\2\u0171\u0172\b\33\1\2\u0172\u0173\7\7\2\2\u0173\u0174\5"+ + "\62\32\2\u0174\u0175\7\b\2\2\u0175\u01a8\3\2\2\2\u0176\u0177\7&\2\2\u0177"+ + "\u017a\7\7\2\2\u0178\u017b\5*\26\2\u0179\u017b\5\64\33\2\u017a\u0178\3"+ + "\2\2\2\u017a\u0179\3\2\2\2\u017b\u017c\3\2\2\2\u017c\u017d\7\b\2\2\u017d"+ + "\u01a8\3\2\2\2\u017e\u017f\7\'\2\2\u017f\u0182\7\7\2\2\u0180\u0183\5*"+ + "\26\2\u0181\u0183\5\64\33\2\u0182\u0180\3\2\2\2\u0182\u0181\3\2\2\2\u0183"+ + "\u0184\3\2\2\2\u0184\u0185\7\b\2\2\u0185\u01a8\3\2\2\2\u0186\u0187\7\7"+ + "\2\2\u0187\u0188\5*\26\2\u0188\u0189\7\b\2\2\u0189\u018a\5\64\33\32\u018a"+ + "\u01a8\3\2\2\2\u018b\u018c\t\3\2\2\u018c\u01a8\5\64\33\31\u018d\u018e"+ + "\7 \2\2\u018e\u01a8\5\64\33\27\u018f\u0190\t\4\2\2\u0190\u01a8\5\64\33"+ + "\26\u0191\u0192\t\5\2\2\u0192\u01a8\5\64\33\22\u0193\u0194\7\t\2\2\u0194"+ + "\u0199\5\64\33\2\u0195\u0196\7\5\2\2\u0196\u0198\5\64\33\2\u0197\u0195"+ + "\3\2\2\2\u0198\u019b\3\2\2\2\u0199\u0197\3\2\2\2\u0199\u019a\3\2\2\2\u019a"+ + "\u019c\3\2\2\2\u019b\u0199\3\2\2\2\u019c\u019d\7\n\2\2\u019d\u01a8\3\2"+ + "\2\2\u019e\u01a8\7`\2\2\u019f\u01a8\7W\2\2\u01a0\u01a2\7T\2\2\u01a1\u01a0"+ + "\3\2\2\2\u01a2\u01a3\3\2\2\2\u01a3\u01a1\3\2\2\2\u01a3\u01a4\3\2\2\2\u01a4"+ + "\u01a8\3\2\2\2\u01a5\u01a8\7U\2\2\u01a6\u01a8\7V\2\2\u01a7\u0171\3\2\2"+ + "\2\u01a7\u0176\3\2\2\2\u01a7\u017e\3\2\2\2\u01a7\u0186\3\2\2\2\u01a7\u018b"+ + "\3\2\2\2\u01a7\u018d\3\2\2\2\u01a7\u018f\3\2\2\2\u01a7\u0191\3\2\2\2\u01a7"+ + "\u0193\3\2\2\2\u01a7\u019e\3\2\2\2\u01a7\u019f\3\2\2\2\u01a7\u01a1\3\2"+ + "\2\2\u01a7\u01a5\3\2\2\2\u01a7\u01a6\3\2\2\2\u01a8\u01e5\3\2\2\2\u01a9"+ + "\u01aa\f\25\2\2\u01aa\u01ab\t\6\2\2\u01ab\u01e4\5\64\33\26\u01ac\u01ad"+ + "\f\24\2\2\u01ad\u01ae\t\7\2\2\u01ae\u01e4\5\64\33\25\u01af\u01b0\f\23"+ + "\2\2\u01b0\u01b1\t\b\2\2\u01b1\u01e4\5\64\33\24\u01b2\u01b3\f\21\2\2\u01b3"+ + "\u01b4\t\t\2\2\u01b4\u01e4\5\64\33\22\u01b5\u01b6\f\20\2\2\u01b6\u01b7"+ + "\7-\2\2\u01b7\u01e4\5\64\33\21\u01b8\u01b9\f\17\2\2\u01b9\u01ba\79\2\2"+ + "\u01ba\u01e4\5\64\33\20\u01bb\u01bc\f\16\2\2\u01bc\u01bd\7:\2\2\u01bd"+ + "\u01e4\5\64\33\17\u01be\u01bf\f\r\2\2\u01bf\u01c0\7;\2\2\u01c0\u01e4\5"+ + "\64\33\16\u01c1\u01c2\f\f\2\2\u01c2\u01c3\7<\2\2\u01c3\u01e4\5\64\33\r"+ + "\u01c4\u01c5\f\13\2\2\u01c5\u01c6\7=\2\2\u01c6\u01c7\5\64\33\2\u01c7\u01c8"+ + "\7\34\2\2\u01c8\u01c9\5\64\33\f\u01c9\u01e4\3\2\2\2\u01ca\u01cb\f\n\2"+ + "\2\u01cb\u01cc\7\6\2\2\u01cc\u01e4\5\64\33\n\u01cd\u01ce\f\t\2\2\u01ce"+ + "\u01cf\t\n\2\2\u01cf\u01e4\5\64\33\t\u01d0\u01d1\f \2\2\u01d1\u01d2\7"+ + "$\2\2\u01d2\u01e4\7`\2\2\u01d3\u01d4\f\37\2\2\u01d4\u01d5\7%\2\2\u01d5"+ + "\u01e4\7`\2\2\u01d6\u01d7\f\36\2\2\u01d7\u01d9\7\7\2\2\u01d8\u01da\5\66"+ + "\34\2\u01d9\u01d8\3\2\2\2\u01d9\u01da\3\2\2\2\u01da\u01db\3\2\2\2\u01db"+ + "\u01e4\7\b\2\2\u01dc\u01dd\f\33\2\2\u01dd\u01de\7!\2\2\u01de\u01df\5\62"+ + "\32\2\u01df\u01e0\7\"\2\2\u01e0\u01e4\3\2\2\2\u01e1\u01e2\f\30\2\2\u01e2"+ + "\u01e4\t\3\2\2\u01e3\u01a9\3\2\2\2\u01e3\u01ac\3\2\2\2\u01e3\u01af\3\2"+ + "\2\2\u01e3\u01b2\3\2\2\2\u01e3\u01b5\3\2\2\2\u01e3\u01b8\3\2\2\2\u01e3"+ + "\u01bb\3\2\2\2\u01e3\u01be\3\2\2\2\u01e3\u01c1\3\2\2\2\u01e3\u01c4\3\2"+ + "\2\2\u01e3\u01ca\3\2\2\2\u01e3\u01cd\3\2\2\2\u01e3\u01d0\3\2\2\2\u01e3"+ + "\u01d3\3\2\2\2\u01e3\u01d6\3\2\2\2\u01e3\u01dc\3\2\2\2\u01e3\u01e1\3\2"+ + "\2\2\u01e4\u01e7\3\2\2\2\u01e5\u01e3\3\2\2\2\u01e5\u01e6\3\2\2\2\u01e6"+ + "\65\3\2\2\2\u01e7\u01e5\3\2\2\2\u01e8\u01ed\5\64\33\2\u01e9\u01ea\7\5"+ + "\2\2\u01ea\u01ec\5\64\33\2\u01eb\u01e9\3\2\2\2\u01ec\u01ef\3\2\2\2\u01ed"+ + "\u01eb\3\2\2\2\u01ed\u01ee\3\2\2\2\u01ee\67\3\2\2\2\u01ef\u01ed\3\2\2"+ + "\2\u01f0\u01f2\7H\2\2\u01f1\u01f3\5:\36\2\u01f2\u01f1\3\2\2\2\u01f2\u01f3"+ + "\3\2\2\2\u01f3\u01f4\3\2\2\2\u01f4\u01f5\7R\2\2\u01f59\3\2\2\2\u01f6\u01f7"+ + "\7\7\2\2\u01f7\u01fc\5<\37\2\u01f8\u01f9\7\5\2\2\u01f9\u01fb\5<\37\2\u01fa"+ + "\u01f8\3\2\2\2\u01fb\u01fe\3\2\2\2\u01fc\u01fa\3\2\2\2\u01fc\u01fd\3\2"+ + "\2\2\u01fd\u01ff\3\2\2\2\u01fe\u01fc\3\2\2\2\u01ff\u0200\7\b\2\2\u0200"+ + ";\3\2\2\2\u0201\u0202\7I\2\2\u0202\u0211\7T\2\2\u0203\u0204\7J\2\2\u0204"+ + "\u0211\7`\2\2\u0205\u0206\7K\2\2\u0206\u0211\7T\2\2\u0207\u0208\7L\2\2"+ + "\u0208\u0211\5\64\33\2\u0209\u020a\7M\2\2\u020a\u0211\5\64\33\2\u020b"+ + "\u020e\7N\2\2\u020c\u020f\7\17\2\2\u020d\u020f\5\64\33\2\u020e\u020c\3"+ + "\2\2\2\u020e\u020d\3\2\2\2\u020f\u0211\3\2\2\2\u0210\u0201\3\2\2\2\u0210"+ + "\u0203\3\2\2\2\u0210\u0205\3\2\2\2\u0210\u0207\3\2\2\2\u0210\u0209\3\2"+ + "\2\2\u0210\u020b\3\2\2\2\u0211=\3\2\2\2\u0212\u0214\5@!\2\u0213\u0212"+ + "\3\2\2\2\u0214\u0217\3\2\2\2\u0215\u0213\3\2\2\2\u0215\u0216\3\2\2\2\u0216"+ + "?\3\2\2\2\u0217\u0215\3\2\2\2\u0218\u021c\5B\"\2\u0219\u021c\5D#\2\u021a"+ + "\u021c\5F$\2\u021b\u0218\3\2\2\2\u021b\u0219\3\2\2\2\u021b\u021a\3\2\2"+ + "\2\u021cA\3\2\2\2\u021d\u021e\7`\2\2\u021e\u0225\7\34\2\2\u021f\u0221"+ + "\7,\2\2\u0220\u0222\7`\2\2\u0221\u0220\3\2\2\2\u0221\u0222\3\2\2\2\u0222"+ + "\u0223\3\2\2\2\u0223\u0225\7\34\2\2\u0224\u021d\3\2\2\2\u0224\u021f\3"+ + "\2\2\2\u0225C\3\2\2\2\u0226\u0228\7Q\2\2\u0227\u0229\5H%\2\u0228\u0227"+ + "\3\2\2\2\u0228\u0229\3\2\2\2\u0229E\3\2\2\2\u022a\u022b\7O\2\2\u022b\u0230"+ + "\5J&\2\u022c\u022d\7\5\2\2\u022d\u022f\5J&\2\u022e\u022c\3\2\2\2\u022f"+ + "\u0232\3\2\2\2\u0230\u022e\3\2\2\2\u0230\u0231\3\2\2\2\u0231G\3\2\2\2"+ + "\u0232\u0230\3\2\2\2\u0233\u024b\5J&\2\u0234\u0235\7P\2\2\u0235\u024b"+ + "\5J&\2\u0236\u0237\5J&\2\u0237\u0238\7\5\2\2\u0238\u0239\7`\2\2\u0239"+ + "\u024b\3\2\2\2\u023a\u023b\7\7\2\2\u023b\u023c\5J&\2\u023c\u023d\7\b\2"+ + "\2\u023d\u023e\7\5\2\2\u023e\u023f\7`\2\2\u023f\u024b\3\2\2\2\u0240\u0241"+ + "\7\7\2\2\u0241\u0242\5J&\2\u0242\u0243\7\5\2\2\u0243\u0244\7`\2\2\u0244"+ + "\u0245\7\b\2\2\u0245\u024b\3\2\2\2\u0246\u0247\7\7\2\2\u0247\u0248\5J"+ + "&\2\u0248\u0249\7\b\2\2\u0249\u024b\3\2\2\2\u024a\u0233\3\2\2\2\u024a"+ + "\u0234\3\2\2\2\u024a\u0236\3\2\2\2\u024a\u023a\3\2\2\2\u024a\u0240\3\2"+ + "\2\2\u024a\u0246\3\2\2\2\u024bI\3\2\2\2\u024c\u024d\b&\1\2\u024d\u024e"+ + "\7!\2\2\u024e\u024f\5J&\2\u024f\u0250\7\"\2\2\u0250\u025b\3\2\2\2\u0251"+ + "\u0252\t\13\2\2\u0252\u025b\5J&\n\u0253\u025b\7`\2\2\u0254\u025b\7a\2"+ + "\2\u0255\u0256\7\t\2\2\u0256\u0257\7`\2\2\u0257\u025b\7\n\2\2\u0258\u025b"+ + "\7W\2\2\u0259\u025b\7U\2\2\u025a\u024c\3\2\2\2\u025a\u0251\3\2\2\2\u025a"+ + "\u0253\3\2\2\2\u025a\u0254\3\2\2\2\u025a\u0255\3\2\2\2\u025a\u0258\3\2"+ + "\2\2\u025a\u0259\3\2\2\2\u025b\u026a\3\2\2\2\u025c\u025d\f\f\2\2\u025d"+ + "\u025e\7$\2\2\u025e\u0269\5J&\r\u025f\u0260\f\13\2\2\u0260\u0261\t\6\2"+ + "\2\u0261\u0269\5J&\f\u0262\u0263\f\t\2\2\u0263\u0264\t\f\2\2\u0264\u0269"+ + "\5J&\n\u0265\u0266\f\b\2\2\u0266\u0267\t\b\2\2\u0267\u0269\5J&\t\u0268"+ + "\u025c\3\2\2\2\u0268\u025f\3\2\2\2\u0268\u0262\3\2\2\2\u0268\u0265\3\2"+ + "\2\2\u0269\u026c\3\2\2\2\u026a\u0268\3\2\2\2\u026a\u026b\3\2\2\2\u026b"+ + "K\3\2\2\2\u026c\u026a\3\2\2\2=V_jov\u0084\u008a\u0090\u0095\u009e\u00a5"+ "\u00ba\u00bd\u00c6\u00ce\u00d5\u00e2\u00e7\u00f3\u0101\u010c\u0115\u011c"+ "\u0123\u0126\u012e\u0131\u0134\u013e\u0142\u0149\u014f\u0151\u0159\u015f"+ - "\u016e\u017a\u0182\u0199\u01a3\u01a7\u01d3\u01dd\u01df\u01e7\u01ec\u01f6"+ - "\u0208\u020a\u020f\u0215\u021b\u021e\u0222\u022a\u0244\u0254\u0262\u0264"; + "\u016e\u017a\u0182\u0199\u01a3\u01a7\u01d9\u01e3\u01e5\u01ed\u01f2\u01fc"+ + "\u020e\u0210\u0215\u021b\u0221\u0224\u0228\u0230\u024a\u025a\u0268\u026a"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java index edb044629..0731b49ae 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java @@ -426,6 +426,20 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> { * @return the visitor result */ T visitExprChar(KickCParser.ExprCharContext ctx); + /** + * Visit a parse tree produced by the {@code exprArrow} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitExprArrow(KickCParser.ExprArrowContext ctx); + /** + * Visit a parse tree produced by the {@code exprDot} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitExprDot(KickCParser.ExprDotContext ctx); /** * Visit a parse tree produced by the {@code initList} * labeled alternative in {@link KickCParser#expr}. diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 63febda6c..0cdfc6051 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -431,6 +431,8 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { private List<Directive> declVarDirectives = null; /** Holds the declared comments when descending into a Variable Declaration. */ private List<Comment> declVarComments = null; + /** State specifying that we are currently populating struct members. */ + private boolean declVarStructMember = false; /** * Visit the type/directive part of a declaration. Setup the local decl-variables @@ -496,6 +498,11 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { lValue.setComments(ensureUnusedComments(comments)); } KickCParser.ExprContext initializer = ctx.expr(); + if(declVarStructMember) { + if(initializer != null) { + throw new CompileError("Initializers not supported inside structs " + type.getTypeName(), new StatementSource(ctx)); + } + } else { if(initializer != null) { addInitialAssignment(initializer, lValue, comments); } else { @@ -519,9 +526,15 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { ConstantValue zero = new ConstantPointer(0L, typePointer.getElementType()); Statement stmt = new StatementAssignment(lValue.getRef(), zero, new StatementSource(ctx), ensureUnusedComments(comments)); sequence.addStatement(stmt); + } else if(type instanceof SymbolTypeStruct) { + // Add an zero-struct initializer + SymbolTypeStruct typeStruct = (SymbolTypeStruct) type; + Statement stmt = new StatementAssignment(lValue.getRef(), new StructZero(typeStruct), new StatementSource(ctx), ensureUnusedComments(comments)); + sequence.addStatement(stmt); } else { throw new CompileError("Default initializer not implemented for type " + type.getTypeName(), new StatementSource(ctx)); } + } } return null; @@ -1119,6 +1132,28 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { return SymbolType.get(ctx.getText()); } + + + + @Override + public Object visitStructDef(KickCParser.StructDefContext ctx) { + String structDefName; + if(ctx.NAME()!=null) { + structDefName = ctx.NAME().getText(); + } else { + structDefName = getCurrentScope().allocateIntermediateVariableName(); + } + StructDefinition structDefinition = getCurrentScope().addStructDefinition(structDefName); + scopeStack.push(structDefinition); + declVarStructMember = true; + for(KickCParser.StructMembersContext memberCtx : ctx.structMembers()) { + visit(memberCtx); + } + declVarStructMember = false; + scopeStack.pop(); + return structDefinition.getType(); + } + @Override public SymbolType visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { String signedness = ctx.getChild(0).getText(); @@ -1214,6 +1249,13 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { } } + @Override + public Object visitExprDot(KickCParser.ExprDotContext ctx) { + RValue structExpr = (RValue) visit(ctx.expr()); + String name = ctx.NAME().getText(); + return new StructMemberRef(structExpr, name); + } + @Override public RValue visitExprCast(KickCParser.ExprCastContext ctx) { RValue child = (RValue) this.visit(ctx.expr()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java index 9977d5211..55f1a9cd0 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java @@ -3,6 +3,7 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.iterator.ProgramValueIterator; import dk.camelot64.kickc.model.symbols.ConstantVar; +import dk.camelot64.kickc.model.symbols.StructDefinition; import dk.camelot64.kickc.model.symbols.Symbol; import dk.camelot64.kickc.model.symbols.VariableUnversioned; import dk.camelot64.kickc.model.values.SymbolRef; @@ -42,6 +43,7 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion { for(Symbol tableSymbol : tableSymbols) { if(tableSymbol instanceof VariableUnversioned) continue; if(tableSymbol instanceof ConstantVar) continue; + if(tableSymbol instanceof StructDefinition) continue; Symbol codeSymbol = null; String codeSymbolFullName = tableSymbol.getFullName(); for(Symbol symbol : codeSymbols) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java index e36e1348a..f181b9eb1 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java @@ -2,6 +2,7 @@ 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.Scope; @@ -224,6 +225,10 @@ public class Pass4RegistersFinalize extends Pass2Base { Registers.RegisterZpWord registerZpWord = new Registers.RegisterZpWord(allocateZp(2)); return registerZpWord; + } else if(varType instanceof SymbolTypeStruct) { + Registers.RegisterZpStruct registerZpStruct = + new Registers.RegisterZpStruct(allocateZp(varType.getSizeBytes())); + return registerZpStruct; } else { throw new RuntimeException("Unhandled variable type " + varType); } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 5fb692d96..a91668f9b 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,6 +32,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testStruct0() throws IOException, URISyntaxException { + compileAndCompare("struct-0", log().verboseCreateSsa().verboseParse().verboseStatementSequence()); + } + @Test public void testC64DtvGfxExplorer() throws IOException, URISyntaxException { compileAndCompare("c64dtv-gfxexplorer", 10); diff --git a/src/test/kc/struct-0.kc b/src/test/kc/struct-0.kc new file mode 100644 index 000000000..6235eb405 --- /dev/null +++ b/src/test/kc/struct-0.kc @@ -0,0 +1,14 @@ +// Minimal struct - declaration & + +struct Point { + byte x; + byte y; +} point; + +void main() { + point.x = 2; + point.y = 3; + const byte* SCREEN = 0x0400; + SCREEN[0] = point.x; + SCREEN[1] = point.y; +} \ No newline at end of file diff --git a/src/test/ref/struct-0.asm b/src/test/ref/struct-0.asm new file mode 100644 index 000000000..16096b806 --- /dev/null +++ b/src/test/ref/struct-0.asm @@ -0,0 +1,23 @@ +// Minimal struct - declaration & +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + .label point = 2 +bbegin: + lda #0 + sta point + sta point+1 + jsr main + rts +main: { + .label SCREEN = $400 + lda #2 + sta point+0 + lda #3 + sta point+1 + lda point+0 + sta SCREEN + lda point+1 + sta SCREEN+1 + rts +} From 9c682e37fe609d892c347a0189f1c5bb0caa800f Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 28 May 2019 22:28:17 +0200 Subject: [PATCH 90/93] Testing structs --- .../java/dk/camelot64/kickc/Compiler.java | 6 ++-- .../kickc/fragment/AsmFragmentInstance.java | 16 ++++++--- .../AsmFragmentInstanceSpecFactory.java | 35 ++++++++++--------- .../dk/camelot64/kickc/model/Registers.java | 20 +++++++++++ .../kickc/model/symbols/ProgramScope.java | 18 ++++++++-- .../kickc/model/symbols/StructDefinition.java | 31 ++++++++++++++++ .../model/types/SymbolTypeProcedure.java | 1 - .../kickc/model/types/SymbolTypeStruct.java | 1 - .../Pass0GenerateStatementSequence.java | 7 ++++ .../dk/camelot64/kickc/test/TestPrograms.java | 15 ++++++-- src/test/kc/for-two-vars.kc | 9 +++++ src/test/kc/struct-0.kc | 2 +- src/test/kc/struct-1.kc | 18 ++++++++++ src/test/ref/for-two-vars.asm | 27 ++++++++++++++ src/test/ref/struct-0.asm | 2 +- src/test/ref/struct-1.asm | 29 +++++++++++++++ 16 files changed, 204 insertions(+), 33 deletions(-) create mode 100644 src/test/kc/for-two-vars.kc create mode 100644 src/test/kc/struct-1.kc create mode 100644 src/test/ref/for-two-vars.asm create mode 100644 src/test/ref/struct-1.asm diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index fcfc80bcb..233be6497 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -159,7 +159,7 @@ public class Compiler { if(getLog().isVerbosePass1CreateSsa()) { getLog().append("SYMBOLS"); - getLog().append(program.getScope().getSymbolTableContents(program)); + getLog().append(program.getScope().toString(program, null)); } new Pass1FixLValuesLoHi(program).execute(); @@ -206,7 +206,7 @@ public class Compiler { getLog().append(program.getGraph().toString(program)); getLog().append("SYMBOL TABLE SSA"); - getLog().append(program.getScope().getSymbolTableContents(program)); + getLog().append(program.getScope().toString(program, null)); return program; } @@ -530,7 +530,7 @@ public class Compiler { new Pass5FixLongBranches(program).optimize(); getLog().append("\nFINAL SYMBOL TABLE"); - getLog().append(program.getScope().getSymbolTableContents(program)); + getLog().append(program.getScope().toString(program, null)); getLog().append("\nFINAL ASSEMBLER"); getLog().append("Score: " + Pass4RegisterUpliftCombinations.getAsmScore(program) + "\n"); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java index 21f9e65f3..92ff9d606 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java @@ -3,14 +3,12 @@ package dk.camelot64.kickc.fragment; import dk.camelot64.kickc.NumberParser; import dk.camelot64.kickc.asm.*; import dk.camelot64.kickc.model.*; -import dk.camelot64.kickc.model.values.ConstantInteger; -import dk.camelot64.kickc.model.values.ConstantValue; +import dk.camelot64.kickc.model.symbols.StructDefinition; +import dk.camelot64.kickc.model.values.*; import dk.camelot64.kickc.model.symbols.ConstantVar; import dk.camelot64.kickc.model.symbols.Label; import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.values.ScopeRef; -import dk.camelot64.kickc.model.values.Value; import dk.camelot64.kickc.parser.KickCBaseVisitor; import dk.camelot64.kickc.parser.KickCParser; @@ -97,6 +95,16 @@ public class AsmFragmentInstance { } else if(boundValue instanceof Label) { String param = ((Label) boundValue).getLocalName().replace('@', 'b').replace(':', '_').replace("$", "_"); return new AsmParameter(param, false); + } else if(boundValue instanceof StructMemberRef) { + StructMemberRef structMemberRef = (StructMemberRef) boundValue; + StructDefinition structDefinition = program.getScope().getStructDefinition(structMemberRef); + Variable structMember = structDefinition.getMember(structMemberRef.getMemberName()); + int memberByteOffset = structDefinition.getMemberByteOffset(structMember); + VariableRef struct = (VariableRef) structMemberRef.getStruct(); + Variable structVar = program.getScope().getVariable( struct); + Registers.RegisterZpStruct structRegister = (Registers.RegisterZpStruct) structVar.getAllocation(); + // TODO Use STRUCT_OFFSET constants instead of hardcoded constants + return new AsmParameter(AsmFormat.getAsmParamName(structVar, codeScopeRef)+"+"+memberByteOffset,true); } else { throw new RuntimeException("Bound Value Type not implemented " + boundValue); } diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java index 760674038..d32b64004 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java @@ -249,9 +249,9 @@ public class AsmFragmentInstanceSpecFactory { } else if(constantLiteral instanceof ConstantPointer) { integerValue = ((ConstantPointer) constantLiteral).getValue(); } else { - throw new InternalError("Not implemented "+constantLiteral); + throw new InternalError("Not implemented " + constantLiteral); } - } catch (ConstantNotLiteral e) { + } catch(ConstantNotLiteral e) { // Assume it is a word integerValue = 0xffffL; } @@ -262,7 +262,7 @@ public class AsmFragmentInstanceSpecFactory { } else if(toType.getSizeBytes() == 2) { val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val); } else { - throw new InternalError("Not implemented "+toType); + throw new InternalError("Not implemented " + toType); } } } @@ -304,25 +304,26 @@ public class AsmFragmentInstanceSpecFactory { bind(name, value); return name; } else if(value instanceof StructZero) { - return "vssf"+((StructZero) value).getTypeStruct().getSizeBytes(); + return "vssf" + ((StructZero) value).getTypeStruct().getSizeBytes(); } else if(value instanceof StructMemberRef) { StructMemberRef structMemberRef = (StructMemberRef) value; + StructDefinition structDefinition = program.getScope().getStructDefinition(structMemberRef); + Variable structMember = structDefinition.getMember(structMemberRef.getMemberName()); + int memberByteOffset = structDefinition.getMemberByteOffset(structMember); + RValue struct = structMemberRef.getStruct(); - String memberName = structMemberRef.getMemberName(); - SymbolType symbolType = SymbolTypeInference.inferType(program.getScope(), struct); - byte idx = 0; - if(symbolType instanceof SymbolTypeStruct) { - String structTypeName = ((SymbolTypeStruct) symbolType).getStructTypeName(); - StructDefinition structDefinition = program.getScope().getStructDefinition(structTypeName); - for(Variable structMember : structDefinition.getAllVariables(false)) { - if(structMember.getLocalName().equals(memberName)) { - break; - } else { - idx += structMember.getType().getSizeBytes(); - } + if(struct instanceof VariableRef) { + Variable structVar = program.getScope().getVariable((VariableRef) struct); + if(structVar.getAllocation() instanceof Registers.RegisterZpStruct) { + Registers.RegisterZpStruct structRegister = (Registers.RegisterZpStruct) structVar.getAllocation(); + Registers.RegisterZpStructMember memberRegister = structRegister.getMemberRegister(memberByteOffset); + String name = getTypePrefix(structMember.getType()) + getRegisterName(memberRegister); + bind(name, structMemberRef); + return name; } + } else { + return bind(struct) + "_mbr_" + memberByteOffset; } - return bind(struct)+"_mbr_"+ idx; } throw new RuntimeException("Binding of value type not supported " + value); } diff --git a/src/main/java/dk/camelot64/kickc/model/Registers.java b/src/main/java/dk/camelot64/kickc/model/Registers.java index 7e2075931..0b36bb7d9 100644 --- a/src/main/java/dk/camelot64/kickc/model/Registers.java +++ b/src/main/java/dk/camelot64/kickc/model/Registers.java @@ -105,6 +105,7 @@ public class Registers { public int hashCode() { return zp; } + } @@ -158,6 +159,10 @@ public class Registers { super(zp); } + public RegisterZpStructMember getMemberRegister(int memberByteOffset) { + return new RegisterZpStructMember(getZp()+memberByteOffset); + } + @Override public RegisterType getType() { return RegisterType.ZP_STRUCT; @@ -165,6 +170,21 @@ public class Registers { } + /** Zero page addresses used as a register for a struct member variable. */ + public static class RegisterZpStructMember extends RegisterZp { + + public RegisterZpStructMember(int zp) { + super(zp); + } + + @Override + public RegisterType getType() { + return RegisterType.ZP_STRUCT; + } + + } + + /** A zero page address used as a register for a boolean variable. */ public static class RegisterZpBool extends RegisterZp { diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/ProgramScope.java b/src/main/java/dk/camelot64/kickc/model/symbols/ProgramScope.java index dc2c9554a..e78825414 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/ProgramScope.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/ProgramScope.java @@ -4,7 +4,11 @@ import dk.camelot64.kickc.model.LiveRangeEquivalenceClass; import dk.camelot64.kickc.model.LiveRangeEquivalenceClassSet; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeInference; import dk.camelot64.kickc.model.types.SymbolTypeProgram; +import dk.camelot64.kickc.model.types.SymbolTypeStruct; +import dk.camelot64.kickc.model.values.RValue; +import dk.camelot64.kickc.model.values.StructMemberRef; /** The program scope containing the symbols of a program */ public class ProgramScope extends Scope { @@ -19,8 +23,18 @@ public class ProgramScope extends Scope { return new SymbolTypeProgram(); } - public String getSymbolTableContents(Program program) { - return toString(program, null); + + /** + * Get the struct definition for a struct + * @param structMemberRef + * @return + */ + public StructDefinition getStructDefinition(StructMemberRef structMemberRef) { + RValue struct = structMemberRef.getStruct(); + SymbolType structType = SymbolTypeInference.inferType(this, struct); + String structTypeName = ((SymbolTypeStruct) structType).getStructTypeName(); + StructDefinition structDefinition = getStructDefinition(structTypeName); + return structDefinition; } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java b/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java index 165980096..32d7d3adc 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java @@ -18,6 +18,37 @@ public class StructDefinition extends Scope { return new SymbolTypeStruct(this); } + /** + * Get a struct member variable + * @param name The name of the member + * @return The member variable + */ + public Variable getMember(String name) { + for(Variable member : getAllVariables(false)) { + if(member.getLocalName().equals(name)) { + return member; + } + } + return null; + } + + /** + * Get the number of bytes that the member data is offset from the start of the struct + * @param member The member to find offset for + * @return The byte offset of the start of the member data + */ + public int getMemberByteOffset(Variable member) { + int byteOffset=0; + for(Variable structMember : getAllVariables(false)) { + if(structMember.equals(member)) { + break; + } else { + byteOffset += structMember.getType().getSizeBytes(); + } + } + return byteOffset; + } + @Override public String toString(Program program) { return "block-"+getFullName(); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java index 30f9e25bd..f38c140db 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java @@ -40,7 +40,6 @@ public class SymbolTypeProcedure implements SymbolType { @Override public int hashCode() { - return Objects.hash(returnType); } } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java index 558f73708..bc6cb3082 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java @@ -48,7 +48,6 @@ public class SymbolTypeStruct implements SymbolType { @Override public int hashCode() { - return Objects.hash(name, sizeBytes); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 0cdfc6051..ee926831a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -1154,6 +1154,13 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { return structDefinition.getType(); } + @Override + public Object visitStructRef(KickCParser.StructRefContext ctx) { + String structDefName = ctx.NAME().getText(); + StructDefinition structDefinition = getCurrentScope().getStructDefinition(structDefName); + return structDefinition.getType(); + } + @Override public SymbolType visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { String signedness = ctx.getChild(0).getText(); diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index a91668f9b..011fd3e50 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,9 +32,19 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testStruct1() throws IOException, URISyntaxException { + compileAndCompare("struct-1"); + } + @Test public void testStruct0() throws IOException, URISyntaxException { - compileAndCompare("struct-0", log().verboseCreateSsa().verboseParse().verboseStatementSequence()); + compileAndCompare("struct-0"); + } + + @Test + public void testForTwoVars() throws IOException, URISyntaxException { + compileAndCompare("for-two-vars"); } @Test @@ -49,7 +59,7 @@ public class TestPrograms { @Test public void testConstantStringConcat0() throws IOException, URISyntaxException { - compileAndCompare("constant-string-concat-0", log().verboseParse().verboseStatementSequence().verboseCreateSsa()); + compileAndCompare("constant-string-concat-0"); } @Test @@ -57,7 +67,6 @@ public class TestPrograms { compileAndCompare("literals"); } - @Test public void testConstantStringConcat() throws IOException, URISyntaxException { compileAndCompare("constant-string-concat"); diff --git a/src/test/kc/for-two-vars.kc b/src/test/kc/for-two-vars.kc new file mode 100644 index 000000000..10cf1e510 --- /dev/null +++ b/src/test/kc/for-two-vars.kc @@ -0,0 +1,9 @@ +// Test a for-loop with two iterating variables +// Illustrates that for()-loops currently cannot contain two variable declarations. + +void main() { + const byte* SCREEN = 0x400; + byte *sc=SCREEN+39; + for( byte i=0; i<40; i++, sc--) + *sc = i; +} diff --git a/src/test/kc/struct-0.kc b/src/test/kc/struct-0.kc index 6235eb405..fd81f7594 100644 --- a/src/test/kc/struct-0.kc +++ b/src/test/kc/struct-0.kc @@ -1,4 +1,4 @@ -// Minimal struct - declaration & +// Minimal struct - declaration, instantiation and usage struct Point { byte x; diff --git a/src/test/kc/struct-1.kc b/src/test/kc/struct-1.kc new file mode 100644 index 000000000..ddbd4a942 --- /dev/null +++ b/src/test/kc/struct-1.kc @@ -0,0 +1,18 @@ +// Minimal struct - two instances being used. + +struct Point { + byte x; + byte y; +}; + +struct Point point1, point2; + +void main() { + point1.x = 2; + point1.y = 3; + point2.x = point1.y; + point2.y = point1.x; + const byte* SCREEN = 0x0400; + SCREEN[0] = point2.x; + SCREEN[1] = point2.y; +} \ No newline at end of file diff --git a/src/test/ref/for-two-vars.asm b/src/test/ref/for-two-vars.asm new file mode 100644 index 000000000..cae2dddd5 --- /dev/null +++ b/src/test/ref/for-two-vars.asm @@ -0,0 +1,27 @@ +// Test a for-loop with two iterating variables +// Illustrates that for()-loops currently cannot contain two variable declarations. +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label SCREEN = $400 + .label sc = 2 + lda #<SCREEN+$27 + sta sc + lda #>SCREEN+$27 + sta sc+1 + ldx #0 + b1: + txa + ldy #0 + sta (sc),y + inx + lda sc + bne !+ + dec sc+1 + !: + dec sc + cpx #$28 + bcc b1 + rts +} diff --git a/src/test/ref/struct-0.asm b/src/test/ref/struct-0.asm index 16096b806..46b08a2aa 100644 --- a/src/test/ref/struct-0.asm +++ b/src/test/ref/struct-0.asm @@ -1,4 +1,4 @@ -// Minimal struct - declaration & +// Minimal struct - declaration, instantiation and usage .pc = $801 "Basic" :BasicUpstart(bbegin) .pc = $80d "Program" diff --git a/src/test/ref/struct-1.asm b/src/test/ref/struct-1.asm new file mode 100644 index 000000000..b4b8782b8 --- /dev/null +++ b/src/test/ref/struct-1.asm @@ -0,0 +1,29 @@ +// Minimal struct - two instances being used. +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + .label point1 = 2 + .label point2 = 4 +bbegin: + lda #0 + sta point1 + sta point1+1 + sta point2 + sta point2+1 + jsr main + rts +main: { + .label SCREEN = $400 + lda #2 + sta point1+0 + lda #3 + sta point1+1 + sta point2+0 + lda point1+0 + sta point2+1 + lda point2+0 + sta SCREEN + lda point2+1 + sta SCREEN+1 + rts +} From 837104f4fd3efdffb1ac680fea496241beefb972 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Tue, 28 May 2019 22:56:52 +0200 Subject: [PATCH 91/93] Working on structs --- .../fragment/_deref_pbuc1=vssz1_mbr_0.asm | 2 -- .../fragment/_deref_pbuc1=vssz1_mbr_1.asm | 2 -- src/main/fragment/vssz1=vssz2.asm | 4 +++ src/main/fragment/vssz1_mbr_0=vbuc1.asm | 2 -- src/main/fragment/vssz1_mbr_1=vbuc1.asm | 2 -- .../Pass0GenerateStatementSequence.java | 3 ++ .../dk/camelot64/kickc/test/TestPrograms.java | 5 +++ src/test/kc/struct-2.kc | 20 +++++++++++ src/test/ref/struct-2.asm | 36 +++++++++++++++++++ 9 files changed, 68 insertions(+), 8 deletions(-) delete mode 100644 src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm delete mode 100644 src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm create mode 100644 src/main/fragment/vssz1=vssz2.asm delete mode 100644 src/main/fragment/vssz1_mbr_0=vbuc1.asm delete mode 100644 src/main/fragment/vssz1_mbr_1=vbuc1.asm create mode 100644 src/test/kc/struct-2.kc create mode 100644 src/test/ref/struct-2.asm diff --git a/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm b/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm deleted file mode 100644 index f235c1aee..000000000 --- a/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm +++ /dev/null @@ -1,2 +0,0 @@ -lda {z1}+0 -sta {c1} \ No newline at end of file diff --git a/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm b/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm deleted file mode 100644 index 59a255b43..000000000 --- a/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm +++ /dev/null @@ -1,2 +0,0 @@ -lda {z1}+1 -sta {c1} \ No newline at end of file diff --git a/src/main/fragment/vssz1=vssz2.asm b/src/main/fragment/vssz1=vssz2.asm new file mode 100644 index 000000000..113613e13 --- /dev/null +++ b/src/main/fragment/vssz1=vssz2.asm @@ -0,0 +1,4 @@ +lda {z2} +sta {z1} +lda {z2}+1 +sta {z1}+1 \ No newline at end of file diff --git a/src/main/fragment/vssz1_mbr_0=vbuc1.asm b/src/main/fragment/vssz1_mbr_0=vbuc1.asm deleted file mode 100644 index cdbf628d1..000000000 --- a/src/main/fragment/vssz1_mbr_0=vbuc1.asm +++ /dev/null @@ -1,2 +0,0 @@ -lda #{c1} -sta {z1}+0 \ No newline at end of file diff --git a/src/main/fragment/vssz1_mbr_1=vbuc1.asm b/src/main/fragment/vssz1_mbr_1=vbuc1.asm deleted file mode 100644 index 540828c77..000000000 --- a/src/main/fragment/vssz1_mbr_1=vbuc1.asm +++ /dev/null @@ -1,2 +0,0 @@ -lda #{c1} -sta {z1}+1 \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index ee926831a..f25f31473 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -497,6 +497,9 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> { // Add comments to constant lValue.setComments(ensureUnusedComments(comments)); } + if(type instanceof SymbolTypeStruct) { + lValue.setDeclaredVolatile(true); + } KickCParser.ExprContext initializer = ctx.expr(); if(declVarStructMember) { if(initializer != null) { diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 011fd3e50..4df4055da 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,6 +32,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testStruct2() throws IOException, URISyntaxException { + compileAndCompare("struct-2"); + } + @Test public void testStruct1() throws IOException, URISyntaxException { compileAndCompare("struct-1"); diff --git a/src/test/kc/struct-2.kc b/src/test/kc/struct-2.kc new file mode 100644 index 000000000..a52a169db --- /dev/null +++ b/src/test/kc/struct-2.kc @@ -0,0 +1,20 @@ +// Minimal struct - different instances and copying + +struct Point { + byte x; + byte y; +}; + +struct Point point1, point2; + +void main() { + point1.x = 2; + point1.y = 3; + point2 = point1; + point2.x = 4; + const byte* SCREEN = 0x0400; + SCREEN[0] = point1.x; + SCREEN[1] = point1.y; + SCREEN[2] = point2.x; + SCREEN[3] = point2.y; +} \ No newline at end of file diff --git a/src/test/ref/struct-2.asm b/src/test/ref/struct-2.asm new file mode 100644 index 000000000..29ff684c8 --- /dev/null +++ b/src/test/ref/struct-2.asm @@ -0,0 +1,36 @@ +// Minimal struct - different instances and copying +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + .label point1 = 2 + .label point2 = 4 +bbegin: + lda #0 + sta point1 + sta point1+1 + sta point2 + sta point2+1 + jsr main + rts +main: { + .label SCREEN = $400 + lda #2 + sta point1+0 + lda #3 + sta point1+1 + lda point1 + sta point2 + lda point1+1 + sta point2+1 + lda #4 + sta point2+0 + lda point1+0 + sta SCREEN + lda point1+1 + sta SCREEN+1 + lda point2+0 + sta SCREEN+2 + lda point2+1 + sta SCREEN+3 + rts +} From 007985111a4cbfa10ffbef63816ae187fa8e7898 Mon Sep 17 00:00:00 2001 From: jespergravgaard <jesper@balmangravgaard.dk> Date: Wed, 29 May 2019 08:05:34 +0200 Subject: [PATCH 92/93] Temporary implementation for arrays of structs --- .../pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm | 2 + .../pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm | 2 + .../pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm | 2 + .../pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm | 2 + .../fragment/vbuaa=_deref_pssc1_mbr_0.asm | 1 + .../fragment/vbuaa=_deref_pssc1_mbr_1.asm | 1 + .../vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm | 1 + .../vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm | 1 + .../vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm | 1 + .../vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm | 1 + .../AsmFragmentInstanceSpecFactory.java | 2 + .../kickc/passes/Pass4CodeGeneration.java | 10 +++-- .../dk/camelot64/kickc/test/TestPrograms.java | 5 +++ src/test/kc/struct-3.kc | 20 ++++++++++ src/test/ref/struct-3.asm | 39 +++++++++++++++++++ 15 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 src/main/fragment/pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm create mode 100644 src/main/fragment/pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm create mode 100644 src/main/fragment/pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm create mode 100644 src/main/fragment/pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm create mode 100644 src/main/fragment/vbuaa=_deref_pssc1_mbr_0.asm create mode 100644 src/main/fragment/vbuaa=_deref_pssc1_mbr_1.asm create mode 100644 src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm create mode 100644 src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm create mode 100644 src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm create mode 100644 src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm create mode 100644 src/test/kc/struct-3.kc create mode 100644 src/test/ref/struct-3.asm diff --git a/src/main/fragment/pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm b/src/main/fragment/pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm new file mode 100644 index 000000000..916e765e0 --- /dev/null +++ b/src/main/fragment/pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm @@ -0,0 +1,2 @@ +sta {c1},x + diff --git a/src/main/fragment/pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm b/src/main/fragment/pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm new file mode 100644 index 000000000..778da5aff --- /dev/null +++ b/src/main/fragment/pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm @@ -0,0 +1,2 @@ +sta {c1}+1,x + diff --git a/src/main/fragment/pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm b/src/main/fragment/pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm new file mode 100644 index 000000000..64fd3eaf2 --- /dev/null +++ b/src/main/fragment/pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm @@ -0,0 +1,2 @@ +sta {c1},y + diff --git a/src/main/fragment/pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm b/src/main/fragment/pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm new file mode 100644 index 000000000..91a797b27 --- /dev/null +++ b/src/main/fragment/pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm @@ -0,0 +1,2 @@ +sta {c1}+1,y + diff --git a/src/main/fragment/vbuaa=_deref_pssc1_mbr_0.asm b/src/main/fragment/vbuaa=_deref_pssc1_mbr_0.asm new file mode 100644 index 000000000..bee08251a --- /dev/null +++ b/src/main/fragment/vbuaa=_deref_pssc1_mbr_0.asm @@ -0,0 +1 @@ +lda {c1} \ No newline at end of file diff --git a/src/main/fragment/vbuaa=_deref_pssc1_mbr_1.asm b/src/main/fragment/vbuaa=_deref_pssc1_mbr_1.asm new file mode 100644 index 000000000..a836deba0 --- /dev/null +++ b/src/main/fragment/vbuaa=_deref_pssc1_mbr_1.asm @@ -0,0 +1 @@ +lda {c1}+1 \ No newline at end of file diff --git a/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm b/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm new file mode 100644 index 000000000..7454fa763 --- /dev/null +++ b/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm @@ -0,0 +1 @@ +lda {c1},x \ No newline at end of file diff --git a/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm b/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm new file mode 100644 index 000000000..66ef35236 --- /dev/null +++ b/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm @@ -0,0 +1 @@ +lda {c1}+1,x \ No newline at end of file diff --git a/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm b/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm new file mode 100644 index 000000000..b2b867b05 --- /dev/null +++ b/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm @@ -0,0 +1 @@ +lda {c1},y \ No newline at end of file diff --git a/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm b/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm new file mode 100644 index 000000000..5c24499d4 --- /dev/null +++ b/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm @@ -0,0 +1 @@ +lda {c1}+1,y \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java index d32b64004..c50725d1b 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java @@ -383,6 +383,8 @@ public class AsmFragmentInstanceSpecFactory { return "ppr"; } else if(elementType instanceof SymbolTypePointer) { return "ppt"; + } else if(elementType instanceof SymbolTypeStruct) { + return "pss"; } else { throw new RuntimeException("Not implemented " + type); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index e758eb361..8a3920906 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -6,10 +6,7 @@ import dk.camelot64.kickc.model.*; import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.*; import dk.camelot64.kickc.model.symbols.*; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.types.SymbolTypeArray; -import dk.camelot64.kickc.model.types.SymbolTypePointer; -import dk.camelot64.kickc.model.types.SymbolTypeProcedure; +import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.*; import java.util.*; @@ -438,6 +435,11 @@ public class Pass4CodeGeneration { String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(2L), Operators.MULTIPLY, arraySize), 99, scopeRef); asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmSize, size, "0"); added.add(asmName); + } else if(constantArrayFilled.getElementType() instanceof SymbolTypeStruct) { + SymbolTypeStruct structElementType = (SymbolTypeStruct) constantArrayFilled.getElementType(); + String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) structElementType.getSizeBytes()), Operators.MULTIPLY, arraySize), 99, scopeRef); + asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmSize, size, "0"); + added.add(asmName); } else { throw new RuntimeException("Unhandled constant array element type " + constantArrayFilled.toString(program)); } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 4df4055da..96badfff4 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,6 +32,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testStruct3() throws IOException, URISyntaxException { + compileAndCompare("struct-3", log().verboseParse().verboseCreateSsa().verboseStatementSequence().verboseFragmentLog()); + } + @Test public void testStruct2() throws IOException, URISyntaxException { compileAndCompare("struct-2"); diff --git a/src/test/kc/struct-3.kc b/src/test/kc/struct-3.kc new file mode 100644 index 000000000..6257aa033 --- /dev/null +++ b/src/test/kc/struct-3.kc @@ -0,0 +1,20 @@ +// Minimal struct - different instances and copying + +struct Point { + byte x; + byte y; +}; + +struct Point[4] points; + +void main() { + for( byte i: 0..4) { + points[i].x = i; + points[i].y = i+1; + } + const byte* SCREEN = 0x0400; + for( byte i: 0..4) { + SCREEN[i] = points[i].x; + (SCREEN+40)[i] = points[i].y; + } +} \ No newline at end of file diff --git a/src/test/ref/struct-3.asm b/src/test/ref/struct-3.asm new file mode 100644 index 000000000..650be77b8 --- /dev/null +++ b/src/test/ref/struct-3.asm @@ -0,0 +1,39 @@ +// Minimal struct - different instances and copying +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label SCREEN = $400 + .label _5 = 2 + ldx #0 + b1: + txa + asl + sta _5 + tay + txa + sta points,y + txa + tay + iny + tya + ldy _5 + sta points+1,y + inx + cpx #5 + bne b1 + ldy #0 + b2: + tya + asl + tax + lda points,x + sta SCREEN,y + lda points+1,x + sta SCREEN+$28,y + iny + cpy #5 + bne b2 + rts +} + points: .fill 2*4, 0 From ef953a12b496f38cf8cd9e44f06f188c6672dd87 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard <jg@ramboll.com> Date: Wed, 29 May 2019 17:45:17 +0200 Subject: [PATCH 93/93] Added some pointer-based struct tests (simulating the ASM we want for array indexing). --- .../dk/camelot64/kickc/test/TestPrograms.java | 12 +++- src/test/kc/struct-3.kc | 2 +- src/test/kc/struct-4.kc | 24 +++++++ src/test/kc/struct-5.kc | 26 +++++++ src/test/ref/struct-3.asm | 2 +- src/test/ref/struct-4.asm | 39 +++++++++++ src/test/ref/struct-5.asm | 67 +++++++++++++++++++ 7 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 src/test/kc/struct-4.kc create mode 100644 src/test/kc/struct-5.kc create mode 100644 src/test/ref/struct-4.asm create mode 100644 src/test/ref/struct-5.asm diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 96badfff4..746e6faa5 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,9 +32,19 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testStruct5() throws IOException, URISyntaxException { + compileAndCompare("struct-5", log().verboseParse().verboseCreateSsa().verboseStatementSequence()); + } + + @Test + public void testStruct4() throws IOException, URISyntaxException { + compileAndCompare("struct-4", log().verboseParse().verboseCreateSsa().verboseStatementSequence()); + } + @Test public void testStruct3() throws IOException, URISyntaxException { - compileAndCompare("struct-3", log().verboseParse().verboseCreateSsa().verboseStatementSequence().verboseFragmentLog()); + compileAndCompare("struct-3"); } @Test diff --git a/src/test/kc/struct-3.kc b/src/test/kc/struct-3.kc index 6257aa033..d6d25f7df 100644 --- a/src/test/kc/struct-3.kc +++ b/src/test/kc/struct-3.kc @@ -1,4 +1,4 @@ -// Minimal struct - different instances and copying +// Minimal struct - array of struct struct Point { byte x; diff --git a/src/test/kc/struct-4.kc b/src/test/kc/struct-4.kc new file mode 100644 index 000000000..504bb7265 --- /dev/null +++ b/src/test/kc/struct-4.kc @@ -0,0 +1,24 @@ +// Minimal struct - array of struct - near pointer math indexing + +struct Point { + byte x; + byte y; +}; + +struct Point[4] points; + +const byte SIZEOF_POINT = 2; +const byte OFFS_X = 0; +const byte OFFS_Y = 1; + +void main() { + for( byte i: 0..3) { + *((byte*)points+OFFS_X+i*SIZEOF_POINT) = i; // points[i].x = i; + *((byte*)points+OFFS_Y+i*SIZEOF_POINT) = i+4; // points[i].y = i+4; + } + const byte* SCREEN = 0x0400; + for( byte i: 0..3) { + SCREEN[i] = *((byte*)points+OFFS_X+i*SIZEOF_POINT); // SCREEN[i] = points[i].x; + (SCREEN+40)[i] = *((byte*)points+OFFS_Y+i*SIZEOF_POINT); // (SCREEN+40)[i] = points[i].y; + } +} \ No newline at end of file diff --git a/src/test/kc/struct-5.kc b/src/test/kc/struct-5.kc new file mode 100644 index 000000000..1d2cf6cd5 --- /dev/null +++ b/src/test/kc/struct-5.kc @@ -0,0 +1,26 @@ +// Minimal struct - array of struct - far pointer math indexing + +struct Point { + byte x; + byte y; +}; + +struct Point[4] points; + +const byte SIZEOF_POINT = 2; +const byte OFFS_X = 0; +const byte OFFS_Y = 1; + +void main() { + for( byte i: 0..3) { + struct Point* point_i = points+i; + *((byte*)point_i+OFFS_X) = i; // points[i].x = i; + *((byte*)point_i+OFFS_Y) = i+4; // points[i].y = i+4; + } + const byte* SCREEN = 0x0400; + for( byte i: 0..3) { + struct Point* point_i = points+i; + SCREEN[i] = *((byte*)point_i+OFFS_X); // SCREEN[i] = points[i].x; + (SCREEN+40)[i] = *((byte*)point_i+OFFS_Y); // (SCREEN+40)[i] = points[i].y; + } +} \ No newline at end of file diff --git a/src/test/ref/struct-3.asm b/src/test/ref/struct-3.asm index 650be77b8..998d77eb6 100644 --- a/src/test/ref/struct-3.asm +++ b/src/test/ref/struct-3.asm @@ -1,4 +1,4 @@ -// Minimal struct - different instances and copying +// Minimal struct - array of struct .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" diff --git a/src/test/ref/struct-4.asm b/src/test/ref/struct-4.asm new file mode 100644 index 000000000..d8901027f --- /dev/null +++ b/src/test/ref/struct-4.asm @@ -0,0 +1,39 @@ +// Minimal struct - array of struct - near pointer math indexing +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const OFFS_X = 0 + .const OFFS_Y = 1 +main: { + .label SCREEN = $400 + ldx #0 + b1: + txa + asl + tay + txa + sta points+OFFS_X,y + txa + clc + adc #4 + // points[i].x = i; + sta points+OFFS_Y,y + inx + cpx #4 + bne b1 + ldy #0 + b2: + tya + asl + tax + lda points+OFFS_X,x + sta SCREEN,y + // SCREEN[i] = points[i].x; + lda points+OFFS_Y,x + sta SCREEN+$28,y + iny + cpy #4 + bne b2 + rts +} + points: .fill 2*4, 0 diff --git a/src/test/ref/struct-5.asm b/src/test/ref/struct-5.asm new file mode 100644 index 000000000..3bbbba092 --- /dev/null +++ b/src/test/ref/struct-5.asm @@ -0,0 +1,67 @@ +// Minimal struct - array of struct - far pointer math indexing +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const OFFS_X = 0 + .const OFFS_Y = 1 +main: { + .label SCREEN = $400 + .label _1 = 4 + .label _3 = 2 + .label _8 = 4 + .label _11 = 2 + .label point_i = 2 + .label point_i1 = 2 + ldx #0 + b1: + txa + asl + clc + adc #<points + sta point_i + lda #>points + adc #0 + sta point_i+1 + lda point_i + sta _1 + lda point_i+1 + sta _1+1 + txa + ldy #OFFS_X + sta (_1),y + txa + clc + adc #4 + // points[i].x = i; + ldy #OFFS_Y + sta (_3),y + inx + cpx #4 + bne b1 + ldx #0 + b2: + txa + asl + clc + adc #<points + sta point_i1 + lda #>points + adc #0 + sta point_i1+1 + lda point_i1 + sta _8 + lda point_i1+1 + sta _8+1 + ldy #OFFS_X + lda (_8),y + sta SCREEN,x + // SCREEN[i] = points[i].x; + ldy #OFFS_Y + lda (_11),y + sta SCREEN+$28,x + inx + cpx #4 + bne b2 + rts +} + points: .fill 2*4, 0