From 6596c6d943f613edeb1debba4d0b48e6dbaff691 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 1 Dec 2014 22:15:03 +0300 Subject: [PATCH] Support native top-level functions --- .../jet/codegen/FunctionCodegen.java | 6 +++++- .../jet/codegen/state/JetTypeMapper.java | 4 +++- .../codegen/boxWithStdlib/native/default.kt | 10 ++++++++++ .../codegen/boxWithStdlib/native/topLevel.kt | 20 +++++++++++++++++++ ...lackBoxWithStdlibCodegenTestGenerated.java | 6 ++++++ 5 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/boxWithStdlib/native/topLevel.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 63f7f615c36..b23a13a6b08 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -30,6 +30,7 @@ import org.jetbrains.jet.codegen.bridges.Bridge; import org.jetbrains.jet.codegen.bridges.BridgesPackage; import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.MethodContext; +import org.jetbrains.jet.codegen.context.PackageContext; import org.jetbrains.jet.codegen.context.PackageFacadeContext; import org.jetbrains.jet.codegen.optimization.OptimizationMethodVisitor; import org.jetbrains.jet.codegen.state.GenerationState; @@ -132,6 +133,10 @@ public class FunctionCodegen extends ParentCodegenAware { int flags = getMethodAsmFlags(functionDescriptor, methodContextKind); boolean isNative = NativeDeclarationsPackage.hasNativeAnnotation(functionDescriptor); + if (isNative && owner instanceof PackageContext && !(owner instanceof PackageFacadeContext)) { + // Native methods are only defined in package facades and do not need package part implementations + return; + } MethodVisitor mv = v.newMethod(origin, flags, asmMethod.getName(), @@ -158,7 +163,6 @@ public class FunctionCodegen extends ParentCodegenAware { generateBridges(functionDescriptor); boolean staticInClassObject = AnnotationsPackage.isPlatformStaticInClassObject(functionDescriptor); - if (staticInClassObject) { MemberCodegen codegen = getParentCodegen().getParentCodegen(); ((ImplementationBodyCodegen) codegen).addAdditionalTask(new PlatformStaticGenerator(functionDescriptor, origin, state)); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index 2698c78e705..5234eb351e2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -47,6 +47,7 @@ import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignat import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature; import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap; import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils; +import org.jetbrains.jet.lang.resolve.kotlin.nativeDeclarations.NativeDeclarationsPackage; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.SpecialNames; @@ -110,10 +111,11 @@ public class JetTypeMapper { DeclarationDescriptor container = descriptor.getContainingDeclaration(); if (container instanceof PackageFragmentDescriptor) { + boolean effectiveInsideModule = isInsideModule && !NativeDeclarationsPackage.hasNativeAnnotation(descriptor); return Type.getObjectType(internalNameForPackage( (PackageFragmentDescriptor) container, (CallableMemberDescriptor) descriptor, - isInsideModule + effectiveInsideModule )); } else if (container instanceof ClassDescriptor) { diff --git a/compiler/testData/codegen/boxWithStdlib/native/default.kt b/compiler/testData/codegen/boxWithStdlib/native/default.kt index dcc99b31771..3ca8bc4b791 100644 --- a/compiler/testData/codegen/boxWithStdlib/native/default.kt +++ b/compiler/testData/codegen/boxWithStdlib/native/default.kt @@ -9,6 +9,8 @@ object ObjWithNative { platformStatic native fun bar(l: Long, s: String = ""): Double } +native fun topLevel(x: Int = 1): Double + fun box(): String { var d = 0.0 @@ -27,5 +29,13 @@ fun box(): String { catch (e: java.lang.UnsatisfiedLinkError) { if (e.getMessage() != "foo.ObjWithNative.foo(I)D") return "Fail 2: " + e.getMessage() } + + try { + d = topLevel() + return "Link error expected on object" + } + catch (e: java.lang.UnsatisfiedLinkError) { + if (e.getMessage() != "foo.FooPackage.topLevel(I)D") return "Fail 3: " + e.getMessage() + } return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/native/topLevel.kt b/compiler/testData/codegen/boxWithStdlib/native/topLevel.kt new file mode 100644 index 00000000000..042db8cf77b --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/native/topLevel.kt @@ -0,0 +1,20 @@ +package foo + +import kotlin.jvm.* +import kotlin.platform.* + +native fun bar(l: Long, s: String): Double + +fun box(): String { + var d = 0.0 + + try { + d = bar(1, "") + return "Link error expected on object" + } + catch (e: java.lang.UnsatisfiedLinkError) { + if (e.getMessage() != "foo.FooPackage.bar(JLjava/lang/String;)D") return "Fail 1: " + e.getMessage() + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 99f74c2d338..b568a419036 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -1836,6 +1836,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/native/staticNative.kt"); doTestWithStdlib(fileName); } + + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/native/topLevel.kt"); + doTestWithStdlib(fileName); + } } @TestMetadata("compiler/testData/codegen/boxWithStdlib/nonLocalReturns")