for review: reorganize label table, reduce executable sizes
Zoltan Somogyi
zs at cs.mu.OZ.AU
Thu Jun 25 15:27:34 AEST 1998
Fergus, please review this.
Reorganize the label table to better fit the needs of accurate gc
and the tracer, and reduce the size of executables.
With these changes, the size of hello world, compiled with static
Mercury libraries but dynamic C libraries, goes from 150+ Kb to
138+ Kb, much of which is beyond our control (e.g. Boehm gc).
Estimated hours taken: 20
runtime/mercury_label.[ch]:
The old label table contained both entry labels and internal labels,
even though they had different kinds of layouts associated with them
(proc layouts and label layouts respectively). The two kinds of labels
have different usage patterns. Internal labels are needed for stack
walking, which requires random access by exact label address. Entry
labels are needed for finding which procedure a program counter is in
for accurate GC, which requires lower-bound inexact search.
The module now has two separate data structures for the two
different kinds of labels. Internal labels are in a hash table,
as before. Entry labels are in an array (resized on demand),
which is sorted for binary search. The entry label array and
its associated functions are present only if they are needed.
runtime/mercury_goto.h:
Call the new functions in mercury_label.c from the
init_{local,label,entry}{,_sl} macros.
runtime/mercury_misc.[ch]
Use the new functions in mercury_label. Fix some software rot,
so that the code now compiles with MR_DEBUG_GOTOS. (It still does not
compile with MR_LOWLEVEL_DEBUG, but the fix for that would conflict
with Tom's planned change to zone handling, so that fix should be
done after Tom is done.)
Note that mercury_misc.c still defines newmem() and oldmem()
although they are declared in mercury_std.h.
runtime/mercury_stack_trace.c:
Use the new functions in mercury_label.
runtime/mercury_table.[ch]:
Add a new traversal predicate to support a new function in
mercury_label.c. (That function is not used yet, but will be soon.)
runtime/mercury_trace.[ch]:
runtime/mercury_trace_permanent.[ch]:
Split the old mercury_trace module into two. The functions and
variables that will always be linked in (because they are referenced
from modules such as mercury_wrapper which are always needed) are
now in mercury_trace_permanent; the other functions and variables
stay in mercury_trace. This way, mercury_trace.o will be linked in
only if some module was compiled with execution tracing. Since
mercury_trace.o drags in mercury_trace_internal.o which drags in
everything needed for printing arbitrary terms (which is a lot),
this can be a significant win.
runtime/Mmakefile:
Include the new module in the library.
runtime/mercury_wrapper.c:
runtime/mercury_conf_param.h:
Remove some obsolete MERCURY_OPTIONS options, which would be
difficult to support with the new label table.
Replace the long help message for malformed MERCURY_OPTIONS
environment variables with a pointer to the appropriate manual.
This saves about 1 Kb on every executable.
util/mkinit.c:
Add a new flag, -i. If this flag is given, include the initialization
code regardless of grade. If it is not given, include the init code
only if the grade requires it.
The -i should be given if you want the executable to support stack
tracing, or uplevel printing in execution tracing, at the cost of
making the executable link in the init functions of all the modules
in the library.
Put the option handling code in alphabetical order.
scripts/c2init.in:
Pass through the -i flag to mkinit.
Put the option handling code in alphabetical order.
compiler/mercury_compile.m:
If the trace level specifies any kind of tracing, pass -i to c2init.
tests/debugger/Mmakefile:
Add -i to the c2init flags.
tests/debugger/*
Update other half the test cases (those which assume a traced
library) to conform to the changes in the debugger interface.
The others were updated earlier.
Zoltan.
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.100
diff -u -r1.100 mercury_compile.m
--- mercury_compile.m 1998/06/18 06:06:37 1.100
+++ mercury_compile.m 1998/06/25 06:08:10
@@ -2330,7 +2330,13 @@
% create the initialization C file
maybe_write_string(Verbose, "% Creating initialization file...\n"),
join_module_list(Modules, ".m", ["> ", InitCFileName], MkInitCmd0),
- { string__append_list(["c2init " | MkInitCmd0], MkInitCmd) },
+ globals__io_get_trace_level(TraceLevel),
+ { trace_level_trace_interface(TraceLevel, yes) ->
+ CmdPrefix = "c2init -i "
+ ;
+ CmdPrefix = "c2init "
+ },
+ { string__append_list([CmdPrefix | MkInitCmd0], MkInitCmd) },
invoke_system_command(MkInitCmd, MkInitOK),
maybe_report_stats(Stats),
( { MkInitOK = no } ->
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.30
diff -u -r1.30 Mmakefile
--- Mmakefile 1998/06/09 02:07:45 1.30
+++ Mmakefile 1998/06/25 06:47:44
@@ -14,7 +14,7 @@
#-----------------------------------------------------------------------------#
CFLAGS = -I$(MERCURY_DIR)/runtime -I$(MERCURY_DIR)/boehm_gc -g \
- $(DLL_CFLAGS) $(EXTRA_CFLAGS)
+ $(DLL_CFLAGS) $(EXTRA_CFLAGS)
MGNUC = MERCURY_C_INCL_DIR=. $(SCRIPTS_DIR)/mgnuc
MGNUCFLAGS = --no-ansi $(EXTRA_MGNUCFLAGS) $(CFLAGS)
MOD2C = $(SCRIPTS_DIR)/mod2c
@@ -69,6 +69,7 @@
mercury_trace.h \
mercury_trace_external.h \
mercury_trace_internal.h \
+ mercury_trace_permanent.h \
mercury_trace_util.h \
mercury_trail.h \
mercury_types.h \
@@ -120,6 +121,7 @@
mercury_trace.c \
mercury_trace_external.c \
mercury_trace_internal.c \
+ mercury_trace_permanent.c \
mercury_trace_util.c \
mercury_trail.c \
mercury_type_info.c \
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_conf_param.h
--- mercury_conf_param.h 1998/06/08 08:26:58 1.5
+++ mercury_conf_param.h 1998/06/19 06:15:43
@@ -145,16 +145,6 @@
** Enables profiling of memory usage.
*/
-/*
-** Miscellaneous options:
-**
-** MR_CHOOSE_ENTRY_POINT
-** Enables support for the `-w' (entry point) command
-** in the MERCURY_OPTIONS environment variable.
-** (`-w' also happens to work if you set certain other
-** options instead, include MR_LOWLEVEL_DEBUG.)
-*/
-
/*---------------------------------------------------------------------------*/
/*
** Settings of configuration parameters which can be passed on
Index: runtime/mercury_goto.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_goto.h,v
retrieving revision 1.10
diff -u -r1.10 mercury_goto.h
--- mercury_goto.h 1998/06/08 08:27:01 1.10
+++ mercury_goto.h 1998/06/23 08:02:17
@@ -12,6 +12,7 @@
#include "mercury_conf.h"
#include "mercury_types.h" /* for `Code *' */
#include "mercury_debug.h" /* for debuggoto() */
+#include "mercury_label.h" /* for insert_{entry,internal}_label() */
#define paste(a,b) a##b
#define stringify(string) #string
@@ -19,13 +20,15 @@
#define skip(label) paste(skip_,label)
#if defined(MR_USE_STACK_LAYOUTS)
- #define MR_STACK_LAYOUT(label) (Word *) (Word) \
+ #define MR_ENTRY_LAYOUT(label) (MR_Stack_Layout_Entry *) (Word) \
&(paste(mercury_data__layout__,label))
+ #define MR_INTERNAL_LAYOUT(label) (MR_Stack_Layout_Label *) (Word) \
+ &(paste(mercury_data__layout__,label))
#else
- #define MR_STACK_LAYOUT(label) (Word *) NULL
+ #define MR_ENTRY_LAYOUT(label) (MR_Stack_Layout_Entry *) NULL
+ #define MR_INTERNAL_LAYOUT(label) (MR_Stack_Layout_Label *) NULL
#endif
-
/*
** Taking the address of a label can inhibit gcc's optimization,
** because it assumes that anything can jump there.
@@ -40,25 +43,27 @@
*/
#if defined(MR_INSERT_LABELS)
- #define make_label(n, a, l) make_entry(n, a, l)
- #define make_label_sl(n, a, l) make_entry_sl(n, a, l)
+ #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))
#else
#define make_label(n, a, l) /* nothing */
#define make_label_sl(n, a, l) /* nothing */
#endif
#if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS)
- #define make_local(n, a, l) make_entry(n, a, l)
- #define make_local_sl(n, a, l) make_entry_sl(n, a, l)
+ #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))
#else
#define make_local(n, a, l) /* nothing */
#define make_local_sl(n, a, l) /* nothing */
#endif
-#if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS) \
- || defined(MR_CHOOSE_ENTRY_POINT)
- #define make_entry(n, a, l) insert_entry(n, a, NULL)
- #define make_entry_sl(n, a, l) insert_entry(n, a, MR_STACK_LAYOUT(l))
+#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))
#else
#define make_entry(n, a, l) /* nothing */
#define make_entry_sl(n, a, l) /* nothing */
Index: runtime/mercury_label.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_label.c,v
retrieving revision 1.6
diff -u -r1.6 mercury_label.c
--- mercury_label.c 1998/03/16 12:23:30 1.6
+++ mercury_label.c 1998/06/23 07:52:36
@@ -23,44 +23,75 @@
#include "mercury_engine.h" /* for `progdebug' */
#include "mercury_wrapper.h" /* for do_init_modules() */
-static const void *entry_name(const void *entry);
-static const void *entry_addr(const void *entry);
-static bool equal_name(const void *name1, const void *name2);
+/*
+** We record information about entry labels in an array that
+** we sort by code address once all the entry labels have been inserted.
+** Space for the array is provided by malloc, and it is expanded when
+** needed.
+**
+** This array is needed only by accurate garbage collection and when
+** doing low-level debugging.
+*/
+
+#ifdef MR_NEED_ENTRY_LABEL_ARRAY
+
+#define INIT_ENTRY_SIZE (1 << 8)
+
+static int compare_entry_by_addr(const void *e1, const void *e2);
+
+static MR_Entry *entry_array;
+static int entry_array_size; /* # of entries allocated */
+static int entry_array_next; /* # of entries used */
+static bool entry_array_sorted;
+
+#endif /* MR_NEED_ENTRY_LABEL_ARRAY */
+
+/*
+** We record information about internal labels in a hash table
+** that is indexed by the code address of the label.
+**
+** This table is used by stack tracing and execution tracing.
+** Since execution tracing and hence stack tracing can be required
+** in any grade, we always include this table.
+*/
+
+#define INTERNAL_SIZE (1 << 16) /* 64k */
+
+static const void *internal_addr(const void *internal);
static bool equal_addr(const void *addr1, const void *addr2);
-static int hash_name(const void *name);
static int hash_addr(const void *addr);
-int entry_table_size = (1 << 16); /* 64k */
+static Table internal_addr_table = {INTERNAL_SIZE, NULL,
+ internal_addr, hash_addr, equal_addr};
-Table entry_name_table =
- {0, NULL, entry_name, hash_name, equal_name};
-Table entry_addr_table =
- {0, NULL, entry_addr, hash_addr, equal_addr};
-
void
-do_init_entries(void)
+MR_do_init_label_tables(void)
{
- static bool done = FALSE;
+ static bool done = FALSE;
+
if (!done) {
- entry_name_table.ta_size = entry_table_size;
- entry_addr_table.ta_size = entry_table_size;
- init_table(entry_name_table);
- init_table(entry_addr_table);
+#ifdef MR_NEED_ENTRY_LABEL_ARRAY
+ entry_array_next = 0;
+ entry_array_size = INIT_ENTRY_SIZE;
+ entry_array_sorted = TRUE;
+ entry_array = malloc(entry_array_size * sizeof(MR_Entry));
+#endif
+
+ init_table(internal_addr_table);
+
done = TRUE;
}
}
-Label *
-insert_entry(const char *name, Code *addr, Word *entry_layout_info)
-{
- Label *entry;
+#ifdef MR_NEED_ENTRY_LABEL_INFO
- do_init_entries();
+static int compare_entry_addr(const void *e1, const void *e2);
- entry = make(Label);
- entry->e_name = name;
- entry->e_addr = addr;
- entry->e_layout = entry_layout_info;
+void
+MR_insert_entry_label(const char *name, Code *addr,
+ MR_Stack_Layout_Entry *entry_layout)
+{
+ MR_do_init_label_tables();
#ifdef PROFILE_CALLS
if (MR_profiling) MR_prof_output_addr_decl(name, addr);
@@ -68,74 +99,130 @@
#ifdef MR_LOWLEVEL_DEBUG
if (progdebug) {
- printf("inserting label %s at %p\n", name, addr);
+ printf("recording entry label %s at %p\n", name, addr);
}
#endif
+
+#ifdef MR_NEED_ENTRY_LABEL_ARRAY
- if (insert_table(entry_name_table, entry)) {
- printf("duplicated label name %s\n", name);
+ if (entry_array_next >= entry_array_size) {
+ entry_array_size *= 2;
+ if (realloc(entry_array, entry_array_size * sizeof(MR_Entry))
+ == NULL) {
+ fatal_error("run out of memory for entry label array");
+ }
}
- /* two labels at same location will happen quite often */
- /* when the code generated between them turns out to be empty */
+ entry_array[entry_array_next].e_addr = addr;
+ entry_array[entry_array_next].e_name = name;
+ entry_array[entry_array_next].e_layout = entry_layout;
+ entry_array_next++;
+ entry_array_sorted = FALSE;
+#endif
+}
+
+#endif
- (void) insert_table(entry_addr_table, entry);
+#ifdef MR_NEED_ENTRY_LABEL_ARRAY
- return entry;
+static int
+compare_entry_addr(const void *e1, const void *e2)
+{
+ const MR_Entry *entry1;
+ const MR_Entry *entry2;
+
+ entry1 = (const MR_Entry *) e1;
+ entry2 = (const MR_Entry *) e2;
+
+ if (entry1->e_addr > entry2->e_addr) {
+ return 1;
+ } else if (entry1->e_addr < entry2->e_addr) {
+ return -1;
+ } else {
+ return 0;
+ }
}
-Label *
-lookup_label_addr(const Code *addr)
+MR_Entry *
+MR_prev_entry_by_addr(const Code *addr)
{
- do_init_entries();
- do_init_modules();
-#ifdef MR_LOWLEVEL_DEBUG
- if (progdebug) {
- printf("looking for label at %p\n", addr);
+ int lo;
+ int hi;
+ int mid;
+ int i;
+
+ if (!entry_array_sorted) {
+ qsort(entry_array, entry_array_next, sizeof(MR_Entry),
+ compare_entry_addr);
}
-#endif
+
+ lo = 0;
+ hi = entry_array_next-1;
+
+ while (lo <= hi) {
+ mid = (lo + hi) / 2;
+ if (entry_array[mid].e_addr == addr) {
+ return &entry_array[mid];
+ } else if (entry_array[mid].e_addr < addr) {
+ lo = mid + 1;
+ } else {
+ hi = mid - 1;
+ }
+ }
- return (Label *) lookup_table(entry_addr_table, addr);
+ if (entry_array[lo].e_addr < addr) {
+ return &entry_array[lo];
+ } else {
+ return &entry_array[lo-1];
+ }
}
-Label *
-lookup_label_name(const char *name)
-{
- do_init_entries();
- do_init_modules();
+#endif
+
+void
+MR_insert_internal_label(const char *name, Code *addr,
+ MR_Stack_Layout_Label *label_layout)
+{
+ MR_Internal *internal;
+
+ MR_do_init_label_tables();
+
+ internal = make(MR_Internal);
+ internal->i_addr = addr;
+ internal->i_layout = label_layout;
+ internal->i_name = name;
+
#ifdef MR_LOWLEVEL_DEBUG
if (progdebug) {
- printf("looking for label %s\n", name);
+ printf("inserting internal label %s at %p\n", name, addr);
}
#endif
- return (Label *) lookup_table(entry_name_table, name);
+ /* two labels at same location will happen quite often */
+ /* when the code generated between them turns out to be empty */
+
+ (void) insert_table(internal_addr_table, internal);
}
-List *
-get_all_labels(void)
+MR_Internal *
+MR_lookup_internal_by_addr(const Code *addr)
{
- do_init_entries();
+ MR_do_init_label_tables();
do_init_modules();
- return get_all_entries(entry_name_table);
-}
-static const void *
-entry_name(const void *entry)
-{
- return (const void *) (((const Label *) entry)->e_name);
-}
+#ifdef MR_LOWLEVEL_DEBUG
+ if (progdebug) {
+ printf("looking for internal label at %p\n", addr);
+ }
+#endif
-static const void *
-entry_addr(const void *entry)
-{
- return (const void *) (((const Label *) entry)->e_addr);
+ return (MR_Internal *) lookup_table(internal_addr_table, addr);
}
-static bool
-equal_name(const void *name1, const void *name2)
+static const void *
+internal_addr(const void *internal)
{
- return streq(((const char *) name1), ((const char *) name2));
+ return (const void *) (((const MR_Internal *) internal)->i_addr);
}
static bool
@@ -145,13 +232,13 @@
}
static int
-hash_name(const void *name)
+hash_addr(const void *addr)
{
- return str_to_int(((const char *) name)) % entry_table_size;
+ return (((Unsigned) addr) >> 3) % INTERNAL_SIZE;
}
-static int
-hash_addr(const void *addr)
+void
+MR_process_all_internal_labels(void f(const void *))
{
- return (((Unsigned) addr) >> 3) % entry_table_size;
+ process_all_entries(internal_addr_table, f);
}
Index: runtime/mercury_label.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_label.h,v
retrieving revision 1.4
diff -u -r1.4 mercury_label.h
--- mercury_label.h 1998/04/21 05:51:37 1.4
+++ mercury_label.h 1998/06/23 07:55:51
@@ -15,24 +15,46 @@
#ifndef MERCURY_LABEL_H
#define MERCURY_LABEL_H
-#include "mercury_types.h" /* for `Code *' */
-#include "mercury_dlist.h" /* for `List' */
+#include "mercury_types.h" /* for `Code *' */
+#include "mercury_dlist.h" /* for `List' */
+#include "mercury_stack_layout.h" /* for `MR_Stack_Layout_*' */
-typedef struct s_label {
- const char *e_name; /* name of the procedure */
- Code *e_addr; /* address of the code */
- Word *e_layout; /* layout info for the label */
-} Label;
-
-extern void do_init_entries(void);
-extern Label *insert_entry(const char *name, Code *addr,
- Word * entry_layout_info);
-extern Label *lookup_label_name(const char *name);
-extern Label *lookup_label_addr(const Code *addr);
-extern List *get_all_labels(void);
-
-extern int entry_table_size;
- /* expected number of entries in the table */
- /* we allocate 8 bytes per entry */
+#if defined(NATIVE_GC) || defined(MR_DEBUG_GOTOS)
+#define MR_NEED_ENTRY_LABEL_ARRAY
+#endif
+
+#if defined(MR_NEED_ENTRY_LABEL_ARRAY) || defined(PROFILE_CALLS)
+#define MR_NEED_ENTRY_LABEL_INFO
+#endif
+
+typedef struct s_entry {
+ Code *e_addr;
+ MR_Stack_Layout_Entry *e_layout;
+ const char *e_name;
+} MR_Entry;
+
+typedef struct s_internal {
+ Code *i_addr;
+ MR_Stack_Layout_Label *i_layout;
+ const char *i_name;
+} MR_Internal;
+
+extern void MR_do_init_label_tables(void);
+
+#ifdef MR_NEED_ENTRY_LABEL_INFO
+extern void MR_insert_entry_label(const char *name, Code *addr,
+ MR_Stack_Layout_Entry *entry_layout);
+#else
+#define MR_insert_entry_label(n, a, l) /* nothing */
+#endif /* not MR_NEED_ENTRY_LABEL_INFO */
+
+#ifdef MR_NEED_ENTRY_LABEL_ARRAY
+extern MR_Entry *MR_prev_entry_by_addr(const Code *addr);
+#endif /* MR_NEED_ENTRY_LABEL_ARRAY */
+
+extern void MR_insert_internal_label(const char *name, Code *addr,
+ MR_Stack_Layout_Label *label_layout);
+extern MR_Internal *MR_lookup_internal_by_addr(const Code *addr);
+extern void MR_process_all_internal_labels(void f(const void *));
#endif /* not MERCURY_LABEL_H */
Index: runtime/mercury_misc.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.c,v
retrieving revision 1.7
diff -u -r1.7 mercury_misc.c
--- mercury_misc.c 1998/06/09 02:08:11 1.7
+++ mercury_misc.c 1998/06/23 07:34:23
@@ -8,6 +8,7 @@
#include "mercury_dlist.h"
#include "mercury_regs.h"
#include "mercury_trace.h"
+#include "mercury_label.h"
#include "mercury_misc.h"
#include <stdio.h>
@@ -214,19 +215,13 @@
#endif /* defined(MR_LOWLEVEL_DEBUG) */
-#if defined(MR_DEBUG_GOTOS)
+#ifdef MR_DEBUG_GOTOS
void
goto_msg(/* const */ Code *addr)
{
printf("\ngoto ");
printlabel(addr);
-
- if (detaildebug) {
- printregs("registers at goto");
- }
-
- return;
}
void
@@ -254,7 +249,7 @@
/*--------------------------------------------------------------------*/
-#if defined(MR_DEBUG_GOTOS)
+#ifdef MR_LOWLEVEL_DEBUG
/* debugging printing tools */
@@ -410,16 +405,25 @@
void
printlabel(/* const */ Code *w)
{
- Label *label;
+ MR_Internal *internal;
- label = lookup_label_addr(w);
- if (label != NULL) {
- printf("label %s (0x%p)\n", label->e_name, w);
+ internal = MR_lookup_internal_by_addr(w);
+ if (internal != NULL) {
+ printf("label %s (0x%p)\n", internal->i_name, w);
} else {
+#ifdef MR_DEBUG_GOTOS
+ MR_Entry *entry;
+ entry = MR_prev_entry_by_addr(w);
+ if (entry->e_addr == w) {
+ printf("label %s (0x%p)\n", entry->e_name, w);
+ } else {
+ printf("label UNKNOWN (0x%p)\n", w);
+ }
+#else
printf("label UNKNOWN (0x%p)\n", w);
+#endif /* not MR_DEBUG_GOTOS */
}
}
-
void *
newmem(size_t n)
Index: runtime/mercury_misc.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.h,v
retrieving revision 1.6
diff -u -r1.6 mercury_misc.h
--- mercury_misc.h 1998/06/09 02:08:12 1.6
+++ mercury_misc.h 1998/06/23 07:16:08
@@ -17,7 +17,6 @@
#include "mercury_types.h" /* for `Code *' */
#ifdef MR_LOWLEVEL_DEBUG
-
extern void mkframe_msg(void);
extern void modframe_msg(void);
extern void succeed_msg(void);
@@ -35,16 +34,13 @@
extern void push_msg(Word val, const Word *addr);
extern void pop_msg(Word val, const Word *addr);
#endif
-
-#if defined(MR_DEBUG_GOTOS)
+#ifdef MR_DEBUG_GOTOS
extern void goto_msg(/* const */ Code *addr);
extern void reg_msg(void);
-
#endif
#ifdef MR_LOWLEVEL_DEBUG
-
extern void printint(Word n);
extern void printstring(const char *s);
extern void printheap(const Word *h);
@@ -55,12 +51,10 @@
extern void printlist(Word p);
extern void printframe(const char *);
extern void printregs(const char *msg);
-
#endif
extern void printlabel(/* const */ Code *w);
-
#if __GNUC__
#define NO_RETURN __attribute__((noreturn))
#else
@@ -76,6 +70,6 @@
** XXX We should fix this eventually by using -fno-builtin since pragma
** c_code may call the builtin functions.
*/
-void MR_memcpy(char *dest, const char *src, size_t nbytes);
+extern void MR_memcpy(char *dest, const char *src, size_t nbytes);
#endif /* not MERCURY_MISC_H */
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.9
diff -u -r1.9 mercury_stack_trace.c
--- mercury_stack_trace.c 1998/06/18 06:08:05 1.9
+++ mercury_stack_trace.c 1998/06/19 07:23:03
@@ -150,11 +150,12 @@
Word **stack_trace_sp_ptr, Word **stack_trace_curfr_ptr,
const char **problem_ptr)
{
- Label *label;
+ MR_Internal *label;
MR_Live_Lval location;
MR_Stack_Layout_Label *label_layout;
MR_Lval_Type type;
- int number, determinism;
+ int number;
+ int determinism;
Code *success;
*return_label_layout = NULL;
@@ -192,13 +193,13 @@
return STEP_OK;
}
- label = lookup_label_addr(success);
+ label = MR_lookup_internal_by_addr(success);
if (label == NULL) {
*problem_ptr = "reached label with no stack trace info";
return STEP_ERROR_AFTER;
}
- label_layout = (MR_Stack_Layout_Label *) label->e_layout;
+ label_layout = (MR_Stack_Layout_Label *) label->i_layout;
if (label_layout == NULL) {
*problem_ptr = "reached label with no stack layout info";
return STEP_ERROR_AFTER;
Index: runtime/mercury_table.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_table.c,v
retrieving revision 1.3
diff -u -r1.3 mercury_table.c
--- mercury_table.c 1997/11/23 09:31:50 1.3
+++ mercury_table.c 1998/06/23 07:50:07
@@ -120,6 +120,23 @@
}
/*
+** Process all table entries with the specified function.
+*/
+
+void
+tab_process_all_entries(const Table *table, void f(const void *))
+{
+ reg List *ptr;
+ reg int i;
+
+ for (i = 0; i < table->ta_size; i++) {
+ for_list (ptr, table->ta_store[i]) {
+ (*f)(ldata(ptr));
+ }
+ }
+}
+
+/*
** Convert a string to a positive int. The return value
** mod the table size is a good hash value.
*/
Index: runtime/mercury_table.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_table.h,v
retrieving revision 1.4
diff -u -r1.4 mercury_table.h
--- mercury_table.h 1998/05/17 07:03:14 1.4
+++ mercury_table.h 1998/06/23 07:48:58
@@ -28,20 +28,22 @@
/* applied to two keys */
} Table;
-#define init_table(t) tab_init_table(&t)
-#define lookup_table(t, k) tab_lookup_table(&t, (const void *) k)
-#define insert_table(t, e) tab_insert_table(&t, (void *) e)
-#define get_all_entries(t) tab_get_all_entries(&t)
-#define str_to_int(val) tab_str_to_int(val)
+#define init_table(t) tab_init_table(&t)
+#define lookup_table(t, k) tab_lookup_table(&t, (const void *) k)
+#define insert_table(t, e) tab_insert_table(&t, (void *) e)
+#define get_all_entries(t) tab_get_all_entries(&t)
+#define process_all_entries(t, f) tab_process_all_entries(&t, f)
+#define str_to_int(val) tab_str_to_int(val)
-#define tablekey(table) (*(table->ta_key))
-#define tablehash(table) (*(table->ta_hash))
-#define tableequal(table) (*(table->ta_equal))
+#define tablekey(table) (*(table->ta_key))
+#define tablehash(table) (*(table->ta_hash))
+#define tableequal(table) (*(table->ta_equal))
extern void tab_init_table(Table *);
extern void * tab_lookup_table(const Table *, const void *);
extern bool tab_insert_table(const Table *, void *);
extern List *tab_get_all_entries(const Table *);
+extern void tab_process_all_entries(const Table *, void f(const void *));
extern int tab_str_to_int(const char *);
#endif /* not MERCURY_TABLE_H */
Index: runtime/mercury_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.c,v
retrieving revision 1.13
diff -u -r1.13 mercury_trace.c
--- mercury_trace.c 1998/05/16 07:28:21 1.13
+++ mercury_trace.c 1998/06/23 08:33:07
@@ -31,71 +31,6 @@
#include <stdio.h>
#include <unistd.h> /* for the write system call */
-/*
-** Do we want to use the debugger within this process, or do want to use
-** the Opium-style trace analyzer debugger implemented by an external process.
-** This variable is set in mercury_wrapper.c and never modified afterwards.
-*/
-
-MR_trace_type MR_trace_handler = MR_TRACE_INTERNAL;
-
-/*
-** Compiler generated tracing code will check whether MR_trace_enabled is true,
-** before calling MR_trace. For now, and until we implement interface tracing,
-** MR_trace_enabled should keep the same value throughout the execution of
-** the entire program after being set in mercury_wrapper.c. There is one
-** exception to this: the Mercury routines called as part of the functionality
-** of the tracer itself (e.g. the term browser) should always be executed
-** with MR_trace_enabled set to FALSE.
-*/
-
-bool MR_trace_enabled = FALSE;
-
-/*
-** MR_trace_call_seqno counts distinct calls. The prologue of every
-** procedure assigns the current value of this counter as the sequence number
-** of that invocation and increments the counter. This is the only way that
-** MR_trace_call_seqno is modified.
-**
-** MR_trace_call_depth records the current depth of the call tree. The prologue
-** of every procedure assigns the current value of this variable plus one
-** as the depth of that invocation. Just before making a call, the caller
-** will set MR_trace_call_depth to its own remembered depth value.
-** These are the only ways in which MR_trace_call_depth is modified.
-**
-** Although neither MR_trace_call_seqno nor MR_trace_call_depth are used
-** directly in this module, the seqno and depth arguments of MR_trace
-** always derive their values from the saved values of these two global
-** variables.
-*/
-
-Unsigned MR_trace_call_seqno = 0;
-Unsigned MR_trace_call_depth = 0;
-
-/*
-** MR_trace_event_number is a simple counter of events. This is used in
-** two places: here, for display to the user and for skipping a given number
-** of events, and when printing an abort message, so that the programmer
-** can zero in on the source of the problem more quickly.
-*/
-
-Unsigned MR_trace_event_number = 0;
-
-/*
-** MR_trace_from_full is a boolean that is set before every call;
-** it states whether the caller is being fully traced, or only interface
-** traced. If the called code is interface traced, it will generate
-** call, exit and fail trace events only if MR_trace_from_full is true.
-** (It will never generate internal events.) If the called code is fully
-** traced, it will always generate all trace events, external and internal,
-** regardless of the setting of this variable on entry.
-**
-** The initial value is set to TRUE to allow the programmer to gain
-** control in the debugger when main/2 is called.
-*/
-
-Bool MR_trace_from_full = 1;
-
static MR_trace_cmd_info MR_trace_ctrl = { MR_CMD_GOTO, 0, 0, FALSE };
static void MR_trace_event(MR_trace_cmd_info *cmd,
@@ -107,40 +42,6 @@
MR_trace_port port, Unsigned seqno, Unsigned depth,
const char *path, int max_r_num);
-void
-MR_trace_init(void)
-{
-#ifdef MR_USE_EXTERNAL_DEBUGGER
- if (MR_trace_handler == MR_TRACE_EXTERNAL)
- MR_trace_init_external();
-#endif
-}
-
-void
-MR_trace_final(void)
-{
-#ifdef MR_USE_EXTERNAL_DEBUGGER
- if (MR_trace_handler == MR_TRACE_EXTERNAL)
- MR_trace_final_external();
-#endif
-}
-
-void
-MR_trace_start(bool enabled)
-{
- MR_trace_event_number = 0;
- MR_trace_call_seqno = 0;
- MR_trace_call_depth = 0;
- MR_trace_from_full = TRUE;
- MR_trace_enabled = enabled;
-}
-
-void
-MR_trace_end(void)
-{
- MR_trace_enabled = FALSE;
-}
-
/*
** This function is called from compiled code whenever an event to be traced
** occurs.
@@ -261,35 +162,4 @@
MR_trace_event_internal_report(layout, port, seqno, depth, path);
#endif
-}
-
-void
-MR_trace_report(FILE *fp)
-{
- if (MR_trace_event_number > 0) {
- /*
- ** This means that the executable was compiled with tracing,
- ** which implies that the user wants trace info on abort.
- */
-
- fprintf(fp, "Last trace event was event #%ld.\n",
- (long) MR_trace_event_number);
- }
-}
-
-void
-MR_trace_report_raw(int fd)
-{
- char buf[80]; /* that ought to be more than long enough */
-
- if (MR_trace_event_number > 0) {
- /*
- ** This means that the executable was compiled with tracing,
- ** which implies that the user wants trace info on abort.
- */
-
- sprintf(buf, "Last trace event was event #%ld.\n",
- (long) MR_trace_event_number);
- write(fd, buf, strlen(buf));
- }
}
Index: runtime/mercury_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.h,v
retrieving revision 1.8
diff -u -r1.8 mercury_trace.h
--- mercury_trace.h 1998/05/16 07:28:23 1.8
+++ mercury_trace.h 1998/06/23 08:32:30
@@ -13,23 +13,28 @@
** (b) It defines the interface by which the internal and external debuggers
** can control how the tracing subsystem treats events.
**
-** The macros and functions defined in this module are intended to be called
-** only from code generated by the Mercury compiler, and from hand-written
-** code in the Mercury runtime or the Mercury standard library.
+** The macros, functions and variables of this module are intended to be
+** referred to only from code generated by the Mercury compiler, and from
+** hand-written code in the Mercury runtime or the Mercury standard library,
+** and even then only if at least some part of the program was compiled
+** with some form of execution tracing.
+**
+** The parts of the tracing system that need to be present even when no
+** part of the program is compiled with execution tracing are in the module
+** mercury_trace_permanent.
*/
#ifndef MERCURY_TRACE_H
#define MERCURY_TRACE_H
+#include "mercury_trace_permanent.h"
+
/* 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)
-extern Word MR_trace_call_seqno;
-extern Word MR_trace_call_depth;
-
/*
** This enum should exactly match the definition of the `trace_port' type in
** library/debugger_interface.
@@ -55,51 +60,6 @@
const char *, /* path to event goal within procedure */
int, /* highest numbered rN register in use */
bool); /* is this event supposed to be traced */
-
-/*
-** These functions will report the number of the last event,
-** if there have been some events, and will do nothing otherwise.
-*/
-
-extern void MR_trace_report(FILE *fp);
-extern void MR_trace_report_raw(int fd);
-
-/*
-** MR_trace_init() is called from mercury_runtime_init()
-** when the debuggee programs begins, to perform any initialization
-** that must be done before any traced Mercury code is executed.
-** This includes the initialization code written in Mercury as well as main.
-**
-** MR_trace_start(enabled) is called from mercury_runtime_init()
-** after the initialization code written in Mercury is executed,
-** when we are about to start executing main. The argument says
-** whether tracing is enabled for main (it is never enabled for
-** initialization and finalization routines).
-**
-** MR_trace_end() is called from mercury_runtime_terminate() just
-** after main has terminated and just before we call the finalization
-** code written in Mercury.
-**
-** MR_trace_final() is called from mercury_runtime_terminate()
-** after all Mercury code, including finalization code, has terminated.
-*/
-
-extern void MR_trace_init(void);
-extern void MR_trace_start(bool enabled);
-extern void MR_trace_end(void);
-extern void MR_trace_final(void);
-
-typedef enum {
- MR_TRACE_INTERNAL,
- MR_TRACE_EXTERNAL
-} MR_trace_type;
-
-extern MR_trace_type MR_trace_handler;
-extern bool MR_trace_enabled;
-
-extern Unsigned MR_trace_event_number;
-
-extern Bool MR_trace_from_full;
/* The interface between the debuggers and the tracing subsystem. */
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.14
diff -u -r1.14 mercury_wrapper.c
--- mercury_wrapper.c 1998/06/18 04:30:47 1.14
+++ mercury_wrapper.c 1998/06/23 08:46:19
@@ -567,27 +567,6 @@
usage();
break;
- case 'L':
- do_init_modules();
- break;
-
- case 'l': {
- List *ptr;
- List *label_list;
-
- label_list = get_all_labels();
- for_list (ptr, label_list) {
- Label *label;
- label = (Label *) ldata(ptr);
- printf("%lu %lx %s\n",
- (unsigned long) label->e_addr,
- (unsigned long) label->e_addr,
- label->e_name);
- }
-
- exit(0);
- }
-
case 'p':
MR_profiling = FALSE;
break;
@@ -619,9 +598,6 @@
detstack_size = size;
else if (optarg[0] == 'n')
nondstack_size = size;
- else if (optarg[0] == 'l')
- entry_table_size = size *
- 1024 / (2 * sizeof(List *));
#ifdef MR_USE_TRAIL
else if (optarg[0] == 't')
trail_size = size;
@@ -656,22 +632,6 @@
}
break;
- case 'w': {
- Label *which_label;
-
- which_label = lookup_label_name(optarg);
- if (which_label == NULL)
- {
- fprintf(stderr, "Mercury runtime: "
- "label name `%s' unknown\n",
- optarg);
- exit(1);
- }
-
- program_entry_point = which_label->e_addr;
-
- break;
- }
case 'x':
#ifdef CONSERVATIVE_GC
GC_dont_gc = TRUE;
@@ -708,54 +668,9 @@
static void
usage(void)
{
- printf("Mercury runtime usage:\n"
- "MERCURY_OPTIONS=\"[-hclLtxp] [-T[rvp]] [-d[abcdghs]]\n"
- " [-[szt][hdn]#] [-C#] [-r#] [-w name] [-[123]#]\"\n"
- "-h \t\tprint this usage message\n"
- "-c \t\tcheck cross-function stack usage\n"
- "-l \t\tprint all labels\n"
- "-L \t\tcheck for duplicate labels\n"
- "-t \t\ttime program execution\n"
- "-x \t\tdisable garbage collection\n"
- "-p \t\tdisable profiling\n"
- "-Tr \t\tprofile real time (using ITIMER_REAL)\n"
- "-Tv \t\tprofile user time (using ITIMER_VIRTUAL)\n"
- "-Tp \t\tprofile user + system time (using ITIMER_PROF)\n"
- "-dg \t\tdebug gotos\n"
- "-dc \t\tdebug calls\n"
- "-db \t\tdebug backtracking\n"
- "-dh \t\tdebug heap\n"
- "-ds \t\tdebug detstack\n"
- "-df \t\tdebug final success/failure\n"
- "-da \t\tdebug all\n"
- "-dm \t\tdebug memory allocation\n"
- "-dG \t\tdebug garbage collection\n"
- "-dd \t\tdetailed debug\n"
- "-Di \t\tdebug the program using the internal debugger\n"
-#ifdef MR_USE_EXTERNAL_DEBUGGER
- "-De \t\tdebug the program using the external debugger\n"
-#endif
- "-sh<n> \t\tallocate n kb for the heap\n"
- "-sd<n> \t\tallocate n kb for the det stack\n"
- "-sn<n> \t\tallocate n kb for the nondet stack\n"
-#ifdef MR_USE_TRAIL
- "-st<n> \t\tallocate n kb for the trail\n"
-#endif
- "-sl<n> \t\tallocate n kb for the label table\n"
- "-zh<n> \t\tallocate n kb for the heap redzone\n"
- "-zd<n> \t\tallocate n kb for the det stack redzone\n"
- "-zn<n> \t\tallocate n kb for the nondet stack redzone\n"
-#ifdef MR_USE_TRAIL
- "-zt<n> \t\tallocate n kb for the trail redzone\n"
-#endif
- "-C<n> \t\tprimary cache size in kbytes\n"
-#ifdef PARALLEL
- "-P<n> \t\tnumber of processes to use for parallel execution\n"
- "\t\tapplies only if Mercury is configured with --enable-parallel\n"
-#endif
- "-r<n> \t\trepeat n times\n"
- "-w<name> \tcall predicate with given name (default: main/2)\n"
- );
+ printf("The MERCURY_OPTIONS environment variable"
+ "contains an invalid option.\n"
+ "Please refer to the Mercury users' guide for details.\n");
fflush(stdout);
exit(1);
} /* end usage() */
Index: scripts/c2init.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/c2init.in,v
retrieving revision 1.15
diff -u -r1.15 c2init.in
--- c2init.in 1998/05/30 13:34:09 1.15
+++ c2init.in 1998/06/25 06:17:53
@@ -19,6 +19,15 @@
Name: c2init - Create Mercury initialization file.
Usage: c2init [options] *.c *.init ...
Options:
+ -c <n>, --max-calls <n>
+ Break up the initialization into groups of at most <n> function
+ calls. (Default value of <n> is 40.)
+ -i, --include-initialization-code
+ Always include code that calls the initialization functions
+ of the various modules. With this option, the debugger can use
+ information from any modules that were compiled with execution
+ tracing to do (partial) stack tracing and uplevel printing
+ even in grades in which this not normally possible.
-l, --library
Don't generate a \`main()' function.
Instead, generate a function
@@ -26,18 +35,15 @@
(declared in \"init.h\") that can be called from C code.
(A more fine-grained interface is also available;
see \"init.h\" for details.)
+ -w <label>, --entry-point <label>
+ Set entry point to <label>.
+ (Default value is \`mercury__main_2_0'.)
-x, --extra-inits
Search \`.c' files for extra initialization functions.
(This may be necessary if the C files contain
hand-coded C code with \`INIT' comments, rather than
containing only C code that was automatically generated
by the Mercury compiler.)
- -c <n>, --max-calls <n>
- Break up the initialization into groups of at most <n> function
- calls. (Default value of <n> is 40.)
- -w <label>, --entry-point <label>
- Set entry point to <label>.
- (Default value is \`mercury__main_2_0'.)
Environment variables:
MERCURY_MOD_LIB_DIR, MERCURY_MOD_LIB_MODS, MERCURY_MKINIT.
"
@@ -52,18 +58,21 @@
# maximum number of calls to put in a single function
maxcalls=40
defentry=mercury__main_2_0
+init_opt=""
library_opt=""
extra_inits_opt=""
while true; do
case "$1" in
-c|--max-calls)
maxcalls="$2"; shift; shift;;
- -w|--entry-point)
- defentry="$2"; shift; shift;;
+ -i|--include-initialization-code)
+ init_opt="-i"; shift;;
-l|--library)
library_opt="-l"; shift;;
-l-|--no-library)
library_opt=""; shift;;
+ -w|--entry-point)
+ defentry="$2"; shift; shift;;
-x|--extra-inits)
extra_inits_opt="-x"; shift;;
-x-|--no-extra-inits)
@@ -83,10 +92,10 @@
done
case $# in
- 0) exec $MKINIT -w"$defentry" -c"$maxcalls" $library_opt \
- $extra_inits_opt $MERCURY_MOD_LIB_MODS
+ 0) exec $MKINIT -c"$maxcalls" $init_opt $library_opt \
+ -w"$defentry" $extra_inits_opt $MERCURY_MOD_LIB_MODS
;;
- *) exec $MKINIT -w"$defentry" -c"$maxcalls" $library_opt \
- $extra_inits_opt "$@" $MERCURY_MOD_LIB_MODS
+ *) exec $MKINIT -c"$maxcalls" $init_opt $library_opt \
+ -w"$defentry" $extra_inits_opt "$@" $MERCURY_MOD_LIB_MODS
;;
esac
Index: tests/debugger/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/Mmakefile,v
retrieving revision 1.5
diff -u -r1.5 Mmakefile
--- Mmakefile 1998/05/18 02:05:11 1.5
+++ Mmakefile 1998/06/24 10:45:42
@@ -14,6 +14,7 @@
queens
MCFLAGS = --trace all $(EXTRA_MCFLAGS)
+EXTRA_C2INITFLAGS = -i
# Not all grades can be used with stack layouts
#
Index: tests/debugger/debugger_regs_lib.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/debugger_regs_lib.exp,v
retrieving revision 1.1
diff -u -r1.1 debugger_regs_lib.exp
--- debugger_regs_lib.exp 1998/05/16 07:31:04 1.1
+++ debugger_regs_lib.exp 1998/06/25 06:27:19
@@ -2,14 +2,6 @@
mtrace> 2: 2 2 CALL DET debugger_regs_lib:data/41-0
mtrace> 3: 2 2 EXIT DET debugger_regs_lib:data/41-0
mtrace> HeadVar__1 [1, 2, 3, 4, 5]
- HeadVar__2 a0
- HeadVar__3 a1
- HeadVar__4 a2
- HeadVar__5 a3
- HeadVar__6 a4
- HeadVar__7 a5
- HeadVar__8 a6
- HeadVar__9 a7
HeadVar__10 a8
HeadVar__11 a9
HeadVar__12 b0
@@ -20,6 +12,7 @@
HeadVar__17 b5
HeadVar__18 b6
HeadVar__19 b7
+ HeadVar__2 a0
HeadVar__20 b8
HeadVar__21 b9
HeadVar__22 c0
@@ -30,6 +23,7 @@
HeadVar__27 c5
HeadVar__28 c6
HeadVar__29 c7
+ HeadVar__3 a1
HeadVar__30 c8
HeadVar__31 c9
HeadVar__32 d0
@@ -40,8 +34,14 @@
HeadVar__37 d5
HeadVar__38 d6
HeadVar__39 d7
+ HeadVar__4 a2
HeadVar__40 d8
HeadVar__41 d9
+ HeadVar__5 a3
+ HeadVar__6 a4
+ HeadVar__7 a5
+ HeadVar__8 a6
+ HeadVar__9 a7
mtrace> a0a1a2a3a4a5a6a7a8a9
b0b1b2b3b4b5b6b7b8b9
c0c1c2c3c4c5c6c7c8c9
Index: tests/debugger/debugger_regs_lib.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/debugger_regs_lib.inp,v
retrieving revision 1.1
diff -u -r1.1 debugger_regs_lib.inp
--- debugger_regs_lib.inp 1998/05/16 07:31:08 1.1
+++ debugger_regs_lib.inp 1998/06/25 06:26:14
@@ -1,4 +1,4 @@
-p
+p *
c
Index: tests/debugger/interpreter_lib.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/interpreter_lib.exp,v
retrieving revision 1.1
diff -u -r1.1 interpreter_lib.exp
--- interpreter_lib.exp 1998/05/16 07:31:15 1.1
+++ interpreter_lib.exp 1998/06/25 06:37:34
@@ -9,23 +9,36 @@
F: finish this call, printing the trace.
<N> g: go to event #N, not printing the trace.
<N> G: go to event #N, printing the trace.
-p: print the variables live at this point.
+v: list the names of the variables live at this point.
+l <n>: set ancestor level to <n>
+p <n>: print variable #n (or all vars if <n> is '*')
r: continue until forward execution is resumed.
[<N>] [s]: skip N events, not printing the trace (default: N=1).
[<N>] S: skip N events, printing the trace (default: N=1).
?: list all the breakpoints.
+ <N>: enable breakpoint #N.
- <N>: disable breakpoint #N.
-mtrace> mtrace> Pure Prolog Interpreter.
+mtrace> Pure Prolog Interpreter.
Consulting file `interpreter_lib.m'...
- 45: 20 4 CALL DET interpreter_lib:consult_until_eof/4-0
-mtrace> HeadVar__1 []
- HeadVar__3 state('<<c_pointer>>')
-mtrace> 47: 22 6 CALL DET parser:read_term/3-0
+ 46: 21 5 CALL DET term_io:read_term/3-0
+mtrace> 0 HeadVar__2
mtrace> HeadVar__2 state('<<c_pointer>>')
-mtrace> 13300: 22 6 EXIT DET parser:read_term/3-0
-mtrace> HeadVar__1 term(varset(0, empty, empty), functor(atom(":-"), [functor(atom("module"), [functor(atom("interpreter"), [], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22)))
- HeadVar__3 state('<<c_pointer>>')
-mtrace> 0: + interpreter_lib:consult_until_eof
-mtrace> mtrace> ?-
\ No newline at end of file
+mtrace> 0: + interpreter_lib:database_assert_clause
+mtrace> 13446: 5011 6 CALL DET interpreter_lib:database_assert_clause/4-0
+mtrace> HeadVar__1 []
+ HeadVar__2 varset(0, empty, empty)
+ HeadVar__3 functor(atom(":-"), [functor(atom("module"), [functor(atom("interpreter_lib"), [], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))
+mtrace> 13447: 5011 6 ELSE DET interpreter_lib:database_assert_clause/4-0 e;
+ 13448: 5012 7 CALL DET term:context_init/1-0
+ 13449: 5012 7 EXIT DET term:context_init/1-0
+ 13450: 5011 6 EXIT DET interpreter_lib:database_assert_clause/4-0
+mtrace> HeadVar__1 []
+ HeadVar__2 varset(0, empty, empty)
+ HeadVar__3 functor(atom(":-"), [functor(atom("module"), [functor(atom("interpreter_lib"), [], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))
+ HeadVar__4 [clause(varset(0, empty, empty), functor(atom(":-"), [functor(atom("module"), [functor(atom("interpreter_lib"), [], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22)), functor(atom("true"), [], context("", 0)))]
+mtrace> 13451: 5013 6 CALL DET interpreter_lib:consult_until_eof/4-0
+mtrace> 368828: 5013 6 EXIT DET interpreter_lib:consult_until_eof/4-0
+mtrace> 368829: 5010 5 EXIT DET interpreter_lib:consult_until_eof_2/5-0
+mtrace> 368830: 20 4 EXIT DET interpreter_lib:consult_until_eof/4-0
+mtrace> ?-
\ No newline at end of file
Index: tests/debugger/interpreter_lib.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/interpreter_lib.inp,v
retrieving revision 1.1
diff -u -r1.1 interpreter_lib.inp
--- interpreter_lib.inp 1998/05/16 07:31:19 1.1
+++ interpreter_lib.inp 1998/06/25 06:36:12
@@ -1,11 +1,14 @@
h
-b interpreter_lib consult_until_eof
+45s
+v
+p *
+b interpreter_lib database_assert_clause
c
-p
-2s
-p
+p *
+F
+p *
+
f
-p
-?
-- 0
+
+
c
Index: tests/debugger/queens_lib.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/queens_lib.exp,v
retrieving revision 1.1
diff -u -r1.1 queens_lib.exp
--- queens_lib.exp 1998/05/16 07:31:26 1.1
+++ queens_lib.exp 1998/06/25 06:27:48
@@ -1,7 +1,7 @@
1: 1 1 CALL CCMUL queens_lib:main/2-0
mtrace> HeadVar__1 state('<<c_pointer>>')
mtrace> 2: 2 2 CALL DET queens_lib:data/1-0
-mtrace> mtrace: no live variables
+mtrace> mtrace: there are no live variables
mtrace> 3: 2 2 EXIT DET queens_lib:data/1-0
mtrace> HeadVar__1 [1, 2, 3, 4, 5]
mtrace> 4: 3 2 CALL NON queens_lib:queen/2-0
@@ -14,12 +14,17 @@
mtrace> HeadVar__2 [1, 2, 3, 4, 5]
mtrace> 8: 5 4 DISJ NON queens_lib:qdelete/3-0 c2;d1;
mtrace> HeadVar__2 [1, 2, 3, 4, 5]
- V_11 1
V_10 [2, 3, 4, 5]
+ V_11 1
+mtrace> Ancestor level set to 1
+mtrace> HeadVar__1 [1, 2, 3, 4, 5]
+mtrace> Ancestor level set to 2
+mtrace> 0 HeadVar__1
+mtrace> HeadVar__1 [1, 2, 3, 4, 5]
mtrace> 9: 5 4 EXIT NON queens_lib:qdelete/3-0
mtrace> HeadVar__1 1
- HeadVar__3 [2, 3, 4, 5]
HeadVar__2 [1, 2, 3, 4, 5]
+ HeadVar__3 [2, 3, 4, 5]
mtrace> 10: 6 4 CALL NON queens_lib:qperm/2-0
mtrace> HeadVar__1 [2, 3, 4, 5]
mtrace> 11: 6 4 SWTC NON queens_lib:qperm/2-0 s1;
@@ -28,12 +33,12 @@
mtrace> HeadVar__2 [2, 3, 4, 5]
mtrace> 13: 7 5 DISJ NON queens_lib:qdelete/3-0 c2;d1;
mtrace> HeadVar__2 [2, 3, 4, 5]
- V_11 2
V_10 [3, 4, 5]
+ V_11 2
mtrace> 14: 7 5 EXIT NON queens_lib:qdelete/3-0
mtrace> HeadVar__1 2
- HeadVar__3 [3, 4, 5]
HeadVar__2 [2, 3, 4, 5]
+ HeadVar__3 [3, 4, 5]
mtrace> 15: 8 5 CALL NON queens_lib:qperm/2-0
mtrace> HeadVar__1 [3, 4, 5]
mtrace> 16: 8 5 SWTC NON queens_lib:qperm/2-0 s1;
@@ -42,12 +47,12 @@
mtrace> HeadVar__2 [3, 4, 5]
mtrace> 18: 9 6 DISJ NON queens_lib:qdelete/3-0 c2;d1;
mtrace> HeadVar__2 [3, 4, 5]
- V_11 3
V_10 [4, 5]
+ V_11 3
mtrace> 19: 9 6 EXIT NON queens_lib:qdelete/3-0
mtrace> HeadVar__1 3
- HeadVar__3 [4, 5]
HeadVar__2 [3, 4, 5]
+ HeadVar__3 [4, 5]
mtrace> 20: 10 6 CALL NON queens_lib:qperm/2-0
mtrace> HeadVar__1 [4, 5]
mtrace> 21: 10 6 SWTC NON queens_lib:qperm/2-0 s1;
@@ -56,12 +61,12 @@
mtrace> HeadVar__2 [4, 5]
mtrace> 23: 11 7 DISJ NON queens_lib:qdelete/3-0 c2;d1;
mtrace> HeadVar__2 [4, 5]
- V_11 4
V_10 [5]
+ V_11 4
mtrace> 24: 11 7 EXIT NON queens_lib:qdelete/3-0
mtrace> HeadVar__1 4
- HeadVar__3 [5]
HeadVar__2 [4, 5]
+ HeadVar__3 [5]
mtrace> 25: 12 7 CALL NON queens_lib:qperm/2-0
mtrace> HeadVar__1 [5]
mtrace> 26: 12 7 SWTC NON queens_lib:qperm/2-0 s1;
@@ -70,33 +75,33 @@
mtrace> HeadVar__2 [5]
mtrace> 28: 13 8 DISJ NON queens_lib:qdelete/3-0 c2;d1;
mtrace> HeadVar__2 [5]
- V_11 5
V_10 []
+ V_11 5
mtrace> 29: 13 8 EXIT NON queens_lib:qdelete/3-0
mtrace> HeadVar__1 5
- HeadVar__3 []
HeadVar__2 [5]
+ HeadVar__3 []
mtrace> 30: 14 8 CALL NON queens_lib:qperm/2-0
mtrace> HeadVar__1 []
mtrace> 31: 14 8 SWTC NON queens_lib:qperm/2-0 s2;
mtrace> mtrace> 32: 14 8 EXIT NON queens_lib:qperm/2-0
-mtrace> HeadVar__2 []
- HeadVar__1 []
+mtrace> HeadVar__1 []
+ HeadVar__2 []
mtrace> 33: 12 7 EXIT NON queens_lib:qperm/2-0
-mtrace> HeadVar__2 [5]
- HeadVar__1 [5]
+mtrace> HeadVar__1 [5]
+ HeadVar__2 [5]
mtrace> 34: 10 6 EXIT NON queens_lib:qperm/2-0
-mtrace> HeadVar__2 [4, 5]
- HeadVar__1 [4, 5]
+mtrace> HeadVar__1 [4, 5]
+ HeadVar__2 [4, 5]
mtrace> 35: 8 5 EXIT NON queens_lib:qperm/2-0
-mtrace> HeadVar__2 [3, 4, 5]
- HeadVar__1 [3, 4, 5]
+mtrace> HeadVar__1 [3, 4, 5]
+ HeadVar__2 [3, 4, 5]
mtrace> 36: 6 4 EXIT NON queens_lib:qperm/2-0
-mtrace> HeadVar__2 [2, 3, 4, 5]
- HeadVar__1 [2, 3, 4, 5]
+mtrace> HeadVar__1 [2, 3, 4, 5]
+ HeadVar__2 [2, 3, 4, 5]
mtrace> 37: 4 3 EXIT NON queens_lib:qperm/2-0
-mtrace> HeadVar__2 [1, 2, 3, 4, 5]
- HeadVar__1 [1, 2, 3, 4, 5]
+mtrace> HeadVar__1 [1, 2, 3, 4, 5]
+ HeadVar__2 [1, 2, 3, 4, 5]
mtrace> 38: 15 3 CALL SEMI queens_lib:safe/1-0
mtrace> HeadVar__1 [1, 2, 3, 4, 5]
mtrace> 39: 15 3 SWTC SEMI queens_lib:safe/1-0 s1;
Index: util/mkinit.c
===================================================================
RCS file: /home/mercury1/repository/mercury/util/mkinit.c,v
retrieving revision 1.33
diff -u -r1.33 mkinit.c
--- mkinit.c 1998/06/08 08:29:17 1.33
+++ mkinit.c 1998/06/25 06:15:01
@@ -43,6 +43,7 @@
static char **files;
static bool output_main_func = TRUE;
static bool c_files_contain_extra_inits = FALSE;
+static bool need_initialization_code = FALSE;
static int num_modules = 0;
static int num_errors = 0;
@@ -178,6 +179,12 @@
"}\n"
;
+
+static const char if_need_to_init[] =
+ "#if defined(MR_NEED_INITIALIZATION_CODE)\n\n"
+ ;
+
+
/* --- function prototypes --- */
static void parse_options(int argc, char *argv[]);
static void usage(void);
@@ -249,21 +256,25 @@
parse_options(int argc, char *argv[])
{
int c;
- while ((c = getopt(argc, argv, "c:w:lx")) != EOF) {
+ while ((c = getopt(argc, argv, "c:ilw:x")) != EOF) {
switch (c) {
case 'c':
if (sscanf(optarg, "%d", &maxcalls) != 1)
usage();
break;
- case 'w':
- entry_point = optarg;
+ case 'i':
+ need_initialization_code = TRUE;
break;
case 'l':
output_main_func = FALSE;
break;
+ case 'w':
+ entry_point = optarg;
+ break;
+
case 'x':
c_files_contain_extra_inits = TRUE;
break;
@@ -309,6 +320,10 @@
{
int filenum;
+ if (! need_initialization_code) {
+ fputs(if_need_to_init, stdout);
+ }
+
fputs("static void init_modules_0(void)\n", stdout);
fputs("{\n", stdout);
@@ -316,7 +331,10 @@
process_file(files[filenum]);
}
- fputs("}\n\n", stdout);
+ fputs("}\n", stdout);
+ if (! need_initialization_code) {
+ fputs("\n#endif\n\n", stdout);
+ }
}
static void
@@ -327,8 +345,16 @@
fputs("static void init_modules(void)\n", stdout);
fputs("{\n", stdout);
+ if (! need_initialization_code) {
+ fputs(if_need_to_init, stdout);
+ }
+
for (i = 0; i <= num_modules; i++) {
printf("\tinit_modules_%d();\n", i);
+ }
+
+ if (! need_initialization_code) {
+ fputs("\n#endif\n", stdout);
}
fputs("}\n", stdout);
New File: runtime/mercury_trace_permanent.c
===================================================================
/*
** 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.
*/
/*
** mercury_trace_permanent.c implements the interface between the main part
** of the runtime system (mainly mercury_wrapper.c) and the part of the
** tracing subsystem that has to be present even if no module in the program
** is compiled with execution tracing.
** are in mercury_trace_util.c.
**
** Main author: Zoltan Somogyi.
*/
#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_engine.h"
#include "mercury_wrapper.h"
#include "mercury_misc.h"
#include <stdio.h>
#include <unistd.h> /* for the write system call */
/*
** Do we want to use the debugger within this process, or do want to use
** the Opium-style trace analyzer debugger implemented by an external process.
** This variable is set in mercury_wrapper.c and never modified afterwards.
*/
MR_trace_type MR_trace_handler = MR_TRACE_INTERNAL;
/*
** Compiler generated tracing code will check whether MR_trace_enabled is true,
** before calling MR_trace. For now, and until we implement interface tracing,
** MR_trace_enabled should keep the same value throughout the execution of
** the entire program after being set in mercury_wrapper.c. There is one
** exception to this: the Mercury routines called as part of the functionality
** of the tracer itself (e.g. the term browser) should always be executed
** with MR_trace_enabled set to FALSE.
*/
bool MR_trace_enabled = FALSE;
/*
** MR_trace_call_seqno counts distinct calls. The prologue of every
** procedure assigns the current value of this counter as the sequence number
** of that invocation and increments the counter. This is the only way that
** MR_trace_call_seqno is modified.
**
** MR_trace_call_depth records the current depth of the call tree. The prologue
** of every procedure assigns the current value of this variable plus one
** as the depth of that invocation. Just before making a call, the caller
** will set MR_trace_call_depth to its own remembered depth value.
** These are the only ways in which MR_trace_call_depth is modified.
**
** Although neither MR_trace_call_seqno nor MR_trace_call_depth are used
** directly in this module, the seqno and depth arguments of MR_trace
** always derive their values from the saved values of these two global
** variables.
*/
Unsigned MR_trace_call_seqno = 0;
Unsigned MR_trace_call_depth = 0;
/*
** MR_trace_event_number is a simple counter of events. This is used in
** two places: here, for display to the user and for skipping a given number
** of events, and when printing an abort message, so that the programmer
** can zero in on the source of the problem more quickly.
*/
Unsigned MR_trace_event_number = 0;
/*
** MR_trace_from_full is a boolean that is set before every call;
** it states whether the caller is being fully traced, or only interface
** traced. If the called code is interface traced, it will generate
** call, exit and fail trace events only if MR_trace_from_full is true.
** (It will never generate internal events.) If the called code is fully
** traced, it will always generate all trace events, external and internal,
** regardless of the setting of this variable on entry.
**
** The initial value is set to TRUE to allow the programmer to gain
** control in the debugger when main/2 is called.
*/
Bool MR_trace_from_full = 1;
void
MR_trace_init(void)
{
#ifdef MR_USE_EXTERNAL_DEBUGGER
if (MR_trace_handler == MR_TRACE_EXTERNAL)
MR_trace_init_external(); /* should be in this module */
#endif
}
void
MR_trace_final(void)
{
#ifdef MR_USE_EXTERNAL_DEBUGGER
if (MR_trace_handler == MR_TRACE_EXTERNAL)
MR_trace_final_external(); /* should be in this module */
#endif
}
void
MR_trace_start(bool enabled)
{
MR_trace_event_number = 0;
MR_trace_call_seqno = 0;
MR_trace_call_depth = 0;
MR_trace_from_full = TRUE;
MR_trace_enabled = enabled;
}
void
MR_trace_end(void)
{
MR_trace_enabled = FALSE;
}
void
MR_trace_report(FILE *fp)
{
if (MR_trace_event_number > 0) {
/*
** This means that the executable was compiled with tracing,
** which implies that the user wants trace info on abort.
*/
fprintf(fp, "Last trace event was event #%ld.\n",
(long) MR_trace_event_number);
}
}
void
MR_trace_report_raw(int fd)
{
char buf[80]; /* that ought to be more than long enough */
if (MR_trace_event_number > 0) {
/*
** This means that the executable was compiled with tracing,
** which implies that the user wants trace info on abort.
*/
sprintf(buf, "Last trace event was event #%ld.\n",
(long) MR_trace_event_number);
write(fd, buf, strlen(buf));
}
}
New File: runtime/mercury_trace_permanent.h
===================================================================
/*
** 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.
*/
/*
** mercury_trace_permanent.h defines the interface between the main part
** of the runtime system (mainly mercury_wrapper.c) and the part of the
** tracing subsystem that has to be present even if no module in the program
** is compiled with execution tracing.
*/
#ifndef MERCURY_TRACE_PERMANENT_H
#define MERCURY_TRACE_PERMANENT_H
/*
** MR_trace_init() is called from mercury_runtime_init()
** when the debuggee programs begins, to perform any initialization
** that must be done before any traced Mercury code is executed.
** This includes the initialization code written in Mercury as well as main.
**
** MR_trace_start(enabled) is called from mercury_runtime_init()
** after the initialization code written in Mercury is executed,
** when we are about to start executing main. The argument says
** whether tracing is enabled for main (it is never enabled for
** initialization and finalization routines).
**
** MR_trace_end() is called from mercury_runtime_terminate() just
** after main has terminated and just before we call the finalization
** code written in Mercury.
**
** MR_trace_final() is called from mercury_runtime_terminate()
** after all Mercury code, including finalization code, has terminated.
*/
extern void MR_trace_init(void);
extern void MR_trace_start(bool enabled);
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.
*/
extern Word MR_trace_call_seqno;
extern Word MR_trace_call_depth;
typedef enum {
MR_TRACE_INTERNAL,
MR_TRACE_EXTERNAL
} MR_trace_type;
extern MR_trace_type MR_trace_handler;
extern bool MR_trace_enabled;
extern Unsigned MR_trace_event_number;
extern Bool MR_trace_from_full;
/*
** These functions will report the number of the last event,
** if there have been some events, and will do nothing otherwise.
*/
extern void MR_trace_report(FILE *fp);
extern void MR_trace_report_raw(int fd);
#endif /* MERCURY_TRACE_PERMANENT_H */
More information about the developers
mailing list