001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.codegen.state;
018
019 import com.intellij.psi.PsiElement;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.asm4.Type;
023 import org.jetbrains.jet.codegen.*;
024 import org.jetbrains.jet.codegen.binding.BindingTraceAware;
025 import org.jetbrains.jet.codegen.binding.CalculatedClosure;
026 import org.jetbrains.jet.codegen.binding.CodegenBinding;
027 import org.jetbrains.jet.codegen.context.CodegenContext;
028 import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
029 import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
030 import org.jetbrains.jet.codegen.signature.JvmMethodParameterSignature;
031 import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
032 import org.jetbrains.jet.lang.descriptors.*;
033 import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
034 import org.jetbrains.jet.lang.psi.*;
035 import org.jetbrains.jet.lang.resolve.BindingContext;
036 import org.jetbrains.jet.lang.resolve.BindingContextUtils;
037 import org.jetbrains.jet.lang.resolve.BindingTrace;
038 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
039 import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
040 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
041 import org.jetbrains.jet.lang.resolve.java.JvmAbi;
042 import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
043 import org.jetbrains.jet.lang.resolve.java.descriptor.JavaClassStaticsPackageFragmentDescriptor;
044 import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap;
045 import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
046 import org.jetbrains.jet.lang.types.*;
047 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
048
049 import java.util.ArrayList;
050 import java.util.List;
051
052 import static org.jetbrains.asm4.Opcodes.*;
053 import static org.jetbrains.jet.codegen.AsmUtil.boxType;
054 import static org.jetbrains.jet.codegen.AsmUtil.getTraitImplThisParameterType;
055 import static org.jetbrains.jet.codegen.CodegenUtil.*;
056 import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionTraitClassName;
057 import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
058 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isAnnotationClass;
059 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isAnonymousObject;
060 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
061
062 public class JetTypeMapper extends BindingTraceAware {
063
064 private final ClassBuilderMode classBuilderMode;
065
066 public JetTypeMapper(BindingTrace bindingTrace, ClassBuilderMode mode) {
067 super(bindingTrace);
068 classBuilderMode = mode;
069 }
070
071 private enum JetTypeMapperMode {
072 /**
073 * foo.Bar is mapped to Lfoo/Bar;
074 */
075 IMPL,
076 /**
077 * kotlin.Int is mapped to I
078 */
079 VALUE,
080 /**
081 * kotlin.Int is mapped to Ljava/lang/Integer;
082 */
083 TYPE_PARAMETER,
084 /**
085 * kotlin.Int is mapped to Ljava/lang/Integer;
086 * No projections allowed in immediate arguments
087 */
088 SUPER_TYPE
089 }
090
091 @NotNull
092 public Type getOwner(@NotNull DeclarationDescriptor descriptor, @NotNull OwnerKind kind, boolean isInsideModule) {
093 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
094 if (containingDeclaration instanceof PackageFragmentDescriptor) {
095 return asmTypeForPackage((PackageFragmentDescriptor) containingDeclaration, descriptor, isInsideModule);
096 }
097 else if (containingDeclaration instanceof ClassDescriptor) {
098 ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
099 return kind == OwnerKind.TRAIT_IMPL ? mapTraitImpl(classDescriptor) : mapClass(classDescriptor);
100 }
101 else if (containingDeclaration instanceof ScriptDescriptor) {
102 return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) containingDeclaration);
103 }
104 else {
105 throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration);
106 }
107 }
108
109 @NotNull
110 private Type asmTypeForPackage(
111 @NotNull PackageFragmentDescriptor packageFragment,
112 @NotNull DeclarationDescriptor descriptor,
113 boolean insideModule
114 ) {
115 return Type.getObjectType(internalNameForPackage(packageFragment, descriptor, insideModule));
116 }
117
118 @NotNull
119 private String internalNameForPackage(
120 @NotNull PackageFragmentDescriptor packageFragment,
121 @NotNull DeclarationDescriptor descriptor,
122 boolean insideModule
123 ) {
124 if (packageFragment instanceof JavaClassStaticsPackageFragmentDescriptor) {
125 JavaClassStaticsPackageFragmentDescriptor javaPackageFragment = (JavaClassStaticsPackageFragmentDescriptor) packageFragment;
126 return mapClass(javaPackageFragment.getCorrespondingClass()).getInternalName();
127 }
128
129 // It's not a package created for Java class statics
130 JetFile file = BindingContextUtils.getContainingFile(bindingContext, descriptor);
131 if (insideModule && file != null) {
132 return PackageCodegen.getPackagePartInternalName(file);
133 }
134 else {
135 return PackageClassUtils.getPackageClassFqName(packageFragment.getFqName()).asString().replace('.', '/');
136 }
137 }
138
139 @NotNull
140 public Type mapReturnType(@NotNull CallableDescriptor descriptor) {
141 return mapReturnType(descriptor, null);
142 }
143
144 @NotNull
145 private Type mapReturnType(@NotNull CallableDescriptor descriptor, @Nullable BothSignatureWriter sw) {
146 JetType returnType = descriptor.getReturnType();
147 assert returnType != null : "Function has no return type: " + descriptor;
148 if (returnType.equals(KotlinBuiltIns.getInstance().getUnitType()) && !(descriptor instanceof PropertyGetterDescriptor)) {
149 if (sw != null) {
150 sw.writeAsmType(Type.VOID_TYPE);
151 }
152 return Type.VOID_TYPE;
153 }
154 else {
155 return mapType(returnType, sw, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE, false);
156 }
157 }
158
159 @NotNull
160 private Type mapType(@NotNull JetType jetType, @NotNull JetTypeMapperMode mode) {
161 return mapType(jetType, null, mode);
162 }
163
164 @NotNull
165 public Type mapSupertype(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
166 return mapType(jetType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE);
167 }
168
169 @NotNull
170 public Type mapClass(@NotNull ClassifierDescriptor classifier) {
171 return mapType(classifier.getDefaultType(), null, JetTypeMapperMode.IMPL);
172 }
173
174 @NotNull
175 public Type mapType(@NotNull JetType jetType) {
176 return mapType(jetType, null, JetTypeMapperMode.VALUE);
177 }
178
179 @NotNull
180 public Type mapType(@NotNull CallableDescriptor descriptor) {
181 //noinspection ConstantConditions
182 return mapType(descriptor.getReturnType());
183 }
184
185 @NotNull
186 public Type mapType(@NotNull ClassifierDescriptor descriptor) {
187 return mapType(descriptor.getDefaultType());
188 }
189
190 @NotNull
191 private Type mapType(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode mode) {
192 return mapType(jetType, signatureVisitor, mode, Variance.INVARIANT, false);
193 }
194
195 @NotNull
196 private Type mapType(
197 @NotNull JetType jetType,
198 @Nullable BothSignatureWriter signatureVisitor,
199 @NotNull JetTypeMapperMode kind,
200 @NotNull Variance howThisTypeIsUsed,
201 boolean arrayParameter
202 ) {
203 Type known = null;
204 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
205
206 if (descriptor instanceof ClassDescriptor) {
207 FqNameUnsafe className = DescriptorUtils.getFqName(descriptor);
208 if (className.isSafe()) {
209 known = KotlinToJavaTypesMap.getInstance().getJavaAnalog(className.toSafe(), jetType.isNullable());
210 }
211 }
212
213 boolean projectionsAllowed = kind != JetTypeMapperMode.SUPER_TYPE;
214 if (known != null) {
215 if (kind == JetTypeMapperMode.VALUE) {
216 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
217 }
218 else if (kind == JetTypeMapperMode.TYPE_PARAMETER || kind == JetTypeMapperMode.SUPER_TYPE) {
219 return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, arrayParameter, projectionsAllowed);
220 }
221 else if (kind == JetTypeMapperMode.IMPL) {
222 // TODO: enable and fix tests
223 //throw new IllegalStateException("must not map known type to IMPL when not compiling builtins: " + jetType);
224 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
225 }
226 else {
227 throw new IllegalStateException("unknown kind: " + kind);
228 }
229 }
230
231 TypeConstructor constructor = jetType.getConstructor();
232 if (constructor instanceof IntersectionTypeConstructor) {
233 jetType = CommonSupertypes.commonSupertype(new ArrayList<JetType>(constructor.getSupertypes()));
234 }
235
236 if (descriptor == null) {
237 throw new UnsupportedOperationException("no descriptor for type constructor of " + jetType);
238 }
239
240 if (ErrorUtils.isError(descriptor)) {
241 if (classBuilderMode != ClassBuilderMode.LIGHT_CLASSES) {
242 throw new IllegalStateException(generateErrorMessageForErrorType(jetType, descriptor));
243 }
244 Type asmType = Type.getObjectType("error/NonExistentClass");
245 if (signatureVisitor != null) {
246 signatureVisitor.writeAsmType(asmType);
247 }
248 return asmType;
249 }
250
251 if (descriptor instanceof ClassDescriptor && KotlinBuiltIns.getInstance().isArray(jetType)) {
252 if (jetType.getArguments().size() != 1) {
253 throw new UnsupportedOperationException("arrays must have one type argument");
254 }
255 TypeProjection memberProjection = jetType.getArguments().get(0);
256 JetType memberType = memberProjection.getType();
257
258 if (signatureVisitor != null) {
259 signatureVisitor.writeArrayType();
260 mapType(memberType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER, memberProjection.getProjectionKind(), true);
261 signatureVisitor.writeArrayEnd();
262 }
263
264 if (memberType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
265 return AsmTypeConstants.getType(Object[].class);
266 }
267
268 return Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor());
269 }
270
271 if (descriptor instanceof ClassDescriptor) {
272 Type asmType = getAsmType(bindingTrace, (ClassDescriptor) descriptor);
273 writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
274 return asmType;
275 }
276
277 if (descriptor instanceof TypeParameterDescriptor) {
278 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
279 Type type = mapType(typeParameterDescriptor.getUpperBounds().iterator().next(), kind);
280 if (signatureVisitor != null) {
281 signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), type);
282 }
283 return type;
284 }
285
286 throw new UnsupportedOperationException("Unknown type " + jetType);
287 }
288
289 @NotNull
290 public Type mapTraitImpl(@NotNull ClassDescriptor descriptor) {
291 return Type.getObjectType(getAsmType(bindingTrace, descriptor).getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
292 }
293
294 @NotNull
295 private String generateErrorMessageForErrorType(@NotNull JetType type, @NotNull DeclarationDescriptor descriptor) {
296 PsiElement declarationElement = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor);
297 PsiElement parentDeclarationElement = null;
298 if (declarationElement != null) {
299 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
300 if (containingDeclaration != null) {
301 parentDeclarationElement = BindingContextUtils.descriptorToDeclaration(bindingContext, containingDeclaration);
302 }
303 }
304
305 return String.format("Error types are not allowed when classBuilderMode = %s. " +
306 "Type: %s (%s). Descriptor: %s. For declaration %s:%s in %s:%s",
307 classBuilderMode,
308 type,
309 type.getClass().getSimpleName(),
310 descriptor,
311 declarationElement,
312 declarationElement != null ? declarationElement.getText() : "null",
313 parentDeclarationElement,
314 parentDeclarationElement != null ? parentDeclarationElement.getText() : "null");
315 }
316
317 private void writeGenericType(
318 BothSignatureWriter signatureVisitor,
319 Type asmType,
320 JetType jetType,
321 Variance howThisTypeIsUsed,
322 boolean projectionsAllowed
323 ) {
324 if (signatureVisitor != null) {
325 signatureVisitor.writeClassBegin(asmType);
326
327 List<TypeProjection> arguments = jetType.getArguments();
328 for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
329 TypeProjection argument = arguments.get(parameter.getIndex());
330
331 Variance projectionKind = projectionsAllowed
332 ? getEffectiveVariance(
333 parameter.getVariance(),
334 argument.getProjectionKind(),
335 howThisTypeIsUsed
336 )
337 : Variance.INVARIANT;
338 signatureVisitor.writeTypeArgument(projectionKind);
339
340 mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
341 signatureVisitor.writeTypeArgumentEnd();
342 }
343 signatureVisitor.writeClassEnd();
344 }
345 }
346
347 private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
348 // Return type must not contain wildcards
349 if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
350
351 if (parameterVariance == Variance.INVARIANT) {
352 return projectionKind;
353 }
354 if (projectionKind == Variance.INVARIANT) {
355 return parameterVariance;
356 }
357 if (parameterVariance == projectionKind) {
358 return parameterVariance;
359 }
360
361 // In<out X> = In<*>
362 // Out<in X> = Out<*>
363 return Variance.OUT_VARIANCE;
364 }
365
366 private Type mapKnownAsmType(
367 JetType jetType,
368 Type asmType,
369 @Nullable BothSignatureWriter signatureVisitor,
370 @NotNull Variance howThisTypeIsUsed
371 ) {
372 return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, false, true);
373 }
374
375 private Type mapKnownAsmType(
376 JetType jetType,
377 Type asmType,
378 @Nullable BothSignatureWriter signatureVisitor,
379 @NotNull Variance howThisTypeIsUsed,
380 boolean arrayParameter,
381 boolean allowProjections
382 ) {
383 if (signatureVisitor != null) {
384 if (jetType.getArguments().isEmpty()) {
385 if (arrayParameter && howThisTypeIsUsed == Variance.IN_VARIANCE) {
386 asmType = AsmTypeConstants.OBJECT_TYPE;
387 }
388 signatureVisitor.writeAsmType(asmType);
389 }
390 else {
391 writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, allowProjections);
392 }
393 }
394 return asmType;
395 }
396
397 @NotNull
398 public CallableMethod mapToCallableMethod(
399 @NotNull FunctionDescriptor functionDescriptor,
400 boolean superCall,
401 @NotNull CodegenContext<?> context
402 ) {
403 DeclarationDescriptor functionParent = functionDescriptor.getOriginal().getContainingDeclaration();
404
405 functionDescriptor = unwrapFakeOverride(functionDescriptor.getOriginal());
406
407 JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal());
408 Type owner;
409 Type ownerForDefaultImpl;
410 Type ownerForDefaultParam;
411 int invokeOpcode;
412 Type thisClass;
413 Type calleeType = null;
414
415 if (isLocalNamedFun(functionDescriptor) || functionDescriptor instanceof ExpressionAsFunctionDescriptor) {
416 if (functionDescriptor instanceof ExpressionAsFunctionDescriptor) {
417 JetExpression expression = JetPsiUtil.deparenthesize(((ExpressionAsFunctionDescriptor) functionDescriptor).getExpression());
418 if (expression instanceof JetFunctionLiteralExpression) {
419 expression = ((JetFunctionLiteralExpression) expression).getFunctionLiteral();
420 }
421 functionDescriptor = bindingContext.get(BindingContext.FUNCTION, expression);
422 }
423 functionDescriptor = functionDescriptor.getOriginal();
424
425 owner = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
426 ownerForDefaultImpl = ownerForDefaultParam = thisClass = owner;
427 invokeOpcode = INVOKEVIRTUAL;
428 descriptor = mapSignature(functionDescriptor);
429 calleeType = owner;
430 }
431 else if (functionParent instanceof PackageFragmentDescriptor) {
432 assert !superCall;
433 owner = asmTypeForPackage((PackageFragmentDescriptor) functionParent, functionDescriptor,
434 isCallInsideSameModuleAsDeclared(functionDescriptor, context));
435 ownerForDefaultImpl = ownerForDefaultParam = owner;
436 invokeOpcode = INVOKESTATIC;
437 thisClass = null;
438 }
439 else if (functionDescriptor instanceof ConstructorDescriptor) {
440 assert !superCall;
441 owner = mapClass((ClassDescriptor) functionParent);
442 ownerForDefaultImpl = ownerForDefaultParam = owner;
443 invokeOpcode = INVOKESPECIAL;
444 thisClass = null;
445 }
446 else if (functionParent instanceof ScriptDescriptor) {
447 thisClass = owner = ownerForDefaultParam = ownerForDefaultImpl =
448 asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) functionParent);
449 invokeOpcode = INVOKEVIRTUAL;
450 }
451 else if (functionParent instanceof ClassDescriptor) {
452
453 FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
454
455 ClassDescriptor currentOwner = (ClassDescriptor) functionParent;
456 ClassDescriptor declarationOwner = (ClassDescriptor) declarationFunctionDescriptor.getContainingDeclaration();
457
458 boolean originalIsInterface = isInterface(declarationOwner);
459 boolean currentIsInterface = isInterface(currentOwner);
460
461 ClassDescriptor receiver;
462 if (currentIsInterface && !originalIsInterface) {
463 receiver = declarationOwner;
464 }
465 else {
466 receiver = currentOwner;
467 }
468
469 boolean isInterface = originalIsInterface && currentIsInterface;
470 owner = mapClass(receiver);
471
472 ClassDescriptor declarationOwnerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration();
473 ownerForDefaultParam = mapClass(declarationOwnerForDefault);
474 ownerForDefaultImpl = Type.getObjectType(
475 ownerForDefaultParam.getInternalName() + (isInterface(declarationOwnerForDefault) ? JvmAbi.TRAIT_IMPL_SUFFIX : ""));
476 if (isInterface) {
477 invokeOpcode = superCall ? INVOKESTATIC : INVOKEINTERFACE;
478 }
479 else {
480 if (isAccessor(functionDescriptor)) {
481 invokeOpcode = INVOKESTATIC;
482 }
483 else {
484 boolean isPrivateFunInvocation = isCallInsideSameClassAsDeclared(functionDescriptor, context) &&
485 functionDescriptor.getVisibility() == Visibilities.PRIVATE;
486 invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL;
487 }
488 }
489
490 if (isInterface && superCall) {
491 descriptor = mapSignature(functionDescriptor, OwnerKind.TRAIT_IMPL);
492 owner = Type.getObjectType(owner.getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
493 }
494 thisClass = mapType(receiver.getDefaultType());
495 }
496 else {
497 throw new UnsupportedOperationException("unknown function parent");
498 }
499
500
501 Type receiverParameterType;
502 ReceiverParameterDescriptor receiverParameter = functionDescriptor.getOriginal().getReceiverParameter();
503 if (receiverParameter != null) {
504 receiverParameterType = mapType(receiverParameter.getType());
505 }
506 else {
507 receiverParameterType = null;
508 }
509 return new CallableMethod(
510 owner, ownerForDefaultImpl, ownerForDefaultParam, descriptor, invokeOpcode,
511 thisClass, receiverParameterType, calleeType);
512 }
513
514 public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
515 return descriptor instanceof AccessorForFunctionDescriptor ||
516 descriptor instanceof AccessorForPropertyDescriptor ||
517 descriptor instanceof AccessorForPropertyDescriptor.Getter ||
518 descriptor instanceof AccessorForPropertyDescriptor.Setter;
519 }
520
521 @NotNull
522 private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) {
523 if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
524 return function;
525 }
526 return findBaseDeclaration(function);
527 }
528
529 @NotNull
530 private static FunctionDescriptor findBaseDeclaration(@NotNull FunctionDescriptor function) {
531 if (function.getOverriddenDescriptors().isEmpty()) {
532 return function;
533 }
534 else {
535 // TODO: prefer class to interface
536 return findBaseDeclaration(function.getOverriddenDescriptors().iterator().next());
537 }
538 }
539
540 @NotNull
541 private static String mapFunctionName(@NotNull FunctionDescriptor descriptor) {
542 if (descriptor instanceof PropertyAccessorDescriptor) {
543 PropertyDescriptor property = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
544 if (isAnnotationClass(property.getContainingDeclaration())) {
545 return property.getName().asString();
546 }
547
548 if (descriptor instanceof PropertyGetterDescriptor) {
549 return PropertyCodegen.getterName(property.getName());
550 }
551 else {
552 return PropertyCodegen.setterName(property.getName());
553 }
554 }
555 else if (isLocalNamedFun(descriptor) ||
556 descriptor instanceof AnonymousFunctionDescriptor ||
557 descriptor instanceof ExpressionAsFunctionDescriptor) {
558 return "invoke";
559 }
560 else {
561 return descriptor.getName().asString();
562 }
563 }
564
565 @NotNull
566 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor descriptor) {
567 return mapSignature(descriptor, OwnerKind.IMPLEMENTATION);
568 }
569
570 @NotNull
571 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
572 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
573
574 if (f instanceof ConstructorDescriptor) {
575 sw.writeParametersStart();
576 writeAdditionalConstructorParameters((ConstructorDescriptor) f, sw);
577
578 for (ValueParameterDescriptor parameter : f.getOriginal().getValueParameters()) {
579 writeParameter(sw, parameter.getType());
580 }
581
582 writeVoidReturn(sw);
583 }
584 else {
585 if (f instanceof PropertyAccessorDescriptor) {
586 writeFormalTypeParameters(((PropertyAccessorDescriptor) f).getCorrespondingProperty().getTypeParameters(), sw);
587 }
588 else {
589 writeFormalTypeParameters(f.getTypeParameters(), sw);
590 }
591
592 sw.writeParametersStart();
593 writeThisIfNeeded(f, kind, sw);
594 writeReceiverIfNeeded(f.getReceiverParameter(), sw);
595
596 for (ValueParameterDescriptor parameter : f.getValueParameters()) {
597 writeParameter(sw, parameter.getType());
598 }
599
600 sw.writeReturnType();
601 if (forceBoxedReturnType(f)) {
602 // TYPE_PARAMETER is a hack to automatically box the return type
603 //noinspection ConstantConditions
604 mapType(f.getReturnType(), sw, JetTypeMapperMode.TYPE_PARAMETER);
605 }
606 else {
607 mapReturnType(f, sw);
608 }
609 sw.writeReturnTypeEnd();
610 }
611
612 return sw.makeJvmMethodSignature(mapFunctionName(f));
613 }
614
615 /**
616 * @return true iff a given function descriptor should be compiled to a method with boxed return type regardless of whether return type
617 * of that descriptor is nullable or not. This happens when a function returning a value of a primitive type overrides another function
618 * with a non-primitive return type. In that case the generated method's return type should be boxed: otherwise it's not possible to use
619 * this class from Java since javac issues errors when loading the class (incompatible return types)
620 */
621 private static boolean forceBoxedReturnType(@NotNull FunctionDescriptor descriptor) {
622 //noinspection ConstantConditions
623 if (!KotlinBuiltIns.getInstance().isPrimitiveType(descriptor.getReturnType())) return false;
624
625 for (FunctionDescriptor overridden : descriptor.getOverriddenDescriptors()) {
626 //noinspection ConstantConditions
627 if (!KotlinBuiltIns.getInstance().isPrimitiveType(overridden.getOriginal().getReturnType())) return true;
628 }
629
630 return false;
631 }
632
633 private static void writeVoidReturn(@NotNull BothSignatureWriter sw) {
634 sw.writeReturnType();
635 sw.writeAsmType(Type.VOID_TYPE);
636 sw.writeReturnTypeEnd();
637 }
638
639 @Nullable
640 public String mapFieldSignature(@NotNull JetType backingFieldType) {
641 BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
642 mapType(backingFieldType, signatureVisitor, JetTypeMapperMode.VALUE);
643 return signatureVisitor.makeJavaGenericSignature();
644 }
645
646 private void writeThisIfNeeded(
647 @NotNull CallableMemberDescriptor descriptor,
648 @NotNull OwnerKind kind,
649 @NotNull BothSignatureWriter sw
650 ) {
651 if (kind == OwnerKind.TRAIT_IMPL) {
652 ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
653 Type type = getTraitImplThisParameterType(containingDeclaration, this);
654
655 sw.writeParameterType(JvmMethodParameterKind.THIS);
656 sw.writeAsmType(type);
657 sw.writeParameterTypeEnd();
658 }
659 else if (isAccessor(descriptor) && descriptor.getExpectedThisObject() != null) {
660 sw.writeParameterType(JvmMethodParameterKind.THIS);
661 mapType(((ClassifierDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), sw, JetTypeMapperMode.VALUE);
662 sw.writeParameterTypeEnd();
663 }
664 }
665
666
667 public void writeFormalTypeParameters(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull BothSignatureWriter sw) {
668 for (TypeParameterDescriptor typeParameter : typeParameters) {
669 writeFormalTypeParameter(typeParameter, sw);
670 }
671 }
672
673 private void writeFormalTypeParameter(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull BothSignatureWriter sw) {
674 sw.writeFormalTypeParameter(typeParameterDescriptor.getName().asString());
675
676 classBound:
677 {
678 sw.writeClassBound();
679
680 for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
681 if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
682 if (!isInterface(jetType)) {
683 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
684 break classBound;
685 }
686 }
687 }
688
689 // "extends Object" is optional according to ClassFileFormat-Java5.pdf
690 // but javac complaints to signature:
691 // <P:>Ljava/lang/Object;
692 // TODO: avoid writing java/lang/Object if interface list is not empty
693 }
694 sw.writeClassBoundEnd();
695
696 for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
697 if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
698 if (isInterface(jetType)) {
699 sw.writeInterfaceBound();
700 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
701 sw.writeInterfaceBoundEnd();
702 }
703 }
704 if (jetType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
705 sw.writeInterfaceBound();
706 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
707 sw.writeInterfaceBoundEnd();
708 }
709 }
710 }
711
712 private void writeReceiverIfNeeded(@Nullable ReceiverParameterDescriptor receiver, @NotNull BothSignatureWriter sw) {
713 if (receiver != null) {
714 sw.writeParameterType(JvmMethodParameterKind.RECEIVER);
715 mapType(receiver.getType(), sw, JetTypeMapperMode.VALUE);
716 sw.writeParameterTypeEnd();
717 }
718 }
719
720 private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JetType type) {
721 sw.writeParameterType(JvmMethodParameterKind.VALUE);
722 mapType(type, sw, JetTypeMapperMode.VALUE);
723 sw.writeParameterTypeEnd();
724 }
725
726 private void writeAdditionalConstructorParameters(
727 @NotNull ConstructorDescriptor descriptor,
728 @NotNull BothSignatureWriter signatureWriter
729 ) {
730 CalculatedClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
731
732 ClassDescriptor captureThis = getExpectedThisObjectForConstructorCall(descriptor, closure);
733 if (captureThis != null) {
734 signatureWriter.writeParameterType(JvmMethodParameterKind.OUTER);
735 mapType(captureThis.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE);
736 signatureWriter.writeParameterTypeEnd();
737 }
738
739 JetType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null;
740 if (captureReceiverType != null) {
741 signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER);
742 mapType(captureReceiverType, signatureWriter, JetTypeMapperMode.VALUE);
743 signatureWriter.writeParameterTypeEnd();
744 }
745
746 ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
747 if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
748 signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_NAME);
749 mapType(KotlinBuiltIns.getInstance().getStringType(), signatureWriter, JetTypeMapperMode.VALUE);
750 signatureWriter.writeParameterTypeEnd();
751 signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_ORDINAL);
752 mapType(KotlinBuiltIns.getInstance().getIntType(), signatureWriter, JetTypeMapperMode.VALUE);
753 signatureWriter.writeParameterTypeEnd();
754 }
755
756 if (closure == null) return;
757
758 for (DeclarationDescriptor variableDescriptor : closure.getCaptureVariables().keySet()) {
759 Type type;
760 if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
761 Type sharedVarType = getSharedVarType(variableDescriptor);
762 if (sharedVarType == null) {
763 sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
764 }
765 type = sharedVarType;
766 }
767 else if (isLocalNamedFun(variableDescriptor)) {
768 type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor);
769 }
770 else {
771 type = null;
772 }
773
774 if (type != null) {
775 signatureWriter.writeParameterType(JvmMethodParameterKind.SHARED_VAR);
776 signatureWriter.writeAsmType(type);
777 signatureWriter.writeParameterTypeEnd();
778 }
779 }
780
781 JetDelegatorToSuperCall superCall = closure.getSuperCall();
782 if (superCall != null) {
783 DeclarationDescriptor superDescriptor = bindingContext
784 .get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
785
786 if (superDescriptor instanceof ConstructorDescriptor && isAnonymousObject(descriptor.getContainingDeclaration())) {
787 for (JvmMethodParameterSignature parameter : mapSignature((ConstructorDescriptor) superDescriptor).getValueParameters()) {
788 signatureWriter.writeParameterType(JvmMethodParameterKind.SUPER_CALL_PARAM);
789 signatureWriter.writeAsmType(parameter.getAsmType());
790 signatureWriter.writeParameterTypeEnd();
791 }
792 }
793 }
794 }
795
796 @NotNull
797 public JvmMethodSignature mapScriptSignature(@NotNull ScriptDescriptor script, @NotNull List<ScriptDescriptor> importedScripts) {
798 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
799
800 signatureWriter.writeParametersStart();
801
802 for (ScriptDescriptor importedScript : importedScripts) {
803 signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
804 ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript);
805 assert descriptor != null;
806 mapType(descriptor.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE);
807 signatureWriter.writeParameterTypeEnd();
808 }
809
810 for (ValueParameterDescriptor valueParameter : script.getValueParameters()) {
811 writeParameter(signatureWriter, valueParameter.getType());
812 }
813
814 writeVoidReturn(signatureWriter);
815
816 return signatureWriter.makeJvmMethodSignature("<init>");
817 }
818
819 @NotNull
820 public CallableMethod mapToCallableMethod(@NotNull ConstructorDescriptor descriptor) {
821 JvmMethodSignature method = mapSignature(descriptor);
822 ClassDescriptor container = descriptor.getContainingDeclaration();
823 Type owner = mapClass(container);
824 if (owner.getSort() != Type.OBJECT) {
825 throw new IllegalStateException("type must have been mapped to object: " + container.getDefaultType() + ", actual: " + owner);
826 }
827 return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null);
828 }
829
830 public Type getSharedVarType(DeclarationDescriptor descriptor) {
831 if (descriptor instanceof PropertyDescriptor) {
832 return StackValue.sharedTypeForType(mapType(((PropertyDescriptor) descriptor).getReceiverParameter().getType()));
833 }
834 else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
835 return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
836 }
837 else if (descriptor instanceof FunctionDescriptor) {
838 return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType()));
839 }
840 else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
841 JetType outType = ((VariableDescriptor) descriptor).getType();
842 return StackValue.sharedTypeForType(mapType(outType));
843 }
844 return null;
845 }
846
847 @NotNull
848 public CallableMethod mapToFunctionInvokeCallableMethod(@NotNull FunctionDescriptor fd) {
849 JvmMethodSignature signature = erasedInvokeSignature(fd);
850 Type owner = getFunctionTraitClassName(fd);
851 Type receiverParameterType;
852 ReceiverParameterDescriptor receiverParameter = fd.getOriginal().getReceiverParameter();
853 if (receiverParameter != null) {
854 receiverParameterType = mapType(receiverParameter.getType());
855 }
856 else {
857 receiverParameterType = null;
858 }
859 return new CallableMethod(owner, null, null, signature, INVOKEINTERFACE, owner, receiverParameterType, owner);
860 }
861
862 @NotNull
863 private static JvmMethodSignature erasedInvokeSignature(@NotNull FunctionDescriptor descriptor) {
864 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
865
866 int paramCount = descriptor.getValueParameters().size();
867 if (descriptor.getReceiverParameter() != null) {
868 paramCount++;
869 }
870
871 sw.writeParametersStart();
872
873 for (int i = 0; i < paramCount; ++i) {
874 sw.writeParameterType(JvmMethodParameterKind.VALUE);
875 sw.writeAsmType(OBJECT_TYPE);
876 sw.writeParameterTypeEnd();
877 }
878
879 sw.writeReturnType();
880 sw.writeAsmType(OBJECT_TYPE);
881 sw.writeReturnTypeEnd();
882
883 return sw.makeJvmMethodSignature("invoke");
884 }
885 }