From 1947f3e64b5d4ee4b009e39a6dff92d61cda88f8 Mon Sep 17 00:00:00 2001 From: SvyatoslavScherbina Date: Wed, 25 Apr 2018 13:59:36 +0300 Subject: [PATCH] Add quick fix for unDCEd private function and classes tables (#1538) --- .../jetbrains/kotlin/backend/konan/Context.kt | 3 + .../backend/konan/llvm/BinaryInterface.kt | 4 +- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 75 +++++++++++-------- 3 files changed, 48 insertions(+), 34 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index f6fe7979465..160ea51bf2f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -248,6 +248,9 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { var phase: KonanPhase? = null var depth: Int = 0 + lateinit var privateFunctions: List + lateinit var privateClasses: List + // Cache used for source offset->(line,column) mapping. val fileEntryCache = mutableMapOf() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt index 3aabc6dbebe..444e4669b2c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt @@ -294,9 +294,9 @@ internal val ClassDescriptor.objectInstanceShadowFieldSymbolName: String internal val ClassDescriptor.typeInfoHasVtableAttached: Boolean get() = !this.isAbstract() && !this.isExternalObjCClass() -internal val ModuleDescriptor.privateFunctionsTableSymbolName get() = "private_functions_${name.asString()}" +internal fun ModuleDescriptor.privateFunctionSymbolName(index: Int) = "private_functions_${name.asString()}_$index" -internal val ModuleDescriptor.privateClassesTableSymbolName get() = "private_classes_${name.asString()}" +internal fun ModuleDescriptor.privateClassSymbolName(index: Int) = "private_classes_${name.asString()}_$index" internal val String.moduleConstructorName get() = "_Konan_init_${this}" diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 91fc2920d8c..ee153a33d96 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -92,18 +92,29 @@ internal fun emitLLVM(context: Context) { devirtualizationAnalysisResult = Devirtualization.run(irModule, context, moduleDFG!!, externalModulesDFG!!) val privateFunctions = moduleDFG!!.symbolTable.getPrivateFunctionsTableForExport() - - codegenVisitor.codegen.staticData.placeGlobalConstArray(irModule.descriptor.privateFunctionsTableSymbolName, int8TypePtr, - privateFunctions.map { constPointer(codegenVisitor.codegen.llvmFunction(it)).bitcast(int8TypePtr) }, - isExported = true - ) + privateFunctions.forEachIndexed { index, it -> + val function = codegenVisitor.codegen.llvmFunction(it) + LLVMAddAlias( + context.llvmModule, + function.type, + function, + irModule.descriptor.privateFunctionSymbolName(index) + )!! + } + context.privateFunctions = privateFunctions val privateClasses = moduleDFG!!.symbolTable.getPrivateClassesTableForExport() - codegenVisitor.codegen.staticData.placeGlobalConstArray(irModule.descriptor.privateClassesTableSymbolName, int8TypePtr, - privateClasses.map { constPointer(codegenVisitor.codegen.typeInfoValue(it)).bitcast(int8TypePtr) }, - isExported = true - ) + privateClasses.forEachIndexed { index, it -> + val typeInfoPtr = codegenVisitor.codegen.typeInfoValue(it) + LLVMAddAlias( + context.llvmModule, + typeInfoPtr.type, + typeInfoPtr, + irModule.descriptor.privateClassSymbolName(index) + )!! + } + context.privateClasses = privateClasses } phaser.phase(KonanPhase.ESCAPE_ANALYSIS) { @@ -1998,36 +2009,36 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map, resultLifetime: Lifetime): LLVMValueRef { - val functionsListName = callee.moduleDescriptor.privateFunctionsTableSymbolName - // LLVM inlines access to this global array (with -opt option on). - val functionsList = - if (callee.moduleDescriptor == context.irModule!!.descriptor) - LLVMGetNamedGlobal(context.llvmModule, functionsListName) - else - codegen.importGlobal(functionsListName, LLVMArrayType(int8TypePtr, callee.totalFunctions)!!, callee.moduleDescriptor.llvmSymbolOrigin) - val functionIndex = Int32(callee.functionIndex).llvm - val functionPlacePtr = LLVMBuildGEP(functionGenerationContext.builder, functionsList, cValuesOf(kImmZero, functionIndex), 2, "")!! - val functionPtr = functionGenerationContext.load(functionPlacePtr) - val target = callee.symbol.owner as IrFunction - val functionPtrType = pointerType(codegen.getLlvmFunctionType(target)) - val function = functionGenerationContext.bitcast(functionPtrType, functionPtr) + + val functionIndex = callee.functionIndex + val function = if (callee.moduleDescriptor == context.irModule!!.descriptor) { + codegen.llvmFunction(context.privateFunctions[functionIndex]) + } else { + context.llvm.externalFunction( + callee.moduleDescriptor.privateFunctionSymbolName(functionIndex), + codegen.getLlvmFunctionType(target), + callee.moduleDescriptor.llvmSymbolOrigin + + ) + } return call(target, function, args, resultLifetime) } //-------------------------------------------------------------------------// private fun evaluatePrivateClassReference(classReference: IrPrivateClassReference): LLVMValueRef { - val classesListName = classReference.moduleDescriptor.privateClassesTableSymbolName - // LLVM inlines access to this global array (with -opt option on). - val functionsList = - if (classReference.moduleDescriptor == context.irModule!!.descriptor) - LLVMGetNamedGlobal(context.llvmModule, classesListName) - else - codegen.importGlobal(classesListName, LLVMArrayType(int8TypePtr, classReference.totalClasses)!!, classReference.moduleDescriptor.llvmSymbolOrigin) - val classIndex = Int32(classReference.classIndex).llvm - val classPlacePtr = LLVMBuildGEP(functionGenerationContext.builder, functionsList, cValuesOf(kImmZero, classIndex), 2, "")!! - return functionGenerationContext.load(classPlacePtr) + val classIndex = classReference.classIndex + val typeInfoPtr = if (classReference.moduleDescriptor == context.irModule!!.descriptor) { + codegen.typeInfoValue(context.privateClasses[classIndex]) + } else { + codegen.importGlobal( + classReference.moduleDescriptor.privateClassSymbolName(classIndex), + codegen.kTypeInfo, + classReference.moduleDescriptor.llvmSymbolOrigin + ) + } + return functionGenerationContext.bitcast(int8TypePtr, typeInfoPtr) } //-------------------------------------------------------------------------//