1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-08-02 09:29:35 +00:00

Merge remote-tracking branch 'gitlab/master'

This commit is contained in:
jespergravgaard 2017-06-13 19:48:14 +02:00
commit a5204acf79
21 changed files with 134 additions and 52 deletions

View File

@ -133,9 +133,9 @@ public class AsmFragment {
signature.append("_then_");
Label destination = conditionalJump.getDestination();
ControlFlowBlock destinationBlock = graph.getBlock(destination);
String destinationLabel = destination.getLocalName();
String destinationLabel = destination.getFullName();
if (destinationBlock.hasPhiStatements()) {
destinationLabel = destination.getLocalName() + "_from_" + block.getLabel().getLocalName();
destinationLabel = destination.getFullName() + "_from_" + block.getLabel().getFullName();
}
signature.append(bind(new Label(destinationLabel, destination.getScope(),false)));
return signature.toString();
@ -348,7 +348,7 @@ public class AsmFragment {
bound = Integer.toString(boundInt.getNumber());
}
} else if (boundValue instanceof Label) {
bound = ((Label) boundValue).getLocalName().replace('@', 'B');
bound = ((Label) boundValue).getFullName().replace('@', 'B');
} else {
throw new RuntimeException("Bound Value Type not implemented " + boundValue);
}

View File

@ -72,13 +72,13 @@ public class ControlFlowBlock {
public String toString(ControlFlowGraph graph) {
StringBuffer out = new StringBuffer();
out.append(label.getLocalName() + ":" );
out.append(label.getFullName() + ":" );
out.append(" from");
if(graph!=null) {
List<ControlFlowBlock> predecessors = graph.getPredecessors(this);
if(predecessors.size()>0) {
for (ControlFlowBlock predecessor : predecessors) {
out.append(" " + predecessor.getLabel().getLocalName());
out.append(" " + predecessor.getLabel().getFullName());
}
}
} else {
@ -90,7 +90,7 @@ public class ControlFlowBlock {
}
if(defaultSuccessor!=null) {
out.append(" to:");
out.append(defaultSuccessor.getLocalName());
out.append(defaultSuccessor.getFullName());
out.append("\n");
}
return out.toString();

View File

@ -69,6 +69,15 @@ public class ControlFlowGraph {
}
}
public ControlFlowBlock getCallSuccessor(ControlFlowBlock block) {
if(block.getCallSuccessor()!=null) {
return blocks.get(block.getCallSuccessor());
} else {
return null;
}
}
public List<ControlFlowBlock> getPredecessors(ControlFlowBlock block) {
ArrayList<ControlFlowBlock> predecessorBlocks = new ArrayList<>();
for (ControlFlowBlock other : getAllBlocks()) {

View File

@ -31,8 +31,8 @@ public class ControlFlowGraphBaseVisitor<T> {
return visitJumpTarget((StatementLabel) statement);
} else if(statement instanceof StatementPhi) {
return visitPhi((StatementPhi) statement);
} else if(statement instanceof StatementCallLValue) {
return visitCallLValue((StatementCallLValue) statement);
} else if(statement instanceof StatementCall) {
return visitCallLValue((StatementCall) statement);
} else if(statement instanceof StatementReturn) {
return visitReturn((StatementReturn) statement);
} else if(statement instanceof StatementProcedureBegin) {
@ -76,7 +76,7 @@ public class ControlFlowGraphBaseVisitor<T> {
return null;
}
public T visitCallLValue(StatementCallLValue callLValue) {
public T visitCallLValue(StatementCall callLValue) {
return null;
}

View File

@ -156,11 +156,11 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
}
@Override
public StatementCallLValue visitCallLValue(StatementCallLValue callLValue) {
public StatementCall visitCallLValue(StatementCall callLValue) {
LValue lValue = callLValue.getLValue();
String procedureName = callLValue.getProcedureName();
List<RValue> parameters = callLValue.getParameters();
return new StatementCallLValue(lValue, procedureName, parameters);
return new StatementCall(lValue, procedureName, parameters);
}
@Override

View File

@ -43,8 +43,8 @@ public class Pass1GenerateSingleStaticAssignmentForm {
VariableVersion version = symbols.createVersion(assignedSymbol);
assignment.setLValue(version);
}
} else if(statement instanceof StatementCallLValue) {
StatementCallLValue call = (StatementCallLValue) statement;
} else if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
LValue lValue = call.getLValue();
if (lValue instanceof VariableUnversioned) {
// Assignment to a non-versioned non-intermediary variable
@ -67,6 +67,16 @@ public class Pass1GenerateSingleStaticAssignmentForm {
// New phi functions introduced in the block to create versions of variables.
Map<VariableUnversioned, VariableVersion> blockNewPhis = new HashMap<>();
for (Statement statement : block.getStatements()) {
if(statement instanceof StatementReturn) {
StatementReturn statementReturn = (StatementReturn) statement;
{
VariableVersion version = findOrCreateVersion(statementReturn.getValue(), blockVersions, blockNewPhis);
if (version != null) {
statementReturn.setValue(version);
}
}
}
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
{
@ -234,8 +244,8 @@ public class Pass1GenerateSingleStaticAssignmentForm {
symbolMap.put(label, blockMap);
}
blockMap.put(unversioned, versioned);
} else if (statement instanceof StatementCallLValue) {
StatementCallLValue call = (StatementCallLValue) statement;
} else if (statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
LValue lValue = call.getLValue();
if (lValue instanceof VariableVersion) {
VariableVersion versioned = (VariableVersion) lValue;

View File

@ -32,6 +32,15 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
return scopeStack.peek();
}
private Procedure getCurrentProcedure() {
for (Scope scope : scopeStack) {
if (scope instanceof Procedure) {
return (Procedure) scope;
}
}
return null;
}
public void generate(KickCParser.FileContext file) {
this.visit(file);
}
@ -131,13 +140,23 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
String name = ctx.NAME().getText();
Procedure procedure = getCurrentSymbols().addProcedure(name, type);
scopeStack.push(procedure);
Label procExit = procedure.addLabel("@return");
VariableUnversioned returnVar = null;
if (!SymbolTypeBasic.VOID.equals(type)) {
returnVar = procedure.addVariable("return", type);
}
List<Variable> parameterList = new ArrayList<>();
if(ctx.parameterListDecl()!=null) {
if (ctx.parameterListDecl() != null) {
parameterList = (List<Variable>) this.visit(ctx.parameterListDecl());
}
procedure.setParameters(parameterList);
sequence.addStatement(new StatementProcedureBegin(procedure));
this.visit(ctx.stmtSeq());
sequence.addStatement(new StatementLabel(procExit));
if(returnVar!=null) {
sequence.addStatement(new StatementAssignment(returnVar, returnVar));
}
sequence.addStatement(new StatementReturn(returnVar));
scopeStack.pop();
sequence.addStatement(new StatementProcedureEnd(procedure));
return null;
@ -146,7 +165,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
@Override
public List<Variable> visitParameterListDecl(KickCParser.ParameterListDeclContext ctx) {
ArrayList<Variable> parameterDecls = new ArrayList<>();
for (KickCParser.ParameterDeclContext parameterDeclCtx: ctx.parameterDecl()) {
for (KickCParser.ParameterDeclContext parameterDeclCtx : ctx.parameterDecl()) {
Variable parameterDecl = (Variable) this.visit(parameterDeclCtx);
parameterDecls.add(parameterDecl);
}
@ -162,13 +181,16 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
@Override
public Void visitStmtReturn(KickCParser.StmtReturnContext ctx) {
Procedure procedure = getCurrentProcedure();
KickCParser.ExprContext exprCtx = ctx.expr();
RValue rValue = null;
if (exprCtx != null) {
rValue = (RValue) this.visit(exprCtx);
Variable returnVar = procedure.getVariable("return");
sequence.addStatement(new StatementAssignment(returnVar, rValue));
}
Statement stmt = new StatementReturn(rValue);
sequence.addStatement(stmt);
Label returnLabel = procedure.getLabel("@return");
sequence.addStatement(new StatementJump(returnLabel));
return null;
}
@ -265,7 +287,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
public Object visitExprCall(KickCParser.ExprCallContext ctx) {
List<RValue> parameters = (List<RValue>) this.visit(ctx.parameterList());
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
sequence.addStatement(new StatementCallLValue(tmpVar, ctx.NAME().getText(), parameters));
sequence.addStatement(new StatementCall(tmpVar, ctx.NAME().getText(), parameters));
return tmpVar;
}

View File

@ -19,7 +19,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
}
@Override
public StatementCallLValue visitCallLValue(StatementCallLValue origCall) {
public StatementCall visitCallLValue(StatementCall origCall) {
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
// Generate parameter passing assignments
Procedure procedure = origCall.getProcedure();
@ -32,7 +32,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
}
String procedureName = origCall.getProcedureName();
Variable procReturnVar = procedure.getVariable("return");
StatementCallLValue copyCall = new StatementCallLValue(procReturnVar, procedureName, null);
StatementCall copyCall = new StatementCall(procReturnVar, procedureName, null);
copyCall.setParametersByAssignment(true);
copyCall.setProcedure(procedure);
addStatementToCurrentBlock(copyCall);

View File

@ -6,9 +6,9 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
private Scope scope;
private ControlFlowGraph graph;
public Pass1ProcedureCallsReturnValue(Scope scope, ControlFlowGraph graph ) {
public Pass1ProcedureCallsReturnValue(Scope scope, ControlFlowGraph graph) {
this.scope = scope;
this.graph= graph;
this.graph = graph;
}
public ControlFlowGraph generate() {
@ -17,22 +17,38 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
}
@Override
public StatementCallLValue visitCallLValue(StatementCallLValue origCall) {
public StatementCall visitCallLValue(StatementCall origCall) {
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
// Generate return value assignment
Procedure procedure = origCall.getProcedure();
String procedureName = origCall.getProcedureName();
StatementCallLValue copyCall = new StatementCallLValue(null, procedureName, null);
StatementCall copyCall = new StatementCall(null, procedureName, null);
copyCall.setParametersByAssignment(true);
copyCall.setProcedure(procedure);
addStatementToCurrentBlock(copyCall);
getCurrentBlock().setCallSuccessor(procedure.getLabel());
//StatementAssignment returnAssignment = new StatementAssignment();
// Find return variable final version
Label returnBlockLabel = procedure.getLabel("@return");
ControlFlowBlock returnBlock = graph.getBlock(returnBlockLabel);
VariableVersion returnVarFinal = null;
for (Statement statement : returnBlock.getStatements()) {
if (statement instanceof StatementReturn) {
StatementReturn statementReturn = (StatementReturn) statement;
RValue returnValue = statementReturn.getValue();
if (returnValue instanceof VariableVersion) {
returnVarFinal = (VariableVersion) returnValue;
}
}
}
if (returnVarFinal == null) {
throw new RuntimeException("Error! Cannot find final return variable for " + procedure.getFullName());
}
StatementAssignment returnAssignment = new StatementAssignment(origCall.getLValue(), returnVarFinal);
addStatementToCurrentBlock(returnAssignment);
return null;
}
}

View File

@ -40,8 +40,8 @@ public class Pass1TypeInference {
}
}
}
} else if(statement instanceof StatementCallLValue) {
StatementCallLValue call = (StatementCallLValue) statement;
} else if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
LValue lValue = call.getLValue();
if(lValue instanceof Variable) {
String procedureName = call.getProcedureName();

View File

@ -23,7 +23,7 @@ public class Pass3CodeGeneration {
// Generate entry points (if needed)
genBlockEntryPoints(asm, block);
// Generate label
asm.addLabel(block.getLabel().getLocalName().replace('@', 'B'));
asm.addLabel(block.getLabel().getFullName().replace('@', 'B'));
// Generate statements
genStatements(asm, block);
// Generate exit
@ -32,7 +32,7 @@ public class Pass3CodeGeneration {
if (defaultSuccessor.hasPhiStatements()) {
genBlockPhiTransition(asm, block, defaultSuccessor);
}
asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getLocalName().replace('@', 'B'));
asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getFullName().replace('@', 'B'));
}
}
return asm;
@ -72,6 +72,15 @@ public class Pass3CodeGeneration {
AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, block, symbols, graph);
asm.addComment(statement + " // " + asmFragment.getSignature());
asmFragment.generate(asm);
} else if (statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
ControlFlowBlock callSuccessor = graph.getCallSuccessor(block);
if (callSuccessor != null && callSuccessor.hasPhiStatements()) {
genBlockPhiTransition(asm, block, callSuccessor);
}
asm.addInstruction("jsr", AsmAddressingMode.ABS, call.getProcedure().getFullName());
} else if (statement instanceof StatementReturn) {
asm.addInstruction("rts", AsmAddressingMode.NON, null);
} else {
throw new RuntimeException("Statement not supported " + statement);
}
@ -84,14 +93,14 @@ public class Pass3CodeGeneration {
for (ControlFlowBlock predecessor : graph.getPredecessors(block)) {
if (block.getLabel().equals(predecessor.getConditionalSuccessor())) {
genBlockPhiTransition(asm, predecessor, block);
asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getLocalName().replace('@', 'B'));
asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getFullName().replace('@', 'B'));
}
}
}
}
private void genBlockPhiTransition(AsmProgram asm, ControlFlowBlock fromBlock, ControlFlowBlock toBlock) {
asm.addLabel((toBlock.getLabel().getLocalName() + "_from_" + fromBlock.getLabel().getLocalName()).replace('@', 'B'));
asm.addLabel((toBlock.getLabel().getFullName() + "_from_" + fromBlock.getLabel().getLocalName()).replace('@', 'B'));
for (Statement statement : toBlock.getStatements()) {
if (!(statement instanceof StatementPhi)) {
// No more phi statements to handle
@ -99,7 +108,7 @@ public class Pass3CodeGeneration {
}
StatementPhi phi = (StatementPhi) statement;
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
if (previousSymbol.getBlock().equals(fromBlock)) {
if (previousSymbol.getBlock().equals(fromBlock.getLabel())) {
genAsmMove(asm, phi.getLValue(), previousSymbol.getRValue());
break;
}

View File

@ -117,6 +117,9 @@ public class Scope implements Symbol {
return symbol;
}
public Label getLabel(String name) {
return (Label) symbols.get(name);
}
public Procedure addProcedure(String name, SymbolType type) {
Symbol symbol = symbols.get(name);
@ -125,7 +128,6 @@ public class Scope implements Symbol {
}
Procedure procedure = new Procedure(name, type, this);
add(procedure);
procedure.addVariable("return", type);
return procedure;
}

View File

@ -7,16 +7,16 @@ import java.util.List;
* <br>
* <i> X<sub>i</sub> := call label param1 param2 param3 ... </i>
*/
public class StatementCallLValue implements StatementLValue {
public class StatementCall implements StatementLValue {
/** The variable being assigned a value by the call. */
/** The variable being assigned a value by the call. Can be null. */
private LValue lValue;
private String procedureName;
private List<RValue> parameters;
private Procedure procedure;
private boolean parametersByAssignment;
public StatementCallLValue(LValue lValue, String procedureName, List<RValue> parameters) {
public StatementCall(LValue lValue, String procedureName, List<RValue> parameters) {
this.lValue = lValue;
this.procedureName = procedureName;
this.parameters = parameters;
@ -66,8 +66,10 @@ public class StatementCallLValue implements StatementLValue {
@Override
public String toString() {
StringBuilder res = new StringBuilder();
res.append(lValue);
res.append("");
if(lValue!=null) {
res.append(lValue);
res.append("");
}
res.append("call ");
if(procedure!=null) {
res.append(procedure.getFullName()+ " ");

View File

@ -72,7 +72,7 @@ public class StatementConditionalJump implements Statement {
}
out.append(rValue2);
out.append(") goto ");
out.append(destination.getLocalName());
out.append(destination.getFullName());
return out.toString();
}

View File

@ -20,7 +20,7 @@ public class StatementJump implements Statement {
@Override
public String toString() {
return "goto "+destination.getLocalName();
return "goto "+destination.getFullName();
}
public void setDestination(Label destination) {

View File

@ -77,7 +77,7 @@ public class StatementPhi implements StatementLValue {
StringBuilder out = new StringBuilder();
out.append(lValue + "" + "phi(");
for (PreviousSymbol previousSymbol : previousVersions) {
out.append(" "+previousSymbol.getBlock().getLocalName()+"/"+previousSymbol.getRValue());
out.append(" "+previousSymbol.getBlock().getFullName()+"/"+previousSymbol.getRValue());
}
out.append(" )");
return out.toString();

View File

@ -15,7 +15,7 @@ public class StatementProcedureEnd implements Statement {
@Override
public String toString() {
return "endproc // "+procedure.getLocalName()+"()";
return "endproc // "+procedure.getFullName()+"()";
}
}

View File

@ -16,6 +16,10 @@ public class StatementReturn implements Statement {
return value;
}
public void setValue(RValue value) {
this.value = value;
}
@Override
public String toString() {
return "return "+(value==null?"":value);

View File

@ -8,6 +8,8 @@ public enum SymbolTypeBasic implements SymbolType {
BOOLEAN("boolean"),
// A label
LABEL("label"),
// Void type.
VOID("void"),
// Unresolved type. Will be infered later
VAR("var");

View File

@ -13,7 +13,7 @@ import java.util.List;
/** Test my KickC Grammar */
public class Main {
public static void main(String[] args) throws IOException {
final String fileName = "src/dk/camelot64/kickc/test/callsum.kc";
final String fileName = "src/dk/camelot64/kickc/test/callmin.kc";
final CharStream input = CharStreams.fromFileName(fileName);
System.out.println(input.toString());
KickCLexer lexer = new KickCLexer(input);
@ -54,12 +54,12 @@ public class Main {
System.out.println("CONTROL FLOW GRAPH SSA");
System.out.println(controlFlowGraph.toString());
//Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue = new Pass1ProcedureCallsReturnValue(programScope, controlFlowGraph);
//controlFlowGraph = pass1ProcedureCallsReturnValue.generate();
//System.out.println("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN");
//System.out.println(controlFlowGraph.toString());
Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue = new Pass1ProcedureCallsReturnValue(programScope, controlFlowGraph);
controlFlowGraph = pass1ProcedureCallsReturnValue.generate();
System.out.println("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN");
System.out.println(controlFlowGraph.toString());
if(1==1) return;
//if(1==1) return;
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, programScope));

View File

@ -0,0 +1,6 @@
byte bv = inc(5);
bv = inc(bv);
byte inc(byte a) {
return a+1;
}