1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-03 07:29:37 +00:00

#815 working on moving control flow graphs into procedure compilation.

This commit is contained in:
jespergravgaard 2023-04-09 23:40:37 +02:00
parent 1fad48f8bc
commit ac96f0b8da
10 changed files with 49 additions and 25 deletions

View File

@ -161,7 +161,7 @@ public class ControlFlowBlock implements Graph.Block {
out.append(" scope:[" + this.scope.getFullName() + "] ");
out.append(" from");
if(graph != null) {
List<Graph.Block> predecessors = graph.getPredecessors(this);
List<Graph.Block> predecessors = program.getGraph().getPredecessors(this);
if(predecessors.size() > 0) {
for(Graph.Block predecessor : predecessors) {
out.append(" " + predecessor.getLabel().getFullName());

View File

@ -68,7 +68,7 @@ public class Program {
private CallGraph callGraph;
/** The procedures being compiled. PASS 1-5 (DYNAMIC)*/
private final LinkedHashMap<ProcedureRef, ProcedureCompilation> procedureCompilations;
private List<ProcedureCompilation> procedureCompilations;
/** Variables modified inside procedures. PASS 1 (STATIC) */
private ProcedureModifiedVars procedureModifiedVars;
@ -113,7 +113,7 @@ public class Program {
this.loadedFiles = new ArrayList<>();
this.asmResourceFiles = new ArrayList<>();
this.reservedZps = new ArrayList<>();
this.procedureCompilations = new LinkedHashMap<>();
this.procedureCompilations = new ArrayList<>();
}
/**
@ -167,8 +167,12 @@ public class Program {
};
}
public Collection<ProcedureCompilation> getProcedureCompilations() {
return procedureCompilations.values();
public List<ProcedureCompilation> getProcedureCompilations() {
return procedureCompilations;
}
public void setProcedureCompilations(List<ProcedureCompilation> procedureCompilations) {
this.procedureCompilations = procedureCompilations;
}
/**
@ -276,15 +280,15 @@ public class Program {
}
public ProcedureCompilation createProcedureCompilation(ProcedureRef procedureRef) {
if(procedureCompilations.get(procedureRef)!=null)
if(getProcedureCompilation(procedureRef)!=null)
throw new CompileError("Error! Procedure already defined "+procedureRef.getFullName());
final ProcedureCompilation procedureCompilation = new ProcedureCompilation(procedureRef);
procedureCompilations.put(procedureRef, procedureCompilation);
procedureCompilations.add(procedureCompilation);
return procedureCompilation;
}
public ProcedureCompilation getProcedureCompilation(ProcedureRef procedureRef) {
return procedureCompilations.get(procedureRef);
return procedureCompilations.stream().filter(pc -> pc.getProcedureRef().equals(procedureRef)).findFirst().orElse(null);
}
public ProgramScope getScope() {
@ -479,9 +483,6 @@ public class Program {
this.registerPotentials = registerPotentials;
}
/**
* Adds a bunch of reserved zero-page addresses that the compiler is not allowed to use.
*
@ -563,7 +564,7 @@ public class Program {
public void removeProcedure(ProcedureRef procedureRef) {
Procedure procedure = getScope().getProcedure(procedureRef);
procedure.getScope().remove(procedure);
procedureCompilations.remove(procedureRef);
procedureCompilations.remove(getProcedureCompilation(procedureRef));
}
/**
@ -580,8 +581,6 @@ public class Program {
/**
* Get all blocks that are program entry points.
* This is the start-block and any blocks referenced by the address-off operator (&)
*
* @param graph@return All entry-point blocks
*/
public List<Graph.Block> getEntryPointBlocks() {
final Graph graph = getGraph();

View File

@ -45,6 +45,11 @@ public class Label implements Symbol {
this.scope = scope;
}
@Override
public Procedure getContainingProcedure() {
return getScope().getContainingProcedure();
}
@Override
public int getScopeDepth() {
if(scope == null) {

View File

@ -38,13 +38,13 @@ public abstract class Scope implements Symbol {
* Get the containing procedure.
* @return The procedure containing the scope. Null if the scope is not contained in a procedure.
*/
public Procedure getProcedure() {
public Procedure getContainingProcedure() {
if(this instanceof Procedure)
return (Procedure) this;
else if(this instanceof ProgramScope)
return null;
else
return this.getScope().getProcedure();
return this.getScope().getContainingProcedure();
}
private void setFullName() {

View File

@ -20,4 +20,6 @@ public interface Symbol extends Value {
int getScopeDepth();
SymbolRef getRef();
Procedure getContainingProcedure();
}

View File

@ -531,6 +531,11 @@ public class Variable implements Symbol {
return false;
}
@Override
public Procedure getContainingProcedure() {
return scope.getContainingProcedure();
}
public boolean isDeclarationOnly() {
return declarationOnly;
}

View File

@ -71,7 +71,7 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
private void removeParameters(Set<ConstantRef> inlineRefs) {
for(ConstantRef inlineRef : inlineRefs) {
final Scope scope = getProgramScope().getConstant(inlineRef).getScope();
final Procedure procedure = scope.getProcedure();
final Procedure procedure = scope.getContainingProcedure();
if(procedure!=null) {
final List<Variable> parameters = procedure.getParameters();
final boolean modified = parameters.removeIf(param -> param.getRef().equals(inlineRef));

View File

@ -57,7 +57,7 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
for(LabelRef unusedBlock : unusedBlocks) {
Symbol unusedSymbol = getProgramScope().getSymbol(unusedBlock);
if(unusedSymbol instanceof Label) {
final Procedure procedure = unusedSymbol.getScope().getProcedure();
final Procedure procedure = unusedSymbol.getScope().getContainingProcedure();
final ProcedureCompilation procedureCompilation = getProgram().getProcedureCompilation(procedure.getRef());
final ControlFlowGraph procedureGraph = procedureCompilation.getGraph();
procedureGraph.remove(unusedBlock);

View File

@ -1,12 +1,11 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.values.LabelRef;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/** Plan the optimal sequence for the blocks of the control flow graph */
public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
@ -82,15 +81,29 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
if(sequence.size() != getGraph().getAllBlocks().size()) {
throw new CompileError("ERROR! Sequence does not contain all blocks from the program. Sequence: " + sequence.size() + " Blocks: " + getGraph().getAllBlocks().size());
}
// First re-order the procedureCompilations
List<ProcedureCompilation> updatedProgramSequence = new ArrayList<>();
for(LabelRef labelRef : sequence) {
final Procedure procedure = getProgramScope().getSymbol(labelRef).getContainingProcedure();
final ProcedureCompilation procedureCompilation = getProgram().getProcedureCompilation(procedure.getRef());
if(!updatedProgramSequence.contains(procedureCompilation)) {
updatedProgramSequence.add(procedureCompilation);
}
}
getProgram().setProcedureCompilations(updatedProgramSequence);
// Now re-order the blocks for each procedure
for(var procedureCompilation : getProgram().getProcedureCompilations()) {
final ControlFlowGraph procedureGraph = procedureCompilation.getGraph();
final List<LabelRef> procedureLabels = procedureGraph.getAllBlocks().stream().map(Graph.Block::getLabel).toList();
final List<Graph.Block> procedureSequence = sequence.stream().filter(procedureLabels::contains).map(procedureGraph::getBlock).toList();
if(procedureSequence.size() != procedureGraph.getAllBlocks().size()) {
throw new CompileError("ERROR! Sequence does not contain all blocks for "+procedureCompilation.getProcedureRef()+". Sequence: " + procedureSequence.size() + " Blocks: " + procedureGraph.getAllBlocks().size());
final List<Graph.Block> updatedProcedureSequence = sequence.stream().filter(procedureLabels::contains).map(procedureGraph::getBlock).toList();
if(updatedProcedureSequence.size() != procedureGraph.getAllBlocks().size()) {
throw new CompileError("ERROR! Sequence does not contain all blocks for "+procedureCompilation.getProcedureRef()+". Sequence: " + updatedProcedureSequence.size() + " Blocks: " + procedureGraph.getAllBlocks().size());
}
procedureCompilation.setGraph(new ControlFlowGraph(procedureSequence));
procedureCompilation.setGraph(new ControlFlowGraph(updatedProcedureSequence));
}
}
void pushTodo(Graph.Block block) {

View File

@ -106,7 +106,7 @@ public class PassNCullEmptyBlocks extends Pass2SsaOptimization {
LabelRef removeBlockLabelRef = removeBlock.getLabel();
Label removeBlockLabel = getProgramScope().getLabel(removeBlockLabelRef);
final Scope removeBlockScope = removeBlockLabel.getScope();
final Procedure procedure = removeBlockScope.getProcedure();
final Procedure procedure = removeBlockScope.getContainingProcedure();
final ProcedureCompilation procedureCompilation = getProgram().getProcedureCompilation(procedure.getRef());
final List<Graph.Block> updatedBlocks = new ArrayList<>(procedureCompilation.getGraph().getAllBlocks());
updatedBlocks.removeIf(block -> block.getLabel().equals(removeBlockLabelRef));