/// <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> /// Ensure the given value register is a temp register. /// If it is not, allocate a temp register an copy to it. /// </summary> public static RLRange EnsureTemp(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec value, IRegisterAllocator frame) { // Is temp? if (value.Register.Category == RCategory.Temp) { return(new RLRange(value)); } // No, allocate temp var tmp = frame.AllocateTemp(value.Type); Instruction ins; switch (value.Register.Type) { case RType.Object: ins = builder.Add(sequencePoint, RCode.Move_object, tmp.Register, value.Register); break; case RType.Wide: ins = builder.Add(sequencePoint, RCode.Move_wide, tmp.Register, value.Register); break; case RType.Value: ins = builder.Add(sequencePoint, RCode.Move, tmp.Register, value.Register); break; default: throw new ArgumentException("Unknown register type " + (int)value.Register.Type); } return(new RLRange(ins, tmp)); }
/// <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)); }
/// <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)); }
/// <summary> /// Create code to box the given source array of primitive type elements into an array of boxed elements. /// </summary> public static RLRange BoxGenericArray(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec source, XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler) { var objectArrayType = new DexLib.ArrayType(new ClassReference("java.lang.Object")); var boxedArray = frame.AllocateTemp(objectArrayType); var internalBoxingType = compiler.GetDot42InternalType("Boxing").Resolve(); var ilBoxMethod = internalBoxingType.Methods.First(x => x.EqualsName("Box") && (x.Parameters.Count == 1) && (x.Parameters[0].ParameterType.IsSame(type, true))); var boxMethod = ilBoxMethod.GetReference(targetPackage); var call = builder.Add(sequencePoint, RCode.Invoke_static, boxMethod, source); var saveArray = builder.Add(sequencePoint, RCode.Move_result_object, boxedArray); return(new RLRange(call, saveArray, boxedArray)); }
/// <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> /// Ensure the given value register is a temp register. /// If it is not, allocate a temp register an copy to it. /// </summary> public static RLRange EnsureTemp(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec value, IRegisterAllocator frame) { // Is temp? if (value.Register.Category == RCategory.Temp) return new RLRange(value); // No, allocate temp var tmp = frame.AllocateTemp(value.Type); Instruction ins; switch (value.Register.Type) { case RType.Object: ins = builder.Add(sequencePoint, RCode.Move_object, tmp.Register, value.Register); break; case RType.Wide: ins = builder.Add(sequencePoint, RCode.Move_wide, tmp.Register, value.Register); break; case RType.Value: ins = builder.Add(sequencePoint, RCode.Move, tmp.Register, value.Register); break; default: throw new ArgumentException("Unknown register type " + (int)value.Register.Type); } return new RLRange(ins, tmp); }
/// <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); }
/// <summary> /// Create code to box the given source array of primitive type elements into an array of boxed elements. /// </summary> public static RLRange BoxGenericArray(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec source, XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame, AssemblyCompiler compiler) { var objectArrayType = new DexLib.ArrayType(new ClassReference("java.lang.Object")); var boxedArray = frame.AllocateTemp(objectArrayType); var internalBoxingType = compiler.GetDot42InternalType("Boxing").Resolve(); var ilBoxMethod = internalBoxingType.Methods.First(x => x.EqualsName("Box") && (x.Parameters.Count == 1) && (x.Parameters[0].ParameterType.IsSame(type, true))); var boxMethod = ilBoxMethod.GetReference(targetPackage); var call = builder.Add(sequencePoint, RCode.Invoke_static, boxMethod, source); var saveArray = builder.Add(sequencePoint, RCode.Move_result_object, boxedArray); return new RLRange(call, saveArray, boxedArray); }
/// <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); }