mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-08 14:37:40 +00:00
#815 working on moving control flow graphs into procedure compilation.
This commit is contained in:
parent
1fad48f8bc
commit
ac96f0b8da
@ -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());
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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() {
|
||||
|
@ -20,4 +20,6 @@ public interface Symbol extends Value {
|
||||
int getScopeDepth();
|
||||
|
||||
SymbolRef getRef();
|
||||
|
||||
Procedure getContainingProcedure();
|
||||
}
|
||||
|
@ -531,6 +531,11 @@ public class Variable implements Symbol {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Procedure getContainingProcedure() {
|
||||
return scope.getContainingProcedure();
|
||||
}
|
||||
|
||||
public boolean isDeclarationOnly() {
|
||||
return declarationOnly;
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user