changeset 6470:b1010f7bc0bf

expanded CallingConvention API class to also include the location of the value (if any) returned by a call
author Doug Simon <doug.simon@oracle.com>
date Mon, 01 Oct 2012 21:37:20 +0200
parents ec2211254419
children b4fe028b6dc8
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRegisterConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java
diffstat 7 files changed, 99 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java	Mon Oct 01 16:12:45 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java	Mon Oct 01 21:37:20 2012 +0200
@@ -28,7 +28,8 @@
 
 
 /**
- * A calling convention describes the locations in which the arguments for a call are placed.
+ * A calling convention describes the locations in which the arguments for a call are placed
+ * and the location in which the return value is placed if the call is not void.
  */
 public class CallingConvention {
 
@@ -72,33 +73,69 @@
     /**
      * The amount of stack space (in bytes) required for the stack-based arguments of the call.
      */
-    public final int stackSize;
+    private final int stackSize;
+
+    private final Value returnLocation;
 
     /**
      * The locations in which the arguments are placed. This array ordered by argument index.
      */
-    public final Value[] locations;
+    private final Value[] argumentLocations;
+
+    public CallingConvention(int stackSize, Value returnLocation, Value... locations) {
+        this.argumentLocations = locations;
+        this.stackSize = stackSize;
+        this.returnLocation = returnLocation;
+        assert verify();
+    }
+
+    /**
+     * @return the location for the return value or {@link Value#IllegalValue} if a void call
+     */
+    public Value getReturn() {
+        return returnLocation;
+    }
 
-    public CallingConvention(Value[] locations, int stackSize) {
-        this.locations = locations;
-        this.stackSize = stackSize;
-        assert verify();
+    /**
+     * @return the location for the {@code index}'th argument
+     */
+    public Value getArgument(int index) {
+        return argumentLocations[index];
+    }
+
+    /**
+     * @return the amount of stack space (in bytes) required for the stack-based arguments of the call.
+     */
+    public int getStackSize() {
+        return stackSize;
+    }
+
+    /**
+     * @return the number of locations required for the arguments
+     */
+    public int getArgumentCount() {
+        return argumentLocations.length;
     }
 
     @Override
     public String toString() {
         StringBuilder result = new StringBuilder();
         result.append("CallingConvention[");
-        for (Value op : locations) {
-            result.append(op.toString()).append(" ");
+        String sep = "";
+        for (Value op : argumentLocations) {
+            result.append(sep).append(op);
+            sep = ", ";
+        }
+        if (returnLocation != Value.IllegalValue) {
+            result.append(" -> ").append(returnLocation);
         }
         result.append("]");
         return result.toString();
     }
 
     private boolean verify() {
-        for (int i = 0; i < locations.length; i++) {
-            Value location = locations[i];
+        for (int i = 0; i < argumentLocations.length; i++) {
+            Value location = argumentLocations[i];
             assert isStackSlot(location) || isRegister(location);
         }
         return true;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java	Mon Oct 01 16:12:45 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java	Mon Oct 01 21:37:20 2012 +0200
@@ -50,11 +50,12 @@
      * Gets the calling convention describing how arguments are passed.
      *
      * @param type the type of calling convention being requested
-     * @param parameters the types of the arguments of the call
+     * @param returnKind the return kind
+     * @param parameters the kinds of the arguments of the call
      * @param target the target platform
      * @param stackOnly ignore registers
      */
-    CallingConvention getCallingConvention(Type type, Kind[] parameters, TargetDescription target, boolean stackOnly);
+    CallingConvention getCallingConvention(Type type, Kind returnKind, Kind[] parameters, TargetDescription target, boolean stackOnly);
 
     /**
      * Gets the ordered set of registers that are can be used to pass parameters
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Oct 01 16:12:45 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Oct 01 21:37:20 2012 +0200
@@ -446,11 +446,11 @@
     }
 
     protected void emitPrologue() {
-        CallingConvention incomingArguments = frameMap.registerConfig.getCallingConvention(JavaCallee, MetaUtil.signatureToKinds(method), target, false);
+        CallingConvention incomingArguments = frameMap.registerConfig.getCallingConvention(JavaCallee, method.signature().returnKind(), MetaUtil.signatureToKinds(method), target, false);
 
-        Value[] params = new Value[incomingArguments.locations.length];
+        Value[] params = new Value[incomingArguments.getArgumentCount()];
         for (int i = 0; i < params.length; i++) {
-            params[i] = toStackKind(incomingArguments.locations[i]);
+            params[i] = toStackKind(incomingArguments.getArgument(i));
             if (ValueUtil.isStackSlot(params[i])) {
                 StackSlot slot = ValueUtil.asStackSlot(params[i]);
                 if (slot.inCallerFrame() && !lir.hasArgInCallerFrame()) {
@@ -695,7 +695,7 @@
     public void emitInvoke(Invoke x) {
         AbstractCallTargetNode callTarget = (AbstractCallTargetNode) x.callTarget();
         Kind[] signature = callTarget.signature();
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), signature, target(), false);
+        CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.node().kind(), signature, target(), false);
         frameMap.callsMethod(cc, callTarget.callType());
 
         List<Value> argList = visitInvokeArguments(cc, callTarget.arguments());
@@ -706,7 +706,7 @@
             callState = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId());
         }
 
-        Value result = resultOperandFor(x.node().kind());
+        Value result = cc.getReturn();
 
         if (callTarget instanceof DirectCallTargetNode) {
             emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, callState);
@@ -747,7 +747,7 @@
         int j = 0;
         for (ValueNode arg : arguments) {
             if (arg != null) {
-                Value operand = toStackKind(cc.locations[j++]);
+                Value operand = toStackKind(cc.getArgument(j++));
                 emitMove(operand(arg), operand);
                 argList.add(operand);
 
@@ -765,30 +765,23 @@
     public Variable emitCall(@SuppressWarnings("hiding") Object target, Kind result, Kind[] arguments, boolean canTrap, Value... args) {
         LIRFrameState info = canTrap ? state() : null;
 
-        Value physReg = resultOperandFor(result);
+        // move the arguments into the correct location
+        CallingConvention cc = frameMap.registerConfig.getCallingConvention(RuntimeCall, result, arguments, target(), false);
+        frameMap.callsMethod(cc, RuntimeCall);
+        assert cc.getArgumentCount() == args.length : "argument count mismatch";
+        Value[] argLocations = new Value[args.length];
+        for (int i = 0; i < args.length; i++) {
+            Value arg = args[i];
+            Value loc = cc.getArgument(i);
+            emitMove(arg, loc);
+            argLocations[i] = loc;
+        }
+        List<Value> argumentList = Arrays.asList(argLocations);
 
-        List<Value> argumentList;
-        if (arguments.length > 0) {
-            // move the arguments into the correct location
-            CallingConvention cc = frameMap.registerConfig.getCallingConvention(RuntimeCall, arguments, target(), false);
-            frameMap.callsMethod(cc, RuntimeCall);
-            assert cc.locations.length == args.length : "argument count mismatch";
-            for (int i = 0; i < args.length; i++) {
-                Value arg = args[i];
-                Value loc = cc.locations[i];
-                emitMove(arg, loc);
-            }
-            argumentList = Arrays.asList(cc.locations);
-        } else {
-            // no arguments
-            assert args == null || args.length == 0;
-            argumentList = Collections.emptyList();
-        }
+        emitCall(target, cc.getReturn(), argumentList, Constant.forLong(0), info, null);
 
-        emitCall(target, physReg, argumentList, Constant.forLong(0), info, null);
-
-        if (isLegal(physReg)) {
-            return emitMove(physReg);
+        if (isLegal(cc.getReturn())) {
+            return emitMove(cc.getReturn());
         } else {
             return null;
         }
@@ -796,9 +789,9 @@
 
     @Override
     public void emitRuntimeCall(RuntimeCallNode x) {
-        Value resultOperand = resultOperandFor(x.kind());
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(RuntimeCall, x.call().getArgumentKinds(), target(), false);
+        CallingConvention cc = frameMap.registerConfig.getCallingConvention(RuntimeCall, x.kind(), x.call().getArgumentKinds(), target(), false);
         frameMap.callsMethod(cc, RuntimeCall);
+        Value resultOperand = cc.getReturn();
         List<Value> argList = visitInvokeArguments(cc, x.arguments());
 
         LIRFrameState info = null;
@@ -960,32 +953,24 @@
 
     protected final Value callRuntime(RuntimeCall runtimeCall, LIRFrameState info, Value... args) {
         // get a result register
-        Kind result = runtimeCall.getResultKind();
         Kind[] arguments = runtimeCall.getArgumentKinds();
 
-        Value physReg = result.isVoid() ? IllegalValue : resultOperandFor(result);
+        // move the arguments into the correct location
+        CallingConvention cc = frameMap.registerConfig.getCallingConvention(RuntimeCall, runtimeCall.getResultKind(), arguments, target(), false);
+        frameMap.callsMethod(cc, RuntimeCall);
+        assert cc.getArgumentCount() == args.length : "argument count mismatch";
+        Value[] argLocations = new Value[args.length];
+        for (int i = 0; i < args.length; i++) {
+            Value arg = args[i];
+            Value loc = cc.getArgument(i);
+            emitMove(arg, loc);
+            argLocations[i] = loc;
+        }
+        List<Value> argumentList = Arrays.asList(argLocations);
 
-        List<Value> argumentList;
-        if (arguments.length > 0) {
-            // move the arguments into the correct location
-            CallingConvention cc = frameMap.registerConfig.getCallingConvention(RuntimeCall, arguments, target(), false);
-            frameMap.callsMethod(cc, RuntimeCall);
-            assert cc.locations.length == args.length : "argument count mismatch";
-            for (int i = 0; i < args.length; i++) {
-                Value arg = args[i];
-                Value loc = cc.locations[i];
-                emitMove(arg, loc);
-            }
-            argumentList = Arrays.asList(cc.locations);
-        } else {
-            // no arguments
-            assert args == null || args.length == 0;
-            argumentList = Util.uncheckedCast(Collections.emptyList());
-        }
+        emitCall(runtimeCall, cc.getReturn(), argumentList, Constant.forLong(0), info, null);
 
-        emitCall(runtimeCall, physReg, argumentList, Constant.forLong(0), info, null);
-
-        return physReg;
+        return cc.getReturn();
     }
 
     protected final Variable callRuntimeWithResult(RuntimeCall runtimeCall, LIRFrameState info, Value... args) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRegisterConfig.java	Mon Oct 01 16:12:45 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRegisterConfig.java	Mon Oct 01 21:37:20 2012 +0200
@@ -108,18 +108,18 @@
     }
 
     @Override
-    public CallingConvention getCallingConvention(Type type, Kind[] parameters, TargetDescription target, boolean stackOnly) {
+    public CallingConvention getCallingConvention(Type type, Kind returnKind, Kind[] parameters, TargetDescription target, boolean stackOnly) {
         if (type == Type.NativeCall) {
             throw new UnsupportedOperationException();
         }
-        return callingConvention(parameters, type, target, stackOnly);
+        return callingConvention(returnKind, parameters, type, target, stackOnly);
     }
 
     public Register[] getCallingConventionRegisters(Type type, RegisterFlag flag) {
         return allParameterRegisters;
     }
 
-    private CallingConvention callingConvention(Kind[] kinds, Type type, TargetDescription target, boolean stackOnly) {
+    private CallingConvention callingConvention(Kind returnKind, Kind[] kinds, Type type, TargetDescription target, boolean stackOnly) {
         Value[] locations = new Value[kinds.length];
 
         int currentGeneral = 0;
@@ -159,7 +159,8 @@
             }
         }
 
-        return new CallingConvention(locations, currentStackOffset);
+        Value returnLocation = returnKind.isVoid() ? Value.IllegalValue : getReturnRegister(returnKind).asValue(returnKind);
+        return new CallingConvention(currentStackOffset, returnLocation, locations);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Mon Oct 01 16:12:45 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Mon Oct 01 21:37:20 2012 +0200
@@ -62,10 +62,10 @@
         boolean isStatic = Modifier.isStatic(method.accessFlags());
 
         Kind[] signature = MetaUtil.signatureToKinds(method.signature(), isStatic ? null : method.holder().kind());
-        CallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, signature, gen.target(), false);
+        CallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, Kind.Void, signature, gen.target(), false);
         gen.frameMap().callsMethod(cc, CallingConvention.Type.JavaCall); // TODO (aw): I think this is unnecessary for a tail call.
         List<ValueNode> parameters = new ArrayList<>();
-        for (int i = 0, slot = 0; i < cc.locations.length; i++, slot += FrameStateBuilder.stackSlots(frameState.localAt(slot).kind())) {
+        for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += FrameStateBuilder.stackSlots(frameState.localAt(slot).kind())) {
             parameters.add(frameState.localAt(slot));
         }
         List<Value> argList = gen.visitInvokeArguments(cc, parameters);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Mon Oct 01 16:12:45 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Mon Oct 01 21:37:20 2012 +0200
@@ -84,7 +84,7 @@
                 sig[pos++] = arg.kind();
             }
 
-            CallingConvention cc = frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, sig, target(), false);
+            CallingConvention cc = frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, Kind.Void, sig, target(), false);
             List<Value> argList = visitInvokeArguments(cc, i.arguments);
             Value[] parameters = argList.toArray(new Value[argList.size()]);
             append(new AMD64BreakpointOp(parameters));
@@ -221,9 +221,9 @@
         boolean isStatic = Modifier.isStatic(method.accessFlags());
         if (!isStatic) {
             tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY);
-            CallingConvention cc = regConfig.getCallingConvention(JavaCallee, new Kind[] {Kind.Object}, target, false);
+            CallingConvention cc = regConfig.getCallingConvention(JavaCallee, Kind.Void, new Kind[] {Kind.Object}, target, false);
             Register inlineCacheKlass = rax; // see definition of IC_Klass in c1_LIRAssembler_x86.cpp
-            Register receiver = asRegister(cc.locations[0]);
+            Register receiver = asRegister(cc.getArgument(0));
             Address src = new Address(target.wordKind, receiver.asValue(), config.hubOffset);
 
             asm.cmpq(inlineCacheKlass, src);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Mon Oct 01 16:12:45 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Mon Oct 01 21:37:20 2012 +0200
@@ -229,7 +229,7 @@
     public void callsMethod(CallingConvention cc, Type type) {
         // TODO look at the actual stack offsets?
         assert type.out;
-        reserveOutgoing(cc.stackSize);
+        reserveOutgoing(cc.getStackSize());
     }
 
     /**