package com.oracle.svm.hosted.code;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.nativeimage.c.function.InvokeCFunctionPointer;
import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.graal.pointsto.meta.HostedProviders;
import com.oracle.svm.core.thread.VMThreads.StatusSupport;
import com.oracle.svm.hosted.c.NativeLibraries;
import com.oracle.svm.hosted.phases.HostedGraphKit;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Signature;
public final class CFunctionPointerCallStubMethod extends CCallStubMethod {
static CFunctionPointerCallStubMethod create(AnalysisMethod aMethod) {
assert !aMethod.isSynthetic() : "Creating a stub for a stub? " + aMethod;
ResolvedJavaMethod method = aMethod.getWrapped();
int newThreadStatus = StatusSupport.getNewThreadStatus(aMethod.getAnnotation(InvokeCFunctionPointer.class).transition());
return new CFunctionPointerCallStubMethod(method, newThreadStatus);
}
private CFunctionPointerCallStubMethod(ResolvedJavaMethod original, int newThreadStatus) {
super(original, newThreadStatus);
}
@Override
public Signature getSignature() {
return new Signature() {
private final Signature wrapped = getOriginal().getSignature();
@Override
public int getParameterCount(boolean receiver) {
return wrapped.getParameterCount(true);
}
@Override
public JavaType getParameterType(int index, ResolvedJavaType accessingClass) {
if (index == 0) {
return getOriginal().getDeclaringClass().resolve(accessingClass);
}
return wrapped.getParameterType(index - 1, accessingClass);
}
@Override
public JavaType getReturnType(ResolvedJavaType accessingClass) {
return wrapped.getReturnType(accessingClass);
}
};
}
@Override
public int getModifiers() {
return (super.getModifiers() & ~(Modifier.ABSTRACT | Modifier.INTERFACE)) | Modifier.STATIC;
}
@Override
public boolean canBeStaticallyBound() {
return true;
}
@Override
protected String getCorrespondingAnnotationName() {
return InvokeCFunctionPointer.class.getSimpleName();
}
@Override
public boolean allowRuntimeCompilation() {
boolean needsTransition = StatusSupport.isValidStatus(newThreadStatus);
return !needsTransition;
}
@Override
public StructuredGraph buildGraph(DebugContext debug, ResolvedJavaMethod method, HostedProviders providers, Purpose purpose) {
assert purpose != Purpose.PREPARE_RUNTIME_COMPILATION || allowRuntimeCompilation();
return super.buildGraph(debug, method, providers, purpose);
}
@Override
protected JavaType[] getParameterTypesForLoad(ResolvedJavaMethod method) {
return method.toParameterTypes();
}
@Override
protected ValueNode createTargetAddressNode(HostedGraphKit kit, HostedProviders providers, List<ValueNode> arguments) {
return arguments.get(0);
}
@Override
protected Signature adaptSignatureAndConvertArguments(HostedProviders providers, NativeLibraries nativeLibraries,
HostedGraphKit kit, ResolvedJavaMethod method, JavaType returnType, JavaType[] paramTypes, List<ValueNode> arguments) {
arguments.remove(0);
JavaType[] paramTypesNoReceiver = Arrays.copyOfRange(paramTypes, 1, paramTypes.length);
return super.adaptSignatureAndConvertArguments(providers, nativeLibraries, kit, method, returnType, paramTypesNoReceiver, arguments);
}
}