/* * 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.VM; import org.jikesrvm.compilers.opt.ir.BasicBlock; import org.jikesrvm.compilers.opt.ir.IR; import org.jikesrvm.compilers.opt.ir.Instruction; import static org.jikesrvm.compilers.opt.ir.Operators.ADDRESS_CONSTANT_opcode; import static org.jikesrvm.compilers.opt.ir.Operators.BRANCH_TARGET_opcode; import static org.jikesrvm.compilers.opt.ir.Operators.LONG_CONSTANT_opcode; import static org.jikesrvm.compilers.opt.ir.Operators.NULL_opcode; import static org.jikesrvm.compilers.opt.ir.Operators.REGISTER_opcode; /** * A few common utilities used for invoking BURS tree-pattern matching * to do instruction selection. The interesting code is in the * subclasses of this class. */ public abstract class BURS { public static final boolean DEBUG = false; protected final AbstractBURS_TreeNode NullTreeNode = AbstractBURS_TreeNode.create(NULL_opcode); protected final AbstractBURS_TreeNode LongConstant = AbstractBURS_TreeNode.create(LONG_CONSTANT_opcode); protected final AbstractBURS_TreeNode AddressConstant = AbstractBURS_TreeNode.create(ADDRESS_CONSTANT_opcode); protected final AbstractBURS_TreeNode Register = AbstractBURS_TreeNode.create(REGISTER_opcode); protected final AbstractBURS_TreeNode BranchTarget = AbstractBURS_TreeNode.create(BRANCH_TARGET_opcode); BURS(IR ir) { this.ir = ir; NullTreeNode.setNumRegisters(0); LongConstant.setNumRegisters(0); AddressConstant.setNumRegisters(0); Register.setNumRegisters(1); BranchTarget.setNumRegisters(0); } public final IR ir; protected Instruction lastInstr; /** @return the architecture dependent BURS coder */ BURS_StateCoder makeCoder() { if (VM.BuildForIA32) { if (VM.BuildFor32Addr) { return new org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_STATE(this); } else { return new org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_STATE(this); } } else { if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); if (VM.BuildFor32Addr) { return new org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_STATE(this); } else { return new org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_STATE(this); } } } /** * Recursively labels the tree with costs. * @param tn the tree to label */ static void label(AbstractBURS_TreeNode tn) { if (VM.BuildForIA32) { if (VM.BuildFor32Addr) { org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_STATE.label(tn); } else { org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_STATE.label(tn); } } else { if (VM.BuildFor32Addr) { org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_STATE.label(tn); } else { org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_STATE.label(tn); } } } /** * Traverses the tree, marking the non-terminal to be generated for each * sub-tree. * * @param tn the tree to traverse * @param goalnt the goal */ static void mark(AbstractBURS_TreeNode tn, byte goalnt) { if (VM.BuildForIA32) { if (VM.BuildFor32Addr) { org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_STATE.mark(tn, goalnt); } else { org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_STATE.mark(tn, goalnt); } } else { if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); if (VM.BuildFor32Addr) { org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_STATE.mark(tn, goalnt); } else { org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_STATE.mark(tn, goalnt); } } } /** * @param rule the rule's number * @return the action associated with a rule */ static byte action(int rule) { if (VM.BuildForIA32) { if (VM.BuildFor32Addr) { return org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_STATE.action(rule); } else { return org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_STATE.action(rule); } } else { if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); if (VM.BuildFor32Addr) { return org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_STATE.action(rule); } else { return org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_STATE.action(rule); } } } /** * Dumps the tree for debugging. * @param tn the root of the tree to be dumped */ static void dumpTree(AbstractBURS_TreeNode tn) { if (VM.BuildForIA32) { if (VM.BuildFor32Addr) { org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_STATE.dumpTree(tn); } else { org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_STATE.dumpTree(tn); } } else { if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); if (VM.BuildFor32Addr) { org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_STATE.dumpTree(tn); } else { org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_STATE.dumpTree(tn); } } } /** * @param rule the rule's number * @return debug string for a particular rule */ static String debug(int rule) { if (VM.BuildForIA32) { if (VM.BuildFor32Addr) { return org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_Debug.string[rule]; } else { return org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_Debug.string[rule]; } } else { if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); if (VM.BuildFor32Addr) { return org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_Debug.string[rule]; } else { return org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_Debug.string[rule]; } } } /** * Prepares for conversion of a block. This method must be called before * using an invoke method from the subclasses. * * @param bb a basic block */ final void prepareForBlock(BasicBlock bb) { if (DEBUG) { VM.sysWriteln("FINAL LIR"); bb.printExtended(); } lastInstr = bb.firstInstruction(); } /** * Finalizes a block. This method must be called after * using an invoke method for all non-empty blocks. * * @param bb a basic block */ final void finalizeBlock(BasicBlock bb) { lastInstr.BURS_backdoor_linkWithNext(bb.lastInstruction()); lastInstr = null; if (DEBUG) { VM.sysWriteln("INITIAL MIR"); bb.printExtended(); } } /** * Appends an instruction, i.e. emits an MIR instruction. * * @param instruction the instruction to emit */ public final void append(Instruction instruction) { lastInstr.BURS_backdoor_linkWithNext(instruction); lastInstr = instruction; } }