1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-02 00:41:42 +00:00

Control Flow Graph now handles procs & sub sprocs

This commit is contained in:
jespergravgaard 2017-06-11 19:15:09 +02:00
parent 40d44da2fc
commit 12bff79433
11 changed files with 128 additions and 57 deletions

View File

@ -16,7 +16,7 @@ public class ConstantInteger implements Constant {
}
public SymbolType getType() {
return PassTypeInference.inferType(this);
return Pass1TypeInference.inferType(this);
}
@Override

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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