# HG changeset patch # User Doug Simon # Date 1349120240 -7200 # Node ID b1010f7bc0bf4898d8517a1d62f47c15f896edf4 # Parent ec22112544197bcdb125bc45ef358444e8b5905a expanded CallingConvention API class to also include the location of the value (if any) returned by a call diff -r ec2211254419 -r b1010f7bc0bf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java --- 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; diff -r ec2211254419 -r b1010f7bc0bf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java --- 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 diff -r ec2211254419 -r b1010f7bc0bf 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 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 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 argumentList = Arrays.asList(argLocations); - List 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 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 argumentList = Arrays.asList(argLocations); - List 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) { diff -r ec2211254419 -r b1010f7bc0bf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRegisterConfig.java --- 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 diff -r ec2211254419 -r b1010f7bc0bf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java --- 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 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 argList = gen.visitInvokeArguments(cc, parameters); diff -r ec2211254419 -r b1010f7bc0bf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java --- 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 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); diff -r ec2211254419 -r b1010f7bc0bf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java --- 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()); } /**