mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-17 10:30:43 +00:00
Implemented sizeof(expr). Closes #171
This commit is contained in:
parent
417a1d4b22
commit
d55a958c70
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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<ConstantRef> getConstRefConsts(ConstantRef constRef) {
|
||||
public Collection<SymbolVariableRef> getSymbolRefConsts(ConstantRef constRef) {
|
||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
||||
LinkedHashSet<ConstantRef> constRefs = new LinkedHashSet<>();
|
||||
LinkedHashSet<SymbolVariableRef> 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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
@ -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())) {
|
||||
|
@ -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())) {
|
||||
|
@ -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) {
|
||||
|
@ -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() );
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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(" ", "_");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -647,18 +647,6 @@ public class KickCBaseListener implements KickCListener {
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprChar(KickCParser.ExprCharContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExprSizeOfType(KickCParser.ExprSizeOfTypeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprSizeOfType(KickCParser.ExprSizeOfTypeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -707,6 +695,18 @@ public class KickCBaseListener implements KickCListener {
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprPar(KickCParser.ExprParContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExprSizeOf(KickCParser.ExprSizeOfContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprSizeOf(KickCParser.ExprSizeOfContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -382,13 +382,6 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprChar(KickCParser.ExprCharContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprSizeOfType(KickCParser.ExprSizeOfTypeContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -417,6 +410,13 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprPar(KickCParser.ExprParContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprSizeOf(KickCParser.ExprSizeOfContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -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}.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -368,13 +368,6 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> {
|
||||
* @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<T> extends ParseTreeVisitor<T> {
|
||||
* @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}.
|
||||
|
@ -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<Object> {
|
||||
}
|
||||
|
||||
@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<RValue> parameters;
|
||||
KickCParser.ParameterListContext parameterList = ctx.parameterList();
|
||||
if(parameterList != null) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -337,11 +337,11 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
}
|
||||
}
|
||||
Collection<ConstantRef> 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<SymbolVariableRef> 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;
|
||||
|
@ -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");
|
||||
|
42
src/test/kc/sizeof-expr.kc
Normal file
42
src/test/kc/sizeof-expr.kc
Normal file
@ -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);
|
||||
|
||||
}
|
42
src/test/ref/sizeof-expr.asm
Normal file
42
src/test/ref/sizeof-expr.asm
Normal file
@ -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
|
||||
}
|
30
src/test/ref/sizeof-expr.cfg
Normal file
30
src/test/ref/sizeof-expr.cfg
Normal file
@ -0,0 +1,30 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] (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
|
804
src/test/ref/sizeof-expr.log
Normal file
804
src/test/ref/sizeof-expr.log
Normal file
@ -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
|
||||
}
|
||||
|
28
src/test/ref/sizeof-expr.sym
Normal file
28
src/test/ref/sizeof-expr.sym
Normal file
@ -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 ]
|
Loading…
x
Reference in New Issue
Block a user