mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-20 08:19:28 +00:00
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.
256 lines
5.6 KiB
C
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 */
|
|
|