diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 577463f7f..eb8f14abf 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -268,6 +268,7 @@ public class Compiler { optimizations.add(new Pass2ConstantCallPointerIdentification(program)); optimizations.add(new Pass2SizeOfSimplification(program)); optimizations.add(new Pass2InlineDerefIdx(program)); + optimizations.add(new Pass2InlineCast(program)); optimizations.add(new Pass2DeInlineWordDerefIdx(program)); optimizations.add(new PassNCastSimplification(program)); pass2Execute(optimizations); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java index bf197e32e..caf298e42 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java @@ -228,13 +228,21 @@ public class AsmFragmentInstanceSpecFactory { public String bind(Value value, SymbolType castType) { if(value instanceof CastValue) { - CastValue castVal = (CastValue) value; - SymbolType toType = castVal.getToType(); + CastValue cast = (CastValue) value; + SymbolType toType = cast.getToType(); OperatorUnary castUnary = Operators.getCastUnary(toType); - return getOperatorFragmentName(castUnary) + bind(castVal.getValue()); + RValue castValue = cast.getValue(); + SymbolType castValueType = SymbolTypeInference.inferType(this.program.getScope(), castValue); + if(castValueType.getSizeBytes()==toType.getSizeBytes()) { + return bind(castValue, toType); + } else { + return getOperatorFragmentName(castUnary) + bind(castValue); + } } else if(value instanceof ConstantCastValue) { ConstantCastValue castVal = (ConstantCastValue) value; if(castType==null) { + // TODO: If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff ) + return bind(castVal.getValue(), castVal.getToType()); } else { return bind(castVal.getValue(), castType); diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java index 6326a145b..b82e23e76 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java @@ -185,9 +185,9 @@ public class SymbolTypeConversion { public static boolean assignmentCastNeeded(SymbolType lValueType, SymbolType rValueType) { if(lValueType.equals(rValueType)) return false; - else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer) + else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(((SymbolTypePointer) rValueType).getElementType())) return false; - else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType)) + else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) return false; else return true; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java new file mode 100644 index 000000000..2ba632bed --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java @@ -0,0 +1,39 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.operators.OperatorCast; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.CastValue; + +/** Identify unary casts */ +public class Pass2InlineCast extends Pass2SsaOptimization { + + public Pass2InlineCast(Program program) { + super(program); + } + + @Override + public boolean step() { + boolean optimized = false; + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementAssignment) { + StatementAssignment assignment = (StatementAssignment) statement; + if(assignment.getrValue1()==null && assignment.getOperator() instanceof OperatorCast) { + SymbolType toType = ((OperatorCast) assignment.getOperator()).getToType(); + assignment.setrValue2(new CastValue(toType, assignment.getrValue2())); + assignment.setOperator(null); + getLog().append("Inlining cast "+assignment.toString(getProgram(), false)); + optimized = true; + } + } + } + } + return optimized; + } + + +} diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 66978362f..ec6380462 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -117,7 +117,7 @@ public class TestPrograms { @Test public void testNumberType() throws IOException, URISyntaxException { - compileAndCompare("number-type"); + compileAndCompare("number-type", log()); } @Test @@ -333,7 +333,7 @@ public class TestPrograms { @Test public void testPointerCast2() throws IOException, URISyntaxException { - compileAndCompare("pointer-cast-2", log()); + compileAndCompare("pointer-cast-2"); } @Test diff --git a/src/test/kc/number-type.kc b/src/test/kc/number-type.kc index 74f270661..2ce2a2ca2 100644 --- a/src/test/kc/number-type.kc +++ b/src/test/kc/number-type.kc @@ -3,25 +3,25 @@ void main() { testBytes(); - testSBytes(); + //testSBytes(); } void testBytes() { // Constant values resolvable to bytes const byte* SCREEN = 0x0400; byte idx = 0; - SCREEN[idx++] = 12; - SCREEN[idx++] = 6+6; - SCREEN[idx++] = 18-6; - SCREEN[idx++] = 1812-1800; - SCREEN[idx++] = 1+2+3+6; - SCREEN[idx++] = 2*6; - SCREEN[idx++] = 3<<2; - SCREEN[idx++] = 24>>1; - SCREEN[idx++] = 15&28; - SCREEN[idx++] = 4|8; - SCREEN[idx++] = 5^9; - SCREEN[idx++] = (2+2)*(15/5); + //SCREEN[idx++] = 12; + //SCREEN[idx++] = 6+6; + //SCREEN[idx++] = 18-6; + //SCREEN[idx++] = 1812-1800; + //SCREEN[idx++] = 1+2+3+6; + //SCREEN[idx++] = 2*6; + //SCREEN[idx++] = 3<<2; + //SCREEN[idx++] = 24>>1; + //SCREEN[idx++] = 15&28; + //SCREEN[idx++] = 4|8; + //SCREEN[idx++] = 5^9; + //SCREEN[idx++] = (2+2)*(15/5); SCREEN[idx++] = (byte)(4096+12); }