[m-rev.] for prelim review: fix generation of type_ctor_info for unboxed types bug

Peter Ross pro at missioncriticalit.com
Tue Dec 2 03:16:34 AEDT 2003


Hi,

This is for preliminary review.  How does this look to you Fergus?

+		% XXX replaced with UnifyInit and CompareInit
+		% Note however that this means that we will always create
+		% an extra level of indirection.
+		% We could be a bit smarter here and try and detect which
+		% types need unboxing (backend dependent)

Of particular interest to me is the answer to the above question.  You
will find it in the code.


===================================================================


The comparison and unification function pointers stored in the
type_ctor_info must be pointers to functions where all the arguments
are boxed.  This wasn't occuring on the IL backend for types which
are value types.

compiler/ml_closure_gen.m:
	Adapt ml_gen_closure_wrapper so that it can generate a wrapper
	for the special preds.

compiler/rtti_to_mlds.m:
	Call ml_gen_closure_wrapper to construct a version of the
	comparison and unification functions where the arguments are
	boxed.

Index: compiler/ml_closure_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_closure_gen.m,v
retrieving revision 1.22
diff -u -r1.22 ml_closure_gen.m
--- compiler/ml_closure_gen.m	13 Nov 2003 13:04:33 -0000	1.22
+++ compiler/ml_closure_gen.m	1 Dec 2003 16:09:58 -0000
@@ -50,7 +50,8 @@
 	%
 	% The ClosureKind parameter specifies whether the closure is
 	% an ordinary closure, used for higher-order procedure calls,
-	% or a typeclass_info, used for class method calls.
+	% or a typeclass_info, used for class method calls, or a call
+	% to a special pred.
 	% The NumClosuresArgs parameter specifies how many arguments
 	% to extract from the closure.
 	%
@@ -62,7 +63,8 @@
 
 :- type closure_kind
 	--->	higher_order_proc_closure
-	;	typeclass_info_closure.
+	;	typeclass_info_closure
+	;	special_pred.
 
 	% ml_gen_local_for_output_arg(VarName, Type, ArgNum, Context,
 	%	LocalVarDefn):
@@ -770,18 +772,24 @@
 	{ WrapperArgs1 = list__map(arg_delete_gc_trace_code, WrapperArgs0) },
 
 	% then insert the `closure_arg' parameter
-	{ ClosureArgType = mlds__generic_type },
-	{ ClosureArgName = mlds__var_name("closure_arg", no) },
-	{ ClosureArgDeclType = list__det_head(ml_make_boxed_types(1)) },
-	gen_closure_gc_trace_code(ClosureArgName, ClosureArgDeclType,
-		ClosureKind, WrapperArgTypes, Purity, PredOrFunc,
-		Context, ClosureArgGCTraceCode),
-	{ ClosureArg = mlds__argument(
-		data(var(ClosureArgName)),
-		ClosureArgType,
-		ClosureArgGCTraceCode) },
-	{ WrapperParams = mlds__func_params([ClosureArg | WrapperArgs1],
-		WrapperRetType) },
+	( { ClosureKind = special_pred } ->
+		{ MaybeClosureA = no },
+		{ WrapperArgs = WrapperArgs1 }
+	;
+		{ ClosureArgType = mlds__generic_type },
+		{ ClosureArgName = mlds__var_name("closure_arg", no) },
+		{ ClosureArgDeclType = list__det_head(ml_make_boxed_types(1)) },
+		gen_closure_gc_trace_code(ClosureArgName, ClosureArgDeclType,
+			ClosureKind, WrapperArgTypes, Purity, PredOrFunc,
+			Context, ClosureArgGCTraceCode),
+		{ ClosureArg = mlds__argument(
+			data(var(ClosureArgName)),
+			ClosureArgType,
+			ClosureArgGCTraceCode) },
+		{ MaybeClosureA = yes({ClosureArgType, ClosureArgName}) },
+		{ WrapperArgs = [ClosureArg | WrapperArgs1] }
+	),
+	{ WrapperParams = mlds__func_params(WrapperArgs, WrapperRetType) },
 
 	% also compute the lvals for the parameters,
 	% and local declarations for any by-value output parameters
@@ -814,14 +822,22 @@
 	% because it won't be live across an allocation, and because
 	% (unlike the closure_arg parameter) it isn't referenced from
 	% the GC tracing for other variables.
-	{ ClosureGCTraceCode = no },
 	{ MLDS_Context = mlds__make_context(Context) },
-	{ ClosureDecl = ml_gen_mlds_var_decl(var(ClosureName),
-		ClosureType, ClosureGCTraceCode, MLDS_Context) },
-	ml_gen_var_lval(ClosureName, ClosureType, ClosureLval),
-	ml_gen_var_lval(ClosureArgName, ClosureArgType, ClosureArgLval),
-	{ InitClosure = ml_gen_assign(ClosureLval, lval(ClosureArgLval),
-		Context) },
+	( { MaybeClosureA = yes({ClosureArgType1, ClosureArgName1}) } ->
+		{ ClosureGCTraceCode = no },
+		{ ClosureDecl = ml_gen_mlds_var_decl(var(ClosureName),
+			ClosureType, ClosureGCTraceCode, MLDS_Context) },
+		ml_gen_var_lval(ClosureName, ClosureType, ClosureLval),
+		ml_gen_var_lval(ClosureArgName1, ClosureArgType1,
+				ClosureArgLval),
+		{ InitClosure = ml_gen_assign(ClosureLval, lval(ClosureArgLval),
+			Context) },
+		{ MaybeClosureB = yes({ClosureDecl, InitClosure}) },
+		{ MaybeClosureC = yes(ClosureLval) }
+	;
+		{ MaybeClosureB = no },
+		{ MaybeClosureC = no }
+	),
 
 	%
 	% if the wrapper function is model_non, then
@@ -867,23 +883,33 @@
 	% `Offset' specifies the offset to add to the argument number to
 	% get the field number within the closure.  (Argument numbers start
 	% from 1, and field numbers start from 0.)
-	{
-		ClosureKind = higher_order_proc_closure,
-		Offset = ml_closure_arg_offset
+	( { MaybeClosureC = yes(ClosureLval1) } ->
+		{ ClosureKind = higher_order_proc_closure,
+			Offset = ml_closure_arg_offset
+		; ClosureKind = typeclass_info_closure,
+			Offset = ml_typeclass_info_arg_offset
+		; ClosureKind = special_pred,
+			unexpected(this_file,
+				"ml_gen_closure_wrapper: special_pred")
+		},
+		ml_gen_closure_field_lvals(ClosureLval1, Offset, 1,
+				NumClosureArgs, ClosureArgLvals)
 	;
-		ClosureKind = typeclass_info_closure,
-		Offset = ml_typeclass_info_arg_offset
-	},
-	ml_gen_closure_field_lvals(ClosureLval, Offset, 1, NumClosureArgs,
-		ClosureArgLvals),
+		{ ClosureArgLvals = [] }
+	),
 	{ CallLvals = list__append(ClosureArgLvals, WrapperHeadVarLvals) },
 	ml_gen_call(PredId, ProcId, ProcHeadVarNames, CallLvals,
 		ProcBoxedArgTypes, CodeModel, Context, yes,
 		Decls0, Statements0),
 
 	% insert the stuff to declare and initialize the closure
-	{ Decls1 = [ClosureDecl | Decls0] },
-	{ Statements1 = [InitClosure | Statements0] },
+	( { MaybeClosureB = yes({ClosureDecl1, InitClosure1}) } ->
+		{ Decls1 = [ClosureDecl1 | Decls0] },
+		{ Statements1 = [InitClosure1 | Statements0] }
+	;
+		{ Decls1 = Decls0 },
+		{ Statements1 = Statements0 }
+	),
 
 	%
 	% For semidet code, add the declaration `MR_bool succeeded;'
@@ -904,9 +930,12 @@
 	% needed for accurate GC
 	%
 	{ module_info_globals(ModuleInfo, Globals) },
-	( { globals__get_gc_method(Globals, accurate) } ->
-		ml_gen_closure_wrapper_gc_decls(ClosureKind, ClosureArgName,
-			ClosureArgType, PredId, ProcId, Context, GC_Decls)
+	(
+		{ MaybeClosureA = yes({ClosureArgType2, ClosureArgName2}) },
+		{ globals__get_gc_method(Globals, accurate) }
+	->
+		ml_gen_closure_wrapper_gc_decls(ClosureKind, ClosureArgName2,
+			ClosureArgType2, PredId, ProcId, Context, GC_Decls)
 	;
 		{ GC_Decls = [] }
 	),
@@ -970,6 +999,10 @@
 	;
 		{ ClosureKind = typeclass_info_closure },
 		{ ClosureActualType = sample_typeclass_info_type }
+	;
+		{ ClosureKind = special_pred },
+		{ unexpected(this_file,
+				"gen_closure_gc_trace_code: special_pred") }
 	),
 	ml_gen_maybe_gc_trace_code(ClosureName, ClosureDeclType,
 		ClosureActualType, Context, ClosureGCTraceCode).
@@ -1177,6 +1210,11 @@
 			target_code_input(lval(ClosureLayoutPtrLval)),
 			raw_target_code(");\n", [])
 		] }
+	;
+		{ ClosureKind = special_pred },
+		{ unexpected(this_file,
+			"ml_gen_closure_wrapper_gc_decls: special_pred") }
+
 	),
 	{ TypeParamsGCInit = mlds__statement(atomic(inline_target_code(
 		lang_C, TypeParamsGCInitFragments)), MLDS_Context) },
Index: compiler/rtti_to_mlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/rtti_to_mlds.m,v
retrieving revision 1.43
diff -u -r1.43 rtti_to_mlds.m
--- compiler/rtti_to_mlds.m	1 Dec 2003 06:53:29 -0000	1.43
+++ compiler/rtti_to_mlds.m	1 Dec 2003 16:09:58 -0000
@@ -196,16 +196,32 @@
 	NumPtags = type_ctor_details_num_ptags(TypeCtorDetails),
 	NumFunctors = type_ctor_details_num_functors(TypeCtorDetails),
 	gen_functors_layout_info(ModuleInfo, RttiTypeCtor, TypeCtorDetails,
-		FunctorsInfo, LayoutInfo, SubDefns),
+		FunctorsInfo, LayoutInfo, SubDefns0),
 	FunctorsRttiId = ctor_rtti_id(RttiTypeCtor, type_functors),
 	LayoutRttiId = ctor_rtti_id(RttiTypeCtor, type_layout),
+
+	some [!Defns] (
+		!:Defns = SubDefns0,
+		gen_init_special_pred(ModuleInfo, UnifyUniv, UnifyInit, !Defns),
+		gen_init_special_pred(ModuleInfo, CompareUniv,
+				CompareInit, !Defns),
+		SubDefns = !.Defns
+	),
+
 	Init = init_struct(mlds__rtti_type(RttiId), [
 		gen_init_int(TypeArity),
 		gen_init_int(Version),
 		gen_init_int(NumPtags),
 		gen_init_type_ctor_rep(TypeCtorData),
-		gen_init_proc_id_from_univ(ModuleInfo, UnifyUniv),
-		gen_init_proc_id_from_univ(ModuleInfo, CompareUniv),
+		% XXX replaced with UnifyInit and CompareInit
+		% Note however that this means that we will always create
+		% an extra level of indirection.
+		% We could be a bit smarter here and try and detect which
+		% types need unboxing (backend dependent)
+		% gen_init_proc_id_from_univ(ModuleInfo, UnifyUniv),
+		% gen_init_proc_id_from_univ(ModuleInfo, CompareUniv),
+		UnifyInit,
+		CompareInit,
 		gen_init_string(TypeModuleName),
 		gen_init_string(TypeName),
 		% In the C back-end, these two "structs" are actually unions.
@@ -1048,8 +1064,7 @@
 		list(mlds__defn), list(mlds__defn)).
 :- mode gen_init_method(in, in, in, out, in, out) is det.
 
-gen_init_method(ModuleInfo, NumExtra, RttiProcId, Init,
-		ExtraDefns0, ExtraDefns) :-
+gen_init_method(ModuleInfo, NumExtra, RttiProcId, Init, !ExtraDefns) :-
 	%
 	% we can't store the address of the typeclass method directly in
 	% the base_typeclass_info; instead, we need to generate
@@ -1064,7 +1079,29 @@
 	% Hopefully the Mercury HLDS->HLDS inlining and/or
 	% the target code compiler will be able to optimize this...
 	%
+	gen_wrapper_func_and_initializer(ModuleInfo, NumExtra, RttiProcId,
+			typeclass_info_closure, Init, !ExtraDefns).
+
+:- pred gen_init_special_pred(module_info::in, univ::in, mlds__initializer::out,
+		list(mlds__defn)::in, list(mlds__defn)::out) is det.
+
+gen_init_special_pred(ModuleInfo, RttiProcIdUniv, Init, !ExtraDefns) :-
+	( univ_to_type(RttiProcIdUniv, RttiProcId) ->
+		NumExtra = 0,
+		gen_wrapper_func_and_initializer(ModuleInfo, NumExtra,
+				RttiProcId, special_pred, Init, !ExtraDefns)
+	;
+		error("gen_init_special_pred: cannot extract univ value")
+	).
+
+
+:- pred gen_wrapper_func_and_initializer(module_info, int, rtti_proc_label,
+		closure_kind, mlds__initializer,
+		list(mlds__defn), list(mlds__defn)).
+:- mode gen_wrapper_func_and_initializer(in, in, in, in, out, in, out) is det.
 
+gen_wrapper_func_and_initializer(ModuleInfo, NumExtra, RttiProcId,
+		ClosureKind, Init, ExtraDefns0, ExtraDefns) :-
 	%
 	% We start off by creating a fresh MLGenInfo here,
 	% using the pred_id and proc_id of the wrapped procedure.
@@ -1083,16 +1120,15 @@
 	% Now we can safely go ahead and generate the wrapper function
 	%
 	term__context_init(Context),
-	ml_gen_closure_wrapper(PredId, ProcId, typeclass_info_closure,
+	ml_gen_closure_wrapper(PredId, ProcId, ClosureKind,
 		NumExtra, Context, WrapperFuncRval, WrapperFuncType,
 		MLGenInfo1, MLGenInfo),
 	ml_gen_info_get_extra_defns(MLGenInfo, ExtraDefns1),
 	ExtraDefns = list__append(ExtraDefns1, ExtraDefns0),
 	
 	%
-	% The initializer for the method field of the base_typeclass_info
-	% is just the wrapper function's address, converted to
-	% mlds__generic_type (by boxing).
+	% The initializer for the wrapper is just the wrapper function's
+	% address, converted to mlds__generic_type (by boxing).
 	%
 	Init = init_obj(unop(box(WrapperFuncType), WrapperFuncRval)).
 


-- 
Peter Ross		
Software Engineer                                (Work)   +32 2 757 10 15
Mission Critical                                 (Mobile) +32 485 482 559
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list