Example #1
0
        /// <summary>
        /// Convert a nullable ctor into a convert function.
        /// </summary>
        private static void ConvertPrimitiveCtor(AstExpression node, XMethodReference ctor, XTypeReference type, AstExpression target, AstExpression value)
        {
            // Clear node
            node.Arguments.Clear();
            node.InferredType = ctor.DeclaringType;
            node.ExpectedType = ctor.DeclaringType;

            switch (target.Code)
            {
            case AstCode.Ldloca:
                node.Code    = AstCode.Stloc;
                node.Operand = target.Operand;
                node.Arguments.Add(new AstExpression(node.SourceLocation, AstCode.Box, type, value));
                break;

            case AstCode.Ldflda:
                node.Code    = AstCode.Stfld;
                node.Operand = target.Operand;
                node.Arguments.Add(new AstExpression(node.SourceLocation, AstCode.Box, type, value));
                break;

            case AstCode.Ldsflda:
                node.Code    = AstCode.Stsfld;
                node.Operand = target.Operand;
                node.Arguments.Add(new AstExpression(node.SourceLocation, AstCode.Box, type, value));
                break;
            }
        }
Example #2
0
 /// <summary>
 /// Create the body of the Create(int|long) method.
 /// </summary>
 private AstBlock CreateCreateBody(XSyntheticMethodDefinition method, XMethodReference ctor)
 {
     return(AstBlock.CreateOptimizedForTarget(
                new AstExpression(AstNode.NoSource, AstCode.Ret, null,
                                  new AstExpression(AstNode.NoSource, AstCode.Newobj, ctor,
                                                    new AstExpression(AstNode.NoSource, AstCode.Ldstr, "?"),
                                                    new AstExpression(AstNode.NoSource, AstCode.Ldc_I4, -1),
                                                    new AstExpression(AstNode.NoSource, AstCode.Ldloc, method.AstParameters[0])))));
 }
Example #3
0
        /// <summary>
        /// Convert a nullable(PrimitiveT) ctor into a convert function.
        /// </summary>
        private static void ConvertPrimitiveNewObj(AstExpression node, XMethodReference ctor, XTypeReference type, AstExpression value)
        {
            // Clear node
            node.Arguments.Clear();
            node.InferredType = ctor.DeclaringType;
            node.ExpectedType = ctor.DeclaringType;

            node.Code    = AstCode.Box;
            node.Operand = type;
            node.Arguments.Add(value);
        }
Example #4
0
 /// <summary>
 /// Generate an Invoke opcode.
 /// </summary>
 internal static RCode Invoke(this XMethodDefinition targetMethod, XMethodReference targetMethodRef, MethodSource currentMethod, bool isSpecial = false)
 {
     if (targetMethod != null)
     {
         if (targetMethod.DeclaringType.IsDelegate())
         {
             return(RCode.Invoke_interface);
         }
         if (targetMethod.IsStatic || targetMethod.IsAndroidExtension)
         {
             return(RCode.Invoke_static);
         }
         if ((currentMethod != null) && targetMethod.UseInvokeSuper(currentMethod.Method))
         {
             return(RCode.Invoke_super);
         }
         if (isSpecial && !targetMethod.IsConstructor && (currentMethod != null) && targetMethod.DeclaringType.IsBaseOf(currentMethod.Method.DeclaringType))
         {
             return(RCode.Invoke_super);
         }
         if (targetMethod.UseInvokeInterface)
         {
             return(RCode.Invoke_interface);
         }
         if (targetMethod.IsDirect)
         {
             return(RCode.Invoke_direct);
         }
         if (targetMethod.DeclaringType.IsInterface)
         {
             return(RCode.Invoke_interface);
         }
     }
     if (targetMethodRef != null)
     {
         if (!targetMethodRef.HasThis)
         {
             return(RCode.Invoke_static);
         }
         switch (targetMethodRef.Name)
         {
         case "<init>":
         case "<clinit>":
         case ".ctor":
         case ".cctor":
             return(RCode.Invoke_direct);
         }
     }
     return(RCode.Invoke_virtual);
 }
Example #5
0
        /// <summary>
        /// Convert a nullable .GetValueOrDefault()
        /// </summary>
        private static void ConvertPrimitiveGetValueOrDefault(AstExpression node, XMethodReference ilMethod, XTypeReference type, AstExpression target, XModule data)
        {
            // Clear node
            var originalArgs = node.Arguments.ToList();
            var getValueRef  = new XMethodReference.Simple("GetValue", false, ilMethod.ReturnType, ilMethod.DeclaringType, new[] { data.TypeSystem.Object, data.TypeSystem.Bool }, null);

            node.Operand = getValueRef;
            node.Arguments.Clear();
            node.InferredType = type;
            node.ExpectedType = type;

            AddLoadArgument(node, target, originalArgs[0]);
            node.Arguments.Add(new AstExpression(node.SourceLocation, AstCode.Ldc_I4, 1)
            {
                InferredType = data.TypeSystem.Bool
            });
        }
Example #6
0
        /// <summary>
        /// Gets the converted name of the given field.
        /// </summary>
        public static string GetConvertedName(XMethodReference method)
        {
            var name = method.Name;

            // Handle special names
            switch (name)
            {
            case ".ctor":
                return("<init>");

            case ".cctor":
                return("<clinit>");
            }

            // Handle properties in custom views.
            var methodDef = method.Resolve();

            if (methodDef.DeclaringType.HasCustomViewAttribute())
            {
                if (methodDef.IsSetter && name.StartsWith("set_"))
                {
                    name = "set" + name.Substring(4);
                }
                else if (methodDef.IsGetter && name.StartsWith("get_"))
                {
                    name = "get" + name.Substring(4);
                }
            }

            // Avoid special characters
            var originalName = name;

            name = name.Replace('<', '_');
            name = name.Replace('>', '_');
            name = name.Replace('.', '_');

            if (name != originalName)
            {
                // Add hash to ensure unique
                name = name + '_' + GetHashPostfix(originalName);
            }

            return(name);
        }
Example #7
0
        /// <summary>
        /// Gets a Dex method reference for the given type reference.
        /// </summary>
        internal static MethodReference GetReference(this XMethodReference method, DexTargetPackage targetPackage)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

//#if DEBUG
//            if (method.DeclaringType.IsArray)
//            {
//                Debugger.Launch();
//            }
//#endif

            // Resolve the type to a method definition
            XMethodDefinition methodDef;

            if (method.TryResolve(out methodDef))
            {
                string className;
                string memberName;
                string descriptor;
                if (methodDef.TryGetDexImportNames(out memberName, out descriptor, out className))
                {
                    var prototype = PrototypeBuilder.ParseMethodSignature(descriptor);
                    return(new MethodReference(GetDeclaringTypeReference(className), memberName, prototype));
                }

                // Method is in the assembly itself
                // Use the mapping
                return(targetPackage.NameConverter.GetMethod(methodDef));
            }

            var javaMethod = method as XModel.Java.XBuilder.JavaMethodReference;

            if (javaMethod != null)
            {
                var prototype = PrototypeBuilder.ParseMethodSignature(javaMethod.JavaDecriptor);
                return(new MethodReference(GetDeclaringTypeReference(javaMethod.JavaClassName), javaMethod.JavaName, prototype));
            }

            // Return reference to a method we do not know yet
            throw new ResolveException(string.Format("Method {0} not found", method.FullName));
        }
Example #8
0
        public static void WriteTo(this XMethodReference method, ITextOutput writer)
        {
            if (method.HasThis)
            {
                writer.Write("instance ");
            }
            method.ReturnType.WriteTo(writer, AstNameSyntax.SignatureNoNamedTypeParameters);
            writer.Write(' ');
            if (method.DeclaringType != null)
            {
                method.DeclaringType.WriteTo(writer, AstNameSyntax.TypeName);
                writer.Write("::");
            }
            writer.WriteReference(Escape(method.Name), method);
            var gim = method as XGenericInstanceMethod;

            if (gim != null)
            {
                writer.Write('<');
                for (int i = 0; i < gim.GenericArguments.Count; i++)
                {
                    if (i > 0)
                    {
                        writer.Write(", ");
                    }
                    gim.GenericArguments[i].WriteTo(writer);
                }
                writer.Write('>');
            }
            writer.Write("(");
            var parameters = method.Parameters;

            for (int i = 0; i < parameters.Count; ++i)
            {
                if (i > 0)
                {
                    writer.Write(", ");
                }
                parameters[i].ParameterType.WriteTo(writer, AstNameSyntax.SignatureNoNamedTypeParameters);
            }
            writer.Write(")");
        }
Example #9
0
        /// <summary>
        /// The given call is a call to a ctor.
        /// Convert it to newobj
        /// </summary>
        private static void ConvertCtorCall(AstExpression callNode, XMethodReference ctor)
        {
            // Create a new node to construct the object
            var newObjNode = new AstExpression(callNode.SourceLocation, AstCode.Newobj, null, callNode.Arguments.Skip(1).ToList());

            newObjNode.Operand      = ctor;
            newObjNode.InferredType = ctor.DeclaringType;

            // Remove "this" argument
            var thisExpr = callNode.Arguments[0];

            callNode.Arguments.Clear();
            callNode.Arguments.Add(newObjNode);
            callNode.InferredType = ctor.DeclaringType;

            // Convert callNode to stX node
            switch (thisExpr.Code)
            {
            case AstCode.Ldloca:
            case AstCode.Ldloc:
                callNode.Code    = AstCode.Stloc;
                callNode.Operand = thisExpr.Operand;
                break;

            case AstCode.Ldflda:
            case AstCode.Ldfld:
                callNode.Code    = AstCode.Stfld;
                callNode.Operand = thisExpr.Operand;
                break;

            case AstCode.Ldsflda:
            case AstCode.Ldsfld:
                callNode.Code    = AstCode.Stsfld;
                callNode.Operand = thisExpr.Operand;
                break;

            default:
                throw new NotSupportedException(string.Format("Unsupported opcode {0} in call to struct ctor", (int)thisExpr.Code));
            }
        }
Example #10
0
 /// <summary>
 /// Is this reference equal to the given other reference?
 /// </summary>
 public override bool IsSameExceptDeclaringType(XMethodReference other)
 {
     if (base.IsSameExceptDeclaringType(other))
     {
         return(true);
     }
     EnsureDexImportName();
     // Check against dex import
     if ((dexImportName == other.Name) && (other.Parameters.Count == Parameters.Count) && (other.HasThis == HasThis))
     {
         var descriptor      = CreateNoGenericsDescriptor(this);
         var otherDescriptor = CreateNoGenericsDescriptor(other);
         return(descriptor == otherDescriptor);
     }
     EnsureJavaImportName();
     // Check against java import
     if ((javaImportName == other.Name) && (other.Parameters.Count == Parameters.Count) && (other.HasThis == HasThis))
     {
         var descriptor      = CreateNoGenericsDescriptor(this);
         var otherDescriptor = CreateNoGenericsDescriptor(other);
         return(descriptor == otherDescriptor);
     }
     return(false);
 }
Example #11
0
 /// <summary>
 /// Create a descriptor for comparing the given method without generics.
 /// </summary>
 private static string CreateNoGenericsDescriptor(XMethodReference method)
 {
     return /*CreateNoGenericsDescriptor(method.ReturnType) + ":" +*/
            (string.Join(",", method.Parameters.Select(x => XBuilder.CreateNoGenericsDescriptor(x.ParameterType))));
 }
 /// <summary>
 /// Create a descriptor for comparing the given method without generics.
 /// </summary>
 private static string CreateNoGenericsDescriptor(XMethodReference method)
 {
     return /*CreateNoGenericsDescriptor(method.ReturnType) + ":" +*/
            string.Join(",", method.Parameters.Select(x => XBuilder.CreateNoGenericsDescriptor(x.ParameterType)));
 }
 /// <summary>
 /// Is this reference equal to the given other reference?
 /// </summary>
 public override bool IsSameExceptDeclaringType(XMethodReference other)
 {
     if (base.IsSameExceptDeclaringType(other))
         return true;
     EnsureDexImportName();
     // Check against dex import 
     if ((dexImportName == other.Name) && (other.Parameters.Count == Parameters.Count) && (other.HasThis == HasThis))
     {
         var descriptor = CreateNoGenericsDescriptor(this);
         var otherDescriptor = CreateNoGenericsDescriptor(other);
         return (descriptor == otherDescriptor);
     }
     EnsureJavaImportName();
     // Check against java import 
     if ((javaImportName == other.Name) && (other.Parameters.Count == Parameters.Count) && (other.HasThis == HasThis))
     {
         var descriptor = CreateNoGenericsDescriptor(this);
         var otherDescriptor = CreateNoGenericsDescriptor(other);
         return (descriptor == otherDescriptor);
     }
     return false;
 }
        void ProcessArgument(AstExpression callNode, XMethodReference methodRef, int argumentIndex, MethodSource currentMethod, XModule assembly)
        {
            var node = callNode.Arguments[argumentIndex];

            // Should we do something?
            switch (node.Code)
            {
            case AstCode.Ldloca:     // Parameter
            case AstCode.AddressOf:  // Local variable
            case AstCode.Ldflda:     // Instance field
            case AstCode.Ldsflda:    // Static field
            case AstCode.Ldelema:    // Array
                break;

            case AstCode.Ldloc:
                if (!node.MatchThis() || !currentMethod.IsDotNet)
                {
                    return;
                }
                break;

            default:
                return;
            }

            // Process argument
            var method         = methodRef.Resolve();
            var argIsThis      = !method.IsStatic && (argumentIndex == 0);
            var parameterIndex = method.IsStatic ? argumentIndex : argumentIndex - 1;
            var parameter      = argIsThis ? null : method.Parameters[parameterIndex];
            var argType        = argIsThis ? method.DeclaringType : parameter.ParameterType;
            //var argAttrs = argIsThis ? ParameterAttributes.None : parameter.Attributes;
            var argIsByRef         = argType.IsByReference;
            var argIsOut           = argIsThis ? false : argIsByRef && (parameter.Kind == XParameterKind.Output); // argIsByRef && argAttrs.HasFlag(ParameterAttributes.Out);
            var argIsGenByRefParam = argIsByRef && argType.ElementType.IsGenericParameter;

            switch (node.Code)
            {
            case AstCode.Ldloca:     // Parameter
            {
                var variable = ((AstVariable)node.Operand);
                if (variable.Type.IsPrimitive || argIsByRef)
                {
                    // Box first
                    var ldloc = new AstExpression(node.SourceLocation, AstCode.Ldloc, node.Operand)
                    {
                        InferredType = variable.Type
                    };
                    if (argIsByRef)
                    {
                        var stloc = new AstExpression(node.SourceLocation, AstCode.Stloc, node.Operand)
                        {
                            InferredType = variable.Type
                        };
                        stloc.Arguments.Add(GetValueOutOfByRefArray(node, variable.Type, argIsGenByRefParam, assembly));
                        ConvertToByRefArray(node, variable.Type, ldloc, stloc, argIsOut, argIsGenByRefParam, argType.ElementType, assembly);
                    }
                    else
                    {
                        ConvertToBox(node, variable.Type, ldloc);
                    }
                }
                else if (variable.Type.IsGenericParameter)
                {
                    // Convert to ldarg
                    var ldloc = new AstExpression(node.SourceLocation, AstCode.Ldloc, node.Operand)
                    {
                        InferredType = variable.Type
                    };
                    callNode.Arguments[argumentIndex] = ldloc;
                }
            }
            break;

            case AstCode.Ldloc:     // this
            {
                var variable = ((AstVariable)node.Operand);
                if (argIsThis && (variable.Type.IsByReference))
                {
                    node.SetType(variable.Type.ElementType);
                }
                else if (argIsByRef)
                {
                    var ldclone     = new AstExpression(node);
                    var stExpr      = new AstExpression(node.SourceLocation, AstCode.Nop, null);
                    var elementType = variable.Type;
                    if (elementType.IsByReference)
                    {
                        elementType = elementType.ElementType;
                    }
                    ConvertToByRefArray(node, elementType, ldclone, stExpr, argIsOut, argIsGenByRefParam, argType.ElementType, assembly);
                }
            }
            break;

            case AstCode.AddressOf:     // Local variable
            {
                var arg     = node.Arguments[0];
                var type    = arg.GetResultType();
                var typeDef = type.Resolve();
                if (typeDef.IsPrimitive)
                {
                    if (argIsByRef)
                    {
                        throw new CompilerException("Unsupported use of AddressOf by byref argument");
                    }
                    else
                    {
                        ConvertToBox(node, type, arg);
                    }
                }
            }
            break;

            case AstCode.Ldflda:     // Instance field
            case AstCode.Ldsflda:    // Static field
            {
                var fieldRef = (XFieldReference)node.Operand;
                var field    = fieldRef.Resolve();
                if (field.FieldType.IsPrimitive || argIsByRef)
                {
                    // Box first
                    var ldfldCode = (node.Code == AstCode.Ldflda) ? AstCode.Ldfld : AstCode.Ldsfld;
                    var ldfld     = new AstExpression(node.SourceLocation, ldfldCode, node.Operand)
                    {
                        InferredType = field.FieldType
                    };
                    ldfld.Arguments.AddRange(node.Arguments);
                    if (argIsByRef)
                    {
                        var stfldCode = (node.Code == AstCode.Ldflda) ? AstCode.Stfld : AstCode.Stsfld;
                        var stfld     = new AstExpression(node.SourceLocation, stfldCode, node.Operand)
                        {
                            InferredType = field.FieldType
                        };
                        stfld.Arguments.AddRange(node.Arguments);                                                          // instance
                        stfld.Arguments.Add(GetValueOutOfByRefArray(node, field.FieldType, argIsGenByRefParam, assembly)); // value
                        ConvertToByRefArray(node, field.FieldType, ldfld, stfld, argIsOut, argIsGenByRefParam, argType.ElementType, assembly);
                    }
                    else
                    {
                        ConvertToBox(node, field.FieldType, ldfld);
                    }
                }
            }
            break;

            case AstCode.Ldelema:     // Array element
            {
                var array     = node.Arguments[0];
                var arrayType = array.GetResultType();
                var type      = arrayType.ElementType;
                if (type.IsPrimitive || argIsByRef)
                {
                    // Box first
                    var ldElemCode = type.GetLdElemCode();
                    var ldelem     = new AstExpression(node.SourceLocation, ldElemCode, node.Operand)
                    {
                        InferredType = type
                    };
                    ldelem.Arguments.AddRange(node.Arguments);
                    if (argIsByRef)
                    {
                        var stelemCode = type.GetStElemCode();
                        var stelem     = new AstExpression(node.SourceLocation, stelemCode, node.Operand)
                        {
                            InferredType = type
                        };
                        stelem.Arguments.AddRange(node.Arguments);
                        stelem.Arguments.Add(GetValueOutOfByRefArray(node, type, argIsGenByRefParam, assembly));
                        ConvertToByRefArray(node, type, ldelem, stelem, argIsOut, argIsGenByRefParam, argType.ElementType, assembly);
                    }
                    else
                    {
                        ConvertToBox(node, type, ldelem);
                    }
                }
            }
            break;
            }
        }
Example #15
0
        /// <summary>
        /// Create the body of the class ctor.
        /// </summary>
        private AstBlock CreateClassCtorBody(bool isWide, XFieldDefinition enumInfoField, XFieldDefinition defaultField, XMethodReference enumInfoCtor, XTypeReference valueType, XTypeSystem typeSystem)
        {
            var internalEnumType     = Compiler.GetDot42InternalType("Enum");
            var internalEnumInfoType = Compiler.GetDot42InternalType("EnumInfo");
            var valueToFieldMap      = new Dictionary <object, XFieldDefinition>();
            var ldc = isWide ? AstCode.Ldc_I8 : AstCode.Ldc_I4;

            var ast = AstBlock.CreateOptimizedForTarget(
                // Instantiate enum info field
                new AstExpression(AstNode.NoSource, AstCode.Stsfld, enumInfoField,
                                  new AstExpression(AstNode.NoSource, AstCode.Newobj, enumInfoCtor)));

            // Instantiate values for each field
            var ordinal = 0;

            foreach (var field in XType.Fields.Where(x => x.IsStatic && !(x is XSyntheticFieldDefinition)))
            {
                // Find dex field
                object value;
                if (!field.TryGetEnumValue(out value))
                {
                    throw new CompilerException(string.Format("Cannot get enum value from field {0}", field.FullName));
                }
                value = isWide ? (object)XConvert.ToLong(value) : (object)XConvert.ToInt(value);
                XFieldDefinition existingField;
                AstExpression    valueExpr;
                if (valueToFieldMap.TryGetValue(value, out existingField))
                {
                    // Re-use instance of existing field
                    valueExpr = new AstExpression(AstNode.NoSource, AstCode.Ldsfld, existingField);
                }
                else
                {
                    // Record
                    valueToFieldMap[value] = field;

                    // Call ctor
                    valueExpr = new AstExpression(AstNode.NoSource, AstCode.Newobj, ctor,
                                                  new AstExpression(AstNode.NoSource, AstCode.Ldstr, field.Name),
                                                  new AstExpression(AstNode.NoSource, AstCode.Ldc_I4, ordinal),
                                                  new AstExpression(AstNode.NoSource, ldc, value));
                }

                // Initialize static field
                ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Stsfld, field, valueExpr));

                // Add to info
                var addMethod = new XMethodReference.Simple("Add", true, typeSystem.Void, internalEnumInfoType,
                                                            XParameter.Create("value", valueType),
                                                            XParameter.Create("instance", internalEnumType));
                ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Call, addMethod,
                                               new AstExpression(AstNode.NoSource, AstCode.Ldsfld, enumInfoField),
                                               new AstExpression(AstNode.NoSource, ldc, value),
                                               new AstExpression(AstNode.NoSource, AstCode.Ldsfld, field)));

                // Increment ordinal
                ordinal++;
            }

            // Initialize default field
            var getValueMethod = new XMethodReference.Simple("GetValue", true, internalEnumType, internalEnumInfoType,
                                                             XParameter.Create("value", valueType));

            ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Stsfld, defaultField,
                                           new AstExpression(AstNode.NoSource, AstCode.SimpleCastclass, XType,
                                                             new AstExpression(AstNode.NoSource, AstCode.Call, getValueMethod,
                                                                               new AstExpression(AstNode.NoSource, AstCode.Ldsfld, enumInfoField),
                                                                               new AstExpression(AstNode.NoSource, ldc, 0)))));

            // Return
            ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Ret, null));
            return(ast);
        }