Search in sources :

Example 1 with SubstrateCallingConventionType

use of com.oracle.svm.core.graal.code.SubstrateCallingConventionType 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 SubstrateCallingConventionType

use of com.oracle.svm.core.graal.code.SubstrateCallingConventionType 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 SubstrateCallingConventionType

use of com.oracle.svm.core.graal.code.SubstrateCallingConventionType 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)

Example 4 with SubstrateCallingConventionType

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

the class NodeLLVMBuilder method emitCall.

private LLVMValueRef emitCall(Invoke invoke, LoweredCallTargetNode callTarget, LLVMValueRef callee, long patchpointId, LLVMValueRef... args) {
    boolean nativeABI = ((SubstrateCallingConventionType) callTarget.callType()).nativeABI();
    if (!SubstrateBackend.hasJavaFrameAnchor(callTarget)) {
        assert SubstrateBackend.getNewThreadStatus(callTarget) == VMThreads.StatusSupport.STATUS_ILLEGAL;
        return emitCallInstruction(invoke, nativeABI, callee, patchpointId, args);
    }
    assert VMThreads.StatusSupport.isValidStatus(SubstrateBackend.getNewThreadStatus(callTarget));
    LLVMValueRef anchor = llvmOperand(SubstrateBackend.getJavaFrameAnchor(callTarget));
    anchor = builder.buildIntToPtr(anchor, builder.rawPointerType());
    LLVMValueRef lastSPAddr = builder.buildGEP(anchor, builder.constantInt(runtimeConfiguration.getJavaFrameAnchorLastSPOffset()));
    Register stackPointer = gen.getRegisterConfig().getFrameRegister();
    builder.buildStore(builder.buildReadRegister(builder.register(stackPointer.name)), builder.buildBitcast(lastSPAddr, builder.pointerType(builder.wordType())));
    if (SubstrateOptions.MultiThreaded.getValue()) {
        LLVMValueRef threadLocalArea = gen.getSpecialRegisterValue(SpecialRegister.ThreadPointer);
        LLVMValueRef statusIndex = builder.constantInt(runtimeConfiguration.getVMThreadStatusOffset());
        LLVMValueRef statusAddress = builder.buildGEP(builder.buildIntToPtr(threadLocalArea, builder.rawPointerType()), statusIndex);
        LLVMValueRef newThreadStatus = builder.constantInt(SubstrateBackend.getNewThreadStatus(callTarget));
        builder.buildVolatileStore(newThreadStatus, builder.buildBitcast(statusAddress, builder.pointerType(builder.intType())), Integer.BYTES);
    }
    LLVMValueRef wrapper = gen.createJNIWrapper(callee, nativeABI, args.length, runtimeConfiguration.getJavaFrameAnchorLastIPOffset());
    LLVMValueRef[] newArgs = new LLVMValueRef[args.length + 2];
    if (!nativeABI) {
        System.arraycopy(args, 0, newArgs, 0, SpecialRegister.count());
        newArgs[SpecialRegister.count() + 0] = anchor;
        newArgs[SpecialRegister.count() + 1] = callee;
        System.arraycopy(args, SpecialRegister.count(), newArgs, 2 + SpecialRegister.count(), args.length - SpecialRegister.count());
    } else {
        newArgs[0] = anchor;
        newArgs[1] = callee;
        System.arraycopy(args, 0, newArgs, 2, args.length);
    }
    return emitCallInstruction(invoke, nativeABI, wrapper, patchpointId, newArgs);
}
Also used : Register(jdk.vm.ci.code.Register) SpecialRegister(com.oracle.svm.core.graal.llvm.LLVMGenerator.SpecialRegister) SubstrateCallingConventionType(com.oracle.svm.core.graal.code.SubstrateCallingConventionType) LLVMValueRef(com.oracle.svm.shadowed.org.bytedeco.llvm.LLVM.LLVMValueRef)

Aggregations

SubstrateCallingConventionType (com.oracle.svm.core.graal.code.SubstrateCallingConventionType)4 SubstrateCallingConvention (com.oracle.svm.core.graal.code.SubstrateCallingConvention)3 Register (jdk.vm.ci.code.Register)3 LLVMValueRef (com.oracle.svm.shadowed.org.bytedeco.llvm.LLVM.LLVMValueRef)2 AllocatableValue (jdk.vm.ci.meta.AllocatableValue)2 JavaKind (jdk.vm.ci.meta.JavaKind)2 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)2 SpecialRegister (com.oracle.svm.core.graal.llvm.LLVMGenerator.SpecialRegister)1 LLVMVariable (com.oracle.svm.core.graal.llvm.util.LLVMUtils.LLVMVariable)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