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