Ejemplo n.º 1
0
 /// <summary>
 /// Optimize expressions
 /// </summary>
 public static void Convert(AstNode ast, AssemblyCompiler compiler)
 {
     // Optimize enum2int(ldsfld(enum-const))
     foreach (var node in ast.GetExpressions())
     {
         switch (node.Code)
         {
         case AstCode.Enum_to_int:
         case AstCode.Enum_to_long:
         {
             var             arg = node.Arguments[0];
             XFieldReference fieldRef;
             if (arg.Match(AstCode.Ldsfld, out fieldRef))
             {
                 XFieldDefinition field;
                 object           value;
                 if (fieldRef.TryResolve(out field) && field.IsStatic && field.DeclaringType.IsEnum && field.TryGetEnumValue(out value))
                 {
                     // Replace with ldc_ix
                     var wide = (node.Code == AstCode.Enum_to_long);
                     node.SetCode(wide ? AstCode.Ldc_I8 : AstCode.Ldc_I4);
                     node.Operand = wide ? (object)XConvert.ToLong(value) : XConvert.ToInt(value);
                     node.Arguments.Clear();
                 }
             }
         }
         break;
         }
     }
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Set the value of the given dex field.
        /// </summary>
        protected virtual void SetFieldValue(DexLib.FieldDefinition dfield, FieldDefinition field)
        {
            var constant = field.Constant;

            if (constant != null)
            {
                var fieldType = field.FieldType;
                if (fieldType.IsByte())
                {
                    constant = XConvert.ToByte(constant);
                }
                else if (fieldType.IsUInt16())
                {
                    constant = XConvert.ToShort(constant);
                }
                else if (fieldType.IsUInt32())
                {
                    constant = XConvert.ToInt(constant);
                }
                else if (fieldType.IsUInt64())
                {
                    constant = XConvert.ToLong(constant);
                }
            }
            dfield.Value = constant;
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Generate converter for the value of an Const instruction.
 /// </summary>
 internal static Func <object, object> ConstValueConverter(this XTypeReference elementType, bool keepUnsigned)
 {
     if (elementType.IsBoolean())
     {
         return(x => Convert.ToBoolean(x) ? 1 : 0);
     }
     if (elementType.IsByte())
     {
         if (keepUnsigned)
         {
             return(x => (int)Convert.ToByte(x));
         }
         return(x => (int)((sbyte)unchecked (Convert.ToByte(x))));
     }
     if (elementType.IsSByte())
     {
         return(x => (int)(Convert.ToSByte(x)));
     }
     if (elementType.IsChar())
     {
         return(x => (int)(Convert.ToChar(x)));
     }
     if (elementType.IsUInt16())
     {
         return(x => (int)(Convert.ToUInt16(x)));
     }
     if (elementType.IsInt16())
     {
         return(x => (int)(Convert.ToInt16(x)));
     }
     if (elementType.IsInt32())
     {
         return(x => XConvert.ToInt(x));
     }
     if (elementType.IsUInt32())
     {
         return(x => XConvert.ToInt(x));                       // unchecked((int)Convert.ToUInt32(Convert.ToInt64(x) & 0xFFFFFFFF));
     }
     if (elementType.IsFloat())
     {
         return(x => Convert.ToSingle(x));
     }
     if (elementType.IsInt64())
     {
         return(x => XConvert.ToLong(x));
     }
     if (elementType.IsUInt64())
     {
         return(x => XConvert.ToLong(x));                        // unchecked((long)Convert.ToInt64(x));
     }
     if (elementType.IsDouble())
     {
         return(x => Convert.ToDouble(x));
     }
     if (elementType.IsDexObject() && !elementType.IsVoid())
     {
         return(x => x);
     }
     throw new NotSupportedException("Unknown type for constValueConverter " + elementType);
 }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Optimize expressions
        /// </summary>
        public static void Convert(AstNode ast, AssemblyCompiler compiler)
        {
            foreach (var node in ast.GetExpressions())
            {
                switch (node.Code)
                {
                // Optimize enum2int(ldsfld(enum-const))
                //      and enum2int(int.to.enum(xxx))
                case AstCode.Enum_to_int:
                case AstCode.Enum_to_long:
                {
                    var             arg = node.Arguments[0];
                    XFieldReference fieldRef;
                    if (arg.Match(AstCode.Ldsfld, out fieldRef))
                    {
                        XFieldDefinition field;
                        object           value;
                        if (fieldRef.TryResolve(out field) && field.IsStatic && field.DeclaringType.IsEnum && field.TryGetEnumValue(out value))
                        {
                            // Replace with ldc_ix
                            var wide = (node.Code == AstCode.Enum_to_long);
                            node.SetCode(wide ? AstCode.Ldc_I8 : AstCode.Ldc_I4);
                            node.Operand = wide ? (object)XConvert.ToLong(value) : XConvert.ToInt(value);
                            node.Arguments.Clear();
                        }
                    }
                    else if (arg.Code == AstCode.Int_to_enum || arg.Code == AstCode.Long_to_enum)
                    {
                        var expectedType = node.ExpectedType;
                        node.CopyFrom(arg.Arguments[0]);
                        node.ExpectedType = expectedType;
                    }
                }
                break;

                // optimize ceq/cne (int/long-to-enum(int), yyy)
                case AstCode.Ceq:
                case AstCode.Cne:
                {
                    if (node.Arguments.Any(a => IsToEnum(a.Code)))
                    {
                        // xx_to_enum is a quite costly operation when compared to enum-to-int,
                        // so convert this to an interger-only compare.
                        bool isLong = node.Arguments.Any(a => a.Code == AstCode.Long_to_enum);

                        foreach (var arg in node.Arguments)
                        {
                            if (IsToEnum(arg.Code))
                            {
                                arg.CopyFrom(arg.Arguments[0]);
                                arg.ExpectedType = isLong ? compiler.Module.TypeSystem.Long : compiler.Module.TypeSystem.Int;
                            }
                            else
                            {
                                Debug.Assert(arg.GetResultType().IsEnum());
                                var orig    = new AstExpression(arg);
                                var convert = new AstExpression(arg.SourceLocation,
                                                                isLong ? AstCode.Enum_to_long : AstCode.Enum_to_int, null, orig);
                                convert.ExpectedType = isLong ? compiler.Module.TypeSystem.Long : compiler.Module.TypeSystem.Int;
                                arg.CopyFrom(convert);
                            }
                        }
                    }
                    break;
                }
                }
            }
        }