// $Id: DelocalizedInstruction.java,v 1.3 1999/12/10 10:32:48 mpp Exp $

package IR2;

import java.util.*;

// Disclaimer: There is some Ugliness here that needs to go away. 
// This class was once an interface, and made the transition to an
// abstract class late in the game; with this change it is now possible
// to clean some of this stuff up. But not today.

public abstract class DelocalizedInstruction implements Traversable {

  protected boolean linearized;
  protected Vector labels = new Vector();
  protected Vector prev_instructions = new Vector();
  protected Vector next_instructions = new Vector();
  public static boolean debug = false;

  // This is a compatibility hack for now. The routines that call next_instr()
  // happen to know that there is only ever _one_ next or prev instruction
  // within a BasicBlock. However before we get to that point, multiple are
  // possible
  public DelocalizedInstruction next_instr() {
    Enumeration e = next();
    if (e.hasMoreElements()) 
      return (DelocalizedInstruction)e.nextElement(); 
    else return null;
  }
  public DelocalizedInstruction prev_instr() {
    Enumeration e = prev();
    if (e.hasMoreElements()) 
      return (DelocalizedInstruction)e.nextElement(); 
    else return null;
  } 
  public void set_next_instr(DelocalizedInstruction i) {
    next_instructions = new Vector();
    next_instructions.addElement(i);
  }
  public void set_prev_instr(DelocalizedInstruction i) {
    prev_instructions = new Vector();
    prev_instructions.addElement(i);
  }
  // end hackish stuff

  
  public Enumeration next() { return next_instructions.elements(); }
  public Enumeration prev() { return prev_instructions.elements(); }

  public int num_next() { return next_instructions.size(); }
  public int num_prev() { return prev_instructions.size(); }

  public void add_next_instr(DelocalizedInstruction i) {
    next_instructions.addElement(i);
  }
  public void add_prev_instr(DelocalizedInstruction i) {
    prev_instructions.addElement(i);
  }

  public void clear_prev() { prev_instructions = new Vector(); }

  // For relinking instructions after dropping one, this is useful
  public void replace_next(DelocalizedInstruction orig, 
			   DelocalizedInstruction next) {
    next_instructions.setElementAt(next, next_instructions.indexOf(orig));
  }


  public void set_label(String s) { 
    labels = new Vector(); 
    labels.addElement(s);
  }
  public void add_label(String s) { labels.addElement(s); }
  public Enumeration get_labels() { return labels.elements(); }
  public int num_labels() { return labels.size(); }

  /* TO BE IMPLEMENTED BY SUBCLASSES */
  public abstract void generate_code(Codegen c);
  public abstract DelocalizedLValue destination();
  public abstract Enumeration lsources(); // sources that are also Lvalues

  // Substitution. For swapping in a symbolic register. Overridden by
  // subclasses that actually have values
  public void substitute_lvalue(DelocalizedLValue oldlval, 
                                DelocalizedLValue newlval) { }
  public void substitute_rvalue(DelocalizedLValue oldlval, 
                                DelocalizedLValue newlval) { }

  // Traverse me!
  public void traverse(Traversal t) {
    if (debug) {
	System.out.print("   Prev: ");
	for (Enumeration e = prev(); e.hasMoreElements(); )
	    System.out.print(e.nextElement() + " ");
	System.out.println("");
	System.out.print("   Next: ");
	for (Enumeration e = next(); e.hasMoreElements(); )
	    System.out.print(e.nextElement() + " ");
	System.out.println("");
    }
    for (Enumeration e = next(); e.hasMoreElements(); )
      t.traverse((DelocalizedInstruction)e.nextElement());
  }



  /* Routines used for copy propagation --- subclasses may override them. */
  public boolean kills_copy(CopyInstruction copy) { return false; }
  public void substitute_copies(Hashtable map) { }
}

  
