Mercurial > hg > truffle
diff graal/Compiler/src/com/sun/c1x/gen/LIRItem.java @ 2507:9ec15d6914ca
Pull over of compiler from maxine repository.
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Wed, 27 Apr 2011 11:43:22 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/Compiler/src/com/sun/c1x/gen/LIRItem.java Wed Apr 27 11:43:22 2011 +0200 @@ -0,0 +1,223 @@ +/* + * 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.sun.c1x.gen; + +import com.sun.c1x.alloc.OperandPool.*; +import com.sun.c1x.ir.*; +import com.sun.c1x.util.*; +import com.sun.cri.ci.*; + +/** + * A helper utility for loading the {@linkplain Value#operand() result} + * of an instruction for use by another instruction. This helper takes + * into account the specifics of the consuming instruction such as whether + * it requires the input operand to be in memory or a register, any + * register size requirements of the input operand, and whether the + * usage has the side-effect of overwriting the input operand. To satisfy + * these constraints, an intermediate operand may be created and move + * instruction inserted to copy the output of the producer instruction + * into the intermediate operand. + * + * @author Marcelo Cintra + * @author Thomas Wuerthinger + * @author Doug Simon + */ +public class LIRItem { + + /** + * The instruction whose usage by another instruction is being modeled by this object. + * An instruction {@code x} uses instruction {@code y} if the {@linkplain Value#operand() result} + * of {@code y} is an input operand of {@code x}. + */ + public Value instruction; + + /** + * The LIR context of this helper object. + */ + private final LIRGenerator gen; + + /** + * The operand holding the result of this item's {@linkplain #instruction}. + */ + private CiValue resultOperand; + + /** + * Denotes if the use of the instruction's {@linkplain #resultOperand result operand} + * overwrites the value in the operand. That is, the use both uses and defines the + * operand. In this case, an {@linkplain #intermediateOperand intermediate operand} + * is created for the use so that other consumers of this item's {@linkplain #instruction} + * are not impacted. + */ + private boolean destructive; + + /** + * @see #destructive + */ + private CiValue intermediateOperand; + + public LIRItem(Value value, LIRGenerator gen) { + this.gen = gen; + setInstruction(value); + } + + public void setInstruction(Value instruction) { + this.instruction = instruction; + if (instruction != null) { + resultOperand = gen.makeOperand(instruction); + } else { + resultOperand = CiValue.IllegalValue; + } + intermediateOperand = CiValue.IllegalValue; + } + + public LIRItem(LIRGenerator gen) { + this.gen = gen; + setInstruction(null); + } + + public void loadItem(CiKind kind) { + if (kind == CiKind.Byte || kind == CiKind.Boolean) { + loadByteItem(); + } else { + loadItem(); + } + } + + public void loadForStore(CiKind kind) { + if (gen.canStoreAsConstant(instruction, kind)) { + resultOperand = instruction.operand(); + if (!resultOperand.isConstant()) { + resultOperand = instruction.asConstant(); + } + } else if (kind == CiKind.Byte || kind == CiKind.Boolean) { + loadByteItem(); + } else { + loadItem(); + } + } + + public CiValue result() { + assert !destructive || !resultOperand.isRegister() : "shouldn't use setDestroysRegister with physical registers"; + if (destructive && (resultOperand.isVariable() || resultOperand.isConstant())) { + if (intermediateOperand.isIllegal()) { + intermediateOperand = gen.newVariable(instruction.kind); + gen.lir.move(resultOperand, intermediateOperand); + } + return intermediateOperand; + } else { + return resultOperand; + } + } + + public void setDestroysRegister() { + destructive = true; + } + + /** + * Determines if the operand is in a stack slot. + */ + public boolean isStack() { + return resultOperand.isAddress() || resultOperand.isStackSlot(); + } + + /** + * Determines if the operand is in a register or may be + * resolved to a register by the register allocator. + */ + public boolean isRegisterOrVariable() { + return resultOperand.isVariableOrRegister(); + } + + public void loadByteItem() { + if (gen.compilation.target.arch.isX86()) { + loadItem(); + CiValue res = result(); + + if (!res.isVariable() || !gen.operands.mustBeByteRegister(res)) { + // make sure that it is a byte register + assert !instruction.kind.isFloat() && !instruction.kind.isDouble() : "can't load floats in byte register"; + CiValue reg = gen.operands.newVariable(CiKind.Byte, VariableFlag.MustBeByteRegister); + gen.lir.move(res, reg); + resultOperand = reg; + } + } else if (gen.compilation.target.arch.isSPARC()) { + loadItem(); + } else { + Util.shouldNotReachHere(); + } + } + + public void loadNonconstant() { + if (gen.compilation.target.arch.isX86()) { + CiValue r = instruction.operand(); + if (r.isConstant()) { + resultOperand = r; + } else { + loadItem(); + } + } else if (gen.compilation.target.arch.isSPARC()) { + CiValue r = instruction.operand(); + if (gen.canInlineAsConstant(instruction)) { + if (!r.isConstant()) { + r = instruction.asConstant(); + } + resultOperand = r; + } else { + loadItem(); + } + } else { + Util.shouldNotReachHere(); + } + } + + private void setResult(CiVariable operand) { + gen.setResult(instruction, operand); + resultOperand = operand; + } + + /** + * Creates an operand containing the result of {@linkplain #instruction input instruction}. + */ + public void loadItem() { + if (result().isIllegal()) { + // update the item's result + resultOperand = instruction.operand(); + } + CiValue result = result(); + if (!result.isVariableOrRegister()) { + CiVariable operand; + operand = gen.newVariable(instruction.kind); + gen.lir.move(result, operand); + if (result.isConstant()) { + resultOperand = operand; + } else { + setResult(operand); + } + } + } + + @Override + public String toString() { + return result().toString(); + } +}