From 58ba5ed37b489a92c1deba4896974a1c4384de05 Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Fri, 23 Sep 2016 15:01:06 +0300 Subject: [PATCH] Default args support --- .../kotlin/codegen/DefaultCallArgs.kt | 14 ++++++++ .../backend/jvm/codegen/ExpressionCodegen.kt | 34 +++++++++++++------ 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultCallArgs.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultCallArgs.kt index 184f8452f9d..321e6c7a319 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultCallArgs.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultCallArgs.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import java.util.* class DefaultCallArgs(val size: Int) { @@ -63,4 +64,17 @@ class DefaultCallArgs(val size: Int) { } return toInts.isNotEmpty() } + + fun generateOnStackIfNeeded(iv: InstructionAdapter, isConstructor: Boolean): Boolean { + val toInts = toInts() + if (!toInts.isEmpty()) { + for (mask in toInts) { + iv.iconst(mask) + } + + val parameterType = if (isConstructor) AsmTypes.DEFAULT_CONSTRUCTOR_MARKER else AsmTypes.OBJECT_TYPE + iv.aconst(null) + } + return toInts.isNotEmpty() + } } \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 0cdc031a164..20ed8623841 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -20,8 +20,7 @@ import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicFunction import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.* -import org.jetbrains.kotlin.codegen.AsmUtil.boxType -import org.jetbrains.kotlin.codegen.AsmUtil.correctElementType +import org.jetbrains.kotlin.codegen.AsmUtil.* import org.jetbrains.kotlin.codegen.StackValue.* import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrElement @@ -158,19 +157,33 @@ class ExpressionCodegen( receiver?.apply { gen(receiver, callable.owner, data) } - val args = (listOf(expression.extensionReceiver) + + + val args = (listOf(expression.extensionReceiver).filterNotNull() + expression.descriptor.valueParameters.mapIndexed { i, valueParameterDescriptor -> - expression.getValueArgument(i) - }).filterNotNull() + expression.getValueArgument(i) ?: DefaultArg(i) + }) + + val defaultMask = DefaultCallArgs(callable.valueParameterTypes.size) args.forEachIndexed { i, expression -> - gen(expression, callable.parameterTypes[i], data) + when (expression) { + is IrExpression -> { + gen(expression, callable.parameterTypes[i], data) + } + is DefaultArg -> { + pushDefaultValueOnStack(callable.parameterTypes[i], mv) + defaultMask.mark(expression.index) + } + else -> TODO() + } } - callable.genInvokeInstruction(mv) + + if (!defaultMask.generateOnStackIfNeeded(mv, expression.descriptor is ConstructorDescriptor)) { + callable.genInvokeInstruction(mv) + } else { + (callable as CallableMethod).genInvokeDefaultInstruction(mv) + } return StackValue.onStack(callable.returnType) -// if (expression.descriptor !is ConstructorDescriptor) { -// //coerce(callable.returnType, expression.asmType, mv) -// } } return expression.onStack @@ -421,3 +434,4 @@ class ExpressionCodegen( get() = typeMapper.mapType(this) } +private class DefaultArg(val index: Int)