diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java index 7a38df5b0..9cb9bf894 100644 --- a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java +++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java @@ -3,6 +3,7 @@ package dk.camelot64.kickc.model; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementLValue; import dk.camelot64.kickc.model.statements.StatementPhiBlock; +import dk.camelot64.kickc.model.statements.StatementSource; import dk.camelot64.kickc.model.symbols.Label; import dk.camelot64.kickc.model.symbols.Procedure; import dk.camelot64.kickc.model.symbols.ProgramScope; @@ -120,6 +121,30 @@ public class ControlFlowGraph implements Serializable { this.variableInitValue = variableInitValue; } + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + if(block!=null) + s.append(block.getLabel()).append("::"); + if(statementLValue!=null) + s.append(statementLValue.toString()); + if(statementPhi!=null) + s.append(statementPhi.toString()).append(" "); + if(statementPhiVariable!=null) + s.append(statementPhiVariable.toString()); + if(variableInitValue!=null) + s.append(variableInitValue.toString()); + return s.toString(); + } + + public StatementSource getSource() { + if(statementLValue!=null) + return statementLValue.getSource(); + if(statementPhi!=null) + return statementPhi.getSource(); + return null; + } + } /** diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertNoLValueIntermediate.java b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertNoLValueIntermediate.java index b0ddcff13..2df152a91 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertNoLValueIntermediate.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertNoLValueIntermediate.java @@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.ControlFlowGraph; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementLValue; @@ -9,6 +10,8 @@ import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.LvalueIntermediate; import dk.camelot64.kickc.model.values.VariableRef; +import java.util.List; + /** * Asserts that all intermediate lvalues have been replaced by something else */ @@ -26,8 +29,9 @@ public class Pass1AssertNoLValueIntermediate extends Pass1Base { LValue lValue = ((StatementLValue) statement).getlValue(); if(lValue instanceof LvalueIntermediate) { VariableRef intermediateVar = ((LvalueIntermediate) lValue).getVariable(); - StatementLValue assignment = getGraph().getAssignment(intermediateVar); - throw new CompileError("Error! LValue is illegal. " + statement + " - definition of lValue " + assignment, assignment.getSource()); + final List varAssignments = ControlFlowGraph.getVarAssignments(intermediateVar, getGraph(), getScope()); + final ControlFlowGraph.VarAssignment varAssignment = varAssignments.get(0); + throw new CompileError("Error! LValue is illegal. " + statement + " - definition of lValue " + varAssignment, varAssignment.getSource()); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java index abfe707e8..bc27b4ea2 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java @@ -1,6 +1,7 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.ControlFlowGraph; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.operators.Operator; import dk.camelot64.kickc.model.operators.Operators; @@ -32,7 +33,7 @@ public class Pass1FixLValuesLoHi extends Pass1Base { @Override public boolean step() { - List intermediates = new ArrayList<>(); + List intermediates = new ArrayList<>(); ProgramScope programScope = getProgram().getScope(); for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { @@ -43,17 +44,20 @@ public class Pass1FixLValuesLoHi extends Pass1Base { if(statement instanceof StatementLValue && ((StatementLValue) statement).getlValue() instanceof LvalueIntermediate) { StatementLValue statementLValue = (StatementLValue) statement; LvalueIntermediate intermediate = (LvalueIntermediate) statementLValue.getlValue(); - StatementLValue intermediateStmtLValue = getProgram().getGraph().getAssignment(intermediate.getVariable()); - if(intermediateStmtLValue instanceof StatementAssignment) { - StatementAssignment intermediateAssignment = (StatementAssignment) intermediateStmtLValue; - if(Operators.LOWBYTE.equals(intermediateAssignment.getOperator()) && intermediateAssignment.getrValue1() == null) { - // Found assignment to an intermediate low byte lValue x = ... - fixLoHiLValue(programScope, statementsIt, statementLValue, intermediate, intermediateAssignment, Operators.SET_HIBYTE); - intermediates.add(intermediate.getVariable()); + final List varAssignments = ControlFlowGraph.getVarAssignments(intermediate.getVariable(), getGraph(), programScope); + if(varAssignments.size() == 1) { + final ControlFlowGraph.VarAssignment varAssignment = varAssignments.get(0); + if(varAssignment.type.equals(ControlFlowGraph.VarAssignment.Type.STATEMENT_LVALUE) && varAssignment.statementLValue instanceof StatementAssignment) { + StatementAssignment intermediateAssignment = (StatementAssignment) varAssignment.statementLValue; + if(Operators.LOWBYTE.equals(intermediateAssignment.getOperator()) && intermediateAssignment.getrValue1() == null) { + // Found assignment to an intermediate low byte lValue x = ... + fixLoHiLValue(programScope, statementsIt, statementLValue, intermediate, intermediateAssignment, Operators.SET_HIBYTE); + intermediates.add(intermediate.getVariable()); + } } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java index 8e7ae7961..9f3db7b6b 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java @@ -47,40 +47,40 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { // Remove all candidates that are used after assignment in phi blocks private static void cleanupCandidates(Aliases candidates, Program program) { - ListIterator aliasSetListIterator = candidates.getAliasSets().listIterator(); - while(aliasSetListIterator.hasNext()) { - AliasSet aliasSet = aliasSetListIterator.next(); - boolean removeSet = false; - for(ControlFlowBlock block : program.getGraph().getAllBlocks()) { - if(block.hasPhiBlock()) { - StatementPhiBlock phi = block.getPhiBlock(); - boolean lMatch = false; - for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) { - if(lMatch) { - if(aliasSet.contains(phiVariable.getVariable())) { - // Assigning inside tha alias set again - no need to check the variables - continue; - } - for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { - RValue rValue = phiRValue.getrValue(); - if(aliasSet.contains(rValue)) { - removeSet = true; - break; - } - } - } else { - if(aliasSet.contains(phiVariable.getVariable())) { - lMatch = true; + ListIterator aliasSetListIterator = candidates.getAliasSets().listIterator(); + while(aliasSetListIterator.hasNext()) { + AliasSet aliasSet = aliasSetListIterator.next(); + boolean removeSet = false; + for(ControlFlowBlock block : program.getGraph().getAllBlocks()) { + if(block.hasPhiBlock()) { + StatementPhiBlock phi = block.getPhiBlock(); + boolean lMatch = false; + for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) { + if(lMatch) { + if(aliasSet.contains(phiVariable.getVariable())) { + // Assigning inside tha alias set again - no need to check the variables + continue; + } + for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { + RValue rValue = phiRValue.getrValue(); + if(aliasSet.contains(rValue)) { + removeSet = true; + break; } } + } else { + if(aliasSet.contains(phiVariable.getVariable())) { + lMatch = true; + } } } } - if(removeSet) { - program.getLog().append("Alias candidate removed (phi-usage) " + aliasSet.toString(program)); - aliasSetListIterator.remove(); - } } + if(removeSet) { + program.getLog().append("Alias candidate removed (phi-usage) " + aliasSet.toString(program)); + aliasSetListIterator.remove(); + } + } } // Remove all candidates that are volatile and not assigned to the same variable @@ -95,7 +95,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { String unversionedFullName = null; for(VariableRef variableRef : aliasSet.getVars()) { Variable variable = programScope.getVariable(variableRef); - if(variable.isVolatile() || variable.isKindLoadStore()) { + if(variable.isVolatile() || variable.isKindLoadStore()) { anyVolatile = true; } if(unversionedFullName == null) { @@ -150,7 +150,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { aliases.add(variable, alias); } } - } + } } } else if(statement instanceof StatementPhiBlock) { StatementPhiBlock phi = (StatementPhiBlock) statement;