mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 21:35:49 +00:00
Estimated hours taken: 16 Branches: main Get Mercury to work with gcc 3.4. This required fixing several problems. One problem that caused errors is that gcc 3.4 is smart enough to figure out that in LLDS grades with gcc gotos, the C functions containing our code are not referred to, and so it optimizes them away. The fix is to ensure that mercury_<module>_init is defined always to call those functions, even if the macro that usually controls this, MR_MAY_NEED_INITIALIZATION, is not defined. The mercury_<module>_init won't be called from the init_modules function in the program's _init.c file, so there is no impact on initialization time, but gcc doesn't know this when compiling a module's .c file, so it doesn't optimize away the code we need. The cost of this change is thus only a small amount of code space. It is worth paying this cost even with compilers other than gcc 3.4 for simplicity. Actually, this size increase seems to be slightly smaller than the size reduction due to the better optimization capabilities of gcc 3.4 compared to gcc 3.2.2. A second problem is that gcc 3.4 warns about casts in lvalues being a deprecated feature. This gave lots of warnings, since we used to define several Mercury abstract machine registers, including MR_succip, MR_hp, MR_sp, MR_maxfr and MR_curfr using lvalue casts. The fix is to have two macros for each of these abstract machine registers, one of type MR_Word that you can assign to (e.g. MR_sp_word), and one of the original type that is of the right type but not an lvalue (e.g. MR_sp). The lvalue itself can't be made the right type, because MR_sp isn't a variable in its own right, but possibly defined to be a machine register. The machine register could made the right type, but only at the cost of a lot of complexity. This problem doesn't apply to the special-purpose Mercury abstract machine registers that can't be allocated to machine registers. Instead of #defining these to slots in MR_fake_reg, we make them global variables of the natural type. This should also make it easier to debug code using these registers. We treat these global variables as if they were machine registers in that MR_save_registers copies values from these global variables to slots reserved for them in the MR_fake_reg array, to allow code to loop over all Mercury abstract machine registers. These saved slots must of course be of type MR_Word, so we again need two macros to refer to them, a lvalue of type MR_Word and an rvalue with the right type. A third problem is that gcc 3.4 warns about conditionals in lvalues being a deprecated feature. This gave a few warnings, since we used to define MR_virtual_reg and MR_saved_reg using lvalues using conditionals. The fix is to have one macro (MR_virtual_reg_value) for use in rvalues and a separate macro which uses an if-then-else instead of a conditional expression (MR_virtual_reg_assign), for assignments. A fourth problem is that gcc 3.4 warns about comma operators in lvalues being a deprecated feature. This gave warnings in the few places where we refer to MR_r(N) for values of N that can map to fake registers directly, since in those cases we preceded the reference to the fake_reg array with a range check of the array index. The fix to this is to move the test to compile time for compiler-generated code. Hand-written code never refers to MR_r(N) for these values, and is very unlikely to do so in the future; instead, it refers to the underlying fake_reg array directly, since that way it doesn't have to worry about which fake registers have their own MR_rN macro and which don't. Therefore no check mechanism for hand-written code is necessary. This change mean that changing the number of MR_rN registers now requires change to the compiler as well as to the runtime system. A fifth problem is that gcc 3.4 by default assumes -fstrict-aliasing at -O2. Since we cast between integers and pointers of different types all the time, and changing that is not practical, at least in the short term, we need to disable -fstrict-aliasing when we enable -O2. NEWS: Note that Mercury now works with gcc 3.4. configure.in: scripts/mgnuc.in: Detect whether the compiler supports -fstrict-aliasing, and if so, whether it assumes it by default with -O2. If the answer is yes to both, make mgnuc specify -fno-strict-aliasing when it specifies -O2. By including it in CFLAGS_FOR_OPT, which gets put into Mercury.config, we also get -f-no-strict-aliasing when mmc invokes the C compiler directly. compiler/llds_out.m: Don't generate #ifdef MR_MAY_NEED_INITIALIZATION around the definitions and calls to the bunch functions, which call the functions we don't want the C compiler to optimize away. Generate the newly required lvalues on the left sides of assignments. We still have code to generate LVALUE_CASTs in some cases, but I don't think those cases ever arise. Add a compile-time check of register numbers. Ideally, the code generator should use stack slots instead of registers beyond the max number, but I don't recall us ever bumping into this limit by accident. compiler/fact_table.m: Use the newly required lvalues on the left sides of assignments in some hand-written C code included in generated .c files. runtime/mercury_regs.h: Make the changes described above to fix the second, third and fourth problems. We still use comma operators in lvalues when counting references to registers, but it is OK to require anyone who wants to enable this feature to use a compiler version that supports comma operators in lvalues or to ignore the warnings. Use the same mapping from Mercury abstract machine registers to the register count array as to the MR_fake_reg array. Have this mapping depend as little as possible on whether we need a real machine register to store MR_engine base, even if it costs a wasted slot in MR_fake_reg. Fix an old inconsistency: treat the Mercury abstract machine registers used for trailing the same way as the other Mercury abstract machine registers, by making MR_save_registers/MR_restore_registers copy them to and from their global variable homes. Document the requirement for the match between the runtime's and the compiler's notions of the maximum MR_rN register number. This requirement makes it harder for users to increase the number of virtual registers, but as far as I know noone has wanted to do this. Change the names of some of the macros to make them clearer. Reorder some parts of this file, and add some documentation, also in the interest of clarity. runtime/mercury_regorder.h: Delete this file after moving its contents, in much modified form, to mercury_regs.h. mercury_regorder.h was always logically part of mercury_regs.h, but was separated out to make it easier to change the mapping from Mercury abstract machine registers to machine registers. However, the cost of incompatibility caused by any such changes would be much greater that any likely performance benefit. runtime/Mmakefile: Remove the reference to mercury_regorder.h. runtime/mercury_regs.[ch]: runtime/mercury_memory_zones.[ch]: Move some functionality dealing with registers from mercury_memory_zones to mercury_regs, since it belongs there. runtime/mercury_regs.[ch]: Add a function to make it easiler to debug changes to map from Mercury abstract machine to MR_fake_reg slots. runtime/mercury_regs.[ch]: runtime/mercury_wrapper.c: Move the code to print counts of register uses from mercury_wrapper.c to mercury_regs.c. Make mercury_wrapper.c call the debugging function in mercury_regs.c if -X is specified in MERCURY_OPTIONS. runtime/mercury_bootstrap.h: Move the old MR_saved_reg and MR_virtual_reg macros from mercury_regs.h to mercury_bootstrap.h to prevent their accidental use. Since they shouldn't be used by user code, move them to the section that is not enabled by default. runtime/mercury_stacks.[ch]: Add _word versions of the macros for stack slots, for the same reason why we need them for Mercury abstract machine registers, and use them. Add global variables for the Mercury abstract machine registers for the gen, cut and pneg stacks. runtime/mercury_heap.h: Change the macros for allocating memory to assign to MR_hp_word instead of MR_hp. runtime/mercury_string.h: Change the macros for allocating strings to accomodate the updates to mercury_heap.h. Also change the expected type of the target to make it MR_String instead of MR_ConstString, since the latter requires casts in the caller. runtime/mercury_trail.h: runtime/mercury_types.h: Move the definition of the type MR_TrailEntry from mercury_trail.h to mercury_types.h, since it is now used in mercury_regs.h. runtime/mercury_accurate_gc.c: runtime/mercury_agc_debug.c: runtime/mercury_calls.h: runtime/mercury_context.[ch]: runtime/mercury_deconstruct_macros.h: runtime/mercury_deep_copy_body.h: runtime/mercury_engine.[ch]: runtime/mercury_hand_compare_body.h: runtime/mercury_hand_unify_body.h: runtime/mercury_ho_call.c: runtime/mercury_layout_util.c: runtime/mercury_make_type_info_body.h: runtime/mercury_minimal_model.c: runtime/mercury_ml_deconstruct_body.h: runtime/mercury_ml_functor_body.h: runtime/mercury_stack_layout.h: runtime/mercury_type_desc.c: runtime/mercury_type_info.c: runtime/mercury_unify_compare_body.h: runtime/mercury_wrapper.c: Conform to the changes in the rest of the runtime. In some cases, fix inconsistencies in indentation. runtime/mercury_stack_trace.c: Add some conditionally compiled debugging code controlled by the macro MR_ADDR_DEBUG, to help debug some problems with stored stack pointers. runtime/mercury_grade.h: Increment the binary compatibility version number. This is needed to avoid potential problems when a Mercury module and the debugger are compiled with different versions of the macros in mercury_regs.h. library/exception.m: Update the code that assigns to abstract machine registers. library/array.m: library/construct.m: library/dir.m: library/io.m: library/string.m: Conform to the new definitions of allocation macros. library/time.m: Delete an unnecessary #include. trace/mercury_trace.c: trace/mercury_trace_declarative.c: trace/mercury_trace_util.c: Conform to the changes in the rest of the runtime. tests/hard_coded/qual_test_is_imported.m: tests/hard_coded/aditi_private_builtin.m: Remove an unnecessary import to avoid a warning. tools/makebatch: Add an option --save-stage2-on-error, that saves the stage2 directory if a bootcheck fails. scripts/ml.in: Make ml more robust in the face of garbage files.
917 lines
20 KiB
C
917 lines
20 KiB
C
/*
|
|
** Copyright (C) 1998-2004 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 implements utilities that can be useful
|
|
** for both the internal and external debuggers.
|
|
**
|
|
** Main authors: Zoltan Somogyi and Fergus Henderson.
|
|
*/
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_stack_layout.h"
|
|
#include "mercury_layout_util.h"
|
|
|
|
static MR_Word MR_lookup_closure_long_lval(MR_Long_Lval locn,
|
|
MR_Closure *closure, MR_bool *succeeded);
|
|
static MR_Word MR_lookup_typeclass_info_long_lval(MR_Long_Lval locn,
|
|
MR_Word typeclass_info, MR_bool *succeeded);
|
|
static MR_Word MR_lookup_answer_block_long_lval(MR_Long_Lval locn,
|
|
MR_Word *answer_block, int block_size, MR_bool *succeeded);
|
|
|
|
void
|
|
MR_copy_regs_to_saved_regs(int max_mr_num, MR_Word *saved_regs)
|
|
{
|
|
/*
|
|
** In the process of browsing within the debugger, we call Mercury,
|
|
** which may clobber the contents of the virtual machine registers,
|
|
** both control and general purpose, and both real and virtual
|
|
** registers. We must therefore save and restore these.
|
|
** We store them in the saved_regs array.
|
|
**
|
|
** The call to MR_trace will clobber the transient registers
|
|
** on architectures that have them. The compiler generated code
|
|
** will therefore call MR_save_transient_registers to save the
|
|
** transient registers in the fake_reg array. We here restore them
|
|
** to the real registers, save them with the other registers back in
|
|
** fake_reg, and then copy all fake_reg entries to saved_regs.
|
|
*/
|
|
|
|
int i;
|
|
|
|
MR_restore_transient_registers();
|
|
MR_save_registers();
|
|
|
|
for (i = 0; i <= max_mr_num; i++) {
|
|
saved_regs[i] = MR_fake_reg[i];
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_copy_saved_regs_to_regs(int max_mr_num, MR_Word *saved_regs)
|
|
{
|
|
/*
|
|
** We execute the converse procedure to MR_copy_regs_to_saved_regs.
|
|
** The MR_save_transient_registers is there so that a call to the
|
|
** MR_restore_transient_registers macro after MR_trace will do the
|
|
** right thing.
|
|
*/
|
|
|
|
int i;
|
|
|
|
for (i = 0; i <= max_mr_num; i++) {
|
|
MR_fake_reg[i] = saved_regs[i];
|
|
}
|
|
|
|
MR_restore_registers();
|
|
MR_save_transient_registers();
|
|
}
|
|
|
|
MR_TypeInfoParams
|
|
MR_materialize_type_params(const MR_Label_Layout *label_layout,
|
|
MR_Word *saved_regs)
|
|
{
|
|
return MR_materialize_type_params_base(label_layout, saved_regs,
|
|
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs));
|
|
}
|
|
|
|
MR_TypeInfoParams
|
|
MR_materialize_type_params_base(const MR_Label_Layout *label_layout,
|
|
MR_Word *saved_regs, MR_Word *base_sp, MR_Word *base_curfr)
|
|
{
|
|
const MR_Type_Param_Locns *tvar_locns;
|
|
|
|
tvar_locns = label_layout->MR_sll_tvars;
|
|
if (tvar_locns != NULL) {
|
|
MR_TypeInfoParams type_params;
|
|
MR_bool succeeded;
|
|
MR_Integer count;
|
|
int i;
|
|
|
|
count = tvar_locns->MR_tp_param_count;
|
|
type_params = (MR_TypeInfoParams)
|
|
MR_NEW_ARRAY(MR_Word, count + 1);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (tvar_locns->MR_tp_param_locns[i] != 0)
|
|
{
|
|
type_params[i + 1] = (MR_TypeInfo)
|
|
MR_lookup_long_lval_base(
|
|
tvar_locns->
|
|
MR_tp_param_locns[i],
|
|
saved_regs, base_sp, base_curfr,
|
|
&succeeded);
|
|
if (! succeeded) {
|
|
MR_fatal_error("missing type param in "
|
|
"MR_materialize_type_params_base");
|
|
}
|
|
}
|
|
}
|
|
|
|
return type_params;
|
|
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
MR_TypeInfoParams
|
|
MR_materialize_closure_type_params(MR_Closure *closure)
|
|
{
|
|
const MR_Type_Param_Locns *tvar_locns;
|
|
|
|
tvar_locns = closure->MR_closure_layout->MR_closure_type_params;
|
|
if (tvar_locns != NULL) {
|
|
MR_TypeInfoParams type_params;
|
|
MR_bool succeeded;
|
|
MR_Integer count;
|
|
int i;
|
|
|
|
count = tvar_locns->MR_tp_param_count;
|
|
type_params = (MR_TypeInfoParams)
|
|
MR_NEW_ARRAY(MR_Word, count + 1);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (tvar_locns->MR_tp_param_locns[i] != 0)
|
|
{
|
|
type_params[i + 1] = (MR_TypeInfo)
|
|
MR_lookup_closure_long_lval(
|
|
tvar_locns->
|
|
MR_tp_param_locns[i],
|
|
closure, &succeeded);
|
|
if (! succeeded) {
|
|
MR_fatal_error("missing type param in "
|
|
"MR_materialize_closure_type_params");
|
|
}
|
|
}
|
|
}
|
|
|
|
return type_params;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
MR_TypeInfoParams
|
|
MR_materialize_typeclass_info_type_params(MR_Word typeclass_info,
|
|
MR_Closure_Layout *closure_layout)
|
|
{
|
|
const MR_Type_Param_Locns *tvar_locns;
|
|
|
|
tvar_locns = closure_layout->MR_closure_type_params;
|
|
if (tvar_locns != NULL) {
|
|
MR_TypeInfoParams type_params;
|
|
MR_bool succeeded;
|
|
MR_Integer count;
|
|
int i;
|
|
|
|
count = tvar_locns->MR_tp_param_count;
|
|
type_params = (MR_TypeInfoParams)
|
|
MR_NEW_ARRAY(MR_Word, count + 1);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (tvar_locns->MR_tp_param_locns[i] != 0)
|
|
{
|
|
type_params[i + 1] = (MR_TypeInfo)
|
|
MR_lookup_typeclass_info_long_lval(
|
|
tvar_locns->
|
|
MR_tp_param_locns[i],
|
|
typeclass_info, &succeeded);
|
|
if (! succeeded) {
|
|
MR_fatal_error("missing type param in "
|
|
"MR_materialize_typeclass_info_type_params");
|
|
}
|
|
}
|
|
}
|
|
|
|
return type_params;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
MR_TypeInfoParams
|
|
MR_materialize_answer_block_type_params(const MR_Type_Param_Locns *tvar_locns,
|
|
MR_Word *answer_block, int block_size)
|
|
{
|
|
if (tvar_locns != NULL) {
|
|
MR_TypeInfoParams type_params;
|
|
MR_bool succeeded;
|
|
MR_Integer count;
|
|
int i;
|
|
|
|
count = tvar_locns->MR_tp_param_count;
|
|
type_params = (MR_TypeInfoParams)
|
|
MR_NEW_ARRAY(MR_Word, count + 1);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (tvar_locns->MR_tp_param_locns[i] != 0)
|
|
{
|
|
type_params[i + 1] = (MR_TypeInfo)
|
|
MR_lookup_answer_block_long_lval(
|
|
tvar_locns->
|
|
MR_tp_param_locns[i],
|
|
answer_block, block_size,
|
|
&succeeded);
|
|
if (! succeeded) {
|
|
MR_fatal_error("missing type param in "
|
|
"MR_materialize_answer_block_type_params");
|
|
}
|
|
}
|
|
}
|
|
|
|
return type_params;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
int
|
|
MR_get_register_number_long(MR_Long_Lval locn)
|
|
{
|
|
if (MR_LONG_LVAL_TYPE(locn) == MR_LONG_LVAL_TYPE_R) {
|
|
return MR_LONG_LVAL_NUMBER(locn);
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int
|
|
MR_get_register_number_short(MR_Short_Lval locn)
|
|
{
|
|
if (MR_SHORT_LVAL_TYPE(locn) == MR_SHORT_LVAL_TYPE_R) {
|
|
return locn >> MR_SHORT_LVAL_TAGBITS;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
#ifdef MR_DEBUG_LVAL_REP
|
|
#define MR_print_locn MR_printlocndebug
|
|
#else
|
|
#define MR_print_locn MR_FALSE
|
|
#endif
|
|
|
|
MR_Word
|
|
MR_lookup_long_lval(MR_Long_Lval locn, MR_Word *saved_regs, MR_bool *succeeded)
|
|
{
|
|
return MR_lookup_long_lval_base(locn, saved_regs,
|
|
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
|
|
succeeded);
|
|
}
|
|
|
|
static MR_Word
|
|
MR_lookup_closure_long_lval(MR_Long_Lval locn, MR_Closure *closure,
|
|
MR_bool *succeeded)
|
|
{
|
|
int locn_num;
|
|
int offset;
|
|
MR_Word value;
|
|
MR_Word baseaddr;
|
|
MR_Word sublocn;
|
|
|
|
*succeeded = MR_FALSE;
|
|
value = 0;
|
|
|
|
locn_num = (int) MR_LONG_LVAL_NUMBER(locn);
|
|
switch (MR_LONG_LVAL_TYPE(locn)) {
|
|
case MR_LONG_LVAL_TYPE_R:
|
|
if (MR_print_locn) {
|
|
printf("closure r%d\n", locn_num);
|
|
}
|
|
if (locn_num <= closure->MR_closure_num_hidden_args) {
|
|
value = closure->
|
|
MR_closure_hidden_args(locn_num);
|
|
*succeeded = MR_TRUE;
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_F:
|
|
if (MR_print_locn) {
|
|
printf("closure f%d\n", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_STACKVAR:
|
|
if (MR_print_locn) {
|
|
printf("closure stackvar%d\n", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_FRAMEVAR:
|
|
if (MR_print_locn) {
|
|
printf("closure framevar%d\n", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SUCCIP:
|
|
if (MR_print_locn) {
|
|
printf("closure succip\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_MAXFR:
|
|
if (MR_print_locn) {
|
|
printf("closure maxfr\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_CURFR:
|
|
if (MR_print_locn) {
|
|
printf("closure curfr\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_HP:
|
|
if (MR_print_locn) {
|
|
printf("closure hp\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SP:
|
|
if (MR_print_locn) {
|
|
printf("closure sp\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_INDIRECT:
|
|
offset = MR_LONG_LVAL_INDIRECT_OFFSET(locn_num);
|
|
sublocn = MR_LONG_LVAL_INDIRECT_BASE_LVAL(locn_num);
|
|
if (MR_print_locn) {
|
|
printf("closure offset %d from ", offset);
|
|
}
|
|
baseaddr = MR_lookup_closure_long_lval(sublocn,
|
|
closure, succeeded);
|
|
if (! *succeeded) {
|
|
break;
|
|
}
|
|
value = MR_typeclass_info_param_type_info(baseaddr,
|
|
offset);
|
|
*succeeded = MR_TRUE;
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_UNKNOWN:
|
|
if (MR_print_locn) {
|
|
printf("closure unknown\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (MR_print_locn) {
|
|
printf("closure DEFAULT\n");
|
|
}
|
|
break;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
static MR_Word
|
|
MR_lookup_typeclass_info_long_lval(MR_Long_Lval locn, MR_Word typeclass_info,
|
|
MR_bool *succeeded)
|
|
{
|
|
int locn_num;
|
|
int offset;
|
|
MR_Word value;
|
|
MR_Word baseaddr;
|
|
MR_Word sublocn;
|
|
|
|
*succeeded = MR_FALSE;
|
|
value = 0;
|
|
|
|
locn_num = (int) MR_LONG_LVAL_NUMBER(locn);
|
|
switch (MR_LONG_LVAL_TYPE(locn)) {
|
|
case MR_LONG_LVAL_TYPE_R:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo r%d\n", locn_num);
|
|
}
|
|
if (locn_num <=
|
|
MR_typeclass_info_num_extra_instance_args(
|
|
typeclass_info))
|
|
{
|
|
value = MR_typeclass_info_arg_typeclass_info(
|
|
typeclass_info, locn_num);
|
|
*succeeded = MR_TRUE;
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_F:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo f%d\n", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_STACKVAR:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo stackvar%d\n", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_FRAMEVAR:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo framevar%d\n", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SUCCIP:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo succip\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_MAXFR:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo maxfr\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_CURFR:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo curfr\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_HP:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo hp\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SP:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo sp\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_INDIRECT:
|
|
offset = MR_LONG_LVAL_INDIRECT_OFFSET(locn_num);
|
|
sublocn = MR_LONG_LVAL_INDIRECT_BASE_LVAL(locn_num);
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo offset %d from ", offset);
|
|
}
|
|
baseaddr = MR_lookup_typeclass_info_long_lval(sublocn,
|
|
typeclass_info, succeeded);
|
|
if (! *succeeded) {
|
|
break;
|
|
}
|
|
value = MR_typeclass_info_param_type_info(baseaddr,
|
|
offset);
|
|
*succeeded = MR_TRUE;
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_UNKNOWN:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo unknown\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (MR_print_locn) {
|
|
printf("typeclassinfo DEFAULT\n");
|
|
}
|
|
break;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
static MR_Word
|
|
MR_lookup_answer_block_long_lval(MR_Long_Lval locn, MR_Word *answer_block,
|
|
int block_size, MR_bool *succeeded)
|
|
{
|
|
int locn_num;
|
|
int offset;
|
|
MR_Word value;
|
|
MR_Word baseaddr;
|
|
MR_Word sublocn;
|
|
|
|
*succeeded = MR_FALSE;
|
|
value = 0;
|
|
|
|
locn_num = (int) MR_LONG_LVAL_NUMBER(locn);
|
|
switch (MR_LONG_LVAL_TYPE(locn)) {
|
|
case MR_LONG_LVAL_TYPE_R:
|
|
if (MR_print_locn) {
|
|
printf("answer_block r%d\n", locn_num);
|
|
}
|
|
if (locn_num <= block_size) {
|
|
value = answer_block[locn_num];
|
|
*succeeded = MR_TRUE;
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_F:
|
|
if (MR_print_locn) {
|
|
printf("answer_block f%d\n", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_STACKVAR:
|
|
if (MR_print_locn) {
|
|
printf("answer_block stackvar%d\n", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_FRAMEVAR:
|
|
if (MR_print_locn) {
|
|
printf("answer_block framevar%d\n", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SUCCIP:
|
|
if (MR_print_locn) {
|
|
printf("answer_block succip\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_MAXFR:
|
|
if (MR_print_locn) {
|
|
printf("answer_block maxfr\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_CURFR:
|
|
if (MR_print_locn) {
|
|
printf("answer_block curfr\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_HP:
|
|
if (MR_print_locn) {
|
|
printf("answer_block hp\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SP:
|
|
if (MR_print_locn) {
|
|
printf("answer_block sp\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_INDIRECT:
|
|
offset = MR_LONG_LVAL_INDIRECT_OFFSET(locn_num);
|
|
sublocn = MR_LONG_LVAL_INDIRECT_BASE_LVAL(locn_num);
|
|
if (MR_print_locn) {
|
|
printf("answer_block offset %d from ", offset);
|
|
}
|
|
baseaddr = MR_lookup_answer_block_long_lval(sublocn,
|
|
answer_block, block_size, succeeded);
|
|
if (! *succeeded) {
|
|
break;
|
|
}
|
|
value = MR_typeclass_info_param_type_info(baseaddr,
|
|
offset);
|
|
*succeeded = MR_TRUE;
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_UNKNOWN:
|
|
if (MR_print_locn) {
|
|
printf("answer_block unknown\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (MR_print_locn) {
|
|
printf("answer_block DEFAULT\n");
|
|
}
|
|
break;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
MR_Word
|
|
MR_lookup_long_lval_base(MR_Long_Lval locn, MR_Word *saved_regs,
|
|
MR_Word *base_sp, MR_Word *base_curfr, MR_bool *succeeded)
|
|
{
|
|
int locn_num;
|
|
int offset;
|
|
MR_Word value;
|
|
MR_Word baseaddr;
|
|
MR_Word sublocn;
|
|
|
|
*succeeded = MR_FALSE;
|
|
value = 0;
|
|
|
|
locn_num = (int) MR_LONG_LVAL_NUMBER(locn);
|
|
switch (MR_LONG_LVAL_TYPE(locn)) {
|
|
case MR_LONG_LVAL_TYPE_R:
|
|
if (MR_print_locn) {
|
|
printf("long r%d\n", locn_num);
|
|
}
|
|
if (saved_regs != NULL) {
|
|
value = MR_saved_reg_value(saved_regs,
|
|
locn_num);
|
|
*succeeded = MR_TRUE;
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_F:
|
|
if (MR_print_locn) {
|
|
printf("long f%d\n", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_STACKVAR:
|
|
if (MR_print_locn) {
|
|
printf("long stackvar%d\n", locn_num);
|
|
}
|
|
value = MR_based_stackvar(base_sp, locn_num);
|
|
*succeeded = MR_TRUE;
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_FRAMEVAR:
|
|
if (MR_print_locn) {
|
|
printf("long framevar%d\n", locn_num);
|
|
}
|
|
value = MR_based_framevar(base_curfr, locn_num);
|
|
*succeeded = MR_TRUE;
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SUCCIP:
|
|
if (MR_print_locn) {
|
|
printf("long succip\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_MAXFR:
|
|
if (MR_print_locn) {
|
|
printf("long maxfr\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_CURFR:
|
|
if (MR_print_locn) {
|
|
printf("long curfr\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_HP:
|
|
if (MR_print_locn) {
|
|
printf("long hp\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SP:
|
|
if (MR_print_locn) {
|
|
printf("long sp\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_INDIRECT:
|
|
offset = MR_LONG_LVAL_INDIRECT_OFFSET(locn_num);
|
|
sublocn = MR_LONG_LVAL_INDIRECT_BASE_LVAL(locn_num);
|
|
if (MR_print_locn) {
|
|
printf("long offset %d from ", offset);
|
|
}
|
|
baseaddr = MR_lookup_long_lval_base(sublocn,
|
|
saved_regs, base_sp, base_curfr,
|
|
succeeded);
|
|
if (! *succeeded) {
|
|
break;
|
|
}
|
|
value = MR_typeclass_info_param_type_info(baseaddr,
|
|
offset);
|
|
*succeeded = MR_TRUE;
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_UNKNOWN:
|
|
if (MR_print_locn) {
|
|
printf("long unknown\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (MR_print_locn) {
|
|
printf("long DEFAULT\n");
|
|
}
|
|
break;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
MR_Word
|
|
MR_lookup_short_lval(MR_Short_Lval locn, MR_Word *saved_regs,
|
|
MR_bool *succeeded)
|
|
{
|
|
return MR_lookup_short_lval_base(locn, saved_regs,
|
|
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
|
|
succeeded);
|
|
}
|
|
|
|
MR_Word
|
|
MR_lookup_short_lval_base(MR_Short_Lval locn, MR_Word *saved_regs,
|
|
MR_Word *base_sp, MR_Word *base_curfr, MR_bool *succeeded)
|
|
{
|
|
int locn_num;
|
|
MR_Word value;
|
|
|
|
*succeeded = MR_FALSE;
|
|
value = 0;
|
|
|
|
locn_num = (int) locn >> MR_SHORT_LVAL_TAGBITS;
|
|
switch (MR_SHORT_LVAL_TYPE(locn)) {
|
|
case MR_SHORT_LVAL_TYPE_R:
|
|
if (MR_print_locn) {
|
|
printf("short r%d\n", locn_num);
|
|
}
|
|
if (saved_regs != NULL) {
|
|
value = MR_saved_reg_value(saved_regs,
|
|
locn_num);
|
|
*succeeded = MR_TRUE;
|
|
}
|
|
break;
|
|
|
|
case MR_SHORT_LVAL_TYPE_STACKVAR:
|
|
if (MR_print_locn) {
|
|
printf("short stackvar%d\n", locn_num);
|
|
}
|
|
value = MR_based_stackvar(base_sp, locn_num);
|
|
*succeeded = MR_TRUE;
|
|
break;
|
|
|
|
case MR_SHORT_LVAL_TYPE_FRAMEVAR:
|
|
if (MR_print_locn) {
|
|
printf("short framevar%d\n", locn_num);
|
|
}
|
|
value = MR_based_framevar(base_curfr, locn_num);
|
|
*succeeded = MR_TRUE;
|
|
break;
|
|
|
|
case MR_SHORT_LVAL_TYPE_SPECIAL:
|
|
switch (locn_num) {
|
|
case MR_LONG_LVAL_TYPE_SUCCIP:
|
|
if (MR_print_locn) {
|
|
printf("short succip\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_MAXFR:
|
|
if (MR_print_locn) {
|
|
printf("short maxfr\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_CURFR:
|
|
if (MR_print_locn) {
|
|
printf("short curfr\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_HP:
|
|
if (MR_print_locn) {
|
|
printf("short hp\n");
|
|
}
|
|
break;
|
|
|
|
case MR_LONG_LVAL_TYPE_SP:
|
|
if (MR_print_locn) {
|
|
printf("short sp\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (MR_print_locn) {
|
|
printf("short spec DEFAULT\n");
|
|
}
|
|
}
|
|
|
|
default:
|
|
MR_fatal_error("MR_lookup_short_lval_base: bad type");
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
MR_bool
|
|
MR_get_type_and_value(const MR_Label_Layout *label_layout, int i,
|
|
MR_Word *saved_regs, MR_TypeInfo *type_params, MR_TypeInfo *type_info,
|
|
MR_Word *value)
|
|
{
|
|
return MR_get_type_and_value_base(label_layout, i, saved_regs,
|
|
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
|
|
type_params, type_info, value);
|
|
}
|
|
|
|
MR_bool
|
|
MR_get_type_and_value_base(const MR_Label_Layout *label_layout, int i,
|
|
MR_Word *saved_regs, MR_Word *base_sp, MR_Word *base_curfr,
|
|
MR_TypeInfo *type_params, MR_TypeInfo *type_info, MR_Word *value)
|
|
{
|
|
MR_PseudoTypeInfo pseudo_type_info;
|
|
MR_bool succeeded;
|
|
|
|
pseudo_type_info = MR_var_pti(label_layout, i);
|
|
*type_info = MR_create_type_info(type_params, pseudo_type_info);
|
|
|
|
if (i < MR_long_desc_var_count(label_layout)) {
|
|
if (MR_print_locn) {
|
|
printf("looking up long lval\n");
|
|
}
|
|
|
|
*value = MR_lookup_long_lval_base(
|
|
MR_long_desc_var_locn(label_layout, i),
|
|
saved_regs, base_sp, base_curfr, &succeeded);
|
|
} else {
|
|
if (MR_print_locn) {
|
|
printf("looking up short lval\n");
|
|
}
|
|
|
|
*value = MR_lookup_short_lval_base(
|
|
MR_short_desc_var_locn(label_layout, i),
|
|
saved_regs, base_sp, base_curfr, &succeeded);
|
|
}
|
|
|
|
return succeeded;
|
|
}
|
|
|
|
MR_bool
|
|
MR_get_type(const MR_Label_Layout *label_layout, int i, MR_Word *saved_regs,
|
|
MR_TypeInfo *type_params, MR_TypeInfo *type_info)
|
|
{
|
|
return MR_get_type_base(label_layout, i, saved_regs,
|
|
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
|
|
type_params, type_info);
|
|
}
|
|
|
|
MR_bool
|
|
MR_get_type_base(const MR_Label_Layout *label_layout, int i,
|
|
MR_Word *saved_regs, MR_Word *base_sp, MR_Word *base_curfr,
|
|
MR_TypeInfo *type_params, MR_TypeInfo *type_info)
|
|
{
|
|
MR_PseudoTypeInfo pseudo_type_info;
|
|
|
|
pseudo_type_info = MR_var_pti(label_layout, i);
|
|
*type_info = MR_create_type_info(type_params, pseudo_type_info);
|
|
|
|
return MR_TRUE;
|
|
}
|
|
|
|
void
|
|
MR_write_variable(MR_TypeInfo type_info, MR_Word value)
|
|
{
|
|
MercuryFilePtr stdout_stream;
|
|
|
|
(*MR_io_stdout_stream)(&stdout_stream);
|
|
(*MR_io_print_to_stream)((MR_Word) type_info, stdout_stream, value);
|
|
}
|
|
|
|
void
|
|
MR_generate_proc_name_from_layout(const MR_Proc_Layout *proc_layout,
|
|
MR_ConstString *proc_name_ptr, int *arity_ptr, MR_Word *is_func_ptr)
|
|
{
|
|
if (MR_PROC_LAYOUT_IS_UCI(proc_layout)) {
|
|
*proc_name_ptr = proc_layout->MR_sle_proc_id.
|
|
MR_proc_uci.MR_uci_pred_name;
|
|
if (MR_streq(*proc_name_ptr, "__Unify__")) {
|
|
*arity_ptr = 2;
|
|
} else if (MR_streq(*proc_name_ptr, "__Compare__")) {
|
|
*arity_ptr = 3;
|
|
} else if (MR_streq(*proc_name_ptr, "__Index__")) {
|
|
*arity_ptr = 2;
|
|
} else {
|
|
MR_fatal_error("MR_generate_proc_name_from_layout: "
|
|
"bad MR_comp_pred_name");
|
|
}
|
|
*is_func_ptr = MR_BOOL_NO;
|
|
} else {
|
|
*proc_name_ptr = proc_layout->MR_sle_proc_id.
|
|
MR_proc_user.MR_user_name;
|
|
*arity_ptr = proc_layout->MR_sle_proc_id.
|
|
MR_proc_user.MR_user_arity;
|
|
if (proc_layout->MR_sle_proc_id.MR_proc_user.
|
|
MR_user_pred_or_func == MR_FUNCTION)
|
|
{
|
|
*is_func_ptr = MR_BOOL_YES;
|
|
} else {
|
|
*is_func_ptr = MR_BOOL_NO;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_proc_id_arity_addedargs_predfunc(const MR_Proc_Layout *proc, int *arity_ptr,
|
|
int *num_added_args_ptr, MR_PredFunc *pred_or_func_ptr)
|
|
{
|
|
if (MR_PROC_LAYOUT_IS_UCI(proc)) {
|
|
/*
|
|
** MR_comp_type_arity is the arity of the type constructor.
|
|
** Each argument of the type constructor adds a typeinfo
|
|
** argument to the headvars for all predicates, unify, compare
|
|
** and index. (The index predicate doesn't need these
|
|
** typeinfos, but it has them anyway.)
|
|
*/
|
|
*num_added_args_ptr = proc->MR_sle_uci.MR_uci_type_arity;
|
|
*arity_ptr = proc->MR_sle_num_head_vars - *num_added_args_ptr;
|
|
*pred_or_func_ptr = MR_PREDICATE;
|
|
} else {
|
|
*arity_ptr = proc->MR_sle_user.MR_user_arity;
|
|
*num_added_args_ptr = proc->MR_sle_num_head_vars - *arity_ptr;
|
|
*pred_or_func_ptr = proc->MR_sle_user.MR_user_pred_or_func;
|
|
}
|
|
}
|