1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-27 04:49:27 +00:00

Working in unumber/snumber. Only few failing tests.

This commit is contained in:
jespergravgaard 2019-05-24 00:50:48 +02:00
parent 9ef7c69c3e
commit f574bb676c
21 changed files with 290 additions and 77 deletions

View File

@ -232,12 +232,15 @@ public class Compiler {
private List<Pass2SsaOptimization> getPass2Optimizations() { private List<Pass2SsaOptimization> getPass2Optimizations() {
List<Pass2SsaOptimization> optimizations = new ArrayList<>(); List<Pass2SsaOptimization> optimizations = new ArrayList<>();
optimizations.add(new Pass2FixInlineConstructorsNew(program)); optimizations.add(new Pass2FixInlineConstructorsNew(program));
optimizations.add(new PassNAddNumberTypeConversions(program)); optimizations.add(new PassNAddNumberTypeConversions(program));
optimizations.add(new PassNAddArrayNumberTypeConversions(program)); optimizations.add(new PassNAddArrayNumberTypeConversions(program));
optimizations.add(new PassNTypeInference(program));
optimizations.add(new PassNAddTypeConversionAssignment(program));
optimizations.add(new Pass2InlineCast(program)); optimizations.add(new Pass2InlineCast(program));
optimizations.add(new PassNCastSimplification(program)); optimizations.add(new PassNCastSimplification(program));
optimizations.add(new PassNFinalizeNumberTypeConversions(program));
optimizations.add(new PassNTypeInference(program));
optimizations.add(new PassNAddTypeConversionAssignment(program));
optimizations.add(new PassNTypeIdSimplification(program)); optimizations.add(new PassNTypeIdSimplification(program));
optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new Pass2SizeOfSimplification(program));
optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNStatementIndices(program));

View File

@ -10,6 +10,7 @@ import dk.camelot64.kickc.model.statements.StatementConditionalJump;
import dk.camelot64.kickc.model.statements.StatementPhiBlock; import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.Scope; import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.symbols.VariableIntermediate; import dk.camelot64.kickc.model.symbols.VariableIntermediate;
import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference; import dk.camelot64.kickc.model.types.SymbolTypeInference;
@ -96,7 +97,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
} else { } else {
Scope blockScope = symbols.getScope(currentScope); Scope blockScope = symbols.getScope(currentScope);
VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
tmpVar.setType(toType); tmpVar.setTypeInferred(toType);
StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue1(), assignment.getSource(), Comment.NO_COMMENTS); StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue1(), assignment.getSource(), Comment.NO_COMMENTS);
assignment.setrValue1(tmpVar.getRef()); assignment.setrValue1(tmpVar.getRef());
stmtIt.previous(); stmtIt.previous();
@ -112,7 +113,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
} else { } else {
Scope blockScope = symbols.getScope(currentScope); Scope blockScope = symbols.getScope(currentScope);
VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
tmpVar.setType(toType); tmpVar.setTypeInferred(toType);
StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue2(), assignment.getSource(), Comment.NO_COMMENTS); StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue2(), assignment.getSource(), Comment.NO_COMMENTS);
assignment.setrValue2(tmpVar.getRef()); assignment.setrValue2(tmpVar.getRef());
stmtIt.previous(); stmtIt.previous();
@ -156,13 +157,21 @@ public interface ProgramExpressionBinary extends ProgramExpression {
@Override @Override
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
Scope blockScope = symbols.getScope(currentScope); if(assignment.getlValue() instanceof VariableRef) {
VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); Variable variable = symbols.getVariable((VariableRef) assignment.getlValue());
SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight()); if(variable.isInferredType())
tmpVar.setType(rightType); variable.setTypeInferred(toType);
StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS); else
assignment.setlValue(tmpVar.getRef()); throw new InternalError("Cannot cast declared type!" + variable.toString());
stmtIt.add(newAssignment); } else {
Scope blockScope = symbols.getScope(currentScope);
VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
tmpVar.setTypeInferred(rightType);
StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
assignment.setlValue(tmpVar.getRef());
stmtIt.add(newAssignment);
}
} }
@Override @Override
@ -173,7 +182,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
Scope blockScope = symbols.getScope(currentScope); Scope blockScope = symbols.getScope(currentScope);
VariableIntermediate tmpVar = blockScope.addVariableIntermediate(); VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight()); SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
tmpVar.setType(rightType); tmpVar.setTypeInferred(rightType);
StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS); StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
assignment.setlValue(tmpVar.getRef()); assignment.setlValue(tmpVar.getRef());
stmtIt.add(newAssignment); stmtIt.add(newAssignment);
@ -314,7 +323,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
if(getPointerDereferenceIndexed().getPointer() instanceof ConstantValue) { if(getPointerDereferenceIndexed().getPointer() instanceof ConstantValue) {
getPointerDereferenceIndexed().setPointer(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getPointer())); getPointerDereferenceIndexed().setPointer(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getPointer()));
} else { } else {
// Try to use CastValue - may later have to be supported! // Try to use CastValue - may later have to be supported!
getPointerDereferenceIndexed().setPointer(new CastValue(toType, getPointerDereferenceIndexed().getPointer())); getPointerDereferenceIndexed().setPointer(new CastValue(toType, getPointerDereferenceIndexed().getPointer()));
} }
@ -324,7 +333,14 @@ public interface ProgramExpressionBinary extends ProgramExpression {
public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
if(getPointerDereferenceIndexed().getIndex() instanceof ConstantValue) { if(getPointerDereferenceIndexed().getIndex() instanceof ConstantValue) {
getPointerDereferenceIndexed().setIndex(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getIndex())); getPointerDereferenceIndexed().setIndex(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getIndex()));
} else { } else if( getPointerDereferenceIndexed().getIndex() instanceof VariableRef) {
Variable variable = symbols.getVariable((VariableRef) getPointerDereferenceIndexed().getIndex());
if(variable.isInferredType())
variable.setTypeInferred(toType);
else
throw new InternalError("Cannot cast declared type!" + variable.toString());
} else {
// Try to use CastValue - may later have to be supported! // Try to use CastValue - may later have to be supported!
getPointerDereferenceIndexed().setIndex(new CastValue(toType, getPointerDereferenceIndexed().getIndex())); getPointerDereferenceIndexed().setIndex(new CastValue(toType, getPointerDereferenceIndexed().getIndex()));
} }
@ -360,15 +376,22 @@ public interface ProgramExpressionBinary extends ProgramExpression {
@Override @Override
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
throw new InternalError("Not supported!"); Variable variable = symbols.getVariable(phiVariable.getVariable());
if(variable.isInferredType())
variable.setTypeInferred(toType);
else
throw new InternalError("Cannot cast declared type!" + variable.toString());
} }
@Override @Override
public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) { public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
if(getRight() instanceof ConstantValue) { if(getRight() instanceof VariableRef) {
Variable variable = symbols.getVariable((VariableRef) getRight());
if(variable.isInferredType())
variable.setTypeInferred(toType);
} else if(getRight() instanceof ConstantValue) {
value.setrValue(new ConstantCastValue(toType, (ConstantValue) getRight())); value.setrValue(new ConstantCastValue(toType, (ConstantValue) getRight()));
} else { } else {
// Try to use CastValue - may later have to be supported!
value.setrValue(new CastValue(toType, getRight())); value.setrValue(new CastValue(toType, getRight()));
} }
} }
@ -380,7 +403,4 @@ public interface ProgramExpressionBinary extends ProgramExpression {
} }
} }

View File

@ -0,0 +1,27 @@
package dk.camelot64.kickc.model.operators;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantLiteral;
/** Unary Cast to signed number operator ( (snumber) x ) */
public class OperatorCastSNumber extends OperatorCast {
public OperatorCastSNumber(int precedence) {
super("((snumber))", "_snumber_", precedence, SymbolType.SNUMBER);
}
@Override
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
if(value instanceof ConstantInteger)
return new ConstantInteger(((ConstantInteger) value).getValue(), SymbolType.SNUMBER);
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
}
@Override
public SymbolType inferType(SymbolType operandType) {
return SymbolType.SNUMBER;
}
}

View File

@ -0,0 +1,28 @@
package dk.camelot64.kickc.model.operators;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantLiteral;
import dk.camelot64.kickc.model.values.ConstantPointer;
/** Unary Cast to unsigned number operator ( (unumber) x ) */
public class OperatorCastUNumber extends OperatorCast {
public OperatorCastUNumber(int precedence) {
super("((unumber))", "_unumber_", precedence, SymbolType.UNUMBER);
}
@Override
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
if(value instanceof ConstantInteger)
return new ConstantInteger(((ConstantInteger) value).getValue(), SymbolType.UNUMBER);
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
}
@Override
public SymbolType inferType(SymbolType operandType) {
return SymbolType.UNUMBER;
}
}

View File

@ -29,7 +29,7 @@ public class OperatorDivide extends OperatorBinary {
@Override @Override
public SymbolType inferType(SymbolType left, SymbolType right) { public SymbolType inferType(SymbolType left, SymbolType right) {
if(left instanceof SymbolTypePointer) { if(left instanceof SymbolTypePointer) {
if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) { if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)|| SymbolType.UNUMBER.equals(right)|| SymbolType.SNUMBER.equals(right)) {
return left; return left;
} else { } else {
throw new NoMatchingType("Cannot divide pointer by "+right.toString()); throw new NoMatchingType("Cannot divide pointer by "+right.toString());

View File

@ -50,6 +50,10 @@ public class OperatorGetHigh extends OperatorUnary {
return SymbolType.BYTE; return SymbolType.BYTE;
} else if(SymbolType.NUMBER.equals(operandType)) { } else if(SymbolType.NUMBER.equals(operandType)) {
return SymbolType.NUMBER; return SymbolType.NUMBER;
} else if(SymbolType.UNUMBER.equals(operandType)) {
return SymbolType.UNUMBER;
} else if(SymbolType.SNUMBER.equals(operandType)) {
return SymbolType.UNUMBER;
} }
throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType); throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
} }

View File

@ -50,6 +50,10 @@ public class OperatorGetLow extends OperatorUnary {
return SymbolType.BYTE; return SymbolType.BYTE;
} else if(SymbolType.NUMBER.equals(operandType)) { } else if(SymbolType.NUMBER.equals(operandType)) {
return SymbolType.NUMBER; return SymbolType.NUMBER;
} else if(SymbolType.UNUMBER.equals(operandType)) {
return SymbolType.UNUMBER;
} else if(SymbolType.SNUMBER.equals(operandType)) {
return SymbolType.UNUMBER;
} }
throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType); throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
} }

View File

@ -26,6 +26,8 @@ public class Operators {
public static final OperatorUnary CAST_DWORD = new OperatorCastDWord(2); public static final OperatorUnary CAST_DWORD = new OperatorCastDWord(2);
public static final OperatorUnary CAST_SDWORD = new OperatorCastSDWord(2); public static final OperatorUnary CAST_SDWORD = new OperatorCastSDWord(2);
public static final OperatorUnary CAST_BOOL= new OperatorCastBool(2); public static final OperatorUnary CAST_BOOL= new OperatorCastBool(2);
public static final OperatorUnary CAST_UNUMBER = new OperatorCastUNumber(2);
public static final OperatorUnary CAST_SNUMBER = new OperatorCastSNumber(2);
public static final OperatorUnary SIZEOF = new OperatorSizeOf(2); public static final OperatorUnary SIZEOF = new OperatorSizeOf(2);
public static final OperatorUnary TYPEID = new OperatorTypeId(2); public static final OperatorUnary TYPEID = new OperatorTypeId(2);
public static final OperatorBinary MULTIPLY = new OperatorMultiply(3); public static final OperatorBinary MULTIPLY = new OperatorMultiply(3);
@ -149,6 +151,10 @@ public class Operators {
return CAST_DWORD; return CAST_DWORD;
} else if(SymbolType.SDWORD.equals(castType)) { } else if(SymbolType.SDWORD.equals(castType)) {
return CAST_SDWORD; return CAST_SDWORD;
} else if(SymbolType.UNUMBER.equals(castType)) {
return CAST_UNUMBER;
} else if(SymbolType.SNUMBER.equals(castType)) {
return CAST_SNUMBER;
} else if(SymbolType.BOOLEAN.equals(castType)) { } else if(SymbolType.BOOLEAN.equals(castType)) {
return CAST_BOOL; return CAST_BOOL;
} else if(castType instanceof SymbolTypePointer) { } else if(castType instanceof SymbolTypePointer) {

View File

@ -12,6 +12,7 @@ public class VariableVersion extends Variable {
this.setDeclaredAlignment(versionOf.getDeclaredAlignment()); this.setDeclaredAlignment(versionOf.getDeclaredAlignment());
this.setDeclaredRegister(versionOf.getDeclaredRegister()); this.setDeclaredRegister(versionOf.getDeclaredRegister());
this.setDeclaredVolatile(versionOf.isDeclaredVolatile()); this.setDeclaredVolatile(versionOf.isDeclaredVolatile());
this.setInferredType(versionOf.isInferredType());
this.versionOfName = versionOf.getLocalName(); this.versionOfName = versionOf.getLocalName();
this.setComments(versionOf.getComments()); this.setComments(versionOf.getComments());
} }

View File

@ -117,7 +117,7 @@ public interface SymbolType {
* @return true if the type is integer * @return true if the type is integer
*/ */
static boolean isInteger(SymbolType type) { static boolean isInteger(SymbolType type) {
return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type); return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type)|| UNUMBER.equals(type)|| SNUMBER.equals(type);
} }
} }

View File

@ -32,6 +32,16 @@ public class SymbolTypeConversion {
if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) { if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) {
return SymbolType.NUMBER; return SymbolType.NUMBER;
} }
// If any of the two types are unresolved unsigned - return an unresolved unsigned result
if(SymbolType.UNUMBER.equals(type1) || SymbolType.UNUMBER.equals(type2)) {
return SymbolType.UNUMBER;
}
// If any of the two types are unresolved signed - return an unresolved signed result
if(SymbolType.SNUMBER.equals(type1) || SymbolType.SNUMBER.equals(type2)) {
return SymbolType.SNUMBER;
}
// Both types are resolved (fixed) integer types
SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1; SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1;
SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2; SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2;
// C99 6.3.1.8 a. If two operands have the same type no conversion is performed // C99 6.3.1.8 a. If two operands have the same type no conversion is performed
@ -82,6 +92,13 @@ public class SymbolTypeConversion {
return null; return null;
} }
// a) If any the two operands are unsigned numbers the result is an unsigned number
if(SymbolType.UNUMBER.equals(leftType) || SymbolType.UNUMBER.equals(rightType))
return SymbolType.UNUMBER;
// a) If any the two operands are signed numbers the result is an signed number
if(SymbolType.SNUMBER.equals(leftType) || SymbolType.SNUMBER.equals(rightType))
return SymbolType.SNUMBER;
// Treat pointers like WORD // Treat pointers like WORD
if(leftType instanceof SymbolTypePointer) leftType = SymbolType.WORD; if(leftType instanceof SymbolTypePointer) leftType = SymbolType.WORD;
if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD; if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD;
@ -102,52 +119,70 @@ public class SymbolTypeConversion {
return null; return null;
} }
// Find the cast type if possible if(fixedType.isSigned()) {
if(numberVal instanceof ConstantValue) { return SymbolType.SNUMBER;
ConstantLiteral constantLiteral;
try {
constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols);
} catch( ConstantNotLiteral e) {
// Postpone til later!
return null;
}
if(constantLiteral instanceof ConstantInteger) {
ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
if(SymbolType.NUMBER.equals(constantInteger.getType())) {
Long value = constantInteger.getValue();
if(fixedType.isSigned()) {
// b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value);
if(smallestSignedType == null) {
throw new CompileError("Number constant has value that cannot be represented by a signed type " + value, currentStmt);
}
return smallestSignedType;
} else {
// b) If one operand is a signed type and the other a number the number is converted to the smallest unsigned type that can hold its values.
// If the number value is negative it is converted to unsigned using two's complement.
SymbolTypeIntegerFixed smallestUnsignedType;
if(value < 0) {
smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(-value);
} else {
smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value);
}
return smallestUnsignedType;
}
} else {
throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt);
}
}
} else { } else {
// Postpone til later! return SymbolType.UNUMBER;
return null;
} }
} }
// No number conversion // No number conversion
return null; return null;
}
public static SymbolType getSmallestSignedFixedIntegerType(ConstantValue constantValue, ProgramScope symbols) {
ConstantLiteral constantLiteral;
try {
constantLiteral = constantValue.calculateLiteral(symbols);
} catch(ConstantNotLiteral e) {
// Postpone til later!
return null;
}
if(constantLiteral instanceof ConstantInteger) {
Long value = ((ConstantInteger) constantLiteral).getValue();
// b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value);
if(smallestSignedType == null) {
throw new CompileError("Number constant has value that cannot be represented by a signed type " + constantValue.toString());
}
return smallestSignedType;
}
// Postpone til later!
return null;
} }
public static SymbolType getSmallestUnsignedFixedIntegerType(ConstantValue constantValue, ProgramScope symbols) {
ConstantLiteral constantLiteral;
try {
constantLiteral = constantValue.calculateLiteral(symbols);
} catch(ConstantNotLiteral e) {
// Postpone til later!
return null;
}
if(constantLiteral instanceof ConstantInteger) {
Long value = ((ConstantInteger) constantLiteral).getValue();
// b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
SymbolTypeIntegerFixed smallestUnsignedType;
if(value < 0) {
smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(-value);
} else {
smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value);
}
if(smallestUnsignedType == null) {
throw new CompileError("Number constant has value that cannot be represented by a unsigned type " + constantValue.toString());
}
return smallestUnsignedType;
}
// Postpone til later!
return null;
}
/** /**
* Determines if the types of an assignment match up properly * Determines if the types of an assignment match up properly
*
* @param lValueType The type of the LValue * @param lValueType The type of the LValue
* @param rValueType The type of the RValue * @param rValueType The type of the RValue
* @return true if the types match up * @return true if the types match up
@ -171,10 +206,26 @@ public class SymbolTypeConversion {
// R-value is still a number - constants are probably not done being identified & typed // R-value is still a number - constants are probably not done being identified & typed
return true; return true;
} }
if(SymbolType.UNUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
// R-value is still a number - constants are probably not done being identified & typed
return true;
}
if(SymbolType.SNUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
// R-value is still a number - constants are probably not done being identified & typed
return true;
}
if(SymbolType.NUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) { if(SymbolType.NUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) {
// R-value is still a number - constants are probably not done being identified & typed // R-value is still a number - constants are probably not done being identified & typed
return true; return true;
} }
if(SymbolType.UNUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) {
// R-value is still a number - constants are probably not done being identified & typed
return true;
}
if(SymbolType.SNUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) {
// R-value is still a number - constants are probably not done being identified & typed
return true;
}
if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType())) { if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType())) {
// String value can be assigned into a pointer // String value can be assigned into a pointer
return true; return true;
@ -189,6 +240,7 @@ public class SymbolTypeConversion {
/** /**
* Determines if the left side of an assignment needs a cast to be assigned to the right side * Determines if the left side of an assignment needs a cast to be assigned to the right side
*
* @param lValueType The type of the LValue * @param lValueType The type of the LValue
* @param rValueType The type of the RValue * @param rValueType The type of the RValue
* @return true if the left side needs a cast * @return true if the left side needs a cast
@ -201,9 +253,8 @@ public class SymbolTypeConversion {
else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType())) else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType()))
return false; return false;
else else
return true; return true;
} }
} }

View File

@ -64,7 +64,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
VariableRef idx2VarRef = handled.getOrDefault(currentStmt, new LinkedHashMap<>()).get(deref.getIndex()); VariableRef idx2VarRef = handled.getOrDefault(currentStmt, new LinkedHashMap<>()).get(deref.getIndex());
if(idx2VarRef==null) { if(idx2VarRef==null) {
VariableIntermediate idx2Var = getScope().getScope(currentBlock.getScope()).addVariableIntermediate(); VariableIntermediate idx2Var = getScope().getScope(currentBlock.getScope()).addVariableIntermediate();
idx2Var.setType(SymbolTypeInference.inferType(getScope(), deref.getIndex())); idx2Var.setTypeInferred(SymbolTypeInference.inferType(getScope(), deref.getIndex()));
ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()); ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
StatementAssignment idx2 = new StatementAssignment(idx2Var.getRef(), deref.getIndex(), Operators.MULTIPLY, sizeOfTargetType, currentStmt.getSource(), Comment.NO_COMMENTS); StatementAssignment idx2 = new StatementAssignment(idx2Var.getRef(), deref.getIndex(), Operators.MULTIPLY, sizeOfTargetType, currentStmt.getSource(), Comment.NO_COMMENTS);
stmtIt.previous(); stmtIt.previous();
@ -100,7 +100,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
// Adding to a pointer - multiply by sizeof() // Adding to a pointer - multiply by sizeof()
getLog().append("Fixing pointer addition " + assignment.toString(getProgram(), false)); getLog().append("Fixing pointer addition " + assignment.toString(getProgram(), false));
VariableIntermediate tmpVar = getScope().getScope(block.getScope()).addVariableIntermediate(); VariableIntermediate tmpVar = getScope().getScope(block.getScope()).addVariableIntermediate();
tmpVar.setType(SymbolTypeInference.inferType(getScope(), assignment.getrValue2())); tmpVar.setTypeInferred(SymbolTypeInference.inferType(getScope(), assignment.getrValue2()));
stmtIt.remove(); stmtIt.remove();
ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()); ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
stmtIt.add(new StatementAssignment(tmpVar.getRef(), assignment.getrValue2(), Operators.MULTIPLY, sizeOfTargetType, assignment.getSource(), Comment.NO_COMMENTS)); stmtIt.add(new StatementAssignment(tmpVar.getRef(), assignment.getrValue2(), Operators.MULTIPLY, sizeOfTargetType, assignment.getSource(), Comment.NO_COMMENTS));

View File

@ -92,6 +92,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
constScope, constScope,
variableType, variableType,
constVal); constVal);
constantVar.setInferredType(variable.isInferredType());
constantVar.setDeclaredAlignment(variable.getDeclaredAlignment()); constantVar.setDeclaredAlignment(variable.getDeclaredAlignment());
constantVar.setDeclaredRegister(variable.getDeclaredRegister()); constantVar.setDeclaredRegister(variable.getDeclaredRegister());
if(variable.getComments().size() > 0) { if(variable.getComments().size() > 0) {

View File

@ -33,8 +33,9 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
@Override @Override
public boolean step() { public boolean step() {
Map<ConstantRef, ConstantValue> inline = new HashMap<>(); Map<ConstantRef, ConstantValue> inline = new HashMap<>();
Map<ConstantRef, ConstantValue> aliasConstants = findAliasConstants();
inline.putAll(aliasConstants);
inline.putAll(findUnnamedConstants()); inline.putAll(findUnnamedConstants());
inline.putAll(findAliasConstants());
inline.putAll(findConstVarVersions()); inline.putAll(findConstVarVersions());
// Remove all string constants // Remove all string constants

View File

@ -42,7 +42,7 @@ public class Pass2DeInlineWordDerefIdx extends Pass2SsaOptimization {
stmtIt.next(); stmtIt.next();
programValue.set(new PointerDereferenceSimple(tmpVar.getRef())); programValue.set(new PointerDereferenceSimple(tmpVar.getRef()));
SymbolType pointerType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(tmpVarAssignment)); SymbolType pointerType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(tmpVarAssignment));
tmpVar.setType(pointerType); tmpVar.setTypeInferred(pointerType);
optimized.set(true); optimized.set(true);
} }
} }

View File

@ -40,6 +40,7 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
if(SymbolType.NUMBER.equals(rightType)) { if(SymbolType.NUMBER.equals(rightType)) {
getLog().append("Adding number conversion cast (" + castType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false))); getLog().append("Adding number conversion cast (" + castType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false)));
binary.addRightCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope()); binary.addRightCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
modified.set(true); modified.set(true);
} }
} }

View File

@ -11,10 +11,11 @@ import dk.camelot64.kickc.model.values.RValue;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
/** Simplifies casts /**
* Simplifies casts
* - Inlines casts of (number) constants * - Inlines casts of (number) constants
* - Removes unnecessary casts * - Removes unnecessary casts
* */ */
public class PassNCastSimplification extends Pass2SsaOptimization { public class PassNCastSimplification extends Pass2SsaOptimization {
public PassNCastSimplification(Program program) { public PassNCastSimplification(Program program) {
@ -39,12 +40,12 @@ public class PassNCastSimplification extends Pass2SsaOptimization {
} else if(unaryOperand instanceof ConstantInteger) { } else if(unaryOperand instanceof ConstantInteger) {
ConstantInteger constantInteger = (ConstantInteger) unaryOperand; ConstantInteger constantInteger = (ConstantInteger) unaryOperand;
if(SymbolType.NUMBER.equals(constantInteger.getType())) { if(SymbolType.NUMBER.equals(constantInteger.getType())) {
if(castType instanceof SymbolTypeIntegerFixed ) { if(castType instanceof SymbolTypeIntegerFixed || SymbolType.UNUMBER.equals(castType) || SymbolType.SNUMBER.equals(castType)) {
ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType); ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
programExpression.set(newConstInt); programExpression.set(newConstInt);
getLog().append("Simplifying constant integer cast " + newConstInt.toString()); getLog().append("Simplifying constant integer cast " + newConstInt.toString());
optimized.set(true); optimized.set(true);
} else if(castType instanceof SymbolTypePointer) { } else if(castType instanceof SymbolTypePointer) {
ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType()); ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType());
programExpression.set(newConstPointer); programExpression.set(newConstPointer);
getLog().append("Simplifying constant pointer cast " + newConstPointer.toString()); getLog().append("Simplifying constant pointer cast " + newConstPointer.toString());

View File

@ -0,0 +1,65 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.symbols.ConstantVar;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeConversion;
import dk.camelot64.kickc.model.values.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Finalize any constant integers to the smallest fixed size signed/unsigned type - if they have been resolved as snumber/unumber.
*/
public class PassNFinalizeNumberTypeConversions extends Pass2SsaOptimization {
public PassNFinalizeNumberTypeConversions(Program program) {
super(program);
}
@Override
public boolean step() {
AtomicBoolean modified = new AtomicBoolean(false);
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
if(programValue.get() instanceof ConstantInteger) {
ConstantInteger constantInteger = (ConstantInteger) programValue.get();
if(SymbolType.UNUMBER.equals(constantInteger.getType())) {
SymbolType integerType = SymbolTypeConversion.getSmallestUnsignedFixedIntegerType(constantInteger, getScope());
programValue.set(new ConstantInteger(constantInteger.getValue(), integerType));
getLog().append("Finalized unsigned number type "+programValue.get().toString(getProgram()));
modified.set(true);
} else if(SymbolType.SNUMBER.equals(constantInteger.getType())) {
SymbolType integerType = SymbolTypeConversion.getSmallestSignedFixedIntegerType(constantInteger, getScope());
programValue.set(new ConstantInteger(constantInteger.getValue(), integerType));
getLog().append("Finalized signed number type "+programValue.get().toString(getProgram()));
modified.set(true);
}
} else if(programValue.get() instanceof ConstantCastValue) {
ConstantCastValue constantCastValue = (ConstantCastValue) programValue.get();
SymbolType toType = constantCastValue.getToType();
if(SymbolType.UNUMBER.equals(toType)) {
if(constantCastValue.getValue() instanceof ConstantRef) {
ConstantRef constRef = (ConstantRef) constantCastValue.getValue();
ConstantVar constant = getScope().getConstant(constRef);
if(constant.isInferredType())
constant.setTypeInferred(toType);
else
throw new InternalError("Cannot cast declared type!" + constant.toString());
} else {
ConstantLiteral constantLiteral = constantCastValue.getValue().calculateLiteral(getProgram().getScope());
SymbolType smallestUnsigned = SymbolTypeConversion.getSmallestUnsignedFixedIntegerType(constantLiteral, getScope());
if(smallestUnsigned!=null) {
constantCastValue.setToType(smallestUnsigned);
}
}
}
if(SymbolType.SNUMBER.equals(toType))
throw new InternalError("TODO: Finalize ConstantCast");
}
});
return modified.get();
}
}

View File

@ -60,7 +60,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
LValue lValue = call.getlValue(); LValue lValue = call.getlValue();
if(lValue instanceof VariableRef) { if(lValue instanceof VariableRef) {
Variable symbol = programScope.getVariable((VariableRef) lValue); Variable symbol = programScope.getVariable((VariableRef) lValue);
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) {
Procedure procedure = programScope.getProcedure(call.getProcedure()); Procedure procedure = programScope.getProcedure(call.getProcedure());
SymbolType type = procedure.getReturnType(); SymbolType type = procedure.getReturnType();
setInferedType(program, call, symbol, type); setInferedType(program, call, symbol, type);
@ -73,7 +73,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
LValue lValue = call.getlValue(); LValue lValue = call.getlValue();
if(lValue instanceof VariableRef) { if(lValue instanceof VariableRef) {
Variable symbol = programScope.getVariable((VariableRef) lValue); Variable symbol = programScope.getVariable((VariableRef) lValue);
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) {
SymbolType procedureType = SymbolTypeInference.inferType(programScope, call.getProcedure()); SymbolType procedureType = SymbolTypeInference.inferType(programScope, call.getProcedure());
if(procedureType instanceof SymbolTypeProcedure) { if(procedureType instanceof SymbolTypeProcedure) {
SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType(); SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType();
@ -86,7 +86,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
private static void updateInferedTypePhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) { private static void updateInferedTypePhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) {
ProgramScope programScope = program.getScope(); ProgramScope programScope = program.getScope();
Variable symbol = programScope.getVariable(phiVariable.getVariable()); Variable symbol = programScope.getVariable(phiVariable.getVariable());
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) {
SymbolType type = null; SymbolType type = null;
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
RValue rValue = phiRValue.getrValue(); RValue rValue = phiRValue.getrValue();
@ -112,7 +112,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
LValue lValue = assignment.getlValue(); LValue lValue = assignment.getlValue();
if(lValue instanceof VariableRef) { if(lValue instanceof VariableRef) {
Variable symbol = programScope.getVariable((VariableRef) lValue); Variable symbol = programScope.getVariable((VariableRef) lValue);
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) { if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType()) || SymbolType.SNUMBER.equals(symbol.getType())) {
SymbolType type = SymbolTypeInference.inferType(programScope, new AssignmentRValue(assignment)); SymbolType type = SymbolTypeInference.inferType(programScope, new AssignmentRValue(assignment));
setInferedType(program, assignment, symbol, type); setInferedType(program, assignment, symbol, type);
// If the type is an array or a string the symbol is constant // If the type is an array or a string the symbol is constant

View File

@ -48,10 +48,10 @@ byte myprintf(byte *dst, byte *str, word w1, word w2, word w3) {
if (bTrailing != 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = ' '; if (bTrailing != 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = ' ';
} else if (b == 'x' || b == 'X'){ // hex } else if (b == 'x' || b == 'X'){ // hex
b = ((byte)w >> 4) & 0xF; b = ((byte)w >> 4) & 0xF;
dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b; dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
// "('a' - 10)" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/184 [FIXED] // "('a' - 10)" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/184 [FIXED]
// (b < 10 ? '0' : 0x57) not supported // (b < 10 ? '0' : 0x57) not supported
b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b; b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
} }
bFormat = 0; bFormat = 0;
continue; continue;

View File

@ -3,6 +3,6 @@
void main() { void main() {
const byte* screen = 0x400; const byte* screen = 0x400;
for(byte i: 0..10) { for(byte i: 0..10) {
screen[i] = (i<5?0x57ub:'0')+i; screen[i] = (i<5?0x57:'0')+i;
} }
} }