/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt.lir2mir;
import org.jikesrvm.*;
import org.jikesrvm.compilers.opt.depgraph.DepGraphNode;
import org.jikesrvm.compilers.opt.ir.*;
/**
* An AbstractBURS_TreeNode is a node in a binary tree that is fed
* as input to BURS. Machine generated versions are created for
* every architecture and address size.
*
* @see BURS
* @see BURS_StateCoder
*/
public abstract class AbstractBURS_TreeNode {
AbstractBURS_TreeNode child1;
AbstractBURS_TreeNode child2;
/**
* Dependence graph node corresponding to
* interior node in BURS tree (set to null for
* leaf node or for OTHER_OPERAND node).
*/
public final DepGraphNode dg_node;
/**
* Opcode of instruction
*/
private final char opcode;
/**
* nonterminal > 0 ==> this tree node is the
* root of a "supernode"; the value of nonterminal
* identifies the matching non-terminal
* nonterminal = 0 ==> this tree node is NOT the
* root of a "supernode".
*/
private byte nonterminal;
/**
* <pre>
* trrr rrrr
* t = tree root
* r = num of registers used
* </pre>
*/
private byte treeroot_registersused;
public final char getOpcode() {
return opcode;
}
public final AbstractBURS_TreeNode getChild1() {
return child1;
}
public final void setChild1(AbstractBURS_TreeNode x) {
child1 = x;
}
public final AbstractBURS_TreeNode getChild2() {
return child2;
}
public final void setChild2(AbstractBURS_TreeNode x) {
child2 = x;
}
public final int getNonTerminal() {
return nonterminal & 0xFF;
}
public final void setNonTerminal(int nonterminal) {
if (VM.VerifyAssertions) VM._assert(nonterminal <= 0xff);
this.nonterminal = (byte)nonterminal;
}
public final boolean isTreeRoot() {
return (treeroot_registersused & 0x80) != 0;
}
public final void setTreeRoot() {
treeroot_registersused |= 0x80;
}
public final void setNumRegisters(int r) {
treeroot_registersused = (byte)((treeroot_registersused & 0x80) | (r & 0x7f));
}
public final int numRegisters() {
return treeroot_registersused & 0x7f;
}
public final Instruction getInstruction() {
return dg_node._instr;
}
public final String getInstructionString() {
if (dg_node != null) {
return dg_node._instr.toString();
} else {
return "";
}
}
/**
* Constructor for interior node.
* @param n the dep graph node
*/
protected AbstractBURS_TreeNode(DepGraphNode n) {
Instruction instr = n._instr;
dg_node = n;
opcode = instr.getOpcode();
}
/**
* @param n the dep graph node
* @return an interior node
*/
public static AbstractBURS_TreeNode create(DepGraphNode n) {
if (VM.BuildForIA32) {
if (VM.BuildFor32Addr) {
return new org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_TreeNode(n);
} else {
return new org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_TreeNode(n);
}
} else {
if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC);
if (VM.BuildFor32Addr) {
return new org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_TreeNode(n);
} else {
return new org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_TreeNode(n);
}
}
}
/**
* Constructor for leaf/auxiliary node.
* @param Opcode the opcode for the node
*/
protected AbstractBURS_TreeNode(char Opcode) {
dg_node = null;
opcode = Opcode;
}
/**
* @param Opcode the node's opcode
* @return a leaf/auxiliary node.
*/
public static AbstractBURS_TreeNode create(char Opcode) {
if (VM.BuildForIA32) {
if (VM.BuildFor32Addr) {
return new org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_TreeNode(Opcode);
} else {
return new org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_TreeNode(Opcode);
}
} else {
if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC);
if (VM.BuildFor32Addr) {
return new org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_TreeNode(Opcode);
} else {
return new org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_TreeNode(Opcode);
}
}
}
@Override
public String toString() {
return Operator.lookupOpcode(getOpcode()).toString();
}
public final boolean isSuperNodeRoot() {
return (getNonTerminal() > 0);
}
public final boolean isREGISTERNode() {
return getOpcode() == Operators.REGISTER_opcode;
}
/**
* Get the BURS rule number associated with this tree node for a given non-terminal
*
* @param goalNT the non-terminal we want to know the rule for (e.g. stm_NT)
* @return the rule number
*/
public abstract int rule(int goalNT);
public abstract char getCost(int goalNT);
public abstract void setCost(int goalNT, char cost);
public abstract void initCost();
public abstract void writePacked(int word, int mask, int shiftedValue);
public abstract int readPacked(int word, int shift, int mask);
}