public override void Implement(ClassDefinition declaringClass, DexTargetPackage targetPackage) { if (xField == null) return; dfield.Type = xField.FieldType.GetReference(targetPackage); }
/// <summary> /// Create annotations for all included attributes /// </summary> public static void Create(AssemblyCompiler compiler, ICustomAttributeProvider attributeProvider, IAnnotationProvider annotationProvider, DexTargetPackage targetPackage, bool customAttributesOnly = false) { if (!attributeProvider.HasCustomAttributes) return; var annotations = new List<Annotation>(); foreach (var attr in attributeProvider.CustomAttributes) { var attributeType = attr.AttributeType.Resolve(); if (!attributeType.HasIgnoreAttribute()) { Create(compiler, attr, attributeType, annotations, targetPackage); } } if (annotations.Count > 0) { // Create 1 IAttributes annotation var attrsAnnotation = new Annotation { Visibility = AnnotationVisibility.Runtime }; attrsAnnotation.Type = compiler.GetDot42InternalType("IAttributes").GetClassReference(targetPackage); attrsAnnotation.Arguments.Add(new AnnotationArgument("Attributes", annotations.ToArray())); annotationProvider.Annotations.Add(attrsAnnotation); } if (!customAttributesOnly) { // Add annotations specified using AnnotationAttribute foreach (var attr in attributeProvider.CustomAttributes.Where(IsAnnotationAttribute)) { var annotationType = (TypeReference) attr.ConstructorArguments[0].Value; var annotationClass = annotationType.GetClassReference(targetPackage, compiler.Module); annotationProvider.Annotations.Add(new Annotation(annotationClass, AnnotationVisibility.Runtime)); } } }
/// <summary> /// Gets a Dex field reference for the given field reference. /// </summary> internal static FieldReference GetReference(this XFieldReference field, DexTargetPackage targetPackage) { if (field == null) throw new ArgumentNullException("field"); // Resolve the field to a field definition XFieldDefinition fieldDef; if (field.TryResolve(out fieldDef)) { string className; string memberName; string descriptor; if (fieldDef.TryGetDexImportNames(out memberName, out descriptor, out className)) { var prototype = PrototypeBuilder.ParseFieldType(descriptor); return new FieldReference(new ClassReference(className), memberName, prototype); } // Field is in the assembly itself // Use the mapping return targetPackage.NameConverter.GetField(fieldDef); } var javaField = field as XModel.Java.XBuilder.JavaFieldReference; if (javaField != null) { var prototype = PrototypeBuilder.ParseFieldType(javaField.JavaDecriptor); return new FieldReference(new ClassReference(javaField.JavaClassName), javaField.JavaName, prototype); } throw new ResolveException(string.Format("Field {0} not found", field.FullName)); }
/// <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); }
/// <summary> /// Create all annotations for this field /// </summary> internal virtual void CreateAnnotations(DexTargetPackage targetPackage) { // Build field annotations AttributeAnnotationInstanceBuilder.CreateAttributeAnnotations(compiler, field, dfield, targetPackage); dfield.AddGenericDefinitionAnnotationIfGeneric(xField.FieldType, compiler, targetPackage); }
/// <summary> /// Set the super class of the class definition. /// </summary> protected override void ImplementSuperClass(DexTargetPackage targetPackage) { // TODO: implement Generic Type Definition Classes and derive from System.Nullable`1-Marker. //Class.SuperClass = Compiler.GetDot42InternalType("System", "Nullable`1").GetClassReference(targetPackage); Class.SuperClass = FrameworkReferences.Object; _underlyingBuilder.Class.NullableMarkerClass = Class; }
/// <summary> /// Generate method code /// </summary> public virtual void GenerateCode(ClassDefinition declaringClass, DexTargetPackage targetPackage) { if (dmethod == null) { return; } // Create body (if any) if (!method.HasBody) { return; } cachedBody = compiler.MethodBodyCompilerCache.GetFromCache(dmethod, xMethod, compiler, targetPackage); if (cachedBody != null) { dmethod.Body = cachedBody.Body; // important to fix the owners source file as early as possible, // so it can't be changed later. Else we would have to recreate // all cached method bodies debug infos. dmethod.Owner.SetSourceFile(cachedBody.ClassSourceFile); return; } var source = new MethodSource(xMethod, method); ExpandSequencePoints(method.Body); bool generateSetNextInstructionCode = compiler.GenerateSetNextInstructionCode && method.DeclaringType.IsInDebugBuildAssembly(); DexMethodBodyCompiler.TranslateToRL(compiler, targetPackage, source, dmethod, generateSetNextInstructionCode, out compiledMethod); }
/// <summary> /// Create and add GenericInstance field. /// </summary> protected virtual void CreateGenericInstanceFields(DexTargetPackage targetPackage) { var accessFlags = AccessFlags.Synthetic; accessFlags |= Type.IsInterface ? AccessFlags.Public : AccessFlags.Protected; if (BuildGenericInstanceFieldAsArray) { var field = new FieldDefinition { Name = CreateUniqueFieldName("$g"), Type = FrameworkReferences.ClassArray, AccessFlags = accessFlags, Owner = Class }; Class.Fields.Add(field); Class.GenericInstanceFields.Add(field); } else { for (int i = 0; i < typeDef.GenericParameters.Count; ++i) { var field = new FieldDefinition { Name = CreateUniqueFieldName("$g", 1), Type = FrameworkReferences.Class, AccessFlags = accessFlags, Owner = Class }; Class.Fields.Add(field); Class.GenericInstanceFields.Add(field); } } }
/// <summary> /// Make minor fixes after the implementation phase. /// </summary> public void FixUp(DexTargetPackage targetPackage) { var iMethod = method.GetBaseInterfaceMethod(); Mono.Cecil.TypeReference inheritedReturnType = null; //var iMethod = method.Overrides.Select(x => x.Resolve()).Where(x => x != null).FirstOrDefault(x => x.DeclaringType.IsInterface); if (iMethod != null) { inheritedReturnType = iMethod.ReturnType; } var baseMethod = method.GetBaseMethod(); if (baseMethod != null) { inheritedReturnType = baseMethod.ReturnType; } if (inheritedReturnType != null) { var inheritedTargetReturnType = inheritedReturnType.GetReference(targetPackage, compiler.Module); if (inheritedTargetReturnType.Descriptor != dmethod.Prototype.ReturnType.Descriptor) { dmethod.Prototype.Unfreeze(); dmethod.Prototype.ReturnType = inheritedTargetReturnType; dmethod.Prototype.Freeze(); //// update the original method's return type as well, //// to make sure the code generation later knows what it is handling. //// TODO: this seems to be a hack. shouldn't this have been handled //// during the IL-conversion phase? xMethod.SetInheritedReturnType(inheritedReturnType); } } }
/// <summary> /// Create the current type as class definition. /// </summary> protected override void CreateClassDefinition(DexTargetPackage targetPackage, ClassDefinition parent, TypeDefinition parentType, XModel.XTypeDefinition parentXType) { base.CreateClassDefinition(targetPackage, parent, parentType, parentXType); Class.IsFinal = false; Class.IsAbstract = true; Class.IsSynthetic = true; }
/// <summary> /// Implement java.lang.Cloneable /// </summary> protected virtual void ImplementCloneable(DexTargetPackage targetPackage) { // Do not implement in some cases if ((classDef == null) || typeDef.IsInterface || typeDef.IsStatic()) { return; } // Do not implement, when there is a .NET base type (it is already implemented there) var baseType = (typeDef.BaseType != null) ? typeDef.BaseType.GetElementType().Resolve() : null; if ((baseType != null) && (baseType.GetDexOrJavaImportAttribute() == null)) { return; } // If explicitly implemented, do not implement again if (classDef.Interfaces.Any(x => x.Fullname == FrameworkReferences.Cloneable.Fullname)) { return; } // Add Cloneable implementation classDef.Interfaces.Add(FrameworkReferences.Cloneable); }
/// <summary> /// Create the current type as class definition. /// </summary> protected override void CreateClassDefinition(DexTargetPackage targetPackage, ClassDefinition parent, TypeDefinition parentType, XModel.XTypeDefinition parentXType) { base.CreateClassDefinition(targetPackage, parent, parentType, parentXType); Class.IsFinal = true; //Class.IsAbstract = true;// Android 6.x verifier does not allow 'final abstract' a.k.a. static classes. Class.IsSynthetic = true; }
/// <summary> /// Add the given method to its declaring class. /// </summary> protected override void AddMethodToDeclaringClass(ClassDefinition declaringClass, DexLib.MethodDefinition dmethod, DexTargetPackage targetPackage) { var generatedCodeClass = targetPackage.GetOrCreateGeneratedCodeClass(); UpdateName(dmethod, generatedCodeClass); dmethod.Owner = generatedCodeClass; generatedCodeClass.Methods.Add(dmethod); }
/// <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); }
/// <summary> /// Generate code for all methods. /// </summary> public override void GenerateCode(DexTargetPackage targetPackage) { base.GenerateCode(targetPackage); // Compile synthetic methods XType.Methods.OfType <XSyntheticMethodDefinition>().ForEach(x => x.Compile(Compiler, targetPackage)); }
/// <summary> /// Gets a class reference for the given type reference. /// </summary> internal static ClassReference GetClassReference(this JvmClassLib.TypeReference type, XTypeUsageFlags usageFlags, DexTargetPackage targetPackage, XModule module) { var classRef = type.GetReference(usageFlags, targetPackage, module) as ClassReference; if (classRef == null) throw new ArgumentException(string.Format("type {0} is not a class reference", type.ClassName)); return classRef; }
/// <summary> /// Operands refering to types, methods or fields need to be fixed, as they might have /// gotten another name in the target package. he same applies for catch references. /// </summary> private void FixReferences(MethodBody body, AssemblyCompiler compiler, DexTargetPackage targetPackage) { // fix operands foreach (var ins in body.Instructions) { var fieldRef = ins.Operand as FieldReference; var methodRef = ins.Operand as MethodReference; var classRef = ins.Operand as ClassReference; if (classRef != null) { ins.Operand = ConvertClassReference(classRef, compiler, targetPackage); } else if (fieldRef != null) { ins.Operand = ConvertFieldReference(fieldRef, compiler, targetPackage); } else if (methodRef != null) { ins.Operand = ConvertMethodReference(methodRef, compiler, targetPackage); } } // fix catch clauses foreach (var @catch in body.Exceptions.SelectMany(e => e.Catches)) { if (@catch.Type != null) { @catch.Type = ConvertTypeReference(@catch.Type, compiler, targetPackage); } } }
/// <summary> /// Create the current type as class definition. /// </summary> protected override void CreateClassDefinition(DexTargetPackage targetPackage, ClassDefinition parent, TypeDefinition parentType, XModel.XTypeDefinition parentXType) { base.CreateClassDefinition(targetPackage, parent, parentType, parentXType); Class.IsFinal = true; Class.IsAbstract = true; Class.IsSynthetic = true; }
/// <summary> /// Create all annotations for this class and it's members /// </summary> public virtual void CreateAnnotations(DexTargetPackage targetPackage) { // Build class annotations if (Class != null) { // Custom attributes AttributeAnnotationInstanceBuilder.CreateAttributeAnnotations(compiler, Type, Class, targetPackage); // Properties if ((methodBuilders != null) && compiler.AddPropertyAnnotations()) { AddPropertiesAnnotation(targetPackage); } AddDefaultAnnotations(targetPackage); } // Build nested class annotation nestedBuilders.ForEach(x => x.CreateAnnotations(targetPackage)); // Build field annotations if (fieldBuilders != null) { fieldBuilders.ForEach(x => x.CreateAnnotations(targetPackage)); } // Build method annotations if (methodBuilders != null) { methodBuilders.ForEach(x => x.CreateAnnotations(targetPackage)); } }
/// <summary> /// Implement the class now that all classes have been created /// </summary> protected override void CreateMembers(DexTargetPackage targetPackage) { base.CreateMembers(targetPackage); // Build default ctor XTypeSystem typeSystem = Compiler.Module.TypeSystem; XSyntheticMethodDefinition ctor = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Constructor, "<init>", typeSystem.Void); ctor.Body = CreateCtorBody(); Class.Methods.Add(ctor.GetDexMethod(Class, targetPackage)); // Build Invoke method. XMethodDefinition sourceMethod = XType.Methods.Single(x => x.EqualsName("Invoke")); Prototype prototype = PrototypeBuilder.BuildPrototype(Compiler, targetPackage, Class, sourceMethod); MethodDefinition method = new MethodDefinition(Class, sourceMethod.Name, prototype) { AccessFlags = AccessFlags.Public | AccessFlags.Abstract }; Class.Methods.Add(method); // Find xSource method targetPackage.NameConverter.Record(sourceMethod, method); // If void() delegate, implement java.lang.Runnable if (sourceMethod.ReturnType.IsVoid() && (sourceMethod.Parameters.Count == 0)) { // Implement interface Class.Interfaces.Add(FrameworkReferences.Runnable); // Build run method var run = new MethodDefinition(Class, "run", new Prototype(PrimitiveType.Void)) { AccessFlags = AccessFlags.Public | AccessFlags.Final }; Class.Methods.Add(run); run.Body = new DexLib.Instructions.MethodBody(run, 1) { IncomingArguments = 1, OutgoingArguments = 1 }; var insList = run.Body.Instructions; var rThis = run.Body.Registers[0]; insList.Add(new DexLib.Instructions.Instruction(OpCodes.Invoke_virtual, method, rThis)); insList.Add(new DexLib.Instructions.Instruction(OpCodes.Return_void)); } }
public override void GenerateCode(DexTargetPackage targetPackage, bool stopAtFirstError) { if (!IsDot42InternalApplication()) { // replace call to base class constructor before generating code foreach (var ctor in Type.Methods.Where(m => m.IsConstructor && m.HasBody && m.IsReachable)) { foreach (var ins in ctor.Body.Instructions) { var methodRef = ins.Operand as MethodReference; if (methodRef == null) { continue; } var method = methodRef.Resolve(); if (!method.IsConstructor || method.DeclaringType.FullName != "Android.App.Application") { continue; } // redirect methodRef.DeclaringType = Dot42InternalApplicationBuilder.Type; } } } base.GenerateCode(targetPackage, stopAtFirstError); }
/// <summary> /// Create the nested classes for this type. /// </summary> protected void CreateNestedClasses(DexTargetPackage targetPackage, ClassDefinition parent) { nestedBuilders = CreateNestedClassBuilders(context, targetPackage, parent) .OrderBy(x => x.SortPriority) .ToList(); nestedBuilders.ForEach(x => x.Create(targetPackage, classDef, typeDef, XType)); }
/// <summary> /// Add the given field to its declaring class. /// </summary> protected override void AddFieldToDeclaringClass(ClassDefinition declaringClass, DexLib.FieldDefinition dfield, DexTargetPackage targetPackage) { var generatedCodeClass = targetPackage.GetOrCreateGeneratedCodeClass(); UpdateName(dfield, generatedCodeClass); dfield.Owner = generatedCodeClass; generatedCodeClass.Fields.Add(dfield); }
/// <summary> /// Implement the class now that all classes have been created /// </summary> public void Implement(DexTargetPackage targetPackage) { ImplementSuperClass(targetPackage); ImplementInterfaces(targetPackage); ImplementCloneable(targetPackage); ImplementInnerClasses(targetPackage); CreateMembers(targetPackage); }
protected override void ImplementInterfaces(DexTargetPackage targetPackage) { base.ImplementInterfaces(targetPackage); var marker = Compiler.GetDot42InternalType(InternalConstants.NullableMarker); Class.Interfaces.Add(marker.GetClassReference(targetPackage)); }
/// <summary> /// Set the super class of the class definition. /// </summary> protected override void ImplementSuperClass(DexTargetPackage targetPackage) { var baseType = Type.BaseType; if (baseType != null) { Class.SuperClass = (ClassReference)baseType.GetReference(targetPackage, Compiler.Module); } }
/// <summary> /// Gets a Dex method reference for the given type reference. /// </summary> internal static MethodReference GetReference(this Mono.Cecil.MethodReference method, DexTargetPackage targetPackage, XModule module) { if (method == null) throw new ArgumentNullException("method"); var xMethod = XBuilder.AsMethodReference(module, method); return xMethod.GetReference(targetPackage); }
/// <summary> /// FixUp all methods. /// </summary> protected virtual void FixUpMethods(DexTargetPackage targetPackage) { // FixUp methods if (methodBuilders != null) { methodBuilders.ForEach(x => x.FixUp(targetPackage)); } }
/// <summary> /// Gets a class reference for the given type reference. /// </summary> internal static TypeReference GetReference(this Mono.Cecil.TypeReference type, DexTargetPackage targetPackage, XModule module) { if (type == null) throw new ArgumentNullException("type"); var xType = XBuilder.AsTypeReference(module, type); return xType.GetReference(targetPackage); }
/// <summary> /// Gets a Dex field reference for the given field reference. /// </summary> internal static FieldReference GetReference(this Mono.Cecil.FieldReference field, DexTargetPackage targetPackage, XModule module) { if (field == null) throw new ArgumentNullException("field"); var xField = XBuilder.AsFieldReference(module, field); return xField.GetReference(targetPackage); }
/// <summary> /// Gets a class reference for the given type reference. /// </summary> internal static TypeReference GetReference(this JvmClassLib.TypeReference type, XTypeUsageFlags usageFlags, DexTargetPackage targetPackage, XModule module) { if (type == null) throw new ArgumentNullException("type"); var xType = XBuilder.AsTypeReference(module, type, usageFlags); return xType.GetReference(targetPackage); }
public static void CreateAssemblyTypes(AssemblyCompiler compiler, DexTargetPackage targetPackage, IEnumerable <TypeDefinition> reachableTypes) { var xAssemblyTypes = compiler.GetDot42InternalType("AssemblyTypes"); var assemblyTypes = (ClassDefinition)xAssemblyTypes.GetClassReference(targetPackage); var entryAssembly = assemblyTypes.Fields.First(f => f.Name == "EntryAssembly"); var iAssemblyTypes = compiler.GetDot42InternalType("IAssemblyTypes").GetClassReference(targetPackage); entryAssembly.Value = compiler.Assemblies.First().Name.Name; List <object> values = new List <object>(); string prevAssemblyName = null; foreach (var type in reachableTypes.OrderBy(t => t.Module.Assembly.Name.Name) .ThenBy(t => t.Namespace) .ThenBy(t => t.Name)) { var assemblyName = type.module.Assembly.Name.Name; if (assemblyName == "dot42") { // group all android types into virtual "android" assembly, // so that MvvmCross can find all view-types. // -- is this a hack? if (type.Namespace.StartsWith("Android")) { assemblyName = "android"; } else // ignore other types, these will get the "default" assembly. { continue; } } if (prevAssemblyName != assemblyName) { values.Add("!" + assemblyName); // we need some identification of assemblies. prevAssemblyName = assemblyName; } // TODO: With compilationmode=all reachable types contains <Module> // this should be excluded earlier. if (type.FullName == "<Module>") { continue; } var tRef = type.GetReference(targetPackage, compiler.Module) as ClassReference; if (tRef != null) { values.Add(tRef.Fullname); } } var anno = new Annotation(iAssemblyTypes, AnnotationVisibility.Runtime, new AnnotationArgument("AssemblyTypeList", values.ToArray())); ((IAnnotationProvider)assemblyTypes).Annotations.Add(anno); }
public override void Implement(ClassDefinition declaringClass, DexTargetPackage targetPackage) { if (xField == null) { return; } dfield.Type = xField.FieldType.GetReference(targetPackage); }
/// <summary> /// Create the current type as class definition. /// </summary> protected override void CreateClassDefinition(DexTargetPackage targetPackage, ClassDefinition parent, TypeDefinition parentType, XTypeDefinition parentXType) { base.CreateClassDefinition(targetPackage, parent, parentType, parentXType); Class.AccessFlags &= ~AccessFlags.Final; Class.IsAbstract = true; //Class.IsInterface = true; // Record in compiler Compiler.Record(new DelegateType(Compiler, XType, Class, targetPackage.DexFile, targetPackage.NameConverter)); }
/// <summary> /// Initializes a mapping. /// </summary> public static AttributeAnnotationMapping CreateMapping( ISourceLocation sequencePoint, AssemblyCompiler compiler, DexTargetPackage targetPackage, TypeDefinition attributeType, ClassDefinition attributeClass) { return(new AttributeAnnotationMapping(attributeType, attributeClass)); }
/// <summary> /// Initializes a mapping. /// </summary> public static AttributeAnnotationMapping CreateMapping( ISourceLocation sequencePoint, AssemblyCompiler compiler, DexTargetPackage targetPackage, TypeDefinition attributeType, ClassDefinition attributeClass) { return new AttributeAnnotationMapping(attributeType, attributeClass); }
/// <summary> /// Create a IGnericDefinition annotation and attaches it to the given provider. /// TODO: this might better belong somewhere else. /// </summary> public static void AddGenericDefinitionAnnotationIfGeneric(this IAnnotationProvider provider, XTypeReference xtype, AssemblyCompiler compiler, DexTargetPackage targetPackage, bool forceTypeDefinition=false) { if (!xtype.IsGenericInstance && !xtype.IsGenericParameter) return; Annotation annotation = GetGenericDefinitionAnnotationForType(xtype, forceTypeDefinition, compiler, targetPackage); if(annotation != null) provider.Annotations.Add(annotation); }
/// <summary> /// Compile RL into the Dex method body. /// </summary> private void CompileToDex(DexTargetPackage targetPackage, bool generateDebugInfo, MapFile mapFile) { var dmethod = DexMethod; if (dmethod == null) { throw new ArgumentException("No DexMethod set"); } if ((dmethod.IsAbstract) || (dmethod.IsNative)) { return; } var rlBody = RLBody; if (rlBody == null && dmethod.Body != null) // already satisfied from the cache? { return; } if (rlBody == null) { throw new ArgumentException(string.Format("internal compiler error: No RL body set on method '{2}'.'{3}' => '{0}'.'{1}'", dmethod.Owner.Name, dmethod.Name, method == null ? null : method.DeclaringType.FullName, method == null ? null : method.Name)); } // Ensure RL is optimized OptimizeRL(targetPackage.DexFile); // Compile to Dex var dbody = new Dot42.DexLib.Instructions.MethodBody(dmethod, 0); var dexCompiler = new DexCompiler(rlBody, dbody, InvocationFrame); regMapper = dexCompiler.Compile(); // Optimize code //dbody.UpdateInstructionOffsets(); DexOptimizer.DexOptimizer.Optimize(dbody); // Ensure correct offsets dbody.UpdateInstructionOffsets(); dmethod.Body = dbody; if (generateDebugInfo || (mapFile != null)) { // Add debug info var debugInfoBuilder = new DebugInfoBuilder(this); if (generateDebugInfo) { debugInfoBuilder.CreateDebugInfo(dbody, regMapper, targetPackage); } if (mapFile != null && dmethod.MapFileId != 0) { debugInfoBuilder.AddDocumentMapping(mapFile); } } }
/// <summary> /// Create an annotation for the given attribute /// </summary> private static void Create(AssemblyCompiler compiler, CustomAttribute attribute, TypeDefinition attributeType, List <Annotation> annotationList, DexTargetPackage targetPackage) { // Gets the mapping for the type of attribute var mapping = compiler.GetAttributeAnnotationType(attributeType); var ctorMap = mapping.CtorMap[attribute.Constructor.Resolve()]; // Create annotation var annotation = new Annotation { Visibility = AnnotationVisibility.Runtime }; annotation.Type = mapping.AnnotationInterfaceClass; // Add ctor arguments var argIndex = 0; foreach (var arg in attribute.ConstructorArguments) { var name = ctorMap.ArgumentGetters[argIndex].Name; annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Type, arg.Value, targetPackage, compiler.Module)); argIndex++; } // Add field values foreach (var arg in attribute.Fields) { var entry = mapping.FieldToGetMethodMap.First(x => x.Key.Name == arg.Name); var name = entry.Value.Name; annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Argument.Type, arg.Argument.Value, targetPackage, compiler.Module)); } // Add property values foreach (var arg in attribute.Properties) { if (mapping.PropertyToGetMethodMap.Keys.Any(x => x.Name == arg.Name)) { var entry = mapping.PropertyToGetMethodMap.First(x => x.Key.Name == arg.Name); var name = entry.Value.Name; annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Argument.Type, arg.Argument.Value, targetPackage, compiler.Module)); } } // Create attribute annotation var attrAnnotation = new Annotation { Visibility = AnnotationVisibility.Runtime }; attrAnnotation.Type = compiler.GetDot42InternalType("IAttribute").GetClassReference(targetPackage); attrAnnotation.Arguments.Add(new AnnotationArgument("AttributeBuilder", ctorMap.Builder)); attrAnnotation.Arguments.Add(new AnnotationArgument("AttributeType", attributeType.GetReference(targetPackage, compiler.Module))); attrAnnotation.Arguments.Add(new AnnotationArgument("Annotation", annotation)); // Add annotation annotationList.Add(attrAnnotation); }
public override void CreateAnnotations(DexTargetPackage targetPackage) { base.CreateAnnotations(targetPackage); if (Class == null) return; bool isBaseTypeGeneric = XType.BaseType != null && (XType.BaseType.IsGenericInstance || XType.BaseType.IsGenericParameter); bool containsGenericInterfaces = XType.Interfaces.Any(i => i.IsGenericInstance || i.IsGenericParameter); bool needsFieldAnnotation = !Class.IsSynthetic && Class.Fields.Count(p => !p.IsSynthetic && !p.IsStatic) > 1; bool needsAnnotation = Class.GenericInstanceFields.Count > 0 || XType.GenericParameters.Count > 0 || isBaseTypeGeneric || containsGenericInterfaces || needsFieldAnnotation; if (!needsAnnotation) return; var annType = Compiler.GetDot42InternalType(InternalConstants.TypeReflectionInfoAnnotation).GetClassReference(targetPackage); var annotation = new Annotation(annType, AnnotationVisibility.Runtime); if (Class.GenericInstanceFields.Count > 0) { annotation.Arguments.Add(new AnnotationArgument(InternalConstants.TypeReflectionInfoGenericArgumentsFields, Class.GenericInstanceFields.Select(f=>f.Name).ToArray())); } if (XType.GenericParameters.Count > 0) annotation.Arguments.Add(new AnnotationArgument(InternalConstants.TypeReflectionInfoGenericArgumentCountField, XType.GenericParameters.Count)); List<Annotation> definitions= new List<Annotation>(); if (isBaseTypeGeneric) definitions.Add(AssemblyCompilerExtensions.GetGenericDefinitionAnnotationForType( XType.BaseType, true, Compiler, targetPackage)); foreach (var intf in XType.Interfaces) { if(!intf.IsGenericInstance && !intf.IsGenericParameter) continue; definitions.Add(AssemblyCompilerExtensions.GetGenericDefinitionAnnotationForType( intf, true, Compiler, targetPackage)); } if(definitions.Count > 0) annotation.Arguments.Add(new AnnotationArgument(InternalConstants.TypeReflectionInfoGenericDefinitionsField, definitions.ToArray())); if (needsFieldAnnotation) { annotation.Arguments.Add(new AnnotationArgument(InternalConstants.TypeReflectionInfoFieldsField, Class.Fields.Where(p=>!p.IsSynthetic && !p.IsStatic).Select(p=>p.Name).ToArray())); } Class.Annotations.Add(annotation); }
protected override void ImplementSuperClass(DexTargetPackage targetPackage) { if (!IsDot42InternalApplication()) { var dot42Internal = Compiler.GetDot42InternalType("Application"); Class.SuperClass = dot42Internal.GetClassReference(targetPackage); } else base.ImplementSuperClass(targetPackage); }
/// <summary> /// Create code to unbox the given source array of boxed type elements into an array of primitive elements. /// </summary> public static RLRange UnboxGenericArray(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec source, RegisterSpec boxedArray, XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler) { var internalBoxingType = compiler.GetDot42InternalType("Boxing").Resolve(); var ilUnboxMethod = internalBoxingType.Methods.First(x => x.EqualsName("UnboxTo") && (x.Parameters.Count == 2) && (x.Parameters[1].ParameterType.IsSame(type, true))); var unboxMethod = ilUnboxMethod.GetReference(targetPackage); var call = builder.Add(sequencePoint, RCode.Invoke_static, unboxMethod, boxedArray, source); return(new RLRange(call, null)); }
/// <summary> /// Implement the class now that all classes have been created /// </summary> public void Implement(DexTargetPackage targetPackage) { var target = targetPackage.DexFile; var nameConverter = targetPackage.NameConverter; ImplementSuperClass(target, nameConverter); ImplementInterfaces(target, nameConverter); ImplementInnerClasses(targetPackage); CreateMembers(targetPackage); }
/// <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); }
/// <summary> /// Create all annotations for this field /// </summary> internal virtual void CreateAnnotations(DexTargetPackage targetPackage) { if (dfield == null) { return; } // Add annotations from java AnnotationBuilder.BuildAnnotations(field, dfield, targetPackage, compiler.Module); }
/// <summary> /// Implement the class now that all classes have been created /// </summary> public void Implement(ClassDefinition declaringClass, DexTargetPackage targetPackage) { if (dfield == null) { return; } SetFieldType(dfield, field, targetPackage); SetFieldValue(dfield, field); }
/// <summary> /// Generate code for all methods. /// </summary> public void GenerateCode(DexTargetPackage targetPackage) { if (nestedBuilders != null) { nestedBuilders.ForEach(x => x.GenerateCode(targetPackage)); } if (methodBuilders != null) { methodBuilders.ForEach(x => x.GenerateCode(classDef, targetPackage)); } }
public override void Create(ClassDefinition declaringClass, XTypeDefinition declaringType, DexTargetPackage targetPackage) { if (_baseFieldBuilder.dfield == null) return; // can't create udater for static fields. if (field.IsStatic) return; var updaterType = GetAtomicFieldUpdaterType(field.FieldType); if (updaterType == null) return; var fullUpdateTypeName = "Java.Util.Concurrent.Atomic." + updaterType; // create matching xField. Note: this seems to be a hack. what to do? var objType = new ObjectTypeReference(fullUpdateTypeName, new TypeArgument[0]); var javaTypeReference = new XBuilder.JavaTypeReference(Compiler.Module, objType, objType.ClassName); var basexField = _baseFieldBuilder.xField; var basedField = _baseFieldBuilder.dfield; var fieldName = basedField.Name + NameConstants.Atomic.FieldUpdaterPostfix; var xflags = XSyntheticFieldFlags.Static | XSyntheticFieldFlags.ReadOnly; if (basedField.IsProtected) xflags |= XSyntheticFieldFlags.Protected; if (basedField.IsPrivate) xflags |= XSyntheticFieldFlags.Private; var xAtomicField = XSyntheticFieldDefinition.Create(basexField.DeclaringType, xflags, fieldName, javaTypeReference); xField = xAtomicField; // create dfield. dfield = new DexLib.FieldDefinition { Name = fieldName, IsStatic = true, IsFinal = true, IsSynthetic = true, // same access as the original field. IsPublic = basedField.IsPublic, IsPrivate = basedField.IsPrivate, IsProtected = basedField.IsProtected, }; AddFieldToDeclaringClass(declaringClass, dfield, targetPackage); targetPackage.NameConverter.Record(xField, dfield); }
/// <summary> /// Implemented all fields and methods. /// </summary> protected override void CreateMembers(DexTargetPackage targetPackage) { // Create normal members base.CreateMembers(targetPackage); if(!Type.IsAbstract) { // Create annotation interface and attribute build methods mapping = AttributeAnnotationInstanceBuilder.CreateMapping(null, Compiler, targetPackage, Type, Class); Compiler.Record(Type, mapping); } }
/// <summary> /// Set the super class of the class definition. /// </summary> protected override void ImplementSuperClass(DexTargetPackage targetPackage) { if (nullableBaseClassBuilder != null) { // Super class == nullable base class Class.SuperClass = nullableBaseClassBuilder.Class; } else { // Super class is Dot42.Internal.Enum Class.SuperClass = Compiler.GetDot42InternalType("Enum").GetClassReference(targetPackage); } }
/// <summary> /// Create a prototype for the given methods signature /// </summary> internal static Prototype BuildPrototype(AssemblyCompiler compiler, DexTargetPackage targetPackage, ClassDefinition declaringClass, MethodDefinition method) { var result = new Prototype(); var module = compiler.Module; result.ReturnType = method.ReturnType.GetReference(XTypeUsageFlags.ReturnType, targetPackage, module); var paramIndex = 0; foreach (var p in method.Parameters) { var dparameter = new Parameter(p.GetReference(XTypeUsageFlags.ParameterType, targetPackage, module), "p" + paramIndex++); result.Parameters.Add(dparameter); } return result; }
/// <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); } } } }
/// <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); }
protected override void CreateClassDefinition(DexTargetPackage targetPackage, ClassDefinition parent, TypeDefinition parentType, XTypeDefinition parentXType) { base.CreateClassDefinition(targetPackage, parent, parentType, parentXType); if (IsDot42InternalApplication()) { // FixUp Visiblility. Class.IsPublic = true; Class.IsProtected = false; Class.IsPrivate = false; } }
/// <summary> /// Create an annotation for the given attribute /// </summary> private static void Create(AssemblyCompiler compiler, CustomAttribute attribute, TypeDefinition attributeType, List<Annotation> annotationList, DexTargetPackage targetPackage) { // Gets the mapping for the type of attribute var mapping = compiler.GetAttributeAnnotationType(attributeType); var ctorMap = mapping.CtorMap[attribute.Constructor.Resolve()]; // Create annotation var annotation = new Annotation {Visibility = AnnotationVisibility.Runtime}; annotation.Type = mapping.AnnotationInterfaceClass; // Add ctor arguments var argIndex = 0; foreach (var arg in attribute.ConstructorArguments) { var name = ctorMap.ArgumentGetters[argIndex].Name; annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Type, arg.Value, targetPackage, compiler.Module)); argIndex++; } // Add field values foreach (var arg in attribute.Fields) { var entry = mapping.FieldToGetMethodMap.First(x => x.Key.Name == arg.Name); var name = entry.Value.Name; annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Argument.Type, arg.Argument.Value, targetPackage, compiler.Module)); } // Add property values foreach (var arg in attribute.Properties) { if (mapping.PropertyToGetMethodMap.Keys.Any(x => x.Name == arg.Name)) { var entry = mapping.PropertyToGetMethodMap.First(x => x.Key.Name == arg.Name); var name = entry.Value.Name; annotation.Arguments.Add(CreateAnnotationArgument(name, arg.Argument.Type, arg.Argument.Value, targetPackage, compiler.Module)); } } // Create attribute annotation var attrAnnotation = new Annotation { Visibility = AnnotationVisibility.Runtime }; attrAnnotation.Type = compiler.GetDot42InternalType("IAttribute").GetClassReference(targetPackage); attrAnnotation.Arguments.Add(new AnnotationArgument("AttributeBuilder", ctorMap.Builder)); attrAnnotation.Arguments.Add(new AnnotationArgument("AttributeType", attributeType.GetReference(targetPackage, compiler.Module))); attrAnnotation.Arguments.Add(new AnnotationArgument("Annotation", annotation)); // Add annotation annotationList.Add(attrAnnotation); }
/// <summary> /// Implement the class now that all classes have been created /// </summary> protected override void CreateMembers(DexTargetPackage targetPackage) { // Build ctors foreach (var baseCtor in GetBaseClassCtors()) { // Build ctor var prototype = PrototypeBuilder.BuildPrototype(Compiler, targetPackage, null, baseCtor); var ctor = new MethodDefinition(Class, "<init>", prototype); ctor.AccessFlags = AccessFlags.Public | AccessFlags.Constructor; Class.Methods.Add(ctor); // Create ctor body var ctorBody = CreateCtorBody(prototype); targetPackage.Record(new CompiledMethod { DexMethod = ctor, RLBody = ctorBody }); } }
public static void CreateAssemblyTypes(AssemblyCompiler compiler, DexTargetPackage targetPackage, IEnumerable<TypeDefinition> reachableTypes) { var xAssemblyTypes = compiler.GetDot42InternalType("AssemblyTypes"); var assemblyTypes = (ClassDefinition)xAssemblyTypes.GetClassReference(targetPackage); var entryAssembly = assemblyTypes.Fields.First(f => f.Name == "EntryAssembly"); var iAssemblyTypes = compiler.GetDot42InternalType("IAssemblyTypes").GetClassReference(targetPackage); entryAssembly.Value = compiler.Assemblies.First().Name.Name; List<object> values = new List<object>(); string prevAssemblyName = null; foreach (var type in reachableTypes.OrderBy(t => t.Module.Assembly.Name.Name) .ThenBy(t => t.Namespace) .ThenBy(t => t.Name)) { var assemblyName = type.module.Assembly.Name.Name; if (assemblyName == "dot42") { // group all android types into virtual "android" assembly, // so that MvvmCross can find all view-types. // -- is this a hack? if (type.Namespace.StartsWith("Android")) assemblyName = "android"; else // ignore other types, these will get the "default" assembly. continue; } if (prevAssemblyName != assemblyName) { values.Add("!" + assemblyName); // we need some identification of assemblies. prevAssemblyName = assemblyName; } // TODO: With compilationmode=all reachable types contains <Module> // this should be excluded earlier. if (type.FullName == "<Module>") continue; var tRef = type.GetReference(targetPackage, compiler.Module) as ClassReference; if(tRef != null) values.Add(tRef.Fullname); } var anno = new Annotation(iAssemblyTypes, AnnotationVisibility.Runtime, new AnnotationArgument("AssemblyTypeList", values.ToArray())); ((IAnnotationProvider)assemblyTypes).Annotations.Add(anno); }