Files
mercury/tests/hard_coded/setjmp_test.m
Fergus Henderson 4e44dfb287 Fix a bug with the handling of commits in the high-level C back-end.
Estimated hours taken: 12

Fix a bug with the handling of commits in the high-level C back-end.

It was implementing commits via calls to setjmp()/longjmp(),
but ANSI/ISO C says that longjmp() is allowed to clobber the values
of any non-volatile local variables in the function that called setjmp()
which have been modified between the setjmp() and the longjmp().

The fix is that whenever we generate a commit, we put it in its own
nested function, with the local variables (e.g. `succeeded',
plus any outputs from the goal that we're committing over)
remaining in the containing function.  This ensures that
none of the variables which get modified between the setjmp()
and the longjmp() and which get referenced after the longjmp()
are local variables in the function containing the setjmp().

[The obvious alternative of declaring the local variables in the
function containing setjmp() as `volatile' doesn't work, since
the assignments to those output variables may be deep in some
function called indirectly from the goal that we're committing
across, and assigning to a volatile-qualified variable via a
non-volatile pointer is undefined behaviour.  The only way to
make it work would be to be to declare *every* output argument
that we pass by reference as `volatile T *'.  But that would
impose distributed fat and would make interoperability difficult.]

compiler/options.m:
	Add a new option `--put-commits-in-own-function'.

compiler/handle_options.m:
	If the target is high-level C, set the
	`--put-commits-in-own-function' option.

compiler/ml_code_util.m:
	Add a routine for accessing the new option.

compiler/ml_code_gen.m:
	If the new option is set, generate each commit in its own
	nested function.

tests/hard_coded/Mmakefile:
tests/hard_coded/setjmp_test.m:
tests/hard_coded/setjmp_test.exp:
	A regression test.
	Previous versions of the compiler generated code for this test
	case that did the wrong thing on *some* systems.
2000-12-10 07:39:47 +00:00

30 lines
626 B
Mathematica

% This is a regression test:
% the compiler used to generate code for this in the hlc.gc grade
% which had undefined behaviour according to ANSI/ISO C,
% and which would in practice fail on some systems
% (e.g. alpha*-dec-osf3.2 with egcs-1.1.2).
:- module setjmp_test.
:- interface.
:- import_module io.
:- pred main(io__state::di, io__state::uo) is cc_multi.
:- implementation.
:- import_module std_util.
main -->
(if { p(X) } then
print("X = "), print(X), nl
;
print("no")
).
:- pragma inline(p/1).
:- pred p(int).
:- mode p(out) is nondet.
p(1) :- semidet_fail.
p(2) :- semidet_succeed.
p(3) :- semidet_fail.