use of com.oracle.svm.hosted.c.info.ElementInfo in project graal by oracle.
the class SizeAndSignednessVerifier method visitEnumInfo.
@Override
protected void visitEnumInfo(EnumInfo enumInfo) {
super.visitEnumInfo(enumInfo);
Map<Enum<?>, Long> javaToC = new HashMap<>();
Map<Long, Enum<?>> cToJava = new HashMap<>();
@SuppressWarnings("rawtypes") Class<? extends Enum> enumClass = null;
long minLookupValue = Long.MAX_VALUE;
long maxLookupValue = Long.MIN_VALUE;
for (ElementInfo child : enumInfo.getChildren()) {
if (child instanceof EnumConstantInfo) {
EnumConstantInfo valueInfo = (EnumConstantInfo) child;
long cValue = (Long) valueInfo.getValueInfo().getProperty();
Enum<?> javaValue = valueInfo.getEnumValue();
assert enumClass == null || enumClass == javaValue.getClass();
enumClass = javaValue.getClass();
assert javaToC.get(javaValue) == null;
javaToC.put(javaValue, Long.valueOf(cValue));
if (enumInfo.getNeedsLookup() && valueInfo.getIncludeInLookup()) {
if (cToJava.get(cValue) != null) {
nativeLibs.addError("C value is not unique, so reverse lookup from C to Java is not possible: " + cToJava.get(cValue) + " and " + javaValue + " hava same C value " + cValue, valueInfo.getAnnotatedElement());
}
cToJava.put(cValue, javaValue);
minLookupValue = Math.min(minLookupValue, cValue);
maxLookupValue = Math.max(maxLookupValue, cValue);
}
}
}
long[] javaToCArray = new long[javaToC.size()];
for (Map.Entry<Enum<?>, Long> entry : javaToC.entrySet()) {
int idx = entry.getKey().ordinal();
assert idx >= 0 && idx < javaToCArray.length && javaToCArray[idx] == 0 : "ordinal values are defined as unique and consecutive";
javaToCArray[idx] = entry.getValue();
}
EnumRuntimeData runtimeData;
if (cToJava.size() > 0) {
assert minLookupValue <= maxLookupValue;
long spread = maxLookupValue - minLookupValue;
assert spread >= cToJava.size() - 1;
/*
* We have a choice between an array-based lookup and keeping the HashMap. Since HashMap
* has a quite high memory footprint, an array is more compact even when most array
* elements are null.
*/
if (spread < cToJava.size() * 5L && spread >= 0 && spread < Integer.MAX_VALUE) {
long offset = minLookupValue;
Enum<?>[] cToJavaArray = (Enum[]) Array.newInstance(enumClass, (int) spread + 1);
for (Map.Entry<Long, Enum<?>> entry : cToJava.entrySet()) {
long idx = entry.getKey() - offset;
assert idx >= 0 && idx < cToJavaArray.length;
assert cToJavaArray[(int) idx] == null;
cToJavaArray[(int) idx] = entry.getValue();
}
runtimeData = new EnumArrayLookup(javaToCArray, offset, cToJavaArray);
} else {
runtimeData = new EnumMapLookup(javaToCArray, cToJava);
}
} else {
runtimeData = new EnumNoLookup(javaToCArray);
}
enumInfo.setRuntimeData(runtimeData);
}
use of com.oracle.svm.hosted.c.info.ElementInfo 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.c.info.ElementInfo in project graal by oracle.
the class CFunctionCallStubMethod method adaptReturnValue.
private static ValueNode adaptReturnValue(ResolvedJavaMethod method, HostedProviders providers, NativeLibraries nativeLibraries, HostedGraphKit kit, ValueNode invokeValue) {
ValueNode returnValue = invokeValue;
JavaType declaredReturnType = method.getSignature().getReturnType(null);
if (isPrimitiveOrWord(providers, declaredReturnType)) {
return returnValue;
}
ElementInfo typeInfo = nativeLibraries.findElementInfo(declaredReturnType);
if (typeInfo instanceof EnumInfo) {
UserError.guarantee(typeInfo.getChildren().stream().anyMatch(EnumValueInfo.class::isInstance), "Enum class " + declaredReturnType.toJavaName() + " needs a method that is annotated with @" + CEnumLookup.class + " because it is used as the return type of a method annotated with @" + CFunction.class.getSimpleName() + ": " + method.format("%H.%n(%p)"));
// We take a word return type because checks expect word type replacements, but it is
// narrowed to cEnumKind here.
CInterfaceEnumTool tool = new CInterfaceEnumTool(providers.getMetaAccess(), providers.getSnippetReflection());
returnValue = tool.createEnumLookupInvoke(kit, (ResolvedJavaType) declaredReturnType, (EnumInfo) typeInfo, cEnumKind, returnValue);
} else {
throw UserError.abort("Return types of methods annotated with @" + CFunction.class.getSimpleName() + " are restricted to primitive types, word types and enumerations (@" + CEnum.class.getSimpleName() + "): " + method.format("%H.%n(%p)"));
}
return returnValue;
}
use of com.oracle.svm.hosted.c.info.ElementInfo 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;
}
};
}
use of com.oracle.svm.hosted.c.info.ElementInfo in project graal by oracle.
the class RawStructureLayoutPlanner method visitRawStructureInfo.
@Override
protected void visitRawStructureInfo(RawStructureInfo info) {
if (info.isPlanned()) {
return;
}
ResolvedJavaType type = (ResolvedJavaType) info.getAnnotatedElement();
for (ResolvedJavaType t : type.getInterfaces()) {
if (!nativeLibs.isPointerBase(t)) {
throw UserError.abort("Type " + type + " must not implement " + t);
}
if (t.equals(nativeLibs.getPointerBaseType())) {
continue;
}
ElementInfo einfo = nativeLibs.findElementInfo(t);
if (!(einfo instanceof RawStructureInfo)) {
throw UserError.abort(new CInterfaceError("Illegal super type " + t + " found", type).getMessage());
}
RawStructureInfo rinfo = (RawStructureInfo) einfo;
rinfo.accept(this);
assert rinfo.isPlanned();
if (info.getParentInfo() != null) {
throw UserError.abort(new CInterfaceError("Only single inheritance of RawStructure types is supported", type).getMessage());
}
info.setParentInfo(rinfo);
}
for (ElementInfo child : new ArrayList<>(info.getChildren())) {
if (child instanceof StructFieldInfo) {
StructFieldInfo fieldInfo = (StructFieldInfo) child;
StructFieldInfo parentFieldInfo = findParentFieldInfo(fieldInfo, info.getParentInfo());
if (parentFieldInfo != null) {
fieldInfo.mergeChildrenAndDelete(parentFieldInfo);
} else {
computeSize(fieldInfo);
}
}
}
planLayout(info);
}
Aggregations