예제 #1
0
        private void ProcessInvoke(RPContext ctx, int instrIndex, int argBeginIndex)
        {
            Tuple <FieldDef, MethodDef> tuple2;
            Instruction instruction  = ctx.Body.Instructions[instrIndex];
            IMethod     operand      = (IMethod)instruction.Operand;
            MethodSig   sig          = RPMode.CreateProxySignature(ctx, operand, instruction.OpCode.Code == Code.Newobj);
            TypeDef     delegateType = RPMode.GetDelegateType(ctx, sig);
            Tuple <Code, IMethod, IRPEncoding> key = Tuple.Create <Code, IMethod, IRPEncoding>(instruction.OpCode.Code, operand, ctx.EncodingHandler);

            if (!this.fields.TryGetValue(key, out tuple2))
            {
                tuple2           = new Tuple <FieldDef, MethodDef>(this.CreateField(ctx, delegateType), null);
                this.fields[key] = tuple2;
            }
            if (argBeginIndex == instrIndex)
            {
                ctx.Body.Instructions.Insert(instrIndex + 1, new Instruction(OpCodes.Call, delegateType.FindMethod("Invoke")));
                instruction.OpCode  = OpCodes.Ldsfld;
                instruction.Operand = tuple2.Item1;
            }
            else
            {
                Instruction instruction2 = ctx.Body.Instructions[argBeginIndex];
                ctx.Body.Instructions.Insert(argBeginIndex + 1, new Instruction(instruction2.OpCode, instruction2.Operand));
                instruction2.OpCode  = OpCodes.Ldsfld;
                instruction2.Operand = tuple2.Item1;
                instruction.OpCode   = OpCodes.Call;
                instruction.Operand  = delegateType.FindMethod("Invoke");
            }
        }
예제 #2
0
        private void ProcessBridge(RPContext ctx, int instrIndex)
        {
            Instruction instruction = ctx.Body.Instructions[instrIndex];
            IMethod     operand     = (IMethod)instruction.Operand;
            TypeDef     def         = operand.DeclaringType.ResolveTypeDefThrow();

            if (def.Module.IsILOnly && !def.IsGlobalModuleType)
            {
                Tuple <FieldDef, MethodDef>        tuple2;
                Tuple <Code, IMethod, IRPEncoding> key = Tuple.Create <Code, IMethod, IRPEncoding>(instruction.OpCode.Code, operand, ctx.EncodingHandler);
                if (this.fields.TryGetValue(key, out tuple2))
                {
                    if (tuple2.Item2 != null)
                    {
                        instruction.OpCode  = OpCodes.Call;
                        instruction.Operand = tuple2.Item2;
                        return;
                    }
                }
                else
                {
                    tuple2 = new Tuple <FieldDef, MethodDef>(null, null);
                }
                MethodSig sig          = RPMode.CreateProxySignature(ctx, operand, instruction.OpCode.Code == Code.Newobj);
                TypeDef   delegateType = RPMode.GetDelegateType(ctx, sig);
                if (tuple2.Item1 == null)
                {
                    tuple2 = new Tuple <FieldDef, MethodDef>(this.CreateField(ctx, delegateType), tuple2.Item2);
                }
                tuple2              = new Tuple <FieldDef, MethodDef>(tuple2.Item1, this.CreateBridge(ctx, delegateType, tuple2.Item1, sig));
                this.fields[key]    = tuple2;
                instruction.OpCode  = OpCodes.Call;
                instruction.Operand = tuple2.Item2;
            }
        }
예제 #3
0
        public override void ProcessCall(RPContext ctx, int instrIndex)
        {
            Instruction instruction = ctx.Body.Instructions[instrIndex];
            IMethod     operand     = (IMethod)instruction.Operand;

            if (!operand.DeclaringType.ResolveTypeDefThrow().IsValueType&& (operand.ResolveThrow().IsPublic || operand.ResolveThrow().IsAssembly))
            {
                MethodDef def;
                Tuple <Code, TypeDef, IMethod> key = Tuple.Create <Code, TypeDef, IMethod>(instruction.OpCode.Code, ctx.Method.DeclaringType, operand);
                if (!this.proxies.TryGetValue(key, out def))
                {
                    MethodSig methodSig = RPMode.CreateProxySignature(ctx, operand, instruction.OpCode.Code == Code.Newobj);
                    def = new MethodDefUser(NameService.RandomNameStatic(), methodSig)
                    {
                        Attributes     = MethodAttributes.CompilerControlled | MethodAttributes.Static,
                        ImplAttributes = MethodImplAttributes.IL
                    };
                    ctx.Method.DeclaringType.Methods.Add(def);
                    if ((instruction.OpCode.Code == Code.Call) && operand.ResolveThrow().IsVirtual)
                    {
                        def.IsStatic      = false;
                        methodSig.HasThis = true;
                        methodSig.Params.RemoveAt(0);
                    }
                    ctx.Marker.Mark(def, ctx.Protection);

                    /*ctx.Name.Analyze(def);
                     * ctx.Name.SetCanRename(def, false);*/
                    def.Body = new CilBody();
                    for (int i = 0; i < def.Parameters.Count; i++)
                    {
                        def.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg, def.Parameters[i]));
                    }
                    def.Body.Instructions.Add(Instruction.Create(instruction.OpCode, operand));
                    def.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                    this.proxies[key] = def;
                }
                instruction.OpCode = OpCodes.Call;
                if (ctx.Method.DeclaringType.HasGenericParameters)
                {
                    GenericVar[] genArgs = new GenericVar[ctx.Method.DeclaringType.GenericParameters.Count];
                    for (int j = 0; j < genArgs.Length; j++)
                    {
                        genArgs[j] = new GenericVar(j);
                    }
                    instruction.Operand = new MemberRefUser(ctx.Module, def.Name, def.MethodSig, new GenericInstSig((ClassOrValueTypeSig)ctx.Method.DeclaringType.ToTypeSig(), genArgs).ToTypeDefOrRef());
                }
                else
                {
                    instruction.Operand = def;
                }
            }
        }