Ejemplo n.º 1
0
        bool ForwardScanInitializeArrayRuntimeHelper(List <AstNode> body, int pos, AstVariable array, XTypeReference arrayType, int arrayLength, out Array values, out int foundPos)
        {
            AstVariable      v2;
            XMethodReference methodRef;
            AstExpression    methodArg1;
            AstExpression    methodArg2;
            XFieldReference  fieldRef;

            if (body.ElementAtOrDefault(pos).Match(AstCode.Call, out methodRef, out methodArg1, out methodArg2) &&
                methodRef.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers" &&
                methodRef.Name == "InitializeArray" &&
                methodArg1.Match(AstCode.Ldloc, out v2) &&
                array == v2 &&
                methodArg2.Match(AstCode.Ldtoken, out fieldRef))
            {
                var fieldDef = fieldRef.Resolve();                 //.ResolveWithinSameModule();
                if (fieldDef != null && fieldDef.InitialValue != null)
                {
                    Array newArr;
                    if (DecodeArrayInitializer(arrayType.GetElementType(), (byte[])fieldDef.InitialValue, arrayLength, out newArr))
                    {
                        values   = newArr;
                        foundPos = pos;
                        return(true);
                    }
                }
            }
            values   = null;
            foundPos = -1;
            return(false);
        }
        /// <summary>
        /// Create an expression that loads the given type at runtime.
        /// </summary>
        private static AstExpression LoadTypeForGenericInstance(ISourceLocation seqp, MethodSource currentMethod,
                                                                XTypeReference type, AssemblyCompiler compiler, XTypeDefinition typeHelperType, XTypeSystem typeSystem,
                                                                TypeConversion typeConversion, XGenericInstanceType typeGenericArguments = null)
        {
            if (type.IsArray)
            {
                // Array type
                var arrayType = (XArrayType)type;
                // Load element type
                var prefix = LoadTypeForGenericInstance(seqp, currentMethod, ((XArrayType)type).ElementType, compiler, typeHelperType, typeSystem, typeConversion);
                // Convert to array type
                if (arrayType.Dimensions.Count() == 1)
                {
                    var giCreateArray = typeHelperType.Methods.Single(x => (x.Name == "Array") && (x.Parameters.Count == 1));
                    return(new AstExpression(seqp, AstCode.Call, giCreateArray, prefix)
                    {
                        ExpectedType = typeSystem.Type
                    });
                }
                else
                {
                    var giCreateArray  = typeHelperType.Methods.Single(x => (x.Name == "Array") && (x.Parameters.Count == 2));
                    var dimensionsExpr = new AstExpression(seqp, AstCode.Ldc_I4, arrayType.Dimensions.Count())
                    {
                        ExpectedType = typeSystem.Int
                    };
                    return(new AstExpression(seqp, AstCode.Call, giCreateArray, prefix, dimensionsExpr)
                    {
                        ExpectedType = typeSystem.Type
                    });
                }
            }

            var gp = type as XGenericParameter;

            if (gp != null)
            {
                AstExpression loadExpr;
                if (gp.Owner is XTypeReference)
                {
                    // Class type parameter
                    var owner = (XTypeReference)gp.Owner;
                    if (owner.GetElementType().Resolve().HasDexImportAttribute())
                    {
                        // Imported type
                        return(new AstExpression(seqp, AstCode.TypeOf, typeSystem.Object)
                        {
                            ExpectedType = typeSystem.Type
                        });
                    }
                    if (currentMethod.IsClassCtor)
                    {
                        // Class ctor's cannot have type information.
                        // Return Object instead
                        if (currentMethod.IsDotNet && !currentMethod.ILMethod.DeclaringType.HasSuppressMessageAttribute("StaticConstructorUsesGenericParameter"))
                        {
                            var msg = "Class (static) constructor of '{0}' tries to use generic parameter. This will always yield Object. " +
                                      "You can suppress this warning with a [SuppressMessage(\"dot42\", \"StaticConstructorUsesGenericParameter\")] " +
                                      "attribute on the class.";

                            if (seqp != null && seqp.Document != null)
                            {
                                DLog.Warning(DContext.CompilerCodeGenerator, seqp.Document, seqp.StartColumn, seqp.StartLine, msg, currentMethod.DeclaringTypeFullName);
                            }
                            else
                            {
                                DLog.Warning(DContext.CompilerCodeGenerator, msg, currentMethod.DeclaringTypeFullName);
                            }
                        }
                        return(new AstExpression(seqp, AstCode.TypeOf, typeSystem.Object)
                        {
                            ExpectedType = typeSystem.Type
                        });
                    }
                    loadExpr = currentMethod.IsStatic ?
                               LoadStaticClassGenericArgument(seqp, typeSystem, currentMethod.Method, gp.Position) :
                               LoadInstanceClassGenericArgument(seqp, typeSystem, currentMethod.Method.DeclaringType, gp.Position);
                }
                else
                {
                    // Method type parameter
                    var owner = (XMethodReference)gp.Owner;
                    if (owner.GetElementMethod().Resolve().DeclaringType.HasDexImportAttribute())
                    {
                        // Imported type
                        return(LoadTypeForGenericInstance(seqp, currentMethod, type.Module.TypeSystem.Object, compiler, typeHelperType, typeSystem, typeConversion));
                    }
                    loadExpr = LoadMethodGenericArgument(seqp, typeSystem, currentMethod.Method, gp.Position);
                }

                if (typeConversion == TypeConversion.EnsureRuntimeType)
                {
                    return(EnsureGenericRuntimeType(loadExpr, typeSystem, typeHelperType));
                }
                else
                {
                    return(loadExpr);
                }
            }

            if (type is XTypeSpecification)
            {
                var typeSpec = (XTypeSpecification)type;
                var git      = type as XGenericInstanceType;
                var baseType = LoadTypeForGenericInstance(seqp, currentMethod, typeSpec.ElementType, compiler, typeHelperType, typeSystem, typeConversion, git);

                if (typeConversion != TypeConversion.EnsureTrueOrMarkerType || typeSpec.GetElementType().IsNullableT())
                {
                    return(baseType);
                }

                // Use the element type and make a generic proxy with the generic arguments.
                var parameters = CreateGenericInstanceCallArguments(seqp, git, currentMethod, compiler);
                if (parameters.Count == 1 && parameters[0].GetResultType().IsArray)
                {
                    // array type call.
                    var method = typeHelperType.Methods.Single(m => m.Name == "GetGenericInstanceType" && m.Parameters.Count == 2 && m.Parameters[1].ParameterType.IsArray);
                    return(new AstExpression(seqp, AstCode.Call, method, baseType, parameters[0]));
                }
                else
                {
                    parameters.Insert(0, baseType);
                    var method = typeHelperType.Methods.Single(m => m.Name == "GetGenericInstanceType" && m.Parameters.Count == parameters.Count && !m.Parameters[1].ParameterType.IsArray);
                    return(new AstExpression(seqp, AstCode.Call, method, parameters.ToArray()));
                }
            }


            if (typeConversion == TypeConversion.EnsureTrueOrMarkerType && type.GetElementType().IsNullableT())
            {
                if (typeGenericArguments != null)
                {
                    var underlying = typeGenericArguments.GenericArguments[0];
                    var code       = underlying.IsPrimitive ? AstCode.BoxedTypeOf : AstCode.NullableTypeOf;
                    return(new AstExpression(seqp, code, underlying)
                    {
                        ExpectedType = typeSystem.Type
                    });
                }
                // if typeGenericArguments is null, this is a generic definition, e.g. typeof(Nullable<>).
            }

            // Plain type reference or definition
            return(new AstExpression(seqp, AstCode.TypeOf, type)
            {
                ExpectedType = typeSystem.Type
            });
        }
Ejemplo n.º 3
0
        public static void WriteTo(this XTypeReference type, ITextOutput writer, AstNameSyntax syntax = AstNameSyntax.Signature)
        {
            var syntaxForElementTypes = syntax == AstNameSyntax.ShortTypeName ? AstNameSyntax.ShortTypeName
                                      : syntax == AstNameSyntax.SignatureNoNamedTypeParameters ? syntax
                                      : AstNameSyntax.Signature;

            if (type is XArrayType)
            {
                var at = (XArrayType)type;
                at.ElementType.WriteTo(writer, syntaxForElementTypes);
                writer.Write('[');
                writer.Write(string.Join(", ", at.Dimensions));
                writer.Write(']');
            }
            else if (type is XGenericParameter)
            {
                writer.Write('!');
                if (((XGenericParameter)type).Owner is XMethodReference)
                {
                    writer.Write('!');
                }
                if (string.IsNullOrEmpty(type.Name) || type.Name[0] == '!' || syntax == AstNameSyntax.SignatureNoNamedTypeParameters)
                {
                    writer.Write(((XGenericParameter)type).Position.ToString());
                }
                else
                {
                    writer.Write(Escape(type.Name));
                }
            }
            else if (type is XByReferenceType)
            {
                ((XByReferenceType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
                writer.Write('&');
            }
            else if (type is XGenericInstanceType)
            {
                type.GetElementType().WriteTo(writer, syntaxForElementTypes);
                writer.Write('<');
                var arguments = ((XGenericInstanceType)type).GenericArguments;
                for (int i = 0; i < arguments.Count; i++)
                {
                    if (i > 0)
                    {
                        writer.Write(", ");
                    }
                    arguments[i].WriteTo(writer, syntaxForElementTypes);
                }
                writer.Write('>');
            }
            else
            {
                string name = PrimitiveTypeName(type.FullName);
                if (syntax == AstNameSyntax.ShortTypeName)
                {
                    if (name != null)
                    {
                        writer.Write(name);
                    }
                    else
                    {
                        writer.WriteReference(Escape(type.Name), type);
                    }
                }
                else if ((syntax == AstNameSyntax.Signature || syntax == AstNameSyntax.SignatureNoNamedTypeParameters) && name != null)
                {
                    writer.Write(name);
                }
                else
                {
                    if (syntax == AstNameSyntax.Signature || syntax == AstNameSyntax.SignatureNoNamedTypeParameters)
                    {
                        writer.Write(type.IsValueType ? "valuetype " : "class ");
                    }

                    var typeAsMember = type as IXMemberReference;
                    if ((typeAsMember != null) && (typeAsMember.DeclaringType != null))
                    {
                        typeAsMember.DeclaringType.WriteTo(writer, AstNameSyntax.TypeName);
                        writer.Write('/');
                        writer.WriteReference(Escape(type.Name), type);
                    }
                    else
                    {
                        writer.WriteReference(Escape(type.FullName), type);
                    }
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// The syntax is experimental, and neither fully fixed nor officially defined.
        /// </summary>
        private static string GetDefinition(XTypeReference xtype, bool forceTypeDefinition, AssemblyCompiler compiler,
                                            DexTargetPackage targetPackage)
        {
            StringBuilder s = new StringBuilder();

            // TODO: reorganize, so that the syntax becomes clear.

            bool setGenericInstanceType = false;

            if (xtype.IsGenericInstance)
            {
                bool handled = false;

                if (xtype.GetElementType().IsNullableT())
                {
                    // privitives and enums are represented by their marker classes.
                    // no annotation needed.
                    var argument = ((XGenericInstanceType)xtype).GenericArguments[0];
                    if (!forceTypeDefinition && (argument.IsEnum() || argument.IsPrimitive))
                    {
                        return("");
                    }

                    // 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)
                    {
                        s.Append("@");
                        s.Append(GetClassName(@class.NullableMarkerClass));
                        setGenericInstanceType = true;
                        handled = true;
                    }
                }

                if (!handled)
                {
                    bool isFirst = true;
                    foreach (var arg in ((XGenericInstanceType)xtype).GenericArguments)
                    {
                        if (!isFirst)
                        {
                            s.Append(",");
                        }
                        isFirst = false;

                        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.
                            s.Append("!");
                            s.Append(gparm.Position);
                        }
                        else if (arg.IsGenericInstance)
                        {
                            var giparm = GetDefinition((XGenericInstanceType)arg, true, compiler, targetPackage);
                            s.Append("{");
                            s.Append(giparm);
                            s.Append("}");
                        }
                        else
                        {
                            s.Append(GetClassName(arg.GetReference(targetPackage)));
                        }
                    }
                }
            }
            else // generic parameter
            {
                var parm = (XGenericParameter)xtype;
                s.Append("!!");
                s.Append(parm.Position);
            }

            if (forceTypeDefinition && !setGenericInstanceType)
            {
                string def = GetClassName(xtype.ElementType.GetReference(targetPackage));
                s.Insert(0, def + "<");
                s.Append(">");
            }

            return(s.ToString());
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Gets a class reference for the given type reference.
        /// </summary>
        internal static TypeReference GetReference(this XTypeReference type, DexTargetPackage targetPackage)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            type = type.GetWithoutModifiers();

            // Handle array's
            if (type.IsArray)
            {
                var arrType    = (XArrayType)type;
                var dimensions = arrType.Dimensions.Count() - 1;
                var dArrayType = new ArrayType(GetReference(type.ElementType, targetPackage));
                while (dimensions > 0)
                {
                    dArrayType = new ArrayType(dArrayType);
                    dimensions--;
                }
                return(dArrayType);
            }

            // Handle generic parameters
            if (type.IsGenericParameter || (type.IsByReference && type.ElementType.IsGenericParameter))
            {
                if (type.IsByReference) // this should be possible as well, but would need some more code at some other places.
                {
                    return(new ByReferenceType(FrameworkReferences.Object));
                }

                var gp = (XGenericParameter)type;
                if (gp.AllowConstraintAsTypeReference())
                {
                    return(gp.Constraints[0].GetReference(targetPackage));
                }

                return(FrameworkReferences.Object);
            }

            // Handle out/ref types
            if (type.IsByReference)
            {
                var byRefType = (XByReferenceType)type;
                return(new ByReferenceType(GetReference(byRefType.ElementType, targetPackage)));
            }

            // Handle Nullable<T>
            if (type.IsGenericInstance)
            {
                var git = (XGenericInstanceType)type;
                if (git.ElementType.IsNullableT())
                {
                    var arg = git.GenericArguments[0];
                    if (arg.IsBoolean())
                    {
                        return(new ClassReference("java/lang/Boolean"));
                    }
                    if (arg.IsByte() || arg.IsSByte())
                    {
                        return(new ClassReference("java/lang/Byte"));
                    }
                    if (arg.IsChar())
                    {
                        return(new ClassReference("java/lang/Character"));
                    }
                    if (arg.IsInt16() || arg.IsUInt16())
                    {
                        return(new ClassReference("java/lang/Short"));
                    }
                    if (arg.IsInt32() || arg.IsUInt32())
                    {
                        return(new ClassReference("java/lang/Integer"));
                    }
                    if (arg.IsInt64() || arg.IsUInt64())
                    {
                        return(new ClassReference("java/lang/Long"));
                    }
                    if (arg.IsDouble())
                    {
                        return(new ClassReference("java/lang/Double"));
                    }
                    if (arg.IsFloat())
                    {
                        return(new ClassReference("java/lang/Float"));
                    }


                    var typeofT = git.GenericArguments[0];

                    if (typeofT.IsGenericParameter) // use object.
                    {
                        return(FrameworkReferences.Object);
                    }

                    XTypeDefinition typeofTDef;
                    if (!typeofT.TryResolve(out typeofTDef))
                    {
                        throw new XResolutionException(typeofT);
                    }

                    var className = targetPackage.NameConverter.GetConvertedFullName(typeofTDef);
                    var classDef  = targetPackage.DexFile.GetClass(className);

                    // Use nullable base class of T, if enum.
                    if (classDef.IsEnum)
                    {
                        return(classDef.SuperClass);
                    }

                    // I like the base class concept for enums. unfortunately it seems to be
                    // impossible for structs and/or might have performance implications.
                    // Just return the type for structs.
                    return(classDef);
                }
            }

            var primType = GetPrimitiveType(type);

            if (primType != null)
            {
                return(primType);
            }

            // Resolve the type to a type definition
            XTypeDefinition typeDef;

            if (type.GetElementType().TryResolve(out typeDef))
            {
                // Handle primitive types
                primType = GetPrimitiveType(typeDef);
                if (primType != null)
                {
                    return(primType);
                }

                string className;
                if (typeDef.TryGetDexImportNames(out className))
                {
                    // type is a framework type
                    return(new ClassReference(className));
                }

                // Handle enums

                /* Enums Are Normal classes now
                 * if (typeDef.IsEnum)
                 * {
                 *  // Convert to primitive type
                 *  //return typeDef.GetEnumUnderlyingType().GetReference(target, nsConverter);
                 * }*/

                // Handle nested types of java types
                string convertedFullName;
                if (typeDef.IsNested && typeDef.DeclaringType.HasDexImportAttribute())
                {
                    // Nested type that is not imported, but it's declaring type is imported.
                    convertedFullName = targetPackage.NameConverter.GetConvertedFullName(typeDef.DeclaringType) + "_" +
                                        NameConverter.GetConvertedName(typeDef);
                }
                else if (typeDef.TryGetJavaImportNames(out className))
                {
                    convertedFullName = className.Replace('/', '.');
                }
                else
                {
                    convertedFullName = targetPackage.NameConverter.GetConvertedFullName(typeDef);
                }

                // type is in the assembly itself
                var result = targetPackage.DexFile.GetClass(convertedFullName);
                if (result == null)
                {
                    throw new ArgumentException(string.Format("Cannot find type {0}", convertedFullName));
                }
                return(result);
            }

            var javaType = type as XModel.Java.XBuilder.JavaTypeReference;

            if (javaType != null)
            {
                return(new ClassReference(javaType.JavaClassName));
            }

            throw new ResolveException(string.Format("Type {0} not found", type.FullName));
        }