# HG changeset patch # User Josef Eisl # Date 1395232513 -3600 # Node ID 20dcae7f93ebb32b9d36a83c1053bed2a3c6e003 # Parent 73a77e65c80567e2a678edbd3ffdd8e22f0f4564 Introduce LIRGeneratorCommon and NodeBasedLIRGenerator interfaces. diff -r 73a77e65c805 -r 20dcae7f93eb graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Mar 18 14:50:17 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Mar 19 13:35:13 2014 +0100 @@ -57,7 +57,7 @@ /** * This class traverses the HIR instructions and generates LIR instructions from them. */ -public abstract class LIRGenerator implements LIRGeneratorTool, LIRTypeTool { +public abstract class LIRGenerator implements LIRGeneratorTool, LIRTypeTool, LIRGeneratorCommon, NodeBasedLIRGenerator { public static class Options { // @formatter:off @@ -164,12 +164,21 @@ */ public abstract boolean canStoreConstant(Constant c, boolean isCompressed); + public LIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult res) { + this(null, providers, cc, res); + } + public LIRGenerator(StructuredGraph graph, Providers providers, CallingConvention cc, LIRGenerationResult res) { this.res = res; this.providers = providers; this.cc = cc; - this.nodeOperands = graph.createNodeMap(); - this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands); + if (graph != null) { + this.nodeOperands = graph.createNodeMap(); + this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands); + } else { + this.nodeOperands = null; + this.debugInfoBuilder = null; + } this.traceLevel = Options.TraceLIRGeneratorLevel.getValue(); this.printIRWithLIR = Options.PrintIRWithLIR.getValue(); } @@ -266,7 +275,7 @@ } public ValueNode valueForOperand(Value value) { - for (Entry entry : nodeOperands.entries()) { + for (Entry entry : getNodeOperands().entries()) { if (entry.getValue().equals(value)) { return (ValueNode) entry.getKey(); } @@ -846,6 +855,7 @@ protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key); public final NodeMap getNodeOperands() { + assert nodeOperands != null; return nodeOperands; } @@ -854,6 +864,7 @@ } public DebugInfoBuilder getDebugInfoBuilder() { + assert debugInfoBuilder != null; return debugInfoBuilder; } diff -r 73a77e65c805 -r 20dcae7f93eb graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGeneratorCommon.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGeneratorCommon.java Wed Mar 19 13:35:13 2014 +0100 @@ -0,0 +1,103 @@ +package com.oracle.graal.compiler.gen; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.type.*; + +public interface LIRGeneratorCommon { + + /** + * Checks whether the supplied constant can be used without loading it into a register for store + * operations, i.e., on the right hand side of a memory access. + * + * @param c The constant to check. + * @return True if the constant can be used directly, false if the constant needs to be in a + * register. + */ + boolean canStoreConstant(Constant c, boolean isCompressed); + + /** + * Returns true if the redundant move elimination optimization should be done after register + * allocation. + */ + boolean canEliminateRedundantMoves(); + + TargetDescription target(); + + MetaAccessProvider getMetaAccess(); + + CodeCacheProvider getCodeCache(); + + ForeignCallsProvider getForeignCalls(); + + /** + * Creates a new {@linkplain Variable variable}. + * + * @param platformKind The kind of the new variable. + * @return a new variable + */ + Variable newVariable(PlatformKind platformKind); + + RegisterAttributes attributes(Register register); + + Variable emitMove(Value input); + + AllocatableValue asAllocatable(Value value); + + Variable load(Value value); + + Value loadNonConst(Value value); + + /** + * Gets the ABI specific operand used to return a value of a given kind from a method. + * + * @param kind the kind of value being returned + * @return the operand representing the ABI defined location used return a value of kind + * {@code kind} + */ + AllocatableValue resultOperandFor(Kind kind); + + void append(LIRInstruction op); + + void emitIncomingValues(Value[] params); + + void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock); + + void emitJump(LabelRef label); + + void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability); + + void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability); + + void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability); + + Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue); + + Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue); + + CallingConvention getCallingConvention(); + + /** + * Default implementation: Return the Java stack kind for each stamp. + */ + PlatformKind getPlatformKind(Stamp stamp); + + PlatformKind getIntegerKind(int bits, boolean unsigned); + + PlatformKind getFloatingKind(int bits); + + PlatformKind getObjectKind(); + + void emitBitCount(Variable result, Value operand); + + void emitBitScanForward(Variable result, Value operand); + + void emitBitScanReverse(Variable result, Value operand); + + void emitByteSwap(Variable result, Value operand); + + void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length); + +} \ No newline at end of file diff -r 73a77e65c805 -r 20dcae7f93eb graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeBasedLIRGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeBasedLIRGenerator.java Wed Mar 19 13:35:13 2014 +0100 @@ -0,0 +1,82 @@ +package com.oracle.graal.compiler.gen; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.extended.*; + +public interface NodeBasedLIRGenerator { + + /** + * Returns the operand that has been previously initialized by + * {@link #setResult(ValueNode, Value)} with the result of an instruction. + * + * @param node A node that produces a result value. + */ + Value operand(ValueNode node); + + ValueNode valueForOperand(Value value); + + Value setResult(ValueNode x, Value operand); + + LabelRef getLIRBlock(FixedNode b); + + LIRFrameState state(DeoptimizingNode deopt); + + LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge); + + LIRFrameState stateFor(FrameState state); + + LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge); + + void append(LIRInstruction op); + + void doBlock(Block block, StructuredGraph graph, BlockMap> blockMap); + + void visitReturn(ReturnNode x); + + void visitMerge(MergeNode x); + + void visitEndNode(AbstractEndNode end); + + /** + * Runtime specific classes can override this to insert a safepoint at the end of a loop. + */ + void visitLoopEnd(LoopEndNode x); + + void emitIf(IfNode x); + + void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability); + + void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability); + + void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability); + + void emitConditional(ConditionalNode conditional); + + Variable emitConditional(LogicNode node, Value trueValue, Value falseValue); + + void emitInvoke(Invoke x); + + Value[] visitInvokeArguments(CallingConvention invokeCc, Collection arguments); + + Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args); + + /** + * This method tries to create a switch implementation that is optimal for the given switch. It + * will either generate a sequential if/then/else cascade, a set of range tests or a table + * switch. + * + * If the given switch does not contain int keys, it will always create a sequential + * implementation. + */ + void emitSwitch(SwitchNode x); + + void beforeRegisterAllocation(); + +} \ No newline at end of file