/// <summary>
        /// Try to resolve definition from reference.
        /// </summary>
        internal static PropertyDefinition Resolve(this PropertyReference prop, ReachableContext context)
        {
            var declType = prop.DeclaringType.Resolve(context);
            var resolver = new GenericsResolver(declType);

            return((declType == null) ? null : declType.Properties.FirstOrDefault(x => x.AreSame(prop, resolver.Resolve)));
        }
        /// <summary>
        /// Try to resolve definition from reference.
        /// </summary>
        internal static EventDefinition Resolve(this EventReference evt, ReachableContext context)
        {
            var declType = evt.DeclaringType.Resolve(context);
            var resolver = new GenericsResolver(declType);

            return((declType == null) ? null : declType.Events.FirstOrDefault(x => x.AreSame(evt, resolver.Resolve)));
        }
 /// <summary>
 /// The given type has been made reachable.
 /// </summary>
 internal void IncludeIfNeeded(ReachableContext context)
 {
     if ((typeCondition == null) || (typeCondition.IsReachable))
     {
         member.MarkReachable(context);
     }
 }
            /// <summary>
            /// Implement IAsyncSetThis.
            /// </summary>
            private static void ImplementISetThis(TypeDefinition type, ReachableContext reachableContext)
            {
                var thisField = type.Fields.FirstOrDefault(x => x.Name.StartsWith("<>") && x.Name.EndsWith("__this"));

                if (thisField == null)
                {
                    return;
                }

                // Add interface
                var intfType = type.Module.Import(new TypeReference(InternalConstants.Dot42InternalNamespace, "IAsyncSetThis", type.Module, type.Module.Assembly.Name));

                type.Interfaces.Add(new InterfaceImpl(intfType));

                // Add "SetThis(object)" method
                var method = new MethodDefinition("SetThis", MethodAttributes.Public, type.Module.TypeSystem.Void);

                method.SetReachable(reachableContext);
                type.Methods.Add(method);
                var valueParam = new ParameterDefinition(type.Module.TypeSystem.Object);

                method.Parameters.Add(valueParam);
                method.Body = new MethodBody(method)
                {
                    InitLocals = true
                };
                var seq = new ILSequence();

                seq.Emit(OpCodes.Ldarg_0); // this
                seq.Emit(OpCodes.Ldarg, valueParam);
                seq.Emit(OpCodes.Castclass, thisField.FieldType);
                seq.Emit(OpCodes.Stfld, thisField);
                seq.Emit(OpCodes.Ret);
                seq.AppendTo(method.Body);
            }
        /// <summary>
        /// Try to resolve definition from reference.
        /// </summary>
        internal static MethodDefinition Resolve(this MethodReference method, ReachableContext context)
        {
            var declType = method.DeclaringType.Resolve(context);
            var resolver = new GenericsResolver(declType);

            return((declType == null) ? null : declType.Methods.FirstOrDefault(x => x.AreSame(method, resolver.Resolve)));
        }
Exemple #6
0
        /// <summary>
        /// Walk the given member.
        /// </summary>
        internal static void Walk(ReachableContext context, AbstractReference member)
        {
            if (member == null)
                return;

            ClassFile classFile;
            FieldDefinition field;
            MethodDefinition method;
            TypeReference typeRef;
            if ((classFile = member as ClassFile) != null)
            {
                Walk(context, classFile);
            }
            else if ((method = member as MethodDefinition) != null)
            {
                Walk(context, method);
            }
            else if ((field = member as FieldDefinition) != null)
            {
                Walk(context, field);
            }
            else if ((typeRef = member as TypeReference) != null)
            {
                Walk(context, typeRef);
            }
        }
            /// <summary>
            /// Create the Ctor
            /// </summary>
            private static void CreateDefaultCtor(ReachableContext reachableContext, TypeDefinition type)
            {
                var typeSystem = type.Module.TypeSystem;
                var ctor = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, typeSystem.Void);
                ctor.DeclaringType = type;

                var body = new MethodBody(ctor);
                body.InitLocals = true;
                ctor.Body = body;

                // Prepare code
                var seq = new ILSequence();
                seq.Emit(OpCodes.Nop);
                seq.Emit(OpCodes.Ret);

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

                // Update offsets
                body.ComputeOffsets();

                // Add ctor
                type.Methods.Add(ctor);
                ctor.SetReachable(reachableContext);
            }
Exemple #8
0
        /// <summary>
        /// Mark all eachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, IGenericParameterProvider provider)
        {
            if (provider.HasGenericParameters)
            {
                // Include types needed for generics
                GetDot42InternalType(context, InternalConstants.TypeHelperName).MarkReachable(context);
                var providerAsType = provider as TypeDefinition;
                if ((providerAsType != null) && !providerAsType.IsStatic())
                {
                    GetDot42InternalType(context, InternalConstants.TypeReflectionInfoAnnotation).MarkReachable(context);
                    GetDot42InternalType(context, InternalConstants.GenericTypeParameterAnnotation).MarkReachable(context);
                    GetDot42InternalType(context, InternalConstants.GenericDefinitionAnnotation).MarkReachable(context);
                }
                if (provider is MethodDefinition)
                {
                    GetDot42InternalType(context, InternalConstants.GenericMethodParameterAnnotation).MarkReachable(context);
                    GetDot42InternalType(context, InternalConstants.GenericDefinitionAnnotation).MarkReachable(context);
                }

                // Mark parameters
                foreach (GenericParameter param in provider.GenericParameters)
                {
                    param.MarkReachable(context);
                }
            }
        }
            /// <summary>
            /// Implement IAsyncSetThis.
            /// </summary>
            private static void ImplementISetThis(TypeDefinition type, ReachableContext reachableContext)
            {
                var thisField = type.Fields.FirstOrDefault(x => x.Name.StartsWith("<>") && x.Name.EndsWith("__this"));
                if (thisField == null)
                    return;

                // Add interface
                var intfType = type.Module.Import(new TypeReference(InternalConstants.Dot42InternalNamespace, "IAsyncSetThis", type.Module, type.Module.Assembly.Name));
                type.Interfaces.Add(new InterfaceImpl(intfType));

                // Add "SetThis(object)" method
                var method = new MethodDefinition("SetThis", MethodAttributes.Public, type.Module.TypeSystem.Void);
                method.SetReachable(reachableContext);
                type.Methods.Add(method);
                var valueParam = new ParameterDefinition(type.Module.TypeSystem.Object);
                method.Parameters.Add(valueParam);
                method.Body = new MethodBody(method) { InitLocals = true };
                var seq = new ILSequence();
                seq.Emit(OpCodes.Ldarg_0); // this
                seq.Emit(OpCodes.Ldarg, valueParam);
                seq.Emit(OpCodes.Castclass, thisField.FieldType);
                seq.Emit(OpCodes.Stfld, thisField);
                seq.Emit(OpCodes.Ret);
                seq.AppendTo(method.Body);
            }
Exemple #10
0
        /// <summary>
        /// Mark all base types and externally visible members reachable
        /// </summary>
        private static void Walk(ReachableContext context, TypeReference type)
        {
            if (type == null)
            {
                return;
            }

            if (type.IsArray)
            {
                var aType = (ArrayTypeReference)type;
                Walk(context, aType.ElementType);
            }
            else if (type.IsObjectType)
            {
                var oType = (ObjectTypeReference)type;
                foreach (var typeArg in oType.Arguments)
                {
                    Walk(context, typeArg.Signature);
                }
                ClassFile classFile;
                if (context.TryLoadClass(oType.ClassName, out classFile))
                {
                    classFile.MarkReachable(context);
                }
            }
            else if (type.IsBaseType || type.IsVoid || type.IsTypeVariable)
            {
                // Not need to mark anything
            }
            else
            {
                throw new ArgumentException("Unknown type: " + type);
            }
        }
Exemple #11
0
        /// <summary>
        /// The given type has been made reachable.
        /// </summary>
        /// <returns>True if the type was marked reachable, false otherwise</returns>
        public bool IncludeIfNeeded(ReachableContext context, TypeDefinition type, TypeDefinition dot42IncludeType)
        {
            if (_pattern == null)
                return false;

            return ApplyByPattern.Apply(_pattern, type, member => Include(member, context, dot42IncludeType));
        }
Exemple #12
0
        /// <summary>
        /// Walk the given member.
        /// </summary>
        internal static void Walk(ReachableContext context, AbstractReference member)
        {
            if (member == null)
            {
                return;
            }

            ClassFile        classFile;
            FieldDefinition  field;
            MethodDefinition method;
            TypeReference    typeRef;

            if ((classFile = member as ClassFile) != null)
            {
                Walk(context, classFile);
            }
            else if ((method = member as MethodDefinition) != null)
            {
                Walk(context, method);
            }
            else if ((field = member as FieldDefinition) != null)
            {
                Walk(context, field);
            }
            else if ((typeRef = member as TypeReference) != null)
            {
                Walk(context, typeRef);
            }
        }
        /// <summary>
        /// The given type has been made reachable.
        /// </summary>
        /// <returns>True if the type was marked reachable, false otherwise</returns>
        internal bool IncludeIfNeeded(ReachableContext context, TypeDefinition type)
        {
            if (type.IsReachable)
                return true; // Already included

            if (instanceOfCondition.IsInterface)
            {
                // Check implements
                if (Implements(context, type))
                {
                    type.MarkReachable(context);
                    return true;
                }
            }
            else
            {
                // Check extends
                if (Extends(context, type))
                {
                    type.MarkReachable(context);
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// The given type has been made reachable.
        /// </summary>
        /// <returns>True if the class was marked reachable, false otherwise</returns>
        internal bool IncludeIfNeeded(ReachableContext context, ClassFile javaClass)
        {
            if (javaClass.IsReachable)
                return true; // Already included
            if (className == null)
                return false;

            if (instanceOfCondition.IsInterface)
            {
                // Check implements
                if (Implements(context, javaClass))
                {
                    javaClass.MarkReachable(context);
                    return true;
                }
            }
            else
            {
                // Check extends
                if (Extends(javaClass))
                {
                    javaClass.MarkReachable(context);
                    return true;
                }
            }
            return false;
        }
Exemple #15
0
 /// <summary>
 /// Mark all properties with the given name reachable.
 /// </summary>
 internal static void MarkPropertiesReachable(this TypeReference type, string propertyName, ReachableContext context)
 {
     while ((type != null) && (context.Contains(type)))
     {
         TypeDefinition typeDef = context.GetTypeDefinition(type);
         if (typeDef != null)
         {
             if (typeDef.HasProperties)
             {
                 foreach (PropertyDefinition prop in typeDef.Properties)
                 {
                     if (prop.Name == propertyName)
                     {
                         prop.MarkReachable(context);
                     }
                 }
             }
             type = typeDef.BaseType;
         }
         else
         {
             type = null;
         }
     }
 }
 /// <summary>
 /// Implement IAsyncSetThis where needed.
 /// </summary>
 public void Convert(ReachableContext reachableContext)
 {
     foreach (var type in reachableContext.ReachableTypes.Where(IsAsyncStateMachine))
     {
         ImplementISetThis(type, reachableContext);
     }
 }
Exemple #17
0
        /// <summary>
        /// Mark all eachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, ClassFile classFile)
        {
            // Mark owner
            classFile.DeclaringClass.MarkReachable(context);

            // Mark base class
            classFile.SuperClass.MarkReachable(context);

            // Mark interfaces
            if (classFile.Interfaces != null)
            {
                foreach (var intf in classFile.Interfaces)
                {
                    intf.MarkReachable(context);
                }
            }

            // Mark class ctor
            classFile.Methods.FirstOrDefault(x => x.Name == "<clinit>").MarkReachable(context);

            // Mark methods of imported classes reachable
            if (classFile.IsCreatedByLoader)
            {
                classFile.Methods.Where(x => x.IsPublic || x.IsProtected).ForEach(x => x.MarkReachable(context));
            }

            // If this is a class that does not have an imported C# wrapper, be safe and include everything from this class.
            if (!context.HasDexImport(classFile))
            {
                context.MarkAsRoot(classFile);
            }

            // Record in context
            context.RecordReachableType(classFile);
        }
Exemple #18
0
            /// <summary>
            /// Make sure all struct fields are initialized in the ctors that need them.
            /// </summary>
            private static void InitializeStructFields(ReachableContext reachableContext, TypeDefinition type, List <FieldDefinition> structFields)
            {
                List <Tuple <MethodDefinition, HashSet <FieldDefinition> > > ctorsToExtend = null;

                foreach (var ctor in type.Methods.Where(x => x.IsConstructor && !x.IsStatic && x.HasBody))
                {
                    HashSet <FieldDefinition> storedFields;
                    if (!NeedsStructInitialization(ctor, structFields, out storedFields))
                    {
                        continue;
                    }

                    // Extend this ctor to initialize all struct fields.
                    if (ctorsToExtend == null)
                    {
                        ctorsToExtend = new List <Tuple <MethodDefinition, HashSet <FieldDefinition> > >();
                    }
                    ctorsToExtend.Add(Tuple.Create(ctor, storedFields));
                }

                if (ctorsToExtend == null)
                {
                    // No ctors need additional initialization
                    return;
                }

                // Inject initialization code
                foreach (var tuple in ctorsToExtend)
                {
                    var ctor         = tuple.Item1;
                    var storedFields = tuple.Item2;
                    InjectInitializationCode(ctor, structFields.Except(storedFields));
                }
            }
            /// <summary>
            /// Add bridge methods when a method with a non-generic parameter overrides a method with a generic parameter.
            /// </summary>
            public void Convert(ReachableContext reachableContext)
            {
                this.reachableContext = reachableContext;

                // Initialize some sets
                reachableMethods = reachableContext.ReachableTypes.Where(x => !x.HasDexImportAttribute())
                                                                  .SelectMany(x => x.Methods)
                                                                  .Where(m => m.IsReachable)
                                                                  .ToList();

                // Do we need to convert anything?
                foreach (var method in reachableMethods)
                {
                    MethodDefinition baseMethod;
                    if (!NeedsBridge(method, out baseMethod))
                        continue;

                    // Add bridge
                    var bridge = AddBridge(method, baseMethod);

                    // Remove bridge if is has an exact duplicate
                    var duplicate = method.DeclaringType.Methods.FirstOrDefault(x => (x != bridge) && x.AreSame(bridge, null));
                    if (duplicate != null)
                    {
                        bridge.DeclaringType.Methods.Remove(bridge);
                    }
                }
            }
            /// <summary>
            /// Ensure there is a class ctor.
            /// </summary>
            private static MethodDefinition EnsureClassCtor(ReachableContext reachableContext, TypeDefinition type)
            {
                var ctor = type.GetClassCtor();
                if (ctor != null)
                    return ctor; // Already exists

                // Create class ctor
                var typeSystem = type.Module.TypeSystem;
                ctor = new MethodDefinition(".cctor", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Static | MethodAttributes.SpecialName, typeSystem.Void);
                ctor.DeclaringType = type;

                var body = new MethodBody(ctor);
                body.InitLocals = true;
                ctor.Body = body;

                // Prepare code
                var seq = new ILSequence();
                seq.Emit(OpCodes.Nop);
                seq.Emit(OpCodes.Ret);

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

                // Update offsets
                body.ComputeOffsets();

                // Add ctor
                type.Methods.Add(ctor);
                ctor.SetReachable(reachableContext);
                return ctor;
            }
Exemple #21
0
        /// <summary>
        /// Mark all eachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, PropertyReference prop)
        {
            prop.PropertyType.MarkReachable(context);

            // Parameters
            if (prop.Parameters.Count > 0)
            {
                foreach (ParameterDefinition param in prop.Parameters)
                {
                    Walk(context, (ParameterReference)param);
                }
            }

            var propDef = prop as PropertyDefinition;

            if (propDef != null)
            {
                // DO NOT AUTOMATICALLY MAKE GET and SET REACHABLE.
                //propDef.GetMethod.MarkReachable(context);
                //propDef.SetMethod.MarkReachable(context);

                // Custom attributes
                Walk(context, (ICustomAttributeProvider)propDef);
            }
            else
            {
                // Try to resolve
                prop.Resolve(context).MarkReachable(context);
            }
        }
Exemple #22
0
        /// <summary>
        /// Mark all children of the given member
        /// </summary>
        internal static void Walk(ReachableContext context, MemberReference member)
        {
            // Mark declaring type
            member.DeclaringType.MarkReachable(context);

            TypeReference     typeRef;
            MethodReference   methodRef;
            EventReference    eventRef;
            FieldReference    fieldRef;
            PropertyReference propertyRef;

            if ((typeRef = member as TypeReference) != null)
            {
                Walk(context, typeRef);
            }
            else if ((methodRef = member as MethodReference) != null)
            {
                Walk(context, methodRef);
            }
            else if ((eventRef = member as EventReference) != null)
            {
                Walk(context, eventRef);
            }
            else if ((fieldRef = member as FieldReference) != null)
            {
                Walk(context, fieldRef);
            }
            else if ((propertyRef = member as PropertyReference) != null)
            {
                Walk(context, propertyRef);
            }
        }
Exemple #23
0
        /// <summary>
        /// Mark all eachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, FieldReference field)
        {
            // Field type
            field.FieldType.MarkReachable(context);

            var fieldDef = field as FieldDefinition;

            if (fieldDef != null)
            {
                // Custom attributes
                Walk(context, (ICustomAttributeProvider)fieldDef);

                // Walk imported java classes
                CustomAttribute javaImportAttr;
                if ((javaImportAttr = fieldDef.GetJavaImportAttribute()) != null)
                {
                    string className;
                    string memberName;
                    string descriptor;
                    javaImportAttr.GetDexOrJavaImportNames(fieldDef, out memberName, out descriptor, out className);
                    ClassFile javaClass;
                    if (context.TryLoadClass(className, out javaClass))
                    {
                        var javaField = javaClass.Fields.FirstOrDefault(x => (x.Name == memberName) && (x.Descriptor == descriptor));
                        javaClass.MarkReachable(context);
                        javaField.MarkReachable(context);
                    }
                }
            }
            else
            {
                // Try to resolve
                field.Resolve(context).MarkReachable(context);
            }
        }
            /// <summary>
            /// Create the Ctor
            /// </summary>
            private static void CreateDefaultCtor(ReachableContext reachableContext, TypeDefinition type)
            {
                var typeSystem = type.Module.TypeSystem;
                var ctor       = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, typeSystem.Void);

                ctor.DeclaringType = type;

                var body = new MethodBody(ctor);

                body.InitLocals = true;
                ctor.Body       = body;

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

                seq.Emit(OpCodes.Nop);
                seq.Emit(OpCodes.Ret);

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

                // Update offsets
                body.ComputeOffsets();

                // Add ctor
                type.Methods.Add(ctor);
                ctor.SetReachable(reachableContext);
            }
Exemple #25
0
        /// <summary>
        /// Mark all eachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, ClassFile classFile)
        {
            // Mark owner
            classFile.DeclaringClass.MarkReachable(context);

            // Mark base class
            classFile.SuperClass.MarkReachable(context);

            // Mark interfaces
            if (classFile.Interfaces != null)
            {
                foreach (var intf in classFile.Interfaces)
                {
                    intf.MarkReachable(context);
                }
            }

            // Mark class ctor
            classFile.Methods.FirstOrDefault(x => x.Name == "<clinit>").MarkReachable(context);

            // Mark methods of imported classes reachable
            if (classFile.IsCreatedByLoader)
            {
                classFile.Methods.Where(x => x.IsPublic || x.IsProtected).ForEach(x => x.MarkReachable(context));
            }

            // If this is a class that does not have an imported C# wrapper, be safe and include everything from this class.
            if (!context.HasDexImport(classFile))
            {
                context.MarkAsRoot(classFile);
            }

            // Record in context
            context.RecordReachableType(classFile);
        }
 /// <summary>
 /// Implement IAsyncSetThis where needed.
 /// </summary>
 public void Convert(ReachableContext reachableContext)
 {
     foreach (var type in reachableContext.ReachableTypes.Where(IsAsyncStateMachine))
     {
         ImplementISetThis(type, reachableContext);
     }
 }
Exemple #27
0
 /// <summary>
 /// Create static ctors for types that have reachable static enum and/or struct fields.
 /// </summary>
 public void Convert(ReachableContext reachableContext)
 {
     foreach (var type in reachableContext.ReachableTypes.Where(NeedsClassCtor))
     {
         EnsureClassCtor(reachableContext, type);
     }
 }
Exemple #28
0
 /// <summary>
 /// Create static ctors for types that have reachable static enum and/or struct fields.
 /// </summary>
 public void Convert(ReachableContext reachableContext)
 {
     foreach (var type in reachableContext.ReachableTypes.Where(NeedsClassCtor))
     {
         EnsureClassCtor(reachableContext, type);
     }
 }
            /// <summary>
            /// Make sure all struct fields are initialized in the ctors that need them.
            /// </summary>
            private static void InitializeStructFields(ReachableContext reachableContext, TypeDefinition type, List<FieldDefinition> structFields)
            {
                List<Tuple<MethodDefinition, HashSet<FieldDefinition>>> ctorsToExtend = null;
                foreach (var ctor in type.Methods.Where(x => x.IsConstructor && !x.IsStatic && x.HasBody))
                {
                    HashSet<FieldDefinition> storedFields;
                    if (!NeedsStructInitialization(ctor, structFields, out storedFields))
                        continue;

                    // Extend this ctor to initialize all struct fields.
                    if (ctorsToExtend == null) 
                        ctorsToExtend = new List<Tuple<MethodDefinition, HashSet<FieldDefinition>>>();
                    ctorsToExtend.Add(Tuple.Create(ctor, storedFields));
                }

                if (ctorsToExtend == null)
                {
                    // No ctors need additional initialization
                    return;
                }

                // Inject initialization code
                foreach (var tuple in ctorsToExtend)
                {
                    var ctor = tuple.Item1;
                    var storedFields = tuple.Item2;
                    InjectInitializationCode(ctor, structFields.Except(storedFields));
                }
            }
            /// <summary>
            /// Add bridge methods when a method with a non-generic parameter overrides a method with a generic parameter.
            /// </summary>
            public void Convert(ReachableContext reachableContext)
            {
                this.reachableContext = reachableContext;

                // Initialize some sets
                reachableMethods = reachableContext.ReachableTypes.Where(x => !x.HasDexImportAttribute()).SelectMany(x => x.Methods).Where(m => m.IsReachable).OrderBy(x => x.FullName).ToList();

                // Do we need to convert anything?
                foreach (var method in reachableMethods)
                {
                    MethodDefinition baseMethod;
                    if (!NeedsBridge(method, out baseMethod))
                    {
                        continue;
                    }

                    // Add bridge
                    var bridge = AddBridge(method, baseMethod);

                    // Remove bridge if is has an exact duplicate
                    var duplicate = method.DeclaringType.Methods.FirstOrDefault(x => (x != bridge) && x.AreSame(bridge, null));
                    if (duplicate != null)
                    {
                        bridge.DeclaringType.Methods.Remove(bridge);
                    }
                }
            }
Exemple #31
0
        /// <summary>
        /// Mark all base types and externally visible members reachable
        /// </summary>
        private static void Walk(ReachableContext context, TypeReference type)
        {
            if (type == null)
                return;

            if (type.IsArray)
            {
                var aType = (ArrayTypeReference)type;
                Walk(context, aType.ElementType);
            }
            else if (type.IsObjectType)
            {
                var oType = (ObjectTypeReference)type;
                foreach (var typeArg in oType.Arguments)
                {
                    Walk(context, typeArg.Signature);
                }
                ClassFile classFile;
                if (context.TryLoadClass(oType.ClassName, out classFile))
                {
                    classFile.MarkReachable(context);
                }
            }
            else if (type.IsBaseType || type.IsVoid || type.IsTypeVariable)
            {
                // Not need to mark anything
            }
            else
            {
                throw new ArgumentException("Unknown type: " + type);
            }
        }
Exemple #32
0
        /// <summary>
        /// Mark all eachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, MethodDefinition method)
        {
            method.DeclaringClass.MarkReachable(context);
            method.ReturnType.MarkReachable(context);

            // All parameters
            foreach (var param in method.Parameters)
            {
                param.MarkReachable(context);
            }

            // Base methods
            if (!method.IsStatic && !method.IsFinal)
            {
                MethodDefinition baseMethod;
                if ((baseMethod = method.GetBaseMethod()) != null)
                {
                    if (context.Contains(baseMethod.DeclaringClass))
                    {
                        baseMethod.MarkReachable(context);
                    }
                }
            }

            Walk(context, method.Body);
        }
Exemple #33
0
 /// <summary>
 /// Create a type builder for the given type.
 /// </summary>
 internal static IClassBuilder[] Create(ReachableContext context, AssemblyCompiler compiler, TypeDefinition typeDef)
 {
     if (typeDef.FullName == "<Module>")
         return new IClassBuilder[] { new SkipClassBuilder() };
     if (typeDef.IsDelegate())
         return new IClassBuilder[] {new DelegateClassBuilder(context, compiler, typeDef) };
     if (typeDef.IsAttribute()) 
         return new IClassBuilder[]  {new AttributeClassBuilder(context, compiler, typeDef) };
     if (typeDef.IsAnnotation())
         return new IClassBuilder[] {new AnnotationClassBuilder(context, compiler, typeDef) };
     if (typeDef.HasDexImportAttribute())
         return new IClassBuilder[] {new DexImportClassBuilder(context, compiler, typeDef) };
     if (typeDef.HasJavaImportAttribute())
         return new IClassBuilder[] {CreateJavaImportBuilder(context, compiler, typeDef)};
     if (typeDef.IsEnum)
     {
         if (typeDef.UsedInNullableT)
         {
             var nullableBaseClassBuilder = new NullableEnumBaseClassBuilder(context, compiler, typeDef);
             IClassBuilder builder = new EnumClassBuilder(context, compiler, typeDef, nullableBaseClassBuilder);
             return new[] { builder, nullableBaseClassBuilder };
         }
         return new IClassBuilder[] { new EnumClassBuilder(context, compiler, typeDef, null) };
     }
     else
     {
         IClassBuilder builder = new StandardClassBuilder(context, compiler, typeDef);
         if (typeDef.UsedInNullableT)
             return new[] { builder, new NullableBaseClassBuilder(context, compiler, typeDef) };
         return new[] { builder };
     }
 }
Exemple #34
0
        /// <summary>
        /// Mark all eachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, CodeAttribute code)
        {
            if (code == null)
            {
                return;
            }

            // Exception handlers
            foreach (var handler in code.ExceptionHandlers)
            {
                handler.CatchType.MarkReachable(context);
            }

            // Local variables

            /*foreach (var var in code.Variables)
             *  {
             *      var.VariableType.MarkReachable(context);
             *  }*/

            // Instructions
            foreach (var ins in code.Instructions)
            {
                object operand = ins.Operand;
                if (operand != null)
                {
                    ConstantPoolClass     cpClass;
                    ConstantPoolFieldRef  cpField;
                    ConstantPoolMethodRef cpMethod;

                    if ((cpClass = operand as ConstantPoolClass) != null)
                    {
                        ClassFile cf;
                        if (cpClass.TryResolve(out cf))
                        {
                            cf.MarkReachable(context);
                        }
                    }
                    else if ((cpField = operand as ConstantPoolFieldRef) != null)
                    {
                        FieldDefinition fieldDef;
                        if (cpField.TryResolve(out fieldDef))
                        {
                            fieldDef.MarkReachable(context);
                        }
                    }
                    else if ((cpMethod = operand as ConstantPoolMethodRef) != null)
                    {
                        MethodDefinition method;
                        if (cpMethod.TryResolve(out method))
                        {
                            method.MarkReachable(context);
                        }
                        else
                        {
                        }
                    }
                }
            }
        }
Exemple #35
0
 /// <summary>
 /// Mark all fields with the given name reachable.
 /// </summary>
 internal static void MarkFieldsReachable(this TypeReference type, string fieldName, ReachableContext context)
 {
     while ((type != null) && (context.Contains(type)))
     {
         TypeDefinition typeDef = context.GetTypeDefinition(type);
         if (typeDef != null)
         {
             if (typeDef.HasFields)
             {
                 foreach (FieldDefinition field in typeDef.Fields)
                 {
                     if (field.Name == fieldName)
                     {
                         field.MarkReachable(context);
                     }
                 }
             }
             type = typeDef.BaseType;
         }
         else
         {
             type = null;
         }
     }
 }
Exemple #36
0
        /// <summary>
        /// Mark all children of the given member
        /// </summary>
        internal static void Walk(ReachableContext context, MemberReference member)
        {
            // Mark declaring type
            member.DeclaringType.MarkReachable(context);

            TypeReference typeRef;
            MethodReference methodRef;
            EventReference eventRef;
            FieldReference fieldRef;
            PropertyReference propertyRef;

            if ((typeRef = member as TypeReference) != null)
            {
                Walk(context, typeRef);
            }
            else if ((methodRef = member as MethodReference) != null)
            {
                Walk(context, methodRef);
            }
            else if ((eventRef = member as EventReference) != null)
            {
                Walk(context, eventRef);
            }
            else if ((fieldRef = member as FieldReference) != null)
            {
                Walk(context, fieldRef);
            }
            else if ((propertyRef = member as PropertyReference) != null)
            {
                Walk(context, propertyRef);
            }
        }
            /// <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))
                {
                    // Not need to bother with cloning struct-type fields here, 
                    // as this will be done automatically by one of the Converters.

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

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

                    // 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;
            }        
Exemple #38
0
 /// <summary>
 /// Convert all constructs of IL that are not compatible with java.
 /// </summary>
 internal static void Convert(ReachableContext reachableContext)
 {
     foreach (var factory in ConverterFactories)
     {
         var converter = factory.Create();
         converter.Convert(reachableContext);
     }
 }
Exemple #39
0
 /// <summary>
 /// Mark all children of the given assembly
 /// </summary>
 internal static void Walk(ReachableContext context, AssemblyDefinition assembly)
 {
     Walk(context, (ICustomAttributeProvider)assembly);
     foreach (ModuleDefinition mod in assembly.Modules)
     {
         Walk(context, (ICustomAttributeProvider)mod);
     }
 }
            private void CreateDefaultField(ReachableContext reachableContext, TypeDefinition type)
            {
                // create the field
                var field = new FieldDefinition(NameConstants.Struct.DefaultFieldName, FieldAttributes.InitOnly | FieldAttributes.Static | FieldAttributes.Public, type);

                type.Fields.Add(field);
                field.SetReachable(reachableContext, true);
            }
 /// <summary>
 /// Create static ctors for types that have dllimport methods.
 /// </summary>
 public void Convert(ReachableContext reachableContext)
 {
     foreach (var type in reachableContext.ReachableTypes.Where(NeedsClassCtor))
     {
         var classCtor = EnsureClassCtor(reachableContext, type);
         AddLoadLibraryCalls(type, classCtor);
     }
 }
Exemple #42
0
 /// <summary>
 /// Convert all constructs of IL that are not compatible with java.
 /// </summary>
 internal static void Convert(ReachableContext reachableContext)
 {
     foreach (var factory in ConverterFactories)
     {
         var converter = factory.Create();
         converter.Convert(reachableContext);
     }
 }
Exemple #43
0
 /// <summary>
 /// Create static ctors for types that have dllimport methods.
 /// </summary>
 public void Convert(ReachableContext reachableContext)
 {
     foreach (var type in reachableContext.ReachableTypes.Where(NeedsClassCtor))
     {
         var classCtor = EnsureClassCtor(reachableContext, type);
         AddLoadLibraryCalls(type, classCtor);
     }
 }
Exemple #44
0
 /// <summary>
 /// Mark all children of the given assembly
 /// </summary>
 internal static void Walk(ReachableContext context, AssemblyDefinition assembly)
 {
     Walk(context, (ICustomAttributeProvider) assembly);
     foreach (ModuleDefinition mod in assembly.Modules)
     {
         Walk(context, (ICustomAttributeProvider) mod);
     }
 }
 /// <summary>
 /// Should the given method be included in the APK?
 /// </summary>
 public bool Include(MethodDefinition method, ReachableContext context)
 {
     if (!(method.HasNUnitTestAttribute() && method.DeclaringType.HasNUnitTestFixtureAttribute()))
         return false;
     // Include the NUnit base class
     var xType = context.Compiler.GetDot42InternalType("Dot42.Test", "NUnitTestCase").Resolve();
     ((TypeDefinition)xType.OriginalTypeDefinition).MarkReachable(context);
     return true;
 }
Exemple #46
0
            /// <summary>
            /// Create static ctors for types that have dllimport methods.
            /// </summary>
            public void Convert(ReachableContext reachableContext)
            {
                var rechableMethods = reachableContext.ReachableTypes.SelectMany(r=>r.Methods)
                                                      .Where(m=> m.IsReachable && m.HasBody);

                foreach (var method in rechableMethods)
                {
                   FixAccesses(method.Body);
                }
            }
Exemple #47
0
 /// <summary>
 /// Create a type builder for the given type with JavaImport attribute.
 /// </summary>
 internal static IClassBuilder CreateJavaImportBuilder(ReachableContext context, AssemblyCompiler compiler, TypeDefinition typeDef)
 {
     var javaImportAttr = typeDef.GetJavaImportAttribute(true);
     var className = (string)javaImportAttr.ConstructorArguments[0].Value;
     ClassFile classFile;
     if (!compiler.ClassLoader.TryLoadClass(className, out classFile))
         throw new ClassNotFoundException(className);
     context.RecordReachableType(classFile);
     return new SkipClassBuilder();
 }
Exemple #48
0
 /// <summary>
 /// Mark all eachable items in argument as such.
 /// </summary>
 private static void Walk(ReachableContext context, IGenericInstance instance)
 {
     if (instance.HasGenericArguments)
     {
         foreach (TypeReference typeRef in instance.GenericArguments)
         {
             typeRef.MarkReachable(context);
         }
     }
 }
 /// <summary>
 /// Should the given method be included in the APK?
 /// </summary>
 public bool Include(MethodDefinition method, ReachableContext context)
 {
     if (!method.IsVirtual)
         return false;
     if (method.GetDexImportBaseMethod() != null)
         return true;
     if (method.GetDexImportBaseInterfaceMethod() != null)
         return true;
     return false;
 }
            /// <summary>
            /// Create static ctors for types that have dllimport methods.
            /// </summary>
            public void Convert(ReachableContext reachableContext)
            {
                var rechableMethods = reachableContext.ReachableTypes.SelectMany(r => r.Methods)
                                      .Where(m => m.IsReachable && m.HasBody);

                foreach (var method in rechableMethods)
                {
                    FixAccesses(method.Body);
                }
            }
 /// <summary>
 /// Extend instance ctors for types that have reachable instance fields of type struct.
 /// </summary>
 public void Convert(ReachableContext reachableContext)
 {
     foreach (var type in reachableContext.ReachableTypes)
     {
         List<FieldDefinition> structFields;
         if (HasInstanceStructFields(type, out structFields))
         {
             InitializeStructFields(reachableContext, type, structFields);
         }
     }
 }
Exemple #52
0
 /// <summary>
 /// Extend instance ctors for types that have reachable instance fields of type struct.
 /// </summary>
 public void Convert(ReachableContext reachableContext)
 {
     foreach (var type in reachableContext.ReachableTypes)
     {
         List <FieldDefinition> structFields;
         if (HasInstanceStructFields(type, out structFields))
         {
             InitializeStructFields(reachableContext, type, structFields);
         }
     }
 }
Exemple #53
0
 /// <summary>
 /// Create a type builder for the given type.
 /// </summary>
 internal static IClassBuilder[] Create(ReachableContext context, AssemblyCompiler compiler, TypeDefinition typeDef)
 {
     if (typeDef.FullName == "<Module>")
     {
         return new IClassBuilder[] { new SkipClassBuilder() }
     }
     ;
     if (typeDef.IsDelegate())
     {
         return new IClassBuilder[] { new DelegateClassBuilder(context, compiler, typeDef) }
     }
     ;
     if (typeDef.IsAttribute())
     {
         return new IClassBuilder[]  { new AttributeClassBuilder(context, compiler, typeDef) }
     }
     ;
     if (typeDef.IsAnnotation())
     {
         return new IClassBuilder[] { new AnnotationClassBuilder(context, compiler, typeDef) }
     }
     ;
     if (typeDef.HasDexImportAttribute())
     {
         return new IClassBuilder[] { new DexImportClassBuilder(context, compiler, typeDef) }
     }
     ;
     if (typeDef.HasJavaImportAttribute())
     {
         return new IClassBuilder[] { CreateJavaImportBuilder(context, compiler, typeDef) }
     }
     ;
     if (typeDef.IsEnum)
     {
         if (typeDef.UsedInNullableT)
         {
             var           nullableBaseClassBuilder = new NullableEnumBaseClassBuilder(context, compiler, typeDef);
             IClassBuilder builder = new EnumClassBuilder(context, compiler, typeDef, nullableBaseClassBuilder);
             return(new[] { builder, nullableBaseClassBuilder });
         }
         return(new IClassBuilder[] { new EnumClassBuilder(context, compiler, typeDef, null) });
     }
     else
     {
         IClassBuilder builder = new StandardClassBuilder(context, compiler, typeDef);
         if (typeDef.UsedInNullableT)
         {
             return new[] { builder, new NullableBaseClassBuilder(context, compiler, typeDef) }
         }
         ;
         return(new[] { builder });
     }
 }
Exemple #54
0
            /// <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 & !HasDefaultCtor(x)).ToList();
                if (todoTypes.Count == 0)
                    return;

                foreach (var type in todoTypes)
                {
                    CreateDefaultCtor(reachableContext, type);
                }
            }
Exemple #55
0
        /// <summary>
        /// Should the given method be included in the APK?
        /// </summary>
        public bool Include(MethodDefinition method, ReachableContext context)
        {
            if (!(method.HasNUnitTestAttribute() && method.DeclaringType.HasNUnitTestFixtureAttribute()))
            {
                return(false);
            }
            // Include the NUnit base class
            var xType = context.Compiler.GetDot42InternalType("Dot42.Test", "NUnitTestCase").Resolve();

            ((TypeDefinition)xType.OriginalTypeDefinition).MarkReachable(context);
            return(true);
        }
Exemple #56
0
 /// <summary>
 /// Mark all eachable items in argument as such.
 /// </summary>
 private static void Walk(ReachableContext context, ICustomAttributeProvider provider)
 {
     if (provider.HasCustomAttributes)
     {
         foreach (var attr in provider.CustomAttributes)
         {
             if (!attr.AttributeType.Resolve().HasIgnoreAttribute())
             {
                 Walk(context, attr);
             }
         }
     }
 }
Exemple #57
0
        /// <summary>
        /// Create a type builder for the given type with JavaImport attribute.
        /// </summary>
        internal static IClassBuilder CreateJavaImportBuilder(ReachableContext context, AssemblyCompiler compiler, TypeDefinition typeDef)
        {
            var       javaImportAttr = typeDef.GetJavaImportAttribute(true);
            var       className      = (string)javaImportAttr.ConstructorArguments[0].Value;
            ClassFile classFile;

            if (!compiler.ClassLoader.TryLoadClass(className, out classFile))
            {
                throw new ClassNotFoundException(className);
            }
            context.RecordReachableType(classFile);
            return(new SkipClassBuilder());
        }
Exemple #58
0
        /// <summary>
        /// Should the given member reference in the given instruction be excluded from being walked?
        /// </summary>
        private static bool ExcludeFromWalking(ReachableContext context, Instruction ins, MemberReference memberReference)
        {
            // Is the given member reference a reference to an array initializer field?
            MethodReference method;

            if (ins.OpCode == OpCodes.Ldtoken)
            {
                var fieldRef = memberReference as FieldReference;
                if (fieldRef == null)
                {
                    return(false);
                }
                var nextIns = ins.Next;
                if (nextIns == null)
                {
                    return(false);
                }
                if (nextIns.OpCode != OpCodes.Call)
                {
                    return(false);
                }
                method = nextIns.Operand as MethodReference;
                if (method == null)
                {
                    return(false);
                }
                return((method.Name == "InitializeArray") &&
                       (method.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers"));
            }
            method = memberReference as MethodReference;
            if (method != null)
            {
                var methodDef = method.Resolve(context);
                if ((methodDef != null) && methodDef.HasDexNativeAttribute())
                {
                    return(true);
                }
            }
            var field = memberReference as FieldReference;

            if (field != null)
            {
                var fieldDef = field.Resolve(context);
                if ((fieldDef != null) && fieldDef.HasResourceIdAttribute())
                {
                    return(true);
                }
            }
            return(false);
        }
            /// <summary>
            /// Create default ctors for reachable structs.
            /// </summary>
            public void Convert(ReachableContext reachableContext)
            {
                // Collect all type
                var todoTypes = reachableContext.ReachableTypes.Where(NeedsSemanticMethods).ToList();
                if (todoTypes.Count == 0)
                    return;

                foreach (var type in todoTypes)
                {
                    // Create methods
                    var copyFromMethod = CreateCopyFromMethod(reachableContext, type);
                    CreateCloneMethod(reachableContext, type, copyFromMethod);
                }
            }
            /// <summary>
            /// Convert calls to android extension ctors.
            /// </summary>
            public void Convert(ReachableContext reachableContext)
            {
                this.reachableContext = reachableContext;

                // Collect all names
                var methodsWithBody =
                    reachableContext.ReachableTypes.SelectMany(x => x.Methods).Where(m => m.HasBody).ToList();
                if (methodsWithBody.Count == 0)
                    return;

                foreach (var method in methodsWithBody)
                {
                    Convert(method.Body);
                }
            }