Rework debugging interface to allow coexisting for multiple frameworks. (#3818)
This commit is contained in:
+5
-1
@@ -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(
|
||||
|
||||
+3
@@ -105,6 +105,9 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
|
||||
}
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
generator.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
+35
-2
@@ -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.
|
||||
|
||||
-1
@@ -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.
|
||||
|
||||
+5
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -102,6 +102,7 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
|
||||
}
|
||||
|
||||
objCCodeGenerator.emitRtti()
|
||||
objCCodeGenerator.dispose()
|
||||
}
|
||||
|
||||
private fun produceFrameworkSpecific(headerLines: List<String>) {
|
||||
|
||||
@@ -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 <typename F>
|
||||
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<int32_t>(operation) >= extendedTypeInfo->debugOperationsCount_)
|
||||
return nullptr;
|
||||
return reinterpret_cast<F>(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<char* (*)(KRef)>(obj, DO_DebugBufferWithObject);
|
||||
if (impl == nullptr) return nullptr;
|
||||
return impl(obj);
|
||||
}
|
||||
|
||||
RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugBufferSizeWithObject(KRef obj) {
|
||||
auto* impl = getImpl<int32_t (*)(KRef)>(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<int32_t (*)(KRef, char*, int32_t)>(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<int32_t (*)(KRef)>(obj, DO_DebugPrint);
|
||||
if (impl == nullptr) return 0;
|
||||
return impl(obj);
|
||||
}
|
||||
|
||||
RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugIsArray(KRef obj) {
|
||||
auto* impl = getImpl<int32_t (*)(KRef)>(obj, DO_DebugIsArray);
|
||||
if (impl == nullptr) return 0;
|
||||
return impl(obj);
|
||||
}
|
||||
|
||||
RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugGetFieldCount(KRef obj) {
|
||||
auto* impl = getImpl<int32_t (*)(KRef)>(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<int32_t (*)(KRef, int32_t)>(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<void* (*)(KRef, int32_t)>(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<const char* (*)(KRef, int32_t)>(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<const char* (*)(KRef)>(obj, DO_DebugGetTypeName);
|
||||
if (impl == nullptr) return nullptr;
|
||||
return impl(obj);
|
||||
}
|
||||
|
||||
const void* Konan_debugOperationsList[] = {
|
||||
nullptr,
|
||||
reinterpret_cast<const void*>(&Konan_DebugBufferImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugBufferSizeImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugBufferWithObjectImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugBufferSizeWithObjectImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugObjectToUtf8ArrayImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugPrintImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugIsArrayImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugGetFieldCountImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugGetFieldTypeImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugGetFieldAddressImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugGetFieldNameImpl),
|
||||
reinterpret_cast<const void*>(&Konan_DebugGetTypeNameImpl)
|
||||
};
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // !KONAN_NO_DEBUG_API
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user