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.
286 lines
7.2 KiB
C
286 lines
7.2 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.
|
|
**
|
|
*/
|
|
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_trace_tables.h"
|
|
|
|
#include "mb_interface.h"
|
|
|
|
#include "mb_disasm.h"
|
|
#include "mb_exec.h"
|
|
#include "mb_module.h"
|
|
|
|
/* Exported definitions */
|
|
MB_Native_Addr MB_bytecode_call_entry(MB_Call *bytecode_call);
|
|
MB_Native_Addr MB_bytecode_return_det(void);
|
|
MB_Native_Addr MB_bytecode_return_temp_det(void);
|
|
MB_Native_Addr MB_bytecode_return_temp_nondet(void);
|
|
MB_Native_Addr MB_bytecode_return_nondet(void);
|
|
MB_Native_Addr MB_native_get_return_det(void);
|
|
MB_Native_Addr MB_native_get_return_temp_det(void);
|
|
MB_Native_Addr MB_native_get_return_temp_nondet(void);
|
|
MB_Native_Addr MB_native_get_return_nondet(void);
|
|
MB_Native_Addr MB_native_get_do_redo(void);
|
|
MB_Native_Addr MB_native_get_do_fail(void);
|
|
MB_Native_Addr MB_native_get_unify_2(void);
|
|
MB_Native_Addr MB_native_get_compare_3(void);
|
|
MB_Native_Addr MB_code_find_proc_native(MB_CString_Const module_name,
|
|
MB_CString_Const pred_name,
|
|
MB_Word mode_num, MB_Word arity,
|
|
MB_Bool is_func);
|
|
MB_Native_Addr MB_code_find_proc_native(MB_CString_Const module_name,
|
|
MB_CString_Const pred_name,
|
|
MB_Word mode_num, MB_Word arity,
|
|
MB_Bool is_func);
|
|
MR_TypeCtorInfo MB_type_find_ctor_info_guaranteed(
|
|
MB_CString_Const module_name,
|
|
MB_CString_Const type_name,
|
|
MB_Word type_arity);
|
|
/* Local declarations */
|
|
|
|
/* Implementation */
|
|
|
|
/* Reentry stubs */
|
|
MR_declare_entry(MB_native_return_det_stub);
|
|
MR_declare_entry(MB_native_return_temp_det_stub);
|
|
MR_declare_entry(MB_native_return_temp_nondet_stub);
|
|
MR_declare_entry(MB_native_return_nondet_stub);
|
|
|
|
MB_Native_Addr
|
|
MB_native_get_return_det(void)
|
|
{
|
|
return (MB_Native_Addr) MR_ENTRY(MB_native_return_det_stub);
|
|
}
|
|
|
|
MB_Native_Addr
|
|
MB_native_get_return_temp_det(void)
|
|
{
|
|
return (MB_Native_Addr) MR_ENTRY(MB_native_return_temp_det_stub);
|
|
}
|
|
|
|
MB_Native_Addr
|
|
MB_native_get_return_temp_nondet(void)
|
|
{
|
|
return (MB_Native_Addr) MR_ENTRY(MB_native_return_temp_nondet_stub);
|
|
}
|
|
|
|
MB_Native_Addr
|
|
MB_native_get_return_nondet(void)
|
|
{
|
|
return (MB_Native_Addr) MR_ENTRY(MB_native_return_nondet_stub);
|
|
}
|
|
|
|
MB_Native_Addr
|
|
MB_native_get_do_redo(void)
|
|
{
|
|
return (MB_Native_Addr) MR_ENTRY(do_redo);
|
|
}
|
|
|
|
MB_Native_Addr
|
|
MB_native_get_do_fail(void)
|
|
{
|
|
return (MB_Native_Addr) MR_ENTRY(do_fail);
|
|
}
|
|
|
|
|
|
MR_declare_entry(mercury__unify_2_0);
|
|
MR_declare_entry(mercury__compare_3_0);
|
|
|
|
MB_Native_Addr
|
|
MB_native_get_unify_2(void)
|
|
{
|
|
return (MB_Native_Addr) MR_ENTRY(mercury__unify_2_0);
|
|
}
|
|
|
|
MB_Native_Addr
|
|
MB_native_get_compare_3(void)
|
|
{
|
|
return (MB_Native_Addr) MR_ENTRY(mercury__compare_3_0);
|
|
}
|
|
|
|
/* Search for the native code address of a procedure */
|
|
MB_Native_Addr
|
|
MB_code_find_proc_native(MB_CString_Const module_name,
|
|
MB_CString_Const pred_name, MB_Word mode_num,
|
|
MB_Word arity, MB_Bool is_func)
|
|
{
|
|
MR_Matches_Info matches;
|
|
MR_Proc_Spec spec;
|
|
|
|
MR_register_all_modules_and_procs(stderr, FALSE);
|
|
|
|
spec.MR_proc_module = module_name;
|
|
spec.MR_proc_name = pred_name;
|
|
spec.MR_proc_arity = arity;
|
|
spec.MR_proc_mode = mode_num;
|
|
spec.MR_proc_pf = (is_func) ? MR_FUNCTION : MR_PREDICATE;
|
|
|
|
matches = MR_search_for_matching_procedures(&spec);
|
|
|
|
switch (matches.match_proc_next) {
|
|
case 0:
|
|
if (MB_str_cmp("builtin", module_name) == 0) {
|
|
if (mode_num == 0 && is_func == FALSE) {
|
|
if (arity == 2 &&
|
|
MB_str_cmp("unify", pred_name) == 0)
|
|
{
|
|
return MB_native_get_unify_2();
|
|
} else if (arity == 3 &&
|
|
MB_str_cmp("compare", pred_name) == 0)
|
|
{
|
|
return MB_native_get_compare_3();
|
|
}
|
|
|
|
}
|
|
}
|
|
return NULL;
|
|
case 1:
|
|
{
|
|
MB_Native_Addr addr = (MB_Native_Addr)
|
|
matches.match_procs[0]->
|
|
MR_sle_traversal.MR_trav_code_addr;
|
|
}
|
|
return (MB_Native_Addr)matches.match_procs[0]->
|
|
MR_sle_traversal.MR_trav_code_addr;
|
|
default:
|
|
MB_fatal("More than one native code entry found!");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Looks up type constructor info.
|
|
** Guaranteed to succeed (aborts program if it fails)
|
|
*/
|
|
MR_TypeCtorInfo
|
|
MB_type_find_ctor_info_guaranteed(MB_CString_Const module_name,
|
|
MB_CString_Const type_name, MB_Word type_arity)
|
|
{
|
|
MR_TypeCtorInfo ret_val;
|
|
MR_do_init_modules_type_tables();
|
|
|
|
ret_val = MR_lookup_type_ctor_info(module_name, type_name, type_arity);
|
|
|
|
if (ret_val == NULL) {
|
|
MB_util_error("Type %s__%s/" MB_FMT_INT " not found",
|
|
module_name, type_name, type_arity);
|
|
MB_fatal("Unable to find type ctor info");
|
|
}
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
/*
|
|
** A native code procedure wishes to call a deterministic bytecode procedure
|
|
*/
|
|
MB_Native_Addr
|
|
MB_bytecode_call_entry(MB_Call *bytecode_call)
|
|
{
|
|
MB_Bytecode_Addr bc_ip;
|
|
|
|
if ((void *) bytecode_call->cached_ip == NULL) {
|
|
bc_ip = MB_code_find_proc(bytecode_call->module_name,
|
|
bytecode_call->pred_name,
|
|
bytecode_call->mode_num,
|
|
bytecode_call->arity,
|
|
bytecode_call->is_func);
|
|
} else {
|
|
bc_ip = bytecode_call->cached_ip;
|
|
}
|
|
|
|
if (bc_ip == MB_CODE_INVALID_ADR) {
|
|
MB_util_error("Attempting to call bytecode %s %s__%s/"
|
|
MB_FMT_INT " (" MB_FMT_INT "):",
|
|
bytecode_call->is_func ? "func" : "pred",
|
|
bytecode_call->module_name,
|
|
bytecode_call->pred_name,
|
|
bytecode_call->arity,
|
|
bytecode_call->mode_num);
|
|
MB_fatal("Unable to find procedure\n"
|
|
"(Is the native code and the bytecode consistent?)");
|
|
}
|
|
|
|
return MB_machine_exec(bc_ip, NULL);
|
|
}
|
|
|
|
/*
|
|
** Reentry point det bytecode procedure has called native code.
|
|
*/
|
|
MB_Native_Addr
|
|
MB_bytecode_return_det(void)
|
|
{
|
|
/* Get the bytecode reentry address */
|
|
MB_Bytecode_Addr ip = (MB_Bytecode_Addr)
|
|
MB_stackitem(MB_DETFRAME_INTERFACE_BCRETIP);
|
|
/* Get the initial stack frame */
|
|
MB_Word *initial_frame = (MB_Word *)
|
|
MB_stackitem(MB_DETFRAME_INTERFACE_BCINITFR);
|
|
|
|
/* Remove interface frame */
|
|
MB_decr_sp(MB_DETFRAME_INTERFACE_SIZE);
|
|
|
|
/* Execute */
|
|
return MB_machine_exec(ip, initial_frame);
|
|
}
|
|
|
|
/*
|
|
** Reentry point after a redo/fail was executed and used a temp nondet stack
|
|
** frame generated by a det procedure
|
|
*/
|
|
MB_Native_Addr
|
|
MB_bytecode_return_temp_det(void)
|
|
{
|
|
/* Get the bytecode reentry address */
|
|
MB_Bytecode_Addr ip = (MB_Bytecode_Addr)
|
|
MB_fr_temp_det_bcredoip(MB_maxfr);
|
|
/* Get the initial stack frame */
|
|
MB_Word *initial_frame = (MB_Word *)
|
|
MB_fr_temp_det_bcinitfr(MB_maxfr);
|
|
|
|
/* execute */
|
|
return MB_machine_exec(ip, initial_frame);
|
|
}
|
|
|
|
/*
|
|
** Reentry point after a redo/fail was executed and used a temp nondet stack
|
|
** frame generated by a nondet procedure
|
|
*/
|
|
MB_Native_Addr
|
|
MB_bytecode_return_temp_nondet(void)
|
|
{
|
|
/* Get the bytecode reentry address */
|
|
MB_Bytecode_Addr ip = (MB_Bytecode_Addr)
|
|
MB_fr_temp_nondet_bcredoip(MB_maxfr);
|
|
|
|
/* Get the initial stack frame */
|
|
MB_Word *initial_frame = (MB_Word *)
|
|
MB_fr_bcinitfr(MB_curfr);
|
|
|
|
/* execute */
|
|
return MB_machine_exec(ip, initial_frame);
|
|
}
|
|
|
|
/*
|
|
** Reentry point after a call by a nondet procedure
|
|
*/
|
|
MB_Native_Addr
|
|
MB_bytecode_return_nondet(void)
|
|
{
|
|
/* Get the bytecode reentry address */
|
|
MB_Bytecode_Addr ip = (MB_Bytecode_Addr)
|
|
MB_fr_bcretip(MB_curfr);
|
|
/* Get the initial stack frame */
|
|
MB_Word *initial_frame = (MB_Word *)
|
|
MB_fr_bcinitfr(MB_curfr);
|
|
|
|
/* execute */
|
|
return MB_machine_exec(ip, initial_frame);
|
|
}
|
|
|