Пример #1
0
        private MethodDefinition Manage(MethodDefinition method)
        {
            var _type = this.m_Type.Type(method.IsConstructor ? "<<Constructor>>" : $"<{ method.Name }>", TypeAttributes.NestedPublic | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Abstract);

            foreach (var _generic in method.DeclaringType.GenericParameters.Concat(method.GenericParameters))
            {
                _type.GenericParameters.Add(_generic.Copy(_type));
            }
            var _importation = new Importation(method, _type);
            var _method      = _type.Method(method.IsConstructor ? "<Constructor>" : method.Name, MethodAttributes.Static | MethodAttributes.Private);

            if (!method.IsStatic)
            {
                _method.Parameter("this", ParameterAttributes.None, _method.Resolve(method.DeclaringType));
            }
            _method.ReturnType             = _method.Resolve(method.ReturnType);
            _method.Body.InitLocals        = method.Body.InitLocals;
            _method.DebugInformation.Scope = method.DebugInformation.Scope;
            _method.Body.MaxStackSize      = method.Body.MaxStackSize;
            _method.Body.LocalVarToken     = method.Body.LocalVarToken;
            foreach (var _parameter in method.Parameters)
            {
                _method.Parameter(_parameter.Name, _parameter.Attributes, _method.Resolve(_parameter.ParameterType));
            }
            foreach (var _variable in method.Body.Variables)
            {
                _method.Body.Variable(_method.Resolve(_variable.VariableType));
            }
            var _dictionary = new Dictionary <Instruction, Instruction>();

            foreach (var _instruction in method.Body.Instructions)
            {
                _method.Body.Instructions.Add(this.Copy(method, _method, _importation, _instruction, _dictionary));
            }
            foreach (var _exception in method.Body.ExceptionHandlers)
            {
                _method.Body.ExceptionHandlers.Add(new ExceptionHandler(_exception.HandlerType)
                {
                    CatchType    = _exception.CatchType,
                    TryStart     = this.Copy(method, _method, _importation, _exception.TryStart, _dictionary),
                    TryEnd       = this.Copy(method, _method, _importation, _exception.TryEnd, _dictionary),
                    HandlerType  = _exception.HandlerType,
                    HandlerStart = this.Copy(method, _method, _importation, _exception.HandlerStart, _dictionary),
                    HandlerEnd   = this.Copy(method, _method, _importation, _exception.HandlerEnd, _dictionary)
                });
            }
            if (method.DebugInformation != null && method.DebugInformation.Scope != null)
            {
                if (method.DebugInformation.Scope.Variables != null)
                {
                    _method.DebugInformation.Scope.Variables.Clear();
                    foreach (var _variable in method.DebugInformation.Scope.Variables)
                    {
                        _method.DebugInformation.Scope.Variables.Add(new VariableDebugInformation(_method.Body.Variables[_variable.Index], _variable.Name));
                    }
                }
            }
            _method.Body.OptimizeMacros();
            return(_method);
        }
Пример #2
0
        private FieldDefinition Manage(MethodDefinition method)
        {
            var _type = this.m_Type.Type(method.IsConstructor ? "<<Constructor>>" : $"<{ method.Name }>", TypeAttributes.NestedPublic | TypeAttributes.Abstract | TypeAttributes.Sealed);

            foreach (var _parameter in this.m_Type.GenericParameters)
            {
                _type.GenericParameters.Add(_parameter.Copy(_type));
            }
            foreach (var _parameter in method.GenericParameters)
            {
                _type.GenericParameters.Add(_parameter.Copy(_type));
            }
            var _handle    = _type.Field <object>("<Handle>", FieldAttributes.Static | FieldAttributes.Public).Relative();
            var _authentic = _type.Field <IntPtr>("<Authentic>", FieldAttributes.Static | FieldAttributes.Public).Relative();
            var _auxiliary = _type.Field <IntPtr>("<Auxiliary>", FieldAttributes.Static | FieldAttributes.Public).Relative();
            var _field     = _type.Field <IntPtr>("<Pointer>", FieldAttributes.Static | FieldAttributes.Public);
            var _pointer   = _field.Relative();
            var _update    = _type.Method("<Update>", MethodAttributes.Static | MethodAttributes.Private);

            _update.Parameter <IntPtr>("<Pointer>");
            var _return = Instruction.Create(OpCodes.Ret);

            using (_update.Body.Lock(_handle))
            {
                _update.Body.Emit(OpCodes.Ldsfld, _auxiliary);
                using (_update.Body.True())
                {
                    _update.Body.Emit(OpCodes.Ldarg_0);
                    _update.Body.Emit(OpCodes.Stsfld, _auxiliary);
                    _update.Body.Emit(OpCodes.Leave, _return);
                }
                _update.Body.Emit(OpCodes.Ldarg_0);
                _update.Body.Emit(OpCodes.Stsfld, _pointer);
            }
            _update.Body.Emit(_return);
            var _primary = _type.Method(method.IsConstructor ? "<Constructor>" : method.Name, MethodAttributes.Static | MethodAttributes.Private);

            _primary.ReturnType = _primary.Resolve(method.ReturnType);
            if (!method.IsStatic)
            {
                _primary.Parameter("this", ParameterAttributes.None, _primary.Resolve(method.DeclaringType));
            }
            foreach (var _parameter in method.Parameters)
            {
                _primary.Parameter(_parameter.Name, _parameter.Attributes, _primary.Resolve(_parameter.ParameterType));
            }
            _primary.Body.Variable <IntPtr>();
            _primary.Body.Emit(OpCodes.Ldsfld, _handle);
            _primary.Body.Emit(OpCodes.Call, Metadata.Method(() => Monitor.Enter(Metadata <object> .Value)));

            _primary.Body.Emit(Metadata <Action <MethodBase> > .Type);
            _primary.Body.Emit(typeof(Metadata));
            _primary.Body.Emit(OpCodes.Ldstr, "Broadcast");
            _primary.Body.Emit(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly);
            _primary.Body.Emit(OpCodes.Call, Metadata <Type> .Method(_Type => _Type.GetMethod(Metadata <string> .Value, Metadata <BindingFlags> .Value)));
            _primary.Body.Emit(OpCodes.Call, Metadata.Method(() => Delegate.CreateDelegate(Metadata <Type> .Value, Metadata <MethodInfo> .Value)));

            var _importation = new Importation(method, _type);

            //_primary.Body.Emit(_importation[method]);


            //TODO THONGTO
            _primary.Body.Emit(method);
            if (method.GenericParameters.Count > 0)
            {
                _primary.Body.Emit(OpCodes.Ldc_I4, method.GenericParameters.Count);
                _primary.Body.Emit(OpCodes.Newarr, typeof(Type));
                for (var i = 0; i < method.GenericParameters.Count; i++)
                {
                    _primary.Body.Emit(OpCodes.Dup);
                    _primary.Body.Emit(OpCodes.Ldc_I4, i);
                    _primary.Body.Emit(_type.GenericParameters.Skip(method.DeclaringType.GenericParameters.Count).ElementAt(i));
                    _primary.Body.Emit(OpCodes.Stelem_Ref);
                }
                _primary.Body.Emit(OpCodes.Callvirt, Metadata <MethodInfo> .Method(_Method => _Method.MakeGenericMethod(Metadata <Type[]> .Value)));
            }

            _primary.Body.Emit(OpCodes.Callvirt, Metadata <Action <MethodBase> > .Method(_Action => _Action.Invoke(Metadata <MethodBase> .Value)));

            _primary.Body.Emit(OpCodes.Ldsfld, _pointer);
            _primary.Body.Emit(OpCodes.Stloc_0);
            _primary.Body.Emit(OpCodes.Ldsfld, _auxiliary);
            using (_primary.Body.True())
            {
                _primary.Body.Emit(OpCodes.Ldsfld, _auxiliary);
                _primary.Body.Emit(OpCodes.Stloc_0);
                _primary.Body.Emit(OpCodes.Ldloc_0);
                _primary.Body.Emit(OpCodes.Stsfld, _pointer);
                _primary.Body.Emit(OpCodes.Ldsfld, Metadata.Field(() => IntPtr.Zero));
                _primary.Body.Emit(OpCodes.Stsfld, _auxiliary);
            }
            _primary.Body.Emit(OpCodes.Ldsfld, _handle);
            _primary.Body.Emit(OpCodes.Call, Metadata.Method(() => Monitor.Exit(Metadata <object> .Value)));
            for (var _index = 0; _index < _primary.Parameters.Count; _index++)
            {
                switch (_index)
                {
                case 0: _primary.Body.Emit(OpCodes.Ldarg_0); break;

                case 1: _primary.Body.Emit(OpCodes.Ldarg_1); break;

                case 2: _primary.Body.Emit(OpCodes.Ldarg_2); break;

                case 3: _primary.Body.Emit(OpCodes.Ldarg_3); break;

                default: _primary.Body.Emit(OpCodes.Ldarg_S, _primary.Parameters[_index]); break;
                }
            }
            _primary.Body.Emit(OpCodes.Ldloc_0);
            _primary.Body.Emit(OpCodes.Calli, _primary.ReturnType, _primary.Parameters);
            _primary.Body.Emit(OpCodes.Ret);
            _primary.Body.OptimizeMacros();
            var _initializer = _type.Initializer();
            var _variable    = _initializer.Body.Variable <RuntimeMethodHandle>();

            _initializer.Body.Variable <Func <IntPtr> >();
            _initializer.Body.Emit(OpCodes.Newobj, Metadata.Constructor(() => new object()));
            _initializer.Body.Emit(OpCodes.Stsfld, _handle);
            //var met = new MethodReference(this.m_Authentic[method].Name, _primary.ReturnType, this.m_Authentic[method].DeclaringType.MakeGenericType(_type.GenericParameters.Take(this.m_Type.GenericParameters.Count)));
            //foreach (var p in met.GenericParameters) { met.GenericParameters.Add(new GenericParameter(p.Name, met)); }
            //foreach (var _parameter in this.m_Authentic[method].Parameters) { met.Parameters.Add(new ParameterDefinition(_parameter.Name, _parameter.Attributes, _parameter.ParameterType.IsMethodGenericParameterType() ? _type.GenericParameterType(_parameter.ParameterType.Name) : _parameter.ParameterType)); }
            //_initializer.Body.Emit(met.MakeGenericMethod(_type.GenericParameters.Reverse().Take(method.GenericParameters.Count).Reverse().ToArray()));
            _initializer.Body.Emit(_importation[this.m_Authentic[method]]);
            _initializer.Body.Emit(OpCodes.Callvirt, Intermediate.GetMethodHandle);
            _initializer.Body.Emit(OpCodes.Stloc_0);
            _initializer.Body.Emit(OpCodes.Ldloca_S, _variable);
            _initializer.Body.Emit(OpCodes.Callvirt, Intermediate.GetFunctionPointer);
            _initializer.Body.Emit(OpCodes.Stsfld, _authentic);
            _initializer.Body.Emit(OpCodes.Ldsfld, _authentic);
            _initializer.Body.Emit(OpCodes.Stsfld, _auxiliary);
            //var met2 = new MethodReference(_primary.Name, _primary.ReturnType, _type.MakeGenericType(_type.GenericParameters));
            //foreach (var _parameter in _primary.Parameters) { met2.Parameters.Add(new ParameterDefinition(_parameter.Name, _parameter.Attributes, _parameter.ParameterType.IsMethodGenericParameterType() ? _type.GenericParameterType(_parameter.ParameterType.Name) : _parameter.ParameterType)); }
            //_initializer.Body.Emit(met2);
            //_initializer.Body.Emit(new MethodReference(_primary.Name, _primary.ReturnType, this.m_Authentic[method].DeclaringType.MakeGenericType(_type.GenericParameters)));
            _initializer.Body.Emit(_importation[_primary]);
            _initializer.Body.Emit(OpCodes.Callvirt, Intermediate.GetMethodHandle);
            _initializer.Body.Emit(OpCodes.Stloc_0);
            _initializer.Body.Emit(OpCodes.Ldloca_S, _variable);
            _initializer.Body.Emit(OpCodes.Callvirt, Intermediate.GetFunctionPointer);
            _initializer.Body.Emit(OpCodes.Stsfld, _pointer);
            _initializer.Body.Emit(OpCodes.Ret);
            _initializer.Body.OptimizeMacros();
            return(_field);
        }
Пример #3
0
        static public void Manage(this MethodDefinition method)
        {
            var _attribute = method.CustomAttributes.SingleOrDefault(_Attribute => _Attribute.AttributeType.Resolve() == method.Module.Import(typeof(AsyncStateMachineAttribute)).Resolve());

            if (_attribute == null)
            {
                return;
            }
            var _genericity = method.DeclaringType.GenericParameters.Concat(method.GenericParameters).ToArray();
            var _type       = _attribute.ConstructorArguments[0].Value as TypeDefinition;
            var _factory    = _type.Field <Func <IAdvice> >("<Factory>", FieldAttributes.Public | FieldAttributes.Static);
            var _advice     = _type.Field <IAdvice>("<Advice>", FieldAttributes.Public);

            _type.IsBeforeFieldInit = true;
            var _intializer = _type.Initializer();

            _intializer.Body.Emit(OpCodes.Call, Metadata.Property(() => Advisor.Null).GetGetMethod(true));
            _intializer.Body.Emit(OpCodes.Stsfld, _factory.Relative());
            _intializer.Body.Emit(OpCodes.Ret);
            var _constructor = _type.Methods.SingleOrDefault(m => m.IsConstructor && !m.IsStatic);

            if (_constructor == null)
            {
                _constructor = _type.Initializer();
            }
            _constructor.Body = new MethodBody(_constructor);
            _constructor.Body.Emit(OpCodes.Ldarg_0);
            _constructor.Body.Emit(OpCodes.Call, Metadata.Constructor(() => new object()));
            _constructor.Body.Emit(OpCodes.Ldarg_0);
            _constructor.Body.Emit(OpCodes.Ldsfld, _constructor.Module.Import(_factory.Relative()));
            _constructor.Body.Emit(OpCodes.Callvirt, Metadata <Func <IAdvice> > .Method(_Function => _Function.Invoke()));
            _constructor.Body.Emit(OpCodes.Stfld, _advice.Relative());
            _constructor.Body.Emit(OpCodes.Ret);
            var _move        = _type.Methods.Single(_Method => _Method.Name == "MoveNext");
            var _importation = new Importation(method, _move);
            var _task        = _move.Body.Variable <Task>();
            var _instance    = null as FieldReference;

            if (!method.IsStatic)
            {
                _instance = _type.Fields.SingleOrDefault(_Field => _Field.Name == "<>4__this");
                if (_instance == null)
                {
                    _instance = _type.Field("<>4__this", FieldAttributes.Public, _importation[method.DeclaringType]);
                    var _variable = method.Body.Variables.Single(_Variable => _Variable.VariableType.Resolve() == _type);
                    method.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Stfld, _genericity.Length > 0 ? new FieldReference(_instance.Name, method.DeclaringType, _type.MakeGenericType(_genericity)) : _instance));
                    method.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldarg_0));
                    method.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldloc, _variable));
                }
                _instance = (_instance as FieldDefinition).Relative();
            }
            var _state   = _type.Fields.Single(_Field => _Field.Name == "<>1__state").Relative();
            var _builder = _type.Fields.Single(_Field => _Field.Name == "<>t__builder").Relative();
            var _offset  = 0;
            var _begin   = _move.Body.Instructions[_offset];
            var _resume  = Instruction.Create(OpCodes.Ldarg_0);

            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldarg_0));
            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldfld, _state));
            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldc_I4_0));
            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Bge, _resume));
            if (_instance != null)
            {
                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldarg_0));
                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldfld, _advice.Relative()));
                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldarg_0));
                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldfld, _instance));
                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Instance <object>(Metadata <object> .Value)).GetGenericMethodDefinition()).MakeGenericMethod(_instance.FieldType))));
            }
            foreach (var _parameter in method.Parameters)
            {
                var _field = null as FieldReference;
                _field = _type.Fields.SingleOrDefault(_Field => _Field.Name == _parameter.Name);
                if (_field == null)
                {
                    _field = _type.Field(_parameter.Name, FieldAttributes.Public, _importation[_parameter.ParameterType]);
                    var _variable = method.Body.Variables.Single(_Variable => _Variable.VariableType.Resolve() == _type);
                    method.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Stfld, _genericity.Length > 0 ? new FieldReference(_field.Name, _parameter.ParameterType, _type.MakeGenericType(_genericity)) : _field));
                    method.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldarg, _parameter));
                    method.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldloc, _variable));
                }
                _field = (_field as FieldDefinition).Relative();
                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldarg_0));
                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldfld, _advice.Relative()));
                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldarg_0));
                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldflda, _field));
                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Argument <object>(ref Metadata <object> .Value)).GetGenericMethodDefinition()).MakeGenericMethod(_field.FieldType))));
            }
            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldarg_0));
            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldfld, _advice.Relative()));
            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Callvirt, _move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Begin()))));
            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Br_S, _begin));
            _move.Body.Instructions.Insert(_offset++, _resume);
            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldfld, _advice.Relative()));
            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Callvirt, _move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Continue()))));
            while (_offset < _move.Body.Instructions.Count)
            {
                var _instruction = _move.Body.Instructions[_offset];
                if (_instruction.OpCode == OpCodes.Callvirt)
                {
                    if (_instruction.Operand is MethodReference)
                    {
                        var _operand = _instruction.Operand as MethodReference;
                        if (_operand.Name == "GetAwaiter")
                        {
                            var _action = _move.Body.Instructions[_offset - 1].Operand as MethodReference;
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Stloc, _task));
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldarg_0));
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldfld, _advice.Relative()));
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldtoken, _action));
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldtoken, _action.DeclaringType));
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Call, _move.Module.Import(Metadata.Method(() => MethodInfo.GetMethodFromHandle(Metadata <RuntimeMethodHandle> .Value, Metadata <RuntimeTypeHandle> .Value))))); //TODO Virtuoze => cache it!
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldloc, _task));
                            if (_action.ReturnType.Resolve() == _move.Module.Import(typeof(Task)).Resolve())
                            {
                                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Callvirt, _move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Await(Metadata <MethodInfo> .Value, Metadata <Task> .Value)))));
                            }
                            else
                            {
                                _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Callvirt, _move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Await(Metadata <MethodInfo> .Value, Metadata <Task <object> > .Value)).GetGenericMethodDefinition()).MakeGenericMethod((_action.ReturnType as GenericInstanceType).GenericArguments[0])));
                            }
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldloc, _task));
                        }
                    }
                }
                else if (_instruction.OpCode == OpCodes.Call)
                {
                    if (_instruction.Operand is MethodReference)
                    {
                        var _operand = _instruction.Operand as MethodReference;
                        if (_operand.Name == "get_IsCompleted")
                        {
                            var _continue = _move.Body.Instructions[++_offset];
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Dup));
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Brfalse_S, _continue));
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldarg_0));
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Ldfld, _advice.Relative()));
                            _move.Body.Instructions.Insert(_offset++, Instruction.Create(OpCodes.Callvirt, _move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Continue()))));
                        }
                        else if (_operand.Name == "SetResult")
                        {
                            var _return = _type.Method("<Return>", MethodAttributes.Public);
                            if (_operand.HasParameters)
                            {
                                var _parameter = new ParameterDefinition("<Value>", ParameterAttributes.None, (_builder.FieldType as GenericInstanceType).GenericArguments[0]);
                                _return.Parameters.Add(_parameter);
                                var _exception = _return.Body.Variable <Exception>();
                                var _disposed  = _return.Body.Variable <bool>();
                                var _end       = Instruction.Create(OpCodes.Ret);
                                _return.Body.Emit(OpCodes.Ldarg_0);
                                _return.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                _return.Body.Emit(OpCodes.Ldarga_S, _parameter);
                                _return.Body.Emit(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Return(ref Metadata <object> .Value)).GetGenericMethodDefinition()).MakeGenericMethod(_parameter.ParameterType)));
                                _return.Body.Emit(OpCodes.Ldc_I4_1);
                                _return.Body.Emit(OpCodes.Stloc_1);
                                _return.Body.Emit(OpCodes.Ldarg_0);
                                _return.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                _return.Body.Emit(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IDisposable> .Method(_IDisposable => _IDisposable.Dispose()))));
                                _return.Body.Emit(OpCodes.Ldarg_0);
                                _return.Body.Emit(OpCodes.Ldflda, _builder);
                                _return.Body.Emit(OpCodes.Ldarg_1);
                                _return.Body.Emit(OpCodes.Call, _operand);
                                _return.Body.Emit(OpCodes.Ret);
                                var _catch = _return.Body.Emit(OpCodes.Stloc_0);
                                _return.Body.Emit(OpCodes.Ldloc_1);
                                using (_return.Body.False())
                                {
                                    _return.Body.Emit(OpCodes.Ldarg_0);
                                    _return.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                    _return.Body.Emit(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IDisposable> .Method(_IDisposable => _IDisposable.Dispose()))));
                                }
                                _return.Body.Emit(OpCodes.Ldarg_0);
                                _return.Body.Emit(OpCodes.Ldflda, _builder);
                                _return.Body.Emit(OpCodes.Ldloc_0);
                                var _method = _move.Module.Import(_builder.FieldType.Resolve().Methods.Single(_Method => _Method.Name == "SetException"));
                                _method.DeclaringType = _builder.FieldType;
                                _return.Body.Emit(OpCodes.Call, _method);
                                _return.Body.Emit(OpCodes.Ret);
                                _return.Body.Emit(OpCodes.Ret);
                                _return.Body.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch)
                                {
                                    TryStart     = _return.Body.Instructions[0],
                                    TryEnd       = _return.Body.Instructions[_catch],
                                    HandlerStart = _return.Body.Instructions[_catch],
                                    HandlerEnd   = _return.Body.Instructions[_return.Body.Instructions.Count - 1],
                                    CatchType    = _exception.VariableType
                                });
                                _return.Body.OptimizeMacros();
                                _instruction.Operand = _type.HasGenericParameters ? _return.MakeHostInstanceGeneric(_type.GenericParameters.ToArray()) : _return;
                                _move.Body.Instructions[_offset - 2].OpCode = OpCodes.Nop;
                            }
                            else
                            {
                                var _exception = _return.Body.Variable <Exception>();
                                var _disposed  = _return.Body.Variable <bool>();
                                var _end       = Instruction.Create(OpCodes.Ret);
                                _return.Body.Emit(OpCodes.Ldarg_0);
                                _return.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                _return.Body.Emit(OpCodes.Callvirt, _move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Return())));
                                _return.Body.Emit(OpCodes.Ldc_I4_1);
                                _return.Body.Emit(OpCodes.Stloc_1);
                                _return.Body.Emit(OpCodes.Ldarg_0);
                                _return.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                _return.Body.Emit(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IDisposable> .Method(_IDisposable => _IDisposable.Dispose()))));
                                _return.Body.Emit(OpCodes.Ldarg_0);
                                _return.Body.Emit(OpCodes.Ldflda, _builder);
                                _return.Body.Emit(OpCodes.Call, _operand);
                                _return.Body.Emit(OpCodes.Ret);
                                var _catch = _return.Body.Emit(OpCodes.Stloc_0);
                                _return.Body.Emit(OpCodes.Ldloc_1);
                                using (_return.Body.False())
                                {
                                    _return.Body.Emit(OpCodes.Ldarg_0);
                                    _return.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                    _return.Body.Emit(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IDisposable> .Method(_IDisposable => _IDisposable.Dispose()))));
                                }
                                _return.Body.Emit(OpCodes.Ldarg_0);
                                _return.Body.Emit(OpCodes.Ldflda, _builder);
                                _return.Body.Emit(OpCodes.Ldloc_0);
                                var _method = _move.Module.Import(_builder.FieldType.Resolve().Methods.Single(_Method => _Method.Name == "SetException"));
                                _method.DeclaringType = _builder.FieldType;
                                _return.Body.Emit(OpCodes.Call, _method);
                                _return.Body.Emit(OpCodes.Ret);
                                _return.Body.Emit(OpCodes.Ret);
                                _return.Body.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch)
                                {
                                    TryStart     = _return.Body.Instructions[0],
                                    TryEnd       = _return.Body.Instructions[_catch],
                                    HandlerStart = _return.Body.Instructions[_catch],
                                    HandlerEnd   = _return.Body.Instructions[_return.Body.Instructions.Count - 1],
                                    CatchType    = _exception.VariableType,
                                });
                                _return.Body.OptimizeMacros();
                                _instruction.Operand = _type.HasGenericParameters ? _return.MakeHostInstanceGeneric(_type.GenericParameters.ToArray()) : _return;
                                _move.Body.Instructions[_offset - 1].OpCode = OpCodes.Nop;
                            }
                        }
                        else if (_operand.Name == "SetException")
                        {
                            var _throw     = _type.Method("<Throw>", MethodAttributes.Public);
                            var _parameter = new ParameterDefinition("<Exception>", ParameterAttributes.None, _throw.Module.Import(typeof(Exception)));
                            _throw.Parameters.Add(_parameter);
                            if (_builder.FieldType.IsGenericInstance)
                            {
                                var _value = new VariableDefinition((_builder.FieldType as GenericInstanceType).GenericArguments[0]);
                                _throw.Body.Variables.Add(_value);
                                var _disposed = _throw.Body.Variable <bool>();
                                _throw.Body.Emit(OpCodes.Ldarg_0);
                                _throw.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                _throw.Body.Emit(OpCodes.Ldarg_S, _parameter);
                                _throw.Body.Emit(OpCodes.Ldloca_S, _value);
                                _throw.Body.Emit(OpCodes.Callvirt, _move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Throw(ref Metadata <Exception> .Value, ref Metadata <object> .Value)).GetGenericMethodDefinition()).MakeGenericMethod(_value.VariableType));
                                _throw.Body.Emit(OpCodes.Ldc_I4_1);
                                _throw.Body.Emit(OpCodes.Stloc_1);
                                _throw.Body.Emit(OpCodes.Ldarg_0);
                                _throw.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                _throw.Body.Emit(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IDisposable> .Method(_IDisposable => _IDisposable.Dispose()))));
                                _throw.Body.Emit(OpCodes.Ldarg_1);
                                using (_throw.Body.True())
                                {
                                    _throw.Body.Emit(OpCodes.Ldarg_0);
                                    _throw.Body.Emit(OpCodes.Ldflda, _builder);
                                    _throw.Body.Emit(OpCodes.Ldarg_1);
                                    _throw.Body.Emit(OpCodes.Call, _operand);
                                    _throw.Body.Emit(OpCodes.Ret);
                                }
                                _throw.Body.Emit(OpCodes.Ldarg_0);
                                _throw.Body.Emit(OpCodes.Ldflda, _builder);
                                _throw.Body.Emit(OpCodes.Ldloc_0);
                                var _method = _move.Module.Import(_move.Module.Import(_builder.FieldType.Resolve().Methods.Single(_Method => _Method.Name == "SetResult" && _Method.Parameters[0].ParameterType.IsGenericParameter)));
                                _method.DeclaringType = _builder.FieldType;
                                _throw.Body.Emit(OpCodes.Call, _method);
                                _throw.Body.Emit(OpCodes.Ret);
                                var _catch = _throw.Body.Emit(OpCodes.Starg, _parameter);
                                _throw.Body.Emit(OpCodes.Ldloc_1);
                                using (_throw.Body.False())
                                {
                                    _throw.Body.Emit(OpCodes.Ldarg_0);
                                    _throw.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                    _throw.Body.Emit(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IDisposable> .Method(_IDisposable => _IDisposable.Dispose()))));
                                }
                                _throw.Body.Emit(OpCodes.Ldarg_0);
                                _throw.Body.Emit(OpCodes.Ldflda, _builder);
                                _throw.Body.Emit(OpCodes.Ldarg_1);
                                _throw.Body.Emit(OpCodes.Call, _operand);
                                _throw.Body.Emit(OpCodes.Ret);
                                _throw.Body.Emit(OpCodes.Ret);
                                _throw.Body.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch)
                                {
                                    TryStart     = _throw.Body.Instructions[0],
                                    TryEnd       = _throw.Body.Instructions[_catch],
                                    HandlerStart = _throw.Body.Instructions[_catch],
                                    HandlerEnd   = _throw.Body.Instructions[_throw.Body.Instructions.Count - 1],
                                    CatchType    = _parameter.ParameterType,
                                });
                            }
                            else
                            {
                                var _disposed = _throw.Body.Variable <bool>();
                                _throw.Body.Emit(OpCodes.Ldarg_0);
                                _throw.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                _throw.Body.Emit(OpCodes.Ldarga_S, _parameter);
                                _throw.Body.Emit(OpCodes.Callvirt, _move.Module.Import(Metadata <IAdvice> .Method(_Advice => _Advice.Throw(ref Metadata <Exception> .Value))));
                                _throw.Body.Emit(OpCodes.Ldc_I4_1);
                                _throw.Body.Emit(OpCodes.Stloc_0);
                                _throw.Body.Emit(OpCodes.Ldarg_0);
                                _throw.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                _throw.Body.Emit(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IDisposable> .Method(_IDisposable => _IDisposable.Dispose()))));
                                _throw.Body.Emit(OpCodes.Ldarg_1);
                                using (_throw.Body.True())
                                {
                                    _throw.Body.Emit(OpCodes.Ldarg_0);
                                    _throw.Body.Emit(OpCodes.Ldflda, _builder);
                                    _throw.Body.Emit(OpCodes.Ldarg_1);
                                    _throw.Body.Emit(OpCodes.Call, _operand);
                                    _throw.Body.Emit(OpCodes.Ret);
                                }
                                _throw.Body.Emit(OpCodes.Ldarg_0);
                                _throw.Body.Emit(OpCodes.Ldflda, _builder);
                                var _method = _move.Module.Import(_builder.FieldType.Resolve().Methods.Single(_Method => _Method.Name == "SetResult" && _Method.Parameters.Count == 0));
                                _method.DeclaringType = _builder.FieldType;
                                _throw.Body.Emit(OpCodes.Call, _method);
                                _throw.Body.Emit(OpCodes.Ret);
                                var _catch = _throw.Body.Emit(OpCodes.Starg, _parameter);
                                _throw.Body.Emit(OpCodes.Ldloc_0);
                                using (_throw.Body.False())
                                {
                                    _throw.Body.Emit(OpCodes.Ldarg_0);
                                    _throw.Body.Emit(OpCodes.Ldfld, _advice.Relative());
                                    _throw.Body.Emit(OpCodes.Callvirt, _move.Module.Import(_move.Module.Import(Metadata <IDisposable> .Method(_IDisposable => _IDisposable.Dispose()))));
                                }
                                _throw.Body.Emit(OpCodes.Ldarg_0);
                                _throw.Body.Emit(OpCodes.Ldflda, _builder);
                                _throw.Body.Emit(OpCodes.Ldarg_1);
                                _throw.Body.Emit(OpCodes.Call, _operand);
                                _throw.Body.Emit(OpCodes.Ret);
                                _throw.Body.Emit(OpCodes.Ret);
                                _throw.Body.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch)
                                {
                                    TryStart     = _throw.Body.Instructions[0],
                                    TryEnd       = _throw.Body.Instructions[_catch],
                                    HandlerStart = _throw.Body.Instructions[_catch],
                                    HandlerEnd   = _throw.Body.Instructions[_throw.Body.Instructions.Count - 1],
                                    CatchType    = _parameter.ParameterType,
                                });
                            }
                            _throw.Body.OptimizeMacros();
                            _instruction.Operand = _type.HasGenericParameters ? _throw.MakeHostInstanceGeneric(_type.GenericParameters.ToArray()) : _throw;
                            _move.Body.Instructions[_offset - 2].OpCode = OpCodes.Nop;
                        }
                    }
                }
                _offset++;
            }
            _move.Body.OptimizeMacros();
        }
Пример #4
0
        private Instruction Copy(MethodDefinition source, MethodDefinition destination, Importation importation, Instruction instruction, Dictionary <Instruction, Instruction> dictionary)
        {
            if (instruction == null)
            {
                return(null);
            }
            if (dictionary.TryGetValue(instruction, out var _instruction))
            {
                return(_instruction);
            }
            var _operand = instruction.Operand;

            if (_operand == null)
            {
                _instruction = Instruction.Create(instruction.OpCode);
            }
            else if (_operand is ParameterDefinition)
            {
                _instruction = Instruction.Create(instruction.OpCode, destination.Parameter((_operand as ParameterDefinition).Name));
            }
            else if (_operand is VariableDefinition)
            {
                _instruction = Instruction.Create(instruction.OpCode, destination.Body.Variable((_operand as VariableDefinition).Index));
            }
            else if (_operand is FieldReference)
            {
                _instruction = Instruction.Create(instruction.OpCode, importation[_operand as FieldReference]);
            }
            else if (_operand is MethodReference)
            {
                _instruction = Instruction.Create(instruction.OpCode, importation[_operand as MethodReference]);
            }
            else if (_operand is TypeReference)
            {
                _instruction = Instruction.Create(instruction.OpCode, importation[_operand as TypeReference]);
            }
            else if (_operand is string)
            {
                _instruction = Instruction.Create(instruction.OpCode, _operand as string);
            }
            else if (_operand is sbyte)
            {
                _instruction = Instruction.Create(instruction.OpCode, (sbyte)_operand);
            }
            else if (_operand is long)
            {
                _instruction = Instruction.Create(instruction.OpCode, (long)_operand);
            }
            else if (_operand is int)
            {
                _instruction = Instruction.Create(instruction.OpCode, (int)_operand);
            }
            else if (_operand is float)
            {
                _instruction = Instruction.Create(instruction.OpCode, (float)_operand);
            }
            else if (_operand is double)
            {
                _instruction = Instruction.Create(instruction.OpCode, (double)_operand);
            }
            else if (_operand is Instruction)
            {
                _instruction = Instruction.Create(instruction.OpCode, this.Copy(source, destination, importation, _operand as Instruction, dictionary));
            }
            else if (_operand is Instruction[])
            {
                _instruction = Instruction.Create(instruction.OpCode, (_operand as Instruction[]).Select(_Instruction => this.Copy(source, destination, importation, _Instruction, dictionary)).ToArray());
            }
            else if (_operand is CallSite)
            {
                _instruction = Instruction.Create(instruction.OpCode, _operand as CallSite);
            }
            else
            {
                throw new NotSupportedException();
            }
            //var _sequence = instruction.SequencePoint;
            var _sequence = source.DebugInformation.GetSequencePoint(instruction);

            _instruction.Offset = instruction.Offset;
            if (_sequence != null)
            {
                destination.DebugInformation.SequencePoints.Add
                (
                    new SequencePoint(_instruction, _sequence.Document)
                {
                    StartLine   = _sequence.StartLine,
                    StartColumn = _sequence.StartColumn,
                    EndLine     = _sequence.EndLine,
                    EndColumn   = _sequence.EndColumn
                }
                );
                //_instruction.SequencePoint = new SequencePoint(_sequence.Document)
                //{
                //    StartLine = _sequence.StartLine,
                //    StartColumn = _sequence.StartColumn,
                //    EndLine = _sequence.EndLine,
                //    EndColumn = _sequence.EndColumn
                //};
            }
            dictionary.Add(instruction, _instruction);
            return(_instruction);
        }