/// <summary> /// Create the body of the valueOf(string) method. /// </summary> private AstBlock CreateValueOfBody(XSyntheticMethodDefinition method, XTypeSystem typeSystem) { var fields = XType.Fields.Where(x => x.IsStatic && !(x is XSyntheticFieldDefinition)).ToList(); var ast = AstBlock.Create <AstExpression>(); // Find name foreach (var field in fields) { var notEqualLabel = new AstLabel(AstNode.NoSource, "not_equal_to" + field.Name); var equalsExpr = new AstExpression(AstNode.NoSource, AstCode.Call, FrameworkReferences.StringEquals(typeSystem), new AstExpression(AstNode.NoSource, AstCode.Ldstr, field.Name), new AstExpression(AstNode.NoSource, AstCode.Ldloc, method.AstParameters[0])); // If !equals(name, field.name) goto notEqualLabel ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Brfalse, notEqualLabel, equalsExpr)); // Return field object ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Ret, null, new AstExpression(AstNode.NoSource, AstCode.Ldsfld, field))); // notEqualLabel: ast.Body.Add(notEqualLabel); } // Return null ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Ret, null, new AstExpression(AstNode.NoSource, AstCode.Ldnull, null))); return(ast); }
/// <summary> /// Create the body of the unbox(object) method. /// </summary> private AstBlock CreateUnboxBody(XSyntheticMethodDefinition method, bool isWide, AssemblyCompiler compiler) { // Prepare var loc = AstNode.NoSource; Func <AstExpression> ldValue = () => new AstExpression(loc, AstCode.Ldloc, method.AstParameters[0]); var afterMyEnum = new AstLabel(loc, "_afterMyEnum"); // value instanceof MyEnumType? var ifNotInstanceOfMyEnum = new AstExpression(loc, AstCode.Brfalse, afterMyEnum, new AstExpression(loc, AstCode.SimpleInstanceOf, XType, ldValue())); var returnMyEnum = new AstExpression(loc, AstCode.Ret, null, new AstExpression(loc, AstCode.SimpleCastclass, XType, ldValue())); // boxToMyEnum(UnboxInteger(value)) var boxingType = compiler.GetDot42InternalType("Boxing").Resolve(); var unboxNumericMethod = boxingType.Methods.First(x => x.Name == (isWide ? "UnboxLong" : "UnboxInteger")); var unboxToNumeric = new AstExpression(loc, AstCode.Call, unboxNumericMethod, ldValue()); var numericToMyEnum = new AstExpression(loc, isWide ? AstCode.Long_to_enum : AstCode.Int_to_enum, XType, unboxToNumeric).SetType(XType); var returnX = new AstExpression(loc, AstCode.Ret, null, numericToMyEnum); var ast = new AstBlock(loc, new AstNode[] { ifNotInstanceOfMyEnum, returnMyEnum, afterMyEnum, returnX }); return(ast); }
/// <summary> /// Create the body of the Create(int|long) method. /// </summary> private AstBlock CreateCreateBody(XSyntheticMethodDefinition method, XMethodReference ctor) { return(AstBlock.CreateOptimizedForTarget( new AstExpression(AstNode.NoSource, AstCode.Ret, null, new AstExpression(AstNode.NoSource, AstCode.Newobj, ctor, new AstExpression(AstNode.NoSource, AstCode.Ldstr, "?"), new AstExpression(AstNode.NoSource, AstCode.Ldc_I4, -1), new AstExpression(AstNode.NoSource, AstCode.Ldloc, method.AstParameters[0]))))); }
/// <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>", null, 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, MapFileId = Compiler.GetNextMapFileId() }; 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)); } }
/// <summary> /// Implement the class now that all classes have been created /// </summary> protected override void CreateMembers(DexTargetPackage targetPackage) { // Build value ctor var module = Compiler.Module; var isWide = Type.GetEnumUnderlyingType().Resolve().IsWide(); var enumType = Compiler.GetDot42InternalType("Enum"); var valueType = isWide ? module.TypeSystem.Long : module.TypeSystem.Int; // Build default ctor defaultCtor = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Constructor, "<init>", module.TypeSystem.Void); Class.Methods.Add(defaultCtor.GetDexMethod(Class, targetPackage)); // Build Create method create = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Protected, "Create", enumType, XParameter.Create("value", valueType)); Class.Methods.Add(create.GetDexMethod(Class, targetPackage)); }
/// <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); }
/// <summary> /// Create the body of the ctor. /// </summary> private AstBlock CreateCtorBody(XSyntheticMethodDefinition method) { // Call base ctor var nameParam = method.AstParameters[0]; var ordinalParam = method.AstParameters[1]; var valueParam = method.AstParameters[2]; var valueField = XType.Fields.First(x => !x.IsStatic && x.Name == NameConstants.Enum.ValueFieldName); return(AstBlock.CreateOptimizedForTarget( // Call base new AstExpression(AstNode.NoSource, AstCode.CallBaseCtor, 2, new AstExpression(AstNode.NoSource, AstCode.Ldthis, null), new AstExpression(AstNode.NoSource, AstCode.Ldloc, nameParam), new AstExpression(AstNode.NoSource, AstCode.Ldloc, ordinalParam)), // Initialize value__ new AstExpression(AstNode.NoSource, AstCode.Stfld, valueField, new AstExpression(AstNode.NoSource, AstCode.Ldthis, null), new AstExpression(AstNode.NoSource, AstCode.Ldloc, valueParam)), // Return void new AstExpression(AstNode.NoSource, AstCode.Ret, null))); }
/// <summary> /// Create the body of the Create(int|long) method. /// </summary> private AstBlock CreateCreateBody(XSyntheticMethodDefinition method, XMethodReference ctor) { return AstBlock.CreateOptimizedForTarget( new AstExpression(AstNode.NoSource, AstCode.Ret, null, new AstExpression(AstNode.NoSource, AstCode.Newobj, ctor, new AstExpression(AstNode.NoSource, AstCode.Ldstr, "?"), new AstExpression(AstNode.NoSource, AstCode.Ldc_I4, -1), new AstExpression(AstNode.NoSource, AstCode.Ldloc, method.AstParameters[0])))); }
/// <summary> /// Add the given generated method to this type. /// </summary> internal abstract void Add(XSyntheticMethodDefinition method);
/// <summary> /// Add the given generated method to this type. /// </summary> internal override void Add(XSyntheticMethodDefinition method) { methods.Add(method); addedMethodCount++; }
/// <summary> /// Create the body of the unbox(object) method. /// </summary> private AstBlock CreateUnboxBody(XSyntheticMethodDefinition method, bool isWide, AssemblyCompiler compiler) { // Prepare var loc = AstNode.NoSource; Func<AstExpression> ldValue = () => new AstExpression(loc, AstCode.Ldloc, method.AstParameters[0]); var afterMyEnum = new AstLabel(loc, "_afterMyEnum"); // value instanceof MyEnumType? var ifNotInstanceOfMyEnum = new AstExpression(loc, AstCode.Brfalse, afterMyEnum, new AstExpression(loc, AstCode.SimpleInstanceOf, XType, ldValue())); var returnMyEnum = new AstExpression(loc, AstCode.Ret, null, new AstExpression(loc, AstCode.SimpleCastclass, XType, ldValue())); // boxToMyEnum(UnboxInteger(value)) var boxingType = compiler.GetDot42InternalType("Boxing").Resolve(); var unboxNumericMethod = boxingType.Methods.First(x => x.Name == (isWide ? "UnboxLong" : "UnboxInteger")); var unboxToNumeric = new AstExpression(loc, AstCode.Call, unboxNumericMethod, ldValue()); var numericToMyEnum = new AstExpression(loc, isWide ? AstCode.Long_to_enum : AstCode.Int_to_enum, XType, unboxToNumeric).SetType(XType); var returnX = new AstExpression(loc, AstCode.Ret, null, numericToMyEnum); var ast = new AstBlock(loc, new AstNode[] { ifNotInstanceOfMyEnum, returnMyEnum, afterMyEnum, returnX }); return ast; }
/// <summary> /// Create the body of the valueOf(string) method. /// </summary> private AstBlock CreateValueOfBody(XSyntheticMethodDefinition method, XTypeSystem typeSystem) { var fields = XType.Fields.Where(x => x.IsStatic && !(x is XSyntheticFieldDefinition)).ToList(); var ast = AstBlock.Create<AstExpression>(); // Find name foreach (var field in fields) { var notEqualLabel = new AstLabel(AstNode.NoSource, "not_equal_to" + field.Name); var equalsExpr = new AstExpression(AstNode.NoSource, AstCode.Call, FrameworkReferences.StringEquals(typeSystem), new AstExpression(AstNode.NoSource, AstCode.Ldstr, field.Name), new AstExpression(AstNode.NoSource, AstCode.Ldloc, method.AstParameters[0])); // If !equals(name, field.name) goto notEqualLabel ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Brfalse, notEqualLabel, equalsExpr)); // Return field object ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Ret, null, new AstExpression(AstNode.NoSource, AstCode.Ldsfld, field))); // notEqualLabel: ast.Body.Add(notEqualLabel); } // Return null ast.Body.Add(new AstExpression(AstNode.NoSource, AstCode.Ret, null, new AstExpression(AstNode.NoSource, AstCode.Ldnull, null))); return ast; }
/// <summary> /// Create the body of the ctor. /// </summary> private AstBlock CreateCtorBody(XSyntheticMethodDefinition method) { // Call base ctor var nameParam = method.AstParameters[0]; var ordinalParam = method.AstParameters[1]; var valueParam = method.AstParameters[2]; var valueField = XType.Fields.First(x => !x.IsStatic && x.Name == NameConstants.Enum.ValueFieldName); return AstBlock.CreateOptimizedForTarget( // Call base new AstExpression(AstNode.NoSource, AstCode.CallBaseCtor, 2, new AstExpression(AstNode.NoSource, AstCode.Ldthis, null), new AstExpression(AstNode.NoSource, AstCode.Ldloc, nameParam), new AstExpression(AstNode.NoSource, AstCode.Ldloc, ordinalParam)), // Initialize value__ new AstExpression(AstNode.NoSource, AstCode.Stfld, valueField, new AstExpression(AstNode.NoSource, AstCode.Ldthis, null), new AstExpression(AstNode.NoSource, AstCode.Ldloc, valueParam)), // Return void new AstExpression(AstNode.NoSource, AstCode.Ret, null)); }
/// <summary> /// Implement the class now that all classes have been created /// </summary> protected override void CreateMembers(DexTargetPackage targetPackage) { // Build value__ field var module = Compiler.Module; var underlyingEnumType = Type.GetEnumUnderlyingType(); var isWide = underlyingEnumType.IsWide(); var xValueType = isWide ? module.TypeSystem.Long : module.TypeSystem.Int; var valueField = XSyntheticFieldDefinition.Create(XType, XSyntheticFieldFlags.Protected, NameConstants.Enum.ValueFieldName, xValueType); Class.Fields.Add(valueField.GetDexField(Class, targetPackage)); // Create normal members base.CreateMembers(targetPackage); // Build value ctor ctor = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Constructor | XSyntheticMethodFlags.Protected, "<init>", module.TypeSystem.Void, XParameter.Create("name", module.TypeSystem.String), XParameter.Create("ordinal", module.TypeSystem.Int), XParameter.Create("value", xValueType)); ctor.Body = CreateCtorBody(ctor); Class.Methods.Add(ctor.GetDexMethod(Class, targetPackage)); // Build enumInfo field var internalEnumInfoType = Compiler.GetDot42InternalType("EnumInfo"); var enumInfoField = XSyntheticFieldDefinition.Create(XType, XSyntheticFieldFlags.Static, NameConstants.Enum.InfoFieldName, internalEnumInfoType/* enumInfoClassBuilder.Class*/); Class.Fields.Add(enumInfoField.GetDexField(Class, targetPackage)); // Build default__ field var defaultField = XSyntheticFieldDefinition.Create(XType, XSyntheticFieldFlags.Static, NameConstants.Enum.DefaultFieldName, XType); Class.Fields.Add(defaultField.GetDexField(Class, targetPackage)); // Build class ctor var classCtor = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Static | XSyntheticMethodFlags.Constructor | XSyntheticMethodFlags.Private, "<clinit>", module.TypeSystem.Void); classCtor.Body = CreateClassCtorBody(isWide, enumInfoField, defaultField, enumInfoClassBuilder.DefaultCtor, xValueType, module.TypeSystem); Class.Methods.Add(classCtor.GetDexMethod(Class, targetPackage)); if (!isWide) { // Build IntValue method var intValue = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Virtual, "IntValue", module.TypeSystem.Int); intValue.Body = CreateIntOrLongValueBody(); Class.Methods.Add(intValue.GetDexMethod(Class, targetPackage)); } else { // Build LongValue method var longValue = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Virtual, "LongValue", module.TypeSystem.Long); longValue.Body = CreateIntOrLongValueBody(); Class.Methods.Add(longValue.GetDexMethod(Class, targetPackage)); } // Build values() method var valuesMethod = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Static, NameConstants.Enum.ValuesMethodName, new XArrayType(XType)); valuesMethod.Body = CreateValuesBody(); Class.Methods.Add(valuesMethod.GetDexMethod(Class, targetPackage)); // Build valueOf(string) method var valueOfMethod = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Static, NameConstants.Enum.ValueOfMethodName, XType, XParameter.Create("name", module.TypeSystem.String)); valueOfMethod.Body = CreateValueOfBody(valueOfMethod, module.TypeSystem); Class.Methods.Add(valueOfMethod.GetDexMethod(Class, targetPackage)); // Build Unbox(object) method unboxMethod = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Static, NameConstants.Enum.UnboxMethodName, XType, XParameter.Create("value", Compiler.Module.TypeSystem.Object)); unboxMethod.Body = CreateUnboxBody(unboxMethod, isWide, Compiler); Class.Methods.Add(unboxMethod.GetDexMethod(Class, targetPackage)); }
/// <summary> /// Add the given generated method to this type. /// </summary> internal override void Add(XSyntheticMethodDefinition method) { throw new NotImplementedException(); }
/// <summary> /// Add the given generated method to this type. /// </summary> internal override void Add(XSyntheticMethodDefinition method) { methods.Add(method); Reset(); }
/// <summary> /// Implement the class now that all classes have been created /// </summary> protected override void CreateMembers(DexTargetPackage targetPackage) { // Build value__ field var module = Compiler.Module; var underlyingEnumType = Type.GetEnumUnderlyingType(); var isWide = underlyingEnumType.IsWide(); var xValueType = isWide ? module.TypeSystem.Long : module.TypeSystem.Int; var valueField = XSyntheticFieldDefinition.Create(XType, XSyntheticFieldFlags.Protected, NameConstants.Enum.ValueFieldName, xValueType); Class.Fields.Add(valueField.GetDexField(Class, targetPackage)); // Create normal members base.CreateMembers(targetPackage); // Build value ctor ctor = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Constructor | XSyntheticMethodFlags.Protected, "<init>", module.TypeSystem.Void, XParameter.Create("name", module.TypeSystem.String), XParameter.Create("ordinal", module.TypeSystem.Int), XParameter.Create("value", xValueType)); ctor.Body = CreateCtorBody(ctor); Class.Methods.Add(ctor.GetDexMethod(Class, targetPackage)); // Build enumInfo field var internalEnumInfoType = Compiler.GetDot42InternalType("EnumInfo"); var enumInfoField = XSyntheticFieldDefinition.Create(XType, XSyntheticFieldFlags.Static, NameConstants.Enum.InfoFieldName, internalEnumInfoType /* enumInfoClassBuilder.Class*/); Class.Fields.Add(enumInfoField.GetDexField(Class, targetPackage)); // Build default__ field var defaultField = XSyntheticFieldDefinition.Create(XType, XSyntheticFieldFlags.Static, NameConstants.Enum.DefaultFieldName, XType); Class.Fields.Add(defaultField.GetDexField(Class, targetPackage)); // Build class ctor var classCtor = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Static | XSyntheticMethodFlags.Constructor | XSyntheticMethodFlags.Private, "<clinit>", module.TypeSystem.Void); classCtor.Body = CreateClassCtorBody(isWide, enumInfoField, defaultField, enumInfoClassBuilder.DefaultCtor, xValueType, module.TypeSystem); Class.Methods.Add(classCtor.GetDexMethod(Class, targetPackage)); if (!isWide) { // Build IntValue method var intValue = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Virtual, "IntValue", module.TypeSystem.Int); intValue.Body = CreateIntOrLongValueBody(); Class.Methods.Add(intValue.GetDexMethod(Class, targetPackage)); } else { // Build LongValue method var longValue = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Virtual, "LongValue", module.TypeSystem.Long); longValue.Body = CreateIntOrLongValueBody(); Class.Methods.Add(longValue.GetDexMethod(Class, targetPackage)); } // Build values() method var valuesMethod = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Static, NameConstants.Enum.ValuesMethodName, new XArrayType(XType)); valuesMethod.Body = CreateValuesBody(); Class.Methods.Add(valuesMethod.GetDexMethod(Class, targetPackage)); // Build valueOf(string) method var valueOfMethod = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Static, NameConstants.Enum.ValueOfMethodName, XType, XParameter.Create("name", module.TypeSystem.String)); valueOfMethod.Body = CreateValueOfBody(valueOfMethod, module.TypeSystem); Class.Methods.Add(valueOfMethod.GetDexMethod(Class, targetPackage)); // Build Unbox(object) method unboxMethod = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Static, NameConstants.Enum.UnboxMethodName, XType, XParameter.Create("value", Compiler.Module.TypeSystem.Object)); unboxMethod.Body = CreateUnboxBody(unboxMethod, isWide, Compiler); Class.Methods.Add(unboxMethod.GetDexMethod(Class, targetPackage)); }
/// <summary> /// Implement the class now that all classes have been created /// </summary> protected override void CreateMembers(DexTargetPackage targetPackage) { // Build value ctor var module = Compiler.Module; var isWide = Type.GetEnumUnderlyingType().Resolve().IsWide(); var enumType = Compiler.GetDot42InternalType("Enum"); var valueType = isWide ? module.TypeSystem.Long : module.TypeSystem.Int; // Build default ctor defaultCtor = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Constructor, "<init>", null, module.TypeSystem.Void); Class.Methods.Add(defaultCtor.GetDexMethod(Class, targetPackage)); // Build Create method create = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Protected, "Create", null, enumType, XParameter.Create("value", valueType)); Class.Methods.Add(create.GetDexMethod(Class, targetPackage)); }
/// <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; }