Add Kotlin object inspection to simplify debugging (#763)
This commit is contained in:
+9
-5
@@ -211,6 +211,10 @@ internal class LinkStage(val context: Context) {
|
||||
private val emitted = context.bitcodeFileName
|
||||
private val libraries = context.config.libraries
|
||||
|
||||
private fun MutableList<String>.addNonEmpty(elements: List<String>) {
|
||||
addAll(elements.filter { !it.isEmpty() })
|
||||
}
|
||||
|
||||
private fun llvmLto(files: List<BitcodeFile>): ObjectFile {
|
||||
val tmpCombined = createTempFile("combined", ".o")
|
||||
tmpCombined.deleteOnExit()
|
||||
@@ -218,13 +222,13 @@ internal class LinkStage(val context: Context) {
|
||||
|
||||
val tool = distribution.llvmLto
|
||||
val command = mutableListOf(tool, "-o", combined)
|
||||
command.addAll(platform.llvmLtoFlags)
|
||||
command.addNonEmpty(platform.llvmLtoFlags)
|
||||
when {
|
||||
optimize -> command.addAll(platform.llvmLtoOptFlags)
|
||||
debug -> command.addAll(platform.llvmDebugOptFlags)
|
||||
else -> command.addAll(platform.llvmLtoNooptFlags)
|
||||
optimize -> command.addNonEmpty(platform.llvmLtoOptFlags)
|
||||
debug -> command.addNonEmpty(platform.llvmDebugOptFlags)
|
||||
else -> command.addNonEmpty(platform.llvmLtoNooptFlags)
|
||||
}
|
||||
command.addAll(files)
|
||||
command.addNonEmpty(files)
|
||||
runTool(*command.toTypedArray())
|
||||
|
||||
return combined
|
||||
|
||||
@@ -30,7 +30,7 @@ targetToolchain.osx = clang-llvm-3.9.0-darwin-macos
|
||||
arch.osx = x86_64
|
||||
targetSysRoot.osx = target-sysroot-1-darwin-macos
|
||||
libffiDir.osx = libffi-3.2.1-2-darwin-macos
|
||||
llvmLtoFlags.osx = -exported-symbol=_Konan_main
|
||||
llvmLtoFlags.osx =
|
||||
llvmLtoOptFlags.osx = -O3 -function-sections
|
||||
llvmLtoNooptFlags.osx = -O1
|
||||
linkerKonanFlags.osx = -lc++
|
||||
@@ -55,7 +55,7 @@ arch.ios = arm64
|
||||
entrySelector.ios = -alias _Konan_main _main
|
||||
targetSysRoot.ios = target-sysroot-2-darwin-ios
|
||||
libffiDir.ios = libffi-3.2.1-2-darwin-ios
|
||||
llvmLtoFlags.ios = -exported-symbol=_Konan_main
|
||||
llvmLtoFlags.ios =
|
||||
llvmLtoOptFlags.ios = -O3 -function-sections
|
||||
linkerDebugFlags.ios = -S
|
||||
llvmLtoNooptFlags.ios = -O1
|
||||
@@ -76,7 +76,7 @@ arch.ios_sim = x86_64
|
||||
entrySelector.ios_sim = -alias _Konan_main _main
|
||||
targetSysRoot.ios_sim = target-sysroot-1-darwin-ios-sim
|
||||
libffiDir.ios_sim = libffi-3.2.1-2-darwin-ios-sim
|
||||
llvmLtoFlags.ios_sim = -exported-symbol=_Konan_main
|
||||
llvmLtoFlags.ios_sim =
|
||||
llvmLtoOptFlags.ios_sim = -O3 -function-sections
|
||||
llvmLtoNooptFlags.ios_sim = -O1
|
||||
linkerKonanFlags.ios_sim = -lc++
|
||||
@@ -97,7 +97,7 @@ targetSysRoot.linux = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-g
|
||||
libffiDir.linux = libffi-3.2.1-2-linux-x86-64
|
||||
# targetSysroot-relative.
|
||||
libGcc.linux = ../../lib/gcc/x86_64-unknown-linux-gnu/4.8.5
|
||||
llvmLtoFlags.linux = -exported-symbol=Konan_main
|
||||
llvmLtoFlags.linux =
|
||||
llvmLtoOptFlags.linux = -O3 -function-sections
|
||||
llvmLtoNooptFlags.linux = -O1
|
||||
llvmLlcFlags.linux = -march=x86-64
|
||||
@@ -132,7 +132,7 @@ libffiDir.raspberrypi = libffi-3.2.1-2-raspberrypi
|
||||
linkerKonanFlags.raspberrypi = -Bstatic -lstdc++ -Bdynamic -ldl -lm -lpthread
|
||||
# targetSysroot-relative.
|
||||
libGcc.raspberrypi = lib/gcc/arm-linux-gnueabihf/4.8.3
|
||||
llvmLtoFlags.raspberrypi = -exported-symbol=Konan_main
|
||||
llvmLtoFlags.raspberrypi =
|
||||
llvmLtoOptFlags.raspberrypi = -O3 -function-sections
|
||||
llvmLtoNooptFlags.raspberrypi = -O1
|
||||
dynamicLinker.raspberrypi = /lib/ld-linux-armhf.so.3
|
||||
@@ -159,7 +159,7 @@ dependencies.linux-android_arm32 = \
|
||||
|
||||
quadruple.android_arm32 = arm-linux-androideabi
|
||||
entrySelector.android_arm32 = -Wl,--defsym -Wl,main=Konan_main
|
||||
llvmLtoFlags.android_arm32 = -exported-symbol=Konan_main -emulated-tls -relocation-model=pic
|
||||
llvmLtoFlags.android_arm32 = -emulated-tls -relocation-model=pic
|
||||
llvmLtoOptFlags.android_arm32 = -O3 -function-sections
|
||||
linkerDebugFlags.android_arm32 = -Wl,-S
|
||||
llvmLtoNooptFlags.android_arm32 = -O1
|
||||
@@ -184,7 +184,7 @@ dependencies.linux-android_arm64 = \
|
||||
|
||||
quadruple.android_arm64 = aarch64-linux-android
|
||||
entrySelector.android_arm64 = -Wl,--defsym -Wl,main=Konan_main
|
||||
llvmLtoFlags.android_arm64 = -exported-symbol=Konan_main -emulated-tls -relocation-model=pic
|
||||
llvmLtoFlags.android_arm64 = -emulated-tls -relocation-model=pic
|
||||
targetSysRoot.android_arm64 = target-sysroot-21-android_arm64
|
||||
libffiDir.android_arm64 = libffi-3.2.1-2-android_arm64
|
||||
linkerKonanFlags.android_arm64 = -lm -latomic -lstdc++ -landroid
|
||||
@@ -198,7 +198,7 @@ targetToolchain.mingw = msys2-mingw-w64-x86_64-gcc-6.3.0-clang-llvm-3.9.1-window
|
||||
quadruple.mingw = x86_64-w64-mingw32
|
||||
targetSysRoot.mingw = msys2-mingw-w64-x86_64-gcc-6.3.0-clang-llvm-3.9.1-windows-x86-64
|
||||
libffiDir.mingw = libffi-3.2.1-mingw-w64-x86-64
|
||||
llvmLtoFlags.mingw = -exported-symbol=Konan_main
|
||||
llvmLtoFlags.mingw =
|
||||
llvmLtoOptFlags.mingw = -O3 -function-sections
|
||||
llvmLtoNooptFlags.mingw = -O1
|
||||
linkerDebugFlags.mingw = -Wl,-S
|
||||
@@ -219,10 +219,11 @@ dependencies.osx-wasm32 = \
|
||||
|
||||
quadruple.wasm32 = wasm32
|
||||
entrySelector.wasm32 = -Wl,--defsym -Wl,main=Konan_main
|
||||
llvmLtoFlags.wasm32 = -exported-symbol=Konan_main
|
||||
llvmLtoFlags.wasm32 =
|
||||
targetSysRoot.wasm32 = target-sysroot-1-wasm
|
||||
clangFlags.wasm32 = -O1 -fno-rtti -fno-exceptions \
|
||||
-D_LIBCPP_ABI_VERSION=2 -DKONAN_NO_FFI=1 -DKONAN_NO_THREADS=1 -DKONAN_NO_EXCEPTIONS=1 \
|
||||
-DKONAN_NO_DEBUG_API=1 \
|
||||
-nostdinc -Xclang -nobuiltininc -Xclang -nostdsysteminc \
|
||||
-Xclang -isystem<sysrootDir>/include/libcxx -Xclang -isystem<sysrootDir>/lib/libcxxabi/include \
|
||||
-Xclang -isystem<sysrootDir>/include/compat -Xclang -isystem<sysrootDir>/include/libc
|
||||
|
||||
@@ -38,7 +38,7 @@ OBJ_GETTER(setupArgs, int argc, const char** argv) {
|
||||
//--- main --------------------------------------------------------------------//
|
||||
extern "C" KInt Konan_start(const ObjHeader*);
|
||||
|
||||
extern "C" int Konan_main(int argc, const char** argv) {
|
||||
extern "C" RUNTIME_USED int Konan_main(int argc, const char** argv) {
|
||||
RuntimeState* state = InitRuntime();
|
||||
|
||||
if (state == nullptr) {
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#define RUNTIME_NOTHROW __attribute__((nothrow))
|
||||
#define RUNTIME_CONST __attribute__((const))
|
||||
#define RUNTIME_PURE __attribute__((pure))
|
||||
#define RUNTIME_USED __attribute__((used))
|
||||
|
||||
#if KONAN_NO_THREADS
|
||||
#define THREAD_LOCAL_VARIABLE
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 "KDebug.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Assert.h"
|
||||
#include "Memory.h"
|
||||
#include "Natives.h"
|
||||
#include "Porting.h"
|
||||
#include "Types.h"
|
||||
|
||||
#ifndef KONAN_NO_DEBUG_API
|
||||
|
||||
extern "C" OBJ_GETTER(KonanObjectToUtf8Array, KRef object);
|
||||
|
||||
namespace {
|
||||
|
||||
char debugBuffer[4096];
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Buffer that can be used by debugger for inspections.
|
||||
RUNTIME_USED char* Konan_DebugBuffer() {
|
||||
return debugBuffer;
|
||||
}
|
||||
|
||||
RUNTIME_USED int Konan_DebugBufferSize() {
|
||||
return sizeof(debugBuffer);
|
||||
}
|
||||
|
||||
// Auxilary function which can be called by developer/debugger to inspect an object.
|
||||
RUNTIME_USED KInt Konan_DebugObjectToUtf8Array(KRef obj, char* buffer, KInt bufferSize) {
|
||||
ObjHolder stringHolder;
|
||||
auto data = KonanObjectToUtf8Array(obj, stringHolder.slot())->array();
|
||||
if (data == nullptr) return 0;
|
||||
KInt toCopy = data->count_ > bufferSize - 1 ? bufferSize - 1 : data->count_;
|
||||
::memcpy(buffer, ByteArrayAddressOfElementAt(data, 0), toCopy);
|
||||
buffer[toCopy + 1] = '\0';
|
||||
return toCopy + 1;
|
||||
}
|
||||
|
||||
RUNTIME_USED KInt Konan_DebugPrint(KRef obj) {
|
||||
KInt size = Konan_DebugObjectToUtf8Array(obj, Konan_DebugBuffer(), Konan_DebugBufferSize());
|
||||
if (size > 1)
|
||||
konan::consoleWriteUtf8(Konan_DebugBuffer(), size - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
RUNTIME_USED int Konan_DebugGetFieldType(KRef obj, int index) {
|
||||
if (obj == nullptr || index < 0) return Konan_RuntimeType::INVALID;
|
||||
auto typeInfo = obj->type_info();
|
||||
if (typeInfo->instanceSize_ < 0) {
|
||||
// Arrays.
|
||||
if (index >= obj->array()->count_) return Konan_RuntimeType::INVALID;
|
||||
if (typeInfo == theArrayTypeInfo) {
|
||||
return Konan_RuntimeType::OBJECT;
|
||||
}
|
||||
// TODO: support other array types.
|
||||
return Konan_RuntimeType::INVALID;
|
||||
}
|
||||
|
||||
// TODO: support primitive type fields as well!
|
||||
if (index >= typeInfo->objOffsetsCount_) return Konan_RuntimeType::INVALID;
|
||||
return Konan_RuntimeType::OBJECT;
|
||||
}
|
||||
|
||||
RUNTIME_USED void* Konan_DebugGetFieldAddress(KRef obj, int index) {
|
||||
if (obj == nullptr || index < 0) return nullptr;
|
||||
auto typeInfo = obj->type_info();
|
||||
if (typeInfo->instanceSize_ < 0) {
|
||||
// Arrays.
|
||||
if (index >= obj->array()->count_) return nullptr;
|
||||
if (typeInfo == theArrayTypeInfo) {
|
||||
return ArrayAddressOfElementAt(obj->array(), index);
|
||||
}
|
||||
// TODO: support other array types.
|
||||
return nullptr;
|
||||
}
|
||||
// TODO: support primitive type fields as well!
|
||||
if (index >= typeInfo->objOffsetsCount_) return nullptr;
|
||||
return reinterpret_cast<uint8_t*>(obj + 1) + typeInfo->objOffsets_[index];
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // !KONAN_NO_DEBUG_API
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RUNTIME_KDEBUG_H
|
||||
#define RUNTIME_KDEBUG_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Memory.h"
|
||||
#include "Types.h"
|
||||
#include "TypeInfo.h"
|
||||
|
||||
#ifndef KONAN_NO_DEBUG_API
|
||||
|
||||
// Type for runtime representation of Konan object.
|
||||
enum Konan_RuntimeType {
|
||||
INVALID = 0,
|
||||
OBJECT = 1,
|
||||
INT8 = 2,
|
||||
INT16 = 3,
|
||||
INT32 = 4,
|
||||
INT64 = 5,
|
||||
FLOAT32 = 6,
|
||||
FLOAT64 = 7
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Get memory buffer where debugger can put data in Konan app process.
|
||||
RUNTIME_USED
|
||||
char* Konan_DebugBuffer();
|
||||
|
||||
// Get size of memory buffer where debugger can put data in Konan app process.
|
||||
RUNTIME_USED
|
||||
int Konan_DebugBufferSize();
|
||||
|
||||
// Put string representation of an object to the provided buffer.
|
||||
RUNTIME_USED
|
||||
int Konan_DebugObjectToUtf8Array(KRef obj, char* buffer, int bufferSize);
|
||||
|
||||
// Print to console string representation of an object.
|
||||
RUNTIME_USED
|
||||
int Konan_DebugPrint(KRef obj);
|
||||
|
||||
// Compute type of field or an array element at the index, or 0, if incorrect,
|
||||
// see Konan_RuntimeType.
|
||||
// TODO: currently, only object fields are supported, will be fixed soon.
|
||||
RUNTIME_USED int Konan_DebugGetFieldType(KRef obj, int index);
|
||||
|
||||
// Compute address of field or an array element at the index, or null, if incorrect.
|
||||
// TODO: currently, only object fields are supported, will be fixed soon.
|
||||
RUNTIME_USED void* Konan_DebugGetFieldAddress(KRef obj, int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !KONAN_NO_DEBUG_API
|
||||
|
||||
#endif // RUNTIME_KDEBUG_H
|
||||
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef RUNTIME_STRING_H
|
||||
#define RUNTIME_STRING_H
|
||||
#ifndef RUNTIME_KSTRING_H
|
||||
#define RUNTIME_KSTRING_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Memory.h"
|
||||
@@ -52,4 +52,4 @@ int binarySearchRange(const T* array, int arrayLength, T needle) {
|
||||
return middle - (needle < value ? 1 : 0);
|
||||
}
|
||||
|
||||
#endif // RUNTIME_STRING_H
|
||||
#endif // RUNTIME_KSTRING_H
|
||||
|
||||
@@ -23,54 +23,60 @@
|
||||
#include "Memory.h"
|
||||
#include "Natives.h"
|
||||
#include "KString.h"
|
||||
#include "Porting.h"
|
||||
#include "Types.h"
|
||||
|
||||
namespace {
|
||||
|
||||
char int_to_digit(uint32_t value) {
|
||||
if (value < 10) {
|
||||
return '0' + value;
|
||||
} else {
|
||||
return 'a' + (value - 10);
|
||||
}
|
||||
}
|
||||
|
||||
// Radix is checked on the Kotlin side.
|
||||
template <typename T> OBJ_GETTER(Kotlin_toStringRadix, T value, KInt radix) {
|
||||
if (value == 0) {
|
||||
RETURN_RESULT_OF(CreateStringFromCString, "0");
|
||||
}
|
||||
char cstring[sizeof(T) * CHAR_BIT + 1];
|
||||
bool negative = (value < 0);
|
||||
if (!negative) {
|
||||
value = -value;
|
||||
}
|
||||
|
||||
int32_t length = 0;
|
||||
while (value < 0) {
|
||||
cstring[length++] = int_to_digit(-(value % radix));
|
||||
value /= radix;
|
||||
}
|
||||
if (negative) {
|
||||
cstring[length++] = '-';
|
||||
}
|
||||
for (int i = 0, j = length - 1; i < j; i++, j--) {
|
||||
char tmp = cstring[i];
|
||||
cstring[i] = cstring[j];
|
||||
cstring[j] = tmp;
|
||||
}
|
||||
cstring[length] = '\0';
|
||||
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
||||
char int_to_digit(uint32_t value) {
|
||||
if (value < 10) {
|
||||
return '0' + value;
|
||||
} else {
|
||||
return 'a' + (value - 10);
|
||||
}
|
||||
}
|
||||
|
||||
// Radix is checked on the Kotlin side.
|
||||
template <typename T> OBJ_GETTER(Kotlin_toStringRadix, T value, KInt radix) {
|
||||
if (value == 0) {
|
||||
RETURN_RESULT_OF(CreateStringFromCString, "0");
|
||||
}
|
||||
char cstring[sizeof(T) * CHAR_BIT + 1];
|
||||
bool negative = (value < 0);
|
||||
if (!negative) {
|
||||
value = -value;
|
||||
}
|
||||
|
||||
int32_t length = 0;
|
||||
while (value < 0) {
|
||||
cstring[length++] = int_to_digit(-(value % radix));
|
||||
value /= radix;
|
||||
}
|
||||
if (negative) {
|
||||
cstring[length++] = '-';
|
||||
}
|
||||
for (int i = 0, j = length - 1; i < j; i++, j--) {
|
||||
char tmp = cstring[i];
|
||||
cstring[i] = cstring[j];
|
||||
cstring[j] = tmp;
|
||||
}
|
||||
cstring[length] = '\0';
|
||||
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
OBJ_GETTER(Kotlin_Any_toString, KConstRef thiz) {
|
||||
char cstring[80];
|
||||
snprintf(cstring, sizeof(cstring), "%s %p type %p",
|
||||
IsArray(thiz) ? "array" : "object",
|
||||
thiz, thiz->type_info_);
|
||||
if (IsArray(thiz)) {
|
||||
konan::snprintf(cstring, sizeof(cstring), "%d@%p: array of %d",
|
||||
Kotlin_Any_hashCode(thiz), thiz->type_info_, thiz->array()->count_);
|
||||
} else {
|
||||
konan::snprintf(cstring, sizeof(cstring), "%d@%p: object",
|
||||
Kotlin_Any_hashCode(thiz), thiz->type_info_);
|
||||
}
|
||||
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
||||
}
|
||||
|
||||
@@ -113,21 +119,4 @@ OBJ_GETTER(Kotlin_Long_toStringRadix, KLong value, KInt radix) {
|
||||
RETURN_RESULT_OF(Kotlin_toStringRadix<KLong>, value, radix)
|
||||
}
|
||||
|
||||
// TODO: use David Gay's dtoa() here instead. It's *very* big and ugly.
|
||||
OBJ_GETTER(Kotlin_Float_toString, KFloat value) {
|
||||
char cstring[32];
|
||||
snprintf(cstring, sizeof(cstring), "%G", value);
|
||||
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
||||
}
|
||||
|
||||
OBJ_GETTER(Kotlin_Double_toString, KDouble value) {
|
||||
char cstring[32];
|
||||
snprintf(cstring, sizeof(cstring), "%G", value);
|
||||
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
||||
}
|
||||
|
||||
OBJ_GETTER(Kotlin_Boolean_toString, KBoolean value) {
|
||||
RETURN_RESULT_OF(CreateStringFromCString, value ? "true" : "false");
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package konan.internal
|
||||
|
||||
import kotlin.text.toUtf8Array
|
||||
|
||||
// Called by debugger.
|
||||
@ExportForCppRuntime
|
||||
fun KonanObjectToUtf8Array(value: Any?): ByteArray {
|
||||
val string = when (value) {
|
||||
is Array<*> -> value.contentToString()
|
||||
is CharArray -> value.contentToString()
|
||||
is BooleanArray -> value.contentToString()
|
||||
is ByteArray -> value.contentToString()
|
||||
is ShortArray -> value.contentToString()
|
||||
is IntArray -> value.contentToString()
|
||||
is LongArray -> value.contentToString()
|
||||
is FloatArray -> value.contentToString()
|
||||
is DoubleArray -> value.contentToString()
|
||||
else -> value.toString()
|
||||
}
|
||||
return toUtf8Array(string, 0, string.length)
|
||||
}
|
||||
@@ -54,10 +54,7 @@ public final class Boolean : Comparable<Boolean> {
|
||||
public override fun equals(other: Any?): Boolean =
|
||||
other is Boolean && konan.internal.areEqualByValue(this, other)
|
||||
|
||||
@SymbolName("Kotlin_Boolean_toString")
|
||||
external public override fun toString(): String
|
||||
public override fun toString() = if (this) "true" else "false"
|
||||
|
||||
public override fun hashCode(): Int {
|
||||
return if (this) 1 else 0;
|
||||
}
|
||||
public override fun hashCode() = if (this) 1 else 0
|
||||
}
|
||||
Reference in New Issue
Block a user