Skip to content

Commit

Permalink
Support @CEnum values in CConstant.ValueAccess.
Browse files Browse the repository at this point in the history
  • Loading branch information
christianhaeubl committed Oct 8, 2024
1 parent 51e59c6 commit b2615fb
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 18 deletions.
19 changes: 10 additions & 9 deletions sdk/src/org.graalvm.nativeimage/snapshot.sigtest
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ meth public void printStackTrace(java.io.PrintStream)
meth public void printStackTrace(java.io.PrintWriter)
meth public void setStackTrace(java.lang.StackTraceElement[])
supr java.lang.Object
hfds CAUSE_CAPTION,EMPTY_THROWABLE_ARRAY,NULL_CAUSE_MESSAGE,SELF_SUPPRESSION_MESSAGE,SUPPRESSED_CAPTION,SUPPRESSED_SENTINEL,UNASSIGNED_STACK,backtrace,cause,depth,detailMessage,serialVersionUID,stackTrace,suppressedExceptions
hfds CAUSE_CAPTION,EMPTY_THROWABLE_ARRAY,NULL_CAUSE_MESSAGE,SELF_SUPPRESSION_MESSAGE,SUPPRESSED_CAPTION,SUPPRESSED_SENTINEL,UNASSIGNED_STACK,backtrace,cause,depth,detailMessage,jfrTracing,serialVersionUID,stackTrace,suppressedExceptions
hcls PrintStreamOrWriter,SentinelHolder,WrappedPrintStream,WrappedPrintWriter

CLSS public abstract interface java.lang.annotation.Annotation
Expand Down Expand Up @@ -224,23 +224,23 @@ meth public abstract void fatalError()
meth public abstract void flush()
meth public abstract void log(org.graalvm.nativeimage.c.type.CCharPointer,org.graalvm.word.UnsignedWord)

CLSS public final org.graalvm.nativeimage.MissingReflectionRegistrationError
cons public init(java.lang.String,java.lang.Class<?>,java.lang.Class<?>,java.lang.String,java.lang.Class<?>[])
CLSS public final org.graalvm.nativeimage.MissingJNIRegistrationError
cons public init(java.lang.String,java.lang.Class<?>,java.lang.Class<?>,java.lang.String,java.lang.String)
meth public java.lang.Class<?> getDeclaringClass()
meth public java.lang.Class<?> getElementType()
meth public java.lang.Class<?>[] getParameterTypes()
meth public java.lang.String getElementName()
meth public java.lang.String getSignature()
supr java.lang.Error
hfds declaringClass,elementName,elementType,parameterTypes,serialVersionUID
hfds declaringClass,elementName,elementType,serialVersionUID,signature

CLSS public final org.graalvm.nativeimage.MissingJNIRegistrationError
cons public init(java.lang.String,java.lang.Class<?>,java.lang.Class<?>,java.lang.String,java.lang.String)
CLSS public final org.graalvm.nativeimage.MissingReflectionRegistrationError
cons public init(java.lang.String,java.lang.Class<?>,java.lang.Class<?>,java.lang.String,java.lang.Class<?>[])
meth public java.lang.Class<?> getDeclaringClass()
meth public java.lang.Class<?> getElementType()
meth public java.lang.String getSignature()
meth public java.lang.Class<?>[] getParameterTypes()
meth public java.lang.String getElementName()
supr java.lang.Error
hfds declaringClass,elementName,elementType,signature,serialVersionUID
hfds declaringClass,elementName,elementType,parameterTypes,serialVersionUID

CLSS public abstract interface org.graalvm.nativeimage.ObjectHandle
intf org.graalvm.word.ComparableWord
Expand Down Expand Up @@ -552,6 +552,7 @@ meth public abstract !hasdefault java.lang.String value()
CLSS public final static org.graalvm.nativeimage.c.constant.CConstant$ValueAccess
outer org.graalvm.nativeimage.c.constant.CConstant
meth public static <%0 extends java.lang.Object> {%%0} get(java.lang.Class<?>,java.lang.String,java.lang.Class<{%%0}>)
meth public static <%0 extends java.lang.Object> {%%0} get(java.lang.Enum<?>,java.lang.String)
supr java.lang.Object

CLSS public abstract interface !annotation org.graalvm.nativeimage.c.constant.CEnum
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,11 @@ private ValueAccess() {
* @param declaringClass The class that contains the method.
* @param methodName The name of the method annotated with {@link CConstant}.
* @param returnType The desired type of the returned value. For integer-kind constants, the
* supported types are {@link Long}, {@link Integer}, and {@link Boolean}. For
* floating point constants, the only supported type is {@link Double}. For
* string constants, the only supported type is {@link String}.
* supported types are {@link Boolean}, {@link Byte}, {@link Short},
* {@link Character}, {@link Integer}, and {@link Long}. For floating point
* constants, the supported types are {@link Double} and {@link Float}. For
* string constants, the only supported types are {@link String} and
* {@code byte[]}.
* @return The value of the C constant.
*
* @since 19.0
Expand All @@ -103,5 +105,24 @@ private ValueAccess() {
public static <T> T get(Class<?> declaringClass, String methodName, Class<T> returnType) {
return ImageSingletons.lookup(CConstantValueSupport.class).getCConstantValue(declaringClass, methodName, returnType);
}

/**
* Returns the value of a {@link CEnum}, i.e., the same value that calling the method
* annotated with {@link CEnumValue} would return.
* <p>
* This method is useful during native image generation, when the annotated method cannot be
* called.
*
* @param cEnum The enum value for which the C value should be returned. The enum type must
* be annotated with {@link CEnum}.
* @param methodName The name of the method annotated with {@link CEnumValue}.
* @return The value of the C constant.
*
* @since 24.2
*/
@Platforms(Platform.HOSTED_ONLY.class)
public static <T> T get(Enum<?> cEnum, String methodName) {
return ImageSingletons.lookup(CConstantValueSupport.class).getCEnumValue(cEnum, methodName);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -46,4 +46,6 @@
@Platforms(Platform.HOSTED_ONLY.class)
public interface CConstantValueSupport {
<T> T getCConstantValue(Class<?> declaringClass, String methodName, Class<T> returnType);

<T> T getCEnumValue(Enum<?> cEnum, String methodName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public final byte enumToByte(Enum<?> value) {
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public final int enumToShort(Enum<?> value) {
public final short enumToShort(Enum<?> value) {
return (short) enumToLong(value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,27 @@
*/
package com.oracle.svm.hosted.c;

import java.lang.annotation.Annotation;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.c.constant.CConstant;
import org.graalvm.nativeimage.c.constant.CEnum;
import org.graalvm.nativeimage.c.constant.CEnumValue;
import org.graalvm.nativeimage.impl.CConstantValueSupport;

import com.oracle.svm.core.c.enums.CEnumRuntimeData;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.c.info.ConstantInfo;
import com.oracle.svm.hosted.c.info.EnumInfo;
import com.oracle.svm.hosted.phases.CInterfaceInvocationPlugin;
import com.oracle.svm.util.ClassUtil;
import com.oracle.svm.util.ReflectionUtil;

import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;

@Platforms(Platform.HOSTED_ONLY.class)
public final class CConstantValueSupportImpl implements CConstantValueSupport {
Expand All @@ -50,7 +59,7 @@ public CConstantValueSupportImpl(NativeLibraries nativeLibraries) {
@Override
@SuppressWarnings("unchecked")
public <T> T getCConstantValue(Class<?> declaringClass, String methodName, Class<T> returnType) {
ResolvedJavaMethod method = getAnnotatedMethod(declaringClass, methodName);
ResolvedJavaMethod method = getAnnotatedMethod(declaringClass, methodName, CConstant.class);
ConstantInfo constantInfo = (ConstantInfo) nativeLibraries.findElementInfo(method);
Object value = constantInfo.getValue();

Expand All @@ -72,16 +81,56 @@ public <T> T getCConstantValue(Class<?> declaringClass, String methodName, Class
}
}

private ResolvedJavaMethod getAnnotatedMethod(Class<?> declaringClass, String methodName) {
@Override
@SuppressWarnings("unchecked")
public <T> T getCEnumValue(Enum<?> cEnum, String methodName) {
Class<?> declaringType = cEnum.getDeclaringClass();
if (declaringType.getAnnotation(CEnum.class) == null) {
throw VMError.shouldNotReachHere("Type " + declaringType + " is not annotated with @" + ClassUtil.getUnqualifiedName(CEnum.class));
}

ResolvedJavaMethod method = getAnnotatedMethod(declaringType, methodName, CEnumValue.class);
ResolvedJavaType enumType = metaAccess.lookupJavaType(declaringType);
EnumInfo enumInfo = (EnumInfo) nativeLibraries.findElementInfo(enumType);

ResolvedJavaType returnType = (ResolvedJavaType) method.getSignature().getReturnType(method.getDeclaringClass());
return (T) getCEnumValue(cEnum, returnType, enumInfo.getRuntimeData());
}

private Object getCEnumValue(Enum<?> cEnum, ResolvedJavaType returnType, CEnumRuntimeData data) {
if (!nativeLibraries.isIntegerType(returnType)) {
throw VMError.shouldNotReachHere("Unsupported return type: " + returnType);
}

if (nativeLibraries.isWordBase(returnType)) {
if (nativeLibraries.isSigned(returnType)) {
return data.enumToSignedWord(cEnum);
}
return data.enumToUnsignedWord(cEnum);
}

JavaKind returnKind = returnType.getJavaKind();
return switch (returnKind) {
case Boolean -> data.enumToBoolean(cEnum);
case Byte -> data.enumToByte(cEnum);
case Short -> data.enumToShort(cEnum);
case Char -> data.enumToChar(cEnum);
case Int -> data.enumToInt(cEnum);
case Long -> data.enumToLong(cEnum);
default -> throw VMError.shouldNotReachHere("Unsupported return type: " + returnType);
};
}

private ResolvedJavaMethod getAnnotatedMethod(Class<?> declaringClass, String methodName, Class<? extends Annotation> annotationClass) {
ResolvedJavaMethod method;
try {
method = metaAccess.lookupJavaMethod(ReflectionUtil.lookupMethod(declaringClass, methodName));
} catch (ReflectionUtil.ReflectionUtilError e) {
throw VMError.shouldNotReachHere("Method not found: " + declaringClass.getName() + "." + methodName);
}

if (method.getAnnotation(CConstant.class) == null) {
throw VMError.shouldNotReachHere("Method " + declaringClass.getName() + "." + methodName + " is not annotated with @" + CConstant.class.getSimpleName());
if (method.getAnnotation(annotationClass) == null) {
throw VMError.shouldNotReachHere("Method " + declaringClass.getName() + "." + methodName + " is not annotated with @" + ClassUtil.getUnqualifiedName(annotationClass));
}
return method;
}
Expand Down

0 comments on commit b2615fb

Please sign in to comment.