1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-26 18:29:54 +00:00

Rewrote calling convention PHI return value pass.

This commit is contained in:
Jesper Gravgaard 2020-03-07 19:11:33 +01:00
parent f32f44cd92
commit 002c498810
2 changed files with 50 additions and 42 deletions

View File

@ -280,7 +280,7 @@ public class Compiler {
//getLog().append("CONTROL FLOW GRAPH (SSA)"); //getLog().append("CONTROL FLOW GRAPH (SSA)");
//getLog().append(program.getGraph().toString(program)); //getLog().append(program.getGraph().toString(program));
program.setGraph(new Pass1ProcedureCallsReturnValue(program).generate()); new Pass1CallingConventionPhiReturnValue(program).execute();
//getLog().append("CONTROL FLOW GRAPH (BEFORE LIST UNWINDING)"); //getLog().append("CONTROL FLOW GRAPH (BEFORE LIST UNWINDING)");
//getLog().append(program.getGraph().toString(program)); //getLog().append(program.getGraph().toString(program));
new PassNUnwindLValueLists(program).execute(); new PassNUnwindLValueLists(program).execute();

View File

@ -8,42 +8,61 @@ import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.ListIterator;
import java.util.Set; import java.util.Set;
/** /**
* Pass that modifies a control flow graph to call procedures by passing return value through registers for {@link Procedure.CallingConvention#PHI_CALL} * Handles return values for {@link Procedure.CallingConvention#PHI_CALL} procedure calls by passing the return value through variable versions.
*/ */
public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor { public class Pass1CallingConventionPhiReturnValue {
private Program program; private Program program;
public Pass1ProcedureCallsReturnValue(Program program) { public Pass1CallingConventionPhiReturnValue(Program program) {
this.program = program; this.program = program;
} }
public ControlFlowGraph generate() { public void execute() {
ControlFlowGraph generated = visitGraph(program.getGraph()); for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
return generated; ListIterator<Statement> stmtIt = block.getStatements().listIterator();
} while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
@Override if(statement instanceof StatementCall) {
public StatementCall visitCall(StatementCall origCall) { StatementCall call = (StatementCall) statement;
// Procedure strategy implemented is currently variable-based transfer of parameters/return values ProcedureRef procedureRef = call.getProcedure();
// Generate return value assignment Procedure procedure = program.getScope().getProcedure(procedureRef);
ProcedureRef procedureRef = origCall.getProcedure(); if(Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention())) {
Procedure procedure = program.getScope().getProcedure(procedureRef); handlePhiCall(call, procedure, block, stmtIt);
// If not PHI-call - skip }
if(!Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention())) { }
StatementCall copyCall = super.visitCall(origCall); }
copyCall.setProcedure(procedureRef);
return copyCall;
} }
String procedureName = origCall.getProcedureName(); for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
StatementCall copyCall = new StatementCall(null, procedureName, null, origCall.getSource(), origCall.getComments()); for(Statement statement : block.getStatements()) {
copyCall.setProcedure(procedureRef); if(statement instanceof StatementReturn) {
addStatementToCurrentBlock(copyCall); StatementReturn statementReturn = (StatementReturn) statement;
getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef()); Procedure procedure = (Procedure) program.getScope().getScope(block.getScope());
if(Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention())) {
statementReturn.setValue(null);
}
}
}
}
}
/**
* Handle PHI-call by assigning return value to LValue and updating all variables modified inside the procedure.
* @param call The call statement
* @param procedure The procedure
* @param block The block containing the call
* @param stmtIt Iterator used for adding statements
*/
void handlePhiCall(StatementCall call, Procedure procedure, ControlFlowBlock block, ListIterator<Statement> stmtIt) {
// Generate return value assignment
block.setCallSuccessor(procedure.getLabel().getRef());
if(!SymbolType.VOID.equals(procedure.getReturnType())) { if(!SymbolType.VOID.equals(procedure.getReturnType())) {
// Find return variable final version // Find return variable final version
Label returnBlockLabel = procedure.getLabel(SymbolRef.PROCEXIT_BLOCK_NAME); Label returnBlockLabel = procedure.getLabel(SymbolRef.PROCEXIT_BLOCK_NAME);
@ -63,12 +82,14 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
if(returnVarFinal == null) { if(returnVarFinal == null) {
throw new RuntimeException("Error! Cannot find final return variable for " + procedure.getFullName()); throw new RuntimeException("Error! Cannot find final return variable for " + procedure.getFullName());
} }
StatementAssignment returnAssignment = new StatementAssignment(origCall.getlValue(), returnVarFinal, origCall.isInitialAssignment(), origCall.getSource(), new ArrayList<>()); // Add assignment of final return variable version to lValue
addStatementToCurrentBlock(returnAssignment); StatementAssignment returnAssignment = new StatementAssignment(call.getlValue(), returnVarFinal, call.isInitialAssignment(), call.getSource(), new ArrayList<>());
stmtIt.add(returnAssignment);
call.setlValue(null);
} }
// Patch versions of rValues in assignments for vars modified in the call // Patch versions of rValues in assignments for vars modified in the call
LabelRef successor = getOrigBlock().getDefaultSuccessor(); LabelRef successor = block.getDefaultSuccessor();
ControlFlowBlock successorBlock = program.getGraph().getBlock(successor); ControlFlowBlock successorBlock = program.getGraph().getBlock(successor);
Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef()); Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef());
for(Statement statement : successorBlock.getStatements()) { for(Statement statement : successorBlock.getStatements()) {
@ -79,7 +100,7 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
VariableRef unversionedVar = new VariableRef(phiVar.getFullNameUnversioned()); VariableRef unversionedVar = new VariableRef(phiVar.getFullNameUnversioned());
if(modifiedVars.contains(unversionedVar)) { if(modifiedVars.contains(unversionedVar)) {
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
if(phiRValue.getPredecessor().equals(getOrigBlock().getLabel())) { if(phiRValue.getPredecessor().equals(block.getLabel())) {
VariableRef procReturnVersion = findReturnVersion(procedure, unversionedVar); VariableRef procReturnVersion = findReturnVersion(procedure, unversionedVar);
phiRValue.setrValue(procReturnVersion); phiRValue.setrValue(procReturnVersion);
} }
@ -89,7 +110,6 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
} }
} }
return null;
} }
private VariableRef findReturnVersion(Procedure procedure, VariableRef assignedVar) { private VariableRef findReturnVersion(Procedure procedure, VariableRef assignedVar) {
@ -110,17 +130,5 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
throw new RuntimeException("Variable " + assignedVar + "modified by procedure " + procedure + " not found in @return block " + block.getLabel()); throw new RuntimeException("Variable " + assignedVar + "modified by procedure " + procedure + " not found in @return block " + block.getLabel());
} }
@Override
public StatementReturn visitReturn(StatementReturn orig) {
ControlFlowBlock currentBlock = getCurrentBlock();
String currentProcName = currentBlock.getLabel().getScopeNames();
Procedure procedure = program.getScope().getProcedure(currentProcName);
// If not PHI-call - skip
if(!Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention()))
return super.visitReturn(orig);
addStatementToCurrentBlock(new StatementReturn(null, orig.getSource(), orig.getComments()));
return null;
}
} }