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