From c0c8ed4cb3493db8e4713523a7becfd21e59c630 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Thu, 6 Feb 2020 07:39:10 +0300 Subject: [PATCH] Rework debugging interface to allow coexisting for multiple frameworks. (#3818) --- .../backend/konan/llvm/BitcodePhases.kt | 6 +- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 3 + .../backend/konan/llvm/RTTIGenerator.kt | 37 +++- .../backend/konan/llvm/StaticDataUtils.kt | 1 - .../objcexport/ObjCExportCodeGenerator.kt | 5 + .../backend/konan/objcexport/ObjCExport.kt | 1 + runtime/src/debug/cpp/KDebug.cpp | 161 ++++++++++++++++-- runtime/src/main/cpp/Common.h | 1 + runtime/src/main/cpp/KDebug.h | 47 +++-- runtime/src/main/cpp/StdCppStubs.cpp | 9 +- runtime/src/main/cpp/TypeInfo.h | 8 +- 11 files changed, 240 insertions(+), 39 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt index 0ed9bf2510a..22a159629d8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt @@ -61,7 +61,11 @@ internal val disposeLLVMPhase = namedUnitPhase( internal val RTTIPhase = makeKonanModuleOpPhase( name = "RTTI", description = "RTTI generation", - op = { context, irModule -> irModule.acceptVoid(RTTIGeneratorVisitor(context)) } + op = { context, irModule -> + val visitor = RTTIGeneratorVisitor(context) + irModule.acceptVoid(visitor) + visitor.dispose() + } ) internal val generateDebugInfoHeaderPhase = makeKonanModuleOpPhase( diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index b6b0a9188ed..a010be125a7 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -105,6 +105,9 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid { } } + fun dispose() { + generator.dispose() + } } //-------------------------------------------------------------------------// 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 08417430cc7..c6739010468 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 @@ -395,6 +395,30 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { private fun mapRuntimeType(type: LLVMTypeRef): Int = runtimeTypeMap[type] ?: throw Error("Unmapped type: ${llvmtype2string(type)}") + private val debugRuntimeOrNull: LLVMModuleRef? by lazy { + context.config.runtimeNativeLibraries.singleOrNull { it.endsWith("debug.bc")}?.let { + parseBitcodeFile(it) + } + } + + private val debugOperations: ConstValue by lazy { + if (debugRuntimeOrNull != null) { + val external = LLVMGetNamedGlobal(debugRuntimeOrNull, "Konan_debugOperationsList")!! + val local = LLVMAddGlobal(context.llvmModule, LLVMGetElementType(LLVMTypeOf(external)),"Konan_debugOperationsList")!! + constPointer(LLVMConstBitCast(local, kInt8PtrPtr)!!) + } else { + Zero(kInt8PtrPtr) + } + } + + val debugOperationsSize: ConstValue by lazy { + if (debugRuntimeOrNull != null) { + val external = LLVMGetNamedGlobal(debugRuntimeOrNull, "Konan_debugOperationsList")!! + Int32(LLVMGetArrayLength(LLVMGetElementType(LLVMTypeOf(external)))) + } else + Int32(0) + } + private fun makeExtendedInfo(irClass: IrClass): ConstPointer { // TODO: shall we actually do that? if (context.shouldOptimize()) @@ -404,12 +428,14 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { val llvmDeclarations = context.llvmDeclarations.forClass(irClass) val bodyType = llvmDeclarations.bodyType val elementType = arrayClasses[className] + val value = if (elementType != null) { // An array type. val runtimeElementType = mapRuntimeType(elementType) Struct(runtime.extendedTypeInfoType, Int32(-runtimeElementType), - NullPointer(int32Type), NullPointer(int8Type), NullPointer(kInt8Ptr)) + NullPointer(int32Type), NullPointer(int8Type), NullPointer(kInt8Ptr), + debugOperationsSize, debugOperations) } else { data class FieldRecord(val offset: Int, val type: Int, val name: String) val fields = getStructElements(bodyType).drop(1).mapIndexed { index, type -> @@ -424,7 +450,10 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { fields.map { Int8(it.type.toByte()) }) val namesPtr = staticData.placeGlobalConstArray("kextname:$className", kInt8Ptr, fields.map { staticData.placeCStringLiteral(it.name) }) - Struct(runtime.extendedTypeInfoType, Int32(fields.size), offsetsPtr, typesPtr, namesPtr) + + Struct(runtime.extendedTypeInfoType, Int32(fields.size), offsetsPtr, typesPtr, namesPtr, + debugOperationsSize, debugOperations) + } val result = staticData.placeGlobal("", value) result.setConstant(true) @@ -566,6 +595,10 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { .joinToString(".") { it.name.asString() } ) } + + fun dispose() { + debugRuntimeOrNull?.let { LLVMDisposeModule(it) } + } } // Keep in sync with Konan_TypeFlags in TypeInfo.h. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticDataUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticDataUtils.kt index b81616d991e..978dda08df6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticDataUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticDataUtils.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.* - /** * Creates const array-typed global with given name and value. * Returns pointer to the first element of the array. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index 9bfe857a7e2..a443b45e106 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -51,6 +51,10 @@ internal open class ObjCExportCodeGeneratorBase(codegen: CodeGenerator) : ObjCCo } } + fun dispose() { + rttiGenerator.dispose() + } + // TODO: currently bridges don't have any custom `landingpad`s, // so it is correct to use [callAtFunctionScope] here. // However, exception handling probably should be refactored @@ -103,6 +107,7 @@ internal class ObjCExportBlockCodeGenerator(codegen: CodeGenerator) : ObjCExport fun generate() { emitFunctionConverters() emitBlockToKotlinFunctionConverters() + dispose() } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt index b02cd9b408d..4f1ff49c332 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt @@ -102,6 +102,7 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) { } objCCodeGenerator.emitRtti() + objCCodeGenerator.dispose() } private fun produceFrameworkSpecific(headerLines: List) { diff --git a/runtime/src/debug/cpp/KDebug.cpp b/runtime/src/debug/cpp/KDebug.cpp index b6f47cf1460..e990374da5a 100644 --- a/runtime/src/debug/cpp/KDebug.cpp +++ b/runtime/src/debug/cpp/KDebug.cpp @@ -43,7 +43,8 @@ constexpr int runtimeTypeSize[] = { 4, // FLOAT32 8, // FLOAT64 sizeof(void*), // NATIVE_PTR - 1 // BOOLEAN + 1, // BOOLEAN + 16 // VECTOR128 }; constexpr int runtimeTypeAlignment[] = { @@ -56,24 +57,59 @@ constexpr int runtimeTypeAlignment[] = { alignof(float), // FLOAT32 alignof(double), // FLOAT64 alignof(void*), // NATIVE_PTR - 1 // BOOLEAN + 1, // BOOLEAN + 16 // VECTOR128 }; -} // namespace +// Never ever change numbering in this enum, as it will break debugging of older binaries. +enum Konan_DebugOperation { + DO_DebugBuffer = 1, + DO_DebugBufferSize = 2, + DO_DebugBufferWithObject = 3, + DO_DebugBufferSizeWithObject = 4, + DO_DebugObjectToUtf8Array = 5, + DO_DebugPrint = 6, + DO_DebugIsArray = 7, + DO_DebugGetFieldCount = 8, + DO_DebugGetFieldType = 9, + DO_DebugGetFieldAddress = 10, + DO_DebugGetFieldName = 11, + DO_DebugGetTypeName = 12, +}; -extern "C" { +template +F getImpl(KRef obj, Konan_DebugOperation operation) { + if (obj == nullptr) + return nullptr; + auto* typeInfo = obj->type_info(); + auto* extendedTypeInfo = typeInfo->extendedInfo_; + + if (extendedTypeInfo == nullptr) + return nullptr; + if (static_cast(operation) >= extendedTypeInfo->debugOperationsCount_) + return nullptr; + return reinterpret_cast(extendedTypeInfo->debugOperations_[operation]); +} // Buffer that can be used by debugger for inspections. -RUNTIME_USED char* Konan_DebugBuffer() { +char* Konan_DebugBufferImpl() { return debugBuffer; } -RUNTIME_USED int Konan_DebugBufferSize() { +int Konan_DebugBufferSizeImpl() { + return sizeof(debugBuffer); +} + +char* Konan_DebugBufferWithObjectImpl(KRef obj) { + return debugBuffer; +} + +int Konan_DebugBufferSizeWithObjectImpl(KRef obj) { 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) { +int32_t Konan_DebugObjectToUtf8ArrayImpl(KRef obj, char* buffer, int32_t bufferSize) { ObjHolder stringHolder; auto data = KonanObjectToUtf8Array(obj, stringHolder.slot())->array(); if (data == nullptr) return 0; @@ -83,23 +119,23 @@ RUNTIME_USED KInt Konan_DebugObjectToUtf8Array(KRef obj, char* buffer, KInt buff return toCopy + 1; } -RUNTIME_USED KInt Konan_DebugPrint(KRef obj) { - KInt size = Konan_DebugObjectToUtf8Array(obj, Konan_DebugBuffer(), Konan_DebugBufferSize()); +int32_t Konan_DebugPrintImpl(KRef obj) { + int32_t size = Konan_DebugObjectToUtf8Array(obj, Konan_DebugBuffer(), Konan_DebugBufferSize()); if (size > 1) konan::consoleWriteUtf8(Konan_DebugBuffer(), size - 1); return 0; } -RUNTIME_USED int Konan_DebugIsArray(KRef obj) { +int32_t Konan_DebugIsArrayImpl(KRef obj) { return obj == nullptr || IsArray(obj) ? 1 : 0; } -RUNTIME_USED int Konan_DebugGetFieldCount(KRef obj) { +int32_t Konan_DebugGetFieldCountImpl(KRef obj) { if (obj == nullptr) return 0; - auto typeInfo = obj->type_info(); - auto extendedTypeInfo = typeInfo->extendedInfo_; + auto* typeInfo = obj->type_info(); + auto* extendedTypeInfo = typeInfo->extendedInfo_; if (extendedTypeInfo == nullptr) return 0; @@ -110,8 +146,7 @@ RUNTIME_USED int Konan_DebugGetFieldCount(KRef obj) { return extendedTypeInfo->fieldsCount_; } - -RUNTIME_USED int Konan_DebugGetFieldType(KRef obj, int index) { +int32_t Konan_DebugGetFieldTypeImpl(KRef obj, int32_t index) { if (obj == nullptr || index < 0) return Konan_RuntimeType::RT_INVALID; @@ -130,7 +165,7 @@ RUNTIME_USED int Konan_DebugGetFieldType(KRef obj, int index) { return extendedTypeInfo->fieldTypes_[index]; } -RUNTIME_USED void* Konan_DebugGetFieldAddress(KRef obj, int index) { +void* Konan_DebugGetFieldAddressImpl(KRef obj, int32_t index) { if (obj == nullptr || index < 0) return nullptr; @@ -157,7 +192,7 @@ RUNTIME_USED void* Konan_DebugGetFieldAddress(KRef obj, int index) { } // Compute address of field or an array element at the index, or null, if incorrect. -RUNTIME_USED const char* Konan_DebugGetFieldName(KRef obj, int index) { +const char* Konan_DebugGetFieldNameImpl(KRef obj, int32_t index) { if (obj == nullptr || index < 0) return nullptr; @@ -177,7 +212,7 @@ RUNTIME_USED const char* Konan_DebugGetFieldName(KRef obj, int index) { return extendedTypeInfo->fieldNames_[index]; } -RUNTIME_USED const char* Konan_DebugGetTypeName(KRef obj) { +const char* Konan_DebugGetTypeNameImpl(KRef obj) { if (obj == nullptr) return nullptr; @@ -188,6 +223,96 @@ RUNTIME_USED const char* Konan_DebugGetTypeName(KRef obj) { return CreateCStringFromString(type_info->relativeName_); } +} // namespace + +extern "C" { + +RUNTIME_USED RUNTIME_WEAK char* Konan_DebugBuffer() { + return Konan_DebugBufferImpl(); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugBufferSize() { + return Konan_DebugBufferSizeImpl(); +} + +RUNTIME_USED RUNTIME_WEAK char* Konan_DebugBufferWithObject(KRef obj) { + auto* impl = getImpl(obj, DO_DebugBufferWithObject); + if (impl == nullptr) return nullptr; + return impl(obj); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugBufferSizeWithObject(KRef obj) { + auto* impl = getImpl(obj, DO_DebugBufferSizeWithObject); + if (impl == nullptr) return 0; + return impl(obj); +} + +// Auxilary function which can be called by developer/debugger to inspect an object. +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugObjectToUtf8Array(KRef obj, char* buffer, int32_t bufferSize) { + auto* impl = getImpl(obj, DO_DebugObjectToUtf8Array); + if (impl == nullptr) return 0; + return impl(obj, buffer, bufferSize); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugPrint(KRef obj) { + auto* impl = getImpl(obj, DO_DebugPrint); + if (impl == nullptr) return 0; + return impl(obj); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugIsArray(KRef obj) { + auto* impl = getImpl(obj, DO_DebugIsArray); + if (impl == nullptr) return 0; + return impl(obj); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugGetFieldCount(KRef obj) { + auto* impl = getImpl(obj, DO_DebugGetFieldCount); + if (impl == nullptr) return 0; + return impl(obj); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugGetFieldType(KRef obj, int32_t index) { + auto* impl = getImpl(obj, DO_DebugGetFieldType); + if (impl == nullptr) return 0; + return impl(obj, index); +} + +RUNTIME_USED RUNTIME_WEAK void* Konan_DebugGetFieldAddress(KRef obj, int32_t index) { + auto* impl = getImpl(obj, DO_DebugGetFieldAddress); + if (impl == nullptr) return nullptr; + return impl(obj, index); +} + +// Compute address of field or an array element at the index, or null, if incorrect. +RUNTIME_USED RUNTIME_WEAK const char* Konan_DebugGetFieldName(KRef obj, int32_t index) { + auto* impl = getImpl(obj, DO_DebugGetFieldName); + if (impl == nullptr) return nullptr; + return impl(obj, index); +} + +RUNTIME_USED RUNTIME_WEAK const char* Konan_DebugGetTypeName(KRef obj) { + auto* impl = getImpl(obj, DO_DebugGetTypeName); + if (impl == nullptr) return nullptr; + return impl(obj); +} + +const void* Konan_debugOperationsList[] = { + nullptr, + reinterpret_cast(&Konan_DebugBufferImpl), + reinterpret_cast(&Konan_DebugBufferSizeImpl), + reinterpret_cast(&Konan_DebugBufferWithObjectImpl), + reinterpret_cast(&Konan_DebugBufferSizeWithObjectImpl), + reinterpret_cast(&Konan_DebugObjectToUtf8ArrayImpl), + reinterpret_cast(&Konan_DebugPrintImpl), + reinterpret_cast(&Konan_DebugIsArrayImpl), + reinterpret_cast(&Konan_DebugGetFieldCountImpl), + reinterpret_cast(&Konan_DebugGetFieldTypeImpl), + reinterpret_cast(&Konan_DebugGetFieldAddressImpl), + reinterpret_cast(&Konan_DebugGetFieldNameImpl), + reinterpret_cast(&Konan_DebugGetTypeNameImpl) +}; + } // extern "C" #endif // !KONAN_NO_DEBUG_API diff --git a/runtime/src/main/cpp/Common.h b/runtime/src/main/cpp/Common.h index 8be6483ac05..71b44af940e 100644 --- a/runtime/src/main/cpp/Common.h +++ b/runtime/src/main/cpp/Common.h @@ -22,6 +22,7 @@ #define RUNTIME_CONST __attribute__((const)) #define RUNTIME_PURE __attribute__((pure)) #define RUNTIME_USED __attribute__((used)) +#define RUNTIME_WEAK __attribute__((weak)) #define ALWAYS_INLINE __attribute__((always_inline)) #define NO_INLINE __attribute__((noinline)) diff --git a/runtime/src/main/cpp/KDebug.h b/runtime/src/main/cpp/KDebug.h index 30a80025208..ddf69b952bb 100644 --- a/runtime/src/main/cpp/KDebug.h +++ b/runtime/src/main/cpp/KDebug.h @@ -28,40 +28,65 @@ extern "C" { #endif +// PLEASE READ: please do not alter signatures of the existing functions, and when adding +// the new function please do not forget to add new functions into the debug operations list. + // Get memory buffer where debugger can put data in Konan app process. -RUNTIME_USED +RUNTIME_USED RUNTIME_WEAK char* Konan_DebugBuffer(); +// Same, but runtime-specific. +RUNTIME_USED RUNTIME_WEAK +char* Konan_DebugBufferWithObject(KRef obj); + // Get size of memory buffer where debugger can put data in Konan app process. -RUNTIME_USED +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugBufferSize(); +// Same, but runtime-specific. +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugBufferSizeWithObject(KRef obj); + // Put string representation of an object to the provided buffer. -RUNTIME_USED -int32_t Konan_DebugObjectToUtf8Array(KRef obj, char* buffer, int bufferSize); +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugObjectToUtf8Array(KRef obj, char* buffer, int32_t bufferSize); // Print to console string representation of an object. -RUNTIME_USED +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugPrint(KRef obj); // Returns 1 if obj refers to an array, string or binary blob and 0 otherwise. -RUNTIME_USED int Konan_DebugIsArray(KRef obj); +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugIsArray(KRef obj); // Returns number of fields in an objects, or elements in an array. -RUNTIME_USED int Konan_DebugGetFieldCount(KRef obj); +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugGetFieldCount(KRef obj); // Compute type of field or an array element at the index, or 0, if incorrect, // see Konan_RuntimeType. -RUNTIME_USED int Konan_DebugGetFieldType(KRef obj, int index); +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugGetFieldType(KRef obj, int32_t index); // Compute address of field or an array element at the index, or null, if incorrect. -RUNTIME_USED void* Konan_DebugGetFieldAddress(KRef obj, int index); +RUNTIME_USED RUNTIME_WEAK +void* Konan_DebugGetFieldAddress(KRef obj, int32_t index); // Compute address of field or an array element at the index, or null, if incorrect. -RUNTIME_USED const char* Konan_DebugGetFieldName(KRef obj, int index); +RUNTIME_USED RUNTIME_WEAK +const char* Konan_DebugGetFieldName(KRef obj, int32_t index); // Returns name of type. -RUNTIME_USED const char* Konan_DebugGetTypeName(KRef obj); +RUNTIME_USED RUNTIME_WEAK +const char* Konan_DebugGetTypeName(KRef obj); + +/** + * Given an object finds debugger interface operation suitable for manipulation with this object. + * Important for cases where multiple K/N runtimes coexist in the same address space and debugger + * doesn't know which debug operation to use on particular instance. + */ +RUNTIME_USED RUNTIME_WEAK +void* Konan_DebugGetOperation(KRef obj, /* Konan_DebugOperation */ int32_t operation); #ifdef __cplusplus } diff --git a/runtime/src/main/cpp/StdCppStubs.cpp b/runtime/src/main/cpp/StdCppStubs.cpp index f1fda87f181..09fd4e6a64c 100644 --- a/runtime/src/main/cpp/StdCppStubs.cpp +++ b/runtime/src/main/cpp/StdCppStubs.cpp @@ -22,7 +22,7 @@ // This function replaces `__cxa_demangle` defined in GNU libstdc++ // by adding `--defsym` flag in `konan.properties`. // This allows to avoid linking `__cxa_demangle` and its dependencies, thus reducing binary size. -RUNTIME_USED extern "C" char* Konan_cxa_demangle( +RUNTIME_USED RUNTIME_WEAK extern "C" char* Konan_cxa_demangle( const char* __mangled_name, char* __output_buffer, size_t* __length, int* __status ) { @@ -31,9 +31,10 @@ RUNTIME_USED extern "C" char* Konan_cxa_demangle( } namespace std { - void __throw_length_error(const char* __s __attribute__((unused))) { - RuntimeAssert(false, __s); - } +void __throw_length_error(const char* __s __attribute__((unused))) { + RuntimeAssert(false, __s); } +} // namespace std + #endif // KONAN_LINUX || KONAN_WINDOWS diff --git a/runtime/src/main/cpp/TypeInfo.h b/runtime/src/main/cpp/TypeInfo.h index 65898ac26d5..80dd2ed99f2 100644 --- a/runtime/src/main/cpp/TypeInfo.h +++ b/runtime/src/main/cpp/TypeInfo.h @@ -49,7 +49,8 @@ enum Konan_RuntimeType { RT_FLOAT32 = 6, RT_FLOAT64 = 7, RT_NATIVE_PTR = 8, - RT_BOOLEAN = 9 + RT_BOOLEAN = 9, + RT_VECTOR128 = 10 }; // Flags per type. @@ -77,7 +78,10 @@ struct ExtendedTypeInfo { const uint8_t* fieldTypes_; // Names of all fields. const char** fieldNames_; - // TODO: do we want any other info here? + // Number of supported debug operations. + int32_t debugOperationsCount_; + // Table of supported debug operations functions. + void** debugOperations_; }; typedef void const* VTableElement;