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