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