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