/*
** 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 */
