changeset 14812:20dcae7f93eb

Introduce LIRGeneratorCommon and NodeBasedLIRGenerator interfaces.
author Josef Eisl <josef.eisl@jku.at>
date Wed, 19 Mar 2014 13:35:13 +0100
parents 73a77e65c805
children fafbff0eeebf
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGeneratorCommon.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeBasedLIRGenerator.java
diffstat 3 files changed, 200 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- 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<Node, Value> entry : nodeOperands.entries()) {
+        for (Entry<Node, Value> 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<Value> getNodeOperands() {
+        assert nodeOperands != null;
         return nodeOperands;
     }
 
@@ -854,6 +864,7 @@
     }
 
     public DebugInfoBuilder getDebugInfoBuilder() {
+        assert debugInfoBuilder != null;
         return debugInfoBuilder;
     }
 
--- /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
--- /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<List<ScheduledNode>> 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<ValueNode> 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