for review: fix for stack traces in -O-1

Tyson Dowd trd at
Wed Apr 8 16:02:42 AEST 1998


Mark, want to review this one?

(Mark reported this bug, so he gets the honour of seeing it fixed. 
Isn't he lucky?).


Estimated hours taken: 3

Fix stack traces dying in -O-1.

error/1 is usually generated with no stack frame, but in -O-1 it is
generated with one (but doesn't need it).  error/1 passes
MR_dump_stack MR_succip and MR_sp, and MR_dump_stack assumes that
MR_succip is for the topmost stack frame, but if error/1 has a stack
frame, this is not true.

	Make sure the caller of MR_dump_stack has no stack frame
	by using handwritten code.  We call the handwritten code
	from error/1, and so we have the nice side effect that
	error now appears in the stack dump.

	Document that MR_dump_stack assumes the succip is for the
	topmost stack frame.

Index: library/require.m
RCS file: /home/staff/zs/imp/mercury/library/require.m,v
retrieving revision 1.19
diff -u -r1.19 require.m
--- require.m	1998/04/07 05:13:30	1.19
+++ require.m	1998/04/07 09:08:07
@@ -55,14 +55,41 @@
 % Hopefully error/1 won't be called often (!), so no point inlining it.
 :- pragma no_inline(error/1). 
-:- pragma c_code(error(Message::in), "
+error(Message) :- 
+	error_internal(Message).
+:- pred error_internal(string::in) is erroneous.
+% We define error using handwritten code in error_internal because we
+% need complete control over it if we want to call MR_dump_stack.  In
+% particular we don't want to have to explicitly tell MR_dump_stack whether
+% a stack frame was generated by its caller.  The easiest way to do
+% this is to make sure it wasn't.
+:- external(error_internal/1).
+:- pragma c_code("
+        init_entry(mercury__require__error_internal_1_0);
+/* code for predicate 'error'/1 in mode 0 */
+	String  Message;
+	Message = (String) r1;
 	fprintf(stderr, ""Software error: %s\\n"", Message);
 	MR_dump_stack(MR_succip, MR_sp, MR_curfr);
-	return 0;	/* suppress some dumb warnings */
 :- end_module require.
Index: runtime/mercury_stack_trace.h
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_stack_trace.h
--- mercury_stack_trace.h	1998/04/07 05:23:07	1.2
+++ mercury_stack_trace.h	1998/04/07 09:12:14
@@ -16,8 +16,21 @@
 ** MR_dump_stack:
-** 	Given the succip and det stack pointer, generate a stack dump
-** 	showing then name of each active procedure on the stack.
+** 	Given the succip, det stack pointer and current frame, generate a 
+** 	stack dump showing then name of each active procedure on the
+** 	stack.
+** 	NOTE: MR_dump_stack will assume that the succip is for the
+** 	topmost stack frame.  If you call MR_dump_stack from some
+** 	pragma c_code that may not be the case.
+** 	Due to some optimizations (or lack thereof) the MR_dump_stack call 
+** 	may end up inside code that has a stack frame allocated, but a
+** 	has a succip for the previous stack frame.
+** 	Don't call MR_dump_stack from Mercury pragma c_code (calling
+** 	from other C code in the runtime is probably ok, provided the
+** 	succip corresponds to the topmost stack frame).
+** 	If you need more convienent calling from Mercury code, it would
+** 	probably be best to make an impure predicate defined as using
+** 	`:- external'.
 extern void MR_dump_stack(Code *success_pointer, Word *det_stack_pointer,

       Tyson Dowd           # There isn't any reason why Linux can't be
                            # implemented as an enterprise computing solution.
     trd at        # Find out what you've been missing while you've # been rebooting Windows NT. -- InfoWorld, 1998.

More information about the developers mailing list