001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.compilers.opt.dfsolver;
014
015import java.util.Enumeration;
016
017import org.jikesrvm.compilers.opt.util.GraphNode;
018
019/**
020 * Represents a single Data Flow equation.
021 */
022public class DF_Equation implements GraphNode {
023
024  /**
025   * Evaluate this equation, setting a new value for the
026   * left-hand side.
027   *
028   * @return {@code true} if the lhs value changed. {@code false} otherwise
029   */
030  boolean evaluate() {
031    return operator.evaluate(operands);
032  }
033
034  /**
035   * Return the left-hand side of this equation.
036   *
037   * @return the lattice cell this equation computes
038   */
039  DF_LatticeCell getLHS() {
040    return operands[0];
041  }
042
043  /**
044   * Return the operands in this equation.
045   * @return the operands in this equation.
046   */
047  public DF_LatticeCell[] getOperands() {
048    return operands;
049  }
050
051  /**
052   * Return the operator for this equation
053   * @return the operator for this equation
054   */
055  DF_Operator getOperator() {
056    return operator;
057  }
058
059  /**
060   * Does this equation contain an appearance of a given cell?
061   * @param cell the cell in question
062   * @return true or false
063   */
064  public boolean hasCell(DF_LatticeCell cell) {
065    for (DF_LatticeCell operand : operands) {
066      if (operand == cell) {
067        return true;
068      }
069    }
070    return false;
071  }
072
073  /**
074   * Return a string representation of this object
075   * @return a string representation of this object
076   */
077  @Override
078  public String toString() {
079    if (operands[0] == null) {
080      return ("NULL LHS");
081    }
082    StringBuilder result = new StringBuilder(operands[0].toString());
083    result.append(' ');
084    result.append(operator);
085    result.append(' ');
086    for (int i = 1; i < operands.length; i++) {
087      result.append(operands[i]);
088      result.append("  ");
089    }
090    return result.toString();
091  }
092
093  /**
094   * Constructor for case of one operand on the right-hand side.
095   *
096   * @param lhs the lattice cell set by this equation
097   * @param operator the equation operator
098   * @param op1 the first operand on the rhs
099   */
100  DF_Equation(DF_LatticeCell lhs, DF_Operator operator, DF_LatticeCell op1) {
101    this.operator = operator;
102    operands = new DF_LatticeCell[2];
103    operands[0] = lhs;
104    operands[1] = op1;
105  }
106
107  /**
108   * Constructor for case of two operands on the right-hand side.
109   *
110   * @param lhs the lattice cell set by this equation
111   * @param operator the equation operator
112   * @param op1 the first operand on the rhs
113   * @param op2 the second operand on the rhs
114   */
115  DF_Equation(DF_LatticeCell lhs, DF_Operator operator, DF_LatticeCell op1, DF_LatticeCell op2) {
116    this.operator = operator;
117    operands = new DF_LatticeCell[3];
118    operands[0] = lhs;
119    operands[1] = op1;
120    operands[2] = op2;
121  }
122
123  /**
124   * Constructor for case of three operands on the right-hand side.
125   *
126   * @param lhs the lattice cell set by this equation
127   * @param operator the equation operator
128   * @param op1 the first operand on the rhs
129   * @param op2 the second operand on the rhs
130   * @param op3 the third operand on the rhs
131   */
132  DF_Equation(DF_LatticeCell lhs, DF_Operator operator, DF_LatticeCell op1, DF_LatticeCell op2,
133                  DF_LatticeCell op3) {
134    this.operator = operator;
135    operands = new DF_LatticeCell[4];
136    operands[0] = lhs;
137    operands[1] = op1;
138    operands[2] = op2;
139    operands[3] = op3;
140  }
141
142  /**
143   * Constructor for case of more than three operands on the right-hand side.
144   *
145   * @param lhs the lattice cell set by this equation
146   * @param operator the equation operator
147   * @param rhs the operands of the right-hand side in order
148   */
149  DF_Equation(DF_LatticeCell lhs, DF_Operator operator, DF_LatticeCell[] rhs) {
150    this.operator = operator;
151    operands = new DF_LatticeCell[rhs.length + 1];
152    operands[0] = lhs;
153    for (int i = 0; i < rhs.length; i++) {
154      operands[i + 1] = rhs[i];
155    }
156  }
157
158  /**
159   * Get the topological number for this equation
160   * @return the topological number
161   */
162  int getTopologicalNumber() {
163    return topologicalNumber;
164  }
165
166  /**
167   * Get the topological number for this equation
168   * @param n the topological order
169   */
170  void setTopologicalNumber(int n) {
171    topologicalNumber = n;
172  }
173
174  /* Implementation */
175  /**
176   * The operator in the equation
177   */
178  protected final DF_Operator operator;
179  /**
180   * The operands. Operand[0] is the left hand side.
181   */
182  protected final DF_LatticeCell[] operands;
183  /**
184   * The number of this equation when the system is sorted in topological
185   * order.
186   */
187  int topologicalNumber;
188  /**
189   * Field used for GraphNode interface.  TODO: is this needed?
190   */
191  private int index;
192
193  /**
194   * Implementation of GraphNode interface.
195   */
196  @Override
197  public void setIndex(int i) {
198    index = i;
199  }
200
201  @Override
202  public int getIndex() {
203    return index;
204  }
205
206  /**
207   * Return an enumeration of the equations which use the result of this
208   * equation.
209   * @return an enumeration of the equations which use the result of this
210   * equation.
211   */
212  @Override
213  public Enumeration<GraphNode> outNodes() {
214    return new Enumeration<GraphNode>() {
215      private GraphNode elt = getLHS();
216
217      @Override
218      public boolean hasMoreElements() {
219        return elt != null;
220      }
221
222      @Override
223      public GraphNode nextElement() {
224        GraphNode x = elt;
225        elt = null;
226        return x;
227      }
228    };
229  }
230
231  /**
232   * Return an enumeration of the equations upon whose results this
233   * equation depends.
234   * @return an enumeration of the equations upon whose results this
235   * equation depends
236   */
237  @Override
238  public Enumeration<GraphNode> inNodes() {
239    return new Enumeration<GraphNode>() {
240      private int i = 1;
241
242      @Override
243      public boolean hasMoreElements() {
244        return (i < operands.length);
245      }
246
247      @Override
248      public GraphNode nextElement() {
249        return operands[i++];
250      }
251    };
252  }
253
254}