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

Now handling uncalled procedures.

This commit is contained in:
jespergravgaard 2023-04-09 11:24:22 +02:00
parent 416184894f
commit 5905c1d5b6
6 changed files with 46 additions and 37 deletions

View File

@ -1,10 +1,8 @@
package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCalling;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.model.values.ScopeRef;
import java.util.*;
@ -92,26 +90,6 @@ public interface Graph {
}
}
/**
* Get all called procedures in the graph
*
* @return All called procedures
*/
default Set<ProcedureRef> getAllCalledProcedures() {
Set<ProcedureRef> calledProcedures = new LinkedHashSet<>();
for(Graph.Block block : getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCalling) {
StatementCalling call = (StatementCalling) statement;
ProcedureRef procedureRef = call.getProcedure();
calledProcedures.add(procedureRef);
}
}
}
return calledProcedures;
}
default String toString(Program program) {
StringBuffer out = new StringBuffer();
for(Graph.Block block : getAllBlocks()) {

View File

@ -550,6 +550,18 @@ public class Program {
}
}
/**
* Delete an entire procedure.
* Removes the entire control flow graph and all symbols.
* Does not check that the removal results in a legal program.
* @param procedureRef The procedure to remove.
*/
public void removeProcedure(ProcedureRef procedureRef) {
Procedure procedure = getScope().getProcedure(procedureRef);
procedure.getScope().remove(procedure);
procedureCompilations.remove(procedureRef);
}
/**
* Is the block the entry of a procedure, ie. the first block of the code of the procedure.
*
@ -580,4 +592,5 @@ public class Program {
}
return entryPointBlocks;
}
}

View File

@ -1,15 +1,15 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCalling;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.passes.utils.ProcedureUtils;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/** Eliminate uncalled methods */
@ -19,10 +19,10 @@ public class Pass1EliminateUncalledProcedures extends Pass1Base {
super(program);
}
@Override
public boolean step() {
Set<ProcedureRef> calledProcedures = getGraph().getAllCalledProcedures();
//calledProcedures.add(getProgram().getStartProcedure());
Set<ProcedureRef> calledProcedures = getAllCalledProcedures(getGraph());
Set<ProcedureRef> unusedProcedures = new LinkedHashSet<>();
Collection<Procedure> allProcedures = getProgram().getScope().getAllProcedures(true);
@ -39,6 +39,25 @@ public class Pass1EliminateUncalledProcedures extends Pass1Base {
return unusedProcedures.size() > 0;
}
/**
* Get all called procedures in a control flow graph
*
* @return All called procedures
*/
public static Set<ProcedureRef> getAllCalledProcedures(Graph graph) {
Set<ProcedureRef> calledProcedures = new LinkedHashSet<>();
for(Graph.Block block : graph.getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCalling) {
StatementCalling call = (StatementCalling) statement;
ProcedureRef procedureRef = call.getProcedure();
calledProcedures.add(procedureRef);
}
}
}
return calledProcedures;
}
/**
* Removed a procedure from the program (the symbol in the symbol table and all blocks in the control flow graph)
*
@ -49,12 +68,7 @@ public class Pass1EliminateUncalledProcedures extends Pass1Base {
if(program.getLog().isVerbosePass1CreateSsa()) {
program.getLog().append("Removing unused procedure " + procedureRef);
}
Procedure procedure = program.getScope().getProcedure(procedureRef);
List<Graph.Block> procedureBlocks = program.getGraph().getScopeBlocks(procedureRef);
for(var procedureBlock : procedureBlocks) {
program.getGraph().remove(procedureBlock.getLabel());
}
procedure.getScope().remove(procedure);
program.removeProcedure(procedureRef);
}
}

View File

@ -16,6 +16,7 @@ import dk.camelot64.kickc.model.values.SymbolRef;
import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.passes.utils.AliasReplacer;
import dk.camelot64.kickc.passes.utils.StatementsBetween;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;

View File

@ -10,13 +10,15 @@ public class ProcedureUtils {
/**
* Determines if a procedure is an entry point.
* Entry points are:
* - the starting procedure (typically main())
* - interrupts
* - any procedure where address-of is used in the code.
* <ul>
* <li> the starting procedure (typically main())
* <li> interrupts
* <li> any procedure where address-of is used in the code.
* </ul>
* TODO: Should all stack call procedures be included (probably no!)
* TODO: Also look at kickasm/asm uses! (Maybe also look at some directive like "__export" )
*
* @param procedure The procedure to examine
* @param procedureRef The procedure to examine
* @param program The program
* @return true if the procedure is an entry point
*/

View File

@ -1,5 +1,6 @@
package dk.camelot64.kickc.model;
package dk.camelot64.kickc.passes.utils;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.ProcedureRef;