001    /*
002     * Copyright 2010-2015 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.kotlin.codegen;
018    
019    import com.intellij.openapi.progress.ProcessCanceledException;
020    import com.intellij.psi.PsiElement;
021    import com.intellij.util.ArrayUtil;
022    import kotlin.Unit;
023    import kotlin.collections.CollectionsKt;
024    import kotlin.jvm.functions.Function0;
025    import kotlin.jvm.functions.Function1;
026    import kotlin.jvm.functions.Function2;
027    import org.jetbrains.annotations.NotNull;
028    import org.jetbrains.annotations.Nullable;
029    import org.jetbrains.kotlin.backend.common.CodegenUtil;
030    import org.jetbrains.kotlin.backend.common.CodegenUtilKt;
031    import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator;
032    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
033    import org.jetbrains.kotlin.codegen.binding.MutableClosure;
034    import org.jetbrains.kotlin.codegen.context.*;
035    import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
036    import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
037    import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension;
038    import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
039    import org.jetbrains.kotlin.codegen.state.GenerationState;
040    import org.jetbrains.kotlin.descriptors.*;
041    import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
042    import org.jetbrains.kotlin.lexer.KtTokens;
043    import org.jetbrains.kotlin.load.java.JvmAbi;
044    import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
045    import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
046    import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
047    import org.jetbrains.kotlin.name.FqName;
048    import org.jetbrains.kotlin.name.Name;
049    import org.jetbrains.kotlin.psi.*;
050    import org.jetbrains.kotlin.resolve.BindingContext;
051    import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
052    import org.jetbrains.kotlin.resolve.DescriptorUtils;
053    import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt;
054    import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
055    import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
056    import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
057    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
058    import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument;
059    import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
060    import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
061    import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
062    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
063    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
064    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
065    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
066    import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
067    import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
068    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
069    import org.jetbrains.kotlin.serialization.DescriptorSerializer;
070    import org.jetbrains.kotlin.serialization.ProtoBuf;
071    import org.jetbrains.kotlin.types.KotlinType;
072    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
073    import org.jetbrains.org.objectweb.asm.*;
074    import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
075    import org.jetbrains.org.objectweb.asm.commons.Method;
076    
077    import java.util.*;
078    
079    import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES;
080    import static org.jetbrains.kotlin.codegen.AsmUtil.*;
081    import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
082    import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
083    import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
084    import static org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull;
085    import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
086    import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
087    import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE;
088    import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
089    import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
090    import static org.jetbrains.kotlin.types.Variance.INVARIANT;
091    import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isLocalFunction;
092    import static org.jetbrains.org.objectweb.asm.Opcodes.*;
093    
094    public class ImplementationBodyCodegen extends ClassBodyCodegen {
095        private static final String ENUM_VALUES_FIELD_NAME = "$VALUES";
096        private Type superClassAsmType;
097        @Nullable // null means java/lang/Object
098        private KotlinType superClassType;
099        private final Type classAsmType;
100        private final boolean isLocal;
101    
102        private List<PropertyAndDefaultValue> companionObjectPropertiesToCopy;
103    
104        private final DelegationFieldsInfo delegationFieldsInfo;
105    
106        private final List<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>> additionalTasks =
107                new ArrayList<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>>();
108    
109        public ImplementationBodyCodegen(
110                @NotNull KtClassOrObject aClass,
111                @NotNull ClassContext context,
112                @NotNull ClassBuilder v,
113                @NotNull GenerationState state,
114                @Nullable MemberCodegen<?> parentCodegen,
115                boolean isLocal
116        ) {
117            super(aClass, context, v, state, parentCodegen);
118            this.classAsmType = typeMapper.mapClass(descriptor);
119            this.isLocal = isLocal;
120            delegationFieldsInfo = getDelegationFieldsInfo(myClass.getSuperTypeListEntries());
121        }
122    
123        @Override
124        protected void generateDeclaration() {
125            getSuperClass();
126    
127            JvmClassSignature signature = signature();
128    
129            boolean isAbstract = false;
130            boolean isInterface = false;
131            boolean isFinal = false;
132            boolean isStatic;
133            boolean isAnnotation = false;
134            boolean isEnum = false;
135    
136            if (myClass instanceof KtClass) {
137                KtClass ktClass = (KtClass) myClass;
138                if (ktClass.hasModifier(KtTokens.ABSTRACT_KEYWORD) || ktClass.isSealed()) {
139                    isAbstract = true;
140                }
141                if (ktClass.isInterface()) {
142                    isAbstract = true;
143                    isInterface = true;
144                }
145                else if (descriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
146                    isAbstract = true;
147                    isInterface = true;
148                    isAnnotation = true;
149                }
150                else if (ktClass.isEnum()) {
151                    isAbstract = hasAbstractMembers(descriptor);
152                    isEnum = true;
153                }
154    
155                if (isObject(descriptor)) {
156                    isFinal = true;
157                }
158    
159                if (!ktClass.hasModifier(KtTokens.OPEN_KEYWORD) && !isAbstract) {
160                    // Light-class mode: Do not make enum classes final since PsiClass corresponding to enum is expected to be inheritable from
161                    isFinal = !(ktClass.isEnum() && state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES);
162                }
163                isStatic = !ktClass.isInner();
164            }
165            else {
166                isStatic = isCompanionObject(descriptor);
167                isFinal = true;
168            }
169    
170            int access = 0;
171    
172            if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES && !DescriptorUtils.isTopLevelDeclaration(descriptor)) {
173                // ClassBuilderMode.LIGHT_CLASSES means we are generating light classes & looking at a nested or inner class
174                // Light class generation is implemented so that Cls-classes only read bare code of classes,
175                // without knowing whether these classes are inner or not (see ClassStubBuilder.EMPTY_STRATEGY)
176                // Thus we must write full accessibility flags on inner classes in this mode
177                access |= getVisibilityAccessFlag(descriptor);
178                // Same for STATIC
179                if (isStatic) {
180                    access |= ACC_STATIC;
181                }
182            }
183            else {
184                access |= getVisibilityAccessFlagForClass(descriptor);
185            }
186            if (isAbstract) {
187                access |= ACC_ABSTRACT;
188            }
189            if (isInterface) {
190                access |= ACC_INTERFACE; // ACC_SUPER
191            }
192            else {
193                access |= ACC_SUPER;
194            }
195            if (isFinal) {
196                access |= ACC_FINAL;
197            }
198            if (isAnnotation) {
199                access |= ACC_ANNOTATION;
200            }
201            if (KotlinBuiltIns.isDeprecated(descriptor)) {
202                access |= ACC_DEPRECATED;
203            }
204            if (isEnum) {
205                for (KtDeclaration declaration : myClass.getDeclarations()) {
206                    if (declaration instanceof KtEnumEntry) {
207                        if (enumEntryNeedSubclass(bindingContext, (KtEnumEntry) declaration)) {
208                            access &= ~ACC_FINAL;
209                        }
210                    }
211                }
212                access |= ACC_ENUM;
213            }
214    
215            v.defineClass(
216                    myClass, V1_6,
217                    access,
218                    signature.getName(),
219                    signature.getJavaGenericSignature(),
220                    signature.getSuperclassName(),
221                    ArrayUtil.toStringArray(signature.getInterfaces())
222            );
223    
224            v.visitSource(myClass.getContainingFile().getName(), null);
225    
226            InlineCodegenUtil.initDefaultSourceMappingIfNeeded(context, this, state);
227    
228            writeEnclosingMethod();
229    
230            AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null);
231    
232            generateEnumEntries();
233        }
234    
235        @Override
236        protected void generateDefaultImplsIfNeeded() {
237            if (isInterface(descriptor) && !isLocal) {
238                Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
239                ClassBuilder defaultImplsBuilder =
240                        state.getFactory().newVisitor(JvmDeclarationOriginKt.TraitImpl(myClass, descriptor), defaultImplsType, myClass.getContainingFile());
241    
242                CodegenContext parentContext = context.getParentContext();
243                assert parentContext != null : "Parent context of interface declaration should not be null";
244    
245                ClassContext defaultImplsContext = parentContext.intoDefaultImplsClass(descriptor, (ClassContext) context, state);
246                new InterfaceImplBodyCodegen(myClass, defaultImplsContext, defaultImplsBuilder, state, this).generate();
247            }
248        }
249    
250        @Override
251        protected void generateKotlinAnnotation() {
252            final DescriptorSerializer serializer =
253                    DescriptorSerializer.create(descriptor, new JvmSerializerExtension(v.getSerializationBindings(), state));
254    
255            final ProtoBuf.Class classProto = serializer.classProto(descriptor).build();
256    
257            WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.CLASS, new Function1<AnnotationVisitor, Unit>() {
258                @Override
259                public Unit invoke(AnnotationVisitor av) {
260                    writeAnnotationData(av, serializer, classProto, false);
261                    return Unit.INSTANCE;
262                }
263            });
264    
265            AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true);
266            writeAbiVersion(av);
267            writeAnnotationData(av, serializer, classProto, true);
268            av.visitEnd();
269        }
270    
271        private void writeEnclosingMethod() {
272            // Do not emit enclosing method in "light-classes mode" since currently we generate local light classes as if they're top level
273            if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) {
274                return;
275            }
276    
277            //JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class.
278            if (isAnonymousObject(descriptor) || !(descriptor.getContainingDeclaration() instanceof ClassOrPackageFragmentDescriptor)) {
279                writeOuterClassAndEnclosingMethod();
280            }
281        }
282    
283        private static final Map<FqName, String> KOTLIN_MARKER_INTERFACES = new HashMap<FqName, String>();
284        static {
285            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.iterator, "kotlin/jvm/internal/markers/KMappedMarker");
286            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.iterable, "kotlin/jvm/internal/markers/KMappedMarker");
287            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.collection, "kotlin/jvm/internal/markers/KMappedMarker");
288            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.list, "kotlin/jvm/internal/markers/KMappedMarker");
289            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.listIterator, "kotlin/jvm/internal/markers/KMappedMarker");
290            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.set, "kotlin/jvm/internal/markers/KMappedMarker");
291            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.map, "kotlin/jvm/internal/markers/KMappedMarker");
292            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mapEntry, "kotlin/jvm/internal/markers/KMappedMarker");
293    
294            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableIterator, "kotlin/jvm/internal/markers/KMutableIterator");
295            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableIterable, "kotlin/jvm/internal/markers/KMutableIterable");
296            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableCollection, "kotlin/jvm/internal/markers/KMutableCollection");
297            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableList, "kotlin/jvm/internal/markers/KMutableList");
298            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableListIterator, "kotlin/jvm/internal/markers/KMutableListIterator");
299            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableSet, "kotlin/jvm/internal/markers/KMutableSet");
300            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableMap, "kotlin/jvm/internal/markers/KMutableMap");
301            KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableMapEntry, "kotlin/jvm/internal/markers/KMutableMap$Entry");
302        }
303    
304        @NotNull
305        private JvmClassSignature signature() {
306            BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
307    
308            typeMapper.writeFormalTypeParameters(descriptor.getDeclaredTypeParameters(), sw);
309    
310            sw.writeSuperclass();
311            if (superClassType == null) {
312                sw.writeClassBegin(superClassAsmType);
313                sw.writeClassEnd();
314            }
315            else {
316                typeMapper.mapSupertype(superClassType, sw);
317            }
318            sw.writeSuperclassEnd();
319    
320            LinkedHashSet<String> superInterfaces = new LinkedHashSet<String>();
321            Set<String> kotlinMarkerInterfaces = new LinkedHashSet<String>();
322    
323            for (KotlinType supertype : descriptor.getTypeConstructor().getSupertypes()) {
324                if (isJvmInterface(supertype.getConstructor().getDeclarationDescriptor())) {
325                    sw.writeInterface();
326                    Type jvmInterfaceType = typeMapper.mapSupertype(supertype, sw);
327                    sw.writeInterfaceEnd();
328                    String jvmInterfaceInternalName = jvmInterfaceType.getInternalName();
329                    superInterfaces.add(jvmInterfaceInternalName);
330    
331                    FqName kotlinInterfaceName = DescriptorUtils.getFqName(supertype.getConstructor().getDeclarationDescriptor()).toSafe();
332                    String kotlinMarkerInterfaceInternalName = KOTLIN_MARKER_INTERFACES.get(kotlinInterfaceName);
333                    if (kotlinMarkerInterfaceInternalName != null) {
334                        kotlinMarkerInterfaces.add(kotlinMarkerInterfaceInternalName);
335                    }
336                }
337            }
338            
339            for (String kotlinMarkerInterface : kotlinMarkerInterfaces) {
340                sw.writeInterface();
341                sw.writeAsmType(Type.getObjectType(kotlinMarkerInterface));
342                sw.writeInterfaceEnd();
343            }
344    
345            superInterfaces.addAll(kotlinMarkerInterfaces);
346    
347            return new JvmClassSignature(classAsmType.getInternalName(), superClassAsmType.getInternalName(),
348                                         new ArrayList<String>(superInterfaces), sw.makeJavaGenericSignature());
349        }
350    
351        protected void getSuperClass() {
352            superClassAsmType = OBJECT_TYPE;
353            superClassType = null;
354    
355            if (descriptor.getKind() == ClassKind.INTERFACE) {
356                return;
357            }
358    
359            for (KotlinType supertype : descriptor.getTypeConstructor().getSupertypes()) {
360                ClassifierDescriptor superClass = supertype.getConstructor().getDeclarationDescriptor();
361                if (superClass != null && !isJvmInterface(superClass)) {
362                    superClassAsmType = typeMapper.mapClass(superClass);
363                    superClassType = supertype;
364                    return;
365                }
366            }
367        }
368    
369        @Override
370        protected void generateSyntheticParts() {
371            generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
372    
373            generateFieldForSingleton();
374    
375            generateCompanionObjectBackingFieldCopies();
376    
377            generateTraitMethods();
378    
379            generateDelegates(delegationFieldsInfo);
380    
381            if (!isInterface(descriptor)  || kind == OwnerKind.DEFAULT_IMPLS) {
382                generateSyntheticAccessors();
383            }
384    
385            generateEnumMethods();
386    
387            generateFunctionsForDataClasses();
388    
389            new CollectionStubMethodGenerator(state, descriptor, functionCodegen, v).generate();
390    
391            generateToArray();
392    
393            genClosureFields(context.closure, v, typeMapper);
394    
395            for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.Companion.getInstances(state.getProject())) {
396                extension.generateClassSyntheticParts(v, state, myClass, descriptor);
397            }
398        }
399    
400        @Override
401        protected void generateConstructors() {
402            try {
403                lookupConstructorExpressionsInClosureIfPresent();
404                generatePrimaryConstructor(delegationFieldsInfo);
405                for (ConstructorDescriptor secondaryConstructor : DescriptorUtilsKt.getSecondaryConstructors(descriptor)) {
406                    generateSecondaryConstructor(secondaryConstructor);
407                }
408            }
409            catch (CompilationException e) {
410                throw e;
411            }
412            catch (ProcessCanceledException e) {
413                throw e;
414            }
415            catch (RuntimeException e) {
416                throw new RuntimeException("Error generating constructors of class " + myClass.getName() + " with kind " + kind, e);
417            }
418        }
419    
420        private boolean isGenericToArrayPresent() {
421            Collection<FunctionDescriptor> functions =
422                    descriptor.getDefaultType().getMemberScope().getContributedFunctions(Name.identifier("toArray"), NoLookupLocation.FROM_BACKEND);
423            for (FunctionDescriptor function : functions) {
424                if (CallResolverUtilKt.isOrOverridesSynthesized(function)) {
425                    continue;
426                }
427    
428                if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) {
429                    continue;
430                }
431    
432                KotlinType returnType = function.getReturnType();
433                assert returnType != null : function.toString();
434                KotlinType paramType = function.getValueParameters().get(0).getType();
435                if (KotlinBuiltIns.isArray(returnType) && KotlinBuiltIns.isArray(paramType)) {
436                    KotlinType elementType = function.getTypeParameters().get(0).getDefaultType();
437                    if (KotlinTypeChecker.DEFAULT.equalTypes(elementType, DescriptorUtilsKt.getBuiltIns(descriptor).getArrayElementType(returnType))
438                        && KotlinTypeChecker.DEFAULT.equalTypes(elementType, DescriptorUtilsKt
439                            .getBuiltIns(descriptor).getArrayElementType(paramType))) {
440                        return true;
441                    }
442                }
443            }
444            return false;
445    
446        }
447    
448        private void generateToArray() {
449            KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor);
450            if (!isSubclass(descriptor, builtIns.getCollection())) return;
451    
452            int access = descriptor.getKind() == ClassKind.INTERFACE ?
453                         ACC_PUBLIC | ACC_ABSTRACT :
454                         ACC_PUBLIC;
455            if (CodegenUtil.getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toArray"), builtIns.getArray()) == null) {
456                MethodVisitor mv = v.newMethod(NO_ORIGIN, access, "toArray", "()[Ljava/lang/Object;", null, null);
457    
458                if (descriptor.getKind() != ClassKind.INTERFACE) {
459                    InstructionAdapter iv = new InstructionAdapter(mv);
460                    mv.visitCode();
461    
462                    iv.load(0, classAsmType);
463                    iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;", false);
464                    iv.areturn(Type.getType("[Ljava/lang/Object;"));
465    
466                    FunctionCodegen.endVisit(mv, "toArray", myClass);
467                }
468            }
469    
470            if (!isGenericToArrayPresent()) {
471                MethodVisitor mv = v.newMethod(NO_ORIGIN, access, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null);
472    
473                if (descriptor.getKind() != ClassKind.INTERFACE) {
474                    InstructionAdapter iv = new InstructionAdapter(mv);
475                    mv.visitCode();
476    
477                    iv.load(0, classAsmType);
478                    iv.load(1, Type.getType("[Ljava/lang/Object;"));
479    
480                    iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray",
481                                    "(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;", false);
482                    iv.areturn(Type.getType("[Ljava/lang/Object;"));
483    
484                    FunctionCodegen.endVisit(mv, "toArray", myClass);
485                }
486            }
487        }
488    
489        private void generateFunctionsForDataClasses() {
490            if (!descriptor.isData()) return;
491    
492            new DataClassMethodGeneratorImpl(myClass, bindingContext).generate();
493        }
494    
495        private class DataClassMethodGeneratorImpl extends DataClassMethodGenerator {
496            DataClassMethodGeneratorImpl(
497                    KtClassOrObject klass,
498                    BindingContext bindingContext
499            ) {
500                super(klass, bindingContext);
501            }
502    
503            @Override
504            public void generateEqualsMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> properties) {
505                MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(function);
506                MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(function), ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
507                InstructionAdapter iv = new InstructionAdapter(mv);
508    
509                mv.visitCode();
510                Label eq = new Label();
511                Label ne = new Label();
512    
513                iv.load(0, OBJECT_TYPE);
514                iv.load(1, OBJECT_TYPE);
515                iv.ifacmpeq(eq);
516    
517                iv.load(1, OBJECT_TYPE);
518                iv.instanceOf(classAsmType);
519                iv.ifeq(ne);
520    
521                iv.load(1, OBJECT_TYPE);
522                iv.checkcast(classAsmType);
523                iv.store(2, OBJECT_TYPE);
524    
525                for (PropertyDescriptor propertyDescriptor : properties) {
526                    Type asmType = typeMapper.mapType(propertyDescriptor);
527    
528                    Type thisPropertyType = genPropertyOnStack(iv, context, propertyDescriptor, 0);
529                    StackValue.coerce(thisPropertyType, asmType, iv);
530    
531                    Type otherPropertyType = genPropertyOnStack(iv, context, propertyDescriptor, 2);
532                    StackValue.coerce(otherPropertyType, asmType, iv);
533    
534                    if (asmType.getSort() == Type.FLOAT) {
535                        iv.invokestatic("java/lang/Float", "compare", "(FF)I", false);
536                        iv.ifne(ne);
537                    }
538                    else if (asmType.getSort() == Type.DOUBLE) {
539                        iv.invokestatic("java/lang/Double", "compare", "(DD)I", false);
540                        iv.ifne(ne);
541                    }
542                    else {
543                        StackValue value = genEqualsForExpressionsOnStack(KtTokens.EQEQ, StackValue.onStack(asmType), StackValue.onStack(asmType));
544                        value.put(Type.BOOLEAN_TYPE, iv);
545                        iv.ifeq(ne);
546                    }
547                }
548    
549                iv.mark(eq);
550                iv.iconst(1);
551                iv.areturn(Type.INT_TYPE);
552    
553                iv.mark(ne);
554                iv.iconst(0);
555                iv.areturn(Type.INT_TYPE);
556    
557                FunctionCodegen.endVisit(mv, "equals", myClass);
558            }
559    
560            @Override
561            public void generateHashCodeMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> properties) {
562                MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(function);
563                MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(function), ACC_PUBLIC, "hashCode", "()I", null, null);
564                InstructionAdapter iv = new InstructionAdapter(mv);
565    
566                mv.visitCode();
567                boolean first = true;
568                for (PropertyDescriptor propertyDescriptor : properties) {
569                    if (!first) {
570                        iv.iconst(31);
571                        iv.mul(Type.INT_TYPE);
572                    }
573    
574                    Type propertyType = genPropertyOnStack(iv, context, propertyDescriptor, 0);
575                    Type asmType = typeMapper.mapType(propertyDescriptor);
576                    StackValue.coerce(propertyType, asmType, iv);
577    
578                    Label ifNull = null;
579                    if (!isPrimitive(asmType)) {
580                        ifNull = new Label();
581                        iv.dup();
582                        iv.ifnull(ifNull);
583                    }
584    
585                    genHashCode(mv, iv, asmType);
586    
587                    if (ifNull != null) {
588                        Label end = new Label();
589                        iv.goTo(end);
590                        iv.mark(ifNull);
591                        iv.pop();
592                        iv.iconst(0);
593                        iv.mark(end);
594                    }
595    
596                    if (first) {
597                        first = false;
598                    }
599                    else {
600                        iv.add(Type.INT_TYPE);
601                    }
602                }
603    
604                mv.visitInsn(IRETURN);
605    
606                FunctionCodegen.endVisit(mv, "hashCode", myClass);
607            }
608    
609            @Override
610            public void generateToStringMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> properties) {
611                MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(function);
612                MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(function), ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
613                InstructionAdapter iv = new InstructionAdapter(mv);
614    
615                mv.visitCode();
616                genStringBuilderConstructor(iv);
617    
618                boolean first = true;
619                for (PropertyDescriptor propertyDescriptor : properties) {
620                    if (first) {
621                        iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().asString()+"=");
622                        first = false;
623                    }
624                    else {
625                        iv.aconst(", " + propertyDescriptor.getName().asString() + "=");
626                    }
627                    genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
628    
629                    Type type = genPropertyOnStack(iv, context, propertyDescriptor, 0);
630    
631                    if (type.getSort() == Type.ARRAY) {
632                        Type elementType = correctElementType(type);
633                        if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
634                            iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;", false);
635                            type = JAVA_STRING_TYPE;
636                        }
637                        else {
638                            if (elementType.getSort() != Type.CHAR) {
639                                iv.invokestatic("java/util/Arrays", "toString", "(" + type.getDescriptor() + ")Ljava/lang/String;", false);
640                                type = JAVA_STRING_TYPE;
641                            }
642                        }
643                    }
644                    genInvokeAppendMethod(iv, type);
645                }
646    
647                iv.aconst(")");
648                genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
649    
650                iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
651                iv.areturn(JAVA_STRING_TYPE);
652    
653                FunctionCodegen.endVisit(mv, "toString", myClass);
654            }
655    
656            private Type genPropertyOnStack(InstructionAdapter iv, MethodContext context, @NotNull PropertyDescriptor propertyDescriptor, int index) {
657                iv.load(index, classAsmType);
658                if (couldUseDirectAccessToProperty(propertyDescriptor, /* forGetter = */ true, /* isDelegated = */ false, context)) {
659                    Type type = typeMapper.mapType(propertyDescriptor.getType());
660                    String fieldName = ((FieldOwnerContext) context.getParentContext()).getFieldName(propertyDescriptor, false);
661                    iv.getfield(classAsmType.getInternalName(), fieldName, type.getDescriptor());
662                    return type.getReturnType();
663                }
664                else {
665                    //noinspection ConstantConditions
666                    Method method = typeMapper.mapSignature(propertyDescriptor.getGetter()).getAsmMethod();
667                    iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor(), false);
668                    return method.getReturnType();
669                }
670            }
671    
672            @Override
673            public void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull final ValueParameterDescriptor parameter) {
674                PsiElement originalElement = DescriptorToSourceUtils.descriptorToDeclaration(parameter);
675                functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(originalElement, function), function, new FunctionGenerationStrategy() {
676                    @Override
677                    public void generateBody(
678                            @NotNull MethodVisitor mv,
679                            @NotNull FrameMap frameMap,
680                            @NotNull JvmMethodSignature signature,
681                            @NotNull MethodContext context,
682                            @NotNull MemberCodegen<?> parentCodegen
683                    ) {
684                        Type componentType = signature.getReturnType();
685                        InstructionAdapter iv = new InstructionAdapter(mv);
686                        if (!componentType.equals(Type.VOID_TYPE)) {
687                            PropertyDescriptor property =
688                                    bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, descriptorToDeclaration(parameter));
689                            assert property != null : "Property descriptor is not found for primary constructor parameter: " + parameter;
690    
691                            Type propertyType = genPropertyOnStack(iv, context, property, 0);
692                            StackValue.coerce(propertyType, componentType, iv);
693                        }
694                        iv.areturn(componentType);
695                    }
696                });
697            }
698    
699            @Override
700            public void generateCopyFunction(@NotNull final FunctionDescriptor function, @NotNull List<KtParameter> constructorParameters) {
701                final Type thisDescriptorType = typeMapper.mapType(descriptor);
702    
703                functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(myClass, function), function, new FunctionGenerationStrategy() {
704                    @Override
705                    public void generateBody(
706                            @NotNull MethodVisitor mv,
707                            @NotNull FrameMap frameMap,
708                            @NotNull JvmMethodSignature signature,
709                            @NotNull MethodContext context,
710                            @NotNull MemberCodegen<?> parentCodegen
711                    ) {
712                        InstructionAdapter iv = new InstructionAdapter(mv);
713    
714                        iv.anew(thisDescriptorType);
715                        iv.dup();
716    
717                        ConstructorDescriptor constructor = getPrimaryConstructorOfDataClass(descriptor);
718                        assert function.getValueParameters().size() == constructor.getValueParameters().size() :
719                                "Number of parameters of copy function and constructor are different. " +
720                                "Copy: " + function.getValueParameters().size() + ", " +
721                                "constructor: " + constructor.getValueParameters().size();
722    
723                        MutableClosure closure = ImplementationBodyCodegen.this.context.closure;
724                        if (closure != null) {
725                            pushCapturedFieldsOnStack(iv, closure);
726                        }
727    
728                        int parameterIndex = 1; // localVariable 0 = this
729                        for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) {
730                            Type type = typeMapper.mapType(parameterDescriptor.getType());
731                            iv.load(parameterIndex, type);
732                            parameterIndex += type.getSize();
733                        }
734    
735                        Method constructorAsmMethod = typeMapper.mapSignature(constructor).getAsmMethod();
736                        iv.invokespecial(thisDescriptorType.getInternalName(), "<init>", constructorAsmMethod.getDescriptor(), false);
737    
738                        iv.areturn(thisDescriptorType);
739                    }
740    
741                    private void pushCapturedFieldsOnStack(InstructionAdapter iv, MutableClosure closure) {
742                        ClassDescriptor captureThis = closure.getCaptureThis();
743                        if (captureThis != null) {
744                            iv.load(0, classAsmType);
745                            Type type = typeMapper.mapType(captureThis);
746                            iv.getfield(classAsmType.getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor());
747                        }
748    
749                        KotlinType captureReceiver = closure.getCaptureReceiverType();
750                        if (captureReceiver != null) {
751                            iv.load(0, classAsmType);
752                            Type type = typeMapper.mapType(captureReceiver);
753                            iv.getfield(classAsmType.getInternalName(), CAPTURED_RECEIVER_FIELD, type.getDescriptor());
754                        }
755    
756                        for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) {
757                            DeclarationDescriptor declarationDescriptor = entry.getKey();
758                            EnclosedValueDescriptor enclosedValueDescriptor = entry.getValue();
759                            StackValue capturedValue = enclosedValueDescriptor.getInstanceValue();
760                            Type sharedVarType = typeMapper.getSharedVarType(declarationDescriptor);
761                            if (sharedVarType == null) {
762                                sharedVarType = typeMapper.mapType((VariableDescriptor) declarationDescriptor);
763                            }
764                            capturedValue.put(sharedVarType, iv);
765                        }
766                    }
767                });
768    
769                functionCodegen.generateDefaultIfNeeded(
770                        context.intoFunction(function), function, OwnerKind.IMPLEMENTATION,
771                        new DefaultParameterValueLoader() {
772                            @Override
773                            public StackValue genValue(ValueParameterDescriptor valueParameter, ExpressionCodegen codegen) {
774                                assert ((ClassDescriptor) function.getContainingDeclaration()).isData()
775                                        : "Function container must have [data] modifier: " + function;
776                                PropertyDescriptor property = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameter);
777                                assert property != null : "Copy function doesn't correspond to any property: " + function;
778                                return codegen.intermediateValueForProperty(property, false, null, StackValue.LOCAL_0);
779                            }
780                        },
781                        null
782                );
783            }
784        }
785    
786        @NotNull
787        private static ConstructorDescriptor getPrimaryConstructorOfDataClass(@NotNull ClassDescriptor classDescriptor) {
788            ConstructorDescriptor constructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
789            assert constructor != null : "Data class must have primary constructor: " + classDescriptor;
790            return constructor;
791        }
792    
793        private void generateEnumMethods() {
794            if (isEnumClass(descriptor)) {
795                generateEnumValuesMethod();
796                generateEnumValueOfMethod();
797            }
798        }
799    
800        private void generateEnumValuesMethod() {
801            Type type = typeMapper.mapType(DescriptorUtilsKt.getBuiltIns(descriptor).getArrayType(INVARIANT, descriptor.getDefaultType()));
802    
803            VariableDescriptor valuesProperty =
804                    CollectionsKt.single(descriptor.getStaticScope().getContributedVariables(ENUM_VALUES, NoLookupLocation.FROM_BACKEND), new Function1<VariableDescriptor, Boolean>() {
805                        @Override
806                        public Boolean invoke(VariableDescriptor descriptor) {
807                            return CodegenUtil.isEnumValuesProperty(descriptor);
808                        }
809                    });
810            MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(myClass, valuesProperty), ACC_PUBLIC | ACC_STATIC, ENUM_VALUES.asString(),
811                                           "()" + type.getDescriptor(), null, null);
812            if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
813    
814            mv.visitCode();
815            mv.visitFieldInsn(GETSTATIC, classAsmType.getInternalName(), ENUM_VALUES_FIELD_NAME, type.getDescriptor());
816            mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;", false);
817            mv.visitTypeInsn(CHECKCAST, type.getInternalName());
818            mv.visitInsn(ARETURN);
819            FunctionCodegen.endVisit(mv, "values()", myClass);
820        }
821    
822        private void generateEnumValueOfMethod() {
823            FunctionDescriptor valueOfFunction =
824                    CollectionsKt.single(descriptor.getStaticScope().getContributedFunctions(ENUM_VALUE_OF, NoLookupLocation.FROM_BACKEND), new Function1<FunctionDescriptor, Boolean>() {
825                        @Override
826                        public Boolean invoke(FunctionDescriptor descriptor) {
827                            return CodegenUtil.isEnumValueOfMethod(descriptor);
828                        }
829                    });
830            MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(myClass, valueOfFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUE_OF.asString(),
831                                           "(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, null);
832            if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
833    
834            mv.visitCode();
835            mv.visitLdcInsn(classAsmType);
836            mv.visitVarInsn(ALOAD, 0);
837            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;", false);
838            mv.visitTypeInsn(CHECKCAST, classAsmType.getInternalName());
839            mv.visitInsn(ARETURN);
840            FunctionCodegen.endVisit(mv, "valueOf()", myClass);
841        }
842    
843        private void generateFieldForSingleton() {
844            if (isEnumEntry(descriptor) || isCompanionObject(descriptor)) return;
845    
846            if (isNonCompanionObject(descriptor)) {
847                StackValue.Field field = StackValue.singletonViaInstance(descriptor, typeMapper);
848                v.newField(JvmDeclarationOriginKt.OtherOrigin(myClass),
849                           ACC_PUBLIC | ACC_STATIC | ACC_FINAL,
850                           field.name, field.type.getDescriptor(), null, null);
851    
852                if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
853                // Invoke the object constructor but ignore the result because INSTANCE will be initialized in the first line of <init>
854                InstructionAdapter v = createOrGetClInitCodegen().v;
855                markLineNumberForElement(element, v);
856                v.anew(classAsmType);
857                v.invokespecial(classAsmType.getInternalName(), "<init>", "()V", false);
858    
859                return;
860            }
861    
862            ClassDescriptor companionObjectDescriptor = descriptor.getCompanionObjectDescriptor();
863            if (companionObjectDescriptor == null) {
864                return;
865            }
866    
867            KtObjectDeclaration companionObject = CollectionsKt.firstOrNull(((KtClass) myClass).getCompanionObjects());
868            assert companionObject != null : "Companion object not found: " + myClass.getText();
869    
870            StackValue.Field field = StackValue.singleton(companionObjectDescriptor, typeMapper);
871            v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject), ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
872        }
873    
874        private void generateCompanionObjectBackingFieldCopies() {
875            if (companionObjectPropertiesToCopy == null) return;
876    
877            for (PropertyAndDefaultValue info : companionObjectPropertiesToCopy) {
878                PropertyDescriptor property = info.descriptor;
879    
880                Type type = typeMapper.mapType(property);
881                int modifiers = ACC_STATIC | ACC_FINAL | ACC_PUBLIC;
882                FieldVisitor fv = v.newField(JvmDeclarationOriginKt.Synthetic(DescriptorToSourceUtils.descriptorToDeclaration(property), property),
883                                             modifiers, context.getFieldName(property, false),
884                                             type.getDescriptor(), typeMapper.mapFieldSignature(property.getType(), property),
885                                             info.defaultValue);
886    
887                AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property, type);
888    
889                //This field are always static and final so if it has constant initializer don't do anything in clinit,
890                //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4
891                // TODO: test this code
892                if (state.getClassBuilderMode() == ClassBuilderMode.FULL && info.defaultValue == null) {
893                    ExpressionCodegen codegen = createOrGetClInitCodegen();
894                    int companionObjectIndex = putCompanionObjectInLocalVar(codegen);
895                    StackValue.local(companionObjectIndex, OBJECT_TYPE).put(OBJECT_TYPE, codegen.v);
896                    copyFieldFromCompanionObject(property);
897                }
898            }
899        }
900    
901        private int putCompanionObjectInLocalVar(ExpressionCodegen codegen) {
902            FrameMap frameMap = codegen.myFrameMap;
903            ClassDescriptor companionObjectDescriptor = descriptor.getCompanionObjectDescriptor();
904            int companionObjectIndex = frameMap.getIndex(companionObjectDescriptor);
905            if (companionObjectIndex == -1) {
906                companionObjectIndex = frameMap.enter(companionObjectDescriptor, OBJECT_TYPE);
907                StackValue companionObject = StackValue.singleton(companionObjectDescriptor, typeMapper);
908                StackValue.local(companionObjectIndex, companionObject.type).store(companionObject, codegen.v);
909            }
910            return companionObjectIndex;
911        }
912    
913        private void copyFieldFromCompanionObject(PropertyDescriptor propertyDescriptor) {
914            ExpressionCodegen codegen = createOrGetClInitCodegen();
915            StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null, StackValue.none());
916            StackValue.Field field = StackValue
917                    .field(property.type, classAsmType, propertyDescriptor.getName().asString(), true, StackValue.none(), propertyDescriptor);
918            field.store(property, codegen.v);
919        }
920    
921        private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) {
922            ExpressionCodegen codegen = createOrGetClInitCodegen();
923    
924            FunctionDescriptor constructor = (FunctionDescriptor) context.accessibleDescriptor(
925                    CollectionsKt.single(companionObject.getConstructors()), /* superCallExpression = */ null
926            );
927            generateMethodCallTo(constructor, null, codegen.v);
928            StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject));
929            StackValue.singleton(companionObject, typeMapper).store(instance, codegen.v, true);
930        }
931    
932        private void generatePrimaryConstructor(final DelegationFieldsInfo delegationFieldsInfo) {
933            if (isInterface(descriptor) || isAnnotationClass(descriptor)) return;
934    
935            ConstructorDescriptor constructorDescriptor = descriptor.getUnsubstitutedPrimaryConstructor();
936            if (constructorDescriptor == null) return;
937    
938            ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
939    
940            final KtPrimaryConstructor primaryConstructor = myClass.getPrimaryConstructor();
941            JvmDeclarationOrigin origin = JvmDeclarationOriginKt
942                    .OtherOrigin(primaryConstructor != null ? primaryConstructor : myClass, constructorDescriptor);
943            functionCodegen.generateMethod(origin, constructorDescriptor, constructorContext,
944                       new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
945                           @Override
946                           public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
947                               generatePrimaryConstructorImpl(callableDescriptor, codegen, delegationFieldsInfo, primaryConstructor);
948                           }
949                       }
950            );
951    
952            functionCodegen.generateDefaultIfNeeded(constructorContext, constructorDescriptor, OwnerKind.IMPLEMENTATION,
953                                                    DefaultParameterValueLoader.DEFAULT, null);
954    
955            new DefaultParameterValueSubstitutor(state).generatePrimaryConstructorOverloadsIfNeeded(constructorDescriptor, v, kind, myClass);
956        }
957    
958        private void generateSecondaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
959            if (!canHaveDeclaredConstructors(descriptor)) return;
960    
961            ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
962    
963            KtSecondaryConstructor constructor = (KtSecondaryConstructor) descriptorToDeclaration(constructorDescriptor);
964    
965            functionCodegen.generateMethod(
966                    JvmDeclarationOriginKt.OtherOrigin(constructor, constructorDescriptor),
967                    constructorDescriptor, constructorContext,
968                    new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
969                                               @Override
970                                               public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
971                                                   generateSecondaryConstructorImpl(callableDescriptor, codegen);
972                                               }
973                                           }
974            );
975    
976            functionCodegen.generateDefaultIfNeeded(constructorContext, constructorDescriptor, OwnerKind.IMPLEMENTATION,
977                                                    DefaultParameterValueLoader.DEFAULT, null);
978    
979            new DefaultParameterValueSubstitutor(state).generateOverloadsIfNeeded(
980                    constructor, constructorDescriptor, constructorDescriptor, kind, v
981            );
982        }
983    
984        private void generatePrimaryConstructorImpl(
985                @NotNull ConstructorDescriptor constructorDescriptor,
986                @NotNull ExpressionCodegen codegen,
987                @NotNull DelegationFieldsInfo fieldsInfo,
988                @Nullable KtPrimaryConstructor primaryConstructor
989        ) {
990            InstructionAdapter iv = codegen.v;
991    
992            markLineNumberForConstructor(constructorDescriptor, primaryConstructor, codegen);
993    
994            generateClosureInitialization(iv);
995    
996            generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor,
997                                               getDelegationConstructorCall(bindingContext, constructorDescriptor));
998    
999            if (isNonCompanionObject(descriptor)) {
1000                StackValue.singletonViaInstance(descriptor, typeMapper).store(StackValue.LOCAL_0, iv);
1001            }
1002    
1003            for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
1004                if (specifier instanceof KtDelegatedSuperTypeEntry) {
1005                    genCallToDelegatorByExpressionSpecifier(iv, codegen, (KtDelegatedSuperTypeEntry) specifier, fieldsInfo);
1006                }
1007            }
1008    
1009            int curParam = 0;
1010            List<ValueParameterDescriptor> parameters = constructorDescriptor.getValueParameters();
1011            for (KtParameter parameter : getPrimaryConstructorParameters()) {
1012                if (parameter.hasValOrVar()) {
1013                    VariableDescriptor descriptor = parameters.get(curParam);
1014                    Type type = typeMapper.mapType(descriptor);
1015                    iv.load(0, classAsmType);
1016                    iv.load(codegen.myFrameMap.getIndex(descriptor), type);
1017                    PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
1018                    assert propertyDescriptor != null : "Property descriptor is not found for primary constructor parameter: " + parameter;
1019                    iv.putfield(classAsmType.getInternalName(), context.getFieldName(propertyDescriptor, false), type.getDescriptor());
1020                }
1021                curParam++;
1022            }
1023    
1024            if (isCompanionObject(descriptor)) {
1025                ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen();
1026                parentCodegen.generateCompanionObjectInitializer(descriptor);
1027            }
1028    
1029            if (JvmAbi.isCompanionObjectWithBackingFieldsInOuter(descriptor)) {
1030                final ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen();
1031                generateInitializers(new Function0<ExpressionCodegen>() {
1032                    @Override
1033                    public ExpressionCodegen invoke() {
1034                        return parentCodegen.createOrGetClInitCodegen();
1035                    }
1036                });
1037            }
1038            else {
1039                generateInitializers(codegen);
1040            }
1041    
1042            iv.visitInsn(RETURN);
1043        }
1044    
1045        private void generateSecondaryConstructorImpl(
1046                @NotNull ConstructorDescriptor constructorDescriptor,
1047                @NotNull ExpressionCodegen codegen
1048        ) {
1049            InstructionAdapter iv = codegen.v;
1050    
1051            KtSecondaryConstructor constructor =
1052                    (KtSecondaryConstructor) DescriptorToSourceUtils.descriptorToDeclaration(constructorDescriptor);
1053    
1054            markLineNumberForConstructor(constructorDescriptor, constructor, codegen);
1055    
1056            ResolvedCall<ConstructorDescriptor> constructorDelegationCall =
1057                    getDelegationConstructorCall(bindingContext, constructorDescriptor);
1058            ConstructorDescriptor delegateConstructor = constructorDelegationCall == null ? null :
1059                                                         constructorDelegationCall.getResultingDescriptor();
1060    
1061            generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, constructorDelegationCall);
1062            if (!isSameClassConstructor(delegateConstructor)) {
1063                // Initialization happens only for constructors delegating to super
1064                generateClosureInitialization(iv);
1065                generateInitializers(codegen);
1066            }
1067    
1068            assert constructor != null;
1069            if (constructor.hasBody()) {
1070                codegen.gen(constructor.getBodyExpression(), Type.VOID_TYPE);
1071            }
1072    
1073            iv.visitInsn(RETURN);
1074        }
1075    
1076        private static void markLineNumberForConstructor(
1077                @NotNull ConstructorDescriptor descriptor,
1078                @Nullable KtConstructor constructor,
1079                @NotNull ExpressionCodegen codegen
1080        ) {
1081            if (constructor == null) {
1082                markLineNumberForDescriptor(descriptor.getContainingDeclaration(), codegen.v);
1083            }
1084            else if (constructor.hasBody() && !(constructor instanceof KtSecondaryConstructor && !((KtSecondaryConstructor) constructor).hasImplicitDelegationCall())) {
1085                KtBlockExpression bodyExpression = constructor.getBodyExpression();
1086                List<KtExpression> statements = bodyExpression != null ? bodyExpression.getStatements() : Collections.<KtExpression>emptyList();
1087                if (!statements.isEmpty()) {
1088                    codegen.markStartLineNumber(statements.iterator().next());
1089                }
1090                else {
1091                    codegen.markStartLineNumber(bodyExpression != null ? bodyExpression : constructor);
1092                }
1093            }
1094            else {
1095                codegen.markStartLineNumber(constructor);
1096            }
1097        }
1098    
1099        private void generateInitializers(@NotNull final ExpressionCodegen codegen) {
1100            generateInitializers(new Function0<ExpressionCodegen>() {
1101                @Override
1102                public ExpressionCodegen invoke() {
1103                    return codegen;
1104                }
1105            });
1106        }
1107    
1108        private void generateClosureInitialization(@NotNull InstructionAdapter iv) {
1109            MutableClosure closure = context.closure;
1110            if (closure != null) {
1111                List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType);
1112                int k = 1;
1113                for (FieldInfo info : argsFromClosure) {
1114                    k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv);
1115                }
1116            }
1117        }
1118    
1119        private void genSimpleSuperCall(InstructionAdapter iv) {
1120            iv.load(0, superClassAsmType);
1121            if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) {
1122                iv.load(1, JAVA_STRING_TYPE);
1123                iv.load(2, Type.INT_TYPE);
1124                iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(Ljava/lang/String;I)V", false);
1125            }
1126            else {
1127                iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V", false);
1128            }
1129        }
1130    
1131        private class DelegationFieldsInfo {
1132            private class Field {
1133                public final Type type;
1134                public final String name;
1135                public final boolean generateField;
1136    
1137                private Field(Type type, String name, boolean generateField) {
1138                    this.type = type;
1139                    this.name = name;
1140                    this.generateField = generateField;
1141                }
1142    
1143                @NotNull
1144                public StackValue getStackValue() {
1145                    return StackValue.field(type, classAsmType, name, false, StackValue.none());
1146                }
1147            }
1148            private final Map<KtDelegatedSuperTypeEntry, Field> fields = new HashMap<KtDelegatedSuperTypeEntry, Field>();
1149    
1150            @NotNull
1151            public Field getInfo(KtDelegatedSuperTypeEntry specifier) {
1152                return fields.get(specifier);
1153            }
1154    
1155            private void addField(KtDelegatedSuperTypeEntry specifier, PropertyDescriptor propertyDescriptor) {
1156                fields.put(specifier,
1157                           new Field(typeMapper.mapType(propertyDescriptor), propertyDescriptor.getName().asString(), false));
1158            }
1159    
1160            private void addField(KtDelegatedSuperTypeEntry specifier, Type type, String name) {
1161                fields.put(specifier, new Field(type, name, true));
1162            }
1163        }
1164    
1165        @NotNull
1166        private DelegationFieldsInfo getDelegationFieldsInfo(@NotNull List<KtSuperTypeListEntry> delegationSpecifiers) {
1167            DelegationFieldsInfo result = new DelegationFieldsInfo();
1168            int n = 0;
1169            for (KtSuperTypeListEntry specifier : delegationSpecifiers) {
1170                if (specifier instanceof KtDelegatedSuperTypeEntry) {
1171                    KtExpression expression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
1172                    PropertyDescriptor propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(expression, descriptor, bindingContext);
1173    
1174    
1175                    if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, bindingContext)) {
1176                        result.addField((KtDelegatedSuperTypeEntry) specifier, propertyDescriptor);
1177                    }
1178                    else {
1179                        KotlinType expressionType = expression != null ? bindingContext.getType(expression) : null;
1180                        Type asmType =
1181                                expressionType != null ? typeMapper.mapType(expressionType) : typeMapper.mapType(getSuperClass(specifier));
1182                        result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, "$delegate_" + n);
1183                    }
1184                    n++;
1185                }
1186            }
1187            return result;
1188        }
1189    
1190        @NotNull
1191        private ClassDescriptor getSuperClass(@NotNull KtSuperTypeListEntry specifier) {
1192            return CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext);
1193        }
1194    
1195        private void genCallToDelegatorByExpressionSpecifier(
1196                InstructionAdapter iv,
1197                ExpressionCodegen codegen,
1198                KtDelegatedSuperTypeEntry specifier,
1199                DelegationFieldsInfo fieldsInfo
1200        ) {
1201            KtExpression expression = specifier.getDelegateExpression();
1202    
1203            DelegationFieldsInfo.Field fieldInfo = fieldsInfo.getInfo(specifier);
1204            if (fieldInfo.generateField) {
1205                iv.load(0, classAsmType);
1206                fieldInfo.getStackValue().store(codegen.gen(expression), iv);
1207            }
1208        }
1209    
1210        private void lookupConstructorExpressionsInClosureIfPresent() {
1211            if (state.getClassBuilderMode() != ClassBuilderMode.FULL || descriptor.getConstructors().isEmpty()) return;
1212    
1213            KtVisitorVoid visitor = new KtVisitorVoid() {
1214                @Override
1215                public void visitKtElement(@NotNull KtElement e) {
1216                    e.acceptChildren(this);
1217                }
1218    
1219                @Override
1220                public void visitSimpleNameExpression(@NotNull KtSimpleNameExpression expr) {
1221                    DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr);
1222    
1223                    if (isLocalFunction(descriptor)) {
1224                        lookupInContext(descriptor);
1225                    }
1226                    else if (descriptor instanceof CallableMemberDescriptor) {
1227                        ResolvedCall<? extends CallableDescriptor> call = CallUtilKt.getResolvedCall(expr, bindingContext);
1228                        if (call != null) {
1229                            lookupReceiver(call.getDispatchReceiver());
1230                            lookupReceiver((ReceiverValue) call.getExtensionReceiver());
1231                        }
1232                    }
1233                    else if (descriptor instanceof VariableDescriptor) {
1234                        if (descriptor.getContainingDeclaration() instanceof ConstructorDescriptor) {
1235                            ClassDescriptor classDescriptor =
1236                                    (ClassDescriptor) descriptor.getContainingDeclaration().getContainingDeclaration();
1237                            if (classDescriptor == ImplementationBodyCodegen.this.descriptor) return;
1238                        }
1239                        lookupInContext(descriptor);
1240                    }
1241                }
1242    
1243                private void lookupReceiver(@Nullable ReceiverValue value) {
1244                    if (value instanceof ImplicitReceiver) {
1245                        if (value instanceof ExtensionReceiver) {
1246                            ReceiverParameterDescriptor parameter =
1247                                    ((ExtensionReceiver) value).getDeclarationDescriptor().getExtensionReceiverParameter();
1248                            assert parameter != null : "Extension receiver should exist: " + ((ExtensionReceiver) value).getDeclarationDescriptor();
1249                            lookupInContext(parameter);
1250                        }
1251                        else {
1252                            lookupInContext(((ImplicitReceiver) value).getDeclarationDescriptor());
1253                        }
1254                    }
1255                }
1256    
1257    
1258                private void lookupInContext(@NotNull DeclarationDescriptor toLookup) {
1259                    context.lookupInContext(toLookup, StackValue.LOCAL_0, state, true);
1260                }
1261    
1262                @Override
1263                public void visitThisExpression(@NotNull KtThisExpression expression) {
1264                    DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
1265                    assert descriptor instanceof CallableDescriptor ||
1266                           descriptor instanceof ClassDescriptor : "'This' reference target should be class or callable descriptor but was " + descriptor;
1267                    if (descriptor instanceof ClassDescriptor) {
1268                        lookupInContext(descriptor);
1269                    }
1270    
1271                    if (descriptor instanceof CallableDescriptor) {
1272                        ReceiverParameterDescriptor parameter = ((CallableDescriptor) descriptor).getExtensionReceiverParameter();
1273                        if (parameter != null) {
1274                            lookupInContext(parameter);
1275                        }
1276                    }
1277                }
1278            };
1279    
1280            for (KtDeclaration declaration : myClass.getDeclarations()) {
1281                if (declaration instanceof KtProperty) {
1282                    KtProperty property = (KtProperty) declaration;
1283                    KtExpression initializer = property.getDelegateExpressionOrInitializer();
1284                    if (initializer != null) {
1285                        initializer.accept(visitor);
1286                    }
1287                }
1288                else if (declaration instanceof KtAnonymousInitializer) {
1289                    KtAnonymousInitializer initializer = (KtAnonymousInitializer) declaration;
1290                    initializer.accept(visitor);
1291                }
1292                else if (declaration instanceof KtSecondaryConstructor) {
1293                    KtSecondaryConstructor constructor = (KtSecondaryConstructor) declaration;
1294                    constructor.accept(visitor);
1295                }
1296            }
1297    
1298            for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
1299                if (specifier instanceof KtDelegatedSuperTypeEntry) {
1300                    KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
1301                    assert delegateExpression != null;
1302                    delegateExpression.accept(visitor);
1303                }
1304            }
1305    
1306            ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassNotAny(descriptor);
1307            if (superClass != null) {
1308                if (superClass.isInner()) {
1309                    context.lookupInContext(superClass.getContainingDeclaration(), StackValue.LOCAL_0, state, true);
1310                }
1311    
1312                ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor();
1313                if (primaryConstructor != null && !isAnonymousObject(descriptor)) {
1314                    ResolvedCall<ConstructorDescriptor> delegationCall = getDelegationConstructorCall(bindingContext, primaryConstructor);
1315                    KtValueArgumentList argumentList = delegationCall != null ? delegationCall.getCall().getValueArgumentList() : null;
1316                    if (argumentList != null) {
1317                        argumentList.accept(visitor);
1318                    }
1319                }
1320            }
1321        }
1322    
1323        private void generateTraitMethods() {
1324            if (isInterface(descriptor)) return;
1325    
1326            for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
1327                FunctionDescriptor traitFun = entry.getKey();
1328                //skip java 8 default methods
1329                if (!(traitFun instanceof JavaCallableMemberDescriptor)) {
1330                    generateDelegationToTraitImpl(traitFun, entry.getValue());
1331                }
1332            }
1333        }
1334    
1335        private void generateDelegationToTraitImpl(@NotNull final FunctionDescriptor traitFun, @NotNull final FunctionDescriptor inheritedFun) {
1336            functionCodegen.generateMethod(
1337                    JvmDeclarationOriginKt.DelegationToTraitImpl(descriptorToDeclaration(traitFun), traitFun),
1338                    inheritedFun,
1339                    new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, inheritedFun) {
1340                        @Override
1341                        public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
1342                            DeclarationDescriptor containingDeclaration = traitFun.getContainingDeclaration();
1343                            if (!DescriptorUtils.isInterface(containingDeclaration)) return;
1344    
1345                            DeclarationDescriptor declarationInheritedFun = inheritedFun.getContainingDeclaration();
1346                            PsiElement classForInheritedFun = descriptorToDeclaration(declarationInheritedFun);
1347                            if (classForInheritedFun instanceof KtDeclaration) {
1348                                codegen.markLineNumber((KtElement) classForInheritedFun, false);
1349                            }
1350    
1351                            ClassDescriptor containingTrait = (ClassDescriptor) containingDeclaration;
1352                            Type traitImplType = typeMapper.mapDefaultImpls(containingTrait);
1353    
1354                            Method traitMethod = typeMapper.mapSignature(traitFun.getOriginal(), OwnerKind.DEFAULT_IMPLS).getAsmMethod();
1355    
1356                            Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
1357                            Type[] originalArgTypes = traitMethod.getArgumentTypes();
1358                            assert originalArgTypes.length == argTypes.length + 1 :
1359                                    "Invalid trait implementation signature: " + signature + " vs " + traitMethod + " for " + traitFun;
1360    
1361                            InstructionAdapter iv = codegen.v;
1362                            iv.load(0, OBJECT_TYPE);
1363                            for (int i = 0, reg = 1; i < argTypes.length; i++) {
1364                                StackValue.local(reg, argTypes[i]).put(originalArgTypes[i + 1], iv);
1365                                //noinspection AssignmentToForLoopParameter
1366                                reg += argTypes[i].getSize();
1367                            }
1368    
1369                            if (KotlinBuiltIns.isCloneable(containingTrait) && traitMethod.getName().equals("clone")) {
1370                                // A special hack for Cloneable: there's no kotlin/Cloneable$DefaultImpls class at runtime,
1371                                // and its 'clone' method is actually located in java/lang/Object
1372                                iv.invokespecial("java/lang/Object", "clone", "()Ljava/lang/Object;", false);
1373                            }
1374                            else {
1375                                iv.invokestatic(traitImplType.getInternalName(), traitMethod.getName(), traitMethod.getDescriptor(), false);
1376                            }
1377    
1378                            Type returnType = signature.getReturnType();
1379                            StackValue.onStack(traitMethod.getReturnType()).put(returnType, iv);
1380                            iv.areturn(returnType);
1381                        }
1382                    }
1383            );
1384        }
1385    
1386        private void generateDelegatorToConstructorCall(
1387                @NotNull InstructionAdapter iv,
1388                @NotNull ExpressionCodegen codegen,
1389                @NotNull ConstructorDescriptor constructorDescriptor,
1390                @Nullable ResolvedCall<ConstructorDescriptor> delegationConstructorCall
1391        ) {
1392            if (delegationConstructorCall == null) {
1393                genSimpleSuperCall(iv);
1394                return;
1395            }
1396            iv.load(0, OBJECT_TYPE);
1397            ConstructorDescriptor delegateConstructor = SamCodegenUtil.resolveSamAdapter(codegen.getConstructorDescriptor(delegationConstructorCall));
1398    
1399            CallableMethod delegateConstructorCallable = typeMapper.mapToCallableMethod(delegateConstructor, false);
1400            CallableMethod callable = typeMapper.mapToCallableMethod(constructorDescriptor, false);
1401    
1402            List<JvmMethodParameterSignature> delegatingParameters = delegateConstructorCallable.getValueParameters();
1403            List<JvmMethodParameterSignature> parameters = callable.getValueParameters();
1404    
1405            ArgumentGenerator argumentGenerator;
1406            if (isSameClassConstructor(delegateConstructor)) {
1407                // if it's the same class constructor we should just pass all synthetic parameters
1408                argumentGenerator =
1409                        generateThisCallImplicitArguments(iv, codegen, delegateConstructor, delegateConstructorCallable, delegatingParameters,
1410                                                          parameters);
1411            }
1412            else {
1413                argumentGenerator =
1414                        generateSuperCallImplicitArguments(iv, codegen, constructorDescriptor, delegateConstructor, delegateConstructorCallable,
1415                                                           delegatingParameters,
1416                                                           parameters);
1417            }
1418    
1419            codegen.invokeMethodWithArguments(
1420                    delegateConstructorCallable, delegationConstructorCall, StackValue.none(), codegen.defaultCallGenerator, argumentGenerator);
1421        }
1422    
1423        private boolean isSameClassConstructor(@Nullable ConstructorDescriptor delegatingConstructor) {
1424            return delegatingConstructor != null && delegatingConstructor.getContainingDeclaration() == descriptor;
1425        }
1426    
1427        @NotNull
1428        private ArgumentGenerator generateSuperCallImplicitArguments(
1429                @NotNull InstructionAdapter iv,
1430                @NotNull ExpressionCodegen codegen,
1431                @NotNull ConstructorDescriptor constructorDescriptor,
1432                @NotNull ConstructorDescriptor superConstructor,
1433                @NotNull CallableMethod superCallable,
1434                @NotNull List<JvmMethodParameterSignature> superParameters,
1435                @NotNull List<JvmMethodParameterSignature> parameters
1436        ) {
1437            int offset = 1;
1438            int superIndex = 0;
1439    
1440            // Here we match all the super constructor parameters except those with kind VALUE to the derived constructor parameters, push
1441            // them all onto the stack and update "offset" variable so that in the end it points to the slot of the first VALUE argument
1442            for (JvmMethodParameterSignature parameter : parameters) {
1443                if (superIndex >= superParameters.size()) break;
1444    
1445                JvmMethodParameterKind superKind = superParameters.get(superIndex).getKind();
1446                JvmMethodParameterKind kind = parameter.getKind();
1447                Type type = parameter.getAsmType();
1448    
1449                if (superKind == JvmMethodParameterKind.VALUE && kind == JvmMethodParameterKind.SUPER_CALL_PARAM) {
1450                    // Stop when we reach the actual value parameters present in the code; they will be generated via ResolvedCall below
1451                    break;
1452                }
1453    
1454                if (superKind == JvmMethodParameterKind.OUTER) {
1455                    assert kind == JvmMethodParameterKind.OUTER || kind == JvmMethodParameterKind.SUPER_CALL_PARAM :
1456                            String.format("Non-outer parameter incorrectly mapped to outer for %s: %s vs %s",
1457                                          constructorDescriptor, parameters, superParameters);
1458                    // Super constructor requires OUTER parameter, but our OUTER instance may be different from what is expected by the super
1459                    // constructor. We need to traverse our outer classes from the bottom up, to find the needed class. See innerExtendsOuter.kt
1460                    ClassDescriptor outerForSuper = (ClassDescriptor) superConstructor.getContainingDeclaration().getContainingDeclaration();
1461                    StackValue outer = codegen.generateThisOrOuter(outerForSuper, true, true);
1462                    outer.put(outer.type, codegen.v);
1463                    superIndex++;
1464                }
1465                else if (kind == JvmMethodParameterKind.SUPER_CALL_PARAM || kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL) {
1466                    iv.load(offset, type);
1467                    superIndex++;
1468                }
1469    
1470                offset += type.getSize();
1471            }
1472    
1473            if (isAnonymousObject(descriptor)) {
1474                List<JvmMethodParameterSignature> superValues = superParameters.subList(superIndex, superParameters.size());
1475                return new ObjectSuperCallArgumentGenerator(superValues, iv, offset);
1476            }
1477            else {
1478                return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, superConstructor.getValueParameters(),
1479                                                       superCallable.getValueParameterTypes());
1480            }
1481        }
1482    
1483        @NotNull
1484        private static ArgumentGenerator generateThisCallImplicitArguments(
1485                @NotNull InstructionAdapter iv,
1486                @NotNull ExpressionCodegen codegen,
1487                @NotNull ConstructorDescriptor delegatingConstructor,
1488                @NotNull CallableMethod delegatingCallable,
1489                @NotNull List<JvmMethodParameterSignature> delegatingParameters,
1490                @NotNull List<JvmMethodParameterSignature> parameters
1491        ) {
1492            int offset = 1;
1493            int index = 0;
1494            for (; index < delegatingParameters.size(); index++) {
1495                JvmMethodParameterKind delegatingKind = delegatingParameters.get(index).getKind();
1496                if (delegatingKind == JvmMethodParameterKind.VALUE) {
1497                    assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE:
1498                            "Delegating constructor has not enough implicit parameters";
1499                    break;
1500                }
1501                assert index < parameters.size() && parameters.get(index).getKind() == delegatingKind :
1502                        "Constructors of the same class should have the same set of implicit arguments";
1503                JvmMethodParameterSignature parameter = parameters.get(index);
1504    
1505                iv.load(offset, parameter.getAsmType());
1506                offset += parameter.getAsmType().getSize();
1507            }
1508    
1509            assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE :
1510                        "Delegating constructor has not enough parameters";
1511    
1512            return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, delegatingConstructor.getValueParameters(),
1513                                                  delegatingCallable.getValueParameterTypes());
1514        }
1515    
1516        private static class ObjectSuperCallArgumentGenerator extends ArgumentGenerator {
1517            private final List<JvmMethodParameterSignature> parameters;
1518            private final InstructionAdapter iv;
1519            private int offset;
1520    
1521            public ObjectSuperCallArgumentGenerator(
1522                    @NotNull List<JvmMethodParameterSignature> superParameters,
1523                    @NotNull InstructionAdapter iv,
1524                    int firstValueParamOffset
1525            ) {
1526                this.parameters = superParameters;
1527                this.iv = iv;
1528                this.offset = firstValueParamOffset;
1529            }
1530    
1531            @Override
1532            public void generateExpression(int i, @NotNull ExpressionValueArgument argument) {
1533                generateSuperCallArgument(i);
1534            }
1535    
1536            @Override
1537            public void generateDefault(int i, @NotNull DefaultValueArgument argument) {
1538                Type type = parameters.get(i).getAsmType();
1539                pushDefaultValueOnStack(type, iv);
1540            }
1541    
1542            @Override
1543            public void generateVararg(int i, @NotNull VarargValueArgument argument) {
1544                generateSuperCallArgument(i);
1545            }
1546    
1547            private void generateSuperCallArgument(int i) {
1548                Type type = parameters.get(i).getAsmType();
1549                iv.load(offset, type);
1550                offset += type.getSize();
1551            }
1552    
1553            @Override
1554            protected void reorderArgumentsIfNeeded(@NotNull List<ArgumentAndDeclIndex> args) {
1555    
1556            }
1557        }
1558    
1559        private void generateEnumEntries() {
1560            if (descriptor.getKind() != ClassKind.ENUM_CLASS) return;
1561    
1562            List<KtEnumEntry> enumEntries = CollectionsKt.filterIsInstance(element.getDeclarations(), KtEnumEntry.class);
1563    
1564            for (KtEnumEntry enumEntry : enumEntries) {
1565                ClassDescriptor descriptor = getNotNull(bindingContext, BindingContext.CLASS, enumEntry);
1566                int isDeprecated = KotlinBuiltIns.isDeprecated(descriptor) ? ACC_DEPRECATED : 0;
1567                FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(enumEntry, descriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL | isDeprecated,
1568                                             descriptor.getName().asString(), classAsmType.getDescriptor(), null, null);
1569                AnnotationCodegen.forField(fv, typeMapper).genAnnotations(descriptor, null);
1570            }
1571    
1572            initializeEnumConstants(enumEntries);
1573        }
1574    
1575        private void initializeEnumConstants(@NotNull List<KtEnumEntry> enumEntries) {
1576            if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
1577    
1578            ExpressionCodegen codegen = createOrGetClInitCodegen();
1579            InstructionAdapter iv = codegen.v;
1580    
1581            Type arrayAsmType = typeMapper.mapType(DescriptorUtilsKt.getBuiltIns(descriptor).getArrayType(INVARIANT, descriptor.getDefaultType()));
1582            v.newField(JvmDeclarationOriginKt.OtherOrigin(myClass), ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, ENUM_VALUES_FIELD_NAME,
1583                       arrayAsmType.getDescriptor(), null, null);
1584    
1585            iv.iconst(enumEntries.size());
1586            iv.newarray(classAsmType);
1587    
1588            if (!enumEntries.isEmpty()) {
1589                iv.dup();
1590                for (int ordinal = 0, size = enumEntries.size(); ordinal < size; ordinal++) {
1591                    initializeEnumConstant(enumEntries, ordinal);
1592                }
1593            }
1594    
1595            iv.putstatic(classAsmType.getInternalName(), ENUM_VALUES_FIELD_NAME, arrayAsmType.getDescriptor());
1596        }
1597    
1598        private void initializeEnumConstant(@NotNull List<KtEnumEntry> enumEntries, int ordinal) {
1599            ExpressionCodegen codegen = createOrGetClInitCodegen();
1600            InstructionAdapter iv = codegen.v;
1601            KtEnumEntry enumEntry = enumEntries.get(ordinal);
1602    
1603            iv.dup();
1604            iv.iconst(ordinal);
1605    
1606            ClassDescriptor classDescriptor = getNotNull(bindingContext, BindingContext.CLASS, enumEntry);
1607            Type implClass = typeMapper.mapClass(classDescriptor);
1608    
1609            iv.anew(implClass);
1610            iv.dup();
1611    
1612            iv.aconst(enumEntry.getName());
1613            iv.iconst(ordinal);
1614    
1615            List<KtSuperTypeListEntry> delegationSpecifiers = enumEntry.getSuperTypeListEntries();
1616            if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(bindingContext, enumEntry)) {
1617                ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(delegationSpecifiers.get(0), bindingContext);
1618    
1619                CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) resolvedCall.getResultingDescriptor(), false);
1620    
1621                codegen.invokeMethodWithArguments(method, resolvedCall, StackValue.none());
1622            }
1623            else {
1624                iv.invokespecial(implClass.getInternalName(), "<init>", "(Ljava/lang/String;I)V", false);
1625            }
1626    
1627            iv.dup();
1628            iv.putstatic(classAsmType.getInternalName(), enumEntry.getName(), classAsmType.getDescriptor());
1629            iv.astore(OBJECT_TYPE);
1630        }
1631    
1632        private void generateDelegates(DelegationFieldsInfo delegationFieldsInfo) {
1633            for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
1634                if (specifier instanceof KtDelegatedSuperTypeEntry) {
1635                    DelegationFieldsInfo.Field field = delegationFieldsInfo.getInfo((KtDelegatedSuperTypeEntry) specifier);
1636                    generateDelegateField(field);
1637                    KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
1638                    KotlinType delegateExpressionType = delegateExpression != null ? bindingContext.getType(delegateExpression) : null;
1639                    generateDelegates(getSuperClass(specifier), delegateExpressionType, field);
1640                }
1641            }
1642        }
1643    
1644        private void generateDelegateField(DelegationFieldsInfo.Field fieldInfo) {
1645            if (!fieldInfo.generateField) return;
1646    
1647            v.newField(JvmDeclarationOrigin.NO_ORIGIN, ACC_PRIVATE | ACC_FINAL | ACC_SYNTHETIC,
1648                       fieldInfo.name, fieldInfo.type.getDescriptor(), /*TODO*/null, null);
1649        }
1650    
1651        protected void generateDelegates(ClassDescriptor toTrait, KotlinType delegateExpressionType, DelegationFieldsInfo.Field field) {
1652            for (Map.Entry<CallableMemberDescriptor, CallableDescriptor> entry : CodegenUtilKt.getDelegates(descriptor, toTrait, delegateExpressionType).entrySet()) {
1653                CallableMemberDescriptor callableMemberDescriptor = entry.getKey();
1654                CallableDescriptor delegateTo = entry.getValue();
1655                if (callableMemberDescriptor instanceof PropertyDescriptor) {
1656                    propertyCodegen
1657                            .genDelegate((PropertyDescriptor) callableMemberDescriptor, (PropertyDescriptor) delegateTo, field.getStackValue());
1658                }
1659                else if (callableMemberDescriptor instanceof FunctionDescriptor) {
1660                    functionCodegen
1661                            .genDelegate((FunctionDescriptor) callableMemberDescriptor, (FunctionDescriptor) delegateTo, field.getStackValue());
1662                }
1663            }
1664        }
1665    
1666        public void addCompanionObjectPropertyToCopy(@NotNull PropertyDescriptor descriptor, Object defaultValue) {
1667            if (companionObjectPropertiesToCopy == null) {
1668                companionObjectPropertiesToCopy = new ArrayList<PropertyAndDefaultValue>();
1669            }
1670            companionObjectPropertiesToCopy.add(new PropertyAndDefaultValue(descriptor, defaultValue));
1671        }
1672    
1673        @Override
1674        protected void done() {
1675            for (Function2<ImplementationBodyCodegen, ClassBuilder, Unit> task : additionalTasks) {
1676                task.invoke(this, v);
1677            }
1678    
1679            super.done();
1680        }
1681    
1682        private static class PropertyAndDefaultValue {
1683            public final PropertyDescriptor descriptor;
1684            public final Object defaultValue;
1685    
1686            public PropertyAndDefaultValue(@NotNull PropertyDescriptor descriptor, Object defaultValue) {
1687                this.descriptor = descriptor;
1688                this.defaultValue = defaultValue;
1689            }
1690        }
1691    
1692        public void addAdditionalTask(Function2<ImplementationBodyCodegen, ClassBuilder, Unit> additionalTask) {
1693            additionalTasks.add(additionalTask);
1694        }
1695    }