package IR2;

import java.util.*;

public class DelocalizedCallInstruction extends DelocalizedInstruction {
  private DelocalizedLabelInstruction target;
  private DelocalizedRValue [] args;
  private DelocalizedLValue result;
  
  public DelocalizedCallInstruction(DelocalizedLabelInstruction target, 
                                    DelocalizedRValue [] args,
                                    DelocalizedLValue result) {
    this.args = args;
    this.target = target;
    this.result = result;
  }

  public Enumeration lsources() {
    return new Enumeration() {
      private int count = 0;
      private DelocalizedRValue [] list = args;
      public boolean hasMoreElements() {
        if (count < list.length) {
          this.go_to_next();
        }
        return (count < list.length);
      }
      public Object nextElement() {
        return list[count++];
      }
      private void go_to_next() {
        if (!(list[count] instanceof DelocalizedLValue)) {
          count++;
          if (count < list.length) {
            this.go_to_next();
          }
        }
      }
    };    
  }

  public DelocalizedLValue destination() {
    return result;
  }

  public void generate_code(Codegen c) {
    c.prep_for_call(args.length);

    // Place each argument in its slot
    for (int i = args.length-1; i >=0; i--)
      c.generate_call_arg(args[i], i);

    // Make the call
    c.generate_call(target);

    // Get the answer
    result.lproxy().store_from_reg(c, c.function_return_register());
  }

  // Substitution. For swapping in a symbolic register
  public void substitute_lvalue(DelocalizedLValue oldlval, 
                                DelocalizedLValue newlval) {
    if (result.lproxy() == oldlval) result = newlval;
  }
  public void substitute_rvalue(DelocalizedLValue oldlval, 
                                DelocalizedLValue newlval) {
    for (int i = 0; i < args.length; i++)
      if (args[i].rproxy() == oldlval) args[i] = (DelocalizedRValue)newlval;
  }

  /* Copy propagation */
  public boolean kills_copy(CopyInstruction copy) {
    return copy.copy_source() instanceof DelocalizedRegister
      || copy.copy_destination() instanceof DelocalizedRegister
      || copy.copy_source() instanceof GlobalScalarVarDescriptor
      || copy.copy_destination() instanceof GlobalScalarVarDescriptor
      || result.equals(copy.copy_source())
      || result.equals(copy.copy_destination());
  }
  public void substitute_copies(Hashtable map) {
    for (int i = 0; i < args.length; i++) {
      if (map.contains(args[i]))
        args[i] = (DelocalizedRValue) map.get(args[i]);
    }
  }
}
