/// <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); }
/// <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); }
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; } }
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) }); }
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))); } }
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 }); }
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 }); }
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); }
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) }); }
/// <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; }
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); }
/// <summary> /// Variable ctor /// </summary> public AstILVariable(string name, XTypeReference type, VariableDefinition originalVariable) { Name = name; Type = type; this.originalVariable = originalVariable; }
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; }
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); }
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); }
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); }
public FlagsInfo(VariableDefinition local, uint value, int offset) { Local = local; Value = value; Offset = offset; }
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); }
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); }
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); }
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); }
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)); }
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); }
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) }); }
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]); } }
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); }
/// <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); }
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(); }
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); }
public virtual void VisitVariableDefinition (VariableDefinition var) { }
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())); }