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:
parent
d38c26eeb5
commit
6ef3af4fdf
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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"),
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()));
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user