Example #1
0
        /// <summary>
        /// Is the given field initialized in the given code?
        /// </summary>
        private static bool IsInitialized(AstBlock ast, XFieldDefinition field)
        {
            var storeCode       = field.IsStatic ? AstCode.Stsfld : AstCode.Stfld;
            var initExpressions = ast.GetSelfAndChildrenRecursive <AstExpression>(x => (x.Code == storeCode) && ((XFieldReference)x.Operand).IsSame(field)).ToList();

            return(initExpressions.Any());
        }
Example #2
0
 /// <summary>
 /// Record the given field mapping
 /// </summary>
 internal DexLib.FieldDefinition GetField(XFieldDefinition xField)
 {
     DexLib.FieldDefinition dfield;
     if (xFieldMap.TryGetValue(xField, out dfield))
     {
         return(dfield);
     }
     throw new ArgumentException(string.Format("Field {0} not found", xField));
 }
Example #3
0
        /// <summary>
        /// Create the current type as class definition.
        /// </summary>
        public virtual void Create(ClassDefinition declaringClass, XTypeDefinition declaringType, DexTargetPackage targetPackage)
        {
            // Find xfield
            xField = XBuilder.AsFieldDefinition(compiler.Module, field);

            // Create field definition
            dfield      = new Dot42.DexLib.FieldDefinition();
            dfield.Name = NameConverter.GetConvertedName(field);
            AddFieldToDeclaringClass(declaringClass, dfield, targetPackage);
            targetPackage.NameConverter.Record(xField, dfield);

            // Set access flags
            SetAccessFlags(dfield, field);

            // Give warning if static in generic class.
            // This could of cause also be handled automagically be the compiler,
            // with mixture of whats done in the Interlocked converter and whats
            // done in the GenericInstanceConverter.
            if (field.IsStatic && declaringType.IsGenericClass)
            {
                if (!field.HasSuppressMessageAttribute("StaticFieldInGenericType") &&
                    !field.DeclaringType.HasSuppressMessageAttribute("StaticFieldInGenericType"))
                {
                    string msg;
                    if (field.Name.Contains("CachedAnonymousMethodDelegate"))
                    {
                        msg = "The compiler generated a static field '{0}' in generic type '{1}'. This is not supported " +
                              "in Dot42 if the anonymous delegate accesses a generic class parameter. A workaround " +
                              "is to convert the anonymous static delegate to a normal method.\n";
                    }
                    else
                    {
                        msg = "Static field '{0}' in generic type {1}: All generic instances will share " +
                              "the same static field, contrary on how CLR operates. A workaround is to " +
                              "use ConcurrentDictionaries to access the values dependent on the type.\n";
                    }

                    msg += "You can suppress this warning with a [SuppressMessage(\"dot42\"," +
                           " \"StaticFieldInGenericType\")] attribute, either on the field or on the class.";

                    var body = field.DeclaringType.Methods.Select(m => m.Body)
                               .FirstOrDefault(m => m != null &&
                                               m.Instructions.Any(i => i.SequencePoint(m) != null));
                    if (body != null)
                    {
                        var seqPoint = body.Instructions.Select(i => i.SequencePoint(body)).First(i => i != null);
                        DLog.Warning(DContext.CompilerILConverter, seqPoint.Document.Url, seqPoint.StartColumn, seqPoint.StartLine, msg, field.Name, declaringType.FullName);
                    }
                    else
                    {
                        DLog.Warning(DContext.CompilerILConverter, msg, field.Name, declaringType.FullName);
                    }
                }
            }
        }
Example #4
0
        /// <summary>
        /// Create the body of the values() method.
        /// </summary>
        private AstBlock CreateValuesBody(XFieldDefinition enumInfoField, XTypeSystem typeSystem)
        {
            var internalEnumInfoType = Compiler.GetDot42InternalType("EnumInfo");
            var valuesMethod         = new XMethodReference.Simple("Values", true, typeSystem.Object, internalEnumInfoType);

            var ast = AstBlock.CreateOptimizedForTarget(
                new AstExpression(AstNode.NoSource, AstCode.Ret, null,
                                  new AstExpression(AstNode.NoSource, AstCode.SimpleCastclass, new XArrayType(XType),
                                                    new AstExpression(AstNode.NoSource, AstCode.Call, valuesMethod,
                                                                      new AstExpression(AstNode.NoSource, AstCode.Ldsfld, enumInfoField)))));

            return(ast);
        }
Example #5
0
        /// <summary>
        /// Create the current type as class definition.
        /// </summary>
        public void Create(ClassDefinition declaringClass, DexTargetPackage targetPackage)
        {
            // Find xField
            xField = XBuilder.AsFieldDefinition(compiler.Module, field);

            // Create field definition
            dfield      = new Dot42.DexLib.FieldDefinition();
            dfield.Name = NameConverter.GetConvertedName(field);
            AddFieldToDeclaringClass(declaringClass, dfield, targetPackage);
            targetPackage.NameConverter.Record(xField, dfield);

            // Set access flags
            SetAccessFlags(dfield, field);
        }
Example #6
0
 /// <summary>
 /// Resolve this reference to it's definition.
 /// </summary>
 public override bool TryResolve(out XFieldDefinition field)
 {
     string fieldName;
     string descriptor;
     string className;
     if (TryGetJavaImportNames(out fieldName, out descriptor, out className))
     {
         // Resolve to java field definition
         var declaringType = Java.XBuilder.AsTypeReference(Module, className, XTypeUsageFlags.DeclaringType);
         var fieldRef = Java.XBuilder.AsFieldReference(Module, fieldName, descriptor, declaringType, className);
         return fieldRef.TryResolve(out field);
     }
     field = this;
     return true;
 }
Example #7
0
        /// <summary>
        /// Resolve this reference to it's definition.
        /// </summary>
        public override bool TryResolve(out XFieldDefinition field)
        {
            string fieldName;
            string descriptor;
            string className;

            if (TryGetJavaImportNames(out fieldName, out descriptor, out className))
            {
                // Resolve to java field definition
                var declaringType = Java.XBuilder.AsTypeReference(Module, className, XTypeUsageFlags.DeclaringType);
                var fieldRef      = Java.XBuilder.AsFieldReference(Module, fieldName, descriptor, declaringType, className);
                return(fieldRef.TryResolve(out field));
            }
            field = this;
            return(true);
        }
            /// <summary>
            /// Try to get the enum field that defines the given constant.
            /// </summary>
            public override bool TryGetEnumConstField(object value, out XFieldDefinition field)
            {
                field = null;
                if (!type.IsEnum || (value == null))
                {
                    return(false);
                }
                var valueType = value.GetType();
                var ilField   = type.Fields.FirstOrDefault(x => x.IsStatic && Equals(XConvert.ChangeType(x.Constant, valueType), value));

                if (ilField == null)
                {
                    return(false);
                }
                field = Fields.OfType <ILFieldDefinition>().FirstOrDefault(x => x.OriginalField == ilField);
                return(field != null);
            }
Example #9
0
        /// <summary>
        /// Create the body of the valueOf(string) method.
        /// </summary>
        private AstBlock CreateValueOfBody(XSyntheticMethodDefinition method, XFieldDefinition enumInfoField, XTypeSystem typeSystem)
        {
            var internalEnumType     = Compiler.GetDot42InternalType("Enum");
            var internalEnumInfoType = Compiler.GetDot42InternalType("EnumInfo");
            var parseMethod          = new XMethodReference.Simple("Parse", true, internalEnumType, internalEnumInfoType,
                                                                   XParameter.Create("value", typeSystem.String),
                                                                   XParameter.Create("ignoreCase", typeSystem.Bool),
                                                                   XParameter.Create("throwIfNotFound", typeSystem.Bool));

            var ast = AstBlock.CreateOptimizedForTarget(
                new AstExpression(AstNode.NoSource, AstCode.Ret, null,
                                  new AstExpression(AstNode.NoSource, AstCode.SimpleCastclass, XType,
                                                    new AstExpression(AstNode.NoSource, AstCode.Call, parseMethod,
                                                                      new AstExpression(AstNode.NoSource, AstCode.Ldsfld, enumInfoField),
                                                                      new AstExpression(AstNode.NoSource, AstCode.Ldloc, method.AstParameters[0]),
                                                                      new AstExpression(AstNode.NoSource, AstCode.Ldc_I4, 0),
                                                                      new AstExpression(AstNode.NoSource, AstCode.Ldc_I4, 1)))));

            return(ast);
        }
Example #10
0
        /// <summary>
        /// Generate a iget opcode.
        /// </summary>
        internal static RCode IGet(this XFieldDefinition field)
        {
            var type = field.FieldType;

            if (type.IsDexWide())
            {
                return(RCode.Iget_wide);
            }
            if (type.IsVoid())
            {
                throw new ArgumentException("Unexpected void expression type");
            }
            if (type.IsDexBoolean())
            {
                return(RCode.Iget_boolean);
            }
            if (type.IsDexChar())
            {
                return(RCode.Iget_char);
            }
            if (type.IsDexShort())
            {
                return(RCode.Iget_short);
            }
            if (type.IsDexByte())
            {
                return(RCode.Iget_byte);
            }
            if (type.IsDexValue())
            {
                return(RCode.Iget);
            }
            if (type.IsDexObject())
            {
                return(RCode.Iget_object);
            }
            throw new ArgumentException("Unknown type in iget " + type);
        }
Example #11
0
 /// <summary>
 /// Try to get the enum field that defines the given constant.
 /// </summary>
 public override bool TryGetEnumConstField(object value, out XFieldDefinition field)
 {
     field = null;
     return false;
 }
 /// <summary>
 /// Try to get the enum field that defines the given constant.
 /// </summary>
 public override bool TryGetEnumConstField(object value, out XFieldDefinition field)
 {
     field = null;
     return(false);
 }
Example #13
0
        /// <summary>
        /// Generate a iput opcode.
        /// </summary>
        internal static RCode IPut(this XFieldDefinition field)
        {
            var type = field.FieldType;

            return(type.IPut());
        }
Example #14
0
 /// <summary>
 /// Record the given field mapping
 /// </summary>
 internal void Record(XFieldDefinition xField, DexLib.FieldDefinition dField)
 {
     xFieldMap.Add(xField, dField);
 }
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);
        }
 /// <summary>
 /// Try to get the enum field that defines the given constant.
 /// </summary>
 public override bool TryGetEnumConstField(object value, out XFieldDefinition field)
 {
     field = null;
     if (!type.IsEnum || (value == null))
         return false;
     var valueType = value.GetType();
     var ilField = type.Fields.FirstOrDefault(x => x.IsStatic && Equals(XConvert.ChangeType(x.Constant, valueType), value));
     if (ilField == null)
         return false;
     field = Fields.OfType<ILFieldDefinition>().FirstOrDefault(x => x.OriginalField == ilField);
     return (field != null);
 }
Example #17
0
        private static bool InterlockedUsingUpdater(AstExpression interlockedCall, string methodName, XFieldReference field,
                                                    XFieldDefinition updater, AstExpression targetExpr, AstExpression parentExpr,
                                                    AssemblyCompiler compiler)
        {
            bool isStatic = field.Resolve().IsStatic;

            string replacementMethod = null;

            if (methodName == "Increment")
            {
                replacementMethod = "IncrementAndGet";
            }
            else if (methodName == "Decrement")
            {
                replacementMethod = "DecrementAndGet";
            }
            else if (methodName == "Add")
            {
                replacementMethod = "AddAndGet";
            }
            else if (methodName == "Read")
            {
                replacementMethod = "Get";
            }
            else if (methodName.StartsWith("Exchange"))
            {
                replacementMethod = "GetAndSet";
            }
            else if (methodName.StartsWith("CompareAndSet"))
            {
                // this patches through to the original java method for performance purists.
                replacementMethod = "CompareAndSet";
            }
            else if (methodName.StartsWith("CompareExchange"))
            {
                if (TransformCompareExchangeToCompareAndSet(parentExpr, compiler, ref interlockedCall))
                {
                    replacementMethod = "CompareAndSet";
                }
                else
                {
                    // The semantics here are slighlty different. Java returns a 'true' on
                    // success, while BCL returns the old value. We have crafted a replacement
                    // method with the BCL semantics though.
                    replacementMethod = "CompareExchange";
                }
            }
            else
            {
                return(false);
            }

            var updaterType = updater.FieldType.Resolve();
            var methodRef   = updaterType.Methods.FirstOrDefault(f => f.Name == replacementMethod);

            if (methodRef == null && methodName == "CompareExchange")
            {
                methodRef = updaterType.Methods.FirstOrDefault(f => f.Name.StartsWith(replacementMethod));
            }

            if (methodRef == null)
            {
                return(false);
            }

            interlockedCall.Operand = methodRef;

            if (isStatic)
            {
                interlockedCall.Arguments[0] = new AstExpression(interlockedCall.SourceLocation, AstCode.Ldnull, null)
                                               .SetType(field.DeclaringType);
            }
            else
            {
                interlockedCall.Arguments[0] = targetExpr.Arguments[0];
            }

            // add field updater instance argument.
            var ldUpdater = new AstExpression(interlockedCall.SourceLocation, AstCode.Ldsfld, updater)
                            .SetType(updaterType);

            interlockedCall.Arguments.Insert(0, ldUpdater);

            return(true);
        }