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