Esempio n. 1
0
        /// <summary>
        /// Convert node with code Cast.
        /// </summary>
        private static void ConvertCastclass(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference)node.Operand;

            if (type.IsSystemArray())
            {
                // Call cast method
                var arrayHelper     = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var castToArray     = arrayHelper.Methods.First(x => x.Name == "CastToArray");
                var castToArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, castToArray, node.Arguments).SetType(type);
                node.CopyFrom(castToArrayExpr);
                return;
            }

            string castMethod = null;

            if (type.IsSystemCollectionsIEnumerable())
            {
                castMethod = "CastToEnumerable";
            }
            else if (type.IsSystemCollectionsICollection())
            {
                castMethod = "CastToCollection";
            }
            else if (type.IsSystemCollectionsIList())
            {
                castMethod = "CastToList";
            }
            else if (type.IsSystemIFormattable())
            {
                castMethod = "CastToFormattable";
            }

            if (castMethod != null)
            {
                // Call cast method
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var castToArray = arrayHelper.Methods.First(x => x.Name == castMethod);

                // Call "(x instanceof T) ? (T)x : asMethod(x)"

                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, node.Arguments[0]).SetType(typeSystem.Bool);

                // CastX(x)
                var castXExpr = new AstExpression(node.SourceLocation, AstCode.Call, castToArray, node.Arguments[0]).SetType(typeSystem.Object);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, node.Arguments[0]).SetType(type);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, castXExpr).SetType(type);

                node.CopyFrom(conditional);
                return;
            }

            // Normal castclass
            node.Code = AstCode.SimpleCastclass;
        }
Esempio n. 2
0
        public static void CreateAssemblyTypes(AssemblyCompiler compiler, DexTargetPackage targetPackage,
                                               IEnumerable <TypeDefinition> reachableTypes)
        {
            var xAssemblyTypes = compiler.GetDot42InternalType("AssemblyTypes");
            var assemblyTypes  = (ClassDefinition)xAssemblyTypes.GetClassReference(targetPackage);
            var entryAssembly  = assemblyTypes.Fields.First(f => f.Name == "EntryAssembly");
            var iAssemblyTypes = compiler.GetDot42InternalType("IAssemblyTypes").GetClassReference(targetPackage);

            entryAssembly.Value = compiler.Assemblies.First().Name.Name;

            List <object> values           = new List <object>();
            string        prevAssemblyName = null;

            foreach (var type in reachableTypes.OrderBy(t => t.Module.Assembly.Name.Name)
                     .ThenBy(t => t.Namespace)
                     .ThenBy(t => t.Name))
            {
                var assemblyName = type.module.Assembly.Name.Name;
                if (assemblyName == "dot42")
                {
                    // group all android types into virtual "android" assembly,
                    // so that MvvmCross can find all view-types.
                    // -- is this a hack?
                    if (type.Namespace.StartsWith("Android"))
                    {
                        assemblyName = "android";
                    }
                    else // ignore other types, these will get the "default" assembly.
                    {
                        continue;
                    }
                }

                if (prevAssemblyName != assemblyName)
                {
                    values.Add("!" + assemblyName); // we need some identification of assemblies.
                    prevAssemblyName = assemblyName;
                }

                // TODO: With compilationmode=all reachable types contains  <Module>
                //       this should be excluded earlier.
                if (type.FullName == "<Module>")
                {
                    continue;
                }

                var tRef = type.GetReference(targetPackage, compiler.Module) as ClassReference;
                if (tRef != null)
                {
                    values.Add(tRef.Fullname);
                }
            }

            var anno = new Annotation(iAssemblyTypes, AnnotationVisibility.Runtime,
                                      new AnnotationArgument("AssemblyTypeList", values.ToArray()));

            ((IAnnotationProvider)assemblyTypes).Annotations.Add(anno);
        }
Esempio n. 3
0
        /// <summary>
        /// Convert node with code Cast.
        /// </summary>
        private static void ConvertCastclass(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference) node.Operand;
            if (type.IsSystemArray())
            {
                // Call cast method
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var castToArray = arrayHelper.Methods.First(x => x.Name == "CastToArray");
                var castToArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, castToArray, node.Arguments).SetType(type);
                node.CopyFrom(castToArrayExpr);
                return;
            }

            string castMethod = null;
            if (type.IsSystemCollectionsIEnumerable())
            {
                castMethod = "CastToEnumerable";
            }
            else if (type.IsSystemCollectionsICollection())
            {
                castMethod = "CastToCollection";
            }
            else if (type.IsSystemCollectionsIList())
            {
                castMethod = "CastToList";
            }
            else if (type.IsSystemIFormattable())
            {
                castMethod = "CastToFormattable";
            }

            if (castMethod != null)
            {
                // Call cast method
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var castToArray = arrayHelper.Methods.First(x => x.Name == castMethod);

                // Call "(x instanceof T) ? (T)x : asMethod(x)"

                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, node.Arguments[0]).SetType(typeSystem.Bool);

                // CastX(x)
                var castXExpr = new AstExpression(node.SourceLocation, AstCode.Call, castToArray, node.Arguments[0]).SetType(typeSystem.Object);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, node.Arguments[0]).SetType(type);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, castXExpr).SetType(type);

                node.CopyFrom(conditional);
                return;
            }

            // Normal castclass
            node.Code = AstCode.SimpleCastclass;
        }
Esempio n. 4
0
        /// <summary>
        /// Convert node with code InstanceOf.
        /// </summary>
        private static void ConvertInstanceOf(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference)node.Operand;

            if (type.IsSystemArray()) // "is System.Array"
            {
                // Call ArrayHelper.IsArray
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isArray     = arrayHelper.Methods.First(x => x.Name == "IsArray");
                var isArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, isArray, node.Arguments).SetType(typeSystem.Bool);
                node.CopyFrom(isArrayExpr);
                return;
            }

            if (type.IsSystemCollectionsIEnumerable() || type.IsSystemCollectionsICollection() ||
                type.IsSystemCollectionsIList())
            {
                // Call "(is x) || IsArray(x)"
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isArray     = arrayHelper.Methods.First(x => x.Name == "IsArray");

                // "is"
                var isExpr = new AstExpression(node).SetCode(AstCode.SimpleInstanceOf);

                // Call IsArray
                var isArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, isArray, node.Arguments).SetType(typeSystem.Bool);

                // Combined
                var combined = new AstExpression(node.SourceLocation, AstCode.Or, null, isExpr, isArrayExpr).SetType(typeSystem.Bool);
                node.CopyFrom(combined);
                return;
            }
            if (type.IsSystemIFormattable())
            {
                // Call "(is x) || IsFormattable(x)"
                var formattable   = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isFormattable = formattable.Methods.First(x => x.Name == "IsVirtualFormattable");

                // "is"
                var isExpr = new AstExpression(node).SetCode(AstCode.SimpleInstanceOf);

                // Call IsFormattable
                var isFormattableExpr = new AstExpression(node.SourceLocation, AstCode.Call, isFormattable, node.Arguments).SetType(typeSystem.Bool);

                // Combined
                var combined = new AstExpression(node.SourceLocation, AstCode.Or, null, isExpr, isFormattableExpr).SetType(typeSystem.Bool);
                node.CopyFrom(combined);
                return;
            }

            // Normal instanceof
            node.Code = AstCode.SimpleInstanceOf;
        }
Esempio n. 5
0
        public static void CreateAssemblyTypes(AssemblyCompiler compiler, DexTargetPackage targetPackage,
                                               IEnumerable<TypeDefinition> reachableTypes)
        {
            var xAssemblyTypes = compiler.GetDot42InternalType("AssemblyTypes");
            var assemblyTypes = (ClassDefinition)xAssemblyTypes.GetClassReference(targetPackage);
            var entryAssembly = assemblyTypes.Fields.First(f => f.Name == "EntryAssembly");
            var iAssemblyTypes = compiler.GetDot42InternalType("IAssemblyTypes").GetClassReference(targetPackage);
            
            entryAssembly.Value = compiler.Assemblies.First().Name.Name;

            List<object> values = new List<object>();
            string prevAssemblyName = null;

            foreach (var type in reachableTypes.OrderBy(t => t.Module.Assembly.Name.Name)
                                               .ThenBy(t  => t.Namespace)
                                               .ThenBy(t =>  t.Name))
            {
                var assemblyName = type.module.Assembly.Name.Name;
                if (assemblyName == "dot42")
                {
                    // group all android types into virtual "android" assembly,
                    // so that MvvmCross can find all view-types.
                    // -- is this a hack?
                    if (type.Namespace.StartsWith("Android"))
                        assemblyName = "android";
                    else // ignore other types, these will get the "default" assembly.
                        continue;
                }

                if (prevAssemblyName != assemblyName)
                {
                    values.Add("!" + assemblyName); // we need some identification of assemblies.
                    prevAssemblyName = assemblyName;
                }

                // TODO: With compilationmode=all reachable types contains  <Module>
                //       this should be excluded earlier.
                if (type.FullName == "<Module>")
                    continue;

                var tRef = type.GetReference(targetPackage, compiler.Module) as ClassReference;    
                if(tRef != null) values.Add(tRef.Fullname);
            }

            var anno = new Annotation(iAssemblyTypes, AnnotationVisibility.Runtime,
                                      new AnnotationArgument("AssemblyTypeList", values.ToArray()));
            ((IAnnotationProvider)assemblyTypes).Annotations.Add(anno);
        }
        /// <summary>
        /// Build expression that creates an instance of GenericInstance with arguments from the given .NET generic instance.
        /// </summary>
        private static AstExpression CreateGenericInstance(ISourceLocation seqp, XReference member, MethodSource currentMethod, AssemblyCompiler compiler)
        {
            // Prepare
            var genericInstance = member as IXGenericInstance;

            if (genericInstance == null)
            {
#if DEBUG
                //Debugger.Launch();
#endif
                throw new CompilerException(string.Format("{0} is not a generic instance", member));
            }
            var count          = genericInstance.GenericArguments.Count;
            var typeHelperType = compiler.GetDot42InternalType(InternalConstants.TypeHelperName).Resolve();

            // Foreach type argument
            var typeExpressions = new List <AstExpression>();
            for (var i = 0; i < count; i++)
            {
                var argType  = genericInstance.GenericArguments[i];
                var typeExpr = LoadTypeForGenericInstance(seqp, currentMethod, argType, typeHelperType, compiler.Module.TypeSystem);
                typeExpressions.Add(typeExpr);
            }

            var elementType = compiler.Module.TypeSystem.Type;
            return(new AstExpression(seqp, AstCode.InitArrayFromArguments, new XArrayType(elementType), typeExpressions)
            {
                ExpectedType = new XArrayType(elementType)
            });
        }
Esempio n. 7
0
 /// <summary>
 /// Create annotations for all included attributes
 /// </summary>
 public static void Create(AssemblyCompiler compiler, ICustomAttributeProvider attributeProvider,
                           IAnnotationProvider annotationProvider, DexTargetPackage targetPackage, bool customAttributesOnly = false)
 {
     if (!attributeProvider.HasCustomAttributes)
         return;
     var annotations = new List<Annotation>();
     foreach (var attr in attributeProvider.CustomAttributes)
     {
         var attributeType = attr.AttributeType.Resolve();
         if (!attributeType.HasIgnoreAttribute())
         {
             Create(compiler, attr, attributeType, annotations, targetPackage);
         }
     }
     if (annotations.Count > 0)
     {
         // Create 1 IAttributes annotation
         var attrsAnnotation = new Annotation { Visibility = AnnotationVisibility.Runtime };
         attrsAnnotation.Type = compiler.GetDot42InternalType("IAttributes").GetClassReference(targetPackage);
         attrsAnnotation.Arguments.Add(new AnnotationArgument("Attributes", annotations.ToArray()));
         annotationProvider.Annotations.Add(attrsAnnotation);
     }
     if (!customAttributesOnly)
     {
         // Add annotations specified using AnnotationAttribute
         foreach (var attr in attributeProvider.CustomAttributes.Where(IsAnnotationAttribute))
         {
             var annotationType = (TypeReference) attr.ConstructorArguments[0].Value;
             var annotationClass = annotationType.GetClassReference(targetPackage, compiler.Module);
             annotationProvider.Annotations.Add(new Annotation(annotationClass, AnnotationVisibility.Runtime));
         }
     }
 }
Esempio n. 8
0
        /// <summary>
        /// Create the body of the unbox(object) method.
        /// </summary>
        private AstBlock CreateUnboxBody(XSyntheticMethodDefinition method, bool isWide, AssemblyCompiler compiler)
        {
            // Prepare
            var loc = AstNode.NoSource;
            Func <AstExpression> ldValue = () => new AstExpression(loc, AstCode.Ldloc, method.AstParameters[0]);
            var afterMyEnum = new AstLabel(loc, "_afterMyEnum");

            // value instanceof MyEnumType?
            var ifNotInstanceOfMyEnum = new AstExpression(loc, AstCode.Brfalse, afterMyEnum, new AstExpression(loc, AstCode.SimpleInstanceOf, XType, ldValue()));
            var returnMyEnum          = new AstExpression(loc, AstCode.Ret, null, new AstExpression(loc, AstCode.SimpleCastclass, XType, ldValue()));

            // boxToMyEnum(UnboxInteger(value))
            var boxingType         = compiler.GetDot42InternalType("Boxing").Resolve();
            var unboxNumericMethod = boxingType.Methods.First(x => x.Name == (isWide ? "UnboxLong" : "UnboxInteger"));
            var unboxToNumeric     = new AstExpression(loc, AstCode.Call, unboxNumericMethod, ldValue());
            var numericToMyEnum    = new AstExpression(loc, isWide ? AstCode.Long_to_enum : AstCode.Int_to_enum, XType, unboxToNumeric).SetType(XType);
            var returnX            = new AstExpression(loc, AstCode.Ret, null, numericToMyEnum);

            var ast = new AstBlock(loc, new AstNode[] {
                ifNotInstanceOfMyEnum,
                returnMyEnum,
                afterMyEnum,
                returnX
            });

            return(ast);
        }
Esempio n. 9
0
        /// <summary>
        /// Convert  ret or store field node.
        ///
        /// converts to IEnumerable, ICollection or IList if required.
        /// </summary>
        private static void ConvertRetOrStfldOrStsfld(AssemblyCompiler compiler, XTypeReference targetType, AstExpression node, XTypeSystem typeSystem)
        {
            var argument = node.Arguments.LastOrDefault();

            if (argument == null)
            {
                return;
            }

            if (argument.InferredType == null || !argument.InferredType.IsArray)
            {
                return;
            }

            var methodName = GetCollectionConvertMethodName(targetType);

            if (methodName == null)
            {
                return;
            }

            // Call "ret asMethod(x)"
            var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
            var asArray     = arrayHelper.Methods.First(x => x.Name == "As" + methodName);

            // AsX(x)
            var asXExpr = new AstExpression(node.SourceLocation, AstCode.Call, asArray, argument).SetType(typeSystem.Object);

            // replace argument.
            node.Arguments[node.Arguments.Count - 1] = asXExpr;
        }
Esempio n. 10
0
        /// <summary>
        /// Create an annotation for the given attribute
        /// </summary>
        private static void CreateAttributeAnnotation(AssemblyCompiler compiler, CustomAttribute attribute, TypeDefinition attributeType,
                                                      List <Annotation> annotationList, DexTargetPackage targetPackage)
        {
            // Gets the mapping for the type of attribute
            var mapping = compiler.GetAttributeAnnotationMapping(attributeType);

            MethodDefinition factoryMethod;

            // Note: not multithreading capable. see my comments elsewhere.
            if (mapping.FactoryMethodMap.ContainsKey(attribute))
            {
                factoryMethod = mapping.FactoryMethodMap[attribute];
            }
            else
            {
                // create the factory method.
                factoryMethod = CreateFactoryMethod(compiler, targetPackage, attribute, mapping);
                mapping.FactoryMethodMap[attribute] = factoryMethod;
            }

            // Create attribute annotation
            var attrAnnotation = new Annotation {
                Visibility = AnnotationVisibility.Runtime
            };

            attrAnnotation.Type = compiler.GetDot42InternalType("IAttribute").GetClassReference(targetPackage);
            attrAnnotation.Arguments.Add(new AnnotationArgument("AttributeType", attributeType.GetReference(targetPackage, compiler.Module)));
            attrAnnotation.Arguments.Add(new AnnotationArgument("FactoryMethod", factoryMethod.Name));

            // Add annotation
            annotationList.Add(attrAnnotation);
        }
Esempio n. 11
0
        /// <summary>
        /// Convert node with code Callvirt.
        ///
        /// For arrays: intercepts call to IEnumerable.IEnumerable_GetEnumerator generated
        /// by foreach statements and swaps them out to System.Array.GetEnumerator.
        ///
        /// This call will then at a later compilation stage be replaced with the final destination.
        /// </summary>
        private static void ConvertCallvirtIEnumerable(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var targetMethodRef      = ((XMethodReference)node.Operand);
            var targetMethodDefOrRef = targetMethodRef;

            if (targetMethodDefOrRef.DeclaringType.IsSystemCollectionsIEnumerable() &&
                targetMethodDefOrRef.Name == "IEnumerable_GetEnumerator" &&
                node.Arguments.Count == 1)
            {
                var argument = node.Arguments[0];
                if (!argument.InferredType.IsArray)
                {
                    return;
                }

                // swap the call to System.Array
                var systemArray   = compiler.GetDot42InternalType("System", "Array").Resolve();
                var getEnumerator = systemArray.Methods.First(x => x.Name == "GetEnumerator" && !x.IsStatic && x.Parameters.Count == 0);
                node.Operand = getEnumerator;
            }
            else if (targetMethodDefOrRef.DeclaringType.IsSystemCollectionsIEnumerableT() &&
                     targetMethodDefOrRef.Name.EndsWith("_GetEnumerator") &&
                     node.Arguments.Count == 1)
            {
                var argument = node.Arguments[0];
                if (!argument.InferredType.IsArray)
                {
                    return;
                }

                var elementType = argument.InferredType.ElementType;

                // Use As...Enumerable to convert
                var asEnumerableName   = FrameworkReferences.GetAsEnumerableTMethodName(elementType);
                var compilerHelper     = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var asEnumerableMethod = compilerHelper.Methods.First(x => x.Name == asEnumerableName);

                var call = new AstExpression(node.SourceLocation, AstCode.Call, asEnumerableMethod, argument)
                {
                    InferredType = asEnumerableMethod.ReturnType
                };
                node.Arguments[0] = call;

                argument.ExpectedType = argument.InferredType;
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Gets a unbox method for the given primitive type.
        /// </summary>
        internal static MethodReference GetUnboxValueMethod(XTypeReference type, AssemblyCompiler compiler, DexTargetPackage targetPackage, out RCode convertAfterCode)
        {
            var info = Get(type);

            convertAfterCode = info.convertAfterCode;
            var boxingClass = compiler.GetDot42InternalType("Boxing").GetClassReference(targetPackage);

            return(new MethodReference(boxingClass, info.unboxMethodName, new Prototype(info.primitiveType, new Parameter(FrameworkReferences.Object, "value"))));
        }
Esempio n. 13
0
        /// <summary>
        /// Create an annotation for the given attribute
        /// </summary>
        private static void Create(AssemblyCompiler compiler, CustomAttribute attribute, TypeDefinition attributeType,
                                   List <Annotation> annotationList, DexTargetPackage targetPackage)
        {
            // Gets the mapping for the type of attribute
            var mapping = compiler.GetAttributeAnnotationType(attributeType);
            var ctorMap = mapping.CtorMap[attribute.Constructor.Resolve()];

            // Create annotation
            var annotation = new Annotation {
                Visibility = AnnotationVisibility.Runtime
            };

            annotation.Type = mapping.AnnotationInterfaceClass;

            // Add ctor arguments
            var argIndex = 0;

            foreach (var arg in attribute.ConstructorArguments)
            {
                var name = ctorMap.ArgumentGetters[argIndex].Name;
                annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Type, arg.Value, targetPackage, compiler.Module));
                argIndex++;
            }

            // Add field values
            foreach (var arg in attribute.Fields)
            {
                var entry = mapping.FieldToGetMethodMap.First(x => x.Key.Name == arg.Name);
                var name  = entry.Value.Name;
                annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Argument.Type, arg.Argument.Value, targetPackage, compiler.Module));
            }

            // Add property values
            foreach (var arg in attribute.Properties)
            {
                if (mapping.PropertyToGetMethodMap.Keys.Any(x => x.Name == arg.Name))
                {
                    var entry = mapping.PropertyToGetMethodMap.First(x => x.Key.Name == arg.Name);
                    var name  = entry.Value.Name;
                    annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Argument.Type, arg.Argument.Value, targetPackage, compiler.Module));
                }
            }

            // Create attribute annotation
            var attrAnnotation = new Annotation {
                Visibility = AnnotationVisibility.Runtime
            };

            attrAnnotation.Type = compiler.GetDot42InternalType("IAttribute").GetClassReference(targetPackage);
            attrAnnotation.Arguments.Add(new AnnotationArgument("AttributeBuilder", ctorMap.Builder));
            attrAnnotation.Arguments.Add(new AnnotationArgument("AttributeType", attributeType.GetReference(targetPackage, compiler.Module)));
            attrAnnotation.Arguments.Add(new AnnotationArgument("Annotation", annotation));

            // Add annotation
            annotationList.Add(attrAnnotation);
        }
        internal static void FinalizeFrameworkPropertyAnnotations(AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            var reflInfoRef = compiler.GetDot42InternalType("Dot42.Internal.ReflectionInfo", "FrameworkPropertyInfoProvider")
                              .GetClassReference(targetPackage);

            var relfInfo        = targetPackage.DexFile.GetClass(reflInfoRef.Fullname);
            var propertiesClass = compiler.GetDot42InternalType("IProperties").GetClassReference(targetPackage);
            var properties      = relfInfo.Annotations.FirstOrDefault(a => a.Type.Fullname == propertiesClass.Fullname);

            if (properties == null)
            {
                return;
            }

            var property = properties.Arguments.Single();

            properties.Arguments.Clear();
            properties.Arguments.Add(new AnnotationArgument(property.Name, ((List <Annotation>)property.Value).ToArray()));
        }
Esempio n. 15
0
        /// <summary>
        /// Create code to unbox the given source array of boxed type elements into an array of primitive elements.
        /// </summary>
        public static RLRange UnboxGenericArray(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec source, RegisterSpec boxedArray,
                                                XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler)
        {
            var internalBoxingType = compiler.GetDot42InternalType("Boxing").Resolve();
            var ilUnboxMethod      = internalBoxingType.Methods.First(x => x.EqualsName("UnboxTo") && (x.Parameters.Count == 2) && (x.Parameters[1].ParameterType.IsSame(type, true)));
            var unboxMethod        = ilUnboxMethod.GetReference(targetPackage);
            var call = builder.Add(sequencePoint, RCode.Invoke_static, unboxMethod, boxedArray, source);

            return(new RLRange(call, null));
        }
Esempio n. 16
0
 /// <summary>
 /// Add generic parameters to the prototype based on the given XMethodDefinition
 /// </summary>
 public static void AddGenericParameters(AssemblyCompiler compiler, DexTargetPackage targetPackage, XMethodDefinition method, Prototype result)
 {
     if (method.NeedsGenericInstanceTypeParameter)
     {
         var annType = compiler.GetDot42InternalType(InternalConstants.GenericTypeParameterAnnotation).GetClassReference(targetPackage);
         int numParameters = method.DeclaringType.GenericParameters.Count;
         var buildAsArray = numParameters > InternalConstants.GenericTypeParametersAsArrayThreshold;
         var parameterArray = result.GenericInstanceTypeParameters;
         AddGenericParameterArguments(result, buildAsArray, numParameters, "__$$git", annType, parameterArray);
     }
     if (method.NeedsGenericInstanceMethodParameter)
     {
         // Add GenericInstance parameter
         var annType = compiler.GetDot42InternalType(InternalConstants.GenericMethodParameterAnnotation).GetClassReference(targetPackage);
         int numParameters = method.GenericParameters.Count;
         var buildAsArray = numParameters > InternalConstants.GenericMethodParametersAsArrayThreshold;
         var parameterArray = result.GenericInstanceMethodParameters;
         AddGenericParameterArguments(result, buildAsArray, numParameters, "__$$gim", annType, parameterArray);
     }
 }
Esempio n. 17
0
 /// <summary>
 /// Add generic parameters to the prototype based on the given XMethodDefinition
 /// </summary>
 public static void AddGenericParameters(AssemblyCompiler compiler, DexTargetPackage targetPackage, XMethodDefinition method, Prototype result)
 {
     if (method.NeedsGenericInstanceTypeParameter)
     {
         var annType        = compiler.GetDot42InternalType(InternalConstants.GenericTypeParameterAnnotation).GetClassReference(targetPackage);
         int numParameters  = method.DeclaringType.GenericParameters.Count;
         var buildAsArray   = numParameters > InternalConstants.GenericTypeParametersAsArrayThreshold;
         var parameterArray = result.GenericInstanceTypeParameters;
         AddGenericParameterArguments(result, buildAsArray, numParameters, "__$$git", annType, parameterArray);
     }
     if (method.NeedsGenericInstanceMethodParameter)
     {
         // Add GenericInstance parameter
         var annType        = compiler.GetDot42InternalType(InternalConstants.GenericMethodParameterAnnotation).GetClassReference(targetPackage);
         int numParameters  = method.GenericParameters.Count;
         var buildAsArray   = numParameters > InternalConstants.GenericMethodParametersAsArrayThreshold;
         var parameterArray = result.GenericInstanceMethodParameters;
         AddGenericParameterArguments(result, buildAsArray, numParameters, "__$$gim", annType, parameterArray);
     }
 }
Esempio n. 18
0
        /// <summary>
        /// Create code to unbox the given source array of boxed type elements resulting from a call into an array of primitive elements.
        /// </summary>
        public static RLRange UnboxGenericArrayResult(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec boxedArray,
                                                      XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler)
        {
            var internalBoxingType = compiler.GetDot42InternalType("Boxing").Resolve();
            var primitiveArray     = frame.AllocateTemp(type.GetReference(targetPackage));
            var ilUnboxMethod      = internalBoxingType.Methods.First(x => x.Name.StartsWith("Unbox") && (x.Parameters.Count == 1) && (x.ReturnType.IsSame(type, true)));
            var unboxMethod        = ilUnboxMethod.GetReference(targetPackage);
            var call      = builder.Add(sequencePoint, RCode.Invoke_static, unboxMethod, boxedArray);
            var saveArray = builder.Add(sequencePoint, RCode.Move_result_object, primitiveArray);

            return(new RLRange(call, saveArray, primitiveArray));
        }
Esempio n. 19
0
        /// <summary>
        /// Create code to box the given source array of primitive type elements into an array of boxed elements.
        /// </summary>
        public static RLRange BoxGenericArray(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec source,
                                              XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler)
        {
            var objectArrayType    = new DexLib.ArrayType(new ClassReference("java.lang.Object"));
            var boxedArray         = frame.AllocateTemp(objectArrayType);
            var internalBoxingType = compiler.GetDot42InternalType("Boxing").Resolve();
            var ilBoxMethod        = internalBoxingType.Methods.First(x => x.EqualsName("Box") && (x.Parameters.Count == 1) && (x.Parameters[0].ParameterType.IsSame(type, true)));
            var boxMethod          = ilBoxMethod.GetReference(targetPackage);
            var call      = builder.Add(sequencePoint, RCode.Invoke_static, boxMethod, source);
            var saveArray = builder.Add(sequencePoint, RCode.Move_result_object, boxedArray);

            return(new RLRange(call, saveArray, boxedArray));
        }
Esempio n. 20
0
        /// <summary>
        /// Create a prototype for the given methods signature
        /// </summary>
        internal static Prototype BuildPrototype(AssemblyCompiler compiler, DexTargetPackage targetPackage, ClassDefinition declaringClass, XMethodDefinition method)
        {
            var result = new Prototype();

            result.ReturnType = method.ReturnType.GetReference(targetPackage);
            if (method.IsAndroidExtension && !method.IsStatic)
            {
                // Add "this" parameter
                var dparameter = new Parameter(method.DeclaringType.GetReference(targetPackage), "this");
                result.Parameters.Add(dparameter);
            }
            foreach (var p in method.Parameters)
            {
                var dparameter = new Parameter(p.ParameterType.GetReference(targetPackage), p.Name);
                result.Parameters.Add(dparameter);
            }
            if (method.NeedsGenericInstanceTypeParameter)
            {
                // Add GenericInstance parameter (to pass the generic instance array of the declaring type)
                var paramType  = FrameworkReferences.ClassArray;
                var dparameter = new Parameter(paramType, "__$$git");
                var annType    = compiler.GetDot42InternalType(InternalConstants.GenericTypeParameterAnnotation).GetClassReference(targetPackage);
                dparameter.Annotations.Add(new Annotation(annType, AnnotationVisibility.Runtime));
                result.Parameters.Add(dparameter);
                result.GenericInstanceTypeParameter = dparameter;
            }
            if (method.NeedsGenericInstanceMethodParameter)
            {
                // Add GenericInstance parameter
                var paramType  = FrameworkReferences.ClassArray;
                var dparameter = new Parameter(paramType, "__$$gim");
                var annType    = compiler.GetDot42InternalType(InternalConstants.GenericMethodParameterAnnotation).GetClassReference(targetPackage);
                dparameter.Annotations.Add(new Annotation(annType, AnnotationVisibility.Runtime));
                result.Parameters.Add(dparameter);
                result.GenericInstanceMethodParameter = dparameter;
            }
            return(result);
        }
Esempio n. 21
0
 /// <summary>
 /// Create a prototype for the given methods signature
 /// </summary>
 internal static Prototype BuildPrototype(AssemblyCompiler compiler, DexTargetPackage targetPackage, ClassDefinition declaringClass, XMethodDefinition method)
 {
     var result = new Prototype();
     result.ReturnType = method.ReturnType.GetReference(targetPackage);
     if (method.IsAndroidExtension && !method.IsStatic)
     {
         // Add "this" parameter
         var dparameter = new Parameter(method.DeclaringType.GetReference(targetPackage), "this");
         result.Parameters.Add(dparameter);
     }
     foreach (var p in method.Parameters)
     {
         var dparameter = new Parameter(p.ParameterType.GetReference(targetPackage), p.Name);
         result.Parameters.Add(dparameter);
     }
     if (method.NeedsGenericInstanceTypeParameter)
     {
         // Add GenericInstance parameter (to pass the generic instance array of the declaring type)
         var paramType = FrameworkReferences.ClassArray;
         var dparameter = new Parameter(paramType, "__$$git");
         var annType = compiler.GetDot42InternalType(InternalConstants.GenericTypeParameterAnnotation).GetClassReference(targetPackage);
         dparameter.Annotations.Add(new Annotation(annType, AnnotationVisibility.Runtime));
         result.Parameters.Add(dparameter);
         result.GenericInstanceTypeParameter = dparameter;
     }
     if (method.NeedsGenericInstanceMethodParameter)
     {
         // Add GenericInstance parameter
         var paramType = FrameworkReferences.ClassArray;
         var dparameter = new Parameter(paramType, "__$$gim");
         var annType = compiler.GetDot42InternalType(InternalConstants.GenericMethodParameterAnnotation).GetClassReference(targetPackage);
         dparameter.Annotations.Add(new Annotation(annType, AnnotationVisibility.Runtime));
         result.Parameters.Add(dparameter);
         result.GenericInstanceMethodParameter = dparameter;
     }
     return result;
 }
 /// <summary>
 /// Create the current type as class definition.
 /// </summary>
 internal DelegateInstanceTypeBuilder(
     ISourceLocation sequencePoint,
     AssemblyCompiler compiler, DexTargetPackage targetPackage,
     ClassDefinition delegateClass,
     XMethodDefinition invokeMethod, Prototype invokePrototype,
     XMethodDefinition calledMethod)
 {
     this.sequencePoint = sequencePoint;
     this.compiler = compiler;
     this.targetPackage = targetPackage;
     this.delegateClass = delegateClass;
     this.invokeMethod = invokeMethod;
     this.invokePrototype = invokePrototype;
     this.calledMethod = calledMethod;
     this.multicastDelegateClass = compiler.GetDot42InternalType("System", "MulticastDelegate").GetClassReference(targetPackage);
 }
 /// <summary>
 /// Create the current type as class definition.
 /// </summary>
 internal DelegateInstanceTypeBuilder(
     ISourceLocation sequencePoint,
     AssemblyCompiler compiler, DexTargetPackage targetPackage,
     ClassDefinition delegateClass,
     XMethodDefinition invokeMethod, Prototype invokePrototype,
     XMethodDefinition calledMethod)
 {
     this.sequencePoint          = sequencePoint;
     this.compiler               = compiler;
     this.targetPackage          = targetPackage;
     this.delegateClass          = delegateClass;
     this.invokeMethod           = invokeMethod;
     this.invokePrototype        = invokePrototype;
     this.calledMethod           = calledMethod;
     this.multicastDelegateClass = compiler.GetDot42InternalType("System", "MulticastDelegate").GetClassReference(targetPackage);
 }
        /// <summary>
        /// Build expressions that are used when calling a .NET method with generic instance parameters, one expression for
        /// each required parameter.
        /// </summary>
        private static IList <AstExpression> CreateGenericInstanceCallArguments(ISourceLocation seqp, XReference member, MethodSource currentMethod, AssemblyCompiler compiler)
        {
            // Prepare
            var genericInstance = member as IXGenericInstance;

            if (genericInstance == null)
            {
#if DEBUG
                //Debugger.Launch();
#endif
                throw new CompilerException(string.Format("{0} is not a generic instance", member));
            }
            var count          = genericInstance.GenericArguments.Count;
            var typeHelperType = compiler.GetDot42InternalType(InternalConstants.TypeHelperName).Resolve();

            // Foreach type argument
            var typeExpressions = new List <AstExpression>();
            for (var i = 0; i < count; i++)
            {
                var argType  = genericInstance.GenericArguments[i];
                var typeExpr = LoadTypeForGenericInstance(seqp, currentMethod, argType, compiler, typeHelperType, compiler.Module.TypeSystem,
                                                          TypeConversion.EnsureTrueOrMarkerType);
                typeExpressions.Add(typeExpr);
            }

            bool isMethod   = member is XMethodReference;
            bool buildArray = count > (isMethod ? InternalConstants.GenericMethodParametersAsArrayThreshold
                                                : InternalConstants.GenericTypeParametersAsArrayThreshold);
            if (buildArray)
            {
                //TODO: when we can determine that all expressions just load our classes generic instance (array) field,
                //      and extract all values in sequence, we should shortcut and just return a load of the field,
                //      instead of unpacking and re-packing each value, putting pressure on the garbage collector
                //      in the process. This is not a huge problem any longer, as we do not use arrays as often
                //      as we used to. Nevertheless, where arrays are used, possible re-use should be faily common,
                //      e.g. when instatiating nested classes or invoking static methods.
                var elementType = compiler.Module.TypeSystem.Type;
                return(new [] { new AstExpression(seqp, AstCode.InitArrayFromArguments, new XArrayType(elementType), typeExpressions)
                                {
                                    ExpectedType = new XArrayType(elementType)
                                } });
            }
            else
            {
                return(typeExpressions);
            }
        }
        public static Annotation CreateAnnotation(XTypeReference xtype, bool forceTypeDefinition,
            AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            var genericsDefAnnotationClass = compiler.GetDot42InternalType(InternalConstants.GenericDefinitionAnnotation)
                .GetClassReference(targetPackage);

            var annotation = new Annotation
            {
                Type = genericsDefAnnotationClass,
                Visibility = AnnotationVisibility.Runtime
            };

            string s = GetDefinition(xtype, forceTypeDefinition, compiler, targetPackage);
            if (string.IsNullOrEmpty(s)) return null;

            annotation.Arguments.Add(new AnnotationArgument("Definition", s));

            return annotation;
        }
Esempio n. 26
0
        /// <summary>
        /// Add references to all implemented interfaces.
        /// </summary>
        protected virtual void ImplementInterfaces(DexTargetPackage targetPackage)
        {
            // Implement interfaces
            foreach (var intf in typeDef.Interfaces.Select(x => x.InterfaceType.GetClassReference(targetPackage, compiler.Module))
                     .Distinct())
            {
                classDef.Interfaces.Add(intf);
            }

            if (IsNetGenericType)
            {
                var genericMarker = compiler.GetDot42InternalType(InternalConstants.GenericTypeDefinitionMarker);
                classDef.Interfaces.Add(genericMarker.GetClassReference(targetPackage));
            }
        }
Esempio n. 27
0
        /// <summary>
        /// Create annotations for all included attributes
        /// </summary>
        public static void CreateAttributeAnnotations(AssemblyCompiler compiler, ICustomAttributeProvider attributeProvider,
                                                      IAnnotationProvider annotationProvider, DexTargetPackage targetPackage, bool customAttributesOnly = false)
        {
            if (!attributeProvider.HasCustomAttributes)
            {
                return;
            }

            var annotations = new List <Annotation>();

            foreach (var attr in attributeProvider.CustomAttributes)
            {
                var attributeType = attr.AttributeType.Resolve();
                if (!attributeType.HasIgnoreAttribute())
                {
                    CreateAttributeAnnotation(compiler, attr, attributeType, annotations, targetPackage);
                }
            }
            if (annotations.Count > 0)
            {
                // Create 1 IAttributes annotation
                var attrsAnnotation = new Annotation {
                    Visibility = AnnotationVisibility.Runtime
                };
                attrsAnnotation.Type = compiler.GetDot42InternalType("IAttributes").GetClassReference(targetPackage);
                attrsAnnotation.Arguments.Add(new AnnotationArgument("Attributes", annotations.ToArray()));
                annotationProvider.Annotations.Add(attrsAnnotation);
            }

            if (!customAttributesOnly)
            {
                // Add annotations specified using AnnotationAttribute
                foreach (var attr in attributeProvider.CustomAttributes.Where(IsAnnotationAttribute))
                {
                    var annotationType  = (TypeReference)attr.ConstructorArguments[0].Value;
                    var annotationClass = annotationType.GetClassReference(targetPackage, compiler.Module);
                    annotationProvider.Annotations.Add(new Annotation(annotationClass, AnnotationVisibility.Runtime));
                }
            }
        }
Esempio n. 28
0
        public static Annotation CreateAnnotation(XTypeReference xtype, bool forceTypeDefinition,
                                                  AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            var genericsDefAnnotationClass = compiler.GetDot42InternalType(InternalConstants.GenericDefinitionAnnotation)
                                             .GetClassReference(targetPackage);

            var annotation = new Annotation
            {
                Type       = genericsDefAnnotationClass,
                Visibility = AnnotationVisibility.Runtime
            };

            string s = GetDefinition(xtype, forceTypeDefinition, compiler, targetPackage);

            if (string.IsNullOrEmpty(s))
            {
                return(null);
            }

            annotation.Arguments.Add(new AnnotationArgument("Definition", s));

            return(annotation);
        }
Esempio n. 29
0
        /// <summary>
        /// Convert node with code IsInst.
        /// </summary>
        private static void ConvertIsInst(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference)node.Operand;
            if (type.IsSystemArray())
            {
                // Call ArrayHelper.AsArray
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var asArray = arrayHelper.Methods.First(x => x.Name == "AsArray");
                var asArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, asArray, node.Arguments).SetType(typeSystem.Bool);
                node.CopyFrom(asArrayExpr);
                return;
            }

            string asMethod = GetCollectionConvertMethodName(type);

            if (asMethod != null)
            {
                asMethod = "As" + asMethod;
            }
            else if (type.IsSystemIFormattable())
            {
                asMethod = "AsFormattable";
            }

            // make sure we don't evaluate the expression twice.
            var tempVar = new AstGeneratedVariable("temp$$", null) { Type = compiler.Module.TypeSystem.Object };
            var storeTempVar = new AstExpression(node.SourceLocation, AstCode.Stloc, tempVar, node.Arguments[0]) { ExpectedType = compiler.Module.TypeSystem.Object };
            var loadTempVar = new AstExpression(node.SourceLocation, AstCode.Ldloc, tempVar).SetType(compiler.Module.TypeSystem.Object);


            if (asMethod != null)
            {
                // Call "(x instanceof T) ? (T)x : asMethod(x)"
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var asArray = arrayHelper.Methods.First(x => x.Name == asMethod);

                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, storeTempVar).SetType(typeSystem.Bool);

                // AsX(x)
                var asXExpr = new AstExpression(node.SourceLocation, AstCode.Call, asArray, loadTempVar).SetType(typeSystem.Object);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, loadTempVar).SetType(type);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, asXExpr).SetType(type);

                node.CopyFrom(conditional);
                return;
            }

            // Normal "as": Convert to (x instanceof T) ? (T)x : null
            if(!type.IsPrimitive)
            {
                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, storeTempVar).SetType(typeSystem.Bool);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, loadTempVar).SetType(type);

                // null
                var nullExpr = new AstExpression(node.SourceLocation, AstCode.Ldnull, null).SetType(typeSystem.Object);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, nullExpr).SetType(type);

                node.CopyFrom(conditional);
                return;                
            }
            else
            {
                // treat as "x is T"
                if(!node.ExpectedType.IsBoolean())
                    throw new NotImplementedException(); // can this happen?

                node.Code = AstCode.SimpleInstanceOf;
            }
        }
Esempio n. 30
0
        /// <summary>
        /// Convert node with code IsInst.
        /// </summary>
        private static void ConvertIsInst(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference)node.Operand;
            if (type.IsSystemArray())
            {
                // Call ArrayHelper.AsArray
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var asArray = arrayHelper.Methods.First(x => x.Name == "AsArray");
                var asArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, asArray, node.Arguments).SetType(typeSystem.Bool);
                node.CopyFrom(asArrayExpr);
                return;
            }

            string asMethod = null;
            if (type.IsSystemCollectionsIEnumerable())
            {
                asMethod = "AsEnumerable";
            }
            else if (type.IsSystemCollectionsICollection())
            {
                asMethod = "AsCollection";
            }
            else if (type.IsSystemCollectionsIList())
            {
                asMethod = "AsList";
            }
            else if (type.IsSystemIFormattable())
            {
                asMethod = "AsFormattable";
            }

            if (asMethod != null)
            {
                // Call "(x instanceof T) ? (T)x : asMethod(x)"
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var asArray = arrayHelper.Methods.First(x => x.Name == asMethod);

                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, node.Arguments[0]).SetType(typeSystem.Bool);

                // AsX(x)
                var asXExpr = new AstExpression(node.SourceLocation, AstCode.Call, asArray, node.Arguments[0]).SetType(typeSystem.Object);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, node.Arguments[0]).SetType(type);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, asXExpr).SetType(type);

                node.CopyFrom(conditional);
                return;
            }

            // Normal "as": Convert to (x instanceof T) ? T(x) : null
            {
                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, node.Arguments[0]).SetType(typeSystem.Bool);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, node.Arguments[0]).SetType(type);

                // null
                var nullExpr = new AstExpression(node.SourceLocation, AstCode.Ldnull, null).SetType(typeSystem.Object);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, nullExpr).SetType(type);

                node.CopyFrom(conditional);
                return;                
            }
        }
        /// <summary>
        /// Create an annotation interface.
        /// </summary>
        internal static AttributeAnnotationInterface Create(
            ISourceLocation sequencePoint,
            AssemblyCompiler compiler,
            DexTargetPackage targetPackage,
            TypeDefinition attributeType,
            ClassDefinition attributeClass)
        {
            // Create class
            ClassDefinition @interface = new ClassDefinition();
            @interface.Name = CreateAnnotationTypeName(attributeClass);
            @interface.Namespace = attributeClass.Namespace;
            @interface.AccessFlags = AccessFlags.Public | AccessFlags.Abstract | AccessFlags.Interface | AccessFlags.Annotation;
            @interface.Owner = attributeClass;
            attributeClass.InnerClasses.Add(@interface);

            // Set super class
            @interface.SuperClass = new ClassReference("java/lang/Object");

            // Implement Dot42.Internal.IAttribute
            @interface.Interfaces.Add(new ClassReference("java/lang/annotation/Annotation"));

            // Prepare result
            AttributeAnnotationInterface result = new AttributeAnnotationInterface(@interface);

            // Add methods from IAttribute
            XModel.XTypeDefinition baseIntfType = compiler.GetDot42InternalType("IAttribute").Resolve();
            foreach (XModel.XMethodDefinition imethod in baseIntfType.Methods)
            {
                if (imethod.Parameters.Count > 0) 
                    throw new CompilerException(string.Format("Invalid IAttribute method {0}", imethod));
                string methodName = NameConverter.GetConvertedName(imethod);
                TypeReference dfieldType = imethod.ReturnType.GetReference(targetPackage);
                MethodDefinition method = new MethodDefinition(@interface, methodName, new Prototype(dfieldType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                @interface.Methods.Add(method);                
            }

            // Add field mapping
            foreach (var field in attributeType.Fields.Where(x => x.IsReachable && x.IsPublic))
            {
                string methodName = CreateGetMethodName(NameConverter.GetConvertedName(field), result);
                TypeReference dfieldType = field.FieldType.GetReference(targetPackage, compiler.Module);
                MethodDefinition method = new MethodDefinition(@interface, methodName, new Prototype(dfieldType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                result.FieldToGetMethodMap.Add(field, method);
                @interface.Methods.Add(method);
            }

            // Add property mapping
            foreach (var property in attributeType.Properties.Where(x => x.IsReachable && (x.SetMethod != null) && (x.SetMethod.IsPublic) && x.SetMethod.IsReachable))
            {
                string methodName = CreateGetMethodName(NameConverter.GetConvertedName(property), result);
                TypeReference dpropType = property.PropertyType.GetReference(targetPackage, compiler.Module);
                MethodDefinition method = new MethodDefinition(@interface, methodName, new Prototype(dpropType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                result.PropertyToGetMethodMap.Add(property, method);
                @interface.Methods.Add(method);
            }

            // Add ctor mapping
            var argIndex = 0;
            foreach (var ctor in attributeType.Methods.Where(x => (x.Name == ".ctor") && x.IsReachable))
            {
                // Add methods for the ctor arguments
                List<MethodDefinition> paramGetMethods = new List<MethodDefinition>();
                foreach (ParameterDefinition p in ctor.Parameters)
                {
                    string methodName = CreateGetMethodName("c" + argIndex++, result);
                    TypeReference dparamType = p.ParameterType.GetReference(targetPackage, compiler.Module);
                    MethodDefinition method = new MethodDefinition(@interface, methodName, new Prototype(dparamType));
                    method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                    @interface.Methods.Add(method);
                    paramGetMethods.Add(method);
                }

                // Add a builder method
                MethodDefinition buildMethod = CreateBuildMethod(sequencePoint, ctor, paramGetMethods, compiler, targetPackage, attributeClass, result);
                result.CtorMap.Add(ctor, new AttributeCtorMapping(buildMethod, paramGetMethods));
            }

            // Create default values annotation
            Annotation defAnnotation = CreateDefaultAnnotation(result);
            result.AnnotationInterfaceClass.Annotations.Add(defAnnotation);

            return result;
        }
Esempio n. 32
0
        /// <summary>
        /// Build expressions that are used when calling a .NET method with generic instance parameters, one expression for
        /// each required parameter.
        /// </summary>
        private static IList<AstExpression> CreateGenericInstanceCallArguments(ISourceLocation seqp, XReference member, MethodSource currentMethod, AssemblyCompiler compiler)
        {
            // Prepare
            var genericInstance = member as IXGenericInstance;
            if (genericInstance == null)
            {
#if DEBUG
                //Debugger.Launch();
#endif
                throw new CompilerException(string.Format("{0} is not a generic instance", member));
            }
            var count = genericInstance.GenericArguments.Count;
            var typeHelperType = compiler.GetDot42InternalType(InternalConstants.TypeHelperName).Resolve();

            // Foreach type argument
            var typeExpressions = new List<AstExpression>();
            for (var i = 0; i < count; i++)
            {
                var argType = genericInstance.GenericArguments[i];
                var typeExpr = LoadTypeForGenericInstance(seqp, currentMethod, argType, compiler, typeHelperType, compiler.Module.TypeSystem, 
                                                          TypeConversion.EnsureTrueOrMarkerType);
                typeExpressions.Add(typeExpr);
            }

            bool isMethod = member is XMethodReference;
            bool buildArray = count > (isMethod ? InternalConstants.GenericMethodParametersAsArrayThreshold 
                                                : InternalConstants.GenericTypeParametersAsArrayThreshold);
            if (buildArray)
            {
                //TODO: when we can determine that all expressions just load our classes generic instance (array) field,
                //      and extract all values in sequence, we should shortcut and just return a load of the field,
                //      instead of unpacking and re-packing each value, putting pressure on the garbage collector
                //      in the process. This is not a huge problem any longer, as we do not use arrays as often
                //      as we used to. Nevertheless, where arrays are used, possible re-use should be faily common,
                //      e.g. when instatiating nested classes or invoking static methods.
                var elementType = compiler.Module.TypeSystem.Type;
                return new [] { new AstExpression(seqp, AstCode.InitArrayFromArguments, new XArrayType(elementType), typeExpressions) { ExpectedType = new XArrayType(elementType) }};
            }
            else
            {
                return typeExpressions;
            }
        }
Esempio n. 33
0
 /// <summary>
 /// Create code to unbox the given source array of boxed type elements into an array of primitive elements.
 /// </summary>
 public static RLRange UnboxGenericArray(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec source, RegisterSpec boxedArray,
                                        XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler)
 {
     var internalBoxingType = compiler.GetDot42InternalType("Boxing").Resolve();
     var ilUnboxMethod = internalBoxingType.Methods.First(x => x.EqualsName("UnboxTo") && (x.Parameters.Count == 2) && (x.Parameters[1].ParameterType.IsSame(type, true)));
     var unboxMethod = ilUnboxMethod.GetReference(targetPackage);
     var call = builder.Add(sequencePoint, RCode.Invoke_static, unboxMethod, boxedArray, source);
     return new RLRange(call, null);
 }
Esempio n. 34
0
        /// <summary>
        /// Convert node with code InstanceOf.
        /// </summary>
        private static void ConvertInstanceOf(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference)node.Operand;
            if (type.IsSystemArray()) // "is System.Array"
            {
                // Call ArrayHelper.IsArray
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isArray = arrayHelper.Methods.First(x => x.Name == "IsArray");
                var isArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, isArray, node.Arguments).SetType(typeSystem.Bool);
                node.CopyFrom(isArrayExpr);
                return;
            }

            // make sure we don't evaluate the expression twice.
            var tempVar = new AstGeneratedVariable("temp$$", null) { Type = compiler.Module.TypeSystem.Object };
            var storeTempVar = new AstExpression(node.SourceLocation, AstCode.Stloc, tempVar, node.Arguments[0]) { ExpectedType = compiler.Module.TypeSystem.Object };
            var loadTempVar = new AstExpression(node.SourceLocation, AstCode.Ldloc, tempVar).SetType(compiler.Module.TypeSystem.Object);

            if (type.IsSystemCollectionsIEnumerable() ||
                type.IsSystemCollectionsICollection() ||
                type.IsSystemCollectionsIList())
            {
                // Call "(is x) || IsArray(x)"
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isArray = arrayHelper.Methods.First(x => x.Name == "IsArray" && x.Parameters.Count == 1);

                // "is" 
                var isExpr = new AstExpression(node).SetArguments(storeTempVar).SetCode(AstCode.SimpleInstanceOf);

                // Call IsArray
                var isArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, isArray, loadTempVar).SetType(typeSystem.Bool);

                // Combined
                var combined = new AstExpression(node.SourceLocation, AstCode.Or, null, isExpr, isArrayExpr).SetType(typeSystem.Bool);
                node.CopyFrom(combined);
                return;
            }

            if (type.IsSystemCollectionsIEnumerableT() ||
                type.IsSystemCollectionsICollectionT() ||
                type.IsSystemCollectionsIListT())
            {
                // TODO: implement InstanceOf with type check for array types.
                // (is that even possible here?)
            }

            if (type.IsSystemIFormattable())
            {
                // Call "(is x) || IsFormattable(x)"
                var formattable = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isFormattable = formattable.Methods.First(x => x.Name == "IsVirtualFormattable");

                // "is" 
                var isExpr = new AstExpression(node).SetArguments(storeTempVar).SetCode(AstCode.SimpleInstanceOf);

                // Call IsFormattable
                var isFormattableExpr = new AstExpression(node.SourceLocation, AstCode.Call, isFormattable, loadTempVar).SetType(typeSystem.Bool);

                // Combined
                var combined = new AstExpression(node.SourceLocation, AstCode.Or, null, isExpr, isFormattableExpr).SetType(typeSystem.Bool);
                node.CopyFrom(combined);
                return;
            }

            // Normal instanceof
            node.Code = AstCode.SimpleInstanceOf;            
        }
        /// <summary>
        /// Optimize expressions
        /// </summary>
        public static void Convert(AstNode ast, MethodSource currentMethod, AssemblyCompiler compiler)
        {
            var typeSystem = compiler.Module.TypeSystem;

            // Expand typeof
            foreach (var node in ast.GetSelfAndChildrenRecursive <AstExpression>(x => x.Code == AstCode.TypeOf))
            {
                var type           = (XTypeReference)node.Operand;
                var typeHelperType = compiler.GetDot42InternalType(InternalConstants.TypeHelperName).Resolve();
                var loadExpr       = LoadTypeForGenericInstance(node.SourceLocation, currentMethod, type, compiler, typeHelperType, typeSystem, TypeConversion.EnsureTrueOrMarkerType);
                node.CopyFrom(loadExpr);
            }

            // Expand instanceOf
            foreach (var node in ast.GetSelfAndChildrenRecursive <AstExpression>(x => x.Code == AstCode.SimpleInstanceOf))
            {
                var type = (XTypeReference)node.Operand;
                var gp   = type as XGenericParameter;
                if (gp == null)
                {
                    continue;
                }

                var typeHelperType = compiler.GetDot42InternalType(InternalConstants.TypeHelperName).Resolve();
                var loadExpr       = LoadTypeForGenericInstance(node.SourceLocation, currentMethod, type, compiler, typeHelperType, typeSystem, TypeConversion.EnsureRuntimeType);
                //// both types are boxed, no need for conversion.
                var typeType         = compiler.GetDot42InternalType("System", "Type").Resolve();
                var isInstanceOfType = typeType.Methods.Single(n => n.Name == "JavaIsInstance" && n.Parameters.Count == 1);
                var call             = new AstExpression(node.SourceLocation, AstCode.Call, isInstanceOfType, loadExpr, node.Arguments[0]);
                node.CopyFrom(call);
            }

            // Expand newarr
            foreach (var node in ast.GetSelfAndChildrenRecursive <AstExpression>(x => x.Code == AstCode.Newarr))
            {
                var type = (XTypeReference)node.Operand;
                if (!type.IsDefinitionOrReferenceOrPrimitive())
                {
                    // Resolve type to a Class<?>
                    var typeHelperType = compiler.GetDot42InternalType(InternalConstants.TypeHelperName).Resolve();
                    // while having primitive arrays for primitive types would be nice, a lot of boxing and unboxing
                    // would be needed. only for-primitive-specialized generic classes we could optimize this.
                    var ldType          = LoadTypeForGenericInstance(node.SourceLocation, currentMethod, type, compiler, typeHelperType, typeSystem, TypeConversion.EnsureRuntimeType);
                    var newInstanceExpr = new AstExpression(node.SourceLocation, AstCode.ArrayNewInstance, null, ldType, node.Arguments[0])
                    {
                        ExpectedType = typeSystem.Object
                    };
                    var arrayType = new XArrayType(type);
                    var cast      = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, arrayType, newInstanceExpr)
                    {
                        ExpectedType = arrayType
                    };
                    node.CopyFrom(cast);
                }
            }

            // Add generic instance call arguments
            foreach (var node in ast.GetSelfAndChildrenRecursive <AstExpression>(x => x.Code.IsCall()))
            {
                var method = (XMethodReference)node.Operand;
                if (method.DeclaringType.IsArray)
                {
                    continue;
                }
                XMethodDefinition methodDef;
                if (!method.TryResolve(out methodDef))
                {
                    continue;
                }
                if (methodDef.HasDexNativeAttribute())
                {
                    continue;
                }

                if (methodDef.NeedsGenericInstanceTypeParameter)
                {
                    // Add generic instance type parameter value
                    var arg = CreateGenericInstanceCallArguments(node.SourceLocation, method.DeclaringType, currentMethod, compiler);
                    node.Arguments.AddRange(arg);
                    node.GenericInstanceArgCount += arg.Count;
                }

                if (methodDef.NeedsGenericInstanceMethodParameter)
                {
                    // Add generic instance method parameter
                    var arg = CreateGenericInstanceCallArguments(node.SourceLocation, method, currentMethod, compiler);
                    node.Arguments.AddRange(arg);
                    node.GenericInstanceArgCount += arg.Count;
                }
            }

            // Add generic instance Delegate arguments for static methods.
            foreach (var node in ast.GetSelfAndChildrenRecursive <AstExpression>(x => x.Code == AstCode.Delegate))
            {
                var delegateInfo = (Tuple <XTypeDefinition, XMethodReference>)node.Operand;

                var genMethodDef = delegateInfo.Item2 as IXGenericInstance;
                var genTypeDef   = delegateInfo.Item2.DeclaringType as IXGenericInstance;

                // Add generic instance type parameter value, if method is static
                if (genTypeDef != null && delegateInfo.Item2.Resolve().IsStatic)
                {
                    var arg = CreateGenericInstanceCallArguments(node.SourceLocation, delegateInfo.Item2.DeclaringType, currentMethod, compiler);
                    node.Arguments.AddRange(arg);
                    node.GenericInstanceArgCount += arg.Count;
                }

                // add generic method type parameter value.
                if (genMethodDef != null)
                {
                    var arg = CreateGenericInstanceCallArguments(node.SourceLocation, delegateInfo.Item2, currentMethod, compiler);
                    node.Arguments.AddRange(arg);
                    node.GenericInstanceArgCount += arg.Count;
                }
            }

            // Convert NewObj when needed
            foreach (var node in ast.GetSelfAndChildrenRecursive <AstExpression>(x => x.Code == AstCode.Newobj))
            {
                var ctorRef       = (XMethodReference)node.Operand;
                var declaringType = ctorRef.DeclaringType;
                if (declaringType.IsArray)
                {
                    // New multi dimensional array
                    // Get element type
                    var elemType = ((XArrayType)declaringType).ElementType;
                    var typeExpr = new AstExpression(node.SourceLocation, AstCode.TypeOf, elemType);

                    // Create dimensions array
                    var intArrayType = new XArrayType(typeSystem.Int);
                    var dimArrayExpr = new AstExpression(node.SourceLocation, AstCode.InitArrayFromArguments, intArrayType, node.Arguments).SetType(intArrayType);

                    // Call java.lang.reflect.Array.newInstance(type, int[])
                    var newInstanceExpr = new AstExpression(node.SourceLocation, AstCode.ArrayNewInstance2, null, typeExpr, dimArrayExpr).SetType(typeSystem.Object);

                    // Cast to correct type
                    var cast = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, declaringType, newInstanceExpr).SetType(declaringType);

                    // Replace node
                    node.CopyFrom(cast);
                }
                else
                {
                    // Normal "new object"
                    XMethodDefinition ctorDef;
                    if (ctorRef.TryResolve(out ctorDef) && ctorDef.NeedsGenericInstanceTypeParameter)
                    {
                        // Add generic instance type parameter value
                        var arg = CreateGenericInstanceCallArguments(node.SourceLocation, ctorRef.DeclaringType, currentMethod, compiler);
                        node.Arguments.AddRange(arg);
                        node.GenericInstanceArgCount += arg.Count;
                    }
                }
            }
        }
Esempio n. 36
0
        /// <summary>
        /// Create an annotation interface.
        /// </summary>
        internal static AttributeAnnotationInterface Create(
            ISourceLocation sequencePoint,
            AssemblyCompiler compiler,
            DexTargetPackage targetPackage,
            TypeDefinition attributeType,
            ClassDefinition attributeClass)
        {
            // Create class
            ClassDefinition @interface = new ClassDefinition();

            @interface.Name        = CreateAnnotationTypeName(attributeClass);
            @interface.Namespace   = attributeClass.Namespace;
            @interface.AccessFlags = AccessFlags.Public | AccessFlags.Abstract | AccessFlags.Interface | AccessFlags.Annotation;
            @interface.Owner       = attributeClass;
            attributeClass.InnerClasses.Add(@interface);

            // Set super class
            @interface.SuperClass = new ClassReference("java/lang/Object");

            // Implement Dot42.Internal.IAttribute
            @interface.Interfaces.Add(new ClassReference("java/lang/annotation/Annotation"));

            // Prepare result
            AttributeAnnotationInterface result = new AttributeAnnotationInterface(@interface);

            // Add methods from IAttribute
            XModel.XTypeDefinition baseIntfType = compiler.GetDot42InternalType("IAttribute").Resolve();
            foreach (XModel.XMethodDefinition imethod in baseIntfType.Methods)
            {
                if (imethod.Parameters.Count > 0)
                {
                    throw new CompilerException(string.Format("Invalid IAttribute method {0}", imethod));
                }
                string           methodName = NameConverter.GetConvertedName(imethod);
                TypeReference    dfieldType = imethod.ReturnType.GetReference(targetPackage);
                MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dfieldType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                @interface.Methods.Add(method);
            }

            // Add field mapping
            foreach (var field in attributeType.Fields.Where(x => x.IsReachable && x.IsPublic))
            {
                string           methodName = CreateGetMethodName(NameConverter.GetConvertedName(field), result);
                TypeReference    dfieldType = field.FieldType.GetReference(targetPackage, compiler.Module);
                MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dfieldType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                result.FieldToGetMethodMap.Add(field, method);
                @interface.Methods.Add(method);
            }

            // Add property mapping
            foreach (var property in attributeType.Properties.Where(x => x.IsReachable && (x.SetMethod != null) && (x.SetMethod.IsPublic) && x.SetMethod.IsReachable))
            {
                string           methodName = CreateGetMethodName(NameConverter.GetConvertedName(property), result);
                TypeReference    dpropType  = property.PropertyType.GetReference(targetPackage, compiler.Module);
                MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dpropType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                result.PropertyToGetMethodMap.Add(property, method);
                @interface.Methods.Add(method);
            }

            // Add ctor mapping
            var argIndex = 0;

            foreach (var ctor in attributeType.Methods.Where(x => (x.Name == ".ctor") && x.IsReachable))
            {
                // Add methods for the ctor arguments
                List <MethodDefinition> paramGetMethods = new List <MethodDefinition>();
                foreach (ParameterDefinition p in ctor.Parameters)
                {
                    string           methodName = CreateGetMethodName("c" + argIndex++, result);
                    TypeReference    dparamType = p.ParameterType.GetReference(targetPackage, compiler.Module);
                    MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dparamType));
                    method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                    @interface.Methods.Add(method);
                    paramGetMethods.Add(method);
                }

                // Add a builder method
                MethodDefinition buildMethod = CreateBuildMethod(sequencePoint, ctor, paramGetMethods, compiler, targetPackage, attributeClass, result);
                result.CtorMap.Add(ctor, new AttributeCtorMapping(buildMethod, paramGetMethods));
            }

            // Create default values annotation
            Annotation defAnnotation = CreateDefaultAnnotation(result);

            result.AnnotationInterfaceClass.Annotations.Add(defAnnotation);

            return(result);
        }
Esempio n. 37
0
        public static Annotation GetGenericDefinitionAnnotationForType(XTypeReference xtype, bool forceTypeDefinition, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            var genericsDefAnnotationClass = compiler.GetDot42InternalType(InternalConstants.GenericDefinitionAnnotation)
                                                     .GetClassReference(targetPackage);
            var annotation = new Annotation {Type = genericsDefAnnotationClass, Visibility = AnnotationVisibility.Runtime};

            if (xtype.IsGenericInstance)
            {
                bool handled = false;
                List<object> genericArguments = new List<object>();

                if (xtype.GetElementType().IsNullableT())
                {
                    // privitives and enums are represented by their marker classes. 
                    // no annotation needed.
                    var argument = ((XGenericInstanceType) xtype).GenericArguments[0];
                    if (argument.IsEnum() || argument.IsPrimitive && !forceTypeDefinition)
                    {
                        return null;
                    }
                        
                    // structs have marker classes.
                    var classRef = xtype.GetReference(targetPackage) as ClassReference;
                    var @class = classRef == null ? null : targetPackage.DexFile.GetClass(classRef.Fullname);
                    if (@class != null && @class.NullableMarkerClass != null)
                    {
                        annotation.Arguments.Add(new AnnotationArgument("GenericInstanceType", @class.NullableMarkerClass));
                        handled = true;
                    }
                }

                if (!handled)
                {
                    foreach (var arg in ((XGenericInstanceType) xtype).GenericArguments)
                    {
                        if (arg.IsGenericParameter)
                        {
                            var gparm = (XGenericParameter) arg;

                            // TODO: if we wanted to annotate methods as well, we should differentiate 
                            //       between generic method arguments and generic type arguments.

                            genericArguments.Add(gparm.Position);
                        }
                        else if (arg.IsGenericInstance)
                        {
                            var giparm = GetGenericDefinitionAnnotationForType((XGenericInstanceType) arg, true,compiler, targetPackage);
                            genericArguments.Add(giparm);
                        }
                        else
                        {
                            genericArguments.Add(arg.GetReference(targetPackage));
                        }
                    }
                    annotation.Arguments.Add(new AnnotationArgument("GenericArguments", genericArguments.ToArray()));
                }
            }
            else // generic parameter
            {
                var parm = (XGenericParameter) xtype;
                annotation.Arguments.Add(new AnnotationArgument("GenericParameter", parm.Position));
            }

            if(forceTypeDefinition && annotation.Arguments.All(a => a.Name != "GenericInstanceType"))
                annotation.Arguments.Add(new AnnotationArgument("GenericTypeDefinition", xtype.ElementType.GetReference(targetPackage)));

            return annotation;
        }
Esempio n. 38
0
        /// <summary>
        /// Convert node with code InstanceOf.
        /// </summary>
        private static void ConvertInstanceOf(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference)node.Operand;

            if (type.IsSystemArray()) // "is System.Array"
            {
                // Call ArrayHelper.IsArray
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isArray     = arrayHelper.Methods.First(x => x.Name == "IsArray");
                var isArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, isArray, node.Arguments).SetType(typeSystem.Bool);
                node.CopyFrom(isArrayExpr);
                return;
            }

            // make sure we don't evaluate the expression twice.
            var tempVar = new AstGeneratedVariable("temp$$", null)
            {
                Type = compiler.Module.TypeSystem.Object
            };
            var storeTempVar = new AstExpression(node.SourceLocation, AstCode.Stloc, tempVar, node.Arguments[0])
            {
                ExpectedType = compiler.Module.TypeSystem.Object
            };
            var loadTempVar = new AstExpression(node.SourceLocation, AstCode.Ldloc, tempVar).SetType(compiler.Module.TypeSystem.Object);

            if (type.IsSystemCollectionsIEnumerable() ||
                type.IsSystemCollectionsICollection() ||
                type.IsSystemCollectionsIList())
            {
                // Call "(is x) || IsArray(x)"
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isArray     = arrayHelper.Methods.First(x => x.Name == "IsArray" && x.Parameters.Count == 1);

                // "is"
                var isExpr = new AstExpression(node).SetArguments(storeTempVar).SetCode(AstCode.SimpleInstanceOf);

                // Call IsArray
                var isArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, isArray, loadTempVar).SetType(typeSystem.Bool);

                // Combined
                var combined = new AstExpression(node.SourceLocation, AstCode.Or, null, isExpr, isArrayExpr).SetType(typeSystem.Bool);
                node.CopyFrom(combined);
                return;
            }

            if (type.IsSystemCollectionsIEnumerableT() ||
                type.IsSystemCollectionsICollectionT() ||
                type.IsSystemCollectionsIListT())
            {
                // TODO: implement InstanceOf with type check for array types.
                // (is that even possible here?)
            }

            if (type.IsSystemIFormattable())
            {
                // Call "(is x) || IsFormattable(x)"
                var formattable   = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isFormattable = formattable.Methods.First(x => x.Name == "IsVirtualFormattable");

                // "is"
                var isExpr = new AstExpression(node).SetArguments(storeTempVar).SetCode(AstCode.SimpleInstanceOf);

                // Call IsFormattable
                var isFormattableExpr = new AstExpression(node.SourceLocation, AstCode.Call, isFormattable, loadTempVar).SetType(typeSystem.Bool);

                // Combined
                var combined = new AstExpression(node.SourceLocation, AstCode.Or, null, isExpr, isFormattableExpr).SetType(typeSystem.Bool);
                node.CopyFrom(combined);
                return;
            }

            // Normal instanceof
            node.Code = AstCode.SimpleInstanceOf;
        }
Esempio n. 39
0
        /// <summary>
        /// Create code to initialize a value from an attribute.
        /// </summary>
        /// <returns>The register(s) holding the value</returns>
        private static Register[] CreateInitializeValueInstructions(ISourceLocation seqp, MethodBody body, XTypeReference targetType, CustomAttributeArgument value, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            List <Register> result = new List <Register>();

            // allocate result, initialize to default value.
            if (targetType.IsWide())
            {
                Tuple <Register, Register> regs = body.AllocateWideRegister(RCategory.Temp);
                //body.Instructions.Add(seqp, RCode.Const_wide, 0, regs.Item1);
                result.Add(regs.Item1);
                result.Add(regs.Item2);
            }
            else if (targetType.IsPrimitive)
            {
                Register reg = body.AllocateRegister(RCategory.Temp, RType.Value);
                //body.Instructions.Add(seqp, RCode.Const, 0, reg);
                result.Add(reg);
            }
            else // object
            {
                Register reg = body.AllocateRegister(RCategory.Temp, RType.Object);
                //body.Instructions.Add(seqp, RCode.Const, 0, reg);
                result.Add(reg);
            }

            // load data

            if (value.Value == null) // must be a reference type
            {
                body.Instructions.Add(seqp, RCode.Const, 0, result[0]);
                body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
                return(result.ToArray());
            }

            var valueType = XBuilder.AsTypeReference(compiler.Module, value.Type);

            if (value.Value is CustomAttributeArgument)
            {
                // this happens if a type conversion is neccessary
                var nestedValue = (CustomAttributeArgument)value.Value;
                valueType = XBuilder.AsTypeReference(compiler.Module, nestedValue.Type);

                var rOrigValue = CreateInitializeValueInstructions(seqp, body, valueType, nestedValue, compiler, targetPackage);

                if (!nestedValue.Type.IsPrimitive)
                {
                    body.Instructions.Add(seqp, RCode.Move_object, result[0], rOrigValue[0]);
                    body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
                }
                else if (!targetType.IsPrimitive)
                {
                    body.Instructions.Add(seqp, RCode.Invoke_static, valueType.GetBoxValueOfMethod(), rOrigValue);
                    body.Instructions.Add(seqp, RCode.Move_result_object, result[0]);
                    body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
                }
                else
                {
                    throw new Exception(string.Format("type converstion in attribute {0}=>{1} not yet supported", valueType.FullName, targetType.FullName));
                }
            }
            else if (valueType.IsArray)
            {
                var array       = (CustomAttributeArgument[])value.Value;
                var elementType = valueType.ElementType;

                Register rIndex = body.AllocateRegister(RCategory.Temp, RType.Value);
                body.Instructions.Add(seqp, RCode.Const, array.Length, rIndex);
                body.Instructions.Add(seqp, RCode.New_array, valueType.GetReference(targetPackage), result[0], rIndex);

                // iterate through each value
                for (int i = 0; i < array.Length; i++)
                {
                    Register rLoaded = CreateInitializeValueInstructions(seqp, body, elementType, array[i], compiler, targetPackage)[0];

                    body.Instructions.Add(seqp, RCode.Const, i, rIndex);
                    body.Instructions.Add(seqp, valueType.APut(), rLoaded, result[0], rIndex);
                }
            }
            else if (targetType.IsEnum())
            {
                var enumClass = (targetType.IsEnum()? targetType:valueType).GetReference(targetPackage);

                Register rEnumClass = body.AllocateRegister(RCategory.Temp, RType.Object);
                body.Instructions.Add(seqp, RCode.Const_class, enumClass, rEnumClass);

                long lVal = Convert.ToInt64(value.Value);
                if (lVal <= int.MaxValue && lVal >= int.MinValue)
                {
                    Register regTmp = body.AllocateRegister(RCategory.Temp, RType.Value);
                    body.Instructions.Add(seqp, RCode.Const, (int)lVal, regTmp);
                    var get = compiler.GetDot42InternalType("Enum").Resolve()
                              .Methods.Single(p => p.Name == "Get" && p.Parameters.Count == 2 && !p.Parameters[1].ParameterType.IsWide())
                              .GetReference(targetPackage);
                    body.Instructions.Add(seqp, RCode.Invoke_static, get, rEnumClass, regTmp);
                    body.Instructions.Add(seqp, targetType.MoveResult(), result[0]);
                }
                else
                {
                    var regTmp = body.AllocateWideRegister(RCategory.Temp);
                    body.Instructions.Add(seqp, RCode.Const, (long)lVal, regTmp.Item1);
                    var get = compiler.GetDot42InternalType("Enum").Resolve()
                              .Methods.Single(p => p.Name == "Get" && p.Parameters.Count == 2 && p.Parameters[1].ParameterType.IsWide())
                              .GetReference(targetPackage);
                    body.Instructions.Add(seqp, RCode.Invoke_static, get, rEnumClass, regTmp.Item1);
                    body.Instructions.Add(seqp, targetType.MoveResult(), result[0]);
                }
                body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
            }
            else if (valueType.IsSystemString())
            {
                body.Instructions.Add(seqp, RCode.Const_string, (string)value.Value, result[0]);
            }
            else if (valueType.IsSystemType())
            {
                var type = XBuilder.AsTypeReference(compiler.Module, (TypeReference)value.Value);
                // TODO: this might not work with typeof(void) on ART runtime.
                body.Instructions.Add(seqp, RCode.Const_class, type.GetReference(targetPackage), result[0]);
            }
            else if (!valueType.IsPrimitive)
            {
                // can this happen?
                throw new Exception("invalid value type in attribute: " + targetType.FullName);
            }
            else
            {
                if (targetType.IsSystemObject())
                {
                    // can this happen? or is this always handled above?

                    // boxing required.
                    var rUnboxed = CreateInitializeValueInstructions(seqp, body, valueType, value, compiler, targetPackage);
                    body.Instructions.Add(seqp, RCode.Invoke_static, valueType.GetBoxValueOfMethod(), rUnboxed);
                    body.Instructions.Add(seqp, RCode.Move_result_object, result[0]);
                }
                else if (targetType.IsDouble())
                {
                    body.Instructions.Add(seqp, RCode.Const_wide, Convert.ToDouble(value.Value), result[0]);
                }
                else if (targetType.IsWide() && valueType.IsUInt64())
                {
                    body.Instructions.Add(seqp, RCode.Const_wide, (long)Convert.ToUInt64(value.Value), result[0]);
                }
                else if (targetType.IsWide())
                {
                    body.Instructions.Add(seqp, RCode.Const_wide, Convert.ToInt64(value.Value), result[0]);
                }
                else if (targetType.IsFloat())
                {
                    body.Instructions.Add(seqp, RCode.Const, Convert.ToSingle(value.Value), result[0]);
                }
                else
                {
                    body.Instructions.Add(seqp, RCode.Const, (int)Convert.ToInt64(value.Value), result[0]);
                }
            }

            return(result.ToArray());
        }
        /// <summary>
        /// Optimize expressions
        /// </summary>
        public static void Convert(AstNode ast, MethodSource currentMethod, AssemblyCompiler compiler)
        {
            foreach (var node in ast.GetExpressions(x => (x.Code == AstCode.Call) || (x.Code == AstCode.Calli) || (x.Code == AstCode.Callvirt)))
            {
                var  method    = (XMethodReference)node.Operand;
                bool processed = false;
                XMethodDefinition methodDef;

                if (method.TryResolve(out methodDef) && methodDef.DeclaringType.IsPrimitive)
                {
                    if (methodDef.IsConstructor && (node.Arguments.Count == 2))
                    {
                        // primitive.ctor(addressof_primitive, value) -> primitive.cast(value)
                        var locVar = node.Arguments[0].Operand;
                        node.Arguments.RemoveAt(0);
                        node.SetCode(AstCode.Stloc).SetType(node.Arguments[0].GetResultType()).Operand = locVar;
                        processed = true;
                    }
                    else if (methodDef.Name == "GetHashCode" && node.Arguments.Count == 1 && methodDef.HasThis)
                    {
                        // we try to avoid boxing.
                        var arg = node.Arguments[0];


                        switch (arg.Code)
                        {
                        case AstCode.AddressOf:
                            arg = arg.Arguments[0];
                            break;

                        case AstCode.Ldloca:
                            arg.SetCode(AstCode.Ldloc);
                            arg.SetType(arg.InferredType.ElementType);
                            break;

                        case AstCode.Ldflda:
                            arg.SetCode(AstCode.Ldfld);
                            arg.SetType(arg.InferredType.ElementType);
                            break;

                        case AstCode.Ldsflda:
                            arg.SetCode(AstCode.Ldsfld);
                            arg.SetType(arg.InferredType.ElementType);
                            break;

                        case AstCode.Ldelema:
                            arg.SetCode(AstCode.Ldelem_Any);
                            arg.SetType(arg.InferredType.ElementType);
                            break;
                        }

                        var type = arg.GetResultType();

                        if (type.IsBoolean() ||
                            type.IsFloat() || type.IsDouble() ||
                            type.IsInt64() || type.IsUInt64())
                        {
                            var ch = compiler.GetDot42InternalType("CompilerHelper").Resolve();

                            // these need special handling

                            var replMethod = ch.Methods.FirstOrDefault(m => m.Name == "GetHashCode" && m.IsStatic &&
                                                                       m.Parameters[0].ParameterType.IsSame(type, true));
                            if (replMethod != null)
                            {
                                node.Operand = replMethod;
                                node.SetCode(AstCode.Call);
                                node.Arguments.Clear();
                                node.Arguments.Add(arg);
                            }
                        }
                        else
                        {
                            // for the other primitive types, we just return the value itself.
                            node.CopyFrom(arg);
                            node.ExpectedType = compiler.Module.TypeSystem.Int;
                        }

                        processed = true;
                    }
                }

                if (!processed)
                {
                    for (var i = 0; i < node.Arguments.Count; i++)
                    {
                        ProcessArgument(node, method, i, currentMethod, compiler.Module);
                    }
                }
            }
        }
Esempio n. 41
0
        internal static void FinalizeFrameworkPropertyAnnotations(AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            var reflInfoRef = compiler.GetDot42InternalType("Dot42.Internal.ReflectionInfo", "FrameworkPropertyInfoProvider")
                          .GetClassReference(targetPackage);

            var relfInfo = targetPackage.DexFile.GetClass(reflInfoRef.Fullname);
            var propertiesClass = compiler.GetDot42InternalType("IProperties").GetClassReference(targetPackage);
            var properties = relfInfo.Annotations.FirstOrDefault(a => a.Type.Fullname == propertiesClass.Fullname);

            if (properties == null)
                return;

            var property = properties.Arguments.Single();
            properties.Arguments.Clear();
            properties.Arguments.Add(new AnnotationArgument(property.Name, ((List<Annotation>)property.Value).ToArray()));

        }
Esempio n. 42
0
        /// <summary>
        /// Convert node with code IsInst.
        /// </summary>
        private static void ConvertIsInst(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference)node.Operand;

            if (type.IsSystemArray())
            {
                // Call ArrayHelper.AsArray
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var asArray     = arrayHelper.Methods.First(x => x.Name == "AsArray");
                var asArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, asArray, node.Arguments).SetType(typeSystem.Bool);
                node.CopyFrom(asArrayExpr);
                return;
            }

            string asMethod = null;

            if (type.IsSystemCollectionsIEnumerable())
            {
                asMethod = "AsEnumerable";
            }
            else if (type.IsSystemCollectionsICollection())
            {
                asMethod = "AsCollection";
            }
            else if (type.IsSystemCollectionsIList())
            {
                asMethod = "AsList";
            }
            else if (type.IsSystemIFormattable())
            {
                asMethod = "AsFormattable";
            }

            if (asMethod != null)
            {
                // Call "(x instanceof T) ? (T)x : asMethod(x)"
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var asArray     = arrayHelper.Methods.First(x => x.Name == asMethod);

                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, node.Arguments[0]).SetType(typeSystem.Bool);

                // AsX(x)
                var asXExpr = new AstExpression(node.SourceLocation, AstCode.Call, asArray, node.Arguments[0]).SetType(typeSystem.Object);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, node.Arguments[0]).SetType(type);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, asXExpr).SetType(type);

                node.CopyFrom(conditional);
                return;
            }

            // Normal "as": Convert to (x instanceof T) ? T(x) : null
            {
                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, node.Arguments[0]).SetType(typeSystem.Bool);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, node.Arguments[0]).SetType(type);

                // null
                var nullExpr = new AstExpression(node.SourceLocation, AstCode.Ldnull, null).SetType(typeSystem.Object);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, nullExpr).SetType(type);

                node.CopyFrom(conditional);
                return;
            }
        }
Esempio n. 43
0
        /// <summary>
        /// Convert node with code Callvirt. 
        /// 
        /// For arrays: intercepts call to IEnumerable.IEnumerable_GetEnumerator generated 
        /// by foreach statements and swaps them out to System.Array.GetEnumerator.
        /// 
        /// This call will then at a later compilation stage be replaced with the final destination.
        /// </summary>
        private static void ConvertCallvirtIEnumerable(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var targetMethodRef = ((XMethodReference)node.Operand);
            var targetMethodDefOrRef = targetMethodRef;

            if (targetMethodDefOrRef.DeclaringType.IsSystemCollectionsIEnumerable()
                && targetMethodDefOrRef.Name == "IEnumerable_GetEnumerator"
                && node.Arguments.Count == 1)
            {
                var argument = node.Arguments[0];
                if (!argument.InferredType.IsArray)
                    return;

                // swap the call to System.Array
                var systemArray = compiler.GetDot42InternalType("System", "Array").Resolve();
                var getEnumerator = systemArray.Methods.First(x => x.Name == "GetEnumerator" && !x.IsStatic && x.Parameters.Count == 0);
                node.Operand = getEnumerator;
            }
            else if (targetMethodDefOrRef.DeclaringType.IsSystemCollectionsIEnumerableT()
                  && targetMethodDefOrRef.Name.EndsWith("_GetEnumerator")
                  && node.Arguments.Count == 1)
            {
                var argument = node.Arguments[0];
                if (!argument.InferredType.IsArray)
                    return;

                var elementType = argument.InferredType.ElementType;

                // Use As...Enumerable to convert
                var asEnumerableName = FrameworkReferences.GetAsEnumerableTMethodName(elementType);
                var compilerHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var asEnumerableMethod = compilerHelper.Methods.First(x => x.Name == asEnumerableName);
                
                var call = new AstExpression(node.SourceLocation, AstCode.Call, asEnumerableMethod, argument)
                {
                    InferredType = asEnumerableMethod.ReturnType
                };
                node.Arguments[0] = call;

                argument.ExpectedType = argument.InferredType;
            }
        }
        /// <summary>
        /// Create an annotation interface.
        /// </summary>
        internal static AttributeAnnotationInterface Create(
            ISourceLocation sequencePoint,
            AssemblyCompiler compiler,
            DexTargetPackage targetPackage,
            TypeDefinition attributeType,
            ClassDefinition attributeClass)
        {
            // Create class
            ClassDefinition @interface = new ClassDefinition();
            @interface.Name = CreateAnnotationTypeName(attributeClass);
            @interface.Namespace = attributeClass.Namespace;
            @interface.AccessFlags = AccessFlags.Public | AccessFlags.Abstract | AccessFlags.Interface | AccessFlags.Annotation;
            @interface.Owner = attributeClass;
            attributeClass.AddInnerClass(@interface);

            // Set super class
            @interface.SuperClass = FrameworkReferences.Object;

            // Implement Dot42.Internal.IAttribute
            @interface.Interfaces.Add(new ClassReference("java/lang/annotation/Annotation"));

            // Prepare result
            AttributeAnnotationInterface result = new AttributeAnnotationInterface(@interface);

            // Add methods from IAttribute
            XModel.XTypeDefinition baseIntfType = compiler.GetDot42InternalType("IAttribute").Resolve();
            foreach (XModel.XMethodDefinition imethod in baseIntfType.Methods)
            {
                if (imethod.Parameters.Count > 0) 
                    throw new CompilerException(string.Format("Invalid IAttribute method {0}", imethod));
                string methodName = NameConverter.GetConvertedName(imethod);
                TypeReference dfieldType = imethod.ReturnType.GetReference(targetPackage);
                MethodDefinition method = new MethodDefinition(@interface, methodName, new Prototype(dfieldType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                @interface.Methods.Add(method);                
            }

            TypeDefinition currentType = attributeType;

            while (currentType != null && currentType.FullName != typeof(Attribute).FullName)
            {
                // Add field mapping
                foreach (var field in currentType.Fields.Where(x => x.IsReachable && x.IsPublic))
                {
                    string methodName = CreateGetMethodName(NameConverter.GetConvertedName(field), result);
                    MethodDefinition method = new MethodDefinition(@interface, methodName,
                                                        MakePrototype(field.FieldType, targetPackage, compiler.Module));
                    method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                    result.FieldToGetMethodMap.Add(field, method);
                    @interface.Methods.Add(method);
                }

                // Add property mapping
                foreach (var property in currentType.Properties.Where(
                                              x => x.IsReachable && (x.SetMethod != null) 
                                         && x.SetMethod.IsPublic && x.SetMethod.IsReachable))
                {
                    // ignore properties with same name [might be overriden]
                    if (result.PropertyToGetMethodMap.Keys.Any(k => k.Name == property.Name))
                        continue;

                    string methodName = CreateGetMethodName(NameConverter.GetConvertedName(property), result);
                    Mono.Cecil.TypeReference propType = property.PropertyType;

                    MethodDefinition method = new MethodDefinition(@interface, methodName,
                                                        MakePrototype(propType, targetPackage, compiler.Module));
                    method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                    result.PropertyToGetMethodMap.Add(property, method);
                    @interface.Methods.Add(method);
                }

                if (currentType.BaseType == null || currentType.BaseType.IsSystemObject())
                    break;

                currentType = currentType.BaseType.Resolve();
            }
            // Add ctor mapping
            var argIndex = 0;
            foreach (var ctor in attributeType.Methods.Where(x => (x.Name == ".ctor") && x.IsReachable))
            {
                // Add methods for the ctor arguments
                List<Tuple<MethodDefinition, Mono.Cecil.TypeReference>> paramGetMethods = new List<Tuple<MethodDefinition, Mono.Cecil.TypeReference>>();
                foreach (ParameterDefinition p in ctor.Parameters)
                {
                    string methodName = CreateGetMethodName("c" + argIndex++, result);
                    MethodDefinition method = new MethodDefinition(@interface, methodName, MakePrototype(p.ParameterType, targetPackage, compiler.Module));
                    method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                    @interface.Methods.Add(method);
                    paramGetMethods.Add(Tuple.Create(method, p.ParameterType));
                }

                // Add a builder method
                MethodDefinition buildMethod = CreateBuildMethod(sequencePoint, ctor, paramGetMethods, compiler, targetPackage, attributeClass, result);
                result.CtorMap.Add(ctor, new AttributeCtorMapping(buildMethod, paramGetMethods.Select(p=>p.Item1).ToList()));
            }

            // Create default values annotation
            Annotation defAnnotation = CreateDefaultAnnotation(result);
            result.AnnotationInterfaceClass.Annotations.Add(defAnnotation);

            return result;
        }
Esempio n. 45
0
        /// <summary>
        /// Convert  ret or store field node.
        /// 
        /// converts to IEnumerable, ICollection or IList if required.
        /// </summary>
        private static void ConvertRetOrStfldOrStsfld(AssemblyCompiler compiler, XTypeReference targetType, AstExpression node, XTypeSystem typeSystem)
        {
            var argument = node.Arguments.LastOrDefault();
            
            if (argument == null)
                return;

            if (argument.InferredType == null || !argument.InferredType.IsArray)
                return;

            var methodName = GetCollectionConvertMethodName(targetType);
            if (methodName == null) 
                return;
            
            // Call "ret asMethod(x)"
            var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
            var asArray = arrayHelper.Methods.First(x => x.Name == "As" + methodName);

            // AsX(x)
            var asXExpr = new AstExpression(node.SourceLocation, AstCode.Call, asArray, argument).SetType(typeSystem.Object);

            // replace argument.
            node.Arguments[node.Arguments.Count-1] = asXExpr;
        }
        /// <summary>
        /// Optimize expressions
        /// </summary>
        public static void Convert(AstNode ast, MethodSource currentMethod, AssemblyCompiler compiler)
        {
            foreach (var node in ast.GetExpressions(x => (x.Code == AstCode.Call) || (x.Code == AstCode.Calli) || (x.Code == AstCode.Callvirt)))
            {
                var method = (XMethodReference)node.Operand;
                bool processed = false;
                XMethodDefinition methodDef;

                if (method.TryResolve(out methodDef) && methodDef.DeclaringType.IsPrimitive)
                {
                    if (methodDef.IsConstructor &&  (node.Arguments.Count == 2))
                    {
                        // primitive.ctor(addressof_primitive, value) -> primitive.cast(value)
                        var locVar = node.Arguments[0].Operand;
                        node.Arguments.RemoveAt(0);
                        node.SetCode(AstCode.Stloc).SetType(node.Arguments[0].GetResultType()).Operand = locVar;
                        processed = true;
                    }
                    else if (methodDef.Name == "GetHashCode" && node.Arguments.Count == 1 && methodDef.HasThis)
                    {
                        // we try to avoid boxing.
                        var arg = node.Arguments[0];


                        switch (arg.Code)
                        {
                            case AstCode.AddressOf:
                                arg = arg.Arguments[0];
                                break;
                            case AstCode.Ldloca:
                                arg.SetCode(AstCode.Ldloc);
                                arg.SetType(arg.InferredType.ElementType);
                                break;
                            case AstCode.Ldflda:
                                arg.SetCode(AstCode.Ldfld);
                                arg.SetType(arg.InferredType.ElementType);
                                break;
                            case AstCode.Ldsflda:
                                arg.SetCode(AstCode.Ldsfld);
                                arg.SetType(arg.InferredType.ElementType);
                                break;
                            case AstCode.Ldelema:
                                arg.SetCode(AstCode.Ldelem_Any);
                                arg.SetType(arg.InferredType.ElementType);
                                break;
                        }

                        var type = arg.GetResultType();

                        if (type.IsBoolean()
                            || type.IsFloat() || type.IsDouble()
                            || type.IsInt64() || type.IsUInt64())
                        {
                            var ch = compiler.GetDot42InternalType("CompilerHelper").Resolve();

                            // these need special handling

                            var replMethod = ch.Methods.FirstOrDefault(m => m.Name == "GetHashCode" && m.IsStatic
                                                 && m.Parameters[0].ParameterType.IsSame(type, true));
                            if (replMethod != null)
                            {
                                node.Operand = replMethod;
                                node.SetCode(AstCode.Call);
                                node.Arguments.Clear();
                                node.Arguments.Add(arg);
                            }
                        }
                        else
                        {
                            // for the other primitive types, we just return the value itself.
                            node.CopyFrom(arg);
                            node.ExpectedType = compiler.Module.TypeSystem.Int;
                        }

                        processed = true;
                    }
                }

                if(!processed)
                {
                    for (var i = 0; i < node.Arguments.Count; i++)
                    {
                        ProcessArgument(node, method, i, currentMethod, compiler.Module);
                    }
                }
            }
        }
Esempio n. 47
0
        /// <summary>
        /// Convert node with code InstanceOf.
        /// </summary>
        private static void ConvertInstanceOf(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference)node.Operand;
            if (type.IsSystemArray()) // "is System.Array"
            {
                // Call ArrayHelper.IsArray
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isArray = arrayHelper.Methods.First(x => x.Name == "IsArray");
                var isArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, isArray, node.Arguments).SetType(typeSystem.Bool);
                node.CopyFrom(isArrayExpr);
                return;
            }

            if (type.IsSystemCollectionsIEnumerable() || type.IsSystemCollectionsICollection() ||
                type.IsSystemCollectionsIList())
            {
                // Call "(is x) || IsArray(x)"
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isArray = arrayHelper.Methods.First(x => x.Name == "IsArray");

                // "is" 
                var isExpr = new AstExpression(node).SetCode(AstCode.SimpleInstanceOf);

                // Call IsArray
                var isArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, isArray, node.Arguments).SetType(typeSystem.Bool);

                // Combined
                var combined = new AstExpression(node.SourceLocation, AstCode.Or, null, isExpr, isArrayExpr).SetType(typeSystem.Bool);
                node.CopyFrom(combined);
                return;
            }
            if (type.IsSystemIFormattable())
            {
                // Call "(is x) || IsFormattable(x)"
                var formattable = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var isFormattable = formattable.Methods.First(x => x.Name == "IsVirtualFormattable");

                // "is" 
                var isExpr = new AstExpression(node).SetCode(AstCode.SimpleInstanceOf);

                // Call IsFormattable
                var isFormattableExpr = new AstExpression(node.SourceLocation, AstCode.Call, isFormattable, node.Arguments).SetType(typeSystem.Bool);

                // Combined
                var combined = new AstExpression(node.SourceLocation, AstCode.Or, null, isExpr, isFormattableExpr).SetType(typeSystem.Bool);
                node.CopyFrom(combined);
                return;
            }

            // Normal instanceof
            node.Code = AstCode.SimpleInstanceOf;            
        }
Esempio n. 48
0
        /// <summary>
        /// Emit code (if needed) to convert a value from source type to destination type.
        /// This method is used in "store" opcodes such stloc, stfld, stsfld, call
        /// </summary>
        internal static RLRange ConvertTypeBeforeStore(this IRLBuilder builder, ISourceLocation sequencePoint, XTypeReference sourceType, XTypeReference destinationType, RegisterSpec source, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler, out bool converted)
        {
            converted = false;
            if (sourceType.IsSame(destinationType))
            {
                // Unsigned conversions
                if (sourceType.IsByte())
                {
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    var ins = builder.Add(sequencePoint, RCode.Int_to_byte, tmp.Result, tmp.Result);
                    converted = true;
                    return new RLRange(tmp, ins, tmp.Result);
                }
                else if (sourceType.IsUInt16())
                {
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    var ins = builder.Add(sequencePoint, RCode.Int_to_short, tmp.Result, tmp.Result);
                    converted = true;
                    return new RLRange(tmp, ins, tmp.Result);
                }
                return new RLRange(source);
            }

            if (sourceType.IsArray)
            {
                var compilerHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var arrayType = targetPackage.DexFile.GetClass(targetPackage.NameConverter.GetConvertedFullName(compilerHelper));
                var sourceArrayElementType = ((XArrayType)sourceType).ElementType;
                if (destinationType.ExtendsIList())
                {
                    // Use ArrayHelper.AsList to convert
                    var convertMethodName = "AsList";
                    var convertMethod = arrayType.GetMethod(convertMethodName);
                    // Add code
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    builder.Add(sequencePoint, RCode.Invoke_static, convertMethod, tmp.Result.Register);
                    var last = builder.Add(sequencePoint, RCode.Move_result_object, tmp.Result.Register);
                    converted = true;
                    return new RLRange(tmp, last, tmp.Result);
                }
                if (destinationType.ExtendsICollection())
                {
                    // Use ArrayHelper.AsCollection to convert
                    var convertMethodName = "AsCollection";
                    var convertMethod = arrayType.GetMethod(convertMethodName);
                    // Add code
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    builder.Add(sequencePoint, RCode.Invoke_static, convertMethod, tmp.Result.Register);
                    var last = builder.Add(sequencePoint, RCode.Move_result_object, tmp.Result.Register);
                    converted = true;
                    return new RLRange(tmp, last, tmp.Result);
                }
                if (destinationType.ExtendsIEnumerable())
                {
                    // Use ArrayHelper.As...Enumerable to convert
                    var convertMethodName = "AsObjectEnumerable";
                    if (sourceArrayElementType.IsPrimitive)
                    {
                        if (sourceArrayElementType.IsBoolean()) convertMethodName = "AsBoolEnumerable";
                        else if (sourceArrayElementType.IsByte()) convertMethodName = "AsByteEnumerable";
                        else if (sourceArrayElementType.IsSByte()) convertMethodName = "AsSByteEnumerable";
                        else if (sourceArrayElementType.IsChar()) convertMethodName = "AsCharEnumerable";
                        else if (sourceArrayElementType.IsInt16()) convertMethodName = "AsInt16Enumerable";
                        else if (sourceArrayElementType.IsUInt16()) convertMethodName = "AsUInt16Enumerable";
                        else if (sourceArrayElementType.IsInt32()) convertMethodName = "AsInt32Enumerable";
                        else if (sourceArrayElementType.IsUInt32()) convertMethodName = "AsUInt32Enumerable";
                        else if (sourceArrayElementType.IsInt64()) convertMethodName = "AsInt64Enumerable";
                        else if (sourceArrayElementType.IsFloat()) convertMethodName = "AsFloatEnumerable";
                        else if (sourceArrayElementType.IsDouble()) convertMethodName = "AsDoubleEnumerable";
                        else throw new ArgumentOutOfRangeException("Unknown primitive array element type " + sourceArrayElementType);
                    }
                    var convertMethod = arrayType.GetMethod(convertMethodName);
                    // Add code
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    builder.Add(sequencePoint, RCode.Invoke_static, convertMethod, tmp.Result.Register);
                    var last = builder.Add(sequencePoint, RCode.Move_result_object, tmp.Result.Register);
                    converted = true;
                    return new RLRange(tmp, last, tmp.Result);
                }
            }

            // Do not convert
            return new RLRange(source);
        }
Esempio n. 49
0
        /// <summary>
        /// Emit code (if needed) to convert a value from source type to destination type.
        /// This method is used in "store" opcodes such stloc, stfld, stsfld, call
        /// </summary>
        internal static RLRange ConvertTypeBeforeStore(this IRLBuilder builder, ISourceLocation sequencePoint, XTypeReference sourceType, XTypeReference destinationType, RegisterSpec source, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler, out bool converted)
        {
            converted = false;
            if (sourceType.IsSame(destinationType))
            {
                // Unsigned conversions
                if (sourceType.IsByte())
                {
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    var ins = builder.Add(sequencePoint, RCode.Int_to_byte, tmp.Result, tmp.Result);
                    converted = true;
                    return(new RLRange(tmp, ins, tmp.Result));
                }
                else if (sourceType.IsUInt16())
                {
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    var ins = builder.Add(sequencePoint, RCode.Int_to_short, tmp.Result, tmp.Result);
                    converted = true;
                    return(new RLRange(tmp, ins, tmp.Result));
                }
                return(new RLRange(source));
            }

            if (sourceType.IsArray)
            {
                var compilerHelper         = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var arrayType              = targetPackage.DexFile.GetClass(targetPackage.NameConverter.GetConvertedFullName(compilerHelper));
                var sourceArrayElementType = ((XArrayType)sourceType).ElementType;
                if (destinationType.ExtendsIList())
                {
                    // Use ArrayHelper.AsList to convert
                    var convertMethodName = "AsList";
                    var convertMethod     = arrayType.GetMethod(convertMethodName);
                    // Add code
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    builder.Add(sequencePoint, RCode.Invoke_static, convertMethod, tmp.Result.Register);
                    var last = builder.Add(sequencePoint, RCode.Move_result_object, tmp.Result.Register);
                    converted = true;
                    return(new RLRange(tmp, last, tmp.Result));
                }
                if (destinationType.ExtendsICollection())
                {
                    // Use ArrayHelper.AsCollection to convert
                    var convertMethodName = "AsCollection";
                    var convertMethod     = arrayType.GetMethod(convertMethodName);
                    // Add code
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    builder.Add(sequencePoint, RCode.Invoke_static, convertMethod, tmp.Result.Register);
                    var last = builder.Add(sequencePoint, RCode.Move_result_object, tmp.Result.Register);
                    converted = true;
                    return(new RLRange(tmp, last, tmp.Result));
                }
                if (destinationType.ExtendsIEnumerable())
                {
                    // Use ArrayHelper.As...Enumerable to convert
                    var convertMethodName = FrameworkReferences.GetAsEnumerableTMethodName(sourceArrayElementType);
                    var convertMethod     = arrayType.GetMethod(convertMethodName);
                    // Add code
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    builder.Add(sequencePoint, RCode.Invoke_static, convertMethod, tmp.Result.Register);
                    var last = builder.Add(sequencePoint, RCode.Move_result_object, tmp.Result.Register);
                    converted = true;
                    return(new RLRange(tmp, last, tmp.Result));
                }
            }

            if (sourceType.IsGenericParameter && !destinationType.IsSystemObject())
            {
                var gp = (XGenericParameter)sourceType;
                if (gp.Constraints.Length > 0)
                {
                    // we could find the best matching constraint here, and check if we actually
                    // need to cast. This would probably allow us to skip some unneccesary casts.
                    // We would need some sort of IsAssignableFrom though, and I'm not sure we have
                    // this logic with XTypeDefinition implemented yet.
                    // Therefore, we just assume that the original compiler has done its job well,
                    // and always cast to the destination type.
                    // Apparently dex seems not to need a cast when destinationType is an interface.
                    // Since i'm not to sure about this, we nevertheless insert the cast here.
                    // [TODO: check if this is needed]
                    var tmp  = builder.EnsureTemp(sequencePoint, source, frame);
                    var cast = builder.Add(sequencePoint, RCode.Check_cast, destinationType.GetReference(targetPackage), tmp.Result);
                    converted = true;
                    return(new RLRange(tmp, cast, tmp.Result));
                }
            }

            // Do not convert
            return(new RLRange(source));
        }
Esempio n. 50
0
        /// <summary>
        /// Optimize expressions
        /// </summary>
        public static void Convert(AstNode ast, MethodSource currentMethod, AssemblyCompiler compiler)
        {
            var typeSystem = compiler.Module.TypeSystem;

            // Expand typeof
            foreach (var node in ast.GetSelfAndChildrenRecursive<AstExpression>(x => x.Code == AstCode.TypeOf))
            {
                var type = (XTypeReference) node.Operand;
                var typeHelperType = compiler.GetDot42InternalType(InternalConstants.TypeHelperName).Resolve();
                var loadExpr = LoadTypeForGenericInstance(node.SourceLocation, currentMethod, type, compiler, typeHelperType, typeSystem, TypeConversion.EnsureTrueOrMarkerType);
                node.CopyFrom(loadExpr);
            }

            // Expand instanceOf
            foreach (var node in ast.GetSelfAndChildrenRecursive<AstExpression>(x => x.Code == AstCode.SimpleInstanceOf))
            {
                var type = (XTypeReference)node.Operand;
                var gp = type as XGenericParameter;
                if (gp == null) continue;

                var typeHelperType = compiler.GetDot42InternalType(InternalConstants.TypeHelperName).Resolve();
                var loadExpr = LoadTypeForGenericInstance(node.SourceLocation, currentMethod, type, compiler, typeHelperType, typeSystem, TypeConversion.EnsureRuntimeType);
                //// both types are boxed, no need for conversion.
                var typeType = compiler.GetDot42InternalType("System", "Type").Resolve();
                var isInstanceOfType = typeType.Methods.Single(n => n.Name == "JavaIsInstance" && n.Parameters.Count == 1);
                var call = new AstExpression(node.SourceLocation, AstCode.Call, isInstanceOfType, loadExpr, node.Arguments[0]);
                node.CopyFrom(call);
            }

            // Expand newarr
            foreach (var node in ast.GetSelfAndChildrenRecursive<AstExpression>(x => x.Code == AstCode.Newarr))
            {
                var type = (XTypeReference)node.Operand;
                if (!type.IsDefinitionOrReferenceOrPrimitive())
                {
                    // Resolve type to a Class<?>
                    var typeHelperType = compiler.GetDot42InternalType(InternalConstants.TypeHelperName).Resolve();
                    // while having primitive arrays for primitive types would be nice, a lot of boxing and unboxing
                    // would be needed. only for-primitive-specialized generic classes we could optimize this.
                    var ldType = LoadTypeForGenericInstance(node.SourceLocation, currentMethod, type, compiler, typeHelperType, typeSystem, TypeConversion.EnsureRuntimeType);
                    var newInstanceExpr = new AstExpression(node.SourceLocation, AstCode.ArrayNewInstance, null, ldType, node.Arguments[0]) { ExpectedType = typeSystem.Object };
                    var arrayType = new XArrayType(type);
                    var cast = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, arrayType, newInstanceExpr) { ExpectedType = arrayType };
                    node.CopyFrom(cast);
                }
            }

            // Add generic instance call arguments
            foreach (var node in ast.GetSelfAndChildrenRecursive<AstExpression>(x => x.Code.IsCall()))
            {
                var method = (XMethodReference)node.Operand;
                if (method.DeclaringType.IsArray)
                    continue;
                XMethodDefinition methodDef;
                if (!method.TryResolve(out methodDef)) 
                    continue;
                if (methodDef.HasDexNativeAttribute())
                    continue;

                if (methodDef.NeedsGenericInstanceTypeParameter)
                {
                    // Add generic instance type parameter value
                    var arg = CreateGenericInstanceCallArguments(node.SourceLocation, method.DeclaringType, currentMethod, compiler);
                    node.Arguments.AddRange(arg);
                    node.GenericInstanceArgCount += arg.Count;
                }

                if (methodDef.NeedsGenericInstanceMethodParameter)
                {
                    // Add generic instance method parameter
                    var arg = CreateGenericInstanceCallArguments(node.SourceLocation, method, currentMethod, compiler);
                    node.Arguments.AddRange(arg);
                    node.GenericInstanceArgCount += arg.Count;
                }
            }

            // Add generic instance Delegate arguments for static methods.
            foreach (var node in ast.GetSelfAndChildrenRecursive<AstExpression>(x => x.Code == AstCode.Delegate))
            {
                var delegateInfo = (Tuple<XTypeDefinition, XMethodReference>)node.Operand;

                var genMethodDef = delegateInfo.Item2 as IXGenericInstance;
                var genTypeDef = delegateInfo.Item2.DeclaringType as IXGenericInstance;

                // Add generic instance type parameter value, if method is static
                if (genTypeDef != null && delegateInfo.Item2.Resolve().IsStatic)
                {
                    var arg = CreateGenericInstanceCallArguments(node.SourceLocation, delegateInfo.Item2.DeclaringType, currentMethod, compiler);
                    node.Arguments.AddRange(arg);
                    node.GenericInstanceArgCount += arg.Count;
                }

                // add generic method type parameter value.
                if (genMethodDef != null)
                {
                    var arg = CreateGenericInstanceCallArguments(node.SourceLocation, delegateInfo.Item2, currentMethod, compiler);
                    node.Arguments.AddRange(arg);
                    node.GenericInstanceArgCount += arg.Count;
                }
            }

            // Convert NewObj when needed
            foreach (var node in ast.GetSelfAndChildrenRecursive<AstExpression>(x => x.Code == AstCode.Newobj))
            {
                var ctorRef = (XMethodReference)node.Operand;
                var declaringType = ctorRef.DeclaringType;
                if (declaringType.IsArray)
                {
                    // New multi dimensional array
                    // Get element type
                    var elemType = ((XArrayType) declaringType).ElementType;
                    var typeExpr = new AstExpression(node.SourceLocation, AstCode.TypeOf, elemType);

                    // Create dimensions array
                    var intArrayType = new XArrayType(typeSystem.Int);
                    var dimArrayExpr = new AstExpression(node.SourceLocation, AstCode.InitArrayFromArguments, intArrayType, node.Arguments).SetType(intArrayType);

                    // Call java.lang.reflect.Array.newInstance(type, int[])
                    var newInstanceExpr = new AstExpression(node.SourceLocation, AstCode.ArrayNewInstance2, null, typeExpr, dimArrayExpr).SetType(typeSystem.Object);

                    // Cast to correct type
                    var cast = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, declaringType, newInstanceExpr).SetType(declaringType);

                    // Replace node
                    node.CopyFrom(cast);
                }
                else
                {
                    // Normal "new object"
                    XMethodDefinition ctorDef;
                    if (ctorRef.TryResolve(out ctorDef) && ctorDef.NeedsGenericInstanceTypeParameter)
                    {
                        // Add generic instance type parameter value
                        var arg = CreateGenericInstanceCallArguments(node.SourceLocation, ctorRef.DeclaringType, currentMethod, compiler);
                        node.Arguments.AddRange(arg);
                        node.GenericInstanceArgCount += arg.Count;
                    }
                }
            }
        }
        /// <summary>
        /// Create code to load a value from an annotation interface.
        /// </summary>
        /// <returns>The register(s) holding the value</returns>
        private static Register[] CreateLoadValueSequence(
            ISourceLocation seqp,
            MethodBody body,
            XTypeReference valueType,
            Register annotationReg,
            MethodDefinition getter,
            AssemblyCompiler compiler,
            DexTargetPackage targetPackage,
            out Instruction branchIfNotSet)
        {
            // NOTE: It would be better if we wouldn't get the values as object arrays
            //       but as arrays of the actual type. 
            //       Apparently though the DexWriter will not write our attributes
            //       if they contain arrays not of type object[]. Therefore the 
            //       conversion code below.
            //       All in all it would be much cleaner if we could emit Ast code here
            //       instead of RL code.
            List<Register> result = new List<Register>();

            // get the array.
            Register regObject = body.AllocateRegister(RCategory.Temp, RType.Object);
            Register regIntVal = body.AllocateRegister(RCategory.Temp, RType.Value);
            
            body.Instructions.Add(seqp, RCode.Invoke_interface, getter, annotationReg);
            body.Instructions.Add(seqp, RCode.Move_result_object, regObject);

            // allocate result, initialize to default value.
            if (valueType.IsWide())
            {
                Tuple<Register, Register> regs = body.AllocateWideRegister(RCategory.Temp);
                body.Instructions.Add(seqp, RCode.Const_wide, 0, regs.Item1);
                result.Add(regs.Item1);
                result.Add(regs.Item2);
            }
            else if (valueType.IsPrimitive)
            {
                Register reg = body.AllocateRegister(RCategory.Temp, RType.Value);
                body.Instructions.Add(seqp, RCode.Const, 0, reg);
                result.Add(reg);
            }
            else // object 
            {
                Register reg = body.AllocateRegister(RCategory.Temp, RType.Object);
                body.Instructions.Add(seqp, RCode.Const, 0, reg);
                result.Add(reg);
            }

            // check if value is unset (array length 0) or null (array length 2)
            body.Instructions.Add(seqp, RCode.Array_length, regIntVal, regObject);
            branchIfNotSet = body.Instructions.Add(seqp, RCode.If_eqz, regIntVal);
            body.Instructions.Add(seqp, RCode.Rsub_int, 1, regIntVal, regIntVal);
            var branchOnNull = body.Instructions.Add(seqp, RCode.If_nez, regIntVal);

            // get the (boxed) value
            body.Instructions.Add(seqp, RCode.Const, 0, regIntVal);

            // convert to target type.
            if (valueType.IsArray)
            {
                Register regTmp = body.AllocateRegister(RCategory.Temp, RType.Object);
                Register regType = body.AllocateRegister(RCategory.Temp, RType.Object);
                
                var helper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName);
                var convertArray = helper.Resolve().Methods.First(p => p.Name == "ConvertArray" && p.Parameters.Count == 2)
                                         .GetReference(targetPackage);
                var underlying = valueType.ElementType.GetReference(targetPackage);

                body.Instructions.Add(seqp, RCode.Aget_object, regTmp, regObject, regIntVal);
                body.Instructions.Add(seqp, RCode.Const_class, underlying, regType);
                body.Instructions.Add(seqp, RCode.Invoke_static, convertArray, regTmp, regType);
                body.Instructions.Add(seqp, RCode.Move_result_object, result[0]);
                body.Instructions.Add(seqp, RCode.Check_cast, valueType.GetReference(targetPackage), result[0]);
            }
            else if (valueType.IsEnum())
            {
                Register regTmp = body.AllocateRegister(RCategory.Temp, RType.Object);
                Register regType = body.AllocateRegister(RCategory.Temp, RType.Object);
                
                var getFromObject = compiler.GetDot42InternalType("Enum").Resolve()
                                            .Methods.Single(p=>p.Name == "GetFromObject")
                                            .GetReference(targetPackage);

                body.Instructions.Add(seqp, RCode.Aget_object, regTmp, regObject, regIntVal);
                body.Instructions.Add(seqp, RCode.Const_class, valueType.GetReference(targetPackage), regType);
                body.Instructions.Add(seqp, RCode.Invoke_static, getFromObject, regType, regTmp);
                body.Instructions.Add(seqp, valueType.MoveResult(), result[0]);
                body.Instructions.Add(seqp, RCode.Check_cast, valueType.GetReference(targetPackage), result[0]);
            }
            else if(!valueType.IsPrimitive)
            {
                body.Instructions.Add(seqp, RCode.Aget_object, result[0], regObject, regIntVal);
                body.Instructions.Add(seqp, RCode.Check_cast, valueType.GetReference(targetPackage), result[0]);
            }
            else
            {
                Register regTmp = body.AllocateRegister(RCategory.Temp, RType.Object);
                // unbox and store
                RCode afterConvert;
                var unbox  = valueType.GetUnboxValueMethod(compiler, targetPackage, out afterConvert);
                body.Instructions.Add(seqp, RCode.Aget_object, regTmp, regObject, regIntVal);
                body.Instructions.Add(seqp, RCode.Invoke_static, unbox, regTmp);
                body.Instructions.Add(seqp, valueType.MoveResult(), result[0]);
                
                if (afterConvert != RCode.Nop)
                {
                    body.Instructions.Add(seqp, afterConvert, result[0], result[0]);
                }
            }

            // nop will be removed at some stage later.
            var nop = body.Instructions.Add(seqp, RCode.Nop);
            branchOnNull.Operand = nop;

            return result.ToArray();
        }
Esempio n. 52
0
        /// <summary>
        /// Convert node with code IsInst.
        /// </summary>
        private static void ConvertIsInst(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference)node.Operand;

            if (type.IsSystemArray())
            {
                // Call ArrayHelper.AsArray
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var asArray     = arrayHelper.Methods.First(x => x.Name == "AsArray");
                var asArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, asArray, node.Arguments).SetType(typeSystem.Bool);
                node.CopyFrom(asArrayExpr);
                return;
            }

            string asMethod = GetCollectionConvertMethodName(type);

            if (asMethod != null)
            {
                asMethod = "As" + asMethod;
            }
            else if (type.IsSystemIFormattable())
            {
                asMethod = "AsFormattable";
            }

            // make sure we don't evaluate the expression twice.
            var tempVar = new AstGeneratedVariable("temp$$", null)
            {
                Type = compiler.Module.TypeSystem.Object
            };
            var storeTempVar = new AstExpression(node.SourceLocation, AstCode.Stloc, tempVar, node.Arguments[0])
            {
                ExpectedType = compiler.Module.TypeSystem.Object
            };
            var loadTempVar = new AstExpression(node.SourceLocation, AstCode.Ldloc, tempVar).SetType(compiler.Module.TypeSystem.Object);


            if (asMethod != null)
            {
                // Call "(x instanceof T) ? (T)x : asMethod(x)"
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var asArray     = arrayHelper.Methods.First(x => x.Name == asMethod);

                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, storeTempVar).SetType(typeSystem.Bool);

                // AsX(x)
                var asXExpr = new AstExpression(node.SourceLocation, AstCode.Call, asArray, loadTempVar).SetType(typeSystem.Object);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, loadTempVar).SetType(type);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, asXExpr).SetType(type);

                node.CopyFrom(conditional);
                return;
            }

            // Normal "as": Convert to (x instanceof T) ? (T)x : null
            if (!type.IsPrimitive)
            {
                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, storeTempVar).SetType(typeSystem.Bool);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, loadTempVar).SetType(type);

                // null
                var nullExpr = new AstExpression(node.SourceLocation, AstCode.Ldnull, null).SetType(typeSystem.Object);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, nullExpr).SetType(type);

                node.CopyFrom(conditional);
                return;
            }
            else
            {
                // treat as "x is T"
                if (!node.ExpectedType.IsBoolean())
                {
                    throw new NotImplementedException(); // can this happen?
                }
                node.Code = AstCode.SimpleInstanceOf;
            }
        }
Esempio n. 53
0
        /// <summary>
        /// Create all annotations for this method
        /// </summary>
        internal virtual void CreateAnnotations(DexTargetPackage targetPackage)
        {
            // Build method annotations
            AttributeAnnotationInstanceBuilder.CreateAttributeAnnotations(compiler, method, dmethod, targetPackage);

            // only add generics annotation for getters or setters or constructors
            if (method.IsGetter)
            {
                // Note that the return type might has been
                // changed above, to compensate for interface
                // inheritance and generic specialization.
                // We need to use the original declaration.
                // TODO: why not get rid of "OriginalReturnType"
                //       and use the IL's return type??
                var returnType = xMethod.OriginalReturnType;
                var xType      = XBuilder.AsTypeReference(compiler.Module, returnType);
                dmethod.AddGenericDefinitionAnnotationIfGeneric(xType, compiler, targetPackage);
            }
            else if (method.IsSetter)
            {
                for (int i = 0; i < xMethod.Parameters.Count; ++i)
                {
                    var dp = dmethod.Prototype.Parameters[i];
                    dp.AddGenericDefinitionAnnotationIfGeneric(xMethod.Parameters[i].ParameterType, compiler,
                                                               targetPackage);
                }
            }
            else if (method.IsConstructor && !method.IsStatic)
            {
                // Add parameter names and original access flags, as these might be important
                // in serialization and/or dependency injection.

                var reflectionInfo = compiler.GetDot42InternalType(InternalConstants.ReflectionInfoAnnotation)
                                     .GetClassReference(targetPackage);
                var annotation = new Annotation {
                    Type = reflectionInfo, Visibility = AnnotationVisibility.Runtime
                };

                bool isPublic = (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;

                // Not sure if it makes any sense to remap the access flags.
                bool isProtected = (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family ||
                                   (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem ||
                                   (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem;

                bool isInternal = (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly ||
                                  (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem ||
                                  (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem;

                bool isPrivate = (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;

                // only create accessFlags if they differs from java's
                if (isPublic != dmethod.IsPublic ||
                    isProtected != dmethod.IsProtected ||
                    isPrivate != dmethod.IsPrivate ||
                    isInternal)
                {
                    int accessFlags = 0;
                    if (isPublic)
                    {
                        accessFlags |= 0x01;
                    }
                    if (isProtected)
                    {
                        accessFlags |= 0x02;
                    }
                    if (isPrivate)
                    {
                        accessFlags |= 0x04;
                    }
                    if (isInternal)
                    {
                        accessFlags |= 0x08;
                    }
                    annotation.Arguments.Add(new AnnotationArgument(InternalConstants.ReflectionInfoAccessFlagsField, accessFlags));
                }

                if (method.Parameters.Count > 0)
                {
                    annotation.Arguments.Add(new AnnotationArgument(InternalConstants.ReflectionInfoParameterNamesField,
                                                                    method.Parameters.Select(p => p.Name).ToArray()));
                }

                if (annotation.Arguments.Count > 0)
                {
                    dmethod.Annotations.Add(annotation);
                }

                //for (int i = 0; i < xMethod.Parameters.Count; ++i)
                //{
                //    var dp = dmethod.Prototype.Parameters[i];
                //    dp.AddGenericDefinitionAnnotationIfGeneric(xMethod.Parameters[i].ParameterType, compiler,
                //        targetPackage);
                //}
            }
        }
        /// <summary>
        /// Create code to initialize a value from an attribute.
        /// </summary>
        /// <returns>The register(s) holding the value</returns>
        private static Register[] CreateInitializeValueInstructions(ISourceLocation seqp, MethodBody body, XTypeReference targetType, CustomAttributeArgument value, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            List<Register> result = new List<Register>();

            // allocate result, initialize to default value.
            if (targetType.IsWide())
            {
                Tuple<Register, Register> regs = body.AllocateWideRegister(RCategory.Temp);
                //body.Instructions.Add(seqp, RCode.Const_wide, 0, regs.Item1);
                result.Add(regs.Item1);
                result.Add(regs.Item2);
            }
            else if (targetType.IsPrimitive)
            {
                Register reg = body.AllocateRegister(RCategory.Temp, RType.Value);
                //body.Instructions.Add(seqp, RCode.Const, 0, reg);
                result.Add(reg);
            }
            else // object 
            {
                Register reg = body.AllocateRegister(RCategory.Temp, RType.Object);
                //body.Instructions.Add(seqp, RCode.Const, 0, reg);
                result.Add(reg);
            }

            // load data

            if (value.Value == null) // must be a reference type
            {
                body.Instructions.Add(seqp, RCode.Const, 0, result[0]);
                body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
                return result.ToArray();
            }

            var valueType = XBuilder.AsTypeReference(compiler.Module, value.Type);

            if (value.Value is CustomAttributeArgument)
            {
                // this happens if a type conversion is neccessary
                var nestedValue = (CustomAttributeArgument)value.Value;
                valueType = XBuilder.AsTypeReference(compiler.Module, nestedValue.Type);

                var rOrigValue = CreateInitializeValueInstructions(seqp, body, valueType, nestedValue, compiler, targetPackage);

                if (!nestedValue.Type.IsPrimitive)
                {
                    body.Instructions.Add(seqp, RCode.Move_object, result[0], rOrigValue[0]);
                    body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
                }
                else if(!targetType.IsPrimitive)
                {
                    body.Instructions.Add(seqp, RCode.Invoke_static, valueType.GetBoxValueOfMethod(), rOrigValue);
                    body.Instructions.Add(seqp, RCode.Move_result_object, result[0]);
                    body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
                }
                else
                {
                    throw new Exception(string.Format("type converstion in attribute {0}=>{1} not yet supported", valueType.FullName, targetType.FullName));
                }
            }
            else if (valueType.IsArray)
            {
                var array = (CustomAttributeArgument[])value.Value;
                var elementType = valueType.ElementType;

                Register rIndex = body.AllocateRegister(RCategory.Temp, RType.Value);
                body.Instructions.Add(seqp, RCode.Const, array.Length, rIndex);
                body.Instructions.Add(seqp, RCode.New_array, valueType.GetReference(targetPackage), result[0], rIndex);

                // iterate through each value
                for (int i = 0; i < array.Length; i++)
                {
                    Register rLoaded = CreateInitializeValueInstructions(seqp, body, elementType, array[i], compiler, targetPackage)[0];

                    body.Instructions.Add(seqp, RCode.Const, i, rIndex);
                    body.Instructions.Add(seqp, valueType.APut(), rLoaded, result[0], rIndex);
                }
            }
            else if (targetType.IsEnum())
            {
                var enumClass = (targetType.IsEnum()? targetType:valueType).GetReference(targetPackage) ;

                Register rEnumClass = body.AllocateRegister(RCategory.Temp, RType.Object);
                body.Instructions.Add(seqp, RCode.Const_class, enumClass, rEnumClass);

                long lVal = Convert.ToInt64(value.Value);
                if (lVal <= int.MaxValue && lVal >= int.MinValue)
                {
                    Register regTmp = body.AllocateRegister(RCategory.Temp, RType.Value);    
                    body.Instructions.Add(seqp, RCode.Const, (int)lVal, regTmp);
                    var get = compiler.GetDot42InternalType("Enum").Resolve()
                                      .Methods.Single(p => p.Name == "Get" && p.Parameters.Count == 2 && !p.Parameters[1].ParameterType.IsWide())
                                      .GetReference(targetPackage);
                    body.Instructions.Add(seqp, RCode.Invoke_static, get, rEnumClass, regTmp);
                    body.Instructions.Add(seqp, targetType.MoveResult(), result[0]);
                }
                else
                {
                    var regTmp = body.AllocateWideRegister(RCategory.Temp);
                    body.Instructions.Add(seqp, RCode.Const, (long)lVal, regTmp.Item1);
                    var get = compiler.GetDot42InternalType("Enum").Resolve()
                                      .Methods.Single(p => p.Name == "Get" && p.Parameters.Count == 2 && p.Parameters[1].ParameterType.IsWide())
                                      .GetReference(targetPackage);
                    body.Instructions.Add(seqp, RCode.Invoke_static, get, rEnumClass, regTmp.Item1);
                    body.Instructions.Add(seqp, targetType.MoveResult(), result[0]);
                }
                body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
            }
            else if (valueType.IsSystemString())
            {
                body.Instructions.Add(seqp, RCode.Const_string, (string)value.Value, result[0]);
            }
            else if (valueType.IsSystemType())
            {
                var type = XBuilder.AsTypeReference(compiler.Module, (TypeReference)value.Value);
                // TODO: this might not work with typeof(void) on ART runtime.
                body.Instructions.Add(seqp, RCode.Const_class, type.GetReference(targetPackage), result[0]);
            }
            else if (!valueType.IsPrimitive)
            {
                // can this happen?
                throw new Exception("invalid value type in attribute: " + targetType.FullName);
            }
            else
            {
                if (targetType.IsSystemObject())
                {
                    // can this happen? or is this always handled above?

                    // boxing required.
                    var rUnboxed = CreateInitializeValueInstructions(seqp, body, valueType, value, compiler, targetPackage);
                    body.Instructions.Add(seqp, RCode.Invoke_static, valueType.GetBoxValueOfMethod(), rUnboxed);
                    body.Instructions.Add(seqp, RCode.Move_result_object, result[0]);
                }
                else if(targetType.IsDouble())
                {
                    body.Instructions.Add(seqp, RCode.Const_wide, Convert.ToDouble(value.Value), result[0]);
                }
                else if (targetType.IsWide() && valueType.IsUInt64())
                {
                    body.Instructions.Add(seqp, RCode.Const_wide, (long)Convert.ToUInt64(value.Value), result[0]);
                }
                else if (targetType.IsWide())
                {
                    body.Instructions.Add(seqp, RCode.Const_wide, Convert.ToInt64(value.Value), result[0]);
                }
                else if (targetType.IsFloat())
                {
                    body.Instructions.Add(seqp, RCode.Const, Convert.ToSingle(value.Value), result[0]);
                }
                else 
                {
                    body.Instructions.Add(seqp, RCode.Const, (int)Convert.ToInt64(value.Value), result[0]);
                }
            }

            return result.ToArray();
        }
Esempio n. 55
0
        /// <summary>
        /// Create an annotation for the given attribute
        /// </summary>
        private static void Create(AssemblyCompiler compiler, CustomAttribute attribute, TypeDefinition attributeType,
                                   List<Annotation> annotationList, DexTargetPackage targetPackage)
        {
            // Gets the mapping for the type of attribute
            var mapping = compiler.GetAttributeAnnotationType(attributeType);
            var ctorMap = mapping.CtorMap[attribute.Constructor.Resolve()];

            // Create annotation
            var annotation = new Annotation {Visibility = AnnotationVisibility.Runtime};
            annotation.Type = mapping.AnnotationInterfaceClass;

            // Add ctor arguments
            var argIndex = 0;
            foreach (var arg in attribute.ConstructorArguments)
            {
                var name = ctorMap.ArgumentGetters[argIndex].Name;
                annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Type, arg.Value, targetPackage, compiler.Module));
                argIndex++;
            }

            // Add field values
            foreach (var arg in attribute.Fields)
            {
                var entry = mapping.FieldToGetMethodMap.First(x => x.Key.Name == arg.Name);
                var name = entry.Value.Name;
                annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Argument.Type, arg.Argument.Value, targetPackage, compiler.Module));
            }

            // Add property values
            foreach (var arg in attribute.Properties)
            {
                if (mapping.PropertyToGetMethodMap.Keys.Any(x => x.Name == arg.Name))
                {
                    var entry = mapping.PropertyToGetMethodMap.First(x => x.Key.Name == arg.Name);
                    var name = entry.Value.Name;
                    annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Argument.Type, arg.Argument.Value, targetPackage, compiler.Module));
                }
            }

            // Create attribute annotation
            var attrAnnotation = new Annotation { Visibility = AnnotationVisibility.Runtime };
            attrAnnotation.Type = compiler.GetDot42InternalType("IAttribute").GetClassReference(targetPackage);
            attrAnnotation.Arguments.Add(new AnnotationArgument("AttributeBuilder", ctorMap.Builder));
            attrAnnotation.Arguments.Add(new AnnotationArgument("AttributeType", attributeType.GetReference(targetPackage, compiler.Module)));
            attrAnnotation.Arguments.Add(new AnnotationArgument("Annotation", annotation));

            // Add annotation
            annotationList.Add(attrAnnotation);
        }
        /// <summary>
        /// Create an annotation for the given attribute
        /// </summary>
        private static void CreateAttributeAnnotation(AssemblyCompiler compiler, CustomAttribute attribute, TypeDefinition attributeType,
                                   List<Annotation> annotationList, DexTargetPackage targetPackage)
        {
            // Gets the mapping for the type of attribute
            var mapping = compiler.GetAttributeAnnotationMapping(attributeType);

            MethodDefinition factoryMethod;

            // Note: not multithreading capable. see my comments elsewhere.
            if(mapping.FactoryMethodMap.ContainsKey(attribute))
                factoryMethod = mapping.FactoryMethodMap[attribute];
            else
            {
                // create the factory method.
                factoryMethod = CreateFactoryMethod(compiler, targetPackage, attribute, mapping);
                mapping.FactoryMethodMap[attribute] = factoryMethod;
            }

            // Create attribute annotation
            var attrAnnotation = new Annotation { Visibility = AnnotationVisibility.Runtime };
            attrAnnotation.Type = compiler.GetDot42InternalType("IAttribute").GetClassReference(targetPackage);
            attrAnnotation.Arguments.Add(new AnnotationArgument("AttributeType", attributeType.GetReference(targetPackage, compiler.Module)));
            attrAnnotation.Arguments.Add(new AnnotationArgument("FactoryMethod", factoryMethod.Name));

            // Add annotation
            annotationList.Add(attrAnnotation);
        }
Esempio n. 57
0
 /// <summary>
 /// Create code to box the given source array of primitive type elements into an array of boxed elements.
 /// </summary>
 public static RLRange BoxGenericArray(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec source,
                                        XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler)
 {
     var objectArrayType = new DexLib.ArrayType(new ClassReference("java.lang.Object"));
     var boxedArray = frame.AllocateTemp(objectArrayType);
     var internalBoxingType = compiler.GetDot42InternalType("Boxing").Resolve();
     var ilBoxMethod = internalBoxingType.Methods.First(x => x.EqualsName("Box") && (x.Parameters.Count == 1) && (x.Parameters[0].ParameterType.IsSame(type, true)));
     var boxMethod = ilBoxMethod.GetReference(targetPackage);
     var call = builder.Add(sequencePoint, RCode.Invoke_static, boxMethod, source);
     var saveArray = builder.Add(sequencePoint, RCode.Move_result_object, boxedArray);
     return new RLRange(call, saveArray, boxedArray);
 }
Esempio n. 58
0
        /// <summary>
        /// Convert node with code Callvirt. 
        /// 
        /// For arrays: intercepts call to IEnumerable.IEnumerable_GetEnumerator generated 
        /// by foreach statements and swaps them out to System.Array.GetEnumerator.
        /// 
        /// This call will then at a later compilation stage be replaced with the final destination.
        /// </summary>
        private static void ConvertCallvirtIEnumerable(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var targetMethodRef = ((XMethodReference)node.Operand);
            var targetMethodDefOrRef = targetMethodRef;
            
            if (!targetMethodDefOrRef.DeclaringType.IsSystemCollectionsIEnumerable())
                return;
            if (targetMethodDefOrRef.Name != "IEnumerable_GetEnumerator")
                return;

            if (node.Arguments.Count != 1) return;

            var argument = node.Arguments[0];
            
            if (!argument.InferredType.IsArray)
                return;
            
            // swap the call to System.Array
            var systemArray = compiler.GetDot42InternalType("System", "Array").Resolve();
            var getEnumerator = systemArray.Methods.First(x => x.Name == "GetEnumerator" && !x.IsStatic && x.Parameters.Count == 0);
            node.Operand = getEnumerator;
        }
Esempio n. 59
0
 /// <summary>
 /// Create code to unbox the given source array of boxed type elements resulting from a call into an array of primitive elements.
 /// </summary>
 public static RLRange UnboxGenericArrayResult(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec boxedArray,
                                        XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler)
 {
     var internalBoxingType = compiler.GetDot42InternalType("Boxing").Resolve();
     var primitiveArray = frame.AllocateTemp(type.GetReference(targetPackage));
     var ilUnboxMethod = internalBoxingType.Methods.First(x => x.Name.StartsWith("Unbox") && (x.Parameters.Count == 1) && (x.ReturnType.IsSame(type, true)));
     var unboxMethod = ilUnboxMethod.GetReference(targetPackage);
     var call = builder.Add(sequencePoint, RCode.Invoke_static, unboxMethod, boxedArray);
     var saveArray = builder.Add(sequencePoint, RCode.Move_result_object, primitiveArray);
     return new RLRange(call, saveArray, primitiveArray);
 }
Esempio n. 60
0
 /// <summary>
 /// Gets a unbox method for the given primitive type.
 /// </summary>
 internal static MethodReference GetUnboxValueMethod(XTypeReference type, AssemblyCompiler compiler, DexTargetPackage targetPackage, out RCode convertAfterCode)
 {
     var info = Get(type);
     convertAfterCode = info.convertAfterCode;
     var boxingClass = compiler.GetDot42InternalType("Boxing").GetClassReference(targetPackage);
     return new MethodReference(boxingClass, info.unboxMethodName, new Prototype(info.primitiveType, new Parameter(FrameworkReferences.Object, "value")));
 }