1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-10 10:29:36 +00:00
kickc/src/main/java/dk/camelot64/kickc/model/LiveRangeVariables.java

149 lines
4.6 KiB
Java

package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.passes.calcs.PassNCalcLiveRangeVariables;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Live ranges for all variables.
* Created by {@link PassNCalcLiveRangeVariables}
*/
public class LiveRangeVariables {
private LinkedHashMap<VariableRef, LiveRange> liveRanges;
private Program program;
public LiveRangeVariables(Program program) {
this.liveRanges = new LinkedHashMap<>();
this.program = program;
}
/**
* Add a single statement to the live range of a variable.
*
* @param variable The variable
* @param statementIdx Index of the statement to add
* @return true if a live range was modified by the addition
*/
public boolean addAlive(VariableRef variable, int statementIdx) {
LiveRange liveRange = liveRanges.get(variable);
if(liveRange == null) {
liveRange = new LiveRange();
liveRanges.put(variable, liveRange);
}
return liveRange.add(statementIdx);
}
/**
* Add an empty alive range for a variable
*
* @param variable The variable
*/
public void addEmptyAlive(VariableRef variable) {
LiveRange liveRange = liveRanges.get(variable);
if(liveRange == null) {
liveRange = new LiveRange();
liveRanges.put(variable, liveRange);
}
}
/**
* Get all variables alive at a specific statement
*
* @param statementIdx Index of the statement
* @return List of all live variables.
*/
public List<VariableRef> getAlive(int statementIdx) {
ArrayList<VariableRef> aliveVars = new ArrayList<>();
for(Map.Entry<VariableRef,LiveRange> entry : liveRanges.entrySet()) {
if(entry.getValue().contains(statementIdx)) {
aliveVars.add(entry.getKey());
}
}
return aliveVars;
}
/**
* Get the alive range of a variable
*
* @param variable The variable reference
* @return The alive range for the variable
*/
public LiveRange getLiveRange(VariableRef variable) {
return liveRanges.get(variable);
}
/**
* Get the number of variable live ranges
* @return The number of variable live ranges
*/
public int size() {
return liveRanges.size();
}
/**
* Get the maximum index of all live ranges
* @return The maximum index of all live ranges
*/
public int getMaxIndex() {
int maxIndex = 0;
for(LiveRange liveRange: liveRanges.values()) {
int liveRangeMaxIndex = liveRange.getMaxIndex();
if(maxIndex < liveRangeMaxIndex)
maxIndex = liveRangeMaxIndex;
}
return maxIndex;
}
/**
* Get variable live ranges by statement index. Usable for quick access if you plan to iterate many statements.
* @return variable live ranges by statement index
*/
public LiveRangeVariablesByStatement getLiveRangeVariablesByStatement() {
LiveRangeVariablesByStatement liveRangeVariablesByStatement = new LiveRangeVariablesByStatement();
for(Map.Entry<VariableRef, LiveRange> variableRefLiveRangeEntry : liveRanges.entrySet()) {
VariableRef variableRef = variableRefLiveRangeEntry.getKey();
LiveRange liveRange = variableRefLiveRangeEntry.getValue();
for(LiveRange.LiveInterval liveInterval : liveRange.getIntervals()) {
for(int stmtIdx = liveInterval.getFirstStatementIdx(); stmtIdx<= liveInterval.getLastStatementIdx(); stmtIdx++) {
liveRangeVariablesByStatement.addAlive(stmtIdx, variableRef);
}
}
}
return liveRangeVariablesByStatement;
}
/** Variable live ranges by statement index. Usable for quick access if you plan to iterate many statements. */
public static class LiveRangeVariablesByStatement {
private ArrayList<List<VariableRef>> aliveByStatementIdx;
public LiveRangeVariablesByStatement() {
this.aliveByStatementIdx = new ArrayList<>();
}
public void addAlive(int statementIdx, VariableRef variableRef) {
while(statementIdx>=aliveByStatementIdx.size()) {
aliveByStatementIdx.add(new ArrayList<>());
}
List<VariableRef> variableRefs = aliveByStatementIdx.get(statementIdx);
variableRefs.add(variableRef);
}
public List<VariableRef> getAlive(int statementIdx) {
if(statementIdx>=aliveByStatementIdx.size())
return new ArrayList<>();
return aliveByStatementIdx.get(statementIdx);
}
}
}