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.ir; 014 015import static org.jikesrvm.compilers.opt.ir.Operators.PHI; 016 017import java.util.Enumeration; 018import java.util.Iterator; 019 020import org.jikesrvm.classloader.TypeReference; 021import org.jikesrvm.compilers.opt.ir.operand.HeapOperand; 022import org.jikesrvm.compilers.opt.ir.operand.Operand; 023import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 024import org.vmmagic.pragma.NoInline; 025 026/** 027 * This class is not meant to be instantiated.<p> 028 * It simply serves as a place to collect the implementation of 029 * primitive IR enumerations.<p> 030 * None of these functions are meant to be called directly from 031 * anywhere except IR, Instruction, and BasicBlock.<p> 032 * General clients should use the higher level interfaces provided 033 * by those classes. 034 */ 035public abstract class IREnumeration { 036 037 /** 038 * Forward intra basic block instruction enumerations from 039 * from start...last inclusive.<p> 040 * 041 * NB: start and last _must_ be in the same basic block 042 * and must be in the proper relative order. 043 * This code does _not_ check this invariant, and will 044 * simply fail by eventually thowing a NoSuchElementException 045 * if it is not met. Caller's must be sure the invariants are met. 046 * 047 * @param start the instruction to start with 048 * @param end the instruction to end with 049 * @return an enumeration of the instructions from start to end 050 */ 051 public static Enumeration<Instruction> forwardIntraBlockIE(final Instruction start, final Instruction end) { 052 return new Enumeration<Instruction>() { 053 private Instruction current = start; 054 private final Instruction last = end; 055 056 @Override 057 public boolean hasMoreElements() { 058 return current != null; 059 } 060 061 @Override 062 public Instruction nextElement() { 063 Instruction res = current; 064 if (current == last) { 065 current = null; 066 } else { 067 try { 068 current = current.getNext(); 069 } catch (NullPointerException e) { 070 fail("forwardIntraBlockIE"); 071 } 072 } 073 return res; 074 } 075 }; 076 } 077 078 /** 079 * Reverse intra basic block instruction enumerations from 080 * from start...last inclusive.<p> 081 * 082 * NB: start and last _must_ be in the same basic block 083 * and must be in the proper relative order. 084 * This code does _not_ check this invariant, and will 085 * simply fail by eventually thowing a NoSuchElementException 086 * if it is not met. Caller's must be sure the invariants are met. 087 * 088 * @param start the instruction to start with 089 * @param end the instruction to end with 090 * @return an enumeration of the instructions from start to end 091 */ 092 public static Enumeration<Instruction> reverseIntraBlockIE(final Instruction start, final Instruction end) { 093 return new Enumeration<Instruction>() { 094 private Instruction current = start; 095 private final Instruction last = end; 096 097 @Override 098 public boolean hasMoreElements() { 099 return current != null; 100 } 101 102 @Override 103 public Instruction nextElement() { 104 Instruction res = current; 105 if (current == last) { 106 current = null; 107 } else { 108 try { 109 current = current.getPrev(); 110 } catch (NullPointerException e) { 111 fail("reverseIntraBlockIE"); 112 } 113 } 114 return res; 115 } 116 }; 117 } 118 119 /** 120 * A forward enumeration of all the instructions in the IR. 121 * 122 * @param ir the IR to walk over 123 * @return a forward enumeration of the insturctions in ir 124 */ 125 public static Enumeration<Instruction> forwardGlobalIE(final IR ir) { 126 return new Enumeration<Instruction>() { 127 private Instruction current = ir.firstInstructionInCodeOrder(); 128 129 @Override 130 public boolean hasMoreElements() { 131 return current != null; 132 } 133 134 @Override 135 public Instruction nextElement() { 136 try { 137 Instruction res = current; 138 current = current.nextInstructionInCodeOrder(); 139 return res; 140 } catch (NullPointerException e) { 141 fail("forwardGlobalIR"); 142 return null; 143 } 144 } 145 }; 146 } 147 148 /** 149 * A reverse enumeration of all the instructions in the IR. 150 * 151 * @param ir the IR to walk over 152 * @return a forward enumeration of the insturctions in ir 153 */ 154 public static Enumeration<Instruction> reverseGlobalIE(final IR ir) { 155 return new Enumeration<Instruction>() { 156 private Instruction current = ir.lastInstructionInCodeOrder(); 157 158 @Override 159 public boolean hasMoreElements() { 160 return current != null; 161 } 162 163 @Override 164 public Instruction nextElement() { 165 try { 166 Instruction res = current; 167 current = current.prevInstructionInCodeOrder(); 168 return res; 169 } catch (NullPointerException e) { 170 fail("forwardGlobalIR"); 171 return null; 172 } 173 } 174 }; 175 } 176 177 /** 178 * A forward enumeration of all the basic blocks in the IR. 179 * 180 * @param ir the IR to walk over 181 * @return a forward enumeration of the basic blocks in ir 182 */ 183 public static Enumeration<BasicBlock> forwardBE(final IR ir) { 184 return new Enumeration<BasicBlock>() { 185 private BasicBlock current = ir.firstBasicBlockInCodeOrder(); 186 187 @Override 188 public boolean hasMoreElements() { 189 return current != null; 190 } 191 192 @Override 193 public BasicBlock nextElement() { 194 try { 195 BasicBlock res = current; 196 current = current.nextBasicBlockInCodeOrder(); 197 return res; 198 } catch (NullPointerException e) { 199 fail("forwardBE"); 200 return null; 201 } 202 } 203 }; 204 } 205 206 /** 207 * A reverse enumeration of all the basic blocks in the IR. 208 * 209 * @param ir the IR to walk over 210 * @return a reverse enumeration of the basic blocks in ir 211 */ 212 public static Enumeration<BasicBlock> reverseBE(final IR ir) { 213 return new Enumeration<BasicBlock>() { 214 private BasicBlock current = ir.lastBasicBlockInCodeOrder(); 215 216 @Override 217 public boolean hasMoreElements() { 218 return current != null; 219 } 220 221 @Override 222 public BasicBlock nextElement() { 223 try { 224 BasicBlock res = current; 225 current = current.prevBasicBlockInCodeOrder(); 226 return res; 227 } catch (NullPointerException e) { 228 fail("forwardBE"); 229 return null; 230 } 231 } 232 }; 233 } 234 235 /** 236 * This class implements an enumeration of instructions over 237 * all instructions for a basic block. This enumeration includes 238 * explicit instructions in the IR and implicit phi instructions for 239 * heap variables, which are stored only in this lookaside 240 * structure. 241 * @see org.jikesrvm.compilers.opt.ssa.SSADictionary 242 */ 243 public static final class AllInstructionsEnum implements Enumeration<Instruction> { 244 /** 245 * An enumeration of the explicit instructions in the IR for a 246 * basic block 247 */ 248 private final Enumeration<Instruction> explicitInstructions; 249 250 /** 251 * An enumeration of the implicit instructions in the IR for a 252 * basic block. These instructions appear only in the SSA 253 * dictionary lookaside structure. 254 */ 255 private final Iterator<Instruction> implicitInstructions; 256 257 /** 258 * The label instruction for the basic block - the label is 259 * special as we want it to appear in the enumeration before the 260 * implicit SSA instructions 261 */ 262 private Instruction labelInstruction; 263 264 /** 265 * Construct an enumeration for all instructions, both implicit and 266 * explicit in the IR, for a given basic block 267 * 268 * @param ir the containing IR 269 * @param block the basic block whose instructions this enumerates 270 */ 271 public AllInstructionsEnum(IR ir, BasicBlock block) { 272 explicitInstructions = block.forwardInstrEnumerator(); 273 if (ir.inSSAForm()) { 274 implicitInstructions = ir.HIRInfo.dictionary.getHeapPhiInstructions(block); 275 } else { 276 implicitInstructions = null; 277 } 278 labelInstruction = explicitInstructions.nextElement(); 279 } 280 281 /** 282 * Are there more elements in the enumeration? 283 * 284 * @return {@code true} or {@code false} 285 */ 286 @Override 287 public boolean hasMoreElements() { 288 return (((implicitInstructions != null) && implicitInstructions.hasNext()) || 289 explicitInstructions.hasMoreElements()); 290 } 291 292 @Override 293 public Instruction nextElement() { 294 if (labelInstruction != null) { 295 Instruction temp = labelInstruction; 296 labelInstruction = null; 297 return temp; 298 } else if ((implicitInstructions != null) && implicitInstructions.hasNext()) { 299 return implicitInstructions.next(); 300 } else { 301 return explicitInstructions.nextElement(); 302 } 303 } 304 } 305 306 /** 307 * This class implements an {@link Enumeration} of {@link Operand}s. It used 308 * for holding the definitions of a particular instruction and being 309 * used as an enumeration for iterating over. It differs from other 310 * enumerations of Operand as it iterates over both implicit 311 * and explicit operands. 312 * @see org.jikesrvm.compilers.opt.ssa.SSADictionary 313 */ 314 public static final class AllDefsEnum implements Enumeration<Operand> { 315 /** 316 * Enumeration of non-heap operands defined by the instruction 317 */ 318 private final Enumeration<Operand> instructionOperands; 319 /** 320 * Array of heap operands defined by the instruction 321 */ 322 private final HeapOperand<?>[] heapOperands; 323 /** 324 * Current heap operand we're upto for the enumeration 325 */ 326 private int curHeapOperand; 327 /** 328 * Implicit definitions from the operator 329 */ 330 private final Enumeration<Register> implicitDefs; 331 /** 332 * Defining instruction 333 */ 334 private final Instruction instr; 335 336 /** 337 * Construct/initialize object 338 * 339 * @param ir Containing IR 340 * @param instr Instruction to get definitions for 341 */ 342 public AllDefsEnum(IR ir, Instruction instr) { 343 this.instr = instr; 344 instructionOperands = instr.getDefs(); 345 if (instr.operator().getNumberOfImplicitDefs() > 0) { 346 implicitDefs = GenericPhysicalDefUse.enumerate(instr.operator().implicitDefs, ir); 347 } else { 348 implicitDefs = null; 349 } 350 if (ir.inSSAForm() && (instr.operator() != PHI)) { 351 // Phi instructions store the heap SSA in the actual 352 // instruction 353 heapOperands = ir.HIRInfo.dictionary.getHeapDefs(instr); 354 } else { 355 heapOperands = null; 356 } 357 } 358 359 /** 360 * Are there any more elements in the enumeration 361 */ 362 @Override 363 public boolean hasMoreElements() { 364 return ((instructionOperands.hasMoreElements()) || 365 ((heapOperands != null) && (curHeapOperand < heapOperands.length)) || 366 ((implicitDefs != null) && (implicitDefs.hasMoreElements()))); 367 } 368 369 @Override 370 public Operand nextElement() { 371 if (instructionOperands.hasMoreElements()) { 372 return instructionOperands.nextElement(); 373 } else { 374 if ((implicitDefs != null) && implicitDefs.hasMoreElements()) { 375 RegisterOperand rop = new RegisterOperand(implicitDefs.nextElement(), TypeReference.Int); 376 rop.instruction = instr; 377 return rop; 378 } else { 379 if (curHeapOperand >= heapOperands.length) { 380 fail("Regular and heap operands exhausted"); 381 } 382 HeapOperand<?> result = heapOperands[curHeapOperand]; 383 curHeapOperand++; 384 return result; 385 } 386 } 387 } 388 } 389 390 /** 391 * This class implements an {@link Enumeration} of {@link Operand}. It used 392 * for holding the uses of a particular instruction and being used 393 * as an enumeration for iterating over. It differs from other 394 * enumerations of Operand as it iterates over both implicit 395 * and explicit operands. 396 * @see org.jikesrvm.compilers.opt.ssa.SSADictionary 397 */ 398 public static final class AllUsesEnum implements Enumeration<Operand> { 399 /** 400 * Enumeration of non-heap operands defined by the instruction 401 */ 402 private final Enumeration<Operand> instructionOperands; 403 /** 404 * Array of heap operands defined by the instruction 405 */ 406 private final HeapOperand<?>[] heapOperands; 407 /** 408 * Current heap operand we're upto for the enumeration 409 */ 410 private int curHeapOperand; 411 /** 412 * Implicit uses from the operator 413 */ 414 private final Enumeration<Register> implicitUses; 415 /** 416 * Defining instruction 417 */ 418 private final Instruction instr; 419 420 /** 421 * Construct/initialize object 422 * 423 * @param ir Containing IR 424 * @param instr Instruction to get uses for 425 */ 426 public AllUsesEnum(IR ir, Instruction instr) { 427 this.instr = instr; 428 instructionOperands = instr.getUses(); 429 if (instr.operator().getNumberOfImplicitUses() > 0) { 430 implicitUses = GenericPhysicalDefUse.enumerate(instr.operator().implicitUses, ir); 431 } else { 432 implicitUses = null; 433 } 434 if (ir.inSSAForm() && (instr.operator() != PHI)) { 435 // Phi instructions store the heap SSA in the actual 436 // instruction 437 heapOperands = ir.HIRInfo.dictionary.getHeapUses(instr); 438 } else { 439 heapOperands = null; 440 } 441 } 442 443 /** 444 * Are there any more elements in the enumeration 445 */ 446 @Override 447 public boolean hasMoreElements() { 448 return ((instructionOperands.hasMoreElements()) || 449 ((heapOperands != null) && (curHeapOperand < heapOperands.length)) || 450 ((implicitUses != null) && (implicitUses.hasMoreElements()))); 451 } 452 453 @Override 454 public Operand nextElement() { 455 if (instructionOperands.hasMoreElements()) { 456 return instructionOperands.nextElement(); 457 } else { 458 if ((implicitUses != null) && implicitUses.hasMoreElements()) { 459 RegisterOperand rop = new RegisterOperand(implicitUses.nextElement(), TypeReference.Int); 460 rop.instruction = instr; 461 return rop; 462 } else { 463 if (curHeapOperand >= heapOperands.length) { 464 fail("Regular and heap operands exhausted"); 465 } 466 HeapOperand<?> result = heapOperands[curHeapOperand]; 467 curHeapOperand++; 468 return result; 469 } 470 } 471 } 472 } 473 474 @NoInline 475 private static void fail(String msg) throws java.util.NoSuchElementException { 476 throw new java.util.NoSuchElementException(msg); 477 } 478}