use of com.oracle.svm.hosted.phases.HostedGraphKit in project graal by oracle.
the class CEntryPointCallStubMethod method adaptReturnValue.
private ValueNode adaptReturnValue(ResolvedJavaMethod method, HostedProviders providers, Purpose purpose, UniverseMetaAccess metaAccess, NativeLibraries nativeLibraries, HostedGraphKit kit, ValueNode invokeValue) {
ValueNode returnValue = invokeValue;
if (returnValue.getStackKind().isPrimitive()) {
return returnValue;
}
JavaType returnType = method.getSignature().getReturnType(null);
ElementInfo typeInfo = nativeLibraries.findElementInfo(returnType);
if (typeInfo instanceof EnumInfo) {
UserError.guarantee(typeInfo.getChildren().stream().anyMatch(EnumValueInfo.class::isInstance), "Enum class " + returnType.toJavaName() + " needs a method that is annotated with @" + CEnumValue.class + " because it is used as the return type of an entry point method: " + targetMethod.format("%H.%n(%p)"));
IsNullNode isNull = kit.unique(new IsNullNode(returnValue));
kit.startIf(isNull, BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY);
kit.thenPart();
ResolvedJavaType enumExceptionType = metaAccess.lookupJavaType(RuntimeException.class);
NewInstanceNode enumException = kit.append(new NewInstanceNode(enumExceptionType, true));
Iterator<ResolvedJavaMethod> enumExceptionCtor = Arrays.stream(enumExceptionType.getDeclaredConstructors()).filter(c -> c.getSignature().getParameterCount(false) == 1 && c.getSignature().getParameterType(0, null).equals(metaAccess.lookupJavaType(String.class))).iterator();
ConstantNode enumExceptionMessage = kit.createConstant(kit.getConstantReflection().forString("null return value cannot be converted to a C enum value"), JavaKind.Object);
kit.createJavaCallWithExceptionAndUnwind(InvokeKind.Special, enumExceptionCtor.next(), enumException, enumExceptionMessage);
assert !enumExceptionCtor.hasNext();
kit.append(new CEntryPointLeaveNode(LeaveAction.ExceptionAbort, enumException));
kit.append(new DeadEndNode());
kit.endIf();
// Always return enum values as a signed word because it should never be a problem if
// the caller expects a narrower integer type and the various checks already handle
// replacements with word types
CInterfaceEnumTool tool = new CInterfaceEnumTool(providers.getMetaAccess(), providers.getSnippetReflection());
JavaKind cEnumReturnType = providers.getWordTypes().getWordKind();
assert !cEnumReturnType.isUnsigned() : "requires correct representation of signed values";
returnValue = tool.createEnumValueInvoke(kit, (EnumInfo) typeInfo, cEnumReturnType, returnValue);
} else if (purpose != Purpose.ANALYSIS) {
// for analysis test cases: abort only during compilation
throw UserError.abort("Entry point method return types are restricted to primitive types, word types and enumerations (@" + CEnum.class.getSimpleName() + "): " + targetMethod.format("%H.%n(%p)"));
}
return returnValue;
}
use of com.oracle.svm.hosted.phases.HostedGraphKit in project graal by oracle.
the class CFunctionCallStubMethod method adaptSignatureAndConvertArguments.
private static Signature adaptSignatureAndConvertArguments(ResolvedJavaMethod method, HostedProviders providers, NativeLibraries nativeLibraries, HostedGraphKit kit, Signature signature, List<ValueNode> arguments) {
MetaAccessProvider metaAccess = providers.getMetaAccess();
JavaType returnType = signature.getReturnType(null);
JavaType[] parameterTypes = signature.toParameterTypes(null);
for (int i = 0; i < parameterTypes.length; i++) {
if (!isPrimitiveOrWord(providers, parameterTypes[i])) {
ElementInfo typeInfo = nativeLibraries.findElementInfo(parameterTypes[i]);
if (typeInfo instanceof EnumInfo) {
UserError.guarantee(typeInfo.getChildren().stream().anyMatch(EnumValueInfo.class::isInstance), "Enum class " + returnType.toJavaName() + " needs a method that is annotated with @" + CEnumValue.class.getSimpleName() + " because it is used as a parameter of a method annotated with @" + CFunction.class.getSimpleName() + ": " + method.format("%H.%n(%p)"));
ValueNode argumentValue = arguments.get(i);
IsNullNode isNull = kit.unique(new IsNullNode(argumentValue));
kit.startIf(isNull, BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY);
kit.thenPart();
ResolvedJavaType enumExceptionType = metaAccess.lookupJavaType(RuntimeException.class);
NewInstanceNode enumException = kit.append(new NewInstanceNode(enumExceptionType, true));
Iterator<ResolvedJavaMethod> enumExceptionCtor = Arrays.stream(enumExceptionType.getDeclaredConstructors()).filter(c -> c.getSignature().getParameterCount(false) == 1 && c.getSignature().getParameterType(0, null).equals(metaAccess.lookupJavaType(String.class))).iterator();
ConstantNode enumExceptionMessage = kit.createConstant(kit.getConstantReflection().forString("null return value cannot be converted to a C enum value"), JavaKind.Object);
kit.createJavaCallWithExceptionAndUnwind(InvokeKind.Special, enumExceptionCtor.next(), enumException, enumExceptionMessage);
assert !enumExceptionCtor.hasNext();
kit.append(new UnwindNode(enumException));
kit.endIf();
CInterfaceEnumTool tool = new CInterfaceEnumTool(metaAccess, providers.getSnippetReflection());
argumentValue = tool.createEnumValueInvoke(kit, (EnumInfo) typeInfo, cEnumKind, argumentValue);
arguments.set(i, argumentValue);
parameterTypes[i] = metaAccess.lookupJavaType(cEnumKind.toJavaClass());
} else {
throw UserError.abort("@" + CFunction.class.getSimpleName() + " parameter types are restricted to primitive types, word types and enumerations (@" + CEnum.class.getSimpleName() + "): " + method.format("%H.%n(%p)"));
}
}
}
if (!isPrimitiveOrWord(providers, returnType)) {
// Assume enum: actual checks and conversion are in adaptReturnValue()
returnType = providers.getWordTypes().getWordImplType();
}
JavaType actualReturnType = returnType;
return new Signature() {
@Override
public int getParameterCount(boolean receiver) {
return parameterTypes.length;
}
@Override
public JavaType getParameterType(int index, ResolvedJavaType accessingClass) {
return parameterTypes[index];
}
@Override
public JavaType getReturnType(ResolvedJavaType accessingClass) {
return actualReturnType;
}
};
}
Aggregations