1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-10-11 12:23:45 +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 { public static class CompilationResult {
private AsmProgram asmProgram; private AsmProgram asmProgram;
private ControlFlowGraph graph; private ControlFlowGraph graph;
private Scope symbols; private ProgramScope symbols;
private CompileLog log; 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.asmProgram = asmProgram;
this.graph = graph; this.graph = graph;
this.symbols = symbols; this.symbols = symbols;
@ -34,7 +34,7 @@ public class Compiler {
return graph; return graph;
} }
public Scope getSymbols() { public ProgramScope getSymbols() {
return symbols; return symbols;
} }
@ -67,37 +67,37 @@ public class Compiler {
pass1GenerateStatementSequence.generate(file); pass1GenerateStatementSequence.generate(file);
StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence(); StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence();
ProgramScope programScope = pass1GenerateStatementSequence.getProgramScope(); ProgramScope programScope = pass1GenerateStatementSequence.getProgramScope();
Pass1TypeInference pass1TypeInference = new Pass1TypeInference(); Pass1TypeInference pass1TypeInference = new Pass1TypeInference(programScope);
pass1TypeInference.inferTypes(statementSequence, programScope); pass1TypeInference.inferTypes(statementSequence);
log.append("PROGRAM"); log.append("PROGRAM");
log.append(statementSequence.toString()); log.append(statementSequence.getAsTypedString(programScope));
log.append("SYMBOLS"); log.append("SYMBOLS");
log.append(programScope.getSymbolTableContents()); log.append(programScope.getSymbolTableContents());
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(programScope); Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(programScope);
ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence); ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence);
log.append("INITIAL CONTROL FLOW GRAPH"); log.append("INITIAL CONTROL FLOW GRAPH");
log.append(controlFlowGraph.toString()); log.append(controlFlowGraph.getAsTypedString(programScope));
Pass1ProcedureCallParameters pass1ProcedureCallParameters = Pass1ProcedureCallParameters pass1ProcedureCallParameters =
new Pass1ProcedureCallParameters(programScope, controlFlowGraph); new Pass1ProcedureCallParameters(programScope, controlFlowGraph);
controlFlowGraph = pass1ProcedureCallParameters.generate(); controlFlowGraph = pass1ProcedureCallParameters.generate();
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL"); log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL");
log.append(controlFlowGraph.toString()); log.append(controlFlowGraph.getAsTypedString(programScope));
Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm = Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm =
new Pass1GenerateSingleStaticAssignmentForm(log, programScope, controlFlowGraph); new Pass1GenerateSingleStaticAssignmentForm(log, programScope, controlFlowGraph);
pass1GenerateSingleStaticAssignmentForm.generate(); pass1GenerateSingleStaticAssignmentForm.generate();
log.append("CONTROL FLOW GRAPH SSA"); log.append("CONTROL FLOW GRAPH SSA");
log.append(controlFlowGraph.toString()); log.append(controlFlowGraph.getAsTypedString(programScope));
Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue = Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue =
new Pass1ProcedureCallsReturnValue(programScope, controlFlowGraph); new Pass1ProcedureCallsReturnValue(programScope, controlFlowGraph);
controlFlowGraph = pass1ProcedureCallsReturnValue.generate(); controlFlowGraph = pass1ProcedureCallsReturnValue.generate();
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN"); log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN");
log.append(controlFlowGraph.toString()); log.append(controlFlowGraph.getAsTypedString(programScope));
List<Pass2SsaOptimization> optimizations = new ArrayList<>(); List<Pass2SsaOptimization> optimizations = new ArrayList<>();
optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, programScope, log)); optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, programScope, log));
@ -124,7 +124,7 @@ public class Compiler {
log.append("Succesful SSA optimization " + optimization.getClass().getSimpleName() + ""); log.append("Succesful SSA optimization " + optimization.getClass().getSimpleName() + "");
ssaOptimized = true; ssaOptimized = true;
log.append("CONTROL FLOW GRAPH"); 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. * @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) { public String bind(Value value) {
if(value instanceof VariableRef) {
value = symbols.getVariable((VariableRef) value);
}
if (value instanceof Variable) { if (value instanceof Variable) {
value = symbols.getRegister((Variable) value); value = symbols.getRegister((Variable) value);
} else if (value instanceof PointerDereferenceSimple) { } else if (value instanceof PointerDereferenceSimple) {
PointerDereferenceSimple deref = (PointerDereferenceSimple) value; PointerDereferenceSimple deref = (PointerDereferenceSimple) value;
RValue pointer = deref.getPointer(); RValue pointer = deref.getPointer();
if(pointer instanceof Variable) { if(pointer instanceof VariableRef) {
Variable pointerVar = (Variable) pointer; VariableRef pointerRef = (VariableRef) pointer;
Variable pointerVar = symbols.getVariable(pointerRef);
RegisterAllocation.Register register = symbols.getRegister(pointerVar); RegisterAllocation.Register register = symbols.getRegister(pointerVar);
value = new PointerDereferenceRegisterZpByte((RegisterAllocation.RegisterZpPointerByte) register); value = new PointerDereferenceRegisterZpByte((RegisterAllocation.RegisterZpPointerByte) register);
} }

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.asm; package dk.camelot64.kickc.asm;
import dk.camelot64.kickc.icl.PointerDereference; import dk.camelot64.kickc.icl.PointerDereference;
import dk.camelot64.kickc.icl.ProgramScope;
import dk.camelot64.kickc.icl.RegisterAllocation; import dk.camelot64.kickc.icl.RegisterAllocation;
/** A dereferenced ZP pointer to a byte */ /** A dereferenced ZP pointer to a byte */
@ -22,7 +23,16 @@ public class PointerDereferenceRegisterZpByte implements PointerDereference {
@Override @Override
public String toString() { 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 @Override
public String toString() { 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); return Boolean.toString(value);
} }
} }

View File

@ -8,15 +8,25 @@ public class ConstantDouble implements Constant {
private Double number; private Double number;
public ConstantDouble(Double number) { public ConstantDouble(Double number) {
this.number= number; this.number = number;
}
@Override
public String toString() {
return Double.toString(number);
} }
public Double getNumber() { public Double getNumber() {
return number; 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 @Override
public String toString() { 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 @Override
public String toString() { public String toString() {
return getAsString();
}
@Override
public String getAsTypedString(ProgramScope scope) {
return "("+SymbolTypeBasic.STRING.getTypeName()+") "+"\\"+value+"\\"; }
@Override
public String getAsString() {
return "\\"+value+"\\"; return "\\"+value+"\\";
} }
} }

View File

@ -62,15 +62,10 @@ public class ControlFlowBlock {
} }
public void addPhiStatement(VariableVersion newVersion) { public void addPhiStatement(VariableVersion newVersion) {
statements.add(0, new StatementPhi(newVersion)); statements.add(0, new StatementPhi(new VariableRef(newVersion)));
} }
@Override public String getAsTypedString(ControlFlowGraph graph, ProgramScope scope) {
public String toString() {
return toString(null);
}
public String toString(ControlFlowGraph graph) {
StringBuffer out = new StringBuffer(); StringBuffer out = new StringBuffer();
out.append(label.getFullName() + ":" ); out.append(label.getFullName() + ":" );
out.append(" from"); out.append(" from");
@ -86,7 +81,7 @@ public class ControlFlowBlock {
} }
out.append("\n"); out.append("\n");
for (Statement statement : statements) { for (Statement statement : statements) {
out.append(" "+statement+"\n"); out.append(" "+statement.getAsTypedString(scope)+"\n");
} }
if(defaultSuccessor!=null) { if(defaultSuccessor!=null) {
out.append(" to:"); out.append(" to:");
@ -96,6 +91,33 @@ public class ControlFlowBlock {
return out.toString(); 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 @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;

View File

@ -23,15 +23,6 @@ public class ControlFlowGraph {
return firstBlock; 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() { public Collection<ControlFlowBlock> getAllBlocks() {
return blocks.values(); return blocks.values();
} }
@ -122,4 +113,23 @@ public class ControlFlowGraph {
} }
return null; 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 @Override
public StatementPhi visitPhi(StatementPhi phi) { public StatementPhi visitPhi(StatementPhi phi) {
VariableVersion lValue = phi.getlValue(); VariableRef lValue = phi.getlValue();
StatementPhi copyPhi = new StatementPhi(lValue); StatementPhi copyPhi = new StatementPhi(lValue);
for (StatementPhi.PreviousSymbol origPreviousVersion : phi.getPreviousVersions()) { for (StatementPhi.PreviousSymbol origPreviousVersion : phi.getPreviousVersions()) {
RValue rValue = origPreviousVersion.getRValue(); RValue rValue = origPreviousVersion.getRValue();

View File

@ -68,10 +68,6 @@ public class Label implements Symbol {
return SymbolTypeBasic.LABEL; return SymbolTypeBasic.LABEL;
} }
public String getTypedName() {
return "("+getType().getTypeName() + ") "+getFullName();
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
@ -93,6 +89,21 @@ public class Label implements Symbol {
@Override @Override
public String toString() { public String toString() {
return getAsString();
}
@Override
public String getAsTypedString(ProgramScope scope) {
return getTypedName(); 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 @Override
public String toString() { 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; return pointer;
} }
@Override
public String toString() {
return "*(" + pointer + ')';
}
public void setPointer(RValue pointer) { public void setPointer(RValue pointer) {
this.pointer = 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(); 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); result = 31 * result + (allocation != null ? allocation.hashCode() : 0);
return result; 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)*/ /** A value usable as part of a calculation (ib the right side of an assignment)*/
public interface RValue extends Value { public interface RValue extends Value {
} }

View File

@ -82,6 +82,16 @@ public class RegisterAllocation {
public int hashCode() { public int hashCode() {
return zp; 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. */ /** Two zero page addresses used as a register for a single word variable. */
@ -119,6 +129,16 @@ public class RegisterAllocation {
public int hashCode() { public int hashCode() {
return zp; 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() { public int hashCode() {
return zp; 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. */ /** 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() { public int getZp() {
return zp; 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; if (obj == null || getClass() != obj.getClass()) return false;
return true; return true;
} }
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
} }
/** The Y register. */ /** The Y register. */
@ -233,6 +283,16 @@ public class RegisterAllocation {
if (obj == null || getClass() != obj.getClass()) return false; if (obj == null || getClass() != obj.getClass()) return false;
return true; return true;
} }
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
} }
/** The A register. */ /** The A register. */
@ -253,6 +313,16 @@ public class RegisterAllocation {
if (obj == null || getClass() != obj.getClass()) return false; if (obj == null || getClass() != obj.getClass()) return false;
return true; return true;
} }
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
} }
/** The special ALU register. */ /** The special ALU register. */
@ -273,6 +343,16 @@ public class RegisterAllocation {
if (obj == null || getClass() != obj.getClass()) return false; if (obj == null || getClass() != obj.getClass()) return false;
return true; return true;
} }
@Override
public String getAsTypedString(ProgramScope scope) {
return toString();
}
@Override
public String getAsString() {
return toString();
}
} }
public static Register getRegisterX() { public static Register getRegisterX() {

View File

@ -149,6 +149,10 @@ public abstract class Scope implements Symbol {
return (Variable) getSymbol(name); return (Variable) getSymbol(name);
} }
public Variable getVariable(VariableRef variableRef) {
return getVariable(variableRef.getFullName());
}
@JsonIgnore @JsonIgnore
public Collection<Variable> getAllVariables() { public Collection<Variable> getAllVariables() {
Collection<Variable> vars = new ArrayList<>(); Collection<Variable> vars = new ArrayList<>();
@ -210,7 +214,7 @@ public abstract class Scope implements Symbol {
if (symbol instanceof Scope) { if (symbol instanceof Scope) {
res.append(((Scope) symbol).getSymbolTableContents()); res.append(((Scope) symbol).getSymbolTableContents());
} else { } else {
res.append(symbol.toString()); res.append(symbol.getTypedName());
} }
if (symbol instanceof Variable && allocation!=null) { if (symbol instanceof Variable && allocation!=null) {
RegisterAllocation.Register register = allocation.getRegister((Variable) symbol); RegisterAllocation.Register register = allocation.getRegister((Variable) symbol);
@ -266,4 +270,5 @@ public abstract class Scope implements Symbol {
result = 31 * result + intermediateLabelCount; result = 31 * result + intermediateLabelCount;
return result; return result;
} }
} }

View File

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

View File

@ -28,6 +28,14 @@ public class StatementAssignment implements StatementLValue {
this.rValue2 = rValue2; 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 @JsonCreator
public StatementAssignment( public StatementAssignment(
@JsonProperty("lValue1") LValue lValue, @JsonProperty("lValue1") LValue lValue,
@ -67,6 +75,10 @@ public class StatementAssignment implements StatementLValue {
return operator; return operator;
} }
public void setOperator(Operator operator) {
this.operator = operator;
}
public RValue getrValue2() { public RValue getrValue2() {
return rValue2; return rValue2;
} }
@ -77,15 +89,25 @@ public class StatementAssignment implements StatementLValue {
@Override @Override
public String toString() { public String toString() {
return getAsString();
}
@Override
public String getAsTypedString(ProgramScope scope) {
return return
lValue.getAsTypedString(scope) + "" +
lValue + "" + (rValue1==null?"":rValue1.getAsTypedString(scope)+" ") +
(rValue1==null?"":rValue1+" ") +
(operator==null?"":operator+" ") + (operator==null?"":operator+" ") +
rValue2 ; rValue2 .getAsTypedString(scope);
} }
public void setOperator(Operator operator) { @Override
this.operator = operator; 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; this.parametersByAssignment = parametersByAssignment;
} }
public void clearParameters() {
this.parameters = null;
this.parametersByAssignment = true;
}
@Override @Override
public String toString() { public String toString() {
return getAsString();
}
@Override
public String getAsTypedString(ProgramScope scope) {
StringBuilder res = new StringBuilder(); StringBuilder res = new StringBuilder();
if(lValue!=null) { if(lValue!=null) {
res.append(lValue); res.append(lValue.getAsTypedString(scope));
res.append(""); res.append("");
} }
res.append("call "); res.append("call ");
@ -82,7 +92,7 @@ public class StatementCall implements StatementLValue {
} }
if(parameters!=null) { if(parameters!=null) {
for (RValue parameter : parameters) { for (RValue parameter : parameters) {
res.append(parameter + " "); res.append(parameter.getAsTypedString(scope) + " ");
} }
} }
if(parametersByAssignment) { if(parametersByAssignment) {
@ -91,9 +101,27 @@ public class StatementCall implements StatementLValue {
return res.toString(); return res.toString();
} }
public void clearParameters() { @Override
this.parameters = null; public String getAsString() {
this.parametersByAssignment = true; 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 @Override
public String toString() { public String toString() {
return getAsString();
}
@Override
public String getAsTypedString(ProgramScope scope) {
StringBuilder out = new StringBuilder(); StringBuilder out = new StringBuilder();
out.append("if("); out.append("if(");
if(rValue1!=null) { if(rValue1!=null) {
out.append(rValue1); out.append(rValue1.getAsTypedString(scope));
out.append(operator.getOperator()); out.append(operator.getOperator());
} }
out.append(rValue2); out.append(rValue2.getAsTypedString(scope));
out.append(") goto "); out.append(") goto ");
out.append(destination.getFullName()); out.append(destination.getFullName());
return out.toString(); 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; return destination;
} }
@Override
public String toString() {
return "goto "+destination.getFullName();
}
public void setDestination(Label destination) { public void setDestination(Label destination) {
this.destination = 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. * 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(); LValue getlValue();

View File

@ -17,8 +17,16 @@ public class StatementLabel implements Statement {
@Override @Override
public String toString() { 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 { public class StatementPhi implements StatementLValue {
/** The versioned variable being assigned a value by the statement. */ /** 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. */ /** The previous version of the rValue from predeccesor control blocks. */
private List<PreviousSymbol> previousVersions; private List<PreviousSymbol> previousVersions;
public StatementPhi(VariableVersion lValue) { public StatementPhi(VariableRef lValue) {
this.lValue = lValue; this.lValue = lValue;
this.previousVersions = new ArrayList<>(); this.previousVersions = new ArrayList<>();
} }
@ -56,16 +56,16 @@ public class StatementPhi implements StatementLValue {
} }
} }
public VariableVersion getlValue() { public VariableRef getlValue() {
return lValue; return lValue;
} }
@Override @Override
public void setlValue(LValue lValue) { 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); 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) { public void addPreviousVersion(Label block, RValue rValue) {
@ -78,6 +78,22 @@ public class StatementPhi implements StatementLValue {
@Override @Override
public String toString() { 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(); StringBuilder out = new StringBuilder();
out.append(lValue + "" + "phi("); out.append(lValue + "" + "phi(");
for (PreviousSymbol previousSymbol : previousVersions) { for (PreviousSymbol previousSymbol : previousVersions) {
@ -86,5 +102,4 @@ public class StatementPhi implements StatementLValue {
out.append(" )"); out.append(" )");
return out.toString(); return out.toString();
} }
} }

View File

@ -30,7 +30,16 @@ public class StatementProcedureBegin implements Statement {
@Override @Override
public String toString() { 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 @Override
public String toString() { 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 @Override
public String toString() { 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); this.statements.add(statement);
} }
@Override public List<Statement> getStatements() {
public String toString() { return statements;
}
public String getAsTypedString(ProgramScope scope) {
StringBuffer out = new StringBuffer(); StringBuffer out = new StringBuffer();
for (Statement statement : statements) { for (Statement statement : statements) {
if(!(statement instanceof StatementLabel)) { if(!(statement instanceof StatementLabel)) {
out.append(" "); out.append(" ");
} }
out.append(statement.toString()+"\n"); out.append(statement.getAsTypedString(scope)+"\n");
} }
return out.toString(); return out.toString();
} }
public List<Statement> getStatements() { public String getAsString() {
return statements; 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") @JsonSubTypes.Type(value = Procedure.class, name = "procedure")
}) })
public interface Value { 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.) * 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. * The name of the symbol.
@ -105,11 +105,6 @@ public abstract class Variable implements Symbol, RValue, LValue {
return result; return result;
} }
@Override
public String toString() {
return getTypedName();
}
public Scope getScope() { public Scope getScope() {
return scope; 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() { private void versionAllAssignments() {
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) { for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
for (Statement statement : block.getStatements()) { for (Statement statement : block.getStatements()) {
if (statement instanceof StatementAssignment) { if (statement instanceof StatementLValue) {
StatementAssignment assignment = (StatementAssignment) statement; StatementLValue statementLValue = (StatementLValue) statement;
LValue lValue = assignment.getlValue(); LValue lValue = statementLValue.getlValue();
if (lValue instanceof VariableUnversioned) { if (lValue instanceof VariableRef) {
// Assignment to a non-versioned non-intermediary variable VariableRef lValueRef = (VariableRef) lValue;
VariableUnversioned assignedSymbol = (VariableUnversioned) lValue; Variable assignedVar = symbols.getVariable(lValueRef);
VariableVersion version = assignedSymbol.createVersion(); if(assignedVar instanceof VariableUnversioned) {
assignment.setlValue(version); // Assignment to a non-versioned non-intermediary variable
} VariableUnversioned assignedSymbol = (VariableUnversioned) assignedVar;
} else if(statement instanceof StatementCall) { VariableVersion version = assignedSymbol.createVersion();
StatementCall call = (StatementCall) statement; statementLValue.setlValue(new VariableRef(version));
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);
} }
} }
} }
@ -77,7 +72,7 @@ public class Pass1GenerateSingleStaticAssignmentForm {
{ {
VariableVersion version = findOrCreateVersion(statementReturn.getValue(), blockVersions, blockNewPhis); VariableVersion version = findOrCreateVersion(statementReturn.getValue(), blockVersions, blockNewPhis);
if (version != null) { 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); VariableVersion version = findOrCreateVersion(assignment.getrValue1(), blockVersions, blockNewPhis);
if (version != null) { if (version != null) {
assignment.setrValue1(version); assignment.setrValue1(new VariableRef(version));
} }
} }
{ {
VariableVersion version = findOrCreateVersion(assignment.getrValue2(), blockVersions, blockNewPhis); VariableVersion version = findOrCreateVersion(assignment.getrValue2(), blockVersions, blockNewPhis);
if (version != null) { if (version != null) {
assignment.setrValue2(version); assignment.setrValue2(new VariableRef(version));
} }
} }
// Update map of versions encountered in the block // Update map of versions encountered in the block
LValue lValue = assignment.getlValue(); LValue lValue = assignment.getlValue();
if (lValue instanceof VariableVersion) { if (lValue instanceof VariableRef) {
VariableVersion versioned = (VariableVersion) lValue; VariableRef lValueRef = (VariableRef) lValue;
blockVersions.put(versioned.getVersionOf(), versioned); Variable variable = symbols.getVariable(lValueRef);
if(variable instanceof VariableVersion) {
VariableVersion versioned = (VariableVersion) variable;
blockVersions.put(versioned.getVersionOf(), versioned);
}
} else if(lValue instanceof PointerDereferenceSimple) { } else if(lValue instanceof PointerDereferenceSimple) {
PointerDereferenceSimple deref = (PointerDereferenceSimple) lValue; PointerDereferenceSimple deref = (PointerDereferenceSimple) lValue;
RValue pointer = deref.getPointer(); RValue pointer = deref.getPointer();
VariableVersion version = findOrCreateVersion(pointer, blockVersions, blockNewPhis); VariableVersion version = findOrCreateVersion(pointer, blockVersions, blockNewPhis);
if (version != null) { if (version != null) {
deref.setPointer(version); deref.setPointer(new VariableRef(version));
} }
} else if(lValue instanceof PointerDereferenceIndexed) { } else if(lValue instanceof PointerDereferenceIndexed) {
PointerDereferenceIndexed deref = (PointerDereferenceIndexed) lValue; PointerDereferenceIndexed deref = (PointerDereferenceIndexed) lValue;
RValue pointer = deref.getPointer(); RValue pointer = deref.getPointer();
VariableVersion version = findOrCreateVersion(pointer, blockVersions, blockNewPhis); VariableVersion version = findOrCreateVersion(pointer, blockVersions, blockNewPhis);
if (version != null) { if (version != null) {
deref.setPointer(version); deref.setPointer(new VariableRef(version));
} }
RValue index = deref.getIndex(); RValue index = deref.getIndex();
VariableVersion iVersion = findOrCreateVersion(index, blockVersions, blockNewPhis); VariableVersion iVersion = findOrCreateVersion(index, blockVersions, blockNewPhis);
if (iVersion != null) { 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> blockVersions,
Map<VariableUnversioned, VariableVersion> blockNewPhis) { Map<VariableUnversioned, VariableVersion> blockNewPhis) {
VariableVersion version = null; VariableVersion version = null;
if (rValue instanceof VariableUnversioned) { if (rValue instanceof VariableRef) {
// rValue needs versioning - look for version in statements Variable rValueVar = symbols.getVariable((VariableRef) rValue);
VariableUnversioned rSymbol = (VariableUnversioned) rValue; if (rValueVar instanceof VariableUnversioned) {
version = blockVersions.get(rSymbol); // rValue needs versioning - look for version in statements
if (version == null) { VariableUnversioned rSymbol = (VariableUnversioned) rValueVar;
// look for version in new phi functions version = blockVersions.get(rSymbol);
version = blockNewPhis.get(rSymbol); if (version == null) {
} // look for version in new phi functions
if (version == null) { version = blockNewPhis.get(rSymbol);
// create a new phi function }
version = rSymbol.createVersion(); if (version == null) {
blockNewPhis.put(rSymbol, version); // create a new phi function
version = rSymbol.createVersion();
blockNewPhis.put(rSymbol, version);
}
} }
} }
return version; return version;
@ -175,7 +177,8 @@ public class Pass1GenerateSingleStaticAssignmentForm {
if (statement instanceof StatementPhi) { if (statement instanceof StatementPhi) {
StatementPhi phi = (StatementPhi) statement; StatementPhi phi = (StatementPhi) statement;
if (phi.getPreviousVersions().isEmpty()) { if (phi.getPreviousVersions().isEmpty()) {
VariableVersion versioned = phi.getlValue(); VariableRef phiLValVarRef = phi.getlValue();
VariableVersion versioned = (VariableVersion) symbols.getVariable(phiLValVarRef);
VariableUnversioned unversioned = versioned.getVersionOf(); VariableUnversioned unversioned = versioned.getVersionOf();
for (ControlFlowBlock predecessor : controlFlowGraph.getPredecessors(block)) { for (ControlFlowBlock predecessor : controlFlowGraph.getPredecessors(block)) {
Label predecessorLabel = predecessor.getLabel(); Label predecessorLabel = predecessor.getLabel();
@ -198,7 +201,7 @@ public class Pass1GenerateSingleStaticAssignmentForm {
predecessorNewPhis.put(unversioned, previousSymbol); 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<>(); Map<Label, Map<VariableUnversioned, VariableVersion>> symbolMap = new LinkedHashMap<>();
for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) { for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) {
for (Statement statement : block.getStatements()) { for (Statement statement : block.getStatements()) {
if (statement instanceof StatementAssignment) { if (statement instanceof StatementLValue) {
StatementAssignment assignment = (StatementAssignment) statement; StatementLValue assignment = (StatementLValue) statement;
LValue lValue = assignment.getlValue(); LValue lValue = assignment.getlValue();
if (lValue instanceof VariableVersion) { if(lValue instanceof VariableRef) {
VariableVersion versioned = (VariableVersion) lValue; Variable lValueVar = symbols.getVariable((VariableRef) lValue);
Label label = block.getLabel(); if (lValueVar instanceof VariableVersion) {
VariableUnversioned unversioned = versioned.getVersionOf(); VariableVersion versioned = (VariableVersion) lValueVar;
Map<VariableUnversioned, VariableVersion> blockMap = symbolMap.get(label); Label label = block.getLabel();
if (blockMap == null) { VariableUnversioned unversioned = versioned.getVersionOf();
blockMap = new LinkedHashMap<>(); Map<VariableUnversioned, VariableVersion> blockMap = symbolMap.get(label);
symbolMap.put(label, blockMap); if (blockMap == null) {
} blockMap = new LinkedHashMap<>();
blockMap.put(unversioned, versioned); symbolMap.put(label, blockMap);
} }
} else if (statement instanceof StatementPhi) { blockMap.put(unversioned, versioned);
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);
}
} }
} }
} }
return symbolMap; return symbolMap;
} }
} }

View File

@ -176,7 +176,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
if (returnVar != null) { if (returnVar != null) {
sequence.addStatement(new StatementAssignment(returnVar, returnVar)); 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(); scopeStack.pop();
sequence.addStatement(new StatementProcedureEnd(procedure)); sequence.addStatement(new StatementProcedureEnd(procedure));
return null; return null;
@ -246,7 +248,8 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
@Override @Override
public LValue visitLvalueName(KickCParser.LvalueNameContext ctx) { public LValue visitLvalueName(KickCParser.LvalueNameContext ctx) {
return getCurrentSymbols().getVariable(ctx.NAME().getText()); Variable variable = getCurrentSymbols().getVariable(ctx.NAME().getText());
return new VariableRef(variable);
} }
@Override @Override
@ -257,8 +260,8 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
@Override @Override
public LValue visitLvaluePtr(KickCParser.LvaluePtrContext ctx) { public LValue visitLvaluePtr(KickCParser.LvaluePtrContext ctx) {
LValue lval = (LValue) visit(ctx.lvalue()); LValue lval = (LValue) visit(ctx.lvalue());
if (lval instanceof Variable) { if (lval instanceof VariableRef) {
return new PointerDereferenceSimple((Variable) lval); return new PointerDereferenceSimple((VariableRef) lval);
} else { } else {
throw new RuntimeException("Not implemented"); throw new RuntimeException("Not implemented");
} }
@ -319,7 +322,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
parameters = new ArrayList<>(); parameters = new ArrayList<>();
} }
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); 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; return tmpVar;
} }
@ -339,9 +342,10 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
RValue index = (RValue) visit(ctx.expr(1)); RValue index = (RValue) visit(ctx.expr(1));
Operator operator = new Operator("*idx"); Operator operator = new Operator("*idx");
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); 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); sequence.addStatement(stmt);
return tmpVar; return tmpVarRef;
} }
@Override @Override
@ -372,9 +376,10 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText(); String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText();
Operator operator = new Operator(op); Operator operator = new Operator(op);
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); 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); sequence.addStatement(stmt);
return tmpVar; return tmpVarRef;
} }
@Override @Override
@ -383,9 +388,10 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText(); String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText();
Operator operator = new Operator(op); Operator operator = new Operator(op);
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); 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); sequence.addStatement(stmt);
return tmpVar; return tmpVarRef;
} }
@Override @Override
@ -407,7 +413,8 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
@Override @Override
public RValue visitExprId(KickCParser.ExprIdContext ctx) { 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() { public StatementSequence getSequence() {
@ -454,7 +461,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
for (PrePostModifier mod : modifiers) { for (PrePostModifier mod : modifiers) {
Statement stmt = new StatementAssignment((LValue) mod.child, mod.operator, mod.child); Statement stmt = new StatementAssignment((LValue) mod.child, mod.operator, mod.child);
parser.sequence.addStatement(stmt); 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++) { for (int i = 0; i < parameterDecls.size(); i++) {
Variable parameterDecl = parameterDecls.get(i); Variable parameterDecl = parameterDecls.get(i);
RValue parameterValue = parameterValues.get(i); RValue parameterValue = parameterValues.get(i);
addStatementToCurrentBlock(new StatementAssignment(parameterDecl, parameterValue)); addStatementToCurrentBlock(new StatementAssignment(new VariableRef(parameterDecl), parameterValue));
} }
String procedureName = origCall.getProcedureName(); String procedureName = origCall.getProcedureName();
Variable procReturnVar = procedure.getVariable("return"); 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.setParametersByAssignment(true);
copyCall.setProcedure(procedure); copyCall.setProcedure(procedure);
addStatementToCurrentBlock(copyCall); addStatementToCurrentBlock(copyCall);
getCurrentBlock().setCallSuccessor(procedure.getLabel()); getCurrentBlock().setCallSuccessor(procedure.getLabel());
splitCurrentBlock(scope.addLabelIntermediate()); splitCurrentBlock(scope.addLabelIntermediate());
if(!SymbolTypeBasic.VOID.equals(procedure.getReturnType())) { if(!SymbolTypeBasic.VOID.equals(procedure.getReturnType())) {
addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVar)); addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVarRef));
} else { } else {
// No return type. Remove variable receiving the result. // No return type. Remove variable receiving the result.
LValue lValue = origCall.getlValue(); LValue lValue = origCall.getlValue();
if(lValue instanceof Variable) { if(lValue instanceof VariableRef) {
Variable lVar = (Variable) lValue; VariableRef lValueRef = (VariableRef) lValue;
lVar.getScope().remove(lVar); 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 // Find return variable final version
Label returnBlockLabel = procedure.getLabel("@return"); Label returnBlockLabel = procedure.getLabel("@return");
ControlFlowBlock returnBlock = graph.getBlock(returnBlockLabel); ControlFlowBlock returnBlock = graph.getBlock(returnBlockLabel);
VariableVersion returnVarFinal = null; VariableRef returnVarFinal = null;
for (Statement statement : returnBlock.getStatements()) { for (Statement statement : returnBlock.getStatements()) {
if (statement instanceof StatementReturn) { if (statement instanceof StatementReturn) {
StatementReturn statementReturn = (StatementReturn) statement; StatementReturn statementReturn = (StatementReturn) statement;
RValue returnValue = statementReturn.getValue(); RValue returnValue = statementReturn.getValue();
if (returnValue instanceof VariableVersion) { if (returnValue instanceof VariableRef) {
returnVarFinal = (VariableVersion) returnValue; returnVarFinal = (VariableRef) returnValue;
} }
} }
} }

View File

@ -10,7 +10,13 @@ import java.util.Stack;
*/ */
public class Pass1TypeInference { 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<>(); Stack<Scope> scopes = new Stack<>();
scopes.add(programScope); scopes.add(programScope);
for (Statement statement : sequence.getStatements()) { for (Statement statement : sequence.getStatements()) {
@ -22,8 +28,8 @@ public class Pass1TypeInference {
} else if (statement instanceof StatementAssignment) { } else if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement; StatementAssignment assignment = (StatementAssignment) statement;
LValue lValue = assignment.getlValue(); LValue lValue = assignment.getlValue();
if (lValue instanceof Variable) { if (lValue instanceof VariableRef) {
Variable symbol = (Variable) lValue; Variable symbol = programScope.getVariable((VariableRef) lValue);
if (SymbolTypeBasic.VAR.equals(symbol.getType())) { if (SymbolTypeBasic.VAR.equals(symbol.getType())) {
// Unresolved symbol - perform inference // Unresolved symbol - perform inference
Operator operator = assignment.getOperator(); Operator operator = assignment.getOperator();
@ -45,14 +51,15 @@ public class Pass1TypeInference {
} else if(statement instanceof StatementCall) { } else if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement; StatementCall call = (StatementCall) statement;
LValue lValue = call.getlValue(); LValue lValue = call.getlValue();
if(lValue instanceof Variable) { if(lValue instanceof VariableRef) {
String procedureName = call.getProcedureName(); String procedureName = call.getProcedureName();
Procedure procedure = scopes.peek().getProcedure(procedureName); Procedure procedure = scopes.peek().getProcedure(procedureName);
call.setProcedure(procedure); call.setProcedure(procedure);
if(procedure.getParameters().size()!=call.getParameters().size()) { if(procedure.getParameters().size()!=call.getParameters().size()) {
throw new RuntimeException("Wrong number of parameters in call. Expected " +procedure.getParameters().size()+". "+statement.toString()); 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; 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; Symbol rSymbol = (Symbol) rValue;
type = rSymbol.getType(); type = rSymbol.getType();
} else if (rValue instanceof ConstantInteger) { } else if (rValue instanceof ConstantInteger) {

View File

@ -10,7 +10,7 @@ import java.util.*;
*/ */
public class Pass2AliasElimination extends Pass2SsaOptimization { 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); super(graph, scope, log);
} }
@ -23,16 +23,16 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
final Aliases aliases = findAliases(); final Aliases aliases = findAliases();
removeAliasAssignments(aliases); removeAliasAssignments(aliases);
replaceVariables(aliases.getReplacements()); replaceVariables(aliases.getReplacements());
deleteSymbols(aliases.getSymbolsToRemove());
for (AliasSet aliasSet : aliases.getAliasSets()) { for (AliasSet aliasSet : aliases.getAliasSets()) {
StringBuilder str = new StringBuilder(); StringBuilder str = new StringBuilder();
str.append(aliasSet.getKeepVar()); str.append(aliasSet.getKeepVar().getAsTypedString(getSymbols()));
str.append(" = "); str.append(" = ");
for (Variable var : aliasSet.getEliminateVars()) { for (VariableRef var : aliasSet.getEliminateVars()) {
str.append(var + " "); str.append(var.getAsTypedString(getSymbols()) + " ");
} }
log.append("Alias " + str); log.append("Alias " + str);
} }
deleteVariables(aliases.getSymbolsToRemove());
return (aliases.size() > 0); return (aliases.size() > 0);
} }
@ -75,19 +75,19 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
this.aliases = new ArrayList<>(); this.aliases = new ArrayList<>();
} }
public List<Variable> getSymbolsToRemove() { public List<VariableRef> getSymbolsToRemove() {
ArrayList<Variable> eliminates = new ArrayList<>(); ArrayList<VariableRef> eliminates = new ArrayList<>();
for (AliasSet alias : aliases) { for (AliasSet alias : aliases) {
eliminates.addAll(alias.getEliminateVars()); eliminates.addAll(alias.getEliminateVars());
} }
return eliminates; return eliminates;
} }
public Map<Variable, Variable> getReplacements() { public Map<VariableRef, VariableRef> getReplacements() {
HashMap<Variable, Variable> replacements = new LinkedHashMap<>(); HashMap<VariableRef, VariableRef> replacements = new LinkedHashMap<>();
for (AliasSet aliasSet : aliases) { for (AliasSet aliasSet : aliases) {
Variable keepVar = aliasSet.getKeepVar(); VariableRef keepVar = aliasSet.getKeepVar();
for (Variable var : aliasSet.getEliminateVars()) { for (VariableRef var : aliasSet.getEliminateVars()) {
if(!var.equals(keepVar)) { if(!var.equals(keepVar)) {
replacements.put(var, keepVar); replacements.put(var, keepVar);
} }
@ -100,7 +100,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
return aliases.size(); return aliases.size();
} }
public void add(Variable var1, Variable var2) { public void add(VariableRef var1, VariableRef var2) {
AliasSet aliasSet1 = findAliasSet(var1); AliasSet aliasSet1 = findAliasSet(var1);
AliasSet aliasSet2 = findAliasSet(var2); AliasSet aliasSet2 = findAliasSet(var2);
if (aliasSet1 != null) { if (aliasSet1 != null) {
@ -123,7 +123,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
} }
public AliasSet findAliasSet(LValue lValue) { public AliasSet findAliasSet(LValue lValue) {
if (lValue instanceof Variable) { if (lValue instanceof VariableRef) {
for (AliasSet alias : aliases) { for (AliasSet alias : aliases) {
if (alias.contains(lValue)) { if (alias.contains(lValue)) {
return alias; return alias;
@ -140,25 +140,25 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
public static class AliasSet { public static class AliasSet {
private List<Variable> vars; private List<VariableRef> vars;
public AliasSet() { public AliasSet() {
this.vars = new ArrayList<>(); this.vars = new ArrayList<>();
} }
public void add(Variable variable) { public void add(VariableRef variable) {
vars.add(variable); vars.add(variable);
} }
public boolean contains(RValue rValue) { public boolean contains(RValue rValue) {
if (rValue instanceof Variable) { if (rValue instanceof VariableRef) {
return vars.contains(rValue); return vars.contains(rValue);
} else { } else {
return false; return false;
} }
} }
public List<Variable> getVars() { public List<VariableRef> getVars() {
return vars; return vars;
} }
@ -166,22 +166,22 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
vars.addAll(aliasSet.getVars()); vars.addAll(aliasSet.getVars());
} }
public Variable getKeepVar() { public VariableRef getKeepVar() {
Variable keep = null; VariableRef keep = null;
List<Variable> vars = new ArrayList<>(this.vars); List<VariableRef> vars = new ArrayList<>(this.vars);
Collections.sort(vars, new Comparator<Variable>() { Collections.sort(vars, new Comparator<VariableRef>() {
@Override @Override
public int compare(Variable o1, Variable o2) { public int compare(VariableRef o1, VariableRef o2) {
return o1.getFullName().compareTo(o2.getFullName()); return o1.getFullName().compareTo(o2.getFullName());
} }
}); });
for (Variable var : vars) { for (VariableRef var : vars) {
if (keep == null) { if (keep == null) {
keep = var; keep = var;
} else { } else {
if (var instanceof VariableVersion) { if (isVersion(var)) {
if (keep instanceof VariableVersion) { if (isVersion(keep)) {
if (var.getScopeDepth() < keep.getScopeDepth()) { if (getScopeDepth(var) < getScopeDepth(keep)) {
keep = var; keep = var;
} }
} else { } else {
@ -193,10 +193,23 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
return keep; return keep;
} }
public List<Variable> getEliminateVars() { private int getScopeDepth(VariableRef var) {
List<Variable> eliminate = new ArrayList<>(); int depth = 0;
Variable keepVar = getKeepVar(); char[] chars = var.getFullName().toCharArray();
for (Variable var : vars) { 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)) { if(!var.equals(keepVar)) {
eliminate.add(var); eliminate.add(var);
} }
@ -205,7 +218,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
} }
public void remove(RValue rValue) { public void remove(RValue rValue) {
if(rValue instanceof Variable) { if(rValue instanceof VariableRef) {
vars.remove(rValue); vars.remove(rValue);
} }
} }
@ -235,7 +248,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) { for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
RValue phiRValue = previousSymbol.getRValue(); RValue phiRValue = previousSymbol.getRValue();
if (aliasSet.contains(phiRValue)) { if (aliasSet.contains(phiRValue)) {
log.append("Alias candidate removed " + phiRValue); log.append("Alias candidate removed " + phiRValue.getAsTypedString(getSymbols()));
aliasSet.remove(phiRValue); aliasSet.remove(phiRValue);
break; break;
} }
@ -261,11 +274,11 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() { ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override @Override
public Void visitAssignment(StatementAssignment assignment) { public Void visitAssignment(StatementAssignment assignment) {
if (assignment.getlValue() instanceof VariableVersion || assignment.getlValue() instanceof VariableIntermediate) { if (assignment.getlValue() instanceof VariableRef) {
Variable variable = (Variable) assignment.getlValue(); VariableRef variable = (VariableRef) assignment.getlValue();
if (assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof Variable) { if (assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof VariableRef) {
// Alias assignment // Alias assignment
Variable alias = (Variable) assignment.getrValue2(); VariableRef alias = (VariableRef) assignment.getrValue2();
aliases.add(variable, alias); aliases.add(variable, alias);
} }
} }
@ -276,9 +289,9 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
public Void visitPhi(StatementPhi phi) { public Void visitPhi(StatementPhi phi) {
if (phi.getPreviousVersions().size() == 1) { if (phi.getPreviousVersions().size() == 1) {
StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0); StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0);
if (previousSymbol.getRValue() instanceof Variable) { if (previousSymbol.getRValue() instanceof VariableRef) {
VariableVersion variable = phi.getlValue(); VariableRef variable = phi.getlValue();
Variable alias = (Variable) previousSymbol.getRValue(); VariableRef alias = (VariableRef) previousSymbol.getRValue();
aliases.add(variable, alias); aliases.add(variable, alias);
} }
} }

View File

@ -5,7 +5,7 @@ import dk.camelot64.kickc.icl.*;
/** Assert that all referenced blocks exist in the program */ /** Assert that all referenced blocks exist in the program */
public class Pass2AssertBlocks extends Pass2SsaAssertion { public class Pass2AssertBlocks extends Pass2SsaAssertion {
public Pass2AssertBlocks(ControlFlowGraph graph, Scope scope) { public Pass2AssertBlocks(ControlFlowGraph graph, ProgramScope scope) {
super(graph, 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 */ /** Asserts that the symbols in the symbol table match exactly the symbols in the program */
public class Pass2AssertSymbols extends Pass2SsaAssertion { public class Pass2AssertSymbols extends Pass2SsaAssertion {
public Pass2AssertSymbols(ControlFlowGraph graph, Scope scope) { public Pass2AssertSymbols(ControlFlowGraph graph, ProgramScope scope) {
super(graph, scope); super(graph, scope);
} }
@Override @Override
public void check() throws AssertionFailed { public void check() throws AssertionFailed {
SymbolFinder symbolFinder = new SymbolFinder(); SymbolFinder symbolFinder = new SymbolFinder(getSymbols());
symbolFinder.visitGraph(getGraph()); symbolFinder.visitGraph(getGraph());
HashSet<Symbol> codeSymbols = symbolFinder.getSymbols(); HashSet<Symbol> codeSymbols = symbolFinder.getSymbols();
// Check that all symbols found in the code is also oin the symbol tabel // 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 static class SymbolFinder extends ControlFlowGraphBaseVisitor<Void> {
private ProgramScope programScope;
public SymbolFinder(ProgramScope programScope) {
this.programScope = programScope;
}
private HashSet<Symbol> symbols = new HashSet<>(); private HashSet<Symbol> symbols = new HashSet<>();
public HashSet<Symbol> getSymbols() { public HashSet<Symbol> getSymbols() {
@ -65,6 +71,8 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
private void addSymbol(Value symbol) { private void addSymbol(Value symbol) {
if (symbol instanceof Symbol) { if (symbol instanceof Symbol) {
symbols.add((Symbol) symbol); symbols.add((Symbol) symbol);
} else if(symbol instanceof VariableRef) {
addSymbol(programScope.getVariable((VariableRef) symbol));
} else if(symbol instanceof PointerDereferenceIndexed) { } else if(symbol instanceof PointerDereferenceIndexed) {
addSymbol(((PointerDereferenceIndexed) symbol).getPointer()); addSymbol(((PointerDereferenceIndexed) symbol).getPointer());
addSymbol(((PointerDereferenceIndexed) symbol).getIndex()); addSymbol(((PointerDereferenceIndexed) symbol).getIndex());

View File

@ -14,7 +14,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
private Map<Variable, List<Statement>> allUsages; 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); super(graph, scope, log);
} }
@ -25,23 +25,23 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
public boolean optimize() { public boolean optimize() {
final Map<LValue, StatementAssignment> assignments = getAllAssignments(); final Map<LValue, StatementAssignment> assignments = getAllAssignments();
final Map<RValue, List<Statement>> usages = getAllUsages(); final Map<RValue, List<Statement>> usages = getAllUsages();
final List<Variable> simpleConditionVars = getSimpleConditions(assignments, usages); final List<VariableRef> simpleConditionVars = getSimpleConditions(assignments, usages);
removeAssignments(simpleConditionVars); removeAssignments(simpleConditionVars);
deleteSymbols(simpleConditionVars); deleteVariables(simpleConditionVars);
return (simpleConditionVars.size()>0); 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>() { ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override @Override
public Void visitConditionalJump(StatementConditionalJump conditionalJump) { public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
if(conditionalJump.getRValue1()==null && conditionalJump.getOperator()==null) { if(conditionalJump.getRValue1()==null && conditionalJump.getOperator()==null) {
RValue conditionRValue = conditionalJump.getRValue2(); RValue conditionRValue = conditionalJump.getRValue2();
if(conditionRValue instanceof Variable && usages.get(conditionRValue).size()==1) { if(conditionRValue instanceof VariableRef && usages.get(conditionRValue).size()==1) {
Variable conditionVar = (Variable) conditionRValue; VariableRef conditionVar = (VariableRef) conditionRValue;
StatementAssignment conditionAssignment = assignments.get(conditionVar); StatementAssignment conditionAssignment = assignments.get(conditionVar);
if(conditionAssignment.getOperator()!=null) { if(conditionAssignment.getOperator()!=null) {
switch (conditionAssignment.getOperator().getOperator()) { switch (conditionAssignment.getOperator().getOperator()) {
@ -58,7 +58,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
conditionalJump.setOperator(conditionAssignment.getOperator()); conditionalJump.setOperator(conditionAssignment.getOperator());
conditionalJump.setRValue2(conditionAssignment.getrValue2()); conditionalJump.setRValue2(conditionAssignment.getrValue2());
simpleConditionVars.add(conditionVar); simpleConditionVars.add(conditionVar);
log.append("Simple Condition " + conditionVar + " " + conditionalJump); log.append("Simple Condition " + conditionVar.getAsTypedString(getSymbols()) + " " + conditionalJump.getAsTypedString(getSymbols()));
break; break;
default: default:
} }

View File

@ -17,9 +17,9 @@ import java.util.Map;
*/ */
public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { 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); super(graph, scope, log);
} }
@ -69,8 +69,8 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
log.append("Consolidated assigned array index constant in assignment " + assignment.getlValue()); log.append("Consolidated assigned array index constant in assignment " + assignment.getlValue());
return true; return true;
} }
if(pointerDereferenceIndexed.getPointer() instanceof ConstantInteger && pointerDereferenceIndexed.getIndex() instanceof Variable) { if(pointerDereferenceIndexed.getPointer() instanceof ConstantInteger && pointerDereferenceIndexed.getIndex() instanceof VariableRef) {
Variable variable = (Variable) pointerDereferenceIndexed.getIndex(); VariableRef variable = (VariableRef) pointerDereferenceIndexed.getIndex();
ConstantInteger consolidated = consolidateSubConstants(variable); ConstantInteger consolidated = consolidateSubConstants(variable);
if (consolidated != null) { if (consolidated != null) {
ConstantInteger ptrConstant = (ConstantInteger) pointerDereferenceIndexed.getPointer(); 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()); log.append("Consolidated referenced array index constant in assignment " + assignment.getlValue());
return true; return true;
} }
if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof Variable) { if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof VariableRef) {
Variable variable = (Variable) assignment.getrValue2(); VariableRef variable = (VariableRef) assignment.getrValue2();
ConstantInteger consolidated = consolidateSubConstants(variable); ConstantInteger consolidated = consolidateSubConstants(variable);
if (consolidated != null) { if (consolidated != null) {
ConstantInteger ptrConstant = (ConstantInteger) assignment.getrValue1(); ConstantInteger ptrConstant = (ConstantInteger) assignment.getrValue1();
@ -109,8 +109,8 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
} }
private boolean optimizePlus(StatementAssignment assignment) { private boolean optimizePlus(StatementAssignment assignment) {
if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof Variable) { if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof VariableRef) {
Variable variable = (Variable) assignment.getrValue2(); VariableRef variable = (VariableRef) assignment.getrValue2();
ConstantInteger consolidated = consolidateSubConstants(variable); ConstantInteger consolidated = consolidateSubConstants(variable);
if (consolidated != null) { if (consolidated != null) {
ConstantInteger const1 = (ConstantInteger) assignment.getrValue1(); ConstantInteger const1 = (ConstantInteger) assignment.getrValue1();
@ -118,8 +118,8 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
log.append("Consolidated constant in assignment " + assignment.getlValue()); log.append("Consolidated constant in assignment " + assignment.getlValue());
return true; return true;
} }
} else if (assignment.getrValue1() instanceof Variable && assignment.getrValue2() instanceof ConstantInteger) { } else if (assignment.getrValue1() instanceof VariableRef && assignment.getrValue2() instanceof ConstantInteger) {
Variable variable = (Variable) assignment.getrValue1(); VariableRef variable = (VariableRef) assignment.getrValue1();
ConstantInteger consolidated = consolidateSubConstants(variable); ConstantInteger consolidated = consolidateSubConstants(variable);
if (consolidated != null) { if (consolidated != null) {
ConstantInteger const2 = (ConstantInteger) assignment.getrValue2(); ConstantInteger const2 = (ConstantInteger) assignment.getrValue2();
@ -143,12 +143,13 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
* @param variable The variable to examine * @param variable The variable to examine
* @return The consolidated constant. Null if no sub-constants were found. * @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) { 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; 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 != null && assignment.getOperator() != null && "+".equals(assignment.getOperator().getOperator())) {
if (assignment.getrValue1() instanceof ConstantInteger) { if (assignment.getrValue1() instanceof ConstantInteger) {
ConstantInteger constant = (ConstantInteger) assignment.getrValue1(); ConstantInteger constant = (ConstantInteger) assignment.getrValue1();
@ -163,12 +164,12 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
return constant; return constant;
} else { } else {
ConstantInteger const1 = null; ConstantInteger const1 = null;
if (assignment.getrValue1() instanceof Variable) { if (assignment.getrValue1() instanceof VariableRef) {
const1 = consolidateSubConstants((Variable) assignment.getrValue1()); const1 = consolidateSubConstants((VariableRef) assignment.getrValue1());
} }
ConstantInteger const2 = null; ConstantInteger const2 = null;
if (assignment.getrValue2() instanceof Variable) { if (assignment.getrValue2() instanceof VariableRef) {
const2 = consolidateSubConstants((Variable) assignment.getrValue2()); const2 = consolidateSubConstants((VariableRef) assignment.getrValue2());
} }
ConstantInteger result = null; ConstantInteger result = null;
if (const1 != null) { if (const1 != null) {
@ -195,12 +196,12 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
return new ConstantInteger(-constant.getNumber()); return new ConstantInteger(-constant.getNumber());
} else { } else {
ConstantInteger const1 = null; ConstantInteger const1 = null;
if (assignment.getrValue1() instanceof Variable) { if (assignment.getrValue1() instanceof VariableRef) {
const1 = consolidateSubConstants((Variable) assignment.getrValue1()); const1 = consolidateSubConstants((VariableRef) assignment.getrValue1());
} }
ConstantInteger const2 = null; ConstantInteger const2 = null;
if (assignment.getrValue2() instanceof Variable) { if (assignment.getrValue2() instanceof VariableRef) {
const2 = consolidateSubConstants((Variable) assignment.getrValue2()); const2 = consolidateSubConstants((VariableRef) assignment.getrValue2());
} }
ConstantInteger result = null; ConstantInteger result = null;
if (const1 != null) { if (const1 != null) {
@ -217,7 +218,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
return null; return null;
} }
private Integer getUsages(Variable variable) { private Integer getUsages(VariableRef variable) {
Integer useCount = usages.get(variable); Integer useCount = usages.get(variable);
if(useCount==null) useCount = 0; if(useCount==null) useCount = 0;
return useCount; return useCount;

View File

@ -9,7 +9,7 @@ import java.util.Map;
/** Compiler Pass propagating constants in expressions eliminating constant variables */ /** Compiler Pass propagating constants in expressions eliminating constant variables */
public class Pass2ConstantPropagation extends Pass2SsaOptimization { 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); super(graph, scope, log);
} }
@ -19,13 +19,13 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization {
*/ */
@Override @Override
public boolean optimize() { public boolean optimize() {
final Map<Variable, Constant> constants = findConstantVariables(); final Map<VariableRef, Constant> constants = findConstantVariables();
for (Variable constantVar : constants.keySet()) { for (VariableRef constantVar : constants.keySet()) {
Constant constantValue = constants.get(constantVar); Constant constantValue = constants.get(constantVar);
log.append("Constant " + constantVar + " " + constantValue); log.append("Constant " + constantVar.getAsTypedString(getSymbols()) + " " + constantValue.getAsTypedString(getSymbols()));
} }
removeAssignments(constants.keySet()); removeAssignments(constants.keySet());
deleteSymbols(constants.keySet()); deleteVariables(constants.keySet());
replaceVariables(constants); replaceVariables(constants);
return constants.size() > 0; return constants.size() > 0;
} }
@ -34,13 +34,13 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization {
* Find variables that have constant values. * Find variables that have constant values.
* @return Map from Variable to the Constant value * @return Map from Variable to the Constant value
*/ */
private Map<Variable, Constant> findConstantVariables() { private Map<VariableRef, Constant> findConstantVariables() {
final Map<Variable, Constant> constants = new LinkedHashMap<>(); final Map<VariableRef, Constant> constants = new LinkedHashMap<>();
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() { ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override @Override
public Void visitAssignment(StatementAssignment assignment) { public Void visitAssignment(StatementAssignment assignment) {
if (assignment.getlValue() instanceof VariableVersion || assignment.getlValue() instanceof VariableIntermediate) { if (assignment.getlValue() instanceof VariableRef ) {
Variable variable = (Variable) assignment.getlValue(); VariableRef variable = (VariableRef) assignment.getlValue();
if (assignment.getrValue1() == null && assignment.getrValue2() instanceof Constant) { if (assignment.getrValue1() == null && assignment.getrValue2() instanceof Constant) {
if (assignment.getOperator() == null) { if (assignment.getOperator() == null) {
// Constant assignment // Constant assignment
@ -72,7 +72,7 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization {
if (phi.getPreviousVersions().size() == 1) { if (phi.getPreviousVersions().size() == 1) {
StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0); StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0);
if (previousSymbol.getRValue() instanceof Constant) { if (previousSymbol.getRValue() instanceof Constant) {
VariableVersion variable = phi.getlValue(); VariableRef variable = phi.getlValue();
Constant constant = (Constant) previousSymbol.getRValue(); Constant constant = (Constant) previousSymbol.getRValue();
constants.put(variable, constant); constants.put(variable, constant);
} }

View File

@ -8,7 +8,7 @@ import java.util.*;
/** Pass that culls empty control flow blocks from the program */ /** Pass that culls empty control flow blocks from the program */
public class Pass2CullEmptyBlocks extends Pass2SsaOptimization { 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); super(graph, scope, log);
} }
@ -64,7 +64,7 @@ public class Pass2CullEmptyBlocks extends Pass2SsaOptimization {
phiFixVisitor.visitBlock(successor); phiFixVisitor.visitBlock(successor);
getGraph().getAllBlocks().remove(removeBlock); getGraph().getAllBlocks().remove(removeBlock);
removeBlock.getLabel().getScope().remove(removeBlock.getLabel()); 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; return remove.size()>0;
} }

View File

@ -9,7 +9,7 @@ import java.util.Map;
/** Compiler Pass eliminating redundant phi functions */ /** Compiler Pass eliminating redundant phi functions */
public class Pass2RedundantPhiElimination extends Pass2SsaOptimization { 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); super(graph, scope, log);
} }
@ -18,14 +18,14 @@ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization {
*/ */
@Override @Override
public boolean optimize() { public boolean optimize() {
final Map<Variable, RValue> aliases = findRedundantPhis(); final Map<VariableRef, RValue> aliases = findRedundantPhis();
removeAssignments(aliases.keySet()); removeAssignments(aliases.keySet());
deleteSymbols(aliases.keySet());
replaceVariables(aliases); replaceVariables(aliases);
for (Variable var : aliases.keySet()) { for (VariableRef var : aliases.keySet()) {
RValue alias = aliases.get(var); 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; return aliases.size()>0;
} }
@ -33,8 +33,8 @@ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization {
* Find phi variables where all previous symbols are identical. * Find phi variables where all previous symbols are identical.
* @return Map from (phi) Variable to the previous value * @return Map from (phi) Variable to the previous value
*/ */
private Map<Variable, RValue> findRedundantPhis() { private Map<VariableRef, RValue> findRedundantPhis() {
final Map<Variable, RValue> aliases = new LinkedHashMap<>(); final Map<VariableRef, RValue> aliases = new LinkedHashMap<>();
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() { ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override @Override
public Void visitPhi(StatementPhi phi) { public Void visitPhi(StatementPhi phi) {
@ -51,7 +51,7 @@ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization {
} }
} }
if(found) { if(found) {
VariableVersion variable = phi.getlValue(); VariableRef variable = phi.getlValue();
if(phiRValue==null) {phiRValue = VOID;} if(phiRValue==null) {phiRValue = VOID;}
aliases.put(variable, phiRValue); aliases.put(variable, phiRValue);
} }

View File

@ -1,17 +1,14 @@
package dk.camelot64.kickc.passes; package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.CompileLog; import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.icl.ControlFlowGraph; import dk.camelot64.kickc.icl.*;
import dk.camelot64.kickc.icl.ControlFlowGraphBaseVisitor;
import dk.camelot64.kickc.icl.Scope;
import dk.camelot64.kickc.icl.StatementPhi;
import java.util.Iterator; import java.util.Iterator;
/** Compiler Pass eliminating phi self assignments */ /** Compiler Pass eliminating phi self assignments */
public class Pass2SelfPhiElimination extends Pass2SsaOptimization { 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); super(graph, scope, log);
} }
@ -29,7 +26,7 @@ public class Pass2SelfPhiElimination extends Pass2SsaOptimization {
if (previousSymbol.getRValue().equals(phi.getlValue())) { if (previousSymbol.getRValue().equals(phi.getlValue())) {
iterator.remove(); iterator.remove();
optimized[0] = Boolean.TRUE; optimized[0] = Boolean.TRUE;
log.append("Self Phi Eliminated "+phi.getlValue()); log.append("Self Phi Eliminated "+phi.getlValue().getAsTypedString(getSymbols()));
} }
} }
return null; return null;

View File

@ -1,25 +1,27 @@
package dk.camelot64.kickc.passes; package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.icl.ControlFlowGraph; import dk.camelot64.kickc.icl.ControlFlowGraph;
import dk.camelot64.kickc.icl.Program;
import dk.camelot64.kickc.icl.ProgramScope;
import dk.camelot64.kickc.icl.Scope; import dk.camelot64.kickc.icl.Scope;
/** Assertion checking that a pass 2 representation of the program is consistent */ /** Assertion checking that a pass 2 representation of the program is consistent */
public abstract class Pass2SsaAssertion { public abstract class Pass2SsaAssertion {
private ControlFlowGraph graph; 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.graph = graph;
this.scope = scope; this.programScope = programScope;
} }
public ControlFlowGraph getGraph() { public ControlFlowGraph getGraph() {
return graph; return graph;
} }
public Scope getSymbols() { public ProgramScope getSymbols() {
return scope; return programScope;
} }
public abstract void check() throws AssertionFailed; public abstract void check() throws AssertionFailed;

View File

@ -13,9 +13,9 @@ public abstract class Pass2SsaOptimization {
protected CompileLog log; protected CompileLog log;
private ControlFlowGraph graph; 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.log = log;
this.graph = graph; this.graph = graph;
this.scope = scope; this.scope = scope;
@ -29,7 +29,7 @@ public abstract class Pass2SsaOptimization {
return graph; return graph;
} }
public Scope getSymbols() { public ProgramScope getSymbols() {
return scope; return scope;
} }
@ -46,6 +46,16 @@ public abstract class Pass2SsaOptimization {
public static RValue VOID = new RValue() { public static RValue VOID = new RValue() {
@Override @Override
public String toString() { public String toString() {
return getAsString();
}
@Override
public String getAsTypedString(ProgramScope scope) {
return getAsString();
}
@Override
public String getAsString() {
return "VOID"; return "VOID";
} }
}; };
@ -55,7 +65,7 @@ public abstract class Pass2SsaOptimization {
* *
* @param aliases Variables that have alias values. * @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>() { ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override @Override
public Void visitAssignment(StatementAssignment assignment) { public Void visitAssignment(StatementAssignment assignment) {
@ -139,7 +149,7 @@ public abstract class Pass2SsaOptimization {
if (getAlias(aliases, phi.getlValue()) != null) { if (getAlias(aliases, phi.getlValue()) != null) {
RValue alias = getAlias(aliases, phi.getlValue()); RValue alias = getAlias(aliases, phi.getlValue());
if (alias instanceof LValue) { if (alias instanceof LValue) {
phi.setlValue((Variable) alias); phi.setlValue((VariableRef) alias);
} }
} }
for (Iterator<StatementPhi.PreviousSymbol> iterator = phi.getPreviousVersions().iterator(); iterator.hasNext(); ) { 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 * @param rValue The RValue to find an alias for
* @return The alias to use. Null if no alias exists. * @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); RValue alias = aliases.get(rValue);
while (aliases.get(alias) != null) { while (aliases.get(alias) != null) {
alias = aliases.get(alias); 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() { public Map<LValue, StatementAssignment> getAllAssignments() {
final HashMap<LValue, StatementAssignment> assignments = new LinkedHashMap<>(); final HashMap<LValue, StatementAssignment> assignments = new LinkedHashMap<>();
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() { ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@ -334,12 +351,12 @@ public abstract class Pass2SsaOptimization {
return usages; return usages;
} }
protected Map<Variable, Integer> countVarUsages() { protected Map<VariableRef, Integer> countVarUsages() {
final HashMap<Variable, Integer> usages = new LinkedHashMap<>(); final HashMap<VariableRef, Integer> usages = new LinkedHashMap<>();
ControlFlowGraphBaseVisitor usageVisitor = new ControlFlowGraphBaseVisitor() { ControlFlowGraphBaseVisitor usageVisitor = new ControlFlowGraphBaseVisitor() {
private void addUsage(RValue rVal) { private void addUsage(RValue rVal) {
if(rVal instanceof Variable) { if(rVal instanceof VariableRef) {
Variable var = (Variable) rVal; VariableRef var = (VariableRef) rVal;
Integer usage = usages.get(var); Integer usage = usages.get(var);
if (usage == null) { if (usage == null) {
usage = 0; usage = 0;

View File

@ -48,8 +48,10 @@ public class Pass3CodeGeneration {
StatementAssignment assignment = (StatementAssignment) statement; StatementAssignment assignment = (StatementAssignment) statement;
LValue lValue = assignment.getlValue(); LValue lValue = assignment.getlValue();
boolean isAlu = false; boolean isAlu = false;
if (lValue instanceof Variable) { if (lValue instanceof VariableRef) {
RegisterAllocation.Register lValRegister = symbols.getRegister((Variable) lValue); VariableRef lValueRef = (VariableRef) lValue;
Variable lValueVar = symbols.getVariable(lValueRef);
RegisterAllocation.Register lValRegister = symbols.getRegister(lValueVar);
if (lValRegister.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) { if (lValRegister.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) {
asm.addComment(statement + " // ALU"); asm.addComment(statement + " // ALU");
StatementAssignment assignmentAlu = assignment; StatementAssignment assignmentAlu = assignment;
@ -59,19 +61,19 @@ public class Pass3CodeGeneration {
} }
assignment = (StatementAssignment) statement; assignment = (StatementAssignment) statement;
AsmFragment asmFragment = new AsmFragment(assignment, assignmentAlu, symbols); AsmFragment asmFragment = new AsmFragment(assignment, assignmentAlu, symbols);
asm.addComment(statement + " // " + asmFragment.getSignature()); asm.addComment(statement.getAsTypedString(symbols) + " // " + asmFragment.getSignature());
asmFragment.generate(asm); asmFragment.generate(asm);
isAlu = true; isAlu = true;
} }
} }
if (!isAlu) { if (!isAlu) {
AsmFragment asmFragment = new AsmFragment(assignment, symbols); AsmFragment asmFragment = new AsmFragment(assignment, symbols);
asm.addComment(statement + " // " + asmFragment.getSignature()); asm.addComment(statement.getAsTypedString(symbols) + " // " + asmFragment.getSignature());
asmFragment.generate(asm); asmFragment.generate(asm);
} }
} else if (statement instanceof StatementConditionalJump) { } else if (statement instanceof StatementConditionalJump) {
AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, block, symbols, graph); AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, block, symbols, graph);
asm.addComment(statement + " // " + asmFragment.getSignature()); asm.addComment(statement.getAsTypedString(symbols) + " // " + asmFragment.getSignature());
asmFragment.generate(asm); asmFragment.generate(asm);
} else if (statement instanceof StatementCall) { } else if (statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement; StatementCall call = (StatementCall) statement;
@ -132,8 +134,10 @@ public class Pass3CodeGeneration {
} }
private RegisterAllocation.Register getRegister(RValue rValue) { private RegisterAllocation.Register getRegister(RValue rValue) {
if (rValue instanceof Variable) { if (rValue instanceof VariableRef) {
return symbols.getRegister((Variable) rValue); VariableRef rValueRef = (VariableRef) rValue;
Variable rValueVar = symbols.getVariable(rValueRef);
return symbols.getRegister(rValueVar);
} else { } else {
return null; return null;
} }
@ -142,11 +146,11 @@ public class Pass3CodeGeneration {
private void genAsmMove(AsmProgram asm, LValue lValue, RValue rValue) { private void genAsmMove(AsmProgram asm, LValue lValue, RValue rValue) {
if (getRegister(lValue).equals(getRegister(rValue))) { if (getRegister(lValue).equals(getRegister(rValue))) {
// Do not move from register to itself // Do not move from register to itself
asm.addComment(lValue + " = " + rValue + " // register copy "); asm.addComment(lValue.getAsTypedString(symbols) + " = " + rValue.getAsTypedString(symbols) + " // register copy ");
return; return;
} }
AsmFragment asmFragment = new AsmFragment(lValue, rValue, symbols); 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); asmFragment.generate(asm);
} }

View File

@ -47,7 +47,7 @@ public class TestCompilationOutput extends TestCase {
Compiler.CompilationResult output = compiler.compile(input); Compiler.CompilationResult output = compiler.compile(input);
assertOutput(fileName, ".asm", output.getAsmProgram().toString(false)); assertOutput(fileName, ".asm", output.getAsmProgram().toString(false));
assertOutput(fileName, ".sym", output.getSymbols().getSymbolTableContents()); 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()); assertOutput(fileName, ".log", output.getLog().toString());
} }

View File

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

View File

@ -899,59 +899,7 @@ CONTROL FLOW GRAPH
to:@END to:@END
@END: from @3 @END: from @3
Consolidated constant in assignment (byte*) cursor#0
Multiple usages for variable. Not optimizing sub-constant (byte) x1#1 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) yd#1 = (byte) yd#3
Alias (byte) STAR#1 = (byte) STAR#3 Alias (byte) STAR#1 = (byte) STAR#3
Alias (byte) x1#2 = (byte) x1#3 Alias (byte) x1#2 = (byte) x1#3
@ -965,7 +913,8 @@ CONTROL FLOW GRAPH
@BEGIN: from @BEGIN: from
(byte) e#0 ← (byte) 24 / (byte) 2 (byte) e#0 ← (byte) 24 / (byte) 2
(byte~) $3 ← (byte) 0 * (byte) 40 (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 to:@1
@1: from @3 @BEGIN @1: from @3 @BEGIN
(byte) x1#2 ← phi( @3/(byte) x1#1 @BEGIN/(byte) 39 ) (byte) x1#2 ← phi( @3/(byte) x1#1 @BEGIN/(byte) 39 )
@ -1011,7 +960,8 @@ CONTROL FLOW GRAPH
@BEGIN: from @BEGIN: from
(byte) e#0 ← (byte) 24 / (byte) 2 (byte) e#0 ← (byte) 24 / (byte) 2
(byte~) $3 ← (byte) 0 * (byte) 40 (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 to:@1
@1: from @3 @BEGIN @1: from @3 @BEGIN
(byte) x1#2 ← phi( @3/(byte) x1#2 @BEGIN/(byte) 39 ) (byte) x1#2 ← phi( @3/(byte) x1#2 @BEGIN/(byte) 39 )
@ -1051,7 +1001,8 @@ CONTROL FLOW GRAPH
@BEGIN: from @BEGIN: from
(byte) e#0 ← (byte) 24 / (byte) 2 (byte) e#0 ← (byte) 24 / (byte) 2
(byte~) $3 ← (byte) 0 * (byte) 40 (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 to:@1
@1: from @3 @BEGIN @1: from @3 @BEGIN
(byte) x1#2 ← phi( @BEGIN/(byte) 39 ) (byte) x1#2 ← phi( @BEGIN/(byte) 39 )
@ -1091,7 +1042,8 @@ Constant (byte) STAR#1 (byte) 81
Succesful SSA optimization Pass2ConstantPropagation Succesful SSA optimization Pass2ConstantPropagation
CONTROL FLOW GRAPH CONTROL FLOW GRAPH
@BEGIN: from @BEGIN: from
(byte*) cursor#0 ← (byte) 0 + (word) 1024 (byte*~) $4 ← (word) 1024 + (byte) 0
(byte*) cursor#0 ← (byte*~) $4 + (byte) 0
to:@1 to:@1
@1: from @3 @BEGIN @1: from @3 @BEGIN
(byte) y#2 ← phi( @3/(byte) y#5 @BEGIN/(byte) 0 ) (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) y#2
Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1 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 Constant (byte~) $13 (byte) 40
Succesful SSA optimization Pass2ConstantPropagation Succesful SSA optimization Pass2ConstantPropagation
CONTROL FLOW GRAPH 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 @BEGIN: from
to:@1 to:@1
@1: from @3 @BEGIN @1: from @3 @BEGIN
@ -1383,3 +1367,146 @@ B3_from_B2:
sta 15 sta 15
jmp B3 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 to:@RETURN
@END: from @BEGIN @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]) buffer2#14 = (byte[256]) buffer2#16
Alias (byte[256]) buffer1#22 = (byte[256]) buffer1#9 (byte[256]) buffer1#5 Alias (byte[256]) buffer1#22 = (byte[256]) buffer1#9 (byte[256]) buffer1#5
Alias (byte[1000]) SCREEN#10 = (byte[1000]) SCREEN#12 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*) 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]) 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[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*) 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) main::c#2 = (byte) main::c#3
Alias (byte) flip::dstIdx#1 = (byte~) flip::$1 (byte) flip::dstIdx#4 Alias (byte) flip::dstIdx#1 = (byte~) flip::$1 (byte) flip::dstIdx#4
@ -1786,7 +1582,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -1943,7 +1740,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -2115,7 +1913,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -2270,7 +2069,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -2411,7 +2211,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -2549,7 +2350,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#4 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -2684,7 +2486,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -2810,7 +2613,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -2929,7 +2733,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -3045,7 +2850,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -3157,7 +2963,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -3269,7 +3076,8 @@ flip::@return: from flip::@3
return return
to:@RETURN to:@RETURN
plot: from @17 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 to:plot::@1
plot::@1: from @12 plot plot::@1: from @12 plot
(byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 ) (byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
@ -3295,6 +3103,118 @@ plot::@return: from @12
to:@RETURN to:@RETURN
@END: from @BEGIN @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 Constant (byte*) plot::line#0 (word) 1236
Succesful SSA optimization Pass2ConstantPropagation Succesful SSA optimization Pass2ConstantPropagation
CONTROL FLOW GRAPH CONTROL FLOW GRAPH