Fix skipping top stack frames in optimized -Xg0 binaries
Also do some refactoring.
This commit is contained in:
committed by
SvyatoslavScherbina
parent
e65ae1c9f7
commit
61a19e0ccf
+1
-2
@@ -312,8 +312,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
|||||||
val result = LLVMAddFunction(llvmModule, name, type)!!
|
val result = LLVMAddFunction(llvmModule, name, type)!!
|
||||||
attributes.forEach {
|
attributes.forEach {
|
||||||
val kindId = getLlvmAttributeKindId(it)
|
val kindId = getLlvmAttributeKindId(it)
|
||||||
val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(type), kindId, 0)!!
|
addLlvmFunctionEnumAttribute(result, kindId)
|
||||||
LLVMAddAttributeAtIndex(result, LLVMAttributeFunctionIndex, attribute)
|
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.konan.llvm
|
||||||
|
|
||||||
|
import llvm.LLVMValueRef
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.types.isNothing
|
||||||
|
import org.jetbrains.kotlin.ir.util.isThrowable
|
||||||
|
|
||||||
|
internal fun addLlvmAttributes(context: Context, irFunction: IrFunction, llvmFunction: LLVMValueRef) {
|
||||||
|
if (irFunction.returnType.isNothing()) {
|
||||||
|
setFunctionNoReturn(llvmFunction)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mustNotInline(context, irFunction)) {
|
||||||
|
setFunctionNoInline(llvmFunction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mustNotInline(context: Context, irFunction: IrFunction): Boolean {
|
||||||
|
if (context.shouldContainLocationDebugInfo()) {
|
||||||
|
if (irFunction is IrConstructor && irFunction.isPrimary && irFunction.returnType.isThrowable()) {
|
||||||
|
// To simplify skipping this constructor when scanning call stack in Kotlin_getCurrentStackTrace.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
+3
-3
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.*
|
|||||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.types.isNothing
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
@@ -366,8 +365,9 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
"kfun:" + qualifyInternalName(declaration)
|
"kfun:" + qualifyInternalName(declaration)
|
||||||
}
|
}
|
||||||
val function = LLVMAddFunction(context.llvmModule, symbolName, llvmFunctionType)!!
|
val function = LLVMAddFunction(context.llvmModule, symbolName, llvmFunctionType)!!
|
||||||
if (declaration.returnType.isNothing())
|
|
||||||
setFunctionNoReturn(function)
|
addLlvmAttributes(context, declaration, function)
|
||||||
|
|
||||||
function
|
function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-7
@@ -284,37 +284,57 @@ private val noreturnAttrKindId by lazy {
|
|||||||
getLlvmAttributeKindId("noreturn")
|
getLlvmAttributeKindId("noreturn")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val noinlineAttrKindId by lazy {
|
||||||
|
getLlvmAttributeKindId("noinline")
|
||||||
|
}
|
||||||
|
|
||||||
private val signextAttrKindId by lazy {
|
private val signextAttrKindId by lazy {
|
||||||
getLlvmAttributeKindId("signext")
|
getLlvmAttributeKindId("signext")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun isFunctionNoUnwind(function: LLVMValueRef): Boolean {
|
fun isFunctionNoUnwind(function: LLVMValueRef): Boolean {
|
||||||
val attribute = LLVMGetEnumAttributeAtIndex(function, LLVMAttributeFunctionIndex, nounwindAttrKindId)
|
val attribute = LLVMGetEnumAttributeAtIndex(function, LLVMAttributeFunctionIndex, nounwindAttrKindId.value)
|
||||||
return attribute != null
|
return attribute != null
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getLlvmAttributeKindId(attributeName: String): Int {
|
internal fun getLlvmAttributeKindId(attributeName: String): LLVMAttributeKindId {
|
||||||
val attrKindId = LLVMGetEnumAttributeKindForName(attributeName, attributeName.length.signExtend())
|
val attrKindId = LLVMGetEnumAttributeKindForName(attributeName, attributeName.length.signExtend())
|
||||||
if (attrKindId == 0) {
|
if (attrKindId == 0) {
|
||||||
throw Error("Unable to find '$attributeName' attribute kind id")
|
throw Error("Unable to find '$attributeName' attribute kind id")
|
||||||
}
|
}
|
||||||
return attrKindId
|
return LLVMAttributeKindId(attrKindId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class LLVMAttributeKindId(val value: Int)
|
||||||
|
|
||||||
fun setFunctionNoUnwind(function: LLVMValueRef) {
|
fun setFunctionNoUnwind(function: LLVMValueRef) {
|
||||||
val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(function.type), nounwindAttrKindId, 0)!!
|
addLlvmFunctionEnumAttribute(function, nounwindAttrKindId)
|
||||||
LLVMAddAttributeAtIndex(function, LLVMAttributeFunctionIndex, attribute)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setFunctionNoReturn(function: LLVMValueRef) {
|
fun setFunctionNoReturn(function: LLVMValueRef) {
|
||||||
val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(function.type), noreturnAttrKindId, 0)!!
|
addLlvmFunctionEnumAttribute(function, noreturnAttrKindId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setFunctionNoInline(function: LLVMValueRef) {
|
||||||
|
addLlvmFunctionEnumAttribute(function, noinlineAttrKindId)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun addLlvmFunctionEnumAttribute(function: LLVMValueRef, attrKindId: LLVMAttributeKindId, value: Long = 0) {
|
||||||
|
val attribute = createLlvmEnumAttribute(LLVMGetTypeContext(function.type)!!, attrKindId, value)
|
||||||
|
addLlvmFunctionAttribute(function, attribute)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun createLlvmEnumAttribute(llvmContext: LLVMContextRef, attrKindId: LLVMAttributeKindId, value: Long = 0) =
|
||||||
|
LLVMCreateEnumAttribute(llvmContext, attrKindId.value, value)!!
|
||||||
|
|
||||||
|
internal fun addLlvmFunctionAttribute(function: LLVMValueRef, attribute: LLVMAttributeRef) {
|
||||||
LLVMAddAttributeAtIndex(function, LLVMAttributeFunctionIndex, attribute)
|
LLVMAddAttributeAtIndex(function, LLVMAttributeFunctionIndex, attribute)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addFunctionSignext(function: LLVMValueRef, index: Int, type: LLVMTypeRef?) {
|
fun addFunctionSignext(function: LLVMValueRef, index: Int, type: LLVMTypeRef?) {
|
||||||
if (type == int1Type || type == int8Type || type == int16Type) {
|
if (type == int1Type || type == int8Type || type == int16Type) {
|
||||||
val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(function.type), signextAttrKindId, 0)!!
|
val attribute = createLlvmEnumAttribute(LLVMGetTypeContext(function.type)!!, signextAttrKindId)
|
||||||
LLVMAddAttributeAtIndex(function, index, attribute)
|
LLVMAddAttributeAtIndex(function, index, attribute)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,12 +121,12 @@ 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.
|
||||||
OBJ_GETTER0(GetCurrentStackTrace) {
|
NO_INLINE OBJ_GETTER0(Kotlin_getCurrentStackTrace) {
|
||||||
#if OMIT_BACKTRACE
|
#if OMIT_BACKTRACE
|
||||||
return AllocArrayInstance(theNativePtrArrayTypeInfo, 0, OBJ_RESULT);
|
return AllocArrayInstance(theNativePtrArrayTypeInfo, 0, OBJ_RESULT);
|
||||||
#else
|
#else
|
||||||
// Skips first 3 elements as irrelevant.
|
// Skips first 2 elements as irrelevant: this function and primary Throwable constructor.
|
||||||
constexpr int kSkipFrames = 3;
|
constexpr int kSkipFrames = 2;
|
||||||
#if USE_GCC_UNWIND
|
#if USE_GCC_UNWIND
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
_Unwind_Backtrace(depthCountCallback, &depth);
|
_Unwind_Backtrace(depthCountCallback, &depth);
|
||||||
|
|||||||
@@ -39,10 +39,6 @@ KInt Kotlin_Any_hashCode(KConstRef thiz) {
|
|||||||
return reinterpret_cast<uintptr_t>(thiz);
|
return reinterpret_cast<uintptr_t>(thiz);
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJ_GETTER0(Kotlin_getCurrentStackTrace) {
|
|
||||||
RETURN_RESULT_OF0(GetCurrentStackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
OBJ_GETTER(Kotlin_getStackTraceStrings, KConstRef stackTrace) {
|
OBJ_GETTER(Kotlin_getStackTraceStrings, KConstRef stackTrace) {
|
||||||
RETURN_RESULT_OF(GetStackTraceStrings, stackTrace);
|
RETURN_RESULT_OF(GetStackTraceStrings, stackTrace);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user