1 /* 2 * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.lir; 24 25 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; 26 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST; 27 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; 28 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; 29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.OUTGOING; 30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; 31 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; 32 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.UNINITIALIZED; 33 import static org.graalvm.compiler.lir.LIRInstruction.OperandMode.ALIVE; 34 import static org.graalvm.compiler.lir.LIRInstruction.OperandMode.DEF; 35 import static org.graalvm.compiler.lir.LIRInstruction.OperandMode.TEMP; 36 import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot; 37 import static jdk.vm.ci.code.ValueUtil.isStackSlot; 38 39 import java.lang.annotation.ElementType; 40 import java.lang.annotation.Retention; 41 import java.lang.annotation.RetentionPolicy; 42 import java.lang.annotation.Target; 43 import java.util.Arrays; 44 import java.util.EnumMap; 45 import java.util.EnumSet; 46 47 import org.graalvm.compiler.debug.Debug; 48 import org.graalvm.compiler.debug.DebugCounter; 49 import org.graalvm.compiler.graph.NodeSourcePosition; 50 import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; 51 import org.graalvm.compiler.lir.StandardOp.MoveOp; 52 import org.graalvm.compiler.lir.StandardOp.ValueMoveOp; 53 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 54 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 55 56 import jdk.vm.ci.code.RegisterValue; 57 import jdk.vm.ci.code.StackSlot; 58 import jdk.vm.ci.meta.JavaConstant; 59 import jdk.vm.ci.meta.Value; 60 61 /** 62 * The base class for an {@code LIRInstruction}. 63 */ 64 public abstract class LIRInstruction { 65 /** 66 * Constants denoting how a LIR instruction uses an operand. 67 */ 68 public enum OperandMode { 69 /** 70 * The value must have been defined before. It is alive before the instruction until the 71 * beginning of the instruction, but not necessarily throughout the instruction. A register 72 * assigned to it can also be assigned to a {@link #TEMP} or {@link #DEF} operand. The value 73 * can be used again after the instruction, so the instruction must not modify the register. 74 */ 75 USE, 76 77 /** 78 * The value must have been defined before. It is alive before the instruction and 79 * throughout the instruction. A register assigned to it cannot be assigned to a 80 * {@link #TEMP} or {@link #DEF} operand. The value can be used again after the instruction, 81 * so the instruction must not modify the register. 82 */ 83 ALIVE, 84 85 /** 86 * The value must not have been defined before, and must not be used after the instruction. 87 * The instruction can do whatever it wants with the register assigned to it (or not use it 88 * at all). 89 */ 90 TEMP, 91 92 /** 93 * The value must not have been defined before. The instruction has to assign a value to the 94 * register. The value can (and most likely will) be used after the instruction. 95 */ 96 DEF, 97 } 98 99 @Retention(RetentionPolicy.RUNTIME) 100 @Target(ElementType.FIELD) 101 public static @interface Use { 102 103 OperandFlag[] value() default OperandFlag.REG; 104 } 105 106 @Retention(RetentionPolicy.RUNTIME) 107 @Target(ElementType.FIELD) 108 public static @interface Alive { 109 110 OperandFlag[] value() default OperandFlag.REG; 111 } 112 113 @Retention(RetentionPolicy.RUNTIME) 114 @Target(ElementType.FIELD) 115 public static @interface Temp { 116 117 OperandFlag[] value() default OperandFlag.REG; 118 } 119 120 @Retention(RetentionPolicy.RUNTIME) 121 @Target(ElementType.FIELD) 122 public static @interface Def { 123 124 OperandFlag[] value() default OperandFlag.REG; 125 } 126 127 @Retention(RetentionPolicy.RUNTIME) 128 @Target(ElementType.FIELD) 129 public static @interface State { 130 } 131 132 /** 133 * Flags for an operand. 134 */ 135 public enum OperandFlag { 136 /** 137 * The value can be a {@link RegisterValue}. 138 */ 139 REG, 140 141 /** 142 * The value can be a {@link StackSlot}. 143 */ 144 STACK, 145 146 /** 147 * The value can be a {@link CompositeValue}. 148 */ 149 COMPOSITE, 150 151 /** 152 * The value can be a {@link JavaConstant}. 153 */ 154 CONST, 155 156 /** 157 * The value can be {@link Value#ILLEGAL}. 158 */ 159 ILLEGAL, 160 161 /** 162 * The register allocator should try to assign a certain register to improve code quality. 163 * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints. 164 */ 165 HINT, 166 167 /** 168 * The value can be uninitialized, e.g., a stack slot that has not written to before. This 169 * is only used to avoid false positives in verification code. 170 */ 171 UNINITIALIZED, 172 173 /** Outgoing block value. */ 174 OUTGOING, 175 } 176 177 /** 178 * For validity checking of the operand flags defined by instruction subclasses. 179 */ 180 protected static final EnumMap<OperandMode, EnumSet<OperandFlag>> ALLOWED_FLAGS; 181 182 static { 183 ALLOWED_FLAGS = new EnumMap<>(OperandMode.class); 184 ALLOWED_FLAGS.put(OperandMode.USE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED)); 185 ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED, OUTGOING)); 186 ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, HINT)); 187 ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, HINT)); 188 } 189 190 /** 191 * The flags of the base and index value of an address. 192 */ 193 protected static final EnumSet<OperandFlag> ADDRESS_FLAGS = EnumSet.of(REG, ILLEGAL); 194 195 private final LIRInstructionClass<?> instructionClass; 196 197 /** 198 * Instruction id for register allocation. 199 */ 200 private int id; 201 202 /** 203 * The source position of the code that generated this instruction. 204 */ 205 private NodeSourcePosition position; 206 207 private static final DebugCounter LIR_NODE_COUNT = Debug.counter("LIRNodes"); 208 209 /** 210 * Constructs a new LIR instruction. 211 */ 212 public LIRInstruction(LIRInstructionClass<? extends LIRInstruction> c) { 213 LIR_NODE_COUNT.increment(); 214 instructionClass = c; 215 assert c.getClazz() == this.getClass(); 216 id = -1; 217 } 218 219 public abstract void emitCode(CompilationResultBuilder crb); 220 221 public final int id() { 222 return id; 223 } 224 225 public final void setId(int id) { 226 this.id = id; 227 } 228 229 public final NodeSourcePosition getPosition() { 230 return position; 231 } 232 233 public final void setPosition(NodeSourcePosition position) { 234 this.position = position; 235 } 236 237 public final String name() { 238 return instructionClass.getOpcode(this); 239 } 240 241 public final boolean hasOperands() { 242 return instructionClass.hasOperands() || hasState() || destroysCallerSavedRegisters(); 243 } 244 245 public final boolean hasState() { 246 return instructionClass.hasState(this); 247 } 248 249 public boolean destroysCallerSavedRegisters() { 250 return false; 251 } 252 253 // InstructionValueProcedures 254 public final void forEachInput(InstructionValueProcedure proc) { 255 instructionClass.forEachUse(this, proc); 256 } 257 258 public final void forEachAlive(InstructionValueProcedure proc) { 259 instructionClass.forEachAlive(this, proc); 260 } 261 262 public final void forEachTemp(InstructionValueProcedure proc) { 263 instructionClass.forEachTemp(this, proc); 264 } 265 266 public final void forEachOutput(InstructionValueProcedure proc) { 267 instructionClass.forEachDef(this, proc); 268 } 269 270 public final void forEachState(InstructionValueProcedure proc) { 271 instructionClass.forEachState(this, proc); 272 } 273 274 // ValueProcedures 275 public final void forEachInput(ValueProcedure proc) { 276 instructionClass.forEachUse(this, proc); 277 } 278 279 public final void forEachAlive(ValueProcedure proc) { 280 instructionClass.forEachAlive(this, proc); 281 } 282 283 public final void forEachTemp(ValueProcedure proc) { 284 instructionClass.forEachTemp(this, proc); 285 } 286 287 public final void forEachOutput(ValueProcedure proc) { 288 instructionClass.forEachDef(this, proc); 289 } 290 291 public final void forEachState(ValueProcedure proc) { 292 instructionClass.forEachState(this, proc); 293 } 294 295 // States 296 public final void forEachState(InstructionStateProcedure proc) { 297 instructionClass.forEachState(this, proc); 298 } 299 300 public final void forEachState(StateProcedure proc) { 301 instructionClass.forEachState(this, proc); 302 } 303 304 // InstructionValueConsumers 305 public final void visitEachInput(InstructionValueConsumer proc) { 306 instructionClass.visitEachUse(this, proc); 307 } 308 309 public final void visitEachAlive(InstructionValueConsumer proc) { 310 instructionClass.visitEachAlive(this, proc); 311 } 312 313 public final void visitEachTemp(InstructionValueConsumer proc) { 314 instructionClass.visitEachTemp(this, proc); 315 } 316 317 public final void visitEachOutput(InstructionValueConsumer proc) { 318 instructionClass.visitEachDef(this, proc); 319 } 320 321 public final void visitEachState(InstructionValueConsumer proc) { 322 instructionClass.visitEachState(this, proc); 323 } 324 325 // ValueConsumers 326 public final void visitEachInput(ValueConsumer proc) { 327 instructionClass.visitEachUse(this, proc); 328 } 329 330 public final void visitEachAlive(ValueConsumer proc) { 331 instructionClass.visitEachAlive(this, proc); 332 } 333 334 public final void visitEachTemp(ValueConsumer proc) { 335 instructionClass.visitEachTemp(this, proc); 336 } 337 338 public final void visitEachOutput(ValueConsumer proc) { 339 instructionClass.visitEachDef(this, proc); 340 } 341 342 public final void visitEachState(ValueConsumer proc) { 343 instructionClass.visitEachState(this, proc); 344 } 345 346 @SuppressWarnings("unused") 347 public final Value forEachRegisterHint(Value value, OperandMode mode, InstructionValueProcedure proc) { 348 return instructionClass.forEachRegisterHint(this, mode, proc); 349 } 350 351 @SuppressWarnings("unused") 352 public final Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc) { 353 return instructionClass.forEachRegisterHint(this, mode, proc); 354 } 355 356 // Checkstyle: stop 357 /** 358 * Returns {@code true} if the instruction is a {@link MoveOp}. 359 * 360 * This function is preferred to {@code instanceof MoveOp} since the type check is more 361 * expensive than reading a field from {@link LIRInstructionClass}. 362 */ 363 public final boolean isMoveOp() { 364 return instructionClass.isMoveOp(); 365 } 366 367 /** 368 * Returns {@code true} if the instruction is a {@link ValueMoveOp}. 369 * 370 * This function is preferred to {@code instanceof ValueMoveOp} since the type check is more 371 * expensive than reading a field from {@link LIRInstructionClass}. 372 */ 373 public final boolean isValueMoveOp() { 374 return instructionClass.isValueMoveOp(); 375 } 376 377 /** 378 * Returns {@code true} if the instruction is a {@link LoadConstantOp}. 379 * 380 * This function is preferred to {@code instanceof LoadConstantOp} since the type check is more 381 * expensive than reading a field from {@link LIRInstructionClass}. 382 */ 383 public final boolean isLoadConstantOp() { 384 return instructionClass.isLoadConstantOp(); 385 } 386 // Checkstyle: resume 387 388 /** 389 * Utility method to add stack arguments to a list of temporaries. Useful for modeling calling 390 * conventions that kill outgoing argument space. 391 * 392 * @return additional temporaries 393 */ 394 protected static Value[] addStackSlotsToTemporaries(Value[] parameters, Value[] temporaries) { 395 int extraTemps = 0; 396 for (Value p : parameters) { 397 if (isStackSlot(p)) { 398 extraTemps++; 399 } 400 assert !isVirtualStackSlot(p) : "only real stack slots in calling convention"; 401 } 402 if (extraTemps != 0) { 403 int index = temporaries.length; 404 Value[] newTemporaries = Arrays.copyOf(temporaries, temporaries.length + extraTemps); 405 for (Value p : parameters) { 406 if (isStackSlot(p)) { 407 newTemporaries[index++] = p; 408 } 409 } 410 return newTemporaries; 411 } 412 return temporaries; 413 } 414 415 public void verify() { 416 } 417 418 /** 419 * Adds a comment to this instruction. 420 */ 421 public final void setComment(LIRGenerationResult res, String comment) { 422 res.setComment(this, comment); 423 } 424 425 /** 426 * Gets the comment attached to this instruction. 427 */ 428 public final String getComment(LIRGenerationResult res) { 429 return res.getComment(this); 430 } 431 432 public final String toStringWithIdPrefix() { 433 if (id != -1) { 434 return String.format("%4d %s", id, toString()); 435 } 436 return " " + toString(); 437 } 438 439 @Override 440 public String toString() { 441 return instructionClass.toString(this); 442 } 443 444 public String toString(LIRGenerationResult res) { 445 String toString = toString(); 446 if (res == null) { 447 return toString; 448 } 449 String comment = getComment(res); 450 if (comment == null) { 451 return toString; 452 } 453 return String.format("%s // %s", toString, comment); 454 } 455 456 public LIRInstructionClass<?> getLIRInstructionClass() { 457 return instructionClass; 458 } 459 460 @Override 461 public int hashCode() { 462 return id; 463 } 464 }