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