Search in sources :

Example 1 with SubstrateCallingConvention

use of com.oracle.svm.core.graal.code.SubstrateCallingConvention in project graal by oracle.

the class SubstrateAArch64RegisterConfig method getCallingConvention.

@Override
public CallingConvention getCallingConvention(Type t, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory) {
    SubstrateCallingConventionType type = (SubstrateCallingConventionType) t;
    boolean isEntryPoint = type.nativeABI() && !type.outgoing;
    AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
    int currentGeneral = 0;
    int currentFP = 0;
    /*
         * We have to reserve a slot between return address and outgoing parameters for the deopt
         * frame handle. Exception: calls to native methods.
         */
    int currentStackOffset = (type.nativeABI() ? nativeParamsStackOffset : target.wordSize);
    JavaKind[] kinds = new JavaKind[locations.length];
    for (int i = 0; i < parameterTypes.length; i++) {
        JavaKind kind = ObjectLayout.getCallSignatureKind(isEntryPoint, (ResolvedJavaType) parameterTypes[i], metaAccess, target);
        kinds[i] = kind;
        Register register = null;
        if (type.kind == SubstrateCallingConventionKind.ForwardReturnValue) {
            VMError.guarantee(i == 0, "Method with calling convention ForwardReturnValue cannot have more than one parameter");
            register = getReturnRegister(kind);
        } else {
            switch(kind) {
                case Byte:
                case Boolean:
                case Short:
                case Char:
                case Int:
                case Long:
                case Object:
                    if (currentGeneral < generalParameterRegs.size()) {
                        register = generalParameterRegs.get(currentGeneral++);
                    }
                    break;
                case Float:
                case Double:
                    if (currentFP < fpParameterRegs.size()) {
                        register = fpParameterRegs.get(currentFP++);
                    }
                    break;
                default:
                    throw shouldNotReachHere();
            }
        }
        if (register != null) {
            /*
                 * The AArch64 procedure call standard does not require subword (i.e., boolean,
                 * byte, char, short) values to be extended to 32 bits. Hence, for incoming native
                 * calls, we can only assume the bits sizes as specified in the standard.
                 *
                 * Since within the graal compiler subwords are already extended to 32 bits, we save
                 * extended values in outgoing calls.
                 *
                 * Darwin deviates from the call standard and requires the caller to extend subword
                 * values.
                 */
            boolean useJavaKind = isEntryPoint && (Platform.includedIn(Platform.LINUX.class) || Platform.includedIn(Platform.WINDOWS.class));
            locations[i] = register.asValue(valueKindFactory.getValueKind(useJavaKind ? kind : kind.getStackKind()));
        } else {
            if (type.nativeABI()) {
                if (Platform.includedIn(Platform.LINUX.class)) {
                    currentStackOffset = linuxNativeStackParameterAssignment(valueKindFactory, locations, i, kind, currentStackOffset, type.outgoing);
                } else if (Platform.includedIn(Platform.DARWIN.class)) {
                    currentStackOffset = darwinNativeStackParameterAssignment(valueKindFactory, locations, i, kind, currentStackOffset, type.outgoing);
                } else {
                    throw VMError.shouldNotReachHere();
                }
            } else {
                currentStackOffset = javaStackParameterAssignment(valueKindFactory, locations, i, kind, currentStackOffset, type.outgoing);
            }
        }
    }
    JavaKind returnKind = returnType == null ? JavaKind.Void : ObjectLayout.getCallSignatureKind(isEntryPoint, (ResolvedJavaType) returnType, metaAccess, target);
    AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
    return new SubstrateCallingConvention(type, kinds, currentStackOffset, returnLocation, locations);
}
Also used : Platform(org.graalvm.nativeimage.Platform) AllocatableValue(jdk.vm.ci.meta.AllocatableValue) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) Register(jdk.vm.ci.code.Register) SubstrateCallingConventionType(com.oracle.svm.core.graal.code.SubstrateCallingConventionType) SubstrateCallingConvention(com.oracle.svm.core.graal.code.SubstrateCallingConvention) JavaKind(jdk.vm.ci.meta.JavaKind)

Example 2 with SubstrateCallingConvention

use of com.oracle.svm.core.graal.code.SubstrateCallingConvention in project graal by oracle.

the class LLVMGenerator method emitForeignCall.

public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, LLVMBasicBlockRef successor, LLVMBasicBlockRef handler, Value... arguments) {
    ResolvedJavaMethod targetMethod = ((SnippetRuntime.SubstrateForeignCallDescriptor) linkage.getDescriptor()).findMethod(getMetaAccess());
    DebugInfo debugInfo = null;
    if (state != null) {
        state.initDebugInfo(null, false);
        debugInfo = state.debugInfo();
    }
    long patchpointId = nextPatchpointId.getAndIncrement();
    compilationResult.recordCall(NumUtil.safeToInt(patchpointId), 0, targetMethod, debugInfo, true);
    LLVMValueRef callee = getFunction(targetMethod);
    LLVMValueRef[] args = Arrays.stream(arguments).map(LLVMUtils::getVal).toArray(LLVMValueRef[]::new);
    CallingConvention.Type callType = ((SubstrateCallingConvention) linkage.getOutgoingCallingConvention()).getType();
    LLVMValueRef[] callArguments = getCallArguments(args, callType);
    LLVMValueRef call;
    boolean nativeABI = ((SubstrateCallingConventionType) callType).nativeABI();
    if (successor == null && handler == null) {
        call = buildStatepointCall(callee, nativeABI, patchpointId, callArguments);
    } else {
        assert successor != null && handler != null;
        call = buildStatepointInvoke(callee, nativeABI, successor, handler, patchpointId, callArguments);
    }
    return (isVoidReturnType(getLLVMFunctionReturnType(targetMethod, false))) ? null : new LLVMVariable(call);
}
Also used : SubstrateCallingConvention(com.oracle.svm.core.graal.code.SubstrateCallingConvention) CallingConvention(jdk.vm.ci.code.CallingConvention) LLVMVariable(com.oracle.svm.core.graal.llvm.util.LLVMUtils.LLVMVariable) SubstrateCallingConventionType(com.oracle.svm.core.graal.code.SubstrateCallingConventionType) LLVMValueRef(com.oracle.svm.shadowed.org.bytedeco.llvm.LLVM.LLVMValueRef) DebugInfo(jdk.vm.ci.code.DebugInfo) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod) SubstrateCallingConvention(com.oracle.svm.core.graal.code.SubstrateCallingConvention)

Example 3 with SubstrateCallingConvention

use of com.oracle.svm.core.graal.code.SubstrateCallingConvention in project graal by oracle.

the class SubstrateAMD64RegisterConfig method getCallingConvention.

@Override
public CallingConvention getCallingConvention(Type t, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory) {
    SubstrateCallingConventionType type = (SubstrateCallingConventionType) t;
    boolean isEntryPoint = type.nativeABI() && !type.outgoing;
    AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
    int currentGeneral = 0;
    int currentXMM = 0;
    /*
         * We have to reserve a slot between return address and outgoing parameters for the deopt
         * frame handle. Exception: calls to native methods.
         */
    int currentStackOffset = (type.nativeABI() ? nativeParamsStackOffset : target.wordSize);
    JavaKind[] kinds = new JavaKind[locations.length];
    for (int i = 0; i < parameterTypes.length; i++) {
        JavaKind kind = ObjectLayout.getCallSignatureKind(isEntryPoint, (ResolvedJavaType) parameterTypes[i], metaAccess, target);
        kinds[i] = kind;
        if (type.nativeABI() && Platform.includedIn(Platform.WINDOWS.class)) {
            // Strictly positional: float parameters consume a general register and vice versa
            currentGeneral = i;
            currentXMM = i;
        }
        Register register = null;
        if (type.kind == SubstrateCallingConventionKind.ForwardReturnValue) {
            VMError.guarantee(i == 0, "Method with calling convention ForwardReturnValue cannot have more than one parameter");
            register = getReturnRegister(kind);
        } else {
            switch(kind) {
                case Byte:
                case Boolean:
                case Short:
                case Char:
                case Int:
                case Long:
                case Object:
                    RegisterArray registers = type.nativeABI() ? nativeGeneralParameterRegs : javaGeneralParameterRegs;
                    if (currentGeneral < registers.size()) {
                        register = registers.get(currentGeneral++);
                    }
                    break;
                case Float:
                case Double:
                    if (currentXMM < xmmParameterRegs.size()) {
                        register = xmmParameterRegs.get(currentXMM++);
                    }
                    break;
                default:
                    throw VMError.shouldNotReachHere();
            }
        }
        /*
             * The AMD64 ABI does not specify whether subword (i.e., boolean, byte, char, short)
             * values should be extended to 32 bits. Hence, for incoming native calls, we can only
             * assume the bits sizes as specified in the standard.
             *
             * Since within the graal compiler subwords are already extended to 32 bits, we save
             * extended values in outgoing calls. Note that some compilers also expect arguments to
             * be extended (https://reviews.llvm.org/rG1db979bae832563efde2523bb36ddabad43293d8).
             */
        ValueKind<?> paramValueKind = valueKindFactory.getValueKind(isEntryPoint ? kind : kind.getStackKind());
        if (register != null) {
            locations[i] = register.asValue(paramValueKind);
        } else {
            locations[i] = StackSlot.get(paramValueKind, currentStackOffset, !type.outgoing);
            currentStackOffset += Math.max(paramValueKind.getPlatformKind().getSizeInBytes(), target.wordSize);
        }
    }
    JavaKind returnKind = returnType == null ? JavaKind.Void : ObjectLayout.getCallSignatureKind(isEntryPoint, (ResolvedJavaType) returnType, metaAccess, target);
    AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
    return new SubstrateCallingConvention(type, kinds, currentStackOffset, returnLocation, locations);
}
Also used : RegisterArray(jdk.vm.ci.code.RegisterArray) AllocatableValue(jdk.vm.ci.meta.AllocatableValue) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) Register(jdk.vm.ci.code.Register) SubstrateCallingConventionType(com.oracle.svm.core.graal.code.SubstrateCallingConventionType) SubstrateCallingConvention(com.oracle.svm.core.graal.code.SubstrateCallingConvention) JavaKind(jdk.vm.ci.meta.JavaKind)

Aggregations

SubstrateCallingConvention (com.oracle.svm.core.graal.code.SubstrateCallingConvention)3 SubstrateCallingConventionType (com.oracle.svm.core.graal.code.SubstrateCallingConventionType)3 Register (jdk.vm.ci.code.Register)2 AllocatableValue (jdk.vm.ci.meta.AllocatableValue)2 JavaKind (jdk.vm.ci.meta.JavaKind)2 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)2 LLVMVariable (com.oracle.svm.core.graal.llvm.util.LLVMUtils.LLVMVariable)1 LLVMValueRef (com.oracle.svm.shadowed.org.bytedeco.llvm.LLVM.LLVMValueRef)1 CallingConvention (jdk.vm.ci.code.CallingConvention)1 DebugInfo (jdk.vm.ci.code.DebugInfo)1 RegisterArray (jdk.vm.ci.code.RegisterArray)1 ResolvedJavaMethod (jdk.vm.ci.meta.ResolvedJavaMethod)1 Platform (org.graalvm.nativeimage.Platform)1