Files
mercury/bytecode/mb_machine_show.c
Levi Cameron 0921310ca5 More work on the bytecode interpreter.
With these changes, it now passes all tests/general/* test cases
  except those with floats.

  Changes to the compiler:
  - Added extra argument to test instruction (string comparisons were
    being treated as integer comparisons; properly deals with different
    atomic type unifications now)
  - Changed bytecode stub functions

  Changes to the bytecode interpreter:
  - Cleaned up comments
  - Forked part of mb_machine to mb_exec
  - Added support for submodules
  - Added support for nondet procedures
  - Added support for cc_xxx procedures
  - Finished higher order calls
  - Added (very basic) debug interface
  - Added support for type information
  - Added memory corruption checking
  - Changed machine state dump formatting
  - Fixed bug in nested switches
  - Resolved builtin__unify and builtin_compare failures
  - Modified bytecode tags generation so .c & .m tag files are separate
  - Header usage rationalised

  Changes to test suite:
  - Added test cases for the bytecode interpreter.
  - More work on the bytecode interpreter.

bytecode/Mmakefile:
        Modified bytecode tags generation so .c & .m tag files are separate.
        mb_machine split into mb_exec.
        test file renamed to simple.m (copy over tests/simple??.m to test).

bytecode/TODO:
        Updated.

bytecode/mb_basetypes.h:
        Removed redundant MB_WORD_BITS (use MR_WORDBITS instead).

bytecode/mb_bytecode.h:
bytecode/mpb_bytecode.c:
        Formatting changes
        Third test instruction argument added.

bytecode/mb_disasm.h:
bytecode/mb_disasm.c:
        Formatting changes.
        Third test instruction argument added.
        Added MB_FMT_INTWIDE.

bytecode/mb_exec.h:
bytecode/mb_exec.c:
bytecode/mb_machine.h:
bytecode/mb_machine.c:
        mb_machine* split into mb_exec* and mb_machine*.
        Almost all instructions now work (see important changes above).

bytecode/mb_interface.h:
bytecode/mb_interface.c:
        Added nondet stub functions.
        Added functions to lookup builtin compiler procedures:
                do_redo, do_fail, __unify, __compare.
        Removed old debugging code.
        Stack layout changed to support nondet procedures.

bytecode/mb_interface_stub.c:
bytecode/mb_interface_stub.h:
        Split off bare minimum of includes for bytecode stubs.
        Added nondet stubs.

bytecode/mb_machine_show.c:
        Made code cleaner (added subfunctions for MB_show_state).
        Added variable names to machine state dump.

bytecode/mb_mem.h:
bytecode/mb_mem.c:
        Added limited memory corruption checking.

bytecode/mb_module.h:
bytecode/mb_module.c:
        Swapped order of temps & vars on stack.
        Fixed nested switches causing random crashes.
        Added nested module support.

bytecode/test/simple??.m:
        Various test files - just to check that it doesn't crash.
        (Most do not output anything & must be verified by stepping through
        manually).

compiler/bytecode.m:
compiler/bytecode_gen.m:
        Added extra argument to test instruction (otherwise
        string comparisons would be treated as integer comparisons).

compiler/code_gen.m:
        Changed call structure name in bytecode stub to resolve
        issues with illegal characters in C structure names.
        Changed bytecode stub header file name.
2001-02-19 02:05:59 +00:00

256 lines
5.6 KiB
C

/*
** Copyright (C) 2000-2001 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.
**
*/
/* Imports */
#include "mercury_imp.h"
#include "mb_machine_show.h"
#include "mb_disasm.h"
#include "mb_interface.h"
#include "mb_machine_def.h"
#include "mb_module.h"
/* Exported definitions */
void MB_show_state(MB_Machine_State *ms, FILE *fp);
/* Local declarations */
static void show_regs(MB_Machine_State *ms, FILE *fp);
static void show_stack(MB_Machine_State *ms, FILE *fp);
/* Number of registers to display */
#define NREGS 8
/* Number of entries in each stack to display */
#define NSTACK 27
/* Maximum line length for disassembly */
#define LINE_LEN 78 /* XXX: make this adjustable */
/* Display the current state of the machine */
static void
show_regs(MB_Machine_State *ms, FILE *fp)
{
int i;
/*
** Show the registers in two columns, like so:
** r0 r4
** r1 r5
** r2 r6
** r3 r7
*/
for (i = 0; i < NREGS; i++) {
int j = i / 2 +
((i & 1) ? (NREGS / 2) : 0);
fprintf(fp,
"reg[%02d] = " MB_FMT_INTWIDE
" ("MB_FMT_HEX ") ",
j, MB_reg(j), MB_reg(j));
if (i & 1) {
fprintf(fp, "\n");
}
}
if (!(i & 1)) {
fprintf(fp, "\n");
}
}
static char *
get_var_name(MB_Machine_State* ms, MB_Bytecode_Arg *cur_proc, MB_Word *var)
{
static char *var_name = NULL;
if (var_name == NULL) {
var_name = MB_str_dup("tmp000");
}
if (cur_proc != NULL) {
MB_Integer offset = ms->cur_proc.var - var;
if (offset >= 0) {
MB_Integer temp_count = cur_proc->enter_proc.temp_count;
MB_Integer var_count = cur_proc->enter_proc.list_length;
if (offset < temp_count) {
sprintf(var_name+3, "%03d", (int) offset);
return var_name;
} else if ((offset -= temp_count) < var_count) {
return cur_proc->enter_proc.var_info[offset];
}
}
}
return NULL;
}
/* Display the top stack entries */
static void
show_stack(MB_Machine_State *ms, FILE *fp)
{
int i;
int frame_index;
MB_Word *thisfr;
char det_sym[NSTACK];
char nondet_sym[NSTACK][2];
MB_Bytecode_Addr ip = MB_ip_get(ms);
MB_Bytecode_Arg *cur_proc = MB_ip_normal(ip)
? MB_code_get_arg(
MB_code_get_proc_addr(ip))
: NULL;
for (i = 0; i < NSTACK; i++) {
/* Indicate variable list */
det_sym[i] =
(&MB_stackitem(i + 1) == ms->cur_proc.var) ? '>'
: ' ';
/* Indicate variable list */
if (&MB_frameitem(MB_maxfr, i) == ms->cur_proc.var) {
nondet_sym[i][0] = '[';
nondet_sym[i][1] = '>';
} else {
nondet_sym[i][0] = ' ';
nondet_sym[i][1] = ' ';
}
}
/* Indicate stack frames */
thisfr = MB_maxfr;
frame_index = 0;
i = 0;
do {
while (i < frame_index) {
if (nondet_sym[i][0] == ' ') {
nondet_sym[i][0] = '|';
}
i++;
}
i++;
if ((MB_Word *) MB_fr_prevfr(thisfr) != NULL) {
nondet_sym[frame_index][0] = '/';
nondet_sym[frame_index][1] = '=';
}
if (frame_index > 0) {
nondet_sym[frame_index-1][0] = '[';
nondet_sym[frame_index-1][1] = '_';
}
thisfr = (MB_Word *) MB_fr_prevfr(thisfr);
frame_index = (&MB_frameitem(MB_maxfr, 0) - thisfr);
} while ((frame_index < NSTACK) && (thisfr != NULL));
/* Show the stack */
fprintf(fp, "\n");
fprintf(fp, " sp = " MB_FMT_HEX " "
" maxfr = " MB_FMT_HEX "\n",
(MB_Unsigned) MB_sp,
(MB_Unsigned) MB_maxfr);
for (i = 0; i < NSTACK; i++) {
char *var_name;
var_name = get_var_name(ms, cur_proc, &MB_stackitem(i + 1));
if (var_name == NULL) {
var_name = get_var_name(ms, cur_proc,
&MB_frameitem(MB_maxfr, i));
}
if (var_name == NULL) {
var_name = "";
}
fprintf(fp,
"%cdet[%02d] = " MB_FMT_INTWIDE " ("MB_FMT_HEX ") "
"%c%c%p=" MB_FMT_INTWIDE " (" MB_FMT_HEX ") %s\n",
det_sym[i],
(int) i + 1,
MB_stackitem(i + 1),
MB_stackitem(i + 1),
nondet_sym[i][0],
nondet_sym[i][1],
&(MB_frameitem(MB_maxfr, i)),
MB_frameitem(MB_maxfr, i),
MB_frameitem(MB_maxfr, i),
var_name
);
}
}
void
MB_show_state(MB_Machine_State *ms, FILE *fp)
{
char buffer[LINE_LEN];
MB_Bytecode_Addr ip = MB_ip_get(ms);
/* Work out what predicate & proc we are in */
MB_Bytecode_Addr cur_pred;
MB_Bytecode_Addr cur_proc;
if (fp == NULL) return;
fprintf(fp, "----------------------------------------"
"------------------------------------\n");
if (MB_code_range_clamp(ip) == ip) {
/* Show what predicate we are in */
cur_pred = MB_code_get_pred_addr(ip);
cur_proc = MB_code_get_proc_addr(ip);
MB_str_bytecode(cur_pred, buffer, sizeof(buffer), 0);
fprintf(fp, "%s\n", buffer);
MB_str_bytecode(cur_proc, buffer, sizeof(buffer), 1);
fprintf(fp, "%s\n", buffer);
fprintf(fp, "\n");
fprintf(fp, "ip: %p\n", ip);
/* show the surrounding lines of code */
MB_listing(ms, fp, ip - 2, ip + 4, LINE_LEN);
} else {
if (MB_ip_special(ip)) {
fprintf(fp, " Special execution address (%p)\n", ip);
} else {
fprintf(fp, " Invalid execution address (%p)\n", ip);
}
}
fprintf(fp, "\n");
show_regs(ms, fp);
fprintf(fp, "\n");
/* Show the machine state */
fprintf(fp, " succip = " MB_FMT_HEX " "
" var_ptr = " MB_FMT_HEX "\n",
(MB_Unsigned) MB_succip,
(MB_Unsigned) ms->cur_proc.var);
fprintf(fp, " init_frame = " MB_FMT_HEX " "
" natv_retun = " MB_FMT_HEX "\n",
(MB_Unsigned) ms->initial_stack,
(MB_Unsigned) ms->native_return);
fprintf(fp, " cur_frame = " MB_FMT_HEX " "
" = " MB_FMT_HEX "\n",
(MB_Unsigned) MB_curfr,
(MB_Unsigned) 0);
show_stack(ms, fp);
fprintf(fp, "\n");
} /* MB_show_state */