IKVM.Internal.CompilerClassLoader.RemapperTypeWrapper.RemappedMethodWrapper.Finish C# (CSharp) Method

Finish() private method

private Finish ( ) : void
return void
                internal override void Finish()
                {
                    // TODO we should insert method tracing (if enabled)
                    Type[] paramTypes = this.GetParametersForDefineMethod();

                    MethodBuilder mbCore = GetMethod() as MethodBuilder;

                    // NOTE sealed types don't have instance methods (only instancehelpers)
                    if(mbCore != null)
                    {
                        CodeEmitter ilgen = CodeEmitter.Create(mbCore);
                        MethodInfo baseMethod = null;
                        if(m.@override != null)
                        {
                            baseMethod = DeclaringType.TypeAsTBD.GetMethod([email protected], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes, null);
                            if(baseMethod == null)
                            {
                                throw new InvalidOperationException();
                            }
                            ((TypeBuilder)DeclaringType.TypeAsBaseType).DefineMethodOverride(mbCore, baseMethod);
                        }
                        // TODO we need to support ghost (and other funky?) parameter types
                        if(m.body != null)
                        {
                            // we manually walk the instruction list, because we need to special case the ret instructions
                            IKVM.Internal.MapXml.CodeGenContext context = new IKVM.Internal.MapXml.CodeGenContext(DeclaringType.GetClassLoader());
                            foreach(IKVM.Internal.MapXml.Instruction instr in m.body.invoke)
                            {
                                if(instr is IKVM.Internal.MapXml.Ret)
                                {
                                    this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
                                }
                                instr.Generate(context, ilgen);
                            }
                        }
                        else
                        {
                            if(m.redirect != null && m.redirect.LineNumber != -1)
                            {
                                ilgen.SetLineNumber((ushort)m.redirect.LineNumber);
                            }
                            int thisOffset = 0;
                            if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0)
                            {
                                thisOffset = 1;
                                ilgen.Emit(OpCodes.Ldarg_0);
                            }
                            for(int i = 0; i < paramTypes.Length; i++)
                            {
                                ilgen.Emit(OpCodes.Ldarg, (short)(i + thisOffset));
                            }
                            if(m.redirect != null)
                            {
                                EmitRedirect(DeclaringType.TypeAsTBD, ilgen);
                            }
                            else
                            {
                                if(baseMethod == null)
                                {
                                    throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
                                }
                                ilgen.Emit(OpCodes.Call, baseMethod);
                            }
                            this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
                            ilgen.Emit(OpCodes.Ret);
                        }
                        ilgen.DoEmit();
                        if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo)
                        {
                            ilgen.EmitLineNumberTable(mbCore);
                        }
                    }

                    // NOTE static methods don't have helpers
                    // NOTE for interface helpers we don't have to do anything,
                    // because they've already been generated in DoLink
                    // (currently this only applies to Comparable.compareTo).
                    if(mbHelper != null && !this.DeclaringType.IsInterface)
                    {
                        CodeEmitter ilgen = CodeEmitter.Create(mbHelper);
                        // check "this" for null
                        if(m.@override != null && m.redirect == null && m.body == null && m.alternateBody == null)
                        {
                            // we're going to be calling the overridden version, so we don't need the null check
                        }
                        else if(!m.NoNullCheck)
                        {
                            ilgen.Emit(OpCodes.Ldarg_0);
                            ilgen.EmitNullCheck();
                        }
                        if(mbCore != null &&
                            (m.@override == null || m.redirect != null) &&
                            (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Private) == 0 && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Final) == 0)
                        {
                            // TODO we should have a way to supress this for overridden methods
                            ilgen.Emit(OpCodes.Ldarg_0);
                            ilgen.Emit(OpCodes.Isinst, DeclaringType.TypeAsBaseType);
                            ilgen.Emit(OpCodes.Dup);
                            CodeEmitterLabel skip = ilgen.DefineLabel();
                            ilgen.Emit(OpCodes.Brfalse_S, skip);
                            for(int i = 0; i < paramTypes.Length; i++)
                            {
                                ilgen.Emit(OpCodes.Ldarg, (short)(i + 1));
                            }
                            ilgen.Emit(OpCodes.Callvirt, mbCore);
                            this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
                            ilgen.Emit(OpCodes.Ret);
                            ilgen.MarkLabel(skip);
                            ilgen.Emit(OpCodes.Pop);
                        }
                        foreach(RemapperTypeWrapper overrider in overriders)
                        {
                            RemappedMethodWrapper mw = (RemappedMethodWrapper)overrider.GetMethodWrapper(Name, Signature, false);
                            if(mw.m.redirect == null && mw.m.body == null && mw.m.alternateBody == null)
                            {
                                // the overridden method doesn't actually do anything special (that means it will end
                                // up calling the .NET method it overrides), so we don't need to special case this
                            }
                            else
                            {
                                ilgen.Emit(OpCodes.Ldarg_0);
                                ilgen.Emit(OpCodes.Isinst, overrider.TypeAsTBD);
                                ilgen.Emit(OpCodes.Dup);
                                CodeEmitterLabel skip = ilgen.DefineLabel();
                                ilgen.Emit(OpCodes.Brfalse_S, skip);
                                for(int i = 0; i < paramTypes.Length; i++)
                                {
                                    ilgen.Emit(OpCodes.Ldarg, (short)(i + 1));
                                }
                                mw.Link();
                                mw.EmitCallvirtImpl(ilgen, false);
                                this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
                                ilgen.Emit(OpCodes.Ret);
                                ilgen.MarkLabel(skip);
                                ilgen.Emit(OpCodes.Pop);
                            }
                        }
                        if(m.body != null || m.alternateBody != null)
                        {
                            IKVM.Internal.MapXml.InstructionList body = m.alternateBody == null ? m.body : m.alternateBody;
                            // we manually walk the instruction list, because we need to special case the ret instructions
                            IKVM.Internal.MapXml.CodeGenContext context = new IKVM.Internal.MapXml.CodeGenContext(DeclaringType.GetClassLoader());
                            foreach(IKVM.Internal.MapXml.Instruction instr in body.invoke)
                            {
                                if(instr is IKVM.Internal.MapXml.Ret)
                                {
                                    this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
                                }
                                instr.Generate(context, ilgen);
                            }
                        }
                        else
                        {
                            if(m.redirect != null && m.redirect.LineNumber != -1)
                            {
                                ilgen.SetLineNumber((ushort)m.redirect.LineNumber);
                            }
                            Type shadowType = ((RemapperTypeWrapper)DeclaringType).shadowType;
                            for(int i = 0; i < paramTypes.Length + 1; i++)
                            {
                                ilgen.Emit(OpCodes.Ldarg, (short)i);
                            }
                            if(m.redirect != null)
                            {
                                EmitRedirect(shadowType, ilgen);
                            }
                            else if(m.@override != null)
                            {
                                MethodInfo baseMethod = shadowType.GetMethod([email protected], BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null);
                                if(baseMethod == null)
                                {
                                    throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
                                }
                                ilgen.Emit(OpCodes.Callvirt, baseMethod);
                            }
                            else
                            {
                                RemappedMethodWrapper baseMethod = DeclaringType.BaseTypeWrapper.GetMethodWrapper(Name, Signature, true) as RemappedMethodWrapper;
                                if(baseMethod == null || baseMethod.m.@override == null)
                                {
                                    throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
                                }
                                MethodInfo overrideMethod = shadowType.GetMethod([email protected], BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null);
                                if(overrideMethod == null)
                                {
                                    throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
                                }
                                ilgen.Emit(OpCodes.Callvirt, overrideMethod);
                            }
                            this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
                            ilgen.Emit(OpCodes.Ret);
                        }
                        ilgen.DoEmit();
                        if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo)
                        {
                            ilgen.EmitLineNumberTable(mbHelper);
                        }
                    }

                    // do we need a helper for non-virtual reflection invocation?
                    if(m.nonvirtualAlternateBody != null || (m.@override != null && overriders.Count > 0))
                    {
                        RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType;
                        Type[] argTypes = new Type[paramTypes.Length + 1];
                        argTypes[0] = typeWrapper.TypeAsSignatureType;
                        this.GetParametersForDefineMethod().CopyTo(argTypes, 1);
                        MethodBuilder mb = typeWrapper.typeBuilder.DefineMethod("nonvirtualhelper/" + this.Name, MethodAttributes.Private | MethodAttributes.Static, this.ReturnTypeForDefineMethod, argTypes);
                        if(m.Attributes != null)
                        {
                            foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
                            {
                                AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mb, custattr);
                            }
                        }
                        SetParameters(DeclaringType.GetClassLoader(), mb, m.Params);
                        AttributeHelper.HideFromJava(mb);
                        CodeEmitter ilgen = CodeEmitter.Create(mb);
                        if(m.nonvirtualAlternateBody != null)
                        {
                            m.nonvirtualAlternateBody.Emit(DeclaringType.GetClassLoader(), ilgen);
                        }
                        else
                        {
                            Type shadowType = ((RemapperTypeWrapper)DeclaringType).shadowType;
                            MethodInfo baseMethod = shadowType.GetMethod([email protected], BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null);
                            if(baseMethod == null)
                            {
                                throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
                            }
                            ilgen.Emit(OpCodes.Ldarg_0);
                            for(int i = 0; i < paramTypes.Length; i++)
                            {
                                ilgen.Emit(OpCodes.Ldarg, (short)(i + 1));
                            }
                            ilgen.Emit(OpCodes.Call, baseMethod);
                            ilgen.Emit(OpCodes.Ret);
                        }
                        ilgen.DoEmit();
                    }
                }