Ensure generated LLVM functions get attributes

In particular, fix missing frame pointers for ObjCExport bridges.

 #KT-44549 Fixed.
This commit is contained in:
Svyatoslav Scherbina
2021-02-08 20:01:42 +03:00
committed by Vasily Levchenko
parent ae32e18634
commit 59c6940caf
7 changed files with 79 additions and 27 deletions
@@ -233,7 +233,12 @@ private class ExportedElement(val kind: ElementKind,
val irClass = irSymbol.owner as IrClass
cname = "_konan_function_${owner.nextFunctionIndex()}"
// Produce type getter.
val getTypeFunction = LLVMAddFunction(context.llvmModule, "${cname}_type", owner.kGetTypeFuncType)!!
val getTypeFunction = addLlvmFunctionWithDefaultAttributes(
context,
context.llvmModule!!,
"${cname}_type",
owner.kGetTypeFuncType
)
val builder = LLVMCreateBuilderInContext(llvmContext)!!
val bb = LLVMAppendBasicBlockInContext(llvmContext, getTypeFunction, "")!!
LLVMPositionBuilderAtEnd(builder, bb)
@@ -140,7 +140,12 @@ internal inline fun generateFunction(
name: String,
block: FunctionGenerationContext.(FunctionGenerationContext) -> Unit
): LLVMValueRef {
val function = LLVMAddFunction(codegen.context.llvmModule, name, functionType)!!
val function = addLlvmFunctionWithDefaultAttributes(
codegen.context,
codegen.context.llvmModule!!,
name,
functionType
)
generateFunction(codegen, function, startLocation = null, endLocation = null, code = block)
return function
}
@@ -1041,9 +1046,13 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
ObjectStorageKind.THREAD_LOCAL -> {
val valueGetterName = irClass.threadLocalObjectStorageGetterSymbolName
val valueGetterFunction = LLVMGetNamedFunction(context.llvmModule, valueGetterName)
?: LLVMAddFunction(context.llvmModule, valueGetterName,
functionType(kObjHeaderPtrPtr, false))
call(valueGetterFunction!!,
?: addLlvmFunctionWithDefaultAttributes(
context,
context.llvmModule!!,
valueGetterName,
functionType(kObjHeaderPtrPtr, false)
)
call(valueGetterFunction,
listOf(),
resultLifetime = Lifetime.GLOBAL,
exceptionHandler = exceptionHandler)
@@ -314,12 +314,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
private fun importMemset(): LLVMValueRef {
val functionType = functionType(voidType, false, int8TypePtr, int8Type, int32Type, int1Type)
return LLVMAddFunction(llvmModule, "llvm.memset.p0i8.i32", functionType)!!
}
private fun importMemcpy(): LLVMValueRef {
val functionType = functionType(voidType, false, int8TypePtr, int8TypePtr, int32Type, int1Type)
return LLVMAddFunction(llvmModule, "llvm.memcpy.p0i8.p0i8.i32", functionType)!!
return llvmIntrinsic("llvm.memset.p0i8.i32", functionType)
}
private fun llvmIntrinsic(name: String, type: LLVMTypeRef, vararg attributes: String): LLVMValueRef {
@@ -350,7 +345,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
} else {
// As exported functions are written in C++ they assume sign extension for promoted types -
// mention that in attributes.
val function = LLVMAddFunction(llvmModule, name, type)!!
val function = addLlvmFunctionWithDefaultAttributes(context, llvmModule, name, type)
return memScoped {
val paramCount = LLVMCountParamTypes(type)
val paramTypes = allocArray<LLVMTypeRefVar>(paramCount)
@@ -389,7 +389,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
val DEINIT_GLOBALS = 3
private fun createInitBody(): LLVMValueRef {
val initFunction = LLVMAddFunction(context.llvmModule, "", kInitFuncType)!!
val initFunction = addLlvmFunctionWithDefaultAttributes(
context,
context.llvmModule!!,
"",
kInitFuncType
)
LLVMSetLinkage(initFunction, LLVMLinkage.LLVMPrivateLinkage)
generateFunction(codegen, initFunction) {
using(FunctionScope(initFunction, "init_body", it)) {
@@ -500,7 +505,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
//-------------------------------------------------------------------------//
private fun createInitCtor(initNodePtr: LLVMValueRef): LLVMValueRef {
val ctorFunction = LLVMAddFunction(context.llvmModule, "", kVoidFuncType)!!
val ctorFunction = addLlvmFunctionWithDefaultAttributes(
context,
context.llvmModule!!,
"",
kVoidFuncType
)
LLVMSetLinkage(ctorFunction, LLVMLinkage.LLVMPrivateLinkage)
generateFunction(codegen, ctorFunction) {
call(context.llvm.appendToInitalizersTail, listOf(initNodePtr))
@@ -2480,7 +2490,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
context.config.moduleId.moduleConstructorName
}
val ctorFunction = LLVMAddFunction(context.llvmModule, ctorName, kVoidFuncType)!!
val ctorFunction = addLlvmFunctionWithDefaultAttributes(
context,
context.llvmModule!!,
ctorName,
kVoidFuncType
)
LLVMSetLinkage(ctorFunction, LLVMLinkage.LLVMExternalLinkage)
val initializers = libraryToInitializers.getValue(library)
@@ -2535,7 +2550,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
private fun appendGlobalCtors(ctorFunctions: List<LLVMValueRef>) {
if (context.config.produce.isFinalBinary) {
// Generate function calling all [ctorFunctions].
val globalCtorFunction = LLVMAddFunction(context.llvmModule, "_Konan_constructors", kVoidFuncType)!!
val globalCtorFunction = addLlvmFunctionWithDefaultAttributes(
context,
context.llvmModule!!,
"_Konan_constructors",
kVoidFuncType
)
LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMPrivateLinkage)
generateFunction(codegen, globalCtorFunction) {
ctorFunctions.forEach {
@@ -5,8 +5,7 @@
package org.jetbrains.kotlin.backend.konan.llvm
import llvm.LLVMAddTargetDependentFunctionAttr
import llvm.LLVMValueRef
import llvm.*
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
@@ -14,15 +13,30 @@ import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.util.isThrowable
import org.jetbrains.kotlin.konan.target.Family
internal fun addLlvmAttributes(context: Context, irFunction: IrFunction, llvmFunction: LLVMValueRef) {
if (irFunction.returnType.isNothing()) {
setFunctionNoReturn(llvmFunction)
}
internal fun addLlvmFunctionWithDefaultAttributes(
context: Context,
module: LLVMModuleRef,
name: String,
type: LLVMTypeRef
): LLVMValueRef = LLVMAddFunction(module, name, type)!!.also {
addDefaultLlvmFunctionAttributes(context, it)
}
/**
* Mimics parts of clang's `CodeGenModule::getDefaultFunctionAttributes`
* that are required for Kotlin/Native compiler.
*/
private fun addDefaultLlvmFunctionAttributes(context: Context, llvmFunction: LLVMValueRef) {
if (shouldEnforceFramePointer(context)) {
// Note: this is default for clang on at least on iOS and macOS.
enforceFramePointer(llvmFunction)
}
}
internal fun addLlvmAttributesForKotlinFunction(context: Context, irFunction: IrFunction, llvmFunction: LLVMValueRef) {
if (irFunction.returnType.isNothing()) {
setFunctionNoReturn(llvmFunction)
}
if (mustNotInline(context, irFunction)) {
setFunctionNoInline(llvmFunction)
@@ -366,11 +366,15 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
} else {
"kfun:" + qualifyInternalName(declaration)
}
val function = LLVMAddFunction(context.llvmModule, symbolName, llvmFunctionType)!!
addLlvmAttributes(context, declaration, function)
function
addLlvmFunctionWithDefaultAttributes(
context,
context.llvmModule!!,
symbolName,
llvmFunctionType
).also {
addLlvmAttributesForKotlinFunction(context, declaration, it)
}
}
declaration.metadata = CodegenFunctionMetadata(
@@ -742,7 +742,12 @@ private inline fun ObjCExportCodeGenerator.generateObjCImpBy(
debugInfo: Boolean = false,
genBody: FunctionGenerationContext.() -> Unit
): LLVMValueRef {
val result = LLVMAddFunction(context.llvmModule, "objc2kotlin", objCFunctionType(context, methodBridge))!!
val result = addLlvmFunctionWithDefaultAttributes(
context,
context.llvmModule!!,
"objc2kotlin",
objCFunctionType(context, methodBridge)
)
val location = if (debugInfo) {
setupBridgeDebugInfo(context, result)