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