for review: mdb support for exceptions
Fergus Henderson
fjh at cs.mu.OZ.AU
Wed Dec 9 22:44:43 AEDT 1998
Hi,
Could someone (Mark?) please review this one for me?
--------------------
Estimated hours taken: 8
Add support for exceptions to the debugger, and
add support for debugging to the exception module.
browser/debugger_interface.m:
Add `exception' to the trace_port_type enumeration.
runtime/mercury_trace_base.h:
Add MR_PORT_EXCEPTION to the MR_Trace_Port enumeration.
trace/mercury_trace_internal.c:
trace/mercury_trace.h:
trace/mercury_trace.c:
Modify the code to handle MR_PORT_EXCEPTION.
extras/exceptions/exception.m:
- Define stack layout structures for the hand-written procedures
`builtin_throw' and `builtin_catch'.
- Use mktempframe() rather than mkframe() to allocate the temporary
frames used to prevent hijacking of the exception-catching frame
(this is more efficient, and avoids the need to give a stack
layout for those frames).
- Change the code for builtin_throw/1 so that if MR_trace_enabled
is true, it calls a new function trace_throw(), which calls
MR_trace(..., MR_PORT_EXCEPTION, ...) for each stack frame.
- Fix some type errors occurring for non-GC grades.
- Fix some uses of obsolete names (e.g. replace `hp' with `MR_hp').
runtime/mercury_trace_base.c:
compiler/trace.m:
Add some comments relating to the above changes.
--- ../mercury-compiler-0.8/browser/debugger_interface.m Fri Oct 16 16:16:50 1998
+++ browser/debugger_interface.m Sat Nov 21 03:52:09 1998
@@ -56,6 +56,7 @@
; switch
; nondet_pragma_first
; nondet_pragma_later
+ ; exception
.
:- type goal_path_string == string.
--- ../mercury-compiler-0.8/compiler/trace.m Mon Nov 16 00:34:12 1998
+++ compiler/trace.m Sat Nov 21 03:51:54 1998
@@ -52,7 +52,7 @@
% The kinds of external ports for which the code we generate will
% call MR_trace. The redo port is not on this list, because for that
% port the code that calls MR_trace is not in compiler-generated code,
- % but in the runtime system.
+ % but in the runtime system. Likewise for the exception port.
:- type external_trace_port
---> call
; exit
--- ../mercury-compiler-0.8/extras/exceptions/exception.m Thu Jul 23 00:31:59 1998
+++ extras/exceptions/exception.m Wed Dec 9 12:24:32 1998
@@ -471,13 +471,96 @@
:- pragma c_code("
+Define_extern_entry(exception_handler_do_fail);
+
+/*
+** MR_trace_throw():
+** Unwind the stack as far as possible, until we reach a frame
+** with an exception handler. As we go, invoke
+** `MR_trace(..., MR_PORT_EXCEPTION, ...)' for each stack frame,
+** to signal to the debugger that that procedure has exited via
+** an exception. This allows to user to use the `retry' command
+** to restart a goal which exited via an exception.
+**
+** Note that if MR_STACK_TRACE is not defined, then we may not be
+** able to traverse the stack all the way; in that case, we just
+** print a warning and then continue. It might be better to just
+** `#ifdef' out all this code (and the code in builtin_throw which
+** calls it) if MR_STACK_TRACE is not defined.
+*/
+
+#define WARNING(msg) \\
+ fprintf(stderr, ""mdb: warning: %s\\n"" \\
+ ""This may result in some exception events\\n"" \\
+ ""being omitted from the trace.\\n"", (msg))
+
+static Code *
+MR_trace_throw(Code *success_pointer, Word *det_stack_pointer,
+ Word *current_frame)
+{
+ const MR_Internal *label;
+ const MR_Stack_Layout_Label *return_label_layout;
+
+ /*
+ ** Find the layout info for the stack frame pointed to by MR_succip
+ */
+ label = MR_lookup_internal_by_addr(success_pointer);
+ if (label == NULL) {
+ WARNING(""internal label not found\\n"");
+ return NULL;
+ }
+ return_label_layout = label->i_layout;
+
+ while (return_label_layout != NULL) {
+ const MR_Stack_Layout_Entry *entry_layout;
+ Code *MR_jumpaddr;
+ MR_Stack_Walk_Step_Result result;
+ const char *problem;
+
+ /*
+ ** check if we've reached a frame with an exception handler
+ */
+ entry_layout = return_label_layout->MR_sll_entry;
+ if (!MR_DETISM_DET_STACK(entry_layout->MR_sle_detism)
+ && MR_redoip_slot(current_frame) ==
+ ENTRY(exception_handler_do_fail))
+ {
+ return NULL;
+ }
+
+ /*
+ ** invoke MR_trace() to trace the exception
+ */
+ MR_jumpaddr = MR_trace(return_label_layout, MR_PORT_EXCEPTION,
+ """", 0);
+ if (MR_jumpaddr != NULL) {
+ return MR_jumpaddr;
+ }
+
+ /*
+ ** unwind the stacks back to the previous stack frame
+ */
+ result = MR_stack_walk_step(entry_layout, &return_label_layout,
+ &det_stack_pointer, ¤t_frame, &problem);
+ if (result != STEP_OK) {
+ WARNING(problem);
+ return NULL;
+ }
+ restore_transient_registers();
+ MR_sp = det_stack_pointer;
+ MR_curfr = current_frame;
+ save_transient_registers();
+ }
+ return NULL;
+}
+
enum CodeModel { MODEL_DET, MODEL_SEMI, MODEL_NON };
/* swap the heap with the solutions heap */
#define swap_heaps() \\
{ \\
/* save the current heap */ \\
- Word *swap_heaps_temp_hp = hp; \\
+ Word *swap_heaps_temp_hp = MR_hp; \\
MemoryZone *swap_heaps_temp_hp_zone = MR_heap_zone; \\
\\
/* set heap to solutions heap */ \\
@@ -503,14 +586,14 @@
Word ticket_counter;
#endif
#ifndef CONSERVATIVE_GC
- Word heap_ptr;
- Word solns_heap_ptr;
- Word heap_zone;
+ Word *heap_ptr;
+ Word *solns_heap_ptr;
+ MemoryZone *heap_zone;
#endif
} Exception_Handler_Frame;
-#define FRAMEVARS \
- (((Exception_Handler_Frame *) (curfr - NONDET_FIXED_SIZE)) - 1)
+#define FRAMEVARS \\
+ (((Exception_Handler_Frame *) (MR_curfr - MR_NONDET_FIXED_SIZE)) - 1)
Define_extern_entry(mercury__exception__builtin_catch_3_0); /* det */
Define_extern_entry(mercury__exception__builtin_catch_3_1); /* semidet */
@@ -521,75 +604,88 @@
Define_extern_entry(mercury__exception__builtin_throw_1_0);
-Define_extern_entry(exception_handler_do_fail);
-
/* the following are defined in runtime/mercury_ho_call.c */
Declare_entry(do_call_det_closure);
Declare_entry(do_call_semidet_closure);
Declare_entry(do_call_nondet_closure);
-Declare_label(mercury__exception__builtin_catch_3_2_i1);
+/* the following is defined in runtime/mercury_trace_base.c */
+Declare_entry(MR_do_trace_redo_fail);
+
Declare_label(mercury__exception__builtin_catch_3_2_i2);
-Declare_label(mercury__exception__builtin_catch_3_3_i1);
Declare_label(mercury__exception__builtin_catch_3_3_i2);
-Declare_label(mercury__exception__builtin_catch_3_5_i1);
Declare_label(mercury__exception__builtin_catch_3_5_i2);
#ifdef MR_USE_TRAIL
Declare_label(mercury__exception__builtin_catch_3_5_i3);
#endif
-#ifndef COMPACT_ARGS
- Declare_label(mercury__exception__builtin_throw_1_0_i1);
- Declare_label(mercury__exception__builtin_throw_1_0_i2);
- Declare_label(mercury__exception__builtin_throw_1_0_i3);
-#endif
-
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__exception__builtin_catch_3_0)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__exception__builtin_catch_3_1)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__exception__builtin_catch_3_2)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__exception__builtin_catch_3_3)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__exception__builtin_catch_3_4)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__exception__builtin_catch_3_5)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__exception__builtin_throw_1_0)
-MR_MAKE_STACK_LAYOUT_ENTRY(exception_handler_do_fail)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__exception__builtin_catch_3_0)
-
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_catch_3_2, 1)
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_catch_3_2, 2)
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_catch_3_3, 1)
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_catch_3_3, 2)
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_catch_3_5, 1)
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_catch_3_5, 2)
-#ifdef MR_USE_TRAIL
- MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_catch_3_5, 3)
+Declare_label(mercury__exception__builtin_throw_1_0_i1);
+
+#ifdef COMPACT_ARGS
+ #define BUILTIN_THROW_STACK_SIZE 1
+#else
+ #define BUILTIN_THROW_STACK_SIZE 2
#endif
+
+
+/*
+** MR_MAKE_PROC_LAYOUT(entry, detism, slots, succip_locn, pred_or_func,
+** module, name, arity, mode)
+*/
+/* do we need one for exception_handler_do_fail? */
+
+MR_MAKE_PROC_LAYOUT(mercury__exception__builtin_throw_1_0,
+ MR_DETISM_DET, BUILTIN_THROW_STACK_SIZE, MR_LIVE_LVAL_STACKVAR(1),
+ MR_PREDICATE, ""exception"", ""builtin_throw"", 1, 0);
+MR_MAKE_INTERNAL_LAYOUT(mercury__exception__builtin_throw_1_0, 1);
#ifndef COMPACT_ARGS
- MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_throw_1_0, 1)
- MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_throw_1_0, 2)
- MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_throw_1_0, 3)
+ MR_MAKE_INTERNAL_LAYOUT(mercury__exception__builtin_throw_1_0, 2);
+ MR_MAKE_INTERNAL_LAYOUT(mercury__exception__builtin_throw_1_0, 3);
+#endif
+
+/*
+** The following procedures all allocate their stack frames on
+** the nondet stack, so for the purposes of doing stack traces
+** we say they have MR_DETISM_NON, even though they are not
+** actually nondet.
+*/
+MR_MAKE_PROC_LAYOUT(mercury__exception__builtin_catch_3_2,
+ MR_DETISM_NON, /* really cc_multi; also used for det */
+ MR_ENTRY_NO_SLOT_COUNT, MR_LVAL_TYPE_UNKNOWN,
+ MR_PREDICATE, ""exception"", ""builtin_catch"", 3, 2);
+MR_MAKE_PROC_LAYOUT(mercury__exception__builtin_catch_3_3,
+ MR_DETISM_NON, /* really cc_nondet; also used for semidet */
+ MR_ENTRY_NO_SLOT_COUNT, MR_LVAL_TYPE_UNKNOWN,
+ MR_PREDICATE, ""exception"", ""builtin_catch"", 3, 3);
+MR_MAKE_PROC_LAYOUT(mercury__exception__builtin_catch_3_5,
+ MR_DETISM_NON, /* ; also used for multi */
+ MR_ENTRY_NO_SLOT_COUNT, MR_LVAL_TYPE_UNKNOWN,
+ MR_PREDICATE, ""exception"", ""builtin_catch"", 3, 5);
+
+MR_MAKE_INTERNAL_LAYOUT(mercury__exception__builtin_catch_3_2, 1);
+MR_MAKE_INTERNAL_LAYOUT(mercury__exception__builtin_catch_3_2, 2);
+MR_MAKE_INTERNAL_LAYOUT(mercury__exception__builtin_catch_3_3, 1);
+MR_MAKE_INTERNAL_LAYOUT(mercury__exception__builtin_catch_3_3, 2);
+MR_MAKE_INTERNAL_LAYOUT(mercury__exception__builtin_catch_3_5, 1);
+MR_MAKE_INTERNAL_LAYOUT(mercury__exception__builtin_catch_3_5, 2);
+#ifdef MR_USE_TRAIL
+ MR_MAKE_INTERNAL_LAYOUT(mercury__exception__builtin_catch_3_5, 3);
#endif
BEGIN_MODULE(exceptions_module)
init_entry(mercury__exception__builtin_catch_3_0);
init_entry(mercury__exception__builtin_catch_3_1);
- init_entry(mercury__exception__builtin_catch_3_2);
- init_entry(mercury__exception__builtin_catch_3_3);
+ init_entry_sl(mercury__exception__builtin_catch_3_2);
+ init_entry_sl(mercury__exception__builtin_catch_3_3);
init_entry(mercury__exception__builtin_catch_3_4);
- init_entry(mercury__exception__builtin_catch_3_5);
- init_label(mercury__exception__builtin_catch_3_2_i1);
- init_label(mercury__exception__builtin_catch_3_2_i2);
- init_label(mercury__exception__builtin_catch_3_3_i1);
- init_label(mercury__exception__builtin_catch_3_3_i2);
- init_label(mercury__exception__builtin_catch_3_5_i1);
- init_label(mercury__exception__builtin_catch_3_5_i2);
+ init_entry_sl(mercury__exception__builtin_catch_3_5);
+ init_label_sl(mercury__exception__builtin_catch_3_2_i2);
+ init_label_sl(mercury__exception__builtin_catch_3_3_i2);
+ init_label_sl(mercury__exception__builtin_catch_3_5_i2);
#ifdef MR_USE_TRAIL
init_label(mercury__exception__builtin_catch_3_5_i3);
#endif
init_entry(mercury__exception__builtin_throw_1_0);
-#ifndef COMPACT_ARGS
init_label(mercury__exception__builtin_throw_1_0_i1);
- init_label(mercury__exception__builtin_throw_1_0_i2);
- init_label(mercury__exception__builtin_throw_1_0_i3);
-#endif
init_entry(exception_handler_do_fail);
BEGIN_CODE
@@ -650,8 +746,7 @@
** can avoid this by creating a second frame above the special
** frame.)
*/
- succip = LABEL(mercury__exception__builtin_catch_3_2_i1);
- mkframe(""builtin_catch_2/1 [model_det]"", 0, ENTRY(do_fail));
+ mktempframe(ENTRY(do_fail));
/*
** Now call `Goal(Result)'.
@@ -676,9 +771,6 @@
#endif
succeed_discard();
-Define_label(mercury__exception__builtin_catch_3_2_i1);
- succeed_discard();
-
/*
** builtin_catch(Goal, Handler, Result)
** call Goal(R).
@@ -747,8 +839,7 @@
** can avoid this by creating a second frame above the special
** frame.)
*/
- succip = LABEL(mercury__exception__builtin_catch_3_3_i1);
- mkframe(""builtin_catch_2/1 [model_semi]"", 0, ENTRY(do_fail));
+ mktempframe(ENTRY(do_fail));
/*
** Now call `Goal(Result)'.
@@ -781,9 +872,6 @@
#endif
succeed_discard();
-Define_label(mercury__exception__builtin_catch_3_3_i1);
- succeed_discard();
-
/*
** builtin_catch(Goal, Handler, Result)
** call Goal(R).
@@ -842,12 +930,10 @@
** can avoid this by creating a second frame above the special
** frame.)
*/
- succip = LABEL(mercury__exception__builtin_catch_3_5_i1);
#ifdef MR_USE_TRAIL
- mkframe(""builtin_catch_2/1 [nondet]"", 0,
- LABEL(mercury__exception__builtin_catch_3_5_i3));
+ mktempframe(LABEL(mercury__exception__builtin_catch_3_5_i3));
#else
- mkframe(""builtin_catch_2/1 [nondet]"", 0, ENTRY(do_fail));
+ mktempframe(ENTRY(do_fail));
#endif
/*
@@ -876,9 +962,6 @@
*/
succeed();
-Define_label(mercury__exception__builtin_catch_3_5_i1);
- succeed();
-
#ifdef MR_USE_TRAIL
Define_label(mercury__exception__builtin_catch_3_5_i3);
MR_discard_ticket();
@@ -900,20 +983,33 @@
enum CodeModel catch_code_model;
/*
+ ** let the debugger trace exception throwing
+ */
+ if (MR_trace_enabled) {
+ Code *MR_jumpaddr;
+ save_transient_registers();
+ MR_jumpaddr = MR_trace_throw(MR_succip, MR_sp, MR_curfr);
+ restore_transient_registers();
+ if (MR_jumpaddr != NULL) GOTO(MR_jumpaddr);
+ }
+
+ /*
** Search the nondet stack for an exception handler,
** i.e. a frame whose redoip is `exception_handler_do_fail'
** (one created by `builtin_catch').
** N.B. We search down the `succfr' chain, not the `prevfr' chain;
** this ensures that we only find handlers installed by our callers,
** not handlers installed by procedures that we called but which
- ** are still on the nondet stack because they choice points behind.
+ ** are still on the nondet stack because they left choice points
+ ** behind.
*/
- do {
- MR_curfr = cursuccfr;
+ while (MR_redoip_slot(MR_curfr) != ENTRY(exception_handler_do_fail)) {
+ MR_curfr = MR_succfr_slot(MR_curfr);
if (MR_curfr < MR_CONTEXT(nondetstack_zone)->min) {
fatal_error(""builtin_throw/1: uncaught exception"");
}
- } while (curredoip != ENTRY(exception_handler_do_fail));
+
+ }
/*
** Save the handler we found, and reset the det stack top.
@@ -962,8 +1058,8 @@
*/
assert(FRAMEVARS->heap_ptr <= FRAMEVARS->heap_zone->top);
save_transient_registers();
- exception = deep_copy(exception,
- (Word *) (Word) &mercury_data_std_util__base_type_info_univ_0,
+ exception = deep_copy((Word *) exception,
+ (Word *) &mercury_data_std_util__base_type_info_univ_0,
FRAMEVARS->heap_ptr, FRAMEVARS->heap_zone->top);
restore_transient_registers();
@@ -977,8 +1073,8 @@
/* deep_copy the exception back to the ordinary heap */
assert(FRAMEVARS->solns_heap_ptr <= MR_solutions_heap_zone->top);
save_transient_registers();
- exception = deep_copy(exception,
- (Word *) (Word) &mercury_data_std_util__base_type_info_univ_0,
+ exception = deep_copy((Word *) exception,
+ (Word *) &mercury_data_std_util__base_type_info_univ_0,
saved_solns_heap_ptr, MR_solutions_heap_zone->top);
restore_transient_registers();
@@ -1013,7 +1109,7 @@
** and reset the nondet stack top. (This must be done last,
** since it invalidates all the framevars.)
*/
- MR_maxfr = curprevfr;
+ MR_maxfr = MR_prevfr_slot(MR_curfr);
MR_curfr = MR_maxfr;
/*
@@ -1036,7 +1132,8 @@
tailcall(ENTRY(do_call_det_closure),
ENTRY(mercury__exception__builtin_throw_1_0));
}
- push(succip);
+ incr_sp_push_msg(1, ""builtin_throw/1"");
+ MR_stackvar(1) = (Word) MR_succip;
call(ENTRY(do_call_det_closure),
LABEL(mercury__exception__builtin_throw_1_0_i1),
ENTRY(mercury__exception__builtin_throw_1_0));
@@ -1046,13 +1143,15 @@
/* we've just returned from do_call_det_closure */
r2 = r1;
r1 = TRUE;
- succip = (Code *) pop();
+ MR_succip = (Code *) MR_succip;
+ decr_sp_pop_msg(1);
proceed();
#else /* not COMPACT_ARGS */
- push(succip);
- push(catch_code_model);
+ incr_sp_push_msg(2, ""builtin_throw/1"");
+ MR_stackvar(1) = (Word) MR_succip;
+ MR_stackvar(2) = catch_code_model;
call(ENTRY(do_call_det_closure),
LABEL(mercury__exception__builtin_throw_1_0_i1)),
ENTRY(mercury__exception__builtin_throw_1_0));
@@ -1060,13 +1159,14 @@
Define_label(mercury__exception__builtin_throw_1_0_i1);
update_prof_current_proc(LABEL(mercury__exception__builtin_throw_1_0));
/* we've just returned from do_call_det_closure */
- catch_code_model = pop();
+ catch_code_model = MR_stackvar(2);
if (catch_code_model == MODEL_SEMI) {
r5 = r1;
else {
r4 = r1;
}
- succip = (Code *) pop();
+ succip = (Code *) MR_stackvar(1);
+ decr_sp_pop_msg(2);
proceed();
#endif /* not COMPACT_ARGS */
--- ../mercury-compiler-0.8/runtime/mercury_trace_base.c Thu Nov 12 00:30:48 1998
+++ runtime/mercury_trace_base.c Sat Nov 21 03:55:00 1998
@@ -281,6 +281,10 @@
printf("MR_redo_layout_framevar(MR_redofr_slot(MR_curfr) = %p\n",
MR_redo_layout_framevar(MR_redofr_slot(MR_curfr)));
#endif
+ /*
+ ** If this code ever needs changing, you may also need to change
+ ** the code in extras/exceptions/exception.m similarly.
+ */
{
Code *MR_jumpaddr;
save_transient_registers();
--- ../mercury-compiler-0.8/runtime/mercury_trace_base.h Tue Nov 10 00:31:33 1998
+++ runtime/mercury_trace_base.h Sat Nov 21 03:50:46 1998
@@ -34,7 +34,8 @@
MR_PORT_DISJ,
MR_PORT_SWITCH,
MR_PORT_PRAGMA_FIRST,
- MR_PORT_PRAGMA_LATER
+ MR_PORT_PRAGMA_LATER,
+ MR_PORT_EXCEPTION
} MR_Trace_Port;
#define MR_trace_incr_seq() ((Word) ++MR_trace_call_seqno)
--- ../mercury-compiler-0.8/trace/mercury_trace.c Fri Oct 16 16:20:08 1998
+++ trace/mercury_trace.c Sat Nov 21 04:00:53 1998
@@ -125,7 +125,10 @@
}
case MR_CMD_RESUME_FORWARD:
- if (! (port == MR_PORT_REDO || port == MR_PORT_FAIL)) {
+ if (port != MR_PORT_REDO &&
+ port != MR_PORT_FAIL &&
+ port != MR_PORT_EXCEPTION)
+ {
return MR_trace_event(&MR_trace_ctrl, TRUE,
layout, port, seqno, depth,
path, max_r_num);
--- ../mercury-compiler-0.8/trace/mercury_trace.h Fri Oct 16 16:20:09 1998
+++ trace/mercury_trace.h Tue Dec 8 15:42:16 1998
@@ -30,10 +30,10 @@
**
** If MR_trace_cmd == MR_CMD_FINISH, the event handler will stop at the next
** event that specifies the procedure invocation whose call number is in
-** MR_trace_stop_seqno and whose port is EXIT or FAIL.
+** MR_trace_stop_seqno and whose port is EXIT or FAIL or EXCEPTION.
**
** If MR_trace_cmd == MR_CMD_RESUME_FORWARD, the event handler will stop at
-** the next event of any call whose port is *not* REDO or FAIL.
+** the next event of any call whose port is *not* REDO or FAIL or EXCEPTION.
**
** If MR_trace_cmd == MR_CMD_RETURN, the event handler will stop at
** the next event of any call whose port is *not* EXIT.
@@ -83,9 +83,11 @@
} MR_Trace_Cmd_Info;
#define MR_port_is_final(port) ((port) == MR_PORT_EXIT || \
- (port) == MR_PORT_FAIL)
+ (port) == MR_PORT_FAIL || \
+ (port) == MR_PORT_EXCEPTION)
-#define MR_port_is_interface(port) ((port) < MR_PORT_FAIL)
+#define MR_port_is_interface(port) ((port) < MR_PORT_FAIL || \
+ (port) == MR_PORT_EXCEPTION)
#define MR_port_is_entry(port) ((port) == MR_PORT_CALL)
--- ../mercury-compiler-0.8/trace/mercury_trace_internal.c Mon Nov 16 04:58:48 1998
+++ trace/mercury_trace_internal.c Sat Nov 21 04:02:48 1998
@@ -514,7 +514,10 @@
{
; /* the usage message has already been printed */
} else if (word_count == 1) {
- if (port == MR_PORT_FAIL || port == MR_PORT_REDO) {
+ if (port == MR_PORT_FAIL ||
+ port == MR_PORT_REDO ||
+ port == MR_PORT_EXCEPTION)
+ {
cmd->MR_trace_cmd = MR_CMD_RESUME_FORWARD;
goto return_stop_interacting;
} else {
@@ -2381,6 +2384,10 @@
case MR_PORT_PRAGMA_LATER:
printf("LATR ");
+ break;
+
+ case MR_PORT_EXCEPTION:
+ printf("EXCP ");
break;
default:
--
Fergus Henderson <fjh at cs.mu.oz.au> | "Binaries may die
WWW: <http://www.cs.mu.oz.au/~fjh> | but source code lives forever"
PGP: finger fjh at 128.250.37.3 | -- leaked Microsoft memo.
More information about the developers
mailing list