Support native top-level functions

This commit is contained in:
Andrey Breslav
2014-12-01 22:15:03 +03:00
parent 56216c4bd8
commit 6596c6d943
5 changed files with 44 additions and 2 deletions
@@ -30,6 +30,7 @@ import org.jetbrains.jet.codegen.bridges.Bridge;
import org.jetbrains.jet.codegen.bridges.BridgesPackage; import org.jetbrains.jet.codegen.bridges.BridgesPackage;
import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.MethodContext; 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.context.PackageFacadeContext;
import org.jetbrains.jet.codegen.optimization.OptimizationMethodVisitor; import org.jetbrains.jet.codegen.optimization.OptimizationMethodVisitor;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
@@ -132,6 +133,10 @@ public class FunctionCodegen extends ParentCodegenAware {
int flags = getMethodAsmFlags(functionDescriptor, methodContextKind); int flags = getMethodAsmFlags(functionDescriptor, methodContextKind);
boolean isNative = NativeDeclarationsPackage.hasNativeAnnotation(functionDescriptor); 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, MethodVisitor mv = v.newMethod(origin,
flags, flags,
asmMethod.getName(), asmMethod.getName(),
@@ -158,7 +163,6 @@ public class FunctionCodegen extends ParentCodegenAware {
generateBridges(functionDescriptor); generateBridges(functionDescriptor);
boolean staticInClassObject = AnnotationsPackage.isPlatformStaticInClassObject(functionDescriptor); boolean staticInClassObject = AnnotationsPackage.isPlatformStaticInClassObject(functionDescriptor);
if (staticInClassObject) { if (staticInClassObject) {
MemberCodegen<?> codegen = getParentCodegen().getParentCodegen(); MemberCodegen<?> codegen = getParentCodegen().getParentCodegen();
((ImplementationBodyCodegen) codegen).addAdditionalTask(new PlatformStaticGenerator(functionDescriptor, origin, state)); ((ImplementationBodyCodegen) codegen).addAdditionalTask(new PlatformStaticGenerator(functionDescriptor, origin, state));
@@ -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.jvmSignature.JvmMethodSignature;
import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap; import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap;
import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils; 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.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.SpecialNames; import org.jetbrains.jet.lang.resolve.name.SpecialNames;
@@ -110,10 +111,11 @@ public class JetTypeMapper {
DeclarationDescriptor container = descriptor.getContainingDeclaration(); DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (container instanceof PackageFragmentDescriptor) { if (container instanceof PackageFragmentDescriptor) {
boolean effectiveInsideModule = isInsideModule && !NativeDeclarationsPackage.hasNativeAnnotation(descriptor);
return Type.getObjectType(internalNameForPackage( return Type.getObjectType(internalNameForPackage(
(PackageFragmentDescriptor) container, (PackageFragmentDescriptor) container,
(CallableMemberDescriptor) descriptor, (CallableMemberDescriptor) descriptor,
isInsideModule effectiveInsideModule
)); ));
} }
else if (container instanceof ClassDescriptor) { else if (container instanceof ClassDescriptor) {
@@ -9,6 +9,8 @@ object ObjWithNative {
platformStatic native fun bar(l: Long, s: String = ""): Double platformStatic native fun bar(l: Long, s: String = ""): Double
} }
native fun topLevel(x: Int = 1): Double
fun box(): String { fun box(): String {
var d = 0.0 var d = 0.0
@@ -27,5 +29,13 @@ fun box(): String {
catch (e: java.lang.UnsatisfiedLinkError) { catch (e: java.lang.UnsatisfiedLinkError) {
if (e.getMessage() != "foo.ObjWithNative.foo(I)D") return "Fail 2: " + e.getMessage() 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" return "OK"
} }
@@ -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"
}
@@ -1836,6 +1836,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/native/staticNative.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/native/staticNative.kt");
doTestWithStdlib(fileName); 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") @TestMetadata("compiler/testData/codegen/boxWithStdlib/nonLocalReturns")