diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt index c87338d09ad..c0b81c3e744 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt @@ -26,6 +26,7 @@ internal class Context(val irModule: IrModuleFragment, val runtime: Runtime, val val initInstanceFunction = importRtFunction("InitInstance") val allocArrayFunction = importRtFunction("AllocArrayInstance") val setArrayFunction = importRtFunction("Kotlin_Array_set") + val copyImplArrayFunction = importRtFunction("Kotlin_Array_copyImpl") val lookupFieldOffset = importRtFunction("LookupFieldOffset") val lookupOpenMethodFunction = importRtFunction("LookupOpenMethod") val isInstanceFunction = importRtFunction("IsInstance") 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 eb2861c81f8..4ed45967eff 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 @@ -727,30 +727,45 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid //-------------------------------------------------------------------------// private fun evaluateVararg(tmpVariableName: String, value: IrVararg): LLVMValueRef? { - val arguments = value.elements.map { - assert (it !is IrSpreadElement) - evaluateExpression(codegen.newVar(), it)!! + var oneSizedElementsCount = 0 + data class Element(val exp: LLVMValueRef, val size: LLVMValueRef?, val isArray: Boolean) + + val elements = value.elements.map { + if (it is IrSpreadElement) { + val exp = evaluateExpression(codegen.newVar(), it.expression)!! + val array = codegen.bitcast(codegen.kArrayHeaderPtr, exp, codegen.newVar()) + val sizePtr = LLVMBuildStructGEP(codegen.builder, array, 1, codegen.newVar()) + return@map Element(exp, codegen.load(sizePtr!!, codegen.newVar()), true) + } + val exp = evaluateExpression(codegen.newVar(), it)!! + oneSizedElementsCount++ + return@map Element(exp, null, false) } - return genCreateArray(tmpVariableName, value.type, arguments) - } - - private fun genCreateArray(tmpVariableName: String, - arrayType: KotlinType, elements: List): LLVMValueRef { - - if (elements.all { codegen.isConst(it) }) { + if (elements.all { codegen.isConst(it.exp) && !it.isArray }) { // Note: even if all elements are const, they aren't guaranteed to be statically initialized. // E.g. an element may be a pointer to lazy-initialized object (aka singleton). // However it is guaranteed that all elements are already initialized at this point. - return codegen.staticData.createKotlinArray(arrayType, elements) + return codegen.staticData.createKotlinArray(value.type, elements.map { it.exp }) } - val typeInfo = codegen.typeInfoValue(arrayType)!! + val length = LLVMConstInt(LLVMInt32Type(), oneSizedElementsCount.toLong(), 0) + val finalLength = elements.filter { it.isArray }.fold(length) { sum, (_, size, _) -> + codegen.plus(sum!!, size!!, codegen.newVar()) + } - val arrayCreationArgs = listOf(typeInfo, kImmInt32One, Int32(elements.size).llvm) + val typeInfo = codegen.typeInfoValue(value.type)!! + val arrayCreationArgs = listOf(typeInfo, kImmInt32One, finalLength!!) val array = currentCodeContext.genCall(context.allocArrayFunction, arrayCreationArgs, tmpVariableName) - elements.forEachIndexed { i, it -> - currentCodeContext.genCall(context.setArrayFunction, listOf(array, Int32(i).llvm, it), "") + + elements.fold(kImmZero) { sum, (exp, size, isArray) -> + if (!isArray) { + currentCodeContext.genCall(context.setArrayFunction, listOf(array, sum, exp), "") + return@fold codegen.plus(sum, kImmOne, codegen.newVar()) + } else { + currentCodeContext.genCall(context.copyImplArrayFunction, listOf(exp, kImmZero, array, sum, size!!), "") + return@fold codegen.plus(sum, size, codegen.newVar()) + } } return array } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt index bb3c47f5f3a..47a1e5a2e0b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt @@ -112,6 +112,10 @@ internal val ContextUtils.kObjHeaderPtr: LLVMTypeRef get() = pointerType(kObjHeader) internal val ContextUtils.kObjHeaderPtrPtr: LLVMTypeRef get() = pointerType(kObjHeaderPtr) +internal val ContextUtils.kArrayHeader: LLVMTypeRef + get() = LLVMGetTypeByName(context.llvmModule, "struct.ArrayHeader")!! +internal val ContextUtils.kArrayHeaderPtr: LLVMTypeRef + get() = pointerType(kArrayHeader) internal val ContextUtils.kTypeInfoPtr: LLVMTypeRef get() = pointerType(kTypeInfo) internal val kInt1 = LLVMInt1Type()!!