diff --git a/Interop/Indexer/clang.def b/Interop/Indexer/clang.def index 3738a9f8303..9bbd52a7b1d 100644 --- a/Interop/Indexer/clang.def +++ b/Interop/Indexer/clang.def @@ -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/** diff --git a/Interop/Indexer/prebuilt/nativeInteropStubs/c/clangstubs.c b/Interop/Indexer/prebuilt/nativeInteropStubs/c/clangstubs.c index d51e95904ba..6930a9792c3 100644 --- a/Interop/Indexer/prebuilt/nativeInteropStubs/c/clangstubs.c +++ b/Interop/Indexer/prebuilt/nativeInteropStubs/c/clangstubs.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); +} diff --git a/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt b/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt index ae03e5b8d38..a7ef69c73a5 100644 --- a/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt +++ b/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt @@ -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(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? get() = memberAt>(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? get() = memberAt>(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(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 @@ -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 @@ -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 @@ -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(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(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(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(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(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 @@ -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(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? get() = memberAt>(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(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 @@ -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(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(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(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? get() = memberAt>(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? get() = memberAt>(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? get() = memberAt>(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? get() = memberAt>(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? get() = memberAt>(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>? get() = memberAt>>(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? get() = memberAt>(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? get() = memberAt>(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? get() = memberAt>(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? get() = memberAt>(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(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 Int>>? get() = memberAt 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(0).value @@ -3838,6 +3838,12 @@ fun clang_Cursor_isObjCConsumingSelfMethod(cursor: CValue): Int { } } +fun clang_isExtVectorType(type: CValue): 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") \ No newline at end of file +private external fun kniBridge339(p0: NativePtr): Int +private val loadLibrary = loadKonanLibrary("clangstubs") diff --git a/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt b/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt index 4771832fbb1..b59e2074118 100644 --- a/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt +++ b/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt @@ -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 diff --git a/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/NativeIndex.kt b/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/NativeIndex.kt index b102e1b64d0..a6eca10eeea 100644 --- a/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/NativeIndex.kt +++ b/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/NativeIndex.kt @@ -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, val returnType: Type ) : ObjCPointer() -object UnsupportedType : Type \ No newline at end of file +object UnsupportedType : Type diff --git a/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Utils.kt b/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Utils.kt index 7772c6e567f..5edc439fb42 100644 --- a/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Utils.kt +++ b/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Utils.kt @@ -30,6 +30,12 @@ internal val CValue.kind: CXTypeKind get() = this.useContents { kind } internal val CValue.kind: CXCursorKind get() = this.useContents { kind } +internal val CValue.type: CValue get() = clang_getCursorType(this) +internal val CValue.spelling: String get() = clang_getCursorSpelling(this).convertAndDispose() +internal val CValue.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.convertAndDispose(): String { try { return clang_getCString(this)!!.toKString() diff --git a/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt b/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt index 25f359715fa..f2a9dd5055b 100644 --- a/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt +++ b/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt @@ -470,4 +470,4 @@ public typealias CArrayPointerVar = CPointerVar /** * The C function. */ -public class CFunction>(rawPtr: NativePtr) : CPointed(rawPtr) \ No newline at end of file +public class CFunction>(rawPtr: NativePtr) : CPointed(rawPtr) diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt index 4478e87d34c..88e69256436 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt @@ -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().ptr diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt index 3e4cf9b9667..7d4d166cb15 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt @@ -56,6 +56,14 @@ external fun CPointer<*>.getRawValue(): NativePtr internal fun CPointer<*>.cPointerToString() = "CPointer(raw=$rawValue)" +public class Vector128VarOf(rawPtr: NativePtr) : CVariable(rawPtr) + +public typealias Vector128Var = Vector128VarOf + +public var Vector128VarOf.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 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 R>> -@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun 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 R>> \ No newline at end of file +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun 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 R>> diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt index 376bde30cf7..80ca3c393e9 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt @@ -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( diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt index cf7afb8642c..d095738f19f 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt @@ -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()) } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGenerator.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGenerator.kt index 2f7f880dde4..1a27ba4e24e 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGenerator.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGenerator.kt @@ -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) diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGeneratorImpl.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGeneratorImpl.kt index 374bb44cdee..b6517d140bf 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGeneratorImpl.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGeneratorImpl.kt @@ -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" diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt index 706ba8deeb0..e8f9241d91a 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt @@ -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 } -} \ No newline at end of file +} diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/TypeUtils.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/TypeUtils.kt index c35b0828fd6..8bc3a60255f 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/TypeUtils.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/TypeUtils.kt @@ -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) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryType.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryType.kt index 10c8bff7ce2..b71b206c3d9 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryType.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryType.kt @@ -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 } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt index 49914c8d2f2..eb4e40a6918 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt @@ -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" } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt index 8aae81d13f5..e4dc26a4a28 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt @@ -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) ; diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt index 837e1995820..92a9a3e8a81 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt @@ -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") diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt index b43d897c802..38ad0910966 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt @@ -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 diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CSyntaxSupport.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CSyntaxSupport.kt index 6efe146b791..4141abc18c0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CSyntaxSupport.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CSyntaxSupport.kt @@ -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(')') }) -} \ No newline at end of file +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index 5f5bea435a4..c95b010c36b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -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") diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index 0dbc3a03602..918fb5dd3ee 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -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) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt index b5b24deb764..71542ec7c74 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt @@ -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) } -} \ No newline at end of file +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt index 39d4f971f50..b260f653efe 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt @@ -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) = bitcast(callSite.llvmReturnType, args[0]) + private fun FunctionGenerationContext.emitExtractElement(callSite: IrCall, args: List): 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) = 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 { val (first, second) = args if (!second.type.isFloatingPoint()) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt index 2434c0b01aa..6f463bac6b1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt @@ -89,7 +89,11 @@ private fun ContextUtils.createClassBodyType(name: String, fields: List 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 } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt index b03c94f8fef..1ccee5a965b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt @@ -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 -} \ No newline at end of file +} + +fun LLVMTypeRef.isVectorElementType(): Boolean = when (llvm.LLVMGetTypeKind(this)) { + LLVMTypeKind.LLVMIntegerTypeKind, + LLVMTypeKind.LLVMFloatTypeKind, + LLVMTypeKind.LLVMDoubleTypeKind -> true + else -> false +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt index 91af8ecf687..9a83d7b78ed 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt @@ -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 { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultParameterInjector.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultParameterInjector.kt index 286a9018561..56a9b65189f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultParameterInjector.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultParameterInjector.kt @@ -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 } } -} \ No newline at end of file +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt index 0038f19b0f0..2167356c26d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt @@ -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) }, diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 3287622c320..92a8d5c231e 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -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" } diff --git a/backend.native/tests/produce_dynamic/simple/hello.kt b/backend.native/tests/produce_dynamic/simple/hello.kt index e466fca69c7..8ad57b40641 100644 --- a/backend.native/tests/produce_dynamic/simple/hello.kt +++ b/backend.native/tests/produce_dynamic/simple/hello.kt @@ -138,4 +138,6 @@ fun getNullableString(param: Int) : String? { } else { return null } -} \ No newline at end of file +} + +fun getVector128() = vectorOf(1, 2, 3, 4) diff --git a/backend.native/tests/produce_dynamic/simple/main.c b/backend.native/tests/produce_dynamic/simple/main.c index 17725003f12..ef07c9bc5bc 100644 --- a/backend.native/tests/produce_dynamic/simple/main.c +++ b/backend.native/tests/produce_dynamic/simple/main.c @@ -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); diff --git a/backend.native/tests/runtime/basic/simd.kt b/backend.native/tests/runtime/basic/simd.kt new file mode 100644 index 00000000000..684ca536ae9 --- /dev/null +++ b/backend.native/tests/runtime/basic/simd.kt @@ -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("f.getByteAt(16) should fail") { + f.getByteAt(16) + } + + assertFailsWith("f.getIntAt(-1) should fail") { + f.getIntAt(-1) + } + + assertFailsWith("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()) +} diff --git a/libclangext/src/main/cpp/ExtVector.cpp b/libclangext/src/main/cpp/ExtVector.cpp new file mode 100644 index 00000000000..0aca72efa8c --- /dev/null +++ b/libclangext/src/main/cpp/ExtVector.cpp @@ -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 + +#include +#include + + +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(); +} diff --git a/libclangext/src/main/include/clang-c/ExtVector.h b/libclangext/src/main/include/clang-c/ExtVector.h new file mode 100644 index 00000000000..d2fe4b59c90 --- /dev/null +++ b/libclangext/src/main/include/clang-c/ExtVector.h @@ -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 + +#ifdef __cplusplus +extern "C" { +#endif + +int clang_isExtVectorType(CXType type); + +#ifdef __cplusplus +} +#endif diff --git a/runtime/src/main/cpp/Types.cpp b/runtime/src/main/cpp/Types.cpp index b26dbe22d64..34f3a7764b0 100644 --- a/runtime/src/main/cpp/Types.cpp +++ b/runtime/src/main/cpp/Types.cpp @@ -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" diff --git a/runtime/src/main/cpp/Types.h b/runtime/src/main/cpp/Types.h index 199d8a9ea9f..473c38fd56b 100644 --- a/runtime/src/main/cpp/Types.h +++ b/runtime/src/main/cpp/Types.h @@ -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; diff --git a/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt b/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt index 5f4ef01757c..25edf9928d0 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt @@ -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" diff --git a/runtime/src/main/kotlin/kotlin/native/internal/Intrinsics.kt b/runtime/src/main/kotlin/kotlin/native/internal/Intrinsics.kt index 1a16c13473a..1120a5cd60a 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/Intrinsics.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/Intrinsics.kt @@ -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 diff --git a/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt b/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt index 9b2890d69e3..473000a7ffb 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt @@ -13,6 +13,11 @@ fun ThrowNullPointerException(): Nothing { throw NullPointerException() } +@ExportForCppRuntime +internal fun ThrowIndexOutOfBoundsException(): Nothing { + throw IndexOutOfBoundsException() +} + @ExportForCppRuntime internal fun ThrowArrayIndexOutOfBoundsException(): Nothing { throw ArrayIndexOutOfBoundsException() diff --git a/runtime/src/main/kotlin/kotlin/native/simd.kt b/runtime/src/main/kotlin/kotlin/native/simd.kt new file mode 100644 index 00000000000..85d4e9de5ec --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/native/simd.kt @@ -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 diff --git a/samples/simd/simd.kt b/samples/simd/simd.kt new file mode 100644 index 00000000000..54400093640 --- /dev/null +++ b/samples/simd/simd.kt @@ -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()}") + + +}