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)!!
|
||||
attributes.forEach {
|
||||
val kindId = getLlvmAttributeKindId(it)
|
||||
val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(type), kindId, 0)!!
|
||||
LLVMAddAttributeAtIndex(result, LLVMAttributeFunctionIndex, attribute)
|
||||
addLlvmFunctionEnumAttribute(result, kindId)
|
||||
}
|
||||
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.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
|
||||
}
|
||||
|
||||
|
||||
+27
-7
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user