LIRInstructionClass.java revision 12651:6ef01bd40ce2
1222900Snp/* 2222900Snp * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 3222900Snp * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4222900Snp * 5222900Snp * This code is free software; you can redistribute it and/or modify it 6222900Snp * under the terms of the GNU General Public License version 2 only, as 7222900Snp * published by the Free Software Foundation. 8222900Snp * 9222900Snp * This code is distributed in the hope that it will be useful, but WITHOUT 10222900Snp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11222900Snp * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12222900Snp * version 2 for more details (a copy is included in the LICENSE file that 13222900Snp * accompanied this code). 14222900Snp * 15222900Snp * You should have received a copy of the GNU General Public License version 16222900Snp * 2 along with this work; if not, write to the Free Software Foundation, 17222900Snp * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18222900Snp * 19222900Snp * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20222900Snp * or visit www.oracle.com if you need additional information or have any 21222900Snp * questions. 22222900Snp */ 23222900Snppackage org.graalvm.compiler.lir; 24222900Snp 25222900Snpimport java.lang.reflect.Field; 26222900Snpimport java.util.Arrays; 27222900Snpimport java.util.EnumSet; 28222900Snp 29222900Snpimport org.graalvm.compiler.core.common.Fields; 30222900Snpimport org.graalvm.compiler.core.common.FieldsScanner; 31287297Srodrigcimport org.graalvm.compiler.debug.GraalError; 32222900Snpimport org.graalvm.compiler.lir.LIRInstruction.OperandFlag; 33228594Snpimport org.graalvm.compiler.lir.LIRInstruction.OperandMode; 34222900Snp 35228594Snpimport jdk.vm.ci.code.BytecodeFrame; 36287297Srodrigcimport jdk.vm.ci.meta.Value; 37287297Srodrigc 38222900Snppublic class LIRInstructionClass<T> extends LIRIntrospection<T> { 39287297Srodrigc 40222900Snp public static <T extends LIRInstruction> LIRInstructionClass<T> create(Class<T> c) { 41222900Snp return new LIRInstructionClass<>(c); 42287297Srodrigc } 43287297Srodrigc 44287297Srodrigc private static final Class<LIRInstruction> INSTRUCTION_CLASS = LIRInstruction.class; 45287297Srodrigc private static final Class<LIRFrameState> STATE_CLASS = LIRFrameState.class; 46287297Srodrigc 47287297Srodrigc private final Values uses; 48287297Srodrigc private final Values alives; 49287297Srodrigc private final Values temps; 50287297Srodrigc private final Values defs; 51287297Srodrigc private final Fields states; 52287297Srodrigc 53222900Snp private String opcodeConstant; 54222900Snp private int opcodeIndex; 55259048Snp 56222974Snp private LIRInstructionClass(Class<T> clazz) { 57222974Snp this(clazz, new FieldsScanner.DefaultCalcOffset()); 58222900Snp } 59253870Snp 60222900Snp public LIRInstructionClass(Class<T> clazz, FieldsScanner.CalcOffset calcOffset) { 61222900Snp super(clazz); 62222900Snp assert INSTRUCTION_CLASS.isAssignableFrom(clazz); 63222900Snp 64222900Snp LIRInstructionFieldsScanner ifs = new LIRInstructionFieldsScanner(calcOffset); 65222900Snp ifs.scan(clazz); 66222900Snp 67222900Snp uses = new Values(ifs.valueAnnotations.get(LIRInstruction.Use.class)); 68222900Snp alives = new Values(ifs.valueAnnotations.get(LIRInstruction.Alive.class)); 69222900Snp temps = new Values(ifs.valueAnnotations.get(LIRInstruction.Temp.class)); 70222900Snp defs = new Values(ifs.valueAnnotations.get(LIRInstruction.Def.class)); 71222900Snp 72222974Snp states = new Fields(ifs.states); 73222974Snp data = new Fields(ifs.data); 74222974Snp 75222974Snp opcodeConstant = ifs.opcodeConstant; 76222974Snp if (ifs.opcodeField == null) { 77222974Snp opcodeIndex = -1; 78222974Snp } else { 79222974Snp opcodeIndex = ifs.data.indexOf(ifs.opcodeField); 80222974Snp } 81222900Snp } 82296471Snp 83296471Snp @SuppressWarnings("unchecked") 84222900Snp public static <T> LIRInstructionClass<T> get(Class<T> clazz) { 85222900Snp try { 86222900Snp Field field = clazz.getDeclaredField("TYPE"); 87222900Snp field.setAccessible(true); 88222900Snp return (LIRInstructionClass<T>) field.get(null); 89222900Snp } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { 90222900Snp throw new RuntimeException(e); 91241416Snp } 92222974Snp } 93222900Snp 94222900Snp private static class LIRInstructionFieldsScanner extends LIRFieldsScanner { 95222900Snp 96222900Snp private String opcodeConstant; 97241401Snp 98306823Snp /** 99306823Snp * Field (if any) annotated by {@link Opcode}. 100228594Snp */ 101228594Snp private FieldsScanner.FieldInfo opcodeField; 102269106Snp 103222900Snp LIRInstructionFieldsScanner(FieldsScanner.CalcOffset calc) { 104222900Snp super(calc); 105222900Snp 106259048Snp valueAnnotations.put(LIRInstruction.Use.class, new OperandModeAnnotation()); 107259048Snp valueAnnotations.put(LIRInstruction.Alive.class, new OperandModeAnnotation()); 108222900Snp valueAnnotations.put(LIRInstruction.Temp.class, new OperandModeAnnotation()); 109228594Snp valueAnnotations.put(LIRInstruction.Def.class, new OperandModeAnnotation()); 110259048Snp } 111253691Snp 112253691Snp @Override 113222900Snp protected EnumSet<OperandFlag> getFlags(Field field) { 114222900Snp EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class); 115222900Snp // Unfortunately, annotations cannot have class hierarchies or implement interfaces, so 116222900Snp // we have to duplicate the code for every operand mode. 117222900Snp // Unfortunately, annotations cannot have an EnumSet property, so we have to convert 118222900Snp // from arrays to EnumSet manually. 119222900Snp if (field.isAnnotationPresent(LIRInstruction.Use.class)) { 120222900Snp result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Use.class).value())); 121222900Snp } else if (field.isAnnotationPresent(LIRInstruction.Alive.class)) { 122222900Snp result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Alive.class).value())); 123222900Snp } else if (field.isAnnotationPresent(LIRInstruction.Temp.class)) { 124222900Snp result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Temp.class).value())); 125222900Snp } else if (field.isAnnotationPresent(LIRInstruction.Def.class)) { 126222900Snp result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Def.class).value())); 127222900Snp } else { 128222900Snp GraalError.shouldNotReachHere(); 129222900Snp } 130222900Snp return result; 131222900Snp } 132222900Snp 133222900Snp public void scan(Class<?> clazz) { 134222900Snp if (clazz.getAnnotation(Opcode.class) != null) { 135222900Snp opcodeConstant = clazz.getAnnotation(Opcode.class).value(); 136222900Snp } 137253870Snp opcodeField = null; 138222900Snp 139222900Snp super.scan(clazz, LIRInstruction.class, false); 140222900Snp 141222900Snp if (opcodeConstant == null && opcodeField == null) { 142222900Snp opcodeConstant = clazz.getSimpleName(); 143222900Snp if (opcodeConstant.endsWith("Op")) { 144222900Snp opcodeConstant = opcodeConstant.substring(0, opcodeConstant.length() - 2); 145222900Snp } 146222900Snp } 147222900Snp } 148222900Snp 149222900Snp @Override 150222900Snp protected void scanField(Field field, long offset) { 151222900Snp Class<?> type = field.getType(); 152222900Snp if (STATE_CLASS.isAssignableFrom(type)) { 153222900Snp assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; 154222900Snp assert field.getAnnotation(LIRInstruction.State.class) != null : "Field must have state annotation: " + field; 155222900Snp states.add(new FieldsScanner.FieldInfo(offset, field.getName(), type, field.getDeclaringClass())); 156222900Snp } else { 157222900Snp super.scanField(field, offset); 158222900Snp } 159222900Snp 160222900Snp if (field.getAnnotation(Opcode.class) != null) { 161222900Snp assert opcodeConstant == null && opcodeField == null : "Can have only one Opcode definition: " + type; 162222900Snp assert data.get(data.size() - 1).offset == offset; 163222900Snp opcodeField = data.get(data.size() - 1); 164222900Snp } 165222900Snp } 166222900Snp } 167222900Snp 168222900Snp @Override 169222900Snp public Fields[] getAllFields() { 170222900Snp assert values == null; 171222900Snp return new Fields[]{data, uses, alives, temps, defs, states}; 172222900Snp } 173222900Snp 174222900Snp @Override 175222900Snp public String toString() { 176222900Snp StringBuilder str = new StringBuilder(); 177222900Snp str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" use["); 178222900Snp uses.appendFields(str); 179222900Snp str.append("] alive["); 180222900Snp alives.appendFields(str); 181222900Snp str.append("] temp["); 182222900Snp temps.appendFields(str); 183222900Snp str.append("] def["); 184222900Snp defs.appendFields(str); 185222900Snp str.append("] state["); 186222900Snp states.appendFields(str); 187222900Snp str.append("] data["); 188222900Snp data.appendFields(str); 189222900Snp str.append("]"); 190222900Snp return str.toString(); 191222900Snp } 192222900Snp 193222900Snp Values getValues(OperandMode mode) { 194222900Snp switch (mode) { 195222900Snp case USE: 196222900Snp return uses; 197222900Snp case ALIVE: 198222900Snp return alives; 199222900Snp case TEMP: 200222900Snp return temps; 201222900Snp case DEF: 202222900Snp return defs; 203222900Snp default: 204222900Snp throw GraalError.shouldNotReachHere("unknown OperandMode: " + mode); 205222900Snp } 206222900Snp } 207222900Snp 208222900Snp final String getOpcode(LIRInstruction obj) { 209222900Snp if (opcodeConstant != null) { 210222900Snp return opcodeConstant; 211222900Snp } 212222900Snp assert opcodeIndex != -1; 213222900Snp return String.valueOf(data.getObject(obj, opcodeIndex)); 214222900Snp } 215222900Snp 216222900Snp final boolean hasOperands() { 217222900Snp return uses.getCount() > 0 || alives.getCount() > 0 || temps.getCount() > 0 || defs.getCount() > 0; 218222900Snp } 219222900Snp 220222900Snp final boolean hasState(LIRInstruction obj) { 221222900Snp for (int i = 0; i < states.getCount(); i++) { 222222900Snp if (states.getObject(obj, i) != null) { 223222900Snp return true; 224222900Snp } 225222900Snp } 226222900Snp return false; 227222900Snp } 228222900Snp 229222900Snp final void forEachUse(LIRInstruction obj, InstructionValueProcedure proc) { 230222900Snp forEach(obj, uses, OperandMode.USE, proc); 231222900Snp } 232222900Snp 233222900Snp final void forEachAlive(LIRInstruction obj, InstructionValueProcedure proc) { 234222900Snp forEach(obj, alives, OperandMode.ALIVE, proc); 235222900Snp } 236222900Snp 237222900Snp final void forEachTemp(LIRInstruction obj, InstructionValueProcedure proc) { 238222900Snp forEach(obj, temps, OperandMode.TEMP, proc); 239222900Snp } 240222900Snp 241222900Snp final void forEachDef(LIRInstruction obj, InstructionValueProcedure proc) { 242222900Snp forEach(obj, defs, OperandMode.DEF, proc); 243222900Snp } 244222900Snp 245222900Snp final void visitEachUse(LIRInstruction obj, InstructionValueConsumer proc) { 246222900Snp visitEach(obj, uses, OperandMode.USE, proc); 247222900Snp } 248222900Snp 249222900Snp final void visitEachAlive(LIRInstruction obj, InstructionValueConsumer proc) { 250222900Snp visitEach(obj, alives, OperandMode.ALIVE, proc); 251222900Snp } 252222900Snp 253222900Snp final void visitEachTemp(LIRInstruction obj, InstructionValueConsumer proc) { 254222900Snp visitEach(obj, temps, OperandMode.TEMP, proc); 255222900Snp } 256222900Snp 257222900Snp final void visitEachDef(LIRInstruction obj, InstructionValueConsumer proc) { 258222900Snp visitEach(obj, defs, OperandMode.DEF, proc); 259222900Snp } 260222900Snp 261222900Snp final void forEachState(LIRInstruction obj, InstructionValueProcedure proc) { 262222900Snp for (int i = 0; i < states.getCount(); i++) { 263222900Snp LIRFrameState state = (LIRFrameState) states.getObject(obj, i); 264222900Snp if (state != null) { 265222900Snp state.forEachState(obj, proc); 266222900Snp } 267222900Snp } 268222900Snp } 269222900Snp 270222900Snp final void visitEachState(LIRInstruction obj, InstructionValueConsumer proc) { 271222900Snp for (int i = 0; i < states.getCount(); i++) { 272222900Snp LIRFrameState state = (LIRFrameState) states.getObject(obj, i); 273222900Snp if (state != null) { 274222900Snp state.visitEachState(obj, proc); 275222900Snp } 276222900Snp } 277222900Snp } 278222900Snp 279222900Snp final void forEachState(LIRInstruction obj, InstructionStateProcedure proc) { 280222900Snp for (int i = 0; i < states.getCount(); i++) { 281222900Snp LIRFrameState state = (LIRFrameState) states.getObject(obj, i); 282222900Snp if (state != null) { 283222900Snp proc.doState(obj, state); 284222900Snp } 285222900Snp } 286222900Snp } 287222900Snp 288222900Snp final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, InstructionValueProcedure proc) { 289222900Snp Values hints; 290222900Snp if (mode == OperandMode.USE) { 291222900Snp hints = defs; 292222900Snp } else if (mode == OperandMode.DEF) { 293222900Snp hints = uses; 294222900Snp } else { 295222900Snp return null; 296222900Snp } 297222900Snp 298222900Snp for (int i = 0; i < hints.getCount(); i++) { 299222900Snp if (i < hints.getDirectCount()) { 300222900Snp Value hintValue = hints.getValue(obj, i); 301222900Snp Value result = proc.doValue(obj, hintValue, null, null); 302222900Snp if (result != null) { 303222900Snp return result; 304222900Snp } 305222900Snp } else { 306222900Snp Value[] hintValues = hints.getValueArray(obj, i); 307222900Snp for (int j = 0; j < hintValues.length; j++) { 308222900Snp Value hintValue = hintValues[j]; 309222900Snp Value result = proc.doValue(obj, hintValue, null, null); 310222900Snp if (result != null) { 311222900Snp return result; 312222900Snp } 313222900Snp } 314222900Snp } 315222900Snp } 316222900Snp return null; 317222900Snp } 318222900Snp 319222900Snp String toString(LIRInstruction obj) { 320222900Snp StringBuilder result = new StringBuilder(); 321222900Snp 322222900Snp appendValues(result, obj, "", " = ", "(", ")", new String[]{""}, defs); 323222900Snp result.append(String.valueOf(getOpcode(obj)).toUpperCase()); 324222900Snp appendValues(result, obj, " ", "", "(", ")", new String[]{"", "~"}, uses, alives); 325222900Snp appendValues(result, obj, " ", "", "{", "}", new String[]{""}, temps); 326222900Snp 327222900Snp for (int i = 0; i < data.getCount(); i++) { 328222900Snp if (i == opcodeIndex) { 329222900Snp continue; 330222900Snp } 331222900Snp result.append(" ").append(data.getName(i)).append(": ").append(getFieldString(obj, i, data)); 332259048Snp } 333222900Snp 334222900Snp for (int i = 0; i < states.getCount(); i++) { 335222900Snp LIRFrameState state = (LIRFrameState) states.getObject(obj, i); 336222900Snp if (state != null) { 337222900Snp result.append(" ").append(states.getName(i)).append(" [bci:"); 338222900Snp String sep = ""; 339222900Snp for (BytecodeFrame cur = state.topFrame; cur != null; cur = cur.caller()) { 340222900Snp result.append(sep).append(cur.getBCI()); 341222900Snp sep = ", "; 342222900Snp } 343222900Snp result.append("]"); 344259048Snp } 345222900Snp } 346222900Snp 347222900Snp return result.toString(); 348222900Snp } 349222900Snp} 350222900Snp