mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-12 20:34:19 +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.
205 lines
4.8 KiB
C
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;
|
|
}
|
|
}
|
|
|