mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 22:35:41 +00:00
Estimated hours taken: 200
Major changes to bytecode interpreter.
Beginnings of native code integration
bytecode/bytecode.c:
bytecode/bytecode.h:
bytecode/dict.c:
bytecode/dict.h:
bytecode/disasm.c:
bytecode/disasm.h:
bytecode/machine.c:
bytecode/machine.h:
bytecode/mbi_main.c:
bytecode/mdb.m:
bytecode/mem.c:
bytecode/mem.h:
bytecode/slist.c:
bytecode/slist.h:
bytecode/template.c:
bytecode/template.h:
bytecode/util.c:
bytecode/util.h:
Removed. These are all the old bytecode files from
before I started. Any parts that were useful have already
been salvaged and used in the new interpreter.
bytecode/*:
Added MB_Bytecode_Addr and MB_Native_Addr types to remove abiguity
as to what type of code an instruction pointer points to, and
provide compiler help for erroneously mixing pointer types.
bytecode/Mmakefile:
bytecode/Mmake.params:
Makefile for test bytecode program. Note that any library
functions that are called from bytecode must be compiled
with trace information. (So their entry labels can be
looked up)
bytecode/mb_basetypes.h:
Added. Contains basic type definitions.
bytecode/mb_bytecode.c:
bytecode/mb_bytecode.h:
Better error messages.
Changed var_lists to direct pointers rather than
lookups through data stacks (much simpler but stop you
using realloc() on the bytecode argument data)
Label addresses are computed at module load time rather
than being looked up each jump
Added endof_negation_goal
Temporary stack slot numbers are translated to variable
numbers (now there is no distinction between temps & vars)
MB_read_cstring return value convention changed (see comments
for how to now free the returned memory)
Added distinction between functions and predicates
Added enter_else
Code addresses are all pointers rather than simple ints
Added MB_Code_Addr type for pred_const and call instructions
bytecode/mb_disasm.c:
bytecode/mb_disasm.h:
Added endof_negation_goal & enter_else
Output strings are now easier to read
MB_listing does not display anything for invalid addresses
MB_listing takes line length argument
bytecode/mb_interface.c:
bytecode/mb_interface.h:
bytecode/mb_interface_stub.m:
Interfacing between native/bytecode
bytecode/mb_machine.c:
bytecode/mb_machine.h:
bytecode/mb_machine_def.h:
Large sections of code branched off into mb_module.?
Most instructions completed, but not integrated with native
code.
Most of mb_machine_def has been removed as the native
code functions provide the same functionality.
bytecode/mb_machine_show.c:
bytecode/mb_machine_show.h:
Completely changed. Less information now as a lot of what
was being displayed before cannot be determined as easily
now that it is stored in the mercury runtime.
bytecode/mb_mem.c:
bytecode/mb_mem.h:
Added routines for garbage collected memory
bytecode/mb_module.c:
bytecode/mb_module.h:
Loading & accessing bytecode. Argument data indexes & id are now
stored in a single word. (see MB_BCID_xxx macros).
Call & label addresses are now calculated at load time.
bytecode/mb_stack.c:
bytecode/mb_stack.h:
Added options for garbage collection of MB_Stack memory
bytecode/mb_util.c:
bytecode/mb_util.h:
Miscellaneous string functions added and SAY() for debugging
bytecode/simple01.m:
Added. Simple test program. (replace with whatever
program is being tested at the time).
494 lines
9.3 KiB
C
494 lines
9.3 KiB
C
|
|
/*
|
|
** Copyright (C) 1997,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.
|
|
**
|
|
** This file contains the bytecode format and data types
|
|
** This must be the same as that in compiler/bytecode.m
|
|
*/
|
|
|
|
#ifndef MB_BYTECODE_H
|
|
#define MB_BYTECODE_H
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "mercury_conf.h"
|
|
#include "mercury_types.h"
|
|
#include "mercury_float.h"
|
|
|
|
#include "mb_basetypes.h"
|
|
#include "mb_stack.h"
|
|
#include "mb_util.h"
|
|
|
|
typedef struct MB_Tag_Struct {
|
|
MB_Byte id;
|
|
union {
|
|
MB_Byte primary;
|
|
struct {
|
|
MB_Byte primary;
|
|
MB_Word secondary;
|
|
} pair;
|
|
MB_Byte enum_tag;
|
|
} opt;
|
|
} MB_Tag;
|
|
|
|
/*
|
|
* Possible values for Tag.id ...
|
|
*/
|
|
#define MB_TAG_SIMPLE 0
|
|
#define MB_TAG_COMPLICATED 1
|
|
#define MB_TAG_COMPLICATED_CONSTANT 2
|
|
#define MB_TAG_ENUM 3
|
|
#define MB_TAG_NONE 4
|
|
|
|
typedef MB_Byte
|
|
MB_Determinism;
|
|
/*
|
|
* Possible values for Determinism ...
|
|
*/
|
|
#define MB_DET_DET 0
|
|
#define MB_DET_SEMIDET 1
|
|
#define MB_DET_MULTIDET 2
|
|
#define MB_DET_NONDET 3
|
|
#define MB_DET_CC_MULTIDET 4
|
|
#define MB_DET_CC_NONDET 5
|
|
#define MB_DET_ERRONEOUS 6
|
|
#define MB_DET_FAILURE 7
|
|
/*
|
|
** Unusable is used to indicate that there is something wrong with
|
|
** this predicate (probably contains foreign code) and the bytecode
|
|
** version cannot be used
|
|
*/
|
|
#define MB_DET_UNUSABLE 99
|
|
|
|
/* Return true if determinism model is the same as that specified */
|
|
#define MB_model_det(x) (\
|
|
((x) == MB_DET_DET) || \
|
|
((x) == MB_DET_CC_MULTIDET) || \
|
|
((x) == MB_DET_ERRONEOUS))
|
|
|
|
#define MB_model_semi(x) (\
|
|
((x) == MB_DET_SEMIDET) || \
|
|
((x) == MB_DET_CC_NONDET) || \
|
|
((x) == MB_DET_FAILURE))
|
|
|
|
#define MB_model_nondet(x) (\
|
|
((x) == MB_DET_NONDET) || \
|
|
((x) == MB_DET_MULTIDET))
|
|
|
|
|
|
typedef struct MB_Op_arg_struct {
|
|
MB_Byte id;
|
|
union {
|
|
MB_Short var;
|
|
MB_Integer int_const;
|
|
MB_Float float_const;
|
|
} opt;
|
|
} MB_Op_arg;
|
|
|
|
/*
|
|
* Possible values for Op_arg.id
|
|
*/
|
|
#define MB_ARG_VAR 0
|
|
#define MB_ARG_INT_CONST 1
|
|
#define MB_ARG_FLOAT_CONST 2
|
|
|
|
|
|
typedef MB_Byte
|
|
MB_Direction;
|
|
|
|
typedef struct MB_Var_dir_struct {
|
|
MB_Short var;
|
|
MB_Direction dir;
|
|
} MB_Var_dir;
|
|
|
|
/*
|
|
* Possible values for Direction ...
|
|
*/
|
|
#define MB_DIR_TO_ARG 0
|
|
#define MB_DIR_TO_VAR 1
|
|
#define MB_DIR_TO_NONE 2
|
|
|
|
typedef struct {
|
|
/* Whether call is a native code call */
|
|
MB_Bool is_native;
|
|
/* code address to call */
|
|
union {
|
|
MB_Bytecode_Addr bc;
|
|
MB_Native_Addr native;
|
|
} addr;
|
|
} MB_Code_Addr;
|
|
|
|
typedef struct MB_Cons_id_struct {
|
|
MB_Byte id;
|
|
union {
|
|
struct {
|
|
MB_CString module_name;
|
|
MB_CString string;
|
|
MB_Short arity;
|
|
MB_Tag tag;
|
|
} cons;
|
|
MB_Integer int_const;
|
|
MB_CString string_const;
|
|
MB_Float float_const;
|
|
struct {
|
|
MB_CString module_name;
|
|
MB_CString pred_name;
|
|
MB_Short arity;
|
|
MB_Bool is_func;
|
|
MB_Byte mode_num;
|
|
/* Actual call address */
|
|
MB_Code_Addr addr;
|
|
} pred_const;
|
|
struct {
|
|
MB_CString module_name;
|
|
MB_CString pred_name;
|
|
MB_Short arity;
|
|
MB_Byte mode_num;
|
|
} code_addr_const;
|
|
struct {
|
|
MB_CString module_name;
|
|
MB_CString type_name;
|
|
MB_Byte type_arity;
|
|
} base_type_info_const;
|
|
struct {
|
|
MB_Byte ch;
|
|
} char_const;
|
|
} opt;
|
|
} MB_Cons_id;
|
|
|
|
/*
|
|
* Possible values for Cons_id.id ...
|
|
*/
|
|
#define MB_CONSID_CONS 0
|
|
#define MB_CONSID_INT_CONST 1
|
|
#define MB_CONSID_STRING_CONST 2
|
|
#define MB_CONSID_FLOAT_CONST 3
|
|
#define MB_CONSID_PRED_CONST 4
|
|
#define MB_CONSID_CODE_ADDR_CONST 5
|
|
#define MB_CONSID_BASE_TYPE_INFO_CONST 6
|
|
#define MB_CONSID_CHAR_CONST 7
|
|
|
|
/*
|
|
** Internal label structure. At load time the index is read from the file
|
|
** and stored. translate_labels translates indexes into actual memory
|
|
** addresses. The module load and label translation functions are the only
|
|
** only functions that should access index, the rest of the program should
|
|
** only use addr.
|
|
*/
|
|
typedef union {
|
|
MB_Short index;
|
|
MB_Bytecode_Addr addr;
|
|
} MB_Label;
|
|
|
|
typedef union MB_Bytecode_Arg_tag {
|
|
struct {
|
|
MB_CString pred_name;
|
|
MB_Short pred_arity;
|
|
MB_Bool is_func;
|
|
MB_Short proc_count;
|
|
} enter_pred;
|
|
|
|
struct {
|
|
} endof_pred;
|
|
|
|
struct {
|
|
MB_Byte mode_num;
|
|
MB_Determinism det;
|
|
MB_Short label_count;
|
|
MB_Label end_label;
|
|
MB_Short temp_count;
|
|
MB_Short list_length;
|
|
MB_CString *var_info;
|
|
|
|
/*
|
|
** index onto label heap for label indexes
|
|
** (not in the file)
|
|
*/
|
|
MB_Word label_index;
|
|
} enter_proc;
|
|
|
|
struct {
|
|
/* start of proc (not in file) */
|
|
MB_Bytecode_Addr proc_start;
|
|
} endof_proc;
|
|
|
|
struct {
|
|
MB_Short label;
|
|
} label;
|
|
|
|
struct {
|
|
MB_Label end_label;
|
|
} enter_disjunction;
|
|
|
|
struct {
|
|
} endof_disjunction;
|
|
|
|
struct {
|
|
MB_Label next_label;
|
|
} enter_disjunct;
|
|
|
|
struct {
|
|
MB_Label end_label;
|
|
} endof_disjunct;
|
|
|
|
struct {
|
|
MB_Short var;
|
|
MB_Label end_label;
|
|
} enter_switch;
|
|
|
|
struct {
|
|
|
|
} endof_switch;
|
|
|
|
struct {
|
|
MB_Cons_id cons_id;
|
|
MB_Label next_label;
|
|
|
|
/* filled in at load time */
|
|
MB_Short var;
|
|
} enter_switch_arm;
|
|
|
|
struct {
|
|
MB_Label end_label;
|
|
} endof_switch_arm;
|
|
|
|
struct {
|
|
MB_Label else_label;
|
|
MB_Label end_label;
|
|
MB_Short frame_ptr_tmp;
|
|
} enter_if;
|
|
|
|
/*
|
|
** identical to enter_else: if you change this, modify instr_else
|
|
** to reflect
|
|
*/
|
|
struct {
|
|
MB_Short frame_ptr_tmp;
|
|
} enter_then;
|
|
|
|
struct {
|
|
MB_Label follow_label;
|
|
} endof_then;
|
|
|
|
/*
|
|
** identical to enter_then: if you change this, modify instr_then
|
|
** to reflect
|
|
*/
|
|
struct {
|
|
MB_Short frame_ptr_tmp;
|
|
} enter_else;
|
|
|
|
struct {
|
|
|
|
} endof_if;
|
|
|
|
struct {
|
|
MB_Short frame_ptr_tmp;
|
|
MB_Label end_label;
|
|
} enter_negation;
|
|
|
|
struct {
|
|
MB_Short frame_ptr_tmp;
|
|
} endof_negation_goal;
|
|
|
|
struct {
|
|
} endof_negation;
|
|
|
|
struct {
|
|
MB_Short frame_ptr_tmp;
|
|
} enter_commit;
|
|
|
|
struct {
|
|
MB_Short frame_ptr_tmp;
|
|
} endof_commit;
|
|
|
|
struct {
|
|
MB_Short to_var;
|
|
MB_Short from_var;
|
|
} assign;
|
|
|
|
struct {
|
|
MB_Short var1;
|
|
MB_Short var2;
|
|
} test;
|
|
|
|
struct {
|
|
MB_Short to_var;
|
|
MB_Cons_id consid;
|
|
MB_Short list_length;
|
|
MB_Short *var_list;
|
|
} construct;
|
|
|
|
struct {
|
|
MB_Short from_var;
|
|
MB_Cons_id consid;
|
|
MB_Short list_length;
|
|
MB_Short *var_list;
|
|
} deconstruct;
|
|
|
|
struct {
|
|
MB_Short to_var;
|
|
MB_Cons_id consid;
|
|
MB_Short list_length;
|
|
MB_Var_dir *var_dir;
|
|
} complex_construct;
|
|
|
|
struct {
|
|
MB_Short from_var;
|
|
MB_Cons_id consid;
|
|
MB_Short list_length;
|
|
MB_Var_dir *var_dir;
|
|
} complex_deconstruct;
|
|
|
|
struct {
|
|
MB_Byte to_reg;
|
|
MB_Short from_var;
|
|
} place_arg;
|
|
|
|
struct {
|
|
MB_Byte from_reg;
|
|
MB_Short to_var;
|
|
} pickup_arg;
|
|
|
|
struct {
|
|
MB_CString module_name;
|
|
MB_CString pred_name;
|
|
MB_Short arity;
|
|
MB_Bool is_func;
|
|
MB_Byte mode_num;
|
|
/* actual call address */
|
|
MB_Code_Addr addr;
|
|
} call;
|
|
|
|
struct {
|
|
MB_Short pred_var;
|
|
MB_Short in_var_count;
|
|
MB_Short out_var_count;
|
|
MB_Determinism det;
|
|
} higher_order_call;
|
|
|
|
struct {
|
|
MB_Byte binop;
|
|
MB_Op_arg arg1;
|
|
MB_Op_arg arg2;
|
|
MB_Short to_var;
|
|
} builtin_binop;
|
|
|
|
struct {
|
|
MB_Byte unop;
|
|
MB_Op_arg arg;
|
|
MB_Short to_var;
|
|
} builtin_unop;
|
|
|
|
struct {
|
|
MB_Byte binop;
|
|
MB_Op_arg arg1;
|
|
MB_Op_arg arg2;
|
|
} builtin_bintest;
|
|
|
|
struct {
|
|
MB_Byte unop;
|
|
MB_Op_arg arg;
|
|
} builtin_untest;
|
|
|
|
struct {
|
|
} semidet_succeed;
|
|
|
|
struct {
|
|
} semidet_success_check;
|
|
|
|
struct {
|
|
} fail;
|
|
|
|
struct {
|
|
/* XXX: is this int or short?? */
|
|
MB_Short line_number;
|
|
} context;
|
|
|
|
struct {
|
|
} not_supported;
|
|
|
|
} MB_Bytecode_Arg;
|
|
|
|
typedef struct MB_Bytecode_struct {
|
|
MB_Byte id; /* Which bytecode instruction. e.g. BC_fail */
|
|
MB_Bytecode_Arg opt;
|
|
} MB_Bytecode;
|
|
|
|
/*
|
|
** Possible Bytecode.id values
|
|
*/
|
|
#define MB_BC_enter_pred 0
|
|
#define MB_BC_endof_pred 1
|
|
#define MB_BC_enter_proc 2
|
|
#define MB_BC_endof_proc 3
|
|
#define MB_BC_label 4
|
|
#define MB_BC_enter_disjunction 5
|
|
#define MB_BC_endof_disjunction 6
|
|
#define MB_BC_enter_disjunct 7
|
|
#define MB_BC_endof_disjunct 8
|
|
#define MB_BC_enter_switch 9
|
|
#define MB_BC_endof_switch 10
|
|
#define MB_BC_enter_switch_arm 11
|
|
#define MB_BC_endof_switch_arm 12
|
|
#define MB_BC_enter_if 13
|
|
#define MB_BC_enter_then 14
|
|
#define MB_BC_endof_then 15
|
|
#define MB_BC_endof_if 16
|
|
#define MB_BC_enter_negation 17
|
|
#define MB_BC_endof_negation 18
|
|
#define MB_BC_enter_commit 19
|
|
#define MB_BC_endof_commit 20
|
|
#define MB_BC_assign 21
|
|
#define MB_BC_test 22
|
|
#define MB_BC_construct 23
|
|
#define MB_BC_deconstruct 24
|
|
#define MB_BC_complex_construct 25
|
|
#define MB_BC_complex_deconstruct 26
|
|
#define MB_BC_place_arg 27
|
|
#define MB_BC_pickup_arg 28
|
|
#define MB_BC_call 29
|
|
#define MB_BC_higher_order_call 30
|
|
#define MB_BC_builtin_binop 31
|
|
#define MB_BC_builtin_unop 32
|
|
#define MB_BC_builtin_bintest 33
|
|
#define MB_BC_builtin_untest 34
|
|
#define MB_BC_semidet_succeed 35
|
|
#define MB_BC_semidet_success_check 36
|
|
#define MB_BC_fail 37
|
|
#define MB_BC_context 38
|
|
#define MB_BC_not_supported 39
|
|
#define MB_BC_enter_else 40
|
|
#define MB_BC_endof_negation_goal 41
|
|
|
|
/* These are used internally by the interpreter */
|
|
/* all codes above MB_BC_debug are debugging values */
|
|
#define MB_BC_debug 0x3d
|
|
#define MB_BC_debug_trap 0x3e
|
|
#define MB_BC_debug_invalid 0x3f
|
|
/*
|
|
** Note that the limit to these is determined in mb_module.c by the
|
|
** number of bits allocated to an id
|
|
*/
|
|
|
|
/*
|
|
** Read the next bytecode from the stream fp.
|
|
** If no bytecode can be read, return FALSE.
|
|
** Otherwise, return TRUE.
|
|
*/
|
|
MB_Bool
|
|
MB_read_bytecode(FILE *fp, MB_Bytecode *bc_p);
|
|
|
|
/*
|
|
** Read the bytecode version number from the stream fp.
|
|
** If the version number cannot be read, return FALSE.
|
|
** Otherwise, return TRUE.
|
|
*/
|
|
MB_Bool
|
|
MB_read_bytecode_version_number(FILE *fp, MB_Short *version_number_p);
|
|
|
|
#endif /* MB_BYTECODE_H */
|
|
|