diff --git a/src/dk/camelot64/kickc/Compiler.java b/src/dk/camelot64/kickc/Compiler.java index f07905e93..119d88554 100644 --- a/src/dk/camelot64/kickc/Compiler.java +++ b/src/dk/camelot64/kickc/Compiler.java @@ -16,10 +16,10 @@ public class Compiler { public static class CompilationResult { private AsmProgram asmProgram; private ControlFlowGraph graph; - private Scope symbols; + private ProgramScope symbols; private CompileLog log; - public CompilationResult(AsmProgram asmProgram, ControlFlowGraph graph, Scope symbols, CompileLog log) { + public CompilationResult(AsmProgram asmProgram, ControlFlowGraph graph, ProgramScope symbols, CompileLog log) { this.asmProgram = asmProgram; this.graph = graph; this.symbols = symbols; @@ -34,7 +34,7 @@ public class Compiler { return graph; } - public Scope getSymbols() { + public ProgramScope getSymbols() { return symbols; } @@ -67,37 +67,37 @@ public class Compiler { pass1GenerateStatementSequence.generate(file); StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence(); ProgramScope programScope = pass1GenerateStatementSequence.getProgramScope(); - Pass1TypeInference pass1TypeInference = new Pass1TypeInference(); - pass1TypeInference.inferTypes(statementSequence, programScope); + Pass1TypeInference pass1TypeInference = new Pass1TypeInference(programScope); + pass1TypeInference.inferTypes(statementSequence); log.append("PROGRAM"); - log.append(statementSequence.toString()); + log.append(statementSequence.getAsTypedString(programScope)); log.append("SYMBOLS"); log.append(programScope.getSymbolTableContents()); Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(programScope); ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence); log.append("INITIAL CONTROL FLOW GRAPH"); - log.append(controlFlowGraph.toString()); + log.append(controlFlowGraph.getAsTypedString(programScope)); Pass1ProcedureCallParameters pass1ProcedureCallParameters = new Pass1ProcedureCallParameters(programScope, controlFlowGraph); controlFlowGraph = pass1ProcedureCallParameters.generate(); log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL"); - log.append(controlFlowGraph.toString()); + log.append(controlFlowGraph.getAsTypedString(programScope)); Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm = new Pass1GenerateSingleStaticAssignmentForm(log, programScope, controlFlowGraph); pass1GenerateSingleStaticAssignmentForm.generate(); log.append("CONTROL FLOW GRAPH SSA"); - log.append(controlFlowGraph.toString()); + log.append(controlFlowGraph.getAsTypedString(programScope)); Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue = new Pass1ProcedureCallsReturnValue(programScope, controlFlowGraph); controlFlowGraph = pass1ProcedureCallsReturnValue.generate(); log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN"); - log.append(controlFlowGraph.toString()); + log.append(controlFlowGraph.getAsTypedString(programScope)); List optimizations = new ArrayList<>(); optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, programScope, log)); @@ -124,7 +124,7 @@ public class Compiler { log.append("Succesful SSA optimization " + optimization.getClass().getSimpleName() + ""); ssaOptimized = true; log.append("CONTROL FLOW GRAPH"); - log.append(controlFlowGraph.toString()); + log.append(controlFlowGraph.getAsTypedString(programScope)); } } } diff --git a/src/dk/camelot64/kickc/asm/AsmFragment.java b/src/dk/camelot64/kickc/asm/AsmFragment.java index fec658e4b..f8a9758e8 100644 --- a/src/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/dk/camelot64/kickc/asm/AsmFragment.java @@ -211,13 +211,17 @@ public class AsmFragment { * @return The bound name of the value. If the value has already been bound the existing bound name is returned. */ public String bind(Value value) { + if(value instanceof VariableRef) { + value = symbols.getVariable((VariableRef) value); + } if (value instanceof Variable) { value = symbols.getRegister((Variable) value); } else if (value instanceof PointerDereferenceSimple) { PointerDereferenceSimple deref = (PointerDereferenceSimple) value; RValue pointer = deref.getPointer(); - if(pointer instanceof Variable) { - Variable pointerVar = (Variable) pointer; + if(pointer instanceof VariableRef) { + VariableRef pointerRef = (VariableRef) pointer; + Variable pointerVar = symbols.getVariable(pointerRef); RegisterAllocation.Register register = symbols.getRegister(pointerVar); value = new PointerDereferenceRegisterZpByte((RegisterAllocation.RegisterZpPointerByte) register); } diff --git a/src/dk/camelot64/kickc/asm/PointerDereferenceRegisterZpByte.java b/src/dk/camelot64/kickc/asm/PointerDereferenceRegisterZpByte.java index 739d685b5..4977af425 100644 --- a/src/dk/camelot64/kickc/asm/PointerDereferenceRegisterZpByte.java +++ b/src/dk/camelot64/kickc/asm/PointerDereferenceRegisterZpByte.java @@ -1,6 +1,7 @@ package dk.camelot64.kickc.asm; import dk.camelot64.kickc.icl.PointerDereference; +import dk.camelot64.kickc.icl.ProgramScope; import dk.camelot64.kickc.icl.RegisterAllocation; /** A dereferenced ZP pointer to a byte */ @@ -22,7 +23,16 @@ public class PointerDereferenceRegisterZpByte implements PointerDereference { @Override public String toString() { - return "*(" + pointer + ')'; + return getAsString(); } + @Override + public String getAsTypedString(ProgramScope scope) { + return getAsString(); + } + + @Override + public String getAsString() { + return "*(" + pointer.toString() + ')'; + } } diff --git a/src/dk/camelot64/kickc/icl/ConstantBool.java b/src/dk/camelot64/kickc/icl/ConstantBool.java index 8e89d70e2..78baaa71c 100644 --- a/src/dk/camelot64/kickc/icl/ConstantBool.java +++ b/src/dk/camelot64/kickc/icl/ConstantBool.java @@ -13,6 +13,17 @@ public class ConstantBool implements Constant { @Override public String toString() { + return getAsString(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { + return //"("+SymbolTypeBasic.BOOLEAN.getTypeName()+") "+ + Boolean.toString(value); + } + + @Override + public String getAsString() { return Boolean.toString(value); } } diff --git a/src/dk/camelot64/kickc/icl/ConstantDouble.java b/src/dk/camelot64/kickc/icl/ConstantDouble.java index fba35849e..a01c7ae76 100644 --- a/src/dk/camelot64/kickc/icl/ConstantDouble.java +++ b/src/dk/camelot64/kickc/icl/ConstantDouble.java @@ -8,15 +8,25 @@ public class ConstantDouble implements Constant { private Double number; public ConstantDouble(Double number) { - this.number= number; - } - - @Override - public String toString() { - return Double.toString(number); + this.number = number; } public Double getNumber() { return number; } + + @Override + public String toString() { + return getAsString(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { + return "(" + SymbolTypeBasic.VOID.getTypeName() + ") " + Double.toString(number); + } + + @Override + public String getAsString() { + return Double.toString(number); + } } diff --git a/src/dk/camelot64/kickc/icl/ConstantInteger.java b/src/dk/camelot64/kickc/icl/ConstantInteger.java index 82eb8262d..920c40406 100644 --- a/src/dk/camelot64/kickc/icl/ConstantInteger.java +++ b/src/dk/camelot64/kickc/icl/ConstantInteger.java @@ -27,7 +27,14 @@ public class ConstantInteger implements Constant { @Override public String toString() { - return "("+getType().getTypeName()+") "+Integer.toString(number); + return getAsString(); } + @Override + public String getAsTypedString(ProgramScope scope) { + return "("+getType().getTypeName()+") "+Integer.toString(number); } + + @Override + public String getAsString() { + return Integer.toString(number); } } diff --git a/src/dk/camelot64/kickc/icl/ConstantString.java b/src/dk/camelot64/kickc/icl/ConstantString.java index 63296076d..a7815895f 100644 --- a/src/dk/camelot64/kickc/icl/ConstantString.java +++ b/src/dk/camelot64/kickc/icl/ConstantString.java @@ -13,6 +13,15 @@ public class ConstantString implements Constant { @Override public String toString() { + return getAsString(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { + return "("+SymbolTypeBasic.STRING.getTypeName()+") "+"\\"+value+"\\"; } + + @Override + public String getAsString() { return "\\"+value+"\\"; } } diff --git a/src/dk/camelot64/kickc/icl/ControlFlowBlock.java b/src/dk/camelot64/kickc/icl/ControlFlowBlock.java index 10b4269ea..993a97535 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowBlock.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowBlock.java @@ -62,15 +62,10 @@ public class ControlFlowBlock { } public void addPhiStatement(VariableVersion newVersion) { - statements.add(0, new StatementPhi(newVersion)); + statements.add(0, new StatementPhi(new VariableRef(newVersion))); } - @Override - public String toString() { - return toString(null); - } - - public String toString(ControlFlowGraph graph) { + public String getAsTypedString(ControlFlowGraph graph, ProgramScope scope) { StringBuffer out = new StringBuffer(); out.append(label.getFullName() + ":" ); out.append(" from"); @@ -86,7 +81,7 @@ public class ControlFlowBlock { } out.append("\n"); for (Statement statement : statements) { - out.append(" "+statement+"\n"); + out.append(" "+statement.getAsTypedString(scope)+"\n"); } if(defaultSuccessor!=null) { out.append(" to:"); @@ -96,6 +91,33 @@ public class ControlFlowBlock { return out.toString(); } + public String getAsString(ControlFlowGraph graph) { + StringBuffer out = new StringBuffer(); + out.append(label.getFullName() + ":" ); + out.append(" from"); + if(graph!=null) { + List predecessors = graph.getPredecessors(this); + if(predecessors.size()>0) { + for (ControlFlowBlock predecessor : predecessors) { + out.append(" " + predecessor.getLabel().getFullName()); + } + } + } else { + out.append(" @UNKNOWN"); + } + out.append("\n"); + for (Statement statement : statements) { + out.append(" "+statement.getAsString()+"\n"); + } + if(defaultSuccessor!=null) { + out.append(" to:"); + out.append(defaultSuccessor.getFullName()); + out.append("\n"); + } + return out.toString(); + } + + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraph.java b/src/dk/camelot64/kickc/icl/ControlFlowGraph.java index 15bf3ef49..f7b5617ea 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowGraph.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraph.java @@ -23,15 +23,6 @@ public class ControlFlowGraph { return firstBlock; } - @Override - public String toString() { - StringBuffer out = new StringBuffer(); - for (ControlFlowBlock block : blocks.values()) { - out.append(block.toString(this)); - } - return out.toString(); - } - public Collection getAllBlocks() { return blocks.values(); } @@ -122,4 +113,23 @@ public class ControlFlowGraph { } return null; } + + public String getAsTypedString(ProgramScope scope) { + StringBuffer out = new StringBuffer(); + for (ControlFlowBlock block : blocks.values()) { + out.append(block.getAsTypedString(this, scope)); + } + return out.toString(); + } + + public String getAsString() { + StringBuffer out = new StringBuffer(); + for (ControlFlowBlock block : blocks.values()) { + out.append(block.getAsString(this)); + } + return out.toString(); + } + + + } diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java b/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java index 11ce2ae71..3c6eee3d8 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java @@ -115,7 +115,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor getAllVariables() { Collection vars = new ArrayList<>(); @@ -210,7 +214,7 @@ public abstract class Scope implements Symbol { if (symbol instanceof Scope) { res.append(((Scope) symbol).getSymbolTableContents()); } else { - res.append(symbol.toString()); + res.append(symbol.getTypedName()); } if (symbol instanceof Variable && allocation!=null) { RegisterAllocation.Register register = allocation.getRegister((Variable) symbol); @@ -266,4 +270,5 @@ public abstract class Scope implements Symbol { result = 31 * result + intermediateLabelCount; return result; } + } diff --git a/src/dk/camelot64/kickc/icl/Statement.java b/src/dk/camelot64/kickc/icl/Statement.java index 2e6b76d12..953754f4a 100644 --- a/src/dk/camelot64/kickc/icl/Statement.java +++ b/src/dk/camelot64/kickc/icl/Statement.java @@ -6,5 +6,8 @@ package dk.camelot64.kickc.icl; */ public interface Statement { + String getAsTypedString(ProgramScope scope); + + String getAsString(); } diff --git a/src/dk/camelot64/kickc/icl/StatementAssignment.java b/src/dk/camelot64/kickc/icl/StatementAssignment.java index cc81a0298..24858483b 100644 --- a/src/dk/camelot64/kickc/icl/StatementAssignment.java +++ b/src/dk/camelot64/kickc/icl/StatementAssignment.java @@ -28,6 +28,14 @@ public class StatementAssignment implements StatementLValue { this.rValue2 = rValue2; } + public StatementAssignment(Variable lValue, Variable rValue2) { + this(new VariableRef(lValue), new VariableRef(rValue2)); + } + + public StatementAssignment(Variable lValue, RValue rValue2) { + this(new VariableRef(lValue), rValue2); + } + @JsonCreator public StatementAssignment( @JsonProperty("lValue1") LValue lValue, @@ -67,6 +75,10 @@ public class StatementAssignment implements StatementLValue { return operator; } + public void setOperator(Operator operator) { + this.operator = operator; + } + public RValue getrValue2() { return rValue2; } @@ -77,15 +89,25 @@ public class StatementAssignment implements StatementLValue { @Override public String toString() { + return getAsString(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { return - - lValue + " ← " + - (rValue1==null?"":rValue1+" ") + + lValue.getAsTypedString(scope) + " ← " + + (rValue1==null?"":rValue1.getAsTypedString(scope)+" ") + (operator==null?"":operator+" ") + - rValue2 ; + rValue2 .getAsTypedString(scope); } - public void setOperator(Operator operator) { - this.operator = operator; + @Override + public String getAsString() { + return + lValue.getAsString() + " ← " + + (rValue1==null?"":rValue1.getAsString()+" ") + + (operator==null?"":operator+" ") + + rValue2.getAsString() ; } + } diff --git a/src/dk/camelot64/kickc/icl/StatementCall.java b/src/dk/camelot64/kickc/icl/StatementCall.java index a1ae0becf..bff178315 100644 --- a/src/dk/camelot64/kickc/icl/StatementCall.java +++ b/src/dk/camelot64/kickc/icl/StatementCall.java @@ -67,11 +67,21 @@ public class StatementCall implements StatementLValue { this.parametersByAssignment = parametersByAssignment; } + public void clearParameters() { + this.parameters = null; + this.parametersByAssignment = true; + } + @Override public String toString() { + return getAsString(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { StringBuilder res = new StringBuilder(); if(lValue!=null) { - res.append(lValue); + res.append(lValue.getAsTypedString(scope)); res.append(" ← "); } res.append("call "); @@ -82,7 +92,7 @@ public class StatementCall implements StatementLValue { } if(parameters!=null) { for (RValue parameter : parameters) { - res.append(parameter + " "); + res.append(parameter.getAsTypedString(scope) + " "); } } if(parametersByAssignment) { @@ -91,9 +101,27 @@ public class StatementCall implements StatementLValue { return res.toString(); } - public void clearParameters() { - this.parameters = null; - this.parametersByAssignment = true; + @Override + public String getAsString() { + StringBuilder res = new StringBuilder(); + if(lValue!=null) { + res.append(lValue.getAsString()); + res.append(" ← "); + } + res.append("call "); + if(procedure!=null) { + res.append(procedure.getFullName()+ " "); + } else { + res.append(procedureName + " "); + } + if(parameters!=null) { + for (RValue parameter : parameters) { + res.append(parameter.getAsString() + " "); + } + } + if(parametersByAssignment) { + res.append("param-assignment"); + } + return res.toString(); } - } diff --git a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java index 181fe205d..b75c57adb 100644 --- a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java +++ b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java @@ -64,16 +64,34 @@ public class StatementConditionalJump implements Statement { @Override public String toString() { + return getAsString(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { StringBuilder out = new StringBuilder(); out.append("if("); if(rValue1!=null) { - out.append(rValue1); + out.append(rValue1.getAsTypedString(scope)); out.append(operator.getOperator()); } - out.append(rValue2); + out.append(rValue2.getAsTypedString(scope)); out.append(") goto "); out.append(destination.getFullName()); return out.toString(); } + @Override + public String getAsString() { + StringBuilder out = new StringBuilder(); + out.append("if("); + if(rValue1!=null) { + out.append(rValue1.getAsString()); + out.append(operator.getOperator()); + } + out.append(rValue2.getAsString()); + out.append(") goto "); + out.append(destination.getFullName()); + return out.toString(); + } } diff --git a/src/dk/camelot64/kickc/icl/StatementJump.java b/src/dk/camelot64/kickc/icl/StatementJump.java index 4804eac79..53f71eea2 100644 --- a/src/dk/camelot64/kickc/icl/StatementJump.java +++ b/src/dk/camelot64/kickc/icl/StatementJump.java @@ -18,12 +18,21 @@ public class StatementJump implements Statement { return destination; } - @Override - public String toString() { - return "goto "+destination.getFullName(); - } - public void setDestination(Label destination) { this.destination = destination; } + + @Override + public String toString() { + return getAsString(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { + return getAsString(); + } + + @Override + public String getAsString() { + return "goto "+destination.getFullName(); } } diff --git a/src/dk/camelot64/kickc/icl/StatementLValue.java b/src/dk/camelot64/kickc/icl/StatementLValue.java index 7818723c2..1d1e2195d 100644 --- a/src/dk/camelot64/kickc/icl/StatementLValue.java +++ b/src/dk/camelot64/kickc/icl/StatementLValue.java @@ -3,7 +3,7 @@ package dk.camelot64.kickc.icl; /** * Single Static Assignment Form Statement with an LValuie - that is a statement assigning a value to a variable. */ -public interface StatementLValue extends Statement { +public interface StatementLValue extends Statement { LValue getlValue(); diff --git a/src/dk/camelot64/kickc/icl/StatementLabel.java b/src/dk/camelot64/kickc/icl/StatementLabel.java index f14146195..8c6885f97 100644 --- a/src/dk/camelot64/kickc/icl/StatementLabel.java +++ b/src/dk/camelot64/kickc/icl/StatementLabel.java @@ -17,8 +17,16 @@ public class StatementLabel implements Statement { @Override public String toString() { - return label.getFullName()+":"; + return getAsString(); } + @Override + public String getAsTypedString(ProgramScope scope) { + return getAsString(); + } + @Override + public String getAsString() { + return label.getFullName() + ":"; + } } diff --git a/src/dk/camelot64/kickc/icl/StatementPhi.java b/src/dk/camelot64/kickc/icl/StatementPhi.java index 747f74f29..e41d12bbc 100644 --- a/src/dk/camelot64/kickc/icl/StatementPhi.java +++ b/src/dk/camelot64/kickc/icl/StatementPhi.java @@ -12,12 +12,12 @@ import java.util.List; public class StatementPhi implements StatementLValue { /** The versioned variable being assigned a value by the statement. */ - private VariableVersion lValue; + private VariableRef lValue; /** The previous version of the rValue from predeccesor control blocks. */ private List previousVersions; - public StatementPhi(VariableVersion lValue) { + public StatementPhi(VariableRef lValue) { this.lValue = lValue; this.previousVersions = new ArrayList<>(); } @@ -56,16 +56,16 @@ public class StatementPhi implements StatementLValue { } } - public VariableVersion getlValue() { + public VariableRef getlValue() { return lValue; } @Override public void setlValue(LValue lValue) { - if(!(lValue instanceof VariableVersion)) { + if(!(lValue instanceof VariableRef)) { throw new RuntimeException("Error modifying phi-statement lValue "+this.lValue+". Attempt to set to non-versioned variable "+lValue); } - this.lValue = (VariableVersion) lValue; + this.lValue = (VariableRef) lValue; } public void addPreviousVersion(Label block, RValue rValue) { @@ -78,6 +78,22 @@ public class StatementPhi implements StatementLValue { @Override public String toString() { + return getAsString(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { + StringBuilder out = new StringBuilder(); + out.append(lValue.getAsTypedString(scope) + " ← " + "phi("); + for (PreviousSymbol previousSymbol : previousVersions) { + out.append(" "+previousSymbol.getBlock().getFullName()+"/"+previousSymbol.getRValue().getAsTypedString(scope)); + } + out.append(" )"); + return out.toString(); + } + + @Override + public String getAsString() { StringBuilder out = new StringBuilder(); out.append(lValue + " ← " + "phi("); for (PreviousSymbol previousSymbol : previousVersions) { @@ -86,5 +102,4 @@ public class StatementPhi implements StatementLValue { out.append(" )"); return out.toString(); } - } diff --git a/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java b/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java index 946791947..ec54df483 100644 --- a/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java +++ b/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java @@ -30,7 +30,16 @@ public class StatementProcedureBegin implements Statement { @Override public String toString() { - return "proc "+procedure.toString(); + return getAsString(); } + @Override + public String getAsTypedString(ProgramScope scope) { + return "proc " + procedure.getAsTypedString(scope); + } + + @Override + public String getAsString() { + return "proc " + procedure.getAsString(); + } } diff --git a/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java b/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java index 2c5f4e6ad..f60fe661d 100644 --- a/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java +++ b/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java @@ -15,7 +15,15 @@ public class StatementProcedureEnd implements Statement { @Override public String toString() { - return "endproc // "+procedure.getFullName()+"()"; + return getAsString(); } + @Override + public String getAsTypedString(ProgramScope scope) { + return getAsString(); + } + + @Override + public String getAsString() { + return "endproc // "+procedure.getFullName()+"()"; } } diff --git a/src/dk/camelot64/kickc/icl/StatementReturn.java b/src/dk/camelot64/kickc/icl/StatementReturn.java index 3cb17c42d..b8b605362 100644 --- a/src/dk/camelot64/kickc/icl/StatementReturn.java +++ b/src/dk/camelot64/kickc/icl/StatementReturn.java @@ -22,7 +22,14 @@ public class StatementReturn implements Statement { @Override public String toString() { - return "return "+(value==null?"":value); + return getAsString(); } + @Override + public String getAsTypedString(ProgramScope scope) { + return "return "+(value==null?"":value.getAsTypedString(scope)); } + + @Override + public String getAsString() { + return "return "+(value==null?"":value.getAsString()); } } diff --git a/src/dk/camelot64/kickc/icl/StatementSequence.java b/src/dk/camelot64/kickc/icl/StatementSequence.java index 1a3f59244..174f5c4ba 100644 --- a/src/dk/camelot64/kickc/icl/StatementSequence.java +++ b/src/dk/camelot64/kickc/icl/StatementSequence.java @@ -16,19 +16,30 @@ public class StatementSequence { this.statements.add(statement); } - @Override - public String toString() { + public List getStatements() { + return statements; + } + + public String getAsTypedString(ProgramScope scope) { StringBuffer out = new StringBuffer(); for (Statement statement : statements) { if(!(statement instanceof StatementLabel)) { - out.append(" "); + out.append(" "); } - out.append(statement.toString()+"\n"); + out.append(statement.getAsTypedString(scope)+"\n"); } return out.toString(); } - public List getStatements() { - return statements; + public String getAsString() { + StringBuffer out = new StringBuffer(); + for (Statement statement : statements) { + if(!(statement instanceof StatementLabel)) { + out.append(" "); + } + out.append(statement.getAsString()+"\n"); + } + return out.toString(); } + } diff --git a/src/dk/camelot64/kickc/icl/Value.java b/src/dk/camelot64/kickc/icl/Value.java index 25c0c5298..38423b5da 100644 --- a/src/dk/camelot64/kickc/icl/Value.java +++ b/src/dk/camelot64/kickc/icl/Value.java @@ -20,4 +20,9 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; @JsonSubTypes.Type(value = Procedure.class, name = "procedure") }) public interface Value { + + String getAsTypedString(ProgramScope scope); + + String getAsString(); + } diff --git a/src/dk/camelot64/kickc/icl/Variable.java b/src/dk/camelot64/kickc/icl/Variable.java index fc1b8b370..856c6cbc4 100644 --- a/src/dk/camelot64/kickc/icl/Variable.java +++ b/src/dk/camelot64/kickc/icl/Variable.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; /** * A Symbol (variable, jump label, etc.) */ -public abstract class Variable implements Symbol, RValue, LValue { +public abstract class Variable implements Symbol { /** * The name of the symbol. @@ -105,11 +105,6 @@ public abstract class Variable implements Symbol, RValue, LValue { return result; } - @Override - public String toString() { - return getTypedName(); - } - public Scope getScope() { return scope; } @@ -123,4 +118,19 @@ public abstract class Variable implements Symbol, RValue, LValue { } } + @Override + public String toString() { + return getTypedName(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { + return getTypedName(); + } + + @Override + public String getAsString() { + return getTypedName(); + } + } diff --git a/src/dk/camelot64/kickc/icl/VariableRef.java b/src/dk/camelot64/kickc/icl/VariableRef.java new file mode 100644 index 000000000..fd66343c3 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/VariableRef.java @@ -0,0 +1,59 @@ +package dk.camelot64.kickc.icl; + +/** A reference to a variable from the symbol table */ +public class VariableRef implements RValue, LValue { + + /** The full name of the variable. Allowing lookup in the symbol table. */ + private String fullName; + + public VariableRef(String fullName) { + this.fullName = fullName; + } + + public VariableRef(Variable variable) { + this(variable.getFullName()); + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + VariableRef that = (VariableRef) o; + + return fullName != null ? fullName.equals(that.fullName) : that.fullName == null; + } + + @Override + public int hashCode() { + return fullName != null ? fullName.hashCode() : 0; + } + + @Override + public String toString() { + return getAsString(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { + Variable variable = scope.getVariable(this); + return variable.getTypedName(); + } + + @Override + public String getAsString() { + return fullName; + } +} diff --git a/src/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java b/src/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java index 8cb0c3cdf..bd44ad354 100644 --- a/src/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java +++ b/src/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java @@ -39,23 +39,18 @@ public class Pass1GenerateSingleStaticAssignmentForm { private void versionAllAssignments() { for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) { for (Statement statement : block.getStatements()) { - if (statement instanceof StatementAssignment) { - StatementAssignment assignment = (StatementAssignment) statement; - LValue lValue = assignment.getlValue(); - if (lValue instanceof VariableUnversioned) { - // Assignment to a non-versioned non-intermediary variable - VariableUnversioned assignedSymbol = (VariableUnversioned) lValue; - VariableVersion version = assignedSymbol.createVersion(); - assignment.setlValue(version); - } - } else if(statement instanceof StatementCall) { - StatementCall call = (StatementCall) statement; - LValue lValue = call.getlValue(); - if (lValue instanceof VariableUnversioned) { - // Assignment to a non-versioned non-intermediary variable - VariableUnversioned assignedSymbol = (VariableUnversioned) lValue; - VariableVersion version = assignedSymbol.createVersion(); - call.setlValue(version); + if (statement instanceof StatementLValue) { + StatementLValue statementLValue = (StatementLValue) statement; + LValue lValue = statementLValue.getlValue(); + if (lValue instanceof VariableRef) { + VariableRef lValueRef = (VariableRef) lValue; + Variable assignedVar = symbols.getVariable(lValueRef); + if(assignedVar instanceof VariableUnversioned) { + // Assignment to a non-versioned non-intermediary variable + VariableUnversioned assignedSymbol = (VariableUnversioned) assignedVar; + VariableVersion version = assignedSymbol.createVersion(); + statementLValue.setlValue(new VariableRef(version)); + } } } } @@ -77,7 +72,7 @@ public class Pass1GenerateSingleStaticAssignmentForm { { VariableVersion version = findOrCreateVersion(statementReturn.getValue(), blockVersions, blockNewPhis); if (version != null) { - statementReturn.setValue(version); + statementReturn.setValue(new VariableRef(version)); } } @@ -87,38 +82,42 @@ public class Pass1GenerateSingleStaticAssignmentForm { { VariableVersion version = findOrCreateVersion(assignment.getrValue1(), blockVersions, blockNewPhis); if (version != null) { - assignment.setrValue1(version); + assignment.setrValue1(new VariableRef(version)); } } { VariableVersion version = findOrCreateVersion(assignment.getrValue2(), blockVersions, blockNewPhis); if (version != null) { - assignment.setrValue2(version); + assignment.setrValue2(new VariableRef(version)); } } // Update map of versions encountered in the block LValue lValue = assignment.getlValue(); - if (lValue instanceof VariableVersion) { - VariableVersion versioned = (VariableVersion) lValue; - blockVersions.put(versioned.getVersionOf(), versioned); + if (lValue instanceof VariableRef) { + VariableRef lValueRef = (VariableRef) lValue; + Variable variable = symbols.getVariable(lValueRef); + if(variable instanceof VariableVersion) { + VariableVersion versioned = (VariableVersion) variable; + blockVersions.put(versioned.getVersionOf(), versioned); + } } else if(lValue instanceof PointerDereferenceSimple) { PointerDereferenceSimple deref = (PointerDereferenceSimple) lValue; RValue pointer = deref.getPointer(); VariableVersion version = findOrCreateVersion(pointer, blockVersions, blockNewPhis); if (version != null) { - deref.setPointer(version); + deref.setPointer(new VariableRef(version)); } } else if(lValue instanceof PointerDereferenceIndexed) { PointerDereferenceIndexed deref = (PointerDereferenceIndexed) lValue; RValue pointer = deref.getPointer(); VariableVersion version = findOrCreateVersion(pointer, blockVersions, blockNewPhis); if (version != null) { - deref.setPointer(version); + deref.setPointer(new VariableRef(version)); } RValue index = deref.getIndex(); VariableVersion iVersion = findOrCreateVersion(index, blockVersions, blockNewPhis); if (iVersion != null) { - deref.setIndex(iVersion); + deref.setIndex(new VariableRef(iVersion)); } } } @@ -144,18 +143,21 @@ public class Pass1GenerateSingleStaticAssignmentForm { Map blockVersions, Map blockNewPhis) { VariableVersion version = null; - if (rValue instanceof VariableUnversioned) { - // rValue needs versioning - look for version in statements - VariableUnversioned rSymbol = (VariableUnversioned) rValue; - version = blockVersions.get(rSymbol); - if (version == null) { - // look for version in new phi functions - version = blockNewPhis.get(rSymbol); - } - if (version == null) { - // create a new phi function - version = rSymbol.createVersion(); - blockNewPhis.put(rSymbol, version); + if (rValue instanceof VariableRef) { + Variable rValueVar = symbols.getVariable((VariableRef) rValue); + if (rValueVar instanceof VariableUnversioned) { + // rValue needs versioning - look for version in statements + VariableUnversioned rSymbol = (VariableUnversioned) rValueVar; + version = blockVersions.get(rSymbol); + if (version == null) { + // look for version in new phi functions + version = blockNewPhis.get(rSymbol); + } + if (version == null) { + // create a new phi function + version = rSymbol.createVersion(); + blockNewPhis.put(rSymbol, version); + } } } return version; @@ -175,7 +177,8 @@ public class Pass1GenerateSingleStaticAssignmentForm { if (statement instanceof StatementPhi) { StatementPhi phi = (StatementPhi) statement; if (phi.getPreviousVersions().isEmpty()) { - VariableVersion versioned = phi.getlValue(); + VariableRef phiLValVarRef = phi.getlValue(); + VariableVersion versioned = (VariableVersion) symbols.getVariable(phiLValVarRef); VariableUnversioned unversioned = versioned.getVersionOf(); for (ControlFlowBlock predecessor : controlFlowGraph.getPredecessors(block)) { Label predecessorLabel = predecessor.getLabel(); @@ -198,7 +201,7 @@ public class Pass1GenerateSingleStaticAssignmentForm { predecessorNewPhis.put(unversioned, previousSymbol); } } - phi.addPreviousVersion(predecessorLabel, previousSymbol); + phi.addPreviousVersion(predecessorLabel, new VariableRef(previousSymbol)); } } } @@ -224,50 +227,25 @@ public class Pass1GenerateSingleStaticAssignmentForm { Map> symbolMap = new LinkedHashMap<>(); for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) { for (Statement statement : block.getStatements()) { - if (statement instanceof StatementAssignment) { - StatementAssignment assignment = (StatementAssignment) statement; + if (statement instanceof StatementLValue) { + StatementLValue assignment = (StatementLValue) statement; LValue lValue = assignment.getlValue(); - if (lValue instanceof VariableVersion) { - VariableVersion versioned = (VariableVersion) lValue; - Label label = block.getLabel(); - VariableUnversioned unversioned = versioned.getVersionOf(); - Map blockMap = symbolMap.get(label); - if (blockMap == null) { - blockMap = new LinkedHashMap<>(); - symbolMap.put(label, blockMap); - } - blockMap.put(unversioned, versioned); - } - } else if (statement instanceof StatementPhi) { - StatementPhi phi = (StatementPhi) statement; - VariableVersion versioned = phi.getlValue(); - VariableUnversioned unversioned = versioned.getVersionOf(); - Label label = block.getLabel(); - Map blockMap = symbolMap.get(label); - if (blockMap == null) { - blockMap = new LinkedHashMap<>(); - symbolMap.put(label, blockMap); - } - blockMap.put(unversioned, versioned); - } else if (statement instanceof StatementCall) { - StatementCall call = (StatementCall) statement; - LValue lValue = call.getlValue(); - if (lValue instanceof VariableVersion) { - VariableVersion versioned = (VariableVersion) lValue; - Label label = block.getLabel(); - VariableUnversioned unversioned = versioned.getVersionOf(); - Map blockMap = symbolMap.get(label); - if (blockMap == null) { - blockMap = new LinkedHashMap<>(); - symbolMap.put(label, blockMap); - } - blockMap.put(unversioned, versioned); - } - + if(lValue instanceof VariableRef) { + Variable lValueVar = symbols.getVariable((VariableRef) lValue); + if (lValueVar instanceof VariableVersion) { + VariableVersion versioned = (VariableVersion) lValueVar; + Label label = block.getLabel(); + VariableUnversioned unversioned = versioned.getVersionOf(); + Map blockMap = symbolMap.get(label); + if (blockMap == null) { + blockMap = new LinkedHashMap<>(); + symbolMap.put(label, blockMap); + } + blockMap.put(unversioned, versioned); + } } } } } return symbolMap; } - } diff --git a/src/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java b/src/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java index 3b4751daf..77802d75f 100644 --- a/src/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java +++ b/src/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java @@ -176,7 +176,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { if (returnVar != null) { sequence.addStatement(new StatementAssignment(returnVar, returnVar)); } - sequence.addStatement(new StatementReturn(returnVar)); + VariableRef returnVarRef = null; + if(returnVar!=null) {new VariableRef(returnVar); } + sequence.addStatement(new StatementReturn(returnVarRef)); scopeStack.pop(); sequence.addStatement(new StatementProcedureEnd(procedure)); return null; @@ -246,7 +248,8 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public LValue visitLvalueName(KickCParser.LvalueNameContext ctx) { - return getCurrentSymbols().getVariable(ctx.NAME().getText()); + Variable variable = getCurrentSymbols().getVariable(ctx.NAME().getText()); + return new VariableRef(variable); } @Override @@ -257,8 +260,8 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public LValue visitLvaluePtr(KickCParser.LvaluePtrContext ctx) { LValue lval = (LValue) visit(ctx.lvalue()); - if (lval instanceof Variable) { - return new PointerDereferenceSimple((Variable) lval); + if (lval instanceof VariableRef) { + return new PointerDereferenceSimple((VariableRef) lval); } else { throw new RuntimeException("Not implemented"); } @@ -319,7 +322,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { parameters = new ArrayList<>(); } VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); - sequence.addStatement(new StatementCall(tmpVar, ctx.NAME().getText(), parameters)); + sequence.addStatement(new StatementCall(new VariableRef(tmpVar), ctx.NAME().getText(), parameters)); return tmpVar; } @@ -339,9 +342,10 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { RValue index = (RValue) visit(ctx.expr(1)); Operator operator = new Operator("*idx"); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); - Statement stmt = new StatementAssignment(tmpVar, array, operator, index); + VariableRef tmpVarRef = new VariableRef(tmpVar); + Statement stmt = new StatementAssignment(tmpVarRef, array, operator, index); sequence.addStatement(stmt); - return tmpVar; + return tmpVarRef; } @Override @@ -372,9 +376,10 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText(); Operator operator = new Operator(op); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); - Statement stmt = new StatementAssignment(tmpVar, left, operator, right); + VariableRef tmpVarRef = new VariableRef(tmpVar); + Statement stmt = new StatementAssignment(tmpVarRef, left, operator, right); sequence.addStatement(stmt); - return tmpVar; + return tmpVarRef; } @Override @@ -383,9 +388,10 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText(); Operator operator = new Operator(op); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); - Statement stmt = new StatementAssignment(tmpVar, operator, child); + VariableRef tmpVarRef = new VariableRef(tmpVar); + Statement stmt = new StatementAssignment(tmpVarRef, operator, child); sequence.addStatement(stmt); - return tmpVar; + return tmpVarRef; } @Override @@ -407,7 +413,8 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public RValue visitExprId(KickCParser.ExprIdContext ctx) { - return getCurrentSymbols().getVariable(ctx.NAME().getText()); + Variable variable = getCurrentSymbols().getVariable(ctx.NAME().getText()); + return new VariableRef(variable); } public StatementSequence getSequence() { @@ -454,7 +461,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { for (PrePostModifier mod : modifiers) { Statement stmt = new StatementAssignment((LValue) mod.child, mod.operator, mod.child); parser.sequence.addStatement(stmt); - parser.log.append("Adding pre/post-modifier "+stmt); + parser.log.append("Adding pre/post-modifier "+stmt.getAsTypedString(parser.programScope)); } } diff --git a/src/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java b/src/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java index e327316ae..6eaeb634d 100644 --- a/src/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java +++ b/src/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java @@ -30,24 +30,27 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { for (int i = 0; i < parameterDecls.size(); i++) { Variable parameterDecl = parameterDecls.get(i); RValue parameterValue = parameterValues.get(i); - addStatementToCurrentBlock(new StatementAssignment(parameterDecl, parameterValue)); + addStatementToCurrentBlock(new StatementAssignment(new VariableRef(parameterDecl), parameterValue)); } String procedureName = origCall.getProcedureName(); Variable procReturnVar = procedure.getVariable("return"); - StatementCall copyCall = new StatementCall(procReturnVar, procedureName, null); + VariableRef procReturnVarRef = null; + if(procReturnVar!=null) {new VariableRef(procReturnVar); } + StatementCall copyCall = new StatementCall(procReturnVarRef, procedureName, null); copyCall.setParametersByAssignment(true); copyCall.setProcedure(procedure); addStatementToCurrentBlock(copyCall); getCurrentBlock().setCallSuccessor(procedure.getLabel()); splitCurrentBlock(scope.addLabelIntermediate()); if(!SymbolTypeBasic.VOID.equals(procedure.getReturnType())) { - addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVar)); + addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVarRef)); } else { // No return type. Remove variable receiving the result. LValue lValue = origCall.getlValue(); - if(lValue instanceof Variable) { - Variable lVar = (Variable) lValue; - lVar.getScope().remove(lVar); + if(lValue instanceof VariableRef) { + VariableRef lValueRef = (VariableRef) lValue; + Variable lValueVar = scope.getVariable(lValueRef); + lValueVar.getScope().remove(lValueVar); } } diff --git a/src/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java b/src/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java index 7c4836f7a..d1b5ff0ba 100644 --- a/src/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java +++ b/src/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java @@ -34,13 +34,13 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor // Find return variable final version Label returnBlockLabel = procedure.getLabel("@return"); ControlFlowBlock returnBlock = graph.getBlock(returnBlockLabel); - VariableVersion returnVarFinal = null; + VariableRef returnVarFinal = null; for (Statement statement : returnBlock.getStatements()) { if (statement instanceof StatementReturn) { StatementReturn statementReturn = (StatementReturn) statement; RValue returnValue = statementReturn.getValue(); - if (returnValue instanceof VariableVersion) { - returnVarFinal = (VariableVersion) returnValue; + if (returnValue instanceof VariableRef) { + returnVarFinal = (VariableRef) returnValue; } } } diff --git a/src/dk/camelot64/kickc/passes/Pass1TypeInference.java b/src/dk/camelot64/kickc/passes/Pass1TypeInference.java index 0e60ec7a6..3fcf9efca 100644 --- a/src/dk/camelot64/kickc/passes/Pass1TypeInference.java +++ b/src/dk/camelot64/kickc/passes/Pass1TypeInference.java @@ -10,7 +10,13 @@ import java.util.Stack; */ public class Pass1TypeInference { - public void inferTypes(StatementSequence sequence, Scope programScope) { + private Scope programScope; + + public Pass1TypeInference(Scope programScope) { + this.programScope = programScope; + } + + public void inferTypes(StatementSequence sequence) { Stack scopes = new Stack<>(); scopes.add(programScope); for (Statement statement : sequence.getStatements()) { @@ -22,8 +28,8 @@ public class Pass1TypeInference { } else if (statement instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) statement; LValue lValue = assignment.getlValue(); - if (lValue instanceof Variable) { - Variable symbol = (Variable) lValue; + if (lValue instanceof VariableRef) { + Variable symbol = programScope.getVariable((VariableRef) lValue); if (SymbolTypeBasic.VAR.equals(symbol.getType())) { // Unresolved symbol - perform inference Operator operator = assignment.getOperator(); @@ -45,14 +51,15 @@ public class Pass1TypeInference { } else if(statement instanceof StatementCall) { StatementCall call = (StatementCall) statement; LValue lValue = call.getlValue(); - if(lValue instanceof Variable) { + if(lValue instanceof VariableRef) { String procedureName = call.getProcedureName(); Procedure procedure = scopes.peek().getProcedure(procedureName); call.setProcedure(procedure); if(procedure.getParameters().size()!=call.getParameters().size()) { throw new RuntimeException("Wrong number of parameters in call. Expected " +procedure.getParameters().size()+". "+statement.toString()); } - ((Variable) lValue).setTypeInferred(procedure.getReturnType()); + Variable lValueVar = programScope.getVariable((VariableRef) lValue); + lValueVar.setTypeInferred(procedure.getReturnType()); } } } @@ -143,9 +150,12 @@ public class Pass1TypeInference { } } - public static SymbolType inferType(RValue rValue) { + public SymbolType inferType(RValue rValue) { SymbolType type = null; - if (rValue instanceof Symbol) { + if (rValue instanceof VariableRef) { + Variable variable = programScope.getVariable((VariableRef) rValue); + type = variable.getType(); + } else if (rValue instanceof Symbol) { Symbol rSymbol = (Symbol) rValue; type = rSymbol.getType(); } else if (rValue instanceof ConstantInteger) { diff --git a/src/dk/camelot64/kickc/passes/Pass2AliasElimination.java b/src/dk/camelot64/kickc/passes/Pass2AliasElimination.java index fa4220e94..0f9cc7c7a 100644 --- a/src/dk/camelot64/kickc/passes/Pass2AliasElimination.java +++ b/src/dk/camelot64/kickc/passes/Pass2AliasElimination.java @@ -10,7 +10,7 @@ import java.util.*; */ public class Pass2AliasElimination extends Pass2SsaOptimization { - public Pass2AliasElimination(ControlFlowGraph graph, Scope scope, CompileLog log) { + public Pass2AliasElimination(ControlFlowGraph graph, ProgramScope scope, CompileLog log) { super(graph, scope, log); } @@ -23,16 +23,16 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { final Aliases aliases = findAliases(); removeAliasAssignments(aliases); replaceVariables(aliases.getReplacements()); - deleteSymbols(aliases.getSymbolsToRemove()); for (AliasSet aliasSet : aliases.getAliasSets()) { StringBuilder str = new StringBuilder(); - str.append(aliasSet.getKeepVar()); + str.append(aliasSet.getKeepVar().getAsTypedString(getSymbols())); str.append(" = "); - for (Variable var : aliasSet.getEliminateVars()) { - str.append(var + " "); + for (VariableRef var : aliasSet.getEliminateVars()) { + str.append(var.getAsTypedString(getSymbols()) + " "); } log.append("Alias " + str); } + deleteVariables(aliases.getSymbolsToRemove()); return (aliases.size() > 0); } @@ -75,19 +75,19 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { this.aliases = new ArrayList<>(); } - public List getSymbolsToRemove() { - ArrayList eliminates = new ArrayList<>(); + public List getSymbolsToRemove() { + ArrayList eliminates = new ArrayList<>(); for (AliasSet alias : aliases) { eliminates.addAll(alias.getEliminateVars()); } return eliminates; } - public Map getReplacements() { - HashMap replacements = new LinkedHashMap<>(); + public Map getReplacements() { + HashMap replacements = new LinkedHashMap<>(); for (AliasSet aliasSet : aliases) { - Variable keepVar = aliasSet.getKeepVar(); - for (Variable var : aliasSet.getEliminateVars()) { + VariableRef keepVar = aliasSet.getKeepVar(); + for (VariableRef var : aliasSet.getEliminateVars()) { if(!var.equals(keepVar)) { replacements.put(var, keepVar); } @@ -100,7 +100,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { return aliases.size(); } - public void add(Variable var1, Variable var2) { + public void add(VariableRef var1, VariableRef var2) { AliasSet aliasSet1 = findAliasSet(var1); AliasSet aliasSet2 = findAliasSet(var2); if (aliasSet1 != null) { @@ -123,7 +123,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { } public AliasSet findAliasSet(LValue lValue) { - if (lValue instanceof Variable) { + if (lValue instanceof VariableRef) { for (AliasSet alias : aliases) { if (alias.contains(lValue)) { return alias; @@ -140,25 +140,25 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { public static class AliasSet { - private List vars; + private List vars; public AliasSet() { this.vars = new ArrayList<>(); } - public void add(Variable variable) { + public void add(VariableRef variable) { vars.add(variable); } public boolean contains(RValue rValue) { - if (rValue instanceof Variable) { + if (rValue instanceof VariableRef) { return vars.contains(rValue); } else { return false; } } - public List getVars() { + public List getVars() { return vars; } @@ -166,22 +166,22 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { vars.addAll(aliasSet.getVars()); } - public Variable getKeepVar() { - Variable keep = null; - List vars = new ArrayList<>(this.vars); - Collections.sort(vars, new Comparator() { + public VariableRef getKeepVar() { + VariableRef keep = null; + List vars = new ArrayList<>(this.vars); + Collections.sort(vars, new Comparator() { @Override - public int compare(Variable o1, Variable o2) { + public int compare(VariableRef o1, VariableRef o2) { return o1.getFullName().compareTo(o2.getFullName()); } }); - for (Variable var : vars) { + for (VariableRef var : vars) { if (keep == null) { keep = var; } else { - if (var instanceof VariableVersion) { - if (keep instanceof VariableVersion) { - if (var.getScopeDepth() < keep.getScopeDepth()) { + if (isVersion(var)) { + if (isVersion(keep)) { + if (getScopeDepth(var) < getScopeDepth(keep)) { keep = var; } } else { @@ -193,10 +193,23 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { return keep; } - public List getEliminateVars() { - List eliminate = new ArrayList<>(); - Variable keepVar = getKeepVar(); - for (Variable var : vars) { + private int getScopeDepth(VariableRef var) { + int depth = 0; + char[] chars = var.getFullName().toCharArray(); + for (char c : chars) { + if(c==':') depth++; + } + return depth/2; + } + + private boolean isVersion(VariableRef var) { + return var.getFullName().contains("#"); + } + + public List getEliminateVars() { + List eliminate = new ArrayList<>(); + VariableRef keepVar = getKeepVar(); + for (VariableRef var : vars) { if(!var.equals(keepVar)) { eliminate.add(var); } @@ -205,7 +218,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { } public void remove(RValue rValue) { - if(rValue instanceof Variable) { + if(rValue instanceof VariableRef) { vars.remove(rValue); } } @@ -235,7 +248,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) { RValue phiRValue = previousSymbol.getRValue(); if (aliasSet.contains(phiRValue)) { - log.append("Alias candidate removed " + phiRValue); + log.append("Alias candidate removed " + phiRValue.getAsTypedString(getSymbols())); aliasSet.remove(phiRValue); break; } @@ -261,11 +274,11 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { @Override public Void visitAssignment(StatementAssignment assignment) { - if (assignment.getlValue() instanceof VariableVersion || assignment.getlValue() instanceof VariableIntermediate) { - Variable variable = (Variable) assignment.getlValue(); - if (assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof Variable) { + if (assignment.getlValue() instanceof VariableRef) { + VariableRef variable = (VariableRef) assignment.getlValue(); + if (assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof VariableRef) { // Alias assignment - Variable alias = (Variable) assignment.getrValue2(); + VariableRef alias = (VariableRef) assignment.getrValue2(); aliases.add(variable, alias); } } @@ -276,9 +289,9 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { public Void visitPhi(StatementPhi phi) { if (phi.getPreviousVersions().size() == 1) { StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0); - if (previousSymbol.getRValue() instanceof Variable) { - VariableVersion variable = phi.getlValue(); - Variable alias = (Variable) previousSymbol.getRValue(); + if (previousSymbol.getRValue() instanceof VariableRef) { + VariableRef variable = phi.getlValue(); + VariableRef alias = (VariableRef) previousSymbol.getRValue(); aliases.add(variable, alias); } } diff --git a/src/dk/camelot64/kickc/passes/Pass2AssertBlocks.java b/src/dk/camelot64/kickc/passes/Pass2AssertBlocks.java index 452d59abb..d2fce524a 100644 --- a/src/dk/camelot64/kickc/passes/Pass2AssertBlocks.java +++ b/src/dk/camelot64/kickc/passes/Pass2AssertBlocks.java @@ -5,7 +5,7 @@ import dk.camelot64.kickc.icl.*; /** Assert that all referenced blocks exist in the program */ public class Pass2AssertBlocks extends Pass2SsaAssertion { - public Pass2AssertBlocks(ControlFlowGraph graph, Scope scope) { + public Pass2AssertBlocks(ControlFlowGraph graph, ProgramScope scope) { super(graph, scope); } diff --git a/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java b/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java index 801ceb1d9..827a33695 100644 --- a/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java +++ b/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java @@ -7,13 +7,13 @@ import java.util.HashSet; /** Asserts that the symbols in the symbol table match exactly the symbols in the program */ public class Pass2AssertSymbols extends Pass2SsaAssertion { - public Pass2AssertSymbols(ControlFlowGraph graph, Scope scope) { + public Pass2AssertSymbols(ControlFlowGraph graph, ProgramScope scope) { super(graph, scope); } @Override public void check() throws AssertionFailed { - SymbolFinder symbolFinder = new SymbolFinder(); + SymbolFinder symbolFinder = new SymbolFinder(getSymbols()); symbolFinder.visitGraph(getGraph()); HashSet codeSymbols = symbolFinder.getSymbols(); // Check that all symbols found in the code is also oin the symbol tabel @@ -56,6 +56,12 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion { private static class SymbolFinder extends ControlFlowGraphBaseVisitor { + private ProgramScope programScope; + + public SymbolFinder(ProgramScope programScope) { + this.programScope = programScope; + } + private HashSet symbols = new HashSet<>(); public HashSet getSymbols() { @@ -65,6 +71,8 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion { private void addSymbol(Value symbol) { if (symbol instanceof Symbol) { symbols.add((Symbol) symbol); + } else if(symbol instanceof VariableRef) { + addSymbol(programScope.getVariable((VariableRef) symbol)); } else if(symbol instanceof PointerDereferenceIndexed) { addSymbol(((PointerDereferenceIndexed) symbol).getPointer()); addSymbol(((PointerDereferenceIndexed) symbol).getIndex()); diff --git a/src/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java b/src/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java index 34e62efc3..29f89f4b8 100644 --- a/src/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java +++ b/src/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java @@ -14,7 +14,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization { private Map> allUsages; - public Pass2ConditionalJumpSimplification(ControlFlowGraph graph, Scope scope, CompileLog log) { + public Pass2ConditionalJumpSimplification(ControlFlowGraph graph, ProgramScope scope, CompileLog log) { super(graph, scope, log); } @@ -25,23 +25,23 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization { public boolean optimize() { final Map assignments = getAllAssignments(); final Map> usages = getAllUsages(); - final List simpleConditionVars = getSimpleConditions(assignments, usages); + final List simpleConditionVars = getSimpleConditions(assignments, usages); removeAssignments(simpleConditionVars); - deleteSymbols(simpleConditionVars); + deleteVariables(simpleConditionVars); return (simpleConditionVars.size()>0); } - private List getSimpleConditions(final Map assignments, final Map> usages) { + private List getSimpleConditions(final Map assignments, final Map> usages) { - final List simpleConditionVars = new ArrayList<>(); + final List simpleConditionVars = new ArrayList<>(); ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { @Override public Void visitConditionalJump(StatementConditionalJump conditionalJump) { if(conditionalJump.getRValue1()==null && conditionalJump.getOperator()==null) { RValue conditionRValue = conditionalJump.getRValue2(); - if(conditionRValue instanceof Variable && usages.get(conditionRValue).size()==1) { - Variable conditionVar = (Variable) conditionRValue; + if(conditionRValue instanceof VariableRef && usages.get(conditionRValue).size()==1) { + VariableRef conditionVar = (VariableRef) conditionRValue; StatementAssignment conditionAssignment = assignments.get(conditionVar); if(conditionAssignment.getOperator()!=null) { switch (conditionAssignment.getOperator().getOperator()) { @@ -58,7 +58,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization { conditionalJump.setOperator(conditionAssignment.getOperator()); conditionalJump.setRValue2(conditionAssignment.getrValue2()); simpleConditionVars.add(conditionVar); - log.append("Simple Condition " + conditionVar + " " + conditionalJump); + log.append("Simple Condition " + conditionVar.getAsTypedString(getSymbols()) + " " + conditionalJump.getAsTypedString(getSymbols())); break; default: } diff --git a/src/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java b/src/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java index 9d1ff7618..05a303272 100644 --- a/src/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java +++ b/src/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java @@ -17,9 +17,9 @@ import java.util.Map; */ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { - private Map usages; + private Map usages; - public Pass2ConstantAdditionElimination(ControlFlowGraph graph, Scope scope, CompileLog log) { + public Pass2ConstantAdditionElimination(ControlFlowGraph graph, ProgramScope scope, CompileLog log) { super(graph, scope, log); } @@ -69,8 +69,8 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { log.append("Consolidated assigned array index constant in assignment " + assignment.getlValue()); return true; } - if(pointerDereferenceIndexed.getPointer() instanceof ConstantInteger && pointerDereferenceIndexed.getIndex() instanceof Variable) { - Variable variable = (Variable) pointerDereferenceIndexed.getIndex(); + if(pointerDereferenceIndexed.getPointer() instanceof ConstantInteger && pointerDereferenceIndexed.getIndex() instanceof VariableRef) { + VariableRef variable = (VariableRef) pointerDereferenceIndexed.getIndex(); ConstantInteger consolidated = consolidateSubConstants(variable); if (consolidated != null) { ConstantInteger ptrConstant = (ConstantInteger) pointerDereferenceIndexed.getPointer(); @@ -94,8 +94,8 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { log.append("Consolidated referenced array index constant in assignment " + assignment.getlValue()); return true; } - if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof Variable) { - Variable variable = (Variable) assignment.getrValue2(); + if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof VariableRef) { + VariableRef variable = (VariableRef) assignment.getrValue2(); ConstantInteger consolidated = consolidateSubConstants(variable); if (consolidated != null) { ConstantInteger ptrConstant = (ConstantInteger) assignment.getrValue1(); @@ -109,8 +109,8 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { } private boolean optimizePlus(StatementAssignment assignment) { - if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof Variable) { - Variable variable = (Variable) assignment.getrValue2(); + if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof VariableRef) { + VariableRef variable = (VariableRef) assignment.getrValue2(); ConstantInteger consolidated = consolidateSubConstants(variable); if (consolidated != null) { ConstantInteger const1 = (ConstantInteger) assignment.getrValue1(); @@ -118,8 +118,8 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { log.append("Consolidated constant in assignment " + assignment.getlValue()); return true; } - } else if (assignment.getrValue1() instanceof Variable && assignment.getrValue2() instanceof ConstantInteger) { - Variable variable = (Variable) assignment.getrValue1(); + } else if (assignment.getrValue1() instanceof VariableRef && assignment.getrValue2() instanceof ConstantInteger) { + VariableRef variable = (VariableRef) assignment.getrValue1(); ConstantInteger consolidated = consolidateSubConstants(variable); if (consolidated != null) { ConstantInteger const2 = (ConstantInteger) assignment.getrValue2(); @@ -143,12 +143,13 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { * @param variable The variable to examine * @return The consolidated constant. Null if no sub-constants were found. */ - private ConstantInteger consolidateSubConstants(Variable variable) { + private ConstantInteger consolidateSubConstants(VariableRef variable) { if(getUsages(variable) >1) { - log.append("Multiple usages for variable. Not optimizing sub-constant "+variable); + log.append("Multiple usages for variable. Not optimizing sub-constant "+variable.getAsTypedString(getSymbols())); return null; } - StatementAssignment assignment = getGraph().getAssignment(variable); + Variable var = getSymbols().getVariable(variable); + StatementAssignment assignment = getGraph().getAssignment(var); if (assignment != null && assignment.getOperator() != null && "+".equals(assignment.getOperator().getOperator())) { if (assignment.getrValue1() instanceof ConstantInteger) { ConstantInteger constant = (ConstantInteger) assignment.getrValue1(); @@ -163,12 +164,12 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { return constant; } else { ConstantInteger const1 = null; - if (assignment.getrValue1() instanceof Variable) { - const1 = consolidateSubConstants((Variable) assignment.getrValue1()); + if (assignment.getrValue1() instanceof VariableRef) { + const1 = consolidateSubConstants((VariableRef) assignment.getrValue1()); } ConstantInteger const2 = null; - if (assignment.getrValue2() instanceof Variable) { - const2 = consolidateSubConstants((Variable) assignment.getrValue2()); + if (assignment.getrValue2() instanceof VariableRef) { + const2 = consolidateSubConstants((VariableRef) assignment.getrValue2()); } ConstantInteger result = null; if (const1 != null) { @@ -195,12 +196,12 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { return new ConstantInteger(-constant.getNumber()); } else { ConstantInteger const1 = null; - if (assignment.getrValue1() instanceof Variable) { - const1 = consolidateSubConstants((Variable) assignment.getrValue1()); + if (assignment.getrValue1() instanceof VariableRef) { + const1 = consolidateSubConstants((VariableRef) assignment.getrValue1()); } ConstantInteger const2 = null; - if (assignment.getrValue2() instanceof Variable) { - const2 = consolidateSubConstants((Variable) assignment.getrValue2()); + if (assignment.getrValue2() instanceof VariableRef) { + const2 = consolidateSubConstants((VariableRef) assignment.getrValue2()); } ConstantInteger result = null; if (const1 != null) { @@ -217,7 +218,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { return null; } - private Integer getUsages(Variable variable) { + private Integer getUsages(VariableRef variable) { Integer useCount = usages.get(variable); if(useCount==null) useCount = 0; return useCount; diff --git a/src/dk/camelot64/kickc/passes/Pass2ConstantPropagation.java b/src/dk/camelot64/kickc/passes/Pass2ConstantPropagation.java index 5515a5521..e57a9bd4e 100644 --- a/src/dk/camelot64/kickc/passes/Pass2ConstantPropagation.java +++ b/src/dk/camelot64/kickc/passes/Pass2ConstantPropagation.java @@ -9,7 +9,7 @@ import java.util.Map; /** Compiler Pass propagating constants in expressions eliminating constant variables */ public class Pass2ConstantPropagation extends Pass2SsaOptimization { - public Pass2ConstantPropagation(ControlFlowGraph graph, Scope scope, CompileLog log) { + public Pass2ConstantPropagation(ControlFlowGraph graph, ProgramScope scope, CompileLog log) { super(graph, scope, log); } @@ -19,13 +19,13 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization { */ @Override public boolean optimize() { - final Map constants = findConstantVariables(); - for (Variable constantVar : constants.keySet()) { + final Map constants = findConstantVariables(); + for (VariableRef constantVar : constants.keySet()) { Constant constantValue = constants.get(constantVar); - log.append("Constant " + constantVar + " " + constantValue); + log.append("Constant " + constantVar.getAsTypedString(getSymbols()) + " " + constantValue.getAsTypedString(getSymbols())); } removeAssignments(constants.keySet()); - deleteSymbols(constants.keySet()); + deleteVariables(constants.keySet()); replaceVariables(constants); return constants.size() > 0; } @@ -34,13 +34,13 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization { * Find variables that have constant values. * @return Map from Variable to the Constant value */ - private Map findConstantVariables() { - final Map constants = new LinkedHashMap<>(); + private Map findConstantVariables() { + final Map constants = new LinkedHashMap<>(); ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { @Override public Void visitAssignment(StatementAssignment assignment) { - if (assignment.getlValue() instanceof VariableVersion || assignment.getlValue() instanceof VariableIntermediate) { - Variable variable = (Variable) assignment.getlValue(); + if (assignment.getlValue() instanceof VariableRef ) { + VariableRef variable = (VariableRef) assignment.getlValue(); if (assignment.getrValue1() == null && assignment.getrValue2() instanceof Constant) { if (assignment.getOperator() == null) { // Constant assignment @@ -72,7 +72,7 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization { if (phi.getPreviousVersions().size() == 1) { StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0); if (previousSymbol.getRValue() instanceof Constant) { - VariableVersion variable = phi.getlValue(); + VariableRef variable = phi.getlValue(); Constant constant = (Constant) previousSymbol.getRValue(); constants.put(variable, constant); } diff --git a/src/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java b/src/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java index a4735e2b5..649c281c9 100644 --- a/src/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java +++ b/src/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java @@ -8,7 +8,7 @@ import java.util.*; /** Pass that culls empty control flow blocks from the program */ public class Pass2CullEmptyBlocks extends Pass2SsaOptimization { - public Pass2CullEmptyBlocks(ControlFlowGraph graph, Scope scope, CompileLog log) { + public Pass2CullEmptyBlocks(ControlFlowGraph graph, ProgramScope scope, CompileLog log) { super(graph, scope, log); } @@ -64,7 +64,7 @@ public class Pass2CullEmptyBlocks extends Pass2SsaOptimization { phiFixVisitor.visitBlock(successor); getGraph().getAllBlocks().remove(removeBlock); removeBlock.getLabel().getScope().remove(removeBlock.getLabel()); - log.append("Culled Empty Block " + removeBlock.getLabel()); + log.append("Culled Empty Block " + removeBlock.getLabel().getTypedName()); } return remove.size()>0; } diff --git a/src/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java b/src/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java index 9b3ab9890..e563861fa 100644 --- a/src/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java +++ b/src/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java @@ -9,7 +9,7 @@ import java.util.Map; /** Compiler Pass eliminating redundant phi functions */ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization { - public Pass2RedundantPhiElimination(ControlFlowGraph graph, Scope scope, CompileLog log) { + public Pass2RedundantPhiElimination(ControlFlowGraph graph, ProgramScope scope, CompileLog log) { super(graph, scope, log); } @@ -18,14 +18,14 @@ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization { */ @Override public boolean optimize() { - final Map aliases = findRedundantPhis(); + final Map aliases = findRedundantPhis(); removeAssignments(aliases.keySet()); - deleteSymbols(aliases.keySet()); replaceVariables(aliases); - for (Variable var : aliases.keySet()) { + for (VariableRef var : aliases.keySet()) { RValue alias = aliases.get(var); - log.append("Redundant Phi " + var + " " + alias); + log.append("Redundant Phi " + var.getAsTypedString(getSymbols()) + " " + alias.getAsTypedString(getSymbols())); } + deleteVariables(aliases.keySet()); return aliases.size()>0; } @@ -33,8 +33,8 @@ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization { * Find phi variables where all previous symbols are identical. * @return Map from (phi) Variable to the previous value */ - private Map findRedundantPhis() { - final Map aliases = new LinkedHashMap<>(); + private Map findRedundantPhis() { + final Map aliases = new LinkedHashMap<>(); ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { @Override public Void visitPhi(StatementPhi phi) { @@ -51,7 +51,7 @@ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization { } } if(found) { - VariableVersion variable = phi.getlValue(); + VariableRef variable = phi.getlValue(); if(phiRValue==null) {phiRValue = VOID;} aliases.put(variable, phiRValue); } diff --git a/src/dk/camelot64/kickc/passes/Pass2SelfPhiElimination.java b/src/dk/camelot64/kickc/passes/Pass2SelfPhiElimination.java index d888539b6..ed1252abc 100644 --- a/src/dk/camelot64/kickc/passes/Pass2SelfPhiElimination.java +++ b/src/dk/camelot64/kickc/passes/Pass2SelfPhiElimination.java @@ -1,17 +1,14 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.CompileLog; -import dk.camelot64.kickc.icl.ControlFlowGraph; -import dk.camelot64.kickc.icl.ControlFlowGraphBaseVisitor; -import dk.camelot64.kickc.icl.Scope; -import dk.camelot64.kickc.icl.StatementPhi; +import dk.camelot64.kickc.icl.*; import java.util.Iterator; /** Compiler Pass eliminating phi self assignments */ public class Pass2SelfPhiElimination extends Pass2SsaOptimization { - public Pass2SelfPhiElimination(ControlFlowGraph graph, Scope scope, CompileLog log) { + public Pass2SelfPhiElimination(ControlFlowGraph graph, ProgramScope scope, CompileLog log) { super(graph, scope, log); } @@ -29,7 +26,7 @@ public class Pass2SelfPhiElimination extends Pass2SsaOptimization { if (previousSymbol.getRValue().equals(phi.getlValue())) { iterator.remove(); optimized[0] = Boolean.TRUE; - log.append("Self Phi Eliminated "+phi.getlValue()); + log.append("Self Phi Eliminated "+phi.getlValue().getAsTypedString(getSymbols())); } } return null; diff --git a/src/dk/camelot64/kickc/passes/Pass2SsaAssertion.java b/src/dk/camelot64/kickc/passes/Pass2SsaAssertion.java index aa3b4d706..d98ae639e 100644 --- a/src/dk/camelot64/kickc/passes/Pass2SsaAssertion.java +++ b/src/dk/camelot64/kickc/passes/Pass2SsaAssertion.java @@ -1,25 +1,27 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.icl.ControlFlowGraph; +import dk.camelot64.kickc.icl.Program; +import dk.camelot64.kickc.icl.ProgramScope; import dk.camelot64.kickc.icl.Scope; /** Assertion checking that a pass 2 representation of the program is consistent */ public abstract class Pass2SsaAssertion { private ControlFlowGraph graph; - private Scope scope; + private ProgramScope programScope; - public Pass2SsaAssertion(ControlFlowGraph graph, Scope scope) { + public Pass2SsaAssertion(ControlFlowGraph graph, ProgramScope programScope) { this.graph = graph; - this.scope = scope; + this.programScope = programScope; } public ControlFlowGraph getGraph() { return graph; } - public Scope getSymbols() { - return scope; + public ProgramScope getSymbols() { + return programScope; } public abstract void check() throws AssertionFailed; diff --git a/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java b/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java index 28d19e644..14f4386c5 100644 --- a/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java +++ b/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java @@ -13,9 +13,9 @@ public abstract class Pass2SsaOptimization { protected CompileLog log; private ControlFlowGraph graph; - private Scope scope; + private ProgramScope scope; - public Pass2SsaOptimization(ControlFlowGraph graph, Scope scope,CompileLog log) { + public Pass2SsaOptimization(ControlFlowGraph graph, ProgramScope scope,CompileLog log) { this.log = log; this.graph = graph; this.scope = scope; @@ -29,7 +29,7 @@ public abstract class Pass2SsaOptimization { return graph; } - public Scope getSymbols() { + public ProgramScope getSymbols() { return scope; } @@ -46,6 +46,16 @@ public abstract class Pass2SsaOptimization { public static RValue VOID = new RValue() { @Override public String toString() { + return getAsString(); + } + + @Override + public String getAsTypedString(ProgramScope scope) { + return getAsString(); + } + + @Override + public String getAsString() { return "VOID"; } }; @@ -55,7 +65,7 @@ public abstract class Pass2SsaOptimization { * * @param aliases Variables that have alias values. */ - public void replaceVariables(final Map aliases) { + public void replaceVariables(final Map aliases) { ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { @Override public Void visitAssignment(StatementAssignment assignment) { @@ -139,7 +149,7 @@ public abstract class Pass2SsaOptimization { if (getAlias(aliases, phi.getlValue()) != null) { RValue alias = getAlias(aliases, phi.getlValue()); if (alias instanceof LValue) { - phi.setlValue((Variable) alias); + phi.setlValue((VariableRef) alias); } } for (Iterator iterator = phi.getPreviousVersions().iterator(); iterator.hasNext(); ) { @@ -166,7 +176,7 @@ public abstract class Pass2SsaOptimization { * @param rValue The RValue to find an alias for * @return The alias to use. Null if no alias exists. */ - private static RValue getAlias(Map aliases, RValue rValue) { + private static RValue getAlias(Map aliases, RValue rValue) { RValue alias = aliases.get(rValue); while (aliases.get(alias) != null) { alias = aliases.get(alias); @@ -278,6 +288,13 @@ public abstract class Pass2SsaOptimization { } } + public void deleteVariables(Collection symbols) { + for (VariableRef variableRef : symbols) { + Symbol symbol = getSymbols().getSymbol(variableRef.getFullName()); + symbol.getScope().remove(symbol); + } + } + public Map getAllAssignments() { final HashMap assignments = new LinkedHashMap<>(); ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { @@ -334,12 +351,12 @@ public abstract class Pass2SsaOptimization { return usages; } - protected Map countVarUsages() { - final HashMap usages = new LinkedHashMap<>(); + protected Map countVarUsages() { + final HashMap usages = new LinkedHashMap<>(); ControlFlowGraphBaseVisitor usageVisitor = new ControlFlowGraphBaseVisitor() { private void addUsage(RValue rVal) { - if(rVal instanceof Variable) { - Variable var = (Variable) rVal; + if(rVal instanceof VariableRef) { + VariableRef var = (VariableRef) rVal; Integer usage = usages.get(var); if (usage == null) { usage = 0; diff --git a/src/dk/camelot64/kickc/passes/Pass3CodeGeneration.java b/src/dk/camelot64/kickc/passes/Pass3CodeGeneration.java index 52a369803..7292a5506 100644 --- a/src/dk/camelot64/kickc/passes/Pass3CodeGeneration.java +++ b/src/dk/camelot64/kickc/passes/Pass3CodeGeneration.java @@ -48,8 +48,10 @@ public class Pass3CodeGeneration { StatementAssignment assignment = (StatementAssignment) statement; LValue lValue = assignment.getlValue(); boolean isAlu = false; - if (lValue instanceof Variable) { - RegisterAllocation.Register lValRegister = symbols.getRegister((Variable) lValue); + if (lValue instanceof VariableRef) { + VariableRef lValueRef = (VariableRef) lValue; + Variable lValueVar = symbols.getVariable(lValueRef); + RegisterAllocation.Register lValRegister = symbols.getRegister(lValueVar); if (lValRegister.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) { asm.addComment(statement + " // ALU"); StatementAssignment assignmentAlu = assignment; @@ -59,19 +61,19 @@ public class Pass3CodeGeneration { } assignment = (StatementAssignment) statement; AsmFragment asmFragment = new AsmFragment(assignment, assignmentAlu, symbols); - asm.addComment(statement + " // " + asmFragment.getSignature()); + asm.addComment(statement.getAsTypedString(symbols) + " // " + asmFragment.getSignature()); asmFragment.generate(asm); isAlu = true; } } if (!isAlu) { AsmFragment asmFragment = new AsmFragment(assignment, symbols); - asm.addComment(statement + " // " + asmFragment.getSignature()); + asm.addComment(statement.getAsTypedString(symbols) + " // " + asmFragment.getSignature()); asmFragment.generate(asm); } } else if (statement instanceof StatementConditionalJump) { AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, block, symbols, graph); - asm.addComment(statement + " // " + asmFragment.getSignature()); + asm.addComment(statement.getAsTypedString(symbols) + " // " + asmFragment.getSignature()); asmFragment.generate(asm); } else if (statement instanceof StatementCall) { StatementCall call = (StatementCall) statement; @@ -132,8 +134,10 @@ public class Pass3CodeGeneration { } private RegisterAllocation.Register getRegister(RValue rValue) { - if (rValue instanceof Variable) { - return symbols.getRegister((Variable) rValue); + if (rValue instanceof VariableRef) { + VariableRef rValueRef = (VariableRef) rValue; + Variable rValueVar = symbols.getVariable(rValueRef); + return symbols.getRegister(rValueVar); } else { return null; } @@ -142,11 +146,11 @@ public class Pass3CodeGeneration { private void genAsmMove(AsmProgram asm, LValue lValue, RValue rValue) { if (getRegister(lValue).equals(getRegister(rValue))) { // Do not move from register to itself - asm.addComment(lValue + " = " + rValue + " // register copy "); + asm.addComment(lValue.getAsTypedString(symbols) + " = " + rValue.getAsTypedString(symbols) + " // register copy "); return; } AsmFragment asmFragment = new AsmFragment(lValue, rValue, symbols); - asm.addComment(lValue + " = " + rValue + " // " + asmFragment.getSignature()); + asm.addComment(lValue.getAsTypedString(symbols) + " = " + rValue.getAsTypedString(symbols) + " // " + asmFragment.getSignature()); asmFragment.generate(asm); } diff --git a/src/dk/camelot64/kickc/test/TestCompilationOutput.java b/src/dk/camelot64/kickc/test/TestCompilationOutput.java index 5eb9ac751..d60fe55b4 100644 --- a/src/dk/camelot64/kickc/test/TestCompilationOutput.java +++ b/src/dk/camelot64/kickc/test/TestCompilationOutput.java @@ -47,7 +47,7 @@ public class TestCompilationOutput extends TestCase { Compiler.CompilationResult output = compiler.compile(input); assertOutput(fileName, ".asm", output.getAsmProgram().toString(false)); assertOutput(fileName, ".sym", output.getSymbols().getSymbolTableContents()); - assertOutput(fileName, ".cfg", output.getGraph().toString()); + assertOutput(fileName, ".cfg", output.getGraph().getAsTypedString(output.getSymbols())); assertOutput(fileName, ".log", output.getLog().toString()); } diff --git a/src/dk/camelot64/kickc/test/TestIclJson.java b/src/dk/camelot64/kickc/test/TestIclJson.java index 1fe6a7920..d0f7db3bb 100644 --- a/src/dk/camelot64/kickc/test/TestIclJson.java +++ b/src/dk/camelot64/kickc/test/TestIclJson.java @@ -44,6 +44,8 @@ public class TestIclJson extends TestCase { assertJsonSerialization(scope, json, Scope.class); } + + public static void assertJsonSerialization( Object object, String json, diff --git a/src/dk/camelot64/kickc/test/ref/bresenham.log b/src/dk/camelot64/kickc/test/ref/bresenham.log index 308007c0b..6b8c778b3 100644 --- a/src/dk/camelot64/kickc/test/ref/bresenham.log +++ b/src/dk/camelot64/kickc/test/ref/bresenham.log @@ -899,59 +899,7 @@ CONTROL FLOW GRAPH to:@END @END: from @3 -Consolidated constant in assignment (byte*) cursor#0 Multiple usages for variable. Not optimizing sub-constant (byte) x1#1 -Succesful SSA optimization Pass2ConstantAdditionElimination -CONTROL FLOW GRAPH -@BEGIN: from - (byte) e#0 ← (byte) 24 / (byte) 2 - (byte~) $3 ← (byte) 0 * (byte) 40 - (byte*~) $4 ← (byte~) $3 - (byte*) cursor#0 ← (byte*~) $4 + (word) 1024 - to:@1 -@1: from @3 @BEGIN - (byte) x1#3 ← phi( @3/(byte) x1#1 @BEGIN/(byte) 39 ) - (byte) y#3 ← phi( @3/(byte) y#5 @BEGIN/(byte) 0 ) - (byte) xd#1 ← phi( @3/(byte) xd#3 @BEGIN/(byte) 39 ) - (byte) yd#1 ← phi( @3/(byte) yd#2 @BEGIN/(byte) 24 ) - (byte) e#3 ← phi( @3/(byte) e#5 @BEGIN/(byte) e#0 ) - (byte) x#2 ← phi( @3/(byte) x#3 @BEGIN/(byte) 0 ) - (byte*) cursor#3 ← phi( @3/(byte*) cursor#5 @BEGIN/(byte*) cursor#0 ) - (byte) STAR#1 ← phi( @3/(byte) STAR#2 @BEGIN/(byte) 81 ) - *((byte*) cursor#3) ← (byte) STAR#1 - (byte) x#1 ← (byte) x#2 + (byte) 1 - (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 - (byte) e#1 ← (byte) e#3 + (byte) yd#1 - if((byte) xd#1<(byte) e#1) goto @2 - to:@3 -@2: from @1 - (byte) yd#3 ← phi( @1/(byte) yd#1 ) - (byte) STAR#3 ← phi( @1/(byte) STAR#1 ) - (byte) x1#2 ← phi( @1/(byte) x1#3 ) - (byte) x#4 ← phi( @1/(byte) x#1 ) - (byte) xd#2 ← phi( @1/(byte) xd#1 ) - (byte) e#4 ← phi( @1/(byte) e#1 ) - (byte*) cursor#4 ← phi( @1/(byte*) cursor#1 ) - (byte) y#2 ← phi( @1/(byte) y#3 ) - (byte) y#1 ← (byte) y#2 + (byte) 1 - (byte*) cursor#2 ← (byte*) cursor#4 + (byte) 40 - (byte) e#2 ← (byte) e#4 - (byte) xd#2 - to:@3 -@3: from @1 @2 - (byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#3 ) - (byte) STAR#2 ← phi( @2/(byte) STAR#3 @1/(byte) STAR#1 ) - (byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 ) - (byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 ) - (byte) yd#2 ← phi( @2/(byte) yd#3 @1/(byte) yd#1 ) - (byte) xd#3 ← phi( @2/(byte) xd#2 @1/(byte) xd#1 ) - (byte) x#3 ← phi( @2/(byte) x#4 @1/(byte) x#1 ) - (byte) x1#1 ← phi( @2/(byte) x1#2 @1/(byte) x1#3 ) - (byte~) $13 ← (byte) x1#1 + (byte) 1 - if((byte) x#3<(byte~) $13) goto @1 - to:@END -@END: from @3 - -Alias (byte~) $3 = (byte*~) $4 Alias (byte) yd#1 = (byte) yd#3 Alias (byte) STAR#1 = (byte) STAR#3 Alias (byte) x1#2 = (byte) x1#3 @@ -965,7 +913,8 @@ CONTROL FLOW GRAPH @BEGIN: from (byte) e#0 ← (byte) 24 / (byte) 2 (byte~) $3 ← (byte) 0 * (byte) 40 - (byte*) cursor#0 ← (byte~) $3 + (word) 1024 + (byte*~) $4 ← (word) 1024 + (byte~) $3 + (byte*) cursor#0 ← (byte*~) $4 + (byte) 0 to:@1 @1: from @3 @BEGIN (byte) x1#2 ← phi( @3/(byte) x1#1 @BEGIN/(byte) 39 ) @@ -1011,7 +960,8 @@ CONTROL FLOW GRAPH @BEGIN: from (byte) e#0 ← (byte) 24 / (byte) 2 (byte~) $3 ← (byte) 0 * (byte) 40 - (byte*) cursor#0 ← (byte~) $3 + (word) 1024 + (byte*~) $4 ← (word) 1024 + (byte~) $3 + (byte*) cursor#0 ← (byte*~) $4 + (byte) 0 to:@1 @1: from @3 @BEGIN (byte) x1#2 ← phi( @3/(byte) x1#2 @BEGIN/(byte) 39 ) @@ -1051,7 +1001,8 @@ CONTROL FLOW GRAPH @BEGIN: from (byte) e#0 ← (byte) 24 / (byte) 2 (byte~) $3 ← (byte) 0 * (byte) 40 - (byte*) cursor#0 ← (byte~) $3 + (word) 1024 + (byte*~) $4 ← (word) 1024 + (byte~) $3 + (byte*) cursor#0 ← (byte*~) $4 + (byte) 0 to:@1 @1: from @3 @BEGIN (byte) x1#2 ← phi( @BEGIN/(byte) 39 ) @@ -1091,7 +1042,8 @@ Constant (byte) STAR#1 (byte) 81 Succesful SSA optimization Pass2ConstantPropagation CONTROL FLOW GRAPH @BEGIN: from - (byte*) cursor#0 ← (byte) 0 + (word) 1024 + (byte*~) $4 ← (word) 1024 + (byte) 0 + (byte*) cursor#0 ← (byte*~) $4 + (byte) 0 to:@1 @1: from @3 @BEGIN (byte) y#2 ← phi( @3/(byte) y#5 @BEGIN/(byte) 0 ) @@ -1120,10 +1072,42 @@ CONTROL FLOW GRAPH Multiple usages for variable. Not optimizing sub-constant (byte) y#2 Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1 -Constant (byte*) cursor#0 (word) 1024 +Constant (byte*~) $4 (word) 1024 Constant (byte~) $13 (byte) 40 Succesful SSA optimization Pass2ConstantPropagation CONTROL FLOW GRAPH +@BEGIN: from + (byte*) cursor#0 ← (word) 1024 + (byte) 0 + to:@1 +@1: from @3 @BEGIN + (byte) y#2 ← phi( @3/(byte) y#5 @BEGIN/(byte) 0 ) + (byte) e#3 ← phi( @3/(byte) e#5 @BEGIN/(byte) 12 ) + (byte) x#2 ← phi( @3/(byte) x#1 @BEGIN/(byte) 0 ) + (byte*) cursor#3 ← phi( @3/(byte*) cursor#5 @BEGIN/(byte*) cursor#0 ) + *((byte*) cursor#3) ← (byte) 81 + (byte) x#1 ← (byte) x#2 + (byte) 1 + (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 + (byte) e#1 ← (byte) e#3 + (byte) 24 + if((byte) 39<(byte) e#1) goto @2 + to:@3 +@2: from @1 + (byte) y#1 ← (byte) y#2 + (byte) 1 + (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 + (byte) e#2 ← (byte) e#1 - (byte) 39 + to:@3 +@3: from @1 @2 + (byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#2 ) + (byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 ) + (byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 ) + if((byte) x#1<(byte) 40) goto @1 + to:@END +@END: from @3 + +Multiple usages for variable. Not optimizing sub-constant (byte) y#2 +Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1 +Constant (byte*) cursor#0 (word) 1024 +Succesful SSA optimization Pass2ConstantPropagation +CONTROL FLOW GRAPH @BEGIN: from to:@1 @1: from @3 @BEGIN @@ -1383,3 +1367,146 @@ B3_from_B2: sta 15 jmp B3 +FINAL SYMBOL TABLE +(label) @1 +(label) @2 +(label) @3 +(label) @BEGIN +(label) @END +(byte[1000]) SCREEN +(byte) STAR +(byte*) cursor +(byte*) cursor#1 zp ptr byte:3 +(byte*) cursor#2 zp ptr byte:7 +(byte*) cursor#3 zp ptr byte:10 +(byte*) cursor#5 zp ptr byte:16 +(byte) e +(byte) e#1 zp byte:5 +(byte) e#2 zp byte:9 +(byte) e#3 zp byte:13 +(byte) e#5 zp byte:15 +(byte) x +(byte) x#1 zp byte:2 +(byte) x#2 zp byte:12 +(byte) x0 +(byte) x1 +(byte) xd +(byte) y +(byte) y#1 zp byte:6 +(byte) y#2 zp byte:14 +(byte) y#5 zp byte:18 +(byte) y0 +(byte) y1 +(byte) yd + +FINAL CODE +BBEGIN: +B1_from_BBEGIN: + // (byte) y#2 = (byte) 0 // zpby1=coby1 + lda #0 + sta 14 + // (byte) e#3 = (byte) 12 // zpby1=coby1 + lda #12 + sta 13 + // (byte) x#2 = (byte) 0 // zpby1=coby1 + lda #0 + sta 12 + // (byte*) cursor#3 = (word) 1024 // zpptrby1=cowo1 + lda #<1024 + sta 10 + lda #>1024 + sta 10+1 + jmp B1 +B1_from_B3: + // (byte) y#2 = (byte) y#5 // zpby1=zpby2 + lda 18 + sta 14 + // (byte) e#3 = (byte) e#5 // zpby1=zpby2 + lda 15 + sta 13 + // (byte) x#2 = (byte) x#1 // zpby1=zpby2 + lda 2 + sta 12 + // (byte*) cursor#3 = (byte*) cursor#5 // zpptrby1=zpptrby2 + lda 16 + sta 10 + lda 16+1 + sta 10+1 +B1: + // *((byte*) cursor#3) ← (byte) 81 // zpiby1=coby1 + ldy #0 + lda #81 + sta (10),y + // (byte) x#1 ← (byte) x#2 + (byte) 1 // zpby1=zpby2_plus_1 + lda 12 + clc + adc #1 + sta 2 + // (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 // zpptrby1=zpptrby2_plus_1 + lda 10 + clc + adc #1 + sta 3 + lda 10+1 + adc #0 + sta 3+1 + // (byte) e#1 ← (byte) e#3 + (byte) 24 // zpby1=zpby2_plus_coby1 + lda 13 + clc + adc #24 + sta 5 + // if((byte) 39<(byte) e#1) goto @2 // coby1_lt_zpby1_then_la1 + lda #39 + cmp 5 + bcc B2 +B3_from_B1: + // (byte) y#5 = (byte) y#2 // zpby1=zpby2 + lda 14 + sta 18 + // (byte*) cursor#5 = (byte*) cursor#1 // zpptrby1=zpptrby2 + lda 3 + sta 16 + lda 3+1 + sta 16+1 + // (byte) e#5 = (byte) e#1 // zpby1=zpby2 + lda 5 + sta 15 +B3: + // if((byte) x#1<(byte) 40) goto @1 // zpby1_lt_coby1_then_la1 + lda 2 + cmp #40 + bcc B1_from_B3 +BEND: +B2: + // (byte) y#1 ← (byte) y#2 + (byte) 1 // zpby1=zpby2_plus_1 + lda 14 + clc + adc #1 + sta 6 + // (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 // zpptrby1=zpptrby2_plus_coby1 + lda #40 + clc + adc 3 + sta 7 + lda #0 + adc 3+1 + sta 7+1 + // (byte) e#2 ← (byte) e#1 - (byte) 39 // zpby1=zpby2_minus_coby1 + lda 5 + sec + sbc #39 + sta 9 +B3_from_B2: + // (byte) y#5 = (byte) y#1 // zpby1=zpby2 + lda 6 + sta 18 + // (byte*) cursor#5 = (byte*) cursor#2 // zpptrby1=zpptrby2 + lda 7 + sta 16 + lda 7+1 + sta 16+1 + // (byte) e#5 = (byte) e#2 // zpby1=zpby2 + lda 9 + sta 15 + jmp B3 + diff --git a/src/dk/camelot64/kickc/test/ref/flipper-rex2.log b/src/dk/camelot64/kickc/test/ref/flipper-rex2.log index 367d5476d..487411904 100644 --- a/src/dk/camelot64/kickc/test/ref/flipper-rex2.log +++ b/src/dk/camelot64/kickc/test/ref/flipper-rex2.log @@ -1432,210 +1432,6 @@ plot::@return: from @12 to:@RETURN @END: from @BEGIN -Consolidated constant in assignment (byte*~) plot::$2 -Succesful SSA optimization Pass2ConstantAdditionElimination -CONTROL FLOW GRAPH -@BEGIN: from - call main param-assignment - to:@END -main: from @BEGIN - (byte[256]) buffer2#16 ← phi( @BEGIN/(word) 4352 ) - (byte[1000]) SCREEN#12 ← phi( @BEGIN/(word) 1024 ) - (byte*) RASTER#9 ← phi( @BEGIN/(word) 53266 ) - (byte[256]) buffer1#9 ← phi( @BEGIN/(word) 4096 ) - call prepare param-assignment - to:@16 -@16: from main - (byte[256]) buffer2#14 ← phi( main/(byte[256]) buffer2#16 ) - (byte[256]) buffer1#22 ← phi( main/(byte[256]) buffer1#9 ) - (byte[1000]) SCREEN#10 ← phi( main/(byte[1000]) SCREEN#12 ) - (byte*) RASTER#7 ← phi( main/(byte*) RASTER#9 ) - to:main::@1 -main::@1: from @16 @18 - (byte[256]) buffer1#21 ← phi( @16/(byte[256]) buffer1#22 @18/(byte[256]) buffer1#23 ) - (byte[256]) buffer2#13 ← phi( @16/(byte[256]) buffer2#14 @18/(byte[256]) buffer2#15 ) - (byte[1000]) SCREEN#9 ← phi( @16/(byte[1000]) SCREEN#10 @18/(byte[1000]) SCREEN#11 ) - (byte*) RASTER#6 ← phi( @16/(byte*) RASTER#7 @18/(byte*) RASTER#8 ) - to:main::@2 -main::@2: from @2 main::@1 - (byte[256]) buffer2#12 ← phi( @2/(byte[256]) buffer2#8 main::@1/(byte[256]) buffer2#13 ) - (byte[256]) buffer1#20 ← phi( @2/(byte[256]) buffer1#16 main::@1/(byte[256]) buffer1#21 ) - (byte[1000]) SCREEN#8 ← phi( @2/(byte[1000]) SCREEN#4 main::@1/(byte[1000]) SCREEN#9 ) - (byte) main::c#6 ← phi( @2/(byte) main::c#1 main::@1/(byte) 25 ) - (byte*) RASTER#3 ← phi( @2/(byte*) RASTER#5 main::@1/(byte*) RASTER#6 ) - to:main::@3 -main::@3: from main::@2 main::@3 - (byte[256]) buffer1#19 ← phi( main::@2/(byte[256]) buffer1#20 main::@3/(byte[256]) buffer1#19 ) - (byte[256]) buffer2#11 ← phi( main::@2/(byte[256]) buffer2#12 main::@3/(byte[256]) buffer2#11 ) - (byte[1000]) SCREEN#7 ← phi( main::@2/(byte[1000]) SCREEN#8 main::@3/(byte[1000]) SCREEN#7 ) - (byte) main::c#5 ← phi( main::@2/(byte) main::c#6 main::@3/(byte) main::c#5 ) - (byte*) RASTER#1 ← phi( main::@2/(byte*) RASTER#3 main::@3/(byte*) RASTER#1 ) - (byte~) main::$1 ← * (byte*) RASTER#1 - (boolean~) main::$2 ← (byte~) main::$1 != (byte) 254 - if((boolean~) main::$2) goto main::@3 - to:@1 -@1: from main::@3 - (byte[256]) buffer2#10 ← phi( main::@3/(byte[256]) buffer2#11 ) - (byte[256]) buffer1#18 ← phi( main::@3/(byte[256]) buffer1#19 ) - (byte[1000]) SCREEN#6 ← phi( main::@3/(byte[1000]) SCREEN#7 ) - (byte) main::c#4 ← phi( main::@3/(byte) main::c#5 ) - (byte*) RASTER#4 ← phi( main::@3/(byte*) RASTER#1 ) - to:main::@4 -main::@4: from @1 main::@4 - (byte[256]) buffer1#17 ← phi( @1/(byte[256]) buffer1#18 main::@4/(byte[256]) buffer1#17 ) - (byte[256]) buffer2#9 ← phi( @1/(byte[256]) buffer2#10 main::@4/(byte[256]) buffer2#9 ) - (byte[1000]) SCREEN#5 ← phi( @1/(byte[1000]) SCREEN#6 main::@4/(byte[1000]) SCREEN#5 ) - (byte) main::c#3 ← phi( @1/(byte) main::c#4 main::@4/(byte) main::c#3 ) - (byte*) RASTER#2 ← phi( @1/(byte*) RASTER#4 main::@4/(byte*) RASTER#2 ) - (byte~) main::$3 ← * (byte*) RASTER#2 - (boolean~) main::$4 ← (byte~) main::$3 != (byte) 255 - if((boolean~) main::$4) goto main::@4 - to:@2 -@2: from main::@4 - (byte[256]) buffer2#8 ← phi( main::@4/(byte[256]) buffer2#9 ) - (byte[256]) buffer1#16 ← phi( main::@4/(byte[256]) buffer1#17 ) - (byte[1000]) SCREEN#4 ← phi( main::@4/(byte[1000]) SCREEN#5 ) - (byte*) RASTER#5 ← phi( main::@4/(byte*) RASTER#2 ) - (byte) main::c#2 ← phi( main::@4/(byte) main::c#3 ) - (byte) main::c#1 ← -- (byte) main::c#2 - (boolean~) main::$5 ← (byte) main::c#1 != (byte) 0 - if((boolean~) main::$5) goto main::@2 - to:@3 -@3: from @2 - (byte*) RASTER#11 ← phi( @2/(byte*) RASTER#5 ) - (byte[256]) buffer1#14 ← phi( @2/(byte[256]) buffer1#16 ) - (byte[256]) buffer2#7 ← phi( @2/(byte[256]) buffer2#8 ) - (byte[1000]) SCREEN#3 ← phi( @2/(byte[1000]) SCREEN#4 ) - call flip param-assignment - to:@17 -@17: from @3 - (byte[256]) buffer2#17 ← phi( @3/(byte[256]) buffer2#7 ) - (byte*) RASTER#10 ← phi( @3/(byte*) RASTER#11 ) - (byte[256]) buffer1#15 ← phi( @3/(byte[256]) buffer1#14 ) - (byte[1000]) SCREEN#2 ← phi( @3/(byte[1000]) SCREEN#3 ) - call plot param-assignment - to:@18 -@18: from @17 - (byte[256]) buffer2#15 ← phi( @17/(byte[256]) buffer2#17 ) - (byte[256]) buffer1#23 ← phi( @17/(byte[256]) buffer1#15 ) - (byte[1000]) SCREEN#11 ← phi( @17/(byte[1000]) SCREEN#2 ) - (byte*) RASTER#8 ← phi( @17/(byte*) RASTER#10 ) - if(true) goto main::@1 - to:main::@return -main::@return: from @18 - return - to:@RETURN -prepare: from main - (byte[256]) buffer1#5 ← phi( main/(byte[256]) buffer1#9 ) - to:prepare::@1 -prepare::@1: from prepare prepare::@1 - (byte[256]) buffer1#1 ← phi( prepare/(byte[256]) buffer1#5 prepare::@1/(byte[256]) buffer1#1 ) - (byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@1/(byte) prepare::i#1 ) - *((byte[256]) buffer1#1 + (byte) prepare::i#2) ← (byte) prepare::i#2 - (byte) prepare::i#1 ← ++ (byte) prepare::i#2 - (boolean~) prepare::$0 ← (byte) prepare::i#1 != (byte) 0 - if((boolean~) prepare::$0) goto prepare::@1 - to:prepare::@return -prepare::@return: from prepare::@1 - return - to:@RETURN -flip: from @3 - (byte[256]) buffer2#6 ← phi( @3/(byte[256]) buffer2#7 ) - (byte[256]) buffer1#11 ← phi( @3/(byte[256]) buffer1#14 ) - to:flip::@1 -flip::@1: from @8 flip - (byte) flip::r#4 ← phi( @8/(byte) flip::r#1 flip/(byte) 16 ) - (byte[256]) buffer1#6 ← phi( @8/(byte[256]) buffer1#10 flip/(byte[256]) buffer1#11 ) - (byte) flip::srcIdx#3 ← phi( @8/(byte) flip::srcIdx#4 flip/(byte) 0 ) - (byte[256]) buffer2#3 ← phi( @8/(byte[256]) buffer2#5 flip/(byte[256]) buffer2#6 ) - (byte) flip::dstIdx#5 ← phi( @8/(byte) flip::dstIdx#2 flip/(byte) 15 ) - to:flip::@2 -flip::@2: from flip::@1 flip::@2 - (byte) flip::r#3 ← phi( flip::@1/(byte) flip::r#4 flip::@2/(byte) flip::r#3 ) - (byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@2/(byte) flip::c#1 ) - (byte) flip::dstIdx#3 ← phi( flip::@1/(byte) flip::dstIdx#5 flip::@2/(byte) flip::dstIdx#1 ) - (byte[256]) buffer2#1 ← phi( flip::@1/(byte[256]) buffer2#3 flip::@2/(byte[256]) buffer2#1 ) - (byte) flip::srcIdx#2 ← phi( flip::@1/(byte) flip::srcIdx#3 flip::@2/(byte) flip::srcIdx#1 ) - (byte[256]) buffer1#2 ← phi( flip::@1/(byte[256]) buffer1#6 flip::@2/(byte[256]) buffer1#2 ) - (byte~) flip::$0 ← (byte[256]) buffer1#2 *idx (byte) flip::srcIdx#2 - *((byte[256]) buffer2#1 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 - (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 - (byte~) flip::$1 ← (byte) flip::dstIdx#3 + (byte) 16 - (byte) flip::dstIdx#1 ← (byte~) flip::$1 - (byte) flip::c#1 ← -- (byte) flip::c#2 - (boolean~) flip::$2 ← (byte) flip::c#1 != (byte) 0 - if((boolean~) flip::$2) goto flip::@2 - to:@8 -@8: from flip::@2 - (byte[256]) buffer2#5 ← phi( flip::@2/(byte[256]) buffer2#1 ) - (byte) flip::srcIdx#4 ← phi( flip::@2/(byte) flip::srcIdx#1 ) - (byte[256]) buffer1#10 ← phi( flip::@2/(byte[256]) buffer1#2 ) - (byte) flip::r#2 ← phi( flip::@2/(byte) flip::r#3 ) - (byte) flip::dstIdx#4 ← phi( flip::@2/(byte) flip::dstIdx#1 ) - (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#4 - (byte) flip::r#1 ← -- (byte) flip::r#2 - (boolean~) flip::$3 ← (byte) flip::r#1 != (byte) 0 - if((boolean~) flip::$3) goto flip::@1 - to:@9 -@9: from @8 - (byte[256]) buffer2#4 ← phi( @8/(byte[256]) buffer2#5 ) - (byte[256]) buffer1#7 ← phi( @8/(byte[256]) buffer1#10 ) - to:flip::@3 -flip::@3: from @9 flip::@3 - (byte[256]) buffer1#3 ← phi( @9/(byte[256]) buffer1#7 flip::@3/(byte[256]) buffer1#3 ) - (byte) flip::i#2 ← phi( @9/(byte) 0 flip::@3/(byte) flip::i#1 ) - (byte[256]) buffer2#2 ← phi( @9/(byte[256]) buffer2#4 flip::@3/(byte[256]) buffer2#2 ) - (byte~) flip::$4 ← (byte[256]) buffer2#2 *idx (byte) flip::i#2 - *((byte[256]) buffer1#3 + (byte) flip::i#2) ← (byte~) flip::$4 - (byte) flip::i#1 ← ++ (byte) flip::i#2 - (boolean~) flip::$5 ← (byte) flip::i#1 != (byte) 0 - if((boolean~) flip::$5) goto flip::@3 - to:flip::@return -flip::@return: from flip::@3 - return - to:@RETURN -plot: from @17 - (byte[256]) buffer1#13 ← phi( @17/(byte[256]) buffer1#15 ) - (byte[1000]) SCREEN#1 ← phi( @17/(byte[1000]) SCREEN#2 ) - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 - (byte*~) plot::$2 ← (byte*~) plot::$1 + (byte) 212 - (byte*) plot::line#0 ← (byte*~) plot::$2 - to:plot::@1 -plot::@1: from @12 plot - (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) - (byte[256]) buffer1#8 ← phi( @12/(byte[256]) buffer1#12 plot/(byte[256]) buffer1#13 ) - (byte) plot::i#3 ← phi( @12/(byte) plot::i#4 plot/(byte) 0 ) - (byte*) plot::line#4 ← phi( @12/(byte*) plot::line#1 plot/(byte*) plot::line#0 ) - to:plot::@2 -plot::@2: from plot::@1 plot::@2 - (byte) plot::y#3 ← phi( plot::@1/(byte) plot::y#4 plot::@2/(byte) plot::y#3 ) - (byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@2/(byte) plot::x#1 ) - (byte*) plot::line#2 ← phi( plot::@1/(byte*) plot::line#4 plot::@2/(byte*) plot::line#2 ) - (byte) plot::i#2 ← phi( plot::@1/(byte) plot::i#3 plot::@2/(byte) plot::i#1 ) - (byte[256]) buffer1#4 ← phi( plot::@1/(byte[256]) buffer1#8 plot::@2/(byte[256]) buffer1#4 ) - (byte~) plot::$3 ← (byte[256]) buffer1#4 *idx (byte) plot::i#2 - *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 - (byte) plot::i#1 ← ++ (byte) plot::i#2 - (byte) plot::x#1 ← ++ (byte) plot::x#2 - (boolean~) plot::$4 ← (byte) plot::x#1 < (byte) 16 - if((boolean~) plot::$4) goto plot::@2 - to:@12 -@12: from plot::@2 - (byte) plot::i#4 ← phi( plot::@2/(byte) plot::i#1 ) - (byte[256]) buffer1#12 ← phi( plot::@2/(byte[256]) buffer1#4 ) - (byte) plot::y#2 ← phi( plot::@2/(byte) plot::y#3 ) - (byte*) plot::line#3 ← phi( plot::@2/(byte*) plot::line#2 ) - (byte*~) plot::$5 ← (byte*) plot::line#3 + (byte) 40 - (byte*) plot::line#1 ← (byte*~) plot::$5 - (byte) plot::y#1 ← -- (byte) plot::y#2 - (boolean~) plot::$6 ← (byte) plot::y#1 != (byte) 0 - if((boolean~) plot::$6) goto plot::@1 - to:plot::@return -plot::@return: from @12 - return - to:@RETURN -@END: from @BEGIN - Alias (byte[256]) buffer2#14 = (byte[256]) buffer2#16 Alias (byte[256]) buffer1#22 = (byte[256]) buffer1#9 (byte[256]) buffer1#5 Alias (byte[1000]) SCREEN#10 = (byte[1000]) SCREEN#12 @@ -1647,7 +1443,7 @@ Alias (byte) main::c#4 = (byte) main::c#5 Alias (byte*) RASTER#1 = (byte*) RASTER#4 Alias (byte[256]) buffer2#15 = (byte[256]) buffer2#8 (byte[256]) buffer2#9 (byte[256]) buffer2#7 (byte[256]) buffer2#17 (byte[256]) buffer2#6 Alias (byte[256]) buffer1#11 = (byte[256]) buffer1#16 (byte[256]) buffer1#17 (byte[256]) buffer1#14 (byte[256]) buffer1#15 (byte[256]) buffer1#23 (byte[256]) buffer1#13 -Alias (byte[1000]) SCREEN#1 = (byte[1000]) SCREEN#4 (byte[1000]) SCREEN#5 (byte[1000]) SCREEN#3 (byte[1000]) SCREEN#2 (byte[1000]) SCREEN#11 (byte*~) plot::$1 +Alias (byte[1000]) SCREEN#1 = (byte[1000]) SCREEN#4 (byte[1000]) SCREEN#5 (byte[1000]) SCREEN#3 (byte[1000]) SCREEN#2 (byte[1000]) SCREEN#11 Alias (byte*) RASTER#10 = (byte*) RASTER#5 (byte*) RASTER#2 (byte*) RASTER#11 (byte*) RASTER#8 Alias (byte) main::c#2 = (byte) main::c#3 Alias (byte) flip::dstIdx#1 = (byte~) flip::$1 (byte) flip::dstIdx#4 @@ -1786,7 +1582,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (byte[1000]) SCREEN#1 + (byte) 212 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -1943,7 +1740,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (byte[1000]) SCREEN#1 + (byte) 212 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -2115,7 +1913,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (byte[1000]) SCREEN#1 + (byte) 212 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -2270,7 +2069,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (byte[1000]) SCREEN#1 + (byte) 212 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -2411,7 +2211,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (byte[1000]) SCREEN#1 + (byte) 212 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -2549,7 +2350,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (byte[1000]) SCREEN#1 + (byte) 212 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -2684,7 +2486,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (byte[1000]) SCREEN#1 + (byte) 212 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -2810,7 +2613,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (byte[1000]) SCREEN#1 + (byte) 212 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -2929,7 +2733,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (byte[1000]) SCREEN#1 + (byte) 212 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -3045,7 +2850,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (byte[1000]) SCREEN#1 + (byte) 212 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -3157,7 +2963,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (word) 1024 + (byte) 212 + (byte*~) plot::$1 ← (word) 1024 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -3269,7 +3076,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from @17 - (byte*) plot::line#0 ← (word) 1024 + (byte) 212 + (byte*~) plot::$1 ← (word) 1024 + (byte) 200 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 to:plot::@1 plot::@1: from @12 plot (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) @@ -3295,6 +3103,118 @@ plot::@return: from @12 to:@RETURN @END: from @BEGIN +Constant (byte*~) plot::$1 (word) 1224 +Succesful SSA optimization Pass2ConstantPropagation +CONTROL FLOW GRAPH +@BEGIN: from + call main param-assignment + to:@END +main: from @BEGIN + call prepare param-assignment + to:main::@2 +main::@2: from @18 @2 main + (byte) main::c#2 ← phi( @2/(byte) main::c#1 @18/(byte) 25 main/(byte) 25 ) + to:main::@3 +main::@3: from main::@2 main::@3 + (byte~) main::$1 ← * (word) 53266 + if((byte~) main::$1!=(byte) 254) goto main::@3 + to:main::@4 +main::@4: from main::@3 main::@4 + (byte~) main::$3 ← * (word) 53266 + if((byte~) main::$3!=(byte) 255) goto main::@4 + to:@2 +@2: from main::@4 + (byte) main::c#1 ← -- (byte) main::c#2 + if((byte) main::c#1!=(byte) 0) goto main::@2 + to:@3 +@3: from @2 + call flip param-assignment + to:@17 +@17: from @3 + call plot param-assignment + to:@18 +@18: from @17 + if(true) goto main::@2 + to:main::@return +main::@return: from @18 + return + to:@RETURN +prepare: from main + to:prepare::@1 +prepare::@1: from prepare prepare::@1 + (byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@1/(byte) prepare::i#1 ) + *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 + (byte) prepare::i#1 ← ++ (byte) prepare::i#2 + if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 + to:prepare::@return +prepare::@return: from prepare::@1 + return + to:@RETURN +flip: from @3 + to:flip::@1 +flip::@1: from @8 flip + (byte) flip::r#2 ← phi( @8/(byte) flip::r#1 flip/(byte) 16 ) + (byte) flip::srcIdx#3 ← phi( @8/(byte) flip::srcIdx#1 flip/(byte) 0 ) + (byte) flip::dstIdx#5 ← phi( @8/(byte) flip::dstIdx#2 flip/(byte) 15 ) + to:flip::@2 +flip::@2: from flip::@1 flip::@2 + (byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@2/(byte) flip::c#1 ) + (byte) flip::dstIdx#3 ← phi( flip::@1/(byte) flip::dstIdx#5 flip::@2/(byte) flip::dstIdx#1 ) + (byte) flip::srcIdx#2 ← phi( flip::@1/(byte) flip::srcIdx#3 flip::@2/(byte) flip::srcIdx#1 ) + (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 + *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 + (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 + (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 + (byte) flip::c#1 ← -- (byte) flip::c#2 + if((byte) flip::c#1!=(byte) 0) goto flip::@2 + to:@8 +@8: from flip::@2 + (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 + (byte) flip::r#1 ← -- (byte) flip::r#2 + if((byte) flip::r#1!=(byte) 0) goto flip::@1 + to:flip::@3 +flip::@3: from @8 flip::@3 + (byte) flip::i#2 ← phi( @8/(byte) 0 flip::@3/(byte) flip::i#1 ) + (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 + *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 + (byte) flip::i#1 ← ++ (byte) flip::i#2 + if((byte) flip::i#1!=(byte) 0) goto flip::@3 + to:flip::@return +flip::@return: from flip::@3 + return + to:@RETURN +plot: from @17 + (byte*) plot::line#0 ← (word) 1224 + (byte) 12 + to:plot::@1 +plot::@1: from @12 plot + (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) + (byte) plot::i#3 ← phi( @12/(byte) plot::i#1 plot/(byte) 0 ) + (byte*) plot::line#2 ← phi( @12/(byte*) plot::line#1 plot/(byte*) plot::line#0 ) + to:plot::@2 +plot::@2: from plot::@1 plot::@2 + (byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@2/(byte) plot::x#1 ) + (byte) plot::i#2 ← phi( plot::@1/(byte) plot::i#3 plot::@2/(byte) plot::i#1 ) + (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 + *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 + (byte) plot::i#1 ← ++ (byte) plot::i#2 + (byte) plot::x#1 ← ++ (byte) plot::x#2 + if((byte) plot::x#1<(byte) 16) goto plot::@2 + to:@12 +@12: from plot::@2 + (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 + (byte) plot::y#1 ← -- (byte) plot::y#2 + if((byte) plot::y#1!=(byte) 0) goto plot::@1 + to:plot::@return +plot::@return: from @12 + return + to:@RETURN +@END: from @BEGIN + +Multiple usages for variable. Not optimizing sub-constant (byte) prepare::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) flip::srcIdx#2 +Multiple usages for variable. Not optimizing sub-constant (byte) flip::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) flip::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) plot::i#2 Constant (byte*) plot::line#0 (word) 1236 Succesful SSA optimization Pass2ConstantPropagation CONTROL FLOW GRAPH