コード例 #1
0
 /// <summary>
 /// Create a dex field definition from this field.
 /// </summary>
 public DexLib.FieldDefinition GetDexField(DexLib.ClassDefinition owner, DexTargetPackage targetPackage)
 {
     if (dexField == null)
     {
         var fdef = new DexLib.FieldDefinition(owner, name, fieldType.GetReference(targetPackage));
         if (IsStatic)
         {
             fdef.IsStatic = true;
         }
         if (IsPrivate)
         {
             fdef.IsPrivate = true;
         }
         else if (IsProtected)
         {
             fdef.IsProtected = true;
         }
         else
         {
             fdef.IsPublic = true;
         }
         if (IsReadOnly)
         {
             fdef.IsFinal = true;
         }
         dexField = fdef;
         targetPackage.NameConverter.Record(this, dexField);
     }
     return(dexField);
 }
コード例 #2
0
ファイル: XModel.cs プロジェクト: luozhiping1987/dot42
        /// <summary>
        /// Gets a class reference for the given type reference.
        /// </summary>
        internal static ClassReference GetClassReference(this XTypeReference type, DexTargetPackage targetPackage)
        {
            var classRef = type.GetReference(targetPackage) as ClassReference;

            if (classRef == null)
            {
                throw new ArgumentException(string.Format("type {0} is not a class reference", type.FullName));
            }
            return(classRef);
        }
コード例 #3
0
ファイル: RLBuilder.cs プロジェクト: luozhiping1987/dot42
        /// <summary>
        /// Create code to unbox the given source array of boxed type elements resulting from a call into an array of primitive elements.
        /// </summary>
        public static RLRange UnboxGenericArrayResult(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec boxedArray,
                                                      XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler)
        {
            var internalBoxingType = compiler.GetDot42InternalType("Boxing").Resolve();
            var primitiveArray     = frame.AllocateTemp(type.GetReference(targetPackage));
            var ilUnboxMethod      = internalBoxingType.Methods.First(x => x.Name.StartsWith("Unbox") && (x.Parameters.Count == 1) && (x.ReturnType.IsSame(type, true)));
            var unboxMethod        = ilUnboxMethod.GetReference(targetPackage);
            var call      = builder.Add(sequencePoint, RCode.Invoke_static, unboxMethod, boxedArray);
            var saveArray = builder.Add(sequencePoint, RCode.Move_result_object, primitiveArray);

            return(new RLRange(call, saveArray, primitiveArray));
        }
コード例 #4
0
ファイル: RLBuilder.cs プロジェクト: luozhiping1987/dot42
        /// <summary>
        /// Create code to unbox the given source value into the given type.
        /// </summary>
        public static RLRange Unbox(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec source, XTypeReference type, AssemblyCompiler compiler, DexTargetPackage targetPackage, IRegisterAllocator frame)
        {
            if (type.IsPrimitive)
            {
                RCode convertAfterCode;
                var   rUnboxed         = frame.AllocateTemp(type.GetReference(targetPackage));
                var   unboxValueMethod = type.GetUnboxValueMethod(compiler, targetPackage, out convertAfterCode);
                var   first            = builder.Add(sequencePoint, RCode.Invoke_static, unboxValueMethod, source);
                var   last             = builder.Add(sequencePoint, type.MoveResult(), rUnboxed);
                if (convertAfterCode != RCode.Nop)
                {
                    last = builder.Add(sequencePoint, convertAfterCode, rUnboxed, rUnboxed);
                }

                return(new RLRange(first, last, rUnboxed));
            }

            XTypeDefinition enumTypeDef;

            if (type.IsEnum(out enumTypeDef))
            {
                var rUnboxed         = frame.AllocateTemp(type.GetReference(targetPackage));
                var unboxValueMethod = enumTypeDef.Methods.First(x => x.Name == NameConstants.Enum.UnboxMethodName).GetReference(targetPackage);
                var first            = builder.Add(sequencePoint, RCode.Invoke_static, unboxValueMethod, source);
                var last             = builder.Add(sequencePoint, type.MoveResult(), rUnboxed);
                return(new RLRange(first, last, rUnboxed));
            }

            if (!type.IsGenericParameter)
            {
                // Just cast
                var checkCast = builder.Add(sequencePoint, RCode.Check_cast, type.GetReference(targetPackage), source);
                return(new RLRange(checkCast, source));
            }

            // Do nothing
            var nop = builder.Add(sequencePoint, RCode.Nop);

            return(new RLRange(nop, source));
        }
コード例 #5
0
ファイル: RLBuilder.cs プロジェクト: luozhiping1987/dot42
        /// <summary>
        /// Create code to box the given source value into the given type.
        /// </summary>
        public static RLRange Box(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec source, XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame)
        {
            if (type.IsPrimitive)
            {
                if (type.IsByte())
                {
                    builder.Add(sequencePoint, RCode.Int_to_byte, source.Register, source.Register);
                }
                else if (type.IsUInt16())
                {
                    builder.Add(sequencePoint, RCode.Int_to_short, source.Register, source.Register);
                }
                // Call appropriate valueOf method
                var boxedType = type.Module.TypeSystem.Object;
                var r         = frame.AllocateTemp(boxedType.GetReference(targetPackage));
                var call      = builder.Add(sequencePoint, RCode.Invoke_static, type.GetBoxValueOfMethod(), source.Registers);
                var last      = builder.Add(sequencePoint, RCode.Move_result_object, r);
                return(new RLRange(call, last, r));
            }
            if (type.IsGenericParameter)
            {
                var nop = builder.Add(sequencePoint, RCode.Nop);
                return(new RLRange(nop, source));
            }
            XTypeDefinition typeDef;

            if (type.TryResolve(out typeDef) && (typeDef.IsEnum))
            {
                // Call appropriate valueOf method

                /*var boxedType = type.Module.TypeSystem.Object;
                 * var r = frame.AllocateTemp(boxedType.GetReference(target, nsConverter));
                 * var call = builder.Add(sequencePoint, RCode.Invoke_static, typeDef.GetEnumUnderlyingType().GetBoxValueOfMethod(), source.Registers);
                 * var last = builder.Add(sequencePoint, RCode.Move_result_object, r);
                 * return new RLRange(call, last, r);*/
            }

            // Just cast
            var checkCast = builder.Add(sequencePoint, RCode.Check_cast, type.GetReference(targetPackage), source);

            return(new RLRange(checkCast, source));
        }
コード例 #6
0
 /// <summary>
 /// Gets a dex type reference from the given IL type reference.
 /// </summary>
 TypeReference ITypeResolver <TypeReference> .GetTypeReference(XTypeReference type)
 {
     return(type.GetReference(this));
 }
コード例 #7
0
ファイル: RLBuilder.cs プロジェクト: luozhiping1987/dot42
        /// <summary>
        /// Emit code (if needed) to convert a value from source type to destination type.
        /// This method is used in "store" opcodes such stloc, stfld, stsfld, call
        /// </summary>
        internal static RLRange ConvertTypeBeforeStore(this IRLBuilder builder, ISourceLocation sequencePoint, XTypeReference sourceType, XTypeReference destinationType, RegisterSpec source, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler, out bool converted)
        {
            converted = false;
            if (sourceType.IsSame(destinationType))
            {
                // Unsigned conversions
                if (sourceType.IsByte())
                {
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    var ins = builder.Add(sequencePoint, RCode.Int_to_byte, tmp.Result, tmp.Result);
                    converted = true;
                    return(new RLRange(tmp, ins, tmp.Result));
                }
                else if (sourceType.IsUInt16())
                {
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    var ins = builder.Add(sequencePoint, RCode.Int_to_short, tmp.Result, tmp.Result);
                    converted = true;
                    return(new RLRange(tmp, ins, tmp.Result));
                }
                return(new RLRange(source));
            }

            if (sourceType.IsArray)
            {
                var compilerHelper         = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var arrayType              = targetPackage.DexFile.GetClass(targetPackage.NameConverter.GetConvertedFullName(compilerHelper));
                var sourceArrayElementType = ((XArrayType)sourceType).ElementType;
                if (destinationType.ExtendsIList())
                {
                    // Use ArrayHelper.AsList to convert
                    var convertMethodName = "AsList";
                    var convertMethod     = arrayType.GetMethod(convertMethodName);
                    // Add code
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    builder.Add(sequencePoint, RCode.Invoke_static, convertMethod, tmp.Result.Register);
                    var last = builder.Add(sequencePoint, RCode.Move_result_object, tmp.Result.Register);
                    converted = true;
                    return(new RLRange(tmp, last, tmp.Result));
                }
                if (destinationType.ExtendsICollection())
                {
                    // Use ArrayHelper.AsCollection to convert
                    var convertMethodName = "AsCollection";
                    var convertMethod     = arrayType.GetMethod(convertMethodName);
                    // Add code
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    builder.Add(sequencePoint, RCode.Invoke_static, convertMethod, tmp.Result.Register);
                    var last = builder.Add(sequencePoint, RCode.Move_result_object, tmp.Result.Register);
                    converted = true;
                    return(new RLRange(tmp, last, tmp.Result));
                }
                if (destinationType.ExtendsIEnumerable())
                {
                    // Use ArrayHelper.As...Enumerable to convert
                    var convertMethodName = FrameworkReferences.GetAsEnumerableTMethodName(sourceArrayElementType);
                    var convertMethod     = arrayType.GetMethod(convertMethodName);
                    // Add code
                    var tmp = builder.EnsureTemp(sequencePoint, source, frame);
                    builder.Add(sequencePoint, RCode.Invoke_static, convertMethod, tmp.Result.Register);
                    var last = builder.Add(sequencePoint, RCode.Move_result_object, tmp.Result.Register);
                    converted = true;
                    return(new RLRange(tmp, last, tmp.Result));
                }
            }

            if (sourceType.IsGenericParameter && !destinationType.IsSystemObject())
            {
                var gp = (XGenericParameter)sourceType;
                if (gp.Constraints.Length > 0)
                {
                    // we could find the best matching constraint here, and check if we actually
                    // need to cast. This would probably allow us to skip some unneccesary casts.
                    // We would need some sort of IsAssignableFrom though, and I'm not sure we have
                    // this logic with XTypeDefinition implemented yet.
                    // Therefore, we just assume that the original compiler has done its job well,
                    // and always cast to the destination type.
                    // Apparently dex seems not to need a cast when destinationType is an interface.
                    // Since i'm not to sure about this, we nevertheless insert the cast here.
                    // [TODO: check if this is needed]
                    var tmp  = builder.EnsureTemp(sequencePoint, source, frame);
                    var cast = builder.Add(sequencePoint, RCode.Check_cast, destinationType.GetReference(targetPackage), tmp.Result);
                    converted = true;
                    return(new RLRange(tmp, cast, tmp.Result));
                }
            }

            // Do not convert
            return(new RLRange(source));
        }
コード例 #8
0
        /// <summary>
        /// Create code to initialize a value from an attribute.
        /// </summary>
        /// <returns>The register(s) holding the value</returns>
        private static Register[] CreateInitializeValueInstructions(ISourceLocation seqp, MethodBody body, XTypeReference targetType, CustomAttributeArgument value, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            List <Register> result = new List <Register>();

            // allocate result, initialize to default value.
            if (targetType.IsWide())
            {
                Tuple <Register, Register> regs = body.AllocateWideRegister(RCategory.Temp);
                //body.Instructions.Add(seqp, RCode.Const_wide, 0, regs.Item1);
                result.Add(regs.Item1);
                result.Add(regs.Item2);
            }
            else if (targetType.IsPrimitive)
            {
                Register reg = body.AllocateRegister(RCategory.Temp, RType.Value);
                //body.Instructions.Add(seqp, RCode.Const, 0, reg);
                result.Add(reg);
            }
            else // object
            {
                Register reg = body.AllocateRegister(RCategory.Temp, RType.Object);
                //body.Instructions.Add(seqp, RCode.Const, 0, reg);
                result.Add(reg);
            }

            // load data

            if (value.Value == null) // must be a reference type
            {
                body.Instructions.Add(seqp, RCode.Const, 0, result[0]);
                body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
                return(result.ToArray());
            }

            var valueType = XBuilder.AsTypeReference(compiler.Module, value.Type);

            if (value.Value is CustomAttributeArgument)
            {
                // this happens if a type conversion is neccessary
                var nestedValue = (CustomAttributeArgument)value.Value;
                valueType = XBuilder.AsTypeReference(compiler.Module, nestedValue.Type);

                var rOrigValue = CreateInitializeValueInstructions(seqp, body, valueType, nestedValue, compiler, targetPackage);

                if (!nestedValue.Type.IsPrimitive)
                {
                    body.Instructions.Add(seqp, RCode.Move_object, result[0], rOrigValue[0]);
                    body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
                }
                else if (!targetType.IsPrimitive)
                {
                    body.Instructions.Add(seqp, RCode.Invoke_static, valueType.GetBoxValueOfMethod(), rOrigValue);
                    body.Instructions.Add(seqp, RCode.Move_result_object, result[0]);
                    body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
                }
                else
                {
                    throw new Exception(string.Format("type converstion in attribute {0}=>{1} not yet supported", valueType.FullName, targetType.FullName));
                }
            }
            else if (valueType.IsArray)
            {
                var array       = (CustomAttributeArgument[])value.Value;
                var elementType = valueType.ElementType;

                Register rIndex = body.AllocateRegister(RCategory.Temp, RType.Value);
                body.Instructions.Add(seqp, RCode.Const, array.Length, rIndex);
                body.Instructions.Add(seqp, RCode.New_array, valueType.GetReference(targetPackage), result[0], rIndex);

                // iterate through each value
                for (int i = 0; i < array.Length; i++)
                {
                    Register rLoaded = CreateInitializeValueInstructions(seqp, body, elementType, array[i], compiler, targetPackage)[0];

                    body.Instructions.Add(seqp, RCode.Const, i, rIndex);
                    body.Instructions.Add(seqp, valueType.APut(), rLoaded, result[0], rIndex);
                }
            }
            else if (targetType.IsEnum())
            {
                var enumClass = (targetType.IsEnum()? targetType:valueType).GetReference(targetPackage);

                Register rEnumClass = body.AllocateRegister(RCategory.Temp, RType.Object);
                body.Instructions.Add(seqp, RCode.Const_class, enumClass, rEnumClass);

                long lVal = Convert.ToInt64(value.Value);
                if (lVal <= int.MaxValue && lVal >= int.MinValue)
                {
                    Register regTmp = body.AllocateRegister(RCategory.Temp, RType.Value);
                    body.Instructions.Add(seqp, RCode.Const, (int)lVal, regTmp);
                    var get = compiler.GetDot42InternalType("Enum").Resolve()
                              .Methods.Single(p => p.Name == "Get" && p.Parameters.Count == 2 && !p.Parameters[1].ParameterType.IsWide())
                              .GetReference(targetPackage);
                    body.Instructions.Add(seqp, RCode.Invoke_static, get, rEnumClass, regTmp);
                    body.Instructions.Add(seqp, targetType.MoveResult(), result[0]);
                }
                else
                {
                    var regTmp = body.AllocateWideRegister(RCategory.Temp);
                    body.Instructions.Add(seqp, RCode.Const, (long)lVal, regTmp.Item1);
                    var get = compiler.GetDot42InternalType("Enum").Resolve()
                              .Methods.Single(p => p.Name == "Get" && p.Parameters.Count == 2 && p.Parameters[1].ParameterType.IsWide())
                              .GetReference(targetPackage);
                    body.Instructions.Add(seqp, RCode.Invoke_static, get, rEnumClass, regTmp.Item1);
                    body.Instructions.Add(seqp, targetType.MoveResult(), result[0]);
                }
                body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]);
            }
            else if (valueType.IsSystemString())
            {
                body.Instructions.Add(seqp, RCode.Const_string, (string)value.Value, result[0]);
            }
            else if (valueType.IsSystemType())
            {
                var type = XBuilder.AsTypeReference(compiler.Module, (TypeReference)value.Value);
                // TODO: this might not work with typeof(void) on ART runtime.
                body.Instructions.Add(seqp, RCode.Const_class, type.GetReference(targetPackage), result[0]);
            }
            else if (!valueType.IsPrimitive)
            {
                // can this happen?
                throw new Exception("invalid value type in attribute: " + targetType.FullName);
            }
            else
            {
                if (targetType.IsSystemObject())
                {
                    // can this happen? or is this always handled above?

                    // boxing required.
                    var rUnboxed = CreateInitializeValueInstructions(seqp, body, valueType, value, compiler, targetPackage);
                    body.Instructions.Add(seqp, RCode.Invoke_static, valueType.GetBoxValueOfMethod(), rUnboxed);
                    body.Instructions.Add(seqp, RCode.Move_result_object, result[0]);
                }
                else if (targetType.IsDouble())
                {
                    body.Instructions.Add(seqp, RCode.Const_wide, Convert.ToDouble(value.Value), result[0]);
                }
                else if (targetType.IsWide() && valueType.IsUInt64())
                {
                    body.Instructions.Add(seqp, RCode.Const_wide, (long)Convert.ToUInt64(value.Value), result[0]);
                }
                else if (targetType.IsWide())
                {
                    body.Instructions.Add(seqp, RCode.Const_wide, Convert.ToInt64(value.Value), result[0]);
                }
                else if (targetType.IsFloat())
                {
                    body.Instructions.Add(seqp, RCode.Const, Convert.ToSingle(value.Value), result[0]);
                }
                else
                {
                    body.Instructions.Add(seqp, RCode.Const, (int)Convert.ToInt64(value.Value), result[0]);
                }
            }

            return(result.ToArray());
        }
コード例 #9
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());
        }