diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 01a0a1e4a..e993969d8 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -252,6 +252,7 @@ public class Compiler { optimizations.add(new Pass2ComparisonOptimization(program)); optimizations.add(new Pass2ConstantCallPointerIdentification(program)); optimizations.add(new Pass2MultiplyToShiftRewriting(program)); + optimizations.add(new Pass2SizeOfSimplification(program)); pass2Execute(optimizations); } diff --git a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java index 11fa4b075..fec6f0316 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java @@ -263,18 +263,18 @@ public class VariableReferenceInfos { /** - * Get all constatns referencing another constant + * Get all constants (or symbol definitions) referencing another constant * * @param constRef The constant to look for - * @return All constants that reference the constant in their value + * @return All constants (or symbol definitions) that reference the constant in their value */ - public Collection getConstRefConsts(ConstantRef constRef) { + public Collection getSymbolRefConsts(ConstantRef constRef) { Collection refs = symbolVarReferences.get(constRef); - LinkedHashSet constRefs = new LinkedHashSet<>(); + LinkedHashSet constRefs = new LinkedHashSet<>(); refs.stream() .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType())) .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol) - .forEach(referenceToSymbolVar -> constRefs.add((ConstantRef) ((ReferenceInSymbol) referenceToSymbolVar).getReferencingSymbol())); + .forEach(referenceToSymbolVar -> constRefs.add(((ReferenceInSymbol) referenceToSymbolVar).getReferencingSymbol())); return constRefs; } 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 cfda70105..5b3c998dd 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAddressOf.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAddressOf.java @@ -1,6 +1,7 @@ package dk.camelot64.kickc.model.operators; 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; @@ -14,7 +15,7 @@ public class OperatorAddressOf extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral operand) { + public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { throw new ConstantNotLiteral("Constant not literal"); } 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 142af23b9..3ef8aac69 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseNot.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseNot.java @@ -1,6 +1,7 @@ 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; @@ -14,7 +15,7 @@ public class OperatorBitwiseNot extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral left) { + public ConstantLiteral calculateLiteral(ConstantLiteral left, ProgramScope scope) { if(left instanceof ConstantInteger) { return new ConstantInteger(Math.abs(~((ConstantInteger) left).getInteger())); } 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 a53e0006f..cb1c8a00e 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java @@ -1,6 +1,7 @@ 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; @@ -15,7 +16,7 @@ public class OperatorCastBool extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral value) { + public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0x1 & ((ConstantInteger) value).getValue()); } else if(value instanceof ConstantPointer) { 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 dbefb96ca..de2a37f71 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java @@ -1,6 +1,7 @@ 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; @@ -15,7 +16,7 @@ public class OperatorCastByte extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral value) { + public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xff & ((ConstantInteger) value).getValue()); } else if(value instanceof ConstantPointer) { 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 810aab36f..f27ae69e2 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java @@ -1,6 +1,7 @@ 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; @@ -15,7 +16,7 @@ public class OperatorCastDWord extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral value) { + public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue()); } 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 9069f53a0..33215cfdb 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java @@ -1,6 +1,7 @@ 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.SymbolTypePointer; import dk.camelot64.kickc.model.types.SymbolTypeSimple; @@ -19,7 +20,7 @@ public class OperatorCastPtr extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral value) { + public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantPointer(((ConstantInteger) value).getInteger(), elementType); } else if(value instanceof ConstantPointer) { 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 6a901bc41..8013ce770 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java @@ -1,6 +1,7 @@ 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; @@ -14,7 +15,7 @@ public class OperatorCastSByte extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral value) { + public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xff & ((ConstantInteger) value).getValue()); } 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 bef969f2b..01f5137bf 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java @@ -1,6 +1,7 @@ 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; @@ -14,7 +15,7 @@ public class OperatorCastSDWord extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral value) { + public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue()); } 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 e0ea0879a..ca7f35d83 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java @@ -1,6 +1,7 @@ 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; @@ -14,7 +15,7 @@ public class OperatorCastSWord extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral value) { + public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue()); } 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 ea9074ee0..6414be198 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java @@ -1,6 +1,7 @@ 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; @@ -15,7 +16,7 @@ public class OperatorCastWord extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral value) { + public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue()); } 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 30dbbbb7a..76dbf6087 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.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; @@ -14,7 +15,7 @@ public class OperatorDecrement extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral operand) { + public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { if(operand instanceof ConstantInteger ) { return new ConstantInteger(((ConstantInteger) operand).getInteger() -1); } 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 991f6ed6f..c8a524b31 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDeref.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDeref.java @@ -1,6 +1,7 @@ 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.SymbolTypePointer; import dk.camelot64.kickc.model.types.SymbolTypeSimple; @@ -14,7 +15,7 @@ public class OperatorDeref extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral operand) { + public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { throw new CompileError("Calculation not implemented " + getOperator() + " " + operand ); } 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 734e50e0c..2a76c569b 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java @@ -2,6 +2,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.types.SymbolTypePointer; import dk.camelot64.kickc.model.types.SymbolTypeSimple; @@ -18,7 +19,7 @@ public class OperatorGetHigh extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral operand) { + public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { if(operand instanceof ConstantInteger) { ConstantInteger operandInt = (ConstantInteger) operand; if(SymbolType.isWord(operandInt.getType()) || SymbolType.isSWord(operandInt.getType())) { 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 6fa234860..bd8d030f3 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java @@ -2,6 +2,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.types.SymbolTypePointer; import dk.camelot64.kickc.model.types.SymbolTypeSimple; @@ -18,7 +19,7 @@ public class OperatorGetLow extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral operand) { + public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { if(operand instanceof ConstantInteger) { ConstantInteger operandInt = (ConstantInteger) operand; if(SymbolType.isWord(operandInt.getType()) || SymbolType.isSWord(operandInt.getType())) { 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 5514a68b0..70671914f 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,7 @@ 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; @@ -15,7 +16,7 @@ public class OperatorIncrement extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral operand) { + public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { if(operand instanceof ConstantInteger ) { return new ConstantInteger(((ConstantInteger) operand).getInteger() + 1); } else if(operand instanceof ConstantPointer) { 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 9b7f39a56..740f1ce01 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicNot.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicNot.java @@ -1,6 +1,7 @@ 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; @@ -14,7 +15,7 @@ public class OperatorLogicNot extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral left) { + public ConstantLiteral calculateLiteral(ConstantLiteral left, ProgramScope scope) { if(left instanceof ConstantBool) { return new ConstantBool(!((ConstantBool) left).getBool() ); } 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 45fe7d0d8..ce736a9d1 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorNeg.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorNeg.java @@ -1,6 +1,7 @@ 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; @@ -14,7 +15,7 @@ public class OperatorNeg extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral operand) { + public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { if(operand instanceof ConstantInteger) { return new ConstantInteger(-((ConstantInteger)operand).getInteger()); } 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 4e70ca96a..03acd3465 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPos.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPos.java @@ -1,6 +1,7 @@ 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; @@ -14,7 +15,7 @@ public class OperatorPos extends OperatorUnary { } @Override - public ConstantLiteral calculateLiteral(ConstantLiteral operand) { + public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { if(operand instanceof ConstantInteger) { return new ConstantInteger(+((ConstantInteger)operand).getInteger()); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java new file mode 100644 index 000000000..a824028b6 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java @@ -0,0 +1,66 @@ +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; +import dk.camelot64.kickc.model.values.ConstantLiteral; +import dk.camelot64.kickc.model.values.ConstantRef; + +/** SizeOf operator sizeof(expr). Will be resolved into a constant as soon as the expression has been resolved enough. */ +public class OperatorSizeOf extends OperatorUnary { + + public OperatorSizeOf(int precedence) { + super("sizeof ", "_sizeof_", precedence); + } + + @Override + public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) { + SymbolType type = operand.getType(scope); + return new ConstantInteger((long)type.getSizeBytes()); + } + + @Override + public SymbolType inferType(SymbolTypeSimple operandType) { + return SymbolType.BYTE; + } + + /** + * 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 + */ + public static ConstantRef getSizeOfConstantVar(ProgramScope programScope, SymbolType type) { + String typeConstName = getSizeofConstantName(type); + ConstantVar typeSizeConstant = programScope.getConstant(typeConstName); + if(typeSizeConstant ==null) { + // Constant not found - create it + long typeSize = type.getSizeBytes(); + typeSizeConstant = new ConstantVar(typeConstName, programScope, SymbolType.BYTE, new ConstantInteger(typeSize)); + programScope.add(typeSizeConstant); + } + return typeSizeConstant.getRef(); + } + + /** + * 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 = ((SymbolTypeMulti) type).getTypes().iterator().next(); + return getSizeofConstantName(subType); + } else if(type instanceof SymbolTypePointer) { + return "SIZEOF_POINTER"; + } else { + return "SIZEOF_"+type.getTypeName().toUpperCase().replace(" ", "_"); + } + } + +} 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 433488b36..d9efd026f 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorUnary.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorUnary.java @@ -1,5 +1,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; @@ -14,9 +15,10 @@ public abstract class OperatorUnary extends Operator { /** * Calculate the literal value of the operator applied to a constant operand * @param operand The constant operand + * @param scope * @return The literal value */ - public abstract ConstantLiteral calculateLiteral(ConstantLiteral operand); + public abstract ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope); /** * Infer the type of the operator applied to an operand of a specific type 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 f905b1f1e..c0fa62d06 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,7 @@ 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 SIZEOF = new OperatorSizeOf(2); public static final OperatorBinary MULTIPLY = new OperatorMultiply(3); public static final OperatorBinary DIVIDE = new OperatorDivide(3); public static final OperatorBinary MODULO = new OperatorModulo(3); 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 3c359e40f..c08d7adbf 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java @@ -21,7 +21,7 @@ public interface SymbolType { /** Signed double word (4 bytes, 32 bits). */ SymbolTypeInteger SDWORD = new SymbolTypeInteger("signed dword", -2_147_483_648, 2_147_483_647, true, 32); /** String value (treated like byte* ). */ - SymbolTypeNamed STRING = new SymbolTypeNamed("string", -1); + SymbolTypeNamed STRING = new SymbolTypeNamed("string", 99); /** Boolean value. */ SymbolTypeNamed BOOLEAN = new SymbolTypeNamed("bool", 1); /** Numeric floating point 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 e20f02bec..cd403a5a3 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -34,7 +34,7 @@ public class SymbolTypeInference { try { ConstantValue constRValue = (ConstantValue) rValue; ConstantLiteral literalRValue = constRValue.calculateLiteral(programScope); - ConstantValue value = operator.calculateLiteral(literalRValue); + ConstantValue value = operator.calculateLiteral(literalRValue, programScope); return value.getType(programScope); } catch(ConstantNotLiteral e) { // Value literal cannot be calculated 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 92fc146c5..802810c7f 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java @@ -26,7 +26,19 @@ public class SymbolTypeMulti implements SymbolType { @Override public int getSizeBytes() { - return -1; + // 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 diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantCastValue.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantCastValue.java index de973db90..f24090e22 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantCastValue.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantCastValue.java @@ -1,7 +1,6 @@ package dk.camelot64.kickc.model.values; import dk.camelot64.kickc.model.Program; -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.symbols.ProgramScope; @@ -34,7 +33,7 @@ public class ConstantCastValue implements ConstantValue { public ConstantLiteral calculateLiteral(ProgramScope scope) { ConstantLiteral valueLiteral = value.calculateLiteral(scope); OperatorUnary castOperator = Operators.getCastUnary(toType); - return castOperator.calculateLiteral(valueLiteral); + return castOperator.calculateLiteral(valueLiteral, scope); } public SymbolType getToType() { 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 fd9d7b16a..80fc32871 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,7 @@ public class ConstantUnary implements ConstantValue { @Override public ConstantLiteral calculateLiteral(ProgramScope scope) { - return operator.calculateLiteral(operand.calculateLiteral(scope)); + return operator.calculateLiteral(operand.calculateLiteral(scope), scope); } @Override diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 index 5ea6d5c13..be888bc09 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 +++ b/src/main/java/dk/camelot64/kickc/parser/KickC.g4 @@ -112,7 +112,7 @@ commaExpr expr : '(' commaExpr ')' #exprPar | expr '(' parameterList? ')' #exprCall - | 'sizeof' '(' typeDecl ')' #exprSizeOfType + | 'sizeof' '(' ( typeDecl | expr ) ')' #exprSizeOf | expr '[' commaExpr ']' #exprArray | '(' typeDecl ')' expr #exprCast | ('--' | '++' ) expr #exprPreMod diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java index c6d5c93d7..005a13201 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java @@ -647,18 +647,6 @@ public class KickCBaseListener implements KickCListener { *

The default implementation does nothing.

*/ @Override public void exitExprChar(KickCParser.ExprCharContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterExprSizeOfType(KickCParser.ExprSizeOfTypeContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitExprSizeOfType(KickCParser.ExprSizeOfTypeContext ctx) { } /** * {@inheritDoc} * @@ -707,6 +695,18 @@ public class KickCBaseListener implements KickCListener { *

The default implementation does nothing.

*/ @Override public void exitExprPar(KickCParser.ExprParContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterExprSizeOf(KickCParser.ExprSizeOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitExprSizeOf(KickCParser.ExprSizeOfContext 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 99e76addf..15e991bca 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java @@ -382,13 +382,6 @@ public class KickCBaseVisitor extends AbstractParseTreeVisitor implements * {@link #visitChildren} on {@code ctx}.

*/ @Override public T visitExprChar(KickCParser.ExprCharContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitExprSizeOfType(KickCParser.ExprSizeOfTypeContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * @@ -417,6 +410,13 @@ public class KickCBaseVisitor extends AbstractParseTreeVisitor implements * {@link #visitChildren} on {@code ctx}.

*/ @Override public T visitExprPar(KickCParser.ExprParContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitExprSizeOf(KickCParser.ExprSizeOfContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java index b52ec88de..3cdc27a95 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java @@ -617,18 +617,6 @@ public interface KickCListener extends ParseTreeListener { * @param ctx the parse tree */ void exitExprChar(KickCParser.ExprCharContext ctx); - /** - * Enter a parse tree produced by the {@code exprSizeOfType} - * labeled alternative in {@link KickCParser#expr}. - * @param ctx the parse tree - */ - void enterExprSizeOfType(KickCParser.ExprSizeOfTypeContext ctx); - /** - * Exit a parse tree produced by the {@code exprSizeOfType} - * labeled alternative in {@link KickCParser#expr}. - * @param ctx the parse tree - */ - void exitExprSizeOfType(KickCParser.ExprSizeOfTypeContext ctx); /** * Enter a parse tree produced by the {@code initList} * labeled alternative in {@link KickCParser#expr}. @@ -677,6 +665,18 @@ public interface KickCListener extends ParseTreeListener { * @param ctx the parse tree */ void exitExprPar(KickCParser.ExprParContext ctx); + /** + * Enter a parse tree produced by the {@code exprSizeOf} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + */ + void enterExprSizeOf(KickCParser.ExprSizeOfContext ctx); + /** + * Exit a parse tree produced by the {@code exprSizeOf} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + */ + void exitExprSizeOf(KickCParser.ExprSizeOfContext ctx); /** * Enter a parse tree produced by the {@code exprString} * 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 69de27de0..bac17c62b 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java @@ -2528,25 +2528,6 @@ public class KickCParser extends Parser { else return visitor.visitChildren(this); } } - public static class ExprSizeOfTypeContext extends ExprContext { - public TypeDeclContext typeDecl() { - return getRuleContext(TypeDeclContext.class,0); - } - public ExprSizeOfTypeContext(ExprContext ctx) { copyFrom(ctx); } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof KickCListener ) ((KickCListener)listener).enterExprSizeOfType(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof KickCListener ) ((KickCListener)listener).exitExprSizeOfType(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof KickCVisitor ) return ((KickCVisitor)visitor).visitExprSizeOfType(this); - else return visitor.visitChildren(this); - } - } public static class InitListContext extends ExprContext { public List expr() { return getRuleContexts(ExprContext.class); @@ -2632,6 +2613,28 @@ public class KickCParser extends Parser { else return visitor.visitChildren(this); } } + public static class ExprSizeOfContext extends ExprContext { + public TypeDeclContext typeDecl() { + return getRuleContext(TypeDeclContext.class,0); + } + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); + } + public ExprSizeOfContext(ExprContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).enterExprSizeOf(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).exitExprSizeOf(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KickCVisitor ) return ((KickCVisitor)visitor).visitExprSizeOf(this); + else return visitor.visitChildren(this); + } + } public static class ExprStringContext extends ExprContext { public TerminalNode STRING() { return getToken(KickCParser.STRING, 0); } public ExprStringContext(ExprContext ctx) { copyFrom(ctx); } @@ -2788,9 +2791,9 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(354); + setState(357); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,33,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,34,_ctx) ) { case 1: { _localctx = new ExprParContext(_localctx); @@ -2807,16 +2810,30 @@ public class KickCParser extends Parser { break; case 2: { - _localctx = new ExprSizeOfTypeContext(_localctx); + _localctx = new ExprSizeOfContext(_localctx); _ctx = _localctx; _prevctx = _localctx; setState(320); match(T__31); setState(321); match(T__4); - setState(322); - typeDecl(0); - setState(323); + setState(324); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,32,_ctx) ) { + case 1: + { + setState(322); + typeDecl(0); + } + break; + case 2: + { + setState(323); + expr(0); + } + break; + } + setState(326); match(T__5); } break; @@ -2825,13 +2842,13 @@ public class KickCParser extends Parser { _localctx = new ExprCastContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(325); - match(T__4); - setState(326); - typeDecl(0); - setState(327); - match(T__5); setState(328); + match(T__4); + setState(329); + typeDecl(0); + setState(330); + match(T__5); + setState(331); expr(24); } break; @@ -2840,7 +2857,7 @@ public class KickCParser extends Parser { _localctx = new ExprPreModContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(330); + setState(333); _la = _input.LA(1); if ( !(_la==T__32 || _la==T__33) ) { _errHandler.recoverInline(this); @@ -2850,7 +2867,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(331); + setState(334); expr(23); } break; @@ -2859,9 +2876,9 @@ public class KickCParser extends Parser { _localctx = new ExprPtrContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(332); + setState(335); match(T__28); - setState(333); + setState(336); expr(21); } break; @@ -2870,7 +2887,7 @@ public class KickCParser extends Parser { _localctx = new ExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(334); + setState(337); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38))) != 0)) ) { _errHandler.recoverInline(this); @@ -2880,7 +2897,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(335); + setState(338); expr(20); } break; @@ -2889,7 +2906,7 @@ public class KickCParser extends Parser { _localctx = new ExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(336); + setState(339); _la = _input.LA(1); if ( !(_la==T__43 || _la==T__44) ) { _errHandler.recoverInline(this); @@ -2899,7 +2916,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(337); + setState(340); expr(16); } break; @@ -2908,27 +2925,27 @@ public class KickCParser extends Parser { _localctx = new InitListContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(338); + setState(341); match(T__6); - setState(339); + setState(342); expr(0); - setState(344); + setState(347); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(340); + setState(343); match(T__2); - setState(341); + setState(344); expr(0); } } - setState(346); + setState(349); _errHandler.sync(this); _la = _input.LA(1); } - setState(347); + setState(350); match(T__7); } break; @@ -2937,7 +2954,7 @@ public class KickCParser extends Parser { _localctx = new ExprIdContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(349); + setState(352); match(NAME); } break; @@ -2946,7 +2963,7 @@ public class KickCParser extends Parser { _localctx = new ExprNumberContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(350); + setState(353); match(NUMBER); } break; @@ -2955,7 +2972,7 @@ public class KickCParser extends Parser { _localctx = new ExprStringContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(351); + setState(354); match(STRING); } break; @@ -2964,7 +2981,7 @@ public class KickCParser extends Parser { _localctx = new ExprCharContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(352); + setState(355); match(CHAR); } break; @@ -2973,30 +2990,30 @@ public class KickCParser extends Parser { _localctx = new ExprBoolContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(353); + setState(356); match(BOOLEAN); } break; } _ctx.stop = _input.LT(-1); - setState(410); + setState(413); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,36,_ctx); + _alt = getInterpreter().adaptivePredict(_input,37,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(408); + setState(411); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,35,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,36,_ctx) ) { case 1: { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(356); + setState(359); if (!(precpred(_ctx, 19))) throw new FailedPredicateException(this, "precpred(_ctx, 19)"); - setState(357); + setState(360); _la = _input.LA(1); if ( !(_la==T__39 || _la==T__40) ) { _errHandler.recoverInline(this); @@ -3006,7 +3023,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(358); + setState(361); expr(20); } break; @@ -3014,9 +3031,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(359); + setState(362); if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)"); - setState(360); + setState(363); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__28) | (1L << T__41) | (1L << T__42))) != 0)) ) { _errHandler.recoverInline(this); @@ -3026,7 +3043,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(361); + setState(364); expr(19); } break; @@ -3034,9 +3051,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(362); + setState(365); if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)"); - setState(363); + setState(366); _la = _input.LA(1); if ( !(_la==T__34 || _la==T__35) ) { _errHandler.recoverInline(this); @@ -3046,7 +3063,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(364); + setState(367); expr(18); } break; @@ -3054,9 +3071,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(365); + setState(368); if (!(precpred(_ctx, 15))) throw new FailedPredicateException(this, "precpred(_ctx, 15)"); - setState(366); + setState(369); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__43) | (1L << T__44) | (1L << T__45) | (1L << T__46) | (1L << T__47) | (1L << T__48))) != 0)) ) { _errHandler.recoverInline(this); @@ -3066,7 +3083,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(367); + setState(370); expr(16); } break; @@ -3074,13 +3091,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(368); + setState(371); if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)"); { - setState(369); + setState(372); match(T__37); } - setState(370); + setState(373); expr(15); } break; @@ -3088,13 +3105,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(371); + setState(374); if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); { - setState(372); + setState(375); match(T__49); } - setState(373); + setState(376); expr(14); } break; @@ -3102,13 +3119,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(374); + setState(377); if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); { - setState(375); + setState(378); match(T__50); } - setState(376); + setState(379); expr(13); } break; @@ -3116,13 +3133,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(377); + setState(380); if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); { - setState(378); + setState(381); match(T__51); } - setState(379); + setState(382); expr(12); } break; @@ -3130,13 +3147,13 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(380); + setState(383); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); { - setState(381); + setState(384); match(T__52); } - setState(382); + setState(385); expr(11); } break; @@ -3144,15 +3161,15 @@ public class KickCParser extends Parser { { _localctx = new ExprTernaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(383); - if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(384); - match(T__53); - setState(385); - expr(0); setState(386); - match(T__24); + if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); setState(387); + match(T__53); + setState(388); + expr(0); + setState(389); + match(T__24); + setState(390); expr(10); } break; @@ -3160,11 +3177,11 @@ public class KickCParser extends Parser { { _localctx = new ExprAssignmentContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(389); + setState(392); if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); - setState(390); + setState(393); match(T__3); - setState(391); + setState(394); expr(8); } break; @@ -3172,9 +3189,9 @@ public class KickCParser extends Parser { { _localctx = new ExprAssignmentCompoundContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(392); + setState(395); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(393); + setState(396); _la = _input.LA(1); if ( !(((((_la - 55)) & ~0x3f) == 0 && ((1L << (_la - 55)) & ((1L << (T__54 - 55)) | (1L << (T__55 - 55)) | (1L << (T__56 - 55)) | (1L << (T__57 - 55)) | (1L << (T__58 - 55)) | (1L << (T__59 - 55)) | (1L << (T__60 - 55)) | (1L << (T__61 - 55)) | (1L << (T__62 - 55)) | (1L << (T__63 - 55)))) != 0)) ) { _errHandler.recoverInline(this); @@ -3184,7 +3201,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(394); + setState(397); expr(7); } break; @@ -3192,21 +3209,21 @@ public class KickCParser extends Parser { { _localctx = new ExprCallContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(395); - if (!(precpred(_ctx, 27))) throw new FailedPredicateException(this, "precpred(_ctx, 27)"); - setState(396); - match(T__4); setState(398); + if (!(precpred(_ctx, 27))) throw new FailedPredicateException(this, "precpred(_ctx, 27)"); + setState(399); + match(T__4); + setState(401); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__28) | (1L << T__31) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__43) | (1L << T__44))) != 0) || ((((_la - 78)) & ~0x3f) == 0 && ((1L << (_la - 78)) & ((1L << (STRING - 78)) | (1L << (CHAR - 78)) | (1L << (BOOLEAN - 78)) | (1L << (NUMBER - 78)) | (1L << (NAME - 78)))) != 0)) { { - setState(397); + setState(400); parameterList(); } } - setState(400); + setState(403); match(T__5); } break; @@ -3214,13 +3231,13 @@ public class KickCParser extends Parser { { _localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(401); - if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)"); - setState(402); - match(T__29); - setState(403); - commaExpr(0); setState(404); + if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)"); + setState(405); + match(T__29); + setState(406); + commaExpr(0); + setState(407); match(T__30); } break; @@ -3228,9 +3245,9 @@ public class KickCParser extends Parser { { _localctx = new ExprPostModContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(406); + setState(409); if (!(precpred(_ctx, 22))) throw new FailedPredicateException(this, "precpred(_ctx, 22)"); - setState(407); + setState(410); _la = _input.LA(1); if ( !(_la==T__32 || _la==T__33) ) { _errHandler.recoverInline(this); @@ -3245,9 +3262,9 @@ public class KickCParser extends Parser { } } } - setState(412); + setState(415); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,36,_ctx); + _alt = getInterpreter().adaptivePredict(_input,37,_ctx); } } } @@ -3295,21 +3312,21 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(413); + setState(416); expr(0); - setState(418); + setState(421); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(414); + setState(417); match(T__2); - setState(415); + setState(418); expr(0); } } - setState(420); + setState(423); _errHandler.sync(this); _la = _input.LA(1); } @@ -3357,19 +3374,19 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(421); + setState(424); match(T__64); - setState(423); + setState(426); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__4) { { - setState(422); + setState(425); asmDirectives(); } } - setState(425); + setState(428); match(KICKASM); } } @@ -3417,27 +3434,27 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(427); + setState(430); match(T__4); - setState(428); + setState(431); asmDirective(); - setState(433); + setState(436); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(429); + setState(432); match(T__2); - setState(430); + setState(433); asmDirective(); } } - setState(435); + setState(438); _errHandler.sync(this); _la = _input.LA(1); } - setState(436); + setState(439); match(T__5); } } @@ -3576,16 +3593,16 @@ public class KickCParser extends Parser { AsmDirectiveContext _localctx = new AsmDirectiveContext(_ctx, getState()); enterRule(_localctx, 48, RULE_asmDirective); try { - setState(453); + setState(456); _errHandler.sync(this); switch (_input.LA(1)) { case T__65: _localctx = new AsmDirectiveResourceContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(438); + setState(441); match(T__65); - setState(439); + setState(442); match(STRING); } break; @@ -3593,9 +3610,9 @@ public class KickCParser extends Parser { _localctx = new AsmDirectiveUsesContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(440); + setState(443); match(T__66); - setState(441); + setState(444); match(NAME); } break; @@ -3603,9 +3620,9 @@ public class KickCParser extends Parser { _localctx = new AsmDirectiveClobberContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(442); + setState(445); match(T__67); - setState(443); + setState(446); match(STRING); } break; @@ -3613,9 +3630,9 @@ public class KickCParser extends Parser { _localctx = new AsmDirectiveBytesContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(444); + setState(447); match(T__68); - setState(445); + setState(448); expr(0); } break; @@ -3623,9 +3640,9 @@ public class KickCParser extends Parser { _localctx = new AsmDirectiveCyclesContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(446); + setState(449); match(T__69); - setState(447); + setState(450); expr(0); } break; @@ -3633,14 +3650,14 @@ public class KickCParser extends Parser { _localctx = new AsmDirectiveAddressContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(448); - match(T__70); setState(451); + match(T__70); + setState(454); _errHandler.sync(this); switch (_input.LA(1)) { case T__12: { - setState(449); + setState(452); match(T__12); } break; @@ -3663,7 +3680,7 @@ public class KickCParser extends Parser { case NUMBER: case NAME: { - setState(450); + setState(453); expr(0); } break; @@ -3720,17 +3737,17 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(458); + setState(461); _errHandler.sync(this); _la = _input.LA(1); while (((((_la - 37)) & ~0x3f) == 0 && ((1L << (_la - 37)) & ((1L << (T__36 - 37)) | (1L << (T__71 - 37)) | (1L << (MNEMONIC - 37)) | (1L << (NAME - 37)))) != 0)) { { { - setState(455); + setState(458); asmLine(); } } - setState(460); + setState(463); _errHandler.sync(this); _la = _input.LA(1); } @@ -3780,28 +3797,28 @@ public class KickCParser extends Parser { AsmLineContext _localctx = new AsmLineContext(_ctx, getState()); enterRule(_localctx, 52, RULE_asmLine); try { - setState(464); + setState(467); _errHandler.sync(this); switch (_input.LA(1)) { case T__36: case NAME: enterOuterAlt(_localctx, 1); { - setState(461); + setState(464); asmLabel(); } break; case MNEMONIC: enterOuterAlt(_localctx, 2); { - setState(462); + setState(465); asmInstruction(); } break; case T__71: enterOuterAlt(_localctx, 3); { - setState(463); + setState(466); asmBytes(); } break; @@ -3871,16 +3888,16 @@ public class KickCParser extends Parser { enterRule(_localctx, 54, RULE_asmLabel); int _la; try { - setState(473); + setState(476); _errHandler.sync(this); switch (_input.LA(1)) { case NAME: _localctx = new AsmLabelNameContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(466); + setState(469); match(NAME); - setState(467); + setState(470); match(T__24); } break; @@ -3888,19 +3905,19 @@ public class KickCParser extends Parser { _localctx = new AsmLabelMultiContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(468); + setState(471); match(T__36); - setState(470); + setState(473); _errHandler.sync(this); _la = _input.LA(1); if (_la==NAME) { { - setState(469); + setState(472); match(NAME); } } - setState(472); + setState(475); match(T__24); } break; @@ -3949,14 +3966,14 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(475); + setState(478); match(MNEMONIC); - setState(477); + setState(480); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,46,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,47,_ctx) ) { case 1: { - setState(476); + setState(479); asmParamMode(); } break; @@ -4007,23 +4024,23 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(479); + setState(482); match(T__71); - setState(480); + setState(483); asmExpr(0); - setState(485); + setState(488); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(481); + setState(484); match(T__2); - setState(482); + setState(485); asmExpr(0); } } - setState(487); + setState(490); _errHandler.sync(this); _la = _input.LA(1); } @@ -4173,14 +4190,14 @@ public class KickCParser extends Parser { AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState()); enterRule(_localctx, 60, RULE_asmParamMode); try { - setState(511); + setState(514); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,48,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,49,_ctx) ) { case 1: _localctx = new AsmModeAbsContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(488); + setState(491); asmExpr(0); } break; @@ -4188,9 +4205,9 @@ public class KickCParser extends Parser { _localctx = new AsmModeImmContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(489); + setState(492); match(T__72); - setState(490); + setState(493); asmExpr(0); } break; @@ -4198,11 +4215,11 @@ public class KickCParser extends Parser { _localctx = new AsmModeAbsXYContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(491); + setState(494); asmExpr(0); - setState(492); + setState(495); match(T__2); - setState(493); + setState(496); match(NAME); } break; @@ -4210,15 +4227,15 @@ public class KickCParser extends Parser { _localctx = new AsmModeIndIdxXYContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(495); - match(T__4); - setState(496); - asmExpr(0); - setState(497); - match(T__5); setState(498); - match(T__2); + match(T__4); setState(499); + asmExpr(0); + setState(500); + match(T__5); + setState(501); + match(T__2); + setState(502); match(NAME); } break; @@ -4226,15 +4243,15 @@ public class KickCParser extends Parser { _localctx = new AsmModeIdxIndXYContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(501); - match(T__4); - setState(502); - asmExpr(0); - setState(503); - match(T__2); setState(504); - match(NAME); + match(T__4); setState(505); + asmExpr(0); + setState(506); + match(T__2); + setState(507); + match(NAME); + setState(508); match(T__5); } break; @@ -4242,11 +4259,11 @@ public class KickCParser extends Parser { _localctx = new AsmModeIndContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(507); + setState(510); match(T__4); - setState(508); + setState(511); asmExpr(0); - setState(509); + setState(512); match(T__5); } break; @@ -4436,7 +4453,7 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(527); + setState(530); _errHandler.sync(this); switch (_input.LA(1)) { case T__29: @@ -4445,11 +4462,11 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(514); + setState(517); match(T__29); - setState(515); + setState(518); asmExpr(0); - setState(516); + setState(519); match(T__30); } break; @@ -4461,7 +4478,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(518); + setState(521); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__34) | (1L << T__35) | (1L << T__43) | (1L << T__44))) != 0)) ) { _errHandler.recoverInline(this); @@ -4471,7 +4488,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(519); + setState(522); asmExpr(8); } break; @@ -4480,7 +4497,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprLabelContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(520); + setState(523); match(NAME); } break; @@ -4489,7 +4506,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprLabelRelContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(521); + setState(524); match(ASMREL); } break; @@ -4498,11 +4515,11 @@ public class KickCParser extends Parser { _localctx = new AsmExprReplaceContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(522); + setState(525); match(T__6); - setState(523); + setState(526); match(NAME); - setState(524); + setState(527); match(T__7); } break; @@ -4511,7 +4528,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprIntContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(525); + setState(528); match(NUMBER); } break; @@ -4520,7 +4537,7 @@ public class KickCParser extends Parser { _localctx = new AsmExprCharContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(526); + setState(529); match(CHAR); } break; @@ -4528,28 +4545,28 @@ public class KickCParser extends Parser { throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(543); + setState(546); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,51,_ctx); + _alt = getInterpreter().adaptivePredict(_input,52,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(541); + setState(544); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,50,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { case 1: { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(529); + setState(532); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); { - setState(530); + setState(533); match(T__73); } - setState(531); + setState(534); asmExpr(11); } break; @@ -4557,9 +4574,9 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(532); + setState(535); if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(533); + setState(536); _la = _input.LA(1); if ( !(_la==T__39 || _la==T__40) ) { _errHandler.recoverInline(this); @@ -4569,7 +4586,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(534); + setState(537); asmExpr(10); } break; @@ -4577,9 +4594,9 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(535); + setState(538); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(536); + setState(539); _la = _input.LA(1); if ( !(_la==T__28 || _la==T__41) ) { _errHandler.recoverInline(this); @@ -4589,7 +4606,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(537); + setState(540); asmExpr(8); } break; @@ -4597,9 +4614,9 @@ public class KickCParser extends Parser { { _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); - setState(538); + setState(541); if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); - setState(539); + setState(542); _la = _input.LA(1); if ( !(_la==T__34 || _la==T__35) ) { _errHandler.recoverInline(this); @@ -4609,16 +4626,16 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(540); + setState(543); asmExpr(7); } break; } } } - setState(545); + setState(548); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,51,_ctx); + _alt = getInterpreter().adaptivePredict(_input,52,_ctx); } } } @@ -4723,7 +4740,7 @@ public class KickCParser extends Parser { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3`\u0225\4\2\t\2\4"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3`\u0228\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"+ @@ -4748,194 +4765,195 @@ public class KickCParser extends Parser { "\24\3\24\3\24\3\24\3\24\3\24\3\24\5\24\u0121\n\24\3\24\3\24\3\24\3\24"+ "\3\24\5\24\u0128\n\24\3\24\3\24\3\24\3\24\7\24\u012e\n\24\f\24\16\24\u0131"+ "\13\24\3\25\3\25\3\25\3\25\3\25\3\25\7\25\u0139\n\25\f\25\16\25\u013c"+ - "\13\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26"+ - "\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26"+ - "\7\26\u0159\n\26\f\26\16\26\u015c\13\26\3\26\3\26\3\26\3\26\3\26\3\26"+ - "\3\26\5\26\u0165\n\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26"+ + "\13\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\5\26\u0147\n\26\3"+ + "\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3"+ + "\26\3\26\3\26\3\26\3\26\7\26\u015c\n\26\f\26\16\26\u015f\13\26\3\26\3"+ + "\26\3\26\3\26\3\26\3\26\3\26\5\26\u0168\n\26\3\26\3\26\3\26\3\26\3\26"+ "\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26"+ "\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26"+ - "\3\26\3\26\3\26\3\26\5\26\u0191\n\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26"+ - "\3\26\7\26\u019b\n\26\f\26\16\26\u019e\13\26\3\27\3\27\3\27\7\27\u01a3"+ - "\n\27\f\27\16\27\u01a6\13\27\3\30\3\30\5\30\u01aa\n\30\3\30\3\30\3\31"+ - "\3\31\3\31\3\31\7\31\u01b2\n\31\f\31\16\31\u01b5\13\31\3\31\3\31\3\32"+ - "\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\5\32\u01c6"+ - "\n\32\5\32\u01c8\n\32\3\33\7\33\u01cb\n\33\f\33\16\33\u01ce\13\33\3\34"+ - "\3\34\3\34\5\34\u01d3\n\34\3\35\3\35\3\35\3\35\5\35\u01d9\n\35\3\35\5"+ - "\35\u01dc\n\35\3\36\3\36\5\36\u01e0\n\36\3\37\3\37\3\37\3\37\7\37\u01e6"+ - "\n\37\f\37\16\37\u01e9\13\37\3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3"+ - " \3 \3 \3 \3 \3 \3 \3 \3 \3 \5 \u0202\n \3!\3!\3!\3!\3!\3!\3!\3!\3!\3"+ - "!\3!\3!\3!\3!\5!\u0212\n!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\7!\u0220"+ - "\n!\f!\16!\u0223\13!\3!\2\7\22&(*@\"\2\4\6\b\n\f\16\20\22\24\26\30\32"+ - "\34\36 \"$&(*,.\60\62\64\668:<>@\2\r\3\2\35\36\3\2#$\3\2%)\3\2./\3\2*"+ - "+\4\2\37\37,-\3\2%&\3\2.\63\3\29B\4\2%&./\4\2\37\37,,\2\u0272\2B\3\2\2"+ - "\2\4F\3\2\2\2\6L\3\2\2\2\bO\3\2\2\2\nS\3\2\2\2\f\\\3\2\2\2\16a\3\2\2\2"+ - "\20k\3\2\2\2\22n\3\2\2\2\24y\3\2\2\2\26~\3\2\2\2\30\u008b\3\2\2\2\32\u0097"+ - "\3\2\2\2\34\u00ab\3\2\2\2\36\u00ae\3\2\2\2 \u00fe\3\2\2\2\"\u0110\3\2"+ - "\2\2$\u0116\3\2\2\2&\u0120\3\2\2\2(\u0132\3\2\2\2*\u0164\3\2\2\2,\u019f"+ - "\3\2\2\2.\u01a7\3\2\2\2\60\u01ad\3\2\2\2\62\u01c7\3\2\2\2\64\u01cc\3\2"+ - "\2\2\66\u01d2\3\2\2\28\u01db\3\2\2\2:\u01dd\3\2\2\2<\u01e1\3\2\2\2>\u0201"+ - "\3\2\2\2@\u0211\3\2\2\2BC\5\6\4\2CD\5\n\6\2DE\7\2\2\3E\3\3\2\2\2FG\5\64"+ - "\33\2GH\7\2\2\3H\5\3\2\2\2IK\5\b\5\2JI\3\2\2\2KN\3\2\2\2LJ\3\2\2\2LM\3"+ - "\2\2\2M\7\3\2\2\2NL\3\2\2\2OP\7\3\2\2PQ\7P\2\2Q\t\3\2\2\2RT\5\f\7\2SR"+ - "\3\2\2\2TU\3\2\2\2US\3\2\2\2UV\3\2\2\2V\13\3\2\2\2WX\5\20\t\2XY\7\4\2"+ - "\2Y]\3\2\2\2Z]\5\26\f\2[]\5.\30\2\\W\3\2\2\2\\Z\3\2\2\2\\[\3\2\2\2]\r"+ - "\3\2\2\2^`\5\34\17\2_^\3\2\2\2`c\3\2\2\2a_\3\2\2\2ab\3\2\2\2bd\3\2\2\2"+ - "ca\3\2\2\2dh\5&\24\2eg\5\34\17\2fe\3\2\2\2gj\3\2\2\2hf\3\2\2\2hi\3\2\2"+ - "\2i\17\3\2\2\2jh\3\2\2\2kl\5\16\b\2lm\5\22\n\2m\21\3\2\2\2no\b\n\1\2o"+ - "p\5\24\13\2pv\3\2\2\2qr\f\3\2\2rs\7\5\2\2su\5\24\13\2tq\3\2\2\2ux\3\2"+ - "\2\2vt\3\2\2\2vw\3\2\2\2w\23\3\2\2\2xv\3\2\2\2y|\7\\\2\2z{\7\6\2\2{}\5"+ - "*\26\2|z\3\2\2\2|}\3\2\2\2}\25\3\2\2\2~\177\5\16\b\2\177\u0080\7\\\2\2"+ - "\u0080\u0082\7\7\2\2\u0081\u0083\5\30\r\2\u0082\u0081\3\2\2\2\u0082\u0083"+ - "\3\2\2\2\u0083\u0084\3\2\2\2\u0084\u0085\7\b\2\2\u0085\u0087\7\t\2\2\u0086"+ - "\u0088\5\36\20\2\u0087\u0086\3\2\2\2\u0087\u0088\3\2\2\2\u0088\u0089\3"+ - "\2\2\2\u0089\u008a\7\n\2\2\u008a\27\3\2\2\2\u008b\u0090\5\32\16\2\u008c"+ - "\u008d\7\5\2\2\u008d\u008f\5\32\16\2\u008e\u008c\3\2\2\2\u008f\u0092\3"+ - "\2\2\2\u0090\u008e\3\2\2\2\u0090\u0091\3\2\2\2\u0091\31\3\2\2\2\u0092"+ - "\u0090\3\2\2\2\u0093\u0094\5\16\b\2\u0094\u0095\7\\\2\2\u0095\u0098\3"+ - "\2\2\2\u0096\u0098\7O\2\2\u0097\u0093\3\2\2\2\u0097\u0096\3\2\2\2\u0098"+ - "\33\3\2\2\2\u0099\u00ac\7\13\2\2\u009a\u00ac\7\f\2\2\u009b\u009c\7\r\2"+ - "\2\u009c\u009d\7\7\2\2\u009d\u009e\7S\2\2\u009e\u00ac\7\b\2\2\u009f\u00a0"+ - "\7\16\2\2\u00a0\u00a1\7\7\2\2\u00a1\u00a2\7\\\2\2\u00a2\u00ac\7\b\2\2"+ - "\u00a3\u00ac\7\17\2\2\u00a4\u00ac\7\20\2\2\u00a5\u00a9\7\21\2\2\u00a6"+ - "\u00a7\7\7\2\2\u00a7\u00a8\7\\\2\2\u00a8\u00aa\7\b\2\2\u00a9\u00a6\3\2"+ - "\2\2\u00a9\u00aa\3\2\2\2\u00aa\u00ac\3\2\2\2\u00ab\u0099\3\2\2\2\u00ab"+ - "\u009a\3\2\2\2\u00ab\u009b\3\2\2\2\u00ab\u009f\3\2\2\2\u00ab\u00a3\3\2"+ - "\2\2\u00ab\u00a4\3\2\2\2\u00ab\u00a5\3\2\2\2\u00ac\35\3\2\2\2\u00ad\u00af"+ - "\5 \21\2\u00ae\u00ad\3\2\2\2\u00af\u00b0\3\2\2\2\u00b0\u00ae\3\2\2\2\u00b0"+ - "\u00b1\3\2\2\2\u00b1\37\3\2\2\2\u00b2\u00b3\5\20\t\2\u00b3\u00b4\7\4\2"+ - "\2\u00b4\u00ff\3\2\2\2\u00b5\u00b7\7\t\2\2\u00b6\u00b8\5\36\20\2\u00b7"+ - "\u00b6\3\2\2\2\u00b7\u00b8\3\2\2\2\u00b8\u00b9\3\2\2\2\u00b9\u00ff\7\n"+ - "\2\2\u00ba\u00bb\5(\25\2\u00bb\u00bc\7\4\2\2\u00bc\u00ff\3\2\2\2\u00bd"+ - "\u00be\7\22\2\2\u00be\u00bf\7\7\2\2\u00bf\u00c0\5(\25\2\u00c0\u00c1\7"+ - "\b\2\2\u00c1\u00c4\5 \21\2\u00c2\u00c3\7\23\2\2\u00c3\u00c5\5 \21\2\u00c4"+ - "\u00c2\3\2\2\2\u00c4\u00c5\3\2\2\2\u00c5\u00ff\3\2\2\2\u00c6\u00c8\5\34"+ - "\17\2\u00c7\u00c6\3\2\2\2\u00c8\u00cb\3\2\2\2\u00c9\u00c7\3\2\2\2\u00c9"+ - "\u00ca\3\2\2\2\u00ca\u00cc\3\2\2\2\u00cb\u00c9\3\2\2\2\u00cc\u00cd\7\24"+ - "\2\2\u00cd\u00ce\7\7\2\2\u00ce\u00cf\5(\25\2\u00cf\u00d0\7\b\2\2\u00d0"+ - "\u00d1\5 \21\2\u00d1\u00ff\3\2\2\2\u00d2\u00d4\5\34\17\2\u00d3\u00d2\3"+ - "\2\2\2\u00d4\u00d7\3\2\2\2\u00d5\u00d3\3\2\2\2\u00d5\u00d6\3\2\2\2\u00d6"+ - "\u00d8\3\2\2\2\u00d7\u00d5\3\2\2\2\u00d8\u00d9\7\25\2\2\u00d9\u00da\5"+ - " \21\2\u00da\u00db\7\24\2\2\u00db\u00dc\7\7\2\2\u00dc\u00dd\5(\25\2\u00dd"+ - "\u00de\7\b\2\2\u00de\u00df\7\4\2\2\u00df\u00ff\3\2\2\2\u00e0\u00e2\5\34"+ - "\17\2\u00e1\u00e0\3\2\2\2\u00e2\u00e5\3\2\2\2\u00e3\u00e1\3\2\2\2\u00e3"+ - "\u00e4\3\2\2\2\u00e4\u00e6\3\2\2\2\u00e5\u00e3\3\2\2\2\u00e6\u00e7\7\26"+ - "\2\2\u00e7\u00e8\7\7\2\2\u00e8\u00e9\5\"\22\2\u00e9\u00ea\7\b\2\2\u00ea"+ - "\u00eb\5 \21\2\u00eb\u00ff\3\2\2\2\u00ec\u00ee\7\27\2\2\u00ed\u00ef\5"+ - "(\25\2\u00ee\u00ed\3\2\2\2\u00ee\u00ef\3\2\2\2\u00ef\u00f0\3\2\2\2\u00f0"+ - "\u00ff\7\4\2\2\u00f1\u00f2\7\30\2\2\u00f2\u00ff\7\4\2\2\u00f3\u00f4\7"+ - "\31\2\2\u00f4\u00ff\7\4\2\2\u00f5\u00f7\7\32\2\2\u00f6\u00f8\5\60\31\2"+ - "\u00f7\u00f6\3\2\2\2\u00f7\u00f8\3\2\2\2\u00f8\u00f9\3\2\2\2\u00f9\u00fa"+ - "\7\t\2\2\u00fa\u00fb\5\64\33\2\u00fb\u00fc\7\n\2\2\u00fc\u00ff\3\2\2\2"+ - "\u00fd\u00ff\5.\30\2\u00fe\u00b2\3\2\2\2\u00fe\u00b5\3\2\2\2\u00fe\u00ba"+ - "\3\2\2\2\u00fe\u00bd\3\2\2\2\u00fe\u00c9\3\2\2\2\u00fe\u00d5\3\2\2\2\u00fe"+ - "\u00e3\3\2\2\2\u00fe\u00ec\3\2\2\2\u00fe\u00f1\3\2\2\2\u00fe\u00f3\3\2"+ - "\2\2\u00fe\u00f5\3\2\2\2\u00fe\u00fd\3\2\2\2\u00ff!\3\2\2\2\u0100\u0101"+ - "\5$\23\2\u0101\u0102\7\4\2\2\u0102\u0103\5(\25\2\u0103\u0105\7\4\2\2\u0104"+ - "\u0106\5(\25\2\u0105\u0104\3\2\2\2\u0105\u0106\3\2\2\2\u0106\u0111\3\2"+ - "\2\2\u0107\u0109\5\16\b\2\u0108\u0107\3\2\2\2\u0108\u0109\3\2\2\2\u0109"+ - "\u010a\3\2\2\2\u010a\u010b\7\\\2\2\u010b\u010c\7\33\2\2\u010c\u010d\5"+ - "*\26\2\u010d\u010e\7\34\2\2\u010e\u010f\5*\26\2\u010f\u0111\3\2\2\2\u0110"+ - "\u0100\3\2\2\2\u0110\u0108\3\2\2\2\u0111#\3\2\2\2\u0112\u0114\5\20\t\2"+ - "\u0113\u0112\3\2\2\2\u0113\u0114\3\2\2\2\u0114\u0117\3\2\2\2\u0115\u0117"+ - "\5(\25\2\u0116\u0113\3\2\2\2\u0116\u0115\3\2\2\2\u0117%\3\2\2\2\u0118"+ - "\u0119\b\24\1\2\u0119\u011a\7\7\2\2\u011a\u011b\5&\24\2\u011b\u011c\7"+ - "\b\2\2\u011c\u0121\3\2\2\2\u011d\u0121\7O\2\2\u011e\u011f\t\2\2\2\u011f"+ - "\u0121\7O\2\2\u0120\u0118\3\2\2\2\u0120\u011d\3\2\2\2\u0120\u011e\3\2"+ - "\2\2\u0121\u012f\3\2\2\2\u0122\u0123\f\5\2\2\u0123\u012e\7\37\2\2\u0124"+ - "\u0125\f\4\2\2\u0125\u0127\7 \2\2\u0126\u0128\5*\26\2\u0127\u0126\3\2"+ - "\2\2\u0127\u0128\3\2\2\2\u0128\u0129\3\2\2\2\u0129\u012e\7!\2\2\u012a"+ - "\u012b\f\3\2\2\u012b\u012c\7\7\2\2\u012c\u012e\7\b\2\2\u012d\u0122\3\2"+ - "\2\2\u012d\u0124\3\2\2\2\u012d\u012a\3\2\2\2\u012e\u0131\3\2\2\2\u012f"+ - "\u012d\3\2\2\2\u012f\u0130\3\2\2\2\u0130\'\3\2\2\2\u0131\u012f\3\2\2\2"+ - "\u0132\u0133\b\25\1\2\u0133\u0134\5*\26\2\u0134\u013a\3\2\2\2\u0135\u0136"+ - "\f\3\2\2\u0136\u0137\7\5\2\2\u0137\u0139\5*\26\2\u0138\u0135\3\2\2\2\u0139"+ - "\u013c\3\2\2\2\u013a\u0138\3\2\2\2\u013a\u013b\3\2\2\2\u013b)\3\2\2\2"+ - "\u013c\u013a\3\2\2\2\u013d\u013e\b\26\1\2\u013e\u013f\7\7\2\2\u013f\u0140"+ - "\5(\25\2\u0140\u0141\7\b\2\2\u0141\u0165\3\2\2\2\u0142\u0143\7\"\2\2\u0143"+ - "\u0144\7\7\2\2\u0144\u0145\5&\24\2\u0145\u0146\7\b\2\2\u0146\u0165\3\2"+ - "\2\2\u0147\u0148\7\7\2\2\u0148\u0149\5&\24\2\u0149\u014a\7\b\2\2\u014a"+ - "\u014b\5*\26\32\u014b\u0165\3\2\2\2\u014c\u014d\t\3\2\2\u014d\u0165\5"+ - "*\26\31\u014e\u014f\7\37\2\2\u014f\u0165\5*\26\27\u0150\u0151\t\4\2\2"+ - "\u0151\u0165\5*\26\26\u0152\u0153\t\5\2\2\u0153\u0165\5*\26\22\u0154\u0155"+ - "\7\t\2\2\u0155\u015a\5*\26\2\u0156\u0157\7\5\2\2\u0157\u0159\5*\26\2\u0158"+ - "\u0156\3\2\2\2\u0159\u015c\3\2\2\2\u015a\u0158\3\2\2\2\u015a\u015b\3\2"+ - "\2\2\u015b\u015d\3\2\2\2\u015c\u015a\3\2\2\2\u015d\u015e\7\n\2\2\u015e"+ - "\u0165\3\2\2\2\u015f\u0165\7\\\2\2\u0160\u0165\7S\2\2\u0161\u0165\7P\2"+ - "\2\u0162\u0165\7Q\2\2\u0163\u0165\7R\2\2\u0164\u013d\3\2\2\2\u0164\u0142"+ - "\3\2\2\2\u0164\u0147\3\2\2\2\u0164\u014c\3\2\2\2\u0164\u014e\3\2\2\2\u0164"+ - "\u0150\3\2\2\2\u0164\u0152\3\2\2\2\u0164\u0154\3\2\2\2\u0164\u015f\3\2"+ - "\2\2\u0164\u0160\3\2\2\2\u0164\u0161\3\2\2\2\u0164\u0162\3\2\2\2\u0164"+ - "\u0163\3\2\2\2\u0165\u019c\3\2\2\2\u0166\u0167\f\25\2\2\u0167\u0168\t"+ - "\6\2\2\u0168\u019b\5*\26\26\u0169\u016a\f\24\2\2\u016a\u016b\t\7\2\2\u016b"+ - "\u019b\5*\26\25\u016c\u016d\f\23\2\2\u016d\u016e\t\b\2\2\u016e\u019b\5"+ - "*\26\24\u016f\u0170\f\21\2\2\u0170\u0171\t\t\2\2\u0171\u019b\5*\26\22"+ - "\u0172\u0173\f\20\2\2\u0173\u0174\7(\2\2\u0174\u019b\5*\26\21\u0175\u0176"+ - "\f\17\2\2\u0176\u0177\7\64\2\2\u0177\u019b\5*\26\20\u0178\u0179\f\16\2"+ - "\2\u0179\u017a\7\65\2\2\u017a\u019b\5*\26\17\u017b\u017c\f\r\2\2\u017c"+ - "\u017d\7\66\2\2\u017d\u019b\5*\26\16\u017e\u017f\f\f\2\2\u017f\u0180\7"+ - "\67\2\2\u0180\u019b\5*\26\r\u0181\u0182\f\13\2\2\u0182\u0183\78\2\2\u0183"+ - "\u0184\5*\26\2\u0184\u0185\7\33\2\2\u0185\u0186\5*\26\f\u0186\u019b\3"+ - "\2\2\2\u0187\u0188\f\n\2\2\u0188\u0189\7\6\2\2\u0189\u019b\5*\26\n\u018a"+ - "\u018b\f\t\2\2\u018b\u018c\t\n\2\2\u018c\u019b\5*\26\t\u018d\u018e\f\35"+ - "\2\2\u018e\u0190\7\7\2\2\u018f\u0191\5,\27\2\u0190\u018f\3\2\2\2\u0190"+ - "\u0191\3\2\2\2\u0191\u0192\3\2\2\2\u0192\u019b\7\b\2\2\u0193\u0194\f\33"+ - "\2\2\u0194\u0195\7 \2\2\u0195\u0196\5(\25\2\u0196\u0197\7!\2\2\u0197\u019b"+ - "\3\2\2\2\u0198\u0199\f\30\2\2\u0199\u019b\t\3\2\2\u019a\u0166\3\2\2\2"+ - "\u019a\u0169\3\2\2\2\u019a\u016c\3\2\2\2\u019a\u016f\3\2\2\2\u019a\u0172"+ - "\3\2\2\2\u019a\u0175\3\2\2\2\u019a\u0178\3\2\2\2\u019a\u017b\3\2\2\2\u019a"+ - "\u017e\3\2\2\2\u019a\u0181\3\2\2\2\u019a\u0187\3\2\2\2\u019a\u018a\3\2"+ - "\2\2\u019a\u018d\3\2\2\2\u019a\u0193\3\2\2\2\u019a\u0198\3\2\2\2\u019b"+ - "\u019e\3\2\2\2\u019c\u019a\3\2\2\2\u019c\u019d\3\2\2\2\u019d+\3\2\2\2"+ - "\u019e\u019c\3\2\2\2\u019f\u01a4\5*\26\2\u01a0\u01a1\7\5\2\2\u01a1\u01a3"+ - "\5*\26\2\u01a2\u01a0\3\2\2\2\u01a3\u01a6\3\2\2\2\u01a4\u01a2\3\2\2\2\u01a4"+ - "\u01a5\3\2\2\2\u01a5-\3\2\2\2\u01a6\u01a4\3\2\2\2\u01a7\u01a9\7C\2\2\u01a8"+ - "\u01aa\5\60\31\2\u01a9\u01a8\3\2\2\2\u01a9\u01aa\3\2\2\2\u01aa\u01ab\3"+ - "\2\2\2\u01ab\u01ac\7N\2\2\u01ac/\3\2\2\2\u01ad\u01ae\7\7\2\2\u01ae\u01b3"+ - "\5\62\32\2\u01af\u01b0\7\5\2\2\u01b0\u01b2\5\62\32\2\u01b1\u01af\3\2\2"+ - "\2\u01b2\u01b5\3\2\2\2\u01b3\u01b1\3\2\2\2\u01b3\u01b4\3\2\2\2\u01b4\u01b6"+ - "\3\2\2\2\u01b5\u01b3\3\2\2\2\u01b6\u01b7\7\b\2\2\u01b7\61\3\2\2\2\u01b8"+ - "\u01b9\7D\2\2\u01b9\u01c8\7P\2\2\u01ba\u01bb\7E\2\2\u01bb\u01c8\7\\\2"+ - "\2\u01bc\u01bd\7F\2\2\u01bd\u01c8\7P\2\2\u01be\u01bf\7G\2\2\u01bf\u01c8"+ - "\5*\26\2\u01c0\u01c1\7H\2\2\u01c1\u01c8\5*\26\2\u01c2\u01c5\7I\2\2\u01c3"+ - "\u01c6\7\17\2\2\u01c4\u01c6\5*\26\2\u01c5\u01c3\3\2\2\2\u01c5\u01c4\3"+ - "\2\2\2\u01c6\u01c8\3\2\2\2\u01c7\u01b8\3\2\2\2\u01c7\u01ba\3\2\2\2\u01c7"+ - "\u01bc\3\2\2\2\u01c7\u01be\3\2\2\2\u01c7\u01c0\3\2\2\2\u01c7\u01c2\3\2"+ - "\2\2\u01c8\63\3\2\2\2\u01c9\u01cb\5\66\34\2\u01ca\u01c9\3\2\2\2\u01cb"+ - "\u01ce\3\2\2\2\u01cc\u01ca\3\2\2\2\u01cc\u01cd\3\2\2\2\u01cd\65\3\2\2"+ - "\2\u01ce\u01cc\3\2\2\2\u01cf\u01d3\58\35\2\u01d0\u01d3\5:\36\2\u01d1\u01d3"+ - "\5<\37\2\u01d2\u01cf\3\2\2\2\u01d2\u01d0\3\2\2\2\u01d2\u01d1\3\2\2\2\u01d3"+ - "\67\3\2\2\2\u01d4\u01d5\7\\\2\2\u01d5\u01dc\7\33\2\2\u01d6\u01d8\7\'\2"+ - "\2\u01d7\u01d9\7\\\2\2\u01d8\u01d7\3\2\2\2\u01d8\u01d9\3\2\2\2\u01d9\u01da"+ - "\3\2\2\2\u01da\u01dc\7\33\2\2\u01db\u01d4\3\2\2\2\u01db\u01d6\3\2\2\2"+ - "\u01dc9\3\2\2\2\u01dd\u01df\7M\2\2\u01de\u01e0\5> \2\u01df\u01de\3\2\2"+ - "\2\u01df\u01e0\3\2\2\2\u01e0;\3\2\2\2\u01e1\u01e2\7J\2\2\u01e2\u01e7\5"+ - "@!\2\u01e3\u01e4\7\5\2\2\u01e4\u01e6\5@!\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=\3\2\2\2\u01e9"+ - "\u01e7\3\2\2\2\u01ea\u0202\5@!\2\u01eb\u01ec\7K\2\2\u01ec\u0202\5@!\2"+ - "\u01ed\u01ee\5@!\2\u01ee\u01ef\7\5\2\2\u01ef\u01f0\7\\\2\2\u01f0\u0202"+ - "\3\2\2\2\u01f1\u01f2\7\7\2\2\u01f2\u01f3\5@!\2\u01f3\u01f4\7\b\2\2\u01f4"+ - "\u01f5\7\5\2\2\u01f5\u01f6\7\\\2\2\u01f6\u0202\3\2\2\2\u01f7\u01f8\7\7"+ - "\2\2\u01f8\u01f9\5@!\2\u01f9\u01fa\7\5\2\2\u01fa\u01fb\7\\\2\2\u01fb\u01fc"+ - "\7\b\2\2\u01fc\u0202\3\2\2\2\u01fd\u01fe\7\7\2\2\u01fe\u01ff\5@!\2\u01ff"+ - "\u0200\7\b\2\2\u0200\u0202\3\2\2\2\u0201\u01ea\3\2\2\2\u0201\u01eb\3\2"+ - "\2\2\u0201\u01ed\3\2\2\2\u0201\u01f1\3\2\2\2\u0201\u01f7\3\2\2\2\u0201"+ - "\u01fd\3\2\2\2\u0202?\3\2\2\2\u0203\u0204\b!\1\2\u0204\u0205\7 \2\2\u0205"+ - "\u0206\5@!\2\u0206\u0207\7!\2\2\u0207\u0212\3\2\2\2\u0208\u0209\t\13\2"+ - "\2\u0209\u0212\5@!\n\u020a\u0212\7\\\2\2\u020b\u0212\7]\2\2\u020c\u020d"+ - "\7\t\2\2\u020d\u020e\7\\\2\2\u020e\u0212\7\n\2\2\u020f\u0212\7S\2\2\u0210"+ - "\u0212\7Q\2\2\u0211\u0203\3\2\2\2\u0211\u0208\3\2\2\2\u0211\u020a\3\2"+ - "\2\2\u0211\u020b\3\2\2\2\u0211\u020c\3\2\2\2\u0211\u020f\3\2\2\2\u0211"+ - "\u0210\3\2\2\2\u0212\u0221\3\2\2\2\u0213\u0214\f\f\2\2\u0214\u0215\7L"+ - "\2\2\u0215\u0220\5@!\r\u0216\u0217\f\13\2\2\u0217\u0218\t\6\2\2\u0218"+ - "\u0220\5@!\f\u0219\u021a\f\t\2\2\u021a\u021b\t\f\2\2\u021b\u0220\5@!\n"+ - "\u021c\u021d\f\b\2\2\u021d\u021e\t\b\2\2\u021e\u0220\5@!\t\u021f\u0213"+ - "\3\2\2\2\u021f\u0216\3\2\2\2\u021f\u0219\3\2\2\2\u021f\u021c\3\2\2\2\u0220"+ - "\u0223\3\2\2\2\u0221\u021f\3\2\2\2\u0221\u0222\3\2\2\2\u0222A\3\2\2\2"+ - "\u0223\u0221\3\2\2\2\66LU\\ahv|\u0082\u0087\u0090\u0097\u00a9\u00ab\u00b0"+ - "\u00b7\u00c4\u00c9\u00d5\u00e3\u00ee\u00f7\u00fe\u0105\u0108\u0110\u0113"+ - "\u0116\u0120\u0127\u012d\u012f\u013a\u015a\u0164\u0190\u019a\u019c\u01a4"+ - "\u01a9\u01b3\u01c5\u01c7\u01cc\u01d2\u01d8\u01db\u01df\u01e7\u0201\u0211"+ - "\u021f\u0221"; + "\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\5\26\u0194\n\26\3\26\3\26"+ + "\3\26\3\26\3\26\3\26\3\26\3\26\7\26\u019e\n\26\f\26\16\26\u01a1\13\26"+ + "\3\27\3\27\3\27\7\27\u01a6\n\27\f\27\16\27\u01a9\13\27\3\30\3\30\5\30"+ + "\u01ad\n\30\3\30\3\30\3\31\3\31\3\31\3\31\7\31\u01b5\n\31\f\31\16\31\u01b8"+ + "\13\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32"+ + "\3\32\3\32\5\32\u01c9\n\32\5\32\u01cb\n\32\3\33\7\33\u01ce\n\33\f\33\16"+ + "\33\u01d1\13\33\3\34\3\34\3\34\5\34\u01d6\n\34\3\35\3\35\3\35\3\35\5\35"+ + "\u01dc\n\35\3\35\5\35\u01df\n\35\3\36\3\36\5\36\u01e3\n\36\3\37\3\37\3"+ + "\37\3\37\7\37\u01e9\n\37\f\37\16\37\u01ec\13\37\3 \3 \3 \3 \3 \3 \3 \3"+ + " \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \5 \u0205\n \3!\3!\3!\3"+ + "!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\5!\u0215\n!\3!\3!\3!\3!\3!\3!\3!\3!\3"+ + "!\3!\3!\3!\7!\u0223\n!\f!\16!\u0226\13!\3!\2\7\22&(*@\"\2\4\6\b\n\f\16"+ + "\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@\2\r\3\2\35\36\3\2#"+ + "$\3\2%)\3\2./\3\2*+\4\2\37\37,-\3\2%&\3\2.\63\3\29B\4\2%&./\4\2\37\37"+ + ",,\2\u0276\2B\3\2\2\2\4F\3\2\2\2\6L\3\2\2\2\bO\3\2\2\2\nS\3\2\2\2\f\\"+ + "\3\2\2\2\16a\3\2\2\2\20k\3\2\2\2\22n\3\2\2\2\24y\3\2\2\2\26~\3\2\2\2\30"+ + "\u008b\3\2\2\2\32\u0097\3\2\2\2\34\u00ab\3\2\2\2\36\u00ae\3\2\2\2 \u00fe"+ + "\3\2\2\2\"\u0110\3\2\2\2$\u0116\3\2\2\2&\u0120\3\2\2\2(\u0132\3\2\2\2"+ + "*\u0167\3\2\2\2,\u01a2\3\2\2\2.\u01aa\3\2\2\2\60\u01b0\3\2\2\2\62\u01ca"+ + "\3\2\2\2\64\u01cf\3\2\2\2\66\u01d5\3\2\2\28\u01de\3\2\2\2:\u01e0\3\2\2"+ + "\2<\u01e4\3\2\2\2>\u0204\3\2\2\2@\u0214\3\2\2\2BC\5\6\4\2CD\5\n\6\2DE"+ + "\7\2\2\3E\3\3\2\2\2FG\5\64\33\2GH\7\2\2\3H\5\3\2\2\2IK\5\b\5\2JI\3\2\2"+ + "\2KN\3\2\2\2LJ\3\2\2\2LM\3\2\2\2M\7\3\2\2\2NL\3\2\2\2OP\7\3\2\2PQ\7P\2"+ + "\2Q\t\3\2\2\2RT\5\f\7\2SR\3\2\2\2TU\3\2\2\2US\3\2\2\2UV\3\2\2\2V\13\3"+ + "\2\2\2WX\5\20\t\2XY\7\4\2\2Y]\3\2\2\2Z]\5\26\f\2[]\5.\30\2\\W\3\2\2\2"+ + "\\Z\3\2\2\2\\[\3\2\2\2]\r\3\2\2\2^`\5\34\17\2_^\3\2\2\2`c\3\2\2\2a_\3"+ + "\2\2\2ab\3\2\2\2bd\3\2\2\2ca\3\2\2\2dh\5&\24\2eg\5\34\17\2fe\3\2\2\2g"+ + "j\3\2\2\2hf\3\2\2\2hi\3\2\2\2i\17\3\2\2\2jh\3\2\2\2kl\5\16\b\2lm\5\22"+ + "\n\2m\21\3\2\2\2no\b\n\1\2op\5\24\13\2pv\3\2\2\2qr\f\3\2\2rs\7\5\2\2s"+ + "u\5\24\13\2tq\3\2\2\2ux\3\2\2\2vt\3\2\2\2vw\3\2\2\2w\23\3\2\2\2xv\3\2"+ + "\2\2y|\7\\\2\2z{\7\6\2\2{}\5*\26\2|z\3\2\2\2|}\3\2\2\2}\25\3\2\2\2~\177"+ + "\5\16\b\2\177\u0080\7\\\2\2\u0080\u0082\7\7\2\2\u0081\u0083\5\30\r\2\u0082"+ + "\u0081\3\2\2\2\u0082\u0083\3\2\2\2\u0083\u0084\3\2\2\2\u0084\u0085\7\b"+ + "\2\2\u0085\u0087\7\t\2\2\u0086\u0088\5\36\20\2\u0087\u0086\3\2\2\2\u0087"+ + "\u0088\3\2\2\2\u0088\u0089\3\2\2\2\u0089\u008a\7\n\2\2\u008a\27\3\2\2"+ + "\2\u008b\u0090\5\32\16\2\u008c\u008d\7\5\2\2\u008d\u008f\5\32\16\2\u008e"+ + "\u008c\3\2\2\2\u008f\u0092\3\2\2\2\u0090\u008e\3\2\2\2\u0090\u0091\3\2"+ + "\2\2\u0091\31\3\2\2\2\u0092\u0090\3\2\2\2\u0093\u0094\5\16\b\2\u0094\u0095"+ + "\7\\\2\2\u0095\u0098\3\2\2\2\u0096\u0098\7O\2\2\u0097\u0093\3\2\2\2\u0097"+ + "\u0096\3\2\2\2\u0098\33\3\2\2\2\u0099\u00ac\7\13\2\2\u009a\u00ac\7\f\2"+ + "\2\u009b\u009c\7\r\2\2\u009c\u009d\7\7\2\2\u009d\u009e\7S\2\2\u009e\u00ac"+ + "\7\b\2\2\u009f\u00a0\7\16\2\2\u00a0\u00a1\7\7\2\2\u00a1\u00a2\7\\\2\2"+ + "\u00a2\u00ac\7\b\2\2\u00a3\u00ac\7\17\2\2\u00a4\u00ac\7\20\2\2\u00a5\u00a9"+ + "\7\21\2\2\u00a6\u00a7\7\7\2\2\u00a7\u00a8\7\\\2\2\u00a8\u00aa\7\b\2\2"+ + "\u00a9\u00a6\3\2\2\2\u00a9\u00aa\3\2\2\2\u00aa\u00ac\3\2\2\2\u00ab\u0099"+ + "\3\2\2\2\u00ab\u009a\3\2\2\2\u00ab\u009b\3\2\2\2\u00ab\u009f\3\2\2\2\u00ab"+ + "\u00a3\3\2\2\2\u00ab\u00a4\3\2\2\2\u00ab\u00a5\3\2\2\2\u00ac\35\3\2\2"+ + "\2\u00ad\u00af\5 \21\2\u00ae\u00ad\3\2\2\2\u00af\u00b0\3\2\2\2\u00b0\u00ae"+ + "\3\2\2\2\u00b0\u00b1\3\2\2\2\u00b1\37\3\2\2\2\u00b2\u00b3\5\20\t\2\u00b3"+ + "\u00b4\7\4\2\2\u00b4\u00ff\3\2\2\2\u00b5\u00b7\7\t\2\2\u00b6\u00b8\5\36"+ + "\20\2\u00b7\u00b6\3\2\2\2\u00b7\u00b8\3\2\2\2\u00b8\u00b9\3\2\2\2\u00b9"+ + "\u00ff\7\n\2\2\u00ba\u00bb\5(\25\2\u00bb\u00bc\7\4\2\2\u00bc\u00ff\3\2"+ + "\2\2\u00bd\u00be\7\22\2\2\u00be\u00bf\7\7\2\2\u00bf\u00c0\5(\25\2\u00c0"+ + "\u00c1\7\b\2\2\u00c1\u00c4\5 \21\2\u00c2\u00c3\7\23\2\2\u00c3\u00c5\5"+ + " \21\2\u00c4\u00c2\3\2\2\2\u00c4\u00c5\3\2\2\2\u00c5\u00ff\3\2\2\2\u00c6"+ + "\u00c8\5\34\17\2\u00c7\u00c6\3\2\2\2\u00c8\u00cb\3\2\2\2\u00c9\u00c7\3"+ + "\2\2\2\u00c9\u00ca\3\2\2\2\u00ca\u00cc\3\2\2\2\u00cb\u00c9\3\2\2\2\u00cc"+ + "\u00cd\7\24\2\2\u00cd\u00ce\7\7\2\2\u00ce\u00cf\5(\25\2\u00cf\u00d0\7"+ + "\b\2\2\u00d0\u00d1\5 \21\2\u00d1\u00ff\3\2\2\2\u00d2\u00d4\5\34\17\2\u00d3"+ + "\u00d2\3\2\2\2\u00d4\u00d7\3\2\2\2\u00d5\u00d3\3\2\2\2\u00d5\u00d6\3\2"+ + "\2\2\u00d6\u00d8\3\2\2\2\u00d7\u00d5\3\2\2\2\u00d8\u00d9\7\25\2\2\u00d9"+ + "\u00da\5 \21\2\u00da\u00db\7\24\2\2\u00db\u00dc\7\7\2\2\u00dc\u00dd\5"+ + "(\25\2\u00dd\u00de\7\b\2\2\u00de\u00df\7\4\2\2\u00df\u00ff\3\2\2\2\u00e0"+ + "\u00e2\5\34\17\2\u00e1\u00e0\3\2\2\2\u00e2\u00e5\3\2\2\2\u00e3\u00e1\3"+ + "\2\2\2\u00e3\u00e4\3\2\2\2\u00e4\u00e6\3\2\2\2\u00e5\u00e3\3\2\2\2\u00e6"+ + "\u00e7\7\26\2\2\u00e7\u00e8\7\7\2\2\u00e8\u00e9\5\"\22\2\u00e9\u00ea\7"+ + "\b\2\2\u00ea\u00eb\5 \21\2\u00eb\u00ff\3\2\2\2\u00ec\u00ee\7\27\2\2\u00ed"+ + "\u00ef\5(\25\2\u00ee\u00ed\3\2\2\2\u00ee\u00ef\3\2\2\2\u00ef\u00f0\3\2"+ + "\2\2\u00f0\u00ff\7\4\2\2\u00f1\u00f2\7\30\2\2\u00f2\u00ff\7\4\2\2\u00f3"+ + "\u00f4\7\31\2\2\u00f4\u00ff\7\4\2\2\u00f5\u00f7\7\32\2\2\u00f6\u00f8\5"+ + "\60\31\2\u00f7\u00f6\3\2\2\2\u00f7\u00f8\3\2\2\2\u00f8\u00f9\3\2\2\2\u00f9"+ + "\u00fa\7\t\2\2\u00fa\u00fb\5\64\33\2\u00fb\u00fc\7\n\2\2\u00fc\u00ff\3"+ + "\2\2\2\u00fd\u00ff\5.\30\2\u00fe\u00b2\3\2\2\2\u00fe\u00b5\3\2\2\2\u00fe"+ + "\u00ba\3\2\2\2\u00fe\u00bd\3\2\2\2\u00fe\u00c9\3\2\2\2\u00fe\u00d5\3\2"+ + "\2\2\u00fe\u00e3\3\2\2\2\u00fe\u00ec\3\2\2\2\u00fe\u00f1\3\2\2\2\u00fe"+ + "\u00f3\3\2\2\2\u00fe\u00f5\3\2\2\2\u00fe\u00fd\3\2\2\2\u00ff!\3\2\2\2"+ + "\u0100\u0101\5$\23\2\u0101\u0102\7\4\2\2\u0102\u0103\5(\25\2\u0103\u0105"+ + "\7\4\2\2\u0104\u0106\5(\25\2\u0105\u0104\3\2\2\2\u0105\u0106\3\2\2\2\u0106"+ + "\u0111\3\2\2\2\u0107\u0109\5\16\b\2\u0108\u0107\3\2\2\2\u0108\u0109\3"+ + "\2\2\2\u0109\u010a\3\2\2\2\u010a\u010b\7\\\2\2\u010b\u010c\7\33\2\2\u010c"+ + "\u010d\5*\26\2\u010d\u010e\7\34\2\2\u010e\u010f\5*\26\2\u010f\u0111\3"+ + "\2\2\2\u0110\u0100\3\2\2\2\u0110\u0108\3\2\2\2\u0111#\3\2\2\2\u0112\u0114"+ + "\5\20\t\2\u0113\u0112\3\2\2\2\u0113\u0114\3\2\2\2\u0114\u0117\3\2\2\2"+ + "\u0115\u0117\5(\25\2\u0116\u0113\3\2\2\2\u0116\u0115\3\2\2\2\u0117%\3"+ + "\2\2\2\u0118\u0119\b\24\1\2\u0119\u011a\7\7\2\2\u011a\u011b\5&\24\2\u011b"+ + "\u011c\7\b\2\2\u011c\u0121\3\2\2\2\u011d\u0121\7O\2\2\u011e\u011f\t\2"+ + "\2\2\u011f\u0121\7O\2\2\u0120\u0118\3\2\2\2\u0120\u011d\3\2\2\2\u0120"+ + "\u011e\3\2\2\2\u0121\u012f\3\2\2\2\u0122\u0123\f\5\2\2\u0123\u012e\7\37"+ + "\2\2\u0124\u0125\f\4\2\2\u0125\u0127\7 \2\2\u0126\u0128\5*\26\2\u0127"+ + "\u0126\3\2\2\2\u0127\u0128\3\2\2\2\u0128\u0129\3\2\2\2\u0129\u012e\7!"+ + "\2\2\u012a\u012b\f\3\2\2\u012b\u012c\7\7\2\2\u012c\u012e\7\b\2\2\u012d"+ + "\u0122\3\2\2\2\u012d\u0124\3\2\2\2\u012d\u012a\3\2\2\2\u012e\u0131\3\2"+ + "\2\2\u012f\u012d\3\2\2\2\u012f\u0130\3\2\2\2\u0130\'\3\2\2\2\u0131\u012f"+ + "\3\2\2\2\u0132\u0133\b\25\1\2\u0133\u0134\5*\26\2\u0134\u013a\3\2\2\2"+ + "\u0135\u0136\f\3\2\2\u0136\u0137\7\5\2\2\u0137\u0139\5*\26\2\u0138\u0135"+ + "\3\2\2\2\u0139\u013c\3\2\2\2\u013a\u0138\3\2\2\2\u013a\u013b\3\2\2\2\u013b"+ + ")\3\2\2\2\u013c\u013a\3\2\2\2\u013d\u013e\b\26\1\2\u013e\u013f\7\7\2\2"+ + "\u013f\u0140\5(\25\2\u0140\u0141\7\b\2\2\u0141\u0168\3\2\2\2\u0142\u0143"+ + "\7\"\2\2\u0143\u0146\7\7\2\2\u0144\u0147\5&\24\2\u0145\u0147\5*\26\2\u0146"+ + "\u0144\3\2\2\2\u0146\u0145\3\2\2\2\u0147\u0148\3\2\2\2\u0148\u0149\7\b"+ + "\2\2\u0149\u0168\3\2\2\2\u014a\u014b\7\7\2\2\u014b\u014c\5&\24\2\u014c"+ + "\u014d\7\b\2\2\u014d\u014e\5*\26\32\u014e\u0168\3\2\2\2\u014f\u0150\t"+ + "\3\2\2\u0150\u0168\5*\26\31\u0151\u0152\7\37\2\2\u0152\u0168\5*\26\27"+ + "\u0153\u0154\t\4\2\2\u0154\u0168\5*\26\26\u0155\u0156\t\5\2\2\u0156\u0168"+ + "\5*\26\22\u0157\u0158\7\t\2\2\u0158\u015d\5*\26\2\u0159\u015a\7\5\2\2"+ + "\u015a\u015c\5*\26\2\u015b\u0159\3\2\2\2\u015c\u015f\3\2\2\2\u015d\u015b"+ + "\3\2\2\2\u015d\u015e\3\2\2\2\u015e\u0160\3\2\2\2\u015f\u015d\3\2\2\2\u0160"+ + "\u0161\7\n\2\2\u0161\u0168\3\2\2\2\u0162\u0168\7\\\2\2\u0163\u0168\7S"+ + "\2\2\u0164\u0168\7P\2\2\u0165\u0168\7Q\2\2\u0166\u0168\7R\2\2\u0167\u013d"+ + "\3\2\2\2\u0167\u0142\3\2\2\2\u0167\u014a\3\2\2\2\u0167\u014f\3\2\2\2\u0167"+ + "\u0151\3\2\2\2\u0167\u0153\3\2\2\2\u0167\u0155\3\2\2\2\u0167\u0157\3\2"+ + "\2\2\u0167\u0162\3\2\2\2\u0167\u0163\3\2\2\2\u0167\u0164\3\2\2\2\u0167"+ + "\u0165\3\2\2\2\u0167\u0166\3\2\2\2\u0168\u019f\3\2\2\2\u0169\u016a\f\25"+ + "\2\2\u016a\u016b\t\6\2\2\u016b\u019e\5*\26\26\u016c\u016d\f\24\2\2\u016d"+ + "\u016e\t\7\2\2\u016e\u019e\5*\26\25\u016f\u0170\f\23\2\2\u0170\u0171\t"+ + "\b\2\2\u0171\u019e\5*\26\24\u0172\u0173\f\21\2\2\u0173\u0174\t\t\2\2\u0174"+ + "\u019e\5*\26\22\u0175\u0176\f\20\2\2\u0176\u0177\7(\2\2\u0177\u019e\5"+ + "*\26\21\u0178\u0179\f\17\2\2\u0179\u017a\7\64\2\2\u017a\u019e\5*\26\20"+ + "\u017b\u017c\f\16\2\2\u017c\u017d\7\65\2\2\u017d\u019e\5*\26\17\u017e"+ + "\u017f\f\r\2\2\u017f\u0180\7\66\2\2\u0180\u019e\5*\26\16\u0181\u0182\f"+ + "\f\2\2\u0182\u0183\7\67\2\2\u0183\u019e\5*\26\r\u0184\u0185\f\13\2\2\u0185"+ + "\u0186\78\2\2\u0186\u0187\5*\26\2\u0187\u0188\7\33\2\2\u0188\u0189\5*"+ + "\26\f\u0189\u019e\3\2\2\2\u018a\u018b\f\n\2\2\u018b\u018c\7\6\2\2\u018c"+ + "\u019e\5*\26\n\u018d\u018e\f\t\2\2\u018e\u018f\t\n\2\2\u018f\u019e\5*"+ + "\26\t\u0190\u0191\f\35\2\2\u0191\u0193\7\7\2\2\u0192\u0194\5,\27\2\u0193"+ + "\u0192\3\2\2\2\u0193\u0194\3\2\2\2\u0194\u0195\3\2\2\2\u0195\u019e\7\b"+ + "\2\2\u0196\u0197\f\33\2\2\u0197\u0198\7 \2\2\u0198\u0199\5(\25\2\u0199"+ + "\u019a\7!\2\2\u019a\u019e\3\2\2\2\u019b\u019c\f\30\2\2\u019c\u019e\t\3"+ + "\2\2\u019d\u0169\3\2\2\2\u019d\u016c\3\2\2\2\u019d\u016f\3\2\2\2\u019d"+ + "\u0172\3\2\2\2\u019d\u0175\3\2\2\2\u019d\u0178\3\2\2\2\u019d\u017b\3\2"+ + "\2\2\u019d\u017e\3\2\2\2\u019d\u0181\3\2\2\2\u019d\u0184\3\2\2\2\u019d"+ + "\u018a\3\2\2\2\u019d\u018d\3\2\2\2\u019d\u0190\3\2\2\2\u019d\u0196\3\2"+ + "\2\2\u019d\u019b\3\2\2\2\u019e\u01a1\3\2\2\2\u019f\u019d\3\2\2\2\u019f"+ + "\u01a0\3\2\2\2\u01a0+\3\2\2\2\u01a1\u019f\3\2\2\2\u01a2\u01a7\5*\26\2"+ + "\u01a3\u01a4\7\5\2\2\u01a4\u01a6\5*\26\2\u01a5\u01a3\3\2\2\2\u01a6\u01a9"+ + "\3\2\2\2\u01a7\u01a5\3\2\2\2\u01a7\u01a8\3\2\2\2\u01a8-\3\2\2\2\u01a9"+ + "\u01a7\3\2\2\2\u01aa\u01ac\7C\2\2\u01ab\u01ad\5\60\31\2\u01ac\u01ab\3"+ + "\2\2\2\u01ac\u01ad\3\2\2\2\u01ad\u01ae\3\2\2\2\u01ae\u01af\7N\2\2\u01af"+ + "/\3\2\2\2\u01b0\u01b1\7\7\2\2\u01b1\u01b6\5\62\32\2\u01b2\u01b3\7\5\2"+ + "\2\u01b3\u01b5\5\62\32\2\u01b4\u01b2\3\2\2\2\u01b5\u01b8\3\2\2\2\u01b6"+ + "\u01b4\3\2\2\2\u01b6\u01b7\3\2\2\2\u01b7\u01b9\3\2\2\2\u01b8\u01b6\3\2"+ + "\2\2\u01b9\u01ba\7\b\2\2\u01ba\61\3\2\2\2\u01bb\u01bc\7D\2\2\u01bc\u01cb"+ + "\7P\2\2\u01bd\u01be\7E\2\2\u01be\u01cb\7\\\2\2\u01bf\u01c0\7F\2\2\u01c0"+ + "\u01cb\7P\2\2\u01c1\u01c2\7G\2\2\u01c2\u01cb\5*\26\2\u01c3\u01c4\7H\2"+ + "\2\u01c4\u01cb\5*\26\2\u01c5\u01c8\7I\2\2\u01c6\u01c9\7\17\2\2\u01c7\u01c9"+ + "\5*\26\2\u01c8\u01c6\3\2\2\2\u01c8\u01c7\3\2\2\2\u01c9\u01cb\3\2\2\2\u01ca"+ + "\u01bb\3\2\2\2\u01ca\u01bd\3\2\2\2\u01ca\u01bf\3\2\2\2\u01ca\u01c1\3\2"+ + "\2\2\u01ca\u01c3\3\2\2\2\u01ca\u01c5\3\2\2\2\u01cb\63\3\2\2\2\u01cc\u01ce"+ + "\5\66\34\2\u01cd\u01cc\3\2\2\2\u01ce\u01d1\3\2\2\2\u01cf\u01cd\3\2\2\2"+ + "\u01cf\u01d0\3\2\2\2\u01d0\65\3\2\2\2\u01d1\u01cf\3\2\2\2\u01d2\u01d6"+ + "\58\35\2\u01d3\u01d6\5:\36\2\u01d4\u01d6\5<\37\2\u01d5\u01d2\3\2\2\2\u01d5"+ + "\u01d3\3\2\2\2\u01d5\u01d4\3\2\2\2\u01d6\67\3\2\2\2\u01d7\u01d8\7\\\2"+ + "\2\u01d8\u01df\7\33\2\2\u01d9\u01db\7\'\2\2\u01da\u01dc\7\\\2\2\u01db"+ + "\u01da\3\2\2\2\u01db\u01dc\3\2\2\2\u01dc\u01dd\3\2\2\2\u01dd\u01df\7\33"+ + "\2\2\u01de\u01d7\3\2\2\2\u01de\u01d9\3\2\2\2\u01df9\3\2\2\2\u01e0\u01e2"+ + "\7M\2\2\u01e1\u01e3\5> \2\u01e2\u01e1\3\2\2\2\u01e2\u01e3\3\2\2\2\u01e3"+ + ";\3\2\2\2\u01e4\u01e5\7J\2\2\u01e5\u01ea\5@!\2\u01e6\u01e7\7\5\2\2\u01e7"+ + "\u01e9\5@!\2\u01e8\u01e6\3\2\2\2\u01e9\u01ec\3\2\2\2\u01ea\u01e8\3\2\2"+ + "\2\u01ea\u01eb\3\2\2\2\u01eb=\3\2\2\2\u01ec\u01ea\3\2\2\2\u01ed\u0205"+ + "\5@!\2\u01ee\u01ef\7K\2\2\u01ef\u0205\5@!\2\u01f0\u01f1\5@!\2\u01f1\u01f2"+ + "\7\5\2\2\u01f2\u01f3\7\\\2\2\u01f3\u0205\3\2\2\2\u01f4\u01f5\7\7\2\2\u01f5"+ + "\u01f6\5@!\2\u01f6\u01f7\7\b\2\2\u01f7\u01f8\7\5\2\2\u01f8\u01f9\7\\\2"+ + "\2\u01f9\u0205\3\2\2\2\u01fa\u01fb\7\7\2\2\u01fb\u01fc\5@!\2\u01fc\u01fd"+ + "\7\5\2\2\u01fd\u01fe\7\\\2\2\u01fe\u01ff\7\b\2\2\u01ff\u0205\3\2\2\2\u0200"+ + "\u0201\7\7\2\2\u0201\u0202\5@!\2\u0202\u0203\7\b\2\2\u0203\u0205\3\2\2"+ + "\2\u0204\u01ed\3\2\2\2\u0204\u01ee\3\2\2\2\u0204\u01f0\3\2\2\2\u0204\u01f4"+ + "\3\2\2\2\u0204\u01fa\3\2\2\2\u0204\u0200\3\2\2\2\u0205?\3\2\2\2\u0206"+ + "\u0207\b!\1\2\u0207\u0208\7 \2\2\u0208\u0209\5@!\2\u0209\u020a\7!\2\2"+ + "\u020a\u0215\3\2\2\2\u020b\u020c\t\13\2\2\u020c\u0215\5@!\n\u020d\u0215"+ + "\7\\\2\2\u020e\u0215\7]\2\2\u020f\u0210\7\t\2\2\u0210\u0211\7\\\2\2\u0211"+ + "\u0215\7\n\2\2\u0212\u0215\7S\2\2\u0213\u0215\7Q\2\2\u0214\u0206\3\2\2"+ + "\2\u0214\u020b\3\2\2\2\u0214\u020d\3\2\2\2\u0214\u020e\3\2\2\2\u0214\u020f"+ + "\3\2\2\2\u0214\u0212\3\2\2\2\u0214\u0213\3\2\2\2\u0215\u0224\3\2\2\2\u0216"+ + "\u0217\f\f\2\2\u0217\u0218\7L\2\2\u0218\u0223\5@!\r\u0219\u021a\f\13\2"+ + "\2\u021a\u021b\t\6\2\2\u021b\u0223\5@!\f\u021c\u021d\f\t\2\2\u021d\u021e"+ + "\t\f\2\2\u021e\u0223\5@!\n\u021f\u0220\f\b\2\2\u0220\u0221\t\b\2\2\u0221"+ + "\u0223\5@!\t\u0222\u0216\3\2\2\2\u0222\u0219\3\2\2\2\u0222\u021c\3\2\2"+ + "\2\u0222\u021f\3\2\2\2\u0223\u0226\3\2\2\2\u0224\u0222\3\2\2\2\u0224\u0225"+ + "\3\2\2\2\u0225A\3\2\2\2\u0226\u0224\3\2\2\2\67LU\\ahv|\u0082\u0087\u0090"+ + "\u0097\u00a9\u00ab\u00b0\u00b7\u00c4\u00c9\u00d5\u00e3\u00ee\u00f7\u00fe"+ + "\u0105\u0108\u0110\u0113\u0116\u0120\u0127\u012d\u012f\u013a\u0146\u015d"+ + "\u0167\u0193\u019d\u019f\u01a7\u01ac\u01b6\u01c8\u01ca\u01cf\u01d5\u01db"+ + "\u01de\u01e2\u01ea\u0204\u0214\u0222\u0224"; 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 840b5ad69..f17463c28 100644 --- a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java +++ b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java @@ -368,13 +368,6 @@ public interface KickCVisitor extends ParseTreeVisitor { * @return the visitor result */ T visitExprChar(KickCParser.ExprCharContext ctx); - /** - * Visit a parse tree produced by the {@code exprSizeOfType} - * labeled alternative in {@link KickCParser#expr}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitExprSizeOfType(KickCParser.ExprSizeOfTypeContext ctx); /** * Visit a parse tree produced by the {@code initList} * labeled alternative in {@link KickCParser#expr}. @@ -403,6 +396,13 @@ public interface KickCVisitor extends ParseTreeVisitor { * @return the visitor result */ T visitExprPar(KickCParser.ExprParContext ctx); + /** + * Visit a parse tree produced by the {@code exprSizeOf} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitExprSizeOf(KickCParser.ExprSizeOfContext ctx); /** * Visit a parse tree produced by the {@code exprString} * 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 8ee964e9b..2df185b12 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -5,6 +5,7 @@ import dk.camelot64.kickc.NumberParser; import dk.camelot64.kickc.asm.AsmClobber; import dk.camelot64.kickc.model.*; import dk.camelot64.kickc.model.operators.Operator; +import dk.camelot64.kickc.model.operators.OperatorSizeOf; import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.*; import dk.camelot64.kickc.model.symbols.*; @@ -1179,30 +1180,24 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { } @Override - public Object visitExprSizeOfType(KickCParser.ExprSizeOfTypeContext ctx) { - SymbolType type = (SymbolType) this.visit(ctx.typeDecl()); - String typeConstName = getSizeofName(type); - ConstantVar typeSizeConstant = program.getScope().getConstant(typeConstName); - if(typeSizeConstant ==null) { - // Constant not found - create it - long typeSize = type.getSizeBytes(); - typeSizeConstant = new ConstantVar(typeConstName, program.getScope(), SymbolType.BYTE, new ConstantInteger(typeSize)); - program.getScope().add(typeSizeConstant); - } - return typeSizeConstant.getRef(); - } - - private String getSizeofName(SymbolType type) { - if(type instanceof SymbolTypePointer) { - return "SIZEOF_POINTER"; + public Object visitExprSizeOf(KickCParser.ExprSizeOfContext ctx) { + if(ctx.typeDecl()!=null) { + // sizeof(type) - add directly + SymbolType type = (SymbolType) this.visit(ctx.typeDecl()); + return OperatorSizeOf.getSizeOfConstantVar(program.getScope(), type); } else { - return "SIZEOF_"+type.getTypeName().toUpperCase().replace(" ", "_"); + // sizeof(expression) - add a unary expression to be resolved later + RValue child = (RValue) this.visit(ctx.expr()); + VariableIntermediate tmpVar = getCurrentScope().addVariableIntermediate(); + VariableRef tmpVarRef = tmpVar.getRef(); + Statement stmt = new StatementAssignment(tmpVarRef, Operators.SIZEOF, child, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx))); + sequence.addStatement(stmt); + return tmpVarRef; } } @Override public Object visitExprCall(KickCParser.ExprCallContext ctx) { - List parameters; KickCParser.ParameterListContext parameterList = ctx.parameterList(); if(parameterList != null) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java index 38055da94..7ae4366dd 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java @@ -4,10 +4,7 @@ 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.OperatorBinary; -import dk.camelot64.kickc.model.operators.OperatorCastPtr; -import dk.camelot64.kickc.model.operators.OperatorUnary; -import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.operators.*; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementPhiBlock; @@ -302,39 +299,11 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { } static ConstantValue createUnary(OperatorUnary operator, ConstantValue c) { - if(operator instanceof OperatorCastPtr) { - return new ConstantUnary(operator, c); - } - switch(operator.getOperator()) { - case "-": - case "+": - case "++": - case "--": - case "<": - case ">": - case "((byte))": - case "((signed byte))": - case "((sbyte))": - case "((word))": - case "((signed word))": - case "((dword))": - case "((signed dword))": - case "((byte*))": - case "((signed byte*))": - case "((word*))": - case "((signed word*))": - case "((dword*))": - case "((signed dword*))": - case "((boolean*))": - case "!": - case "~": - return new ConstantUnary(operator, c); - case "*": { // pointer dereference - not constant - return null; - } - default: - throw new RuntimeException("Unhandled Unary Operator " + operator.getOperator()); + if(Operators.DEREF.equals(operator)) { + // Pointer dereferencing is not constant + return null; } + return new ConstantUnary(operator, c); } static ConstantValue createBinary(ConstantValue c1, OperatorBinary operator, ConstantValue c2, ProgramScope programScope) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java new file mode 100644 index 000000000..e2c1e6f2c --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java @@ -0,0 +1,130 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.ConstantNotLiteral; +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.ProgramValueIterator; +import dk.camelot64.kickc.model.operators.OperatorSizeOf; +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.ConstantVar; +import dk.camelot64.kickc.model.symbols.SymbolVariable; +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.values.*; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Simplifies sizeof() operators whenever the expression is constant + */ +public class Pass2SizeOfSimplification extends Pass2SsaOptimization { + + public Pass2SizeOfSimplification(Program program) { + super(program); + } + + @Override + public boolean step() { + AtomicBoolean modified = new AtomicBoolean(false); + + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementAssignment) { + StatementAssignment assignment = (StatementAssignment) statement; + if(Operators.SIZEOF.equals(assignment.getOperator())) { + if(assignment.getrValue2() instanceof SymbolVariableRef) { + SymbolVariableRef symbolRef = (SymbolVariableRef) assignment.getrValue2(); + SymbolVariable symbolVar = (SymbolVariable) getScope().getSymbol(symbolRef); + SymbolType symbolType = symbolVar.getType(); + if(!(symbolType instanceof SymbolTypeArray)) { + getLog().append("Resolving sizeof() " + assignment.toString(getProgram(), false)); + ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), symbolType); + assignment.setrValue2(sizeOfConstantVar); + assignment.setOperator(null); + modified.set(true); + } + } + } + } + } + } + + ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> { + if(programValue.get() instanceof ConstantUnary) { + ConstantUnary unary = (ConstantUnary) programValue.get(); + if(unary.getOperator().equals(Operators.SIZEOF)) { + ConstantValue operand = unary.getOperand(); + resolveConstantSizeOf(modified, programValue, unary, operand); + } + } + } + ); + + return modified.get(); + } + + public void resolveConstantSizeOf(AtomicBoolean modified, ProgramValue programValue, ConstantUnary unary, ConstantValue operand) { + if(operand instanceof ConstantRef) { + ConstantVar constant = getScope().getConstant((ConstantRef) operand); + SymbolType symbolType = constant.getType(); + if(symbolType instanceof SymbolTypeArray) { + SymbolTypeArray arrayType = (SymbolTypeArray) symbolType; + RValue arraySize = arrayType.getSize(); + if(arraySize instanceof ConstantValue) { + getLog().append("Resolving 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())); + 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)); + modified.set(true); + } else { + // Try to calculate the literal to check if it is a string + ConstantLiteral stringLiteral = null; + try { + stringLiteral = constant.getValue().calculateLiteral(getProgram().getScope()); + } catch(ConstantNotLiteral e) { + // Ignore + } + if(stringLiteral instanceof ConstantString) { + ConstantString constString = (ConstantString) stringLiteral; + int length = constString.getString().length(); + ConstantRef sizeOfChar = OperatorSizeOf.getSizeOfConstantVar(getScope(), SymbolType.BYTE); + programValue.set(new ConstantBinary(new ConstantInteger((long) length), Operators.MULTIPLY, sizeOfChar)); + modified.set(true); + } else { + throw new CompileError("Not implemented!"); + } + } + } else if(symbolType instanceof SymbolTypePointer ){ + getLog().append("Resolving sizeof() " + unary.toString(getProgram())); + ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), symbolType); + programValue.set(sizeOfConstantVar); + modified.set(true); + } else { + getLog().append("Resolving sizeof() " + unary.toString(getProgram())); + ConstantLiteral literal = operand.calculateLiteral(getProgram().getScope()); + SymbolType constType = literal.getType(getProgram().getScope()); + ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), constType); + programValue.set(sizeOfConstantVar); + modified.set(true); + } + } else { + getLog().append("Resolving sizeof() " + unary.toString(getProgram())); + ConstantLiteral literal = operand.calculateLiteral(getProgram().getScope()); + SymbolType constType = literal.getType(getProgram().getScope()); + ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), constType); + programValue.set(sizeOfConstantVar); + modified.set(true); + } + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index ba9c45513..6c41d76ba 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -337,11 +337,11 @@ public class Pass4CodeGeneration { } } } - Collection constRefConsts = program.getVariableReferenceInfos().getConstRefConsts(constantVar.getRef()); - if(constRefConsts != null) { - for(ConstantRef constRefConst : constRefConsts) { - ConstantVar refConst = program.getScope().getConstant(constRefConst); - if(!refConst.getScope().getRef().equals(scopeRef)) { + Collection symbolRefConsts = program.getVariableReferenceInfos().getSymbolRefConsts(constantVar.getRef()); + if(symbolRefConsts != null) { + for(SymbolVariableRef symbolRefConst : symbolRefConsts) { + SymbolVariable symbolRefVar = (SymbolVariable) program.getScope().getSymbol(symbolRefConst); + if(!symbolRefVar.getScope().getRef().equals(scopeRef)) { // Used in constant in another scope - generate label useLabel = true; break; diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 13b8ab642..8112497ea 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -37,6 +37,11 @@ public class TestPrograms { // compileAndCompare("pointer-cast-3"); //} + @Test + public void testSizeofExpression() throws IOException, URISyntaxException { + compileAndCompare("sizeof-expr"); + } + @Test public void testSizeofTypes() throws IOException, URISyntaxException { compileAndCompare("sizeof-types"); diff --git a/src/test/kc/sizeof-expr.kc b/src/test/kc/sizeof-expr.kc new file mode 100644 index 000000000..d48116db5 --- /dev/null +++ b/src/test/kc/sizeof-expr.kc @@ -0,0 +1,42 @@ +// Tests the sizeof() operator on epressions + +const byte* SCREEN = $400; + +void main() { + byte idx = 0; + + // Simple types + volatile byte b = 0; + volatile word w = 0; + // Pointers + byte* bp = $1000; + word* wp = &w; + // Arrays + byte[3] ba; + word[3] wa; + byte sz = 15; + byte[sz+2] bb; + byte[] bc = { 1, 2, 3, 4 }; + // Strings + byte[] sa = "camelot"; + byte[] sb = "cml"+" "+"rules"; + + SCREEN[idx++] = '0'+sizeof(0); + SCREEN[idx++] = '0'+sizeof(idx); + SCREEN[idx++] = '0'+sizeof(b); + SCREEN[idx++] = '0'+sizeof(b*2); + idx++; + SCREEN[idx++] = '0'+sizeof($43ff); + SCREEN[idx++] = '0'+sizeof(w); + idx++; + SCREEN[idx++] = '0'+sizeof(bp); + SCREEN[idx++] = '0'+sizeof(wp); + idx++; + SCREEN[idx++] = '0'+sizeof(ba); + SCREEN[idx++] = '0'+sizeof(wa); + SCREEN[idx++] = '0'+sizeof(bb); + SCREEN[idx++] = '0'+sizeof(bc); + SCREEN[idx++] = '0'+sizeof(sa); + SCREEN[idx++] = '0'+sizeof(sb); + +} \ No newline at end of file diff --git a/src/test/ref/sizeof-expr.asm b/src/test/ref/sizeof-expr.asm new file mode 100644 index 000000000..1749feae1 --- /dev/null +++ b/src/test/ref/sizeof-expr.asm @@ -0,0 +1,42 @@ +// Tests the sizeof() operator on epressions +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label SCREEN = $400 + .const SIZEOF_BYTE = 1 + .const SIZEOF_WORD = 2 + .const SIZEOF_POINTER = 2 +main: { + .const sz = $f + .label b = 2 + .label w = 3 + // Simple types + lda #0 + sta b + sta w + sta w+1 + lda #'0'+SIZEOF_BYTE + sta SCREEN + sta SCREEN+1 + sta SCREEN+2 + sta SCREEN+3 + lda #'0'+SIZEOF_WORD + sta SCREEN+5 + sta SCREEN+6 + lda #'0'+SIZEOF_POINTER + sta SCREEN+8 + sta SCREEN+9 + lda #'0'+3*SIZEOF_BYTE + sta SCREEN+$b + lda #'0'+3*SIZEOF_WORD + sta SCREEN+$c + lda #'0'+(sz+2)*SIZEOF_BYTE + sta SCREEN+$d + lda #'0'+4*SIZEOF_BYTE + 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/sizeof-expr.cfg b/src/test/ref/sizeof-expr.cfg new file mode 100644 index 000000000..26278562d --- /dev/null +++ b/src/test/ref/sizeof-expr.cfg @@ -0,0 +1,30 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() +main: scope:[main] from @1 + [4] (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + [5] (word) main::w#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + [6] *((const byte*) SCREEN#0) ← (byte) '0'+(const byte) SIZEOF_BYTE + [7] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) '0'+(const byte) SIZEOF_BYTE + [8] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) '0'+(const byte) SIZEOF_BYTE + [9] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte) '0'+(const byte) SIZEOF_BYTE + [10] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 5) ← (byte) '0'+(const byte) SIZEOF_WORD + [11] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 6) ← (byte) '0'+(const byte) SIZEOF_WORD + [12] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 8) ← (byte) '0'+(const byte) SIZEOF_POINTER + [13] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 9) ← (byte) '0'+(const byte) SIZEOF_POINTER + [14] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $b) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_BYTE + [15] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $c) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_WORD + [16] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $d) ← (byte) '0'+(const byte) main::sz#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_BYTE + [17] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $e) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 4*(const byte) SIZEOF_BYTE + [18] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $f) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 8*(const byte) SIZEOF_BYTE + [19] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $10) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) $c*(const byte) SIZEOF_BYTE + to:main::@return +main::@return: scope:[main] from main + [20] return + to:@return diff --git a/src/test/ref/sizeof-expr.log b/src/test/ref/sizeof-expr.log new file mode 100644 index 000000000..4be212f88 --- /dev/null +++ b/src/test/ref/sizeof-expr.log @@ -0,0 +1,804 @@ +Identified constant variable (byte*) main::bp +Identified constant variable (byte) main::sz + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + (byte*) SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400 + to:@1 +main: scope:[main] from @1 + (byte) main::idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (word) main::w#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte*) main::bp#0 ← ((byte*)) (word/signed word/dword/signed dword) $1000 + (word*~) main::$0 ← & (word) main::w#0 + (word*) main::wp#0 ← (word*~) main::$0 + (byte[3]) main::ba#0 ← { fill( 3, 0) } + (word[3]) main::wa#0 ← { fill( 3, 0) } + (byte) main::sz#0 ← (byte/signed byte/word/signed word/dword/signed dword) $f + (byte/signed word/word/dword/signed dword~) main::$1 ← (byte) main::sz#0 + (byte/signed byte/word/signed word/dword/signed dword) 2 + (byte[main::$1]) main::bb#0 ← { fill( main::$1, 0) } + (byte[]) main::bc#0 ← { (byte/signed byte/word/signed word/dword/signed dword) 1, (byte/signed byte/word/signed word/dword/signed dword) 2, (byte/signed byte/word/signed word/dword/signed dword) 3, (byte/signed byte/word/signed word/dword/signed dword) 4 } + (byte[]) main::sa#0 ← (const string) main::$33 + (string~) main::$2 ← (const string) main::$34 + (const string) main::$35 + (string~) main::$3 ← (string~) main::$2 + (const string) main::$36 + (byte[]) main::sb#0 ← (string~) main::$3 + (byte/signed byte/word/signed word/dword/signed dword~) main::$4 ← sizeof (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte/signed word/word/dword/signed dword~) main::$5 ← (byte) '0' + (byte/signed byte/word/signed word/dword/signed dword~) main::$4 + *((byte*) SCREEN#0 + (byte) main::idx#0) ← (byte/signed word/word/dword/signed dword~) main::$5 + (byte) main::idx#1 ← ++ (byte) main::idx#0 + (byte~) main::$6 ← sizeof (byte) main::idx#1 + (byte~) main::$7 ← (byte) '0' + (byte~) main::$6 + *((byte*) SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$7 + (byte) main::idx#2 ← ++ (byte) main::idx#1 + (byte~) main::$8 ← sizeof (byte) main::b#0 + (byte~) main::$9 ← (byte) '0' + (byte~) main::$8 + *((byte*) SCREEN#0 + (byte) main::idx#2) ← (byte~) main::$9 + (byte) main::idx#3 ← ++ (byte) main::idx#2 + (byte/signed word/word/dword/signed dword~) main::$10 ← (byte) main::b#0 * (byte/signed byte/word/signed word/dword/signed dword) 2 + (byte~) main::$11 ← sizeof (byte/signed word/word/dword/signed dword~) main::$10 + (byte~) main::$12 ← (byte) '0' + (byte~) main::$11 + *((byte*) SCREEN#0 + (byte) main::idx#3) ← (byte~) main::$12 + (byte) main::idx#4 ← ++ (byte) main::idx#3 + (byte) main::idx#5 ← ++ (byte) main::idx#4 + (byte/signed byte/word/signed word/dword/signed dword~) main::$13 ← sizeof (word/signed word/dword/signed dword) $43ff + (byte/signed word/word/dword/signed dword~) main::$14 ← (byte) '0' + (byte/signed byte/word/signed word/dword/signed dword~) main::$13 + *((byte*) SCREEN#0 + (byte) main::idx#5) ← (byte/signed word/word/dword/signed dword~) main::$14 + (byte) main::idx#6 ← ++ (byte) main::idx#5 + (byte~) main::$15 ← sizeof (word) main::w#0 + (byte~) main::$16 ← (byte) '0' + (byte~) main::$15 + *((byte*) SCREEN#0 + (byte) main::idx#6) ← (byte~) main::$16 + (byte) main::idx#7 ← ++ (byte) main::idx#6 + (byte) main::idx#8 ← ++ (byte) main::idx#7 + (byte~) main::$17 ← sizeof (byte*) main::bp#0 + (byte~) main::$18 ← (byte) '0' + (byte~) main::$17 + *((byte*) SCREEN#0 + (byte) main::idx#8) ← (byte~) main::$18 + (byte) main::idx#9 ← ++ (byte) main::idx#8 + (byte~) main::$19 ← sizeof (word*) main::wp#0 + (byte~) main::$20 ← (byte) '0' + (byte~) main::$19 + *((byte*) SCREEN#0 + (byte) main::idx#9) ← (byte~) main::$20 + (byte) main::idx#10 ← ++ (byte) main::idx#9 + (byte) main::idx#11 ← ++ (byte) main::idx#10 + (byte~) main::$21 ← sizeof (byte[3]) main::ba#0 + (byte~) main::$22 ← (byte) '0' + (byte~) main::$21 + *((byte*) SCREEN#0 + (byte) main::idx#11) ← (byte~) main::$22 + (byte) main::idx#12 ← ++ (byte) main::idx#11 + (byte~) main::$23 ← sizeof (word[3]) main::wa#0 + (byte~) main::$24 ← (byte) '0' + (byte~) main::$23 + *((byte*) SCREEN#0 + (byte) main::idx#12) ← (byte~) main::$24 + (byte) main::idx#13 ← ++ (byte) main::idx#12 + (byte~) main::$25 ← sizeof (byte[main::$1]) main::bb#0 + (byte~) main::$26 ← (byte) '0' + (byte~) main::$25 + *((byte*) SCREEN#0 + (byte) main::idx#13) ← (byte~) main::$26 + (byte) main::idx#14 ← ++ (byte) main::idx#13 + (byte~) main::$27 ← sizeof (byte[]) main::bc#0 + (byte~) main::$28 ← (byte) '0' + (byte~) main::$27 + *((byte*) SCREEN#0 + (byte) main::idx#14) ← (byte~) main::$28 + (byte) main::idx#15 ← ++ (byte) main::idx#14 + (byte~) main::$29 ← sizeof (byte[]) main::sa#0 + (byte~) main::$30 ← (byte) '0' + (byte~) main::$29 + *((byte*) SCREEN#0 + (byte) main::idx#15) ← (byte~) main::$30 + (byte) main::idx#16 ← ++ (byte) main::idx#15 + (byte~) main::$31 ← sizeof (byte[]) main::sb#0 + (byte~) main::$32 ← (byte) '0' + (byte~) main::$31 + *((byte*) SCREEN#0 + (byte) main::idx#16) ← (byte~) main::$32 + (byte) main::idx#17 ← ++ (byte) main::idx#16 + to:main::@return +main::@return: scope:[main] from main + 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 +(byte*) SCREEN +(byte*) SCREEN#0 +(void()) main() +(word*~) main::$0 +(byte/signed word/word/dword/signed dword~) main::$1 +(byte/signed word/word/dword/signed dword~) main::$10 +(byte~) main::$11 +(byte~) main::$12 +(byte/signed byte/word/signed word/dword/signed dword~) main::$13 +(byte/signed word/word/dword/signed dword~) main::$14 +(byte~) main::$15 +(byte~) main::$16 +(byte~) main::$17 +(byte~) main::$18 +(byte~) main::$19 +(string~) main::$2 +(byte~) main::$20 +(byte~) main::$21 +(byte~) main::$22 +(byte~) main::$23 +(byte~) main::$24 +(byte~) main::$25 +(byte~) main::$26 +(byte~) main::$27 +(byte~) main::$28 +(byte~) main::$29 +(string~) main::$3 +(byte~) main::$30 +(byte~) main::$31 +(byte~) main::$32 +(const string) main::$33 = (string) "camelot@" +(const string) main::$34 = (string) "cml@" +(const string) main::$35 = (string) " @" +(const string) main::$36 = (string) "rules@" +(byte/signed byte/word/signed word/dword/signed dword~) main::$4 +(byte/signed word/word/dword/signed dword~) main::$5 +(byte~) main::$6 +(byte~) main::$7 +(byte~) main::$8 +(byte~) main::$9 +(label) main::@return +(byte) main::b +(byte) main::b#0 +(byte[3]) main::ba +(byte[3]) main::ba#0 +(byte[main::$1]) main::bb +(byte[main::$1]) main::bb#0 +(byte[]) main::bc +(byte[]) main::bc#0 +(byte*) main::bp +(byte*) main::bp#0 +(byte) main::idx +(byte) main::idx#0 +(byte) main::idx#1 +(byte) main::idx#10 +(byte) main::idx#11 +(byte) main::idx#12 +(byte) main::idx#13 +(byte) main::idx#14 +(byte) main::idx#15 +(byte) main::idx#16 +(byte) main::idx#17 +(byte) main::idx#2 +(byte) main::idx#3 +(byte) main::idx#4 +(byte) main::idx#5 +(byte) main::idx#6 +(byte) main::idx#7 +(byte) main::idx#8 +(byte) main::idx#9 +(byte[]) main::sa +(byte[]) main::sa#0 +(byte[]) main::sb +(byte[]) main::sb#0 +(byte) main::sz +(byte) main::sz#0 +(word) main::w +(word) main::w#0 +(word[3]) main::wa +(word[3]) main::wa#0 +(word*) main::wp +(word*) main::wp#0 + +Culled Empty Block (label) @2 +Successful SSA optimization Pass2CullEmptyBlocks +Alias (word*) main::wp#0 = (word*~) main::$0 +Alias (byte[]) main::sb#0 = (string~) main::$3 +Successful SSA optimization Pass2AliasElimination +Constant (const byte*) SCREEN#0 = ((byte*))$400 +Constant (const byte) main::idx#0 = 0 +Constant (const byte*) main::bp#0 = ((byte*))$1000 +Constant (const word*) main::wp#0 = &main::w#0 +Constant (const byte[3]) main::ba#0 = { fill( 3, 0) } +Constant (const word[3]) main::wa#0 = { fill( 3, 0) } +Constant (const byte) main::sz#0 = $f +Constant (const byte[]) main::bc#0 = { 1, 2, 3, 4 } +Constant (const byte[]) main::sa#0 = main::$33 +Constant (const string) main::$2 = "cml@"+" @" +Constant (const byte/signed byte/word/signed word/dword/signed dword) main::$4 = sizeof 0 +Constant (const byte/signed byte/word/signed word/dword/signed dword) main::$13 = sizeof $43ff +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte/signed word/word/dword/signed dword) main::$1 = main::sz#0+2 +Constant (const byte[]) main::sb#0 = "cml@"+" @"+"rules@" +Constant (const byte/signed word/word/dword/signed dword) main::$5 = '0'+main::$4 +Constant (const byte) main::idx#1 = ++main::idx#0 +Constant (const byte/signed word/word/dword/signed dword) main::$14 = '0'+main::$13 +Constant (const byte) main::$17 = sizeof main::bp#0 +Constant (const byte) main::$19 = sizeof main::wp#0 +Constant (const byte) main::$21 = sizeof main::ba#0 +Constant (const byte) main::$23 = sizeof main::wa#0 +Constant (const byte) main::$27 = sizeof main::bc#0 +Constant (const byte) main::$29 = sizeof main::sa#0 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte[main::$1]) main::bb#0 = { fill( main::$1, 0) } +Constant (const byte) main::$6 = sizeof main::idx#1 +Constant (const byte) main::idx#2 = ++main::idx#1 +Constant (const byte) main::$18 = '0'+main::$17 +Constant (const byte) main::$20 = '0'+main::$19 +Constant (const byte) main::$22 = '0'+main::$21 +Constant (const byte) main::$24 = '0'+main::$23 +Constant (const byte) main::$28 = '0'+main::$27 +Constant (const byte) main::$30 = '0'+main::$29 +Constant (const byte) main::$31 = sizeof main::sb#0 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::$7 = '0'+main::$6 +Constant (const byte) main::idx#3 = ++main::idx#2 +Constant (const byte) main::$25 = sizeof main::bb#0 +Constant (const byte) main::$32 = '0'+main::$31 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#4 = ++main::idx#3 +Constant (const byte) main::$26 = '0'+main::$25 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#5 = ++main::idx#4 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#6 = ++main::idx#5 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#7 = ++main::idx#6 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#8 = ++main::idx#7 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#9 = ++main::idx#8 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#10 = ++main::idx#9 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#11 = ++main::idx#10 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#12 = ++main::idx#11 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#13 = ++main::idx#12 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#14 = ++main::idx#13 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#15 = ++main::idx#14 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#16 = ++main::idx#15 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::idx#17 = ++main::idx#16 +Successful SSA optimization Pass2ConstantIdentification +Consolidated array index constant in *(SCREEN#0+main::idx#0) +Consolidated array index constant in *(SCREEN#0+main::idx#1) +Consolidated array index constant in *(SCREEN#0+main::idx#2) +Consolidated array index constant in *(SCREEN#0+main::idx#3) +Consolidated array index constant in *(SCREEN#0+main::idx#5) +Consolidated array index constant in *(SCREEN#0+main::idx#6) +Consolidated array index constant in *(SCREEN#0+main::idx#8) +Consolidated array index constant in *(SCREEN#0+main::idx#9) +Consolidated array index constant in *(SCREEN#0+main::idx#11) +Consolidated array index constant in *(SCREEN#0+main::idx#12) +Consolidated array index constant in *(SCREEN#0+main::idx#13) +Consolidated array index constant in *(SCREEN#0+main::idx#14) +Consolidated array index constant in *(SCREEN#0+main::idx#15) +Consolidated array index constant in *(SCREEN#0+main::idx#16) +Successful SSA optimization Pass2ConstantAdditionElimination +Successful SSA optimization PassNEliminateUnusedVars +Rewriting multiplication to use shift (byte/signed word/word/dword/signed dword~) main::$10 ← (byte) main::b#0 * (byte/signed byte/word/signed word/dword/signed dword) 2 +Successful SSA optimization Pass2MultiplyToShiftRewriting +Resolving sizeof() (byte~) main::$8 ← sizeof (byte) main::b#0 +Resolving sizeof() (byte~) main::$11 ← sizeof (byte/signed word/word/dword/signed dword~) main::$10 +Resolving sizeof() (byte~) main::$15 ← sizeof (word) main::w#0 +Resolving sizeof() sizeof (byte/signed byte/word/signed word/dword/signed dword) 0 +Resolving sizeof() sizeof (word/signed word/dword/signed dword) $43ff +Resolving sizeof() sizeof (const byte*) main::bp#0 +Resolving sizeof() sizeof (const word*) main::wp#0 +Resolving sizeof() sizeof (const byte[3]) main::ba#0 +Resolving sizeof() sizeof (const word[3]) main::wa#0 +Resolving sizeof() sizeof (const byte[]) main::bc#0 +Resolving sizeof() sizeof (const byte) main::idx#1 +Resolving sizeof() sizeof (const byte[main::$1]) main::bb#0 +Successful SSA optimization Pass2SizeOfSimplification +Constant (const byte) main::$8 = SIZEOF_BYTE +Constant (const byte) main::$11 = SIZEOF_BYTE +Constant (const byte) main::$15 = SIZEOF_WORD +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::$9 = '0'+main::$8 +Constant (const byte) main::$12 = '0'+main::$11 +Constant (const byte) main::$16 = '0'+main::$15 +Successful SSA optimization Pass2ConstantIdentification +Inferred type updated to byte in [5] (byte/signed word/word/dword/signed dword~) main::$10 ← (byte) main::b#0 << (byte/signed byte/word/signed word/dword/signed dword) 1 +Successful SSA optimization PassNEliminateUnusedVars +Successful SSA optimization PassNEliminateUnusedVars +Inlining constant with different constant siblings (const byte) main::idx#0 +Inlining constant with different constant siblings (const byte) main::idx#1 +Inlining constant with different constant siblings (const byte) main::idx#2 +Inlining constant with different constant siblings (const byte) main::idx#3 +Inlining constant with different constant siblings (const byte) main::idx#4 +Inlining constant with different constant siblings (const byte) main::idx#5 +Inlining constant with different constant siblings (const byte) main::idx#6 +Inlining constant with different constant siblings (const byte) main::idx#7 +Inlining constant with different constant siblings (const byte) main::idx#8 +Inlining constant with different constant siblings (const byte) main::idx#9 +Inlining constant with different constant siblings (const byte) main::idx#10 +Inlining constant with different constant siblings (const byte) main::idx#11 +Inlining constant with different constant siblings (const byte) main::idx#12 +Inlining constant with different constant siblings (const byte) main::idx#13 +Inlining constant with different constant siblings (const byte) main::idx#14 +Inlining constant with different constant siblings (const byte) main::idx#15 +Inlining constant with different constant siblings (const byte) main::idx#16 +Constant inlined main::idx#16 = ++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::idx#12 = ++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::idx#13 = ++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::idx#14 = ++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::idx#15 = ++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::$12 = (byte) '0'+(const byte) SIZEOF_BYTE +Constant inlined main::$13 = (const byte) SIZEOF_WORD +Constant inlined main::$14 = (byte) '0'+(const byte) SIZEOF_WORD +Constant inlined main::$15 = (const byte) SIZEOF_WORD +Constant inlined main::$30 = (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 8*(const byte) SIZEOF_BYTE +Constant inlined main::$31 = (byte/signed byte/word/signed word/dword/signed dword) $c*(const byte) SIZEOF_BYTE +Constant inlined main::$32 = (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) $c*(const byte) SIZEOF_BYTE +Constant inlined main::$11 = (const byte) SIZEOF_BYTE +Constant inlined main::$16 = (byte) '0'+(const byte) SIZEOF_WORD +Constant inlined main::$17 = (const byte) SIZEOF_POINTER +Constant inlined main::$18 = (byte) '0'+(const byte) SIZEOF_POINTER +Constant inlined main::$19 = (const byte) SIZEOF_POINTER +Constant inlined main::$23 = (byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_WORD +Constant inlined main::$24 = (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_WORD +Constant inlined main::$25 = (const byte) main::sz#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_BYTE +Constant inlined main::$26 = (byte) '0'+(const byte) main::sz#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_BYTE +Constant inlined main::$20 = (byte) '0'+(const byte) SIZEOF_POINTER +Constant inlined main::$21 = (byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_BYTE +Constant inlined main::$22 = (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_BYTE +Constant inlined main::idx#0 = (byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::idx#1 = ++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::idx#2 = ++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::$1 = (const byte) main::sz#0+(byte/signed byte/word/signed word/dword/signed dword) 2 +Constant inlined main::$27 = (byte/signed byte/word/signed word/dword/signed dword) 4*(const byte) SIZEOF_BYTE +Constant inlined main::idx#3 = ++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::$28 = (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 4*(const byte) SIZEOF_BYTE +Constant inlined main::idx#4 = ++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::$29 = (byte/signed byte/word/signed word/dword/signed dword) 8*(const byte) SIZEOF_BYTE +Constant inlined main::idx#5 = ++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::idx#6 = ++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::$5 = (byte) '0'+(const byte) SIZEOF_BYTE +Constant inlined main::idx#7 = ++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::$6 = (const byte) SIZEOF_BYTE +Constant inlined main::idx#8 = ++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::idx#9 = ++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::idx#10 = ++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::$4 = (const byte) SIZEOF_BYTE +Constant inlined main::idx#11 = ++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::$9 = (byte) '0'+(const byte) SIZEOF_BYTE +Constant inlined main::$7 = (byte) '0'+(const byte) SIZEOF_BYTE +Constant inlined main::$8 = (const byte) SIZEOF_BYTE +Successful SSA optimization Pass2ConstantInlining +Simplifying constant plus zero 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 integer increment ++$b +Successful SSA optimization Pass2ConstantSimplification +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++2 +Simplifying constant integer increment ++4 +Simplifying constant integer increment ++5 +Simplifying constant integer increment ++7 +Simplifying constant integer increment ++8 +Simplifying constant integer increment ++$a +Simplifying constant integer increment ++$b +Simplifying constant integer increment ++$c +Simplifying constant integer increment ++$c +Simplifying constant integer increment ++$d +Simplifying constant integer increment ++$e +Successful SSA optimization Pass2ConstantSimplification +Simplifying constant integer increment ++$d +Simplifying constant integer increment ++$e +Simplifying constant integer increment ++$f +Successful SSA optimization Pass2ConstantSimplification +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +CALL GRAPH +Calls in [] to main:2 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() +main: scope:[main] from @1 + [4] (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + [5] (word) main::w#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + [6] *((const byte*) SCREEN#0) ← (byte) '0'+(const byte) SIZEOF_BYTE + [7] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) '0'+(const byte) SIZEOF_BYTE + [8] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) '0'+(const byte) SIZEOF_BYTE + [9] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte) '0'+(const byte) SIZEOF_BYTE + [10] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 5) ← (byte) '0'+(const byte) SIZEOF_WORD + [11] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 6) ← (byte) '0'+(const byte) SIZEOF_WORD + [12] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 8) ← (byte) '0'+(const byte) SIZEOF_POINTER + [13] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 9) ← (byte) '0'+(const byte) SIZEOF_POINTER + [14] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $b) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_BYTE + [15] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $c) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_WORD + [16] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $d) ← (byte) '0'+(const byte) main::sz#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_BYTE + [17] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $e) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 4*(const byte) SIZEOF_BYTE + [18] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $f) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 8*(const byte) SIZEOF_BYTE + [19] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $10) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) $c*(const byte) SIZEOF_BYTE + to:main::@return +main::@return: scope:[main] from main + [20] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte*) SCREEN +(void()) main() +(byte) main::b +(byte) main::b#0 20.0 +(byte[3]) main::ba +(byte[main::sz#0+2]) main::bb +(byte[]) main::bc +(byte*) main::bp +(byte) main::idx +(byte[]) main::sa +(byte[]) main::sb +(byte) main::sz +(word) main::w +(word) main::w#0 20.0 +(word[3]) main::wa +(word*) main::wp + +Initial phi equivalence classes +Complete equivalence classes +[ main::b#0 ] +[ main::w#0 ] +Allocated zp ZP_BYTE:2 [ main::b#0 ] +Allocated zp ZP_WORD:3 [ main::w#0 ] + +INITIAL ASM +//SEG0 File Comments +// Tests the sizeof() operator on epressions +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .label SCREEN = $400 + .const SIZEOF_BYTE = 1 + .const SIZEOF_WORD = 2 + .const SIZEOF_POINTER = 2 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + .const sz = $f + .label b = 2 + .label w = 3 + //SEG10 [4] (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vbuz1=vbuc1 + // Simple types + lda #0 + sta b + //SEG11 [5] (word) main::w#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vwuz1=vbuc1 + lda #0 + sta w + lda #0 + sta w+1 + //SEG12 [6] *((const byte*) SCREEN#0) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_BYTE + sta SCREEN + //SEG13 [7] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_BYTE + sta SCREEN+1 + //SEG14 [8] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_BYTE + sta SCREEN+2 + //SEG15 [9] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_BYTE + sta SCREEN+3 + //SEG16 [10] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 5) ← (byte) '0'+(const byte) SIZEOF_WORD -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_WORD + sta SCREEN+5 + //SEG17 [11] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 6) ← (byte) '0'+(const byte) SIZEOF_WORD -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_WORD + sta SCREEN+6 + //SEG18 [12] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 8) ← (byte) '0'+(const byte) SIZEOF_POINTER -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_POINTER + sta SCREEN+8 + //SEG19 [13] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 9) ← (byte) '0'+(const byte) SIZEOF_POINTER -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_POINTER + sta SCREEN+9 + //SEG20 [14] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $b) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+3*SIZEOF_BYTE + sta SCREEN+$b + //SEG21 [15] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $c) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_WORD -- _deref_pbuc1=vbuc2 + lda #'0'+3*SIZEOF_WORD + sta SCREEN+$c + //SEG22 [16] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $d) ← (byte) '0'+(const byte) main::sz#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+(sz+2)*SIZEOF_BYTE + sta SCREEN+$d + //SEG23 [17] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $e) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 4*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+4*SIZEOF_BYTE + sta SCREEN+$e + //SEG24 [18] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $f) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 8*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+8*SIZEOF_BYTE + sta SCREEN+$f + //SEG25 [19] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $10) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) $c*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+$c*SIZEOF_BYTE + sta SCREEN+$10 + jmp breturn + //SEG26 main::@return + breturn: + //SEG27 [20] return + rts +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [5] (word) main::w#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [6] *((const byte*) SCREEN#0) ← (byte) '0'+(const byte) SIZEOF_BYTE [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [7] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) '0'+(const byte) SIZEOF_BYTE [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [8] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) '0'+(const byte) SIZEOF_BYTE [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [9] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte) '0'+(const byte) SIZEOF_BYTE [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [10] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 5) ← (byte) '0'+(const byte) SIZEOF_WORD [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [11] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 6) ← (byte) '0'+(const byte) SIZEOF_WORD [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [12] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 8) ← (byte) '0'+(const byte) SIZEOF_POINTER [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [13] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 9) ← (byte) '0'+(const byte) SIZEOF_POINTER [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [14] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $b) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_BYTE [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [15] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $c) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_WORD [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [16] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $d) ← (byte) '0'+(const byte) main::sz#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_BYTE [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [17] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $e) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 4*(const byte) SIZEOF_BYTE [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [18] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $f) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 8*(const byte) SIZEOF_BYTE [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [19] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $10) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) $c*(const byte) SIZEOF_BYTE [ ] ( main:2 [ ] ) always clobbers reg byte a +Potential registers zp ZP_BYTE:2 [ main::b#0 ] : zp ZP_BYTE:2 , +Potential registers zp ZP_WORD:3 [ main::w#0 ] : zp ZP_WORD:3 , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 20: zp ZP_BYTE:2 [ main::b#0 ] 20: zp ZP_WORD:3 [ main::w#0 ] +Uplift Scope [] + +Uplifting [main] best 120 combination zp ZP_BYTE:2 [ main::b#0 ] zp ZP_WORD:3 [ main::w#0 ] +Uplifting [] best 120 combination +Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::b#0 ] +Uplifting [main] best 120 combination zp ZP_BYTE:2 [ main::b#0 ] + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 File Comments +// Tests the sizeof() operator on epressions +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .label SCREEN = $400 + .const SIZEOF_BYTE = 1 + .const SIZEOF_WORD = 2 + .const SIZEOF_POINTER = 2 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + .const sz = $f + .label b = 2 + .label w = 3 + //SEG10 [4] (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vbuz1=vbuc1 + // Simple types + lda #0 + sta b + //SEG11 [5] (word) main::w#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vwuz1=vbuc1 + lda #0 + sta w + lda #0 + sta w+1 + //SEG12 [6] *((const byte*) SCREEN#0) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_BYTE + sta SCREEN + //SEG13 [7] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_BYTE + sta SCREEN+1 + //SEG14 [8] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_BYTE + sta SCREEN+2 + //SEG15 [9] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_BYTE + sta SCREEN+3 + //SEG16 [10] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 5) ← (byte) '0'+(const byte) SIZEOF_WORD -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_WORD + sta SCREEN+5 + //SEG17 [11] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 6) ← (byte) '0'+(const byte) SIZEOF_WORD -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_WORD + sta SCREEN+6 + //SEG18 [12] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 8) ← (byte) '0'+(const byte) SIZEOF_POINTER -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_POINTER + sta SCREEN+8 + //SEG19 [13] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 9) ← (byte) '0'+(const byte) SIZEOF_POINTER -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_POINTER + sta SCREEN+9 + //SEG20 [14] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $b) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+3*SIZEOF_BYTE + sta SCREEN+$b + //SEG21 [15] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $c) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_WORD -- _deref_pbuc1=vbuc2 + lda #'0'+3*SIZEOF_WORD + sta SCREEN+$c + //SEG22 [16] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $d) ← (byte) '0'+(const byte) main::sz#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+(sz+2)*SIZEOF_BYTE + sta SCREEN+$d + //SEG23 [17] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $e) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 4*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+4*SIZEOF_BYTE + sta SCREEN+$e + //SEG24 [18] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $f) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 8*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+8*SIZEOF_BYTE + sta SCREEN+$f + //SEG25 [19] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $10) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) $c*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+$c*SIZEOF_BYTE + sta SCREEN+$10 + jmp breturn + //SEG26 main::@return + breturn: + //SEG27 [20] return + rts +} + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction lda #0 +Removing instruction lda #0 +Removing instruction lda #'0'+SIZEOF_BYTE +Removing instruction lda #'0'+SIZEOF_BYTE +Removing instruction lda #'0'+SIZEOF_BYTE +Removing instruction lda #'0'+SIZEOF_WORD +Removing instruction lda #'0'+SIZEOF_POINTER +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction bend_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +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*) SCREEN +(const byte*) SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400 +(const byte) SIZEOF_BYTE SIZEOF_BYTE = (byte/signed byte/word/signed word/dword/signed dword) 1 +(const byte) SIZEOF_POINTER SIZEOF_POINTER = (byte/signed byte/word/signed word/dword/signed dword) 2 +(const byte) SIZEOF_WORD SIZEOF_WORD = (byte/signed byte/word/signed word/dword/signed dword) 2 +(void()) main() +(label) main::@return +(byte) main::b +(byte) main::b#0 b zp ZP_BYTE:2 20.0 +(byte[3]) main::ba +(byte[main::sz#0+2]) main::bb +(byte[]) main::bc +(byte*) main::bp +(byte) main::idx +(byte[]) main::sa +(byte[]) main::sb +(byte) main::sz +(const byte) main::sz#0 sz = (byte/signed byte/word/signed word/dword/signed dword) $f +(word) main::w +(word) main::w#0 w zp ZP_WORD:3 20.0 +(word[3]) main::wa +(word*) main::wp + +zp ZP_BYTE:2 [ main::b#0 ] +zp ZP_WORD:3 [ main::w#0 ] + + +FINAL ASSEMBLER +Score: 91 + +//SEG0 File Comments +// Tests the sizeof() operator on epressions +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .label SCREEN = $400 + .const SIZEOF_BYTE = 1 + .const SIZEOF_WORD = 2 + .const SIZEOF_POINTER = 2 +//SEG3 @begin +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +//SEG5 @1 +//SEG6 [2] call main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +//SEG8 @end +//SEG9 main +main: { + .const sz = $f + .label b = 2 + .label w = 3 + //SEG10 [4] (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vbuz1=vbuc1 + // Simple types + lda #0 + sta b + //SEG11 [5] (word) main::w#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vwuz1=vbuc1 + sta w + sta w+1 + //SEG12 [6] *((const byte*) SCREEN#0) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_BYTE + sta SCREEN + //SEG13 [7] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + sta SCREEN+1 + //SEG14 [8] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + sta SCREEN+2 + //SEG15 [9] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte) '0'+(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + sta SCREEN+3 + //SEG16 [10] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 5) ← (byte) '0'+(const byte) SIZEOF_WORD -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_WORD + sta SCREEN+5 + //SEG17 [11] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 6) ← (byte) '0'+(const byte) SIZEOF_WORD -- _deref_pbuc1=vbuc2 + sta SCREEN+6 + //SEG18 [12] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 8) ← (byte) '0'+(const byte) SIZEOF_POINTER -- _deref_pbuc1=vbuc2 + lda #'0'+SIZEOF_POINTER + sta SCREEN+8 + //SEG19 [13] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 9) ← (byte) '0'+(const byte) SIZEOF_POINTER -- _deref_pbuc1=vbuc2 + sta SCREEN+9 + //SEG20 [14] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $b) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+3*SIZEOF_BYTE + sta SCREEN+$b + //SEG21 [15] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $c) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 3*(const byte) SIZEOF_WORD -- _deref_pbuc1=vbuc2 + lda #'0'+3*SIZEOF_WORD + sta SCREEN+$c + //SEG22 [16] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $d) ← (byte) '0'+(const byte) main::sz#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+(sz+2)*SIZEOF_BYTE + sta SCREEN+$d + //SEG23 [17] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $e) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 4*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+4*SIZEOF_BYTE + sta SCREEN+$e + //SEG24 [18] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $f) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) 8*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+8*SIZEOF_BYTE + sta SCREEN+$f + //SEG25 [19] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) $10) ← (byte) '0'+(byte/signed byte/word/signed word/dword/signed dword) $c*(const byte) SIZEOF_BYTE -- _deref_pbuc1=vbuc2 + lda #'0'+$c*SIZEOF_BYTE + sta SCREEN+$10 + //SEG26 main::@return + //SEG27 [20] return + rts +} + diff --git a/src/test/ref/sizeof-expr.sym b/src/test/ref/sizeof-expr.sym new file mode 100644 index 000000000..3de491c93 --- /dev/null +++ b/src/test/ref/sizeof-expr.sym @@ -0,0 +1,28 @@ +(label) @1 +(label) @begin +(label) @end +(byte*) SCREEN +(const byte*) SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400 +(const byte) SIZEOF_BYTE SIZEOF_BYTE = (byte/signed byte/word/signed word/dword/signed dword) 1 +(const byte) SIZEOF_POINTER SIZEOF_POINTER = (byte/signed byte/word/signed word/dword/signed dword) 2 +(const byte) SIZEOF_WORD SIZEOF_WORD = (byte/signed byte/word/signed word/dword/signed dword) 2 +(void()) main() +(label) main::@return +(byte) main::b +(byte) main::b#0 b zp ZP_BYTE:2 20.0 +(byte[3]) main::ba +(byte[main::sz#0+2]) main::bb +(byte[]) main::bc +(byte*) main::bp +(byte) main::idx +(byte[]) main::sa +(byte[]) main::sb +(byte) main::sz +(const byte) main::sz#0 sz = (byte/signed byte/word/signed word/dword/signed dword) $f +(word) main::w +(word) main::w#0 w zp ZP_WORD:3 20.0 +(word[3]) main::wa +(word*) main::wp + +zp ZP_BYTE:2 [ main::b#0 ] +zp ZP_WORD:3 [ main::w#0 ]