From 01cb9d4cacbd32093cc9fc3f2d37aa6c6a3a8ba9 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Fri, 27 Jan 2017 16:38:48 +0500 Subject: [PATCH] Implementation of super methods calling (#203) * implemented super call * tests * removed redundant code --- .../konan/descriptors/DescriptorUtils.kt | 12 +++++-- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 8 ++--- backend.native/tests/build.gradle | 15 +++++++++ .../tests/codegen/basics/superFunCall.kt | 19 +++++++++++ .../tests/codegen/basics/superGetterCall.kt | 19 +++++++++++ .../tests/codegen/basics/superSetterCall.kt | 32 +++++++++++++++++++ 6 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 backend.native/tests/codegen/basics/superFunCall.kt create mode 100644 backend.native/tests/codegen/basics/superGetterCall.kt create mode 100644 backend.native/tests/codegen/basics/superSetterCall.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index 15d46ded1d8..4106b161ea8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -5,6 +5,10 @@ import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -12,6 +16,8 @@ import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeSubstitution +import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.util.OperatorNameConventions @@ -152,7 +158,7 @@ internal val FunctionDescriptor.isFunctionInvoke: Boolean internal fun ClassDescriptor.isUnit() = this.defaultType.isUnit() -internal val ClassDescriptor.сontributedMethods: List +internal val ClassDescriptor.contributedMethods: List get() { val contributedDescriptors = unsubstitutedMemberScope.getContributedDescriptors() // (includes declarations from supers) @@ -184,7 +190,7 @@ val ClassDescriptor.vtableEntries: List this.getSuperClassOrAny().vtableEntries } - val methods = this.сontributedMethods + val methods = this.contributedMethods val inheritedVtableSlots = superVtableEntries.map { superMethod -> methods.singleOrNull { OverridingUtil.overrides(it, superMethod) } ?: superMethod @@ -204,6 +210,6 @@ val ClassDescriptor.methodTableEntries: List get() { assert (!this.isAbstract()) - return this.сontributedMethods.filter { it.isOverridableOrOverrides } + return this.contributedMethods.filter { it.isOverridableOrOverrides } // TODO: probably method table should contain all accessible methods to improve binary compatibility } \ No newline at end of file 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 7bd120c96f3..de215d6cbcb 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 @@ -1681,7 +1681,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid when (descriptor) { is IrBuiltinOperatorDescriptorBase -> return evaluateOperatorCall (callee, args) is ConstructorDescriptor -> return evaluateConstructorCall (callee, args) - else -> return evaluateSimpleFunctionCall(descriptor, args) + else -> return evaluateSimpleFunctionCall(descriptor, args, callee.superQualifier) } } @@ -1721,9 +1721,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid //-------------------------------------------------------------------------// - private fun evaluateSimpleFunctionCall(descriptor: FunctionDescriptor, args: List): LLVMValueRef { + private fun evaluateSimpleFunctionCall(descriptor: FunctionDescriptor, args: List, superClass: ClassDescriptor? = null): LLVMValueRef { //context.log("evaluateSimpleFunctionCall : $tmpVariableName = ${ir2string(value)}") - if (descriptor.isOverridable) + if (descriptor.isOverridable && superClass == null) return callVirtual(descriptor, args) else return callDirect(descriptor, args) @@ -1737,7 +1737,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid if (descriptor.dispatchReceiverParameter != null) args.add(evaluateExpression(value.dispatchReceiver!!)) //add this ptr args.add(evaluateExpression(value.getValueArgument(0)!!)) - return evaluateSimpleFunctionCall(descriptor, args) + return evaluateSimpleFunctionCall(descriptor, args, value.superQualifier) } //-------------------------------------------------------------------------// diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 3b14afb8967..3e9852323b6 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -292,6 +292,21 @@ task empty_substring(type: RunKonanTest) { source = "runtime/basic/empty_substring.kt" } +task superFunCall(type: RunKonanTest) { + goldValue = "\n\n" + source = "codegen/basics/superFunCall.kt" +} + +task superGetterCall(type: RunKonanTest) { + goldValue = "\n\n" + source = "codegen/basics/superGetterCall.kt" +} + +task superSetterCall(type: RunKonanTest) { + goldValue = "zzz\nzzz\n" + source = "codegen/basics/superSetterCall.kt" +} + task enum0(type: RunKonanTest) { goldValue = "VALUE\n" source = "codegen/enum/test0.kt" diff --git a/backend.native/tests/codegen/basics/superFunCall.kt b/backend.native/tests/codegen/basics/superFunCall.kt new file mode 100644 index 00000000000..d524ccf961a --- /dev/null +++ b/backend.native/tests/codegen/basics/superFunCall.kt @@ -0,0 +1,19 @@ +open class C { + open fun f() = "" +} + +class C1: C() { + override fun f() = super.f() + "" +} + +open class C2: C() { +} + +class C3: C2() { + override fun f() = super.f() + "" +} + +fun main(args: Array) { + println(C1().f()) + println(C3().f()) +} \ No newline at end of file diff --git a/backend.native/tests/codegen/basics/superGetterCall.kt b/backend.native/tests/codegen/basics/superGetterCall.kt new file mode 100644 index 00000000000..63dfd9b09f4 --- /dev/null +++ b/backend.native/tests/codegen/basics/superGetterCall.kt @@ -0,0 +1,19 @@ +open class C { + open val p1 = "" +} + +class C1: C() { + override val p1 = super.p1 + "" +} + +open class C2: C() { +} + +class C3: C2() { + override val p1 = super.p1 + "" +} + +fun main(args: Array) { + println(C1().p1) + println(C3().p1) +} \ No newline at end of file diff --git a/backend.native/tests/codegen/basics/superSetterCall.kt b/backend.native/tests/codegen/basics/superSetterCall.kt new file mode 100644 index 00000000000..215852a1d91 --- /dev/null +++ b/backend.native/tests/codegen/basics/superSetterCall.kt @@ -0,0 +1,32 @@ +open class C { + open var p2 = "" + set(value) { field = "" + value } +} + +class C1: C() { + override var p2 = super.p2 + "" + set(value) { + super.p2 = value + field = "" + super.p2 + } +} + +open class C2: C() { +} + +class C3: C2() { + override var p2 = super.p2 + "" + set(value) { + super.p2 = value + field = "" + super.p2 + } +} + +fun main(args: Array) { + val c1 = C1() + val c3 = C3() + c1.p2 = "zzz" + c3.p2 = "zzz" + println(c1.p2) + println(c3.p2) +} \ No newline at end of file