public void gen(@NotNull JetNamedFunction function) {
    SimpleFunctionDescriptor functionDescriptor =
        bindingContext.get(BindingContext.FUNCTION, function);
    assert functionDescriptor != null
        : "No descriptor for function "
            + function.getText()
            + "\n"
            + "in "
            + function.getContainingFile().getVirtualFile();

    if (owner.getContextKind() != OwnerKind.DEFAULT_IMPLS || function.hasBody()) {
      generateMethod(
          OtherOrigin(function, functionDescriptor),
          functionDescriptor,
          new FunctionGenerationStrategy.FunctionDefault(state, functionDescriptor, function));
    }

    generateDefaultIfNeeded(
        owner.intoFunction(functionDescriptor),
        functionDescriptor,
        owner.getContextKind(),
        DefaultParameterValueLoader.DEFAULT,
        function);

    generateOverloadsWithDefaultValues(function, functionDescriptor, functionDescriptor);
  }
 public void generateOverloadsWithDefaultValues(
     @Nullable JetNamedFunction function,
     @NotNull FunctionDescriptor functionDescriptor,
     @NotNull FunctionDescriptor delegateFunctionDescriptor) {
   new DefaultParameterValueSubstitutor(state)
       .generateOverloadsIfNeeded(
           function, functionDescriptor, delegateFunctionDescriptor, owner.getContextKind(), v);
 }
  private void generateBridge(
      @Nullable PsiElement origin,
      @NotNull FunctionDescriptor descriptor,
      @NotNull Method bridge,
      @NotNull Method delegateTo,
      boolean isSpecialBridge,
      boolean superCallNeeded) {
    int flags =
        ACC_PUBLIC
            | ACC_BRIDGE
            | (!isSpecialBridge ? ACC_SYNTHETIC : 0)
            | (isSpecialBridge ? ACC_FINAL : 0); // TODO.

    MethodVisitor mv =
        v.newMethod(
            DiagnosticsPackage.Bridge(descriptor, origin),
            flags,
            bridge.getName(),
            bridge.getDescriptor(),
            null,
            null);
    if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;

    mv.visitCode();

    Type[] argTypes = bridge.getArgumentTypes();
    Type[] originalArgTypes = delegateTo.getArgumentTypes();

    InstructionAdapter iv = new InstructionAdapter(mv);
    ImplementationBodyCodegen.markLineNumberForSyntheticFunction(owner.getThisDescriptor(), iv);

    iv.load(0, OBJECT_TYPE);
    for (int i = 0, reg = 1; i < argTypes.length; i++) {
      StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
      //noinspection AssignmentToForLoopParameter
      reg += argTypes[i].getSize();
    }

    if (superCallNeeded) {
      ClassDescriptor parentClass =
          getSuperClassDescriptor((ClassDescriptor) descriptor.getContainingDeclaration());
      assert parentClass != null;
      String parentInternalName = typeMapper.mapClass(parentClass).getInternalName();
      iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor());
    } else {
      iv.invokevirtual(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
    }

    StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv);
    iv.areturn(bridge.getReturnType());

    endVisit(mv, "bridge method", origin);
  }
  public void generateBridges(@NotNull FunctionDescriptor descriptor) {
    if (descriptor instanceof ConstructorDescriptor) return;
    if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return;
    if (isInterface(descriptor.getContainingDeclaration())) return;

    // equals(Any?), hashCode(), toString() never need bridges
    if (isMethodOfAny(descriptor)) return;

    // If the function doesn't have a physical declaration among super-functions, it's a SAM adapter
    // or alike and doesn't need bridges
    if (CallResolverUtilPackage.isOrOverridesSynthesized(descriptor)) return;

    boolean isSpecial = BuiltinsPropertiesUtilKt.overridesBuiltinSpecialDeclaration(descriptor);

    Set<Bridge<Method>> bridgesToGenerate;
    if (!isSpecial) {
      bridgesToGenerate =
          BridgesPackage.generateBridgesForFunctionDescriptor(
              descriptor,
              new Function1<FunctionDescriptor, Method>() {
                @Override
                public Method invoke(FunctionDescriptor descriptor) {
                  return typeMapper.mapSignature(descriptor).getAsmMethod();
                }
              });
      if (!bridgesToGenerate.isEmpty()) {
        PsiElement origin =
            descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
        for (Bridge<Method> bridge : bridgesToGenerate) {
          generateBridge(origin, descriptor, bridge.getFrom(), bridge.getTo(), false, false);
        }
      }
    } else {
      Set<BridgeForBuiltinSpecial<Method>> specials =
          BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
              descriptor,
              new Function1<FunctionDescriptor, Method>() {
                @Override
                public Method invoke(FunctionDescriptor descriptor) {
                  return typeMapper.mapSignature(descriptor).getAsmMethod();
                }
              });

      if (!specials.isEmpty()) {
        PsiElement origin =
            descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
        for (BridgeForBuiltinSpecial<Method> bridge : specials) {
          generateBridge(
              origin,
              descriptor,
              bridge.getFrom(),
              bridge.getTo(),
              bridge.isSpecial(),
              bridge.isDelegateToSuper());
        }
      }

      if (!descriptor.getKind().isReal()
          && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
        CallableDescriptor overridden =
            BuiltinsPropertiesUtilKt.getBuiltinSpecialOverridden(descriptor);
        assert overridden != null;

        Method method = typeMapper.mapSignature(descriptor).getAsmMethod();
        int flags = ACC_ABSTRACT | getVisibilityAccessFlag(descriptor);
        v.newMethod(
            OtherOrigin(overridden), flags, method.getName(), method.getDescriptor(), null, null);
      }
    }
  }
 public void generateMethod(
     @NotNull JvmDeclarationOrigin origin,
     @NotNull FunctionDescriptor descriptor,
     @NotNull FunctionGenerationStrategy strategy) {
   generateMethod(origin, descriptor, owner.intoFunction(descriptor), strategy);
 }