package com.oracle.truffle.llvm.runtime.interop.convert;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.llvm.runtime.interop.LLVMInternalTruffleObject;
import com.oracle.truffle.llvm.runtime.interop.LLVMTypedForeignObject;
import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType;
import com.oracle.truffle.llvm.runtime.interop.convert.ToPointer.Dummy;
import com.oracle.truffle.llvm.runtime.interop.convert.ToPointer.InteropTypeNode;
import com.oracle.truffle.llvm.runtime.library.internal.LLVMAsForeignLibrary;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode;
import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer;
import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer;
import com.oracle.truffle.llvm.spi.NativeTypeLibrary;
@NodeChild(type = Dummy.class)
@NodeChild(type = InteropTypeNode.class)
public abstract class ToPointer extends ForeignToLLVM {
public static ToPointer create() {
return ToPointerNodeGen.create(null, new InteropTypeNode(null));
}
public static ToPointer create(LLVMInteropType.Structured type) {
return ToPointerNodeGen.create(null, new InteropTypeNode(type));
}
abstract static class Dummy extends LLVMNode {
protected abstract Object execute();
}
static final class InteropTypeNode extends LLVMNode {
private final LLVMInteropType.Structured type;
private InteropTypeNode(LLVMInteropType.Structured type) {
this.type = type;
}
public LLVMInteropType.Structured execute() {
return type;
}
}
@Specialization
protected LLVMManagedPointer fromInt(int value, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return LLVMManagedPointer.create(value);
}
@Specialization
protected LLVMManagedPointer fromChar(char value, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return LLVMManagedPointer.create(value);
}
@Specialization
protected LLVMManagedPointer fromLong(long value, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return LLVMManagedPointer.create(value);
}
@Specialization
protected LLVMManagedPointer fromByte(byte value, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return LLVMManagedPointer.create(value);
}
@Specialization
protected LLVMManagedPointer fromShort(short value, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return LLVMManagedPointer.create(value);
}
@Specialization
protected LLVMManagedPointer fromFloat(float value, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return LLVMManagedPointer.create(value);
}
@Specialization
protected LLVMManagedPointer fromDouble(double value, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return LLVMManagedPointer.create(value);
}
@Specialization
protected LLVMManagedPointer fromBoolean(boolean value, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return LLVMManagedPointer.create(value);
}
@Specialization
protected String fromString(String obj, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return obj;
}
@Specialization
protected LLVMPointer fromPointer(LLVMPointer pointer, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return pointer;
}
@Specialization(guards = {"foreigns.isForeign(obj)", "nativeTypes.hasNativeType(obj) || typeFromMethodSignature == null"})
protected LLVMManagedPointer fromTypedTruffleObjectNoAttachedType(Object obj, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature,
@SuppressWarnings("unused") @CachedLibrary(limit = "3") NativeTypeLibrary nativeTypes,
@SuppressWarnings("unused") @CachedLibrary(limit = "3") LLVMAsForeignLibrary foreigns) {
return LLVMManagedPointer.create(obj);
}
@Specialization(guards = {"foreigns.isForeign(obj)", "!nativeTypes.hasNativeType(obj)", "typeFromMethodSignature != null"})
protected LLVMManagedPointer fromNonTypedTruffleObject(Object obj, LLVMInteropType.Structured typeFromMethodSignature,
@SuppressWarnings("unused") @CachedLibrary(limit = "3") NativeTypeLibrary nativeTypes,
@SuppressWarnings("unused") @CachedLibrary(limit = "3") LLVMAsForeignLibrary foreigns) {
return LLVMManagedPointer.create(LLVMTypedForeignObject.create(obj, typeFromMethodSignature));
}
@Specialization
protected LLVMManagedPointer fromInternal(LLVMInternalTruffleObject object, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return LLVMManagedPointer.create(object);
}
@Specialization
protected LLVMInteropType fromInteropType(LLVMInteropType object, @SuppressWarnings("unused") LLVMInteropType.Structured typeFromMethodSignature) {
return object;
}
@TruffleBoundary
static Object slowPathPrimitiveConvert(Object value, LLVMInteropType.Structured typeFromMethodSignature) throws UnsupportedTypeException {
if (value instanceof Number) {
return LLVMManagedPointer.create(value);
} else if (value instanceof Boolean) {
return LLVMManagedPointer.create(value);
} else if (value instanceof Character) {
return LLVMManagedPointer.create(value);
} else if (value instanceof String) {
return value;
} else if (LLVMPointer.isInstance(value)) {
return value;
} else if (value instanceof LLVMInternalTruffleObject) {
return LLVMManagedPointer.create(value);
} else if (LLVMAsForeignLibrary.getFactory().getUncached().isForeign(value)) {
if (typeFromMethodSignature == null || NativeTypeLibrary.getFactory().getUncached().hasNativeType(value)) {
return LLVMManagedPointer.create(value);
} else {
return LLVMManagedPointer.create(LLVMTypedForeignObject.create(value, typeFromMethodSignature));
}
} else if (value instanceof LLVMInteropType) {
return value;
} else {
throw UnsupportedTypeException.create(new Object[]{value});
}
}
}