Files
mercury/bytecode/mb_machine.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

205 lines
4.8 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.h"
#include "mb_interface.h"
#include "mb_machine_def.h"
#include "mb_module.h"
/* Exported definitions */
/* Local declarations */
/* Implementation */
/* Get the next instruction pointer */
MB_Bytecode_Addr
MB_ip_get(MB_Machine_State *ms)
{
return ms->ip;
}
/* set the native code return address */
void
MB_native_return_set(MB_Machine_State *ms, MB_Native_Addr native_return)
{
#if 0
MB_SAY("Returning to %p", native_return);
MB_SAY("MB_succip is %p (%s)",
MB_succip,
(MB_succip == MB_native_get_return_temp_det()) ?
"temp det return" :
(MB_succip == MB_native_get_return_temp_nondet()) ?
"temp nondet return" :
(MB_succip == MB_native_get_return_nondet()) ?
"nondet return" :
(MB_succip == MB_native_get_return_det()) ?
"det return" : "unknown");
#endif
MB_ip_set(ms, MB_CODE_NATIVE_RETURN);
ms->native_return = native_return;
}
MB_Native_Addr
MB_native_return_get(MB_Machine_State * ms)
{
assert(ms->ip == MB_CODE_NATIVE_RETURN);
return ms->native_return;
}
void
MB_ip_set(MB_Machine_State *ms, MB_Bytecode_Addr new_ip)
{
if (MB_ip_special(new_ip)) {
switch ((MB_Word) new_ip) {
case (MB_Word) MB_CODE_DO_FAIL:
case (MB_Word) MB_CODE_DO_REDO:
case (MB_Word) MB_CODE_NATIVE_RETURN:
ms->ip = new_ip;
break;
default:
assert(FALSE);
}
} else {
ms->ip = new_ip;
}
}
/*
** Check which procedure we are in & set variable stack pointer appropriately
**
** If you don't call this after the ip switches to a new function
** then MB_var_get and MB_var_set will give incorrect results
**
** If det/semidet, set the machine state variable slot pointer to the det stack
** If nondet, set the machine state variable slot pointer to the nondet stack
*/
void
MB_proc_var_init(MB_Machine_State *ms)
{
MB_Bytecode_Addr ip = MB_ip_get(ms);
if (!MB_ip_normal(ip)) return;
/* Check that we are actually in a procedure and not just entering one*/
if (MB_code_get_id(ip) != MB_BC_enter_proc) {
/* If we are, check the determinism & set vars as appropriate */
ms->cur_proc.is_det = MB_code_get_det(ip);
ms->cur_proc.var = (ms->cur_proc.is_det == MB_ISDET_YES)
? &(MB_stackvar(0))
: &(MB_framevar(0));
}
}
MB_Bool
MB_proc_is_det(MB_Machine_State* ms)
{
return ms->cur_proc.is_det == MB_ISDET_YES;
}
/*
** Get a variable from the appropriate mercury stack
**
** It knows which stack to use because you have of course already
** called MB_proc_var_init to set the current procedure's
** variable pointer to point to variable 0.
*/
MB_Word
MB_var_get(MB_Machine_State *ms, MB_Word idx)
{
/*
** idx is negative because variable 0 is the topmost and
** higher number variables are below it on the stack
*/
return ms->cur_proc.var[-idx];
}
/* Set a variable on the mercury stack */
void
MB_var_set(MB_Machine_State *ms, MB_Word idx, MB_Word value)
{
ms->cur_proc.var[-idx] = value;
}
/* Get/set the initial stack frame (see machine_def.h for use) */
MB_Word *
MB_initialstackframe_get(MB_Machine_State *ms)
{
return ms->initial_stack;
}
void
MB_initialstackframe_set(MB_Machine_State *ms, MB_Word *frame)
{
assert(ms->initial_stack == NULL);
ms->initial_stack = frame;
}
/* Add a temporary stack frame with a redo_ip of do_fail
** Because the do_fail is native code, we can get by with
** a nativecode-type stack frame
*/
void
MB_frame_temp_push_do_fail(MB_Machine_State *ms)
{
MB_Word *prevfr = MB_maxfr;
if (ms->cur_proc.is_det) {
MB_maxfr += MR_DET_TEMP_SIZE;
MB_fr_prevfr(MB_maxfr) = prevfr;
MB_fr_redoip(MB_maxfr) = (MB_Word) MB_native_get_do_fail();
MB_fr_redofr(MB_maxfr) = (MB_Word) MB_curfr;
MB_fr_detfr(MB_maxfr) = (MB_Word) MB_sp;
} else {
MB_maxfr += MR_NONDET_TEMP_SIZE;
MB_fr_prevfr(MB_maxfr) = prevfr;
MB_fr_redoip(MB_maxfr) = (MB_Word) MB_native_get_do_fail();
MB_fr_redofr(MB_maxfr) = (MB_Word) MB_curfr;
}
}
/* Add a temporary stack frame */
void
MB_frame_temp_push(MB_Machine_State *ms, MB_Bytecode_Addr redoip)
{
MB_Word *prevfr = MB_maxfr;
if (ms->cur_proc.is_det) {
MB_maxfr += MB_FRAME_TEMP_DET_SIZE;
MB_fr_prevfr(MB_maxfr) = prevfr;
MB_fr_redoip(MB_maxfr) =
(MB_Word) MB_native_get_return_temp_det();
MB_fr_redofr(MB_maxfr) = (MB_Word) MB_curfr;
MB_fr_detfr(MB_maxfr) = (MB_Word) MB_sp;
MB_fr_temp_det_bcredoip(MB_maxfr) = (MB_Word) redoip;
MB_fr_temp_det_bcinitfr(MB_maxfr) =
(MB_Word) MB_initialstackframe_get(ms);
} else {
MB_maxfr += MB_FRAME_TEMP_NONDET_SIZE;
MB_fr_prevfr(MB_maxfr) = prevfr;
MB_fr_redoip(MB_maxfr) =
(MB_Word) MB_native_get_return_temp_nondet();
MB_fr_redofr(MB_maxfr) = (MB_Word) MB_curfr;
MB_fr_temp_nondet_bcredoip(MB_maxfr) = (MB_Word) redoip;
}
}