mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-03-13 19:33:12 +00:00
Control Flow Graph now handles procs & sub sprocs
This commit is contained in:
parent
40d44da2fc
commit
12bff79433
@ -16,7 +16,7 @@ public class ConstantInteger implements Constant {
|
||||
}
|
||||
|
||||
public SymbolType getType() {
|
||||
return PassTypeInference.inferType(this);
|
||||
return Pass1TypeInference.inferType(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,8 +86,8 @@ public class ControlFlowBlock {
|
||||
if(defaultSuccessor!=null) {
|
||||
out.append(" to:");
|
||||
out.append(defaultSuccessor.getLabel().getLocalName());
|
||||
out.append("\n");
|
||||
}
|
||||
out.append("\n");
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ public class ControlFlowGraph {
|
||||
public String toString() {
|
||||
StringBuffer out = new StringBuffer();
|
||||
for (ControlFlowBlock block : blocks.values()) {
|
||||
out.append(block);
|
||||
out.append(block.toString());
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package dk.camelot64.kickc.icl;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
/** Pass that generates a control flow graph for the program */
|
||||
public class Pass1GenerateControlFlowGraph {
|
||||
@ -19,22 +20,26 @@ public class Pass1GenerateControlFlowGraph {
|
||||
|
||||
public ControlFlowGraph generate(StatementSequence sequence) {
|
||||
this.firstBlock = getOrCreateBlock(scope.addLabel(BEGIN_BLOCK_NAME));
|
||||
ControlFlowBlock currentBlock = this.firstBlock;
|
||||
Stack<ControlFlowBlock> blockStack = new Stack<>();
|
||||
blockStack.push(firstBlock);
|
||||
sequence.addStatement(new StatementLabel(scope.addLabel(END_BLOCK_NAME)));
|
||||
for (Statement statement : sequence.getStatements()) {
|
||||
ControlFlowBlock currentBlock = blockStack.peek();
|
||||
if(statement instanceof StatementLabel) {
|
||||
StatementLabel statementLabel = (StatementLabel) statement;
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(statementLabel.getLabel());
|
||||
currentBlock.setDefaultSuccessor(nextBlock);
|
||||
nextBlock.addPredecessor(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
blockStack.pop();
|
||||
blockStack.push(nextBlock);
|
||||
} else if(statement instanceof StatementJump) {
|
||||
StatementJump statementJump = (StatementJump) statement;
|
||||
ControlFlowBlock jmpBlock = getOrCreateBlock(statementJump.getDestination());
|
||||
currentBlock.setDefaultSuccessor(jmpBlock);
|
||||
jmpBlock.addPredecessor(currentBlock);
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate());
|
||||
currentBlock = nextBlock;
|
||||
blockStack.pop();
|
||||
blockStack.push(nextBlock);
|
||||
} else if(statement instanceof StatementConditionalJump) {
|
||||
currentBlock.addStatement(statement);
|
||||
StatementConditionalJump statementConditionalJump = (StatementConditionalJump) statement;
|
||||
@ -44,8 +49,25 @@ public class Pass1GenerateControlFlowGraph {
|
||||
currentBlock.setConditionalSuccessor(jmpBlock);
|
||||
nextBlock.addPredecessor(currentBlock);
|
||||
jmpBlock.addPredecessor(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
} else {
|
||||
blockStack.pop();
|
||||
blockStack.push(nextBlock);
|
||||
} else if(statement instanceof StatementProcedureBegin) {
|
||||
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
||||
StatementProcedureBegin procedure = (StatementProcedureBegin) statement;
|
||||
procedure.setStrategy(StatementProcedureBegin.Strategy.PASS_BY_REGISTER);
|
||||
Label procedureLabel = procedure.getProcedure().getLabel();
|
||||
ControlFlowBlock procBlock = getOrCreateBlock(procedureLabel);
|
||||
blockStack.push(procBlock);
|
||||
} else if(statement instanceof StatementProcedureEnd) {
|
||||
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
||||
currentBlock.setDefaultSuccessor(new ControlFlowBlock(new Label("@RETURN", scope, false)));
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate());
|
||||
blockStack.pop();
|
||||
ControlFlowBlock prevBlock = blockStack.pop();
|
||||
prevBlock.setDefaultSuccessor(nextBlock);
|
||||
nextBlock.addPredecessor(prevBlock);
|
||||
blockStack.push(nextBlock);
|
||||
} else {
|
||||
currentBlock.addStatement(statement);
|
||||
}
|
||||
}
|
||||
|
@ -13,23 +13,23 @@ import java.util.Stack;
|
||||
*/
|
||||
public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
private Scope programSymbols;
|
||||
private Stack<Scope> symbolsStack;
|
||||
private Scope programScope;
|
||||
private Stack<Scope> scopeStack;
|
||||
private StatementSequence sequence;
|
||||
|
||||
public Pass1GenerateStatementSequence() {
|
||||
this.programSymbols = new Scope();
|
||||
this.symbolsStack = new Stack<>();
|
||||
symbolsStack.push(programSymbols);
|
||||
this.programScope = new Scope();
|
||||
this.scopeStack = new Stack<>();
|
||||
scopeStack.push(programScope);
|
||||
this.sequence = new StatementSequence();
|
||||
}
|
||||
|
||||
public Scope getProgramSymbols() {
|
||||
return programSymbols;
|
||||
public Scope getProgramScope() {
|
||||
return programScope;
|
||||
}
|
||||
|
||||
private Scope getCurrentSymbols() {
|
||||
return symbolsStack.peek();
|
||||
return scopeStack.peek();
|
||||
}
|
||||
|
||||
public void generate(KickCParser.FileContext file) {
|
||||
@ -130,12 +130,15 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
SymbolType type = (SymbolType) visit(ctx.typeDecl());
|
||||
String name = ctx.NAME().getText();
|
||||
Procedure procedure = getCurrentSymbols().addProcedure(name, type);
|
||||
symbolsStack.push(procedure);
|
||||
List<Variable> parameterList = (List<Variable>) this.visit(ctx.parameterListDecl());
|
||||
scopeStack.push(procedure);
|
||||
List<Variable> parameterList = new ArrayList<>();
|
||||
if(ctx.parameterListDecl()!=null) {
|
||||
parameterList = (List<Variable>) this.visit(ctx.parameterListDecl());
|
||||
}
|
||||
procedure.setParameters(parameterList);
|
||||
sequence.addStatement(new StatementProcedureBegin(procedure));
|
||||
this.visit(ctx.stmtSeq());
|
||||
symbolsStack.pop();
|
||||
scopeStack.pop();
|
||||
sequence.addStatement(new StatementProcedureEnd(procedure));
|
||||
return null;
|
||||
}
|
||||
@ -260,10 +263,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public Object visitExprCall(KickCParser.ExprCallContext ctx) {
|
||||
Label label = new Label(ctx.NAME().getText(), getCurrentSymbols(), false);
|
||||
List<RValue> parameters = (List<RValue>) this.visit(ctx.parameterList());
|
||||
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
|
||||
sequence.addStatement(new StatementCallLValue(tmpVar, label, parameters));
|
||||
sequence.addStatement(new StatementCallLValue(tmpVar, ctx.NAME().getText(), parameters));
|
||||
return tmpVar;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,23 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/**
|
||||
* Pass through the SSA statements inferring types of unresolved variables.
|
||||
*/
|
||||
public class PassTypeInference {
|
||||
import java.util.Stack;
|
||||
|
||||
public void inferTypes(StatementSequence sequence, Scope symbols) {
|
||||
/**
|
||||
* Pass through the generated statements inferring types of unresolved variables.
|
||||
* Also updates procedure calls to point to the actual procedure called.
|
||||
*/
|
||||
public class Pass1TypeInference {
|
||||
|
||||
public void inferTypes(StatementSequence sequence, Scope programScope) {
|
||||
Stack<Scope> scopes = new Stack<>();
|
||||
scopes.add(programScope);
|
||||
for (Statement statement : sequence.getStatements()) {
|
||||
if (statement instanceof StatementAssignment) {
|
||||
if(statement instanceof StatementProcedureBegin) {
|
||||
StatementProcedureBegin procedureBegin = (StatementProcedureBegin) statement;
|
||||
scopes.push(procedureBegin.getProcedure());
|
||||
} else if(statement instanceof StatementProcedureEnd) {
|
||||
scopes.pop();
|
||||
} else if (statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
LValue lValue = assignment.getLValue();
|
||||
if (lValue instanceof Variable) {
|
||||
@ -31,11 +41,12 @@ public class PassTypeInference {
|
||||
}
|
||||
}
|
||||
} else if(statement instanceof StatementCallLValue) {
|
||||
StatementCallLValue callLValue = (StatementCallLValue) statement;
|
||||
LValue lValue = callLValue.getLValue();
|
||||
StatementCallLValue call = (StatementCallLValue) statement;
|
||||
LValue lValue = call.getLValue();
|
||||
if(lValue instanceof Variable) {
|
||||
Label label = callLValue.getCallLabel();
|
||||
Procedure procedure = symbols.getProcedure(label.getLocalName());
|
||||
String procedureName = call.getProcedureName();
|
||||
Procedure procedure = scopes.peek().getProcedure(procedureName);
|
||||
call.setProcedure(procedure);
|
||||
((Variable) lValue).setInferredType(procedure.getReturnType());
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ public class Procedure extends Scope {
|
||||
}
|
||||
|
||||
public Label getLabel() {
|
||||
return new Label(getLocalName(), this, false);
|
||||
return new Label(getFullName(), getScope(), false);
|
||||
}
|
||||
|
||||
public SymbolType getReturnType() {
|
||||
|
@ -11,12 +11,13 @@ public class StatementCallLValue implements StatementLValue {
|
||||
|
||||
/** The variable being assigned a value by the call. */
|
||||
private LValue lValue;
|
||||
private Label callLabel;
|
||||
private String procedureName;
|
||||
private List<RValue> parameters;
|
||||
private Procedure procedure;
|
||||
|
||||
public StatementCallLValue(LValue lValue, Label callLabel, List<RValue> parameters) {
|
||||
public StatementCallLValue(LValue lValue, String procedureName, List<RValue> parameters) {
|
||||
this.lValue = lValue;
|
||||
this.callLabel = callLabel;
|
||||
this.procedureName = procedureName;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
@ -28,8 +29,16 @@ public class StatementCallLValue implements StatementLValue {
|
||||
this.lValue = lValue;
|
||||
}
|
||||
|
||||
public Label getCallLabel() {
|
||||
return callLabel;
|
||||
public String getProcedureName() {
|
||||
return procedureName;
|
||||
}
|
||||
|
||||
public Procedure getProcedure() {
|
||||
return procedure;
|
||||
}
|
||||
|
||||
public void setProcedure(Procedure procedure) {
|
||||
this.procedure = procedure;
|
||||
}
|
||||
|
||||
public List<RValue> getParameters() {
|
||||
@ -50,7 +59,11 @@ public class StatementCallLValue implements StatementLValue {
|
||||
res.append(lValue);
|
||||
res.append(" ← ");
|
||||
res.append("call ");
|
||||
res.append(callLabel+" ");
|
||||
if(procedure!=null) {
|
||||
res.append(procedure.getFullName()+ " ");
|
||||
} else {
|
||||
res.append(procedureName + " ");
|
||||
}
|
||||
for (RValue parameter : parameters) {
|
||||
res.append(parameter+" ");
|
||||
}
|
||||
|
@ -5,6 +5,13 @@ public class StatementProcedureBegin implements Statement {
|
||||
|
||||
private Procedure procedure;
|
||||
|
||||
private Strategy strategy;
|
||||
|
||||
public static enum Strategy {
|
||||
PASS_BY_REGISTER,
|
||||
INLINE
|
||||
}
|
||||
|
||||
public StatementProcedureBegin(Procedure procedure) {
|
||||
this.procedure = procedure;
|
||||
}
|
||||
@ -13,6 +20,14 @@ public class StatementProcedureBegin implements Statement {
|
||||
return procedure;
|
||||
}
|
||||
|
||||
public Strategy getStrategy() {
|
||||
return strategy;
|
||||
}
|
||||
|
||||
public void setStrategy(Strategy strategy) {
|
||||
this.strategy = strategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "proc "+procedure.toString();
|
||||
|
@ -29,32 +29,37 @@ public class Main {
|
||||
Pass1GenerateStatementSequence pass1GenerateStatementSequence = new Pass1GenerateStatementSequence();
|
||||
pass1GenerateStatementSequence.generate(file);
|
||||
StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence();
|
||||
Scope scope = pass1GenerateStatementSequence.getProgramSymbols();
|
||||
new PassTypeInference().inferTypes(statementSequence, scope);
|
||||
Scope programScope = pass1GenerateStatementSequence.getProgramScope();
|
||||
new Pass1TypeInference().inferTypes(statementSequence, programScope);
|
||||
|
||||
System.out.println("PROGRAM");
|
||||
System.out.println(statementSequence.toString());
|
||||
System.out.println("SYMBOLS");
|
||||
System.out.println(scope.getSymbolTableContents());
|
||||
System.out.println(programScope.getSymbolTableContents());
|
||||
|
||||
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(scope);
|
||||
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(programScope);
|
||||
ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence);
|
||||
System.out.println("INITIAL CONTROL FLOW GRAPH");
|
||||
System.out.println(controlFlowGraph.toString());
|
||||
|
||||
|
||||
|
||||
|
||||
if(1==1) return;
|
||||
|
||||
Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm =
|
||||
new Pass1GenerateSingleStaticAssignmentForm(scope, controlFlowGraph);
|
||||
new Pass1GenerateSingleStaticAssignmentForm(programScope, controlFlowGraph);
|
||||
pass1GenerateSingleStaticAssignmentForm.generate();
|
||||
|
||||
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
|
||||
optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, scope));
|
||||
optimizations.add(new Pass2ConstantPropagation(controlFlowGraph, scope));
|
||||
optimizations.add(new Pass2ConstantAdditionElimination(controlFlowGraph, scope));
|
||||
optimizations.add(new Pass2AliasElimination(controlFlowGraph, scope));
|
||||
optimizations.add(new Pass2RedundantPhiElimination(controlFlowGraph, scope));
|
||||
optimizations.add(new Pass2SelfPhiElimination(controlFlowGraph, scope));
|
||||
optimizations.add(new Pass2ConditionalJumpSimplification(controlFlowGraph, scope));
|
||||
optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, programScope));
|
||||
optimizations.add(new Pass2ConstantPropagation(controlFlowGraph, programScope));
|
||||
optimizations.add(new Pass2ConstantAdditionElimination(controlFlowGraph, programScope));
|
||||
optimizations.add(new Pass2AliasElimination(controlFlowGraph, programScope));
|
||||
optimizations.add(new Pass2RedundantPhiElimination(controlFlowGraph, programScope));
|
||||
optimizations.add(new Pass2SelfPhiElimination(controlFlowGraph, programScope));
|
||||
optimizations.add(new Pass2ConditionalJumpSimplification(controlFlowGraph, programScope));
|
||||
|
||||
System.out.println("INITIAL CONTROL FLOW GRAPH");
|
||||
System.out.println(controlFlowGraph.toString());
|
||||
|
||||
boolean ssaOptimized = true;
|
||||
while (ssaOptimized) {
|
||||
@ -70,9 +75,9 @@ public class Main {
|
||||
}
|
||||
}
|
||||
|
||||
Pass3RegisterAllocation pass3RegisterAllocation = new Pass3RegisterAllocation(controlFlowGraph, scope);
|
||||
Pass3RegisterAllocation pass3RegisterAllocation = new Pass3RegisterAllocation(controlFlowGraph, programScope);
|
||||
pass3RegisterAllocation.allocate();
|
||||
Pass3CodeGeneration pass3CodeGeneration = new Pass3CodeGeneration(controlFlowGraph, scope);
|
||||
Pass3CodeGeneration pass3CodeGeneration = new Pass3CodeGeneration(controlFlowGraph, programScope);
|
||||
AsmProgram asmProgram = pass3CodeGeneration.generate();
|
||||
|
||||
System.out.println("INITIAL ASM");
|
||||
@ -96,7 +101,7 @@ public class Main {
|
||||
}
|
||||
|
||||
System.out.println("SYMBOLS");
|
||||
System.out.println(scope.toString());
|
||||
System.out.println(programScope.toString());
|
||||
System.out.println("CONTROL FLOW GRAPH");
|
||||
System.out.println(controlFlowGraph.toString());
|
||||
System.out.println("ASSEMBLER");
|
||||
|
@ -5,5 +5,8 @@ a = sum(s, a);
|
||||
return;
|
||||
|
||||
byte sum(byte b1, byte b2) {
|
||||
return b1+b2;
|
||||
}
|
||||
byte b = b1+b2;
|
||||
byte inc( byte c) { return c+1;}
|
||||
return inc(b);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user