1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

ICL Programs are now JSON serializable

This commit is contained in:
jespergravgaard 2017-07-21 01:53:38 +02:00
parent d38c26eeb5
commit 6ef3af4fdf
34 changed files with 564 additions and 240 deletions

View File

@ -46,128 +46,149 @@ public class Compiler {
public CompilationResult compile(final CharStream input) {
CompileLog log = new CompileLog();
try {
log.append(input.toString());
KickCLexer lexer = new KickCLexer(input);
KickCParser parser = new KickCParser(new CommonTokenStream(lexer));
parser.setBuildParseTree(true);
parser.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(
Recognizer<?, ?> recognizer,
Object offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e) {
throw new RuntimeException("Error parsing file " + input.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
}
});
KickCParser.FileContext file = parser.file();
Pass1GenerateStatementSequence pass1GenerateStatementSequence = new Pass1GenerateStatementSequence(log);
pass1GenerateStatementSequence.generate(file);
StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence();
ProgramScope programScope = pass1GenerateStatementSequence.getProgramScope();
Pass1TypeInference pass1TypeInference = new Pass1TypeInference(programScope);
pass1TypeInference.inferTypes(statementSequence);
log.append("PROGRAM");
log.append(statementSequence.getAsTypedString(programScope));
log.append("SYMBOLS");
log.append(programScope.getSymbolTableContents());
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(programScope);
ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence);
log.append("INITIAL CONTROL FLOW GRAPH");
log.append(controlFlowGraph.getAsTypedString(programScope));
Pass1ProcedureCallParameters pass1ProcedureCallParameters =
new Pass1ProcedureCallParameters(programScope, controlFlowGraph);
controlFlowGraph = pass1ProcedureCallParameters.generate();
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL");
log.append(controlFlowGraph.getAsTypedString(programScope));
Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm =
new Pass1GenerateSingleStaticAssignmentForm(log, programScope, controlFlowGraph);
pass1GenerateSingleStaticAssignmentForm.generate();
log.append("CONTROL FLOW GRAPH SSA");
log.append(controlFlowGraph.getAsTypedString(programScope));
Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue =
new Pass1ProcedureCallsReturnValue(programScope, controlFlowGraph);
controlFlowGraph = pass1ProcedureCallsReturnValue.generate();
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN");
log.append(controlFlowGraph.getAsTypedString(programScope));
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, programScope, log));
optimizations.add(new Pass2ConstantPropagation(controlFlowGraph, programScope, log));
optimizations.add(new Pass2ConstantAdditionElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2AliasElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2RedundantPhiElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2SelfPhiElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2ConditionalJumpSimplification(controlFlowGraph, programScope, log));
List<Pass2SsaAssertion> assertions = new ArrayList<>();
assertions.add(new Pass2AssertSymbols(controlFlowGraph, programScope));
assertions.add(new Pass2AssertBlocks(controlFlowGraph, programScope));
boolean ssaOptimized = true;
while (ssaOptimized) {
for (Pass2SsaAssertion assertion : assertions) {
assertion.check();
}
ssaOptimized = false;
for (Pass2SsaOptimization optimization : optimizations) {
boolean stepOptimized = optimization.optimize();
if (stepOptimized) {
log.append("Succesful SSA optimization " + optimization.getClass().getSimpleName() + "");
ssaOptimized = true;
log.append("CONTROL FLOW GRAPH");
log.append(controlFlowGraph.getAsTypedString(programScope));
}
}
}
Pass3BlockSequencePlanner pass3BlockSequencePlanner = new Pass3BlockSequencePlanner(
controlFlowGraph,
programScope);
pass3BlockSequencePlanner.plan();
Pass3RegisterAllocation pass3RegisterAllocation = new Pass3RegisterAllocation(controlFlowGraph, programScope);
pass3RegisterAllocation.allocate();
Pass3CodeGeneration pass3CodeGeneration = new Pass3CodeGeneration(controlFlowGraph, programScope);
AsmProgram asmProgram = pass3CodeGeneration.generate();
log.append("INITIAL ASM");
log.append(asmProgram.toString());
List<Pass4AsmOptimization> pass4Optimizations = new ArrayList<>();
pass4Optimizations.add(new Pass4NextJumpElimination(asmProgram, log));
pass4Optimizations.add(new Pass4UnnecesaryLoadElimination(asmProgram, log));
boolean asmOptimized = true;
while (asmOptimized) {
asmOptimized = false;
for (Pass4AsmOptimization optimization : pass4Optimizations) {
boolean stepOtimized = optimization.optimize();
if (stepOtimized) {
log.append("Succesful ASM optimization " + optimization.getClass().getSimpleName());
asmOptimized = true;
log.append("ASSEMBLER");
log.append(asmProgram.toString());
}
}
}
KickCParser.FileContext file = pass0ParseInput(input, log);
Program program = pass1GenerateSSA(file, log);
pass2OptimizeSSA(program, log);
AsmProgram asmProgram = pass3GenerateAsm(program, log);
pass4OptimizeAsm(asmProgram, log);
log.append("FINAL SYMBOL TABLE");
log.append(programScope.getSymbolTableContents());
log.append(program.getScope().getSymbolTableContents());
log.append("FINAL CODE");
log.append(asmProgram.toString());
return new CompilationResult(asmProgram, controlFlowGraph, programScope, log);
return new CompilationResult(asmProgram, program.getGraph(), program.getScope(), log);
} catch (Exception e) {
System.out.println(log.getLog());
throw e;
}
}
public void pass4OptimizeAsm(AsmProgram asmProgram, CompileLog log) {
List<Pass4AsmOptimization> pass4Optimizations = new ArrayList<>();
pass4Optimizations.add(new Pass4NextJumpElimination(asmProgram, log));
pass4Optimizations.add(new Pass4UnnecesaryLoadElimination(asmProgram, log));
boolean asmOptimized = true;
while (asmOptimized) {
asmOptimized = false;
for (Pass4AsmOptimization optimization : pass4Optimizations) {
boolean stepOtimized = optimization.optimize();
if (stepOtimized) {
log.append("Succesful ASM optimization " + optimization.getClass().getSimpleName());
asmOptimized = true;
log.append("ASSEMBLER");
log.append(asmProgram.toString());
}
}
}
}
public AsmProgram pass3GenerateAsm(Program program, CompileLog log) {
Pass3BlockSequencePlanner pass3BlockSequencePlanner = new Pass3BlockSequencePlanner(program);
pass3BlockSequencePlanner.plan();
Pass3RegisterAllocation pass3RegisterAllocation = new Pass3RegisterAllocation(program);
pass3RegisterAllocation.allocate();
Pass3CodeGeneration pass3CodeGeneration = new Pass3CodeGeneration(program);
AsmProgram asmProgram = pass3CodeGeneration.generate();
log.append("INITIAL ASM");
log.append(asmProgram.toString());
return asmProgram;
}
public void pass2OptimizeSSA(Program program, CompileLog log) {
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
optimizations.add(new Pass2CullEmptyBlocks(program, log));
optimizations.add(new Pass2ConstantPropagation(program, log));
optimizations.add(new Pass2ConstantAdditionElimination(program, log));
optimizations.add(new Pass2AliasElimination(program, log));
optimizations.add(new Pass2RedundantPhiElimination(program, log));
optimizations.add(new Pass2SelfPhiElimination(program, log));
optimizations.add(new Pass2ConditionalJumpSimplification(program, log));
List<Pass2SsaAssertion> assertions = new ArrayList<>();
assertions.add(new Pass2AssertSymbols(program));
assertions.add(new Pass2AssertBlocks(program));
boolean ssaOptimized = true;
while (ssaOptimized) {
for (Pass2SsaAssertion assertion : assertions) {
assertion.check();
}
ssaOptimized = false;
for (Pass2SsaOptimization optimization : optimizations) {
boolean stepOptimized = optimization.optimize();
if (stepOptimized) {
log.append("Succesful SSA optimization " + optimization.getClass().getSimpleName() + "");
ssaOptimized = true;
log.append("CONTROL FLOW GRAPH");
log.append(program.getGraph().getAsTypedString(program.getScope()));
}
}
}
}
public Program pass1GenerateSSA(KickCParser.FileContext file, CompileLog log) {
Pass1GenerateStatementSequence pass1GenerateStatementSequence1 = new Pass1GenerateStatementSequence(log);
pass1GenerateStatementSequence1.generate(file);
Pass1GenerateStatementSequence pass1GenerateStatementSequence = pass1GenerateStatementSequence1;
StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence();
ProgramScope programScope = pass1GenerateStatementSequence.getProgramScope();
Pass1TypeInference pass1TypeInference = new Pass1TypeInference(programScope);
pass1TypeInference.inferTypes(statementSequence);
log.append("PROGRAM");
log.append(statementSequence.getAsTypedString(programScope));
log.append("SYMBOLS");
log.append(programScope.getSymbolTableContents());
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(programScope);
ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence);
Program program = new Program(programScope, controlFlowGraph);
log.append("INITIAL CONTROL FLOW GRAPH");
log.append(program.getGraph().getAsTypedString(program.getScope()));
Pass1ProcedureCallParameters pass1ProcedureCallParameters =
new Pass1ProcedureCallParameters(program);
program.setGraph(pass1ProcedureCallParameters.generate());
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL");
log.append(program.getGraph().getAsTypedString(program.getScope()));
Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm =
new Pass1GenerateSingleStaticAssignmentForm(log, program);
pass1GenerateSingleStaticAssignmentForm.generate();
log.append("CONTROL FLOW GRAPH SSA");
log.append(program.getGraph().getAsTypedString(program.getScope()));
Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue =
new Pass1ProcedureCallsReturnValue(program);
program.setGraph(pass1ProcedureCallsReturnValue.generate());
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN");
log.append(program.getGraph().getAsTypedString(program.getScope()));
return program;
}
public KickCParser.FileContext pass0ParseInput(final CharStream input, CompileLog log) {
log.append(input.toString());
KickCLexer lexer = new KickCLexer(input);
KickCParser parser = new KickCParser(new CommonTokenStream(lexer));
parser.setBuildParseTree(true);
parser.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(
Recognizer<?, ?> recognizer,
Object offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e) {
throw new RuntimeException("Error parsing file " + input.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
}
});
return parser.file();
}
}

View File

@ -1,5 +1,9 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* SSA form constant integer value
*/
@ -7,7 +11,9 @@ public class ConstantInteger implements Constant {
private Integer number;
public ConstantInteger(Integer number) {
@JsonCreator
public ConstantInteger(
@JsonProperty("number") Integer number) {
this.number = number;
}
@ -15,6 +21,7 @@ public class ConstantInteger implements Constant {
return number;
}
@JsonIgnore
public SymbolType getType() {
SymbolType type;
if (getNumber() < 256) {
@ -35,6 +42,23 @@ public class ConstantInteger implements Constant {
return "("+getType().getTypeName()+") "+Integer.toString(number); }
@Override
@JsonIgnore
public String getAsString() {
return Integer.toString(number); }
return Integer.toString(number);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConstantInteger that = (ConstantInteger) o;
return number != null ? number.equals(that.number) : that.number == null;
}
@Override
public int hashCode() {
return number != null ? number.hashCode() : 0;
}
}

View File

@ -1,5 +1,8 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.List;
@ -25,6 +28,20 @@ public class ControlFlowBlock {
this.conditionalSuccessor = null;
}
@JsonCreator
public ControlFlowBlock(
@JsonProperty("label") LabelRef label,
@JsonProperty("statements") List<Statement> statements,
@JsonProperty("defaultSuccessor") LabelRef defaultSuccessor,
@JsonProperty("conditionalSuccessor") LabelRef conditionalSuccessor,
@JsonProperty("callSuccessor") LabelRef callSuccessor) {
this.label = label;
this.statements = statements;
this.defaultSuccessor = defaultSuccessor;
this.conditionalSuccessor = conditionalSuccessor;
this.callSuccessor = callSuccessor;
}
public LabelRef getLabel() {
return label;
}
@ -117,20 +134,6 @@ public class ControlFlowBlock {
return out.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ControlFlowBlock that = (ControlFlowBlock) o;
return label.equals(that.label);
}
@Override
public int hashCode() {
return label.hashCode();
}
public boolean hasPhiStatements() {
if(statements.size()>0) {
if(statements.get(0) instanceof StatementPhi) {
@ -140,4 +143,29 @@ public class ControlFlowBlock {
return false;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ControlFlowBlock that = (ControlFlowBlock) o;
if (!label.equals(that.label)) return false;
if (statements != null ? !statements.equals(that.statements) : that.statements != null) return false;
if (defaultSuccessor != null ? !defaultSuccessor.equals(that.defaultSuccessor) : that.defaultSuccessor != null)
return false;
if (conditionalSuccessor != null ? !conditionalSuccessor.equals(that.conditionalSuccessor) : that.conditionalSuccessor != null)
return false;
return callSuccessor != null ? callSuccessor.equals(that.callSuccessor) : that.callSuccessor == null;
}
@Override
public int hashCode() {
int result = label.hashCode();
result = 31 * result + (statements != null ? statements.hashCode() : 0);
result = 31 * result + (defaultSuccessor != null ? defaultSuccessor.hashCode() : 0);
result = 31 * result + (conditionalSuccessor != null ? conditionalSuccessor.hashCode() : 0);
result = 31 * result + (callSuccessor != null ? callSuccessor.hashCode() : 0);
return result;
}
}

View File

@ -1,28 +1,44 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.*;
/** The control flow graph of the program.
* The control flow graph is a set of connected basic blocks. */
public class ControlFlowGraph {
private Map<SymbolRef, ControlFlowBlock> blocks;
private ControlFlowBlock firstBlock;
private List<ControlFlowBlock> sequence;
private Map<LabelRef, ControlFlowBlock> blocks;
private LabelRef firstBlockRef;
private List<LabelRef> sequence;
public ControlFlowGraph(Map<SymbolRef, ControlFlowBlock> blocks, ControlFlowBlock firstBlock) {
public ControlFlowGraph(Map<LabelRef, ControlFlowBlock> blocks, LabelRef firstBlockRef) {
this.blocks = blocks;
this.firstBlock = firstBlock;
this.firstBlockRef = firstBlockRef;
}
public ControlFlowBlock getBlock(SymbolRef symbol) {
@JsonCreator
public ControlFlowGraph(
@JsonProperty("blocks") Map<LabelRef, ControlFlowBlock> blocks,
@JsonProperty("firstBlockRef") LabelRef firstBlockRef,
@JsonProperty("sequence") List<LabelRef> sequence) {
this.blocks = blocks;
this.firstBlockRef = firstBlockRef;
this.sequence = sequence;
}
public ControlFlowBlock getBlock(LabelRef symbol) {
return blocks.get(symbol);
}
@JsonIgnore
public ControlFlowBlock getFirstBlock() {
return firstBlock;
return getBlock(firstBlockRef);
}
@JsonIgnore
public Collection<ControlFlowBlock> getAllBlocks() {
return blocks.values();
}
@ -96,14 +112,15 @@ public class ControlFlowGraph {
return predecessorBlocks;
}
public void setBlockSequence(List<ControlFlowBlock> sequence) {
this.sequence = sequence;
}
public List<ControlFlowBlock> getBlockSequence() {
public List<LabelRef> getSequence() {
return sequence;
}
public void setSequence(List<LabelRef> sequence) {
this.sequence = sequence;
}
@JsonIgnore
public ControlFlowBlock getMainBlock() {
for (ControlFlowBlock block : getAllBlocks()) {
LabelRef label = block.getLabel();
@ -122,6 +139,7 @@ public class ControlFlowGraph {
return out.toString();
}
@JsonIgnore
public String getAsString() {
StringBuffer out = new StringBuffer();
for (ControlFlowBlock block : blocks.values()) {
@ -131,5 +149,23 @@ public class ControlFlowGraph {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ControlFlowGraph that = (ControlFlowGraph) o;
if (!blocks.equals(that.blocks)) return false;
if (!firstBlockRef.equals(that.firstBlockRef)) return false;
return sequence != null ? sequence.equals(that.sequence) : that.sequence == null;
}
@Override
public int hashCode() {
int result = blocks.hashCode();
result = 31 * result + firstBlockRef.hashCode();
result = 31 * result + (sequence != null ? sequence.hashCode() : 0);
return result;
}
}

View File

@ -16,7 +16,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
/**
* The copied blocks.
*/
private LinkedHashMap<SymbolRef, ControlFlowBlock> copyBlockMap;
private LinkedHashMap<LabelRef, ControlFlowBlock> copyBlockMap;
/**
* The current block being copied.
@ -40,7 +40,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
}
}
ControlFlowBlock copyFirstBlock = copyBlockMap.get(origGraph.getFirstBlock().getLabel());
ControlFlowGraph copyGraph = new ControlFlowGraph(copyBlockMap, copyFirstBlock);
ControlFlowGraph copyGraph = new ControlFlowGraph(copyBlockMap, copyFirstBlock.getLabel());
return copyGraph;
}
@ -118,7 +118,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
VariableRef lValue = phi.getlValue();
StatementPhi copyPhi = new StatementPhi(lValue);
for (StatementPhi.PreviousSymbol origPreviousVersion : phi.getPreviousVersions()) {
RValue rValue = origPreviousVersion.getRValue();
RValue rValue = origPreviousVersion.getrValue();
LabelRef block = origPreviousVersion.getBlock();
copyPhi.addPreviousVersion(block, rValue);
}

View File

@ -1,9 +1,14 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/** A reference to a label */
public class LabelRef extends SymbolRef {
public LabelRef(String fullName) {
@JsonCreator
public LabelRef(
@JsonProperty("fullName") String fullName) {
super(fullName);
}

View File

@ -1,11 +1,16 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/** An Operator. The operation performed on the rvalues in a Statement. */
public class Operator {
private String operator;
public Operator(String operator) {
@JsonCreator
public Operator(
@JsonProperty("operator") String operator) {
this.operator = operator;
}
@ -17,4 +22,19 @@ public class Operator {
public String toString() {
return operator ;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Operator operator1 = (Operator) o;
return operator != null ? operator.equals(operator1.operator) : operator1.operator == null;
}
@Override
public int hashCode() {
return operator != null ? operator.hashCode() : 0;
}
}

View File

@ -6,23 +6,23 @@ import com.fasterxml.jackson.annotation.JsonProperty;
/** A KickC Intermediate Compiler Language (ICL) Program */
public class Program {
/** The main scope. */
private Scope scope;
private ProgramScope scope;
/** The control flow graph. */
private ControlFlowGraph graph;
@JsonCreator
public Program(
@JsonProperty("scope") Scope scope,
@JsonProperty("scope") ProgramScope scope,
@JsonProperty("graph") ControlFlowGraph graph) {
this.scope = scope;
this.graph = graph;
}
public Scope getScope() {
public ProgramScope getScope() {
return scope;
}
public void setScope(Scope scope) {
public void setScope(ProgramScope scope) {
this.scope = scope;
}
@ -33,4 +33,22 @@ public class Program {
public void setGraph(ControlFlowGraph graph) {
this.graph = graph;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Program program = (Program) o;
if (scope != null ? !scope.equals(program.scope) : program.scope != null) return false;
return graph != null ? graph.equals(program.graph) : program.graph == null;
}
@Override
public int hashCode() {
int result = scope != null ? scope.hashCode() : 0;
result = 31 * result + (graph != null ? graph.hashCode() : 0);
return result;
}
}

View File

@ -1,13 +1,30 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
/**
* Single Static Assignment Form Statement.
* Intermediate form used for compiler optimization.
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
@JsonSubTypes({
@JsonSubTypes.Type(value = StatementAssignment.class, name = "assign"),
@JsonSubTypes.Type(value = StatementPhi.class, name = "phi"),
@JsonSubTypes.Type(value = StatementConditionalJump.class, name = "cond"),
@JsonSubTypes.Type(value = StatementJump.class, name = "jump"),
@JsonSubTypes.Type(value = StatementLabel.class, name = "label"),
@JsonSubTypes.Type(value = StatementCall.class, name = "call"),
@JsonSubTypes.Type(value = StatementCall.class, name = "return"),
@JsonSubTypes.Type(value = StatementProcedureBegin.class, name = "procbegin"),
@JsonSubTypes.Type(value = StatementProcedureEnd.class, name = "procend")
})
public interface Statement {
String getAsTypedString(ProgramScope scope);
@JsonIgnore
String getAsString();
}

View File

@ -110,4 +110,25 @@ public class StatementAssignment implements StatementLValue {
rValue2.getAsString() ;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StatementAssignment that = (StatementAssignment) o;
if (!lValue.equals(that.lValue)) return false;
if (rValue1 != null ? !rValue1.equals(that.rValue1) : that.rValue1 != null) return false;
if (operator != null ? !operator.equals(that.operator) : that.operator != null) return false;
return rValue2 != null ? rValue2.equals(that.rValue2) : that.rValue2 == null;
}
@Override
public int hashCode() {
int result = lValue.hashCode();
result = 31 * result + (rValue1 != null ? rValue1.hashCode() : 0);
result = 31 * result + (operator != null ? operator.hashCode() : 0);
result = 31 * result + (rValue2 != null ? rValue2.hashCode() : 0);
return result;
}
}

View File

@ -1,5 +1,8 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Intermediate Compiler Form Statement with a conditional jump.
* Intermediate form used for compiler optimization.
@ -23,7 +26,12 @@ public class StatementConditionalJump implements Statement {
this.destination = destination;
}
public StatementConditionalJump(RValue rValue1, Operator operator, RValue rValue2, LabelRef destination) {
@JsonCreator
public StatementConditionalJump(
@JsonProperty("rValue1") RValue rValue1,
@JsonProperty("operator") Operator operator,
@JsonProperty("rValue2") RValue rValue2,
@JsonProperty("destination") LabelRef destination) {
this.rValue1 = rValue1;
this.operator = operator;
this.rValue2 = rValue2;
@ -94,4 +102,26 @@ public class StatementConditionalJump implements Statement {
out.append(destination.getFullName());
return out.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StatementConditionalJump that = (StatementConditionalJump) o;
if (rValue1 != null ? !rValue1.equals(that.rValue1) : that.rValue1 != null) return false;
if (operator != null ? !operator.equals(that.operator) : that.operator != null) return false;
if (rValue2 != null ? !rValue2.equals(that.rValue2) : that.rValue2 != null) return false;
return destination.equals(that.destination);
}
@Override
public int hashCode() {
int result = rValue1 != null ? rValue1.hashCode() : 0;
result = 31 * result + (operator != null ? operator.hashCode() : 0);
result = 31 * result + (rValue2 != null ? rValue2.hashCode() : 0);
result = 31 * result + destination.hashCode();
return result;
}
}

View File

@ -1,5 +1,8 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.List;
@ -22,6 +25,14 @@ public class StatementPhi implements StatementLValue {
this.previousVersions = new ArrayList<>();
}
@JsonCreator
StatementPhi(
@JsonProperty("lValue") VariableRef lValue,
@JsonProperty("previousVersions") List<PreviousSymbol> previousVersions) {
this.lValue = lValue;
this.previousVersions = previousVersions;
}
public PreviousSymbol getPreviousVersion(int i) {
return previousVersions.get(i);
}
@ -34,7 +45,10 @@ public class StatementPhi implements StatementLValue {
private LabelRef block;
private RValue rValue;
public PreviousSymbol(LabelRef block, RValue rValue) {
@JsonCreator
public PreviousSymbol(
@JsonProperty("block") LabelRef block,
@JsonProperty("rValue") RValue rValue) {
this.block = block;
this.rValue = rValue;
}
@ -43,17 +57,35 @@ public class StatementPhi implements StatementLValue {
return block;
}
public RValue getRValue() {
public RValue getrValue() {
return rValue;
}
public void setRValue(RValue RValue) {
public void setrValue(RValue RValue) {
this.rValue = RValue;
}
public void setBlock(LabelRef block) {
this.block = block;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PreviousSymbol that = (PreviousSymbol) o;
if (!block.equals(that.block)) return false;
return rValue.equals(that.rValue);
}
@Override
public int hashCode() {
int result = block.hashCode();
result = 31 * result + rValue.hashCode();
return result;
}
}
public VariableRef getlValue() {
@ -86,7 +118,7 @@ public class StatementPhi implements StatementLValue {
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(" "+previousSymbol.getBlock().getFullName()+"/"+previousSymbol.getrValue().getAsTypedString(scope));
}
out.append(" )");
return out.toString();
@ -97,9 +129,27 @@ public class StatementPhi implements StatementLValue {
StringBuilder out = new StringBuilder();
out.append(lValue + "" + "phi(");
for (PreviousSymbol previousSymbol : previousVersions) {
out.append(" "+previousSymbol.getBlock().getFullName()+"/"+previousSymbol.getRValue());
out.append(" "+previousSymbol.getBlock().getFullName()+"/"+previousSymbol.getrValue());
}
out.append(" )");
return out.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StatementPhi that = (StatementPhi) o;
if (!lValue.equals(that.lValue)) return false;
return previousVersions.equals(that.previousVersions);
}
@Override
public int hashCode() {
int result = lValue.hashCode();
result = 31 * result + previousVersions.hashCode();
return result;
}
}

View File

@ -14,6 +14,9 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonSubTypes.Type(value = VariableVersion.class, name = "variable_versioned"),
@JsonSubTypes.Type(value = VariableIntermediate.class, name = "variable_intermediate"),
@JsonSubTypes.Type(value = Label.class, name = "label"),
@JsonSubTypes.Type(value = VariableRef.class, name = "varref"),
@JsonSubTypes.Type(value = LabelRef.class, name = "labelref"),
@JsonSubTypes.Type(value = ProcedureRef.class, name = "procref"),
@JsonSubTypes.Type(value = PointerDereferenceIndexed.class, name = "pointer_indexed"),
@JsonSubTypes.Type(value = PointerDereferenceSimple.class, name = "pointer_simple"),
@JsonSubTypes.Type(value = ProgramScope.class, name = "program"),

View File

@ -1,9 +1,14 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/** A reference to a variable from the symbol table */
public class VariableRef extends SymbolRef implements RValue, LValue {
public VariableRef(String fullName) {
@JsonCreator
public VariableRef(
@JsonProperty("fullName") String fullName) {
super(fullName);
}

View File

@ -12,7 +12,7 @@ public class Pass1GenerateControlFlowGraph {
public static final String BEGIN_BLOCK_NAME = "@BEGIN";
public static final String END_BLOCK_NAME = "@END";
private Scope scope;
private Map<SymbolRef, ControlFlowBlock> blocks;
private Map<LabelRef, ControlFlowBlock> blocks;
private ControlFlowBlock firstBlock;
public Pass1GenerateControlFlowGraph(Scope scope) {
@ -75,7 +75,7 @@ public class Pass1GenerateControlFlowGraph {
}
}
return new ControlFlowGraph(blocks, firstBlock);
return new ControlFlowGraph(blocks, firstBlock.getLabel());
}
private ControlFlowBlock getOrCreateBlock(LabelRef label) {

View File

@ -14,13 +14,13 @@ import java.util.Map;
public class Pass1GenerateSingleStaticAssignmentForm {
private CompileLog log;
private Scope symbols;
private ProgramScope symbols;
private ControlFlowGraph controlFlowGraph;
public Pass1GenerateSingleStaticAssignmentForm(CompileLog log, Scope symbols, ControlFlowGraph controlFlowGraph) {
public Pass1GenerateSingleStaticAssignmentForm(CompileLog log, Program program) {
this.log = log;
this.symbols = symbols;
this.controlFlowGraph = controlFlowGraph;
this.symbols = program.getScope();
this.controlFlowGraph = program.getGraph();
}
public void generate() {

View File

@ -7,12 +7,12 @@ import java.util.List;
/** Pass that modifies a control flow graph to call procedures by passing parameters through registers */
public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
private Scope scope;
private ProgramScope scope;
private ControlFlowGraph graph;
public Pass1ProcedureCallParameters(Scope scope, ControlFlowGraph graph ) {
this.scope = scope;
this.graph= graph;
public Pass1ProcedureCallParameters(Program program) {
this.scope = program.getScope();
this.graph = program.getGraph();
}
public ControlFlowGraph generate() {

View File

@ -8,9 +8,9 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
private ProgramScope scope;
private ControlFlowGraph graph;
public Pass1ProcedureCallsReturnValue(ProgramScope scope, ControlFlowGraph graph) {
this.scope = scope;
this.graph = graph;
public Pass1ProcedureCallsReturnValue(Program program) {
this.scope = program.getScope();
this.graph = program.getGraph();
}
public ControlFlowGraph generate() {

View File

@ -10,12 +10,16 @@ import java.util.Stack;
*/
public class Pass1TypeInference {
private Scope programScope;
private ProgramScope programScope;
public Pass1TypeInference(Scope programScope) {
public Pass1TypeInference(ProgramScope programScope) {
this.programScope = programScope;
}
public ProgramScope getProgramScope() {
return programScope;
}
public void inferTypes(StatementSequence sequence) {
Stack<Scope> scopes = new Stack<>();
scopes.add(programScope);

View File

@ -10,8 +10,8 @@ import java.util.*;
*/
public class Pass2AliasElimination extends Pass2SsaOptimization {
public Pass2AliasElimination(ControlFlowGraph graph, ProgramScope scope, CompileLog log) {
super(graph, scope, log);
public Pass2AliasElimination(Program program, CompileLog log) {
super(program, log);
}
@ -58,7 +58,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
StatementPhi phi = (StatementPhi) statement;
AliasSet aliasSet = aliases.findAliasSet(phi.getlValue());
if (aliasSet != null) {
if (phi.getPreviousVersions().size() == 1 && aliasSet.contains(phi.getPreviousVersion(0).getRValue())) {
if (phi.getPreviousVersions().size() == 1 && aliasSet.contains(phi.getPreviousVersion(0).getrValue())) {
iterator.remove();
}
}
@ -233,7 +233,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
public Void visitPhi(StatementPhi phi) {
if(lMatch[0]) {
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
RValue phiRValue = previousSymbol.getRValue();
RValue phiRValue = previousSymbol.getrValue();
if (aliasSet.contains(phiRValue)) {
log.append("Alias candidate removed " + phiRValue.getAsTypedString(getSymbols()));
aliasSet.remove(phiRValue);
@ -276,9 +276,9 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
public Void visitPhi(StatementPhi phi) {
if (phi.getPreviousVersions().size() == 1) {
StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0);
if (previousSymbol.getRValue() instanceof VariableRef) {
if (previousSymbol.getrValue() instanceof VariableRef) {
VariableRef variable = phi.getlValue();
VariableRef alias = (VariableRef) previousSymbol.getRValue();
VariableRef alias = (VariableRef) previousSymbol.getrValue();
aliases.add(variable, alias);
}
}

View File

@ -5,8 +5,8 @@ import dk.camelot64.kickc.icl.*;
/** Assert that all referenced blocks exist in the program */
public class Pass2AssertBlocks extends Pass2SsaAssertion {
public Pass2AssertBlocks(ControlFlowGraph graph, ProgramScope scope) {
super(graph, scope);
public Pass2AssertBlocks(Program program) {
super(program);
}
@Override

View File

@ -7,8 +7,8 @@ import java.util.HashSet;
/** Asserts that the symbols in the symbol table match exactly the symbols in the program */
public class Pass2AssertSymbols extends Pass2SsaAssertion {
public Pass2AssertSymbols(ControlFlowGraph graph, ProgramScope scope) {
super(graph, scope);
public Pass2AssertSymbols(Program program) {
super(program);
}
@Override
@ -156,7 +156,7 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
public Void visitPhi(StatementPhi phi) {
addSymbol(phi.getlValue());
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
addSymbol(previousSymbol.getRValue());
addSymbol(previousSymbol.getrValue());
}
return super.visitPhi(phi);
}

View File

@ -12,10 +12,8 @@ import java.util.Map;
*/
public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
private Map<Variable, List<Statement>> allUsages;
public Pass2ConditionalJumpSimplification(ControlFlowGraph graph, ProgramScope scope, CompileLog log) {
super(graph, scope, log);
public Pass2ConditionalJumpSimplification(Program program, CompileLog log) {
super(program, log);
}
/**

View File

@ -19,8 +19,8 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
private Map<VariableRef, Integer> usages;
public Pass2ConstantAdditionElimination(ControlFlowGraph graph, ProgramScope scope, CompileLog log) {
super(graph, scope, log);
public Pass2ConstantAdditionElimination(Program program, CompileLog log) {
super(program, log);
}
/**

View File

@ -9,8 +9,8 @@ import java.util.Map;
/** Compiler Pass propagating constants in expressions eliminating constant variables */
public class Pass2ConstantPropagation extends Pass2SsaOptimization {
public Pass2ConstantPropagation(ControlFlowGraph graph, ProgramScope scope, CompileLog log) {
super(graph, scope, log);
public Pass2ConstantPropagation(Program program, CompileLog log) {
super(program, log);
}
/**
@ -71,9 +71,9 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization {
public Void visitPhi(StatementPhi phi) {
if (phi.getPreviousVersions().size() == 1) {
StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0);
if (previousSymbol.getRValue() instanceof Constant) {
if (previousSymbol.getrValue() instanceof Constant) {
VariableRef variable = phi.getlValue();
Constant constant = (Constant) previousSymbol.getRValue();
Constant constant = (Constant) previousSymbol.getrValue();
constants.put(variable, constant);
}
}

View File

@ -8,8 +8,8 @@ import java.util.*;
/** Pass that culls empty control flow blocks from the program */
public class Pass2CullEmptyBlocks extends Pass2SsaOptimization {
public Pass2CullEmptyBlocks(ControlFlowGraph graph, ProgramScope scope, CompileLog log) {
super(graph, scope, log);
public Pass2CullEmptyBlocks(Program program, CompileLog log) {
super(program, log);
}
@Override
@ -46,7 +46,7 @@ public class Pass2CullEmptyBlocks extends Pass2SsaOptimization {
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
if(previousSymbol.getBlock().equals(removeBlock.getLabel())) {
// Found a phi function referencing the remove block - add copies for each predecessor
RValue previousRValue = previousSymbol.getRValue();
RValue previousRValue = previousSymbol.getrValue();
for (ControlFlowBlock predecessor : predecessors) {
if(previousSymbol!=null) {
previousSymbol.setBlock(predecessor.getLabel());

View File

@ -9,8 +9,8 @@ import java.util.Map;
/** Compiler Pass eliminating redundant phi functions */
public class Pass2RedundantPhiElimination extends Pass2SsaOptimization {
public Pass2RedundantPhiElimination(ControlFlowGraph graph, ProgramScope scope, CompileLog log) {
super(graph, scope, log);
public Pass2RedundantPhiElimination(Program program, CompileLog log) {
super(program, log);
}
/**
@ -42,9 +42,9 @@ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization {
RValue phiRValue = null;
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
if(phiRValue==null) {
phiRValue = previousSymbol.getRValue();
phiRValue = previousSymbol.getrValue();
} else {
if(!phiRValue.equals(previousSymbol.getRValue())) {
if(!phiRValue.equals(previousSymbol.getrValue())) {
found = false;
break;
}

View File

@ -8,8 +8,8 @@ import java.util.Iterator;
/** Compiler Pass eliminating phi self assignments */
public class Pass2SelfPhiElimination extends Pass2SsaOptimization {
public Pass2SelfPhiElimination(ControlFlowGraph graph, ProgramScope scope, CompileLog log) {
super(graph, scope, log);
public Pass2SelfPhiElimination(Program program, CompileLog log) {
super(program, log);
}
/**
@ -23,7 +23,7 @@ public class Pass2SelfPhiElimination extends Pass2SsaOptimization {
public Void visitPhi(StatementPhi phi) {
for (Iterator<StatementPhi.PreviousSymbol> iterator = phi.getPreviousVersions().iterator(); iterator.hasNext(); ) {
StatementPhi.PreviousSymbol previousSymbol = iterator.next();
if (previousSymbol.getRValue().equals(phi.getlValue())) {
if (previousSymbol.getrValue().equals(phi.getlValue())) {
iterator.remove();
optimized[0] = Boolean.TRUE;
log.append("Self Phi Eliminated "+phi.getlValue().getAsTypedString(getSymbols()));

View File

@ -11,9 +11,9 @@ public abstract class Pass2SsaAssertion {
private ControlFlowGraph graph;
private ProgramScope programScope;
public Pass2SsaAssertion(ControlFlowGraph graph, ProgramScope programScope) {
this.graph = graph;
this.programScope = programScope;
public Pass2SsaAssertion(Program program) {
this.graph = program.getGraph();
this.programScope = program.getScope();
}
public ControlFlowGraph getGraph() {

View File

@ -15,10 +15,10 @@ public abstract class Pass2SsaOptimization {
private ControlFlowGraph graph;
private ProgramScope scope;
public Pass2SsaOptimization(ControlFlowGraph graph, ProgramScope scope,CompileLog log) {
public Pass2SsaOptimization(Program program,CompileLog log) {
this.log = log;
this.graph = graph;
this.scope = scope;
this.graph = program.getGraph();
this.scope = program.getScope();
}
public CompileLog getLog() {
@ -154,12 +154,12 @@ public abstract class Pass2SsaOptimization {
}
for (Iterator<StatementPhi.PreviousSymbol> iterator = phi.getPreviousVersions().iterator(); iterator.hasNext(); ) {
StatementPhi.PreviousSymbol previousSymbol = iterator.next();
if (getAlias(aliases, previousSymbol.getRValue()) != null) {
RValue alias = getAlias(aliases, previousSymbol.getRValue());
if (getAlias(aliases, previousSymbol.getrValue()) != null) {
RValue alias = getAlias(aliases, previousSymbol.getrValue());
if (VOID.equals(alias)) {
iterator.remove();
} else {
previousSymbol.setRValue(alias);
previousSymbol.setrValue(alias);
}
}
}
@ -328,7 +328,7 @@ public abstract class Pass2SsaOptimization {
@Override
public Void visitPhi(StatementPhi phi) {
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
addUsage(previousSymbol.getRValue(), phi);
addUsage(previousSymbol.getrValue(), phi);
}
return null;
}
@ -395,7 +395,7 @@ public abstract class Pass2SsaOptimization {
@Override
public Object visitPhi(StatementPhi phi) {
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
addUsage(previousSymbol.getRValue());
addUsage(previousSymbol.getrValue());
}
return null;
}

View File

@ -1,8 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.icl.ControlFlowBlock;
import dk.camelot64.kickc.icl.ControlFlowGraph;
import dk.camelot64.kickc.icl.Scope;
import dk.camelot64.kickc.icl.*;
import java.util.ArrayList;
import java.util.List;
@ -11,42 +9,42 @@ import java.util.Stack;
/** Plan the optimal sequence for the blocks of the control flow graph */
public class Pass3BlockSequencePlanner {
private ControlFlowGraph controlFlowGraph;
private Scope programScope;
private ControlFlowGraph graph;
private ProgramScope scope;
public Pass3BlockSequencePlanner(ControlFlowGraph controlFlowGraph, Scope programScope) {
this.controlFlowGraph = controlFlowGraph;
this.programScope = programScope;
public Pass3BlockSequencePlanner(Program program) {
this.graph = program.getGraph();
this.scope = program.getScope();
}
public void plan() {
Stack<ControlFlowBlock> todo = new Stack<>();
ControlFlowBlock mainBlock = controlFlowGraph.getMainBlock();
ControlFlowBlock mainBlock = graph.getMainBlock();
if (mainBlock != null) {
todo.push(mainBlock);
}
todo.push(controlFlowGraph.getFirstBlock());
List<ControlFlowBlock> sequence = new ArrayList<>();
todo.push(graph.getFirstBlock());
List<LabelRef> sequence = new ArrayList<>();
while(!todo.empty()){
ControlFlowBlock block = todo.pop();
if(block==null) {
break;
}
if(sequence.contains(block)) {
if(sequence.contains(block.getLabel())) {
// already handled - move on
continue;
}
sequence.add(block);
sequence.add(block.getLabel());
if(block.getCallSuccessor()!=null) {
todo.push(controlFlowGraph.getCallSuccessor(block));
todo.push(graph.getCallSuccessor(block));
}
if(block.getConditionalSuccessor()!=null) {
todo.push(controlFlowGraph.getConditionalSuccessor(block));
todo.push(graph.getConditionalSuccessor(block));
}
if(controlFlowGraph.getDefaultSuccessor(block)!=null) {
todo.push(controlFlowGraph.getDefaultSuccessor(block));
if(graph.getDefaultSuccessor(block)!=null) {
todo.push(graph.getDefaultSuccessor(block));
}
}
controlFlowGraph.setBlockSequence(sequence);
graph.setSequence(sequence);
}
}

View File

@ -13,14 +13,15 @@ public class Pass3CodeGeneration {
private ControlFlowGraph graph;
private ProgramScope symbols;
public Pass3CodeGeneration(ControlFlowGraph graph, ProgramScope symbols) {
this.graph = graph;
this.symbols = symbols;
public Pass3CodeGeneration(Program program) {
this.graph = program.getGraph();
this.symbols = program.getScope();
}
public AsmProgram generate() {
AsmProgram asm = new AsmProgram();
for (ControlFlowBlock block : graph.getBlockSequence()) {
for (LabelRef blockRef : graph.getSequence()) {
ControlFlowBlock block = graph.getBlock(blockRef);
// Generate entry points (if needed)
genBlockEntryPoints(asm, block);
// Generate label
@ -126,7 +127,7 @@ public class Pass3CodeGeneration {
});
for (StatementPhi.PreviousSymbol previousSymbol : previousVersions) {
if (previousSymbol.getBlock().equals(fromBlock.getLabel())) {
genAsmMove(asm, phi.getlValue(), previousSymbol.getRValue());
genAsmMove(asm, phi.getlValue(), previousSymbol.getrValue());
break;
}
}

View File

@ -11,9 +11,9 @@ public class Pass3RegisterAllocation {
private ProgramScope symbols;
int currentZp = 2;
public Pass3RegisterAllocation(ControlFlowGraph graph, ProgramScope symbols) {
this.graph = graph;
this.symbols = symbols;
public Pass3RegisterAllocation(Program program) {
this.graph = program.getGraph();
this.symbols = program.getScope();
}
public void allocate() {

File diff suppressed because one or more lines are too long