simd-128 basic support (#3498)

This commit is contained in:
Vladimir Ivanov
2019-11-13 19:16:35 +03:00
committed by GitHub
parent dd19cb76c9
commit 2358edf4e8
43 changed files with 497 additions and 56 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
headers = clang-c/Index.h clang-c/ext.h
headers = clang-c/Index.h clang-c/ext.h clang-c/ExtVector.h
headerFilter = clang-c/**
@@ -1119,3 +1119,6 @@ JNIEXPORT jint JNICALL Java_clang_clang_kniBridge337 (JNIEnv* jniEnv, jclass jcl
JNIEXPORT jint JNICALL Java_clang_clang_kniBridge338 (JNIEnv* jniEnv, jclass jclss, jlong p0) {
return (jint)clang_Cursor_isObjCConsumingSelfMethod(*(CXCursor*)p0);
}
JNIEXPORT jint JNICALL Java_clang_clang_kniBridge339 (JNIEnv* jniEnv, jclass jclss, jlong p0) {
return (jint)clang_isExtVectorType(*(CXType*)p0);
}
@@ -9,7 +9,7 @@ import kotlinx.cinterop.*
@CNaturalStruct("data", "private_flags")
class CXString(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(16, 8)
companion object : CStructVar.Type(16, 8)
var data: COpaquePointer?
get() = memberAt<COpaquePointerVar>(0).value
@@ -23,7 +23,7 @@ class CXString(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("Strings", "Count")
class CXStringSet(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(16, 8)
companion object : CStructVar.Type(16, 8)
var Strings: CPointer<CXString>?
get() = memberAt<CPointerVar<CXString>>(0).value
@@ -45,7 +45,7 @@ class CXTranslationUnitImpl(rawPtr: NativePtr) : COpaque(rawPtr)
@CNaturalStruct("Filename", "Contents", "Length")
class CXUnsavedFile(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
var Filename: CPointer<ByteVar>?
get() = memberAt<CPointerVar<ByteVar>>(0).value
@@ -63,7 +63,7 @@ class CXUnsavedFile(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("Major", "Minor", "Subminor")
class CXVersion(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(12, 4)
companion object : CStructVar.Type(12, 4)
var Major: Int
get() = memberAt<IntVar>(0).value
@@ -81,7 +81,7 @@ class CXVersion(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("data")
class CXFileUniqueID(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
@CLength(3)
val data: CArrayPointer<LongVar>
@@ -91,7 +91,7 @@ class CXFileUniqueID(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("ptr_data", "int_data")
class CXSourceLocation(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
@CLength(2)
val ptr_data: CArrayPointer<COpaquePointerVar>
@@ -105,7 +105,7 @@ class CXSourceLocation(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("ptr_data", "begin_int_data", "end_int_data")
class CXSourceRange(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
@CLength(2)
val ptr_data: CArrayPointer<COpaquePointerVar>
@@ -123,7 +123,7 @@ class CXSourceRange(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("count", "ranges")
class CXSourceRangeList(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(16, 8)
companion object : CStructVar.Type(16, 8)
var count: Int
get() = memberAt<IntVar>(0).value
@@ -137,7 +137,7 @@ class CXSourceRangeList(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("kind", "amount")
class CXTUResourceUsageEntry(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(16, 8)
companion object : CStructVar.Type(16, 8)
var kind: CXTUResourceUsageKind
get() = memberAt<CXTUResourceUsageKind.Var>(0).value
@@ -151,7 +151,7 @@ class CXTUResourceUsageEntry(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("data", "numEntries", "entries")
class CXTUResourceUsage(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
var data: COpaquePointer?
get() = memberAt<COpaquePointerVar>(0).value
@@ -169,7 +169,7 @@ class CXTUResourceUsage(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("kind", "xdata", "data")
class CXCursor(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(32, 8)
companion object : CStructVar.Type(32, 8)
var kind: CXCursorKind
get() = memberAt<CXCursorKind.Var>(0).value
@@ -187,7 +187,7 @@ class CXCursor(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("Platform", "Introduced", "Deprecated", "Obsoleted", "Unavailable", "Message")
class CXPlatformAvailability(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(72, 8)
companion object : CStructVar.Type(72, 8)
val Platform: CXString
get() = memberAt(0)
@@ -214,7 +214,7 @@ class CXCursorSetImpl(rawPtr: NativePtr) : COpaque(rawPtr)
@CNaturalStruct("kind", "data")
class CXType(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
var kind: CXTypeKind
get() = memberAt<CXTypeKind.Var>(0).value
@@ -228,7 +228,7 @@ class CXType(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("int_data", "ptr_data")
class CXToken(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
@CLength(4)
val int_data: CArrayPointer<IntVar>
@@ -242,7 +242,7 @@ class CXToken(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("CursorKind", "CompletionString")
class CXCompletionResult(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(16, 8)
companion object : CStructVar.Type(16, 8)
var CursorKind: CXCursorKind
get() = memberAt<CXCursorKind.Var>(0).value
@@ -256,7 +256,7 @@ class CXCompletionResult(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("Results", "NumResults")
class CXCodeCompleteResults(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(16, 8)
companion object : CStructVar.Type(16, 8)
var Results: CPointer<CXCompletionResult>?
get() = memberAt<CPointerVar<CXCompletionResult>>(0).value
@@ -270,7 +270,7 @@ class CXCodeCompleteResults(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("context", "visit")
class CXCursorAndRangeVisitor(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(16, 8)
companion object : CStructVar.Type(16, 8)
var context: COpaquePointer?
get() = memberAt<COpaquePointerVar>(0).value
@@ -284,7 +284,7 @@ class CXCursorAndRangeVisitor(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("ptr_data", "int_data")
class CXIdxLoc(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
@CLength(2)
val ptr_data: CArrayPointer<COpaquePointerVar>
@@ -298,7 +298,7 @@ class CXIdxLoc(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("hashLoc", "filename", "file", "isImport", "isAngled", "isModuleImport")
class CXIdxIncludedFileInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(56, 8)
companion object : CStructVar.Type(56, 8)
val hashLoc: CXIdxLoc
get() = memberAt(0)
@@ -327,7 +327,7 @@ class CXIdxIncludedFileInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("file", "module", "loc", "isImplicit")
class CXIdxImportedASTFileInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(48, 8)
companion object : CStructVar.Type(48, 8)
var file: CXFile?
get() = memberAt<CXFileVar>(0).value
@@ -348,7 +348,7 @@ class CXIdxImportedASTFileInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("kind", "cursor", "loc")
class CXIdxAttrInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(64, 8)
companion object : CStructVar.Type(64, 8)
var kind: CXIdxAttrKind
get() = memberAt<CXIdxAttrKindVar>(0).value
@@ -364,7 +364,7 @@ class CXIdxAttrInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("kind", "templateKind", "lang", "name", "USR", "cursor", "attributes", "numAttributes")
class CXIdxEntityInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(80, 8)
companion object : CStructVar.Type(80, 8)
var kind: CXIdxEntityKind
get() = memberAt<CXIdxEntityKind.Var>(0).value
@@ -401,7 +401,7 @@ class CXIdxEntityInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("cursor")
class CXIdxContainerInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(32, 8)
companion object : CStructVar.Type(32, 8)
val cursor: CXCursor
get() = memberAt(0)
@@ -410,7 +410,7 @@ class CXIdxContainerInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("attrInfo", "objcClass", "classCursor", "classLoc")
class CXIdxIBOutletCollectionAttrInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(72, 8)
companion object : CStructVar.Type(72, 8)
var attrInfo: CPointer<CXIdxAttrInfo>?
get() = memberAt<CPointerVar<CXIdxAttrInfo>>(0).value
@@ -430,7 +430,7 @@ class CXIdxIBOutletCollectionAttrInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("entityInfo", "cursor", "loc", "semanticContainer", "lexicalContainer", "isRedeclaration", "isDefinition", "isContainer", "declAsContainer", "isImplicit", "attributes", "numAttributes", "flags")
class CXIdxDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(128, 8)
companion object : CStructVar.Type(128, 8)
var entityInfo: CPointer<CXIdxEntityInfo>?
get() = memberAt<CPointerVar<CXIdxEntityInfo>>(0).value
@@ -486,7 +486,7 @@ class CXIdxDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("declInfo", "kind")
class CXIdxObjCContainerDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(16, 8)
companion object : CStructVar.Type(16, 8)
var declInfo: CPointer<CXIdxDeclInfo>?
get() = memberAt<CPointerVar<CXIdxDeclInfo>>(0).value
@@ -500,7 +500,7 @@ class CXIdxObjCContainerDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("base", "cursor", "loc")
class CXIdxBaseClassInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(64, 8)
companion object : CStructVar.Type(64, 8)
var base: CPointer<CXIdxEntityInfo>?
get() = memberAt<CPointerVar<CXIdxEntityInfo>>(0).value
@@ -516,7 +516,7 @@ class CXIdxBaseClassInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("protocol", "cursor", "loc")
class CXIdxObjCProtocolRefInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(64, 8)
companion object : CStructVar.Type(64, 8)
var protocol: CPointer<CXIdxEntityInfo>?
get() = memberAt<CPointerVar<CXIdxEntityInfo>>(0).value
@@ -532,7 +532,7 @@ class CXIdxObjCProtocolRefInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("protocols", "numProtocols")
class CXIdxObjCProtocolRefListInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(16, 8)
companion object : CStructVar.Type(16, 8)
var protocols: CPointer<CPointerVar<CXIdxObjCProtocolRefInfo>>?
get() = memberAt<CPointerVar<CPointerVar<CXIdxObjCProtocolRefInfo>>>(0).value
@@ -546,7 +546,7 @@ class CXIdxObjCProtocolRefListInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("containerInfo", "superInfo", "protocols")
class CXIdxObjCInterfaceDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
var containerInfo: CPointer<CXIdxObjCContainerDeclInfo>?
get() = memberAt<CPointerVar<CXIdxObjCContainerDeclInfo>>(0).value
@@ -564,7 +564,7 @@ class CXIdxObjCInterfaceDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("containerInfo", "objcClass", "classCursor", "classLoc", "protocols")
class CXIdxObjCCategoryDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(80, 8)
companion object : CStructVar.Type(80, 8)
var containerInfo: CPointer<CXIdxObjCContainerDeclInfo>?
get() = memberAt<CPointerVar<CXIdxObjCContainerDeclInfo>>(0).value
@@ -588,7 +588,7 @@ class CXIdxObjCCategoryDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("declInfo", "getter", "setter")
class CXIdxObjCPropertyDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
var declInfo: CPointer<CXIdxDeclInfo>?
get() = memberAt<CPointerVar<CXIdxDeclInfo>>(0).value
@@ -606,7 +606,7 @@ class CXIdxObjCPropertyDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("declInfo", "bases", "numBases")
class CXIdxCXXClassDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(24, 8)
companion object : CStructVar.Type(24, 8)
var declInfo: CPointer<CXIdxDeclInfo>?
get() = memberAt<CPointerVar<CXIdxDeclInfo>>(0).value
@@ -624,7 +624,7 @@ class CXIdxCXXClassDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("kind", "cursor", "loc", "referencedEntity", "parentEntity", "container", "role")
class CXIdxEntityRefInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(96, 8)
companion object : CStructVar.Type(96, 8)
var kind: CXIdxEntityRefKind
get() = memberAt<CXIdxEntityRefKindVar>(0).value
@@ -656,7 +656,7 @@ class CXIdxEntityRefInfo(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("abortQuery", "diagnostic", "enteredMainFile", "ppIncludedFile", "importedASTFile", "startedTranslationUnit", "indexDeclaration", "indexEntityReference")
class IndexerCallbacks(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(64, 8)
companion object : CStructVar.Type(64, 8)
var abortQuery: CPointer<CFunction<(CXClientData?, COpaquePointer?) -> Int>>?
get() = memberAt<CPointerVar<CFunction<(CXClientData?, COpaquePointer?) -> Int>>>(0).value
@@ -694,7 +694,7 @@ class IndexerCallbacks(rawPtr: NativePtr) : CStructVar(rawPtr) {
@CNaturalStruct("typeOpaquePtr")
class CXTypeAttributes(rawPtr: NativePtr) : CStructVar(rawPtr) {
companion object : Type(8, 8)
companion object : CStructVar.Type(8, 8)
var typeOpaquePtr: COpaquePointer?
get() = memberAt<COpaquePointerVar>(0).value
@@ -3838,6 +3838,12 @@ fun clang_Cursor_isObjCConsumingSelfMethod(cursor: CValue<CXCursor>): Int {
}
}
fun clang_isExtVectorType(type: CValue<CXType>): Int {
memScoped {
return kniBridge339(type.getPointer(memScope).rawValue)
}
}
val CINDEX_VERSION_MAJOR: Int get() = 0
val CINDEX_VERSION_MINOR: Int get() = 50
@@ -4723,4 +4729,5 @@ private external fun kniBridge335(p0: NativePtr, p1: Int, p2: NativePtr): Unit
private external fun kniBridge336(p0: NativePtr): Int
private external fun kniBridge337(p0: NativePtr): Int
private external fun kniBridge338(p0: NativePtr): Int
private val loadLibrary = loadKonanLibrary("clangstubs")
private external fun kniBridge339(p0: NativePtr): Int
private val loadLibrary = loadKonanLibrary("clangstubs")
@@ -499,6 +499,43 @@ internal class NativeIndexImpl(val library: NativeLibrary, val verbose: Boolean
spelling = clang_getTypeSpelling(type).convertAndDispose().dropConstQualifier()
)
CXType_Unexposed -> {
// FIXME Remove this cludge for libclang version >= 9 (CINDEX_VERSION > 55)
if (clang_isExtVectorType(type) != 0) {
val size = clang_Type_getSizeOf(type)
if (size == 16L) {
// ExtVector elementType and elementCount are ignored for now but stubs are still needed for
// CXType_Vector compatibility. Incoming clang v9 provide CXType_ExtVector compatible with CXType_Vector
val spelling = "__attribute__((__vector_size__($size))) float"
VectorType(FloatingType(4, "float"), 4, spelling)
} else {
UnsupportedType
}
} else {
UnsupportedType
}
}
CXType_Vector -> {
val elementCXType = clang_getElementType(type)
val elementType = convertType(elementCXType)
val size = clang_Type_getSizeOf(type)
val elemSize = clang_Type_getSizeOf(elementCXType)
val elementCount = clang_getNumElements(type)
assert(size >= elemSize * elementCount && size % elemSize == 0L)
// Spelling example: `__attribute__((__vector_size__(4 * sizeof(float)))) const float`
// Re-generate spelling removing constness and typedefs to limit number of variants for bridge generator
// Supposed to be the same (i.e. natively compatible) as clang_getTypeSpelling(type) aka type.name
val spelling = "__attribute__((__vector_size__($size))) ${clang_getCanonicalType(elementCXType).name}"
if (size == 16L) {
VectorType(elementType, elementCount.toInt(), spelling)
} else {
UnsupportedType
}
}
CXTypeKind.CXType_Bool -> CBoolType
else -> UnsupportedType
@@ -271,6 +271,8 @@ data class IntegerType(val size: Int, val isSigned: Boolean, val spelling: Strin
// TODO: floating type is not actually defined entirely by its size.
data class FloatingType(val size: Int, val spelling: String) : PrimitiveType
data class VectorType(val elementType: Type, val elementCount: Int, val spelling: String) : PrimitiveType
object VoidType : Type
data class RecordType(val decl: StructDecl) : Type
@@ -326,4 +328,4 @@ data class ObjCBlockPointer(
val parameterTypes: List<Type>, val returnType: Type
) : ObjCPointer()
object UnsupportedType : Type
object UnsupportedType : Type
@@ -30,6 +30,12 @@ internal val CValue<CXType>.kind: CXTypeKind get() = this.useContents { kind }
internal val CValue<CXCursor>.kind: CXCursorKind get() = this.useContents { kind }
internal val CValue<CXCursor>.type: CValue<CXType> get() = clang_getCursorType(this)
internal val CValue<CXCursor>.spelling: String get() = clang_getCursorSpelling(this).convertAndDispose()
internal val CValue<CXType>.name: String get() = clang_getTypeSpelling(this).convertAndDispose()
internal val CXTypeKind.spelling: String get() = clang_getTypeKindSpelling(this).convertAndDispose()
internal val CXCursorKind.spelling: String get() = clang_getCursorKindSpelling(this).convertAndDispose()
internal fun CValue<CXString>.convertAndDispose(): String {
try {
return clang_getCString(this)!!.toKString()
@@ -470,4 +470,4 @@ public typealias CArrayPointerVar<T> = CPointerVar<T>
/**
* The C function.
*/
public class CFunction<T : Function<*>>(rawPtr: NativePtr) : CPointed(rawPtr)
public class CFunction<T : Function<*>>(rawPtr: NativePtr) : CPointed(rawPtr)
@@ -53,6 +53,9 @@ internal object nativeMemUtils {
@TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getNativePtr(mem: NativePointed): NativePtr
@TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putNativePtr(mem: NativePointed, value: NativePtr)
@TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getVector(mem: NativePointed): Vector128
@TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putVector(mem: NativePointed, value: Vector128)
// TODO: optimize
fun getByteArray(source: NativePointed, dest: ByteArray, length: Int) {
val sourceArray = source.reinterpret<ByteVar>().ptr
@@ -56,6 +56,14 @@ external fun CPointer<*>.getRawValue(): NativePtr
internal fun CPointer<*>.cPointerToString() = "CPointer(raw=$rawValue)"
public class Vector128VarOf<T : Vector128>(rawPtr: NativePtr) : CVariable(rawPtr)
public typealias Vector128Var = Vector128VarOf<Vector128>
public var <T : Vector128> Vector128VarOf<T>.value: T
get() = nativeMemUtils.getVector(this) as T
set(value) = nativeMemUtils.putVector(this, value)
/**
* Returns a pointer to C function which calls given Kotlin *static* function.
*
@@ -106,4 +114,4 @@ internal fun CPointer<*>.cPointerToString() = "CPointer(raw=$rawValue)"
@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, R> staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) -> R): CPointer<CFunction<(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) -> R>>
@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, R> staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R): CPointer<CFunction<(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R>>
@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, R> staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R): CPointer<CFunction<(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R>>
@@ -187,6 +187,7 @@ object KotlinTypes {
val map by CollectionClassifier
val nativePtr by InteropType
val vector128 by KotlinNativeType
val cOpaque by InteropType
val cOpaquePointer by InteropType
@@ -233,6 +234,7 @@ object KotlinTypes {
private object InteropClassifier : ClassifierAtPackage("kotlinx.cinterop")
private object InteropType : TypeAtPackage("kotlinx.cinterop")
private object KotlinNativeType : TypeAtPackage("kotlin.native")
}
abstract class KotlinFile(
@@ -75,6 +75,10 @@ fun PrimitiveType.getKotlinType(declarationMapper: DeclarationMapper): KotlinCla
else -> TODO(this.toString())
}
is VectorType -> {
/// @todo assert elementType and size here
KotlinTypes.vector128
}
else -> throw NotImplementedError()
}
@@ -373,6 +377,9 @@ fun mirrorPrimitiveType(type: PrimitiveType, declarationMapper: DeclarationMappe
8 -> "DoubleVar"
else -> TODO(type.toString())
}
is VectorType -> {
"Vector128Var"
}
else -> TODO(type.toString())
}
@@ -30,6 +30,7 @@ enum class BridgedType(val kotlinType: KotlinClassifierType, val convertor: Stri
ULONG(KotlinTypes.uLong, "toULong"),
FLOAT(KotlinTypes.float, "toFloat"),
DOUBLE(KotlinTypes.double, "toDouble"),
VECTOR128(KotlinTypes.vector128),
NATIVE_PTR(KotlinTypes.nativePtr),
OBJC_POINTER(KotlinTypes.nativePtr),
VOID(KotlinTypes.unit)
@@ -46,6 +46,7 @@ class SimpleBridgeGeneratorImpl(
BridgedType.ULONG -> "jlong"
BridgedType.FLOAT -> "jfloat"
BridgedType.DOUBLE -> "jdouble"
BridgedType.VECTOR128 -> TODO()
BridgedType.NATIVE_PTR -> "jlong"
BridgedType.OBJC_POINTER -> TODO()
BridgedType.VOID -> "void"
@@ -61,6 +62,7 @@ class SimpleBridgeGeneratorImpl(
BridgedType.ULONG -> "uint64_t"
BridgedType.FLOAT -> "float"
BridgedType.DOUBLE -> "double"
BridgedType.VECTOR128 -> TODO() // "float __attribute__ ((__vector_size__ (16)))"
BridgedType.NATIVE_PTR -> "void*"
BridgedType.OBJC_POINTER -> "id"
BridgedType.VOID -> "void"
@@ -91,7 +91,8 @@ private object PredefinedTypesHandler {
KotlinTypes.boolean,
KotlinTypes.byte, KotlinTypes.short, KotlinTypes.int, KotlinTypes.long,
KotlinTypes.uByte, KotlinTypes.uShort, KotlinTypes.uInt, KotlinTypes.uLong,
KotlinTypes.float, KotlinTypes.double
KotlinTypes.float, KotlinTypes.double,
KotlinTypes.vector128
)
/**
@@ -173,4 +174,4 @@ private object PredefinedTypesHandler {
nativePtrClassifier -> expandNativePtr(platform, nullable)
else -> null
}
}
}
@@ -38,6 +38,7 @@ fun Type.getStringRepresentation(): String = when (this) {
is IntegerType -> this.spelling
is FloatingType -> this.spelling
is VectorType -> this.spelling
is PointerType -> getPointerTypeStringRepresentation(this.pointeeType)
is ArrayType -> getPointerTypeStringRepresentation(this.elemType)
@@ -16,5 +16,5 @@ fun BinaryType<*>.primitiveBinaryTypeOrNull(): PrimitiveBinaryType? = when (this
}
enum class PrimitiveBinaryType {
BOOLEAN, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, POINTER
BOOLEAN, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, POINTER, VECTOR128
}
@@ -846,6 +846,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
output("typedef unsigned long long ${prefix}_KULong;")
output("typedef float ${prefix}_KFloat;")
output("typedef double ${prefix}_KDouble;")
output("typedef float __attribute__ ((__vector_size__ (16))) ${prefix}_KVector128;")
output("typedef void* ${prefix}_KNativePtr;")
output("struct ${prefix}_KType;")
output("typedef struct ${prefix}_KType ${prefix}_KType;")
@@ -1026,6 +1027,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
KonanPrimitiveType.FLOAT -> "${prefix}_KFloat"
KonanPrimitiveType.DOUBLE -> "${prefix}_KDouble"
KonanPrimitiveType.NON_NULL_NATIVE_PTR -> "void*"
KonanPrimitiveType.VECTOR128 -> "${prefix}_KVector128"
}
}
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
@@ -81,7 +82,8 @@ enum class KonanPrimitiveType(val classId: ClassId, val binaryType: BinaryType.P
LONG(PrimitiveType.LONG, PrimitiveBinaryType.LONG),
FLOAT(PrimitiveType.FLOAT, PrimitiveBinaryType.FLOAT),
DOUBLE(PrimitiveType.DOUBLE, PrimitiveBinaryType.DOUBLE),
NON_NULL_NATIVE_PTR(ClassId.topLevel(KonanFqNames.nonNullNativePtr.toSafe()), PrimitiveBinaryType.POINTER)
NON_NULL_NATIVE_PTR(ClassId.topLevel(KonanFqNames.nonNullNativePtr.toSafe()), PrimitiveBinaryType.POINTER),
VECTOR128(ClassId.topLevel(KonanFqNames.Vector128), PrimitiveBinaryType.VECTOR128)
;
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.name.Name
internal const val NATIVE_PTR_NAME = "NativePtr"
internal const val NON_NULL_NATIVE_PTR_NAME = "NonNullNativePtr"
internal const val VECTOR128 = "Vector128"
object KonanFqNames {
val function = FqName("kotlin.Function")
@@ -19,6 +20,7 @@ object KonanFqNames {
val internalPackageName = FqName("kotlin.native.internal")
val nativePtr = internalPackageName.child(Name.identifier(NATIVE_PTR_NAME)).toUnsafe()
val nonNullNativePtr = internalPackageName.child(Name.identifier(NON_NULL_NATIVE_PTR_NAME)).toUnsafe()
val Vector128 = packageName.child(Name.identifier(VECTOR128))
val throws = FqName("kotlin.native.Throws")
val threadLocal = FqName("kotlin.native.concurrent.ThreadLocal")
val sharedImmutable = FqName("kotlin.native.concurrent.SharedImmutable")
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
import org.jetbrains.kotlin.backend.common.ir.simpleFunctions
import org.jetbrains.kotlin.backend.common.lower.at
import org.jetbrains.kotlin.backend.common.lower.irNot
import org.jetbrains.kotlin.backend.konan.KonanFqNames
import org.jetbrains.kotlin.backend.konan.PrimitiveBinaryType
import org.jetbrains.kotlin.backend.konan.RuntimeNames
import org.jetbrains.kotlin.backend.konan.ir.*
@@ -757,6 +758,13 @@ private fun KotlinStubs.mapType(type: IrType, retained: Boolean, variadic: Boole
private fun IrType.isTypeOfNullLiteral(): Boolean = this is IrSimpleType && hasQuestionMark
&& classifier.isClassWithFqName(KotlinBuiltIns.FQ_NAMES.nothing)
private fun IrType.isVector(): Boolean {
if (this is IrSimpleType && !this.hasQuestionMark) {
return classifier.isClassWithFqName(KonanFqNames.Vector128.toUnsafe())
}
return false
}
private fun KotlinStubs.mapType(
type: IrType,
retained: Boolean,
@@ -782,6 +790,8 @@ private fun KotlinStubs.mapType(
type.isUInt() -> UnsignedValuePassing(type, CTypes.int, CTypes.unsignedInt)
type.isULong() -> UnsignedValuePassing(type, CTypes.longLong, CTypes.unsignedLongLong)
type.isVector() -> TrivialValuePassing(type, CTypes.vector128)
type.isCEnumType() -> {
val enumClass = type.getClass()!!
val value = enumClass.declarations
@@ -33,6 +33,8 @@ internal object CTypes {
val C99Bool = simple("_Bool")
val char = simple("char")
val vector128 = simple("float __attribute__ ((__vector_size__ (16)))")
val id = simple("id")
}
@@ -61,4 +63,4 @@ private class FunctionCType(
}
append(')')
})
}
}
@@ -219,6 +219,8 @@ internal class KonanSymbols(
val throwArithmeticException = internalFunction("ThrowArithmeticException")
val throwIndexOutOfBoundsException = internalFunction("ThrowIndexOutOfBoundsException")
override val ThrowNullPointerException = internalFunction("ThrowNullPointerException")
override val ThrowNoWhenBranchMatchedException = internalFunction("ThrowNoWhenBranchMatchedException")
@@ -558,6 +558,10 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
return LLVMBuildLandingPad(builder, landingpadType, personalityFunction, numClauses, name)!!
}
fun extractElement(vector: LLVMValueRef, index: LLVMValueRef, name: String = ""): LLVMValueRef {
return LLVMBuildExtractElement(builder, vector, index, name)!!
}
fun filteringExceptionHandler(codeContext: CodeContext): ExceptionHandler {
val lpBlock = basicBlockInFunction("filteringExceptionHandler", position()?.start)
@@ -23,6 +23,7 @@ private fun RuntimeAware.getLlvmType(primitiveBinaryType: PrimitiveBinaryType?)
PrimitiveBinaryType.FLOAT -> floatType
PrimitiveBinaryType.DOUBLE -> doubleType
PrimitiveBinaryType.VECTOR128 -> vector128Type
PrimitiveBinaryType.POINTER -> int8TypePtr
}
@@ -37,4 +38,4 @@ internal fun RuntimeAware.getLLVMReturnType(type: IrType): LLVMTypeRef {
type.isUnit() || type.isNothing() -> voidType
else -> getLLVMType(type)
}
}
}
@@ -47,6 +47,7 @@ internal enum class IntrinsicType {
UNSIGNED_COMPARE_TO,
NOT,
REINTERPRET,
EXTRACT_ELEMENT,
ARE_EQUAL_BY_VALUE,
IEEE_754_EQUALS,
// OBJC
@@ -130,6 +131,9 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
private val IrCall.llvmReturnType: LLVMTypeRef
get() = LLVMGetReturnType(codegen.getLlvmFunctionType(symbol.owner))!!
private fun LLVMTypeRef.sizeInBits() = LLVMSizeOfTypeInBits(codegen.llvmTargetData, this).toInt()
/**
* Some intrinsics have to be processed before evaluation of their arguments.
* So this method looks at [callSite] and if it is call to "special" intrinsic
@@ -213,6 +217,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
IntrinsicType.UNSIGNED_COMPARE_TO -> emitUnsignedCompareTo(args)
IntrinsicType.NOT -> emitNot(args)
IntrinsicType.REINTERPRET -> emitReinterpret(callSite, args)
IntrinsicType.EXTRACT_ELEMENT -> emitExtractElement(callSite, args)
IntrinsicType.SIGN_EXTEND -> emitSignExtend(callSite, args)
IntrinsicType.ZERO_EXTEND -> emitZeroExtend(callSite, args)
IntrinsicType.INT_TRUNCATE -> emitIntTruncate(callSite, args)
@@ -485,9 +490,10 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
assert (first.type == second.type) { "Types are different: '${llvmtype2string(first.type)}' and '${llvmtype2string(second.type)}'" }
return when (val typeKind = LLVMGetTypeKind(first.type)) {
llvm.LLVMTypeKind.LLVMFloatTypeKind, llvm.LLVMTypeKind.LLVMDoubleTypeKind -> {
val numBits = llvm.LLVMSizeOfTypeInBits(codegen.llvmTargetData, first.type).toInt()
val integerType = LLVMIntTypeInContext(llvmContext, numBits)!!
llvm.LLVMTypeKind.LLVMFloatTypeKind, llvm.LLVMTypeKind.LLVMDoubleTypeKind,
LLVMTypeKind.LLVMVectorTypeKind -> {
// TODO LLVM API does not provide guarantee for LLVMIntTypeInContext availability for longer types; consider meaningful diag message instead of NPE
val integerType = LLVMIntTypeInContext(llvmContext, first.type.sizeInBits())!!
icmpEq(bitcast(integerType, first), bitcast(integerType, second))
}
llvm.LLVMTypeKind.LLVMIntegerTypeKind, llvm.LLVMTypeKind.LLVMPointerTypeKind -> icmpEq(first, second)
@@ -508,6 +514,24 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
private fun FunctionGenerationContext.emitReinterpret(callSite: IrCall, args: List<LLVMValueRef>) =
bitcast(callSite.llvmReturnType, args[0])
private fun FunctionGenerationContext.emitExtractElement(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
val (vector, index) = args
val elementSize = LLVMSizeOfTypeInBits(codegen.llvmTargetData, callSite.llvmReturnType).toInt()
val vectorSize = LLVMSizeOfTypeInBits(codegen.llvmTargetData, vector.type).toInt()
assert(callSite.llvmReturnType.isVectorElementType()
&& vectorSize % elementSize == 0
) { "Invalid vector element type ${LLVMGetTypeKind(callSite.llvmReturnType)}"}
val elementCount = vectorSize / elementSize
emitThrowIfOOB(index, Int32((elementCount)).llvm)
val targetType = LLVMVectorType(callSite.llvmReturnType, elementCount)!!
return extractElement(
(if (targetType == vector.type) vector else bitcast(targetType, vector)),
index)
}
private fun FunctionGenerationContext.emitNot(args: List<LLVMValueRef>) =
not(args[0])
@@ -611,6 +635,14 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
}
}
private fun FunctionGenerationContext.emitThrowIfOOB(index: LLVMValueRef, size: LLVMValueRef) {
ifThen(icmpUGe(index, size)) {
val throwIndexOutOfBoundsException = codegen.llvmFunction(context.ir.symbols.throwIndexOutOfBoundsException.owner)
call(throwIndexOutOfBoundsException, emptyList(), Lifetime.GLOBAL, environment.exceptionHandler)
unreachable()
}
}
private fun FunctionGenerationContext.emitSignedDiv(args: List<LLVMValueRef>): LLVMValueRef {
val (first, second) = args
if (!second.type.isFloatingPoint()) {
@@ -89,7 +89,11 @@ private fun ContextUtils.createClassBodyType(name: String, fields: List<IrField>
val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!!
LLVMStructSetBody(classType, fieldTypes.toCValues(), fieldTypes.size, 0)
// LLVMStructSetBody expects the struct to be properly aligned and will insert padding accordingly. In our case
// `allocInstance` returns 16x + 8 address, i.e. always misaligned for vector types. Workaround is to use packed struct.
val hasBigAlignment = fields.any { LLVMABIAlignmentOfType(context.llvm.runtime.targetData, getLLVMType(it.type)) > 8 }
val packed = if (hasBigAlignment) 1 else 0
LLVMStructSetBody(classType, fieldTypes.toCValues(), fieldTypes.size, packed)
return classType
}
@@ -110,6 +110,7 @@ internal val int64Type get() = LLVMInt64TypeInContext(llvmContext)!!
internal val int8TypePtr get() = pointerType(int8Type)
internal val floatType get() = LLVMFloatTypeInContext(llvmContext)!!
internal val doubleType get() = LLVMDoubleTypeInContext(llvmContext)!!
internal val vector128Type get() = LLVMVectorType(floatType, 4)!!
internal val voidType get() = LLVMVoidTypeInContext(llvmContext)!!
@@ -384,4 +385,11 @@ internal fun LLVMValueRef.setUnaligned() = apply { LLVMSetAlignment(this, 1) }
fun LLVMTypeRef.isFloatingPoint(): Boolean = when (llvm.LLVMGetTypeKind(this)) {
LLVMTypeKind.LLVMFloatTypeKind, LLVMTypeKind.LLVMDoubleTypeKind -> true
else -> false
}
}
fun LLVMTypeRef.isVectorElementType(): Boolean = when (llvm.LLVMGetTypeKind(this)) {
LLVMTypeKind.LLVMIntegerTypeKind,
LLVMTypeKind.LLVMFloatTypeKind,
LLVMTypeKind.LLVMDoubleTypeKind -> true
else -> false
}
@@ -171,7 +171,8 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
floatType to 6,
doubleType to 7,
kInt8Ptr to 8,
int1Type to 9
int1Type to 9,
vector128Type to 10
)
private fun getInstanceSize(classType: LLVMTypeRef?, className: FqName) : Int {
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.types.IrType
@@ -29,6 +28,7 @@ internal class KonanDefaultParameterInjector(private val konanContext: KonanBack
PrimitiveBinaryType.FLOAT -> IrConstImpl.float(startOffset, endOffset, type, 0.0F)
PrimitiveBinaryType.DOUBLE -> IrConstImpl.double(startOffset, endOffset, type, 0.0)
PrimitiveBinaryType.POINTER -> irCall(startOffset, endOffset, symbols.getNativeNullPtr.owner, emptyList())
PrimitiveBinaryType.VECTOR128 -> TODO()
}
return irCall(
@@ -40,4 +40,4 @@ internal class KonanDefaultParameterInjector(private val konanContext: KonanBack
extensionReceiver = nullConstOfEquivalentType
}
}
}
}
@@ -207,6 +207,7 @@ private fun ObjCExportMapper.bridgeType(
KonanPrimitiveType.FLOAT -> ObjCValueType.FLOAT
KonanPrimitiveType.DOUBLE -> ObjCValueType.DOUBLE
KonanPrimitiveType.NON_NULL_NATIVE_PTR -> ObjCValueType.POINTER
KonanPrimitiveType.VECTOR128 -> TODO()
}
ValueTypeBridge(objCValueType)
},
+5
View File
@@ -764,6 +764,10 @@ task runtime_random(type: KonanLocalTest) {
source = "runtime/basic/random.kt"
}
task runtime_basic_simd(type: KonanLocalTest) {
source = "runtime/basic/simd.kt"
}
task runtime_worker_random(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') // Uses workers.
source = "runtime/basic/worker_random.kt"
@@ -3658,6 +3662,7 @@ dynamicTest("produce_dynamic") {
"singleton = I am single\n" +
"mutable = foo\n" +
"topLevel = 777 3\n" +
"getVector128 = (1, 2, 3, 4)\n" +
"Error handler: kotlin.Error: Expected error\n"
}
@@ -138,4 +138,6 @@ fun getNullableString(param: Int) : String? {
} else {
return null
}
}
}
fun getVector128() = vectorOf(1, 2, 3, 4)
@@ -9,6 +9,11 @@ void errorHandler(const char* str) {
printf("Error handler: %s\n", str);
}
void testVector128() {
int __attribute__ ((__vector_size__ (16))) v4f = __ kotlin.root.getVector128();
printf("getVector128 = (%d, %d, %d, %d)\n", v4f[0], v4f[1], v4f[2], v4f[3]);
}
int main(void) {
T_(Singleton) singleton = __ kotlin.root.Singleton._instance();
T_(Base) base = __ kotlin.root.Base.Base();
@@ -65,6 +70,8 @@ int main(void) {
__ kotlin.root.testNullableWithNulls(nullableIntNull, nullableUnitNull);
testVector128();
__ DisposeStablePointer(singleton.pinned);
__ DisposeString(string1);
__ DisposeString(string2);
@@ -0,0 +1,79 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package runtime.basic.simd
import kotlin.test.*
@Test fun runTest() {
testSetGet()
testString()
testOOB()
testEquals()
testHash()
testDefaultValue()
}
fun testSetGet() {
var v4any = vectorOf(0, 1, 2, 3)
(0 until 4).forEach { assertEquals(it, v4any.getIntAt(it)) }
// type punning: set the variable to another runtime type
val a = arrayOf(1f, 3.162f, 10f, 31f)
v4any = vectorOf(a[0], a[1], a[2], a[3])
(0 until 4).forEach { assertEquals(a[it], v4any.getFloatAt(it)) }
}
fun testString() {
val v4i = vectorOf(100, 1024, Int.MAX_VALUE, Int.MIN_VALUE)
assertEquals("(0x64, 0x400, 0x7fffffff, 0x80000000)", v4i.toString())
}
fun testOOB() {
val f = vectorOf(1f, 3.162f, 10f, 31f)
println("f.getByteAt(15) is OK ${f.getByteAt(15)}")
assertFailsWith<IndexOutOfBoundsException>("f.getByteAt(16) should fail") {
f.getByteAt(16)
}
assertFailsWith<IndexOutOfBoundsException>("f.getIntAt(-1) should fail") {
f.getIntAt(-1)
}
assertFailsWith<IndexOutOfBoundsException>("f.getFloatAt(4) should fail") {
f.getFloatAt(4)
}
}
fun testEquals() {
var v1 = vectorOf(-1f, 0f, 0f, -7f)
var v2 = vectorOf(1f, 4f, 3f, 7f)
assertEquals(false, v1 == v2)
assertEquals(false, v1.equals(v2))
assertEquals(false, v1.equals(Any()))
assertEquals(true, v2 == v2)
v1 = v2
assertEquals(true, v1 == v2)
}
fun testHash() {
val h1 = vectorOf(1f, 4f, 3f, 7f).hashCode()
val h2 = vectorOf(3f, 7f, 1f, 4f).hashCode()
assertEquals(false, h1 == h2)
val i = 654687
assertEquals(true, vectorOf(0, 0, i, 0).hashCode() == i.hashCode()) // exploit little endianness
assertEquals(true, vectorOf(1, 0, 0, 0).hashCode() == vectorOf(0, 0, 31, 0).hashCode())
}
private fun funDefaultValue(v: Vector128 = vectorOf(1.0f, 2.0f, 3.0f, 4.0f)) = v
fun testDefaultValue() {
assertEquals(vectorOf(1.0f, 2.0f, 3.0f, 4.0f), funDefaultValue())
}
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cassert>
#include <clang/AST/Type.h>
#include <clang-c/Index.h>
using namespace clang;
static inline QualType GetQualType(CXType CT) {
return QualType::getFromOpaquePtr(CT.data[0]);
}
extern "C"
int clang_isExtVectorType(CXType CT) {
static_assert(CINDEX_VERSION < 59, "Use CXType_ExtVector for this libclang version");
QualType T = GetQualType(CT);
const clang::Type *TP = T.getTypePtrOrNull();
return TP && TP->isExtVectorType();
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <clang-c/Index.h>
#ifdef __cplusplus
extern "C" {
#endif
int clang_isExtVectorType(CXType type);
#ifdef __cplusplus
}
#endif
+8
View File
@@ -93,4 +93,12 @@ bool IsSubInterface(const TypeInfo* thiz, const TypeInfo* other) {
return false;
}
KVector4f Kotlin_Vector4f_of(KFloat f0, KFloat f1, KFloat f2, KFloat f3) {
return {f0, f1, f2, f3};
}
KVector4i32 Kotlin_Vector4i32_of(KInt f0, KInt f1, KInt f2, KInt f3) {
return {f0, f1, f2, f3};
}
} // extern "C"
+2
View File
@@ -51,6 +51,8 @@ typedef uint64_t KULong;
typedef float KFloat;
typedef double KDouble;
typedef void* KNativePtr;
typedef KFloat __attribute__ ((__vector_size__ (16))) KVector4f;
typedef KInt __attribute__ ((__vector_size__ (16))) KVector4i32;
typedef const void* KConstNativePtr;
@@ -33,6 +33,7 @@ class IntrinsicType {
const val UNSIGNED_COMPARE_TO = "UNSIGNED_COMPARE_TO"
const val NOT = "NOT"
const val REINTERPRET = "REINTERPRET"
const val EXTRACT_ELEMENT = "EXTRACT_ELEMENT"
const val ARE_EQUAL_BY_VALUE = "ARE_EQUAL_BY_VALUE"
const val IEEE_754_EQUALS = "IEEE_754_EQUALS"
@@ -22,6 +22,7 @@ import kotlin.native.internal.IntrinsicType
// Bitwise equality:
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Float, second: Float): Boolean
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Double, second: Double): Boolean
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Vector128, second: Vector128): Boolean
// IEEE754 equality:
@TypedIntrinsic(IntrinsicType.IEEE_754_EQUALS) @PublishedApi external internal fun ieee754Equals(first: Float, second: Float): Boolean
@@ -13,6 +13,11 @@ fun ThrowNullPointerException(): Nothing {
throw NullPointerException()
}
@ExportForCppRuntime
internal fun ThrowIndexOutOfBoundsException(): Nothing {
throw IndexOutOfBoundsException()
}
@ExportForCppRuntime
internal fun ThrowArrayIndexOutOfBoundsException(): Nothing {
throw ArrayIndexOutOfBoundsException()
@@ -0,0 +1,57 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package kotlin.native
import kotlin.native.internal.TypedIntrinsic
import kotlin.native.internal.IntrinsicType
public final class Vector128 private constructor() {
@TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT)
external fun getByteAt(index: Int): Byte
@TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT)
external fun getIntAt(index: Int): Int
@TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT)
external fun getLongAt(index: Int): Long
@TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT)
external fun getFloatAt(index: Int): Float
@TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT)
external fun getDoubleAt(index: Int): Double
@TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT)
external fun getUByteAt(index: Int): UByte
@TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT)
external fun getUIntAt(index: Int): UInt
@TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT)
external fun getULongAt(index: Int): ULong
public override fun toString() =
"(0x${getUIntAt(0).toString(16)}, 0x${getUIntAt(1).toString(16)}, 0x${getUIntAt(2).toString(16)}, 0x${getUIntAt(3).toString(16)})"
// Not as good for floating types
public fun equals(other: Vector128): Boolean =
getLongAt(0) == other.getLongAt(0) && getLongAt(1) == other.getLongAt(1)
public override fun equals(other: Any?): Boolean =
other is Vector128 && this.equals(other)
override fun hashCode(): Int {
val x0 = getLongAt(0)
val x1 = getLongAt(1)
return 31 * (x0 xor (x0 shr 32)).toInt() + (x1 xor (x1 shr 32)).toInt()
}
}
@SymbolName("Kotlin_Vector4f_of")
external fun vectorOf(f0: Float, f1: Float, f2: Float, f3: Float): Vector128
@SymbolName("Kotlin_Vector4i32_of")
external fun vectorOf(f0: Int, f1: Int, f2: Int, f3: Int): Vector128
+58
View File
@@ -0,0 +1,58 @@
import kotlinx.cinterop.*
import platform.Accelerate.*
import platform.darwin.*
// Custom print
fun Vector128.toStringHex(): String {
return "0x" + (0 until 16).map { getUByteAt(it).toString(16) }.joinToString("")
}
// Custom print
fun Vector128.toStringFloat(): String {
return "(${(0 until 4).map { getFloatAt(it).toString() }.joinToString(", ")})"
}
fun main() {
// Accessors
val vf4 = vectorOf(1f, 3.162f, 10f, 31f)
println(vf4)
println(vf4.toStringFloat())
println(vf4.toStringHex())
println(vf4.getFloatAt(1))
println(vf4.getIntAt(0))
println(vf4.getByteAt(3))
// Illegal access (out of bounds)
try {
println(vf4.getIntAt(4))
println("FAILED")
} catch (e: IndexOutOfBoundsException) {
println("Handling $e")
}
// Assignment and equality
var x1 = vectorOf(-1f, 0f, 0f, -7f)
val y1 = vectorOf(-1f, 0f, 0f, -7f)
var x2 = vectorOf(1f, 4f, 3f, 7f)
println("(x1 == y1) is ${(x1 == y1)}")
println("(x1.equals(y1)) is ${(x1.equals(y1))}")
println("(x1 == x2) is ${(x1 == x2)}")
x1 = x2
println("Now (x1 == x1) is ${(x1 == x1)}")
// Using library function (MacOS Accelerate framework)
val sum = vS128Add(vectorOf(1,2,3,4), vectorOf(4,3,2,1))
println(sum)
// More Accelerate framework
val q = vectorOf(1f, 9f, 25f, 49f)
val sq = vsqrtf(q)
println("vsqrtf$q = ${sq.toStringFloat()}")
val f4 = vectorOf(1f, 3.162f, 10f, 31f)
println("vlog10f($f4) = ${vlog10f(vf4).toStringFloat()}")
}