mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-11 04:37:29 +00:00
Optimized block successor closure slightly.
This commit is contained in:
parent
0359c85846
commit
513a71ce64
@ -360,6 +360,7 @@ public class Compiler {
|
||||
optimizations.add(new PassNStatementIndices(program));
|
||||
optimizations.add(() -> {
|
||||
program.clearVariableReferenceInfos();
|
||||
program.clearControlFlowBlockSuccessorClosure();
|
||||
return false;
|
||||
});
|
||||
optimizations.add(new Pass2UnaryNotSimplification(program));
|
||||
@ -372,6 +373,7 @@ public class Compiler {
|
||||
});
|
||||
optimizations.add(() -> {
|
||||
program.clearVariableReferenceInfos();
|
||||
program.clearControlFlowBlockSuccessorClosure();
|
||||
return false;
|
||||
});
|
||||
optimizations.add(() -> {
|
||||
@ -433,6 +435,7 @@ public class Compiler {
|
||||
loopUnrolling.add(new PassNStatementIndices(program));
|
||||
loopUnrolling.add(() -> {
|
||||
program.clearVariableReferenceInfos();
|
||||
program.clearControlFlowBlockSuccessorClosure();
|
||||
return false;
|
||||
});
|
||||
loopUnrolling.add(() -> {
|
||||
@ -481,6 +484,7 @@ public class Compiler {
|
||||
constantOptimizations.add(new PassNStatementIndices(program));
|
||||
constantOptimizations.add(() -> {
|
||||
program.clearVariableReferenceInfos();
|
||||
program.clearControlFlowBlockSuccessorClosure();
|
||||
return false;
|
||||
});
|
||||
constantOptimizations.add(new Pass2NopCastInlining(program));
|
||||
@ -571,6 +575,7 @@ public class Compiler {
|
||||
|
||||
program.clearStatementInfos();
|
||||
program.clearVariableReferenceInfos();
|
||||
program.clearControlFlowBlockSuccessorClosure();
|
||||
pass2AssertSSA();
|
||||
|
||||
// Phi mem coalesce removes as many variables introduced by phi lifting as possible - as long as their live ranges do not overlap
|
||||
@ -585,6 +590,7 @@ public class Compiler {
|
||||
program.clearStatementIndices();
|
||||
program.clearStatementInfos();
|
||||
program.clearVariableReferenceInfos();
|
||||
program.clearControlFlowBlockSuccessorClosure();
|
||||
program.clearLiveRangeVariables();
|
||||
program.clearLiveRangeVariablesEffective();
|
||||
new PassNStatementIndices(program).execute();
|
||||
|
@ -143,6 +143,7 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
* @return The map with all best fragments from the cache file. null if the cache file is not found.
|
||||
*/
|
||||
private Map<String, AsmFragmentTemplate> loadBestFragmentCache(Path cacheFolder, CompileLog log) {
|
||||
final Date before = new Date();
|
||||
if(cacheFolder == null) {
|
||||
return null;
|
||||
}
|
||||
@ -173,8 +174,10 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
}
|
||||
cacheLine = fragmentCacheReader.readLine();
|
||||
}
|
||||
final Date after = new Date();
|
||||
final long millis = after.getTime() - before.getTime();
|
||||
if(log.isVerboseFragmentLog())
|
||||
log.append("Loaded cached fragments " + bestFragmentCache.size() + " from " + cacheFile.getPath());
|
||||
log.append("Loaded cached fragments " + bestFragmentCache.size() + " from " + cacheFile.getPath() + " in " + millis + "ms");
|
||||
return bestFragmentCache;
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException("Error loading fragment cache file " + baseFragmentFolder, e);
|
||||
@ -189,6 +192,7 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
* @param log The compile log
|
||||
*/
|
||||
public void saveBestFragmentCache(CompileLog log) {
|
||||
Date before = new Date();
|
||||
if(this.cacheFolder == null) {
|
||||
return;
|
||||
}
|
||||
@ -202,8 +206,10 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
fragmentFilePrint.println(fragmentTemplate.getBody());
|
||||
}
|
||||
fragmentFilePrint.close();
|
||||
final Date after = new Date();
|
||||
final long millis = after.getTime() - before.getTime();
|
||||
if(log.isVerboseFragmentLog())
|
||||
log.append("Saved cached fragments " + this.bestFragmentCache.size() + " to " + cacheFile.getPath());
|
||||
log.append("Saved cached fragments " + this.bestFragmentCache.size() + " to " + cacheFile.getPath() + " in " + millis + "ms");
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException("Error saving fragment cache file " + cacheFile, e);
|
||||
} catch(StringIndexOutOfBoundsException e) {
|
||||
|
@ -0,0 +1,48 @@
|
||||
package dk.camelot64.kickc.model;
|
||||
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/** The transitive closure of control flow graph blocks */
|
||||
public class ControlFlowBlockSuccessorClosure {
|
||||
|
||||
/** For each block this is the closure of all successor blocks. */
|
||||
private Map<LabelRef, Collection<LabelRef>> blockSuccessorClosure;
|
||||
|
||||
public ControlFlowBlockSuccessorClosure(Map<LabelRef, Collection<LabelRef>> blockSuccessorClosure) {
|
||||
this.blockSuccessorClosure = blockSuccessorClosure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all variables used or defined inside a block and its successors (including any called method)
|
||||
*
|
||||
* @param labelRef The block to examine
|
||||
* @return All used variables
|
||||
*/
|
||||
public Collection<VariableRef> getSuccessorClosureReferencedVars(LabelRef labelRef, VariableReferenceInfos varInfos) {
|
||||
ArrayList<VariableRef> variableRefs = new ArrayList<>();
|
||||
final Collection<LabelRef> successors = blockSuccessorClosure.get(labelRef);
|
||||
successors.forEach(labelRef1 -> variableRefs.addAll(varInfos.getReferencedVars(labelRef1)));
|
||||
return variableRefs;
|
||||
}
|
||||
|
||||
|
||||
public String getSizeInfo() {
|
||||
StringBuilder sizeInfo = new StringBuilder();
|
||||
if(blockSuccessorClosure != null) {
|
||||
sizeInfo.append("SIZE blockSuccessorClosure ").append(blockSuccessorClosure.size()).append(" labels ");
|
||||
int sub = 0;
|
||||
for(Collection<LabelRef> labelRefs : blockSuccessorClosure.values()) {
|
||||
sub += labelRefs.size();
|
||||
}
|
||||
sizeInfo.append(" ").append(sub).append(" labels").append("\n");
|
||||
}
|
||||
return sizeInfo.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -33,15 +33,17 @@ public class LiveRangeVariablesEffectiveCallPaths implements LiveRangeVariablesE
|
||||
/** Variables (normally) alive at each statement by index. */
|
||||
private Map<Integer, Collection<VariableRef>> statementLiveVariables;
|
||||
|
||||
/**
|
||||
* Information about which procedures reference which variables.
|
||||
*/
|
||||
/** Information about which procedures reference which variables. */
|
||||
private VariableReferenceInfos referenceInfo;
|
||||
|
||||
public LiveRangeVariablesEffectiveCallPaths(Program program, Map<ProcedureRef, CallPaths> procedureCallPaths, LiveRangeVariables liveRangeVariables, VariableReferenceInfos referenceInfo) {
|
||||
/** Information about which blocks follow other blocks. */
|
||||
private ControlFlowBlockSuccessorClosure blockSuccessorClosure;
|
||||
|
||||
public LiveRangeVariablesEffectiveCallPaths(Program program, Map<ProcedureRef, CallPaths> procedureCallPaths, LiveRangeVariables liveRangeVariables, VariableReferenceInfos referenceInfo, ControlFlowBlockSuccessorClosure blockSuccessorClosure) {
|
||||
this.program = program;
|
||||
this.procedureCallPaths = procedureCallPaths;
|
||||
this.referenceInfo = referenceInfo;
|
||||
this.blockSuccessorClosure = blockSuccessorClosure;
|
||||
this.statementLiveVariables = new LinkedHashMap<>();
|
||||
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
@ -106,7 +108,7 @@ public class LiveRangeVariablesEffectiveCallPaths implements LiveRangeVariablesE
|
||||
if(scope instanceof Procedure) {
|
||||
Procedure procedure = (Procedure) scope;
|
||||
callPaths = procedureCallPaths.get(procedure.getRef());
|
||||
referencedInProcedure = referenceInfo.getReferencedVars(procedure.getRef().getLabelRef());
|
||||
referencedInProcedure = blockSuccessorClosure.getSuccessorClosureReferencedVars(procedure.getRef().getLabelRef(), referenceInfo);
|
||||
} else {
|
||||
callPaths = new CallPaths(ROOT_PROCEDURE);
|
||||
// Interrupt is called outside procedure scope - create initial call-path.
|
||||
|
@ -79,6 +79,8 @@ public class Program {
|
||||
private CallGraph callGraph;
|
||||
/** Cached information about the variables referenced by blocks/statements. PASS 1-4 (CACHED ON-DEMAND) */
|
||||
private VariableReferenceInfos variableReferenceInfos;
|
||||
/** Cached information about the closure of all block successors. */
|
||||
private ControlFlowBlockSuccessorClosure blockSuccessorClosure;
|
||||
/** Information about dominators of all blocks. PASS 2U-4 (CACHED ON-DEMAND) */
|
||||
private DominatorsGraph dominators;
|
||||
/** Cached information about symbols. Contains a symbol table cache for fast access. PASS 3-4 (CACHED ON-DEMAND) */
|
||||
@ -339,6 +341,16 @@ public class Program {
|
||||
this.variableReferenceInfos = null;
|
||||
}
|
||||
|
||||
public ControlFlowBlockSuccessorClosure getControlFlowBlockSuccessorClosure() {
|
||||
if(blockSuccessorClosure == null)
|
||||
this.blockSuccessorClosure = new PassNCalcBlockSuccessorClosure(this).calculate();
|
||||
return blockSuccessorClosure;
|
||||
}
|
||||
|
||||
public void clearControlFlowBlockSuccessorClosure() {
|
||||
this.blockSuccessorClosure = null;
|
||||
}
|
||||
|
||||
public DominatorsGraph getDominators() {
|
||||
if(dominators == null)
|
||||
this.dominators = new PassNCalcDominators(this).calculate();
|
||||
|
@ -203,7 +203,7 @@ public class Registers {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(zp, bytes, nonRelocatable);
|
||||
return zp;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ public class StatementInfos {
|
||||
/** The control flow graph. */
|
||||
private ControlFlowGraph graph;
|
||||
|
||||
/** Maps statement index to block label. */
|
||||
/** Maps statement index to block. */
|
||||
private Map<Integer, ControlFlowBlock> stmtBlocks;
|
||||
|
||||
/** Maps statement index to statement. */
|
||||
|
@ -20,9 +20,6 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class VariableReferenceInfos {
|
||||
|
||||
/** For each block this is the closure of all successor blocks. */
|
||||
private Map<LabelRef, Collection<LabelRef>> blockSuccessorClosure;
|
||||
|
||||
/** References to variables/constants by block label. */
|
||||
private Map<LabelRef, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> blockVarReferences;
|
||||
|
||||
@ -124,12 +121,10 @@ public class VariableReferenceInfos {
|
||||
}
|
||||
|
||||
public VariableReferenceInfos(
|
||||
Map<LabelRef, Collection<LabelRef>> blockSuccessorClosure,
|
||||
Map<SymbolVariableRef, Collection<ReferenceToSymbolVar>> symbolVarReferences,
|
||||
Map<LabelRef, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> blockVarReferences,
|
||||
Map<Integer, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> statementVarReferences
|
||||
) {
|
||||
this.blockSuccessorClosure = blockSuccessorClosure;
|
||||
this.symbolVarReferences = symbolVarReferences;
|
||||
this.blockVarReferences = blockVarReferences;
|
||||
this.statementVarReferences = statementVarReferences;
|
||||
@ -137,14 +132,6 @@ public class VariableReferenceInfos {
|
||||
|
||||
public String getSizeInfo() {
|
||||
StringBuilder sizeInfo = new StringBuilder();
|
||||
if(blockSuccessorClosure != null) {
|
||||
sizeInfo.append("SIZE blockSuccessorClosure ").append(blockSuccessorClosure.size()).append(" labels ");
|
||||
int sub = 0;
|
||||
for(Collection<LabelRef> labelRefs : blockSuccessorClosure.values()) {
|
||||
sub += labelRefs.size();
|
||||
}
|
||||
sizeInfo.append(" ").append(sub).append(" labels").append("\n");
|
||||
}
|
||||
{
|
||||
sizeInfo.append("SIZE symbolVarReferences ").append(symbolVarReferences.size()).append(" SymbolVariableRefs ");
|
||||
int sub = 0;
|
||||
@ -182,28 +169,6 @@ public class VariableReferenceInfos {
|
||||
return PassNCalcVariableReferenceInfos.getReferencedVars(rValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all variables used or defined inside a block and its successors (including any called method)
|
||||
*
|
||||
* @param labelRef The block to examine
|
||||
* @return All used variables
|
||||
*/
|
||||
public Collection<VariableRef> getReferencedVars(LabelRef labelRef) {
|
||||
ArrayList<VariableRef> variableRefs = new ArrayList<>();
|
||||
blockSuccessorClosure.get(labelRef)
|
||||
.forEach(labelRef1 -> blockVarReferences
|
||||
.get(labelRef1)
|
||||
.stream()
|
||||
.filter(referenceToSymbolVar -> referenceToSymbolVar.getReferenced() instanceof VariableRef)
|
||||
.forEach(referenceToSymbolVar -> {
|
||||
if(!variableRefs.contains(referenceToSymbolVar.getReferenced()))
|
||||
variableRefs.add((VariableRef) referenceToSymbolVar.getReferenced());
|
||||
}
|
||||
)
|
||||
);
|
||||
return variableRefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the variables defined by a statement
|
||||
*
|
||||
@ -213,7 +178,7 @@ public class VariableReferenceInfos {
|
||||
public Collection<VariableRef> getDefinedVars(Statement stmt) {
|
||||
Collection<ReferenceToSymbolVar> referenceToSymbolVars = statementVarReferences.get(stmt.getIndex());
|
||||
// TODO: This may cause problems since it is a sign that the maps are out of date!
|
||||
if(referenceToSymbolVars==null)
|
||||
if(referenceToSymbolVars == null)
|
||||
return new ArrayList<>();
|
||||
return referenceToSymbolVars
|
||||
.stream()
|
||||
@ -255,6 +220,26 @@ public class VariableReferenceInfos {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the variables referenced (used or defined) in a block.
|
||||
*
|
||||
* @param labelRef The label of the block.
|
||||
* @return The referenced variables
|
||||
*/
|
||||
public Collection<VariableRef> getReferencedVars(LabelRef labelRef) {
|
||||
ArrayList<VariableRef> variableRefs = new ArrayList<>();
|
||||
blockVarReferences
|
||||
.get(labelRef)
|
||||
.stream()
|
||||
.filter(referenceToSymbolVar -> referenceToSymbolVar.getReferenced() instanceof VariableRef)
|
||||
.forEach(referenceToSymbolVar -> {
|
||||
if(!variableRefs.contains(referenceToSymbolVar.getReferenced()))
|
||||
variableRefs.add((VariableRef) referenceToSymbolVar.getReferenced());
|
||||
}
|
||||
);
|
||||
return variableRefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a variable is unused
|
||||
*
|
||||
|
@ -32,6 +32,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
|
||||
|
||||
new PassNStatementIndices(getProgram()).execute();
|
||||
getProgram().clearVariableReferenceInfos();
|
||||
getProgram().clearControlFlowBlockSuccessorClosure();
|
||||
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
|
||||
|
||||
ControlFlowBlock beginBlock = getProgram().getGraph().getBlock(new LabelRef(SymbolRef.BEGIN_BLOCK_NAME));
|
||||
@ -44,6 +45,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
|
||||
}
|
||||
assertUsedVars(beginBlock, null, referenceInfos, defined, new LinkedHashSet<>());
|
||||
getProgram().clearVariableReferenceInfos();
|
||||
getProgram().clearControlFlowBlockSuccessorClosure();
|
||||
getProgram().clearStatementIndices();
|
||||
return false;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ public class Pass1CallVoidReturns extends Pass2SsaOptimization {
|
||||
public boolean step() {
|
||||
new PassNStatementIndices(getProgram()).execute();
|
||||
getProgram().clearVariableReferenceInfos();
|
||||
getProgram().clearControlFlowBlockSuccessorClosure();
|
||||
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
|
||||
|
||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
@ -59,6 +60,7 @@ public class Pass1CallVoidReturns extends Pass2SsaOptimization {
|
||||
}
|
||||
getProgram().clearStatementIndices();
|
||||
getProgram().clearVariableReferenceInfos();
|
||||
getProgram().clearControlFlowBlockSuccessorClosure();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ public class Pass2LoopHeadConstantIdentification extends Pass2SsaOptimization {
|
||||
boolean modified = optimizeLoopHead(loopHeadBlock, loop, variableReferenceInfos);
|
||||
if(modified) {
|
||||
getProgram().clearVariableReferenceInfos();
|
||||
getProgram().clearControlFlowBlockSuccessorClosure();
|
||||
getProgram().clearStatementInfos();
|
||||
getProgram().clearLoopSet();
|
||||
getProgram().clearDominators();
|
||||
|
@ -31,6 +31,7 @@ public class PassNEliminateUnusedVars extends Pass2SsaOptimization {
|
||||
public boolean step() {
|
||||
new PassNStatementIndices(getProgram()).execute();
|
||||
getProgram().clearVariableReferenceInfos();
|
||||
getProgram().clearControlFlowBlockSuccessorClosure();
|
||||
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
|
||||
boolean modified = false;
|
||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
@ -138,6 +139,7 @@ public class PassNEliminateUnusedVars extends Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
getProgram().clearVariableReferenceInfos();
|
||||
getProgram().clearControlFlowBlockSuccessorClosure();
|
||||
getProgram().clearStatementIndices();
|
||||
return modified;
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
package dk.camelot64.kickc.passes.calcs;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlockSuccessorClosure;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementCallExecute;
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
import dk.camelot64.kickc.model.values.ProcedureRef;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/** Calculates {@link dk.camelot64.kickc.model.ControlFlowBlockSuccessorClosure}. */
|
||||
public class PassNCalcBlockSuccessorClosure extends PassNCalcBase<ControlFlowBlockSuccessorClosure> {
|
||||
|
||||
public PassNCalcBlockSuccessorClosure(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControlFlowBlockSuccessorClosure calculate() {
|
||||
LinkedHashMap<LabelRef, Collection<LabelRef>> blockSuccessors = new LinkedHashMap<>();
|
||||
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
||||
LabelRef blockLabel = block.getLabel();
|
||||
LinkedHashSet<LabelRef> successorClosure = new LinkedHashSet<>();
|
||||
findSuccessorClosure(block.getLabel(), successorClosure, new ArrayList<>());
|
||||
blockSuccessors.put(blockLabel, successorClosure);
|
||||
}
|
||||
return new ControlFlowBlockSuccessorClosure(blockSuccessors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively get all blocks in the closure of successors & calls for a specific block
|
||||
*
|
||||
* @param labelRef The block to examine
|
||||
* @param successorClosure the set of all blocks that are successors (including called methods).
|
||||
* @param visited The blocks already visited during the search. Used to stop infinite recursion.
|
||||
*/
|
||||
private void findSuccessorClosure(LabelRef labelRef, LinkedHashSet<LabelRef> successorClosure, Collection<LabelRef> visited) {
|
||||
if(labelRef == null || visited.contains(labelRef))
|
||||
return;
|
||||
visited.add(labelRef);
|
||||
ControlFlowBlock block = getProgram().getGraph().getBlock(labelRef);
|
||||
if(block == null)
|
||||
return;
|
||||
successorClosure.add(labelRef);
|
||||
findSuccessorClosure(block.getDefaultSuccessor(), successorClosure, visited);
|
||||
findSuccessorClosure(block.getConditionalSuccessor(), successorClosure, visited);
|
||||
findSuccessorClosure(block.getCallSuccessor(), successorClosure, visited);
|
||||
// Also handle stack-calls
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementCallExecute) {
|
||||
final ProcedureRef calledProcRef = ((StatementCallExecute) statement).getProcedure();
|
||||
findSuccessorClosure(calledProcRef.getLabelRef(), successorClosure, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -42,10 +42,11 @@ public class PassNCalcLiveRangeVariables extends PassNCalcBase<LiveRangeVariable
|
||||
*/
|
||||
public static Map<ProcedureRef, Collection<VariableRef>> calculateProcedureReferencedVars(Program program) {
|
||||
VariableReferenceInfos referenceInfo = program.getVariableReferenceInfos();
|
||||
final ControlFlowBlockSuccessorClosure blockSuccessorClosure = program.getControlFlowBlockSuccessorClosure();
|
||||
Collection<Procedure> allProcedures = program.getScope().getAllProcedures(true);
|
||||
Map<ProcedureRef, Collection<VariableRef>> procReferencedVars = new LinkedHashMap<>();
|
||||
for(Procedure procedure : allProcedures) {
|
||||
Collection<VariableRef> referencedVars = referenceInfo.getReferencedVars(procedure.getRef().getLabelRef());
|
||||
Collection<VariableRef> referencedVars = blockSuccessorClosure.getSuccessorClosureReferencedVars(procedure.getRef().getLabelRef(), referenceInfo);
|
||||
procReferencedVars.put(procedure.getRef(), referencedVars);
|
||||
}
|
||||
return procReferencedVars;
|
||||
|
@ -33,18 +33,20 @@ public class PassNCalcLiveRangesEffectiveCallPaths extends PassNCalcBase<LiveRan
|
||||
*/
|
||||
private LiveRangeVariables liveRangeVariables;
|
||||
|
||||
/**
|
||||
* Information about which procedures reference which variables.
|
||||
*/
|
||||
/** Information about which procedures reference which variables. */
|
||||
private VariableReferenceInfos referenceInfo;
|
||||
|
||||
/** Information about which blocks follow other blocks. */
|
||||
private ControlFlowBlockSuccessorClosure blockSuccessorClosure;
|
||||
|
||||
@Override
|
||||
public LiveRangeVariablesEffectiveCallPaths calculate() {
|
||||
this.liveRangeVariables = getProgram().getLiveRangeVariables();
|
||||
this.referenceInfo = getProgram().getVariableReferenceInfos();
|
||||
this.blockSuccessorClosure = getProgram().getControlFlowBlockSuccessorClosure();
|
||||
this.procedureCallPaths = new LinkedHashMap<>();
|
||||
populateProcedureCallPaths();
|
||||
LiveRangeVariablesEffectiveCallPaths aliveEffective = new LiveRangeVariablesEffectiveCallPaths(getProgram(), procedureCallPaths, liveRangeVariables, referenceInfo);
|
||||
LiveRangeVariablesEffectiveCallPaths aliveEffective = new LiveRangeVariablesEffectiveCallPaths(getProgram(), procedureCallPaths, liveRangeVariables, referenceInfo, blockSuccessorClosure);
|
||||
return aliveEffective;
|
||||
//getLog().append("Calculated effective variable live ranges");
|
||||
}
|
||||
@ -92,7 +94,7 @@ public class PassNCalcLiveRangesEffectiveCallPaths extends PassNCalcBase<LiveRan
|
||||
// Make sure we have populated the call-paths of the calling procedure
|
||||
populateProcedureCallPaths(callerProcedure, visited);
|
||||
// Find variables referenced in caller procedure
|
||||
Collection<VariableRef> referencedInCaller = referenceInfo.getReferencedVars(callerProcedure.getRef().getLabelRef());
|
||||
Collection<VariableRef> referencedInCaller = blockSuccessorClosure.getSuccessorClosureReferencedVars(callerProcedure.getRef().getLabelRef(), referenceInfo);
|
||||
// For each caller path - create a new call-path
|
||||
LiveRangeVariablesEffectiveCallPaths.CallPaths callerPaths = procedureCallPaths.get(callerProcedure.getRef());
|
||||
if(callerPaths!=null)
|
||||
|
@ -22,8 +22,6 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
|
||||
|
||||
@Override
|
||||
public VariableReferenceInfos calculate() {
|
||||
LinkedHashMap<LabelRef, Collection<LabelRef>> blockSuccessors = new LinkedHashMap<>();
|
||||
|
||||
Map<SymbolVariableRef, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> symbolVarReferences = new LinkedHashMap<>();
|
||||
Map<LabelRef, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> blockVarReferences = new LinkedHashMap<>();
|
||||
Map<Integer, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> statementVarReferences = new LinkedHashMap<>();
|
||||
@ -57,12 +55,7 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
|
||||
}
|
||||
}
|
||||
}
|
||||
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
||||
LabelRef blockLabel = block.getLabel();
|
||||
LinkedHashSet<LabelRef> successorClosure = new LinkedHashSet<>();
|
||||
findSuccessorClosure(block.getLabel(), successorClosure, new ArrayList<>());
|
||||
blockSuccessors.put(blockLabel, successorClosure);
|
||||
}
|
||||
|
||||
// Gather symbols in the symbol table referencing other variables/constants
|
||||
Collection<Variable> allVariables = getProgram().getScope().getAllVars(true);
|
||||
for(Variable referencingVar : allVariables) {
|
||||
@ -77,7 +70,7 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
|
||||
}
|
||||
});
|
||||
}
|
||||
return new VariableReferenceInfos(blockSuccessors, symbolVarReferences, blockVarReferences, statementVarReferences);
|
||||
return new VariableReferenceInfos(symbolVarReferences, blockVarReferences, statementVarReferences);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,34 +174,6 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
|
||||
return referenced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively get all blocks in the closure of successors & calls for a specific block
|
||||
*
|
||||
* @param labelRef The block to examine
|
||||
* @param successorClosure the set of all blocks that are successors (including called methods).
|
||||
* @param visited The blocks already visited during the search. Used to stop infinite recursion.
|
||||
*/
|
||||
private void findSuccessorClosure(LabelRef labelRef, LinkedHashSet<LabelRef> successorClosure, Collection<LabelRef> visited) {
|
||||
if(labelRef == null || visited.contains(labelRef))
|
||||
return;
|
||||
visited.add(labelRef);
|
||||
ControlFlowBlock block = getProgram().getGraph().getBlock(labelRef);
|
||||
if(block == null)
|
||||
return;
|
||||
successorClosure.add(labelRef);
|
||||
findSuccessorClosure(block.getDefaultSuccessor(), successorClosure, visited);
|
||||
findSuccessorClosure(block.getConditionalSuccessor(), successorClosure, visited);
|
||||
findSuccessorClosure(block.getCallSuccessor(), successorClosure, visited);
|
||||
// Also handle stack-calls
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementCallExecute) {
|
||||
final ProcedureRef calledProcRef = ((StatementCallExecute) statement).getProcedure();
|
||||
findSuccessorClosure(calledProcRef.getLabelRef(), successorClosure, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the variables defined by a statement
|
||||
*
|
||||
|
@ -140,6 +140,13 @@ public class TestFragments {
|
||||
testFragments("fragments-complex", signaturesComplex);
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testPointers() throws IOException {
|
||||
// List<String> signatures = Arrays.asList("vbuz1=pbuz2_derefidx_vbuc1");
|
||||
// testFragments("fragments-complex", signatures);
|
||||
// }
|
||||
|
||||
|
||||
@Test
|
||||
public void testFragmentsExist() {
|
||||
testFragmentExists("vbuaa=pbuc2_derefidx_vbuxx");
|
||||
|
@ -4308,8 +4308,8 @@ public class TestPrograms {
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
Path asmFragmentBaseFolder = new File("src/main/fragment/").toPath();
|
||||
Path asmFragmentCacheFolder = null;
|
||||
asmFragmentSynthesizer = new AsmFragmentTemplateSynthesizer(asmFragmentBaseFolder, TargetCpu.MOS6502X, asmFragmentCacheFolder, new CompileLog());
|
||||
// Path asmFragmentCacheFolder = new File("src/main/fragment/cache").toPath();
|
||||
asmFragmentSynthesizer = new AsmFragmentTemplateSynthesizer(asmFragmentBaseFolder, TargetCpu.MOS6502X, null, new CompileLog());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
Loading…
x
Reference in New Issue
Block a user