for review: the new debugger command set (part 3 of 5)
Zoltan Somogyi
zs at cs.mu.OZ.AU
Wed Sep 16 18:21:33 AEST 1998
cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.38
diff -u -u -r1.38 Mmakefile
--- Mmakefile 1998/09/15 07:19:11 1.38
+++ Mmakefile 1998/09/15 08:28:22
@@ -14,7 +14,7 @@
#-----------------------------------------------------------------------------#
CFLAGS = -I$(MERCURY_DIR)/runtime -I$(MERCURY_DIR)/boehm_gc -g \
- $(DLL_CFLAGS) $(EXTRA_CFLAGS)
+ $(DLL_CFLAGS) $(EXTRA_CFLAGS) -O0
MGNUC = MERCURY_C_INCL_DIR=. $(SCRIPTS_DIR)/mgnuc
MGNUCFLAGS = --no-ansi $(EXTRA_MGNUCFLAGS) $(CFLAGS)
MOD2C = $(SCRIPTS_DIR)/mod2c
@@ -46,6 +46,7 @@
mercury_init.h \
mercury_label.h \
mercury_library_types.h \
+ mercury_macros.h \
mercury_memory.h \
mercury_memory_zones.h \
mercury_memory_handlers.h \
@@ -70,9 +71,13 @@
mercury_thread.h \
mercury_timing.h \
mercury_trace.h \
+ mercury_trace_alias.h \
mercury_trace_base.h \
mercury_trace_external.h \
+ mercury_trace_help.h \
mercury_trace_internal.h \
+ mercury_trace_spy.h \
+ mercury_trace_tables.h \
mercury_trace_util.h \
mercury_trail.h \
mercury_types.h \
@@ -128,9 +133,13 @@
mercury_thread.c \
mercury_timing.c \
mercury_trace.c \
+ mercury_trace_alias.c \
mercury_trace_base.c \
mercury_trace_external.c \
+ mercury_trace_help.c \
mercury_trace_internal.c \
+ mercury_trace_spy.c \
+ mercury_trace_tables.c \
mercury_trace_util.c \
mercury_trail.c \
mercury_type_info.c \
Index: runtime/mercury_agc_debug.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_agc_debug.c,v
retrieving revision 1.2
diff -u -u -r1.2 mercury_agc_debug.c
--- mercury_agc_debug.c 1998/08/10 06:40:12 1.2
+++ mercury_agc_debug.c 1998/08/10 07:04:37
@@ -154,7 +154,7 @@
}
success_ip = (Code *)
- based_detstackvar(stack_pointer, number);
+ MR_based_stackvar(stack_pointer, number);
stack_pointer = stack_pointer -
entry_layout->MR_sle_stack_slots;
label = MR_lookup_internal_by_addr(success_ip);
@@ -191,7 +191,7 @@
break;
case MR_LVAL_TYPE_STACKVAR:
- value = based_detstackvar(stack_pointer, locn_num);
+ value = MR_based_stackvar(stack_pointer, locn_num);
have_value = TRUE;
fprintf(stderr, "stackvar%d", locn_num);
break;
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_conf_param.h
--- mercury_conf_param.h 1998/07/25 13:15:37 1.9
+++ mercury_conf_param.h 1998/09/08 06:48:24
@@ -187,6 +187,14 @@
** Enables profiling of memory usage.
*/
+/*
+** Experimental options:
+**
+** MR_TRACE_HISTOGRAM
+** Enable this if you want to count the number of execution tracing events
+** at various call depths.
+*/
+
/*---------------------------------------------------------------------------*/
/*
** Settings of configuration parameters which can be passed on
Index: runtime/mercury_engine.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_engine.c,v
retrieving revision 1.14
diff -u -u -r1.14 mercury_engine.c
--- mercury_engine.c 1998/08/24 08:24:38 1.14
+++ mercury_engine.c 1998/08/24 09:05:49
@@ -170,10 +170,10 @@
** That will copy the real registers we use to the fake_reg array.
**
** Beware, however, that if you are planning to return to C code
-** that did not #include "mercury_regs.h" (directly or via e.g. "mercury_imp.h"),
-** and you have fiddled with the Mercury registers or invoked
-** call_engine() or anything like that, then you will need to
-** save the real registers that C is using before modifying the
+** that did not #include "mercury_regs.h" (directly or via e.g.
+** "mercury_imp.h"), and you have fiddled with the Mercury registers
+** or invoked call_engine() or anything like that, then you will need
+** to save the real registers that C is using before modifying the
** Mercury registers and then restore them afterwards.
**
** The called routine may invoke C functions; currently this
@@ -532,18 +532,12 @@
Define_extern_entry(do_last_succeed);
Define_extern_entry(do_not_reached);
-MR_MAKE_STACK_LAYOUT_ENTRY(do_redo)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_fail)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_succeed)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_last_succeed)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_not_reached)
-
BEGIN_MODULE(special_labels_module)
- init_entry(do_redo);
- init_entry(do_fail);
- init_entry(do_succeed);
- init_entry(do_last_succeed);
- init_entry(do_not_reached);
+ init_label(do_redo);
+ init_label(do_fail);
+ init_label(do_succeed);
+ init_label(do_last_succeed);
+ init_label(do_not_reached);
BEGIN_CODE
Define_entry(do_redo);
Index: runtime/mercury_goto.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_goto.h,v
retrieving revision 1.14
diff -u -u -r1.14 mercury_goto.h
--- mercury_goto.h 1998/09/04 11:26:10 1.14
+++ mercury_goto.h 1998/09/09 07:53:51
@@ -19,11 +19,14 @@
#define entry(label) paste(_entry_,label)
#define skip(label) paste(skip_,label)
-#if defined(MR_USE_STACK_LAYOUTS)
- #define MR_ENTRY_LAYOUT(label) (const MR_Stack_Layout_Entry *) (Word) \
+#define MR_ALWAYS_ENTRY_LAYOUT(label) (const MR_Stack_Layout_Entry *) (Word) \
&(paste(mercury_data__layout__,label))
- #define MR_INTERNAL_LAYOUT(label) (const MR_Stack_Layout_Label *) (Word) \
+#define MR_ALWAYS_INTERNAL_LAYOUT(label)(const MR_Stack_Layout_Label *) (Word) \
&(paste(mercury_data__layout__,label))
+
+#if defined(MR_USE_STACK_LAYOUTS)
+ #define MR_ENTRY_LAYOUT(label) MR_ALWAYS_ENTRY_LAYOUT(label)
+ #define MR_INTERNAL_LAYOUT(label) MR_ALWAYS_INTERNAL_LAYOUT(label)
#else
#define MR_ENTRY_LAYOUT(label) (const MR_Stack_Layout_Entry *) NULL
#define MR_INTERNAL_LAYOUT(label) (const MR_Stack_Layout_Label *) NULL
@@ -39,34 +42,43 @@
** The versions of the macros below with the _sl suffix assume that the label
** that they are applied to has a stack layout record; the versions without
** do not. This governs whether they try to pass the address of this record
-** to insert_entry().
+** to MR_insert_*_label().
*/
#if defined(MR_INSERT_LABELS)
#define make_label(n, a, l) MR_insert_internal_label(n, a, NULL)
#define make_label_sl(n, a, l) \
- MR_insert_internal_label(n, a, MR_INTERNAL_LAYOUT(l))
+ MR_insert_internal_label(n, a, MR_INTERNAL_LAYOUT(l))
+ #define make_label_asl(n, a, l) \
+ MR_insert_internal_label(n, a, MR_ALWAYS_INTERNAL_LAYOUT(l))
#else
#define make_label(n, a, l) /* nothing */
#define make_label_sl(n, a, l) /* nothing */
+ #define make_label_asl(n, a, l) /* nothing */
#endif
#if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS)
#define make_local(n, a, l) MR_insert_internal_label(n, a, NULL)
#define make_local_sl(n, a, l) \
- MR_insert_internal_label(n, a, MR_INTERNAL_LAYOUT(l))
+ MR_insert_internal_label(n, a, MR_INTERNAL_LAYOUT(l))
+ #define make_local_asl(n, a, l) \
+ MR_insert_internal_label(n, a, MR_ALWAYS_INTERNAL_LAYOUT(l))
#else
#define make_local(n, a, l) /* nothing */
#define make_local_sl(n, a, l) /* nothing */
+ #define make_local_asl(n, a, l) /* nothing */
#endif
#if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS)
#define make_entry(n, a, l) MR_insert_entry_label(n, a, NULL)
#define make_entry_sl(n, a, l) \
MR_insert_entry_label(n, a, MR_ENTRY_LAYOUT(l))
+ #define make_entry_asl(n, a, l) \
+ MR_insert_entry_label(n, a, MR_ALWAYS_ENTRY_LAYOUT(l))
#else
#define make_entry(n, a, l) /* nothing */
#define make_entry_sl(n, a, l) /* nothing */
+ #define make_entry_asl(n, a, l) /* nothing */
#endif
#ifdef SPLIT_C_FILES
@@ -483,12 +495,25 @@
** prevent an over-zealous gcc from optimizing away `label'
** and the code that followed.
*/
- #define init_entry(label) \
- PRETEND_ADDRESS_IS_USED(&&label); \
+ #define init_entry(label) \
+ PRETEND_ADDRESS_IS_USED(&&label); \
make_entry(stringify(label), label, label)
- #define init_entry_sl(label) \
- PRETEND_ADDRESS_IS_USED(&&label); \
+ #define init_entry_sl(label) \
+ PRETEND_ADDRESS_IS_USED(&&label); \
make_entry_sl(stringify(label), label, label)
+ #define init_entry_asl(label) \
+ PRETEND_ADDRESS_IS_USED(&&label); \
+ make_entry_asl(stringify(label), label, label)
+ #define MR_always_init_entry(label) \
+ PRETEND_ADDRESS_IS_USED(&&label); \
+ MR_insert_entry_label(stringify(label), label, NULL)
+ #define MR_always_init_entry_sl(label) \
+ PRETEND_ADDRESS_IS_USED(&&label); \
+ MR_insert_entry_label(stringify(label), label, MR_ENTRY_LAYOUT(label))
+ #define MR_always_init_entry_asl(label) \
+ PRETEND_ADDRESS_IS_USED(&&label); \
+ MR_insert_entry_label(stringify(label), label, \
+ MR_ALWAYS_ENTRY_LAYOUT(label))
#define ENTRY(label) (&label)
#define STATIC(label) (&label)
@@ -513,12 +538,26 @@
entry(label): \
label: \
{
- #define init_entry(label) \
- make_entry(stringify(label), &&label, label); \
+ #define init_entry(label) \
+ make_entry(stringify(label), &&label, label); \
entry(label) = &&label
- #define init_entry_sl(label) \
+ #define init_entry_sl(label) \
make_entry_sl(stringify(label), &&label, label); \
entry(label) = &&label
+ #define init_entry_asl(label) \
+ make_entry_asl(stringify(label), &&label, label); \
+ entry(label) = &&label
+ #define MR_always_init_entry(label) \
+ MR_insert_entry_label(stringify(label), &&label, NULL); \
+ entry(label) = &&label
+ #define MR_always_init_entry_sl(label) \
+ MR_insert_entry_label(stringify(label), &&label, \
+ MR_ENTRY_LAYOUT(label)); \
+ entry(label) = &&label
+ #define MR_always_init_entry_asl(label) \
+ MR_insert_entry_label(stringify(label), &&label, \
+ MR_ALWAYS_ENTRY_LAYOUT(label))); \
+ entry(label) = &&label
#define ENTRY(label) (entry(label))
#define STATIC(label) (entry(label))
@@ -536,16 +575,45 @@
{
#define init_local(label) make_local(stringify(label), &&label, label)
#define init_local_sl(label) make_local_sl(stringify(label), &&label, label)
+ #define init_local_asl(label) make_local_asl(stringify(label), &&label, label)
+ #define MR_always_init_local(label) \
+ MR_insert_internal_label(stringify(label), &&label, NULL)
+ #define MR_always_init_local_sl(label) \
+ MR_insert_internal_label(stringify(label), &&label, \
+ MR_INTERNAL_LAYOUT(label))
+ #define MR_always_init_local_asl(label) \
+ MR_insert_internal_label(stringify(label), &&label, \
+ MR_ALWAYS_INTERNAL_LAYOUT(label))
#define Define_label(label) Define_local(label)
#define Declare_label(label) /* no declaration required */
#ifdef MR_INSERT_LABELS
- #define init_label(label) \
+ #define init_label(label) \
make_label(stringify(label), &&entry(label), label)
- #define init_label_sl(label) \
+ #define init_label_sl(label) \
make_label_sl(stringify(label), &&entry(label), label)
+ #define init_label_asl(label) \
+ make_label_asl(stringify(label), &&entry(label), label)
+ #define MR_always_init_label(label) \
+ MR_insert_internal_label(stringify(label), &&entry(label), NULL)
+ #define MR_always_init_label_sl(label) \
+ MR_insert_internal_label(stringify(label), &&entry(label), \
+ MR_INTERNAL_LAYOUT(label))
+ #define MR_always_init_label_asl(label) \
+ MR_insert_internal_label(stringify(label), &&entry(label), \
+ MR_ALWAYS_INTERNAL_LAYOUT(label))
#else
#define init_label(label) make_label(stringify(label), &&label, label)
#define init_label_sl(label) make_label_sl(stringify(label), &&label, label)
+ #define init_label_asl(label) \
+ make_label_asl(stringify(label), &&label, label)
+ #define MR_always_init_label(label) \
+ MR_insert_internal_label(stringify(label), &&label, NULL)
+ #define MR_always_init_label_sl(label) \
+ MR_insert_internal_label(stringify(label), &&label, \
+ MR_INTERNAL_LAYOUT(label))
+ #define MR_always_init_label_asl(label) \
+ MR_insert_internal_label(stringify(label), &&label, \
+ MR_ALWAYS_INTERNAL_LAYOUT(label))
#endif
#define LOCAL(label) (&&entry(label))
@@ -586,6 +654,16 @@
static Code* label(void) {
#define init_entry(label) make_entry(stringify(label), label, label)
#define init_entry_sl(label) make_entry_sl(stringify(label), label, label)
+ #define init_entry_asl(label) make_entry_asl(stringify(label), label, label)
+ #define MR_always_init_entry(label) \
+ MR_insert_entry_label(stringify(label), label, NULL)
+ MR_ALWAYS_INTERNAL_LAYOUT(label))
+ #define MR_always_init_entry_sl(label) \
+ MR_insert_entry_label(stringify(label), label, \
+ MR_INTERNAL_LAYOUT(label))
+ #define MR_always_init_entry_asl(label) \
+ MR_insert_entry_label(stringify(label), label, \
+ MR_ALWAYS_INTERNAL_LAYOUT(label))
#define Declare_local(label) static Code *label(void)
#define Define_local(label) \
@@ -594,6 +672,15 @@
static Code* label(void) {
#define init_local(label) make_local(stringify(label), label, label)
#define init_local_sl(label) make_local_sl(stringify(label), label, label)
+ #define init_local_asl(label) make_local_asl(stringify(label), label, label)
+ #define MR_always_init_local(label) \
+ MR_insert_internal_label(stringify(label), label, NULL)
+ #define MR_always_init_local_sl(label) \
+ MR_insert_internal_label(stringify(label), label, \
+ MR_INTERNAL_LAYOUT(label))
+ #define MR_always_init_local_asl(label) \
+ MR_insert_internal_label(stringify(label), label, \
+ MR_ALWAYS_INTERNAL_LAYOUT(label))
#define Declare_label(label) static Code *label(void)
#define Define_label(label) \
@@ -602,6 +689,15 @@
static Code* label(void) {
#define init_label(label) make_label(stringify(label), label, label)
#define init_label_sl(label) make_label_sl(stringify(label), label, label)
+ #define init_label_asl(label) make_label_asl(stringify(label), label, label)
+ #define MR_always_init_label(label) \
+ MR_insert_internal_label(stringify(label), label, NULL)
+ #define MR_always_init_label_sl(label) \
+ MR_insert_internal_label(stringify(label), label, \
+ MR_INTERNAL_LAYOUT(label))
+ #define MR_always_init_label_asl(label) \
+ MR_insert_internal_label(stringify(label), label, \
+ MR_ALWAYS_INTERNAL_LAYOUT(label))
#define ENTRY(label) ((Code *) (label))
#define STATIC(label) ((Code *) (label))
Index: runtime/mercury_label.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_label.c,v
retrieving revision 1.10
diff -u -u -r1.10 mercury_label.c
--- mercury_label.c 1998/09/15 07:19:23 1.10
+++ mercury_label.c 1998/09/15 08:29:42
@@ -248,5 +248,6 @@
void
MR_process_all_internal_labels(void f(const void *))
{
+ MR_do_init_label_tables();
MR_process_all_entries(internal_addr_table, f);
}
Index: runtime/mercury_macros.h
===================================================================
RCS file: mercury_macros.h
diff -N mercury_macros.h
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_macros.h Wed Jul 29 13:28:20 1998
@@ -0,0 +1,171 @@
+/*
+** 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.
+*/
+
+/*
+** mercury_macros.h defines macros that are useful in more than one
+** module of the Mercury runtime system.
+*/
+
+#ifndef MERCURY_MACROS_H
+#define MERCURY_MACROS_H
+
+/*
+** The MR_ensure_room_for_next macro works with a group of three variables
+** that follow the pattern
+**
+** Item widgets = NULL;
+** int widget_max = 0;
+** int widget_next = 0;
+**
+** where widgets is a pointer to a malloc'd array of items, widget_max
+** gives the number of elements in the array, and widget_next is the
+** index of the first free slot in the widgets array. Widget_max is
+** zero if and only if widgets is NULL.
+**
+** MR_ensure_room_for_next(widget, Item, INIT_SIZE) checks whether
+** there is enough room in the widgets array to add a new item.
+** If not, doubles the size of the existing widgets array, or
+** allocates an array of INIT_SIZE items if the widgets array
+** has not been initialized before.
+*/
+
+#define MR_ensure_room_for_next(base, type, init) \
+ do { \
+ if (base##_next >= base##_max) { \
+ if (base##_max == 0) { \
+ base##_max = init; \
+ base##s = checked_malloc( \
+ base##_max * sizeof(type)); \
+ } else { \
+ base##_max *= 2; \
+ base##s = checked_realloc(base##s, \
+ base##_max * sizeof(type)); \
+ } \
+ } \
+ } while(0)
+
+/*
+** MR_ensure_big_enough makes the same assumptions as MR_ensure_room_for_next,
+** and operates almost the same way. The exception is that it does not assume
+** that the array grows one item at a time; instead it ensures that the array
+** is big enough to contain the element at index `slot'. Since with this regime
+** there is no notion of the "next" slot, this macro does not access, nor does
+** it require the existence of, base##_next.
+*/
+
+#define MR_ensure_big_enough(slot, base, type, init) \
+ do { \
+ if (slot >= base##_max) { \
+ if (base##_max == 0) { \
+ base##_max = max(init, slot + 1); \
+ base##s = checked_malloc( \
+ base##_max * sizeof(type)); \
+ } else { \
+ base##_max = max(base##_max * 2, slot + 1); \
+ base##s = checked_realloc(base##s, \
+ base##_max * sizeof(type)); \
+ } \
+ } \
+ } while(0)
+
+/*
+** MR_ensure_big_enough2 works like MR_ensure_big_enough, except that
+** it resizes two arrays at once. These two arrays are named base##s1 and
+** base##s2, and since they are always the same size, they share the
+** base##_max variable.
+*/
+
+#define MR_ensure_big_enough2(slot, base, s1, s2, type, init) \
+ do { \
+ if (slot >= base##_max) { \
+ if (base##_max == 0) { \
+ base##_max = max(init, slot + 1); \
+ base##s1 = checked_malloc( \
+ base##_max * sizeof(type)); \
+ base##s2 = checked_malloc( \
+ base##_max * sizeof(type)); \
+ } else { \
+ base##_max = max(base##_max * 2, slot + 1); \
+ base##s1 = checked_realloc(base##s1, \
+ base##_max * sizeof(type)); \
+ base##s2 = checked_realloc(base##s2, \
+ base##_max * sizeof(type)); \
+ } \
+ } \
+ } while(0)
+
+/*
+** MR_bsearch(int next, int& element, bool& found, COMPARE)
+**
+** Given a sorted array, this macro performs a binary search.
+** If the search is successful, MR_bsearch sets the `found' parameter
+** to TRUE and the `element' parameter to the index of the desired item.
+** If the search is unsuccessful, MR_bsearch sets `found' to FALSE;
+** `element' will be clobbered.
+**
+** The number of the elements in the array is given by the `next' parameter.
+** The `COMPARE' parameter should be an expression which compares
+** the value at the index specified by the current value of `element'
+** with the desired value, and returns <0, 0, or >0 according to whether
+** it is less than, equal to, or greater than the desired value.
+**
+** The name of the array to be searched is not explicitly a parameter;
+** its identity is encoded in the boolean expression of the `COMPARE'
+** parameter.
+*/
+
+#define MR_bsearch(next, element, found, COMPARE) \
+ do { \
+ int lo; \
+ int hi; \
+ int diff; \
+ \
+ lo = 0; \
+ hi = (next) - 1; \
+ (found) = FALSE; \
+ while (lo <= hi) { \
+ (element) = (lo + hi) / 2; \
+ diff = (COMPARE); \
+ if (diff == 0) { \
+ (found) = TRUE; \
+ break; \
+ } else if (diff < 0) { \
+ lo = (element) + 1; \
+ } else { \
+ hi = (element) - 1; \
+ } \
+ } \
+ } while(0)
+
+/*
+** MR_prepare_insert_into_sorted(array[], int& next, int& element, COMPARE)
+**
+** Given a sorted array `items', this prepares for the insertion of a new
+** item into the array at the proper point. It find the index at which
+** the new item should be inserted, and moves all items at and above that
+** index one position to the right to make room for the new item.
+**
+** The `next' parameter holds the number of elements in the array;
+** it is incremented by this macro. The macro returns the indexs of the slot
+** at which the new item should be inserted in the `element' parameter.
+** The `COMPARE' parameter should be an expression which compares
+** the item at the index specified by the current value of `element' with
+** the item being inserted, and returns <0, 0, or >0 according to whether
+** it is less than, equal to, or greater than the item being inserted.
+*/
+
+#define MR_prepare_insert_into_sorted(items, next, element, COMPARE) \
+ do { \
+ (element) = (next) - 1; \
+ while ((element) >= 0 && COMPARE > 0) { \
+ items[element + 1] = items[element]; \
+ (element) -= 1; \
+ } \
+ (element) += 1; \
+ (next) += 1; \
+ } while(0)
+
+#endif /* MERCURY_MACROS_H */
Index: runtime/mercury_memory.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory.c,v
retrieving revision 1.13
diff -u -u -r1.13 mercury_memory.c
--- mercury_memory.c 1998/08/24 08:24:45 1.13
+++ mercury_memory.c 1998/08/24 09:05:52
@@ -244,16 +244,16 @@
{
#ifdef CONSERVATIVE_GC
GC_FREE(ptr);
-
#else
free(ptr);
#endif
}
+
+/*
+** Note: checked_malloc()ed structures never contain pointers into GCed memory,
+** so we don't need to GC_malloc() them. (cf. newmem())
+*/
- /* Note: checked_malloc()ed structures */
- /* never contain pointers into GCed */
- /* memory, so we don't need to */
- /* GC_malloc() them. (cf. newmem()) */
void *
checked_malloc(size_t n)
{
@@ -267,7 +267,6 @@
return p;
}
-
void *
checked_realloc(void *old, size_t n)
{
@@ -281,3 +280,14 @@
return p;
}
+char *
+MR_copy_string(const char *s)
+{
+ int len;
+ char *copy;
+
+ len = strlen(s);
+ copy = checked_malloc(len + 1);
+ strcpy(copy, s);
+ return copy;
+}
Index: runtime/mercury_memory.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory.h,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_memory.h
--- mercury_memory.h 1998/07/22 07:52:54 1.7
+++ mercury_memory.h 1998/07/23 06:38:11
@@ -51,6 +51,7 @@
** For these functions, see the comments in mercury_memory.c and
** mercury_engine.c
*/
+
extern void init_memory(void);
extern void init_heap(void);
extern void debug_memory(void);
@@ -82,7 +83,6 @@
void deallocate_memory(void *);
-
/*
** checked_malloc() and checked_realloc() are like the standard C
** malloc() and realloc() functions, except that the return values
@@ -94,16 +94,22 @@
*/
#include <stddef.h> /* for size_t */
-void *checked_malloc(size_t n);
-void *checked_realloc(void *old, size_t n);
+void *checked_malloc(size_t n);
+void *checked_realloc(void *old, size_t n);
+
+/*
+** MR_copy_string makes a copy of the given string with checked_malloc.
+*/
+
+char *MR_copy_string(const char *s);
/*
** `unit' is the size of the minimum unit of memory we allocate (in bytes).
** `page_size' is the size of a single page of memory.
*/
-extern size_t unit;
-extern size_t page_size;
+extern size_t unit;
+extern size_t page_size;
/*
** Users need to call MR_add_root() for any global variable which
Index: runtime/mercury_misc.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.c,v
retrieving revision 1.12
diff -u -u -r1.12 mercury_misc.c
--- mercury_misc.c 1998/08/24 08:24:48 1.12
+++ mercury_misc.c 1998/08/25 04:24:56
@@ -500,12 +500,25 @@
exit(EXIT_FAILURE);
}
- /* See header file for documentation on why we need this function */
+/*
+** See header file for documentation on why we need these two functions.
+*/
+
void
MR_memcpy(char *dest, const char *src, size_t nbytes)
{
while (nbytes-- > 0)
*dest++ = *src++;
+}
+
+void
+MR_memcpy_fromhigh(char *dest, const char *src, size_t nbytes)
+{
+ dest += nbytes;
+ src += nbytes;
+
+ while (nbytes-- > 0)
+ *--dest = *--src;
}
/*
Index: runtime/mercury_misc.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.h,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_misc.h
--- mercury_misc.h 1998/08/19 07:45:24 1.9
+++ mercury_misc.h 1998/08/24 09:05:54
@@ -9,7 +9,7 @@
** MR_warning(),
** fatal_error(),
** checked_malloc(),
-** MR_memcpy
+** MR_memcpy/MR_memrevcpy
*/
#ifndef MERCURY_MISC_H
@@ -68,9 +68,16 @@
** standard memcpy and generates inline code for them. Unfortunately this
** causes it to abort because it tries to use a register that we're already
** reserved.
+**
** XXX We should fix this eventually by using -fno-builtin since pragma
** c_code may call the builtin functions.
+**
+** MR_memcpy does the copying from the low bytes first; MR_memcpy_fromhigh
+** does the copying from the high bytes first. If the src and dest arrays
+** overlap, you must be careful to call the right version.
*/
+
extern void MR_memcpy(char *dest, const char *src, size_t nbytes);
+extern void MR_memcpy_fromhigh(char *dest, const char *src, size_t nbytes);
#endif /* not MERCURY_MISC_H */
Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.8
diff -u -u -r1.8 mercury_stack_layout.h
--- mercury_stack_layout.h 1998/07/09 04:37:57 1.8
+++ mercury_stack_layout.h 1998/09/15 08:19:38
@@ -9,7 +9,7 @@
/*
** mercury_stack_layout.h -
-** Definitions for the stack layout data structures.
+** Definitions for the stack layout data structures.
**
** NOTE: The constants and data-structures used here need to be kept in
** sync with the ones generated in the compiler. If you change anything here,
@@ -70,7 +70,7 @@
** - stack slots, registers, and special lvals such as succip, hp,
** etc.
**
-** MR_Live_Lval is encoded using an 8 bit low tag, the rest of the word is a
+** MR_Live_Lval is encoded using an 8 bit low tag, the rest of the word is a
** data field describing which stack slot number or register number.
**
** Lval Tag Rest
@@ -93,7 +93,7 @@
typedef Word MR_Live_Lval;
-typedef enum {
+typedef enum {
MR_LVAL_TYPE_R,
MR_LVAL_TYPE_F,
MR_LVAL_TYPE_STACKVAR,
@@ -103,7 +103,7 @@
MR_LVAL_TYPE_CURFR,
MR_LVAL_TYPE_HP,
MR_LVAL_TYPE_SP,
- MR_LVAL_TYPE_UNKNOWN
+ MR_LVAL_TYPE_UNKNOWN
} MR_Lval_Type;
#define MR_LIVE_LVAL_TAGBITS 8
@@ -126,7 +126,7 @@
**
** The data is encoded such that low values (less than
** TYPELAYOUT_MAX_VARINT) represent succip, hp, etc. Higher values
-** represent data variables, and are pointers to a 2 word cell,
+** represent data variables, and are pointers to a 2 word cell,
** containing a pseudo type_info and an instantiation represention.
**
** This data is generated in compiler/stack_layout.m, which must be kept
@@ -135,16 +135,16 @@
typedef Word MR_Live_Type;
-typedef enum {
+typedef enum {
MR_LIVE_TYPE_SUCCIP,
MR_LIVE_TYPE_HP,
MR_LIVE_TYPE_CURFR,
MR_LIVE_TYPE_MAXFR,
MR_LIVE_TYPE_REDOIP,
- MR_LIVE_TYPE_UNWANTED
+ MR_LIVE_TYPE_UNWANTED
} MR_Lval_NonVar;
-typedef struct {
+typedef struct {
Word *pseudo_type_info;
Word inst; /* not yet used; currently always -1 */
} MR_Var_Shape_Info;
@@ -189,12 +189,18 @@
MR_Live_Lval *MR_slvs_tvars;
} MR_Stack_Layout_Vars;
-#define MR_name_if_present(vars, i) \
- ((vars->MR_slvs_names != NULL \
- && vars->MR_slvs_names[(i)] != NULL) \
- ? vars->MR_slvs_names[(i)] \
+#define MR_name_if_present(vars, i) \
+ ((vars->MR_slvs_names != NULL \
+ && vars->MR_slvs_names[(i)] != NULL) \
+ ? strchr(vars->MR_slvs_names[(i)], ':') + 1 \
: "")
+#define MR_numbered_name_if_present(vars, i) \
+ ((vars->MR_slvs_names != NULL \
+ && vars->MR_slvs_names[(i)] != NULL) \
+ ? vars->MR_slvs_names[(i)] \
+ : "")
+
/*-------------------------------------------------------------------------*/
/*
** Definitions for MR_Stack_Layout_Entry
@@ -222,6 +228,10 @@
** if MR_ENTRY_LAYOUT_HAS_PROC_ID(entry) evaluates to true.
** Group (3) is present and meaningful
** if MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry) evaluates to true.
+**
+** Group (2) fields have a different interpretation if the procedure is
+** compiler-generated. You can test for this via the macro
+** MR_ENTRY_LAYOUT_COMPILER_GENERATED.
*/
typedef struct MR_Stack_Layout_Entry_Struct {
@@ -242,6 +252,7 @@
/* exec trace group */
struct MR_Stack_Layout_Label_Struct
*MR_sle_call_label;
+ int MR_sle_maybe_from_full;
} MR_Stack_Layout_Entry;
#define MR_ENTRY_LAYOUT_HAS_PROC_ID(entry) \
@@ -251,31 +262,75 @@
(MR_ENTRY_LAYOUT_HAS_PROC_ID(entry) \
&& entry->MR_sle_call_label != NULL)
+#define MR_ENTRY_LAYOUT_COMPILER_GENERATED(entry) \
+ ((int) entry->MR_sle_pred_or_func > MR_FUNCTION)
+
/*
** Define a stack layout for a label that you know very little about.
** It is just a generic entry label, no useful information, except
** the code address for the label.
-*/
+*/
+
+#define MR_DEFINE_STACK_LAYOUT_ENTRY(l) \
+ const struct mercury_data__layout__##l##_struct { \
+ Code *f1; \
+ Integer f2; \
+ Integer f3; \
+ Integer f4; \
+ Integer f5; \
+ } mercury_data__layout__##l = { \
+ STATIC(l), \
+ (Integer) -1, /* Unknown determinism */ \
+ (Integer) -1, /* Unknown number of stack slots */ \
+ (Integer) MR_LVAL_TYPE_UNKNOWN, /* Unknown succip locn */\
+ (Integer) -1, /* Procid component is not present */ \
+ };
#ifdef MR_USE_STACK_LAYOUTS
- #define MR_MAKE_STACK_LAYOUT_ENTRY(l) \
- const struct mercury_data__layout__##l##_struct { \
- Code *f1; \
- Integer f2; \
- Integer f3; \
- Integer f4; \
- Integer f5; \
- } mercury_data__layout__##l = { \
- STATIC(l), \
- (Integer) -1, /* Unknown determinism */ \
- (Integer) -1, /* Unknown number of stack slots */ \
- (Integer) MR_LVAL_TYPE_UNKNOWN, /* Unknown succip location */ \
- (Integer) -1, /* The procid component is not present */ \
- };
+ #define MR_MAKE_STACK_LAYOUT_ENTRY(l) \
+ MR_DEFINE_STACK_LAYOUT_ENTRY(l)
#else
- #define MR_MAKE_STACK_LAYOUT_ENTRY(l)
+ #define MR_MAKE_STACK_LAYOUT_ENTRY(l)
#endif /* MR_USE_STACK_LAYOUTS */
+/*
+** In procedures compiled with execution tracing, three items are stored
+** in stack slots with fixed numbers. They are:
+**
+** the event number of the call event,
+** the call number, and
+** the call depth.
+**
+** The following macros will access them. They can be used whenever
+** MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry) is true; which set you should use
+** depends on the determinism of the procedure.
+**
+** These macros have to be kept in sync with compiler/trace.m.
+*/
+
+#define MR_event_num_framevar(base_curfr) MR_based_framevar(base_curfr, 1)
+#define MR_call_num_framevar(base_curfr) MR_based_framevar(base_curfr, 2)
+#define MR_call_depth_framevar(base_curfr) MR_based_framevar(base_curfr, 3)
+
+#define MR_event_num_stackvar(base_sp) MR_based_stackvar(base_sp, 1)
+#define MR_call_num_stackvar(base_sp) MR_based_stackvar(base_sp, 2)
+#define MR_call_depth_stackvar(base_sp) MR_based_stackvar(base_sp, 3)
+
+/*
+** In model_non procedures compiled with an execution trace options that
+** require REDO events, one other item is stored in a fixed stack slot.
+** This is
+**
+** the address of the layout structure for the redo event
+**
+** The following macro will access it. This macro should be used only from
+** within the code that calls MR_trace for the REDO event.
+**
+** This macros have to be kept in sync with compiler/trace.m.
+*/
+
+#define MR_redo_layout_framevar(base_curfr) MR_based_framevar(base_curfr, 4)
+
/*-------------------------------------------------------------------------*/
/*
** Definitions for MR_Stack_Layout_Label
@@ -310,21 +365,24 @@
**
** The only useful information in this structure is the code address
** and the reference to the entry for this label.
-*/
+*/
+#define MR_DEFINE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e) \
+ const struct mercury_data__layout__##l##_struct { \
+ const Word *f1; \
+ UNKNOWN_INTERNAL_LABEL_FIELD \
+ Integer f3; \
+ } mercury_data__layout__##l = { \
+ (const Word *) &mercury_data__layout__##e, \
+ UNKNOWN_INTERNAL_LABEL_NUMBER \
+ (Integer) -1 /* No information about live values */ \
+ };
+
#ifdef MR_USE_STACK_LAYOUTS
- #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e) \
- const struct mercury_data__layout__##l##_struct { \
- const Word *f1; \
- UNKNOWN_INTERNAL_LABEL_FIELD \
- Integer f3; \
- } mercury_data__layout__##l = { \
- (const Word *) &mercury_data__layout__##e, \
- UNKNOWN_INTERNAL_LABEL_NUMBER \
- (Integer) -1 /* No information about live values */ \
- };
+ #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e) \
+ MR_DEFINE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)
#else
- #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)
+ #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)
#endif /* MR_USE_STACK_LAYOUTS */
/*
@@ -333,29 +391,32 @@
** label_name_i3, x is 3. It is assumed the entry label for that
** corresponds to this label is the label name without the _iX suffix.
**
-** (MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY, above, is a little
-** more general than MR_MAKE_STACK_LAYOUT_INTERNAL. This macro can
+** (MR_DEFINE_STACK_LAYOUT_INTERNAL_WITH_ENTRY, above, is a little
+** more general than MR_DEFINE_STACK_LAYOUT_INTERNAL. This macro can
** only describe relationships between labels that have the same
-** base -- MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY can create layouts
+** base -- MR_DEFINE_STACK_LAYOUT_INTERNAL_WITH_ENTRY can create layouts
** for internal labels no matter what the name of the entry layout is).
**
** The only useful information in this structure is the code address
** and the reference to the entry for this label.
-*/
+*/
+
+#define MR_DEFINE_STACK_LAYOUT_INTERNAL(e, x) \
+ const struct mercury_data__layout__##e##_i##x##_struct { \
+ const Word *f1; \
+ UNKNOWN_INTERNAL_LABEL_FIELD \
+ Integer f3; \
+ } mercury_data__layout__##e##_i##x = { \
+ (const Word *) &mercury_data__layout__##e, \
+ UNKNOWN_INTERNAL_LABEL_NUMBER \
+ (Integer) -1 /* No information about live values */ \
+ };
#ifdef MR_USE_STACK_LAYOUTS
- #define MR_MAKE_STACK_LAYOUT_INTERNAL(e, x) \
- const struct mercury_data__layout__##e##_i##x##_struct { \
- const Word *f1; \
- UNKNOWN_INTERNAL_LABEL_FIELD \
- Integer f3; \
- } mercury_data__layout__##e##_i##x = { \
- (const Word *) &mercury_data__layout__##e, \
- UNKNOWN_INTERNAL_LABEL_NUMBER \
- (Integer) -1 /* No information about live values */ \
- };
+ #define MR_MAKE_STACK_LAYOUT_INTERNAL(e, x) \
+ MR_DEFINE_STACK_LAYOUT_INTERNAL(e, x)
#else
- #define MR_MAKE_STACK_LAYOUT_INTERNAL(l, x)
+ #define MR_MAKE_STACK_LAYOUT_INTERNAL(e, x)
#endif /* MR_USE_STACK_LAYOUTS */
#endif /* not MERCURY_STACK_LAYOUT_H */
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.16
diff -u -u -r1.16 mercury_stack_trace.c
--- mercury_stack_trace.c 1998/07/29 08:56:03 1.16
+++ mercury_stack_trace.c 1998/08/19 10:30:19
@@ -171,7 +171,8 @@
return STEP_ERROR_AFTER;
}
- success = (Code *) field(0, *stack_trace_sp_ptr, -number);
+ success = (Code *) MR_based_stackvar(*stack_trace_sp_ptr,
+ number);
*stack_trace_sp_ptr = *stack_trace_sp_ptr -
entry_layout->MR_sle_stack_slots;
} else {
@@ -286,15 +287,42 @@
fprintf(fp, "%9d ", start_level);
if (count > 1) {
- fprintf(fp, " %3d*", count);
+ fprintf(fp, " %3d* ", count);
} else {
- fprintf(fp, "%5s", "");
+ fprintf(fp, "%5s ", "");
}
- fprintf(fp, " %s:%s/%ld-%ld (%s)\n",
+ MR_print_proc_id(fp, entry_layout, NULL);
+}
+
+void
+MR_print_proc_id_for_debugger(const MR_Stack_Layout_Entry *entry_layout)
+{
+ MR_print_proc_id(stdout, entry_layout, NULL);
+}
+
+void
+MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
+ const char *extra)
+{
+ /*
+ ** The following should be a full identification of the procedure
+ ** provided (a) there was no intermodule optimization and (b) we are
+ ** not interested in the details of compiler-generated procedures.
+ */
+
+ fprintf(fp, "%s %s:%s/%ld-%ld (%s)",
+ entry_layout->MR_sle_pred_or_func == MR_PREDICATE ?
+ "pred" : "func",
entry_layout->MR_sle_def_module,
entry_layout->MR_sle_name,
(long) entry_layout->MR_sle_arity,
(long) entry_layout->MR_sle_mode,
detism_names[entry_layout->MR_sle_detism]);
+
+ if (extra != NULL) {
+ fprintf(fp, " %s\n", extra);
+ } else {
+ fprintf(fp, "\n");
+ }
}
Index: runtime/mercury_stack_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_stack_trace.h
--- mercury_stack_trace.h 1998/07/22 07:53:09 1.9
+++ mercury_stack_trace.h 1998/07/23 06:39:41
@@ -37,9 +37,8 @@
** using `:- external'.
*/
-extern void MR_dump_stack(Code *success_pointer,
- Word *det_stack_pointer,
- Word *current_frame);
+extern void MR_dump_stack(Code *success_pointer, Word *det_stack_pointer,
+ Word *current_frame);
/*
** MR_dump_stack_from_layout:
@@ -62,8 +61,7 @@
** The value of maxfr should be in *base_maxfr.
*/
-extern void MR_dump_nondet_stack_from_layout(FILE *fp,
- Word *base_maxfr);
+extern void MR_dump_nondet_stack_from_layout(FILE *fp, Word *base_maxfr);
/*
** MR_find_nth_ancestor:
@@ -81,36 +79,11 @@
*/
extern const MR_Stack_Layout_Label *MR_find_nth_ancestor(
- const MR_Stack_Layout_Label *label_layout,
- int ancestor_level, Word **stack_trace_sp,
- Word **stack_trace_curfr, const char **problem);
+ const MR_Stack_Layout_Label *label_layout,
+ int ancestor_level, Word **stack_trace_sp,
+ Word **stack_trace_curfr, const char **problem);
/*
-** MR_stack_trace_bottom should be set to the address of global_success,
-** the label main/2 goes to on success. Stack dumps terminate when they
-** reach a stack frame whose saved succip slot contains this address.
-*/
-
-Code *MR_stack_trace_bottom;
-
-/*
-** MR_nondet_stack_trace_bottom should be set to the address of the buffer
-** nondet stack frame created before calling main. Nondet stack dumps terminate
-** when they reach a stack frame whose redoip contains this address. Note that
-** the redoip and redofr slots of this frame may be hijacked.
-*/
-
-Word *MR_nondet_stack_trace_bottom;
-
-
-typedef enum {
- STEP_ERROR_BEFORE, /* the current entry_layout has no valid info */
- STEP_ERROR_AFTER, /* the current entry_layout has valid info,
- but the next one does not */
- STEP_OK /* both have valid info */
-} MR_Stack_Walk_Step_Result;
-
-/*
** MR_stack_walk_step:
** This function takes the entry_layout for the current stack
** frame (which is the topmost stack frame from the two stack
@@ -126,10 +99,47 @@
** encountered, problem_ptr will be set to a string representation
** of the error.
*/
+
+typedef enum {
+ STEP_ERROR_BEFORE, /* the current entry_layout has no valid info */
+ STEP_ERROR_AFTER, /* the current entry_layout has valid info,
+ but the next one does not */
+ STEP_OK /* both have valid info */
+} MR_Stack_Walk_Step_Result;
+
extern MR_Stack_Walk_Step_Result
MR_stack_walk_step(const MR_Stack_Layout_Entry *entry_layout,
const MR_Stack_Layout_Label **return_label_layout,
Word **stack_trace_sp_ptr, Word **stack_trace_curfr_ptr,
const char **problem_ptr);
+
+/*
+** MR_stack_trace_bottom should be set to the address of global_success,
+** the label main/2 goes to on success. Stack dumps terminate when they
+** reach a stack frame whose saved succip slot contains this address.
+*/
+
+Code *MR_stack_trace_bottom;
+
+/*
+** MR_nondet_stack_trace_bottom should be set to the address of the buffer
+** nondet stack frame created before calling main. Nondet stack dumps terminate
+** when they reach a stack frame whose redoip contains this address. Note that
+** the redoip and redofr slots of this frame may be hijacked.
+*/
+
+Word *MR_nondet_stack_trace_bottom;
+
+/*
+** MR_print_proc_id prints an identification of the given procedure,
+** consisting of "pred" or "func", module name, pred or func name, arity,
+** mode number and determinism, followed by an optional extra string,
+** and a newline.
+*/
+
+extern void MR_print_proc_id_for_debugger(
+ const MR_Stack_Layout_Entry *entry);
+extern void MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry,
+ const char *extra);
#endif /* MERCURY_STACK_TRACE_H */
Index: runtime/mercury_stacks.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stacks.h,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_stacks.h
--- mercury_stacks.h 1998/08/02 06:37:00 1.9
+++ mercury_stacks.h 1998/09/10 09:06:02
@@ -21,9 +21,6 @@
#define MR_stackvar(n) MR_based_stackvar(MR_sp, n)
#define detstackvar(n) MR_based_stackvar(MR_sp, n)
-#define based_detstackvar(base_sp, n) MR_based_stackvar(base_sp, n)
-#define saved_detstackvar(save_area, n) \
- MR_based_stackvar(MR_saved_sp(save_area), n)
#define incr_sp_push_msg(n, msg) \
( \
@@ -127,10 +124,6 @@
#define MR_framevar(n) MR_based_framevar(MR_curfr,n)
#define framevar(n) MR_framevar(n+1)
-#define based_framevar(base_curfr, n) \
- MR_based_framevar(base_curfr, n+1)
-#define saved_framevar(save_area, n) \
- MR_based_framevar(MR_saved_curfr(save_area), n+1)
/* DEFINITIONS FOR MANIPULATING THE NONDET STACK */
Index: runtime/mercury_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.c,v
retrieving revision 1.17
diff -u -u -r1.17 mercury_trace.c
--- mercury_trace.c 1998/07/23 20:12:23 1.17
+++ mercury_trace.c 1998/08/12 09:21:11
@@ -1,4 +1,8 @@
/*
+INIT mercury_sys_init_trace
+ENDINIT
+*/
+/*
** Copyright (C) 1997-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.
@@ -20,104 +24,188 @@
** Main author: Zoltan Somogyi.
*/
+#define MR_STACK_TRACE_THIS_MODULE
#include "mercury_imp.h"
#include "mercury_trace.h"
#include "mercury_trace_util.h"
#include "mercury_trace_internal.h"
#include "mercury_trace_external.h"
+#include "mercury_trace_spy.h"
+#include "mercury_memory.h"
#include "mercury_engine.h"
#include "mercury_wrapper.h"
#include "mercury_misc.h"
+#include "mercury_macros.h"
#include <stdio.h>
#include <unistd.h> /* for the write system call */
-static MR_trace_cmd_info MR_trace_ctrl = { MR_CMD_GOTO, 0, 0, FALSE };
+static MR_Trace_Cmd_Info MR_trace_ctrl = { MR_CMD_GOTO, 0, 0,
+ MR_PRINT_LEVEL_SOME, FALSE };
-static void MR_trace_event(MR_trace_cmd_info *cmd,
+static Code *MR_trace_event(MR_Trace_Cmd_Info *cmd, bool interactive,
const MR_Stack_Layout_Label *layout,
- MR_trace_port port, Unsigned seqno, Unsigned depth,
+ MR_Trace_Port port, Unsigned seqno, Unsigned depth,
const char *path, int max_r_num);
-static void MR_trace_event_report(const MR_Stack_Layout_Label *layout,
- MR_trace_port port, Unsigned seqno, Unsigned depth,
- const char *path, int max_r_num);
+/*
+** Reserve room for event counts for this many depths initially.
+*/
+
+#define INIT_HISTOGRAM 128
/*
-** This function is called from compiled code whenever an event to be traced
+** MR_trace() is called from compiled code whenever an event to be traced
** occurs.
*/
-void
-MR_trace(const MR_Stack_Layout_Label *layout, MR_trace_port port,
- Unsigned seqno, Unsigned depth, const char *path, int max_r_num,
- bool trace_this)
+Code *
+MR_trace(const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
+ const char *path, int max_r_num)
{
- if (! (MR_trace_enabled && trace_this))
- return;
+ MR_Spy_Action action;
+ bool match;
+ Unsigned seqno;
+ Unsigned depth;
+ bool maybe_from_full;
+
+ if (! MR_trace_enabled)
+ return NULL;
+
+ maybe_from_full = layout->MR_sll_entry->MR_sle_maybe_from_full;
+ if (MR_DETISM_DET_STACK(layout->MR_sll_entry->MR_sle_detism)) {
+ if (maybe_from_full > 0 && !MR_stackvar(maybe_from_full))
+ return NULL;
+ seqno = (Unsigned) MR_call_num_stackvar(MR_sp);
+ depth = (Unsigned) MR_call_depth_stackvar(MR_sp);
+ } else {
+ if (maybe_from_full > 0 && !MR_framevar(maybe_from_full))
+ return NULL;
+
+ seqno = (Unsigned) MR_call_num_framevar(MR_curfr);
+ depth = (Unsigned) MR_call_depth_framevar(MR_curfr);
+ }
+
MR_trace_event_number++;
+#ifdef MR_TRACE_HISTOGRAM
+
+ /*
+ ** The depths do not necessarily increase one-by-one, since
+ ** a procedure from a fully traced module can be called from
+ ** deep within interface traced code.
+ */
+
+ MR_ensure_big_enough2(depth, MR_trace_histogram, _all, _exp,
+ int, INIT_HISTOGRAM);
+
+ if (depth > MR_trace_histogram_hwm) {
+ MR_trace_histogram_hwm = depth;
+ }
+
+ MR_trace_histogram_all[depth]++;
+ MR_trace_histogram_exp[depth]++;
+
+#endif /* MR_TRACE_HISTOGRAM */
+
switch (MR_trace_ctrl.MR_trace_cmd) {
case MR_CMD_FINISH:
- if (MR_trace_ctrl.MR_trace_stop_seqno == seqno
- && MR_port_is_final(port)) {
- MR_trace_event(&MR_trace_ctrl, layout,
- port, seqno, depth, path, max_r_num);
-
- } else if (MR_trace_ctrl.MR_trace_print_intermediate) {
- MR_trace_event_report(layout,
- port, seqno, depth, path, max_r_num);
+ if (MR_trace_ctrl.MR_trace_stop_depth == depth
+ && MR_port_is_final(port))
+ {
+ return MR_trace_event(&MR_trace_ctrl, TRUE,
+ layout, port, seqno, depth,
+ path, max_r_num);
+ } else {
+ goto check_stop_print;
}
- break;
-
case MR_CMD_GOTO:
if (MR_trace_event_number >=
- MR_trace_ctrl.MR_trace_stop_event
- || MR_event_matches_spy_point(layout)) {
- MR_trace_event(&MR_trace_ctrl, layout,
- port, seqno, depth, path, max_r_num);
- } else if (MR_trace_ctrl.MR_trace_print_intermediate) {
- MR_trace_event_report(layout,
- port, seqno, depth, path, max_r_num);
+ MR_trace_ctrl.MR_trace_stop_event)
+ {
+ return MR_trace_event(&MR_trace_ctrl, TRUE,
+ layout, port, seqno, depth,
+ path, max_r_num);
+ } else {
+ goto check_stop_print;
}
- break;
-
case MR_CMD_RESUME_FORWARD:
if (MR_port_is_final(port)) {
- MR_trace_event(&MR_trace_ctrl, layout,
- port, seqno, depth, path, max_r_num);
- } else if (MR_trace_ctrl.MR_trace_print_intermediate) {
- MR_trace_event_report(layout,
- port, seqno, depth, path, max_r_num);
+ return MR_trace_event(&MR_trace_ctrl, TRUE,
+ layout, port, seqno, depth,
+ path, max_r_num);
+ } else {
+ goto check_stop_print;
}
- break;
-
case MR_CMD_TO_END:
- if (MR_event_matches_spy_point(layout)) {
- MR_trace_event(&MR_trace_ctrl, layout,
- port, seqno, depth, path, max_r_num);
- } else if (MR_trace_ctrl.MR_trace_print_intermediate) {
- MR_trace_event_report(layout,
- port, seqno, depth, path, max_r_num);
- }
-
- break;
+ goto check_stop_print;
default:
fatal_error("invalid cmd in MR_trace");
- break;
}
+
+check_stop_print:
+
+ if (MR_trace_ctrl.MR_trace_must_check) {
+ /*
+ ** The value of MR_trace_ctrl.MR_trace_must_check was
+ ** precomputed when the command was set up; it was set to TRUE
+ ** iff either MR_trace_ctrl.MR_trace_strict is FALSE (allowing
+ ** us to stop at breakpoints whose action is MR_SPY_STOP) or
+ ** MR_trace_ctrl.MR_trace_print_level is something other than
+ ** MR_PRINT_LEVEL_NONE (allowing us to print at least some
+ ** events). The precomputation avoids several jumps in the
+ ** very frequent case that MR_trace_must_check is false.
+ */
+
+ match = MR_event_matches_spy_point(layout, port, &action);
+ if (! match) {
+ if (MR_trace_ctrl.MR_trace_print_level ==
+ MR_PRINT_LEVEL_ALL)
+ {
+ return MR_trace_event(&MR_trace_ctrl, FALSE,
+ layout, port, seqno, depth,
+ path, max_r_num);
+ }
+
+ return NULL;
+ }
+
+ if ((! MR_trace_ctrl.MR_trace_strict)
+ && action == MR_SPY_STOP)
+ {
+ return MR_trace_event(&MR_trace_ctrl, TRUE,
+ layout, port, seqno, depth,
+ path, max_r_num);
+ }
+
+ if (MR_trace_ctrl.MR_trace_print_level != MR_PRINT_LEVEL_NONE) {
+ /*
+ ** It doesn't matter whether action is MR_SPY_STOP or
+ ** MR_SPY_PRINT; even if it is MR_SPY_STOP, we want
+ ** to print it if printing is allowed and we did not
+ ** stop.
+ */
+
+ return MR_trace_event(&MR_trace_ctrl, FALSE,
+ layout, port, seqno, depth,
+ path, max_r_num);
+ }
+ }
+
+ return NULL;
}
-static void
-MR_trace_event(MR_trace_cmd_info *cmd,
- const MR_Stack_Layout_Label *layout, MR_trace_port port,
+static Code *
+MR_trace_event(MR_Trace_Cmd_Info *cmd, bool interactive,
+ const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
Unsigned seqno, Unsigned depth, const char *path, int max_r_num)
{
int max_mr_num;
+ Code *jumpaddr;
if (max_r_num + MR_NUM_SPECIAL_REG > MR_MAX_SPECIAL_REG_MR) {
max_mr_num = max_r_num + MR_NUM_SPECIAL_REG;
@@ -126,11 +214,18 @@
}
MR_copy_regs_to_saved_regs(max_mr_num);
+
#ifdef MR_USE_EXTERNAL_DEBUGGER
if (MR_trace_handler == MR_TRACE_EXTERNAL) {
+ if (!interactive) {
+ fatal_error("reporting event for external debugger");
+ }
+
MR_trace_event_external(cmd, layout, port, seqno, depth, path);
+ jumpaddr = NULL;
} else {
- MR_trace_event_internal(cmd, layout, port, seqno, depth, path);
+ jumpaddr = MR_trace_event_internal(cmd, interactive,
+ layout, port, seqno, depth, path, &max_mr_num);
}
#else
/*
@@ -138,28 +233,46 @@
** This is enforced by mercury_wrapper.c.
*/
- MR_trace_event_internal(cmd, layout, port, seqno, depth, path);
+ jumpaddr = MR_trace_event_internal(cmd, interactive,
+ layout, port, seqno, depth, path, &max_mr_num);
#endif
- MR_copy_saved_regs_to_regs(max_mr_num);
-}
-static void
-MR_trace_event_report(const MR_Stack_Layout_Label *layout, MR_trace_port port,
- Unsigned seqno, Unsigned depth, const char *path, int max_r_num)
-{
-#ifdef MR_USE_EXTERNAL_DEBUGGER
- if (MR_trace_handler == MR_TRACE_EXTERNAL) {
- fatal_error("trying to report an event to external debugger");
- } else {
- MR_trace_event_internal_report(layout,
- port, seqno, depth, path);
- }
-#else
/*
- ** We should get here only if MR_trace_handler == MR_TRACE_INTERNAL.
- ** This is enforced by mercury_wrapper.c.
+ ** Whenever the debugger changes the flow of control, e.g. by
+ ** executing a retry command, it also sets up the saved registers
+ ** to the state that is appropriate for the label at which execution
+ ** will resume. There may be more registers live at that point than
+ ** at the point at which MR_trace was called. Therefore max_mr_num
+ ** should also be set appropriately when executing a retry command.
*/
+
+ MR_copy_saved_regs_to_regs(max_mr_num);
+ return jumpaddr;
+}
+
+Define_extern_entry(MR_do_trace_redo_fail);
- MR_trace_event_internal_report(layout, port, seqno, depth, path);
+BEGIN_MODULE(MR_trace_labels_module)
+ init_label(MR_do_trace_redo_fail);
+BEGIN_CODE
+
+Define_entry(MR_do_trace_redo_fail);
+#if 0
+ printf("MR_curfr = %p\n", MR_curfr);
+ printf("MR_redofr_slot(MR_curfr) = %p\n", MR_redofr_slot(MR_curfr));
+ printf("&MR_redo_layout_framevar(MR_redofr_slot(MR_curfr) = %p\n",
+ &MR_redo_layout_framevar(MR_redofr_slot(MR_curfr)));
+ printf("MR_redo_layout_framevar(MR_redofr_slot(MR_curfr) = %p\n",
+ MR_redo_layout_framevar(MR_redofr_slot(MR_curfr)));
#endif
+ MR_trace((const MR_Stack_Layout_Label *)
+ MR_redo_layout_framevar(MR_redofr_slot(MR_curfr)),
+ MR_PORT_REDO, "", 0);
+ fail();
+
+END_MODULE
+
+void mercury_sys_init_trace(void); /* suppress gcc warning */
+void mercury_sys_init_trace(void) {
+ MR_trace_labels_module();
}
Index: runtime/mercury_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.h,v
retrieving revision 1.10
diff -u -u -r1.10 mercury_trace.h
--- mercury_trace.h 1998/07/17 06:35:14 1.10
+++ mercury_trace.h 1998/08/12 09:11:53
@@ -31,9 +31,11 @@
/* The interface between the tracing subsystem and compiled code. */
-#define MR_trace_incr_seq() (++MR_trace_call_seqno)
-#define MR_trace_incr_depth() (++MR_trace_call_depth)
-#define MR_trace_reset_depth(d) do { MR_trace_call_depth = (d); } while (0)
+#define MR_trace_incr_seq() ((Word) ++MR_trace_call_seqno)
+#define MR_trace_incr_depth() ((Word) ++MR_trace_call_depth)
+#define MR_trace_reset_depth(d) do { \
+ MR_trace_call_depth = (Unsigned) (d);\
+ } while (0)
/*
** This enum should EXACTLY match the definition of the `trace_port_type' type
@@ -42,6 +44,7 @@
typedef enum {
MR_PORT_CALL,
MR_PORT_EXIT,
+ MR_PORT_REDO,
MR_PORT_FAIL,
MR_PORT_THEN,
MR_PORT_ELSE,
@@ -49,16 +52,16 @@
MR_PORT_SWITCH,
MR_PORT_PRAGMA_FIRST,
MR_PORT_PRAGMA_LATER
-} MR_trace_port;
+} MR_Trace_Port;
-extern void MR_trace(
- const MR_Stack_Layout_Label *, /* layout info for the event */
- MR_trace_port,
- Word, /* call sequence number */
- Word, /* call depth */
- const char *, /* path to event goal within procedure */
- int, /* highest numbered rN register in use */
- bool); /* is this event supposed to be traced */
+extern Code *MR_trace( /* if the return value is non-NULL, */
+ /* it gives an address to jump to */
+ const MR_Stack_Layout_Label *,
+ /* layout info for the event */
+ MR_Trace_Port,
+ const char *, /* path to event goal within procedure */
+ int /* highest numbered rN register in use */
+ );
/* The interface between the debuggers and the tracing subsystem. */
@@ -88,15 +91,34 @@
MR_CMD_FINISH, /* stop when exiting/failing out of a proc */
MR_CMD_RESUME_FORWARD, /* stop at the next non-final port */
MR_CMD_TO_END /* do not stop until the end of execution */
-} MR_trace_cmd_type;
+} MR_Trace_Cmd_Type;
+typedef enum {
+ MR_PRINT_LEVEL_NONE, /* no events at all */
+ MR_PRINT_LEVEL_SOME, /* events matching an active spy point */
+ MR_PRINT_LEVEL_ALL /* all events */
+} MR_Trace_Print_Level;
+
typedef struct {
- MR_trace_cmd_type MR_trace_cmd;
- Unsigned MR_trace_stop_seqno;
- Unsigned MR_trace_stop_event;
- bool MR_trace_print_intermediate;
-} MR_trace_cmd_info;
+ MR_Trace_Cmd_Type MR_trace_cmd;
+ Unsigned MR_trace_stop_depth; /* if MR_CMD_FINISH */
+ Unsigned MR_trace_stop_event; /* if MR_CMD_GOTO */
+ MR_Trace_Print_Level MR_trace_print_level;
+ bool MR_trace_strict;
+
+ /*
+ ** The next field is an optimization;
+ ** it must be set to !MR_trace_strict ||
+ ** MR_trace_print_level != MR_PRINT_LEVEL_NONE
+ */
+ bool MR_trace_must_check;
+} MR_Trace_Cmd_Info;
+
+#define MR_port_is_final(port) ((port) == MR_PORT_EXIT || \
+ (port) == MR_PORT_FAIL)
+
+#define MR_port_is_interface(port) ((port) < MR_PORT_FAIL)
-#define MR_port_is_final(port) (port == MR_PORT_EXIT || port == MR_PORT_FAIL)
+#define MR_port_is_entry(port) ((port) == MR_PORT_CALL)
#endif /* MERCURY_TRACE_H */
Index: runtime/mercury_trace_alias.c
===================================================================
RCS file: mercury_trace_alias.c
diff -N mercury_trace_alias.c
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_trace_alias.c Wed Sep 9 15:34:40 1998
@@ -0,0 +1,148 @@
+/*
+** 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.
+*/
+
+/*
+** mercury_trace_alias.h
+**
+** Author: zs.
+*/
+
+#include "mercury_imp.h"
+#include "mercury_trace_alias.h"
+#include "mercury_macros.h"
+
+static MR_Alias *MR_alias_records = NULL;
+static int MR_alias_record_max = 0;
+static int MR_alias_record_next = 0;
+
+/* The initial size of the alias table. */
+#define INIT_ALIAS_COUNT 32
+
+static void MR_trace_print_alias_num(FILE *fp, int slot);
+
+void
+MR_trace_add_alias(char *name, char **words, int word_count)
+{
+ bool found;
+ int slot;
+ int i;
+ int count;
+
+ MR_bsearch(MR_alias_record_next, slot, found,
+ strcmp(MR_alias_records[slot].MR_alias_name, name));
+ if (found) {
+ count = MR_alias_records[slot].MR_alias_word_count;
+ for (i = 0; i < count; i++) {
+ free(MR_alias_records[slot].MR_alias_words[i]);
+ }
+
+ free(MR_alias_records[slot].MR_alias_name);
+ free(MR_alias_records[slot].MR_alias_words);
+ } else {
+ MR_ensure_room_for_next(MR_alias_record, MR_Alias,
+ INIT_ALIAS_COUNT);
+ MR_prepare_insert_into_sorted(MR_alias_records,
+ MR_alias_record_next, slot,
+ strcmp(MR_alias_records[slot].MR_alias_name,
+ name));
+ }
+
+ MR_alias_records[slot].MR_alias_name = MR_copy_string(name);
+ MR_alias_records[slot].MR_alias_word_count = word_count;
+ MR_alias_records[slot].MR_alias_words = checked_malloc(word_count
+ * sizeof(char *));
+ for (i = 0; i < word_count; i++) {
+ MR_alias_records[slot].MR_alias_words[i]
+ = MR_copy_string(words[i]);
+ }
+}
+
+bool
+MR_trace_remove_alias(const char *name)
+{
+ bool found;
+ int slot;
+ int i;
+ int count;
+
+ MR_bsearch(MR_alias_record_next, slot, found,
+ strcmp(MR_alias_records[slot].MR_alias_name, name));
+ if (! found) {
+ return FALSE;
+ } else {
+ count = MR_alias_records[slot].MR_alias_word_count;
+ for (i = 0; i < count; i++) {
+ free(MR_alias_records[slot].MR_alias_words[i]);
+ }
+
+ free(MR_alias_records[slot].MR_alias_name);
+ free(MR_alias_records[slot].MR_alias_words);
+
+ for (i = slot; i < MR_alias_record_next - 1; i++) {
+ MR_alias_records[slot] = MR_alias_records[slot+1];
+ }
+
+ MR_alias_record_next--;
+
+ return TRUE;
+ }
+}
+
+bool
+MR_trace_lookup_alias(const char *name,
+ char ***words_ptr, int *word_count_ptr)
+{
+ bool found;
+ int slot;
+
+ MR_bsearch(MR_alias_record_next, slot, found,
+ strcmp(MR_alias_records[slot].MR_alias_name, name));
+ if (found) {
+ *word_count_ptr = MR_alias_records[slot].MR_alias_word_count;
+ *words_ptr = MR_alias_records[slot].MR_alias_words;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+void
+MR_trace_print_alias(FILE *fp, const char *name)
+{
+ bool found;
+ int slot;
+
+ MR_bsearch(MR_alias_record_next, slot, found,
+ strcmp(MR_alias_records[slot].MR_alias_name, name));
+ if (found) {
+ MR_trace_print_alias_num(fp, slot);
+ } else {
+ fprintf(fp, "There is no such alias.\n");
+ }
+}
+
+void
+MR_trace_print_all_aliases(FILE *fp)
+{
+ int slot;
+
+ for (slot = 0; slot < MR_alias_record_next; slot++) {
+ MR_trace_print_alias_num(fp, slot);
+ }
+}
+
+static void
+MR_trace_print_alias_num(FILE *fp, int slot)
+{
+ int i;
+
+ fprintf(fp, "%-6s => ", MR_alias_records[slot].MR_alias_name);
+ for (i = 0; i < MR_alias_records[slot].MR_alias_word_count; i++) {
+ fprintf(fp, " %s", MR_alias_records[slot].MR_alias_words[i]);
+ }
+
+ fprintf(fp, "\n");
+}
Index: runtime/mercury_trace_alias.h
===================================================================
RCS file: mercury_trace_alias.h
diff -N mercury_trace_alias.h
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_trace_alias.h Sun Jul 12 16:41:51 1998
@@ -0,0 +1,67 @@
+/*
+** 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.
+*/
+
+/*
+** mercury_trace_alias.h
+**
+** Defines the interface of the alias system for the internal debugger.
+*/
+
+#ifndef MERCURY_TRACE_ALIAS_H
+#define MERCURY_TRACE_ALIAS_H
+
+#include <stdio.h>
+
+typedef struct {
+ char *MR_alias_name;
+ char **MR_alias_words;
+ int MR_alias_word_count;
+} MR_Alias;
+
+/*
+** Add an alias with the given name and expansion to the list.
+** The name, the words in the expansion and the array of pointers to the
+** expansion will all be copied, so their storage can be released
+** when MR_trace_add_alias returns.
+**
+** Overwrites any previous alias with the same name.
+*/
+
+extern void MR_trace_add_alias(char *name, char **words,
+ int word_count);
+
+/*
+** Remove the given alias from the list. Returns FALSE if there is no
+** such alias, and TRUE if there was such an alias and the removal was
+** successful.
+*/
+
+extern bool MR_trace_remove_alias(const char *name);
+
+/*
+** Looks up whether the given alias exists. If yes, returns TRUE, and
+** sets *words_ptr to point to a vector of words forming the alias expansion,
+** and *word_count_ptr to the number of words in the expansion. If no,
+** returns FALSE.
+*/
+
+extern bool MR_trace_lookup_alias(const char *name,
+ char ***words_ptr, int *word_count_ptr);
+
+/*
+** Print the alias of the given name, if it exists, and an error message
+** if it does not.
+*/
+
+extern void MR_trace_print_alias(FILE *fp, const char *name);
+
+/*
+** Print all the aliases to the given file.
+*/
+
+extern void MR_trace_print_all_aliases(FILE *fp);
+
+#endif /* MERCURY_TRACE_ALIAS_H */
Index: runtime/mercury_trace_base.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.c,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace_base.c
--- mercury_trace_base.c 1998/07/03 05:34:46 1.1
+++ mercury_trace_base.c 1998/09/09 05:45:51
@@ -30,7 +30,7 @@
** This variable is set in mercury_wrapper.c and never modified afterwards.
*/
-MR_trace_type MR_trace_handler = MR_TRACE_INTERNAL;
+MR_Trace_Type MR_trace_handler = MR_TRACE_INTERNAL;
/*
** Compiler generated tracing code will check whether MR_trace_enabled is true,
@@ -89,6 +89,11 @@
Bool MR_trace_from_full = 1;
+int *MR_trace_histogram_all = NULL;
+int *MR_trace_histogram_exp = NULL;
+int MR_trace_histogram_max = 0;
+int MR_trace_histogram_hwm = 0;
+
void
MR_trace_init(void)
{
@@ -134,6 +139,22 @@
fprintf(fp, "Last trace event was event #%ld.\n",
(long) MR_trace_event_number);
+
+#ifdef MR_TRACE_HISTOGRAM
+ {
+ FILE *hfp;
+
+ hfp = fopen(".mercury_histogram", "w");
+ if (hfp != NULL) {
+ fprintf(fp, "All-include event histogram put"
+ " into file .mercury_histogram\n");
+ MR_trace_print_histogram(hfp, "All-inclusive",
+ MR_trace_histogram_all,
+ MR_trace_histogram_hwm);
+ fclose(hfp);
+ }
+ }
+#endif /* MR_TRACE_HISTOGRAM */
}
}
@@ -151,5 +172,22 @@
sprintf(buf, "Last trace event was event #%ld.\n",
(long) MR_trace_event_number);
write(fd, buf, strlen(buf));
+ }
+}
+
+void
+MR_trace_print_histogram(FILE *fp, const char *which, int *histogram, int max)
+{
+ int i;
+
+ fprintf(fp, "%s histogram\n", which);
+ for (i = 1; i <= max; i++) {
+ fprintf(fp, "depth %4d: %10d", i, histogram[i]);
+ if (i + 1 <= max && histogram[i] != 0) {
+ fprintf(fp, ", branching factor %7.2f\n",
+ (float) histogram[i+1] / (float) histogram[i]);
+ } else {
+ fprintf(fp, "\n");
+ }
}
}
Index: runtime/mercury_trace_base.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.h,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace_base.h
--- mercury_trace_base.h 1998/07/03 05:34:47 1.1
+++ mercury_trace_base.h 1998/09/09 05:46:11
@@ -11,8 +11,8 @@
** is compiled with execution tracing.
*/
-#ifndef MERCURY_TRACE_PERMANENT_H
-#define MERCURY_TRACE_PERMANENT_H
+#ifndef MERCURY_TRACE_BASE_H
+#define MERCURY_TRACE_BASE_H
/*
** MR_trace_init() is called from mercury_runtime_init()
@@ -39,25 +39,23 @@
extern void MR_trace_end(void);
extern void MR_trace_final(void);
-#define MR_trace_incr_seq() (++MR_trace_call_seqno)
-#define MR_trace_incr_depth() (++MR_trace_call_depth)
-#define MR_trace_reset_depth(d) do { MR_trace_call_depth = (d); } while (0)
-
/*
** The globals that define the interface between the tracing subsystem
** and compiled code, and which must be initialized in the permanent part
** of the runtime.
+**
+** XXX They should probably be in MercuryEngine.
*/
-extern Word MR_trace_call_seqno;
-extern Word MR_trace_call_depth;
+extern Unsigned MR_trace_call_seqno;
+extern Unsigned MR_trace_call_depth;
typedef enum {
MR_TRACE_INTERNAL,
MR_TRACE_EXTERNAL
-} MR_trace_type;
+} MR_Trace_Type;
-extern MR_trace_type MR_trace_handler;
+extern MR_Trace_Type MR_trace_handler;
extern bool MR_trace_enabled;
extern Unsigned MR_trace_event_number;
@@ -70,5 +68,33 @@
extern void MR_trace_report(FILE *fp);
extern void MR_trace_report_raw(int fd);
+
+/*
+** If MR_TRACE_HISTOGRAM is defined, MR_trace maintains two arrays of integers,
+** MR_trace_histogram_all and MR_trace_histogram_exp, in which the element
+** with subscript d is incremented when a trace event occurs at depth d.
+** The intention is that the MR_trace_histogram_all records all events
+** and is never reset, which means that it records information about a whole
+** execution of the program. MR_trace_histogram_exp on the other hand can be
+** zeroed by a command from the debugger at e.g a call port, and examined at
+** e.g. an exit port, which means that it can record information about the
+** execution of a call.
+**
+** Both arrays are allocated via malloc, and resized on demand. They are
+** always the same size, and this size is stored in MR_trace_histogram_max.
+** MR_trace_histogram_hwm stores the high water mark, i.e. the biggest
+** depth number that has been encountered so far in the execution of the
+** program.
+*/
+
+#define MR_INIT_HISTOGRAM_SIZE 128
+
+extern int *MR_trace_histogram_all;
+extern int *MR_trace_histogram_exp;
+extern int MR_trace_histogram_max;
+extern int MR_trace_histogram_hwm;
+
+extern void MR_trace_print_histogram(FILE *fp, const char *which,
+ int *histogram, int max);
-#endif /* MERCURY_TRACE_PERMANENT_H */
+#endif /* MERCURY_TRACE_BASE_H */
Index: runtime/mercury_trace_external.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_external.c,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_trace_external.c
--- mercury_trace_external.c 1998/07/31 15:14:14 1.7
+++ mercury_trace_external.c 1998/08/02 22:52:57
@@ -68,11 +68,11 @@
Integer *debugger_request_type_ptr);
static bool MR_found_match(const MR_Stack_Layout_Label *layout,
- MR_trace_port port, Unsigned seqno, Unsigned depth,
+ MR_Trace_Port port, Unsigned seqno, Unsigned depth,
/* XXX registers */
const char *path, Word search_data);
static void MR_output_current_slots(const MR_Stack_Layout_Label *layout,
- MR_trace_port port, Unsigned seqno, Unsigned depth,
+ MR_Trace_Port port, Unsigned seqno, Unsigned depth,
const char *path);
static void MR_output_current_vars(Word var_list, Word string_list);
static void MR_output_current_nth_var(Word var);
@@ -321,7 +321,7 @@
void
MR_trace_event_external(MR_trace_cmd_info *cmd,
- const MR_Stack_Layout_Label *layout, MR_trace_port port,
+ const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
Unsigned seqno, Unsigned depth, const char *path)
{
static bool searching = FALSE;
@@ -420,7 +420,7 @@
static void
MR_output_current_slots(const MR_Stack_Layout_Label *layout,
- MR_trace_port port, Unsigned seqno, Unsigned depth, const char *path)
+ MR_Trace_Port port, Unsigned seqno, Unsigned depth, const char *path)
{
MR_DI_output_current_slots(
MR_trace_event_number,
@@ -477,7 +477,7 @@
static bool
MR_found_match(const MR_Stack_Layout_Label *layout,
- MR_trace_port port, Unsigned seqno, Unsigned depth,
+ MR_Trace_Port port, Unsigned seqno, Unsigned depth,
/* XXX live vars */
const char *path, Word search_data)
{
Index: runtime/mercury_trace_external.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_external.h,v
retrieving revision 1.2
diff -u -u -r1.2 mercury_trace_external.h
--- mercury_trace_external.h 1998/07/23 20:12:26 1.2
+++ mercury_trace_external.h 1998/07/29 00:02:11
@@ -13,7 +13,7 @@
extern void MR_trace_final_external(void);
extern void MR_trace_event_external(MR_trace_cmd_info *cmd,
const MR_Stack_Layout_Label *layout,
- MR_trace_port port, Unsigned seqno, Unsigned depth,
+ MR_Trace_Port port, Unsigned seqno, Unsigned depth,
const char *path);
#endif /* MR_USE_EXTERNAL_DEBUGGER */
Index: runtime/mercury_trace_internal.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_internal.h,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace_internal.h
--- mercury_trace_internal.h 1998/05/16 07:28:28 1.1
+++ mercury_trace_internal.h 1998/07/07 11:09:22
@@ -7,16 +7,10 @@
#ifndef MERCURY_TRACE_INTERNAL_H
#define MERCURY_TRACE_INTERNAL_H
-extern void MR_trace_event_internal(MR_trace_cmd_info *cmd,
+extern Code *MR_trace_event_internal(MR_Trace_Cmd_Info *cmd,
+ bool interactive,
const MR_Stack_Layout_Label *layout,
- MR_trace_port port, int seqno, int depth,
- const char *path);
-
-extern void MR_trace_event_internal_report(
- const MR_Stack_Layout_Label *layout,
- MR_trace_port port, int seqno, int depth,
- const char *path);
-
-extern bool MR_event_matches_spy_point(const MR_Stack_Layout_Label *layout);
+ MR_Trace_Port port, int seqno, int depth,
+ const char *path, int *max_mr_num);
#endif /* MERCURY_TRACE_INTERNAL_H */
Index: runtime/mercury_trace_spy.c
===================================================================
RCS file: mercury_trace_spy.c
diff -N mercury_trace_spy.c
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_trace_spy.c Fri Aug 7 16:42:53 1998
@@ -0,0 +1,181 @@
+/*
+** 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 manage spy points for both
+** the internal and external debuggers.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#undef USE_GCC_GLOBAL_REGISTERS
+#include "mercury_imp.h"
+#include "mercury_trace_base.h"
+#include "mercury_trace.h"
+#include "mercury_trace_spy.h"
+#include "mercury_macros.h"
+
+typedef struct {
+ const MR_Stack_Layout_Entry *spy_proc;
+ MR_Spy_Point *spy_points;
+} MR_Spied_Proc;
+
+static MR_Spied_Proc *MR_spied_procs;
+static int MR_spied_proc_next = 0;
+static int MR_spied_proc_max = 0;
+
+#define INIT_SPY_TABLE_SIZE 10
+
+ /* Return the index of the entry in MR_spied_procs whose */
+ /* spy_proc field is entry, or a negative number if absent */
+static int MR_search_spy_table_for_proc(const MR_Stack_Layout_Entry
+ *entry);
+
+static int
+MR_search_spy_table_for_proc(const MR_Stack_Layout_Entry *entry)
+{
+ int lo;
+ int hi;
+ int mid;
+
+ lo = 0;
+ hi = MR_spied_proc_next - 1;
+ while (lo <= hi) {
+ mid = (lo + hi) / 2;
+ if (MR_spied_procs[mid].spy_proc == entry) {
+ return mid;
+ } else if (MR_spied_procs[mid].spy_proc < entry) {
+ lo = mid + 1;
+ } else {
+ hi = mid - 1;
+ }
+ }
+
+ return -1;
+}
+
+bool
+MR_event_matches_spy_point(const MR_Stack_Layout_Label *layout,
+ MR_Trace_Port port, MR_Spy_Action *action_ptr)
+{
+ int slot;
+ bool enabled;
+ MR_Spy_Point *point;
+ MR_Spy_Action action;
+
+ slot = MR_search_spy_table_for_proc(layout->MR_sll_entry);
+ if (slot < 0) {
+ return FALSE;
+ }
+
+ enabled = FALSE;
+ action = MR_SPY_PRINT;
+ for (point = MR_spied_procs[slot].spy_points; point != NULL;
+ point = point->spy_next) {
+ if (! point->spy_enabled) {
+ continue;
+ }
+
+ switch (point->spy_when) {
+
+ case MR_SPY_ALL:
+ enabled = TRUE;
+ action = max(action, point->spy_action);
+ break;
+
+ case MR_SPY_ENTRY:
+ if (MR_port_is_entry(port)) {
+ enabled = TRUE;
+ action = max(action, point->spy_action);
+ } else {
+ continue;
+ }
+
+ break;
+
+ case MR_SPY_INTERFACE:
+ if (MR_port_is_interface(port)) {
+ enabled = TRUE;
+ action = max(action, point->spy_action);
+ } else {
+ continue;
+ }
+
+ break;
+
+ case MR_SPY_SPECIFIC:
+ if (layout == point->spy_label) {
+ enabled = TRUE;
+ action = max(action, point->spy_action);
+ } else {
+ continue;
+ }
+
+ break;
+
+ default:
+ fatal_error("bad spy point when in "
+ "MR_event_matches_spy_point");
+ }
+ }
+
+ if (enabled) {
+ *action_ptr = action;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static bool MR_need_move(int i, const MR_Stack_Layout_Entry *entry);
+
+MR_Spy_Point *
+MR_add_spy_point(MR_Spy_When when, MR_Spy_Action action,
+ const MR_Stack_Layout_Entry *entry, const MR_Stack_Layout_Label *label,
+ const char *path)
+{
+ MR_Spy_Point *point;
+ int i;
+ int slot;
+ bool found;
+
+ slot = MR_search_spy_table_for_proc(entry);
+ if (slot < 0) {
+ MR_ensure_room_for_next(MR_spied_proc, MR_Spied_Proc,
+ INIT_SPY_TABLE_SIZE);
+ MR_prepare_insert_into_sorted(MR_spied_procs,
+ MR_spied_proc_next, slot, MR_need_move(i, entry));
+ MR_spied_procs[slot].spy_proc = entry;
+ MR_spied_procs[slot].spy_points = NULL;
+ }
+
+ /* Insert the spy point at the head of the list for the proc. */
+ point = checked_malloc(sizeof(MR_Spy_Point));
+ point->spy_when = when;
+ point->spy_enabled = TRUE;
+ point->spy_action = action;
+ point->spy_proc = entry;
+ point->spy_label = label;
+ point->spy_next = MR_spied_procs[slot].spy_points;
+ MR_spied_procs[slot].spy_points = point;
+
+ return point;
+}
+
+/*
+** The only reason why MR_need_move is a function is that gcc version 2.7.2.3
+** on i686-pc-linux-gnu gets an internal error ("fixed or forbidden register
+** was spilled") if it isn't a function.
+*/
+
+static bool
+MR_need_move(int i, const MR_Stack_Layout_Entry *entry)
+{
+ if (MR_spied_procs[i].spy_proc > entry)
+ return TRUE;
+ else
+ return FALSE;
+}
Index: runtime/mercury_trace_spy.h
===================================================================
RCS file: mercury_trace_spy.h
diff -N mercury_trace_spy.h
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_trace_spy.h Sun Jul 5 14:02:53 1998
@@ -0,0 +1,56 @@
+/*
+** 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 the declarations of the types and functions that
+** the internal and external debuggers can use to manipulate spy points.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#ifndef MERCURY_TRACE_SPY_H
+#define MERCURY_TRACE_SPY_H
+
+typedef enum {
+ MR_SPY_PRINT, MR_SPY_STOP
+} MR_Spy_Action;
+
+#define MR_spy_action_string(a) ((a == MR_SPY_STOP) ? "stop" : \
+ (a == MR_SPY_PRINT) ? "print" : \
+ "weird spy action")
+
+typedef enum {
+ MR_SPY_ALL, MR_SPY_INTERFACE, MR_SPY_ENTRY, MR_SPY_SPECIFIC
+} MR_Spy_When;
+
+#define MR_spy_when_string(w) ((w == MR_SPY_ALL) ? "all" : \
+ (w == MR_SPY_INTERFACE) ? "interface":\
+ (w == MR_SPY_ENTRY) ? "entry" : \
+ (w == MR_SPY_SPECIFIC) ? "specific" : \
+ "weird spy when")
+
+typedef struct struct_mr_spy_point MR_Spy_Point;
+
+struct struct_mr_spy_point {
+ MR_Spy_When spy_when;
+ bool spy_enabled;
+ MR_Spy_Action spy_action;
+ const MR_Stack_Layout_Entry *spy_proc;
+ const MR_Stack_Layout_Label *spy_label; /* if MR_SPY_SPECIFIC */
+ MR_Spy_Point *spy_next;
+};
+
+extern bool MR_event_matches_spy_point(const MR_Stack_Layout_Label
+ *layout, MR_Trace_Port port,
+ MR_Spy_Action *action);
+
+extern MR_Spy_Point *MR_add_spy_point(MR_Spy_When when,
+ MR_Spy_Action action,
+ const MR_Stack_Layout_Entry *entry,
+ const MR_Stack_Layout_Label *label,
+ const char *path);
+
+#endif /* not MERCURY_TRACE_SPY_H */
Index: runtime/mercury_trace_tables.c
===================================================================
RCS file: mercury_trace_tables.c
diff -N mercury_trace_tables.c
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_trace_tables.c Wed Sep 16 12:03:18 1998
@@ -0,0 +1,376 @@
+/*
+** 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 manages a table listing the debuggable modules of the program,
+** and subsidiary tables listing the procedures of each of those modules.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#undef USE_GCC_GLOBAL_REGISTERS
+#include "mercury_imp.h"
+#include "mercury_label.h"
+#include "mercury_macros.h"
+#include "mercury_trace_tables.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+static MR_Module_Info *MR_module_infos;
+static int MR_module_info_next = 0;
+static int MR_module_info_max = 0;
+static int MR_module_info_proc_count = 0;
+
+#define INIT_MODULE_TABLE_SIZE 10
+
+static void MR_register_from_internal_label(const void *info);
+static void MR_ensure_proc_node_is_present(MR_Module_Info *module,
+ const MR_Stack_Layout_Entry *entry);
+static MR_Module_Info *MR_search_module_info(const char *name);
+static MR_Module_Info *MR_insert_module_info(const char *name);
+static MR_Module_Info *MR_ensure_module_info_is_present(const char *name);
+
+static void MR_process_matching_procedures_in_module(
+ MR_Module_Info *module, MR_Proc_Spec *spec,
+ void f(const MR_Stack_Layout_Entry *));
+
+void
+MR_register_all_modules_and_procs(FILE *fp, bool verbose)
+{
+ static bool done = FALSE;
+
+ if (! done) {
+ if (verbose) {
+ fprintf(fp, "Registering debuggable procedures... ");
+ fflush(fp);
+ }
+
+ do_init_modules();
+ MR_process_all_internal_labels(MR_register_from_internal_label);
+ done = TRUE;
+ if (verbose) {
+ fprintf(fp, "done.\n");
+ if (MR_module_info_next == 0) {
+ fprintf(fp, "There are no debuggable modules.");
+ } else if (MR_module_info_next == 1) {
+ fprintf(fp, "There is one debuggable module, "
+ "with %d procedures.\n",
+ MR_module_info_proc_count);
+ } else {
+ fprintf(fp, "There are %d debuggable modules, "
+ "with a total of %d procedures.\n",
+ MR_module_info_next,
+ MR_module_info_proc_count);
+ }
+ }
+ }
+}
+
+static void
+MR_register_from_internal_label(const void *info)
+{
+ const MR_Stack_Layout_Label *label;
+ const MR_Stack_Layout_Entry *entry;
+ MR_Module_Info *module;
+
+ label = ((const MR_Internal *) info)->i_layout;
+
+ if (label == NULL) {
+ /* some labels have no layout structure */
+ return;
+ }
+
+ if (label->MR_sll_entry == NULL) {
+ /* some hand-crafted label structures have no entry */
+ return;
+ }
+
+ entry = label->MR_sll_entry;
+
+ if (MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry) &&
+ ! MR_ENTRY_LAYOUT_COMPILER_GENERATED(entry))
+ {
+ module = MR_ensure_module_info_is_present(
+ entry->MR_sle_def_module);
+ MR_ensure_proc_node_is_present(module, entry);
+ }
+}
+
+static void
+MR_ensure_proc_node_is_present(MR_Module_Info *module,
+ const MR_Stack_Layout_Entry *entry)
+{
+ MR_Proc_Node *cur;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ if (entry == cur->MR_proc_layout) {
+ return;
+ }
+ }
+
+ cur = checked_malloc(sizeof(MR_Proc_Node));
+ cur->MR_proc_layout = entry;
+ cur->MR_proc_next = module->MR_module_procs;
+ module->MR_module_procs = cur;
+ MR_module_info_proc_count++;
+}
+
+static MR_Module_Info *
+MR_search_module_info(const char *name)
+{
+ int slot;
+ bool found;
+
+ MR_bsearch(MR_module_info_next, slot, found,
+ strcmp(MR_module_infos[slot].MR_module_name, name));
+ if (found) {
+ return &MR_module_infos[slot];
+ } else {
+ return NULL;
+ }
+}
+
+static MR_Module_Info *
+MR_insert_module_info(const char *name)
+{
+ int slot;
+
+ MR_ensure_room_for_next(MR_module_info, MR_Module_Info,
+ INIT_MODULE_TABLE_SIZE);
+ MR_prepare_insert_into_sorted(MR_module_infos, MR_module_info_next,
+ slot, strcmp(MR_module_infos[slot].MR_module_name, name));
+
+ MR_module_infos[slot].MR_module_name = name;
+ MR_module_infos[slot].MR_module_procs = NULL;
+ return &MR_module_infos[slot];
+}
+
+static MR_Module_Info *
+MR_ensure_module_info_is_present(const char *name)
+{
+ MR_Module_Info *module;
+
+ module = MR_search_module_info(name);
+ if (module != NULL) {
+ return module;
+ } else {
+ return MR_insert_module_info(name);
+ }
+}
+
+void
+MR_dump_module_tables(FILE *fp)
+{
+ const MR_Proc_Node *cur;
+ int i;
+
+ for (i = 0; i < MR_module_info_next; i++) {
+ fprintf(fp, "====================\n");
+ fprintf(fp, "module %s\n", MR_module_infos[i].MR_module_name);
+ fprintf(fp, "====================\n");
+ for (cur = MR_module_infos[i].MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ MR_print_proc_id(fp, cur->MR_proc_layout, NULL);
+ }
+ }
+}
+
+void
+MR_dump_module_list(FILE *fp)
+{
+ int i;
+
+ fprintf(fp, "List of debuggable modules\n\n");
+ for (i = 0; i < MR_module_info_next; i++) {
+ fprintf(fp, "%s\n", MR_module_infos[i].MR_module_name);
+ }
+}
+
+void
+MR_dump_module_procs(FILE *fp, const char *name)
+{
+ MR_Module_Info *module;
+ const MR_Proc_Node *cur;
+
+ module = MR_search_module_info(name);
+ if (module == NULL) {
+ fprintf(fp, "There is no debugging info about module %s\n",
+ name);
+ } else {
+ fprintf(fp, "List of procedures in module %s\n\n", name);
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ MR_print_proc_id(fp, cur->MR_proc_layout, NULL);
+ }
+ }
+}
+
+bool
+MR_parse_proc_spec(char *str, MR_Proc_Spec *spec)
+{
+ char *dash;
+ char *slash;
+ char *s;
+ int n;
+ bool found;
+
+ spec->MR_proc_module = NULL;
+ spec->MR_proc_name = NULL;
+ spec->MR_proc_arity = -1;
+ spec->MR_proc_mode = -1;
+ spec->MR_proc_pf = (MR_PredFunc) -1;
+
+ if (strneq(str, "pred*", 5)) {
+ spec->MR_proc_pf = MR_PREDICATE;
+ str += 5;
+ } else if (strneq(str, "func*", 5)) {
+ spec->MR_proc_pf = MR_FUNCTION;
+ str += 5;
+ }
+
+ if ((dash = strrchr(str, '-')) != NULL) {
+ found = FALSE;
+ n = 0;
+ for (s = dash + 1; *s != '\0'; s++) {
+ if (MR_isdigit(*s)) {
+ found = TRUE;
+ n = n * 10 + *s - '0';
+ } else {
+ /* a dash followed by a nondigit is an error */
+ return FALSE;
+ }
+ }
+
+ if (! found) {
+ /* a dash with no following digit is an error */
+ return FALSE;
+ }
+
+ spec->MR_proc_mode = n;
+ *dash = '\0';
+ }
+
+ if ((slash = strrchr(str, '/')) != NULL) {
+ found = FALSE;
+ n = 0;
+ for (s = slash + 1; *s != '\0'; s++) {
+ if (MR_isdigit(*s)) {
+ found = TRUE;
+ n = n * 10 + *s - '0';
+ } else {
+ /* a slash followed by a nondigit is an error */
+ return FALSE;
+ }
+ }
+
+ if (! found) {
+ /* a slash with no following digit is an error */
+ return FALSE;
+ }
+
+ spec->MR_proc_arity = n;
+ *slash = '\0';
+ }
+
+ for (s = str; *s != '\0'; s++) {
+ if (*s == ':' || (*s == '_' && *(s+1) == '_')) {
+ if (*s == ':') {
+ spec->MR_proc_name = s+1;
+ } else {
+ spec->MR_proc_name = s+2;
+ }
+
+ *s = '\0';
+ spec->MR_proc_module = str;
+
+ return TRUE;
+ }
+ }
+
+ spec->MR_proc_name = str;
+ return TRUE;
+}
+
+/* These two variables are for communication between */
+/* MR_register_match and MR_search_for_matching_procedure. */
+static const MR_Stack_Layout_Entry *matching_entry;
+static bool match_unique;
+
+static void
+MR_register_match(const MR_Stack_Layout_Entry *entry)
+{
+ if (matching_entry == NULL) {
+ matching_entry = entry;
+ } else {
+ match_unique = FALSE;
+ }
+}
+
+const MR_Stack_Layout_Entry *
+MR_search_for_matching_procedure(MR_Proc_Spec *spec, bool *unique)
+{
+ matching_entry = NULL;
+ match_unique = TRUE;
+ MR_process_matching_procedures(spec, MR_register_match);
+ *unique = match_unique;
+ return matching_entry;
+}
+
+void
+MR_process_matching_procedures(MR_Proc_Spec *spec,
+ void f(const MR_Stack_Layout_Entry *))
+{
+ if (spec->MR_proc_module != NULL) {
+ MR_Module_Info *module;
+
+ module = MR_search_module_info(spec->MR_proc_module);
+ if (module != NULL) {
+ MR_process_matching_procedures_in_module(
+ module, spec, f);
+ }
+ } else {
+ int i;
+
+ for (i = 0; i < MR_module_info_next; i++) {
+ MR_process_matching_procedures_in_module(
+ &MR_module_infos[i], spec, f);
+ }
+ }
+}
+
+#define match_name(spec, cur) (((spec)->MR_proc_name == NULL) || \
+ streq((spec)->MR_proc_name, cur->MR_sle_name))
+
+#define match_arity(spec, cur) (((spec)->MR_proc_arity < 0) || \
+ (spec)->MR_proc_arity == cur->MR_sle_arity)
+
+#define match_mode(spec, cur) (((spec)->MR_proc_mode < 0) || \
+ (spec)->MR_proc_mode == cur->MR_sle_mode)
+
+#define match_pf(spec, cur) (((int) (spec)->MR_proc_pf < 0) || \
+ (spec)->MR_proc_pf == cur->MR_sle_pred_or_func)
+
+static void
+MR_process_matching_procedures_in_module(MR_Module_Info *module,
+ MR_Proc_Spec *spec, void f(const MR_Stack_Layout_Entry *))
+{
+ MR_Proc_Node *cur;
+ const MR_Stack_Layout_Entry *cur_entry;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ cur_entry = cur->MR_proc_layout;
+ if (match_name(spec, cur_entry) &&
+ match_arity(spec, cur_entry) &&
+ match_mode(spec, cur_entry) &&
+ match_pf(spec, cur_entry))
+ {
+ f(cur_entry);
+ }
+ }
+}
Index: runtime/mercury_trace_tables.h
===================================================================
RCS file: mercury_trace_tables.h
diff -N mercury_trace_tables.h
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_trace_tables.h Wed Sep 16 12:03:55 1998
@@ -0,0 +1,120 @@
+/*
+** 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 the declarations of the tables that contain
+** the identities of the debuggable modules and their procedures.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#ifndef MERCURY_TRACE_TABLES_H
+#define MERCURY_TRACE_TABLES_H
+
+#include "mercury_stack_layout.h"
+#include <stdio.h>
+
+/*
+** The module info table is an array with one element for each module
+** that has procedures with execution tracing information. This element
+** gives the module's name and points to a list of the procedure layouts
+** of the traceable procedures of the module.
+*/
+
+typedef struct struct_mr_proc_node MR_Proc_Node;
+
+struct struct_mr_proc_node {
+ const MR_Stack_Layout_Entry *MR_proc_layout;
+ MR_Proc_Node *MR_proc_next;
+};
+
+typedef struct {
+ const char *MR_module_name;
+ MR_Proc_Node *MR_module_procs;
+} MR_Module_Info;
+
+/*
+** MR_register_all_modules_and_procs gathers all available debugging info
+** about the modules and procedures of the program into the module info table.
+** If verbose is TRUE, print progress and summary messages.
+*/
+
+extern void MR_register_all_modules_and_procs(FILE *fp,
+ bool verbose);
+
+/*
+** These functions print (parts of) the module info table.
+**
+** MR_dump_module_tables lists all procedures in all modules.
+** Its output can be very big; it should be used only by developers,
+** for debugging the debugger.
+**
+** MR_dump_module_list lists the names of all the modules,
+** while MR_dump_module_procs lists the names of all the procs in the named
+** module. These are intended for ordinary, non-developer users.
+*/
+
+extern void MR_dump_module_tables(FILE *fp);
+extern void MR_dump_module_list(FILE *fp);
+extern void MR_dump_module_procs(FILE *fp, const char *name);
+
+/*
+** A procedure specification gives some or all of
+**
+** the name of the module defining the procedure
+** the name of the predicate or function
+** the arity of the predicate or function
+** the mode of the predicate or function
+** whether the procedure belongs to a predicate or function
+**
+** A NULL pointer for the string fields, and a negative number for the other
+** fields signifies the absence of information about that field, which should
+** therefore be treated as a wildcard.
+*/
+
+typedef struct {
+ const char *MR_proc_module;
+ const char *MR_proc_name;
+ int MR_proc_arity;
+ int MR_proc_mode;
+ MR_PredFunc MR_proc_pf;
+} MR_Proc_Spec;
+
+/*
+** Given a string containing the specification of a procedure in the form
+**
+** [`pred*'|`func*']module:name/arity-mode
+**
+** in which some of the five components (but not the name) may be missing,
+** parse it into the more usable form of a MR_Proc_Spec. The original string
+** may be overwritten in the process.
+**
+** Returns TRUE if the string was correctly formed, and FALSE otherwise.
+*/
+
+extern bool MR_parse_proc_spec(char *str, MR_Proc_Spec *spec);
+
+/*
+** Search the tables for a procedure that matches the given specification.
+** If no procedure matches, return NULL.
+** If one procedure matches, return its layout structure,
+** and set *unique to TRUE.
+** If more than one procedure matches, return the layout structure of one
+** and set *unique to FALSE.
+*/
+
+extern const MR_Stack_Layout_Entry *MR_search_for_matching_procedure(
+ MR_Proc_Spec *spec, bool *unique);
+
+/*
+** Call f(entry) on the layout of every procedure that matches
+** the given specification.
+*/
+
+extern void MR_process_matching_procedures(MR_Proc_Spec *spec,
+ void f(const MR_Stack_Layout_Entry *));
+
+#endif /* not MERCURY_TRACE_TABLES_H */
Index: runtime/mercury_trace_util.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_util.c,v
retrieving revision 1.8
diff -u -u -r1.8 mercury_trace_util.c
--- mercury_trace_util.c 1998/07/31 15:14:17 1.8
+++ mercury_trace_util.c 1998/09/16 02:12:24
@@ -14,6 +14,7 @@
#include "mercury_imp.h"
#include "mercury_stack_layout.h"
#include "mercury_trace_util.h"
+#include "../library/io.h"
Word MR_saved_regs[MAX_FAKE_REG];
@@ -178,6 +179,16 @@
return univ_list;
}
+int
+MR_trace_get_register_number(MR_Live_Lval locn)
+{
+ if (MR_LIVE_LVAL_TYPE(locn) == MR_LVAL_TYPE_R) {
+ return MR_LIVE_LVAL_NUMBER(locn);
+ } else {
+ return -1;
+ }
+}
+
/* if you want to debug this code, you may want to set this var to TRUE */
static bool MR_trace_print_locn = FALSE;
@@ -221,7 +232,7 @@
if (MR_trace_print_locn) {
printf("stackvar%d", locn_num);
}
- value = based_detstackvar(base_sp, locn_num);
+ value = MR_based_stackvar(base_sp, locn_num);
*succeeded = TRUE;
break;
@@ -229,7 +240,7 @@
if (MR_trace_print_locn) {
printf("framevar%d", locn_num);
}
- value = based_framevar(base_curfr, locn_num);
+ value = MR_based_framevar(base_curfr, locn_num);
*succeeded = TRUE;
break;
@@ -339,6 +350,17 @@
void
MR_trace_write_variable(Word type_info, Word value)
{
+ static bool done = FALSE;
+ static Word stdout_stream;
+
+ if (! done) {
+ ML_io_stdout_stream(&stdout_stream);
+ done = TRUE;
+ }
+
+#if 1
+ ML_io_print_to_stream(type_info, stdout_stream, value);
+#else
/*
** XXX It would be nice if we could call an exported C function
@@ -352,16 +374,18 @@
**
** call_engine() expects the transient registers to be in
** fake_reg, others in their normal homes. That is the case on
- ** entry to this function. But r1 or r2 may be transient, so we
+ ** entry to this function. But r1, r2 or r3 may be transient, so we
** need to save/restore transient regs around the assignments to
** them.
*/
restore_transient_registers();
r1 = type_info;
- r2 = value;
+ r2 =
+ r3 = value;
save_transient_registers();
call_engine(MR_library_trace_browser);
+#endif
}
Index: runtime/mercury_trace_util.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_util.h,v
retrieving revision 1.5
diff -u -u -r1.5 mercury_trace_util.h
--- mercury_trace_util.h 1998/07/31 15:14:19 1.5
+++ mercury_trace_util.h 1998/08/02 22:53:00
@@ -7,10 +7,43 @@
#ifndef MERCURY_TRACE_UTIL_H
#define MERCURY_TRACE_UTIL_H
-extern Word MR_saved_regs[MAX_FAKE_REG];
+/*
+** These two functions copy the register state to and from MR_saved_regs.
+** XXX MR_saved_regs should probably be in MercuryEngine.
+*/
+
extern void MR_copy_regs_to_saved_regs(int max_mr_num);
extern void MR_copy_saved_regs_to_regs(int max_mr_num);
+extern Word MR_saved_regs[MAX_FAKE_REG];
+
+/*
+** A MR_Stack_Layout_Vars describes the variables that are live at a given
+** program point. Some of the types of these variables may contain type
+** variables. Since the values of those type variables are not known until
+** runtime, the MR_Stack_Layout_Vars cannot include full typeinfos for the
+** variables. Instead, it contains pseudo-typeinfos, in which some parts
+** of some typeinfo structures may contain an indication "this data is
+** not available at compile time, but at runtime it will be in this location".
+**
+** MR_trace_materialize_typeinfos takes as input a MR_Stack_Layout_Vars
+** structure. It returns a vector of typeinfos which has one entry for each
+** pseudo-typeinfo in the MR_Stack_Layout_Vars structure, with this typeinfo
+** being the pseudo-typeinfo with the runtime-only information substituted in.
+** Since type variable numbers start at one, the element of this array at
+** index zero will be unused. This means that the array will itself look
+** like a typeinfo.
+**
+** The vector returned by MR_trace_materialize_typeinfos is from malloc;
+** it should be freed after last use.
+**
+** MR_trace_materialize_typeinfos looks up locations in the current
+** environment. MR_trace_materialize_typeinfos_base does the same job but
+** assumes the environment is given by the given values of MR_sp and MR_curfr,
+** and does not assume that the registers have valid contents unless the
+** flag says so.
+*/
+
extern Word *MR_trace_materialize_typeinfos(const MR_Stack_Layout_Vars
*vars);
extern Word *MR_trace_materialize_typeinfos_base(const MR_Stack_Layout_Vars
@@ -18,10 +51,45 @@
Word *base_sp, Word *base_curfr);
extern Word MR_trace_make_var_list(const MR_Stack_Layout_Label *layout);
+
+/*
+** If the given encoded location refers to a register, return its number.
+** If it does not, return -1.
+*/
+
+extern int MR_trace_get_register_number(MR_Live_Lval locn);
+
+/*
+** Given an encoded location, return the value at that location if possible.
+** *succeeded will say whether the attempt was successful.
+**
+** MR_trace_lookup_live_lval looks up locations in the current environment.
+** MR_trace_lookup_live_lval_base does the same job but assumes the environment
+** is given by the given values of MR_sp and MR_curfr, and does not assume
+** that the registers have valid contents unless the flag says so.
+*/
+
extern Word MR_trace_lookup_live_lval(MR_Live_Lval locn, bool *succeeded);
extern Word MR_trace_lookup_live_lval_base(MR_Live_Lval locn,
bool saved_regs_valid, Word *base_sp, Word *base_curfr,
bool *succeeded);
+
+/*
+** Given information about the location of a variable (var) and a vector giving
+** the typeinfos corresponding to the type variables that may occur in
+** the type of that variable (type_params), try to return the value of the
+** variable in *value and the typeinfo describing its type in *type_info.
+** *succeeded will say whether the attempt was successful.
+**
+** The type_params array should have the same format as the array returned
+** by MR_trace_materialize_typeinfos.
+**
+** MR_trace_get_type_and_value looks up locations in the current environment.
+** MR_trace_get_type_and_value_base does the same job but assumes the
+** environment is given by the given values of MR_sp and MR_curfr, and does
+** not assume that the registers have valid contents unless the flag says so.
+*/
+
extern bool MR_trace_get_type_and_value(const MR_Stack_Layout_Var *var,
Word *type_params, Word *type_info, Word *value);
extern bool MR_trace_get_type_and_value_base(const MR_Stack_Layout_Var *var,
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.12
diff -u -u -r1.12 mercury_wrapper.h
--- mercury_wrapper.h 1998/07/31 15:14:21 1.12
+++ mercury_wrapper.h 1998/08/02 22:53:03
@@ -5,8 +5,8 @@
*/
/*
-** mercury_wrapper.h - defines the interface to wrapper.c.
-** See wrapper.c for documentation.
+** mercury_wrapper.h - defines the interface to mercury_wrapper.c.
+** See mercury_wrapper.c for documentation.
*/
#ifndef MERCURY_WRAPPER_H
@@ -40,7 +40,7 @@
** The address_of_foo pointers are set to the address of
** the corresponding foo.
*/
-extern Code * program_entry_point; /* normally mercury__main_2_0; */
+extern Code *program_entry_point; /* normally mercury__main_2_0; */
extern void (*MR_library_initializer)(void);
extern void (*MR_library_finalizer)(void);
@@ -88,9 +88,9 @@
extern void do_init_modules(void);
-extern const char * progname;
+extern const char *progname;
extern int mercury_argc;
-extern char ** mercury_argv;
+extern char **mercury_argv;
extern int mercury_exit_status;
/* sizes of the data areas, *including* the red zone size */
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
More information about the developers
mailing list