Example #1
0
 /// <summary>
 /// Create code to load a value from an annotation interface.
 /// </summary>
 /// <returns>The register(s) holding the value</returns>
 private static Register[] CreateLoadValueSequence(
     ISourceLocation seqp,
     MethodBody body,
     TypeReference valueType,
     Register annotationReg,
     MethodDefinition getter)
 {
     if (valueType.IsWide())
     {
         Tuple <Register, Register> regs = body.AllocateWideRegister(RCategory.Temp);
         body.Instructions.Add(seqp, RCode.Invoke_interface, getter, annotationReg);
         body.Instructions.Add(seqp, RCode.Move_result_wide, regs.Item1);
         return(new[] { regs.Item1, regs.Item2 });
     }
     if (valueType is PrimitiveType)
     {
         Register reg = body.AllocateRegister(RCategory.Temp, RType.Value);
         body.Instructions.Add(seqp, RCode.Invoke_interface, getter, annotationReg);
         body.Instructions.Add(seqp, RCode.Move_result, reg);
         return(new[] { reg });
     }
     else
     {
         Register reg = body.AllocateRegister(RCategory.Temp, RType.Object);
         body.Instructions.Add(seqp, RCode.Invoke_interface, getter, annotationReg);
         body.Instructions.Add(seqp, RCode.Move_result_object, reg);
         return(new[] { reg });
     }
 }
        private TypeReference ConvertTypeReference(TypeReference sourceRef, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            if (sourceRef is PrimitiveType)
            {
                return(sourceRef);
            }

            if (sourceRef is ByReferenceType)
            {
                var type        = (ByReferenceType)sourceRef;
                var elementType = ConvertTypeReference(type.ElementType, compiler, targetPackage);
                return(new ByReferenceType(elementType));
            }

            if (sourceRef is ArrayType)
            {
                var arrayType   = (ArrayType)sourceRef;
                var elementType = ConvertTypeReference(arrayType.ElementType, compiler, targetPackage);
                return(new ArrayType(elementType));
            }

            // must be ClassReference
            return(ConvertClassReference((ClassReference)sourceRef, compiler, targetPackage));
        }
        private TypeReference ConvertTypeReference(TypeReference sourceRef, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            if (sourceRef is PrimitiveType)
            {
                return sourceRef;
            }

            if (sourceRef is ByReferenceType)
            {
                var type = (ByReferenceType) sourceRef;
                var elementType = ConvertTypeReference(type.ElementType, compiler, targetPackage);
                return new ByReferenceType(elementType);
            }

            if (sourceRef is ArrayType)
            {
                var arrayType = (ArrayType) sourceRef;
                var elementType = ConvertTypeReference(arrayType.ElementType,compiler, targetPackage);
                return new ArrayType(elementType);
            }
            
            // must be ClassReference
            return ConvertClassReference((ClassReference)sourceRef, compiler, targetPackage);
        }
Example #4
0
        /// <summary>
        /// Create an annotation interface.
        /// </summary>
        internal static AttributeAnnotationInterface Create(
            ISourceLocation sequencePoint,
            AssemblyCompiler compiler,
            DexTargetPackage targetPackage,
            TypeDefinition attributeType,
            ClassDefinition attributeClass)
        {
            // Create class
            ClassDefinition @interface = new ClassDefinition();

            @interface.Name        = CreateAnnotationTypeName(attributeClass);
            @interface.Namespace   = attributeClass.Namespace;
            @interface.AccessFlags = AccessFlags.Public | AccessFlags.Abstract | AccessFlags.Interface | AccessFlags.Annotation;
            @interface.Owner       = attributeClass;
            attributeClass.InnerClasses.Add(@interface);

            // Set super class
            @interface.SuperClass = new ClassReference("java/lang/Object");

            // Implement Dot42.Internal.IAttribute
            @interface.Interfaces.Add(new ClassReference("java/lang/annotation/Annotation"));

            // Prepare result
            AttributeAnnotationInterface result = new AttributeAnnotationInterface(@interface);

            // Add methods from IAttribute
            XModel.XTypeDefinition baseIntfType = compiler.GetDot42InternalType("IAttribute").Resolve();
            foreach (XModel.XMethodDefinition imethod in baseIntfType.Methods)
            {
                if (imethod.Parameters.Count > 0)
                {
                    throw new CompilerException(string.Format("Invalid IAttribute method {0}", imethod));
                }
                string           methodName = NameConverter.GetConvertedName(imethod);
                TypeReference    dfieldType = imethod.ReturnType.GetReference(targetPackage);
                MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dfieldType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                @interface.Methods.Add(method);
            }

            // Add field mapping
            foreach (var field in attributeType.Fields.Where(x => x.IsReachable && x.IsPublic))
            {
                string           methodName = CreateGetMethodName(NameConverter.GetConvertedName(field), result);
                TypeReference    dfieldType = field.FieldType.GetReference(targetPackage, compiler.Module);
                MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dfieldType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                result.FieldToGetMethodMap.Add(field, method);
                @interface.Methods.Add(method);
            }

            // Add property mapping
            foreach (var property in attributeType.Properties.Where(x => x.IsReachable && (x.SetMethod != null) && (x.SetMethod.IsPublic) && x.SetMethod.IsReachable))
            {
                string           methodName = CreateGetMethodName(NameConverter.GetConvertedName(property), result);
                TypeReference    dpropType  = property.PropertyType.GetReference(targetPackage, compiler.Module);
                MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dpropType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                result.PropertyToGetMethodMap.Add(property, method);
                @interface.Methods.Add(method);
            }

            // Add ctor mapping
            var argIndex = 0;

            foreach (var ctor in attributeType.Methods.Where(x => (x.Name == ".ctor") && x.IsReachable))
            {
                // Add methods for the ctor arguments
                List <MethodDefinition> paramGetMethods = new List <MethodDefinition>();
                foreach (ParameterDefinition p in ctor.Parameters)
                {
                    string           methodName = CreateGetMethodName("c" + argIndex++, result);
                    TypeReference    dparamType = p.ParameterType.GetReference(targetPackage, compiler.Module);
                    MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dparamType));
                    method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                    @interface.Methods.Add(method);
                    paramGetMethods.Add(method);
                }

                // Add a builder method
                MethodDefinition buildMethod = CreateBuildMethod(sequencePoint, ctor, paramGetMethods, compiler, targetPackage, attributeClass, result);
                result.CtorMap.Add(ctor, new AttributeCtorMapping(buildMethod, paramGetMethods));
            }

            // Create default values annotation
            Annotation defAnnotation = CreateDefaultAnnotation(result);

            result.AnnotationInterfaceClass.Annotations.Add(defAnnotation);

            return(result);
        }
Example #5
0
        /// <summary>
        /// Create a method definition for the builder method that builds a custom attribute from an annotation.
        /// </summary>
        private static MethodDefinition CreateBuildMethod(
            ISourceLocation seqp,
            Mono.Cecil.MethodDefinition ctor,
            List <MethodDefinition> paramGetMethods,
            AssemblyCompiler compiler,
            DexTargetPackage targetPackage,
            ClassDefinition attributeClass,
            AttributeAnnotationInterface mapping)
        {
            // Create method definition
            string           name             = CreateBuildMethodName(attributeClass);
            TypeReference    attributeTypeRef = ctor.DeclaringType.GetReference(targetPackage, compiler.Module);
            MethodDefinition method           = new MethodDefinition(attributeClass, name, new Prototype(attributeTypeRef, new Parameter(mapping.AnnotationInterfaceClass, "ann")));

            method.AccessFlags = AccessFlags.Public | AccessFlags.Static | AccessFlags.Synthetic;
            attributeClass.Methods.Add(method);

            // Create method body
            MethodBody body          = new MethodBody(null);
            Register   annotationReg = body.AllocateRegister(RCategory.Argument, RType.Object);
            //body.Instructions.Add(seqp, RCode.Check_cast, mapping.AnnotationInterfaceClass, annotationReg);

            // Allocate attribute
            Register attributeReg = body.AllocateRegister(RCategory.Temp, RType.Object);

            body.Instructions.Add(seqp, RCode.New_instance, attributeClass, attributeReg);

            // Get ctor arguments
            List <Register> ctorArgRegs = new List <Register>();

            foreach (MethodDefinition p in paramGetMethods)
            {
                TypeReference paramType = p.Prototype.ReturnType;
                Register[]    valueRegs = CreateLoadValueSequence(seqp, body, paramType, annotationReg, p);
                ctorArgRegs.AddRange(valueRegs);
            }

            // Invoke ctor
            DexLib.MethodReference dctor = ctor.GetReference(targetPackage, compiler.Module);
            body.Instructions.Add(seqp, RCode.Invoke_direct, dctor, new[] { attributeReg }.Concat(ctorArgRegs).ToArray());

            // Get field values
            foreach (var fieldMap in mapping.FieldToGetMethodMap)
            {
                Mono.Cecil.FieldDefinition field  = fieldMap.Key;
                MethodDefinition           getter = fieldMap.Value;
                Register[]            valueRegs   = CreateLoadValueSequence(seqp, body, getter.Prototype.ReturnType, annotationReg, getter);
                DexLib.FieldReference dfield      = field.GetReference(targetPackage, compiler.Module);
                XModel.XTypeReference xFieldType  = XBuilder.AsTypeReference(compiler.Module, field.FieldType);
                body.Instructions.Add(seqp, xFieldType.IPut(), dfield, valueRegs[0], attributeReg);
            }

            // Get property values
            foreach (var propertyMap in mapping.PropertyToGetMethodMap)
            {
                PropertyDefinition       property   = propertyMap.Key;
                MethodDefinition         getter     = propertyMap.Value;
                Register[]               valueRegs  = CreateLoadValueSequence(seqp, body, getter.Prototype.ReturnType, annotationReg, getter);
                DexLib.MethodReference   dmethod    = property.SetMethod.GetReference(targetPackage, compiler.Module);
                XModel.XMethodDefinition xSetMethod = XBuilder.AsMethodDefinition(compiler.Module, property.SetMethod);
                body.Instructions.Add(seqp, xSetMethod.Invoke(xSetMethod, null), dmethod, new[] { attributeReg }.Concat(valueRegs).ToArray());
            }

            // Return attribute
            body.Instructions.Add(seqp, RCode.Return_object, attributeReg);

            // Register method body
            targetPackage.Record(new CompiledMethod()
            {
                DexMethod = method, RLBody = body
            });

            // Return method
            return(method);
        }
 /// <summary>
 /// Create code to load a value from an annotation interface.
 /// </summary>
 /// <returns>The register(s) holding the value</returns>
 private static Register[] CreateLoadValueSequence(
     ISourceLocation seqp,
     MethodBody body,
     TypeReference valueType,
     Register annotationReg,
     MethodDefinition getter)
 {
     if (valueType.IsWide())
     {
         Tuple<Register, Register> regs = body.AllocateWideRegister(RCategory.Temp);
         body.Instructions.Add(seqp, RCode.Invoke_interface, getter, annotationReg);
         body.Instructions.Add(seqp, RCode.Move_result_wide, regs.Item1);
         return new[] { regs.Item1, regs.Item2 };
     }
     if (valueType is PrimitiveType)
     {
         Register reg = body.AllocateRegister(RCategory.Temp, RType.Value);
         body.Instructions.Add(seqp, RCode.Invoke_interface, getter, annotationReg);
         body.Instructions.Add(seqp, RCode.Move_result, reg);
         return new[] { reg };
     }
     else
     {
         Register reg = body.AllocateRegister(RCategory.Temp, RType.Object);
         body.Instructions.Add(seqp, RCode.Invoke_interface, getter, annotationReg);
         body.Instructions.Add(seqp, RCode.Move_result_object, reg);
         return new[] { reg };
     }
 }
Example #7
0
 public Parameter(TypeReference type, string name) : this()
 {
     Type = type;
     Name = name;
 }