From 1fe7c186407d24fd377d27e0ff16202def992f62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D0=BD=D0=B4=D0=B0=D1=80=D0=B5=D0=B2=20=D0=98?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD?= Date: Thu, 8 Mar 2018 21:40:19 +0100 Subject: [PATCH] bug fix #699 --- NETGenerator/NETGenegratorTools.cs | 10 +++--- NETGenerator/NETGenerator.cs | 53 +++++------------------------- TestSuite/boxing3.pas | 9 +++++ 3 files changed, 21 insertions(+), 51 deletions(-) create mode 100644 TestSuite/boxing3.pas diff --git a/NETGenerator/NETGenegratorTools.cs b/NETGenerator/NETGenegratorTools.cs index 730aa846d..ddf947e36 100644 --- a/NETGenerator/NETGenegratorTools.cs +++ b/NETGenerator/NETGenegratorTools.cs @@ -55,6 +55,7 @@ namespace PascalABCCompiler.NETGenerator private static Hashtable types; private static Hashtable sizes; public static MethodInfo ArrayCopyMethod; + public static MethodInfo GetTypeFromHandleMethod; public static MethodInfo ResizeMethod; public static MethodInfo GCHandleFreeMethod; public static MethodInfo StringNullOrEmptyMethod; @@ -120,6 +121,7 @@ namespace PascalABCCompiler.NETGenerator IndexOutOfRangeConstructor = typeof(IndexOutOfRangeException).GetConstructor(Type.EmptyTypes); ParamArrayAttributeConstructor = typeof(ParamArrayAttribute).GetConstructor(Type.EmptyTypes); GCHandleFreeMethod = typeof(GCHandle).GetMethod("Free"); + GetTypeFromHandleMethod = typeof(Type).GetMethod("GetTypeFromHandle"); } public static bool IsStandType(Type t) @@ -421,7 +423,7 @@ namespace PascalABCCompiler.NETGenerator public static void PushCast(ILGenerator il, Type tp, Type from_value_type) { - if (IsPointer(tp)) //INTPTR TODO Здесть проблема с Unbox_Any + if (IsPointer(tp)) return; //(ssyy) Вставил 15.05.08 if (from_value_type != null) @@ -521,7 +523,6 @@ namespace PascalABCCompiler.NETGenerator { ILGenerator il = clone_meth.GetILGenerator(); il.Emit(OpCodes.Ldloca_S, (byte)0); - //il.Emit(OpCodes.Ldarga_S,(byte)0); il.Emit(OpCodes.Ldarg_0); if (ti.clone_meth != null) { @@ -541,8 +542,6 @@ namespace PascalABCCompiler.NETGenerator public static void AssignField(MethodBuilder ass_meth, FieldBuilder fb, TypeInfo ti) { ILGenerator il = ass_meth.GetILGenerator(); - //il.Emit(OpCodes.Ldarga_S, (byte)0); - //il.Emit(OpCodes.Ldarga_S, (byte)1); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarga_S, (byte)1); if (ti.clone_meth != null) @@ -563,8 +562,7 @@ namespace PascalABCCompiler.NETGenerator public static void PushTypeOf(ILGenerator il, Type tp) { il.Emit(OpCodes.Ldtoken, tp); - //TODO это надо ускорить хештаблицей! - il.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); + il.EmitCall(OpCodes.Call, TypeFactory.GetTypeFromHandleMethod, null); } public static bool IsPointer(Type tp) diff --git a/NETGenerator/NETGenerator.cs b/NETGenerator/NETGenerator.cs index ef64926fc..0d7756ae6 100644 --- a/NETGenerator/NETGenerator.cs +++ b/NETGenerator/NETGenerator.cs @@ -6739,7 +6739,7 @@ namespace PascalABCCompiler.NETGenerator //DarkStar Fixed: type t:=i.gettype(); bool _box = value.obj.type.is_value_type && !value.compiled_method.method_info.DeclaringType.IsValueType; if (!_box && value.obj.conversion_type != null) - _box = value.obj.conversion_type != null && value.obj.conversion_type.is_value_type; + _box = value.obj.conversion_type.is_value_type; if (_box) is_dot_expr = false; value.obj.visit(this); @@ -6757,21 +6757,14 @@ namespace PascalABCCompiler.NETGenerator { il.Emit(OpCodes.Box, helper.GetTypeReference(value.obj.conversion_type).tp); } + else if (_box && value.obj.type.is_value_type) + { + LocalBuilder lb = il.DeclareLocal(helper.GetTypeReference(value.obj.type).tp); + il.Emit(OpCodes.Stloc, lb); + il.Emit(OpCodes.Ldloca, lb); + } is_dot_expr = false; EmitArguments(parameters, real_parameters); - /*for (int i = 0; i < real_parameters.Length; i++) - { - if (parameters[i].parameter_type == parameter_type.var) - is_addr = true; - real_parameters[i].visit(this); - //ICompiledTypeNode ctn = value.real_parameters[i].type as ICompiledTypeNode; - ICompiledTypeNode ctn2 = parameters[i].type as ICompiledTypeNode; - ITypeNode ctn3 = real_parameters[i].type; - if (!(real_parameters[i] is INullConstantNode)) - if (ctn2 != null && (ctn3.is_value_type || ctn3.is_generic_parameter) && ctn2.compiled_type == TypeFactory.ObjectType) - il.Emit(OpCodes.Box, helper.GetTypeReference(ctn3).tp); - is_addr = false; - }*/ MethodInfo mi = value.compiled_method.method_info; if (value.compiled_method.comperehensive_type.is_value_type || !value.virtual_call && value.compiled_method.polymorphic_state == polymorphic_state.ps_virtual || value.compiled_method.polymorphic_state == polymorphic_state.ps_static) { @@ -6916,42 +6909,12 @@ namespace PascalABCCompiler.NETGenerator { il.Emit(OpCodes.Box, helper.GetTypeReference(value.obj.conversion_type).tp); } + is_dot_expr = false; //bool is_comp_gen = false; //bool need_fee = false; IParameterNode[] parameters = value.method.parameters; EmitArguments(parameters, real_parameters); - /*for (int i = 0; i < real_parameters.Length; i++) - { - if (parameters[i].parameter_type == parameter_type.var) - is_addr = true; - ITypeNode ctn = real_parameters[i].type; - TypeInfo ti = null; - - //(ssyy) moved up - ITypeNode tn2 = parameters[i].type; - ICompiledTypeNode ctn2 = tn2 as ICompiledTypeNode; - ITypeNode ctn3 = real_parameters[i].type; - //(ssyy) 07.12.2007 При боксировке нужно вызывать Ldsfld вместо Ldsflda. - //Дополнительная проверка введена именно для этого. - bool box_awaited = - (ctn2 != null && ctn2.compiled_type == TypeFactory.ObjectType || tn2.IsInterface) && (ctn3.is_value_type || ctn3.is_generic_parameter) && !(real_parameters[i] is SemanticTree.INullConstantNode); - - if (!(real_parameters[i] is INullConstantNode)) - { - ti = helper.GetTypeReference(ctn); - if (ti.clone_meth != null && ti.tp != null && ti.tp.IsValueType && !box_awaited && !parameters[i].is_const) - is_dot_expr = true; - } - //is_comp_gen = CheckForCompilerGenerated(value.real_parameters[i]); - //if (is_comp_gen) need_fee = true; - real_parameters[i].visit(this); - is_dot_expr = false; - CallCloneIfNeed(il, parameters[i], real_parameters[i]); - if (box_awaited) - il.Emit(OpCodes.Box, helper.GetTypeReference(ctn3).tp); - is_addr = false; - }*/ //вызов метода //(ssyy) Функции размерных типов всегда вызываются через call if (value.method.comperehensive_type.is_value_type || !value.virtual_call && value.method.polymorphic_state == polymorphic_state.ps_virtual || value.method.polymorphic_state == polymorphic_state.ps_static /*|| !value.virtual_call || (value.method.polymorphic_state != polymorphic_state.ps_virtual && value.method.polymorphic_state != polymorphic_state.ps_virtual_abstract && !value.method.common_comprehensive_type.IsInterface)*/) diff --git a/TestSuite/boxing3.pas b/TestSuite/boxing3.pas new file mode 100644 index 000000000..58af8325d --- /dev/null +++ b/TestSuite/boxing3.pas @@ -0,0 +1,9 @@ +begin + var a: BigInteger := 1; + var s := byte(a).ToString; + var s2 := object(a).ToString; + var s3 := BigInteger(1).ToString; + assert(s='1'); + assert(s2='1'); + assert(s3='1'); +end. \ No newline at end of file