/// <summary>
        /// if a variable defintion has a default value, it is effectively non-null.
        /// </summary>
        private GraphType effectiveType(GraphType varType, VariableDefinition varDef)
        {
            if (varDef.DefaultValue == null || varType is NonNullGraphType)
            {
                return varType;
            }

            var type = varType.GetType();
            var genericType = typeof(NonNullGraphType<>).MakeGenericType(type);

            return (GraphType)Activator.CreateInstance(genericType);
        }
示例#2
0
        /// <summary>
        /// Adds a call to SpendGas from the RuntimeObserver before the given instruction.
        /// </summary>
        private static void AddSpendGasMethodBeforeInstruction(ILProcessor il, ObserverReferences observer, VariableDefinition variable, CodeSegment codeSegment)
        {
            Instruction first       = codeSegment.Instructions.First();
            Instruction newFirst    = il.CreateLdlocBest(variable);
            long        segmentCost = (long)codeSegment.CalculateGasCost().Value;

            il.Body.SimplifyMacros();
            il.InsertBefore(first, newFirst);                                         // load observer
            il.InsertBefore(first, il.Create(OpCodes.Ldc_I8, (long)segmentCost));     // load gas amount
            il.InsertBefore(first, il.Create(OpCodes.Call, observer.SpendGasMethod)); // trigger method
            il.Body.OptimizeMacros();
        }
    int InsertVariableAssignmentFromCurrentValue(int index, PropertyDefinition property, VariableDefinition variable)
    {
        var getMethod = property.GetMethod.GetGeneric();

        instructions.Insert(index,
                            Instruction.Create(OpCodes.Ldarg_0),
                            CreateCall(getMethod),
                            Instruction.Create(OpCodes.Box, property.GetMethod.ReturnType),
                            Instruction.Create(OpCodes.Stloc, variable));

        return(index + 4);
    }
示例#4
0
        private void DealWithReturnValue(MethodDefinition method, ILWeaver weaver)
        {
            // What return behaviour do we use?
            switch (ReturnBehaviour)
            {
            case Hooks.ReturnBehaviour.Continue:
                // Just discard the return value
                weaver.Add(Instruction.Create(OpCodes.Pop));
                break;

            case Hooks.ReturnBehaviour.ExitWhenValidType:
                // Is there a return value or not?
                if (method.ReturnType.FullName == "System.Void")
                {
                    // If the hook returned something that was non-null, return
                    Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                    weaver.Add(Instruction.Create(OpCodes.Ret));
                }
                else
                {
                    // Create variable
                    VariableDefinition returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");

                    // Store the return value in it
                    weaver.Stloc(returnvar);
                    weaver.Ldloc(returnvar);

                    // If it's non-null and matches the return type, return it - else continue
                    weaver.Add(Instruction.Create(OpCodes.Isinst, method.ReturnType));
                    Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                    weaver.Ldloc(returnvar);
                    weaver.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType));
                    weaver.Add(Instruction.Create(OpCodes.Ret));
                }
                break;

            case Hooks.ReturnBehaviour.ModifyRefArg:
                // TODO: This
                weaver.Add(Instruction.Create(OpCodes.Pop));
                break;

            case Hooks.ReturnBehaviour.UseArgumentString:
                // Deal with it according to the retvalue of the arg string
                string retvalue;
                ParseArgumentString(out retvalue);
                if (!string.IsNullOrEmpty(retvalue))
                {
                    if (retvalue[0] == 'l' && retvalue.Length > 1)
                    {
                        int localindex;
                        if (int.TryParse(retvalue.Substring(1), out localindex))
                        {
                            // Create variable and get the target variable
                            VariableDefinition returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");
                            VariableDefinition targetvar = weaver.Variables[localindex];

                            // Store the return value in it
                            weaver.Stloc(returnvar);
                            weaver.Ldloc(returnvar);

                            // If it's non-null and matches the variable type, store it in the target variable
                            weaver.Add(Instruction.Create(OpCodes.Isinst, targetvar.VariableType));
                            Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                            weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                            weaver.Ldloc(returnvar);
                            weaver.Add(Instruction.Create(OpCodes.Unbox_Any, targetvar.VariableType));
                            weaver.Stloc(targetvar);

                            // Handled
                            return;
                        }
                    }
                    else if (retvalue == "ret" || retvalue == "return")
                    {
                        // Create variable
                        VariableDefinition returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");

                        // Store the return value in it
                        weaver.Stloc(returnvar);
                        weaver.Ldloc(returnvar);

                        // If it's non-null and matches the return type, return it - else continue
                        weaver.Add(Instruction.Create(OpCodes.Isinst, method.ReturnType));
                        Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                        weaver.Ldloc(returnvar);
                        weaver.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType));
                        weaver.Add(Instruction.Create(OpCodes.Ret));

                        // Handled
                        return;
                    }
                }

                // Not handled
                weaver.Add(Instruction.Create(OpCodes.Pop));
                break;
            }
        }
示例#5
0
    void AddRpc(TypeDefinition newType, MethodDefinition irpc)
    {
        var tag = irpc.CustomAttributes.FirstOrDefault(x => x.AttributeType.Name == "TAG");

        if (tag is null)
        {
            return;
        }
        var cmdx = tag.ConstructorArguments.First().Value;
        var cmd  = 0;

        switch (cmdx)
        {
        case Mono.Cecil.CustomAttributeArgument args:
            cmd = (int)args.Value;
            break;

        default:
            cmd = (int)cmdx;
            break;
        }


        var method = new MethodDefinition(irpc.Name, MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final, irpc.ReturnType);

        var il = method.Body.GetILProcessor();

        var parameters = irpc.Parameters;
        var paramTypes = ParamTypes(parameters.ToArray(), false);

        for (int i = 0; i < paramTypes.Length; i++)
        {
            method.Parameters.Add(new ParameterDefinition(parameters[i].Name, parameters[i].Attributes, paramTypes[i]));
        }

        if (irpc.ContainsGenericParameter)
        {
            throw new Exception($"not have generic parameter{irpc.FullName}");
        }

        var returntype = irpc.ReturnType;

        if (returntype.IsGenericInstance)
        {
            var genreturntype = returntype as GenericInstanceType;

            if (genreturntype.Name != "Task`1")
            {
                throw new Exception($"return type error:{genreturntype.FullName}");
            }

            if (genreturntype.GenericArguments[0].Name == "IResult")
            {
                ParametersArray args = new ParametersArray(this, il, paramTypes);

                il.Emit(OpCodes.Nop);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, obj);
                il.Emit(OpCodes.Ldc_I4, cmd);

                GenericArray <System.Object> argsArr = new GenericArray <System.Object>(this, il, ParamTypes(parameters.ToArray(), true).Length);

                for (int i = 0; i < parameters.Count; i++)
                {
                    // args[i] = argi;
                    if (!parameters[i].IsOut)
                    {
                        argsArr.BeginSet(i);
                        args.Get(i);
                        argsArr.EndSet(parameters[i].ParameterType);
                    }
                }
                argsArr.Load();

                var asyncAction = obj.FieldType.Resolve().Methods.First(p => p.Name == "AsyncFunc");

                il.Emit(OpCodes.Callvirt, ModuleDefinition.ImportReference(asyncAction));
                il.Emit(OpCodes.Ret);
                newType.Methods.Add(method);
            }
            else
            {
                ParametersArray args = new ParametersArray(this, il, paramTypes);

                il.Emit(OpCodes.Nop);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, obj);
                il.Emit(OpCodes.Ldc_I4, cmd);

                GenericArray <System.Object> argsArr = new GenericArray <System.Object>(this, il, ParamTypes(parameters.ToArray(), true).Length);

                for (int i = 0; i < parameters.Count; i++)
                {
                    // args[i] = argi;
                    if (!parameters[i].IsOut)
                    {
                        argsArr.BeginSet(i);
                        args.Get(i);
                        argsArr.EndSet(parameters[i].ParameterType);
                    }
                }
                argsArr.Load();

                var genericAsyncFunc = obj.FieldType.Resolve().Methods.First(p => p.Name == "AsyncFunc" && p.CallingConvention == MethodCallingConvention.Generic);

                il.Emit(OpCodes.Callvirt, ModuleDefinition.ImportReference(MakeGenericInstanceMethod(genericAsyncFunc, genreturntype.GenericArguments.ToArray())));
                il.Emit(OpCodes.Ret);
                newType.Methods.Add(method);
            }
        }
        else if (returntype.FullName == "System.Void")
        {
            ParametersArray args = new ParametersArray(this, il, paramTypes);

            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, obj);
            il.Emit(OpCodes.Ldc_I4, cmd);

            GenericArray <System.Object> argsArr = new GenericArray <System.Object>(this, il, ParamTypes(parameters.ToArray(), true).Length);

            for (int i = 0; i < parameters.Count; i++)
            {
                // args[i] = argi;
                if (!parameters[i].IsOut)
                {
                    argsArr.BeginSet(i);
                    args.Get(i);
                    argsArr.EndSet(parameters[i].ParameterType);
                }
            }
            argsArr.Load();

            var Action = obj.FieldType.Resolve().Methods.First(p => p.Name == "Action");

            il.Emit(OpCodes.Callvirt, ModuleDefinition.ImportReference(Action));
            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Ret);
            newType.Methods.Add(method);
        }
        else if (returntype.FullName == "System.Threading.Tasks.Task")
        {
            ParametersArray args = new ParametersArray(this, il, paramTypes);

            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, obj);
            il.Emit(OpCodes.Ldc_I4, cmd);

            GenericArray <System.Object> argsArr = new GenericArray <System.Object>(this, il, ParamTypes(parameters.ToArray(), true).Length);

            for (int i = 0; i < parameters.Count; i++)
            {
                // args[i] = argi;
                if (!parameters[i].IsOut)
                {
                    argsArr.BeginSet(i);
                    args.Get(i);
                    argsArr.EndSet(parameters[i].ParameterType);
                }
            }
            argsArr.Load();

            var asyncAction = obj.FieldType.Resolve().Methods.First(p => p.Name == "AsyncAction");

            il.Emit(OpCodes.Callvirt, ModuleDefinition.ImportReference(asyncAction));
            il.Emit(OpCodes.Ret);
            newType.Methods.Add(method);
        }
        else
        {
            ParametersArray args = new ParametersArray(this, il, paramTypes);
            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, obj);
            il.Emit(OpCodes.Ldc_I4, cmd);

            il.Emit(OpCodes.Ldtoken, irpc.ReturnType);
            var ptype = ModuleDefinition.ImportReference(GetMethodInfo.GetTypeofHandler());
            il.Emit(OpCodes.Call, ptype);


            GenericArray <object> argsArr = new GenericArray <object>(this, il, ParamTypes(parameters.ToArray(), true).Length);

            for (int i = 0; i < parameters.Count; i++)
            {
                // args[i] = argi;
                if (!parameters[i].IsOut)
                {
                    argsArr.BeginSet(i);
                    args.Get(i);
                    argsArr.EndSet(parameters[i].ParameterType);
                }
            }
            argsArr.Load();

            var func = obj.FieldType.Resolve().Methods.First(p => p.Name == "Func");
            il.Emit(OpCodes.Callvirt, ModuleDefinition.ImportReference(func));

            var res = new VariableDefinition(irpc.ReturnType);
            method.Body.Variables.Add(res);
            Convert(il, ModuleDefinition.ImportReference(typeof(System.Object)), irpc.ReturnType, false);
            il.Emit(OpCodes.Stloc, res);
            il.Emit(OpCodes.Ldloc, res);

            il.Emit(OpCodes.Ret);
            newType.Methods.Add(method);
        }
    }
        void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker, MethodDefinition deserialize)
        {
            // check for Hook function
            if (!SyncVarProcessor.CheckForHookFunction(netBehaviourSubclass, syncVar, out MethodDefinition foundMethod))
            {
                return;
            }

            // [SyncVar] GameObject/NetworkIdentity?

            /*
             * Generates code like:
             *  uint num = reader.ReadPackedUInt32();
             *  if (!SyncVarEqual(num, ref q))
             *  {
             *      OnSetQ(GetSyncVarGameObject(num, ref q));
             *  }
             *  ___qNetId = num;
             */
            if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName ||
                syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
            {
                // GameObject/NetworkIdentity SyncVar:
                //   OnSerialize sends writer.Write(go);
                //   OnDeserialize reads to __netId manually so we can use
                //     lookups in the getter (so it still works if objects
                //     move in and out of range repeatedly)
                FieldDefinition netIdField = syncVarNetIds[syncVar];

                VariableDefinition tmpValue = new VariableDefinition(Weaver.uint32Type);
                deserialize.Body.Variables.Add(tmpValue);

                // read id and store in a local variable
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                serWorker.Append(serWorker.Create(OpCodes.Call, Readers.GetReadFunc(Weaver.uint32Type)));
                serWorker.Append(serWorker.Create(OpCodes.Stloc, tmpValue));

                if (foundMethod != null)
                {
                    // call Hook(this.GetSyncVarGameObject/NetworkIdentity(reader.ReadPackedUInt32()))
                    // because we send/receive the netID, not the GameObject/NetworkIdentity
                    // but only if SyncVar changed. otherwise a client would
                    // get hook calls for all initial values, even if they
                    // didn't change from the default values on the client.
                    // see also: https://github.com/vis2k/Mirror/issues/1278

                    // IMPORTANT: for GameObjects/NetworkIdentities we usually
                    //            use SyncVarGameObjectEqual to compare equality.
                    //            in this case however, we can just use
                    //            SyncVarEqual with the two uint netIds.
                    //            => this is easier weaver code because we don't
                    //               have to get the GameObject/NetworkIdentity
                    //               from the uint netId
                    //            => this is faster because we void one
                    //               GetComponent call for GameObjects to get
                    //               their NetworkIdentity when comparing.

                    // Generates: if (!SyncVarEqual);
                    Instruction syncVarEqualLabel = serWorker.Create(OpCodes.Nop);

                    // 'this.' for 'this.SyncVarEqual'
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    // 'tmpValue'
                    serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
                    // 'ref this.__netId'
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldflda, netIdField));
                    // call the function
                    GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(Weaver.syncVarEqualReference);
                    syncVarEqualGm.GenericArguments.Add(netIdField.FieldType);
                    serWorker.Append(serWorker.Create(OpCodes.Call, syncVarEqualGm));
                    serWorker.Append(serWorker.Create(OpCodes.Brtrue, syncVarEqualLabel));

                    // call the hook
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // this.
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldflda, syncVar));
                    if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName)
                    {
                        serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarGameObjectReference));
                    }
                    else if (syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
                    {
                        serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarNetworkIdentityReference));
                    }
                    serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));

                    // Generates: end if (!SyncVarEqual);
                    serWorker.Append(syncVarEqualLabel);
                }
                // set the netid field
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
                serWorker.Append(serWorker.Create(OpCodes.Stfld, netIdField));
            }
            // [SyncVar] int/float/struct/etc.?

            /*
             * Generates code like:
             *  int num = reader.ReadPackedInt32();
             *  if (!SyncVarEqual(num, ref a))
             *  {
             *      OnSetA(num);
             *  }
             *  Networka = num;
             */
            else
            {
                MethodReference readFunc = Readers.GetReadFunc(syncVar.FieldType);
                if (readFunc == null)
                {
                    Weaver.Error($"{syncVar} has unsupported type. Use a supported Mirror type instead");
                    return;
                }
                VariableDefinition tmpValue = new VariableDefinition(syncVar.FieldType);
                deserialize.Body.Variables.Add(tmpValue);

                // read value and put it in a local variable
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
                serWorker.Append(serWorker.Create(OpCodes.Stloc, tmpValue));

                if (foundMethod != null)
                {
                    // call hook
                    // but only if SyncVar changed. otherwise a client would
                    // get hook calls for all initial values, even if they
                    // didn't change from the default values on the client.
                    // see also: https://github.com/vis2k/Mirror/issues/1278

                    // Generates: if (!SyncVarEqual);
                    Instruction syncVarEqualLabel = serWorker.Create(OpCodes.Nop);

                    // 'this.' for 'this.SyncVarEqual'
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    // 'tmpValue'
                    serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
                    // 'ref this.syncVar'
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldflda, syncVar));
                    // call the function
                    GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(Weaver.syncVarEqualReference);
                    syncVarEqualGm.GenericArguments.Add(syncVar.FieldType);
                    serWorker.Append(serWorker.Create(OpCodes.Call, syncVarEqualGm));
                    serWorker.Append(serWorker.Create(OpCodes.Brtrue, syncVarEqualLabel));

                    // call the hook
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
                    serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));

                    // Generates: end if (!SyncVarEqual);
                    serWorker.Append(syncVarEqualLabel);
                }
                // set the property
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
                serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar));
            }
        }
 private static IList <Instruction> GetSaveRetvalInstructions(ILProcessor processor, VariableDefinition retvalVariableDefinition)
 {
     return(retvalVariableDefinition == null || processor.Body.Instructions.All(i => i.OpCode != OpCodes.Ret) ?
            new Instruction[0] : new[] { processor.Create(OpCodes.Stloc_S, retvalVariableDefinition) });
 }
示例#8
0
        public void SetVariableFromOutsideProgram()
        {
            s_output = new List<string>();
            TextReader programString = File.OpenText("code50.txt");

            // print(MAGIC_NUMBER)

            FunctionDefinition[] funcs = new FunctionDefinition[1];
            funcs[0] = new FunctionDefinition("void",
                                              "print",
                                              new string[] { "string" },
                                              new string[] { "text" },
                                              new ExternalFunctionCreator.OnFunctionCall(print),
                                                FunctionDocumentation.Default()
            );

            VariableDefinition[] vars = new VariableDefinition[3];
            vars[0] = new VariableDefinition("MAGIC_NUMBER", new ReturnValue(43));
            vars[1] = new VariableDefinition("MAGIC_BOOL", new ReturnValue(true));
            vars[2] = new VariableDefinition("MAGIC_STRING", new ReturnValue("hej"));

            SprakRunner program = new SprakRunner(programString, funcs, vars);

            program.run();

            Assert.AreEqual(0, program.getRuntimeErrorHandler().getErrors().Count);
               	Assert.AreEqual("43", s_output[0]);
             	Assert.AreEqual("true", s_output[1]);
            Assert.AreEqual("hej", s_output[2]);
        }
        public static IEnumerable <Instruction> PushParentObjectsArray(this INode node, ILContext context)
        {
            var module = context.Body.Method.Module;

            var   nodes = new List <IElementNode>();
            INode n     = node.Parent;

            while (n != null)
            {
                var en = n as IElementNode;
                if (en != null && context.Variables.ContainsKey(en))
                {
                    nodes.Add(en);
                }
                n = n.Parent;
            }

            if (nodes.Count == 0 && context.ParentContextValues == null)
            {
                yield return(Instruction.Create(OpCodes.Ldnull));

                yield break;
            }

            if (nodes.Count == 0)
            {
                yield return(Instruction.Create(OpCodes.Ldarg_0));

                yield return(Instruction.Create(OpCodes.Ldfld, context.ParentContextValues));

                yield break;
            }

            //Compute parent object length
            if (context.ParentContextValues != null)
            {
                yield return(Instruction.Create(OpCodes.Ldarg_0));

                yield return(Instruction.Create(OpCodes.Ldfld, context.ParentContextValues));

                yield return(Instruction.Create(OpCodes.Ldlen));

                yield return(Instruction.Create(OpCodes.Conv_I4));
            }
            else
            {
                yield return(Instruction.Create(OpCodes.Ldc_I4_0));
            }
            var parentObjectLength = new VariableDefinition(module.TypeSystem.Int32);

            context.Body.Variables.Add(parentObjectLength);
            yield return(Instruction.Create(OpCodes.Stloc, parentObjectLength));

            //Create the final array
            yield return(Instruction.Create(OpCodes.Ldloc, parentObjectLength));

            yield return(Instruction.Create(OpCodes.Ldc_I4, nodes.Count));

            yield return(Instruction.Create(OpCodes.Add));

            yield return(Instruction.Create(OpCodes.Newarr, module.TypeSystem.Object));

            var finalArray = new VariableDefinition(module.ImportReferenceCached(typeof(object[])));

            context.Body.Variables.Add(finalArray);
            yield return(Instruction.Create(OpCodes.Stloc, finalArray));

            //Copy original array to final
            if (context.ParentContextValues != null)
            {
                yield return(Instruction.Create(OpCodes.Ldarg_0));

                yield return(Instruction.Create(OpCodes.Ldfld, context.ParentContextValues)); //sourceArray

                yield return(Instruction.Create(OpCodes.Ldc_I4_0));                           //sourceIndex

                yield return(Instruction.Create(OpCodes.Ldloc, finalArray));                  //destinationArray

                yield return(Instruction.Create(OpCodes.Ldc_I4, nodes.Count));                //destinationIndex

                yield return(Instruction.Create(OpCodes.Ldloc, parentObjectLength));          //length

                var arrayCopy =
                    module.ImportReferenceCached(typeof(Array))
                    .ResolveCached()
                    .Methods.First(
                        md =>
                        md.Name == "Copy" && md.Parameters.Count == 5 &&
                        md.Parameters[1].ParameterType.FullName == module.TypeSystem.Int32.FullName);
                yield return(Instruction.Create(OpCodes.Call, module.ImportReference(arrayCopy)));
            }

            //Add nodes to array
            yield return(Instruction.Create(OpCodes.Ldloc, finalArray));

            if (nodes.Count > 0)
            {
                for (var i = 0; i < nodes.Count; i++)
                {
                    var en = nodes[i];
                    yield return(Instruction.Create(OpCodes.Dup));

                    yield return(Instruction.Create(OpCodes.Ldc_I4, i));

                    yield return(Instruction.Create(OpCodes.Ldloc, context.Variables[en]));

                    if (context.Variables[en].VariableType.IsValueType)
                    {
                        yield return(Instruction.Create(OpCodes.Box, module.ImportReference(context.Variables[en].VariableType)));
                    }
                    yield return(Instruction.Create(OpCodes.Stelem_Ref));
                }
            }
        }
        public static IEnumerable <Instruction> PushConvertedValue(this ValueNode node, ILContext context,
                                                                   TypeReference targetTypeRef, TypeReference typeConverter, IEnumerable <Instruction> pushServiceProvider,
                                                                   bool boxValueTypes, bool unboxValueTypes)
        {
            var module = context.Body.Method.Module;
            var str    = (string)node.Value;

            //If the TypeConverter has a ProvideCompiledAttribute that can be resolved, shortcut this
            var  compiledConverterName = typeConverter?.GetCustomAttribute(module.ImportReferenceCached(typeof(ProvideCompiledAttribute)))?.ConstructorArguments?.First().Value as string;
            Type compiledConverterType;

            if (compiledConverterName != null && (compiledConverterType = Type.GetType(compiledConverterName)) != null)
            {
                var compiledConverter = Activator.CreateInstance(compiledConverterType);
                var converter         = typeof(ICompiledTypeConverter).GetMethods().FirstOrDefault(md => md.Name == "ConvertFromString");
                var instructions      = (IEnumerable <Instruction>)converter.Invoke(compiledConverter, new object[] {
                    node.Value as string, context, node as BaseNode
                });
                foreach (var i in instructions)
                {
                    yield return(i);
                }
                if (targetTypeRef.IsValueType && boxValueTypes)
                {
                    yield return(Instruction.Create(OpCodes.Box, module.ImportReference(targetTypeRef)));
                }
                yield break;
            }

            //If there's a [TypeConverter], use it
            if (typeConverter != null)
            {
                var isExtendedConverter  = typeConverter.ImplementsInterface(module.ImportReferenceCached(typeof(IExtendedTypeConverter)));
                var typeConverterCtor    = typeConverter.ResolveCached().Methods.Single(md => md.IsConstructor && md.Parameters.Count == 0 && !md.IsStatic);
                var typeConverterCtorRef = module.ImportReference(typeConverterCtor);
                var convertFromInvariantStringDefinition = isExtendedConverter
                                        ? module.ImportReferenceCached(typeof(IExtendedTypeConverter))
                                                           .ResolveCached()
                                                           .Methods.FirstOrDefault(md => md.Name == "ConvertFromInvariantString" && md.Parameters.Count == 2)
                                        : typeConverter.ResolveCached()
                                                           .AllMethods()
                                                           .FirstOrDefault(md => md.Name == "ConvertFromInvariantString" && md.Parameters.Count == 1);
                var convertFromInvariantStringReference = module.ImportReference(convertFromInvariantStringDefinition);

                yield return(Instruction.Create(OpCodes.Newobj, typeConverterCtorRef));

                yield return(Instruction.Create(OpCodes.Ldstr, node.Value as string));

                if (isExtendedConverter)
                {
                    foreach (var instruction in pushServiceProvider)
                    {
                        yield return(instruction);
                    }
                }

                yield return(Instruction.Create(OpCodes.Callvirt, convertFromInvariantStringReference));

                if (targetTypeRef.IsValueType && unboxValueTypes)
                {
                    yield return(Instruction.Create(OpCodes.Unbox_Any, module.ImportReference(targetTypeRef)));
                }

                //ConvertFrom returns an object, no need to Box
                yield break;
            }
            var             originalTypeRef = targetTypeRef;
            var             isNullable      = false;
            MethodReference nullableCtor    = null;

            if (targetTypeRef.ResolveCached().FullName == "System.Nullable`1")
            {
                var nullableTypeRef = targetTypeRef;
                targetTypeRef = ((GenericInstanceType)targetTypeRef).GenericArguments[0];
                isNullable    = true;
                nullableCtor  = originalTypeRef.GetMethods(md => md.IsConstructor && md.Parameters.Count == 1, module).Single().Item1;
                nullableCtor  = nullableCtor.ResolveGenericParameters(nullableTypeRef, module);
            }

            var implicitOperator = module.TypeSystem.String.GetImplicitOperatorTo(targetTypeRef, module);

            //Obvious Built-in conversions
            if (targetTypeRef.ResolveCached().BaseType != null && targetTypeRef.ResolveCached().BaseType.FullName == "System.Enum")
            {
                yield return(PushParsedEnum(targetTypeRef, str, node));
            }
            else if (targetTypeRef.FullName == "System.Char")
            {
                yield return(Instruction.Create(OpCodes.Ldc_I4, Char.Parse(str)));
            }
            else if (targetTypeRef.FullName == "System.SByte")
            {
                yield return(Instruction.Create(OpCodes.Ldc_I4, SByte.Parse(str, CultureInfo.InvariantCulture)));
            }
            else if (targetTypeRef.FullName == "System.Int16")
            {
                yield return(Instruction.Create(OpCodes.Ldc_I4, Int16.Parse(str, CultureInfo.InvariantCulture)));
            }
            else if (targetTypeRef.FullName == "System.Int32")
            {
                yield return(Instruction.Create(OpCodes.Ldc_I4, Int32.Parse(str, CultureInfo.InvariantCulture)));
            }
            else if (targetTypeRef.FullName == "System.Int64")
            {
                yield return(Instruction.Create(OpCodes.Ldc_I8, Int64.Parse(str, CultureInfo.InvariantCulture)));
            }
            else if (targetTypeRef.FullName == "System.Byte")
            {
                yield return(Instruction.Create(OpCodes.Ldc_I4, Byte.Parse(str, CultureInfo.InvariantCulture)));
            }
            else if (targetTypeRef.FullName == "System.UInt16")
            {
                yield return(Instruction.Create(OpCodes.Ldc_I4, unchecked ((int)UInt16.Parse(str, CultureInfo.InvariantCulture))));
            }
            else if (targetTypeRef.FullName == "System.UInt32")
            {
                yield return(Instruction.Create(OpCodes.Ldc_I4, UInt32.Parse(str, CultureInfo.InvariantCulture)));
            }
            else if (targetTypeRef.FullName == "System.UInt64")
            {
                yield return(Instruction.Create(OpCodes.Ldc_I8, unchecked ((long)UInt64.Parse(str, CultureInfo.InvariantCulture))));
            }
            else if (targetTypeRef.FullName == "System.Single")
            {
                yield return(Instruction.Create(OpCodes.Ldc_R4, Single.Parse(str, CultureInfo.InvariantCulture)));
            }
            else if (targetTypeRef.FullName == "System.Double")
            {
                yield return(Instruction.Create(OpCodes.Ldc_R8, Double.Parse(str, CultureInfo.InvariantCulture)));
            }
            else if (targetTypeRef.FullName == "System.Boolean")
            {
                if (Boolean.Parse(str))
                {
                    yield return(Instruction.Create(OpCodes.Ldc_I4_1));
                }
                else
                {
                    yield return(Instruction.Create(OpCodes.Ldc_I4_0));
                }
            }
            else if (targetTypeRef.FullName == "System.TimeSpan")
            {
                var ts           = TimeSpan.Parse(str, CultureInfo.InvariantCulture);
                var ticks        = ts.Ticks;
                var timeSpanCtor =
                    module.ImportReferenceCached(typeof(TimeSpan))
                    .ResolveCached()
                    .Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1);
                var timeSpanCtorRef = module.ImportReference(timeSpanCtor);

                yield return(Instruction.Create(OpCodes.Ldc_I8, ticks));

                yield return(Instruction.Create(OpCodes.Newobj, timeSpanCtorRef));
            }
            else if (targetTypeRef.FullName == "System.DateTime")
            {
                var dt           = DateTime.Parse(str, CultureInfo.InvariantCulture);
                var ticks        = dt.Ticks;
                var dateTimeCtor =
                    module.ImportReferenceCached(typeof(DateTime))
                    .ResolveCached()
                    .Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1);
                var dateTimeCtorRef = module.ImportReference(dateTimeCtor);

                yield return(Instruction.Create(OpCodes.Ldc_I8, ticks));

                yield return(Instruction.Create(OpCodes.Newobj, dateTimeCtorRef));
            }
            else if (targetTypeRef.FullName == "System.String" && str.StartsWith("{}", StringComparison.Ordinal))
            {
                yield return(Instruction.Create(OpCodes.Ldstr, str.Substring(2)));
            }
            else if (targetTypeRef.FullName == "System.String")
            {
                yield return(Instruction.Create(OpCodes.Ldstr, str));
            }
            else if (targetTypeRef.FullName == "System.Object")
            {
                yield return(Instruction.Create(OpCodes.Ldstr, str));
            }
            else if (targetTypeRef.FullName == "System.Decimal")
            {
                decimal outdecimal;
                if (decimal.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out outdecimal))
                {
                    var vardef = new VariableDefinition(context.Body.Method.Module.ImportReferenceCached(typeof(decimal)));
                    context.Body.Variables.Add(vardef);
                    //Use an extra temp var so we can push the value to the stack, just like other cases
                    //					IL_0003:  ldstr "adecimal"
                    //					IL_0008:  ldc.i4.s 0x6f
                    //					IL_000a:  call class [mscorlib]System.Globalization.CultureInfo class [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture()
                    //					IL_000f:  ldloca.s 0
                    //					IL_0011:  call bool valuetype [mscorlib]System.Decimal::TryParse(string, valuetype [mscorlib]System.Globalization.NumberStyles, class [mscorlib]System.IFormatProvider, [out] valuetype [mscorlib]System.Decimal&)
                    //					IL_0016:  pop
                    yield return(Instruction.Create(OpCodes.Ldstr, str));

                    yield return(Instruction.Create(OpCodes.Ldc_I4, 0x6f));                    //NumberStyles.Number

                    var getInvariantInfo =
                        context.Body.Method.Module.ImportReferenceCached(typeof(CultureInfo))
                        .ResolveCached()
                        .Properties.FirstOrDefault(pd => pd.Name == "InvariantCulture")
                        .GetMethod;
                    var getInvariant = context.Body.Method.Module.ImportReference(getInvariantInfo);
                    yield return(Instruction.Create(OpCodes.Call, getInvariant));

                    yield return(Instruction.Create(OpCodes.Ldloca, vardef));

                    var tryParseInfo =
                        context.Body.Method.Module.ImportReferenceCached(typeof(decimal))
                        .ResolveCached()
                        .Methods.FirstOrDefault(md => md.Name == "TryParse" && md.Parameters.Count == 4);
                    var tryParse = context.Body.Method.Module.ImportReference(tryParseInfo);
                    yield return(Instruction.Create(OpCodes.Call, tryParse));

                    yield return(Instruction.Create(OpCodes.Pop));

                    yield return(Instruction.Create(OpCodes.Ldloc, vardef));
                }
                else
                {
                    yield return(Instruction.Create(OpCodes.Ldc_I4_0));

                    var decimalctorinfo =
                        context.Body.Method.Module.ImportReferenceCached(typeof(decimal))
                        .ResolveCached()
                        .Methods.FirstOrDefault(
                            md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType.FullName == "System.Int32");
                    var decimalctor = context.Body.Method.Module.ImportReference(decimalctorinfo);
                    yield return(Instruction.Create(OpCodes.Newobj, decimalctor));
                }
            }
            else if (implicitOperator != null)
            {
                yield return(Instruction.Create(OpCodes.Ldstr, node.Value as string));

                yield return(Instruction.Create(OpCodes.Call, module.ImportReference(implicitOperator)));
            }
            else
            {
                yield return(Instruction.Create(OpCodes.Ldnull));
            }

            if (isNullable)
            {
                yield return(Instruction.Create(OpCodes.Newobj, module.ImportReference(nullableCtor)));
            }
            if (originalTypeRef.IsValueType && boxValueTypes)
            {
                yield return(Instruction.Create(OpCodes.Box, module.ImportReference(originalTypeRef)));
            }
        }
示例#11
0
 private static IEnumerable <Instruction> GetAttributeInstanceInstructions(ILProcessor processor, MethodReference method, ICustomAttribute attribute,
                                                                           VariableDefinition attributeVariableDefinition, VariableDefinition methodVariableDefinition,
                                                                           MethodReference getCustomAttributesRef, MethodReference getTypeFromHandleRef, MethodReference getMethodFromHandleRef)
 {
     // Get the attribute instance (this gets a new instance for each invocation.
     // Might be better to create a static class that keeps a track of a single
     // instance per method and we just refer to that)
     return(new List <Instruction>
     {
         processor.Create(OpCodes.Ldtoken, method),
         processor.Create(OpCodes.Ldtoken, method.DeclaringType),
         processor.Create(OpCodes.Call, getMethodFromHandleRef),                 // Push method onto the stack, GetMethodFromHandle, result on stack
         processor.Create(OpCodes.Stloc_S, methodVariableDefinition),            // Store method in __fody$method
         processor.Create(OpCodes.Ldloc_S, methodVariableDefinition),
         processor.Create(OpCodes.Ldtoken, attribute.AttributeType),
         processor.Create(OpCodes.Call, getTypeFromHandleRef),                   // Push method + attribute onto the stack, GetTypeFromHandle, result on stack
         processor.Create(OpCodes.Ldc_I4_0),
         processor.Create(OpCodes.Callvirt, getCustomAttributesRef),             // Push false onto the stack (result still on stack), GetCustomAttributes
         processor.Create(OpCodes.Ldc_I4_0),
         processor.Create(OpCodes.Ldelem_Ref),                                   // Get 0th index from result
         processor.Create(OpCodes.Castclass, attribute.AttributeType),
         processor.Create(OpCodes.Stloc_S, attributeVariableDefinition)          // Cast to attribute stor in __fody$attribute
     });
 }
示例#12
0
        public void Decorate(MethodDefinition method, CustomAttribute attribute)
        {
            method.Body.InitLocals = true;

            var getMethodFromHandleRef = referenceFinder.GetMethodReference(typeof(MethodBase), md => md.Name == "GetMethodFromHandle" && md.Parameters.Count == 2);
            var getCustomAttributesRef = referenceFinder.GetMethodReference(typeof(MemberInfo), md => md.Name == "GetCustomAttributes" && md.Parameters.Count == 2);
            var getTypeFromHandleRef   = referenceFinder.GetMethodReference(typeof(Type), md => md.Name == "GetTypeFromHandle");

            var methodBaseTypeRef = referenceFinder.GetTypeReference(typeof(MethodBase));
            var exceptionTypeRef  = referenceFinder.GetTypeReference(typeof(Exception));

            var methodVariableDefinition                = AddVariableDefinition(method, "__fody$method", methodBaseTypeRef);
            var attributeVariableDefinition             = AddVariableDefinition(method, "__fody$attribute", attribute.AttributeType);
            var exceptionVariableDefinition             = AddVariableDefinition(method, "__fody$exception", exceptionTypeRef);
            VariableDefinition retvalVariableDefinition = null;

            if (method.ReturnType.FullName != "System.Void")
            {
                retvalVariableDefinition = AddVariableDefinition(method, "__fody$retval", method.ReturnType);
            }

            var onEntryMethodRef     = referenceFinder.GetMethodReference(attribute.AttributeType, md => md.Name == "OnEntry");
            var onExitMethodRef      = referenceFinder.GetMethodReference(attribute.AttributeType, md => md.Name == "OnExit");
            var onExceptionMethodRef = referenceFinder.GetMethodReference(attribute.AttributeType, md => md.Name == "OnException");

            var processor = method.Body.GetILProcessor();
            var methodBodyFirstInstruction = method.Body.Instructions.First();

            if (method.IsConstructor)
            {
                methodBodyFirstInstruction = method.Body.Instructions.First(i => i.OpCode == OpCodes.Call).Next;
            }

            var getAttributeInstanceInstructions = GetAttributeInstanceInstructions(processor, method, attribute, attributeVariableDefinition, methodVariableDefinition, getCustomAttributesRef, getTypeFromHandleRef, getMethodFromHandleRef);
            var callOnEntryInstructions          = GetCallOnEntryInstructions(processor, attributeVariableDefinition, methodVariableDefinition, onEntryMethodRef);
            var saveRetvalInstructions           = GetSaveRetvalInstructions(processor, retvalVariableDefinition);
            var callOnExitInstructions           = GetCallOnExitInstructions(processor, attributeVariableDefinition, methodVariableDefinition, onExitMethodRef);
            var methodBodyReturnInstructions     = GetMethodBodyReturnInstructions(processor, retvalVariableDefinition);
            var methodBodyReturnInstruction      = methodBodyReturnInstructions.First();
            var tryCatchLeaveInstructions        = GetTryCatchLeaveInstructions(processor, methodBodyReturnInstruction);
            var catchHandlerInstructions         = GetCatchHandlerInstructions(processor, attributeVariableDefinition, exceptionVariableDefinition, methodVariableDefinition, onExceptionMethodRef);

            ReplaceRetInstructions(processor, saveRetvalInstructions.Concat(callOnExitInstructions).First());

            processor.InsertBefore(methodBodyFirstInstruction, getAttributeInstanceInstructions);
            processor.InsertBefore(methodBodyFirstInstruction, callOnEntryInstructions);

            processor.InsertAfter(method.Body.Instructions.Last(), methodBodyReturnInstructions);

            processor.InsertBefore(methodBodyReturnInstruction, saveRetvalInstructions);
            processor.InsertBefore(methodBodyReturnInstruction, callOnExitInstructions);
            processor.InsertBefore(methodBodyReturnInstruction, tryCatchLeaveInstructions);

            processor.InsertBefore(methodBodyReturnInstruction, catchHandlerInstructions);

            method.Body.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch)
            {
                CatchType    = exceptionTypeRef,
                TryStart     = methodBodyFirstInstruction,
                TryEnd       = tryCatchLeaveInstructions.Last().Next,
                HandlerStart = catchHandlerInstructions.First(),
                HandlerEnd   = catchHandlerInstructions.Last().Next
            });
        }
示例#13
0
        private static IList <Instruction> GetMethodBodyReturnInstructions(ILProcessor processor, VariableDefinition retvalVariableDefinition)
        {
            var instructions = new List <Instruction>();

            if (retvalVariableDefinition != null)
            {
                instructions.Add(processor.Create(OpCodes.Ldloc_S, retvalVariableDefinition));
            }
            instructions.Add(processor.Create(OpCodes.Ret));
            return(instructions);
        }
示例#14
0
 private static IList <Instruction> GetCallOnExitInstructions(ILProcessor processor, VariableDefinition attributeVariableDefinition, VariableDefinition methodVariableDefinition, MethodReference onExitMethodRef)
 {
     // Call __fody$attribute.OnExit("{methodName}")
     return(new List <Instruction>
     {
         processor.Create(OpCodes.Ldloc_S, attributeVariableDefinition),
         processor.Create(OpCodes.Ldloc_S, methodVariableDefinition),
         processor.Create(OpCodes.Callvirt, onExitMethodRef)
     });
 }
示例#15
0
 /// <summary>
 /// add a parametername from the current context to a context which has names
 /// </summary>
 /// <returns></returns>
 bool AddVariable(string name, IDataType datatype, LiteralContext literal, RuleContext context)
 {
     RuleContext root = GetRootContext(context, typeof(SelectStatementBlockContext));
     VariableDefinition def = new VariableDefinition(name: name, datatype: datatype, defaultvalue: literal.XPTreeNode);
     if (root != null)
     {
         if (!((SelectStatementBlockContext)root).names.ContainsKey(name))
         {
             ((SelectStatementBlockContext)root).names.Add(name, def);
             ((StatementBlock)((SelectStatementBlockContext)root).XPTreeNode).AddNewVariable(name, datatype);
         }
         else { this.NotifyErrorListeners(String.Format(Messages.RCM_1, name, "SelectStatementBlock")); return false; }
         return true;
     }
     this.NotifyErrorListeners(String.Format(Messages.RCM_2, name, "SelectStatementBlock"));
     return false;
 }
示例#16
0
        public void ComplexDotNotation()
        {
            s_output = new List<string> ();

            StringReader programString = new StringReader(
                @"var a = 10
                  number inc(number x)
                     return x + 5
                  end
                  (inc(a*a)).foo(inc(1), inc(2), [inc(3), inc(4)])"
            );

            FunctionDefinition[] funcs = new FunctionDefinition[1];
            funcs[0] = new FunctionDefinition("void",
                "RemoteFunctionCall",
                new string[] { "number", "string", "array" },
                new string[] { "id", "functionName", "args" },
                new ExternalFunctionCreator.OnFunctionCall(ExternalFunctionCall),
                FunctionDocumentation.Default()
            );

            VariableDefinition[] vars = new VariableDefinition[] {};

            SprakRunner program = new SprakRunner(programString, funcs, vars);

            program.run();

            Assert.AreEqual (1, s_output.Count);
            Assert.AreEqual ("id = 105, functionName = foo, args = [6, 7, [8, 9]]", s_output[0]);
            Assert.AreEqual(0, program.getCompileTimeErrorHandler().getErrors().Count);
        }
示例#17
0
 /// <summary>
 /// Variable ctor
 /// </summary>
 public AstILVariable(string name, XTypeReference type, VariableDefinition originalVariable)
 {
     Name = name;
     Type = type;
     this.originalVariable = originalVariable;
 }
示例#18
0
        public object GetVariableValue(Document document, ISchema schema, VariableDefinition variable, object input)
        {
            var type = variable.Type.GraphTypeFromType(schema);

            if (IsValidValue(schema, type, input))
            {
                if (input == null)
                {
                    if (variable.DefaultValue != null)
                    {
                        return ValueFromAst(variable.DefaultValue);
                    }
                }
                var coercedValue = CoerceValue(schema, type, input.AstFromValue(schema, type));
                return coercedValue;
            }

            if (input == null)
            {
                var error2 = new ExecutionError("Variable '${0}' of required type '{1}' was not provided.".ToFormat(variable.Name, type.Name ?? variable.Type.FullName()));
                error2.AddLocation(variable, document);
                throw error2;
            }

            var error = new ExecutionError("Variable '${0}' expected value of type '{1}'.".ToFormat(variable.Name, type?.Name ?? variable.Type.FullName()));
            error.AddLocation(variable, document);
            throw error;
        }
示例#19
0
        private void EmitGetMethodReplacement(CilWorker IL, IMethodSignature hostMethod, VariableDefinition provider)
        {
            // var replacement = MethodReplacementProvider.GetReplacement(info);
            IL.Emit(OpCodes.Ldloc, provider);

            // Push the host instance
            var pushInstance = hostMethod.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull);

            IL.Append(pushInstance);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Callvirt, _getReplacement);
            IL.Emit(OpCodes.Stloc, _replacement);
        }
        void GenerateSerialization()
        {
            Weaver.DLog(netBehaviourSubclass, "  GenerateSerialization");

            foreach (MethodDefinition m in netBehaviourSubclass.Methods)
            {
                if (m.Name == "OnSerialize")
                {
                    return;
                }
            }

            if (syncVars.Count == 0)
            {
                // no synvars,  no need for custom OnSerialize
                return;
            }

            MethodDefinition serialize = new MethodDefinition("OnSerialize",
                                                              MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                                                              Weaver.boolType);

            serialize.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkWriterType)));
            serialize.Parameters.Add(new ParameterDefinition("forceAll", ParameterAttributes.None, Weaver.boolType));
            ILProcessor serWorker = serialize.Body.GetILProcessor();

            serialize.Body.InitLocals = true;

            // loc_0,  this local variable is to determine if any variable was dirty
            VariableDefinition dirtyLocal = new VariableDefinition(Weaver.boolType);

            serialize.Body.Variables.Add(dirtyLocal);

            MethodReference baseSerialize = Resolvers.ResolveMethodInParents(netBehaviourSubclass.BaseType, Weaver.CurrentAssembly, "OnSerialize");

            if (baseSerialize != null)
            {
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // writer
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // forceAll
                serWorker.Append(serWorker.Create(OpCodes.Call, baseSerialize));
                serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); // set dirtyLocal to result of base.OnSerialize()
            }

            // Generates: if (forceAll);
            Instruction initialStateLabel = serWorker.Create(OpCodes.Nop);

            serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // forceAll
            serWorker.Append(serWorker.Create(OpCodes.Brfalse, initialStateLabel));

            foreach (FieldDefinition syncVar in syncVars)
            {
                // Generates a writer call for each sync variable
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // writer
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // this
                serWorker.Append(serWorker.Create(OpCodes.Ldfld, syncVar));
                MethodReference writeFunc = Writers.GetWriteFunc(syncVar.FieldType);
                if (writeFunc != null)
                {
                    serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
                }
                else
                {
                    Weaver.Error($"{syncVar} has unsupported type. Use a supported Mirror type instead");
                    return;
                }
            }

            // always return true if forceAll

            // Generates: return true
            serWorker.Append(serWorker.Create(OpCodes.Ldc_I4_1));
            serWorker.Append(serWorker.Create(OpCodes.Ret));

            // Generates: end if (forceAll);
            serWorker.Append(initialStateLabel);

            // write dirty bits before the data fields
            // Generates: writer.WritePackedUInt64 (base.get_syncVarDirtyBits ());
            serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // writer
            serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
            serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference));
            serWorker.Append(serWorker.Create(OpCodes.Call, Writers.GetWriteFunc(Weaver.uint64Type)));

            // generate a writer call for any dirty variable in this class

            // start at number of syncvars in parent
            int dirtyBit = Weaver.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName);

            foreach (FieldDefinition syncVar in syncVars)
            {
                Instruction varLabel = serWorker.Create(OpCodes.Nop);

                // Generates: if ((base.get_syncVarDirtyBits() & 1uL) != 0uL)
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));                // base
                serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference));
                serWorker.Append(serWorker.Create(OpCodes.Ldc_I8, 1L << dirtyBit)); // 8 bytes = long
                serWorker.Append(serWorker.Create(OpCodes.And));
                serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel));

                // Generates a call to the writer for that field
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // writer
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
                serWorker.Append(serWorker.Create(OpCodes.Ldfld, syncVar));

                MethodReference writeFunc = Writers.GetWriteFunc(syncVar.FieldType);
                if (writeFunc != null)
                {
                    serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
                }
                else
                {
                    Weaver.Error($"{syncVar} has unsupported type. Use a supported Mirror type instead");
                    return;
                }

                // something was dirty
                serWorker.Append(serWorker.Create(OpCodes.Ldc_I4_1));
                serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); // set dirtyLocal to true

                serWorker.Append(varLabel);
                dirtyBit += 1;
            }

            if (Weaver.GenerateLogErrors)
            {
                serWorker.Append(serWorker.Create(OpCodes.Ldstr, "Injected Serialize " + netBehaviourSubclass.Name));
                serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.logErrorReference));
            }

            // generate: return dirtyLocal
            serWorker.Append(serWorker.Create(OpCodes.Ldloc_0));
            serWorker.Append(serWorker.Create(OpCodes.Ret));
            netBehaviourSubclass.Methods.Add(serialize);
        }
示例#21
0
        public static void ErrantAddFizzBuzzBehavior(TypeDefinition printerType)
        {
            // This method emits a valid CIL method but
            // it contains a logical error that cannot be directly debugged

            var printMethod = (from m in printerType.Methods
                               where m.Name == "Print"
                               select m).First();

            var module   = printerType.Module;
            var boolType = module.Import(typeof(bool));

            var body = printMethod.Body;

            body.InitLocals = true;

            var isFizz = new VariableDefinition(boolType);
            var isBuzz = new VariableDefinition(boolType);

            body.Variables.Add(isFizz);
            body.Variables.Add(isBuzz);

            // Remove the original instructions altogether
            body.Instructions.Clear();
            var processor = body.GetILProcessor();

            // var isFizz = num % 3 == 0;
            EmitIsDivisibleBy(processor, 3, isFizz);

            // var isBuzz = num % 5 == 0;
            EmitIsDivisibleBy(processor, 5, isBuzz);

            processor.EmitWriteLine("--Begin--");

            var endLabel        = processor.Create(OpCodes.Nop);
            var printFizzOrBuzz = processor.Create(OpCodes.Nop);

            // if (isFizz && isBuzz) {
            processor.Emit(OpCodes.Ldloc, isFizz);
            processor.Emit(OpCodes.Ldloc, isBuzz);
            processor.Emit(OpCodes.And);

            processor.EmitWriteLine("--Marker--");

            processor.Emit(OpCodes.Brfalse, printFizzOrBuzz);

            // Console.WriteLine("FizzBuzz");
            processor.EmitWriteLine("FizzBuzz");

            // return;
            processor.Emit(OpCodes.Br, endLabel);
            // }

            processor.Append(printFizzOrBuzz);

            var skipFizz = processor.Create(OpCodes.Nop);

            processor.Emit(OpCodes.Ldloc, isFizz);
            processor.Emit(OpCodes.Brfalse, skipFizz);

            processor.EmitWriteLine("Fizz");
            processor.Append(skipFizz);

            var skipBuzz = processor.Create(OpCodes.Nop);

            processor.Emit(OpCodes.Ldloc, isBuzz);
            processor.Emit(OpCodes.Brfalse, skipFizz);

            processor.EmitWriteLine("Buzz");
            processor.Append(skipBuzz);

            processor.Append(endLabel);

            processor.EmitWriteLine("--End--");
            processor.Emit(OpCodes.Ret);
        }
        void GenerateDeSerialization()
        {
            Weaver.DLog(netBehaviourSubclass, "  GenerateDeSerialization");

            foreach (MethodDefinition m in netBehaviourSubclass.Methods)
            {
                if (m.Name == "OnDeserialize")
                {
                    return;
                }
            }

            if (syncVars.Count == 0)
            {
                // no synvars,  no need for custom OnDeserialize
                return;
            }

            MethodDefinition serialize = new MethodDefinition("OnDeserialize",
                                                              MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                                                              Weaver.voidType);

            serialize.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
            serialize.Parameters.Add(new ParameterDefinition("initialState", ParameterAttributes.None, Weaver.boolType));
            ILProcessor serWorker = serialize.Body.GetILProcessor();

            // setup local for dirty bits
            serialize.Body.InitLocals = true;
            VariableDefinition dirtyBitsLocal = new VariableDefinition(Weaver.int64Type);

            serialize.Body.Variables.Add(dirtyBitsLocal);

            MethodReference baseDeserialize = Resolvers.ResolveMethodInParents(netBehaviourSubclass.BaseType, Weaver.CurrentAssembly, "OnDeserialize");

            if (baseDeserialize != null)
            {
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // reader
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // initialState
                serWorker.Append(serWorker.Create(OpCodes.Call, baseDeserialize));
            }

            // Generates: if (initialState);
            Instruction initialStateLabel = serWorker.Create(OpCodes.Nop);

            serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
            serWorker.Append(serWorker.Create(OpCodes.Brfalse, initialStateLabel));

            foreach (FieldDefinition syncVar in syncVars)
            {
                DeserializeField(syncVar, serWorker, serialize);
            }

            serWorker.Append(serWorker.Create(OpCodes.Ret));

            // Generates: end if (initialState);
            serWorker.Append(initialStateLabel);

            // get dirty bits
            serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
            serWorker.Append(serWorker.Create(OpCodes.Call, Readers.GetReadFunc(Weaver.uint64Type)));
            serWorker.Append(serWorker.Create(OpCodes.Stloc_0));

            // conditionally read each syncvar
            int dirtyBit = Weaver.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName); // start at number of syncvars in parent

            foreach (FieldDefinition syncVar in syncVars)
            {
                Instruction varLabel = serWorker.Create(OpCodes.Nop);

                // check if dirty bit is set
                serWorker.Append(serWorker.Create(OpCodes.Ldloc_0));
                serWorker.Append(serWorker.Create(OpCodes.Ldc_I8, 1L << dirtyBit));
                serWorker.Append(serWorker.Create(OpCodes.And));
                serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel));

                DeserializeField(syncVar, serWorker, serialize);

                serWorker.Append(varLabel);
                dirtyBit += 1;
            }

            if (Weaver.GenerateLogErrors)
            {
                serWorker.Append(serWorker.Create(OpCodes.Ldstr, "Injected Deserialize " + netBehaviourSubclass.Name));
                serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.logErrorReference));
            }

            serWorker.Append(serWorker.Create(OpCodes.Ret));
            netBehaviourSubclass.Methods.Add(serialize);
        }
示例#23
0
    IEnumerable <Instruction> CreateParametersArrayInstructions(ILProcessor processor, MethodDefinition method, VariableDefinition arrayVariable /*parameters*/)
    {
        var createArray = new List <Instruction>
        {
            processor.Create(OpCodes.Ldc_I4, method.Parameters.Count),      //method.Parameters.Count
            processor.Create(OpCodes.Newarr, (TypeReference)objectTypeRef), // new object[method.Parameters.Count]
            processor.Create(OpCodes.Stloc, arrayVariable)                  // var objArray = new object[method.Parameters.Count]
        };

        foreach (var p in method.Parameters)
        {
            createArray.AddRange(IlHelper.ProcessParam(p, arrayVariable));
        }

        return(createArray);
    }
示例#24
0
 public FlagsInfo(VariableDefinition local, uint value, int offset)
 {
     Local  = local;
     Value  = value;
     Offset = offset;
 }
示例#25
0
    IEnumerable <Instruction> GetAttributeInstanceInstructions(
        ILProcessor processor,
        ICustomAttribute attribute,
        MethodDefinition method,
        VariableDefinition attributeVariableDefinition,
        VariableDefinition methodVariableDefinition,
        bool explicitMatch)
    {
        var getMethodFromHandleRef = referenceFinder.GetMethodReference(methodBaseTypeRef, md => md.Name == "GetMethodFromHandle" &&
                                                                        md.Parameters.Count == 2);

        var getTypeof = referenceFinder.GetMethodReference(systemTypeRef, md => md.Name == "GetTypeFromHandle");
        var ctor      = referenceFinder.GetMethodReference(activatorTypeRef, md => md.Name == "CreateInstance" &&
                                                           md.Parameters.Count == 1);

        var getCustomAttrs = referenceFinder.GetMethodReference(attributeTypeRef,
                                                                md => md.Name == "GetCustomAttributes" &&
                                                                md.Parameters.Count == 2 &&
                                                                md.Parameters[0].ParameterType.FullName == typeof(MemberInfo).FullName &&
                                                                md.Parameters[1].ParameterType.FullName == typeof(Type).FullName);

        /*
         *  // Code size       23 (0x17)
         *    .maxstack  1
         *    .locals init ([0] class SimpleTest.IntersectMethodsMarkedByAttribute i)
         *    IL_0000:  nop
         *    IL_0001:  ldtoken    SimpleTest.IntersectMethodsMarkedByAttribute
         *    IL_0006:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
         *    IL_000b:  call       object [mscorlib]System.Activator::CreateInstance(class [mscorlib]System.Type)
         *    IL_0010:  castclass  SimpleTest.IntersectMethodsMarkedByAttribute
         *    IL_0015:  stloc.0
         *    IL_0016:  ret
         */

        var oInstructions = new List <Instruction>
        {
            processor.Create(OpCodes.Nop),

            processor.Create(OpCodes.Ldtoken, method),
            processor.Create(OpCodes.Ldtoken, method.DeclaringType),
            processor.Create(OpCodes.Call, getMethodFromHandleRef),     // Push method onto the stack, GetMethodFromHandle, result on stack
            processor.Create(OpCodes.Stloc, methodVariableDefinition),  // Store method in __fody$method

            processor.Create(OpCodes.Nop),
        };

        if (explicitMatch &&
            method.CustomAttributes.Any(m => m.AttributeType.Equals(attribute.AttributeType)))
        {
            oInstructions.AddRange(new[]
            {
                processor.Create(OpCodes.Ldloc, methodVariableDefinition),
                processor.Create(OpCodes.Ldtoken, attribute.AttributeType),
                processor.Create(OpCodes.Call, getTypeof),
                processor.Create(OpCodes.Call, getCustomAttrs),

                processor.Create(OpCodes.Dup),
                processor.Create(OpCodes.Ldlen),
                processor.Create(OpCodes.Ldc_I4_1),
                processor.Create(OpCodes.Sub),

//                      processor.Create(OpCodes.Ldc_I4_0),
                processor.Create(OpCodes.Ldelem_Ref),

                processor.Create(OpCodes.Castclass, attribute.AttributeType),
                processor.Create(OpCodes.Stloc, attributeVariableDefinition),
            });
        }
        else if (explicitMatch &&
                 method.DeclaringType.CustomAttributes.Any(m => m.AttributeType.Equals(attribute.AttributeType)))
        {
            oInstructions.AddRange(new[]
            {
                processor.Create(OpCodes.Ldtoken, method.DeclaringType),
                processor.Create(OpCodes.Call, getTypeof),
                processor.Create(OpCodes.Ldtoken, attribute.AttributeType),
                processor.Create(OpCodes.Call, getTypeof),
                processor.Create(OpCodes.Call, getCustomAttrs),

                processor.Create(OpCodes.Dup),
                processor.Create(OpCodes.Ldlen),
                processor.Create(OpCodes.Ldc_I4_1),
                processor.Create(OpCodes.Sub),

                processor.Create(OpCodes.Ldelem_Ref),

                processor.Create(OpCodes.Castclass, attribute.AttributeType),
                processor.Create(OpCodes.Stloc, attributeVariableDefinition),
            });
        }
        else
        {
            oInstructions.AddRange(new[]
            {
                processor.Create(OpCodes.Ldtoken, attribute.AttributeType),
                processor.Create(OpCodes.Call, getTypeof),
                processor.Create(OpCodes.Call, ctor),
                processor.Create(OpCodes.Castclass, attribute.AttributeType),
                processor.Create(OpCodes.Stloc, attributeVariableDefinition),
            });
        }

        return(oInstructions);
    }
示例#26
0
        private void PushArgsArray(MethodDefinition method, ILWeaver weaver)
        {
            // Are we going to use arguments?
            if (ArgumentBehaviour == Hooks.ArgumentBehaviour.None)
            {
                // Push null and we're done
                weaver.Add(Instruction.Create(OpCodes.Ldnull));
                return;
            }

            // Create array variable
            VariableDefinition argsvar = weaver.AddVariable(new ArrayType(method.Module.TypeSystem.Object), "args");

            // Are we using the argument string?
            if (ArgumentBehaviour == Hooks.ArgumentBehaviour.UseArgumentString)
            {
                string   retvalue;
                string[] args = ParseArgumentString(out retvalue);
                if (args == null)
                {
                    // Silently fail, but at least produce valid IL
                    weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    return;
                }

                // Create the array
                weaver.Add(ILWeaver.Ldc_I4_n(args.Length));
                weaver.Add(Instruction.Create(OpCodes.Newarr, method.Module.TypeSystem.Object));
                weaver.Stloc(argsvar);

                // Populate it
                for (int i = 0; i < args.Length; i++)
                {
                    weaver.Ldloc(argsvar);
                    string arg = args[i].ToLowerInvariant();
                    weaver.Add(ILWeaver.Ldc_I4_n(i));
                    if (string.IsNullOrEmpty(arg))
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    }
                    else if (arg == "this")
                    {
                        if (method.IsStatic)
                        {
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        }
                        else
                        {
                            weaver.Add(ILWeaver.Ldarg_n(0));
                        }
                    }
                    else if (arg[0] == 'p' || arg[0] == 'a')
                    {
                        int index;
                        if (int.TryParse(arg.Substring(1), out index))
                        {
                            ParameterDefinition pdef;

                            /*if (method.IsStatic)
                             *  pdef = method.Parameters[index];
                             * else
                             *  pdef = method.Parameters[index + 1];*/
                            pdef = method.Parameters[index];

                            weaver.Add(ILWeaver.Ldarg_n(pdef.Sequence));
                            if (pdef.ParameterType.IsByReference)
                            {
                                weaver.Add(Instruction.Create(OpCodes.Ldobj, pdef.ParameterType));
                                weaver.Add(Instruction.Create(OpCodes.Box, pdef.ParameterType));
                            }
                            else if (pdef.ParameterType.IsValueType)
                            {
                                weaver.Add(Instruction.Create(OpCodes.Box, pdef.ParameterType));
                            }
                        }
                        else
                        {
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        }
                    }
                    else if (arg[0] == 'l' || arg[0] == 'v')
                    {
                        int index;
                        if (int.TryParse(arg.Substring(1), out index))
                        {
                            VariableDefinition vdef = weaver.Variables[index];

                            if (vdef.VariableType.IsByReference)
                            {
                                weaver.Add(Instruction.Create(OpCodes.Ldobj, vdef.VariableType));
                                weaver.Add(Instruction.Create(OpCodes.Box, vdef.VariableType));
                            }
                            else if (vdef.VariableType.IsValueType)
                            {
                                weaver.Add(Instruction.Create(OpCodes.Box, vdef.VariableType));
                            }

                            weaver.Ldloc(vdef);
                        }
                        else
                        {
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        }
                    }
                    else
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    }


                    weaver.Add(Instruction.Create(OpCodes.Stelem_Ref));
                }
            }
            else
            {
                // Figure out what we're doing
                bool includeargs = ArgumentBehaviour == Hooks.ArgumentBehaviour.All || ArgumentBehaviour == Hooks.ArgumentBehaviour.JustParams;
                bool includethis = ArgumentBehaviour == Hooks.ArgumentBehaviour.All || ArgumentBehaviour == Hooks.ArgumentBehaviour.JustThis;
                if (method.IsStatic)
                {
                    includethis = false;
                }

                // Work out what arguments we're going to transmit
                List <ParameterDefinition> args = new List <ParameterDefinition>();
                if (includeargs)
                {
                    for (int i = 0; i < method.Parameters.Count; i++)
                    {
                        ParameterDefinition arg = method.Parameters[i];
                        if (!arg.IsOut)
                        {
                            args.Add(arg);
                        }
                    }
                }

                // Load arg count, create array, store
                if (includethis)
                {
                    weaver.Add(ILWeaver.Ldc_I4_n(args.Count + 1));
                }
                else
                {
                    weaver.Add(ILWeaver.Ldc_I4_n(args.Count));
                }
                weaver.Add(Instruction.Create(OpCodes.Newarr, method.Module.TypeSystem.Object));
                weaver.Stloc(argsvar);

                // Include this
                if (includethis)
                {
                    weaver.Ldloc(argsvar);
                    weaver.Add(ILWeaver.Ldc_I4_n(0));
                    weaver.Add(ILWeaver.Ldarg_n(0));
                    weaver.Add(Instruction.Create(OpCodes.Stelem_Ref));
                }

                // Loop each argument
                for (int i = 0; i < args.Count; i++)
                {
                    // Load array, load index load arg, store in array
                    ParameterDefinition arg = args[i];
                    weaver.Ldloc(argsvar);
                    if (includethis)
                    {
                        weaver.Add(ILWeaver.Ldc_I4_n(i + 1));
                    }
                    else
                    {
                        weaver.Add(ILWeaver.Ldc_I4_n(i));
                    }
                    weaver.Add(ILWeaver.Ldarg_n(args[i].Sequence));
                    if (arg.ParameterType.IsByReference)
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldobj, arg.ParameterType));
                        weaver.Add(Instruction.Create(OpCodes.Box, arg.ParameterType));
                    }
                    else if (arg.ParameterType.IsValueType)
                    {
                        weaver.Add(Instruction.Create(OpCodes.Box, arg.ParameterType));
                    }
                    weaver.Add(Instruction.Create(OpCodes.Stelem_Ref));
                }
            }

            // Finally, load it
            weaver.Ldloc(argsvar);
        }
示例#27
0
    public void Decorate(TypeDefinition type, MethodDefinition method, CustomAttribute attribute, bool explicitMatch)
    {
        method.Body.InitLocals = true;

        var parametersArrayTypeRef = new ArrayType(objectTypeRef);

        var initMethodRef1 = referenceFinder.GetOptionalMethodReference(attribute.AttributeType,
                                                                        md => md.Name == "Init" && md.Parameters.Count == 1 && md.Parameters[0].ParameterType.FullName == typeof(MethodBase).FullName);
        var initMethodRef2 = referenceFinder.GetOptionalMethodReference(attribute.AttributeType,
                                                                        md => md.Name == "Init" && md.Parameters.Count == 2 && md.Parameters[0].ParameterType.FullName == typeof(object).FullName);
        var initMethodRef3 = referenceFinder.GetOptionalMethodReference(attribute.AttributeType,
                                                                        md => md.Name == "Init" && md.Parameters.Count == 3);

        var needBypassRef0 = referenceFinder.GetOptionalMethodReference(attribute.AttributeType,
                                                                        md => md.Name == "NeedBypass" && md.Parameters.Count == 0);

        var onEntryMethodRef0 = referenceFinder.GetOptionalMethodReference(attribute.AttributeType,
                                                                           md => md.Name == "OnEntry" && md.Parameters.Count == 0);

        var onExitMethodRef0 = referenceFinder.GetOptionalMethodReference(attribute.AttributeType,
                                                                          md => md.Name == "OnExit" && md.Parameters.Count == 0);
        var onExitMethodRef1 = referenceFinder.GetOptionalMethodReference(attribute.AttributeType,
                                                                          md => md.Name == "OnExit" && md.Parameters.Count == 1 && md.Parameters[0].ParameterType.FullName == typeof(object).FullName);

        var alterRetvalRef1 = referenceFinder.GetOptionalMethodReference(attribute.AttributeType,
                                                                         md => md.Name == "AlterRetval" && md.Parameters.Count == 1);

        var onExceptionMethodRef = referenceFinder.GetOptionalMethodReference(attribute.AttributeType,
                                                                              md => md.Name == "OnException" && md.Parameters.Count == 1 && md.Parameters[0].ParameterType.FullName == typeof(Exception).FullName);

        var taskContinuationMethodRef = referenceFinder.GetOptionalMethodReference(attribute.AttributeType, md => md.Name == "OnTaskContinuation");

        var attributeVariableDefinition = AddVariableDefinition(method, "__fody$attribute", attribute.AttributeType);
        var methodVariableDefinition    = AddVariableDefinition(method, "__fody$method", methodBaseTypeRef);

        VariableDefinition exceptionVariableDefinition  = null;
        VariableDefinition parametersVariableDefinition = null;
        VariableDefinition retvalVariableDefinition     = null;

        if (initMethodRef3 != null)
        {
            parametersVariableDefinition = AddVariableDefinition(method, "__fody$parameters", parametersArrayTypeRef);
        }

        if (onExceptionMethodRef != null)
        {
            exceptionVariableDefinition = AddVariableDefinition(method, "__fody$exception", exceptionTypeRef);
        }

        var needCatchReturn = null != (onExitMethodRef1 ?? onExitMethodRef0 ?? onExceptionMethodRef ?? taskContinuationMethodRef ?? alterRetvalRef1 ?? needBypassRef0);

        if (method.ReturnType.FullName != "System.Void" && needCatchReturn)
        {
            retvalVariableDefinition = AddVariableDefinition(method, "__fody$retval", method.ReturnType);
        }

        method.Body.SimplifyMacros();

        var processor = method.Body.GetILProcessor();
        var methodBodyFirstInstruction = method.Body.Instructions.First();

        if (method.IsConstructor)
        {
            var callBase = method.Body.Instructions.FirstOrDefault(
                i => i.OpCode == OpCodes.Call &&
                (i.Operand is MethodReference reference) &&
                reference.Resolve().IsConstructor);

            methodBodyFirstInstruction = callBase?.Next ?? methodBodyFirstInstruction;
        }

        var initAttributeVariable = GetAttributeInstanceInstructions(processor,
                                                                     attribute,
                                                                     method,
                                                                     attributeVariableDefinition,
                                                                     methodVariableDefinition,
                                                                     explicitMatch);

        List <Instruction> callInitInstructions = null;
        List <Instruction> createParametersArrayInstructions = null;
        List <Instruction> callOnEntryInstructions           = null;
        List <Instruction> saveRetvalInstructions            = null;
        List <Instruction> callOnExitInstructions            = null;

        if (parametersVariableDefinition != null)
        {
            createParametersArrayInstructions = CreateParametersArrayInstructions(
                processor,
                method,
                parametersVariableDefinition).ToList();
        }

        var initMethodRef = initMethodRef3 ?? initMethodRef2 ?? initMethodRef1;

        if (initMethodRef != null)
        {
            callInitInstructions = GetCallInitInstructions(
                processor,
                type,
                method,
                attributeVariableDefinition,
                methodVariableDefinition,
                parametersVariableDefinition,
                initMethodRef).ToList();
        }

        if (onEntryMethodRef0 != null)
        {
            callOnEntryInstructions = GetCallOnEntryInstructions(processor, attributeVariableDefinition, onEntryMethodRef0).ToList();
        }

        if (retvalVariableDefinition != null)
        {
            saveRetvalInstructions = GetSaveRetvalInstructions(processor, retvalVariableDefinition).ToList();
        }

        if (retvalVariableDefinition != null && onExitMethodRef1 != null)
        {
            callOnExitInstructions = GetCallOnExitInstructions(processor, attributeVariableDefinition, onExitMethodRef1, retvalVariableDefinition).ToList();
        }
        else if (onExitMethodRef0 != null)
        {
            callOnExitInstructions = GetCallOnExitInstructions(processor, attributeVariableDefinition, onExitMethodRef0).ToList();
        }

        List <Instruction> methodBodyReturnInstructions = null;
        List <Instruction> tryCatchLeaveInstructions    = null;
        List <Instruction> catchHandlerInstructions     = null;
        List <Instruction> bypassInstructions           = null;

        if (needCatchReturn)
        {
            methodBodyReturnInstructions = GetMethodBodyReturnInstructions(processor, attributeVariableDefinition, retvalVariableDefinition, alterRetvalRef1).ToList();

            if (needBypassRef0 != null)
            {
                bypassInstructions = GetBypassInstructions(processor, attributeVariableDefinition, needBypassRef0, methodBodyReturnInstructions.First()).ToList();
            }

            if (onExceptionMethodRef != null)
            {
                tryCatchLeaveInstructions = GetTryCatchLeaveInstructions(processor, methodBodyReturnInstructions.First()).ToList();
                catchHandlerInstructions  = GetCatchHandlerInstructions(processor,
                                                                        attributeVariableDefinition, exceptionVariableDefinition, onExceptionMethodRef);
            }

            ReplaceRetInstructions(processor, saveRetvalInstructions?.FirstOrDefault() ?? callOnExitInstructions?.FirstOrDefault() ?? methodBodyReturnInstructions.First());
        }

        processor.InsertBefore(methodBodyFirstInstruction, initAttributeVariable);

        if (createParametersArrayInstructions != null)
        {
            processor.InsertBefore(methodBodyFirstInstruction, createParametersArrayInstructions);
        }

        if (callInitInstructions != null)
        {
            processor.InsertBefore(methodBodyFirstInstruction, callInitInstructions);
        }

        if (bypassInstructions != null)
        {
            processor.InsertBefore(methodBodyFirstInstruction, bypassInstructions);
        }

        if (callOnEntryInstructions != null)
        {
            processor.InsertBefore(methodBodyFirstInstruction, callOnEntryInstructions);
        }

        if (methodBodyReturnInstructions != null)
        {
            processor.InsertAfter(method.Body.Instructions.Last(), methodBodyReturnInstructions);

            if (saveRetvalInstructions != null)
            {
                processor.InsertBefore(methodBodyReturnInstructions.First(), saveRetvalInstructions);
            }

            if (taskContinuationMethodRef != null)
            {
                var taskContinuationInstructions = GetTaskContinuationInstructions(
                    processor,
                    retvalVariableDefinition,
                    attributeVariableDefinition,
                    taskContinuationMethodRef);

                processor.InsertBefore(methodBodyReturnInstructions.First(), taskContinuationInstructions);
            }

            if (callOnExitInstructions != null)
            {
                processor.InsertBefore(methodBodyReturnInstructions.First(), callOnExitInstructions);
            }

            if (onExceptionMethodRef != null)
            {
                processor.InsertBefore(methodBodyReturnInstructions.First(), tryCatchLeaveInstructions);
                processor.InsertBefore(methodBodyReturnInstructions.First(), catchHandlerInstructions);

                method.Body.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch)
                {
                    CatchType    = exceptionTypeRef,
                    TryStart     = methodBodyFirstInstruction,
                    TryEnd       = tryCatchLeaveInstructions.Last().Next,
                    HandlerStart = catchHandlerInstructions.First(),
                    HandlerEnd   = catchHandlerInstructions.Last().Next
                });
            }
        }

        MethodBodyRocks.OptimizeMacros(method.Body);
    }
        private MethodDefinition CopyMethod(TypeDefinition newtype, MethodDefinition method)
        {
            var newMethod = new MethodDefinition(method.Name, method.Attributes, CopyReference(method.ReturnType));

            _refsMap.Add(method, newMethod);
            newtype.Methods.Add(newMethod);

            CopyCommonStuff(method.MethodReturnType, newMethod.MethodReturnType);

            var instMap = new Dictionary <Instruction, Instruction>();
            var varMap  = new Dictionary <VariableDefinition, VariableDefinition>();
            var parMap  = new Dictionary <ParameterDefinition, ParameterDefinition>();

            foreach (var par in method.Parameters)
            {
                var npar = CopyMember(par);
                newMethod.Parameters.Add(npar);
                parMap.Add(par, npar);
            }

            foreach (var v in method.Body.Variables)
            {
                var nv = new VariableDefinition(v.Name, CopyReference(v.VariableType));
                newMethod.Body.Variables.Add(nv);
                varMap.Add(v, nv);
            }

            newMethod.Body.InitLocals = method.Body.InitLocals;

            var ilp = newMethod.Body.GetILProcessor();

            foreach (var i in method.Body.Instructions)
            {
                var ni = CopyInstruction(ilp, i);
                instMap.Add(i, ni);
                ilp.Append(ni);
            }

            //fix local refs
            foreach (var i in newMethod.Body.Instructions.ToList())
            {
                if (i.Operand is ParameterDefinition)
                {
                    var ni = ilp.Create(i.OpCode, parMap[(ParameterDefinition)i.Operand]);
                    ilp.SafeReplace(i, ni);
                }

                if (i.Operand is VariableDefinition)
                {
                    var ni = ilp.Create(i.OpCode, varMap[(VariableDefinition)i.Operand]);
                    ilp.SafeReplace(i, ni);
                }

                if (i.Operand is Instruction)
                {
                    var ni = ilp.Create(i.OpCode, instMap[(Instruction)i.Operand]);
                    ilp.SafeReplace(i, ni);
                }

                if (i.Operand is Instruction[])
                {
                    var ni = ilp.Create(i.OpCode, ((Instruction[])i.Operand).Select(ii => instMap[ii]).ToArray());
                    ilp.SafeReplace(i, ni);
                }
            }

            foreach (var h in method.Body.ExceptionHandlers)
            {
                var nh = new ExceptionHandler(h.HandlerType);
                nh.CatchType    = h.CatchType == null ? null : CopyReference(h.CatchType);
                nh.FilterStart  = h.FilterStart == null ? null : instMap[h.FilterStart];
                nh.HandlerEnd   = h.HandlerEnd == null ? null : instMap[h.HandlerEnd];
                nh.HandlerStart = h.HandlerStart == null ? null : instMap[h.HandlerStart];
                nh.TryEnd       = h.TryEnd == null ? null : instMap[h.TryEnd];
                nh.TryStart     = h.TryStart == null ? null : instMap[h.TryStart];

                newMethod.Body.ExceptionHandlers.Add(nh);
            }

            return(newMethod);
        }
示例#29
0
    static IList <Instruction> GetCallOnExitInstructions(ILProcessor processor,
                                                         VariableDefinition attributeVariableDefinition, MethodReference onExitMethodRef, VariableDefinition retvalVariableDefinition)
    {
        var oInstructions = new List <Instruction>
        {
            processor.Create(OpCodes.Ldloc, attributeVariableDefinition),
            processor.Create(OpCodes.Ldloc, retvalVariableDefinition),
        };

        if (retvalVariableDefinition.VariableType.IsValueType ||
            retvalVariableDefinition.VariableType.IsGenericParameter)
        {
            oInstructions.Add(processor.Create(OpCodes.Box, retvalVariableDefinition.VariableType));
        }

        oInstructions.Add(processor.Create(OpCodes.Callvirt, onExitMethodRef));
        return(oInstructions);
    }
示例#30
0
        public static IEnumerable <Instruction> ProcessParam(ParameterDefinition parameterDefinition, VariableDefinition paramsArray)
        {
            var paramMetaData = parameterDefinition.ParameterType.MetadataType;

            if (paramMetaData == MetadataType.UIntPtr ||
                paramMetaData == MetadataType.FunctionPointer ||
                paramMetaData == MetadataType.IntPtr ||
                paramMetaData == MetadataType.Pointer)
            {
                yield break;
            }

            yield return(Instruction.Create(OpCodes.Ldloc, paramsArray));

            yield return(Instruction.Create(OpCodes.Ldc_I4, parameterDefinition.Index));

            yield return(Instruction.Create(OpCodes.Ldarg, parameterDefinition));

            // Reset boolean flag variable to false

            // If a parameter is passed by reference then you need to use Ldind
            // ------------------------------------------------------------
            var paramType = parameterDefinition.ParameterType;

            if (paramType.IsByReference)
            {
                var referencedTypeSpec = (TypeSpecification)paramType;

                var pointerToValueTypeVariable = false;
                switch (referencedTypeSpec.ElementType.MetadataType)
                {
                //Indirect load value of type int8 as int32 on the stack
                case MetadataType.Boolean:
                case MetadataType.SByte:
                    yield return(Instruction.Create(OpCodes.Ldind_I1));

                    pointerToValueTypeVariable = true;
                    break;

                // Indirect load value of type int16 as int32 on the stack
                case MetadataType.Int16:
                    yield return(Instruction.Create(OpCodes.Ldind_I2));

                    pointerToValueTypeVariable = true;
                    break;

                // Indirect load value of type int32 as int32 on the stack
                case MetadataType.Int32:
                    yield return(Instruction.Create(OpCodes.Ldind_I4));

                    pointerToValueTypeVariable = true;
                    break;

                // Indirect load value of type int64 as int64 on the stack
                // Indirect load value of type unsigned int64 as int64 on the stack (alias for ldind.i8)
                case MetadataType.Int64:
                case MetadataType.UInt64:
                    yield return(Instruction.Create(OpCodes.Ldind_I8));

                    pointerToValueTypeVariable = true;
                    break;

                // Indirect load value of type unsigned int8 as int32 on the stack
                case MetadataType.Byte:
                    yield return(Instruction.Create(OpCodes.Ldind_U1));

                    pointerToValueTypeVariable = true;
                    break;

                // Indirect load value of type unsigned int16 as int32 on the stack
                case MetadataType.UInt16:
                case MetadataType.Char:
                    yield return(Instruction.Create(OpCodes.Ldind_U2));

                    pointerToValueTypeVariable = true;
                    break;

                // Indirect load value of type unsigned int32 as int32 on the stack
                case MetadataType.UInt32:
                    yield return(Instruction.Create(OpCodes.Ldind_U4));

                    pointerToValueTypeVariable = true;
                    break;

                // Indirect load value of type float32 as F on the stack
                case MetadataType.Single:
                    yield return(Instruction.Create(OpCodes.Ldind_R4));

                    pointerToValueTypeVariable = true;
                    break;

                // Indirect load value of type float64 as F on the stack
                case MetadataType.Double:
                    yield return(Instruction.Create(OpCodes.Ldind_R8));

                    pointerToValueTypeVariable = true;
                    break;

                // Indirect load value of type native int as native int on the stack
                case MetadataType.IntPtr:
                case MetadataType.UIntPtr:
                    yield return(Instruction.Create(OpCodes.Ldind_I));

                    pointerToValueTypeVariable = true;
                    break;

                default:
                    // Need to check if it is a value type instance, in which case
                    // we use Ldobj instruction to copy the contents of value type
                    // instance to stack and then box it
                    if (referencedTypeSpec.ElementType.IsValueType)
                    {
                        yield return(Instruction.Create(OpCodes.Ldobj, referencedTypeSpec.ElementType));

                        pointerToValueTypeVariable = true;
                    }
                    else
                    {
                        // It is a reference type so just use reference the pointer
                        yield return(Instruction.Create(OpCodes.Ldind_Ref));
                    }
                    break;
                }

                if (pointerToValueTypeVariable)
                {
                    // Box the de-referenced parameter type
                    yield return(Instruction.Create(OpCodes.Box, referencedTypeSpec.ElementType));
                }
            }
            else
            {
                // If it is a value type then you need to box the instance as we are going
                // to add it to an array which is of type object (reference type)
                // ------------------------------------------------------------
                if (paramType.IsValueType || paramType.IsGenericParameter)
                {
                    // Box the parameter type
                    yield return(Instruction.Create(OpCodes.Box, paramType));
                }
            }

            // Store parameter in object[] array
            // ------------------------------------------------------------
            yield return(Instruction.Create(OpCodes.Stelem_Ref));
        }
示例#31
0
    static IList <Instruction> GetMethodBodyReturnInstructions(ILProcessor processor, VariableDefinition attributeVariableDefinition, VariableDefinition retvalVariableDefinition, MethodReference alterRetvalMethodRef)
    {
        var instructions = new List <Instruction>();

        if (retvalVariableDefinition != null)
        {
            if (alterRetvalMethodRef != null)
            {
                instructions.Add(processor.Create(OpCodes.Ldloc, attributeVariableDefinition));
                instructions.Add(processor.Create(OpCodes.Ldloc, retvalVariableDefinition));

                if (retvalVariableDefinition.VariableType.IsValueType ||
                    retvalVariableDefinition.VariableType.IsGenericParameter)
                {
                    instructions.Add(processor.Create(OpCodes.Box, retvalVariableDefinition.VariableType));
                }

                instructions.Add(processor.Create(OpCodes.Callvirt, alterRetvalMethodRef));
                instructions.Add(processor.Create(OpCodes.Unbox_Any, retvalVariableDefinition.VariableType));
            }
            else
            {
                instructions.Add(processor.Create(OpCodes.Ldloc, retvalVariableDefinition));
            }
        }

        instructions.Add(processor.Create(OpCodes.Ret));
        return(instructions);
    }
示例#32
0
 static List <Instruction> GetCatchHandlerInstructions(ILProcessor processor, VariableDefinition attributeVariableDefinition, VariableDefinition exceptionVariableDefinition, MethodReference onExceptionMethodRef)
 {
     // Store the exception in __fody$exception
     // Call __fody$attribute.OnException("{methodName}", __fody$exception)
     // rethrow
     return(new List <Instruction>
     {
         processor.Create(OpCodes.Stloc, exceptionVariableDefinition),
         processor.Create(OpCodes.Ldloc, attributeVariableDefinition),
         processor.Create(OpCodes.Ldloc, exceptionVariableDefinition),
         processor.Create(OpCodes.Callvirt, onExceptionMethodRef),
         processor.Create(OpCodes.Rethrow)
     });
 }
示例#33
0
    static IEnumerable <Instruction> GetTaskContinuationInstructions(ILProcessor processor, VariableDefinition retvalVariableDefinition, VariableDefinition attributeVariableDefinition, MethodReference taskContinuationMethodReference)
    {
        if (retvalVariableDefinition != null)
        {
            var tr = retvalVariableDefinition.VariableType;

            if (tr.FullName.Contains("System.Threading.Tasks.Task"))
            {
                return new[]
                       {
                           processor.Create(OpCodes.Ldloc, attributeVariableDefinition),
                           processor.Create(OpCodes.Ldloc, retvalVariableDefinition),
                           processor.Create(OpCodes.Callvirt, taskContinuationMethodReference),
                       }
            }
            ;
        }

        return(new Instruction[0]);
    }
}
示例#34
0
        public void DotNotation()
        {
            s_output = new List<string> ();

            StringReader programString = new StringReader(
                @"var id = 100
                  id.foo(42, true)"
            );

            FunctionDefinition[] funcs = new FunctionDefinition[1];
            funcs[0] = new FunctionDefinition("void",
                "RemoteFunctionCall",
                new string[] { "number", "string", "array" },
                new string[] { "id", "functionName", "args" },
                new ExternalFunctionCreator.OnFunctionCall(ExternalFunctionCall),
                FunctionDocumentation.Default()
            );

            VariableDefinition[] vars = new VariableDefinition[] {};

            SprakRunner program = new SprakRunner(programString, funcs, vars);

            program.run();

            Assert.AreEqual (1, s_output.Count);
            Assert.AreEqual ("id = 100, functionName = foo, args = [42, true]", s_output[0]);
            Assert.AreEqual(0, program.getCompileTimeErrorHandler().getErrors().Count);
        }
示例#35
0
        /// <summary>
        /// Generates a method body for the <paramref name="targetMethod"/>.
        /// </summary>
        /// <param name="originalMethod">The method currently being intercepted.</param>
        /// <param name="targetMethod">The target method that will contain the new method body.</param>
        public void Emit(MethodInfo originalMethod, MethodDefinition targetMethod)
        {
            VariableDefinition invocationInfo = targetMethod.AddLocal <IInvocationInfo>();

            invocationInfo.Name = "___invocationInfo___";

            // Emit the code to generate the IInvocationInfo instance
            // and save it into the invocationInfo local variable
            if (InvocationInfoEmitter != null)
            {
                InvocationInfoEmitter.Emit(originalMethod, targetMethod, invocationInfo);
            }

            TypeDefinition     declaringType        = targetMethod.DeclaringType;
            ModuleDefinition   module               = declaringType.Module;
            TypeReference      proxyType            = module.ImportType <IProxy>();
            MethodReference    getInterceptorMethod = module.ImportMethod("get_Interceptor", typeof(IProxy));
            VariableDefinition interceptor          = targetMethod.AddLocal <IInterceptor>();
            VariableDefinition arguments            = targetMethod.AddLocal <object[]>();

            // if (!(this is IProxy))
            CilWorker IL = targetMethod.GetILGenerator();

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Isinst, proxyType);

            Instruction noImplementationFound = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Brfalse, noImplementationFound);

            Instruction endLabel = IL.Create(OpCodes.Nop);

            EmitGetInterceptorInstruction(IL, proxyType, getInterceptorMethod);
            IL.Emit(OpCodes.Stloc, interceptor);

            //If (interceptor == null)
            //    throw a not implemented exception here
            IL.Emit(OpCodes.Ldloc, interceptor);
            IL.Emit(OpCodes.Brfalse, noImplementationFound);


            // var returnValue = interceptor.Intercept(info);
            TypeReference   voidType        = module.ImportType(typeof(void));
            MethodReference interceptMethod = module.ImportMethod <IInterceptor>("Intercept", typeof(IInvocationInfo));

            IL.Emit(OpCodes.Ldloc, interceptor);
            IL.Emit(OpCodes.Ldloc, invocationInfo);
            IL.Emit(OpCodes.Callvirt, interceptMethod);

            // Save the ref arguments
            IEnumerable <ParameterDefinition> parameters = from ParameterDefinition param in targetMethod.Parameters
                                                           select param;

            // Determine the return type
            TypeReference returnType = targetMethod.ReturnType != null
                                           ? targetMethod.ReturnType.ReturnType
                                           : voidType;

            IL.PackageReturnValue(module, returnType);

            SaveRefArguments(IL, parameters, invocationInfo, arguments);
            IL.Emit(OpCodes.Br, endLabel);

            // This code at this point will execute if no implementation
            // is found
            IL.Append(noImplementationFound);

            ImplementNotFound(IL);

            IL.Append(endLabel);
            IL.Emit(OpCodes.Ret);
        }
示例#36
0
        private static void ProcessMethod(ModuleDefinition module, MethodDefinition method, CustomAttribute aspect)
        {
            method.Body.SimplifyMacros();

            MethodReference aspectConstructorRef = aspect.Constructor;

            MethodInfo getCurrentMethod = typeof(MethodBase).GetMethod("GetCurrentMethod", BindingFlags.Public | BindingFlags.Static);
            MethodReference getCurrentMethodRef = module.Import(getCurrentMethod);

            TypeReference methodInfoRef = module.Import(typeof(MethodInfo));
            TypeReference objectRef = module.Import(typeof(Object));

            MethodReference methodExecutionArgsCtorRef =
                module.Import(typeof(MethodExecutionArgs).GetConstructor(new Type[]
                    {
                        typeof(MethodInfo), typeof(object[])
                    }));

            MethodReference onEntryRef =
                module.Import(typeof(OnMethodBoundaryAspect).GetMethod("OnEntry"));

            MethodReference onSuccessRef =
                module.Import(typeof(OnMethodBoundaryAspect).GetMethod("OnSuccess"));

            MethodReference onExceptionRef =
                module.Import(typeof(OnMethodBoundaryAspect).GetMethod("OnException"));

            MethodReference onExitRef =
                module.Import(typeof(OnMethodBoundaryAspect).GetMethod("OnExit"));

            MethodInfo getFlowBehavior =
                typeof(MethodExecutionArgs).GetProperty("FlowBehavior").GetGetMethod();
            MethodReference getFlowBehaviorRef = module.Import(getFlowBehavior);

            MethodInfo setException =
                typeof(MethodExecutionArgs).GetProperty("Exception").GetSetMethod();
            MethodReference setExceptionRef = module.Import(setException);

            MethodInfo getException =
                typeof(MethodExecutionArgs).GetProperty("Exception").GetGetMethod();
            MethodReference getExceptionRef = module.Import(getException);

            MethodInfo getParameters = typeof(MethodBase).GetMethod("GetParameters");
            MethodReference getParametersRef = module.Import(getParameters);

            var processor = method.Body.GetILProcessor();
            var firstInstruction = method.Body.Instructions[0];

            // Original last instruction, change to a Nop.
            method.Body.Instructions.Last().OpCode = OpCodes.Nop;

            var finalInstruction = processor.Create(OpCodes.Nop);
            method.Body.Instructions.Add(finalInstruction);
            method.Body.Instructions.Add(processor.Create(OpCodes.Ret));

            // Add necessary variables
            int existingVariableCount = method.Body.Variables.Count;

            method.Body.Variables.Add(new VariableDefinition("__aspect", aspect.AttributeType)); // module.Import(aspect.GetType())));
            method.Body.Variables.Add(new VariableDefinition("__methodInfo", module.Import(typeof(MethodInfo))));
            method.Body.Variables.Add(new VariableDefinition("__methodExecutionArgs",
                                                             module.Import(typeof(MethodExecutionArgs))));
            method.Body.Variables.Add(new VariableDefinition("__ex", module.Import(typeof(Exception))));

            var argsVariableRef = new VariableDefinition("__args", module.Import(typeof(object[])));
            method.Body.Variables.Add(argsVariableRef);

            var boolVariableRef = new VariableDefinition("__bool", module.Import(typeof(bool)));
            method.Body.Variables.Add(boolVariableRef);

            var flowBehaviorVariableRef = new VariableDefinition("__flow", module.Import(typeof(FlowBehavior)));
            method.Body.Variables.Add(flowBehaviorVariableRef);

            Instruction L_0032_Instruction;
            Instruction firstAfterInstruction = Instruction.Create(OpCodes.Nop);

            const int Variable_aspect = 0;
            const int Variable_methodInfo = 1;
            const int Variable_methodExecutionArgs = 2;
            const int Variable_ex = 3;

            var beforeInstructions = new List<Instruction>
                {
                    processor.Create(OpCodes.Nop),
                    processor.Create(OpCodes.Newobj, aspectConstructorRef),
                    processor.Create(OpCodes.Stloc, Variable_aspect + existingVariableCount),
                    processor.Create(OpCodes.Call, getCurrentMethodRef),
                    processor.Create(OpCodes.Isinst, methodInfoRef),
                    processor.Create(OpCodes.Stloc, Variable_methodInfo + existingVariableCount),
                    processor.Create(OpCodes.Ldloc, Variable_methodInfo + existingVariableCount),
                };

            beforeInstructions.AddRange(new List<Instruction> {
                    processor.Create(OpCodes.Ldc_I4, method.Parameters.Count), // Number of arguments in method
                    processor.Create(OpCodes.Newarr, objectRef), // Create the object array (sized to hold args)
                    processor.Create(OpCodes.Stloc_S, argsVariableRef), // Save array to variable
                    processor.Create(OpCodes.Ldloc_S, argsVariableRef), // Load variable for evaluation
            });

            for (int i = 0; i < method.Parameters.Count; i++)
            {
                beforeInstructions.Add(processor.Create(OpCodes.Ldc_I4, i));  // Index value 0
                beforeInstructions.Add(processor.Create(OpCodes.Ldarg, i + 1)); // Load first argument

                var parameterType = method.Parameters[i].ParameterType;

                if (parameterType.IsValueType)
                    beforeInstructions.Add(processor.Create(OpCodes.Box, parameterType)); // Box the value types

                beforeInstructions.Add(processor.Create(OpCodes.Stelem_Ref)); // Assign argument to index 0 of array
                beforeInstructions.Add(processor.Create(OpCodes.Ldloc_S, argsVariableRef));
            }

            beforeInstructions.AddRange(new List<Instruction> {
                    //processor.Create(OpCodes.Ldc_I4, 2), // Number of arguments in method
                    //processor.Create(OpCodes.Newarr, objectRef), // Create the object array (sized to hold args)
                    //processor.Create(OpCodes.Stloc_S, argsVariableRef), // Save array to variable
                    //processor.Create(OpCodes.Ldloc_S, argsVariableRef), // Load variable for evaluation

                    //processor.Create(OpCodes.Ldc_I4_0), // Index value 0
                    //processor.Create(OpCodes.Ldarg_1), // Load first argument
                    //processor.Create(OpCodes.Stelem_Ref), // Assign argument to index 0 of array
                    //processor.Create(OpCodes.Ldloc_S, argsVariableRef),

                    //processor.Create(OpCodes.Ldc_I4_1), // Index value 1
                    //processor.Create(OpCodes.Ldarg_2), // Second argument
                    //processor.Create(OpCodes.Box, int32Ref), // Box the value types
                    //processor.Create(OpCodes.Stelem_Ref), // Assign argument to index 1 of array
                    //processor.Create(OpCodes.Ldloc_S, argsVariableRef),
                    
                    processor.Create(OpCodes.Newobj, methodExecutionArgsCtorRef),
                    processor.Create(OpCodes.Stloc, Variable_methodExecutionArgs + existingVariableCount),
                    (L_0032_Instruction = processor.Create(OpCodes.Nop)),
                    processor.Create(OpCodes.Ldloc, Variable_aspect + existingVariableCount),
                    processor.Create(OpCodes.Ldloc, Variable_methodExecutionArgs + existingVariableCount),
                    processor.Create(OpCodes.Callvirt, onEntryRef),
                    processor.Create(OpCodes.Nop),
                    processor.Create(OpCodes.Ldloc, Variable_methodExecutionArgs + existingVariableCount),
                    processor.Create(OpCodes.Callvirt, getFlowBehaviorRef),
                    processor.Create(OpCodes.Ldc_I4_3),
                    processor.Create(OpCodes.Ceq),
                    processor.Create(OpCodes.Ldc_I4_0),
                    processor.Create(OpCodes.Ceq),
                    processor.Create(OpCodes.Stloc_S, boolVariableRef),
                    processor.Create(OpCodes.Ldloc_S, boolVariableRef),
                    processor.Create(OpCodes.Brtrue_S, firstInstruction),
                    processor.Create(OpCodes.Leave, finalInstruction),
                });

            var L_0094_Instruction = processor.Create(OpCodes.Rethrow);
            var L_00a2_Instruction = processor.Create(OpCodes.Nop);
            var L_00b0_Instruction = processor.Create(OpCodes.Nop);
            var L_00b1_Instruction = processor.Create(OpCodes.Nop);
            var L_0096_Instruction = processor.Create(OpCodes.Leave_S, L_00b1_Instruction);
            var L_009f_Instruction = processor.Create(OpCodes.Nop);
            var L_0098_Instruction = processor.Create(OpCodes.Ldloc, 2 + existingVariableCount);

            Instruction L_005d_Instruction;
            Instruction L_00a5_Instruction;

            var afterInstructions = new List<Instruction>
                {
                    firstAfterInstruction,
                    processor.Create(OpCodes.Ldloc, Variable_aspect + existingVariableCount),
                    processor.Create(OpCodes.Ldloc, Variable_methodExecutionArgs + existingVariableCount),
                    processor.Create(OpCodes.Callvirt, onSuccessRef),
                    processor.Create(OpCodes.Nop),
                    processor.Create(OpCodes.Nop),
                    processor.Create(OpCodes.Leave_S, L_00a2_Instruction),
                    (L_005d_Instruction = processor.Create(OpCodes.Stloc, Variable_ex + existingVariableCount)),
                    processor.Create(OpCodes.Nop),
                    processor.Create(OpCodes.Ldloc, Variable_methodExecutionArgs + existingVariableCount),
                    processor.Create(OpCodes.Ldloc, Variable_ex + existingVariableCount),
                    processor.Create(OpCodes.Callvirt, setExceptionRef),
                    processor.Create(OpCodes.Nop),
                    processor.Create(OpCodes.Ldloc, Variable_aspect + existingVariableCount),
                    processor.Create(OpCodes.Ldloc, Variable_methodExecutionArgs + existingVariableCount),
                    processor.Create(OpCodes.Callvirt, onExceptionRef),
                    processor.Create(OpCodes.Nop),
                    processor.Create(OpCodes.Ldloc, Variable_methodExecutionArgs + existingVariableCount),
                    processor.Create(OpCodes.Callvirt, getFlowBehaviorRef),
                    processor.Create(OpCodes.Stloc_S, flowBehaviorVariableRef),
                    processor.Create(OpCodes.Ldloc_S, flowBehaviorVariableRef),
                    processor.Create(OpCodes.Switch,
                                     new[]
                                         {
                                             L_0094_Instruction, L_0096_Instruction, L_0094_Instruction, L_009f_Instruction,
                                             L_0098_Instruction
                                         }),
                    processor.Create(OpCodes.Br_S, L_009f_Instruction),
                    L_0094_Instruction,
                    L_0096_Instruction,
                    L_0098_Instruction,
                    processor.Create(OpCodes.Callvirt, getExceptionRef),
                    processor.Create(OpCodes.Throw),
                    L_009f_Instruction,
                    processor.Create(OpCodes.Leave_S, L_00a2_Instruction),
                    L_00a2_Instruction,
                    processor.Create(OpCodes.Leave_S, L_00b0_Instruction),
                    (L_00a5_Instruction = processor.Create(OpCodes.Nop)),
                    processor.Create(OpCodes.Ldloc, Variable_aspect + existingVariableCount),
                    processor.Create(OpCodes.Ldloc, Variable_methodExecutionArgs + existingVariableCount),
                    processor.Create(OpCodes.Callvirt, onExitRef), // L_00a8
                    processor.Create(OpCodes.Nop),
                    processor.Create(OpCodes.Nop),
                    processor.Create(OpCodes.Endfinally),
                    L_00b0_Instruction,
                    L_00b1_Instruction,
                };

            var catchHandler = new ExceptionHandler(ExceptionHandlerType.Catch)
            {
                TryStart = L_0032_Instruction,
                TryEnd = L_005d_Instruction,
                HandlerStart = L_005d_Instruction,
                HandlerEnd = L_00a2_Instruction,
                CatchType = module.Import(typeof(Exception)),
            };

            var finallyHandler = new ExceptionHandler(ExceptionHandlerType.Finally)
            {
                TryStart = L_0032_Instruction,
                TryEnd = L_00a5_Instruction,
                HandlerStart = L_00a5_Instruction,
                HandlerEnd = L_00b0_Instruction,
            };

            // Add the OnEntry portion
            foreach (var instruction in beforeInstructions)
                processor.InsertBefore(firstInstruction, instruction);

            // Add the OnExit portion
            foreach (var instruction in afterInstructions)
                processor.InsertBefore(finalInstruction, instruction);

            //// Add try/catch
            method.Body.ExceptionHandlers.Add(catchHandler);
            method.Body.ExceptionHandlers.Add(finallyHandler);

            method.Body.OptimizeMacros();
        }
示例#37
0
        public static MethodDefinition ProcessSyncVarSet(TypeDefinition td, FieldDefinition fd, string originalName, long dirtyBit, FieldDefinition netFieldId)
        {
            //Create the set method
            MethodDefinition set = new MethodDefinition("set_Network" + originalName, MethodAttributes.Public |
                                                        MethodAttributes.SpecialName |
                                                        MethodAttributes.HideBySig,
                                                        Weaver.voidType);

            ILProcessor setWorker = set.Body.GetILProcessor();

            // if (!SyncVarEqual(value, ref playerData))
            Instruction endOfMethod = setWorker.Create(OpCodes.Nop);

            // this
            setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
            // new value to set
            setWorker.Append(setWorker.Create(OpCodes.Ldarg_1));
            // reference to field to set
            // make generic version of SetSyncVar with field type
            if (fd.FieldType.FullName == Weaver.gameObjectType.FullName)
            {
                // reference to netId Field to set
                setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
                setWorker.Append(setWorker.Create(OpCodes.Ldfld, netFieldId));

                setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.syncVarGameObjectEqualReference));
            }
            else if (fd.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
            {
                // reference to netId Field to set
                setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
                setWorker.Append(setWorker.Create(OpCodes.Ldfld, netFieldId));

                setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.syncVarNetworkIdentityEqualReference));
            }
            else
            {
                setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
                setWorker.Append(setWorker.Create(OpCodes.Ldflda, fd));

                GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(Weaver.syncVarEqualReference);
                syncVarEqualGm.GenericArguments.Add(fd.FieldType);
                setWorker.Append(setWorker.Create(OpCodes.Call, syncVarEqualGm));
            }

            setWorker.Append(setWorker.Create(OpCodes.Brtrue, endOfMethod));

            // T oldValue = value;
            // TODO for GO/NI we need to backup the netId don't we?
            VariableDefinition oldValue = new VariableDefinition(fd.FieldType);

            set.Body.Variables.Add(oldValue);
            setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
            setWorker.Append(setWorker.Create(OpCodes.Ldfld, fd));
            setWorker.Append(setWorker.Create(OpCodes.Stloc, oldValue));

            // this
            setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));

            // new value to set
            setWorker.Append(setWorker.Create(OpCodes.Ldarg_1));

            // reference to field to set
            setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
            setWorker.Append(setWorker.Create(OpCodes.Ldflda, fd));

            // dirty bit
            // 8 byte integer aka long
            setWorker.Append(setWorker.Create(OpCodes.Ldc_I8, dirtyBit));

            if (fd.FieldType.FullName == Weaver.gameObjectType.FullName)
            {
                // reference to netId Field to set
                setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
                setWorker.Append(setWorker.Create(OpCodes.Ldflda, netFieldId));

                setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarGameObjectReference));
            }
            else if (fd.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
            {
                // reference to netId Field to set
                setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
                setWorker.Append(setWorker.Create(OpCodes.Ldflda, netFieldId));

                setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarNetworkIdentityReference));
            }
            else
            {
                // make generic version of SetSyncVar with field type
                GenericInstanceMethod gm = new GenericInstanceMethod(Weaver.setSyncVarReference);
                gm.GenericArguments.Add(fd.FieldType);

                // invoke SetSyncVar
                setWorker.Append(setWorker.Create(OpCodes.Call, gm));
            }

            CheckForHookFunction(td, fd, out MethodDefinition hookFunctionMethod);

            if (hookFunctionMethod != null)
            {
                //if (NetworkServer.localClientActive && !getSyncVarHookGuard(dirtyBit))
                Instruction label = setWorker.Create(OpCodes.Nop);
                setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.NetworkServerGetLocalClientActive));
                setWorker.Append(setWorker.Create(OpCodes.Brfalse, label));
                setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
                setWorker.Append(setWorker.Create(OpCodes.Ldc_I8, dirtyBit));
                setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.getSyncVarHookGuard));
                setWorker.Append(setWorker.Create(OpCodes.Brtrue, label));

                // setSyncVarHookGuard(dirtyBit, true);
                setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
                setWorker.Append(setWorker.Create(OpCodes.Ldc_I8, dirtyBit));
                setWorker.Append(setWorker.Create(OpCodes.Ldc_I4_1));
                setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarHookGuard));

                // call hook (oldValue, newValue)
                setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
                setWorker.Append(setWorker.Create(OpCodes.Ldloc, oldValue));
                setWorker.Append(setWorker.Create(OpCodes.Ldarg_1));
                setWorker.Append(setWorker.Create(OpCodes.Callvirt, hookFunctionMethod));

                // setSyncVarHookGuard(dirtyBit, false);
                setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
                setWorker.Append(setWorker.Create(OpCodes.Ldc_I8, dirtyBit));
                setWorker.Append(setWorker.Create(OpCodes.Ldc_I4_0));
                setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarHookGuard));

                setWorker.Append(label);
            }

            setWorker.Append(endOfMethod);

            setWorker.Append(setWorker.Create(OpCodes.Ret));

            set.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.In, fd.FieldType));
            set.SemanticsAttributes = MethodSemanticsAttributes.Setter;

            return(set);
        }
示例#38
0
		public virtual void VisitVariableDefinition (VariableDefinition var)
		{
		}
示例#39
0
        public object GetVariableValue(ISchema schema, VariableDefinition variable, IValue input)
        {
            var type = variable.Type.GraphTypeFromType(schema);

            var value = input ?? variable.DefaultValue;
            if (IsValidValue(schema, type, variable.Type, input))
            {
                var coercedValue = CoerceValue(schema, type, value);
                return coercedValue;
            }

            var val = ValueFromAst(value);

            if (val == null)
            {
                throw new ExecutionError("Variable '${0}' of required type '{1}' was not provided.".ToFormat(variable.Name, type.Name ?? variable.Type.FullName()));
            }

            throw new ExecutionError("Variable '${0}' expected value of type '{1}'.".ToFormat(variable.Name, type?.Name ?? variable.Type.FullName()));
        }