예제 #1
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 != null));
                    if (body != null)
                    {
                        var seqPoint = body.Instructions.Select(i=>i.SequencePoint).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);
                    }
                }
            }
        }
예제 #2
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);
        }
예제 #3
0
        /// <summary>
        /// Try to get a field with given reference in this type.
        /// The declaring type of the method reference is assumed to refer to this type.
        /// </summary>
        public bool TryGet(XFieldReference fieldRef, out XFieldDefinition field)
        {
            // Look in my own fields
            field = Fields.FirstOrDefault(x => x.IsSameExceptDeclaringType(fieldRef));
            if (field != null)
            {
                return(true);
            }

            // Look in base type
            XTypeDefinition baseTypeDef;

            if ((BaseType != null) && BaseType.TryResolve(out baseTypeDef))
            {
                return(baseTypeDef.TryGet(fieldRef, out field));
            }
            return(false);
        }
예제 #4
0
 /// <summary>
 /// Resolve this reference to it's definition.
 /// </summary>
 public virtual bool TryResolve(out XFieldDefinition field)
 {
     if (resolvedField != null)
     {
         field = resolvedField;
         return true;
     }
     field = null;
     XTypeDefinition declaringType;
     if (!DeclaringType.GetElementType().TryResolve(out declaringType))
         return false;
     if (!declaringType.TryGet(this, out field))
         return false;
     // Cache for later
     resolvedField = field;
     declaringType.AddFlushAction(() => resolvedField = null);
     return true;
 }
예제 #5
0
        /// <summary>
        /// Resolve this reference to it's definition.
        /// </summary>
        public virtual bool TryResolve(out XFieldDefinition field)
        {
            if (resolvedField != null)
            {
                field = resolvedField;
                return(true);
            }
            field = null;
            XTypeDefinition declaringType;

            if (!DeclaringType.GetElementType().TryResolve(out declaringType))
            {
                return(false);
            }
            if (!declaringType.TryGet(this, out field))
            {
                return(false);
            }
            // Cache for later
            resolvedField = field;
            declaringType.AddFlushAction(() => resolvedField = null);
            return(true);
        }
예제 #6
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));
 }
예제 #7
0
 /// <summary>
 /// Record the given field mapping
 /// </summary>
 internal void Record(XFieldDefinition xField, DexLib.FieldDefinition dField)
 {
     xFieldMap.Add(xField, dField);
 }
예제 #8
0
 /// <summary>
 /// Try to get the enum field that defines the given constant.
 /// </summary>
 public abstract bool TryGetEnumConstField(object value, out XFieldDefinition field);
예제 #9
0
        /// <summary>
        /// Try to get a field with given reference in this type.
        /// The declaring type of the method reference is assumed to refer to this type.
        /// </summary>
        public bool TryGet(XFieldReference fieldRef, out XFieldDefinition field)
        {
            // Look in my own fields
            field = Fields.FirstOrDefault(x => x.IsSameExceptDeclaringType(fieldRef));
            if (field != null)
                return true;

            // Look in base type
            XTypeDefinition baseTypeDef;
            if ((BaseType != null) && BaseType.TryResolve(out baseTypeDef))
            {
                return baseTypeDef.TryGet(fieldRef, out field);
            }
            return false;
        }
예제 #10
0
 /// <summary>
 /// Try to get the enum field that defines the given constant.
 /// </summary>
 public abstract bool TryGetEnumConstField(object value, out XFieldDefinition field);
예제 #11
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());
 }
예제 #12
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;

        }
예제 #13
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;
        }
예제 #14
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;
        }
예제 #15
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;
        }