for review: declarative debugger back end
Mark Anthony BROWN
dougl at cs.mu.OZ.AU
Thu Dec 10 19:01:50 AEDT 1998
Hello,
Fergus, would you like to review this please?
Without MR_USE_DECLARATIVE_DEBUGGER defined, these changes have no
effect. Since Zoltan asked me to commit these changes by Friday,
and since they are unlikely to cause problems for anyone, I will
probably commit them later this evening (before review). I will
address any problems afterwards. If there are any serious objections,
please say so now!
Cheers,
Mark.
Estimated hours taken: 210
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.
trace/mercury_trace_internal.{c,h}:
Declare a global variable, MR_trace_decl_mode, that stores the
current mode of the internal debugger, and an enum listing the
possible modes.
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 (new files).
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.13
diff -u -t -r1.13 mercury_conf_param.h
--- mercury_conf_param.h 1998/11/05 03:53:31 1.13
+++ mercury_conf_param.h 1998/11/26 00:53:41
@@ -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: trace/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/Mmakefile,v
retrieving revision 1.5
diff -u -t -r1.5 Mmakefile
--- Mmakefile 1998/11/15 16:47:50 1.5
+++ Mmakefile 1998/11/26 01:22:35
@@ -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 -t -r1.16 mercury_trace_internal.c
--- mercury_trace_internal.c 1998/11/15 16:47:52 1.16
+++ mercury_trace_internal.c 1998/12/10 06:32:15
@@ -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
@@ -120,6 +115,12 @@
const char *MR_var_spec_name; /* valid if VAR_NAME */
} MR_Var_Spec;
+#ifdef MR_USE_DECLARATIVE_DEBUGGER
+
+MR_Trace_Mode MR_trace_decl_mode = MR_TRACE_INTERACTIVE;
+
+#endif /* MR_USE_DECLARATIVE_DEBUGGER */
+
static void MR_trace_internal_ensure_init(void);
static void MR_trace_internal_init_from_env(void);
static void MR_trace_internal_init_from_local(void);
@@ -144,10 +145,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 +188,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 +217,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 +1177,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 +1428,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 +2280,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 -t -r1.2 mercury_trace_internal.h
--- mercury_trace_internal.h 1998/10/16 06:20:19 1.2
+++ mercury_trace_internal.h 1998/12/10 07:26:15
@@ -7,11 +7,52 @@
#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;
+
+#ifdef MR_USE_DECLARATIVE_DEBUGGER
+
+/*
+** The following enum gives the possible modes that the declarative
+** debugger can be in (see trace/mercury_trace_declarative.{c,h}).
+** MR_TRACE_INTERACTIVE indicates the usual operation of the internal
+** debugger. The other modes refer to what type of analysis is
+** being performed.
+*/
+
+typedef enum {
+ MR_TRACE_INTERACTIVE,
+ MR_TRACE_WRONG_ANSWER
+} MR_Trace_Mode;
+
+/*
+** This variable is modified whenever we start or stop collecting
+** an EDT for a particular type of analysis (see
+** trace/mercury_trace_declarative.c).
+*/
+
+extern MR_Trace_Mode MR_trace_decl_mode;
+
+#endif /* MR_USE_DECLARATIVE_DEBUGGER */
+
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.
*/
/*
** Main author: Mark Brown
**
** This file implements the back end of the declarative debugger. The
** back end is an extension to the internal debugger which collects
** related trace events and builds them into an Evaluation Dependency
** Tree (EDT). Once built, the EDT is passed to the front end where it can
** be analysed to find bugs.
**
** In this incarnation, the front end just dumps the EDT to stdout where
** the user can do manual analysis.
*/
#include "mercury_imp.h"
#ifdef MR_USE_DECLARATIVE_DEBUGGER
#include "mercury_dummy.h"
#include "mercury_trace.h"
#include "mercury_trace_internal.h"
#include "mercury_trace_declarative.h"
#include "mercury_layout_util.h"
#include <stdio.h>
/*
** We only build the execution tree to a certain depth. The following
** macro gives the default depth limit (relative to the starting depth).
*/
#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;
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)) {
/* XXX this should be handled better. */
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 {
/*
** At this point depth == MR_edt_max_depth.
*/
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;
#ifdef 0
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");
#endif
}
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 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;
}
/*
** The following functions do a fairly unpretty print of the EDT. They
** currently form the front end of the declarative debugger. In the
** future the front end will be in a separate module to the back, and
** will be much more detailed. These functions will probably disappear.
*/
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);
}
#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 */
More information about the developers
mailing list