[m-dev.] bug fixes for module qualified cons_ids

Simon TAYLOR stayl at students.cs.mu.oz.au
Tue Apr 1 20:58:50 AEST 1997


Hi Fergus,

> Can you please add Mark Brown's bug report example as a test case?

OK.

>
> > +		{ pred_info_get_marker_list(PredInfo0, Markers) },
> >  		(
> >  			% Don't export builtins since they will be
> >  			% recreated in the importing module anyway.
> >  			{ \+ code_util__compiler_generated(PredInfo0) },
> >  			{ \+ code_util__predinfo_is_builtin(PredInfo0) },
> > +				% The compiler may have difficulty parsing
> > +				% inferred modes due to $typed_inst etc.
> > +			{ \+ list__member(request(infer_modes), Markers) },
> 
> Also, that change is not an acceptable solution, IMHO.
> The compiler should not give up on intermodule optimization
> just because you haven't declared the modes.
> 

Currently the `.opt' files are written out immediately after type-checking,
so mode inference cannot be supported without running mode analysis as well.
Is the extra compilation time worth it? Actually, the check added here
is unnecessary, since exported predicates must have modes declared, so I've
removed it.

>
> How come it writes the `.opt' file *before* invoking the front-end
> passes and polymorphism?  Shouldn't it write the `.opt' file last?
> 

Having polymorphism stuff in the `.opt' file would complicate reading
the `.opt' files back in. Mode and determinism analysis and polymorphism 
are only run here because unused_args needs the information.

Here's an updated log message and some minor changes to the diff.

Simon.


Estimated hours: 6

Bug fixes for module qualified cons_ids. This includes changes to ensure 
that everything is module qualified after mode analysis.

Improve the compilation time of modules with lots of user_defined insts.
(Compiling tree234.m is still way too slow).

compiler/mode_util.m
	In propagate_type_info_mode_list and the predicates it calls, avoid
	finding the constructors for a type and substituting the argument
	types.

compiler/hlds_pred.m
	Add a new field to the proc_info, maybe_declared_argmodes which
	holds the declared arg_modes for use in .opt files and error messages.

compiler/typecheck.m
	Call propagate_type_info_into_modes from here to avoid calling it
	many times throughout mode analysis. This does not cause a
	substantial performance improvement, but reduces confusion
	over where everything should be module qualified.
	This also fixes a bug with the no_tag optimisation reported by
	Mark Brown. A runtime abort occurred because a constructor in a bound
	inst was not being module qualified which confused mode_to_arg_mode
	into giving the argument an arg_mode of top_unused.

compiler/modecheck_unify.m
	Call propagate_type_info_mode_list for modes of lambda predicates,
	to ensure that everything is module qualified after mode analysis.

compiler/modes.m
compiler/modecheck_call.m
compiler/unique_modes.m
	Don't call propagate_type_info_mode_list since that has
	already been done in typecheck.m.

compiler/intermod.m
	Write out the declared arg_modes, since these don't contain
	constructs such $typed_inst which the parser doesn't handle.

compiler/clause_to_proc.m
compiler/unify_proc.m
	Fill in the declared_argmodes field in proc_infos.

compiler/type_util.m
	Avoid creating the substitution multiple times in type_constructors.

tests/hard_coded/Mmake
tests/hard_coded/imported_no_tag.m
tests/hard_coded/test_imported_no_tag.m
tests/hard_coded/test_imported_no_tag.exp
	Add Mark Brown's test case.




Updated diff:

Changes to lambda were undone, instead modes of lambda expressions
are module qualified during mode analysis. This was done to ensure 
that everything is module qualified after mode analysis.


Index: intermod.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/intermod.m,v
retrieving revision 1.21
diff -u -r1.21 intermod.m
--- intermod.m	1997/03/23 19:01:09	1.21
+++ intermod.m	1997/03/23 22:03:38
@@ -440,7 +440,8 @@
 	{ module_info_pred_info(ModuleInfo, PredId, PredInfo) },
 	{ pred_info_import_status(PredInfo, Status) },
 	{ pred_info_procids(PredInfo, ProcIds) },
-	( { ProcIds = [] } ->
+	{ pred_info_get_marker_list(PredInfo, Markers) },
+	( { list__member(request(infer_modes), Markers) } ->
 		% Don't write this pred if it calls preds without mode decls.
 		{ DoWrite = no }
 	; 
@@ -873,12 +874,13 @@
 intermod__write_pred_modes(_, _, _, []) --> [].
 intermod__write_pred_modes(Procs, SymName, PredOrFunc, [ProcId | ProcIds]) -->
 	{ map__lookup(Procs, ProcId, ProcInfo) },
-	{ proc_info_argmodes(ProcInfo, ArgModes) },
+	{ proc_info_maybe_declared_argmodes(ProcInfo, MaybeArgModes) },
 	{ proc_info_declared_determinism(ProcInfo, MaybeDetism) },
-	{ MaybeDetism = yes(Detism0) ->
+	{ MaybeArgModes = yes(ArgModes0), MaybeDetism = yes(Detism0) ->
+		ArgModes = ArgModes0,
 		Detism = Detism0
 	;
-		error("Attempt to write pred mode decl without det decl")
+		error("intermod__write_pred_modes: attempt to write undeclared mode")
 	},
 	{ proc_info_context(ProcInfo, Context) },
 	{ varset__init(Varset) },
@@ -996,13 +998,17 @@
 intermod__write_c_clauses(Procs, [ProcId | ProcIds], PredOrFunc,
 			CCode, MayCallMercury, Vars, Varset, SymName) -->
 	{ map__lookup(Procs, ProcId, ProcInfo) },
-	{ proc_info_argmodes(ProcInfo, ArgModes) },
-	{ get_pragma_c_code_vars(Vars, Varset, ArgModes, PragmaVars) },
-	% XXX will need modification for nondet pragma C code
-	mercury_output_pragma_c_code(MayCallMercury, SymName, PredOrFunc,
-		PragmaVars, no, Varset, CCode),
-	intermod__write_c_clauses(Procs, ProcIds, PredOrFunc, CCode,
-		MayCallMercury, Vars, Varset, SymName).
+	{ proc_info_maybe_declared_argmodes(ProcInfo, MaybeArgModes) },
+	( { MaybeArgModes = yes(ArgModes) } ->
+		{ get_pragma_c_code_vars(Vars, Varset, ArgModes, PragmaVars) },
+		% XXX will need modification for nondet pragma C code
+		mercury_output_pragma_c_code(MayCallMercury, SymName,
+			PredOrFunc, PragmaVars, no, Varset, CCode),
+		intermod__write_c_clauses(Procs, ProcIds, PredOrFunc, CCode,
+			MayCallMercury, Vars, Varset, SymName)
+	;
+		{ error("intermod__write_c_clauses: no mode declaration") }
+	).
 
 :- pred get_pragma_c_code_vars(list(var)::in, varset::in,
 		list(mode)::in, list(pragma_var)::out) is det.

Index: modecheck_unify.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/modecheck_unify.m,v
retrieving revision 1.12
diff -u -r1.12 modecheck_unify.m
--- modecheck_unify.m	1997/03/23 07:34:09	1.12
+++ modecheck_unify.m	1997/03/31 07:10:57
@@ -349,7 +349,7 @@
 		)
 	).
 
-modecheck_unification(X, lambda_goal(PredOrFunc, Vars, Modes, Det, Goal0),
+modecheck_unification(X, lambda_goal(PredOrFunc, Vars, Modes0, Det, Goal0),
 			Unification0, UnifyContext, _GoalInfo, HowToCheckGoal,
 			unify(X, RHS, Mode, Unification, UnifyContext),
 			ModeInfo0, ModeInfo) :-
@@ -377,6 +377,15 @@
 	%
 
 	mode_info_get_module_info(ModeInfo0, ModuleInfo0),
+
+	( HowToCheckGoal = check_modes ->
+		% This only needs to be done once.
+		mode_info_get_types_of_vars(ModeInfo0, Vars, VarTypes),
+		propagate_type_info_mode_list(VarTypes, ModuleInfo0,
+			Modes0, Modes)
+ 	;
+		Modes = Modes0
+	),
  
 	% initialize the initial insts of the lambda variables
 	mode_list_get_initial_insts(Modes, ModuleInfo0, VarInitialInsts),




Index: tests/hard_coded/Mmake
===================================================================
RCS file: /home/staff/zs/imp/tests/hard_coded/Mmake,v
retrieving revision 1.36
diff -u -r1.36 Mmake
--- Mmake	1997/03/21 10:57:43	1.36
+++ Mmake	1997/03/23 06:10:46
@@ -13,7 +13,7 @@
 	cc_nondet_disj bidirectional address_of_builtins \
 	reverse_arith curry curry2 higher_order_syntax \
 	ho_func_reg float_reg write expand ho_solns write_reg1 \
-	ho_univ_to_type elim_special_pred division_test
+	ho_univ_to_type elim_special_pred division_test test_imported_no_tag
 
 #-----------------------------------------------------------------------------#
 

tests/hard_coded/imported_no_tag.m:

% Test handling of imported no_tag types.
:- module imported_no_tag.
:- interface.

:- type printable(T) ---> class(pred(T)).
:- inst printable_data = bound(class(pred(in) is semidet)).
:- mode printable :: in(printable_data).
:- mode new_printable :: out(printable_data).

:- pred pwrite(printable(T)::printable, T::in) is semidet.

:- implementation.

pwrite(C, Data)  :-
 C = class(Test),
 call(Test, Data).



tests/hard_coded/imported_no_tag.m:

% Test handling of no_tag types without inlining.
:- module test_imported_no_tag.
:- interface.

:- import_module imported_no_tag, io.

:- pred main(io:state, io:state).
:- mode main(di, uo) is det.

:- implementation.

:- pred test_int(int::in) is semidet.

test_int(99).

main -->
 ( { pwrite(class(test_int), 99) } ->
	io__write_string("ok\n")	
;
	io__write_string("uh oh\n")
).



tests/hard_coded/imported_no_tag.exp:

ok




More information about the developers mailing list