Files
mercury/runtime/mercury_layout_util.h
Peter Wang 2ccac171dd Add float registers to the Mercury abstract machine, implemented as an
Branches: main

Add float registers to the Mercury abstract machine, implemented as an
array of MR_Float in the Mercury engine structure.

Float registers are only useful if a Mercury `float' is wider than a word
(i.e. when using double precision floats on 32-bit platforms) so we let them
exist only then.  In other cases floats may simply be passed via the regular
registers, as before.

Currently, higher order calls still require the use of the regular registers
for all arguments.  As all exported procedures are potentially the target of
higher order calls, exported procedures must use only the regular registers for
argument passing.  This can lead to more (un)boxing than if floats were simply
always boxed.  Until this is solved, float registers must be enabled explicitly
with the developer only option `--use-float-registers'.

The other aspect of this change is using two consecutive stack slots to hold a
single double variable.  Without that, the benefit of passing unboxed floats
via dedicated float registers would be largely eroded.


compiler/options.m:
	Add developer option `--use-float-registers'.

compiler/handle_options.m:
	Disable `--use-float-registers' if floats are not wider than words.

compiler/make_hlds_passes.m:
	If `--use-float-registers' is in effect, enable a previous change that
	allows float constructor arguments to be stored unboxed in structures.

compiler/hlds_llds.m:
	Move `reg_type' here from llds.m and `reg_f' option.

	Add stack slot width to `stack_slot' type.

	Add register type and stack slot width to `abs_locn' type.

	Remember next available float register in `abs_follow_vars'.

compiler/hlds_pred.m:
	Add register type to `arg_loc' type.

compiler/llds.m:
	Add a new kind of lval: double-width stack slots.
	These are used to hold double-precision floating point values only.

	Record setting of `--use-float-registers' in exprn_opts.

	Conform to addition of float registers and double stack slots.

compiler/code_info.m:
	Make predicates take the register type as an argument,
	where it can no longer be assumed.

	Remember whether float registers are being used.

	Remember max float register for calls to MR_trace.

	Count double width stack slots as two slots.

compiler/arg_info.m:
	Allocate float registers for procedure arguments when appropriate.

	Delete unused predicates.

compiler/var_locn.m:
	Make predicates working with registers either take the register type as
	an argument, or handle both register types at once.

	Select float registers for variables when appropriate.

compiler/call_gen.m:
	Explicitly use regular registers for all higher-order calls,
	which was implicit before.

compiler/pragma_c_gen.m:
	Use float registers, when available, at the interface between Mercury
	code and C foreign_procs.

compiler/export.m:
	Whether a float rval needs to be boxed/unboxed when assigned to/from a
	register depends on the register type.

compiler/fact_table.m:
	Use float registers for arguments to predicates defined by fact tables.

compiler/stack_alloc.m:
	Allocate two consecutive stack slots for float variables when
	appropriate.

compiler/stack_layout.m:
	Represent double-width stack slots in procedure layout structures.

	Conform to changes.

compiler/store_alloc.m:
	Allocate float registers (if they exist) for float variables.

compiler/use_local_vars.m:
	Substitute float abstract machine registers with MR_Float local
	variables.

compiler/llds_out_data.m:
compiler/llds_out_instr.m:
	Output float registers and double stack slots.

compiler/code_util.m:
compiler/follow_vars.m:
	Count float registers separately from regular registers.

compiler/layout.m:
compiler/layout_out.m:
compiler/trace_gen.m:
	Remember the max used float register for calls to MR_trace().

compiler/builtin_lib_types.m:
	Fix incorrect definition of float_type_ctor.

compiler/bytecode_gen.m:
compiler/continuation_info.m:
compiler/disj_gen.m:
compiler/dupelim.m:
compiler/exprn_aux.m:
compiler/global_data.m:
compiler/hlds_out_goal.m:
compiler/jumpopt.m:
compiler/llds_to_x86_64.m:
compiler/lookup_switch.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/par_conj_gen.m:
compiler/proc_gen.m:
compiler/string_switch.m:
compiler/tag_switch.m:
compiler/tupling.m:
compiler/x86_64_regs.m:
	Conform to changes.

runtime/mercury_engine.h:
	Add an array of fake float "registers" to the Mercury engine structure,
	when MR_Float is wider than MR_Word.

runtime/mercury_regs.h:
	Document float registers in the Mercury abstract machine.

	Add macros to access float registers in the Mercury engine.

runtime/mercury_stack_layout.h:
	Add new MR_LongLval cases to represent double-width stack slots.

	MR_LONG_LVAL_TAGBITS had to be increased to accomodate the new cases,
	which increases the number of integers in [0, 2^MR_LONG_LVAL_TAGBITS)
	equal to 0 modulo 4.  These are the new MR_LONG_LVAL_TYPE_CONS_n cases.

	Add max float register field to MR_ExecTrace.

runtime/mercury_layout_util.c:
runtime/mercury_layout_util.h:
	Extend MR_copy_regs_to_saved_regs and MR_copy_saved_regs_to_regs
	for float registers.

	Understand how to look up new kinds of MR_LongLval: MR_LONG_LVAL_TYPE_F
	(previously unused), MR_LONG_LVAL_TYPE_DOUBLE_STACKVAR,
	MR_LONG_LVAL_TYPE_DOUBLE_FRAMEVAR.

	Conform to the new MR_LONG_LVAL_TYPE_CONS_n cases.

runtime/mercury_float.h:
	Delete redundant #ifdef.

runtime/mercury_accurate_gc.c:
runtime/mercury_agc_debug.c:
	Conform to changes (untested).

trace/mercury_trace.c:
trace/mercury_trace.h:
trace/mercury_trace_declarative.c:
trace/mercury_trace_external.c:
trace/mercury_trace_internal.c:
trace/mercury_trace_spy.c:
trace/mercury_trace_vars.c:
trace/mercury_trace_vars.h:
	Handle float registers in the trace subsystem.  This is mostly a matter
	of saving/restoring them as with regular registers.
2011-10-17 04:31:33 +00:00

191 lines
8.6 KiB
C

/*
** vim:sw=4 ts=4 expandtab
*/
/*
** Copyright (C) 1998-2003, 2005-2006, 2011 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.
*/
#ifndef MERCURY_LAYOUT_UTIL_H
#define MERCURY_LAYOUT_UTIL_H
#include "mercury_std.h"
#include "mercury_types.h" /* for MR_Word, etc. */
#include "mercury_stack_layout.h" /* for MR_LabelLayout, etc. */
#include "mercury_type_info.h" /* for MR_TypeInfoParams, etc. */
#include "mercury_ho_call.h" /* for MR_Closure */
/*
** These two functions copy the register state to and from the provided
** saved_regs and saved_f_regs arrays, which should have room for
** MR_MAX_FAKE_REG MR_Words and MR_MAX_VIRTUAL_F_REG MR_Floats respectively.
*/
extern void MR_copy_regs_to_saved_regs(int max_mr_num, MR_Word *saved_regs,
int max_f_num, MR_Float *saved_f_regs);
extern void MR_copy_saved_regs_to_regs(int max_mr_num, MR_Word *saved_regs,
int max_f_num, MR_Float *saved_f_regs);
/*
** A MR_LabelLayout describes the variables that are live at a given
** program point. Some of the types of these variables may contain type
** variables. Since the values of those type variables are not known until
** runtime, the MR_LabelLayout cannot include full typeinfos for the
** variables. Instead, it contains pseudo-typeinfos, in which some parts
** of some typeinfo structures may contain an indication "this data is
** not available at compile time, but at runtime it will be in this location".
**
** MR_materialize_type_params takes as input a MR_LabelLayout structure.
** It returns a vector of typeinfos which has one entry for each
** type variable in the MR_LabelLayout structure, with this typeinfo
** being the value of the corresponding type variable.
** Since type variable numbers start at one, the element of this array at
** index zero will not have a type_info in it. We store a dummy type_ctor_info
** there, so that the array will itself look like a typeinfo.
**
** The vector returned by MR_materialize_type_params is from MR_malloc;
** it should be MR_freed after last use.
**
** MR_materialize_type_params looks up locations in the current
** environment, as indicated by the set of saved registers (including MR_sp
** and MR_curfr). MR_materialize_typeinfos_base does the same job but
** assumes the environment is given by the given values of MR_sp and MR_curfr,
** and does not assume that the registers have valid contents unless saved_regs
** is non-null.
**
** MR_materialize_closure_type_params does much the same except that
** it takes an MR_Closure rather than an MR_LabelLayout,
** and it gets the type_infos from a closure using the closure_layout,
** rather than getting them from the registers/stacks using a label_layout.
**
** MR_materialize_typeclass_info_type_params is the same as
** MR_materialize_closure_type_params except that it takes
** a typeclass_info and a closure layout (for the type class method)
** and it gets the type_infos from the typeclass_info.
*/
extern MR_TypeInfoParams MR_materialize_type_params(
const MR_LabelLayout *label_layout,
MR_Word *saved_regs);
extern MR_TypeInfoParams MR_materialize_type_params_base(
const MR_LabelLayout *label_layout,
MR_Word *saved_regs,
MR_Word *base_sp, MR_Word *base_curfr);
extern MR_TypeInfoParams MR_materialize_closure_type_params(
MR_Closure *closure);
extern MR_TypeInfoParams MR_materialize_typeclass_info_type_params(
MR_Word typeclass_info,
MR_Closure_Layout *closure_layout);
extern MR_TypeInfoParams MR_materialize_answer_block_type_params(
const MR_TypeParamLocns *tvar_locns,
MR_Word *answer_block, int block_size);
/*
** If the given encoded location refers to a register, return its number.
** If it does not, return -1.
*/
extern int MR_get_register_number_long(MR_LongLval locn);
extern int MR_get_register_number_short(MR_ShortLval locn);
/*
** Given an location either in a long or short form, return the value
** at that location if possible. *succeeded will say whether the attempt
** was successful.
**
** MR_lookup_{long,short}_lval looks up locations in the current environment,
** as indicated by the set of saved registers (including MR_sp and MR_curfr).
** MR_lookup_{long,short}_lval_base does the same job but assumes the
** environment is given by the given values of MR_sp and MR_curfr, and does
** not assume that the registers have valid contents unless saved_regs is
** non-null.
*/
extern MR_Word MR_lookup_long_lval(MR_LongLval locn,
MR_Word *saved_regs, MR_Float *saved_f_regs,
MR_bool *succeeded);
extern MR_Word MR_lookup_long_lval_base(MR_LongLval locn,
MR_Word *saved_regs, MR_Word *base_sp,
MR_Word *base_curfr, MR_Float *saved_f_regs,
MR_bool *succeeded);
extern MR_Word MR_lookup_short_lval(MR_ShortLval locn,
MR_Word *saved_regs, MR_bool *succeeded);
extern MR_Word MR_lookup_short_lval_base(MR_ShortLval locn,
MR_Word *saved_regs, MR_Word *base_sp,
MR_Word *base_curfr, MR_bool *succeeded);
/*
** Given information about the location of a variable (var) and a vector giving
** the typeinfos corresponding to the type variables that may occur in
** the type of that variable (type_params), try to return the value of the
** variable in *value and the typeinfo describing its type in *type_info.
** *succeeded will say whether the attempt was successful.
**
** The type_params array should have the same format as the array returned
** by MR_materialize_type_params.
**
** MR_get_type_and_value looks up locations in the current environment,
** as indicated by the set of saved registers (including MR_sp and MR_curfr).
** MR_get_type_and_value_base does the same job but assumes the
** environment is given by the given values of MR_sp and MR_curfr, and does
** not assume that the registers have valid contents unless saved_regs is
** non-null.
**
** MR_get_type and MR_get_type_base are similar but do not
** return the value.
**
** All of these functions may need to allocate memory (to hold the
** type_infos that they return); any memory that they allocate will
** be allocated on the Mercury heap.
*/
extern MR_bool MR_get_type_and_value(const MR_LabelLayout *label_layout,
int var, MR_Word *saved_regs, MR_Float *saved_f_regs,
MR_TypeInfo *type_params, MR_TypeInfo *type_info,
MR_Word *value);
extern MR_bool MR_get_type_and_value_base(const MR_LabelLayout *label_layout,
int var, MR_Word *saved_regs, MR_Word *base_sp,
MR_Word *base_curfr, MR_Float *saved_f_regs,
MR_TypeInfo *type_params, MR_TypeInfo *type_info,
MR_Word *value);
extern MR_bool MR_get_type(const MR_LabelLayout *label_layout, int var,
MR_Word *saved_regs, MR_TypeInfo *type_params,
MR_TypeInfo *type_info);
extern MR_bool MR_get_type_base(const MR_LabelLayout *label_layout, int var,
MR_Word *saved_regs, MR_Word *base_sp,
MR_Word *base_curfr, MR_TypeInfo *type_params,
MR_TypeInfo *type_info);
/*
** MR_write_variable: write a variable to stdout.
** This uses the fake_reg copies of the registers,
** and it may also clobber the real registers.
*/
extern void MR_write_variable(MR_TypeInfo type_info, MR_Word value);
/*
** Return the name of a procedure specified by the given proc layout in three
** pieces: the name of the procedure in *proc_name_ptr, its arity in
** *arity_ptr, and a boolean that is true iff procedure is a function
** in *is_func_ptr,
*/
extern void MR_generate_proc_name_from_layout(const MR_ProcLayout
*proc_layout, MR_ConstString *proc_name_ptr,
int *arity_ptr, MR_Word *is_func_ptr);
/*
** Return the user-visible arity of the procedure (including the return value
** for functions), the number of typeinfo and/or typeclassinfo arguments added
** by the compiler, and an indication whether the procedure is from a predicate
** or a function.
*/
extern void MR_proc_id_arity_addedargs_predfunc(const MR_ProcLayout *proc,
int *arity_ptr, int *num_added_args_ptr,
MR_PredFunc *pred_or_func_ptr);
#endif /* MERCURY_LAYOUT_UTIL_H */