Mercurial > hg > truffle
view graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java @ 4142:bc8527f3071c
Adjust code base to new level of warnings.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sun, 18 Dec 2011 05:24:06 +0100 |
parents | e233f5660da4 |
children | f5328dda9714 |
line wrap: on
line source
/* * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.oracle.max.graal.compiler.lir; import com.oracle.max.graal.compiler.asm.*; import com.oracle.max.graal.compiler.lir.LIRDebugInfo.ValueProcedure; import com.oracle.max.graal.compiler.util.*; import com.sun.cri.ci.*; import com.sun.cri.ci.CiValue.Formatter; /** * The {@code LIRInstruction} class definition. */ public abstract class LIRInstruction { public static final CiValue[] NO_OPERANDS = {}; public static final OperandMode[] OPERAND_MODES = OperandMode.values(); /** * Constants denoting how a LIR instruction uses an operand. */ public enum OperandMode { /** * The value must have been defined before. It is alive before the instruction until the beginning of the * instruction, but not necessarily throughout the instruction. A register assigned to it can also be assigend * to a Temp or Output operand. The value can be used again after the instruction, so the instruction must not * modify the register. */ Input, /** * The value must have been defined before. It is alive before the instruction and throughout the instruction. A * register assigned to it cannot be assigned to a Temp or Output operand. The value can be used again after the * instruction, so the instruction must not modify the register. */ Alive, /** * The value must not have been defined before, and must not be used after the instruction. The instruction can * do whatever it wants with the register assigned to it (or not use it at all). */ Temp, /** * The value must not have been defined beforee. The instruction has to assign a value to the register. The * value can (and most likely will) be used after the instruction. */ Output, } /** * The opcode of this instruction. */ public final LIROpcode code; /** * The result operand for this instruction (modified by the register allocator). */ protected CiValue result; /** * The input operands for this instruction (modified by the register allocator). */ protected final CiValue[] inputs; /** * The alive operands for this instruction (modified by the register allocator). */ protected final CiValue[] alives; /** * The temp operands for this instruction (modified by the register allocator). */ protected final CiValue[] temps; /** * Used to emit debug information. */ public final LIRDebugInfo info; /** * Instruction id for register allocation. */ private int id; /** * Constructs a new LIR instruction that has input and temp operands. * * @param opcode the opcode of the new instruction * @param result the operand that holds the operation result of this instruction. This will be * {@link CiValue#IllegalValue} for instructions that do not produce a result. * @param info the {@link LIRDebugInfo} info that is to be preserved for the instruction. This will be {@code null} when no debug info is required for the instruction. * @param inputs the input operands for the instruction. * @param temps the temp operands for the instruction. */ public LIRInstruction(LIROpcode opcode, CiValue result, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { this.code = opcode; this.result = result; this.inputs = inputs; this.alives = alives; this.temps = temps; this.info = info; this.id = -1; } public abstract void emitCode(TargetMethodAssembler tasm); public final int id() { return id; } public final void setId(int id) { this.id = id; } /** * Gets an input operand of this instruction. * * @param index the index of the operand requested. * @return the {@code index}'th input operand. */ public final CiValue input(int index) { return inputs[index]; } /** * Gets an alive operand of this instruction. * * @param index the index of the operand requested. * @return the {@code index}'th alive operand. */ public final CiValue alive(int index) { return alives[index]; } /** * Gets a temp operand of this instruction. * * @param index the index of the operand requested. * @return the {@code index}'th temp operand. */ public final CiValue temp(int index) { return temps[index]; } /** * Gets the result operand for this instruction. * * @return return the result operand */ public final CiValue result() { return result; } /** * Gets the instruction name. */ public String name() { return code.toString(); } public boolean hasOperands() { return inputs.length > 0 || alives.length > 0 || temps.length > 0 || info != null || hasCall(); } public final int operandCount(OperandMode mode) { switch (mode) { case Output: return result.isLegal() ? 1 : 0; case Input: return inputs.length; case Alive: return alives.length; case Temp: return temps.length; default: throw Util.shouldNotReachHere(); } } public final CiValue operandAt(OperandMode mode, int index) { assert index < operandCount(mode); switch (mode) { case Output: return result; case Input: return inputs[index]; case Alive: return alives[index]; case Temp: return temps[index]; default: throw Util.shouldNotReachHere(); } } public final void setOperandAt(OperandMode mode, int index, CiValue location) { assert index < operandCount(mode); assert location.kind != CiKind.Illegal; assert operandAt(mode, index).isVariable() && operandAt(mode, index).kind == location.kind; switch (mode) { case Output: result = location; break; case Input: inputs[index] = location; break; case Alive: alives[index] = location; break; case Temp: temps[index] = location; break; default: throw Util.shouldNotReachHere(); } } public final void forEachOperand(OperandMode mode, ValueProcedure proc) { for (int i = 0; i < operandCount(mode); i++) { CiValue newValue = proc.doValue(operandAt(mode, i)); if (newValue != null) { setOperandAt(mode, i, newValue); } } } /** * Returns true when this instruction is a call instruction that destroys all caller-saved registers. */ public boolean hasCall() { return false; } /** * Used by the register allocator. The result operand of this instruction should get * the same register assigned as the returned operand. * @return The register hint for the output operand, or null if no register hint should be defined. */ public CiValue registerHint() { return null; } /** * Used by the register allocator to decide whether an input operand can be assigned a stack slot. * Subclasses should override this method when an input can be memory. * @param index The index of the operand in {@link #inputs}. * @return true if the input operand with the given index can be assigned a stack slot. */ public boolean inputCanBeMemory(int index) { return false; } @Override public String toString() { return toString(Formatter.DEFAULT); } public final String toStringWithIdPrefix() { if (id != -1) { return String.format("%4d %s", id, toString()); } return " " + toString(); } /** * Gets the operation performed by this instruction in terms of its operands as a string. */ public String operationString(Formatter operandFmt) { StringBuilder buf = new StringBuilder(); if (result.isLegal()) { buf.append(operandFmt.format(result)).append(" = "); } if (inputs.length + alives.length > 1) { buf.append("("); } String sep = ""; for (CiValue input : inputs) { buf.append(sep).append(operandFmt.format(input)); sep = ", "; } for (CiValue input : alives) { buf.append(sep).append(operandFmt.format(input)).append(" ~"); sep = ", "; } if (inputs.length + alives.length > 1) { buf.append(")"); } if (temps.length > 0) { buf.append(" ["); } sep = ""; for (CiValue temp : temps) { buf.append(sep).append(operandFmt.format(temp)); sep = ", "; } if (temps.length > 0) { buf.append("]"); } return buf.toString(); } protected static String refMapToString(CiDebugInfo debugInfo, Formatter operandFmt) { StringBuilder buf = new StringBuilder(); if (debugInfo.hasStackRefMap()) { CiBitMap bm = debugInfo.frameRefMap; for (int slot = bm.nextSetBit(0); slot >= 0; slot = bm.nextSetBit(slot + 1)) { if (buf.length() != 0) { buf.append(", "); } buf.append(operandFmt.format(CiStackSlot.get(CiKind.Object, slot))); } } if (debugInfo.hasRegisterRefMap()) { CiBitMap bm = debugInfo.registerRefMap; for (int reg = bm.nextSetBit(0); reg >= 0; reg = bm.nextSetBit(reg + 1)) { if (buf.length() != 0) { buf.append(", "); } buf.append("r").append(reg); } } return buf.toString(); } protected void appendDebugInfo(StringBuilder buf, Formatter operandFmt) { if (info != null) { buf.append(" [bci:").append(info.topFrame.bci); if (info.hasDebugInfo()) { CiDebugInfo debugInfo = info.debugInfo(); String refmap = refMapToString(debugInfo, operandFmt); if (refmap.length() != 0) { buf.append(", refmap(").append(refmap.trim()).append(')'); } } buf.append(']'); } } public String toString(Formatter operandFmt) { StringBuilder buf = new StringBuilder(name()).append(' ').append(operationString(operandFmt)); appendDebugInfo(buf, operandFmt); return buf.toString(); } }