diff: pragma no_inline

Tyson Richard DOWD trd at cs.mu.oz.au
Fri Jun 27 02:02:02 AEST 1997


Hi,

This change implements `:- pragma no_inline'. I've had to make a few
related changes along the way in the handling of markers and creation of
new predicates. 

I'd appeciate it if Simon could have a look at some of those changes,
to be sure I haven't broken anything that was relied upon elsewhere
(higher order spec. and unused args in particular). Anyone else can
review the other changes.

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

Estimated hours taken: 3

Implement `:- pragma no_inline'. This pragma prevents the compiler from
inlining predicates.

compiler/higher_order.m:
compiler/unused_args.m:
	Create new preds using entire marker list, rather than just
	inlining.

compiler/hlds_out.m:
compiler/mercury_to_mercury.m:
compiler/module_qual.m:
compiler/prog_data.m:
compiler/prog_io_pragma.m:
	Add code to support no_inline marker and pragma.

compiler/hlds_pred.m:
	Add `no_inline' marker.
	Create new preds using entire marker list, rather than just
	inlining.
	Change `pred_info_is_inlined' to `pred_info_requested_inlining',
	as it was inappropriately named, and added
	`pred_info_requested_no_inlining'.

compiler/inlining.m:
	Don't inline predicates with pragma no_inlines

compiler/intermod.m:
	Use `pred_info_requested_inlining'.

compiler/make_hlds.m:
	Add code to check for conflicting markers, check for conflicts
	between `inline' and `no_inline' markers.
	Add `no_inline' markers.
	Rename pragma_set_markers as pragma_add_markers, as it was
	actually adding extra markers to what was already there.

doc/reference_manual.texi:
	Document no_inline.

tests/hard_coded/Mmake:
tests/invalid/Mmake:
tests/hard_coded/no_inline.exp:
tests/hard_coded/no_inline.m:
tests/invalid/inline_conflict.err_exp:
tests/invalid/inline_conflict.m:
	Add test cases for no_inline and conflicts between inline and
	no_inline.
	
Index: compiler/higher_order.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/higher_order.m,v
retrieving revision 1.27
diff -u -r1.27 higher_order.m
--- higher_order.m	1997/06/17 22:59:17	1.27
+++ higher_order.m	1997/06/25 08:55:05
@@ -829,13 +829,7 @@
 	pred_info_typevarset(PredInfo0, TypeVars),
 	remove_listof_higher_order_args(Types0, 1, HOArgs, Types),
 	pred_info_context(PredInfo0, Context),
-	(
-		pred_info_is_inlined(PredInfo0)
-	->
-		Inline = yes
-	;
-		Inline = no
-	),
+	pred_info_get_marker_list(PredInfo0, MarkerList),
 	pred_info_get_goal_type(PredInfo0, GoalType),
 	Name = qualified(PredModule, PredName),
 	varset__init(EmptyVarSet),
@@ -846,7 +840,7 @@
 	ClausesInfo = clauses_info(EmptyVarSet, EmptyVarTypes,
 		EmptyVarTypes, [], []),
 	pred_info_init(PredModule, Name, Arity, Tvars,
-		Types, true, Context, ClausesInfo, local, Inline, GoalType,
+		Types, true, Context, ClausesInfo, local, MarkerList, GoalType,
 		PredOrFunc, PredInfo1),
 	pred_info_set_typevarset(PredInfo1, TypeVars, PredInfo2),
 	pred_info_procedures(PredInfo2, Procs0),
Index: compiler/hlds_out.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_out.m,v
retrieving revision 1.164
diff -u -r1.164 hlds_out.m
--- hlds_out.m	1997/05/29 09:03:32	1.164
+++ hlds_out.m	1997/06/24 09:26:47
@@ -499,6 +499,7 @@
 hlds_out__marker_name(infer_type, "infer_type").
 hlds_out__marker_name(infer_modes, "infer_modes").
 hlds_out__marker_name(inline, "inline").
+hlds_out__marker_name(no_inline, "no_inline").
 hlds_out__marker_name(dnf, "dnf").
 hlds_out__marker_name(magic, "magic").
 hlds_out__marker_name(obsolete, "obsolete").
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_pred.m,v
retrieving revision 1.32
diff -u -r1.32 hlds_pred.m
--- hlds_pred.m	1997/05/29 09:04:29	1.32
+++ hlds_pred.m	1997/06/25 09:11:10
@@ -197,6 +197,10 @@
 				% Since the transformation affects *other*
 				% predicates, the `done' status is not
 				% meaningful
+	;	no_inline	% Requests that this be predicate not be 
+				% inlined.
+				% Used for pragma(no_inline).
+				% Conflicts with `inline' marker.
 	;	dnf		% Requests that this predicate be transformed
 				% into disjunctive normal form.
 				% Used for pragma(memo).
@@ -216,7 +220,7 @@
 
 :- pred pred_info_init(module_name, sym_name, arity, tvarset, list(type),
 	condition, term__context, clauses_info, import_status,
-	bool, goal_type, pred_or_func, pred_info).
+	list(marker_status), goal_type, pred_or_func, pred_info).
 :- mode pred_info_init(in, in, in, in, in, in, in, in, in, in, in, in, out)
 	is det.
 
@@ -314,8 +318,14 @@
 	% to inline a predicate even if there was no pragma(inline, ...)
 	% declaration for that predicate.
 
-:- pred pred_info_is_inlined(pred_info).
-:- mode pred_info_is_inlined(in) is semidet.
+:- pred pred_info_requested_inlining(pred_info).
+:- mode pred_info_requested_inlining(in) is semidet.
+
+	% Succeeds if there was a `:- pragma(no_inline, ...)' declaration
+	% for this predicate.
+
+:- pred pred_info_requested_no_inlining(pred_info).
+:- mode pred_info_requested_no_inlining(in) is semidet.
 
 :- pred pred_info_get_marker_list(pred_info, list(marker_status)).
 :- mode pred_info_get_marker_list(in, out) is det.
@@ -395,15 +405,10 @@
 		).
 
 pred_info_init(ModuleName, SymName, Arity, TypeVarSet, Types, Cond, Context,
-		ClausesInfo, Status, Inline, GoalType, PredOrFunc, PredInfo) :-
+		ClausesInfo, Status, Markers, GoalType, PredOrFunc, PredInfo) :-
 	map__init(Procs),
 	unqualify_name(SymName, PredName),
 	sym_name_get_module_name(SymName, ModuleName, PredModuleName),
-	( Inline = yes ->
-		Markers = [request(inline)]
-	;
-		Markers = []
-	),
 	PredInfo = predicate(TypeVarSet, Types, Cond, ClausesInfo, Procs,
 		Context, PredModuleName, PredName, Arity, Status, TypeVarSet, 
 		GoalType, Markers, PredOrFunc).
@@ -543,9 +548,13 @@
 	PredInfo0 = predicate(A, B, C, D, E, F, G, H, I, J, K, _, M, N),
 	PredInfo  = predicate(A, B, C, D, E, F, G, H, I, J, K, GoalType, M, N).
 
-pred_info_is_inlined(PredInfo0) :-
+pred_info_requested_inlining(PredInfo0) :-
 	pred_info_get_marker_list(PredInfo0, Markers),
 	list__member(request(inline), Markers).
+
+pred_info_requested_no_inlining(PredInfo0) :-
+	pred_info_get_marker_list(PredInfo0, Markers),
+	list__member(request(no_inline), Markers).
 
 pred_info_get_marker_list(PredInfo, Markers) :-
 	PredInfo = predicate(_, _, _, _, _, _, _, _, _, _, _, _, Markers, _).
Index: compiler/inlining.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/inlining.m,v
retrieving revision 1.64
diff -u -r1.64 inlining.m
--- inlining.m	1997/06/12 00:10:47	1.64
+++ inlining.m	1997/06/24 14:56:51
@@ -27,6 +27,9 @@
 	%
 	% 	* procedures which have a `:- pragma inline(name/arity).'
 	%
+	% It will not inline procedures which have a 
+	% 	`:- pragma no_inline(name/arity).'
+	%
 	% If inlining a procedure takes the total number of variables over
 	% a given threshold (from a command-line option), then the procedure
 	% is not inlined - note that this means that some calls to a
@@ -280,7 +283,7 @@
 		InlinedProcs0, InlinedProcs) -->
 	{ set__insert(InlinedProcs0, proc(PredId, ProcId), InlinedProcs) },
 	{ module_info_pred_info(ModuleInfo, PredId, PredInfo) },
-	( { pred_info_is_inlined(PredInfo) } ->
+	( { pred_info_requested_inlining(PredInfo) } ->
 		[]
 	;
 		write_proc_progress_message("% Inlining ", PredId, ProcId,
@@ -600,9 +603,15 @@
 		hlds_pred__in_in_unification_proc_id(ProcId)
 	),
 
+	% don't inlining anything we have been specifically requested
+	% not to inline.
+
+	\+ pred_info_requested_no_inlining(PredInfo),
+
 	% OK, we could inline it - but should we?  Apply our heuristic.
+
 	(
-		pred_info_is_inlined(PredInfo)
+		pred_info_requested_inlining(PredInfo)
 	;
 		set__member(proc(PredId, ProcId), InlinedProcs)
 	).
Index: compiler/intermod.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/intermod.m,v
retrieving revision 1.25
diff -u -r1.25 intermod.m
--- intermod.m	1997/05/24 02:19:17	1.25
+++ intermod.m	1997/06/25 09:47:37
@@ -179,7 +179,7 @@
 				{ inlining__is_simple_goal(Goal,
 						InlineThreshold) }
 			;
-				{ pred_info_is_inlined(PredInfo0) }
+				{ pred_info_requested_inlining(PredInfo0) }
 			;
 				{ has_ho_input(ModuleInfo0, ProcInfo) }
 			)
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/make_hlds.m,v
retrieving revision 1.232
diff -u -r1.232 make_hlds.m
--- make_hlds.m	1997/06/02 10:36:32	1.232
+++ make_hlds.m	1997/06/25 09:13:48
@@ -285,17 +285,21 @@
 	;
 		{ Pragma = memo(Name, Arity) },
 		add_pred_marker(Module0, "memo", Name, Arity, Context,
-			[request(memo)], Module1),
+			[request(memo)], [], Module1),
 		add_stratified_pred(Module1, "memo", Name, Arity, Context, 
 			Module)
 	;
 		{ Pragma = inline(Name, Arity) },
 		add_pred_marker(Module0, "inline", Name, Arity, Context,
-			[request(inline)], Module)
+			[request(inline)], [request(no_inline)], Module)
+	;
+		{ Pragma = no_inline(Name, Arity) },
+		add_pred_marker(Module0, "no_inline", Name, Arity, Context,
+			[request(no_inline)], [request(inline)], Module)
 	;
 		{ Pragma = obsolete(Name, Arity) },
 		add_pred_marker(Module0, "obsolete", Name, Arity, Context,
-			[request(obsolete)], Module)
+			[request(obsolete)], [], Module)
 	;
 		{ Pragma = export(Name, PredOrFunc, Modes, C_Function) },
 		{ module_info_get_predicate_table(Module0, PredTable) },
@@ -507,22 +511,42 @@
 
 %-----------------------------------------------------------------------------%
 
+	% add_pred_marker(ModuleInfo0, PragmaName, Name, Arity, Context, 
+	% 	Markers, ConflictMarkers, ModuleInfo, IO0, IO)
+	% Adds Markers to the marker list of pred with give Name and
+	% Arity, updating the ModuleInfo. If the pred does not exist,
+	% or the pred already has a marker in ConflictMarkers, report
+	% an error.
+
 :- pred add_pred_marker(module_info, string, sym_name, arity,
-	term__context, list(marker_status), module_info, io__state, io__state).
-:- mode add_pred_marker(in, in, in, in, in, in, out, di, uo) is det.
+	term__context, list(marker_status), list(marker_status), 
+	module_info, io__state, io__state).
+:- mode add_pred_marker(in, in, in, in, in, in, in, out, di, uo) is det.
 
-add_pred_marker(Module0, PragmaName, Name, Arity, Context, Markers, Module) -->
+add_pred_marker(Module0, PragmaName, Name, Arity, Context, Markers,
+		ConflictMarkers, Module) --> 
 	{ module_info_get_predicate_table(Module0, PredTable0) },
 	(
 		{ predicate_table_search_sym_arity(PredTable0, Name, 
 			Arity, PredIds) }
 	->
 		{ predicate_table_get_preds(PredTable0, Preds0) },
-		{ pragma_set_markers(Preds0, PredIds, Markers, Preds) },
+		{ pragma_add_markers(Preds0, PredIds, Markers, Preds) },
 		{ predicate_table_set_preds(PredTable0, Preds, 
 			PredTable) },
 		{ module_info_set_predicate_table(Module0, PredTable, 
-			Module) }
+			Module1) },
+		{ pragma_check_markers(Preds, PredIds, ConflictMarkers, 
+			Conflict) },
+		(
+			{ Conflict = yes }
+		->
+			pragma_conflict_error(Name, Arity, Context,
+				PragmaName),
+			{ module_info_incr_errors(Module1, Module) }
+		;
+			{ Module = Module1 }
+		)
 	;
 		{ string__append_list(
 			["`:- pragma ", PragmaName, "' declaration"],
@@ -1003,7 +1027,7 @@
 		{ module_info_get_predicate_table(Module1, PredicateTable0) },
 		{ clauses_info_init(Arity, ClausesInfo) },
 		{ pred_info_init(ModuleName, PredName, Arity, TVarSet, Types,
-				Cond, Context, ClausesInfo, Status, no, none,	
+				Cond, Context, ClausesInfo, Status, [], none,	
 				PredOrFunc, PredInfo0) },
 		(
 			{ predicate_table_search_pf_m_n_a(PredicateTable0,
@@ -1183,7 +1207,7 @@
 	clauses_info_init(Arity, ClausesInfo0),
 	adjust_special_pred_status(Status0, SpecialPredId, Status),
 	pred_info_init(ModuleName, PredName, Arity, TVarSet, ArgTypes, Cond,
-		Context, ClausesInfo0, Status, no, none, predicate, PredInfo0),
+		Context, ClausesInfo0, Status, [], none, predicate, PredInfo0),
 	ArgLives = no,
 	add_new_proc(PredInfo0, Arity, ArgModes, yes(ArgModes),
 		ArgLives, yes(Det), Context, PredInfo, _),
@@ -1331,7 +1355,7 @@
 	Cond = true,
 	clauses_info_init(Arity, ClausesInfo),
 	pred_info_init(ModuleName, PredName, Arity, TVarSet, Types, Cond,
-		Context, ClausesInfo, local, no, none, PredOrFunc, PredInfo0),
+		Context, ClausesInfo, local, [], none, PredOrFunc, PredInfo0),
 	pred_info_set_marker_list(PredInfo0, [request(infer_type)], PredInfo),
 	(
 		\+ predicate_table_search_pf_sym_arity(PredicateTable0,
@@ -1715,34 +1739,56 @@
 
 %---------------------------------------------------------------------------%
 
-	% For each pred_id in the list, set the given markers
-	% in the corresponding pred_info.
+	% For each pred_id in the list, check that the given markers are
+	% present in the list of conflicting markers in the corresponding 
+	% pred_info.
+	% The bool indicates whether there was a conflicting marker
+	% present.
+
+:- pred pragma_check_markers(pred_table, list(pred_id), list(marker_status),
+	bool).
+:- mode pragma_check_markers(in, in, in, out) is det.
+
+pragma_check_markers(_, [], _, no).
+pragma_check_markers(PredTable, [PredId | PredIds], ConflictList, 
+		WasConflict) :-
+	map__lookup(PredTable, PredId, PredInfo),
+	pred_info_get_marker_list(PredInfo, MarkerList),
+	pragma_check_markers(PredTable, PredIds, ConflictList, WasConflicts0),
+	( list__delete_elems(ConflictList, MarkerList, ConflictList) ->
+		WasConflict = WasConflicts0
+	;
+		WasConflict = yes
+	).
+
+	% For each pred_id in the list, add the given markers to the
+	% list of markers in the corresponding pred_info.
 
-:- pred pragma_set_markers(pred_table, list(pred_id), list(marker_status),
+:- pred pragma_add_markers(pred_table, list(pred_id), list(marker_status),
 	pred_table).
-:- mode pragma_set_markers(in, in, in, out) is det.
+:- mode pragma_add_markers(in, in, in, out) is det.
 
-pragma_set_markers(PredTable, [], _, PredTable).
-pragma_set_markers(PredTable0, [PredId | PredIds], Markers, PredTable) :-
+pragma_add_markers(PredTable, [], _, PredTable).
+pragma_add_markers(PredTable0, [PredId | PredIds], Markers, PredTable) :-
 	map__lookup(PredTable0, PredId, PredInfo0),
 	pred_info_get_marker_list(PredInfo0, MarkerList0),
-	pragma_set_markers_2(Markers, MarkerList0, MarkerList),
+	pragma_add_markers_2(Markers, MarkerList0, MarkerList),
 	pred_info_set_marker_list(PredInfo0, MarkerList, PredInfo),
 	map__det_update(PredTable0, PredId, PredInfo, PredTable1),
-	pragma_set_markers(PredTable1, PredIds, Markers, PredTable).
+	pragma_add_markers(PredTable1, PredIds, Markers, PredTable).
 
-:- pred pragma_set_markers_2(list(marker_status), list(marker_status),
+:- pred pragma_add_markers_2(list(marker_status), list(marker_status),
 	list(marker_status)).
-:- mode pragma_set_markers_2(in, in, out) is det.
+:- mode pragma_add_markers_2(in, in, out) is det.
 
-pragma_set_markers_2([], MarkerList, MarkerList).
-pragma_set_markers_2([Marker | Markers], MarkerList0, MarkerList) :-
+pragma_add_markers_2([], MarkerList, MarkerList).
+pragma_add_markers_2([Marker | Markers], MarkerList0, MarkerList) :-
 	( list__member(Marker, MarkerList0) ->
 		MarkerList1 = MarkerList0
 	;
 		MarkerList1 = [Marker | MarkerList0]
 	),
-	pragma_set_markers_2(Markers, MarkerList1, MarkerList).
+	pragma_add_markers_2(Markers, MarkerList1, MarkerList).
 
 %---------------------------------------------------------------------------%
 
@@ -3233,6 +3279,22 @@
 	io__write_string("'.\n"),
 	prog_out__write_context(Context),
 	io__write_string("  should have been qualified by prog_io.m.\n").
+
+:- pred pragma_conflict_error(sym_name, int, term__context, string,
+				io__state, io__state).
+:- mode pragma_conflict_error(in, in, in, in, di, uo) is det.
+
+pragma_conflict_error(Name, Arity, Context, PragmaName) -->
+	io__set_exit_status(1),
+	prog_out__write_context(Context),
+	io__write_string("Error: `:- pragma "),
+	io__write_string(PragmaName),
+	io__write_string("' declaration conflicts with\n"),
+	prog_out__write_context(Context),
+	io__write_string("  previous pragma for "),
+	hlds_out__write_pred_call_id(Name/Arity),
+	io__write_string(".\n").
+
 
 %-----------------------------------------------------------------------------%
 %	module_add_pragma_fact_table(PredName, Arity, FileName, 
Index: compiler/mercury_to_mercury.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/mercury_to_mercury.m,v
retrieving revision 1.106
diff -u -r1.106 mercury_to_mercury.m
--- mercury_to_mercury.m	1997/06/02 08:06:11	1.106
+++ mercury_to_mercury.m	1997/06/24 09:15:16
@@ -293,6 +293,9 @@
 		{ Pragma = inline(Pred, Arity) },
 		mercury_output_pragma_decl(Pred, Arity, "inline")
 	;
+		{ Pragma = no_inline(Pred, Arity) },
+		mercury_output_pragma_decl(Pred, Arity, "no_inline")
+	;
 		{ Pragma = unused_args(PredOrFunc, PredName,
 			Arity, ProcId, UnusedArgs) },
 		mercury_output_pragma_unused_args(PredOrFunc,
Index: compiler/module_qual.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/module_qual.m,v
retrieving revision 1.17
diff -u -r1.17 module_qual.m
--- module_qual.m	1997/06/13 07:54:01	1.17
+++ module_qual.m	1997/06/24 05:21:30
@@ -574,6 +574,7 @@
 	qualify_pragma_vars(PragmaVars0, PragmaVars, Info0, Info).
 qualify_pragma(memo(A, B), memo(A, B), Info, Info) --> [].
 qualify_pragma(inline(A, B), inline(A, B), Info, Info) --> [].
+qualify_pragma(no_inline(A, B), no_inline(A, B), Info, Info) --> [].
 qualify_pragma(obsolete(A, B), obsolete(A, B), Info, Info) --> [].
 qualify_pragma(export(Name, PredOrFunc, Modes0, CFunc),
 		export(Name, PredOrFunc, Modes, CFunc), Info0, Info) -->
Index: compiler/prog_data.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/prog_data.m,v
retrieving revision 1.18
diff -u -r1.18 prog_data.m
--- prog_data.m	1997/06/13 06:41:39	1.18
+++ prog_data.m	1997/06/24 05:00:58
@@ -108,6 +108,9 @@
 			;	inline(sym_name, int)
 				% Predname, Arity
 
+			;	no_inline(sym_name, int)
+				% Predname, Arity
+
 			;	obsolete(sym_name, int)
 				% Predname, Arity
 
Index: compiler/prog_io_pragma.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/prog_io_pragma.m,v
retrieving revision 1.4
diff -u -r1.4 prog_io_pragma.m
--- prog_io_pragma.m	1997/03/06 05:09:48	1.4
+++ prog_io_pragma.m	1997/06/24 10:06:15
@@ -224,6 +224,13 @@
 			Pragma = inline(Name, Arity)),
 		PragmaTerms, ErrorTerm, Result).
 
+parse_pragma_type(ModuleName, "no_inline", PragmaTerms,
+				ErrorTerm, _VarSet, Result) :-
+	parse_simple_pragma(ModuleName, "no_inline",
+		lambda([Name::in, Arity::in, Pragma::out] is det,
+			Pragma = no_inline(Name, Arity)),
+		PragmaTerms, ErrorTerm, Result).
+
 parse_pragma_type(ModuleName, "memo", PragmaTerms,
 			ErrorTerm, _VarSet, Result) :-
 	parse_simple_pragma(ModuleName, "memo",
Index: compiler/unused_args.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/unused_args.m,v
retrieving revision 1.29
diff -u -r1.29 unused_args.m
--- unused_args.m	1997/05/05 11:17:40	1.29
+++ unused_args.m	1997/06/25 09:51:03
@@ -883,18 +883,12 @@
 	remove_listof_elements(ArgTypes0, 1, UnusedArgs, ArgTypes),
 	pred_info_context(PredInfo0, Context),
 	pred_info_clauses_info(PredInfo0, ClausesInfo),
-	(
-		pred_info_is_inlined(PredInfo0)
-	->
-		Inline = yes
-	;
-		Inline = no
-	),
+	pred_info_get_marker_list(PredInfo0, MarkerList),
 	pred_info_get_goal_type(PredInfo0, GoalType),
 		% *** This will need to be fixed when the condition
 		%	field of the pred_info becomes used.
 	pred_info_init(PredModule, qualified(PredModule, Name), Arity, Tvars,
-		ArgTypes, true, Context, ClausesInfo, Status, Inline,
+		ArgTypes, true, Context, ClausesInfo, Status, MarkerList,
 		GoalType, PredOrFunc, PredInfo1),
 	pred_info_set_typevarset(PredInfo1, TypeVars, PredInfo).
 
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/reference_manual.texi,v
retrieving revision 1.51
diff -u -r1.51 reference_manual.texi
--- reference_manual.texi	1997/06/10 03:58:26	1.51
+++ reference_manual.texi	1997/06/26 13:19:29
@@ -2505,6 +2505,7 @@
                                 from Mercury code, and vice versa.
 * Inlining::                    Calls to Mercury predicates can be inlined
                                 by the compiler to improve efficiency.
+* Preventing Inlining::         Inlining can be avoided when undesirable.
 @c * Tabling::                     Mercury predicates can be evaluated
 @c                                 using a three different forms of tabled
 @c                                 evaluation.
@@ -2770,6 +2771,22 @@
 if a predicate for which there is an @samp{inline} pragma is called
 from a module other than the one it is defined in, the compiler will
 ignore the hint.
+
+ at node Preventing Inlining
+ at section Preventing Inlining
+
+A declaration of the form
+
+ at example
+:- pragma no_inline(@var{Name}/@var{Arity}).
+ at end example
+
+ at noindent
+ensures the compiler will not inline this predicate.  This may be used
+simply for performance concerns (inlining can cause unwanted code bloat
+in some cases) or to prevent possibly dangerous inlining when using
+low-level C code.
+
 
 @c @node Tabling
 @c @section Tabling
Index: tests/hard_coded/Mmake
===================================================================
RCS file: /home/staff/zs/imp/tests/hard_coded/Mmake,v
retrieving revision 1.46
diff -u -r1.46 Mmake
--- Mmake	1997/06/10 04:03:58	1.46
+++ Mmake	1997/06/26 13:07:29
@@ -33,6 +33,7 @@
 	ho_univ_to_type \
 	name_mangling \
 	no_fully_strict \
+	no_inline \
 	pragma_c_code \
 	pragma_inline \
 	qual_adv_test \
Index: tests/invalid/Mmake
===================================================================
RCS file: /home/staff/zs/imp/tests/invalid/Mmake,v
retrieving revision 1.17
diff -u -r1.17 Mmake
--- Mmake	1997/06/16 08:55:30	1.17
+++ Mmake	1997/06/26 13:11:58
@@ -17,6 +17,7 @@
 	external.m \
 	funcs_as_preds.m \
 	ho_type_mode_bug.m \
+	inline_conflict.m \
 	io_in_ite_cond.m \
 	missing_det_decls.m \
 	modes_erroneous.m \

New File: tests/hard_coded/no_inline.exp
===================================================================
I'm going to see whether `bar'/2 is inlined.
(Remember kids, don't try this one at home.)

It wasn't.

New File: tests/hard_coded/no_inline.m
===================================================================

:- module no_inline.

:- interface.

:- import_module io.

:- pred main(io__state::di, io__state::uo) is det.
:- pred baz(io__state::di, io__state::uo) is det.

:- implementation.

main -->
	io__write_string("I'm going to see whether `bar'/2 is inlined.\n"),
	io__write_string("(Remember kids, don't try this one at home.)\n\n"),
	bar,
	io__write_string("It wasn't.\n").

:- pragma no_inline(bar/2).

:- pred bar(io__state::di, io__state::uo) is det.

:- pragma c_header_code("
#include <stdio.h>
").

:- pragma c_code(bar(IO0::di, IO::uo), "
	/* START INLINING */
{
	static int i = 0;
	IO = IO0;

	/* Check if I get run again - I'm supposed to only execute once! */

	if (i > 0) { 
		printf(""bar/2: You inlined me!\n""
			""Read my lips, `no_inline'\n\n"");
		    fatal_error(""pragma no_inline ignored."");
	}
	i++;

	tailcall(ENTRY(mercury__no_inline__baz_2_0),
			ENTRY(mercury__no_inline__bar_2_0));
	/* END INLINING */
}
").


:- pragma c_code(baz(IO0::di, IO::uo), "
	IO = IO0;
	proceed();
").


New File: tests/invalid/inline_conflict.err_exp
===================================================================
inline_conflict.m:016: Error: `:- pragma no_inline' declaration conflicts with
inline_conflict.m:016:   previous pragma for inline_conflict:bar/2.
For more information, try recompiling with `-E'.

New File: tests/invalid/inline_conflict.m
===================================================================

:- module inline_conflict.

:- interface.

:- pred foo(int::in, int::out) is det.

:- implementation.


foo(X, Y) :- bar(X, Y).

:- pred inline_conflict__bar(int::in, int::out) is det.

:- pragma inline(bar/2).
:- pragma no_inline(bar/2).


bar(X, X).

-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't eveyone's cup of
     trd at cs.mu.oz.au        #  fur.
http://www.cs.mu.oz.au/~trd #



More information about the developers mailing list