1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-04-08 14:37:40 +00:00

Eliminated old getAssignment() method.

This commit is contained in:
jespergravgaard 2020-02-12 22:24:29 +01:00
parent 3d7914c31f
commit 687705f5d2
12 changed files with 152 additions and 143 deletions

@ -65,119 +65,6 @@ public class ControlFlowGraph implements Serializable {
}
}
/**
* Get the assignment of the passed variable. Assumes that only a single assignment exists.
*
* @param variable The variable to find the assignment for
* @return The assignment. null if the variable is not assigned. The variable is assigned by a Phi-statement instead.
*/
public StatementLValue getAssignment(VariableRef variable) {
for(ControlFlowBlock block : getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
StatementLValue assignment = (StatementLValue) statement;
if(variable.equals(assignment.getlValue())) {
return assignment;
}
}
}
}
return null;
}
/** Any assignment of a value to a SymbolVariable.
* Potential assignments include StatementLValue, StatementPhi and Variable.initValue
* */
public static class VarAssignment {
public enum Type {
STATEMENT_LVALUE,
STATEMENT_PHI,
INIT_VALUE
}
/** The type of assignment. */
public final Type type;
/** The block containing the assignment statement. Null if type is not STATEMENT_LVALUE or STATEMENT_PHI */
public final ControlFlowBlock block;
/* The LValue-statement. Null if type is not STATEMENT_LVALUE. */
public final StatementLValue statementLValue;
/* The PHI-statement. Null if type is not STATEMENT_PHI. */
public final StatementPhiBlock statementPhi;
public final StatementPhiBlock.PhiVariable statementPhiVariable;
/* The Variable with initValue. Null if type is not INIT_VALUE. */
public final Variable variableInitValue;
public VarAssignment(Type type, ControlFlowBlock block, StatementLValue statementLValue, StatementPhiBlock statementPhi, StatementPhiBlock.PhiVariable statementPhiVariable, Variable variableInitValue) {
this.type = type;
this.block = block;
this.statementLValue = statementLValue;
this.statementPhi = statementPhi;
this.statementPhiVariable = statementPhiVariable;
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;
}
}
/**
* Get all assignments of value to a variable.
*
* @param variable The variable to find the assignment for
* @return All assignments of values to the variable
*/
public static List<VarAssignment> getVarAssignments(SymbolVariableRef variable, ControlFlowGraph graph, ProgramScope programScope) {
ArrayList<VarAssignment> varAssignments = new ArrayList<>();
Variable varDef = programScope.getVariable(variable);
if(varDef.getInitValue()!=null) {
varAssignments.add(new VarAssignment(VarAssignment.Type.INIT_VALUE, null, null, null, null, varDef));
}
for(ControlFlowBlock block : graph.getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
StatementLValue assignment = (StatementLValue) statement;
if(variable.equals(assignment.getlValue())) {
varAssignments.add(new VarAssignment(VarAssignment.Type.STATEMENT_LVALUE, block, assignment, null, null, null));
}
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
if(phiVariable.getVariable().equals(variable)) {
varAssignments.add(new VarAssignment(VarAssignment.Type.STATEMENT_PHI, block, null, (StatementPhiBlock) statement, phiVariable, null));
}
}
}
}
}
return varAssignments;
}
public ControlFlowBlock getDefaultSuccessor(ControlFlowBlock block) {
if(block.getDefaultSuccessor() != null) {
return getBlock(block.getDefaultSuccessor());
@ -293,7 +180,7 @@ public class ControlFlowGraph implements Serializable {
if(!blocks.equals(that.blocks)) return false;
if(!firstBlockRef.equals(that.firstBlockRef)) return false;
return sequence != null ? sequence.equals(that.sequence) : that.sequence == null;
return Objects.equals(sequence, that.sequence);
}
@Override

@ -2,13 +2,13 @@ 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;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.LvalueIntermediate;
import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.passes.utils.VarAssignments;
import java.util.List;
@ -29,8 +29,8 @@ public class Pass1AssertNoLValueIntermediate extends Pass1Base {
LValue lValue = ((StatementLValue) statement).getlValue();
if(lValue instanceof LvalueIntermediate) {
VariableRef intermediateVar = ((LvalueIntermediate) lValue).getVariable();
final List<ControlFlowGraph.VarAssignment> varAssignments = ControlFlowGraph.getVarAssignments(intermediateVar, getGraph(), getScope());
final ControlFlowGraph.VarAssignment varAssignment = varAssignments.get(0);
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(intermediateVar, getGraph(), getScope());
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
throw new CompileError("Error! LValue is illegal. " + statement + " - definition of lValue " + varAssignment, varAssignment.getSource());
}
}

@ -18,6 +18,7 @@ import dk.camelot64.kickc.model.types.SymbolTypeConversion;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.utils.AliasReplacer;
import java.util.ArrayList;
import java.util.Collection;

@ -1,7 +1,6 @@
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;
@ -15,6 +14,7 @@ import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.LvalueIntermediate;
import dk.camelot64.kickc.model.values.SymbolVariableRef;
import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.passes.utils.VarAssignments;
import java.util.ArrayList;
import java.util.List;
@ -44,10 +44,10 @@ public class Pass1FixLValuesLoHi extends Pass1Base {
if(statement instanceof StatementLValue && ((StatementLValue) statement).getlValue() instanceof LvalueIntermediate) {
StatementLValue statementLValue = (StatementLValue) statement;
LvalueIntermediate intermediate = (LvalueIntermediate) statementLValue.getlValue();
final List<ControlFlowGraph.VarAssignment> varAssignments = ControlFlowGraph.getVarAssignments(intermediate.getVariable(), getGraph(), programScope);
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(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) {
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
if(varAssignment.type.equals(VarAssignments.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 = ...

@ -1,13 +1,13 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.ControlFlowGraph;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.utils.VarAssignments;
import java.util.*;
@ -128,15 +128,15 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
if(assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof VariableRef) {
// Alias assignment
VariableRef alias = (VariableRef) assignment.getrValue2();
List<ControlFlowGraph.VarAssignment> assignments = ControlFlowGraph.getVarAssignments(alias, program.getGraph(), program.getScope());
List<VarAssignments.VarAssignment> assignments = VarAssignments.get(alias, program.getGraph(), program.getScope());
if(assignments.size() == 0)
throw new InternalError("Error! Var is never assigned! " + variable);
else if(assignments.size() > 1)
// Multiple assignments exist
continue;
// assignments.size()==1
ControlFlowGraph.VarAssignment varAssignment = assignments.get(0);
if(ControlFlowGraph.VarAssignment.Type.INIT_VALUE.equals(varAssignment.type)) {
VarAssignments.VarAssignment varAssignment = assignments.get(0);
if(VarAssignments.VarAssignment.Type.INIT_VALUE.equals(varAssignment.type)) {
aliases.add(variable, alias);
} else {
// Examine if the alias is assigned inside another scope
@ -169,7 +169,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
alias = null;
break;
}
List<ControlFlowGraph.VarAssignment> assignments = ControlFlowGraph.getVarAssignments(alias, program.getGraph(), program.getScope());
List<VarAssignments.VarAssignment> assignments = VarAssignments.get(alias, program.getGraph(), program.getScope());
if(assignments.size() == 0)
throw new InternalError("Error! Var is never assigned! " + variable);
if(assignments.size() > 1) {
@ -178,8 +178,8 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
break;
}
// assignments.size()==1
ControlFlowGraph.VarAssignment varAssignment = assignments.get(0);
if(!ControlFlowGraph.VarAssignment.Type.INIT_VALUE.equals(varAssignment.type)) {
VarAssignments.VarAssignment varAssignment = assignments.get(0);
if(!VarAssignments.VarAssignment.Type.INIT_VALUE.equals(varAssignment.type)) {
// Examine if the alias is assigned inside another scope
ScopeRef varAssignmentScope = block.getScope();
ScopeRef aliasAssignmentScope = varAssignment.block.getScope();
@ -247,9 +247,13 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
StatementSource bestSource = null;
List<Statement> assignments = new ArrayList<>();
for(VariableRef aliasVar : aliasSet.getVars()) {
Statement assignment = getGraph().getAssignment(aliasVar);
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(aliasVar, getGraph(), getScope());
if(varAssignments.size()!=1)
continue;
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
if(!VarAssignments.VarAssignment.Type.STATEMENT_LVALUE.equals(varAssignment.type))
continue;
Statement assignment = varAssignment.statementLValue;
if(assignment != null) {
assignments.add(assignment);
StatementSource source = assignment.getSource();

@ -10,6 +10,7 @@ import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementLValue;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.utils.VarAssignments;
import java.util.Collection;
import java.util.List;
@ -191,11 +192,11 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
final Variable var = getScope().getVar(variable);
if(var.isKindLoadStore())
return null;
final List<ControlFlowGraph.VarAssignment> varAssignments = ControlFlowGraph.getVarAssignments(variable, getGraph(), getScope());
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(variable, getGraph(), getScope());
if(varAssignments.size()!=1)
return null;
final ControlFlowGraph.VarAssignment varAssignment = varAssignments.get(0);
if(!ControlFlowGraph.VarAssignment.Type.STATEMENT_LVALUE.equals(varAssignment.type))
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
if(!VarAssignments.VarAssignment.Type.STATEMENT_LVALUE.equals(varAssignment.type))
return null;
StatementLValue statementLValue = varAssignment.statementLValue;
if(statementLValue instanceof StatementAssignment) {

@ -7,7 +7,6 @@ import dk.camelot64.kickc.model.operators.OperatorUnary;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementLValue;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.Scope;
@ -16,6 +15,7 @@ import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeConversion;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.utils.VarAssignments;
import java.util.*;
@ -167,10 +167,10 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
if(variable.isVolatile() || !variable.isKindLoadStore())
// Do not examine volatiles, non-constants or versioned variables
continue;
final List<ControlFlowGraph.VarAssignment> varAssignments = ControlFlowGraph.getVarAssignments(variable.getRef(), getGraph(), getScope());
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(variable.getRef(), getGraph(), getScope());
if(varAssignments.size() == 1) {
final ControlFlowGraph.VarAssignment varAssignment = varAssignments.get(0);
if(!ControlFlowGraph.VarAssignment.Type.STATEMENT_LVALUE.equals(varAssignment.type) || !(varAssignment.statementLValue instanceof StatementAssignment))
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
if(!VarAssignments.VarAssignment.Type.STATEMENT_LVALUE.equals(varAssignment.type) || !(varAssignment.statementLValue instanceof StatementAssignment))
// Only look at assignments
continue;
StatementAssignment assignment = (StatementAssignment) varAssignment.statementLValue;

@ -7,6 +7,7 @@ import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.Symbol;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.utils.AliasReplacer;
import java.util.*;

@ -1,7 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowGraph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.OperatorCastPtr;
@ -13,6 +12,7 @@ import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.utils.VarAssignments;
import java.util.Collection;
import java.util.List;
@ -54,11 +54,11 @@ public class Pass2InlineDerefIdx extends Pass2SsaOptimization {
final Variable var = getScope().getVar(derefVar);
if(var.isKindLoadStore())
return null;
final List<ControlFlowGraph.VarAssignment> varAssignments = ControlFlowGraph.getVarAssignments(derefVar, getGraph(), getScope());
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(derefVar, getGraph(), getScope());
if(varAssignments.size()!=1)
return null;
final ControlFlowGraph.VarAssignment varAssignment = varAssignments.get(0);
if(!ControlFlowGraph.VarAssignment.Type.STATEMENT_LVALUE.equals(varAssignment.type))
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
if(!VarAssignments.VarAssignment.Type.STATEMENT_LVALUE.equals(varAssignment.type))
return null;
StatementLValue derefVarDefined = varAssignment.statementLValue;
if(derefVarDefined instanceof StatementAssignment) {

@ -6,6 +6,7 @@ import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Symbol;
import dk.camelot64.kickc.passes.utils.AliasReplacer;
import java.util.*;

@ -1,4 +1,4 @@
package dk.camelot64.kickc.passes;
package dk.camelot64.kickc.passes.utils;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.iterator.ProgramValue;

@ -0,0 +1,114 @@
package dk.camelot64.kickc.passes.utils;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.ControlFlowGraph;
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.ProgramScope;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.SymbolVariableRef;
import java.util.ArrayList;
import java.util.List;
/**
* Utility for finding all assignments for a variable.
*/
public class VarAssignments {
/**
* Get all assignments of value to a variable.
*
* @param variable The variable to find the assignment for
* @return All assignments of values to the variable
*/
public static List<VarAssignment> get(SymbolVariableRef variable, ControlFlowGraph graph, ProgramScope programScope) {
ArrayList<VarAssignment> varAssignments = new ArrayList<>();
Variable varDef = programScope.getVariable(variable);
if(varDef.getInitValue() != null) {
varAssignments.add(new VarAssignment(VarAssignment.Type.INIT_VALUE, null, null, null, null, varDef));
}
for(ControlFlowBlock block : graph.getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
StatementLValue assignment = (StatementLValue) statement;
if(variable.equals(assignment.getlValue())) {
varAssignments.add(new VarAssignment(VarAssignment.Type.STATEMENT_LVALUE, block, assignment, null, null, null));
}
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
if(phiVariable.getVariable().equals(variable)) {
varAssignments.add(new VarAssignment(VarAssignment.Type.STATEMENT_PHI, block, null, (StatementPhiBlock) statement, phiVariable, null));
}
}
}
}
}
return varAssignments;
}
/**
* Any assignment of a value to a SymbolVariable.
* Potential assignments include StatementLValue, StatementPhi and Variable.initValue
*/
public static class VarAssignment {
public enum Type {
STATEMENT_LVALUE,
STATEMENT_PHI,
INIT_VALUE
}
/** The type of assignment. */
public final Type type;
/** The block containing the assignment statement. Null if type is not STATEMENT_LVALUE or STATEMENT_PHI */
public final ControlFlowBlock block;
/* The LValue-statement. Null if type is not STATEMENT_LVALUE. */
public final StatementLValue statementLValue;
/* The PHI-statement. Null if type is not STATEMENT_PHI. */
public final StatementPhiBlock statementPhi;
public final StatementPhiBlock.PhiVariable statementPhiVariable;
/* The Variable with initValue. Null if type is not INIT_VALUE. */
public final Variable variableInitValue;
public VarAssignment(Type type, ControlFlowBlock block, StatementLValue statementLValue, StatementPhiBlock statementPhi, StatementPhiBlock.PhiVariable statementPhiVariable, Variable variableInitValue) {
this.type = type;
this.block = block;
this.statementLValue = statementLValue;
this.statementPhi = statementPhi;
this.statementPhiVariable = statementPhiVariable;
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;
}
}
}