Mostly avoid using ArrayHeader* in generated code. (#116)
This commit is contained in:
+2
-1
@@ -6,6 +6,8 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
|
|
||||||
internal fun ContextUtils.getLLVMType(type: KotlinType): LLVMTypeRef {
|
internal fun ContextUtils.getLLVMType(type: KotlinType): LLVMTypeRef {
|
||||||
return when {
|
return when {
|
||||||
|
// Nullable types must be represented as objects for boxing.
|
||||||
|
type.isMarkedNullable -> this.kObjHeaderPtr
|
||||||
KotlinBuiltIns.isBoolean(type) -> LLVMInt1Type()
|
KotlinBuiltIns.isBoolean(type) -> LLVMInt1Type()
|
||||||
KotlinBuiltIns.isByte(type) -> LLVMInt8Type()
|
KotlinBuiltIns.isByte(type) -> LLVMInt8Type()
|
||||||
KotlinBuiltIns.isShort(type) || KotlinBuiltIns.isChar(type) -> LLVMInt16Type()
|
KotlinBuiltIns.isShort(type) || KotlinBuiltIns.isChar(type) -> LLVMInt16Type()
|
||||||
@@ -14,7 +16,6 @@ internal fun ContextUtils.getLLVMType(type: KotlinType): LLVMTypeRef {
|
|||||||
KotlinBuiltIns.isUnit(type) -> LLVMVoidType() // TODO: handle Unit parameter case
|
KotlinBuiltIns.isUnit(type) -> LLVMVoidType() // TODO: handle Unit parameter case
|
||||||
KotlinBuiltIns.isFloat(type) -> LLVMFloatType()
|
KotlinBuiltIns.isFloat(type) -> LLVMFloatType()
|
||||||
KotlinBuiltIns.isDouble(type) -> LLVMDoubleType()
|
KotlinBuiltIns.isDouble(type) -> LLVMDoubleType()
|
||||||
KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type)-> this.kArrayHeaderPtr
|
|
||||||
!KotlinBuiltIns.isPrimitiveType(type) -> this.kObjHeaderPtr
|
!KotlinBuiltIns.isPrimitiveType(type) -> this.kObjHeaderPtr
|
||||||
else -> throw NotImplementedError(type.toString() + " is not supported")
|
else -> throw NotImplementedError(type.toString() + " is not supported")
|
||||||
}!!
|
}!!
|
||||||
|
|||||||
-7
@@ -112,10 +112,6 @@ internal val ContextUtils.kObjHeaderPtr: LLVMTypeRef
|
|||||||
get() = pointerType(kObjHeader)
|
get() = pointerType(kObjHeader)
|
||||||
internal val ContextUtils.kObjHeaderPtrPtr: LLVMTypeRef
|
internal val ContextUtils.kObjHeaderPtrPtr: LLVMTypeRef
|
||||||
get() = pointerType(kObjHeaderPtr)
|
get() = pointerType(kObjHeaderPtr)
|
||||||
internal val ContextUtils.kArrayHeader: LLVMTypeRef
|
|
||||||
get() = LLVMGetTypeByName(context.llvmModule, "struct.ArrayHeader")!!
|
|
||||||
internal val ContextUtils.kArrayHeaderPtr: LLVMTypeRef
|
|
||||||
get() = pointerType(kArrayHeader)
|
|
||||||
internal val ContextUtils.kTypeInfoPtr: LLVMTypeRef
|
internal val ContextUtils.kTypeInfoPtr: LLVMTypeRef
|
||||||
get() = pointerType(kTypeInfo)
|
get() = pointerType(kTypeInfo)
|
||||||
internal val kInt1 = LLVMInt1Type()!!
|
internal val kInt1 = LLVMInt1Type()!!
|
||||||
@@ -124,9 +120,6 @@ internal val kInt8PtrPtr = pointerType(kInt8Ptr)
|
|||||||
internal val kImmInt32One = Int32(1).llvm
|
internal val kImmInt32One = Int32(1).llvm
|
||||||
internal val ContextUtils.kNullObjHeaderPtr: LLVMValueRef
|
internal val ContextUtils.kNullObjHeaderPtr: LLVMValueRef
|
||||||
get() = LLVMConstNull(this.kObjHeaderPtr)!!
|
get() = LLVMConstNull(this.kObjHeaderPtr)!!
|
||||||
internal val ContextUtils.kNullArrayHeaderPtr: LLVMValueRef
|
|
||||||
get() = LLVMConstNull(this.kArrayHeaderPtr)!!
|
|
||||||
|
|
||||||
|
|
||||||
internal fun pointerType(pointeeType: LLVMTypeRef) = LLVMPointerType(pointeeType, 0)!!
|
internal fun pointerType(pointeeType: LLVMTypeRef) = LLVMPointerType(pointeeType, 0)!!
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,9 @@
|
|||||||
#include "Natives.h"
|
#include "Natives.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
ArrayHeader* setupArgs(int argc, char** argv) {
|
ObjHeader* setupArgs(int argc, char** argv) {
|
||||||
|
|
||||||
// The count is one less, because we skip argv[0] which is the binary name.
|
// The count is one less, because we skip argv[0] which is the binary name.
|
||||||
ArrayHeader* args = AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, argc-1);
|
ObjHeader* args = AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, argc-1);
|
||||||
|
|
||||||
for (int i = 0; i < argc-1; i++) {
|
for (int i = 0; i < argc-1; i++) {
|
||||||
Kotlin_Array_set(args, i, AllocStringInstance(
|
Kotlin_Array_set(args, i, AllocStringInstance(
|
||||||
@@ -16,13 +15,13 @@ ArrayHeader* setupArgs(int argc, char** argv) {
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Konan_start(ArrayHeader* );
|
extern "C" void Konan_start(ObjHeader* );
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
InitMemory();
|
InitMemory();
|
||||||
|
|
||||||
ArrayHeader* args = setupArgs(argc, argv);
|
ObjHeader* args = setupArgs(argc, argv);
|
||||||
Konan_start(args);
|
Konan_start(args);
|
||||||
|
|
||||||
// Yes, we have to follow Java convention and return zero.
|
// Yes, we have to follow Java convention and return zero.
|
||||||
|
|||||||
+123
-85
@@ -12,21 +12,24 @@ extern "C" {
|
|||||||
// TODO: those must be compiler intrinsics afterwards.
|
// TODO: those must be compiler intrinsics afterwards.
|
||||||
|
|
||||||
// Array.kt
|
// Array.kt
|
||||||
KRef Kotlin_Array_get(const ArrayHeader* obj, KInt index) {
|
KRef Kotlin_Array_get(const ObjHeader* thiz, KInt index) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return *ArrayAddressOfElementAt(obj, index);
|
return *ArrayAddressOfElementAt(array, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_Array_set(ArrayHeader* obj, KInt index, KConstRef value) {
|
void Kotlin_Array_set(ObjHeader* thiz, KInt index, KConstRef value) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
ArrayHeader* array = static_cast<ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
*ArrayAddressOfElementAt(obj, index) = value;
|
*ArrayAddressOfElementAt(array, index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_Array_clone(const ArrayHeader* array) {
|
ObjHeader* Kotlin_Array_clone(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
ArrayHeader* result = ArrayContainer(
|
ArrayHeader* result = ArrayContainer(
|
||||||
array->type_info(), array->count_).GetPlace();
|
array->type_info(), array->count_).GetPlace();
|
||||||
memcpy(
|
memcpy(
|
||||||
@@ -36,48 +39,55 @@ ArrayHeader* Kotlin_Array_clone(const ArrayHeader* array) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KInt Kotlin_Array_getArrayLength(const ArrayHeader* array) {
|
KInt Kotlin_Array_getArrayLength(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
return array->count_;
|
return array->count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_Array_fillImpl(ArrayHeader* array, KInt fromIndex,
|
void Kotlin_Array_fillImpl(ObjHeader* thiz, KInt fromIndex,
|
||||||
KInt toIndex, ObjHeader* value) {
|
KInt toIndex, ObjHeader* value) {
|
||||||
if (fromIndex < 0 || toIndex < fromIndex || toIndex >= array->count_) {
|
ArrayHeader* array = static_cast<ArrayHeader*>(thiz);
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
if (fromIndex < 0 || toIndex < fromIndex || toIndex >= array->count_) {
|
||||||
}
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
// TODO: refcounting!
|
}
|
||||||
for (KInt index = fromIndex; index < toIndex; ++index) {
|
// TODO: refcounting!
|
||||||
*ArrayAddressOfElementAt(array, index) = value;
|
for (KInt index = fromIndex; index < toIndex; ++index) {
|
||||||
}
|
*ArrayAddressOfElementAt(array, index) = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_Array_copyImpl(const ArrayHeader* array, KInt fromIndex,
|
void Kotlin_Array_copyImpl(const ObjHeader* thiz, KInt fromIndex,
|
||||||
ArrayHeader* destination, KInt toIndex, KInt count) {
|
ObjHeader* destination, KInt toIndex, KInt count) {
|
||||||
if (fromIndex < 0 || fromIndex + count > array->count_ ||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
toIndex < 0 || toIndex + count > destination->count_) {
|
ArrayHeader* destinationArray = static_cast<ArrayHeader*>(destination);
|
||||||
|
if (fromIndex < 0 || fromIndex + count > array->count_ ||
|
||||||
|
toIndex < 0 || toIndex + count > destinationArray->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
// TODO: refcounting!
|
// TODO: refcounting!
|
||||||
memmove(ArrayAddressOfElementAt(destination, toIndex),
|
memmove(ArrayAddressOfElementAt(destinationArray, toIndex),
|
||||||
ArrayAddressOfElementAt(array, fromIndex), count * sizeof(KRef));
|
ArrayAddressOfElementAt(array, fromIndex), count * sizeof(KRef));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arrays.kt
|
// Arrays.kt
|
||||||
KByte Kotlin_ByteArray_get(const ArrayHeader* obj, KInt index) {
|
KByte Kotlin_ByteArray_get(const ObjHeader* thiz, KInt index) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return *ByteArrayAddressOfElementAt(obj, index);
|
return *ByteArrayAddressOfElementAt(array, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_ByteArray_set(ArrayHeader* obj, KInt index, KByte value) {
|
void Kotlin_ByteArray_set(ObjHeader* thiz, KInt index, KByte value) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
ArrayHeader* array = static_cast<ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
*ByteArrayAddressOfElementAt(obj, index) = value;
|
*ByteArrayAddressOfElementAt(array, index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_ByteArray_clone(const ArrayHeader* array) {
|
ObjHeader* Kotlin_ByteArray_clone(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
ArrayHeader* result = ArrayContainer(
|
ArrayHeader* result = ArrayContainer(
|
||||||
theByteArrayTypeInfo, array->count_).GetPlace();
|
theByteArrayTypeInfo, array->count_).GetPlace();
|
||||||
memcpy(
|
memcpy(
|
||||||
@@ -87,25 +97,29 @@ ArrayHeader* Kotlin_ByteArray_clone(const ArrayHeader* array) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KInt Kotlin_ByteArray_getArrayLength(const ArrayHeader* array) {
|
KInt Kotlin_ByteArray_getArrayLength(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
return array->count_;
|
return array->count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
KChar Kotlin_CharArray_get(const ArrayHeader* obj, KInt index) {
|
KChar Kotlin_CharArray_get(const ObjHeader* thiz, KInt index) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return *PrimitiveArrayAddressOfElementAt<KChar>(obj, index);
|
return *PrimitiveArrayAddressOfElementAt<KChar>(array, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_CharArray_set(ArrayHeader* obj, KInt index, KChar value) {
|
void Kotlin_CharArray_set(ObjHeader* thiz, KInt index, KChar value) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
ArrayHeader* array = static_cast<ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
*PrimitiveArrayAddressOfElementAt<KChar>(obj, index) = value;
|
*PrimitiveArrayAddressOfElementAt<KChar>(array, index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_CharArray_clone(const ArrayHeader* array) {
|
ObjHeader* Kotlin_CharArray_clone(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
ArrayHeader* result = ArrayContainer(
|
ArrayHeader* result = ArrayContainer(
|
||||||
theCharArrayTypeInfo, array->count_).GetPlace();
|
theCharArrayTypeInfo, array->count_).GetPlace();
|
||||||
memcpy(
|
memcpy(
|
||||||
@@ -115,7 +129,8 @@ ArrayHeader* Kotlin_CharArray_clone(const ArrayHeader* array) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_CharArray_copyOf(const ArrayHeader* array, KInt newSize) {
|
ObjHeader* Kotlin_CharArray_copyOf(const ObjHeader* thiz, KInt newSize) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
ArrayHeader* result = ArrayContainer(
|
ArrayHeader* result = ArrayContainer(
|
||||||
theCharArrayTypeInfo, newSize).GetPlace();
|
theCharArrayTypeInfo, newSize).GetPlace();
|
||||||
KInt toCopy = array->count_ < newSize ? array->count_ : newSize;
|
KInt toCopy = array->count_ < newSize ? array->count_ : newSize;
|
||||||
@@ -126,22 +141,25 @@ ArrayHeader* Kotlin_CharArray_copyOf(const ArrayHeader* array, KInt newSize) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KInt Kotlin_CharArray_getArrayLength(const ArrayHeader* array) {
|
KInt Kotlin_CharArray_getArrayLength(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
return array->count_;
|
return array->count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
KShort Kotlin_ShortArray_get(const ArrayHeader* obj, KInt index) {
|
KShort Kotlin_ShortArray_get(const ObjHeader* thiz, KInt index) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return *PrimitiveArrayAddressOfElementAt<KShort>(obj, index);
|
return *PrimitiveArrayAddressOfElementAt<KShort>(array, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_ShortArray_set(ArrayHeader* obj, KInt index, KShort value) {
|
void Kotlin_ShortArray_set(ObjHeader* thiz, KInt index, KShort value) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
ArrayHeader* array = static_cast<ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
*PrimitiveArrayAddressOfElementAt<KShort>(obj, index) = value;
|
*PrimitiveArrayAddressOfElementAt<KShort>(array, index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_ShortArray_clone(const ArrayHeader* array) {
|
ArrayHeader* Kotlin_ShortArray_clone(const ArrayHeader* array) {
|
||||||
@@ -158,21 +176,24 @@ KInt Kotlin_ShortArray_getArrayLength(const ArrayHeader* array) {
|
|||||||
return array->count_;
|
return array->count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
KInt Kotlin_IntArray_get(const ArrayHeader* obj, KInt index) {
|
KInt Kotlin_IntArray_get(const ObjHeader* thiz, KInt index) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return *PrimitiveArrayAddressOfElementAt<KInt>(obj, index);
|
return *PrimitiveArrayAddressOfElementAt<KInt>(array, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_IntArray_set(ArrayHeader* obj, KInt index, KInt value) {
|
void Kotlin_IntArray_set(ObjHeader* thiz, KInt index, KInt value) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
ArrayHeader* array = static_cast<ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
*PrimitiveArrayAddressOfElementAt<KInt>(obj, index) = value;
|
*PrimitiveArrayAddressOfElementAt<KInt>(array, index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_IntArray_clone(const ArrayHeader* array) {
|
ObjHeader* Kotlin_IntArray_clone(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
ArrayHeader* result = ArrayContainer(
|
ArrayHeader* result = ArrayContainer(
|
||||||
theIntArrayTypeInfo, array->count_).GetPlace();
|
theIntArrayTypeInfo, array->count_).GetPlace();
|
||||||
memcpy(
|
memcpy(
|
||||||
@@ -182,25 +203,29 @@ ArrayHeader* Kotlin_IntArray_clone(const ArrayHeader* array) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KInt Kotlin_IntArray_getArrayLength(const ArrayHeader* array) {
|
KInt Kotlin_IntArray_getArrayLength(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
return array->count_;
|
return array->count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
KLong Kotlin_LongArray_get(const ArrayHeader* obj, KInt index) {
|
KLong Kotlin_LongArray_get(const ObjHeader* thiz, KInt index) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return *PrimitiveArrayAddressOfElementAt<KLong>(obj, index);
|
return *PrimitiveArrayAddressOfElementAt<KLong>(array, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_LongArray_set(ArrayHeader* obj, KInt index, KLong value) {
|
void Kotlin_LongArray_set(ObjHeader* thiz, KInt index, KLong value) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
ArrayHeader* array = static_cast<ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
*PrimitiveArrayAddressOfElementAt<KLong>(obj, index) = value;
|
*PrimitiveArrayAddressOfElementAt<KLong>(array, index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_LongArray_clone(const ArrayHeader* array) {
|
ArrayHeader* Kotlin_LongArray_clone(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
ArrayHeader* result = ArrayContainer(
|
ArrayHeader* result = ArrayContainer(
|
||||||
theLongArrayTypeInfo, array->count_).GetPlace();
|
theLongArrayTypeInfo, array->count_).GetPlace();
|
||||||
memcpy(
|
memcpy(
|
||||||
@@ -210,25 +235,29 @@ ArrayHeader* Kotlin_LongArray_clone(const ArrayHeader* array) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KInt Kotlin_LongArray_getArrayLength(const ArrayHeader* array) {
|
KInt Kotlin_LongArray_getArrayLength(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
return array->count_;
|
return array->count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
KFloat Kotlin_FloatArray_get(const ArrayHeader* obj, KInt index) {
|
KFloat Kotlin_FloatArray_get(const ObjHeader* thiz, KInt index) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return *PrimitiveArrayAddressOfElementAt<KFloat>(obj, index);
|
return *PrimitiveArrayAddressOfElementAt<KFloat>(array, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_FloatArray_set(ArrayHeader* obj, KInt index, KFloat value) {
|
void Kotlin_FloatArray_set(ObjHeader* thiz, KInt index, KFloat value) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
ArrayHeader* array = static_cast<ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
*PrimitiveArrayAddressOfElementAt<KFloat>(obj, index) = value;
|
*PrimitiveArrayAddressOfElementAt<KFloat>(array, index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_FloatArray_clone(const ArrayHeader* array) {
|
ArrayHeader* Kotlin_FloatArray_clone(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
ArrayHeader* result = ArrayContainer(
|
ArrayHeader* result = ArrayContainer(
|
||||||
theFloatArrayTypeInfo, array->count_).GetPlace();
|
theFloatArrayTypeInfo, array->count_).GetPlace();
|
||||||
memcpy(
|
memcpy(
|
||||||
@@ -238,25 +267,29 @@ ArrayHeader* Kotlin_FloatArray_clone(const ArrayHeader* array) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KInt Kotlin_FloatArray_getArrayLength(const ArrayHeader* array) {
|
KInt Kotlin_FloatArray_getArrayLength(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
return array->count_;
|
return array->count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
KDouble Kotlin_DoubleArray_get(const ArrayHeader* obj, KInt index) {
|
KDouble Kotlin_DoubleArray_get(const ObjHeader* thiz, KInt index) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return *PrimitiveArrayAddressOfElementAt<KDouble>(obj, index);
|
return *PrimitiveArrayAddressOfElementAt<KDouble>(array, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_DoubleArray_set(ArrayHeader* obj, KInt index, KDouble value) {
|
void Kotlin_DoubleArray_set(ObjHeader* thiz, KInt index, KDouble value) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
ArrayHeader* array = static_cast<ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
*PrimitiveArrayAddressOfElementAt<KDouble>(obj, index) = value;
|
*PrimitiveArrayAddressOfElementAt<KDouble>(array, index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_DoubleArray_clone(const ArrayHeader* array) {
|
ObjHeader* Kotlin_DoubleArray_clone(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
ArrayHeader* result = ArrayContainer(
|
ArrayHeader* result = ArrayContainer(
|
||||||
theDoubleArrayTypeInfo, array->count_).GetPlace();
|
theDoubleArrayTypeInfo, array->count_).GetPlace();
|
||||||
memcpy(
|
memcpy(
|
||||||
@@ -266,25 +299,29 @@ ArrayHeader* Kotlin_DoubleArray_clone(const ArrayHeader* array) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KInt Kotlin_DoubleArray_getArrayLength(const ArrayHeader* array) {
|
KInt Kotlin_DoubleArray_getArrayLength(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
return array->count_;
|
return array->count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
KBoolean Kotlin_BooleanArray_get(const ArrayHeader* obj, KInt index) {
|
KBoolean Kotlin_BooleanArray_get(const ObjHeader* thiz, KInt index) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return *PrimitiveArrayAddressOfElementAt<KBoolean>(obj, index);
|
return *PrimitiveArrayAddressOfElementAt<KBoolean>(array, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_BooleanArray_set(ArrayHeader* obj, KInt index, KBoolean value) {
|
void Kotlin_BooleanArray_set(ObjHeader* thiz, KInt index, KBoolean value) {
|
||||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
ArrayHeader* array = static_cast<ArrayHeader*>(thiz);
|
||||||
|
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
*PrimitiveArrayAddressOfElementAt<KBoolean>(obj, index) = value;
|
*PrimitiveArrayAddressOfElementAt<KBoolean>(array, index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_BooleanArray_clone(const ArrayHeader* array) {
|
ObjHeader* Kotlin_BooleanArray_clone(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
ArrayHeader* result = ArrayContainer(
|
ArrayHeader* result = ArrayContainer(
|
||||||
theBooleanArrayTypeInfo, array->count_).GetPlace();
|
theBooleanArrayTypeInfo, array->count_).GetPlace();
|
||||||
memcpy(
|
memcpy(
|
||||||
@@ -294,7 +331,8 @@ ArrayHeader* Kotlin_BooleanArray_clone(const ArrayHeader* array) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KInt Kotlin_BooleanArray_getArrayLength(const ArrayHeader* array) {
|
KInt Kotlin_BooleanArray_getArrayLength(const ObjHeader* thiz) {
|
||||||
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
return array->count_;
|
return array->count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,10 @@ class AutoFree {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: this method ignores the encoding
|
// TODO: this method ignores the encoding.
|
||||||
KString CreateKotlinStringFromCString(const char* str) {
|
KString CreateKotlinStringFromCString(const char* str) {
|
||||||
return AllocStringInstance(SCOPE_GLOBAL, str, strlen(str));
|
return static_cast<KString>(AllocStringInstance(
|
||||||
|
SCOPE_GLOBAL, str, strlen(str)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -45,7 +46,7 @@ extern "C" {
|
|||||||
|
|
||||||
// TODO: this implementation is just a hack, e.g. the result is inexact;
|
// TODO: this implementation is just a hack, e.g. the result is inexact;
|
||||||
// however it is better to have an inexact stacktrace than not to have any.
|
// however it is better to have an inexact stacktrace than not to have any.
|
||||||
KArrayRef GetCurrentStackTrace() {
|
KRef GetCurrentStackTrace() {
|
||||||
const int maxSize = 32;
|
const int maxSize = 32;
|
||||||
void* buffer[maxSize];
|
void* buffer[maxSize];
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ KArrayRef GetCurrentStackTrace() {
|
|||||||
RuntimeAssert(symbols != nullptr, "Not enough memory to retrieve the stacktrace");
|
RuntimeAssert(symbols != nullptr, "Not enough memory to retrieve the stacktrace");
|
||||||
|
|
||||||
AutoFree autoFree(symbols);
|
AutoFree autoFree(symbols);
|
||||||
KArrayRef result = AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, size);
|
KRef result = AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, size);
|
||||||
|
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
KString symbol = CreateKotlinStringFromCString(symbols[i]);
|
KString symbol = CreateKotlinStringFromCString(symbols[i]);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Returns current stacktrace as Array<String>.
|
// Returns current stacktrace as Array<String>.
|
||||||
KArrayRef GetCurrentStackTrace();
|
KRef GetCurrentStackTrace();
|
||||||
|
|
||||||
// Throws arbitrary exception.
|
// Throws arbitrary exception.
|
||||||
void ThrowException(KRef exception);
|
void ThrowException(KRef exception);
|
||||||
|
|||||||
@@ -83,13 +83,13 @@ ObjHeader* AllocInstance(const TypeInfo* type_info, PlacementHint hint) {
|
|||||||
return ObjectContainer(type_info).GetPlace();
|
return ObjectContainer(type_info).GetPlace();
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* AllocArrayInstance(
|
ObjHeader* AllocArrayInstance(
|
||||||
const TypeInfo* type_info, PlacementHint hint, uint32_t elements) {
|
const TypeInfo* type_info, PlacementHint hint, uint32_t elements) {
|
||||||
RuntimeAssert(type_info->instanceSize_ < 0, "must be an array");
|
RuntimeAssert(type_info->instanceSize_ < 0, "must be an array");
|
||||||
return ArrayContainer(type_info, elements).GetPlace();
|
return ArrayContainer(type_info, elements).GetPlace();
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* AllocStringInstance(
|
ObjHeader* AllocStringInstance(
|
||||||
PlacementHint hint, const char* data, uint32_t length) {
|
PlacementHint hint, const char* data, uint32_t length) {
|
||||||
ArrayHeader* result = ArrayContainer(theStringTypeInfo, length).GetPlace();
|
ArrayHeader* result = ArrayContainer(theStringTypeInfo, length).GetPlace();
|
||||||
memcpy(
|
memcpy(
|
||||||
|
|||||||
@@ -252,9 +252,9 @@ extern "C" {
|
|||||||
|
|
||||||
void InitMemory();
|
void InitMemory();
|
||||||
ObjHeader* AllocInstance(const TypeInfo* type_info, PlacementHint hint);
|
ObjHeader* AllocInstance(const TypeInfo* type_info, PlacementHint hint);
|
||||||
ArrayHeader* AllocArrayInstance(
|
ObjHeader* AllocArrayInstance(
|
||||||
const TypeInfo* type_info, PlacementHint hint, uint32_t elements);
|
const TypeInfo* type_info, PlacementHint hint, uint32_t elements);
|
||||||
ArrayHeader* AllocStringInstance(PlacementHint hint,
|
ObjHeader* AllocStringInstance(PlacementHint hint,
|
||||||
const char* data, uint32_t length);
|
const char* data, uint32_t length);
|
||||||
ObjHeader* InitInstance(
|
ObjHeader* InitInstance(
|
||||||
ObjHeader** location, const TypeInfo* type_info, PlacementHint hint,
|
ObjHeader** location, const TypeInfo* type_info, PlacementHint hint,
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ KInt Kotlin_String_getStringLength(KString thiz) {
|
|||||||
return thiz->count_;
|
return thiz->count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
KString Kotlin_String_fromUtf8Array(
|
KString Kotlin_String_fromUtf8Array(KConstRef thiz, KInt start, KInt size) {
|
||||||
const ArrayHeader* array, KInt start, KInt size) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
RuntimeAssert(array->type_info() == theByteArrayTypeInfo, "Must use a byte array");
|
RuntimeAssert(array->type_info() == theByteArrayTypeInfo, "Must use a byte array");
|
||||||
if (start < 0 || size < 0 || start + size > array->count_) {
|
if (start < 0 || size < 0 || start + size > array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
@@ -96,8 +96,8 @@ KString Kotlin_String_fromUtf8Array(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KString Kotlin_String_fromCharArray(
|
KString Kotlin_String_fromCharArray(KConstRef thiz, KInt start, KInt size) {
|
||||||
const ArrayHeader* array, KInt start, KInt size) {
|
const ArrayHeader* array = static_cast<const ArrayHeader*>(thiz);
|
||||||
RuntimeAssert(array->type_info() == theCharArrayTypeInfo, "Must use a byte array");
|
RuntimeAssert(array->type_info() == theCharArrayTypeInfo, "Must use a byte array");
|
||||||
if (start < 0 || size < 0 || start + size > array->count_) {
|
if (start < 0 || size < 0 || start + size > array->count_) {
|
||||||
ThrowArrayIndexOutOfBoundsException();
|
ThrowArrayIndexOutOfBoundsException();
|
||||||
@@ -116,7 +116,7 @@ KString Kotlin_String_fromCharArray(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayHeader* Kotlin_String_toCharArray(KString string) {
|
KRef Kotlin_String_toCharArray(KString string) {
|
||||||
// TODO: support full UTF-8.
|
// TODO: support full UTF-8.
|
||||||
ArrayHeader* result = ArrayContainer(
|
ArrayHeader* result = ArrayContainer(
|
||||||
theCharArrayTypeInfo, string->count_).GetPlace();
|
theCharArrayTypeInfo, string->count_).GetPlace();
|
||||||
@@ -180,7 +180,7 @@ KString Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
KArrayRef Kotlin_getCurrentStackTrace() {
|
KConstRef Kotlin_getCurrentStackTrace() {
|
||||||
return GetCurrentStackTrace();
|
return GetCurrentStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,25 +58,25 @@ KString Kotlin_Any_toString(KConstRef thiz);
|
|||||||
|
|
||||||
// Arrays.kt
|
// Arrays.kt
|
||||||
// TODO: those must be compiler intrinsics afterwards.
|
// TODO: those must be compiler intrinsics afterwards.
|
||||||
ArrayHeader* Kotlin_Array_clone(const ArrayHeader* thiz);
|
KRef Kotlin_Array_clone(KConstRef thiz);
|
||||||
KRef Kotlin_Array_get(const ArrayHeader* thiz, KInt index);
|
KRef Kotlin_Array_get(KConstRef thiz, KInt index);
|
||||||
void Kotlin_Array_set(ArrayHeader* thiz, KInt index, KConstRef value);
|
void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value);
|
||||||
KInt Kotlin_Array_getArrayLength(const ArrayHeader* thiz);
|
KInt Kotlin_Array_getArrayLength(KConstRef thiz);
|
||||||
|
|
||||||
ArrayHeader* Kotlin_ByteArray_clone(const ArrayHeader* thiz);
|
KRef Kotlin_ByteArray_clone(KConstRef thiz);
|
||||||
KByte Kotlin_ByteArray_get(const ArrayHeader* thiz, KInt index);
|
KByte Kotlin_ByteArray_get(KConstRef thiz, KInt index);
|
||||||
void Kotlin_ByteArray_set(ArrayHeader* thiz, KInt index, KByte value);
|
void Kotlin_ByteArray_set(KRef thiz, KInt index, KByte value);
|
||||||
KInt Kotlin_ByteArray_getArrayLength(const ArrayHeader* thiz);
|
KInt Kotlin_ByteArray_getArrayLength(KConstRef thiz);
|
||||||
|
|
||||||
ArrayHeader* Kotlin_CharArray_clone(const ArrayHeader* thiz);
|
KRef Kotlin_CharArray_clone(KConstRef thiz);
|
||||||
KChar Kotlin_CharArray_get(const ArrayHeader* thiz, KInt index);
|
KChar Kotlin_CharArray_get(KConstRef thiz, KInt index);
|
||||||
void Kotlin_CharArray_set(ArrayHeader* thiz, KInt index, KChar value);
|
void Kotlin_CharArray_set(KRef thiz, KInt index, KChar value);
|
||||||
KInt Kotlin_CharArray_getArrayLength(const ArrayHeader* thiz);
|
KInt Kotlin_CharArray_getArrayLength(KConstRef thiz);
|
||||||
|
|
||||||
ArrayHeader* Kotlin_IntArray_clone(const ArrayHeader* thiz);
|
KRef Kotlin_IntArray_clone(KConstRef thiz);
|
||||||
KInt Kotlin_IntArray_get(const ArrayHeader* thiz, KInt index);
|
KInt Kotlin_IntArray_get(KConstRef thiz, KInt index);
|
||||||
void Kotlin_IntArray_set(ArrayHeader* thiz, KInt index, KInt value);
|
void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value);
|
||||||
KInt Kotlin_IntArray_getArrayLength(const ArrayHeader* thiz);
|
KInt Kotlin_IntArray_getArrayLength(KConstRef thiz);
|
||||||
|
|
||||||
// io/Console.kt
|
// io/Console.kt
|
||||||
void Kotlin_io_Console_print(KString message);
|
void Kotlin_io_Console_print(KString message);
|
||||||
@@ -92,13 +92,13 @@ KInt Kotlin_String_hashCode(KString thiz);
|
|||||||
KBoolean Kotlin_String_equals(KString thiz, KConstRef other);
|
KBoolean Kotlin_String_equals(KString thiz, KConstRef other);
|
||||||
KInt Kotlin_String_compareTo(KString thiz, KString other);
|
KInt Kotlin_String_compareTo(KString thiz, KString other);
|
||||||
KChar Kotlin_String_get(KString thiz, KInt index);
|
KChar Kotlin_String_get(KString thiz, KInt index);
|
||||||
KString Kotlin_String_fromUtf8Array(const ArrayHeader* array, KInt start, KInt size);
|
KString Kotlin_String_fromUtf8Array(KConstRef array, KInt start, KInt size);
|
||||||
KString Kotlin_String_fromCharArray(const ArrayHeader* array, KInt start, KInt size);
|
KString Kotlin_String_fromCharArray(KConstRef array, KInt start, KInt size);
|
||||||
KString Kotlin_String_plusImpl(KString thiz, KString other);
|
KString Kotlin_String_plusImpl(KString thiz, KString other);
|
||||||
KInt Kotlin_String_getStringLength(KString thiz);
|
KInt Kotlin_String_getStringLength(KString thiz);
|
||||||
KString Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex);
|
KString Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex);
|
||||||
|
|
||||||
KArrayRef Kotlin_getCurrentStackTrace();
|
KConstRef Kotlin_getCurrentStackTrace();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ typedef float KFloat;
|
|||||||
typedef double KDouble;
|
typedef double KDouble;
|
||||||
|
|
||||||
typedef ObjHeader* KRef;
|
typedef ObjHeader* KRef;
|
||||||
typedef ArrayHeader* KArrayRef;
|
|
||||||
typedef const ObjHeader* KConstRef;
|
typedef const ObjHeader* KConstRef;
|
||||||
typedef const ArrayHeader* KString;
|
typedef const ArrayHeader* KString;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user