Пример #1
0
            /// <summary>
            /// Inject initialization code to the given ctor
            /// </summary>
            private static void InjectInitializationCode(MethodDefinition ctor, IEnumerable <FieldDefinition> structFields)
            {
                // Create sequence
                var initSeq = StructFields.CreateInitializationCode(structFields, true);

                // Find location where to insert
                var body = ctor.Body;

                // Insert at start of method
                initSeq.InsertTo(0, body);
            }
Пример #2
0
            /// <summary>
            /// Inject initialization code to the given ctor
            /// </summary>
            private static void InjectInitializationCode(MethodDefinition ctor, IEnumerable <FieldDefinition> structFields)
            {
                // Create sequence
                var initSeq = StructFields.CreateInitializationCode(structFields, false);

                // Find location where to insert
                var body         = ctor.Body;
                var baseCtorCall = body.Instructions.FirstOrDefault(x => IsBaseOrThisCtorCall(ctor, x));

                if (baseCtorCall != null)
                {
                    // Insert after call to base/this ctor
                    initSeq.InsertToAfter(baseCtorCall, body);
                }
                else
                {
                    // Insert at start of method
                    initSeq.InsertTo(0, body);
                }
            }
            /// <summary>
            /// Create default ctors for reachable structs.
            /// </summary>
            public void Convert(ReachableContext reachableContext)
            {
                // Collect all type
                var todoTypes = reachableContext.ReachableTypes.Where(x => x.IsValueType && !x.IsPrimitive && !x.IsEnum).ToList();

                if (todoTypes.Count == 0)
                {
                    return;
                }

                foreach (var type in todoTypes)
                {
                    if (!HasDefaultCtor(type))
                    {
                        CreateDefaultCtor(reachableContext, type);
                    }

                    if (StructFields.IsImmutableStruct(type) && !type.HasGenericParameters)
                    {
                        CreateDefaultField(reachableContext, type);
                    }
                }
            }
Пример #4
0
 /// <summary>
 /// Does the given type have any instance field that is a struct?
 /// </summary>
 private static bool HasInstanceStructFields(TypeDefinition type, out List <FieldDefinition> structFields)
 {
     structFields = null;
     if (type.IsEnum) // Class ctor is already created automatically for enums
     {
         return(false);
     }
     if (type.Name.StartsWith("<PrivateImplementationDetails>"))
     {
         return(false);
     }
     foreach (var field in type.Fields.Where(x => !x.IsStatic && x.IsReachable && StructFields.IsStructField(x)))
     {
         if (structFields == null)
         {
             structFields = new List <FieldDefinition>();
         }
         structFields.Add(field);
     }
     return(structFields != null);
 }
Пример #5
0
            /// <summary>
            /// Create a CopyFrom method.
            /// </summary>
            private static MethodDefinition CreateCopyFromMethod(ReachableContext reachableContext, TypeDefinition type)
            {
                var typeSystem  = type.Module.TypeSystem;
                var method      = new MethodDefinition(NameConstants.Struct.CopyFromMethodName, MethodAttributes.Public, type);
                var sourceParam = new ParameterDefinition(type);

                method.Parameters.Add(sourceParam);
                method.DeclaringType = type;

                var body = new MethodBody(method);

                body.InitLocals = true;
                method.Body     = body;

                // Prepare code
                var seq = new ILSequence();

                seq.Emit(OpCodes.Nop);

                // Call base CopyFrom
                var baseType = (type.BaseType != null) ? type.BaseType.GetElementType().Resolve() : null;

                if ((baseType != null) && baseType.IsValueType && (baseType.FullName != "System.ValueType"))
                {
                    var baseMethod = new MethodReference(NameConstants.Struct.CopyFromMethodName, baseType, baseType)
                    {
                        HasThis = true
                    };
                    baseMethod.Parameters.Add(new ParameterDefinition(baseType));
                    seq.Emit(OpCodes.Ldarg, sourceParam);
                    seq.Emit(OpCodes.Call, baseMethod);
                }

                // Copy all fields
                foreach (var field in type.Fields.Where(x => !x.IsStatic))
                {
                    TypeDefinition fieldTypeDef;
                    var            isStructField = StructFields.IsStructField(field, out fieldTypeDef);

                    // Prepare for stfld
                    seq.Emit(OpCodes.Ldarg, body.ThisParameter);

                    // Load from source
                    seq.Emit(OpCodes.Ldarg, sourceParam);
                    seq.Emit(OpCodes.Ldfld, field);

                    // If struct, create clone
                    if (isStructField)
                    {
                        var cloneMethod = new MethodReference(NameConstants.Struct.CloneMethodName, fieldTypeDef, fieldTypeDef)
                        {
                            HasThis = true
                        };
                        seq.Emit(OpCodes.Call, cloneMethod);
                    }

                    // Save in this
                    seq.Emit(OpCodes.Stfld, field);
                }

                // Return this
                seq.Emit(OpCodes.Ldarg, body.ThisParameter);
                seq.Emit(OpCodes.Ret);

                // Append ret sequence
                seq.AppendTo(body);

                // Update offsets
                body.ComputeOffsets();

                // Add method
                type.Methods.Add(method);
                method.SetReachable(reachableContext);

                return(method);
            }