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.lir2mir;
014
015import org.jikesrvm.*;
016import org.jikesrvm.compilers.opt.depgraph.DepGraphNode;
017import org.jikesrvm.compilers.opt.ir.*;
018
019/**
020 * An AbstractBURS_TreeNode is a node in a binary tree that is fed
021 * as input to BURS. Machine generated versions are created for
022 * every architecture and address size.
023 *
024 * @see BURS
025 * @see BURS_StateCoder
026 */
027public abstract class AbstractBURS_TreeNode {
028
029  AbstractBURS_TreeNode child1;
030  AbstractBURS_TreeNode child2;
031
032  /**
033   * Dependence graph node corresponding to
034   * interior node in BURS tree (set to null for
035   * leaf node or for OTHER_OPERAND node).
036   */
037  public final DepGraphNode dg_node;
038
039  /**
040   * Opcode of instruction
041   */
042  private final char opcode;
043
044  /**
045   * nonterminal > 0 ==> this tree node is the
046   * root of a "supernode"; the value of nonterminal
047   * identifies the matching non-terminal
048   * nonterminal = 0 ==> this tree node is NOT the
049   * root of a "supernode".
050   */
051  private byte nonterminal;
052
053  /**
054   * <pre>
055   * trrr rrrr
056   * t = tree root
057   * r = num of registers used
058   * </pre>
059   */
060  private byte treeroot_registersused;
061
062  public final char getOpcode() {
063    return opcode;
064  }
065
066  public final AbstractBURS_TreeNode getChild1() {
067    return child1;
068  }
069
070  public final void setChild1(AbstractBURS_TreeNode x) {
071    child1 = x;
072  }
073
074  public final AbstractBURS_TreeNode getChild2() {
075    return child2;
076  }
077
078  public final void setChild2(AbstractBURS_TreeNode x) {
079    child2 = x;
080  }
081
082  public final int getNonTerminal() {
083     return nonterminal & 0xFF;
084  }
085
086  public final void setNonTerminal(int nonterminal) {
087     if (VM.VerifyAssertions) VM._assert(nonterminal <= 0xff);
088     this.nonterminal = (byte)nonterminal;
089  }
090
091  public final boolean isTreeRoot() {
092     return (treeroot_registersused & 0x80) != 0;
093  }
094
095  public final void setTreeRoot() {
096     treeroot_registersused |= 0x80;
097  }
098
099  public final void setNumRegisters(int r) {
100    treeroot_registersused = (byte)((treeroot_registersused & 0x80) | (r & 0x7f));
101  }
102  public final int numRegisters() {
103    return treeroot_registersused & 0x7f;
104  }
105
106  public final Instruction getInstruction() {
107     return dg_node._instr;
108  }
109
110  public final String getInstructionString() {
111    if (dg_node != null) {
112      return dg_node._instr.toString();
113    } else {
114      return "";
115    }
116  }
117
118  /**
119   * Constructor for interior node.
120   * @param n the dep graph node
121   */
122  protected AbstractBURS_TreeNode(DepGraphNode n) {
123    Instruction instr = n._instr;
124    dg_node = n;
125    opcode = instr.getOpcode();
126  }
127
128
129  /**
130   * @param n the dep graph node
131   * @return an interior node
132   */
133  public static AbstractBURS_TreeNode create(DepGraphNode n) {
134    if (VM.BuildForIA32) {
135      if (VM.BuildFor32Addr) {
136        return new org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_TreeNode(n);
137      } else {
138        return new org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_TreeNode(n);
139      }
140    } else {
141      if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC);
142      if (VM.BuildFor32Addr) {
143        return new org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_TreeNode(n);
144      } else {
145        return new org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_TreeNode(n);
146      }
147    }
148  }
149
150  /**
151   * Constructor for leaf/auxiliary node.
152   * @param Opcode the opcode for the node
153   */
154  protected AbstractBURS_TreeNode(char Opcode) {
155    dg_node = null;
156    opcode = Opcode;
157  }
158
159  /**
160   * @param Opcode the node's opcode
161   * @return a leaf/auxiliary node.
162   */
163  public static AbstractBURS_TreeNode create(char Opcode) {
164    if (VM.BuildForIA32) {
165      if (VM.BuildFor32Addr) {
166        return new org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_TreeNode(Opcode);
167      } else {
168        return new org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_TreeNode(Opcode);
169      }
170    } else {
171      if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC);
172      if (VM.BuildFor32Addr) {
173        return new org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_TreeNode(Opcode);
174      } else {
175        return new org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_TreeNode(Opcode);
176      }
177    }
178  }
179
180  @Override
181  public String toString() {
182    return Operator.lookupOpcode(getOpcode()).toString();
183  }
184
185  public final boolean isSuperNodeRoot() {
186    return (getNonTerminal() > 0);
187  }
188
189  public final boolean isREGISTERNode() {
190    return getOpcode() == Operators.REGISTER_opcode;
191  }
192
193 /**
194  * Get the BURS rule number associated with this tree node for a given non-terminal
195  *
196  * @param goalNT the non-terminal we want to know the rule for (e.g. stm_NT)
197  * @return the rule number
198  */
199  public abstract int rule(int goalNT);
200
201  public abstract char getCost(int goalNT);
202
203  public abstract void setCost(int goalNT, char cost);
204
205  public abstract void initCost();
206
207  public abstract void writePacked(int word, int mask, int shiftedValue);
208
209  public abstract int readPacked(int word, int shift, int mask);
210}