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:
parent
9ef7c69c3e
commit
f574bb676c
@ -232,12 +232,15 @@ public class Compiler {
|
||||
private List<Pass2SsaOptimization> getPass2Optimizations() {
|
||||
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
|
||||
optimizations.add(new Pass2FixInlineConstructorsNew(program));
|
||||
|
||||
optimizations.add(new PassNAddNumberTypeConversions(program));
|
||||
optimizations.add(new PassNAddArrayNumberTypeConversions(program));
|
||||
optimizations.add(new PassNTypeInference(program));
|
||||
optimizations.add(new PassNAddTypeConversionAssignment(program));
|
||||
optimizations.add(new Pass2InlineCast(program));
|
||||
optimizations.add(new PassNCastSimplification(program));
|
||||
optimizations.add(new PassNFinalizeNumberTypeConversions(program));
|
||||
optimizations.add(new PassNTypeInference(program));
|
||||
optimizations.add(new PassNAddTypeConversionAssignment(program));
|
||||
|
||||
optimizations.add(new PassNTypeIdSimplification(program));
|
||||
optimizations.add(new Pass2SizeOfSimplification(program));
|
||||
optimizations.add(new PassNStatementIndices(program));
|
||||
|
@ -10,6 +10,7 @@ import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.symbols.Scope;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.symbols.VariableIntermediate;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
||||
@ -96,7 +97,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
|
||||
} else {
|
||||
Scope blockScope = symbols.getScope(currentScope);
|
||||
VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
|
||||
tmpVar.setType(toType);
|
||||
tmpVar.setTypeInferred(toType);
|
||||
StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue1(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||
assignment.setrValue1(tmpVar.getRef());
|
||||
stmtIt.previous();
|
||||
@ -112,7 +113,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
|
||||
} else {
|
||||
Scope blockScope = symbols.getScope(currentScope);
|
||||
VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
|
||||
tmpVar.setType(toType);
|
||||
tmpVar.setTypeInferred(toType);
|
||||
StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue2(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||
assignment.setrValue2(tmpVar.getRef());
|
||||
stmtIt.previous();
|
||||
@ -156,13 +157,21 @@ public interface ProgramExpressionBinary extends ProgramExpression {
|
||||
|
||||
@Override
|
||||
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||
Scope blockScope = symbols.getScope(currentScope);
|
||||
VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
|
||||
SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
|
||||
tmpVar.setType(rightType);
|
||||
StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||
assignment.setlValue(tmpVar.getRef());
|
||||
stmtIt.add(newAssignment);
|
||||
if(assignment.getlValue() instanceof VariableRef) {
|
||||
Variable variable = symbols.getVariable((VariableRef) assignment.getlValue());
|
||||
if(variable.isInferredType())
|
||||
variable.setTypeInferred(toType);
|
||||
else
|
||||
throw new InternalError("Cannot cast declared type!" + variable.toString());
|
||||
} else {
|
||||
Scope blockScope = symbols.getScope(currentScope);
|
||||
VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
|
||||
SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
|
||||
tmpVar.setTypeInferred(rightType);
|
||||
StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||
assignment.setlValue(tmpVar.getRef());
|
||||
stmtIt.add(newAssignment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -173,7 +182,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
|
||||
Scope blockScope = symbols.getScope(currentScope);
|
||||
VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
|
||||
SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
|
||||
tmpVar.setType(rightType);
|
||||
tmpVar.setTypeInferred(rightType);
|
||||
StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||
assignment.setlValue(tmpVar.getRef());
|
||||
stmtIt.add(newAssignment);
|
||||
@ -314,7 +323,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
|
||||
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||
if(getPointerDereferenceIndexed().getPointer() instanceof ConstantValue) {
|
||||
getPointerDereferenceIndexed().setPointer(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getPointer()));
|
||||
} else {
|
||||
} else {
|
||||
// Try to use CastValue - may later have to be supported!
|
||||
getPointerDereferenceIndexed().setPointer(new CastValue(toType, getPointerDereferenceIndexed().getPointer()));
|
||||
}
|
||||
@ -324,7 +333,14 @@ public interface ProgramExpressionBinary extends ProgramExpression {
|
||||
public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||
if(getPointerDereferenceIndexed().getIndex() instanceof ConstantValue) {
|
||||
getPointerDereferenceIndexed().setIndex(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getIndex()));
|
||||
} else {
|
||||
} else if( getPointerDereferenceIndexed().getIndex() instanceof VariableRef) {
|
||||
Variable variable = symbols.getVariable((VariableRef) getPointerDereferenceIndexed().getIndex());
|
||||
if(variable.isInferredType())
|
||||
variable.setTypeInferred(toType);
|
||||
else
|
||||
throw new InternalError("Cannot cast declared type!" + variable.toString());
|
||||
|
||||
} else {
|
||||
// Try to use CastValue - may later have to be supported!
|
||||
getPointerDereferenceIndexed().setIndex(new CastValue(toType, getPointerDereferenceIndexed().getIndex()));
|
||||
}
|
||||
@ -360,15 +376,22 @@ public interface ProgramExpressionBinary extends ProgramExpression {
|
||||
|
||||
@Override
|
||||
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||
throw new InternalError("Not supported!");
|
||||
Variable variable = symbols.getVariable(phiVariable.getVariable());
|
||||
if(variable.isInferredType())
|
||||
variable.setTypeInferred(toType);
|
||||
else
|
||||
throw new InternalError("Cannot cast declared type!" + variable.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||
if(getRight() instanceof ConstantValue) {
|
||||
if(getRight() instanceof VariableRef) {
|
||||
Variable variable = symbols.getVariable((VariableRef) getRight());
|
||||
if(variable.isInferredType())
|
||||
variable.setTypeInferred(toType);
|
||||
} else if(getRight() instanceof ConstantValue) {
|
||||
value.setrValue(new ConstantCastValue(toType, (ConstantValue) getRight()));
|
||||
} else {
|
||||
// Try to use CastValue - may later have to be supported!
|
||||
} else {
|
||||
value.setrValue(new CastValue(toType, getRight()));
|
||||
}
|
||||
}
|
||||
@ -380,7 +403,4 @@ public interface ProgramExpressionBinary extends ProgramExpression {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ public class OperatorDivide extends OperatorBinary {
|
||||
@Override
|
||||
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||
if(left instanceof SymbolTypePointer) {
|
||||
if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) {
|
||||
if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)|| SymbolType.UNUMBER.equals(right)|| SymbolType.SNUMBER.equals(right)) {
|
||||
return left;
|
||||
} else {
|
||||
throw new NoMatchingType("Cannot divide pointer by "+right.toString());
|
||||
|
@ -50,6 +50,10 @@ public class OperatorGetHigh extends OperatorUnary {
|
||||
return SymbolType.BYTE;
|
||||
} else if(SymbolType.NUMBER.equals(operandType)) {
|
||||
return SymbolType.NUMBER;
|
||||
} else if(SymbolType.UNUMBER.equals(operandType)) {
|
||||
return SymbolType.UNUMBER;
|
||||
} else if(SymbolType.SNUMBER.equals(operandType)) {
|
||||
return SymbolType.UNUMBER;
|
||||
}
|
||||
throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
|
||||
}
|
||||
|
@ -50,6 +50,10 @@ public class OperatorGetLow extends OperatorUnary {
|
||||
return SymbolType.BYTE;
|
||||
} else if(SymbolType.NUMBER.equals(operandType)) {
|
||||
return SymbolType.NUMBER;
|
||||
} else if(SymbolType.UNUMBER.equals(operandType)) {
|
||||
return SymbolType.UNUMBER;
|
||||
} else if(SymbolType.SNUMBER.equals(operandType)) {
|
||||
return SymbolType.UNUMBER;
|
||||
}
|
||||
throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ public class Operators {
|
||||
public static final OperatorUnary CAST_DWORD = new OperatorCastDWord(2);
|
||||
public static final OperatorUnary CAST_SDWORD = new OperatorCastSDWord(2);
|
||||
public static final OperatorUnary CAST_BOOL= new OperatorCastBool(2);
|
||||
public static final OperatorUnary CAST_UNUMBER = new OperatorCastUNumber(2);
|
||||
public static final OperatorUnary CAST_SNUMBER = new OperatorCastSNumber(2);
|
||||
public static final OperatorUnary SIZEOF = new OperatorSizeOf(2);
|
||||
public static final OperatorUnary TYPEID = new OperatorTypeId(2);
|
||||
public static final OperatorBinary MULTIPLY = new OperatorMultiply(3);
|
||||
@ -149,6 +151,10 @@ public class Operators {
|
||||
return CAST_DWORD;
|
||||
} else if(SymbolType.SDWORD.equals(castType)) {
|
||||
return CAST_SDWORD;
|
||||
} else if(SymbolType.UNUMBER.equals(castType)) {
|
||||
return CAST_UNUMBER;
|
||||
} else if(SymbolType.SNUMBER.equals(castType)) {
|
||||
return CAST_SNUMBER;
|
||||
} else if(SymbolType.BOOLEAN.equals(castType)) {
|
||||
return CAST_BOOL;
|
||||
} else if(castType instanceof SymbolTypePointer) {
|
||||
|
@ -12,6 +12,7 @@ public class VariableVersion extends Variable {
|
||||
this.setDeclaredAlignment(versionOf.getDeclaredAlignment());
|
||||
this.setDeclaredRegister(versionOf.getDeclaredRegister());
|
||||
this.setDeclaredVolatile(versionOf.isDeclaredVolatile());
|
||||
this.setInferredType(versionOf.isInferredType());
|
||||
this.versionOfName = versionOf.getLocalName();
|
||||
this.setComments(versionOf.getComments());
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ public interface SymbolType {
|
||||
* @return true if the type is integer
|
||||
*/
|
||||
static boolean isInteger(SymbolType type) {
|
||||
return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type);
|
||||
return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type)|| UNUMBER.equals(type)|| SNUMBER.equals(type);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,6 +32,16 @@ public class SymbolTypeConversion {
|
||||
if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) {
|
||||
return SymbolType.NUMBER;
|
||||
}
|
||||
// If any of the two types are unresolved unsigned - return an unresolved unsigned result
|
||||
if(SymbolType.UNUMBER.equals(type1) || SymbolType.UNUMBER.equals(type2)) {
|
||||
return SymbolType.UNUMBER;
|
||||
}
|
||||
// If any of the two types are unresolved signed - return an unresolved signed result
|
||||
if(SymbolType.SNUMBER.equals(type1) || SymbolType.SNUMBER.equals(type2)) {
|
||||
return SymbolType.SNUMBER;
|
||||
}
|
||||
|
||||
// Both types are resolved (fixed) integer types
|
||||
SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1;
|
||||
SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2;
|
||||
// C99 6.3.1.8 a. If two operands have the same type no conversion is performed
|
||||
@ -82,6 +92,13 @@ public class SymbolTypeConversion {
|
||||
return null;
|
||||
}
|
||||
|
||||
// a) If any the two operands are unsigned numbers the result is an unsigned number
|
||||
if(SymbolType.UNUMBER.equals(leftType) || SymbolType.UNUMBER.equals(rightType))
|
||||
return SymbolType.UNUMBER;
|
||||
// a) If any the two operands are signed numbers the result is an signed number
|
||||
if(SymbolType.SNUMBER.equals(leftType) || SymbolType.SNUMBER.equals(rightType))
|
||||
return SymbolType.SNUMBER;
|
||||
|
||||
// Treat pointers like WORD
|
||||
if(leftType instanceof SymbolTypePointer) leftType = SymbolType.WORD;
|
||||
if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD;
|
||||
@ -102,52 +119,70 @@ public class SymbolTypeConversion {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find the cast type if possible
|
||||
if(numberVal instanceof ConstantValue) {
|
||||
ConstantLiteral constantLiteral;
|
||||
try {
|
||||
constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols);
|
||||
} catch( ConstantNotLiteral e) {
|
||||
// Postpone til later!
|
||||
return null;
|
||||
}
|
||||
if(constantLiteral instanceof ConstantInteger) {
|
||||
ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
|
||||
if(SymbolType.NUMBER.equals(constantInteger.getType())) {
|
||||
Long value = constantInteger.getValue();
|
||||
if(fixedType.isSigned()) {
|
||||
// b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
|
||||
SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value);
|
||||
if(smallestSignedType == null) {
|
||||
throw new CompileError("Number constant has value that cannot be represented by a signed type " + value, currentStmt);
|
||||
}
|
||||
return smallestSignedType;
|
||||
} else {
|
||||
// b) If one operand is a signed type and the other a number the number is converted to the smallest unsigned type that can hold its values.
|
||||
// If the number value is negative it is converted to unsigned using two's complement.
|
||||
SymbolTypeIntegerFixed smallestUnsignedType;
|
||||
if(value < 0) {
|
||||
smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(-value);
|
||||
} else {
|
||||
smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value);
|
||||
}
|
||||
return smallestUnsignedType;
|
||||
}
|
||||
} else {
|
||||
throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt);
|
||||
}
|
||||
}
|
||||
if(fixedType.isSigned()) {
|
||||
return SymbolType.SNUMBER;
|
||||
} else {
|
||||
// Postpone til later!
|
||||
return null;
|
||||
return SymbolType.UNUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
// No number conversion
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static SymbolType getSmallestSignedFixedIntegerType(ConstantValue constantValue, ProgramScope symbols) {
|
||||
ConstantLiteral constantLiteral;
|
||||
try {
|
||||
constantLiteral = constantValue.calculateLiteral(symbols);
|
||||
} catch(ConstantNotLiteral e) {
|
||||
// Postpone til later!
|
||||
return null;
|
||||
}
|
||||
if(constantLiteral instanceof ConstantInteger) {
|
||||
Long value = ((ConstantInteger) constantLiteral).getValue();
|
||||
// b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
|
||||
SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value);
|
||||
if(smallestSignedType == null) {
|
||||
throw new CompileError("Number constant has value that cannot be represented by a signed type " + constantValue.toString());
|
||||
}
|
||||
return smallestSignedType;
|
||||
}
|
||||
// Postpone til later!
|
||||
return null;
|
||||
}
|
||||
|
||||
public static SymbolType getSmallestUnsignedFixedIntegerType(ConstantValue constantValue, ProgramScope symbols) {
|
||||
ConstantLiteral constantLiteral;
|
||||
try {
|
||||
constantLiteral = constantValue.calculateLiteral(symbols);
|
||||
} catch(ConstantNotLiteral e) {
|
||||
// Postpone til later!
|
||||
return null;
|
||||
}
|
||||
if(constantLiteral instanceof ConstantInteger) {
|
||||
Long value = ((ConstantInteger) constantLiteral).getValue();
|
||||
// b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
|
||||
SymbolTypeIntegerFixed smallestUnsignedType;
|
||||
if(value < 0) {
|
||||
smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(-value);
|
||||
} else {
|
||||
smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value);
|
||||
}
|
||||
if(smallestUnsignedType == null) {
|
||||
throw new CompileError("Number constant has value that cannot be represented by a unsigned type " + constantValue.toString());
|
||||
}
|
||||
return smallestUnsignedType;
|
||||
}
|
||||
// Postpone til later!
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines if the types of an assignment match up properly
|
||||
*
|
||||
* @param lValueType The type of the LValue
|
||||
* @param rValueType The type of the RValue
|
||||
* @return true if the types match up
|
||||
@ -171,10 +206,26 @@ public class SymbolTypeConversion {
|
||||
// R-value is still a number - constants are probably not done being identified & typed
|
||||
return true;
|
||||
}
|
||||
if(SymbolType.UNUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
|
||||
// R-value is still a number - constants are probably not done being identified & typed
|
||||
return true;
|
||||
}
|
||||
if(SymbolType.SNUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
|
||||
// R-value is still a number - constants are probably not done being identified & typed
|
||||
return true;
|
||||
}
|
||||
if(SymbolType.NUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) {
|
||||
// R-value is still a number - constants are probably not done being identified & typed
|
||||
return true;
|
||||
}
|
||||
if(SymbolType.UNUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) {
|
||||
// R-value is still a number - constants are probably not done being identified & typed
|
||||
return true;
|
||||
}
|
||||
if(SymbolType.SNUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) {
|
||||
// R-value is still a number - constants are probably not done being identified & typed
|
||||
return true;
|
||||
}
|
||||
if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType())) {
|
||||
// String value can be assigned into a pointer
|
||||
return true;
|
||||
@ -189,6 +240,7 @@ public class SymbolTypeConversion {
|
||||
|
||||
/**
|
||||
* Determines if the left side of an assignment needs a cast to be assigned to the right side
|
||||
*
|
||||
* @param lValueType The type of the LValue
|
||||
* @param rValueType The type of the RValue
|
||||
* @return true if the left side needs a cast
|
||||
@ -201,9 +253,8 @@ public class SymbolTypeConversion {
|
||||
else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType()))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
|
||||
VariableRef idx2VarRef = handled.getOrDefault(currentStmt, new LinkedHashMap<>()).get(deref.getIndex());
|
||||
if(idx2VarRef==null) {
|
||||
VariableIntermediate idx2Var = getScope().getScope(currentBlock.getScope()).addVariableIntermediate();
|
||||
idx2Var.setType(SymbolTypeInference.inferType(getScope(), deref.getIndex()));
|
||||
idx2Var.setTypeInferred(SymbolTypeInference.inferType(getScope(), deref.getIndex()));
|
||||
ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
|
||||
StatementAssignment idx2 = new StatementAssignment(idx2Var.getRef(), deref.getIndex(), Operators.MULTIPLY, sizeOfTargetType, currentStmt.getSource(), Comment.NO_COMMENTS);
|
||||
stmtIt.previous();
|
||||
@ -100,7 +100,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
|
||||
// Adding to a pointer - multiply by sizeof()
|
||||
getLog().append("Fixing pointer addition " + assignment.toString(getProgram(), false));
|
||||
VariableIntermediate tmpVar = getScope().getScope(block.getScope()).addVariableIntermediate();
|
||||
tmpVar.setType(SymbolTypeInference.inferType(getScope(), assignment.getrValue2()));
|
||||
tmpVar.setTypeInferred(SymbolTypeInference.inferType(getScope(), assignment.getrValue2()));
|
||||
stmtIt.remove();
|
||||
ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
|
||||
stmtIt.add(new StatementAssignment(tmpVar.getRef(), assignment.getrValue2(), Operators.MULTIPLY, sizeOfTargetType, assignment.getSource(), Comment.NO_COMMENTS));
|
||||
|
@ -92,6 +92,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
constScope,
|
||||
variableType,
|
||||
constVal);
|
||||
constantVar.setInferredType(variable.isInferredType());
|
||||
constantVar.setDeclaredAlignment(variable.getDeclaredAlignment());
|
||||
constantVar.setDeclaredRegister(variable.getDeclaredRegister());
|
||||
if(variable.getComments().size() > 0) {
|
||||
|
@ -33,8 +33,9 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
|
||||
@Override
|
||||
public boolean step() {
|
||||
Map<ConstantRef, ConstantValue> inline = new HashMap<>();
|
||||
Map<ConstantRef, ConstantValue> aliasConstants = findAliasConstants();
|
||||
inline.putAll(aliasConstants);
|
||||
inline.putAll(findUnnamedConstants());
|
||||
inline.putAll(findAliasConstants());
|
||||
inline.putAll(findConstVarVersions());
|
||||
|
||||
// Remove all string constants
|
||||
|
@ -42,7 +42,7 @@ public class Pass2DeInlineWordDerefIdx extends Pass2SsaOptimization {
|
||||
stmtIt.next();
|
||||
programValue.set(new PointerDereferenceSimple(tmpVar.getRef()));
|
||||
SymbolType pointerType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(tmpVarAssignment));
|
||||
tmpVar.setType(pointerType);
|
||||
tmpVar.setTypeInferred(pointerType);
|
||||
optimized.set(true);
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
|
||||
if(SymbolType.NUMBER.equals(rightType)) {
|
||||
getLog().append("Adding number conversion cast (" + castType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false)));
|
||||
binary.addRightCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
|
||||
|
||||
modified.set(true);
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,11 @@ import dk.camelot64.kickc.model.values.RValue;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/** Simplifies casts
|
||||
/**
|
||||
* Simplifies casts
|
||||
* - Inlines casts of (number) constants
|
||||
* - Removes unnecessary casts
|
||||
* */
|
||||
*/
|
||||
public class PassNCastSimplification extends Pass2SsaOptimization {
|
||||
|
||||
public PassNCastSimplification(Program program) {
|
||||
@ -39,12 +40,12 @@ public class PassNCastSimplification extends Pass2SsaOptimization {
|
||||
} else if(unaryOperand instanceof ConstantInteger) {
|
||||
ConstantInteger constantInteger = (ConstantInteger) unaryOperand;
|
||||
if(SymbolType.NUMBER.equals(constantInteger.getType())) {
|
||||
if(castType instanceof SymbolTypeIntegerFixed ) {
|
||||
if(castType instanceof SymbolTypeIntegerFixed || SymbolType.UNUMBER.equals(castType) || SymbolType.SNUMBER.equals(castType)) {
|
||||
ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
|
||||
programExpression.set(newConstInt);
|
||||
getLog().append("Simplifying constant integer cast " + newConstInt.toString());
|
||||
optimized.set(true);
|
||||
} else if(castType instanceof SymbolTypePointer) {
|
||||
} else if(castType instanceof SymbolTypePointer) {
|
||||
ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType());
|
||||
programExpression.set(newConstPointer);
|
||||
getLog().append("Simplifying constant pointer cast " + newConstPointer.toString());
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -60,7 +60,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
|
||||
LValue lValue = call.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
Variable symbol = programScope.getVariable((VariableRef) lValue);
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) {
|
||||
Procedure procedure = programScope.getProcedure(call.getProcedure());
|
||||
SymbolType type = procedure.getReturnType();
|
||||
setInferedType(program, call, symbol, type);
|
||||
@ -73,7 +73,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
|
||||
LValue lValue = call.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
Variable symbol = programScope.getVariable((VariableRef) lValue);
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) {
|
||||
SymbolType procedureType = SymbolTypeInference.inferType(programScope, call.getProcedure());
|
||||
if(procedureType instanceof SymbolTypeProcedure) {
|
||||
SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType();
|
||||
@ -86,7 +86,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
|
||||
private static void updateInferedTypePhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) {
|
||||
ProgramScope programScope = program.getScope();
|
||||
Variable symbol = programScope.getVariable(phiVariable.getVariable());
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) {
|
||||
SymbolType type = null;
|
||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
RValue rValue = phiRValue.getrValue();
|
||||
@ -112,7 +112,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
|
||||
LValue lValue = assignment.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
Variable symbol = programScope.getVariable((VariableRef) lValue);
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType()) || SymbolType.SNUMBER.equals(symbol.getType())) {
|
||||
SymbolType type = SymbolTypeInference.inferType(programScope, new AssignmentRValue(assignment));
|
||||
setInferedType(program, assignment, symbol, type);
|
||||
// If the type is an array or a string the symbol is constant
|
||||
|
@ -48,10 +48,10 @@ byte myprintf(byte *dst, byte *str, word w1, word w2, word w3) {
|
||||
if (bTrailing != 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = ' ';
|
||||
} else if (b == 'x' || b == 'X'){ // hex
|
||||
b = ((byte)w >> 4) & 0xF;
|
||||
dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b;
|
||||
dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
|
||||
// "('a' - 10)" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/184 [FIXED]
|
||||
// (b < 10 ? '0' : 0x57) not supported
|
||||
b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b;
|
||||
b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
|
||||
}
|
||||
bFormat = 0;
|
||||
continue;
|
||||
|
@ -3,6 +3,6 @@
|
||||
void main() {
|
||||
const byte* screen = 0x400;
|
||||
for(byte i: 0..10) {
|
||||
screen[i] = (i<5?0x57ub:'0')+i;
|
||||
screen[i] = (i<5?0x57:'0')+i;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user