This commit is contained in:
Бондарев Иван 2018-03-08 21:40:19 +01:00
parent 6400880643
commit 1fe7c18640
3 changed files with 21 additions and 51 deletions

View file

@ -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)

View file

@ -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)*/)

9
TestSuite/boxing3.pas Normal file
View file

@ -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.