public static void MarkAsProcessed(TypeDefinition td) { if (!WasProcessed(td)) { MethodDefinition versionMethod = td.AddMethod(ProcessedFunctionName, MethodAttributes.Private); ILProcessor worker = versionMethod.Body.GetILProcessor(); worker.Append(worker.Create(OpCodes.Ret)); } }
private static PropertyDefinition CreateProperty <T>(TypeDefinition wrapper, ModuleDefinition module, string name) { FieldDefinition field = wrapper.AddField <T>($"<{name}>k__BackingField", FieldAttributes.Private); field.CustomAttributes.Add(new CustomAttribute(module.GetConstructor <CompilerGeneratedAttribute>())); var get = wrapper.AddMethod <T>($"get_{name}", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual); get.AddAttribute <CompilerGeneratedAttribute>(); get.AddAttribute <IsReadOnlyAttribute>(); ILProcessor il = get.BeginEdit(); il.EmitLdarg(); il.Emit(OpCodes.Ldfld, field); il.Emit(OpCodes.Ret); get.EndEdit(); var set = wrapper.AddMethod($"set_{name}", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName); var paraValue = set.AddParameter <T>("value"); set.AddAttribute <CompilerGeneratedAttribute>(); il = set.BeginEdit(); il.EmitLdarg(); il.EmitLdarg(paraValue); il.Emit(OpCodes.Stfld, field); il.Emit(OpCodes.Ret); set.EndEdit(); PropertyDefinition property = new PropertyDefinition(name, PropertyAttributes.None, module.GetTypeReference <T>()) { GetMethod = get, SetMethod = set }; wrapper.Properties.Add(property); return(property); }
private void InjectEquatable([NotNull] TypeDefinition classDefinition, [NotNull, ItemNotNull] ICollection <MemberDefinition> membersToCompare, [CanBeNull] MethodDefinition customEquals, [CanBeNull] MethodDefinition customGetHashCode) { _logger.LogInfo($"Weaving IEquatable into {classDefinition}"); VerifyCustomEqualsSignature(classDefinition, customEquals); VerifyCustomGetHashCodeSignature(classDefinition, customGetHashCode); if (classDefinition.Interfaces.Any(i => i.InterfaceType.Resolve().FullName == typeof(IEquatable <>).FullName)) { throw new WeavingException($"Class {classDefinition} already implements {typeof(IEquatable<>)}", classDefinition.GetEntryPoint()); } classDefinition.Interfaces.Add(new InterfaceImplementation(_systemReferences.IEquatable.MakeGenericInstanceType(classDefinition.ReferenceFrom(classDefinition)))); var internalEqualsMethod = CreateInternalEqualsMethod(classDefinition, membersToCompare, customEquals); classDefinition.AddMethod(internalEqualsMethod); var equalsTypeMethod = CreateTypedEqualsMethod(classDefinition, internalEqualsMethod); classDefinition.AddMethod(equalsTypeMethod); var getHashCodeMethod = CreateGetHashCode(classDefinition, membersToCompare, customGetHashCode); classDefinition.AddMethod(getHashCodeMethod); classDefinition.AddMethod(CreateObjectEqualsOverrideMethod(classDefinition, equalsTypeMethod)); classDefinition.AddMethod(CreateEqualityOperator(classDefinition, internalEqualsMethod)); classDefinition.AddMethod(CreateInequalityOperator(classDefinition, internalEqualsMethod)); }
private void SetRpcCount(int count) { // set const so that child classes know count of base classes rpcCounter.Set(count); // override virtual method so returns total var method = netBehaviourSubclass.AddMethod(nameof(NetworkBehaviour.GetRpcCount), MethodAttributes.Virtual | MethodAttributes.Family, typeof(int)); var worker = method.Body.GetILProcessor(); // write count of base+current so that `GetInBase` call will return total worker.Emit(OpCodes.Ldc_I4, rpcCounter.GetInBase() + count); worker.Emit(OpCodes.Ret); }
private static void CreateSerializeMethod(TypeDefinition wrapper, ModuleDefinition module, PropertyDefinition valuesField, IReadOnlyList <IExposedProperty> properties) { MethodDefinition m = wrapper.AddMethod("Serialize", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual); ParameterDefinition paraId = m.AddParameter <int>("id"); ParameterDefinition paraWriter = m.AddParameter(module.GetTypeReference(typeof(MessagePackWriter).MakeByRefType()), "writer"); ParameterDefinition paraOptions = m.AddParameter <MessagePackSerializerOptions>("options"); ILProcessor il = m.BeginEdit(); MethodReference getItem = module.GetMethod <Dictionary <int, object> >("get_Item").MakeHostInstanceGeneric(module.GetTypeReference(typeof(Dictionary <,>)).MakeGenericInstanceType(module.GetTypeReference <int>(), module.GetTypeReference <object>())); il.EmitIfElse(properties, (property, index, next, body, fill) => { // if (id == <id>) fill.Add(ILHelper.Ldarg(il, paraId)); if (property.Id == 0) { fill.Add(Instruction.Create(OpCodes.Brtrue, next)); } else { fill.Add(ILHelper.Int(property.Id)); fill.Add(Instruction.Create(OpCodes.Bne_Un, next)); } }, (property, index, next, fill) => { // writer.Write((Type) values[id]) // options.Resolver.GetFormatterWithVerify<Type>().Serialize(ref writer, (Type) values[id], options) fill.AddRange(FormatterHelper.GetWriteValue(property.FieldTypeComponentAware, module, il, paraWriter, paraOptions, list => { list.Add(Instruction.Create(OpCodes.Call, valuesField.GetMethod)); list.Add(ILHelper.Int(property.Id)); list.Add(Instruction.Create(OpCodes.Callvirt, getItem)); if (property.IsValueType) { list.Add(Instruction.Create(OpCodes.Unbox_Any, property.FieldTypeComponentAware)); } })); if (index <= properties.Count - 1) { fill.Add(Instruction.Create(OpCodes.Ret)); } }, fill => { fill.Add(Instruction.Create(OpCodes.Ret)); }); m.EndEdit(); }
void RegisterRpcs() { Weaver.DLog(netBehaviourSubclass, " GenerateConstants "); // find static constructor MethodDefinition cctor = netBehaviourSubclass.GetMethod(".cctor"); if (cctor != null) { // remove the return opcode from end of function. will add our own later. if (cctor.Body.Instructions.Count != 0) { Instruction retInstr = cctor.Body.Instructions[cctor.Body.Instructions.Count - 1]; if (retInstr.OpCode == OpCodes.Ret) { cctor.Body.Instructions.RemoveAt(cctor.Body.Instructions.Count - 1); } else { logger.Error($"{netBehaviourSubclass.Name} has invalid class constructor", cctor); return; } } } else { // make one! cctor = netBehaviourSubclass.AddMethod(".cctor", MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Static); } ILProcessor cctorWorker = cctor.Body.GetILProcessor(); serverRpcProcessor.RegisterServerRpcs(cctorWorker); clientRpcProcessor.RegisterClientRpcs(cctorWorker); cctorWorker.Append(cctorWorker.Create(OpCodes.Ret)); // in case class had no cctor, it might have BeforeFieldInit, so injected cctor would be called too late netBehaviourSubclass.Attributes &= ~TypeAttributes.BeforeFieldInit; }
private static void CreateDeserializeMethod(TypeDefinition wrapper, ModuleDefinition module, IReadOnlyList <IExposedProperty> properties) { MethodDefinition m = wrapper.AddMethod <object>("Deserialize", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual); ParameterDefinition paraId = m.AddParameter <int>("id"); ParameterDefinition paraReader = m.AddParameter(module.GetTypeReference(typeof(MessagePackReader).MakeByRefType()), "reader"); ParameterDefinition paraOptions = m.AddParameter <MessagePackSerializerOptions>("options"); ILProcessor il = m.BeginEdit(); il.EmitIfElse(properties, (property, index, next, body, fill) => { // if (id == <id>) fill.Add(ILHelper.Ldarg(il, paraId)); if (property.Id == 0) { fill.Add(Instruction.Create(OpCodes.Brtrue, next)); } else { fill.Add(ILHelper.Int(property.Id)); fill.Add(Instruction.Create(OpCodes.Bne_Un, next)); } }, (property, index, next, fill) => { // return reader.Read() // return options.Resolver.GetFormatterWithVerify<Type>().Deserialize(ref reader, options) fill.AddRange(FormatterHelper.GetReadValue(property.FieldTypeComponentAware, module, il, paraReader, paraOptions)); if (property.IsValueType) { fill.Add(Instruction.Create(OpCodes.Box, property.FieldTypeComponentAware)); } fill.Add(Instruction.Create(OpCodes.Ret)); }, fill => { // return null fill.Add(Instruction.Create(OpCodes.Ldnull)); fill.Add(Instruction.Create(OpCodes.Ret)); }); m.EndEdit(); }
/// <summary> /// Adds code to static Constructor /// <para> /// If Constructor is missing a new one will be created /// </para> /// </summary> /// <param name="body">code to write</param> public static void AddToStaticConstructor(this TypeDefinition typeDefinition, Action <ILProcessor> body) { var cctor = typeDefinition.GetMethod(".cctor"); if (cctor != null) { // remove the return opcode from end of function. will add our own later. if (cctor.Body.Instructions.Count != 0) { var retInstr = cctor.Body.Instructions[cctor.Body.Instructions.Count - 1]; if (retInstr.OpCode == OpCodes.Ret) { cctor.Body.Instructions.RemoveAt(cctor.Body.Instructions.Count - 1); } else { throw new NetworkBehaviourException($"{typeDefinition.Name} has invalid static constructor", cctor, cctor.GetSequencePoint(retInstr)); } } } else { // make one! cctor = typeDefinition.AddMethod(".cctor", MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Static); } var worker = cctor.Body.GetILProcessor(); // add new code to bottom of constructor // todo should we be adding new code to top of function instead? incase user has early return in custom constructor? body.Invoke(worker); // re-add return bececause we removed it earlier worker.Append(worker.Create(OpCodes.Ret)); // in case class had no cctor, it might have BeforeFieldInit, so injected cctor would be called too late typeDefinition.Attributes &= ~TypeAttributes.BeforeFieldInit; }
public static MethodDefinition AddMethod(this TypeDefinition type, string name, MethodAttributes attributes) { return(type.AddMethod(name, attributes, type.Module.Void())); }
public static MethodDefinition AddMethod <T>(this TypeDefinition type, string name, MethodAttributes attributes) { return(type.AddMethod(name, attributes, type.Module.ImportReference(typeof(T)))); }
private MethodDefinition CreateMethod(string fullMethodIndentificator, string originalMethodIndentificator, MethodDefinition originalMethodDefinition, TypeExpression[] args, BaseCallExpression node) { if (!specilizedMethods.ContainsKey(fullMethodIndentificator)) { String methodIndentificator = fullMethodIndentificator.Replace(originalMethodDefinition.FullName, originalMethodDefinition.Identifier); List <MethodDefinition> methods = new List <MethodDefinition>(); foreach (TypeExpression[] listOfArgs in GetTypes(args)) { String currentMethodIdentificator = MethodIndentificator(originalMethodDefinition.FullName, listOfArgs); MethodDefinition md; if (currentMethodIdentificator.Equals(originalMethodIndentificator)) { md = originalMethodDefinition; } else { md = SpecilizeMethod(currentMethodIdentificator, originalMethodDefinition, listOfArgs); } if (md != null && !methods.Any(m => m.ILTypeExpression.Equals(md.ILTypeExpression))) { methods.Add(md); } } MethodType originalMethodType = (MethodType)originalMethodDefinition.TypeExpr; isCurrentMethodDynamic = IsCurrentMethodDynamic(originalMethodType); MethodType newMethodType = new MethodType(originalMethodType.Return); Location location = originalMethodDefinition.IdentifierExp.Location; SingleIdentifierExpression newSingleIdentifierExpression = new SingleIdentifierExpression(methodIndentificator, location); Block newBlock = new Block(location); IList <InvocationExpression> invocations = new List <InvocationExpression>(); IList <CastExpression> castExpressions = new List <CastExpression>(); int methodsCount = 0; foreach (var methodDefinition in methods) { MethodType methodType = (MethodType)methodDefinition.TypeExpr; IList <IsExpression> isExpressions = new List <IsExpression>(); CompoundExpression compoundExpression = new CompoundExpression(location); for (int i = 0; i < methodDefinition.ParametersInfo.Count; i++) { SingleIdentifierExpression identifier = new SingleIdentifierExpression(methodDefinition.ParametersInfo[i].Identifier, location); identifier.IndexOfSSA = 0; if (args[i] is UnionType || (args[i] is TypeVariable && ((TypeVariable)args[i]).Substitution is UnionType)) { IsExpression isExpression = new IsExpression(identifier, methodType.GetParameter(i).Freeze().ILType(), location); isExpression.TypeExpr = methodType.GetParameter(i).Freeze(); isExpressions.Add(isExpression); CastExpression castExpression = new CastExpression(isExpression.TypeExpr.ILType(), identifier, location); castExpressions.Add(castExpression); castExpression.CastType = isExpression.TypeExpr; compoundExpression.AddExpression(castExpression); } else { compoundExpression.AddExpression(identifier); } } Expression condition = isExpressions[0]; if (isExpressions.Count > 1) { for (int i = 1; i < isExpressions.Count; i++) { condition = new LogicalExpression(condition, isExpressions[i], LogicalOperator.And, location); } } InvocationExpression invocationExpression = new InvocationExpression(methodDefinition.IdentifierExp, compoundExpression, location); invocations.Add(invocationExpression); ReturnStatement returnStatement = new ReturnStatement(invocationExpression, location); if (++methodsCount < methods.Count || isCurrentMethodDynamic) { IfElseStatement ifElseStatement = new IfElseStatement(condition, returnStatement, location); newBlock.AddStatement(ifElseStatement); } else if (!isCurrentMethodDynamic) { newBlock.AddStatement(returnStatement); } } //If there is any dynamic union type then it is necessary invoke the original method if (isCurrentMethodDynamic) { CompoundExpression compoundExpression = new CompoundExpression(location); foreach (var parameter in originalMethodDefinition.ParametersInfo) { SingleIdentifierExpression identifier = new SingleIdentifierExpression(parameter.Identifier, location); identifier.IndexOfSSA = 0; compoundExpression.AddExpression(identifier); } newBlock.AddStatement(new ReturnStatement(new InvocationExpression(new SingleIdentifierExpression(originalMethodDefinition.Identifier, location), compoundExpression, location), location)); } MethodDefinition newMethodDefinition = new MethodDefinition(newSingleIdentifierExpression, newBlock, originalMethodDefinition.ReturnTypeInfo, originalMethodDefinition.ParametersInfo, originalMethodDefinition.ModifiersInfo, location); newMethodDefinition.FullName = fullMethodIndentificator; newMethodType.MemberInfo = new AccessModifier(originalMethodType.MemberInfo.Modifiers, newSingleIdentifierExpression.Identifier, newMethodType, false); newMethodType.MemberInfo.Class = originalMethodType.MemberInfo.Class; newMethodType.MemberInfo.TypeDefinition = originalMethodType.MemberInfo.TypeDefinition; for (int i = 0; i < originalMethodType.ParameterListCount; i++) { newMethodType.AddParameter(args[i].Simplify()); } newMethodType.ASTNode = newMethodDefinition; newMethodDefinition.TypeExpr = newMethodType; newMethodDefinition.TypeExpr.BuildFullName(); newMethodDefinition.TypeExpr.BuildTypeExpressionString(4); TypeDefinition originalTypeDefinition = newMethodType.MemberInfo.TypeDefinition; originalTypeDefinition.AddMethod(newMethodDefinition); UserType originalClass = newMethodType.MemberInfo.Class; originalClass.AddMember(methodIndentificator, newMethodType.MemberInfo); newMethodDefinition.Accept(new VisitorSymbolIdentification(null), null); bool previousDynamism = DynVarOptions.Instance.EverythingDynamic; DynVarOptions.Instance.EverythingDynamic = false; newMethodDefinition.Accept(visitorTypeInference, null); DynVarOptions.Instance.EverythingDynamic = previousDynamism; foreach (var invocation in invocations) { if (invocation.ActualMethodCalled is UnionType) { invocation.ActualMethodCalled = ((UnionType)invocation.ActualMethodCalled).TypeSet[1]; } } foreach (var castExpression in castExpressions) { ((SingleIdentifierExpression)castExpression.Expression).FrozenTypeExpression = new ClassType("System.Object"); castExpression.Expression.ExpressionType = new ClassType("System.Object"); } specilizedMethods.Add(fullMethodIndentificator, newMethodDefinition); return(newMethodDefinition); } return(specilizedMethods[fullMethodIndentificator]); }
static public MethodDefinition AddEmptyMethod(this TypeDefinition item, MethodDefinition method) { return(item.AddMethod(method, new Instruction[] { Instruction.Create(OpCodes.Ret) })); }
public override Object Visit(MethodDefinition node, Object obj) { typeVariableMappings = new Dictionary <TypeVariable, TypeVariable>(); typeExpresionVariableMapping = new Dictionary <TypeExpression, TypeExpression>(); var previouslyUnified = new List <Pair <TypeExpression, TypeExpression> >(); MethodType originalMethodType = (MethodType)node.TypeExpr; TypeExpression[] args = (TypeExpression[])obj; TypeExpression[] clonedArgs = new TypeExpression[args.Count()]; List <Parameter> clonedParametersInfo = new List <Parameter>(); for (int i = 0; i < node.ParametersInfo.Count; i++) { Parameter originalParameter = node.ParametersInfo[i]; TypeExpression originalParamType = originalMethodType.GetParameter(i); if (originalParamType is TypeVariable) { TypeVariable clonedParamType = (TypeVariable)originalParamType.CloneType(typeVariableMappings); if (clonedParamType.EquivalenceClass != null) { clonedParamType.EquivalenceClass.add(args[i], SortOfUnification.Override, previouslyUnified); typeExpresionVariableMapping.Add(originalParamType, clonedParamType); originalParamType = clonedParamType; } else { typeExpresionVariableMapping.Add(originalParamType, args[i]); originalParamType = args[i]; } } originalParamType.ValidTypeExpression = false; clonedArgs[i] = originalParamType.Simplify(); var parameter = new Parameter() { Identifier = originalParameter.Identifier, Column = originalParameter.Column, Line = originalParameter.Line, ParamType = clonedArgs[i].typeExpression }; if (parameter.ParamType == null || !originalParameter.ILName.Equals(parameter.ILName)) { var rebuildParamType = clonedArgs[i].ToString(); parameter.ParamType = clonedArgs[i].typeExpression; } clonedParametersInfo.Add(parameter); } foreach (var constraint in originalMethodType.Constraints.Constraints) { if (constraint is CloneConstraint) { CloneConstraint cc = constraint as CloneConstraint; if (typeExpresionVariableMapping.ContainsKey(cc.FirstOperand)) { typeExpresionVariableMapping.Add(cc.ReturnType, typeExpresionVariableMapping[cc.FirstOperand]); } } } MethodType clonedMethodType = new MethodType(originalMethodType.Return.CloneType(typeVariableMappings, typeExpresionVariableMapping)); currentMethodType = clonedMethodType; SingleIdentifierExpression clonedSingleIdentifierExpression = new SingleIdentifierExpression(node.IdentifierExp.Identifier, node.IdentifierExp.Location); Block clonedBlock = (Block)node.Body.Accept(this, null); MethodDefinition clonedMethodDefinition = null; if (node is ConstructorDefinition) { clonedMethodDefinition = new ConstructorDefinition(clonedSingleIdentifierExpression, node.ModifiersInfo, clonedParametersInfo, null, clonedBlock, node.Location); } else { clonedMethodDefinition = new MethodDefinition(clonedSingleIdentifierExpression, clonedBlock, clonedMethodType.Return.typeExpression, clonedParametersInfo, node.ModifiersInfo, node.Location); } clonedMethodDefinition.FullName = node.FullName; clonedMethodType.MemberInfo = new AccessModifier(originalMethodType.MemberInfo.Modifiers, clonedSingleIdentifierExpression.Identifier, clonedMethodType, false); clonedMethodType.MemberInfo.Class = originalMethodType.MemberInfo.Class; clonedMethodType.MemberInfo.TypeDefinition = originalMethodType.MemberInfo.TypeDefinition; for (int i = 0; i < originalMethodType.ParameterListCount; i++) { clonedMethodType.AddParameter(clonedArgs[i]); } clonedMethodType.ASTNode = clonedMethodDefinition; clonedMethodDefinition.TypeExpr = clonedMethodType; var previousShowMessages = ErrorManager.Instance.ShowMessages; ErrorManager.Instance.UnNotifiedErrors = false; ErrorManager.Instance.ShowMessages = false; clonedMethodDefinition.Accept(this.visitorSpecializer.visitorTypeInference, null); ErrorManager.Instance.ShowMessages = previousShowMessages; if (ErrorManager.Instance.UnNotifiedErrors) { ErrorManager.Instance.UnNotifiedErrors = false; return(null); } TypeDefinition originalTypeDefinition = clonedMethodType.MemberInfo.TypeDefinition; originalTypeDefinition.AddMethod(clonedMethodDefinition); UserType originalClass = clonedMethodType.MemberInfo.Class; AccessModifier am = originalClass.Members[clonedMethodDefinition.Identifier]; IntersectionMemberType intersectionMemberType = am.Type as IntersectionMemberType; if (intersectionMemberType != null) { intersectionMemberType.TypeSet.Add(clonedMethodType); } else { am = clonedMethodType.MemberInfo; IntersectionMemberType intersection = new IntersectionMemberType(); intersection.TypeSet.Add(originalMethodType); intersection.TypeSet.Add(clonedMethodType); am.Type = intersection; originalClass.Members[clonedMethodDefinition.Identifier] = am; } clonedMethodDefinition.IdentifierExp.ExpressionType = clonedMethodDefinition.TypeExpr; return(clonedMethodDefinition); }
public static MethodDefinition AddMethod(this TypeDefinition typeDefinition, string name, MethodAttributes attributes, Type returnType) => typeDefinition.AddMethod(name, attributes, typeDefinition.Module.ImportReference(returnType));