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);
}
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);
}
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);
}
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);
}
Aggregations