1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-08-02 09:29:35 +00:00

Added typed and untyped print functions everywhere. Now getting the same output as the old compilation!

This commit is contained in:
Jesper Gravgaard 2017-07-19 13:21:16 +02:00
parent 6e087e9a1c
commit e6d09187e3
54 changed files with 1119 additions and 598 deletions

View File

@ -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<Pass2SsaOptimization> 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));
}
}
}

View File

@ -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);
}

View File

@ -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() + ')';
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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); }
}

View File

@ -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+"\\";
}
}

View File

@ -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<ControlFlowBlock> 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;

View File

@ -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<ControlFlowBlock> 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();
}
}

View File

@ -115,7 +115,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
@Override
public StatementPhi visitPhi(StatementPhi phi) {
VariableVersion lValue = phi.getlValue();
VariableRef lValue = phi.getlValue();
StatementPhi copyPhi = new StatementPhi(lValue);
for (StatementPhi.PreviousSymbol origPreviousVersion : phi.getPreviousVersions()) {
RValue rValue = origPreviousVersion.getRValue();

View File

@ -68,10 +68,6 @@ public class Label implements Symbol {
return SymbolTypeBasic.LABEL;
}
public String getTypedName() {
return "("+getType().getTypeName() + ") "+getFullName();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -93,6 +89,21 @@ public class Label implements Symbol {
@Override
public String toString() {
return getAsString();
}
@Override
public String getAsTypedString(ProgramScope scope) {
return getTypedName();
}
@Override
public String getAsString() {
return getFullName();
}
public String getTypedName() {
return "("+getType().getTypeName() + ") "+getFullName();
}
}

View File

@ -30,7 +30,16 @@ public class PointerDereferenceIndexed implements PointerDereference {
@Override
public String toString() {
return "*(" + pointer + " + " +index + ')';
return getAsString();
}
@Override
public String getAsTypedString(ProgramScope scope) {
return "*(" + pointer.getAsTypedString(scope) + " + " +index.getAsTypedString(scope) + ')';
}
@Override
public String getAsString() {
return "*(" + pointer.getAsString() + " + " +index.getAsString() + ')';
}
}

View File

@ -13,12 +13,23 @@ public class PointerDereferenceSimple implements PointerDereference {
return pointer;
}
@Override
public String toString() {
return "*(" + pointer + ')';
}
public void setPointer(RValue pointer) {
this.pointer = pointer;
}
@Override
public String toString() {
return getAsString();
}
@Override
public String getAsTypedString(ProgramScope scope) {
return "*(" + pointer.getAsTypedString(scope) + ')';
}
@Override
public String getAsString() {
return "*(" + pointer.getAsString() + ')';
}
}

View File

@ -118,4 +118,13 @@ public class Procedure extends Scope {
return getTypedName();
}
@Override
public String getAsTypedString(ProgramScope scope) {
return getTypedName();
}
@Override
public String getAsString() {
return getTypedName();
}
}

View File

@ -70,4 +70,15 @@ public class ProgramScope extends Scope {
result = 31 * result + (allocation != null ? allocation.hashCode() : 0);
return result;
}
@Override
public String getAsTypedString(ProgramScope scope) {
return getAsString();
}
@Override
public String getAsString() {
return "program";
}
}

View File

@ -2,4 +2,5 @@ package dk.camelot64.kickc.icl;
/** A value usable as part of a calculation (ib the right side of an assignment)*/
public interface RValue extends Value {
}

View File

@ -82,6 +82,16 @@ public class RegisterAllocation {
public int hashCode() {
return zp;
}
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
}
/** Two zero page addresses used as a register for a single word variable. */
@ -119,6 +129,16 @@ public class RegisterAllocation {
public int hashCode() {
return zp;
}
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
}
@ -156,6 +176,16 @@ public class RegisterAllocation {
public int hashCode() {
return zp;
}
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
}
/** A zro page address pair used as a register containing a pointer to a byte. */
@ -192,6 +222,16 @@ public class RegisterAllocation {
public int getZp() {
return zp;
}
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
}
@ -213,6 +253,16 @@ public class RegisterAllocation {
if (obj == null || getClass() != obj.getClass()) return false;
return true;
}
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
}
/** The Y register. */
@ -233,6 +283,16 @@ public class RegisterAllocation {
if (obj == null || getClass() != obj.getClass()) return false;
return true;
}
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
}
/** The A register. */
@ -253,6 +313,16 @@ public class RegisterAllocation {
if (obj == null || getClass() != obj.getClass()) return false;
return true;
}
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
}
/** The special ALU register. */
@ -273,6 +343,16 @@ public class RegisterAllocation {
if (obj == null || getClass() != obj.getClass()) return false;
return true;
}
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
}
public static Register getRegisterX() {

View File

@ -149,6 +149,10 @@ public abstract class Scope implements Symbol {
return (Variable) getSymbol(name);
}
public Variable getVariable(VariableRef variableRef) {
return getVariable(variableRef.getFullName());
}
@JsonIgnore
public Collection<Variable> getAllVariables() {
Collection<Variable> 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;
}
}

View File

@ -6,5 +6,8 @@ package dk.camelot64.kickc.icl;
*/
public interface Statement {
String getAsTypedString(ProgramScope scope);
String getAsString();
}

View File

@ -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() ;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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(); }
}

View File

@ -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();

View File

@ -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() + ":";
}
}

View File

@ -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<PreviousSymbol> 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();
}
}

View File

@ -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();
}
}

View File

@ -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()+"()"; }
}

View File

@ -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()); }
}

View File

@ -16,19 +16,30 @@ public class StatementSequence {
this.statements.add(statement);
}
@Override
public String toString() {
public List<Statement> 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<Statement> 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();
}
}

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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<VariableUnversioned, VariableVersion> blockVersions,
Map<VariableUnversioned, VariableVersion> 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<Label, Map<VariableUnversioned, VariableVersion>> 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<VariableUnversioned, VariableVersion> 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<VariableUnversioned, VariableVersion> 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<VariableUnversioned, VariableVersion> 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<VariableUnversioned, VariableVersion> blockMap = symbolMap.get(label);
if (blockMap == null) {
blockMap = new LinkedHashMap<>();
symbolMap.put(label, blockMap);
}
blockMap.put(unversioned, versioned);
} }
}
}
}
return symbolMap;
}
}

View File

@ -176,7 +176,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
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<Object> {
@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<Object> {
@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<Object> {
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<Object> {
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<Object> {
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<Object> {
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<Object> {
@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<Object> {
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));
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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<Scope> 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) {

View File

@ -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<Variable> getSymbolsToRemove() {
ArrayList<Variable> eliminates = new ArrayList<>();
public List<VariableRef> getSymbolsToRemove() {
ArrayList<VariableRef> eliminates = new ArrayList<>();
for (AliasSet alias : aliases) {
eliminates.addAll(alias.getEliminateVars());
}
return eliminates;
}
public Map<Variable, Variable> getReplacements() {
HashMap<Variable, Variable> replacements = new LinkedHashMap<>();
public Map<VariableRef, VariableRef> getReplacements() {
HashMap<VariableRef, VariableRef> 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<Variable> vars;
private List<VariableRef> 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<Variable> getVars() {
public List<VariableRef> getVars() {
return vars;
}
@ -166,22 +166,22 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
vars.addAll(aliasSet.getVars());
}
public Variable getKeepVar() {
Variable keep = null;
List<Variable> vars = new ArrayList<>(this.vars);
Collections.sort(vars, new Comparator<Variable>() {
public VariableRef getKeepVar() {
VariableRef keep = null;
List<VariableRef> vars = new ArrayList<>(this.vars);
Collections.sort(vars, new Comparator<VariableRef>() {
@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<Variable> getEliminateVars() {
List<Variable> 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<VariableRef> getEliminateVars() {
List<VariableRef> 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<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@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);
}
}

View File

@ -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);
}

View File

@ -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<Symbol> 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<Void> {
private ProgramScope programScope;
public SymbolFinder(ProgramScope programScope) {
this.programScope = programScope;
}
private HashSet<Symbol> symbols = new HashSet<>();
public HashSet<Symbol> 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());

View File

@ -14,7 +14,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
private Map<Variable, List<Statement>> 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<LValue, StatementAssignment> assignments = getAllAssignments();
final Map<RValue, List<Statement>> usages = getAllUsages();
final List<Variable> simpleConditionVars = getSimpleConditions(assignments, usages);
final List<VariableRef> simpleConditionVars = getSimpleConditions(assignments, usages);
removeAssignments(simpleConditionVars);
deleteSymbols(simpleConditionVars);
deleteVariables(simpleConditionVars);
return (simpleConditionVars.size()>0);
}
private List<Variable> getSimpleConditions(final Map<LValue, StatementAssignment> assignments, final Map<RValue, List<Statement>> usages) {
private List<VariableRef> getSimpleConditions(final Map<LValue, StatementAssignment> assignments, final Map<RValue, List<Statement>> usages) {
final List<Variable> simpleConditionVars = new ArrayList<>();
final List<VariableRef> simpleConditionVars = new ArrayList<>();
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@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:
}

View File

@ -17,9 +17,9 @@ import java.util.Map;
*/
public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
private Map<Variable, Integer> usages;
private Map<VariableRef, Integer> 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;

View File

@ -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<Variable, Constant> constants = findConstantVariables();
for (Variable constantVar : constants.keySet()) {
final Map<VariableRef, Constant> 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<Variable, Constant> findConstantVariables() {
final Map<Variable, Constant> constants = new LinkedHashMap<>();
private Map<VariableRef, Constant> findConstantVariables() {
final Map<VariableRef, Constant> constants = new LinkedHashMap<>();
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@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);
}

View File

@ -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;
}

View File

@ -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<Variable, RValue> aliases = findRedundantPhis();
final Map<VariableRef, RValue> 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<Variable, RValue> findRedundantPhis() {
final Map<Variable, RValue> aliases = new LinkedHashMap<>();
private Map<VariableRef, RValue> findRedundantPhis() {
final Map<VariableRef, RValue> aliases = new LinkedHashMap<>();
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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<Variable, ? extends RValue> aliases) {
public void replaceVariables(final Map<VariableRef, ? extends RValue> aliases) {
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@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<StatementPhi.PreviousSymbol> 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<Variable, ? extends RValue> aliases, RValue rValue) {
private static RValue getAlias(Map<VariableRef, ? extends RValue> 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<? extends VariableRef> symbols) {
for (VariableRef variableRef : symbols) {
Symbol symbol = getSymbols().getSymbol(variableRef.getFullName());
symbol.getScope().remove(symbol);
}
}
public Map<LValue, StatementAssignment> getAllAssignments() {
final HashMap<LValue, StatementAssignment> assignments = new LinkedHashMap<>();
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@ -334,12 +351,12 @@ public abstract class Pass2SsaOptimization {
return usages;
}
protected Map<Variable, Integer> countVarUsages() {
final HashMap<Variable, Integer> usages = new LinkedHashMap<>();
protected Map<VariableRef, Integer> countVarUsages() {
final HashMap<VariableRef, Integer> 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;

View File

@ -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);
}

View File

@ -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());
}

View File

@ -44,6 +44,8 @@ public class TestIclJson extends TestCase {
assertJsonSerialization(scope, json, Scope.class);
}
public static void assertJsonSerialization(
Object object,
String json,

View File

@ -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

View File

@ -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