mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 14:57:03 +00:00
Estimated hours taken: 20 Branches: main Implement a large chunk of the code that was previously missing for .mmos grades. The system now correctly computes several answers for the tc_minimal test case, before going into an infinite loop (since the code for recognizing the absence of further solutions is not yet there). Significantly improve the infrastructure for debugging such changes. compiler/table_gen.m: Complete the mmos transformation. compiler/proc_gen.m: Handle the special return requirements of mmos generators, which must return not to a caller (since each generator is the root of its own SLD tree), but to a consumer in another SLD tree that is waiting for an answer. compiler/hlds_pred.m: Provide a mechanism whereby table_gen.m can communicate to proc_gen.m the requirement for this special return. compiler/trace_gen.m: When generating events, include the port and the goal path in a comment. This makes the generated C code significantly easier to understand. compiler/layout_out.m: Export a function for trace_gen.m to use. compiler/hlds_goal.m: Change goal_path_to_string to a function to make it easier to use. compiler/*.m: Conform to the change to goal_path_to_string. runtime/mercury_context.[ch]: In .mmos grades, include the current debugger call sequence number, depth, and event number in contexts, to be saved and loaded with the contexts. This allows each context to have its own separate sequence of events. This capability depends not directly on the grade, but on the macro MR_EXEC_TRACE_INFO_IN_CONTEXT. For now, this is defined only in .mmos grades, but in future, it may be useful in other grades as well. runtime/mercury_conf_param.h: Define and document MR_EXEC_TRACE_INFO_IN_CONTEXT. runtime/mercury_mm_own_stacks.[ch]: runtime/mercury_tabling_preds.h: Implement some predicates needed by the own stack transformation. Implement the code for generators returning answers to consumers, and the code for consumers scheduling generators when they need more answers. At the moment, the code for detecting when generators depend on each other is not yet written. Provide better facilities for debugging own stack minimal model grades. Fix a cut-and-paste bug (wrong macro name guarding the handwritten C module). runtime/Mmakefile: Rebuild only what needs to be rebuilt when mercury_tabling_preds.h changes. runtime/mercury_label.[ch]: Add a utility function for returning the name of an arbitrary label (internal or entry). Rename some fields to give them MR_ prefixes. Always define the functions for recording both entry and internal labels, even if they are not called from most modules, since they may be called from a few handwritten modules in the runtime. Rename a function to avoid a clash with the name of a macro, and thus allow the change to mercury_goto.h. runtime/mercury_goto.h: Fix a bug with MR_init_entry_an. This macro was supposed to always insert the entry label that is its argument into the entry table, but instead of calling the function it was meant to call, it called a macro that could be (and usually way) defined to expand to nothing. The fix is to call the function a different name than the macro, and to call the function, not the macro. runtime/mercury_wrapper.c: In own stack minimal model grades, create a main context separate from the current context, since the current context may be needed to hold a generator's state. Make MR_eng_this_context point to this context. Register all labels in the debugging variants of minimal model grades. runtime/mercury_accurate_gc.c: runtime/mercury_agc_debug.c: runtime/mercury_debug.c: library/exception.m: Conform to the change to runtime/mercury_label.h. runtime/mercury_stack_trace.c: Conform to the change to runtime/mercury_label.h. Document the link to trace/mercury_trace_internal.c. trace/mercury_trace.[ch]: trace/mercury_trace_cmd_forward.c: Split the GOTO command into two: STEP and GOTO. STEP always stops at the next event (without any test), even if it is in a different context (and possibly with a lower event number than the immediately previous event, since the event numbers in different contexts are not related). As before, GOTO always goes to the specified event number, but in .dmmos grades it can now be told that this event number should be matched only in a specified context. The specification is done by an extra argument specifying the short name of the context's generator; the ansence of such an argument means the main context. trace/mercury_trace_cmd_internal.c: In own stack grades, when the current context is that of a generator, print the subgoal the generator is working on before the event number, call depth, call sequence number and the rest of the event report. Document the link to runtime/mercury_stack_trace.c, which has similar code. trace/mercury_trace_cmd_external.c: trace/mercury_trace_cmd_declararive.c: Use the STEP command where GOTO was used for this simpler job, since this is (very slightly) faster. trace/mercury_trace_cmd_developer.c: Fix some bugs with handling own stack tables. doc/user_guide.texi: Document the new functionality of the goto mdb command. The documentation is commented out, since .mmos grades are for developers only at the moment. tools/lmc.in: Turn off C optimizations when C debugging is enabled. For some reason, the default value of --cflags-for-debug does not include -O0.
1271 lines
32 KiB
C
1271 lines
32 KiB
C
/*
|
|
** vim: ts=4 sw=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 1996-2007 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_dlist.h"
|
|
#include "mercury_regs.h"
|
|
#include "mercury_trace_base.h"
|
|
#include "mercury_label.h"
|
|
#include "mercury_debug.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
static MR_bool MR_find_zone_for_det_ptr_in_context(const MR_Word *ptr,
|
|
MR_Context *ctxt,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr);
|
|
static MR_bool MR_find_zone_for_nondet_ptr_in_context(const MR_Word *ptr,
|
|
MR_Context *ctxt,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr);
|
|
static MR_bool MR_find_zone_for_det_ptr(const MR_Word *ptr,
|
|
MR_Context **ctxt_ptr,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr);
|
|
static MR_bool MR_find_zone_for_nondet_ptr(const MR_Word *ptr,
|
|
MR_Context **ctxt_ptr,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr);
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
static void MR_check_watch_csd_start(MR_Code *proc);
|
|
static MR_bool MR_csds_are_different(const MR_CallSiteDynamic *csd1,
|
|
const MR_CallSiteDynamic *csd2);
|
|
static void MR_assign_csd(MR_CallSiteDynamic *csd1,
|
|
const MR_CallSiteDynamic *csd2);
|
|
#endif
|
|
|
|
static void MR_count_call(FILE *fp, const MR_Code *proc);
|
|
static void MR_print_ordinary_regs(FILE *fp);
|
|
static void MR_do_watches(FILE *fp);
|
|
static MR_bool MR_proc_matches_name(const MR_Code *proc, const char *name);
|
|
|
|
#ifdef MR_LOWLEVEL_ADDR_DEBUG
|
|
#define MR_PRINT_RAW_ADDRS MR_TRUE
|
|
#else
|
|
#define MR_PRINT_RAW_ADDRS MR_FALSE
|
|
#endif
|
|
|
|
static MR_bool MR_print_raw_addrs = MR_PRINT_RAW_ADDRS;
|
|
|
|
/* debugging messages */
|
|
|
|
#ifdef MR_DEBUG_HEAP_ALLOC
|
|
|
|
void
|
|
MR_unravel_univ_msg(FILE *fp, MR_Word univ, MR_TypeInfo type_info,
|
|
MR_Word value)
|
|
{
|
|
if (MR_lld_print_enabled && MR_heapdebug) {
|
|
fprintf(fp, "unravel univ %p: typeinfo %p, value %p\n",
|
|
(void *) univ, (void *) type_info, (void *) value);
|
|
fflush(fp);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_new_univ_on_hp_msg(FILE *fp, MR_Word univ, MR_TypeInfo type_info,
|
|
MR_Word value)
|
|
{
|
|
if (MR_lld_print_enabled && MR_heapdebug) {
|
|
fprintf(fp"new univ on hp: typeinfo %p, value %p => %p\n",
|
|
(void *) type_info, (void *) value, (void *) univ);
|
|
fflush(fp);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_debug_tag_offset_incr_hp_base_msg(FILE *fp, MR_Word ptr,
|
|
int tag, int offset, int count, int is_atomic)
|
|
{
|
|
if (MR_lld_print_enabled && MR_heapdebug) {
|
|
fprintf(fp, "tag_offset_incr_hp: "
|
|
"tag %d, offset %d, count %d%s => %p\n",
|
|
tag, offset, count, (is_atomic ? ", atomic" : ""), (void *) ptr);
|
|
fflush(fp);
|
|
}
|
|
}
|
|
|
|
#endif /* MR_DEBUG_HEAP_ALLOC */
|
|
|
|
#ifdef MR_LOWLEVEL_DEBUG
|
|
|
|
void
|
|
MR_mkframe_msg(FILE *fp, const char *predname)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nnew choice point for procedure %s\n", predname);
|
|
fprintf(fp, "new fr: ");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "prev fr: ");
|
|
MR_printnondetstack(fp, MR_prevfr_slot(MR_curfr));
|
|
fprintf(fp, "succ fr: ");
|
|
MR_printnondetstack(fp, MR_succfr_slot(MR_curfr));
|
|
fprintf(fp, "succ ip: ");
|
|
MR_printlabel(fp, MR_succip_slot(MR_curfr));
|
|
fprintf(fp, "redo fr: ");
|
|
MR_printnondetstack(fp, MR_redofr_slot(MR_curfr));
|
|
fprintf(fp, "redo ip: ");
|
|
MR_printlabel(fp, MR_redoip_slot(MR_curfr));
|
|
#ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
|
|
fprintf(fp, "det fr: ");
|
|
MR_printdetstack(fp, MR_table_detfr_slot(MR_curfr));
|
|
#endif
|
|
|
|
if (MR_detaildebug) {
|
|
MR_dumpnondetstack(fp);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_mktempframe_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nnew temp nondet frame\n");
|
|
fprintf(fp, "new fr: ");
|
|
MR_printnondetstack(fp, MR_maxfr);
|
|
fprintf(fp, "prev fr: ");
|
|
MR_printnondetstack(fp, MR_prevfr_slot(MR_maxfr));
|
|
fprintf(fp, "redo fr: ");
|
|
MR_printnondetstack(fp, MR_redofr_slot(MR_maxfr));
|
|
fprintf(fp, "redo ip: ");
|
|
MR_printlabel(fp, MR_redoip_slot(MR_maxfr));
|
|
|
|
if (MR_detaildebug) {
|
|
MR_dumpnondetstack(fp);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_mkdettempframe_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nnew det temp nondet frame\n");
|
|
fprintf(fp, "new fr: ");
|
|
MR_printnondetstack(fp, MR_maxfr);
|
|
fprintf(fp, "prev fr: ");
|
|
MR_printnondetstack(fp, MR_prevfr_slot(MR_maxfr));
|
|
fprintf(fp, "redo fr: ");
|
|
MR_printnondetstack(fp, MR_redofr_slot(MR_maxfr));
|
|
fprintf(fp, "redo ip: ");
|
|
MR_printlabel(fp, MR_redoip_slot(MR_maxfr));
|
|
fprintf(fp, "det fr: ");
|
|
MR_printdetstack(fp, MR_tmp_detfr_slot(MR_maxfr));
|
|
|
|
if (MR_detaildebug) {
|
|
MR_dumpnondetstack(fp);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_succeed_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nsucceeding from procedure\n");
|
|
fprintf(fp, "curr fr: ");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "succ fr: ");
|
|
MR_printnondetstack(fp, MR_succfr_slot(MR_curfr));
|
|
fprintf(fp, "succ ip: ");
|
|
MR_printlabel(fp, MR_succip_slot(MR_curfr));
|
|
|
|
if (MR_detaildebug) {
|
|
MR_printregs(fp, "registers at success");
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_succeeddiscard_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nsucceeding from procedure\n");
|
|
fprintf(fp, "curr fr: ");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "succ fr: ");
|
|
MR_printnondetstack(fp, MR_succfr_slot(MR_curfr));
|
|
fprintf(fp, "succ ip: ");
|
|
MR_printlabel(fp, MR_succip_slot(MR_curfr));
|
|
|
|
if (MR_detaildebug) {
|
|
MR_printregs(fp, "registers at success");
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_fail_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nfailing from procedure\n");
|
|
fprintf(fp, "curr fr: ");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "fail fr: ");
|
|
MR_printnondetstack(fp, MR_prevfr_slot(MR_curfr));
|
|
fprintf(fp, "fail ip: ");
|
|
MR_printlabel(fp, MR_redoip_slot(MR_prevfr_slot(MR_curfr)));
|
|
}
|
|
|
|
void
|
|
MR_redo_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nredo from procedure\n");
|
|
fprintf(fp, "curr fr: ");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "redo fr: ");
|
|
MR_printnondetstack(fp, MR_maxfr);
|
|
fprintf(fp, "redo ip: ");
|
|
MR_printlabel(fp, MR_redoip_slot(MR_maxfr));
|
|
}
|
|
|
|
void
|
|
MR_call_msg(FILE *fp, const MR_Code *proc, const MR_Code *succ_cont)
|
|
{
|
|
MR_count_call(fp, proc);
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_check_watch_csd_start(proc);
|
|
#endif /* MR_DEEP_PROFILING */
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\ncall %lu: ", MR_lld_cur_call);
|
|
MR_printlabel(fp, proc);
|
|
fprintf(fp, "cont ");
|
|
MR_printlabel(fp, succ_cont);
|
|
|
|
if (MR_anyregdebug) {
|
|
MR_printregs(fp, "at call:");
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_print_deep_prof_vars(fp, "MR_call_msg");
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_tailcall_msg(FILE *fp, const MR_Code *proc)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
MR_count_call(fp, proc);
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_check_watch_csd_start(proc);
|
|
#endif /* MR_DEEP_PROFILING */
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\ntail call %lu: ", MR_lld_cur_call);
|
|
MR_printlabel(fp, proc);
|
|
fprintf(fp, "cont ");
|
|
MR_printlabel(fp, MR_succip);
|
|
|
|
if (MR_anyregdebug) {
|
|
MR_printregs(fp, "at tailcall:");
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_print_deep_prof_vars(fp, "MR_tailcall_msg");
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_proceed_msg(FILE *fp)
|
|
{
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nreturning from determinate procedure\n");
|
|
if (MR_anyregdebug) {
|
|
MR_printregs(fp, "at proceed:");
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_print_deep_prof_vars(fp, "MR_proceed_msg");
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_cr1_msg(FILE *fp, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MR_RECORD_TERM_SIZES
|
|
fprintf(fp, "create1: put size %ld, value %9lx at ",
|
|
(long) (MR_Integer) addr[-2],
|
|
(long) (MR_Integer) addr[-1]);
|
|
#else
|
|
fprintf(fp, "create1: put value %9lx at ",
|
|
(long) (MR_Integer) addr[-1]);
|
|
#endif
|
|
MR_printheap(fp, addr);
|
|
}
|
|
|
|
void
|
|
MR_cr2_msg(FILE *fp, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MR_RECORD_TERM_SIZES
|
|
fprintf(fp, "create2: put size %ld, values %9lx,%9lx at ",
|
|
(long) (MR_Integer) addr[-3],
|
|
(long) (MR_Integer) addr[-2],
|
|
(long) (MR_Integer) addr[-1]);
|
|
#else
|
|
fprintf(fp, "create2: put values %9lx,%9lx at ",
|
|
(long) (MR_Integer) addr[-2],
|
|
(long) (MR_Integer) addr[-1]);
|
|
#endif
|
|
MR_printheap(fp, addr);
|
|
}
|
|
|
|
void
|
|
MR_cr3_msg(FILE *fp, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MR_RECORD_TERM_SIZES
|
|
fprintf(fp, "create3: put size %ld, values %9lx,%9lx,%9lx at ",
|
|
(long) (MR_Integer) addr[-4],
|
|
(long) (MR_Integer) addr[-3],
|
|
(long) (MR_Integer) addr[-2],
|
|
(long) (MR_Integer) addr[-1]);
|
|
#else
|
|
fprintf(fp, "create3: put values %9lx,%9lx,%9lx at ",
|
|
(long) (MR_Integer) addr[-3],
|
|
(long) (MR_Integer) addr[-2],
|
|
(long) (MR_Integer) addr[-1]);
|
|
#endif
|
|
MR_printheap(fp, addr);
|
|
}
|
|
|
|
void
|
|
MR_incr_hp_debug_msg(FILE *fp, MR_Word val, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MR_CONSERVATIVE_GC
|
|
fprintf(fp, "allocated %ld words at %p\n", (long) val, addr);
|
|
#else
|
|
fprintf(fp, "increment hp by %ld from ", (long) (MR_Integer) val);
|
|
MR_printheap(fp, addr);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_incr_sp_msg(FILE *fp, MR_Word val, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "increment sp by %ld from ", (long) (MR_Integer) val);
|
|
MR_printdetstack(fp, addr);
|
|
}
|
|
|
|
void
|
|
MR_decr_sp_msg(FILE *fp, MR_Word val, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "decrement sp by %ld from ", (long) (MR_Integer) val);
|
|
MR_printdetstack(fp, addr);
|
|
}
|
|
|
|
#endif /* defined(MR_LOWLEVEL_DEBUG) */
|
|
|
|
#ifdef MR_DEBUG_GOTOS
|
|
|
|
void
|
|
MR_goto_msg(FILE *fp, const MR_Code *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
if (addr == NULL) {
|
|
fprintf(fp, "\ngoto NULL\n");
|
|
MR_fatal_error("MR_goto_msg: NULL");
|
|
}
|
|
|
|
fprintf(fp, "\ngoto ");
|
|
MR_printlabel(fp, addr);
|
|
}
|
|
|
|
void
|
|
MR_reg_msg(FILE *fp)
|
|
{
|
|
int i;
|
|
MR_Integer x;
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
for(i=1; i<=8; i++) {
|
|
x = (MR_Integer) MR_get_reg(i);
|
|
#ifndef MR_CONSERVATIVE_GC
|
|
if ((MR_Integer) MR_ENGINE(MR_eng_heap_zone)->MR_zone_min <= x
|
|
&& x < (MR_Integer) MR_ENGINE(MR_eng_heap_zone)->MR_zone_top)
|
|
{
|
|
x -= (MR_Integer) MR_ENGINE(MR_eng_heap_zone)->MR_zone_min;
|
|
}
|
|
#endif
|
|
fprintf(fp, "%8lx ", (long) x);
|
|
}
|
|
fprintf(fp, "\n");
|
|
}
|
|
|
|
#endif /* defined(MR_DEBUG_GOTOS) */
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
#ifdef MR_LOWLEVEL_DEBUG
|
|
|
|
/* debugging printing tools */
|
|
|
|
static void
|
|
MR_count_call(FILE *fp, const MR_Code *proc)
|
|
{
|
|
MR_lld_cur_call++;
|
|
if (!MR_lld_print_region_enabled) {
|
|
if (MR_lld_cur_call == MR_lld_print_min) {
|
|
MR_lld_print_region_enabled = MR_TRUE;
|
|
fprintf(fp, "entering printed region\n");
|
|
fprintf(fp, "min %lu, max %lu, more <%s>\n",
|
|
MR_lld_print_min, MR_lld_print_max,
|
|
MR_lld_print_more_min_max);
|
|
}
|
|
} else {
|
|
if (MR_lld_cur_call == MR_lld_print_max) {
|
|
MR_lld_print_region_enabled = MR_FALSE;
|
|
MR_setup_call_intervals(&MR_lld_print_more_min_max,
|
|
&MR_lld_print_min, &MR_lld_print_max);
|
|
fprintf(fp, "leaving printed region\n");
|
|
fprintf(fp, "min %lu, max %lu, more <%s>\n",
|
|
MR_lld_print_min, MR_lld_print_max,
|
|
MR_lld_print_more_min_max);
|
|
}
|
|
}
|
|
|
|
if (MR_proc_matches_name(proc, MR_lld_start_name)) {
|
|
MR_lld_print_name_enabled = MR_TRUE;
|
|
MR_lld_start_until = MR_lld_cur_call + MR_lld_start_block;
|
|
fprintf(fp, "entering printed name block %s\n", MR_lld_start_name);
|
|
} else if (MR_lld_cur_call == MR_lld_start_until) {
|
|
MR_lld_print_name_enabled = MR_FALSE;
|
|
fprintf(fp, "leaving printed name block\n");
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
if (MR_watch_csd_addr == MR_next_call_site_dynamic
|
|
&& MR_watch_csd_addr != NULL)
|
|
{
|
|
MR_lld_print_csd_enabled = MR_TRUE;
|
|
MR_lld_csd_until = MR_lld_cur_call + MR_lld_start_block;
|
|
MR_watch_csd_started = MR_TRUE;
|
|
fprintf(fp, "entering printed csd block %p\n", MR_watch_csd_addr);
|
|
} else if (MR_lld_cur_call == MR_lld_csd_until) {
|
|
MR_lld_print_csd_enabled = MR_FALSE;
|
|
fprintf(fp, "leaving printed csd block\n");
|
|
}
|
|
#endif
|
|
|
|
/* the bitwise ORs implement logical OR */
|
|
MR_lld_print_enabled = MR_lld_print_region_enabled
|
|
| MR_lld_print_name_enabled | MR_lld_print_csd_enabled
|
|
| MR_lld_debug_enabled;
|
|
}
|
|
|
|
void
|
|
MR_printint(FILE *fp, MR_Word n)
|
|
{
|
|
fprintf(fp, "int %ld\n", (long) (MR_Integer) n);
|
|
}
|
|
|
|
void
|
|
MR_printstring(FILE *fp, const char *s)
|
|
{
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, "string %p %s\n", (const void *) s, s);
|
|
} else {
|
|
fprintf(fp, "string %s\n", s);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_printheap(FILE *fp, const MR_Word *h)
|
|
{
|
|
#ifndef MR_CONSERVATIVE_GC
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, "ptr %p, ", (const void *) h);
|
|
}
|
|
|
|
fprintf(fp, "offset %3ld words\n",
|
|
(long) (MR_Integer) (h - MR_ENGINE(MR_eng_heap_zone)->min));
|
|
#else
|
|
fprintf(fp, "ptr %p\n", (const void *) h);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_dumpframe(FILE *fp, const MR_Word *fr)
|
|
{
|
|
int i;
|
|
|
|
fprintf(fp, "frame at ");
|
|
MR_printnondetstack(fp, fr),
|
|
fprintf(fp, "\n");
|
|
fprintf(fp, "\t succip ");
|
|
MR_printlabel(fp, MR_succip_slot(fr));
|
|
fprintf(fp, "\t redoip ");
|
|
MR_printlabel(fp, MR_redoip_slot(fr));
|
|
fprintf(fp, "\t succfr ");
|
|
MR_printnondetstack(fp, MR_succfr_slot(fr));
|
|
fprintf(fp, "\t prevfr ");
|
|
MR_printnondetstack(fp, MR_prevfr_slot(fr));
|
|
|
|
for (i = 1; &MR_based_framevar(fr,i) > MR_prevfr_slot(fr); i++) {
|
|
fprintf(fp, "\t framevar(%d) %ld 0x%lx\n",
|
|
i, (long) (MR_Integer) MR_based_framevar(fr,i),
|
|
(unsigned long) MR_based_framevar(fr,i));
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_dumpnondetstack(FILE *fp)
|
|
{
|
|
MR_Word *fr;
|
|
|
|
fprintf(fp, "\nnondetstack dump\n");
|
|
for (fr = MR_maxfr; fr > MR_nondet_stack_trace_bottom;
|
|
fr = MR_prevfr_slot(fr))
|
|
{
|
|
MR_dumpframe(fp, fr);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_printframe(FILE *fp, const char *msg)
|
|
{
|
|
fprintf(fp, "\n%s\n", msg);
|
|
MR_dumpframe(fp, MR_curfr);
|
|
|
|
MR_print_ordinary_regs(fp);
|
|
}
|
|
|
|
void
|
|
MR_printregs(FILE *fp, const char *msg)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
fprintf(fp, "\n%s\n", msg);
|
|
|
|
if (MR_sregdebug) {
|
|
fprintf(fp, "%-9s", "succip:");
|
|
MR_printlabel(fp, MR_succip);
|
|
fprintf(fp, "%-9s", "curfr:");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "%-9s", "maxfr:");
|
|
MR_printnondetstack(fp, MR_maxfr);
|
|
fprintf(fp, "%-9s", "hp:");
|
|
MR_printheap(fp, MR_hp);
|
|
fprintf(fp, "%-9s", "sp:");
|
|
MR_printdetstack(fp, MR_sp);
|
|
}
|
|
|
|
if (MR_ordregdebug) {
|
|
MR_print_ordinary_regs(fp);
|
|
}
|
|
}
|
|
|
|
static void
|
|
MR_print_ordinary_regs(FILE *fp)
|
|
{
|
|
int i;
|
|
MR_Integer value;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
fprintf(fp, "r%d: ", i + 1);
|
|
value = (MR_Integer) MR_get_reg(i+1);
|
|
|
|
#ifndef MR_CONSERVATIVE_GC
|
|
if ((MR_Integer) MR_ENGINE(MR_eng_heap_zone)->min <= value
|
|
&& value < (MR_Integer) MR_ENGINE(MR_eng_heap_zone)->top)
|
|
{
|
|
fprintf(fp, "(heap) ");
|
|
}
|
|
#endif
|
|
|
|
fprintf(fp, "%ld %lx\n", (long) value, (long) value);
|
|
}
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
|
|
static struct MR_CallSiteDynamic_Struct MR_watched_csd_last_value =
|
|
{
|
|
/* MR_csd_callee_ptr */ NULL,
|
|
{
|
|
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
/* MR_own_calls */ 0,
|
|
#else
|
|
/* calls are computed from the other fields */
|
|
#endif
|
|
/* MR_own_exits */ 0,
|
|
/* MR_own_fails */ 0,
|
|
/* MR_own_redos */ 0,
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
/* MR_own_quanta */ 0,
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_CALL_SEQ
|
|
/* MR_own_call_seqs */ 0,
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_MEMORY
|
|
/* MR_own_allocs */ 0,
|
|
/* MR_own_words */ 0,
|
|
#endif
|
|
},
|
|
/* MR_csd_depth_count */ 0
|
|
};
|
|
|
|
static void
|
|
MR_check_watch_csd_start(MR_Code *proc)
|
|
{
|
|
#if 0
|
|
if (MR_watch_csd_start_name == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (MR_proc_matches_name(proc, MR_watch_csd_start_name)) {
|
|
if (MR_watch_csd_addr == MR_next_call_site_dynamic) {
|
|
/*
|
|
** Optimize future checks and make MR_watch_csd_addr static.
|
|
*/
|
|
MR_watch_csd_started = MR_TRUE;
|
|
MR_watch_csd_start_name = NULL;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static MR_bool
|
|
MR_csds_are_different(const MR_CallSiteDynamic *csd1,
|
|
const MR_CallSiteDynamic *csd2)
|
|
{
|
|
const MR_ProfilingMetrics *pm1;
|
|
const MR_ProfilingMetrics *pm2;
|
|
|
|
if (csd1->MR_csd_callee_ptr != csd2->MR_csd_callee_ptr) {
|
|
return MR_TRUE;
|
|
}
|
|
|
|
pm1 = &csd1->MR_csd_own;
|
|
pm2 = &csd2->MR_csd_own;
|
|
|
|
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
if (pm1->MR_own_calls != pm2->MR_own_calls) {
|
|
return MR_TRUE;
|
|
}
|
|
#endif
|
|
if (pm1->MR_own_exits != pm2->MR_own_exits) {
|
|
return MR_TRUE;
|
|
}
|
|
if (pm1->MR_own_fails != pm2->MR_own_fails) {
|
|
return MR_TRUE;
|
|
}
|
|
if (pm1->MR_own_redos != pm2->MR_own_redos) {
|
|
return MR_TRUE;
|
|
}
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
if (pm1->MR_own_quanta != pm2->MR_own_quanta) {
|
|
return MR_TRUE;
|
|
}
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_CALL_SEQ
|
|
if (pm1->MR_own_call_seqs != pm2->MR_own_call_seqs) {
|
|
return MR_TRUE;
|
|
}
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_MEMORY
|
|
if (pm1->MR_own_allocs != pm2->MR_own_allocs) {
|
|
return MR_TRUE;
|
|
}
|
|
if (pm1->MR_own_words != pm2->MR_own_words) {
|
|
return MR_TRUE;
|
|
}
|
|
#endif
|
|
|
|
if (csd1->MR_csd_depth_count != csd2->MR_csd_depth_count) {
|
|
return MR_TRUE;
|
|
}
|
|
|
|
return MR_FALSE;
|
|
};
|
|
|
|
static void
|
|
MR_assign_csd(MR_CallSiteDynamic *csd1, const MR_CallSiteDynamic *csd2)
|
|
{
|
|
csd1->MR_csd_callee_ptr = csd2->MR_csd_callee_ptr;
|
|
|
|
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
csd1->MR_csd_own.MR_own_calls = csd2->MR_csd_own.MR_own_calls;
|
|
#endif
|
|
csd1->MR_csd_own.MR_own_exits = csd2->MR_csd_own.MR_own_exits;
|
|
csd1->MR_csd_own.MR_own_fails = csd2->MR_csd_own.MR_own_fails;
|
|
csd1->MR_csd_own.MR_own_redos = csd2->MR_csd_own.MR_own_redos;
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
csd1->MR_csd_own.MR_own_quanta = csd2->MR_csd_own.MR_own_quanta;
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_CALL_SEQ
|
|
csd1->MR_csd_own.MR_own_call_seqs = csd2->MR_csd_own.MR_own_call_seqs;
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_MEMORY
|
|
csd1->MR_csd_own.MR_own_allocs = csd2->MR_csd_own.MR_own_allocs;
|
|
csd1->MR_csd_own.MR_own_words = csd2->MR_csd_own.MR_own_words;
|
|
#endif
|
|
|
|
csd1->MR_csd_depth_count = csd2->MR_csd_depth_count;
|
|
};
|
|
|
|
#endif /* MR_DEEP_PROFILING */
|
|
|
|
static void
|
|
MR_do_watches(FILE *fp)
|
|
{
|
|
if (MR_watch_addr != NULL) {
|
|
fprintf(fp, "watch addr %p: 0x%lx %ld\n", MR_watch_addr,
|
|
(long) *MR_watch_addr, (long) *MR_watch_addr);
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
if (MR_watch_csd_addr != NULL) {
|
|
if (MR_watch_csd_started) {
|
|
if (MR_csds_are_different(&MR_watched_csd_last_value,
|
|
MR_watch_csd_addr))
|
|
{
|
|
MR_assign_csd(&MR_watched_csd_last_value, MR_watch_csd_addr);
|
|
fprintf(fp, "current call: %lu\n", MR_lld_cur_call);
|
|
MR_print_deep_prof_var(fp, "watch_csd", MR_watch_csd_addr);
|
|
}
|
|
}
|
|
}
|
|
#endif /* MR_DEEP_PROFILING */
|
|
}
|
|
|
|
static MR_bool
|
|
MR_proc_matches_name(const MR_Code *proc, const char *name)
|
|
{
|
|
#ifdef MR_NEED_ENTRY_LABEL_ARRAY
|
|
MR_Entry *entry;
|
|
|
|
entry = MR_prev_entry_by_addr(proc);
|
|
if (entry != NULL && entry->MR_entry_addr == proc
|
|
&& entry->MR_entry_name != NULL)
|
|
{
|
|
if (MR_streq(entry->MR_entry_name, name)) {
|
|
return MR_TRUE;
|
|
}
|
|
}
|
|
|
|
#endif /* MR_NEED_ENTRY_LABEL_ARRAY */
|
|
return MR_FALSE;
|
|
}
|
|
|
|
#endif /* defined(MR_DEBUG_GOTOS) */
|
|
|
|
#ifndef MR_HIGHLEVEL_CODE
|
|
|
|
void
|
|
MR_print_detstackptr(FILE *fp, const MR_Word *s)
|
|
{
|
|
MR_MemoryZone *zone;
|
|
int zone_num;
|
|
|
|
if (MR_find_zone_for_det_ptr(s, NULL, &zone, &zone_num)) {
|
|
if (zone_num == 0) {
|
|
fprintf(fp, "det %3ld",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min));
|
|
} else {
|
|
fprintf(fp, "det %3ld, segment %d",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min), zone_num);
|
|
}
|
|
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, " (%p)", (const void *) s);
|
|
}
|
|
} else {
|
|
fprintf(fp, "det raw %p", (const void *) s);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_printdetstack(FILE *fp, const MR_Word *s)
|
|
{
|
|
MR_MemoryZone *zone;
|
|
int zone_num;
|
|
|
|
if (MR_find_zone_for_det_ptr(s, NULL, &zone, &zone_num)) {
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, "ptr %p, ", (const void *) s);
|
|
}
|
|
|
|
if (zone_num == 0) {
|
|
fprintf(fp, "offset %3ld words",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min));
|
|
} else {
|
|
fprintf(fp, "offset %3ld words in segment %d",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min), zone_num);
|
|
}
|
|
} else {
|
|
fprintf(fp, "raw ptr %p", (const void *) s);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_print_nondetstackptr(FILE *fp, const MR_Word *s)
|
|
{
|
|
MR_MemoryZone *zone;
|
|
int zone_num;
|
|
|
|
if (MR_find_zone_for_nondet_ptr(s, NULL, &zone, &zone_num)) {
|
|
if (zone_num == 0) {
|
|
fprintf(fp, "non %3ld",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min));
|
|
} else {
|
|
fprintf(fp, "non %3ld, segment %d",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min), zone_num);
|
|
}
|
|
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, " (%p)", (const void *) s);
|
|
}
|
|
} else {
|
|
fprintf(fp, "non raw %p", (const void *) s);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_printnondetstack(FILE *fp, const MR_Word *s)
|
|
{
|
|
MR_MemoryZone *zone;
|
|
int zone_num;
|
|
|
|
if (MR_find_zone_for_nondet_ptr(s, NULL, &zone, &zone_num)) {
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, "ptr %p, ", (const void *) s);
|
|
}
|
|
|
|
if (zone_num == 0) {
|
|
fprintf(fp, "offset %3ld words",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min));
|
|
} else {
|
|
fprintf(fp, "offset %3ld words in segment %d",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min), zone_num);
|
|
}
|
|
} else {
|
|
fprintf(fp, "raw ptr %p", (const void *) s);
|
|
}
|
|
}
|
|
|
|
#endif /* !MR_HIGHLEVEL_CODE */
|
|
|
|
void
|
|
MR_print_heapptr(FILE *fp, const MR_Word *s)
|
|
{
|
|
#ifdef MR_CONSERVATIVE_GC
|
|
fprintf(fp, "heap %ld", (long) s);
|
|
#else
|
|
fprintf(fp, "heap %3ld",
|
|
(long) (MR_Integer) (s - MR_ENGINE(MR_eng_heap_zone)->MR_zone_min));
|
|
#endif
|
|
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, " (%p)", (const void *) s);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** The code of MR_print_label is similar to, but significantly more powerful
|
|
** than, MR_lookup_entry_or_internal in mercury_label.c, since it does not
|
|
** have to return a single short constant string.
|
|
*/
|
|
|
|
void
|
|
MR_print_label(FILE *fp, const MR_Code *w)
|
|
{
|
|
MR_Internal *internal;
|
|
|
|
internal = MR_lookup_internal_by_addr(w);
|
|
if (internal != NULL) {
|
|
if (internal->MR_internal_name != NULL) {
|
|
fprintf(fp, "label %s", internal->MR_internal_name);
|
|
} else {
|
|
fprintf(fp, "unnamed label %p", internal->MR_internal_addr);
|
|
}
|
|
#ifdef MR_DEBUG_LABEL_GOAL_PATHS
|
|
if (internal->MR_internal_layout != NULL) {
|
|
fprintf(fp, " <%s>",
|
|
MR_label_goal_path(internal->MR_internal_layout));
|
|
}
|
|
#endif
|
|
} else {
|
|
MR_Entry *entry;
|
|
|
|
entry = MR_prev_entry_by_addr(w);
|
|
if (entry != NULL && entry->MR_entry_addr == w) {
|
|
if (entry->MR_entry_name != NULL) {
|
|
fprintf(fp, "entry label %s", entry->MR_entry_name);
|
|
} else {
|
|
fprintf(fp, "unnamed entry label %p", entry->MR_entry_addr);
|
|
}
|
|
} else {
|
|
fprintf(fp, "label UNKNOWN %p", w);
|
|
}
|
|
}
|
|
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, " (%p)", w);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_printlabel(FILE *fp, const MR_Code *w)
|
|
{
|
|
MR_print_label(fp, w);
|
|
fprintf(fp, "\n");
|
|
}
|
|
|
|
void
|
|
MR_print_deep_prof_var(FILE *fp, const char *name, MR_CallSiteDynamic *csd)
|
|
{
|
|
#ifdef MR_DEEP_PROFILING
|
|
fprintf(fp, "%s: %p", name, csd);
|
|
|
|
if (csd == NULL) {
|
|
fprintf(fp, "\n");
|
|
} else {
|
|
const MR_ProcDynamic *pd;
|
|
const MR_ProcLayout *pl;
|
|
const MR_ProcStatic *ps;
|
|
const MR_ProcId *proc_id;
|
|
|
|
fprintf(fp, ", depth %d,", csd->MR_csd_depth_count);
|
|
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
fprintf(fp, " calls %d,",
|
|
csd->MR_csd_own.MR_own_calls);
|
|
#endif
|
|
fprintf(fp, " exits %d, fails %d, redos %d\n",
|
|
csd->MR_csd_own.MR_own_exits,
|
|
csd->MR_csd_own.MR_own_fails,
|
|
csd->MR_csd_own.MR_own_redos);
|
|
|
|
pd = csd->MR_csd_callee_ptr;
|
|
fprintf(fp, " pd: %p", pd);
|
|
if (pd == NULL) {
|
|
fprintf(fp, "\n");
|
|
} else if (pd->MR_pd_proc_layout == NULL) {
|
|
fprintf(fp, ", pl is NULL\n");
|
|
} else {
|
|
pl = pd->MR_pd_proc_layout;
|
|
ps = pl->MR_sle_proc_static;
|
|
fprintf(fp, ", pl: %p, ps: %p\n", pl, ps);
|
|
proc_id = &pl->MR_sle_proc_id;
|
|
if (MR_PROC_ID_IS_UCI(*proc_id)) {
|
|
fprintf(fp, " %s:%s %s/%d-%d\n ",
|
|
proc_id->MR_proc_uci.MR_uci_type_module,
|
|
proc_id->MR_proc_uci.MR_uci_type_name,
|
|
proc_id->MR_proc_uci.MR_uci_pred_name,
|
|
proc_id->MR_proc_uci.MR_uci_type_arity,
|
|
proc_id->MR_proc_uci.MR_uci_mode);
|
|
} else {
|
|
fprintf(fp, " %s.%s/%d-%d\n ",
|
|
proc_id->MR_proc_user.MR_user_decl_module,
|
|
proc_id->MR_proc_user.MR_user_name,
|
|
proc_id->MR_proc_user.MR_user_arity,
|
|
proc_id->MR_proc_user.MR_user_mode);
|
|
}
|
|
|
|
#ifdef MR_USE_ACTIVATION_COUNTS
|
|
fprintf(fp, "active %d, ", ps->MR_ps_activation_count);
|
|
#endif
|
|
fprintf(fp, "outermost %p, array %d\n",
|
|
ps->MR_ps_outermost_activation_ptr, ps->MR_ps_num_call_sites);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* auxiliary routines for the code that prints debugging messages */
|
|
|
|
static MR_bool
|
|
MR_find_zone_for_det_ptr_in_context(const MR_Word *ptr, MR_Context *ctxt,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr)
|
|
{
|
|
#ifdef MR_HIGHLEVEL_CODE
|
|
return MR_FALSE;
|
|
#else /* !MR_HIGHLEVEL_CODE */
|
|
int segment_number;
|
|
MR_MemoryZones *remaining_zones;
|
|
MR_MemoryZone *cur_zone;
|
|
|
|
remaining_zones = ctxt->MR_ctxt_prev_detstack_zones;
|
|
if (MR_in_zone(ptr, ctxt->MR_ctxt_detstack_zone)) {
|
|
if (zone_ptr != NULL) {
|
|
*zone_ptr = ctxt->MR_ctxt_detstack_zone;
|
|
}
|
|
} else {
|
|
while (remaining_zones != NULL) {
|
|
cur_zone = remaining_zones->MR_zones_head;
|
|
if (MR_in_zone(ptr, cur_zone)) {
|
|
if (zone_ptr != NULL) {
|
|
*zone_ptr = cur_zone;
|
|
}
|
|
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
break;
|
|
}
|
|
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
}
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|
|
if (zone_num_ptr != NULL) {
|
|
segment_number = 0;
|
|
while (remaining_zones != NULL) {
|
|
segment_number++;
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
}
|
|
|
|
*zone_num_ptr = segment_number;
|
|
}
|
|
|
|
return MR_TRUE;
|
|
#endif /* !MR_HIGHLEVEL_CODE */
|
|
}
|
|
|
|
static MR_bool
|
|
MR_find_zone_for_nondet_ptr_in_context(const MR_Word *ptr, MR_Context *ctxt,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr)
|
|
{
|
|
#ifdef MR_HIGHLEVEL_CODE
|
|
return MR_FALSE;
|
|
#else /* !MR_HIGHLEVEL_CODE */
|
|
int segment_number;
|
|
MR_MemoryZones *remaining_zones;
|
|
MR_MemoryZone *cur_zone;
|
|
|
|
remaining_zones = ctxt->MR_ctxt_prev_nondetstack_zones;
|
|
if (MR_in_zone(ptr, ctxt->MR_ctxt_nondetstack_zone)) {
|
|
if (zone_ptr != NULL) {
|
|
*zone_ptr = ctxt->MR_ctxt_nondetstack_zone;
|
|
}
|
|
} else {
|
|
while (remaining_zones != NULL) {
|
|
cur_zone = remaining_zones->MR_zones_head;
|
|
if (MR_in_zone(ptr, cur_zone)) {
|
|
if (zone_ptr != NULL) {
|
|
*zone_ptr = cur_zone;
|
|
}
|
|
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
break;
|
|
}
|
|
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
}
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|
|
if (zone_num_ptr != NULL) {
|
|
segment_number = 0;
|
|
while (remaining_zones != NULL) {
|
|
segment_number++;
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
}
|
|
|
|
*zone_num_ptr = segment_number;
|
|
}
|
|
|
|
return MR_TRUE;
|
|
#endif /* !MR_HIGHLEVEL_CODE */
|
|
}
|
|
|
|
static MR_bool
|
|
MR_find_zone_for_det_ptr(const MR_Word *ptr, MR_Context **ctxt_ptr,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr)
|
|
{
|
|
#ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
|
|
|
|
const MR_Dlist *item;
|
|
MR_Context *ctxt;
|
|
|
|
if (MR_find_zone_for_det_ptr_in_context(ptr,
|
|
MR_ENGINE(MR_eng_main_context), zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = MR_ENGINE(MR_eng_main_context);
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
|
|
MR_for_dlist(item, MR_ENGINE(MR_eng_gen_contexts)) {
|
|
ctxt = (MR_Context *) MR_dlist_data(item);
|
|
if (MR_find_zone_for_det_ptr_in_context(ptr, ctxt,
|
|
zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = ctxt;
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
}
|
|
|
|
#else /* !MR_USE_MINIMAL_MODEL_OWN_STACKS */
|
|
|
|
if (MR_find_zone_for_det_ptr_in_context(ptr, &MR_ENGINE(MR_eng_context),
|
|
zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = &MR_ENGINE(MR_eng_context);
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
|
|
#endif /* MR_USE_MINIMAL_MODEL_OWN_STACKS */
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|
|
static MR_bool
|
|
MR_find_zone_for_nondet_ptr(const MR_Word *ptr, MR_Context **ctxt_ptr,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr)
|
|
{
|
|
#ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
|
|
|
|
const MR_Dlist *item;
|
|
MR_Context *ctxt;
|
|
|
|
if (MR_find_zone_for_nondet_ptr_in_context(ptr,
|
|
MR_ENGINE(MR_eng_main_context), zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = MR_ENGINE(MR_eng_main_context);
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
|
|
MR_for_dlist(item, MR_ENGINE(MR_eng_gen_contexts)) {
|
|
ctxt = (MR_Context *) MR_dlist_data(item);
|
|
if (MR_find_zone_for_nondet_ptr_in_context(ptr, ctxt,
|
|
zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = ctxt;
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
}
|
|
|
|
#else /* !MR_USE_MINIMAL_MODEL_OWN_STACKS */
|
|
|
|
if (MR_find_zone_for_nondet_ptr_in_context(ptr, &MR_ENGINE(MR_eng_context),
|
|
zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = &MR_ENGINE(MR_eng_context);
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
|
|
#endif /* MR_USE_MINIMAL_MODEL_OWN_STACKS */
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|