Fix skipping top stack frames in optimized -Xg0 binaries

Also do some refactoring.
This commit is contained in:
Svyatoslav Scherbina
2019-07-31 11:36:32 +03:00
committed by SvyatoslavScherbina
parent e65ae1c9f7
commit 61a19e0ccf
6 changed files with 68 additions and 19 deletions
@@ -312,8 +312,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
val result = LLVMAddFunction(llvmModule, name, type)!!
attributes.forEach {
val kindId = getLlvmAttributeKindId(it)
val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(type), kindId, 0)!!
LLVMAddAttributeAtIndex(result, LLVMAttributeFunctionIndex, attribute)
addLlvmFunctionEnumAttribute(result, kindId)
}
return result
}
@@ -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
}
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -366,8 +365,9 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
"kfun:" + qualifyInternalName(declaration)
}
val function = LLVMAddFunction(context.llvmModule, symbolName, llvmFunctionType)!!
if (declaration.returnType.isNothing())
setFunctionNoReturn(function)
addLlvmAttributes(context, declaration, function)
function
}
@@ -284,37 +284,57 @@ private val noreturnAttrKindId by lazy {
getLlvmAttributeKindId("noreturn")
}
private val noinlineAttrKindId by lazy {
getLlvmAttributeKindId("noinline")
}
private val signextAttrKindId by lazy {
getLlvmAttributeKindId("signext")
}
fun isFunctionNoUnwind(function: LLVMValueRef): Boolean {
val attribute = LLVMGetEnumAttributeAtIndex(function, LLVMAttributeFunctionIndex, nounwindAttrKindId)
val attribute = LLVMGetEnumAttributeAtIndex(function, LLVMAttributeFunctionIndex, nounwindAttrKindId.value)
return attribute != null
}
internal fun getLlvmAttributeKindId(attributeName: String): Int {
internal fun getLlvmAttributeKindId(attributeName: String): LLVMAttributeKindId {
val attrKindId = LLVMGetEnumAttributeKindForName(attributeName, attributeName.length.signExtend())
if (attrKindId == 0) {
throw Error("Unable to find '$attributeName' attribute kind id")
}
return attrKindId
return LLVMAttributeKindId(attrKindId)
}
data class LLVMAttributeKindId(val value: Int)
fun setFunctionNoUnwind(function: LLVMValueRef) {
val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(function.type), nounwindAttrKindId, 0)!!
LLVMAddAttributeAtIndex(function, LLVMAttributeFunctionIndex, attribute)
addLlvmFunctionEnumAttribute(function, nounwindAttrKindId)
}
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)
}
fun addFunctionSignext(function: LLVMValueRef, index: Int, type: LLVMTypeRef?) {
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)
}
}
+3 -3
View File
@@ -121,12 +121,12 @@ extern "C" {
// 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.
OBJ_GETTER0(GetCurrentStackTrace) {
NO_INLINE OBJ_GETTER0(Kotlin_getCurrentStackTrace) {
#if OMIT_BACKTRACE
return AllocArrayInstance(theNativePtrArrayTypeInfo, 0, OBJ_RESULT);
#else
// Skips first 3 elements as irrelevant.
constexpr int kSkipFrames = 3;
// Skips first 2 elements as irrelevant: this function and primary Throwable constructor.
constexpr int kSkipFrames = 2;
#if USE_GCC_UNWIND
int depth = 0;
_Unwind_Backtrace(depthCountCallback, &depth);
-4
View File
@@ -39,10 +39,6 @@ KInt Kotlin_Any_hashCode(KConstRef thiz) {
return reinterpret_cast<uintptr_t>(thiz);
}
OBJ_GETTER0(Kotlin_getCurrentStackTrace) {
RETURN_RESULT_OF0(GetCurrentStackTrace);
}
OBJ_GETTER(Kotlin_getStackTraceStrings, KConstRef stackTrace) {
RETURN_RESULT_OF(GetStackTraceStrings, stackTrace);
}