mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-22 12:53:47 +00:00
Estimated hours taken: 12 Get the debugger to sort variables better. trace/mercury_trace_vars.[ch]: A new module to manage the debugger's information about the variables live at the current program point (which can be defined as the combination of a specific event and an ancestor level). This new module centralizes the management of the (sorted) list of current variables. This in turn allows us to use a better sorting method, one that orders VarName15 correctly wrt both VarName2 and VarName. The new module also uses the type, not the name, of a variable to decide whether to exclude it from the list of variables that may be presented to the user (e.g. if it is a typeinfo or a typeclassinfo). trace/mercury_trace_internal.c: trace/mercury_trace_external.c: Use the new module's facilities. This factors out some "mostly" common code. trace/Mmakefile: Add the new module. runtime/mercury_layout_util.[ch]: Remove the code recently moved here from trace/mercury_trace_internal, as well as the filtered versions of some functions, since they are not needed anymore. Move the code for MR_make_var_list to trace/mercury_trace_external, since that is the only place where it is used (or is at all likely to be used). Since its new home is next to several very similar functions, this should also reduce the probability that any required maintenance will be overlooked. Also alter its coding style to conform to its new neighbours. Move the definition of MR_Var_Spec to trace/mercury_trace_vars.h. tests/debugger/*.exp: Update the expected output files. In most cases, this is just because the new module outputs different white space, but in some cases, it also reflects that the debugger now prints variables in a different order.
409 lines
8.9 KiB
C
409 lines
8.9 KiB
C
/*
|
|
** Copyright (C) 1998-1999 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
/*
|
|
** This file implements utilities that can be useful
|
|
** for both the internal and external debuggers.
|
|
**
|
|
** Main authors: Zoltan Somogyi and Fergus Henderson.
|
|
*/
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_stack_layout.h"
|
|
#include "mercury_layout_util.h"
|
|
|
|
void
|
|
MR_copy_regs_to_saved_regs(int max_mr_num, Word *saved_regs)
|
|
{
|
|
/*
|
|
** In the process of browsing within the debugger, we call Mercury,
|
|
** which may clobber the contents of the virtual machine registers,
|
|
** both control and general purpose, and both real and virtual
|
|
** registers. We must therefore save and restore these.
|
|
** We store them in the saved_regs array.
|
|
**
|
|
** The call to MR_trace will clobber the transient registers
|
|
** on architectures that have them. The compiler generated code
|
|
** will therefore call save_transient_registers to save the transient
|
|
** registers in the fake_reg array. We here restore them to the
|
|
** real registers, save them with the other registers back in
|
|
** fake_reg, and then copy all fake_reg entries to saved_regs.
|
|
*/
|
|
|
|
int i;
|
|
|
|
restore_transient_registers();
|
|
save_registers();
|
|
|
|
for (i = 0; i <= max_mr_num; i++) {
|
|
saved_regs[i] = MR_fake_reg[i];
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_copy_saved_regs_to_regs(int max_mr_num, Word *saved_regs)
|
|
{
|
|
/*
|
|
** We execute the converse procedure to MR_copy_regs_to_saved_regs.
|
|
** The save_transient_registers is there so that a call to the
|
|
** restore_transient_registers macro after MR_trace will do the
|
|
** right thing.
|
|
*/
|
|
|
|
int i;
|
|
|
|
for (i = 0; i <= max_mr_num; i++) {
|
|
MR_fake_reg[i] = saved_regs[i];
|
|
}
|
|
|
|
restore_registers();
|
|
save_transient_registers();
|
|
}
|
|
|
|
Word *
|
|
MR_materialize_typeinfos(const MR_Stack_Layout_Vars *vars,
|
|
Word *saved_regs)
|
|
{
|
|
return MR_materialize_typeinfos_base(vars, saved_regs,
|
|
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs));
|
|
}
|
|
|
|
Word *
|
|
MR_materialize_typeinfos_base(const MR_Stack_Layout_Vars *vars,
|
|
Word *saved_regs, Word *base_sp, Word *base_curfr)
|
|
{
|
|
Word *type_params;
|
|
bool succeeded;
|
|
Integer count;
|
|
int i;
|
|
|
|
if (vars->MR_slvs_tvars != NULL) {
|
|
count = vars->MR_slvs_tvars->MR_tp_param_count;
|
|
type_params = checked_malloc((count + 1) * sizeof(Word));
|
|
|
|
/*
|
|
** type_params should look like a typeinfo;
|
|
** type_params[0] is empty and will not be referred to
|
|
*/
|
|
for (i = 0; i < count; i++) {
|
|
if (vars->MR_slvs_tvars->MR_tp_param_locns[i] != 0) {
|
|
type_params[i + 1] = MR_lookup_long_lval_base(
|
|
vars->MR_slvs_tvars->
|
|
MR_tp_param_locns[i],
|
|
saved_regs, base_sp, base_curfr,
|
|
&succeeded);
|
|
if (! succeeded) {
|
|
fatal_error("missing type param in MR_materialize_typeinfos_base");
|
|
}
|
|
}
|
|
}
|
|
|
|
return type_params;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
int
|
|
MR_get_register_number_long(MR_Long_Lval locn)
|
|
{
|
|
if (MR_LONG_LVAL_TYPE(locn) == MR_LONG_LVAL_TYPE_R) {
|
|
return MR_LONG_LVAL_NUMBER(locn);
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int
|
|
MR_get_register_number_short(MR_Short_Lval locn)
|
|
{
|
|
if (MR_SHORT_LVAL_TYPE(locn) == MR_SHORT_LVAL_TYPE_R) {
|
|
return locn >> MR_SHORT_LVAL_TAGBITS;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* if you want to debug this code, you may want to set this var to TRUE */
|
|
static bool MR_print_locn = FALSE;
|
|
|
|
Word
|
|
MR_lookup_long_lval(MR_Long_Lval locn, Word *saved_regs, bool *succeeded)
|
|
{
|
|
return MR_lookup_long_lval_base(locn, saved_regs,
|
|
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
|
|
succeeded);
|
|
}
|
|
|
|
Word
|
|
MR_lookup_long_lval_base(MR_Long_Lval locn, Word *saved_regs,
|
|
Word *base_sp, Word *base_curfr, bool *succeeded)
|
|
{
|
|
int locn_num;
|
|
int offset;
|
|
Word value;
|
|
Word baseaddr;
|
|
Word sublocn;
|
|
|
|
*succeeded = FALSE;
|
|
value = 0;
|
|
|
|
locn_num = (int) MR_LONG_LVAL_NUMBER(locn);
|
|
switch (MR_LONG_LVAL_TYPE(locn)) {
|
|
case MR_LONG_LVAL_TYPE_R:
|
|
if (MR_print_locn) {
|
|
printf("r%d", locn_num);
|
|
}
|
|
if (saved_regs != NULL) {
|
|
value = saved_reg(saved_regs, locn_num);
|
|
*succeeded = TRUE;
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_F:
|
|
if (MR_print_locn) {
|
|
printf("f%d", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_STACKVAR:
|
|
if (MR_print_locn) {
|
|
printf("stackvar%d", locn_num);
|
|
}
|
|
value = MR_based_stackvar(base_sp, locn_num);
|
|
*succeeded = TRUE;
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_FRAMEVAR:
|
|
if (MR_print_locn) {
|
|
printf("framevar%d", locn_num);
|
|
}
|
|
value = MR_based_framevar(base_curfr, locn_num);
|
|
*succeeded = TRUE;
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SUCCIP:
|
|
if (MR_print_locn) {
|
|
printf("succip");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_MAXFR:
|
|
if (MR_print_locn) {
|
|
printf("maxfr");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_CURFR:
|
|
if (MR_print_locn) {
|
|
printf("curfr");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_HP:
|
|
if (MR_print_locn) {
|
|
printf("hp");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SP:
|
|
if (MR_print_locn) {
|
|
printf("sp");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_INDIRECT:
|
|
offset = MR_LONG_LVAL_INDIRECT_OFFSET(locn_num);
|
|
sublocn = MR_LONG_LVAL_INDIRECT_BASE_LVAL(locn_num);
|
|
if (MR_print_locn) {
|
|
printf("offset %d from ", offset);
|
|
}
|
|
baseaddr = MR_lookup_long_lval_base(sublocn,
|
|
saved_regs, base_sp, base_curfr,
|
|
succeeded);
|
|
if (! *succeeded) {
|
|
break;
|
|
}
|
|
value = MR_typeclass_info_superclass_info(baseaddr,
|
|
offset);
|
|
*succeeded = TRUE;
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_UNKNOWN:
|
|
if (MR_print_locn) {
|
|
printf("unknown");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (MR_print_locn) {
|
|
printf("DEFAULT");
|
|
}
|
|
break;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
Word
|
|
MR_lookup_short_lval(MR_Short_Lval locn, Word *saved_regs, bool *succeeded)
|
|
{
|
|
return MR_lookup_short_lval_base(locn, saved_regs,
|
|
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
|
|
succeeded);
|
|
}
|
|
|
|
Word
|
|
MR_lookup_short_lval_base(MR_Short_Lval locn, Word *saved_regs,
|
|
Word *base_sp, Word *base_curfr, bool *succeeded)
|
|
{
|
|
int locn_num;
|
|
Word value;
|
|
|
|
*succeeded = FALSE;
|
|
value = 0;
|
|
|
|
locn_num = (int) locn >> MR_SHORT_LVAL_TAGBITS;
|
|
switch (MR_SHORT_LVAL_TYPE(locn)) {
|
|
case MR_SHORT_LVAL_TYPE_R:
|
|
if (MR_print_locn) {
|
|
printf("r%d", locn_num);
|
|
}
|
|
if (saved_regs != NULL) {
|
|
value = saved_reg(saved_regs, locn_num);
|
|
*succeeded = TRUE;
|
|
}
|
|
break;
|
|
|
|
case MR_SHORT_LVAL_TYPE_STACKVAR:
|
|
if (MR_print_locn) {
|
|
printf("stackvar%d", locn_num);
|
|
}
|
|
value = MR_based_stackvar(base_sp, locn_num);
|
|
*succeeded = TRUE;
|
|
break;
|
|
|
|
case MR_SHORT_LVAL_TYPE_FRAMEVAR:
|
|
if (MR_print_locn) {
|
|
printf("framevar%d", locn_num);
|
|
}
|
|
value = MR_based_framevar(base_curfr, locn_num);
|
|
*succeeded = TRUE;
|
|
break;
|
|
|
|
case MR_SHORT_LVAL_TYPE_SPECIAL:
|
|
switch (locn_num) {
|
|
case MR_LONG_LVAL_TYPE_SUCCIP:
|
|
if (MR_print_locn) {
|
|
printf("succip");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_MAXFR:
|
|
if (MR_print_locn) {
|
|
printf("maxfr");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_CURFR:
|
|
if (MR_print_locn) {
|
|
printf("curfr");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_HP:
|
|
if (MR_print_locn) {
|
|
printf("hp");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SP:
|
|
if (MR_print_locn) {
|
|
printf("sp");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (MR_print_locn) {
|
|
printf("DEFAULT");
|
|
}
|
|
}
|
|
|
|
default:
|
|
if (MR_print_locn) {
|
|
printf("DEFAULT");
|
|
}
|
|
break;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
bool
|
|
MR_get_type_and_value(const MR_Stack_Layout_Vars *vars, int i,
|
|
Word *saved_regs, Word *type_params, Word *type_info, Word *value)
|
|
{
|
|
return MR_get_type_and_value_base(vars, i, saved_regs,
|
|
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
|
|
type_params, type_info, value);
|
|
}
|
|
|
|
bool
|
|
MR_get_type_and_value_base(const MR_Stack_Layout_Vars *vars, int i,
|
|
Word *saved_regs, Word *base_sp, Word *base_curfr,
|
|
Word *type_params, Word *type_info, Word *value)
|
|
{
|
|
bool succeeded;
|
|
Word *pseudo_type_info;
|
|
|
|
pseudo_type_info = MR_var_pti(vars, i);
|
|
*type_info = (Word) MR_create_type_info(type_params, pseudo_type_info);
|
|
|
|
if (i < MR_long_desc_var_count(vars)) {
|
|
*value = MR_lookup_long_lval_base(
|
|
MR_long_desc_var_locn(vars, i),
|
|
saved_regs, base_sp, base_curfr, &succeeded);
|
|
} else {
|
|
*value = MR_lookup_short_lval_base(
|
|
MR_short_desc_var_locn(vars, i),
|
|
saved_regs, base_sp, base_curfr, &succeeded);
|
|
}
|
|
|
|
return succeeded;
|
|
}
|
|
|
|
bool
|
|
MR_get_type(const MR_Stack_Layout_Vars *vars, int i, Word *saved_regs,
|
|
Word *type_params, Word *type_info)
|
|
{
|
|
return MR_get_type_base(vars, i, saved_regs,
|
|
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
|
|
type_params, type_info);
|
|
}
|
|
|
|
bool
|
|
MR_get_type_base(const MR_Stack_Layout_Vars *vars, int i,
|
|
Word *saved_regs, Word *base_sp, Word *base_curfr,
|
|
Word *type_params, Word *type_info)
|
|
{
|
|
bool succeeded;
|
|
Word *pseudo_type_info;
|
|
|
|
pseudo_type_info = MR_var_pti(vars, i);
|
|
*type_info = (Word) MR_create_type_info(type_params, pseudo_type_info);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
MR_write_variable(Word type_info, Word value)
|
|
{
|
|
Word stdout_stream;
|
|
|
|
(*MR_io_stdout_stream)(&stdout_stream);
|
|
(*MR_io_print_to_stream)(type_info, stdout_stream, value);
|
|
}
|