[m-rev.] diff: fix obscure MLDS back-end bug

Fergus Henderson fjh at cs.mu.OZ.AU
Sun May 27 03:17:09 AEST 2001


Estimated hours taken: 8
Branches: main

Fix a bug where the MLDS back-end was generating incorrect code when you
pass an argument of type `float' to procedure expecting a polymorphically
typed parameter with mode `unused'.

This bug broke the test cases that used `--trace rep' in
tests/debugger/declarative, if you built the compiler with `--target asm',
because the stage 1 compiler got miscompiled.

compiler/ml_call_gen.m:
	Don't unbox arguments that whose mode is top_unused.

tests/hard_coded/Mmakefile:
tests/hard_coded/unused_float_box_test.m:
tests/hard_coded/unused_float_box_test.exp:
	A regression test.

Workspace: /home/mars/fjh/ws1/mercury
Index: compiler/ml_call_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_call_gen.m,v
retrieving revision 1.21
diff -u -d -r1.21 ml_call_gen.m
--- compiler/ml_call_gen.m	2001/05/02 11:36:35	1.21
+++ compiler/ml_call_gen.m	2001/05/26 15:22:51
@@ -637,16 +637,23 @@
 			{ ConvOutputStatements = ConvOutputStatements1 }
 		;
 			%
-			% it's an output argument
+			% it's an output argument, or an unused argument
 			%
 			ml_gen_box_or_unbox_lval(CallerType, CalleeType,
 				VarLval, VarName, Context, ArgLval,
 				ThisArgConvDecls, _ThisArgConvInput,
 				ThisArgConvOutput),
-			{ ConvDecls = list__append(ThisArgConvDecls,
-				ConvDecls1) },
-			{ ConvOutputStatements = list__append(
-				ThisArgConvOutput, ConvOutputStatements1) },
+			{ ConvDecls = ThisArgConvDecls ++ ConvDecls1 },
+			{ ConvOutputStatements =
+				(if ArgMode = top_out then
+					ThisArgConvOutput
+				else
+					% don't unbox arguments
+					% with mode `top_unused'
+					[]
+				)
+				++ ConvOutputStatements1 },
+
 			ml_gen_info_get_globals(Globals),
 			{ CopyOut = get_copy_out_option(Globals, CodeModel) },
 			(
@@ -654,6 +661,10 @@
 					%
 					% if the target language allows
 					% multiple return values, then use them
+					%
+					% XXX for top_unused argument modes,
+					% the generated code will copy an
+					% uninitialized value
 					%
 					{ CopyOut = yes }
 				;
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.116
diff -u -d -r1.116 Mmakefile
--- tests/hard_coded/Mmakefile	2001/05/16 17:28:40	1.116
+++ tests/hard_coded/Mmakefile	2001/05/26 17:02:57
@@ -118,6 +118,7 @@
 	type_qual \
 	type_spec_modes \
 	type_to_term_bug \
+	unused_float_box_test \
 	user_defined_equality \
 	user_defined_equality2 \
 	write \
@@ -191,6 +192,7 @@
 MCFLAGS-existential_float = --infer-all
 MCFLAGS-user_defined_equality	= --infer-all
 MCFLAGS-parse		=	--trace deep
+MCFLAGS-unused_float_box_test =	--infer-all
 
 # In grade `none' with options `-O1 --opt-space' on kryten
 # (a sparc-sun-solaris2.5 system), mode_choice needs to be linked
Index: tests/hard_coded/unused_float_box_test.exp
===================================================================
RCS file: unused_float_box_test.exp
diff -N unused_float_box_test.exp
--- /dev/null	Wed Apr 11 00:52:25 2001
+++ unused_float_box_test.exp	Sun May 27 03:03:31 2001
@@ -0,0 +1 @@
+my_functor_float(42.0000000000000)
Index: tests/hard_coded/unused_float_box_test.m
===================================================================
RCS file: unused_float_box_test.m
diff -N unused_float_box_test.m
--- /dev/null	Wed Apr 11 00:52:25 2001
+++ unused_float_box_test.m	Sun May 27 02:58:50 2001
@@ -0,0 +1,132 @@
+% This is a regression test (extracted from some code in std_util.m).
+% The MLDS back-end in Mercury 0.10.1 generated incorrect code
+% for this test case.  In particular when the float argument is
+% passed to private_builtin__var(T::unused), it generated code
+% which passes a pointer and then tries to unbox the float value returned,
+% even though no value was actually returned, so it ends up dereferencing
+% an uninitialized pointer.
+
+:- module unused_float_box_test.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- import_module std_util.
+
+:- type my_functor_tag_info
+        --->    my_functor_integer(int)
+        ;       my_functor_float(float)
+        ;       my_functor_string(string)
+        ;       my_functor_enum(int)
+        ;       my_functor_local(int, int)
+        ;       my_functor_remote(int, int, list(univ))
+        ;       my_functor_unshared(int, list(univ))
+        ;       my_functor_notag(univ)
+        ;       my_functor_equiv(univ).
+
+:- pred my_get_functor_info(my_univ::in, my_functor_tag_info::out) is semidet.
+
+:- implementation.
+:- import_module list, int.
+
+main -->
+	wipe_stack(200),
+	( { my_get_functor_info('new my_univ_cons'(42.0), R) } ->
+		print(R), nl
+	;
+		print("failed"), nl
+	).
+
+:- pred wipe_stack(int, io__state, io__state).
+wipe_stack(N) -->
+	( if { N =< 0 } then []
+	else wipe_stack(N - 1), wipe_stack(N // 10 - 1)
+	).
+
+:- pragma no_inline(my_get_functor_info/2).
+my_get_functor_info(Univ, FunctorInfo) :-
+    ( my_univ_to_type(Univ, Int) ->
+        FunctorInfo = my_functor_integer(Int)
+    ; my_univ_to_type(Univ, Float) ->
+        FunctorInfo = my_functor_float(Float)
+    ; my_univ_to_type(Univ, String) ->
+        FunctorInfo = my_functor_string(String)
+    ; get_enum_functor_info(Univ, Enum) ->
+        FunctorInfo = my_functor_enum(Enum)
+    ; get_du_functor_info(Univ, Where, Ptag, Sectag, Args) ->
+        ( Where = 0 ->
+            FunctorInfo = my_functor_unshared(Ptag, Args)
+        ; Where > 0 ->
+            FunctorInfo = my_functor_remote(Ptag, Sectag, Args)
+        ;
+            FunctorInfo = my_functor_local(Ptag, Sectag)
+        )
+    ; get_notag_functor_info(Univ, ExpUniv) ->
+        FunctorInfo = my_functor_notag(ExpUniv)
+    ; get_equiv_functor_info(Univ, ExpUniv) ->
+        FunctorInfo = my_functor_equiv(ExpUniv)
+    ;
+        fail
+    ).
+
+:- pred get_notag_functor_info(Univ::in, ExpUniv::out) is semidet.
+
+:- pragma foreign_proc("C", 
+	get_notag_functor_info(_Univ::in, _ExpUniv::out),
+	will_not_call_mercury, "
+{
+	abort();
+}").
+
+    % from the type stored in the univ.)
+:- pred get_equiv_functor_info(Univ::in, ExpUniv::out) is semidet.
+
+:- pragma foreign_proc("C",
+	get_equiv_functor_info(_Univ::in, _ExpUniv::out),
+    will_not_call_mercury, "
+{
+	abort();
+}").
+
+:- pred get_enum_functor_info(Univ::in, Int::out) is semidet.
+
+:- pragma foreign_proc("C",
+	get_enum_functor_info(_Univ::in, _Enum::out),
+	will_not_call_mercury, "
+{
+	abort();
+}").
+
+:- pred get_du_functor_info(my_univ::in, int::out, int::out, int::out,
+    list(univ)::out) is semidet.
+
+:- pragma foreign_proc("C", get_du_functor_info(_Univ::in, _Where::out,
+    _Ptag::out, _Sectag::out, _Args::out), will_not_call_mercury, "
+{
+	abort();
+}").
+
+%------------------------------------------------------------------------------%
+
+:- type my_univ --->
+	some [T] my_univ_cons(T).
+
+my_univ_to_type(Univ, X) :- my_type_to_univ(X, Univ).
+
+:- pred my_type_to_univ(T, my_univ).
+:- pragma promise_pure(my_type_to_univ/2).
+my_type_to_univ(T, Univ) :-
+	(
+		impure private_builtin__var(T),
+		Univ = my_univ_cons(T0),
+		private_builtin__typed_unify(T0, T)
+	;
+		impure private_builtin__var(Univ),
+		Univ0 = 'new my_univ_cons'(T),
+		unsafe_promise_unique(Univ0, Univ)
+	).
+
+%------------------------------------------------------------------------------%
+%------------------------------------------------------------------------------%

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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