[m-dev.] for review: passing boxed floats to pragma C code

Zoltan Somogyi zs at cs.mu.OZ.AU
Tue Dec 28 18:33:08 AEDT 1999


For review by anyone.

Add support for passing boxed float arguments to pragma C codes, i.e. as Words.
This requires the C code to call word_to_float on inputs and float_to_word
on outputs as necessary, but also allows C code to store *already boxed*
floats in data structures, and return them to C code without the memory
allocation inherent in reboxing. When this change has been bootstrapped,
I will modify the routines in mercury_tabling.c and private_builtin.m
that save and restore floats to use this new facility.

compiler/prog_data.m:
	Add an extra kind of attribute to pragma_c_code goals: the
	pragma_float_format, with two values: pragma_unboxed_float and
	pragma_boxed_float. With the former, which is the default, float
	arguments are passed to and from pragma C code as type Float, as now.
	With the latter, they are passed in boxed form, as type Word.

compiler/prog_io_pragma.m:
	Parse the new attribute.

compiler/llds.m:
	Add an extra parameter to pragma_c instructions that records the
	pragma_float_format.

compiler/llds_out.m:
	When the pragma_float_format is pragma_boxed_float, don't convert float
	arguments of pragmas from or to the internal boxed representation.

compiler/pragma_c_gen.m:
compiler/code_gen.m:
	Transmit the float format from the HLDS to the LLDS. In code_gen.m,
	also fix a bug: the may_call_mercury attribute was being ignored.

compiler/*.m:
	In other files, lots of minor changes to conform to the changes
	in the data structures.

Zoltan.

cvs diff: Diffing .
Index: code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.71
diff -u -b -r1.71 code_gen.m
--- code_gen.m	1999/12/14 04:52:31	1.71
+++ code_gen.m	1999/12/28 00:10:29
@@ -174,8 +174,10 @@
 			maybe(int),	% Slot number of succip if succip is
 					% present in a general slot.
 
-			bool		% Is this the frame of a model_non
+			maybe(pair(may_call_mercury, pragma_float_format))
+					% Is this the frame of a model_non
 					% proc defined via pragma C code?
+					% If so, give its relevant attributes.
 		).
 
 %---------------------------------------------------------------------------%
@@ -569,7 +571,8 @@
 		{ code_info__resume_point_stack_addr(OutsideResumePoint,
 			OutsideResumeAddress) },
 		(
-			{ Goal = pragma_c_code(_,_,_,_,_,_, PragmaCode) - _},
+			{ Goal = pragma_c_code(Attributes, _,_,_,_,_,
+				PragmaCode) - _},
 			{ PragmaCode = nondet(Fields, FieldsContext,
 				_,_,_,_,_,_,_) }
 		->
@@ -582,14 +585,17 @@
 			{ DefineComponents = [pragma_c_raw_code(DefineStr)] },
 			{ NondetFrameInfo = ordinary_frame(PushMsg, TotalSlots,
 				yes(Struct)) },
+			{ may_call_mercury(Attributes, MayCallMercury) },
+			{ pragma_float_format(Attributes, FloatFormat) },
 			{ AllocCode = node([
 				mkframe(NondetFrameInfo, OutsideResumeAddress)
 					- "Allocate stack frame",
 				pragma_c([], DefineComponents,
-					will_not_call_mercury, no, no, no)
+					MayCallMercury, FloatFormat,
+					no, no, no)
 					- ""
 			]) },
-			{ NondetPragma = yes }
+			{ NondetPragma = yes(MayCallMercury - FloatFormat) }
 		;
 			{ NondetFrameInfo = ordinary_frame(PushMsg, TotalSlots,
 				no) },
@@ -668,12 +674,12 @@
 		comment("End of procedure epilogue") - ""
 	]) },
 	{ FrameInfo = frame(TotalSlots, MaybeSuccipSlot, NondetPragma) },
-	( { NondetPragma = yes } ->
+	( { NondetPragma = yes(MayCallMercury - FloatFormat) } ->
 		{ UndefStr = "#undef\tMR_ORDINARY_SLOTS\n" },
 		{ UndefComponents = [pragma_c_raw_code(UndefStr)] },
 		{ UndefCode = node([
 			pragma_c([], UndefComponents,
-				will_not_call_mercury, no, no, no)
+				MayCallMercury, FloatFormat, no, no, no)
 				- ""
 		]) },
 		{ RestoreDeallocCode = empty },	% always empty for nondet code
Index: code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.246
diff -u -b -r1.246 code_info.m
--- code_info.m	1999/12/14 04:52:33	1.246
+++ code_info.m	1999/12/27 23:43:24
@@ -1802,7 +1802,7 @@
 			],
 			MarkCode = node([
 				pragma_c([], Components, will_not_call_mercury,
-					no, no, no) - ""
+					pragma_boxed_float, no, no, no) - ""
 			])
 		;
 			UseMinimalModel = no,
@@ -1880,7 +1880,7 @@
 			],
 			CutCode = node([
 				pragma_c([], Components, will_not_call_mercury,
-					no, no, no)
+					pragma_boxed_float, no, no, no)
 					- "commit for temp frame hijack"
 			])
 		;
Index: dupelim.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.44
diff -u -b -r1.44 dupelim.m
--- dupelim.m	1999/11/15 00:42:21	1.44
+++ dupelim.m	1999/12/27 23:44:24
@@ -115,7 +115,7 @@
 	),
 	AddPragmaReferredLabels = lambda(
 		[Instr::in, FoldFixed0::in, FoldFixed::out] is det, (
-		( Instr = pragma_c(_, _, _, yes(FixedLabel), _, _) - _ ->
+		( Instr = pragma_c(_, _, _, _, yes(FixedLabel), _, _) - _ ->
 			set__insert(FoldFixed0, FixedLabel, FoldFixed)
 		;
 			FoldFixed = FoldFixed0
@@ -367,7 +367,7 @@
 		standardize_lval(Lval1, Lval),
 		Instr = join_and_continue(Lval, N)
 	;
-		Instr1 = pragma_c(_, _, _, _, _, _),
+		Instr1 = pragma_c(_, _, _, _, _, _, _),
 		Instr = Instr1
 	).
 
@@ -636,7 +636,7 @@
 		Instr2 = Instr1,
 		Instr = Instr1
 	;
-		Instr1 = pragma_c(_, _, _, _, _, _),
+		Instr1 = pragma_c(_, _, _, _, _, _, _),
 		Instr2 = Instr1,
 		Instr = Instr1
 	).
Index: frameopt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/frameopt.m,v
retrieving revision 1.74
diff -u -b -r1.74 frameopt.m
--- frameopt.m	1999/11/15 00:42:23	1.74
+++ frameopt.m	1999/12/27 23:44:35
@@ -539,7 +539,7 @@
 				Uinstr = c_code(_)
 			;
 				Uinstr = pragma_c(_, _, MayCallMercury,
-					MaybeFixed, _, NeedStack),
+					_, MaybeFixed, _, NeedStack),
 				(
 					MayCallMercury = may_call_mercury
 				;
@@ -668,7 +668,7 @@
 			Uinstr = call(_, _, _, _, _)
 		;
 			% Only may_call_mercury pragma_c's can clobber succip.
-			Uinstr = pragma_c(_, _, may_call_mercury, _, _, _)
+			Uinstr = pragma_c(_, _, may_call_mercury, _, _, _, _)
 		)
 	->
 		CanClobberSuccip = yes
Index: livemap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/livemap.m,v
retrieving revision 1.45
diff -u -b -r1.45 livemap.m
--- livemap.m	1999/11/15 00:42:28	1.45
+++ livemap.m	1999/12/27 23:44:41
@@ -356,7 +356,7 @@
 		DontValueNumber = yes
 	;
 		% XXX we shouldn't just give up here
-		Uinstr0 = pragma_c(_, _, _, _, _, _),
+		Uinstr0 = pragma_c(_, _, _, _, _, _, _),
 		Livemap = Livemap0,
 		Livevals = Livevals0,
 		Instrs = Instrs0,
Index: llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.255
diff -u -b -r1.255 llds.m
--- llds.m	1999/12/16 11:36:37	1.255
+++ llds.m	1999/12/27 23:13:55
@@ -342,8 +342,8 @@
 			% Decrement the det stack pointer.
 
 	;	pragma_c(list(pragma_c_decl), list(pragma_c_component),
-				may_call_mercury, maybe(label), maybe(label),
-				bool)
+				may_call_mercury, pragma_float_format,
+				maybe(label), maybe(label), bool)
 			% The first argument says what local variable
 			% declarations are required for the following
 			% components, which in turn can specify how
@@ -361,20 +361,24 @@
 			% can be performed across pragma_c instructions that
 			% cannot call Mercury.
 			%
+			% The fourth argument says how float arguments
+			% should be passed to and from C code: as floats
+			% for simplicity, or as words for performance.
+			%
 			% Some components in some pragma_c instructions
 			% refer to a Mercury label. If they do, we must
 			% prevent the label from being optimized away.
 			% To make it known to labelopt, we mention it in
-			% the fourth or the fifth arg. The fourth argument
+			% the fifth or the sixth arg. The fifth argument
 			% may give the name of a label whose name is fixed
 			% (e.g. because it embedded in raw C code or because it
 			% has associated an label layout structure), while
-			% the fifth may give the name of a label that can
+			% the sixth may give the name of a label that can
 			% be changed (because it is not mentioned in C code
 			% and has no associated layout structure, being
 			% mentioned only in pragma_c_fail_to components).
 			%
-			% The sixth argument says whether the contents
+			% The last argument says whether the contents
 			% of the pragma C code can refer to stack slots.
 			% User-written shouldn't refer to stack slots,
 			% the question is whether the compiler-generated
Index: llds_common.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_common.m,v
retrieving revision 1.26
diff -u -b -r1.26 llds_common.m
--- llds_common.m	1999/12/14 04:52:45	1.26
+++ llds_common.m	1999/12/27 23:44:48
@@ -259,7 +259,7 @@
 		Instr = Instr0,
 		Info = Info0
 	;
-		Instr0 = pragma_c(_, _, _, _, _, _),
+		Instr0 = pragma_c(_, _, _, _, _, _, _),
 		Instr = Instr0,
 		Info = Info0
 	).
Index: llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.133
diff -u -b -r1.133 llds_out.m
--- llds_out.m	1999/12/16 11:36:39	1.133
+++ llds_out.m	1999/12/27 23:26:32
@@ -1323,7 +1323,8 @@
 	output_rval_decls(Rval, "", "", 0, _, DeclSet0, DeclSet).
 output_instruction_decls(incr_sp(_, _), DeclSet, DeclSet) --> [].
 output_instruction_decls(decr_sp(_), DeclSet, DeclSet) --> [].
-output_instruction_decls(pragma_c(_, Comps, _, _, _, _), DeclSet0, DeclSet) -->
+output_instruction_decls(pragma_c(_, Comps, _, _, _, _, _),
+		DeclSet0, DeclSet) -->
 	output_pragma_c_component_list_decls(Comps, DeclSet0, DeclSet).
 output_instruction_decls(init_sync_term(Lval, _), DeclSet0, DeclSet) -->
 	output_lval_decls(Lval, "", "", 0, _, DeclSet0, DeclSet).
@@ -1648,10 +1649,10 @@
 	io__write_int(N),
 	io__write_string(");\n").
 
-output_instruction(pragma_c(Decls, Components, _, _, _, _), _) -->
+output_instruction(pragma_c(Decls, Components, _, FloatFormat, _, _, _), _) -->
 	io__write_string("\t{\n"),
-	output_pragma_decls(Decls),
-	output_pragma_c_components(Components),
+	output_pragma_decls(Decls, FloatFormat),
+	output_pragma_c_components(Components, FloatFormat),
 	io__write_string("\n\t}\n").
 
 output_instruction(init_sync_term(Lval, N), _) -->
@@ -1683,22 +1684,23 @@
 	io__write_string(");\n").
 
 :- pred output_pragma_c_components(list(pragma_c_component),
+	pragma_float_format, io__state, io__state).
+:- mode output_pragma_c_components(in, in, di, uo) is det.
+
+output_pragma_c_components([], _) --> [].
+output_pragma_c_components([C | Cs], FloatFormat) -->
+	output_pragma_c_component(C, FloatFormat),
+	output_pragma_c_components(Cs, FloatFormat).
+
+:- pred output_pragma_c_component(pragma_c_component, pragma_float_format,
 	io__state, io__state).
-:- mode output_pragma_c_components(in, di, uo) is det.
+:- mode output_pragma_c_component(in, in, di, uo) is det.
 
-output_pragma_c_components([]) --> [].
-output_pragma_c_components([C | Cs]) -->
-	output_pragma_c_component(C),
-	output_pragma_c_components(Cs).
-
-:- pred output_pragma_c_component(pragma_c_component, io__state, io__state).
-:- mode output_pragma_c_component(in, di, uo) is det.
-
-output_pragma_c_component(pragma_c_inputs(Inputs)) -->
-	output_pragma_inputs(Inputs).
-output_pragma_c_component(pragma_c_outputs(Outputs)) -->
-	output_pragma_outputs(Outputs).
-output_pragma_c_component(pragma_c_user_code(MaybeContext, C_Code)) -->
+output_pragma_c_component(pragma_c_inputs(Inputs), FloatFormat) -->
+	output_pragma_inputs(Inputs, FloatFormat).
+output_pragma_c_component(pragma_c_outputs(Outputs), FloatFormat) -->
+	output_pragma_outputs(Outputs, FloatFormat).
+output_pragma_c_component(pragma_c_user_code(MaybeContext, C_Code), _) -->
 	( { C_Code = "" } ->
 		[]
 	;
@@ -1716,39 +1718,47 @@
 			io__write_string(";}\n")
 		)
 	).
-output_pragma_c_component(pragma_c_raw_code(C_Code)) -->
+output_pragma_c_component(pragma_c_raw_code(C_Code), _) -->
 	io__write_string(C_Code).
-output_pragma_c_component(pragma_c_fail_to(Label)) -->
+output_pragma_c_component(pragma_c_fail_to(Label), _) -->
 	io__write_string("if (!r1) GOTO_LABEL("),
 	output_label(Label),
 	io__write_string(");\n").
-output_pragma_c_component(pragma_c_noop) --> [].
+output_pragma_c_component(pragma_c_noop, _) --> [].
 
 	% Output the local variable declarations at the top of the 
 	% pragma_c_code code.
-:- pred output_pragma_decls(list(pragma_c_decl), io__state, io__state).
-:- mode output_pragma_decls(in, di, uo) is det.
+:- pred output_pragma_decls(list(pragma_c_decl), pragma_float_format,
+	io__state, io__state).
+:- mode output_pragma_decls(in, in, di, uo) is det.
 
-output_pragma_decls([]) --> [].
-output_pragma_decls([D|Decls]) -->
+output_pragma_decls([], _) --> [].
+output_pragma_decls([Decl | Decls], FloatFormat) -->
 	(
-		{ D = pragma_c_arg_decl(Type, VarName) },
+		{ Decl = pragma_c_arg_decl(Type, VarName) },
 		% Apart from special cases, the local variables are Words
-		{ export__type_to_type_string(Type, VarType) },
+		{
+			Type = term__functor(term__atom("float"), [], _),
+			FloatFormat = pragma_boxed_float
+		->
+			VarType = "Word"
+		;
+			export__type_to_type_string(Type, VarType)
+		},
 		io__write_string("\t"),
 		io__write_string(VarType),
 		io__write_string("\t"),
 		io__write_string(VarName),
 		io__write_string(";\n")
 	;
-		{ D = pragma_c_struct_ptr_decl(StructTag, VarName) },
+		{ Decl = pragma_c_struct_ptr_decl(StructTag, VarName) },
 		io__write_string("\tstruct "),
 		io__write_string(StructTag),
 		io__write_string("\t*"),
 		io__write_string(VarName),
 		io__write_string(";\n")
 	),
-	output_pragma_decls(Decls).
+	output_pragma_decls(Decls, FloatFormat).
 
 	% Output declarations for any rvals used to initialize the inputs
 :- pred output_pragma_input_rval_decls(list(pragma_c_input), decl_set, decl_set,
@@ -1763,12 +1773,13 @@
 
 	% Output the input variable assignments at the top of the 
 	% pragma_c_code code.
-:- pred output_pragma_inputs(list(pragma_c_input), io__state, io__state).
-:- mode output_pragma_inputs(in, di, uo) is det.
+:- pred output_pragma_inputs(list(pragma_c_input), pragma_float_format,
+	io__state, io__state).
+:- mode output_pragma_inputs(in, in, di, uo) is det.
 
-output_pragma_inputs([]) --> [].
-output_pragma_inputs([I|Inputs]) -->
-	{ I = pragma_c_input(VarName, Type, Rval) },
+output_pragma_inputs([], _) --> [].
+output_pragma_inputs([Input | Inputs], FloatFormat) -->
+	{ Input = pragma_c_input(VarName, Type, Rval) },
 	io__write_string("\t"),
 	io__write_string(VarName),
 	io__write_string(" = "),
@@ -1778,14 +1789,15 @@
 		io__write_string("(String) "),
 		output_rval_as_type(Rval, word)
 	;
-        	{ Type = term__functor(term__atom("float"), [], _) }
+        	{ Type = term__functor(term__atom("float"), [], _) },
+		{ FloatFormat = pragma_unboxed_float }
 	->
 		output_rval_as_type(Rval, float)
 	;
 		output_rval_as_type(Rval, word)
 	),
 	io__write_string(";\n"),
-	output_pragma_inputs(Inputs).
+	output_pragma_inputs(Inputs, FloatFormat).
 
 	% Output declarations for any lvals used for the outputs
 :- pred output_pragma_output_lval_decls(list(pragma_c_output),
@@ -1800,12 +1812,13 @@
 
 	% Output the output variable assignments at the bottom of the
 	% pragma_c_code
-:- pred output_pragma_outputs(list(pragma_c_output), io__state, io__state).
-:- mode output_pragma_outputs(in, di, uo) is det.
+:- pred output_pragma_outputs(list(pragma_c_output), pragma_float_format,
+	io__state, io__state).
+:- mode output_pragma_outputs(in, in, di, uo) is det.
 
-output_pragma_outputs([]) --> [].
-output_pragma_outputs([O|Outputs]) --> 
-	{ O = pragma_c_output(Lval, Type, VarName) },
+output_pragma_outputs([], _) --> [].
+output_pragma_outputs([Output | Outputs], FloatFormat) --> 
+	{ Output = pragma_c_output(Lval, Type, VarName) },
 	io__write_string("\t"),
 	output_lval_as_word(Lval),
 	io__write_string(" = "),
@@ -1815,7 +1828,8 @@
 		io__write_string("(Word) "),
 		io__write_string(VarName)
 	;
-        	{ Type = term__functor(term__atom("float"), [], _) }
+        	{ Type = term__functor(term__atom("float"), [], _) },
+		{ FloatFormat = pragma_unboxed_float }
 	->
 		io__write_string("float_to_word("),
 		io__write_string(VarName),
@@ -1824,7 +1838,7 @@
 		io__write_string(VarName)
 	),
 	io__write_string(";\n"),
-	output_pragma_outputs(Outputs).
+	output_pragma_outputs(Outputs, FloatFormat).
 
 :- pred output_reset_trail_reason(reset_trail_reason, io__state, io__state).
 :- mode output_reset_trail_reason(in, di, uo) is det.
Index: middle_rec.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/middle_rec.m,v
retrieving revision 1.80
diff -u -b -r1.80 middle_rec.m
--- middle_rec.m	1999/11/15 00:42:37	1.80
+++ middle_rec.m	1999/12/27 23:45:14
@@ -424,7 +424,7 @@
 	middle_rec__find_used_registers_rval(Rval, Used0, Used).
 middle_rec__find_used_registers_instr(incr_sp(_, _), Used, Used).
 middle_rec__find_used_registers_instr(decr_sp(_), Used, Used).
-middle_rec__find_used_registers_instr(pragma_c(_, Components, _, _, _, _),
+middle_rec__find_used_registers_instr(pragma_c(_, Components, _, _, _, _, _),
 		Used0, Used) :-
 	middle_rec__find_used_registers_components(Components, Used0, Used).
 middle_rec__find_used_registers_instr(init_sync_term(Lval, _), Used0, Used) :-
Index: opt_debug.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.97
diff -u -b -r1.97 opt_debug.m
--- opt_debug.m	1999/11/15 00:42:40	1.97
+++ opt_debug.m	1999/12/28 00:10:48
@@ -956,7 +956,7 @@
 	opt_debug__dump_label(Label, LabelStr),
 	string__append_list(["join(", LvalStr, ", ", LabelStr, ")"], Str).
 % XXX  should probably give more info than this
-opt_debug__dump_instr(pragma_c(_, Comps, _, _, _, _), Str) :-
+opt_debug__dump_instr(pragma_c(_, Comps, _, _, _, _, _), Str) :-
 	opt_debug__dump_components(Comps, C_str),
 	string__append_list(["pragma_c(", C_str, ")"], Str).
 
Index: opt_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_util.m,v
retrieving revision 1.104
diff -u -b -r1.104 opt_util.m
--- opt_util.m	1999/11/15 00:42:41	1.104
+++ opt_util.m	1999/12/28 00:12:17
@@ -893,7 +893,7 @@
 		Uinstr0 = decr_sp(_),
 		Need = no
 	;
-		Uinstr0 = pragma_c(_, _, _, _, _, _),
+		Uinstr0 = pragma_c(_, _, _, _, _, _, _),
 		Need = no
 	;
 		Uinstr0 = init_sync_term(Lval, _),
@@ -1018,7 +1018,8 @@
 opt_util__can_instr_branch_away(fork(_, _, _), yes).
 opt_util__can_instr_branch_away(join_and_terminate(_), no).
 opt_util__can_instr_branch_away(join_and_continue(_, _), yes).
-opt_util__can_instr_branch_away(pragma_c(_, Comps, _, _, _, _), BranchAway) :-
+opt_util__can_instr_branch_away(pragma_c(_, Comps, _, _, _, _, _),
+		BranchAway) :-
 	opt_util__can_components_branch_away(Comps, BranchAway).
 
 :- pred opt_util__can_components_branch_away(list(pragma_c_component), bool).
@@ -1082,7 +1083,7 @@
 opt_util__can_instr_fall_through(fork(_, _, _), no).
 opt_util__can_instr_fall_through(join_and_terminate(_), no).
 opt_util__can_instr_fall_through(join_and_continue(_, _), no).
-opt_util__can_instr_fall_through(pragma_c(_, _, _, _, _, _), yes).
+opt_util__can_instr_fall_through(pragma_c(_, _, _, _, _, _, _), yes).
 
 	% Check whether an instruction sequence can possibly fall through
 	% to the next instruction without using its label.
@@ -1126,7 +1127,7 @@
 opt_util__can_use_livevals(fork(_, _, _), no).
 opt_util__can_use_livevals(join_and_terminate(_), no).
 opt_util__can_use_livevals(join_and_continue(_, _), no).
-opt_util__can_use_livevals(pragma_c(_, _, _, _, _, _), no).
+opt_util__can_use_livevals(pragma_c(_, _, _, _, _, _, _), no).
 
 % determine all the labels and code_addresses that are referenced by Instr
 
@@ -1187,7 +1188,7 @@
 opt_util__instr_labels_2(fork(Child, Parent, _), [Child, Parent], []).
 opt_util__instr_labels_2(join_and_terminate(_), [], []).
 opt_util__instr_labels_2(join_and_continue(_, Label), [Label], []).
-opt_util__instr_labels_2(pragma_c(_, _, _, MaybeFixLabel, MaybeSubLabel, _),
+opt_util__instr_labels_2(pragma_c(_, _, _, _, MaybeFixLabel, MaybeSubLabel, _),
 		Labels, []) :-
 	( MaybeFixLabel = yes(FixLabel) ->
 		( MaybeSubLabel = yes(SubLabel) ->
@@ -1244,7 +1245,7 @@
 opt_util__possible_targets(fork(Child, Parent, _), [Child, Parent]).
 opt_util__possible_targets(join_and_terminate(_), []).
 opt_util__possible_targets(join_and_continue(_, L), [L]).
-opt_util__possible_targets(pragma_c(_, _, _, MaybeFixLabel, MaybeSubLabel, _),
+opt_util__possible_targets(pragma_c(_,_,_,_, MaybeFixLabel, MaybeSubLabel, _),
 		Labels) :-
 	( MaybeFixLabel = yes(FixLabel) ->
 		( MaybeSubLabel = yes(SubLabel) ->
@@ -1291,7 +1292,7 @@
 opt_util__instr_rvals_and_lvals(fork(_, _, _), [], []).
 opt_util__instr_rvals_and_lvals(join_and_terminate(Lval), [], [Lval]).
 opt_util__instr_rvals_and_lvals(join_and_continue(Lval, _), [], [Lval]).
-opt_util__instr_rvals_and_lvals(pragma_c(_, Cs, _, _, _, _), Rvals, Lvals) :-
+opt_util__instr_rvals_and_lvals(pragma_c(_, Cs, _,_,_,_,_), Rvals, Lvals) :-
 	pragma_c_components_get_rvals_and_lvals(Cs, Rvals, Lvals).
 
 	% extract the rvals and lvals from the pragma_c_components
@@ -1436,7 +1437,7 @@
 	opt_util__count_temps_lval(Lval, R0, R, F0, F).
 opt_util__count_temps_instr(join_and_continue(Lval, _), R0, R, F0, F) :-
 	opt_util__count_temps_lval(Lval, R0, R, F0, F).
-opt_util__count_temps_instr(pragma_c(_, _, _, _, _, _), R, R, F, F).
+opt_util__count_temps_instr(pragma_c(_, _, _, _, _, _, _), R, R, F, F).
 
 :- pred opt_util__count_temps_lval(lval, int, int, int, int).
 :- mode opt_util__count_temps_lval(in, in, out, in, out) is det.
@@ -1543,7 +1544,7 @@
 		opt_util__touches_nondet_ctrl_lval(Lval, Touch)
 	; Uinstr = restore_hp(Rval) ->
 		opt_util__touches_nondet_ctrl_rval(Rval, Touch)
-	; Uinstr = pragma_c(_, Components, _, _, _, _) ->
+	; Uinstr = pragma_c(_, Components, _, _, _, _, _) ->
 		opt_util__touches_nondet_ctrl_components(Components, Touch)
 	;
 		Touch = yes
@@ -1879,8 +1880,9 @@
 		Replmap, _, join_and_continue(Lval, Label)) :-
 	opt_util__replace_labels_label(Label0, Replmap, Label),
 	opt_util__replace_labels_lval(Lval0, Replmap, Lval).
-opt_util__replace_labels_instr(pragma_c(A, Comps0, C, MaybeFix, MaybeSub0, F),
-		ReplMap, _, pragma_c(A, Comps, C, MaybeFix, MaybeSub, F)) :-
+opt_util__replace_labels_instr(
+		pragma_c(A, Comps0, C, D, MaybeFix, MaybeSub0, G), ReplMap, _,
+		pragma_c(A, Comps, C, D, MaybeFix, MaybeSub, G)) :-
 	(
 		MaybeFix = no
 	;
Index: pragma_c_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/pragma_c_gen.m,v
retrieving revision 1.33
diff -u -b -r1.33 pragma_c_gen.m
--- pragma_c_gen.m	1999/11/15 00:42:47	1.33
+++ pragma_c_gen.m	1999/12/27 23:17:37
@@ -335,6 +335,7 @@
 	%
 	{ may_call_mercury(Attributes, MayCallMercury) },
 	{ thread_safe(Attributes, ThreadSafe) },
+	{ pragma_float_format(Attributes, FloatFormat) },
 
 	%
 	% First we need to get a list of input and output arguments
@@ -485,7 +486,7 @@
 			CheckR1_Comp, RestoreRegsComp,
 			OutputComp, ProcLabelHashUndef] },
 	{ PragmaCCode = node([
-		pragma_c(Decls, Components, MayCallMercury, no,
+		pragma_c(Decls, Components, MayCallMercury, FloatFormat, no,
 			MaybeFailLabel, no)
 			- "Pragma C inclusion"
 	]) },
@@ -564,9 +565,10 @@
 	{ require(unify(CodeModel, model_non),
 		"inappropriate code model for nondet pragma C code") },
 	%
-	% Extract the may_call_mercury attribute
+	% Extract the relevant attributes
 	%
 	{ may_call_mercury(Attributes, MayCallMercury) },
+	{ pragma_float_format(Attributes, FloatFormat) },
 
 	%
 	% Generate #define MR_PROC_LABEL <procedure label> /* see note (5) */
@@ -752,7 +754,7 @@
 		],
 		CallBlockCode = node([
 			pragma_c(CallDecls, CallComponents,
-				MayCallMercury, no, no, yes)
+				MayCallMercury, FloatFormat, no, no, yes)
 				- "Call and shared pragma C inclusion"
 		]),
 
@@ -781,7 +783,7 @@
 		],
 		RetryBlockCode = node([
 			pragma_c(RetryDecls, RetryComponents,
-				MayCallMercury, no, no, yes)
+				MayCallMercury, FloatFormat, no, no, yes)
 				- "Retry and shared pragma C inclusion"
 		]),
 
@@ -838,7 +840,8 @@
 		],
 		CallBlockCode = node([
 			pragma_c(CallDecls, CallComponents,
-				MayCallMercury, yes(SharedLabel), no, yes)
+				MayCallMercury, FloatFormat,
+				yes(SharedLabel), no, yes)
 				- "Call pragma C inclusion"
 		]),
 
@@ -867,7 +870,8 @@
 		],
 		RetryBlockCode = node([
 			pragma_c(RetryDecls, RetryComponents,
-				MayCallMercury, yes(SharedLabel), no, yes)
+				MayCallMercury, FloatFormat,
+				yes(SharedLabel), no, yes)
 				- "Retry pragma C inclusion"
 		]),
 
@@ -895,7 +899,7 @@
 		],
 		SharedBlockCode = node([
 			pragma_c(SharedDecls, SharedComponents,
-				MayCallMercury, no, no, yes)
+				MayCallMercury, FloatFormat, no, no, yes)
 				- "Shared pragma C inclusion"
 		]),
 
Index: prog_data.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_data.m,v
retrieving revision 1.50
diff -u -b -r1.50 prog_data.m
--- prog_data.m	1999/11/11 23:12:09	1.50
+++ prog_data.m	1999/12/26 00:12:08
@@ -499,6 +499,13 @@
 		pragma_c_code_attributes).
 :- mode set_thread_safe(in, in, out) is det.
 
+:- pred pragma_float_format(pragma_c_code_attributes, pragma_float_format).
+:- mode pragma_float_format(in, out) is det.
+
+:- pred set_pragma_float_format(pragma_c_code_attributes, pragma_float_format,
+		pragma_c_code_attributes).
+:- mode set_pragma_float_format(in, in, out) is det.
+
 	% For pragma c_code, there are two different calling conventions,
 	% one for C code that may recursively call Mercury code, and another
 	% more efficient one for the case when we know that the C code will
@@ -514,6 +521,21 @@
 	--->	not_thread_safe
 	;	thread_safe.
 
+	% By default, float arguments are passed to and from pragma C code
+	% in unboxed form, for programmer convenience. However, sometimes
+	% one wants control over boxing and unboxing operations for efficiency,
+	% e.g. we want to avoid reboxing a float that has just been unboxed
+	% by the pragma C code interface.
+	%
+	% This type says whether floats are passed boxed or unboxed. If
+	% boxed, the float arguments will of type word, and you must call
+	% word_to_float for inputs and float_to_word for outputs to perform
+	% the required conversions. On machines that always use unboxed floats,
+	% the conversion will be a no-op.
+:- type pragma_float_format
+	--->	pragma_boxed_float
+	;	pragma_unboxed_float.
+
 :- type pragma_var    
 	--->	pragma_var(prog_var, string, mode).
 	  	% variable, name, mode
@@ -886,23 +908,32 @@
 :- type pragma_c_code_attributes
 	--->	attributes(
 			may_call_mercury,
-			thread_safe
+			thread_safe,
+			pragma_float_format
 		).
 
-default_attributes(attributes(may_call_mercury, not_thread_safe)).
+default_attributes(attributes(may_call_mercury, not_thread_safe,
+	pragma_unboxed_float)).
 
 may_call_mercury(Attrs, MayCallMercury) :-
-	Attrs = attributes(MayCallMercury, _).
+	Attrs = attributes(MayCallMercury, _, _).
 
 thread_safe(Attrs, ThreadSafe) :-
-	Attrs = attributes(_, ThreadSafe).
+	Attrs = attributes(_, ThreadSafe, _).
+
+pragma_float_format(Attrs, PragmaFloatFormat) :-
+	Attrs = attributes(_, _, PragmaFloatFormat).
 
-set_may_call_mercury(Attrs0, MayCallMercury, Attrs) :-
-	Attrs0 = attributes(_, ThreadSafe),
-	Attrs  = attributes(MayCallMercury, ThreadSafe).
-
-set_thread_safe(Attrs0, ThreadSafe, Attrs) :-
-	Attrs0 = attributes(MayCallMercury, _),
-	Attrs  = attributes(MayCallMercury, ThreadSafe).
+set_may_call_mercury(Attrs0, A, Attrs) :-
+	Attrs0 = attributes(_, B, C),
+	Attrs  = attributes(A, B, C).
+
+set_thread_safe(Attrs0, B, Attrs) :-
+	Attrs0 = attributes(A, _, C),
+	Attrs  = attributes(A, B, C).
+
+set_pragma_float_format(Attrs0, C, Attrs) :-
+	Attrs0 = attributes(A, B, _),
+	Attrs  = attributes(A, B, C).
 
 %-----------------------------------------------------------------------------%
Index: prog_io_pragma.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io_pragma.m,v
retrieving revision 1.21
diff -u -b -r1.21 prog_io_pragma.m
--- prog_io_pragma.m	1999/07/13 08:53:24	1.21
+++ prog_io_pragma.m	1999/12/28 00:46:24
@@ -691,6 +691,7 @@
 :- type collected_pragma_c_code_attribute
 	--->	may_call_mercury(may_call_mercury)
 	;	thread_safe(thread_safe)
+	;	pragma_float_format(pragma_float_format)
 	.
 
 :- pred parse_pragma_c_code_attributes_term(term, pragma_c_code_attributes).
@@ -715,10 +716,22 @@
 			% XXX an error message would be nice
 			fail
 		;
-			set_thread_safe(Attributes1, thread_safe, Attributes)
+			set_thread_safe(Attributes1, thread_safe, Attributes2)
 		)
 	;
-		Attributes = Attributes1
+		Attributes2 = Attributes1
+	),
+	( list__member(pragma_float_format(pragma_boxed_float), AttrList) ->
+		( list__member(pragma_float_format(pragma_unboxed_float),
+				AttrList) ->
+			% XXX an error message would be nice
+			fail
+		;
+			set_pragma_float_format(Attributes2,
+				pragma_boxed_float, Attributes)
+		)
+	;
+		Attributes = Attributes2
 	).
 
 :- pred parse_pragma_c_code_attributes_term0(term,
@@ -751,6 +764,8 @@
 		Flag = may_call_mercury(MayCallMercury)
 	; parse_threadsafe(Term, ThreadSafe) ->
 		Flag = thread_safe(ThreadSafe)
+	; parse_pragma_float_format(Term, PragmaFloatFormat) ->
+		Flag = pragma_float_format(PragmaFloatFormat)
 	;
 		fail
 	).
@@ -774,6 +789,14 @@
 	thread_safe).
 parse_threadsafe(term__functor(term__atom("not_thread_safe"), [], _),
 	not_thread_safe).
+
+:- pred parse_pragma_float_format(term, pragma_float_format).
+:- mode parse_pragma_float_format(in, out) is semidet.
+
+parse_pragma_float_format(term__functor(term__atom("boxed_float"), [], _),
+	pragma_boxed_float).
+parse_pragma_float_format(term__functor(term__atom("unboxed_float"), [], _),
+	pragma_unboxed_float).
 
 % parse a pragma c_code declaration
 
Index: trace.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trace.m,v
retrieving revision 1.29
diff -u -b -r1.29 trace.m
--- trace.m	1999/12/16 19:06:52	1.29
+++ trace.m	1999/12/28 00:13:31
@@ -423,7 +423,8 @@
 	),
 	TraceCode = node([
 		pragma_c([], [pragma_c_raw_code(TraceStmt)],
-			will_not_call_mercury, no, no, yes) - ""
+			will_not_call_mercury, pragma_boxed_float,
+			no, no, yes) - ""
 	])
 	}.
 
@@ -647,7 +648,8 @@
 				% by another label, and this way we can
 				% eliminate this other label.
 			pragma_c([], [pragma_c_raw_code(TraceStmt)],
-				may_call_mercury, yes(Label), no, yes)
+				may_call_mercury, pragma_boxed_float,
+				yes(Label), no, yes)
 				- ""
 		]),
 	Code = tree(ProduceCode, TraceCode)
Index: value_number.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/value_number.m,v
retrieving revision 1.100
diff -u -b -r1.100 value_number.m
--- value_number.m	1999/11/15 00:42:53	1.100
+++ value_number.m	1999/12/28 00:13:37
@@ -1101,7 +1101,7 @@
 value_number__boundary_instr(fork(_, _, _), yes).
 value_number__boundary_instr(join_and_terminate(_), yes).
 value_number__boundary_instr(join_and_continue(_, _), yes).
-value_number__boundary_instr(pragma_c(_, _, _, _, _, _), yes).
+value_number__boundary_instr(pragma_c(_, _, _, _, _, _, _), yes).
 
 %-----------------------------------------------------------------------------%
 
Index: vn_block.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_block.m,v
retrieving revision 1.61
diff -u -b -r1.61 vn_block.m
--- vn_block.m	1999/11/15 00:42:55	1.61
+++ vn_block.m	1999/12/28 00:13:51
@@ -360,7 +360,7 @@
 	vn_block__new_ctrl_node(vn_decr_sp(N), Livemap,
 		Params, VnTables0, VnTables,
 		Liveset0, Liveset, Tuple0, Tuple).
-vn_block__handle_instr(pragma_c(_, _, _, _, _, _),
+vn_block__handle_instr(pragma_c(_, _, _, _, _, _, _),
 		_Livemap, _Params, VnTables, VnTables, Liveset, Liveset,
 		SeenIncr, SeenIncr, Tuple, Tuple) :-
 	error("value numbering not supported for pragma_c").
@@ -918,7 +918,7 @@
 vn_block__is_ctrl_instr(fork(_, _, _), yes).
 vn_block__is_ctrl_instr(join_and_terminate(_), yes).
 vn_block__is_ctrl_instr(join_and_continue(_, _), yes).
-vn_block__is_ctrl_instr(pragma_c(_, _, _, _, _, _), no).
+vn_block__is_ctrl_instr(pragma_c(_, _, _, _, _, _, _), no).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: vn_cost.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_cost.m,v
retrieving revision 1.39
diff -u -b -r1.39 vn_cost.m
--- vn_cost.m	1999/11/15 00:42:55	1.39
+++ vn_cost.m	1999/12/28 00:13:57
@@ -178,7 +178,7 @@
 		Uinstr = decr_sp(_),
 		Cost = 0
 	;
-		Uinstr = pragma_c(_, _, _, _, _, _),
+		Uinstr = pragma_c(_, _, _, _, _, _, _),
 		error("pragma_c found in vn_block_cost")
 	;
 		Uinstr = init_sync_term(_, _),
Index: vn_filter.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_filter.m,v
retrieving revision 1.23
diff -u -b -r1.23 vn_filter.m
--- vn_filter.m	1999/11/15 00:42:56	1.23
+++ vn_filter.m	1999/12/28 00:14:16
@@ -153,7 +153,7 @@
 vn_filter__user_instr(discard_tickets_to(Rval), yes(Rval)).
 vn_filter__user_instr(incr_sp(_, _), no).
 vn_filter__user_instr(decr_sp(_), no).
-vn_filter__user_instr(pragma_c(_, _, _, _, _, _), _):-
+vn_filter__user_instr(pragma_c(_, _, _, _, _, _, _), _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__user_instr(init_sync_term(_, _), _):-
 	error("init_sync_term instruction in vn__filter").
@@ -221,7 +221,7 @@
 	error("non-user instruction in vn_filter__replace_in_user_instr").
 vn_filter__replace_in_user_instr(decr_sp(_), _, _, _) :-
 	error("non-user instruction in vn_filter__replace_in_user_instr").
-vn_filter__replace_in_user_instr(pragma_c(_, _, _, _, _, _), _, _, _):-
+vn_filter__replace_in_user_instr(pragma_c(_, _, _, _, _, _, _), _, _, _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__replace_in_user_instr(init_sync_term(_, _), _, _, _):-
 	error("init_sync_term instruction in vn__filter").
@@ -260,7 +260,7 @@
 vn_filter__defining_instr(discard_tickets_to(_), no).
 vn_filter__defining_instr(incr_sp(_, _), no).
 vn_filter__defining_instr(decr_sp(_), no).
-vn_filter__defining_instr(pragma_c(_, _, _, _, _, _), _):-
+vn_filter__defining_instr(pragma_c(_, _, _, _, _, _, _), _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__defining_instr(init_sync_term(_, _), _):-
 	error("init_sync_term instruction in vn__filter").
@@ -334,7 +334,7 @@
 	error("join_and_terminate instruction in vn_filter__replace_in_defining_instr").
 vn_filter__replace_in_defining_instr(join_and_continue(_, _), _, _, _):-
 	error("join_and_continue instruction in vn_filter__replace_in_defining_instr").
-vn_filter__replace_in_defining_instr(pragma_c(_, _, _, _, _, _), _, _, _):-
+vn_filter__replace_in_defining_instr(pragma_c(_, _, _, _, _, _, _), _, _, _) :-
 	error("inappropriate instruction in vn__filter").
 
 	% vn_filter__replace_in_lval(Lval0, Old, New, Lval):
Index: vn_verify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_verify.m,v
retrieving revision 1.23
diff -u -b -r1.23 vn_verify.m
--- vn_verify.m	1999/11/15 00:42:59	1.23
+++ vn_verify.m	1999/12/28 00:14:22
@@ -370,7 +370,7 @@
 		NoDeref = NoDeref0,
 		Tested = Tested0
 	;
-		Instr = pragma_c(_, _, _, _, _, _),
+		Instr = pragma_c(_, _, _, _, _, _, _),
 		error("found c_code in vn_verify__tags_instr")
 	).
 
cvs diff: Diffing notes
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list