[m-rev.] diff: Fix bug #309

Paul Bone paul at bone.id.au
Tue Jan 28 15:06:26 AEDT 2014


Fix bug #309

Make existential casts from dummy types assign the value NULL rather than
reading a bogus value.

Bug #309 occurs when a dummy type is existentially quantified and the
resulting existentially typed value needs to get placed on the stack for
some reason.  The stack slot chosen in these cases has a negative stack slot
number, as it was allocated for the dummy typed value, this can cause the
code generator to crash.

We fix this by transforming an existential cast from a dummy type to an
assignment of the value zero during LLDS code generation.  Normally these
casts are transformed to copies from the old variable's rval into the new
variable's lval.  This fixes the problem because a constant such as zero
does not need a stack slot.  Using zero rather than an arbitrary value (that
may have been left in a register) may also minimise the amount of pointers
kept to memory that could be freed.

compiler/call_gen.m:
    As above.

tests/valid/exists_dummy.m:
tests/valid/Mmakefile:
    Added a test case for bug #309
---
 compiler/call_gen.m        | 16 +++++++++++++++-
 tests/valid/Mmakefile      |  1 +
 tests/valid/exists_dummy.m | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 tests/valid/exists_dummy.m

diff --git a/compiler/call_gen.m b/compiler/call_gen.m
index 2455d93..d07f1da 100644
--- a/compiler/call_gen.m
+++ b/compiler/call_gen.m
@@ -183,7 +183,21 @@ generate_generic_call(OuterCodeModel, GenericCall, Args, Modes,
     ;
         GenericCall = cast(_),
         ( Args = [InputArg, OutputArg] ->
-            generate_assign_builtin(OutputArg, leaf(InputArg), Code, !CI)
+            get_module_info(!.CI, ModuleInfo),
+            get_proc_info(!.CI, ProcInfo),
+            proc_info_get_vartypes(ProcInfo, VarTypes),
+            ( var_is_of_dummy_type(ModuleInfo, VarTypes, InputArg) ->
+                % Dummy types don't actually have values, which is
+                % normally harmless. However using the constant zero means
+                % that we don't need to allocate space for an existentially
+                % typed version of a dummy type.  Using the constant zero
+                % also avoids keeping pointers to memory that could be
+                % freed.
+                Rval = int_const(0)
+            ;
+                Rval = leaf(InputArg)
+            ),
+            generate_assign_builtin(OutputArg, Rval, Code, !CI)
         ;
             unexpected($module, $pred, "invalid type/inst cast call")
         )
diff --git a/tests/valid/Mmakefile b/tests/valid/Mmakefile
index bbb6b66..f4feefb 100644
--- a/tests/valid/Mmakefile
+++ b/tests/valid/Mmakefile
@@ -22,6 +22,7 @@ TYPECLASS_PROGS= \
 	bug271 \
 	complex_constraint \
 	exists_bug \
+	exists_dummy \
 	exists_fundeps \
 	exists_fundeps_2 \
 	exists_fundeps_3 \
diff --git a/tests/valid/exists_dummy.m b/tests/valid/exists_dummy.m
new file mode 100644
index 0000000..fb4fff1
--- /dev/null
+++ b/tests/valid/exists_dummy.m
@@ -0,0 +1,37 @@
+:- module exists_dummy.
+
+% Test for Bug #309, existentially quantifying a dummy variable such as
+% store(S) can cause the compiler to crash if the variable's register is
+% clubbered and the value needs to be retrived from the stack,.
+
+:- interface.
+:- import_module map, string, store.
+
+:- type lisp_val ---> lisp_val.
+
+:- type mappings(S) == generic_mutvar(map(string, lisp_val), S).
+
+:- type environment(S) ---> root_environment(mappings(S))
+                          ; child_environment(environment(S), mappings(S)).
+
+:- some[S] pred root_env(environment(S)::out, S::uo) is det => store(S).
+
+:- implementation.
+
+root_env(Environment, Store) :-
+    store.init(Store0),
+    store.new_mutvar(map.init, Mappings, Store0, Store),
+    Environment = root_environment(Mappings).
+
+/*
+$ mmc -C environment.m
+
+Making Mercury/int3s/environment.int3
+Making Mercury/ints/environment.int
+Making Mercury/cs/environment.c
+Uncaught Mercury exception:
+Software Error: ll_backend.llds_out.llds_out_data: predicate `ll_backend.llds_out.llds_out_data.output_lval'/4: Unexpected: stack var out of range
+Stack dump not available in this grade.
+** Error making `Mercury/cs/environment.c'.
+make: *** [all] Error 1
+*/
-- 
1.8.5.2




More information about the reviews mailing list