diff --git a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest index 76d53efedfd7..95f7d6e73bc7 100644 --- a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest +++ b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest @@ -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 @@ -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 @@ -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 diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/c/constant/CConstant.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/c/constant/CConstant.java index 7c54c0645e85..299c7862aac8 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/c/constant/CConstant.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/c/constant/CConstant.java @@ -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 @@ -103,5 +105,24 @@ private ValueAccess() { public static T get(Class declaringClass, String methodName, Class 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. + *

+ * 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 get(Enum cEnum, String methodName) { + return ImageSingletons.lookup(CConstantValueSupport.class).getCEnumValue(cEnum, methodName); + } } } diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/CConstantValueSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/CConstantValueSupport.java index 69842b3f9ba3..8c228ca83e20 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/CConstantValueSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/CConstantValueSupport.java @@ -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 @@ -46,4 +46,6 @@ @Platforms(Platform.HOSTED_ONLY.class) public interface CConstantValueSupport { T getCConstantValue(Class declaringClass, String methodName, Class returnType); + + T getCEnumValue(Enum cEnum, String methodName); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/enums/CEnumRuntimeData.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/enums/CEnumRuntimeData.java index f13120e72fe5..5be2efeaedf5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/enums/CEnumRuntimeData.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/enums/CEnumRuntimeData.java @@ -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); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java index cb9d180cc2ed..e7412ebccbc9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java @@ -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 { @@ -50,7 +59,7 @@ public CConstantValueSupportImpl(NativeLibraries nativeLibraries) { @Override @SuppressWarnings("unchecked") public T getCConstantValue(Class declaringClass, String methodName, Class returnType) { - ResolvedJavaMethod method = getAnnotatedMethod(declaringClass, methodName); + ResolvedJavaMethod method = getAnnotatedMethod(declaringClass, methodName, CConstant.class); ConstantInfo constantInfo = (ConstantInfo) nativeLibraries.findElementInfo(method); Object value = constantInfo.getValue(); @@ -72,7 +81,47 @@ public T getCConstantValue(Class declaringClass, String methodName, Class } } - private ResolvedJavaMethod getAnnotatedMethod(Class declaringClass, String methodName) { + @Override + @SuppressWarnings("unchecked") + public 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 annotationClass) { ResolvedJavaMethod method; try { method = metaAccess.lookupJavaMethod(ReflectionUtil.lookupMethod(declaringClass, methodName)); @@ -80,8 +129,8 @@ private ResolvedJavaMethod getAnnotatedMethod(Class declaringClass, String me 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; }