package de.fuberlin.optimierung;
import java.util.*;
import de.fuberlin.optimierung.commands.*;;
/**
* Ermöglicht die Zuordnung von Definition und Verwendungen (als ILLVMCommands) zu einem Register
* Identifikation laeuft ueber den Namen des Registers als String
*
* Doppelte Verwendungen, z.B. a = x+x, werden nur einmal in den Verwendungen (usemap)
* abgelegt.
* Loeschbefehle auf nicht vorhandenen Eintraegen machen nichts, stuerzen nicht ab.
*/
public class LLVM_RegisterMap {
// Hashmap, die dem Namen eines Registers den Befehl zuordnet, in dem das Register definiert wird
private HashMap<String,LLVM_GenericCommand> definitionMap = new HashMap<String,LLVM_GenericCommand>();
// Hashmap, die dem Namen eines Registers die Befehle zuordnet, in dem das Register genutzt wird
private HashMap<String,LinkedList<LLVM_GenericCommand>> useMap = new HashMap<String,LinkedList<LLVM_GenericCommand>>();
/**
* Gibt alle Registernamen aus, die laut Definitionsmap definiert sind
* @return Menge der Registernamen
*/
public Set<String> getDefinedRegisterNames() {
return this.definitionMap.keySet();
}
/**
* Loesche alle Eintraege
*/
public void clean() {
this.definitionMap.clear();
this.useMap.clear();
}
/**
* Gibt die Definition des Registers zurueck
* @param registerName Name des Registers
* @return Befehl, das Register definiert, null, falls nicht vorhanden
*/
public LLVM_GenericCommand getDefinition(String registerName) {
return this.definitionMap.get(registerName);
}
/**
* Gibt die Verwendungen des Registers zurueck
* @param registerName Name des Registers
* @return Befehle, die Register nutzen, null, falls nicht vorhanden
*/
public LinkedList<LLVM_GenericCommand> getUses(String registerName) {
return this.useMap.get(registerName);
}
/**
* Fuege Register des gegebenen Befehls in Hashmaps ein
* @param c Einzufuegender Befehl
*/
public void addCommand(LLVM_GenericCommand c) {
// Fuege Definition ein
LLVM_Parameter target = c.getTarget();
if(target!=null && target.getType()==LLVM_ParameterType.REGISTER)
this.definitionMap.put(target.getName(), c);
// Fuege Verwendungen ein
LinkedList<LLVM_Parameter> operands = c.getOperands();
if(operands!=null) { // Gibt es Verwendungen zum Einfuegen?
LinkedList<LLVM_GenericCommand> uses;
for(LLVM_Parameter op : operands) { // Gehe Operanden durch
if(op.getType()==LLVM_ParameterType.REGISTER) { // Ist Operand ein Register?
// Fuege Befehl in useMap ein
uses = this.getUses(op.getName());
if(uses==null) {
uses = new LinkedList<LLVM_GenericCommand>();
}
// Fuege ein, falls der Befehl noch nicht enthalten ist
if(!uses.contains(c)) {
uses.add(c);
}
this.useMap.put(op.getName(), uses);
}
}
}
}
/**
* Loesche Register des gegebenen Befehls aus Hashmap
* @param c Zu loeschender Befehl
*/
public void deleteCommand(LLVM_GenericCommand c) {
// Loesche Definition
LLVM_Parameter target = c.getTarget();
if(target!=null && target.getType()==LLVM_ParameterType.REGISTER) {
this.definitionMap.remove(target.getName());
}
// Loesche Verwendungen
LinkedList<LLVM_Parameter> operands = c.getOperands();
if(operands!=null) { // Gibt es Verwendungen zum Loeschen?
LinkedList<LLVM_GenericCommand> uses;
for(LLVM_Parameter op : operands) { // Gehe Operanden durch
if(op.getType()==LLVM_ParameterType.REGISTER) { // Ist Operand ein Register?
// Loesche Befehel aus useMap
uses = this.getUses(op.getName());
if(!(uses==null)) {
uses.remove(c);
if(uses.isEmpty()) {
this.useMap.remove(op.getName());
}
else {
this.useMap.put(op.getName(), uses);
}
}
}
}
}
}
/**
* Loesche gegebenen Operanden aus gegebenem Befehl
* @param c Befehl, aus dem geloescht werden soll
* @param _target Operand, der geloescht werden soll
*/
public void deleteCommand(LLVM_GenericCommand c, LLVM_Parameter _target) {
// Loesche Definition
/*LLVM_Parameter target = c.getTarget();
if(target!=null && target.getType()==LLVM_ParameterType.REGISTER) {
this.definitionMap.remove(target.getName());
}*/
// Loesche Verwendungen
LinkedList<LLVM_Parameter> operands = c.getOperands();
if(operands!=null) { // Gibt es Verwendungen zum Loeschen?
LinkedList<LLVM_GenericCommand> uses;
for(LLVM_Parameter op : operands){
if(op.getName().equals(_target.getName())){
// Loesche Befehel aus useMap
uses = this.getUses(op.getName());
if(!(uses==null)) {
uses.remove(c);
if(uses.isEmpty()) {
this.useMap.remove(op.getName());
}
else {
this.useMap.put(op.getName(), uses);
}
}
}
}
}
}
/**
* Gibt an, ob zu gegebenem Register eine Definition existiert
* @param registerName Name des Registers
* @return true, falls Definition existiert, sonst false
*/
public boolean existsDefintion(String registerName) {
return (this.getDefinition(registerName)!=null);
}
/**
* Gibt an, ob zu gegebenem Register mindestens eine Verwendung existiert
* @param registerName Name des Registers
* @return true, falls eine Verwendung existiert, sonst false
*/
public boolean existsUses(String registerName) {
LinkedList<LLVM_GenericCommand> uses = this.getUses(registerName);
if(uses==null)
return false;
return !(uses.isEmpty());
}
}