001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.codegen;
018    
019    import com.intellij.openapi.progress.ProcessCanceledException;
020    import com.intellij.psi.PsiElement;
021    import kotlin.jvm.functions.Function0;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.kotlin.backend.common.CodegenUtil;
025    import org.jetbrains.kotlin.codegen.context.*;
026    import org.jetbrains.kotlin.codegen.inline.*;
027    import org.jetbrains.kotlin.codegen.state.GenerationState;
028    import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
029    import org.jetbrains.kotlin.descriptors.*;
030    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
031    import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
032    import org.jetbrains.kotlin.fileClasses.FileClasses;
033    import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
034    import org.jetbrains.kotlin.load.java.JavaVisibilities;
035    import org.jetbrains.kotlin.load.java.JvmAbi;
036    import org.jetbrains.kotlin.name.Name;
037    import org.jetbrains.kotlin.name.SpecialNames;
038    import org.jetbrains.kotlin.psi.*;
039    import org.jetbrains.kotlin.resolve.*;
040    import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
041    import org.jetbrains.kotlin.resolve.constants.ConstantValue;
042    import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
043    import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
044    import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
045    import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
046    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
047    import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
048    import org.jetbrains.kotlin.storage.LockBasedStorageManager;
049    import org.jetbrains.kotlin.storage.NotNullLazyValue;
050    import org.jetbrains.kotlin.types.ErrorUtils;
051    import org.jetbrains.kotlin.types.KotlinType;
052    import org.jetbrains.org.objectweb.asm.Label;
053    import org.jetbrains.org.objectweb.asm.MethodVisitor;
054    import org.jetbrains.org.objectweb.asm.Type;
055    import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
056    import org.jetbrains.org.objectweb.asm.commons.Method;
057    
058    import java.util.*;
059    
060    import static org.jetbrains.kotlin.codegen.AsmUtil.calculateInnerClassAccessFlags;
061    import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
062    import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
063    import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
064    import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
065    import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
066    import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
067    import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic;
068    import static org.jetbrains.org.objectweb.asm.Opcodes.*;
069    
070    public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclarationContainer*/> {
071        protected final GenerationState state;
072        protected final T element;
073        protected final FieldOwnerContext context;
074        protected final ClassBuilder v;
075        protected final FunctionCodegen functionCodegen;
076        protected final PropertyCodegen propertyCodegen;
077        protected final JetTypeMapper typeMapper;
078        protected final BindingContext bindingContext;
079        protected final JvmFileClassesProvider fileClassesProvider;
080        private final MemberCodegen<?> parentCodegen;
081        private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
082        protected final Collection<ClassDescriptor> innerClasses = new LinkedHashSet<ClassDescriptor>();
083    
084        protected ExpressionCodegen clInit;
085        private NameGenerator inlineNameGenerator;
086    
087        private SourceMapper sourceMapper;
088        private final ConstantExpressionEvaluator constantExpressionEvaluator;
089    
090        public MemberCodegen(
091                @NotNull GenerationState state,
092                @Nullable MemberCodegen<?> parentCodegen,
093                @NotNull FieldOwnerContext context,
094                T element,
095                @NotNull ClassBuilder builder
096        ) {
097            this.state = state;
098            this.typeMapper = state.getTypeMapper();
099            this.bindingContext = state.getBindingContext();
100            this.fileClassesProvider = state.getFileClassesProvider();
101            this.element = element;
102            this.context = context;
103            this.v = builder;
104            this.functionCodegen = new FunctionCodegen(context, v, state, this);
105            this.propertyCodegen = new PropertyCodegen(context, v, functionCodegen, this);
106            this.parentCodegen = parentCodegen;
107            this.constantExpressionEvaluator = new ConstantExpressionEvaluator(state.getModule().getBuiltIns());
108        }
109    
110        protected MemberCodegen(@NotNull MemberCodegen<T> wrapped, T declaration, FieldOwnerContext codegenContext) {
111            this(wrapped.state, wrapped.getParentCodegen(), codegenContext, declaration, wrapped.v);
112        }
113    
114        public void generate() {
115            generateDeclaration();
116    
117            generateBody();
118    
119            generateSyntheticParts();
120    
121            if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
122                generateKotlinMetadataAnnotation();
123            }
124    
125            done();
126        }
127    
128        protected abstract void generateDeclaration();
129    
130        protected abstract void generateBody();
131    
132        protected void generateSyntheticParts() {
133        }
134    
135        protected abstract void generateKotlinMetadataAnnotation();
136    
137        @Nullable
138        protected ClassDescriptor classForInnerClassRecord() {
139            return null;
140        }
141    
142        public static void markLineNumberForDescriptor(@Nullable ClassDescriptor declarationDescriptor, @NotNull InstructionAdapter v) {
143            if (declarationDescriptor == null) {
144                return;
145            }
146    
147            PsiElement classElement = DescriptorToSourceUtils.getSourceFromDescriptor(declarationDescriptor);
148            if (classElement != null) {
149                markLineNumberForElement(classElement, v);
150            }
151        }
152    
153        public static void markLineNumberForElement(@NotNull PsiElement element, @NotNull InstructionAdapter v) {
154            Integer lineNumber = CodegenUtil.getLineNumberForElement(element, false);
155            if (lineNumber != null) {
156                Label label = new Label();
157                v.visitLabel(label);
158                v.visitLineNumber(lineNumber, label);
159            }
160        }
161    
162        protected void done() {
163            if (clInit != null) {
164                clInit.v.visitInsn(RETURN);
165                FunctionCodegen.endVisit(clInit.v, "static initializer", element);
166            }
167    
168            writeInnerClasses();
169    
170            if (sourceMapper != null) {
171                SourceMapper.Companion.flushToClassBuilder(sourceMapper, v);
172            }
173    
174            v.done();
175        }
176    
177        public void genFunctionOrProperty(@NotNull KtDeclaration functionOrProperty) {
178            if (functionOrProperty instanceof KtNamedFunction) {
179                try {
180                    functionCodegen.gen((KtNamedFunction) functionOrProperty);
181                }
182                catch (ProcessCanceledException e) {
183                    throw e;
184                }
185                catch (CompilationException e) {
186                    throw e;
187                }
188                catch (Exception e) {
189                    throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty);
190                }
191            }
192            else if (functionOrProperty instanceof KtProperty) {
193                try {
194                    propertyCodegen.gen((KtProperty) functionOrProperty);
195                }
196                catch (ProcessCanceledException e) {
197                    throw e;
198                }
199                catch (CompilationException e) {
200                    throw e;
201                }
202                catch (Exception e) {
203                    throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty);
204                }
205            }
206            else {
207                throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty);
208            }
209        }
210    
211        public static void genClassOrObject(
212                @NotNull CodegenContext parentContext,
213                @NotNull KtClassOrObject aClass,
214                @NotNull GenerationState state,
215                @Nullable MemberCodegen<?> parentCodegen
216        ) {
217            ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
218    
219            if (descriptor == null || ErrorUtils.isError(descriptor)) {
220                badDescriptor(descriptor, state.getClassBuilderMode());
221                return;
222            }
223    
224            if (descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED)) {
225                badDescriptor(descriptor, state.getClassBuilderMode());
226            }
227    
228            Type classType = state.getTypeMapper().mapClass(descriptor);
229            ClassBuilder classBuilder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(aClass, descriptor), classType, aClass.getContainingFile());
230            ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
231            new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, parentCodegen, false).generate();
232        }
233    
234        private static void badDescriptor(ClassDescriptor descriptor, ClassBuilderMode mode) {
235            if (mode != ClassBuilderMode.LIGHT_CLASSES) {
236                throw new IllegalStateException("Generating bad descriptor in ClassBuilderMode = " + mode + ": " + descriptor);
237            }
238        }
239    
240        public void genClassOrObject(KtClassOrObject aClass) {
241            genClassOrObject(context, aClass, state, this);
242        }
243    
244        private void writeInnerClasses() {
245            // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
246            // for each enclosing class and for each immediate member
247            ClassDescriptor classDescriptor = classForInnerClassRecord();
248            if (classDescriptor != null) {
249                if (parentCodegen != null) {
250                    parentCodegen.innerClasses.add(classDescriptor);
251                }
252    
253                for (MemberCodegen<?> codegen = this; codegen != null; codegen = codegen.getParentCodegen()) {
254                    ClassDescriptor outerClass = codegen.classForInnerClassRecord();
255                    if (outerClass != null) {
256                        innerClasses.add(outerClass);
257                    }
258                }
259            }
260    
261            for (ClassDescriptor innerClass : innerClasses) {
262                writeInnerClass(innerClass);
263            }
264        }
265    
266        private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
267            DeclarationDescriptor containing = innerClass.getContainingDeclaration();
268            String outerClassInternalName = null;
269            if (containing instanceof ClassDescriptor) {
270                outerClassInternalName = typeMapper.mapClass((ClassDescriptor) containing).getInternalName();
271            }
272            String innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
273            String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName();
274            v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass));
275        }
276    
277        protected void writeOuterClassAndEnclosingMethod() {
278            CodegenContext context = this.context.getParentContext();
279    
280            while (context instanceof InlineLambdaContext) {
281                // If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext
282                //noinspection ConstantConditions
283                context = context.getParentContext().getParentContext();
284            }
285            assert context != null : "Outermost context can't be null: " + this.context;
286    
287            Type enclosingAsmType = computeOuterClass(context);
288            if (enclosingAsmType != null) {
289                Method method = computeEnclosingMethod(context);
290    
291                v.visitOuterClass(
292                        enclosingAsmType.getInternalName(),
293                        method == null ? null : method.getName(),
294                        method == null ? null : method.getDescriptor()
295                );
296            }
297        }
298    
299        @Nullable
300        private Type computeOuterClass(@NotNull CodegenContext<?> context) {
301            CodegenContext<? extends ClassOrPackageFragmentDescriptor> outermost = context.getClassOrPackageParentContext();
302            if (outermost instanceof ClassContext) {
303                return typeMapper.mapType(((ClassContext) outermost).getContextDescriptor());
304            }
305            else if (outermost instanceof MultifileClassFacadeContext || outermost instanceof DelegatingToPartContext) {
306                Type implementationOwnerType = CodegenContextUtil.getImplementationOwnerClassType(outermost);
307                if (implementationOwnerType != null) {
308                    return implementationOwnerType;
309                }
310                else {
311                    return FileClasses.getFileClassType(fileClassesProvider, element.getContainingKtFile());
312                }
313            }
314    
315            return null;
316        }
317    
318        @Nullable
319        private Method computeEnclosingMethod(@NotNull CodegenContext context) {
320            if (context instanceof MethodContext) {
321                Method method = typeMapper.mapSignature(((MethodContext) context).getFunctionDescriptor()).getAsmMethod();
322                if (!method.getName().equals("<clinit>")) {
323                    return method;
324                }
325            }
326            return null;
327        }
328    
329        @NotNull
330        public NameGenerator getInlineNameGenerator() {
331            if (inlineNameGenerator == null) {
332                String prefix = InlineCodegenUtil.getInlineName(context, typeMapper, fileClassesProvider);
333                inlineNameGenerator = new NameGenerator(prefix);
334            }
335            return inlineNameGenerator;
336        }
337    
338        @NotNull
339        protected ExpressionCodegen createOrGetClInitCodegen() {
340            DeclarationDescriptor descriptor = context.getContextDescriptor();
341            if (clInit == null) {
342                MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), ACC_STATIC, "<clinit>", "()V", null, null);
343                SimpleFunctionDescriptorImpl clInit =
344                        SimpleFunctionDescriptorImpl.create(descriptor, Annotations.Companion.getEMPTY(), Name.special("<clinit>"), SYNTHESIZED,
345                                                            KotlinSourceElementKt.toSourceElement(element));
346                clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
347                                  Collections.<ValueParameterDescriptor>emptyList(),
348                                  DescriptorUtilsKt.getModule(descriptor).getBuiltIns().getUnitType(),
349                                  null, Visibilities.PRIVATE);
350    
351                this.clInit = new ExpressionCodegen(mv, new FrameMap(), Type.VOID_TYPE, context.intoFunction(clInit), state, this);
352            }
353            return clInit;
354        }
355    
356        protected void generateInitializers(@NotNull Function0<ExpressionCodegen> createCodegen) {
357            NotNullLazyValue<ExpressionCodegen> codegen = LockBasedStorageManager.NO_LOCKS.createLazyValue(createCodegen);
358            for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) {
359                if (declaration instanceof KtProperty) {
360                    if (shouldInitializeProperty((KtProperty) declaration)) {
361                        initializeProperty(codegen.invoke(), (KtProperty) declaration);
362                    }
363                }
364                else if (declaration instanceof KtAnonymousInitializer) {
365                    KtExpression body = ((KtAnonymousInitializer) declaration).getBody();
366                    if (body != null) {
367                        codegen.invoke().gen(body, Type.VOID_TYPE);
368                    }
369                }
370            }
371        }
372    
373        private void initializeProperty(@NotNull ExpressionCodegen codegen, @NotNull KtProperty property) {
374            PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
375            assert propertyDescriptor != null;
376    
377            KtExpression initializer = property.getDelegateExpressionOrInitializer();
378            assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
379    
380            StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, false, null, true, StackValue.LOCAL_0);
381    
382            propValue.store(codegen.gen(initializer), codegen.v);
383        }
384    
385        private boolean shouldInitializeProperty(@NotNull KtProperty property) {
386            if (!property.hasDelegateExpressionOrInitializer()) return false;
387    
388            PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
389            assert propertyDescriptor != null;
390    
391            if (propertyDescriptor.isConst()) {
392                //const initializer always inlined
393                return false;
394            }
395    
396            KtExpression initializer = property.getInitializer();
397    
398            ConstantValue<?> initializerValue = computeInitializerValue(property, propertyDescriptor, initializer);
399            // we must write constant values for fields in light classes,
400            // because Java's completion for annotation arguments uses this information
401            if (initializerValue == null) return state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES;
402    
403            //TODO: OPTIMIZATION: don't initialize static final fields
404            KotlinType jetType = getPropertyOrDelegateType(property, propertyDescriptor);
405            Type type = typeMapper.mapType(jetType);
406            return !skipDefaultValue(propertyDescriptor, initializerValue.getValue(), type);
407        }
408    
409        @Nullable
410        private ConstantValue<?> computeInitializerValue(
411                @NotNull KtProperty property,
412                @NotNull PropertyDescriptor propertyDescriptor,
413                @Nullable KtExpression initializer
414        ) {
415            if (property.isVar() && initializer != null) {
416                BindingTrace tempTrace = TemporaryBindingTrace.create(state.getBindingTrace(), "property initializer");
417                return constantExpressionEvaluator.evaluateToConstantValue(initializer, tempTrace, propertyDescriptor.getType());
418            }
419            return propertyDescriptor.getCompileTimeInitializer();
420        }
421    
422        @NotNull
423        private KotlinType getPropertyOrDelegateType(@NotNull KtProperty property, @NotNull PropertyDescriptor descriptor) {
424            KtExpression delegateExpression = property.getDelegateExpression();
425            if (delegateExpression != null) {
426                KotlinType delegateType = bindingContext.getType(delegateExpression);
427                assert delegateType != null : "Type of delegate expression should be recorded";
428                return delegateType;
429            }
430            return descriptor.getType();
431        }
432    
433        private static boolean skipDefaultValue(@NotNull PropertyDescriptor propertyDescriptor, Object value, @NotNull Type type) {
434            if (isPrimitive(type)) {
435                if (!propertyDescriptor.getType().isMarkedNullable() && value instanceof Number) {
436                    if (type == Type.INT_TYPE && ((Number) value).intValue() == 0) {
437                        return true;
438                    }
439                    if (type == Type.BYTE_TYPE && ((Number) value).byteValue() == 0) {
440                        return true;
441                    }
442                    if (type == Type.LONG_TYPE && ((Number) value).longValue() == 0L) {
443                        return true;
444                    }
445                    if (type == Type.SHORT_TYPE && ((Number) value).shortValue() == 0) {
446                        return true;
447                    }
448                    if (type == Type.DOUBLE_TYPE && ((Number) value).doubleValue() == 0d) {
449                        return true;
450                    }
451                    if (type == Type.FLOAT_TYPE && ((Number) value).floatValue() == 0f) {
452                        return true;
453                    }
454                }
455                if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean) value)) {
456                    return true;
457                }
458                if (type == Type.CHAR_TYPE && value instanceof Character && ((Character) value) == 0) {
459                    return true;
460                }
461            }
462            else {
463                if (value == null) {
464                    return true;
465                }
466            }
467            return false;
468        }
469    
470        protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
471            List<KtProperty> delegatedProperties = new ArrayList<KtProperty>();
472            for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) {
473                if (declaration instanceof KtProperty) {
474                    KtProperty property = (KtProperty) declaration;
475                    if (property.hasDelegate()) {
476                        delegatedProperties.add(property);
477                    }
478                }
479            }
480            if (delegatedProperties.isEmpty()) return;
481    
482            v.newField(NO_ORIGIN, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
483                       "[" + K_PROPERTY_TYPE, null, null);
484    
485            if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
486    
487            InstructionAdapter iv = createOrGetClInitCodegen().v;
488            iv.iconst(delegatedProperties.size());
489            iv.newarray(K_PROPERTY_TYPE);
490    
491            for (int i = 0, size = delegatedProperties.size(); i < size; i++) {
492                PropertyDescriptor property =
493                        (PropertyDescriptor) BindingContextUtils.getNotNull(bindingContext, VARIABLE, delegatedProperties.get(i));
494    
495                iv.dup();
496                iv.iconst(i);
497    
498                int receiverCount = (property.getDispatchReceiverParameter() != null ? 1 : 0) +
499                                    (property.getExtensionReceiverParameter() != null ? 1 : 0);
500                Type implType = property.isVar() ? MUTABLE_PROPERTY_REFERENCE_IMPL[receiverCount] : PROPERTY_REFERENCE_IMPL[receiverCount];
501                iv.anew(implType);
502                iv.dup();
503                // TODO: generate the container once and save to a local field instead (KT-10495)
504                ClosureCodegen.generateCallableReferenceDeclarationContainer(iv, property, state);
505                iv.aconst(property.getName().asString());
506                iv.aconst(PropertyReferenceCodegen.getPropertyReferenceSignature(property, state));
507                iv.invokespecial(
508                        implType.getInternalName(), "<init>",
509                        Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false
510                );
511                Method wrapper = PropertyReferenceCodegen.getWrapperMethodForPropertyReference(property, receiverCount);
512                iv.invokestatic(REFLECTION, wrapper.getName(), wrapper.getDescriptor(), false);
513    
514                StackValue.onStack(implType).put(K_PROPERTY_TYPE, iv);
515    
516                iv.astore(K_PROPERTY_TYPE);
517            }
518    
519            iv.putstatic(thisAsmType.getInternalName(), JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + K_PROPERTY_TYPE);
520        }
521    
522        public String getClassName() {
523            return v.getThisName();
524        }
525    
526        @NotNull
527        public FieldOwnerContext<?> getContext() {
528            return context;
529        }
530    
531        @NotNull
532        public ReifiedTypeParametersUsages getReifiedTypeParametersUsages() {
533            return reifiedTypeParametersUsages;
534        }
535    
536        public MemberCodegen<?> getParentCodegen() {
537            return parentCodegen;
538        }
539    
540        @Override
541        public String toString() {
542            return context.toString();
543        }
544    
545        @NotNull
546        public SourceMapper getOrCreateSourceMapper() {
547            if (sourceMapper == null) {
548                sourceMapper = new DefaultSourceMapper(SourceInfo.Companion.createInfo(element, getClassName()), null);
549            }
550            return sourceMapper;
551        }
552    
553        protected void generateConstInstance(@NotNull Type thisAsmType, @NotNull Type fieldAsmType) {
554            v.newField(
555                    JvmDeclarationOriginKt.OtherOrigin(element), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD,
556                    fieldAsmType.getDescriptor(), null, null
557            );
558    
559            if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
560                InstructionAdapter iv = createOrGetClInitCodegen().v;
561                iv.anew(thisAsmType);
562                iv.dup();
563                iv.invokespecial(thisAsmType.getInternalName(), "<init>", "()V", false);
564                iv.putstatic(thisAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, fieldAsmType.getDescriptor());
565            }
566        }
567    
568        protected void generateSyntheticAccessors() {
569            for (AccessorForCallableDescriptor<?> accessor : ((CodegenContext<?>) context).getAccessors()) {
570                generateSyntheticAccessor(accessor);
571            }
572        }
573    
574        private void generateSyntheticAccessor(@NotNull AccessorForCallableDescriptor<?> accessorForCallableDescriptor) {
575            if (accessorForCallableDescriptor instanceof FunctionDescriptor) {
576                final FunctionDescriptor accessor = (FunctionDescriptor) accessorForCallableDescriptor;
577                final FunctionDescriptor original = (FunctionDescriptor) accessorForCallableDescriptor.getCalleeDescriptor();
578                functionCodegen.generateMethod(
579                        Synthetic(null, original), accessor,
580                        new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, accessor) {
581                            @Override
582                            public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
583                                markLineNumberForElement(element, codegen.v);
584    
585                                generateMethodCallTo(original, accessor, codegen.v).coerceTo(signature.getReturnType(), codegen.v);
586    
587                                codegen.v.areturn(signature.getReturnType());
588                            }
589                        }
590                );
591            }
592            else if (accessorForCallableDescriptor instanceof AccessorForPropertyDescriptor) {
593                final AccessorForPropertyDescriptor accessor = (AccessorForPropertyDescriptor) accessorForCallableDescriptor;
594                final PropertyDescriptor original = accessor.getCalleeDescriptor();
595    
596                class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
597                    public PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
598                        super(MemberCodegen.this.state, callableDescriptor);
599                    }
600    
601                    @Override
602                    public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
603                        boolean syntheticBackingField = accessor instanceof AccessorForPropertyBackingFieldFromLocal;
604                        boolean forceFieldForCompanionProperty = JvmAbi.isPropertyWithBackingFieldInOuterClass(original) &&
605                                                                 !isCompanionObject(accessor.getContainingDeclaration());
606                        boolean forceField = forceFieldForCompanionProperty ||
607                                             syntheticBackingField ||
608                                             original.getVisibility() == JavaVisibilities.PROTECTED_STATIC_VISIBILITY;
609                        StackValue property = codegen.intermediateValueForProperty(
610                                original, forceField, syntheticBackingField, accessor.getSuperCallTarget(), forceFieldForCompanionProperty, StackValue.none()
611                        );
612    
613                        InstructionAdapter iv = codegen.v;
614    
615                        markLineNumberForElement(element, iv);
616    
617                        Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
618                        for (int i = 0, reg = 0; i < argTypes.length; i++) {
619                            Type argType = argTypes[i];
620                            iv.load(reg, argType);
621                            //noinspection AssignmentToForLoopParameter
622                            reg += argType.getSize();
623                        }
624    
625                        if (callableDescriptor instanceof PropertyGetterDescriptor) {
626                            property.put(signature.getReturnType(), iv);
627                        }
628                        else {
629                            property.store(StackValue.onStack(property.type), iv, true);
630                        }
631    
632                        iv.areturn(signature.getReturnType());
633                    }
634                }
635    
636                if (accessor.isWithSyntheticGetterAccessor()) {
637                    PropertyGetterDescriptor getter = accessor.getGetter();
638                    assert getter != null;
639                    functionCodegen.generateMethod(Synthetic(null, original.getGetter() != null ? original.getGetter() : original),
640                                                   getter, new PropertyAccessorStrategy(getter));
641                }
642    
643                if (accessor.isVar() && accessor.isWithSyntheticSetterAccessor()) {
644                    PropertySetterDescriptor setter = accessor.getSetter();
645                    assert setter != null;
646    
647                    functionCodegen.generateMethod(Synthetic(null, original.getSetter() != null ? original.getSetter() : original),
648                                                   setter, new PropertyAccessorStrategy(setter));
649                }
650            }
651            else {
652                throw new UnsupportedOperationException();
653            }
654        }
655    
656        protected StackValue generateMethodCallTo(
657                @NotNull FunctionDescriptor functionDescriptor,
658                @Nullable FunctionDescriptor accessorDescriptor,
659                @NotNull InstructionAdapter iv
660        ) {
661            CallableMethod callableMethod = typeMapper.mapToCallableMethod(
662                    functionDescriptor,
663                    accessorDescriptor instanceof AccessorForCallableDescriptor &&
664                    ((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null
665            );
666    
667            boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) && !isInterface(functionDescriptor.getContainingDeclaration());
668            int reg = hasDispatchReceiver ? 1 : 0;
669            boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
670            if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) {
671                iv.anew(callableMethod.getOwner());
672                iv.dup();
673                reg = 0;
674            }
675            else if (accessorIsConstructor || (accessorDescriptor != null && JetTypeMapper.isAccessor(accessorDescriptor) && hasDispatchReceiver)) {
676                if (!AnnotationUtilKt.isPlatformStaticInObjectOrClass(functionDescriptor)) {
677                    iv.load(0, OBJECT_TYPE);
678                }
679            }
680    
681            for (Type argType : callableMethod.getParameterTypes()) {
682                if (AsmTypes.DEFAULT_CONSTRUCTOR_MARKER.equals(argType)) {
683                    iv.aconst(null);
684                }
685                else {
686                    iv.load(reg, argType);
687                    reg += argType.getSize();
688                }
689            }
690    
691            callableMethod.genInvokeInstruction(iv);
692    
693            return StackValue.onStack(callableMethod.getReturnType());
694        }
695    }