for review: declarative debugging back end
Mark Anthony BROWN
dougl at cs.mu.OZ.AU
Fri Nov 27 17:38:32 AEDT 1998
Hi,
These are the changes I have been working on to implement the back end
of a declarative debugger under the internal debugger. The idea is
as follows:
- add state to the internal debugger, to tell it whether we
are collecting a proof tree (MR_TRACE_WRONG_ANSWER) or
not (MR_TRACE_INTERACTIVE);
- add a new command, dd_wrong, which initialises the proof
tree and changes the internal debugger state;
- when collecting a proof tree call MR_trace_decl_wrong_answer
from within MR_trace_event_internal instead of reading
further mdb commands;
- when a full proof has been collected, it is passed to the
front end (except that since there is no front end yet, I
just dump the proof to stdout).
This code is not really ready for review, but since Zoltan is leaving
soon I don't want to leave it too much longer before people see this.
Any comments now will be welcome, but feel free to save them for a
_real_ review at a later stage (Zoltan, I would appreciate any
feedback you have now, though).
Some of the problems I am aware of are:
- It compiles, but doesn't work, on murlibobo :(. I am still
yet to figure out why; when I do, I will post another diff.
It compiles and runs correctly (at least in some cases) under
Linux at home -- I am currently trying to get a version
working here.
- Most of it is poorly documented.
- I am unsure whether memory is being allocated correctly; I am
sure memory is not being deallocated correctly.
- The goal path is not recorded correctly.
- I don't think procedure arguments are recorded correctly.
- Some code to print debugging messages is still in there.
- The changes in runtime/mercury_trace_base.{c,h} instead
probably should be in trace/mercury_trace_internal.{c,h},
since they are not used outside the internal debugger.
Cheers,
Mark.
Estimated hours taken: 200
Changes to the internal tracer to implement a declarative
debugging back end.
runtime/mercury_conf_param.h:
Document the new MR_USE_DECLARATIVE_DEBUGGER configuration
parameter.
runtime/mercury_trace_base.{c,h}:
Declare a global variable that stores the current mode of
the internal debugger, and an enum listing the possible modes.
trace/mercury_trace_internal.{c,h}:
Move MR_Event_Details and MR_trace_retry into
mercury_trace_internal.h, and make the latter extern, so that
the declarative debugger back end can use them.
trace/mercury_trace_internal.c:
Call the back end in mercury_trace_declarative.c.
Add a new command, dd_wrong, to start wrong answer analysis.
trace/Mmakefile:
Add mercury_trace_declarative.{c,h} to the dependencies.
trace/mercury_trace_declarative.{c,h}:
The declarative debugging back end.
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.13
diff -u -r1.13 mercury_conf_param.h
--- mercury_conf_param.h 1998/11/05 03:53:31 1.13
+++ mercury_conf_param.h 1998/11/25 12:33:18
@@ -117,6 +117,10 @@
** Causes the generated code to become VERY big and VERY inefficient.
** Slows down compilation a LOT.
**
+** MR_USE_DECLARATIVE_DEBUGGER
+** Enable this if you want declarative debugging support in the
+** internal debugger.
+**
** MR_DEBUG_GOTOS
** (Implied by MR_LOWLEVEL_DEBUG.)
** Enables low-level debugging of gotos.
Index: runtime/mercury_trace_base.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.c,v
retrieving revision 1.8
diff -u -r1.8 mercury_trace_base.c
--- mercury_trace_base.c 1998/11/19 06:19:19 1.8
+++ mercury_trace_base.c 1998/11/25 12:33:22
@@ -102,6 +102,12 @@
#endif
+#ifdef MR_USE_DECLARATIVE_DEBUGGER
+
+MR_Trace_Mode MR_trace_decl_mode = MR_TRACE_INTERACTIVE;
+
+#endif /* MR_USE_DECLARATIVE_DEBUGGER */
+
Code *
MR_trace(const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
const char * path, int max_mr_num)
Index: runtime/mercury_trace_base.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.h,v
retrieving revision 1.4
diff -u -r1.4 mercury_trace_base.h
--- mercury_trace_base.h 1998/11/09 10:24:40 1.4
+++ mercury_trace_base.h 1998/11/25 12:33:23
@@ -143,4 +143,15 @@
#endif /* MR_TRACE_HISTOGRAM */
+#ifdef MR_USE_DECLARATIVE_DEBUGGER
+
+typedef enum {
+ MR_TRACE_INTERACTIVE,
+ MR_TRACE_WRONG_ANSWER
+} MR_Trace_Mode;
+
+extern MR_Trace_Mode MR_trace_decl_mode;
+
+#endif /* MR_USE_DECLARATIVE_DEBUGGER */
+
#endif /* MERCURY_TRACE_BASE_H */
Index: trace/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/Mmakefile,v
retrieving revision 1.5
diff -u -r1.5 Mmakefile
--- Mmakefile 1998/11/15 16:47:50 1.5
+++ Mmakefile 1998/11/25 12:33:27
@@ -28,6 +28,7 @@
mercury_trace.h \
mercury_trace_alias.h \
mercury_trace_browse.h \
+ mercury_trace_declarative.h \
mercury_trace_external.h \
mercury_trace_help.h \
mercury_trace_internal.h \
@@ -40,6 +41,7 @@
mercury_trace.c \
mercury_trace_alias.c \
mercury_trace_browse.c \
+ mercury_trace_declarative.c \
mercury_trace_external.c \
mercury_trace_help.c \
mercury_trace_internal.c \
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.16
diff -u -r1.16 mercury_trace_internal.c
--- mercury_trace_internal.c 1998/11/15 16:47:52 1.16
+++ mercury_trace_internal.c 1998/11/25 12:33:47
@@ -13,6 +13,7 @@
#include "mercury_imp.h"
#include "mercury_trace.h"
#include "mercury_trace_internal.h"
+#include "mercury_trace_declarative.h"
#include "mercury_trace_alias.h"
#include "mercury_trace_help.h"
#include "mercury_trace_browse.h"
@@ -98,12 +99,6 @@
static MR_Line *MR_line_head = NULL;
static MR_Line *MR_line_tail = NULL;
-typedef struct MR_Event_Details_Struct {
- int MR_call_seqno;
- int MR_call_depth;
- int MR_event_number;
-} MR_Event_Details;
-
typedef enum {
KEEP_INTERACTING,
STOP_INTERACTING
@@ -144,10 +139,6 @@
static bool MR_trace_options_confirmed(bool *confirmed, char ***words,
int *word_count, const char *cat, const char *item);
static void MR_trace_usage(const char *cat, const char *item);
-static void MR_trace_retry(const MR_Stack_Layout_Label *layout,
- Word *saved_regs, MR_Event_Details *event_details,
- int seqno, int depth, int *max_mr_num,
- Code **jumpaddr);
static Word MR_trace_find_input_arg(const MR_Stack_Layout_Label *label,
Word *saved_regs, const char *name, bool *succeeded);
static void MR_trace_internal_add_spy_point(MR_Spy_When when,
@@ -191,10 +182,6 @@
static void MR_insert_line_at_head(const char *line);
static void MR_insert_line_at_tail(const char *line);
-static Code *MR_trace_event_internal_report(MR_Trace_Cmd_Info *cmd,
- const MR_Stack_Layout_Label *layout, Word *saved_regs,
- MR_Trace_Port port, int seqno, int depth,
- const char *path, int *max_mr_num);
static void MR_trace_event_print_internal_report(
const MR_Stack_Layout_Label *layout,
MR_Trace_Port port, int seqno, int depth,
@@ -224,6 +211,13 @@
port, seqno, depth, path, max_mr_num);
}
+#ifdef MR_USE_DECLARATIVE_DEBUGGER
+ if (MR_trace_decl_mode == MR_TRACE_WRONG_ANSWER) {
+ return MR_trace_decl_wrong_answer(cmd, layout, saved_regs,
+ port, seqno, depth, path, max_mr_num);
+ }
+#endif MR_USE_DECLARATIVE_DEBUGGER
+
MR_trace_enabled = FALSE;
MR_trace_internal_ensure_init();
@@ -1177,6 +1171,23 @@
} else {
MR_trace_usage("misc", "quit");
}
+#ifdef MR_USE_DECLARATIVE_DEBUGGER
+ } else if (streq(words[0], "dd_wrong")) {
+ if (word_count != 1) {
+ fprintf(stderr,
+ "mdb: dd_wrong requires no arguments.\n");
+ } else if (port != MR_PORT_EXIT) {
+ fprintf(stderr, "mdb: wrong answer analysis is only "
+ "available from EXIT events.\n");
+ } else if (MR_trace_start_wrong_answer(cmd, layout,
+ saved_regs, event_details, seqno, depth,
+ max_mr_num, jumpaddr)) {
+ goto return_stop_interacting;
+ } else {
+ fprintf(stderr, "mdb: unable to start declarative "
+ "debugging.\n");
+ }
+#endif /* MR_USE_DECLARATIVE_DEBUGGER */
} else {
printf("Unknown command `%s'. "
"Give the command `help' for help.\n", words[0]);
@@ -1411,7 +1422,7 @@
item, item);
}
-static void
+void
MR_trace_retry(const MR_Stack_Layout_Label *this_label, Word *saved_regs,
MR_Event_Details *event_details, int seqno, int depth,
int *max_mr_num, Code **jumpaddr)
@@ -2263,7 +2274,7 @@
}
}
-static Code *
+Code *
MR_trace_event_internal_report(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Trace_Port port, int seqno, int depth, const char *path,
Index: trace/mercury_trace_internal.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_trace_internal.h
--- mercury_trace_internal.h 1998/10/16 06:20:19 1.2
+++ mercury_trace_internal.h 1998/11/25 12:33:47
@@ -7,11 +7,27 @@
#ifndef MERCURY_TRACE_INTERNAL_H
#define MERCURY_TRACE_INTERNAL_H
+typedef struct MR_Event_Details_Struct {
+ int MR_call_seqno;
+ int MR_call_depth;
+ int MR_event_number;
+} MR_Event_Details;
+
extern Code *MR_trace_event_internal(MR_Trace_Cmd_Info *cmd,
bool interactive,
const MR_Stack_Layout_Label *layout,
Word *saved_regs, MR_Trace_Port port,
int seqno, int depth,
+ const char *path, int *max_mr_num);
+
+extern void MR_trace_retry(const MR_Stack_Layout_Label *layout,
+ Word *saved_regs, MR_Event_Details *event_details,
+ int seqno, int depth, int *max_mr_num,
+ Code **jumpaddr);
+
+extern Code *MR_trace_event_internal_report(MR_Trace_Cmd_Info *cmd,
+ const MR_Stack_Layout_Label *layout, Word *saved_regs,
+ MR_Trace_Port port, int seqno, int depth,
const char *path, int *max_mr_num);
#endif /* MERCURY_TRACE_INTERNAL_H */
--- trace/mercury_trace_declarative.c:
/*
** Copyright (C) 1998 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
/*
** This file contains code to support declarative debugging extensions
** to the internal debugger.
**
** Main author: Mark Brown
*/
#include "mercury_imp.h"
#ifdef MR_USE_DECLARATIVE_DEBUGGER
#include "mercury_trace.h"
#include "mercury_trace_internal.h"
#include "mercury_trace_declarative.h"
#include "mercury_layout_util.h"
#include <stdio.h>
#define MR_EDT_DEPTH_STEP_SIZE 8
/*
** The declarative debugger back end is controlled by the
** settings of the following variables. They are set in
** MR_trace_start_wrong_answer when the back end is started. They
** are used by MR_trace_decl_wrong_answer to decide what action to
** take for a particular trace event. Events that are outside
** the given depth range are ignored. Events that are beyond the
** given last event cause the internal debugger to be switched
** back into interactive mode.
*/
static int MR_edt_min_depth;
static int MR_edt_max_depth;
static int MR_edt_last_event;
/*
** MR_edt_parent points to the the parent edt_node of a procedure
** that is being called. When a CALL event occurs, this value is
** saved in a dedicated stackvar (or framevar). It is then set to
** point to the new edt_node for that procedure, ready to be used
** by CALL events at the next depth down.
*/
static MR_Edt_Node *MR_edt_parent;
static void
MR_trace_decl_wrong_answer_call(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Trace_Port port, int seqno, int depth, const char *path,
int *max_mr_num, int decl_slot);
static void
MR_trace_decl_wrong_answer_exit(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Trace_Port port, int seqno, int depth, const char *path,
int *max_mr_num, int decl_slot);
static void
MR_trace_decl_wrong_answer_redo(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Trace_Port port, int seqno, int depth, const char *path,
int *max_mr_num, int decl_slot);
static void
MR_trace_decl_wrong_answer_fail(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Trace_Port port, int seqno, int depth, const char *path,
int *max_mr_num, int decl_slot);
static void
MR_trace_decl_update_path(const MR_Stack_Layout_Label *layout,
const char *path, int decl_slot);
static void
MR_trace_decl_save_args(const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Edt_Node *edt_node);
static void
MR_edt_print(MR_Edt_Node *root, int level);
static void
MR_edt_print_node(MR_Edt_Node *node, int level);
static MR_Edt_Node *
MR_edt_node_construct(const MR_Stack_Layout_Label *layout,
MR_Edt_Node_Type node_tag, int start_event);
Code *
MR_trace_decl_wrong_answer(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Trace_Port port, int seqno, int depth, const char *path,
int *max_mr_num)
{
int decl_slot;
MR_Stack_Layout_Entry *entry = layout->MR_sll_entry;
MR_Edt_Node *edt_node;
/*
MR_trace_event_internal_report(cmd, layout, saved_regs, port, seqno,
depth, path, max_mr_num);
*/
if (MR_trace_event_number > MR_edt_last_event) {
MR_trace_decl_mode = MR_TRACE_INTERACTIVE;
return MR_trace_event_internal(cmd, TRUE, layout, saved_regs,
port, seqno, depth, path, max_mr_num);
}
if (!MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry)) {
fatal_error("layout has no execution tracing");
}
if (depth > MR_edt_max_depth ||
depth < MR_edt_min_depth ||
entry->MR_sle_maybe_decl_debug < 1 ) {
/*
** We can just ignore any event with a depth outside the
** range given by MR_edt_{min,max}_depth, or which
** does not have slots reserved for declarative
** debugging.
*/
return NULL;
}
MR_trace_enabled = FALSE;
decl_slot = entry->MR_sle_maybe_decl_debug;
switch (port) {
case MR_PORT_CALL:
MR_trace_decl_wrong_answer_call(cmd, layout,
saved_regs, port, seqno, depth, path,
max_mr_num, decl_slot);
break;
case MR_PORT_EXIT:
MR_trace_decl_wrong_answer_exit(cmd, layout,
saved_regs, port, seqno, depth, path,
max_mr_num, decl_slot);
break;
case MR_PORT_REDO:
MR_trace_decl_wrong_answer_redo(cmd, layout,
saved_regs, port, seqno, depth, path,
max_mr_num, decl_slot);
break;
case MR_PORT_FAIL:
MR_trace_decl_wrong_answer_fail(cmd, layout,
saved_regs, port, seqno, depth, path,
max_mr_num, decl_slot);
break;
case MR_PORT_THEN:
case MR_PORT_ELSE:
case MR_PORT_DISJ:
case MR_PORT_SWITCH:
MR_trace_decl_update_path(layout, path, decl_slot);
case MR_PORT_PRAGMA_FIRST:
case MR_PORT_PRAGMA_LATER:
break;
default:
fatal_error("Unknown port type");
}
if (MR_trace_event_number == MR_edt_last_event) {
/* Call the front end */
MR_edt_print(MR_edt_parent->MR_edt_node_children, 0);
MR_trace_decl_mode = MR_TRACE_INTERACTIVE;
}
MR_trace_enabled = TRUE;
return NULL;
}
static void
MR_trace_decl_wrong_answer_call(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Trace_Port port, int seqno, int depth, const char *path,
int *max_mr_num, int decl_slot)
{
MR_Edt_Node *edt_node;
MR_Edt_Node_Type node_tag;
MR_Stack_Layout_Entry *entry = layout->MR_sll_entry;
if (depth < MR_edt_max_depth) {
node_tag = MR_EDT_WRONG_ANSWER_EXPLICIT;
} else {
node_tag = MR_EDT_WRONG_ANSWER_IMPLICIT;
}
edt_node = MR_edt_node_construct(layout, node_tag,
MR_trace_event_number);
if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
MR_stackvar(decl_slot) = (Word) edt_node;
MR_stackvar(decl_slot + 1) = (Word) MR_edt_parent;
} else {
MR_framevar(decl_slot) = (Word) edt_node;
MR_framevar(decl_slot + 1) = (Word) MR_edt_parent;
}
/*
** The children of edt_node will refer to the
** global variable MR_edt_parent to locate their
** parent.
*/
MR_edt_parent = edt_node;
}
static void
MR_trace_decl_wrong_answer_exit(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Trace_Port port, int seqno, int depth, const char *path,
int *max_mr_num, int decl_slot)
{
MR_Edt_Node *edt_node;
MR_Stack_Layout_Entry *entry = layout->MR_sll_entry;
if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
edt_node = (MR_Edt_Node *) MR_stackvar(decl_slot);
MR_edt_parent = (MR_Edt_Node *) MR_stackvar(decl_slot + 1);
} else {
edt_node = (MR_Edt_Node *) MR_framevar(decl_slot);
MR_edt_parent = (MR_Edt_Node *) MR_framevar(decl_slot + 1);
}
edt_node->MR_edt_node_layout = layout;
edt_node->MR_edt_node_end_event = MR_trace_event_number;
edt_node->MR_edt_node_seqno = seqno;
MR_trace_decl_save_args(layout, saved_regs, edt_node);
/*
** Attach this node to the child list of its parent.
*/
edt_node->MR_edt_node_sibling = MR_edt_parent->MR_edt_node_children;
MR_edt_parent->MR_edt_node_children = edt_node;
}
static void
MR_trace_decl_wrong_answer_redo(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Trace_Port port, int seqno, int depth, const char *path,
int *max_mr_num, int decl_slot)
{
MR_Edt_Node *edt_node;
MR_Stack_Layout_Entry *entry = layout->MR_sll_entry;
/*
** Re-use the node that was allocated at the CALL event.
*/
if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
edt_node = (MR_Edt_Node *) MR_stackvar(decl_slot);
MR_edt_parent = (MR_Edt_Node *) MR_stackvar(decl_slot + 1);
} else {
edt_node = (MR_Edt_Node *) MR_framevar(decl_slot);
MR_edt_parent = (MR_Edt_Node *) MR_framevar(decl_slot + 1);
}
/*
** Remove the nodes that we have bactracked over. Since we have
** a REDO event for this goal, we must have had an EXIT event
** earlier, therefore the current node is known to be attached
** to the current parent.
**
** XXX need to deallocate properly.
*/
if (MR_edt_parent != NULL ) {
MR_edt_parent->MR_edt_node_children =
edt_node->MR_edt_node_sibling;
}
MR_edt_parent = edt_node;
}
static void
MR_trace_decl_wrong_answer_fail(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Trace_Port port, int seqno, int depth, const char *path,
int *max_mr_num, int decl_slot)
{
MR_Edt_Node *edt_node;
MR_Stack_Layout_Entry *entry = layout->MR_sll_entry;
if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
edt_node = (MR_Edt_Node *) MR_stackvar(decl_slot);
MR_edt_parent = (MR_Edt_Node *) MR_stackvar(decl_slot + 1);
} else {
edt_node = (MR_Edt_Node *) MR_framevar(decl_slot);
MR_edt_parent = (MR_Edt_Node *) MR_framevar(decl_slot + 1);
}
deallocate_memory(edt_node);
}
/*
** MR_trace_decl_update_path adds to the record of the execution path
** taken for the current edt_node.
**
** XXX It currently just overwrites all but the last path seen. If
** the goal is a conjunction of two disjunctions, only the path
** through the second disjunction is remembered.
*/
static void
MR_trace_decl_update_path(const MR_Stack_Layout_Label *layout,
const char *path, int decl_slot)
{
MR_Edt_Node *edt_node;
if (MR_DETISM_DET_STACK(layout->MR_sll_entry->MR_sle_detism)) {
edt_node = (MR_Edt_Node *) MR_stackvar(decl_slot);
} else {
edt_node = (MR_Edt_Node *) MR_framevar(decl_slot);
}
edt_node->MR_edt_node_path = path;
}
static void
MR_trace_decl_save_args(const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Edt_Node *edt_node)
{
Word *arg_values;
Word *arg_types;
int arg_count;
const MR_Stack_Layout_Vars *vars;
Word *base_sp;
Word *base_curfr;
Word *type_params;
const MR_Stack_Layout_Var *var;
MR_Live_Lval locn;
int i;
bool succeeded;
Word *pseudo_type_info;
Word type_info;
arg_count = layout->MR_sll_var_count;
if (arg_count < 0) {
printf("mdb: no info about live variables.\n");
edt_node->MR_edt_node_arg_values = NULL;
edt_node->MR_edt_node_arg_types = NULL;
return;
}
arg_values = allocate_array(Word, arg_count);
arg_types = allocate_array(Word, arg_count);
vars = &layout->MR_sll_var_info;
base_sp = MR_saved_sp(saved_regs);
base_curfr = MR_saved_curfr(saved_regs);
type_params = MR_materialize_typeinfos_base(vars, saved_regs,
base_sp, base_curfr);
for (i = 0; i < arg_count; i++) {
var = &vars->MR_slvs_pairs[i];
MR_get_type_and_value_base(var, saved_regs, base_sp,
base_curfr, type_params, &arg_types[i],
&arg_values[i]);
locn = var->MR_slv_locn;
/*
printf("var %d: lval type = %d, "
"lval number = %d, value = ",
i,
MR_LIVE_LVAL_TYPE(locn),
MR_LIVE_LVAL_NUMBER(locn)
);
MR_write_variable(arg_types[i], arg_values[i]);
printf("\n");
*/
}
edt_node->MR_edt_node_arg_values = arg_values;
edt_node->MR_edt_node_arg_types = arg_types;
}
bool
MR_trace_start_wrong_answer(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout, Word *saved_regs,
MR_Event_Details *event_details, int seqno, int depth,
int *max_mr_num, Code **jumpaddr)
{
MR_Stack_Layout_Entry *entry = layout->MR_sll_entry;
int decl_slot;
if (!MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry)) {
return FALSE;
}
decl_slot = entry->MR_sle_maybe_decl_debug;
if (decl_slot < 1) {
/* No slots are reserved for declarative debugging */
return FALSE;
}
MR_trace_decl_mode = MR_TRACE_WRONG_ANSWER;
MR_edt_parent = MR_edt_node_construct(NULL,
MR_EDT_WRONG_ANSWER_EXPLICIT, 0);
MR_edt_last_event = MR_trace_event_number;
MR_edt_min_depth = depth;
MR_edt_max_depth = depth + MR_EDT_DEPTH_STEP_SIZE;
MR_trace_retry(layout, saved_regs, event_details, seqno, depth,
max_mr_num, jumpaddr);
cmd->MR_trace_cmd = MR_CMD_GOTO;
cmd->MR_trace_stop_event = MR_trace_event_number + 1;
cmd->MR_trace_strict = FALSE;
cmd->MR_trace_print_level = MR_PRINT_LEVEL_ALL;
return TRUE;
}
static void
MR_edt_print(MR_Edt_Node *root, int level)
{
int i;
if (root->MR_edt_node_sibling != NULL) {
MR_edt_print(root->MR_edt_node_sibling, level);
}
MR_edt_print_node(root, level);
if (root->MR_edt_node_tag == MR_EDT_WRONG_ANSWER_IMPLICIT) {
for (i = 0; i < level + 1; i++) {
printf(" ");
}
printf("/* implicit */\n");
}
if (root->MR_edt_node_children != NULL) {
MR_edt_print(root->MR_edt_node_children, level + 1);
}
}
static void
MR_edt_print_node(MR_Edt_Node *node, int level)
{
int i;
for (i = 0; i < level; i++) {
printf(" ");
}
printf("(");
MR_write_variable(node->MR_edt_node_arg_types[0],
node->MR_edt_node_arg_values[0]);
for (i = 1; i < node->MR_edt_node_layout->MR_sll_var_count; i++) {
printf(", ");
MR_write_variable(node->MR_edt_node_arg_types[i],
node->MR_edt_node_arg_values[i]);
}
printf(") ");
if (node->MR_edt_node_path != NULL) {
printf("%s ", node->MR_edt_node_path);
}
MR_print_proc_id_for_debugger(node->MR_edt_node_layout->MR_sll_entry);
}
static MR_Edt_Node *
MR_edt_node_construct(const MR_Stack_Layout_Label *layout,
MR_Edt_Node_Type node_tag, int start_event)
{
MR_Edt_Node *edt_node;
edt_node = allocate_object(MR_Edt_Node);
edt_node->MR_edt_node_tag = node_tag;
edt_node->MR_edt_node_layout = layout;
edt_node->MR_edt_node_path = NULL;
edt_node->MR_edt_node_start_event = start_event;
edt_node->MR_edt_node_children = NULL;
edt_node->MR_edt_node_sibling = NULL;
return edt_node;
}
#endif /* MR_USE_DECLARATIVE_DEBUGGER */
--- trace/mercury_trace_declarative.h:
/*
** Copyright (C) 1998 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
#include "mercury_imp.h"
#ifndef MERCURY_TRACE_DECLARATIVE_H
#define MERCURY_TRACE_DECLARATIVE_H
/*
** This file defines the MR_Edt_Node data type, which stores nodes
** of an Evaluation Dependency Tree (EDT), used for declarative
** debugging. It also defines an interface to the back end of the
** declarative debugger from the internal debugger.
*/
/*
** Each node in an EDT has a tag to denote its type. At the moment
** the only type of analysis is wrong answer analysis, so the tag
** is just used to distinguish between implicitly and explicitly
** represented nodes.
**
** Implicit nodes are similar to explicit nodes, but they do not
** store their children. The children can be created by re-executing
** the events in the stored range and collecting a new EDT.
*/
typedef enum {
MR_EDT_WRONG_ANSWER_EXPLICIT,
MR_EDT_WRONG_ANSWER_IMPLICIT
} MR_Edt_Node_Type;
/*
** Wrong answer analysis is currently the only type of analysis available.
** Consequently, the EDT nodes only contain enough information to support
** this type of analysis.
*/
typedef struct MR_Edt_Node_Struct MR_Edt_Node;
struct MR_Edt_Node_Struct {
/*
** Type of EDT node.
*/
MR_Edt_Node_Type MR_edt_node_tag;
/*
** The layout of the EXIT port.
*/
const MR_Stack_Layout_Label *MR_edt_node_layout;
/*
** The arguments.
*/
Word *MR_edt_node_arg_values;
Word *MR_edt_node_arg_types;
const char *MR_edt_node_path;
/*
** The event numbers of the
** CALL and EXIT events for
** this proof.
*/
int MR_edt_node_start_event;
int MR_edt_node_end_event;
/*
** The sequence number of the
** CALL and EXIT events.
*/
int MR_edt_node_seqno;
/*
** The rightmost child of this
** node, or NULL if there are
** no children.
*/
MR_Edt_Node *MR_edt_node_children;
/*
** The next sibling to the
** left of this node, or NULL
** if this is the leftmost.
*/
MR_Edt_Node *MR_edt_node_sibling;
};
/*
** When in declarative debugging mode, the internal debugger calls
** MR_trace_decl_wrong_answer for each event.
*/
extern Code *MR_trace_decl_wrong_answer(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout,
Word *saved_regs, MR_Trace_Port port,
int seqno, int depth,
const char *path, int *max_mr_num);
/*
** The internal (interactive) debugger calls this to change to
** declarative debugging mode.
*/
extern bool MR_trace_start_wrong_answer(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout,
Word *saved_regs, MR_Event_Details *event_details,
int seqno, int depth, int *max_mr_num,
Code **jumpaddr);
#endif /* MERCURY_TRACE_DECLARATIVE_H */
--
Mark Brown (dougl at cs.mu.oz.au) )O+ | For Microsoft to win,
MEngSc student, | the customer must lose
Dept of Computer Science, Melbourne Uni | -- Eric S. Raymond
More information about the developers
mailing list