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.VM; 016import org.jikesrvm.compilers.opt.ir.BasicBlock; 017import org.jikesrvm.compilers.opt.ir.IR; 018import org.jikesrvm.compilers.opt.ir.Instruction; 019import static org.jikesrvm.compilers.opt.ir.Operators.ADDRESS_CONSTANT_opcode; 020import static org.jikesrvm.compilers.opt.ir.Operators.BRANCH_TARGET_opcode; 021import static org.jikesrvm.compilers.opt.ir.Operators.LONG_CONSTANT_opcode; 022import static org.jikesrvm.compilers.opt.ir.Operators.NULL_opcode; 023import static org.jikesrvm.compilers.opt.ir.Operators.REGISTER_opcode; 024 025/** 026 * A few common utilities used for invoking BURS tree-pattern matching 027 * to do instruction selection. The interesting code is in the 028 * subclasses of this class. 029 */ 030public abstract class BURS { 031 032 public static final boolean DEBUG = false; 033 034 protected final AbstractBURS_TreeNode NullTreeNode = AbstractBURS_TreeNode.create(NULL_opcode); 035 protected final AbstractBURS_TreeNode LongConstant = AbstractBURS_TreeNode.create(LONG_CONSTANT_opcode); 036 protected final AbstractBURS_TreeNode AddressConstant = AbstractBURS_TreeNode.create(ADDRESS_CONSTANT_opcode); 037 protected final AbstractBURS_TreeNode Register = AbstractBURS_TreeNode.create(REGISTER_opcode); 038 protected final AbstractBURS_TreeNode BranchTarget = AbstractBURS_TreeNode.create(BRANCH_TARGET_opcode); 039 040 BURS(IR ir) { 041 this.ir = ir; 042 NullTreeNode.setNumRegisters(0); 043 LongConstant.setNumRegisters(0); 044 AddressConstant.setNumRegisters(0); 045 Register.setNumRegisters(1); 046 BranchTarget.setNumRegisters(0); 047 } 048 049 public final IR ir; 050 protected Instruction lastInstr; 051 052 /** @return the architecture dependent BURS coder */ 053 BURS_StateCoder makeCoder() { 054 if (VM.BuildForIA32) { 055 if (VM.BuildFor32Addr) { 056 return new org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_STATE(this); 057 } else { 058 return new org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_STATE(this); 059 } 060 } else { 061 if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); 062 if (VM.BuildFor32Addr) { 063 return new org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_STATE(this); 064 } else { 065 return new org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_STATE(this); 066 } 067 } 068 } 069 070 /** 071 * Recursively labels the tree with costs. 072 * @param tn the tree to label 073 */ 074 static void label(AbstractBURS_TreeNode tn) { 075 if (VM.BuildForIA32) { 076 if (VM.BuildFor32Addr) { 077 org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_STATE.label(tn); 078 } else { 079 org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_STATE.label(tn); 080 } 081 } else { 082 if (VM.BuildFor32Addr) { 083 org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_STATE.label(tn); 084 } else { 085 org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_STATE.label(tn); 086 } 087 } 088 } 089 090 /** 091 * Traverses the tree, marking the non-terminal to be generated for each 092 * sub-tree. 093 * 094 * @param tn the tree to traverse 095 * @param goalnt the goal 096 */ 097 static void mark(AbstractBURS_TreeNode tn, byte goalnt) { 098 if (VM.BuildForIA32) { 099 if (VM.BuildFor32Addr) { 100 org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_STATE.mark(tn, goalnt); 101 } else { 102 org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_STATE.mark(tn, goalnt); 103 } 104 } else { 105 if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); 106 if (VM.BuildFor32Addr) { 107 org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_STATE.mark(tn, goalnt); 108 } else { 109 org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_STATE.mark(tn, goalnt); 110 } 111 } 112 } 113 114 /** 115 * @param rule the rule's number 116 * @return the action associated with a rule 117 */ 118 static byte action(int rule) { 119 if (VM.BuildForIA32) { 120 if (VM.BuildFor32Addr) { 121 return org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_STATE.action(rule); 122 } else { 123 return org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_STATE.action(rule); 124 } 125 } else { 126 if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); 127 if (VM.BuildFor32Addr) { 128 return org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_STATE.action(rule); 129 } else { 130 return org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_STATE.action(rule); 131 } 132 } 133 } 134 135 /** 136 * Dumps the tree for debugging. 137 * @param tn the root of the tree to be dumped 138 */ 139 static void dumpTree(AbstractBURS_TreeNode tn) { 140 if (VM.BuildForIA32) { 141 if (VM.BuildFor32Addr) { 142 org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_STATE.dumpTree(tn); 143 } else { 144 org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_STATE.dumpTree(tn); 145 } 146 } else { 147 if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); 148 if (VM.BuildFor32Addr) { 149 org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_STATE.dumpTree(tn); 150 } else { 151 org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_STATE.dumpTree(tn); 152 } 153 } 154 } 155 156 /** 157 * @param rule the rule's number 158 * @return debug string for a particular rule 159 */ 160 static String debug(int rule) { 161 if (VM.BuildForIA32) { 162 if (VM.BuildFor32Addr) { 163 return org.jikesrvm.compilers.opt.lir2mir.ia32_32.BURS_Debug.string[rule]; 164 } else { 165 return org.jikesrvm.compilers.opt.lir2mir.ia32_64.BURS_Debug.string[rule]; 166 } 167 } else { 168 if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC); 169 if (VM.BuildFor32Addr) { 170 return org.jikesrvm.compilers.opt.lir2mir.ppc_32.BURS_Debug.string[rule]; 171 } else { 172 return org.jikesrvm.compilers.opt.lir2mir.ppc_64.BURS_Debug.string[rule]; 173 } 174 } 175 } 176 177 /** 178 * Prepares for conversion of a block. This method must be called before 179 * using an invoke method from the subclasses. 180 * 181 * @param bb a basic block 182 */ 183 final void prepareForBlock(BasicBlock bb) { 184 if (DEBUG) { 185 VM.sysWrite("FINAL LIR\n"); 186 bb.printExtended(); 187 } 188 lastInstr = bb.firstInstruction(); 189 } 190 191 /** 192 * Finalizes a block. This method must be called after 193 * using an invoke method for all non-empty blocks. 194 * 195 * @param bb a basic block 196 */ 197 final void finalizeBlock(BasicBlock bb) { 198 lastInstr.BURS_backdoor_linkWithNext(bb.lastInstruction()); 199 lastInstr = null; 200 if (DEBUG) { 201 VM.sysWrite("INITIAL MIR\n"); 202 bb.printExtended(); 203 } 204 } 205 206 /** 207 * Appends an instruction, i.e. emits an MIR instruction. 208 * 209 * @param instruction the instruction to emit 210 */ 211 public final void append(Instruction instruction) { 212 lastInstr.BURS_backdoor_linkWithNext(instruction); 213 lastInstr = instruction; 214 } 215} 216 217