Files
mercury/runtime/mercury_stack_layout.h
Zoltan Somogyi 58211e2f2e Allow more than 2^15 vars in a procedure representation.
Estimated hours taken: 12
Branches: main

Allow more than 2^15 vars in a procedure representation.

mdbcomp/program_representation.m:
	Allow a variable number to be represented by four bytes as well as
	two and one. This means that we also have to represent the number
	of variables in a procedure using a four-byte number, not a two-byte
	number.

	Use four bytes to represent line numbers. Programs that overflow
	16-bit var numbers may also overflow 16 bit line numbers.

	These requires a change in the deep profiler data's binary
	compatibility version number.

compiler/prog_rep.m:
	Encode vars using four bytes if necessary. Be consistent in using
	only signed 8-bit as well as signed 16-bit numbers.

compiler/implicit_parallelism.m:
	Conform to the change in program_representation.m.

deep_profiler/profile.m:
deep_profiler/read_profile.m:
	Add a compression flag to the set of flags read from the data file.
	Put the flags into the profile_stats as a group, not one-by-one.

deep_profiler/canonical.m:
deep_profiler/create_report.m:
deep_profiler/dump.m:
deep_profiler/mdprof_feedback.m:
deep_profiler/old_html_format.m:
deep_profiler/old_query.m:
deep_profiler/query.m:
	Conform to the change in profile.m.

runtime/mercury_deep_profiling.c:
	Prepare for compression of profiling data files being implemented.

runtime/mercury_stack_layout.h:
	Fix some documentation rot.

runtime/mercury_conf_param.h:
	Add an implication between debug flags to make debugging easier.
2010-10-11 00:49:27 +00:00

1679 lines
83 KiB
C

/*
** vim: ts=4 sw=4 expandtab
*/
/*
** Copyright (C) 1998-2010 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_STACK_LAYOUT_H
#define MERCURY_STACK_LAYOUT_H
/*
** mercury_stack_layout.h -
**
** Definitions for stack layout data structures. These are generated by the
** compiler, and are used by the parts of the runtime system that need to look
** at the stacks (and sometimes the registers) and make sense of their
** contents. The parts of the runtime system that need to do this include
** exception handling, the debugger, and (eventually) the accurate garbage
** collector.
**
** For a general description of the idea of stack layouts, see the paper
** "Run time type information in Mercury" by Tyson Dowd, Zoltan Somogyi,
** Fergus Henderson, Thomas Conway and David Jeffery, which is available from
** the Mercury web site. The relevant section is section 3.8, but be warned:
** while the general principles remain applicable, the details have changed
** since that paper was written.
**
** NOTE: The constants and data-structures used here need to be kept in
** sync with the ones generated in the compiler. If you change anything here,
** you may need to change stack_layout.m, layout.m, and/or layout_out.m in
** the compiler directory as well.
*/
#include "mercury_types.h"
#include "mercury_std.h" /* for MR_VARIABLE_SIZED */
#include "mercury_tags.h"
#include "mercury_type_info.h" /* for MR_PseudoTypeInfo */
#include "mercury_proc_id.h" /* for MR_ProcId */
#include "mercury_goto.h" /* for MR_PROC_LAYOUT etc */
#include "mercury_tabling.h" /* for MR_TableTrieStep etc */
#include "mercury_bootstrap.h" /* for MR_Table_Trie_Step */
/*-------------------------------------------------------------------------*/
/*
** Definitions for MR_Determinism.
*/
/*
** The max_soln component of the determinism is encoded in the 1 and 2 bits.
** The can_fail component of the determinism is encoded in the 4 bit.
** The first_solution component of the determinism is encoded in the 8 bit.
**
** MR_DETISM_AT_MOST_MANY could also be defined as ((d) & 3) == 3),
** but this would be less efficient, since the C compiler does not know
** that we do not set the 1 bit unless we also set the 2 bit.
**
** NOTE: this must match the encoding specified by represent_determinism/1
** in mdbcomp/program_representation.m.
*/
typedef MR_int_least16_t MR_Determinism;
#define MR_DETISM_DET 6
#define MR_DETISM_SEMI 2
#define MR_DETISM_NON 3
#define MR_DETISM_MULTI 7
#define MR_DETISM_ERRONEOUS 4
#define MR_DETISM_FAILURE 0
#define MR_DETISM_CCNON 10
#define MR_DETISM_CCMULTI 14
#define MR_DETISM_MAX 14
#define MR_DETISM_AT_MOST_ZERO(d) (((d) & 3) == 0)
#define MR_DETISM_AT_MOST_ONE(d) (((d) & 3) == 2)
#define MR_DETISM_AT_MOST_MANY(d) (((d) & 1) != 0)
#define MR_DETISM_CAN_FAIL(d) (((d) & 4) == 0)
#define MR_DETISM_FIRST_SOLN(d) (((d) & 8) != 0)
#define MR_DETISM_DET_STACK(d) (!MR_DETISM_AT_MOST_MANY(d) \
|| MR_DETISM_FIRST_SOLN(d))
/*-------------------------------------------------------------------------*/
/*
** Definitions for MR_LongLval and MR_ShortLval.
*/
/*
** MR_LongLval is an MR_Unsigned which describes a location.
** This includes lvals such as stack slots, general registers, and special
** registers such as succip, hp, etc, as well as locations whose address is
** given as a typeinfo inside the type class info structure pointed to by an
** lval.
**
** What kind of location an MR_LongLval refers to is encoded using
** a low tag with MR_LONG_LVAL_TAGBITS bits; the type MR_LongLvalType
** describes the different tag values. The interpretation of the rest of
** the word depends on the location type:
**
** Locn Rest
**
** MR_r(Num) Num (register number)
** MR_f(Num) Num (register number)
** MR_stackvar(Num) Num (stack slot number)
** MR_framevar(Num) Num (stack slot number)
** MR_succip
** MR_maxfr
** MR_curfr
** MR_hp
** MR_sp
** constant See below
** indirect(Base, N) See below
** unknown (The location is not known)
**
** For constants, the rest of the word is a pointer to static data. The
** pointer has only two low tag bits free, so we reserve every four-bit tag
** which has 00 as its bottom two bits for representing them.
**
** For indirect references, the word exclusive of the tag consists of
** (a) an integer with MR_LONG_LVAL_OFFSETBITS bits giving the index of
** the typeinfo inside a type class info (to be interpreted by
** MR_typeclass_info_type_info or the predicate
** private_builtin.type_info_from_typeclass_info, which calls it) and
** (b) a MR_LongLval value giving the location of the pointer to the
** type class info. This MR_LongLval value will *not* have an indirect tag.
**
** This data is generated in stack_layout.represent_locn_as_int,
** which must be kept in sync with the constants and macros defined here.
*/
typedef MR_Unsigned MR_LongLval;
typedef enum {
MR_LONG_LVAL_TYPE_CONS_0,
MR_LONG_LVAL_TYPE_R,
MR_LONG_LVAL_TYPE_F,
MR_LONG_LVAL_TYPE_STACKVAR,
MR_LONG_LVAL_TYPE_CONS_1,
MR_LONG_LVAL_TYPE_FRAMEVAR,
MR_LONG_LVAL_TYPE_SUCCIP,
MR_LONG_LVAL_TYPE_MAXFR,
MR_LONG_LVAL_TYPE_CONS_2,
MR_LONG_LVAL_TYPE_CURFR,
MR_LONG_LVAL_TYPE_HP,
MR_LONG_LVAL_TYPE_SP,
MR_LONG_LVAL_TYPE_CONS_3,
MR_LONG_LVAL_TYPE_INDIRECT,
MR_LONG_LVAL_TYPE_UNKNOWN
} MR_LongLvalType;
/* This must be in sync with stack_layout.long_lval_tag_bits */
#define MR_LONG_LVAL_TAGBITS 4
#define MR_LONG_LVAL_CONST_TAGBITS 2
#define MR_LONG_LVAL_TYPE(Locn) \
((MR_LongLvalType) ((Locn) & ((1 << MR_LONG_LVAL_TAGBITS) - 1)))
#define MR_LONG_LVAL_NUMBER(Locn) \
((int) ((Locn) >> MR_LONG_LVAL_TAGBITS))
#define MR_LONG_LVAL_CONST(Locn) \
(* (MR_Word *) ((Locn) & ~ ((1 << MR_LONG_LVAL_CONST_TAGBITS) - 1)))
/* This must be in sync with stack_layout.offset_bits */
#define MR_LONG_LVAL_OFFSETBITS 6
#define MR_LONG_LVAL_INDIRECT_OFFSET(LocnNumber) \
((int) ((LocnNumber) & ((1 << MR_LONG_LVAL_OFFSETBITS) - 1)))
#define MR_LONG_LVAL_INDIRECT_BASE_LVAL_INT(LocnNumber) \
(((MR_uint_least32_t) (LocnNumber)) >> MR_LONG_LVAL_OFFSETBITS)
#define MR_LONG_LVAL_STACKVAR_INT(n) \
(((n) << MR_LONG_LVAL_TAGBITS) + MR_LONG_LVAL_TYPE_STACKVAR)
#define MR_LONG_LVAL_FRAMEVAR_INT(n) \
(((n) << MR_LONG_LVAL_TAGBITS) + MR_LONG_LVAL_TYPE_FRAMEVAR)
#define MR_LONG_LVAL_R_REG_INT(n) \
(((n) << MR_LONG_LVAL_TAGBITS) + MR_LONG_LVAL_TYPE_R)
/*
** MR_ShortLval is a MR_uint_least8_t which describes an location. This
** includes lvals such as stack slots and general registers that have small
** numbers, and special registers such as succip, hp, etc.
**
** What kind of location an MR_LongLval refers to is encoded using
** a low tag with 2 bits; the type MR_ShortLval_Type describes
** the different tag values. The interpretation of the rest of the word
** depends on the location type:
**
** Locn Tag Rest
** MR_r(Num) 0 Num (register number)
** MR_stackvar(Num) 1 Num (stack slot number)
** MR_framevar(Num) 2 Num (stack slot number)
** special reg 3 MR_LongLvalType
**
** This data is generated in stack_layout.represent_locn_as_byte,
** which must be kept in sync with the constants and macros defined here.
*/
typedef MR_uint_least8_t MR_ShortLval;
typedef enum {
MR_SHORT_LVAL_TYPE_R,
MR_SHORT_LVAL_TYPE_STACKVAR,
MR_SHORT_LVAL_TYPE_FRAMEVAR,
MR_SHORT_LVAL_TYPE_SPECIAL
} MR_ShortLval_Type;
/* This must be in sync with stack_layout.short_lval_tag_bits */
#define MR_SHORT_LVAL_TAGBITS 2
#define MR_SHORT_LVAL_TYPE(Locn) \
((MR_ShortLval_Type) \
(((MR_Word) Locn) & ((1 << MR_SHORT_LVAL_TAGBITS) - 1)))
#define MR_SHORT_LVAL_NUMBER(Locn) \
((int) (((MR_Word) Locn) >> MR_SHORT_LVAL_TAGBITS))
#define MR_SHORT_LVAL_STACKVAR(n) \
((MR_ShortLval) (((n) << MR_SHORT_LVAL_TAGBITS) \
+ MR_SHORT_LVAL_TYPE_STACKVAR))
#define MR_SHORT_LVAL_FRAMEVAR(n) \
((MR_ShortLval) (((n) << MR_SHORT_LVAL_TAGBITS) \
+ MR_SHORT_LVAL_TYPE_FRAMEVAR))
#define MR_SHORT_LVAL_R_REG(n) \
((MR_ShortLval) (((n) << MR_SHORT_LVAL_TAGBITS) \
+ MR_SHORT_LVAL_TYPE_R))
/*-------------------------------------------------------------------------*/
/*
** Definitions for MR_UserEvent and MR_UserEventSpec.
*/
/*
** Our layout structures link to information about user events from two places:
** the label layout structures of labels that correspond to user events,
** and the module layout structures of modules that contain user events.
** Label layout structures link to MR_UserEvent structures; module layout
** structures link to MR_UserEventSpec structures. Most of the information
** is in the MR_UserEventSpec structures; MR_UserEvent structures contain
** only information that may differ between two instances of the same event.
*/
/*
** The fields of MR_UserEvent:
**
** The event_number field contains the ordinal number of the event in the
** event set the module was compiled with: it gives the identity of the event.
** (Event numbers start at zero.) This field is also the link to the rest of
** the information about the event, contained in the MR_UserEventSpec structure
** linked to by the module layout structure. The MR_user_event_spec macro
** follows this link.
**
** The next two fields all point to arrays whose length is the number of
** attributes (which is available in the MR_UserEventSpec structure).
**
** attr_locns[i] gives the location where we can find the value of the
** i'th attribute (the first attribute is attribute zero). This is
** meaningful only if the attribute is not a synthesized attribute.
**
** attr_var_nums[i] gives the variable number of the i'th attribute;
** if it contains zero, that means the attribute is synthesized. This field
** is used by the debugger to display the associated value just once
** (not twice, as both attribute and variable value) with "print *". (Note
** that we don't delete the variables that are also attributes from the set of
** live variables in layout structures, because that would require any native
** garbage collector to look at the list of attributes as well as the list of
** other variables, slowing it down.)
*/
typedef MR_uint_least16_t MR_HLDSVarNum;
struct MR_UserEvent_Struct {
MR_uint_least16_t MR_ue_event_number;
MR_LongLval *MR_ue_attr_locns;
const MR_HLDSVarNum *MR_ue_attr_var_nums;
};
/*
** The fields of MR_UserEventSpec:
**
** The event_name field contains the name of the event.
**
** The num_attrs field gives the number of attributes.
**
** The next three fields (attr_names, attr_types and synth_attrs) all point
** to arrays whose length is the number of attributes.
**
** attr_names[i] gives the name of the i'th attribute.
**
** attr_types[i] is the typeinfo giving the type of the i'th attribute.
**
** If the i'th attribute is synthesized, synth_attrs[i] points to the
** information required to synthesize it: the number of the attribute
** containing the synthesis function, the number of arguments of the synthesis
** function, and an array of attribute numbers (of length num_arg_attrs)
** giving the list of those arguments. The depend_attrs field will point to
** a list of numbers of the synthesized attributes whose values must be
** materialized before this attribute can be evaluated. (This list will include
** the argument attributes, and will be in a feasible evaluation order.)
** If the i'th attribute is not synthesized, synth_attrs[i] and depend_attrs[i]
** will both be NULL. (For now, depend_attrs[i] will not be filled in for
** synthesized attributes either.)
**
** The synth_attr_order field points to an array of attribute numbers that
** gives the order in which the values of the synthesized attributes should be
** evaluated. The array is ended by -1 as a sentinel.
**
** The synth_attrs and synth_attr_order fields will both be NULL for events
** that have no synthesized attributes.
*/
struct MR_SynthAttr_Struct {
MR_int_least16_t MR_sa_func_attr;
MR_int_least16_t MR_sa_num_arg_attrs;
MR_uint_least16_t *MR_sa_arg_attrs;
MR_int_least16_t *MR_sa_depend_attrs;
};
struct MR_UserEventSpec_Struct {
const char *MR_ues_event_name;
MR_uint_least16_t MR_ues_num_attrs;
const char **MR_ues_attr_names;
MR_TypeInfo *MR_ues_attr_types;
MR_SynthAttr *MR_ues_synth_attrs;
MR_int_least16_t *MR_ues_synth_attr_order;
};
#define MR_user_event_spec(label_layout) \
label_layout->MR_sll_entry->MR_sle_module_layout-> \
MR_ml_user_event_specs[label_layout->MR_sll_user_event-> \
MR_ue_event_number]
#define MR_user_event_set_name(label_layout) \
label_layout->MR_sll_entry->MR_sle_module_layout-> \
MR_ml_user_event_set_name
/*-------------------------------------------------------------------------*/
/*
** Definitions for MR_LabelLayout.
*/
/*
** An MR_LabelLayout structure describes the debugging and accurate gc
** information available at a given label.
**
** The MR_sll_entry field points to the proc layout structure of the procedure
** in which the label occurs.
**
** The MR_sll_port field will contain a negative number if there is no
** execution tracing port associated with the label. If there is, the
** field will contain a value of type MR_TracePort. For labels associated
** with events, this will be the port of the event. For return labels,
** this port will be exception (since exception events are associated with
** the return from the call that raised the exception).
**
** The MR_sll_hidden field contains a boolean which is meaningful only if the
** label corresponds to an execution tracing event. It will be MR_HIDDEN if the
** event should have no effects that the user can see (no message printed, no
** increment of the event number etc), and MR_NOT_HIDDEN otherwise. Hidden
** events are sometimes needed by the declarative debugger to provide the
** proper context for other events.
**
** The MR_sll_goal_path field contains an offset into the module-wide string
** table, leading to a string that gives the goal path associated with the
** label. If there is no meaningful goal path associated with the label,
** the offset will be zero, leading to the empty string. You can use the macro
** MR_label_goal_path to convert the value in the MR_sll_goal_path field to a
** string.
**
** If the label is the label of a user-defined event, then the
** MR_sll_user_event field will point to information about the user event;
** otherwise, the field will be NULL.
**
** The remaining fields give information about the values live at the given
** label, if this information is available. If it is available, the
** MR_has_valid_var_count macro will return true and the fields after the count
** are meaningful; if it is not available, the macro will return false and
** those fields are not meaningful (i.e. you are looking at an
** MR_LabelLayoutNoVarInfo structure).
**
** The format in which we store information about the values live at the label
** is somewhat complicated, due to our desire to make this information compact.
** We can represent a location in one of two ways, as an 8-bit MR_ShortLval
** or as a 32-bit MR_LongLval. We prefer representing a location as an
** MR_ShortLval, but of course not all locations can be represented in
** this way, so those other locations are represented as MR_LongLvals.
**
** The MR_sll_var_count field, if it is valid, is encoded by the formula
** (#Long << MR_SHORT_COUNT_BITS + #Short), where #Short is the number
** data items whose descriptions fit into an MR_ShortLval and #Long is the
** number of data items whose descriptions do not. (The number of distinct
** values that fit into 8 bits also fits into 8 bits, but since some
** locations hold the value of more than one variable at a time, not all
** the values need to be distinct; this is why MR_SHORT_COUNT_BITS is
** more than 8.)
**
** The MR_sll_types field points to an array of #Long + #Short
** MR_PseudoTypeInfos each giving the type of a live data item, with
** a small integer instead of a pointer representing a special kind of
** live data item (e.g. a saved succip or hp). This field will be null if
** #Long + #Short is zero.
**
** The MR_sll_long_locns field points to an array of #Long MR_LongLvals,
** while the MR_sll_short_locns field points to an array of #Short
** MR_ShortLvals. The element at index i in the MR_sll_long_locns vector
** will have its type described by the element at index i in the MR_sll_types
** vector, while the element at index i in the MR_sll_short_locns vector
** will have its type described by the element at index #Long + i in the
** MR_sll_types vector. MR_sll_long_locns will be NULL if #Long is zero,
** and similarly MR_sll_short_locns will be NULL if #Short is zero.
**
** The MR_sll_var_nums field may be NULL, which means that there is no
** information about the variable numbers of the live values. If the field
** is not NULL, it points to a vector of variable numbers, which has an element
** for each live data item. This is either the live data item's HLDS variable
** number, or one of two special values. Zero means that the live data item
** is not a variable (e.g. it is a saved copy of succip). The largest possible
** 16-bit number on the other hand means "the number of this variable does not
** fit into 16 bits". With the exception of these special values, the value
** in this slot uniquely identifies the live data item. (Not being able to
** uniquely identify nonvariable data items is never a problem. Not being able
** to uniquely identify variables is a problem, at the moment, only to the
** extent that the debugger cannot print their names.)
**
** The types of the live variables may or may not have type variables in them.
** If they do not, the MR_sll_tvars field will be NULL. If they do, it will
** point to an MR_TypeParamLocns structure that gives the locations of the
** typeinfos for those type variables. This structure gives the number of type
** variables and their locations, so that the code that needs the type
** parameters can materialize all the type parameters from their location
** descriptions in one go. This is an optimization, since the type parameter
** vector could simply be indexed on demand by the type variable's variable
** number stored within the MR_PseudoTypeInfos stored inside the vector
** pointed to by the MR_sll_types field.
**
** Since we allocate type variable numbers sequentially, the MR_tp_param_locns
** vector will usually be dense. However, after all variables whose types
** include e.g. type variable 2 have gone out of scope, variables whose
** types include type variable 3 may still be around. In cases like this,
** the entry for type variable 2 will be zero; this signals to the code
** in the internal debugger that materializes typeinfo structures that
** this typeinfo structure need not be materialized. Note that the array
** element MR_tp_param_locns[i] describes the location of the typeinfo
** structure for type variable i+1, since array offsets start at zero
** but type variable numbers start at one.
**
** The MR_sll_label_num_in_module is used for counting the number of times
** the event of this label is executed. It gives the label's index in the
** array pointed to by the module layout's MR_ml_label_exec_count field;
** whenever the event of this label is executed, the element in that array
** indicated by this index will be incremented (when MR_trace_count_enabled
** is set). The array element at index zero is ignored. A label layout will
** have zero in its MR_sll_label_num_in_module field if the label doesn't
** correspond to an event.
**
** XXX: Presently, inst information is ignored; we assume that all live values
** are ground.
*/
#define MR_HIDDEN 1
#define MR_NOT_HIDDEN 0
struct MR_TypeParamLocns_Struct {
MR_uint_least32_t MR_tp_param_count;
MR_LongLval MR_tp_param_locns[MR_VARIABLE_SIZED];
};
struct MR_LabelLayout_Struct {
const MR_ProcLayout *MR_sll_entry;
MR_int_least8_t MR_sll_port;
MR_int_least8_t MR_sll_hidden;
MR_uint_least16_t MR_sll_label_num_in_module;
MR_uint_least32_t MR_sll_goal_path;
const MR_UserEvent *MR_sll_user_event;
MR_Integer MR_sll_var_count; /* >= 0, encoding Long > 0 */
const MR_TypeParamLocns *MR_sll_tvars;
const MR_PseudoTypeInfo *MR_sll_types;
const MR_HLDSVarNum *MR_sll_var_nums;
const MR_ShortLval *MR_sll_short_locns;
const MR_LongLval *MR_sll_long_locns;
};
typedef struct MR_LabelLayoutShort_Struct {
const MR_ProcLayout *MR_sll_entry;
MR_int_least8_t MR_sll_port;
MR_int_least8_t MR_sll_hidden;
MR_uint_least16_t MR_sll_label_num_in_module;
MR_uint_least32_t MR_sll_goal_path;
const MR_UserEvent *MR_sll_user_event;
MR_Integer MR_sll_var_count; /* >= 0 , encoding Long == 0*/
const MR_TypeParamLocns *MR_sll_tvars;
const MR_PseudoTypeInfo *MR_sll_types;
const MR_HLDSVarNum *MR_sll_var_nums;
const MR_ShortLval *MR_sll_short_locns;
} MR_LabelLayoutShort;
typedef struct MR_LabelLayoutNoVarInfo_Struct {
const MR_ProcLayout *MR_sll_entry;
MR_int_least8_t MR_sll_port;
MR_int_least8_t MR_sll_hidden;
MR_uint_least16_t MR_sll_label_num_in_module;
MR_uint_least32_t MR_sll_goal_path;
const MR_UserEvent *MR_sll_user_event;
MR_Integer MR_sll_var_count; /* < 0 */
} MR_LabelLayoutNoVarInfo;
#define MR_label_goal_path(layout) \
((MR_PROC_LAYOUT_HAS_EXEC_TRACE((layout)->MR_sll_entry)) ? \
((layout)->MR_sll_entry->MR_sle_module_layout \
->MR_ml_string_table \
+ (layout)->MR_sll_goal_path) \
: "")
#define MR_SHORT_COUNT_BITS 10
#define MR_SHORT_COUNT_MASK ((1 << MR_SHORT_COUNT_BITS) - 1)
#define MR_has_valid_var_count(sll) \
(((sll)->MR_sll_var_count) >= 0)
#define MR_has_valid_var_info(sll) \
(((sll)->MR_sll_var_count) > 0)
#define MR_short_desc_var_count(sll) \
(((sll)->MR_sll_var_count) & MR_SHORT_COUNT_MASK)
#define MR_long_desc_var_count(sll) \
(((sll)->MR_sll_var_count) >> MR_SHORT_COUNT_BITS)
#define MR_all_desc_var_count(sll) \
(MR_long_desc_var_count(sll) + MR_short_desc_var_count(sll))
#define MR_var_pti(sll, i) \
((sll)->MR_sll_types[(i)])
#define MR_short_desc_var_locn(sll, i) \
((sll)->MR_sll_short_locns[(i)])
#define MR_long_desc_var_locn(sll, i) \
((sll)->MR_sll_long_locns[(i)])
/*
** Define a stack layout for an internal label.
**
** The only useful information in the structures created by this macro
** is the reference to the procedure layout, which allows you to find the
** stack frame size and the succip location, thereby enabling stack tracing.
**
** For the native garbage collector, we will need to add meaningful
** live value information as well to these macros.
*/
#define MR_LAYOUT_FROM_LABEL(label) \
MR_PASTE2(mercury_data__label_layout__, label)
#define MR_LABEL_LAYOUT_REF(label) \
((const MR_LabelLayout *) &MR_LAYOUT_FROM_LABEL(MR_add_prefix(label)))
#define MR_MAKE_USER_INTERNAL_LAYOUT(module, name, arity, mode, label) \
MR_LabelLayoutNoVarInfo \
MR_label_layout_user_name(module, name, arity, mode, label) = { \
(MR_ProcLayout *) & \
MR_proc_layout_user_name(module, name, arity, mode), \
0, \
-1, \
MR_FALSE, \
0, \
0, \
-1 /* No info about live values */ \
}
/*-------------------------------------------------------------------------*/
/*
** These macros are used as shorthands in generated C source files.
** The first two arguments are the entry label name and the label number;
** the others are the fields of MR_LabelLayouts.
*/
/*
** The following macros are obsolete. They should be deleted as soon as
** workspaces referring to them have been updated and recompiled.
*/
#define MR_DEF_LL_GEN(e, ln, port, h, num, path, ue, vc, lt, vn, tv) \
static const MR_LabelLayout \
MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)) \
= { \
MR_PROC_LAYOUT(MR_add_prefix(e)), \
MR_PASTE2(MR_PORT_, port), \
(h), (num), (path), (ue), (vc), \
((const void *) lt), \
((const MR_uint_least16_t *) vn), \
((const MR_TypeParamLocns *) tv) \
}
#define MR_DEF_LLNVI_GEN(e, ln, port, h, num, path, ue) \
static const MR_LabelLayoutNoVarInfo \
MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)) \
= { \
MR_PROC_LAYOUT(MR_add_prefix(e)), \
MR_PASTE2(MR_PORT_, port), \
(h), (num), (path), (ue), -1 \
}
#define MR_DEF_LL(e, ln, port, num, path, vc, lt, vn, tv) \
MR_DEF_LL_GEN(e, ln, port, MR_FALSE, num, path, NULL, vc, lt, vn, tv)
#define MR_DEF_LLT(e, ln, port, num, path, vc, lt, vn, tv) \
MR_DEF_LL_GEN(e, ln, port, MR_TRUE, num, path, NULL, vc, lt, vn, tv)
#define MR_DEF_LL_U(e, ln, port, num, path, vc, lt, vn, tv) \
MR_DEF_LL_GEN(e, ln, port, MR_FALSE, num, path, \
&MR_USER_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)), \
vc, lt, vn, tv)
#define MR_DEF_LLT_U(e, ln, port, num, path, vc, lt, vn, tv) \
MR_DEF_LL_GEN(e, ln, port, MR_TRUE, num, path, \
&MR_USER_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)), \
vc, lt, vn, tv)
#define MR_DEF_LLXCCC(e, ln, port, num, path, vc, ltt, ltc, vnt, vnc, tvt, tvc)\
MR_DEF_LL_GEN(e, ln, port, MR_FALSE, num, path, NULL, vc, \
MR_COMMON(ltt, ltc), \
MR_COMMON(vnt, vnc), \
MR_COMMON(tvt, tvc))
#define MR_DEF_LLXCC0(e, ln, port, num, path, vc, ltt, ltc, vnt, vnc) \
MR_DEF_LL_GEN(e, ln, port, MR_FALSE, num, path, NULL, vc, \
MR_COMMON(ltt, ltc), \
MR_COMMON(vnt, vnc), 0)
#define MR_DEF_LLTXCCC(e, ln, port, num, path, vc, ltt, ltc, vnt, vnc, tvt,tvc)\
MR_DEF_LL_GEN(e, ln, port, MR_TRUE, num, path, NULL, vc, \
MR_COMMON(ltt, ltc), \
MR_COMMON(vnt, vnc), \
MR_COMMON(tvt, tvc))
#define MR_DEF_LLTXCC0(e, ln, port, num, path, vc, ltt, ltc, vnt, vnc) \
MR_DEF_LL_GEN(e, ln, port, MR_TRUE, num, path, NULL, vc, \
MR_COMMON(ltt, ltc), \
MR_COMMON(vnt, vnc), 0)
#define MR_DEF_LLXCCC_U(e, ln, port, num, path, vc, ltt, ltc, vnt, vnc, tvt, tvc)\
MR_DEF_LL_GEN(e, ln, port, MR_FALSE, num, path, \
&MR_USER_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)), \
vc, \
MR_COMMON(ltt, ltc), \
MR_COMMON(vnt, vnc), \
MR_COMMON(tvt, tvc))
#define MR_DEF_LLXCC0_U(e, ln, port, num, path, vc, ltt, ltc, vnt, vnc) \
MR_DEF_LL_GEN(e, ln, port, MR_FALSE, num, path, \
&MR_USER_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)), \
vc, \
MR_COMMON(ltt, ltc), \
MR_COMMON(vnt, vnc), 0)
#define MR_DEF_LLTXCCC_U(e, ln, port, num, path, vc, ltt, ltc, vnt, vnc, tvt,tvc)\
MR_DEF_LL_GEN(e, ln, port, MR_TRUE, num, path, \
&MR_USER_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)), \
vc, \
MR_COMMON(ltt, ltc), \
MR_COMMON(vnt, vnc), \
MR_COMMON(tvt, tvc))
#define MR_DEF_LLTXCC0_U(e, ln, port, num, path, vc, ltt, ltc, vnt, vnc) \
MR_DEF_LL_GEN(e, ln, port, MR_TRUE, num, path, \
&MR_USER_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)), \
vc, \
MR_COMMON(ltt, ltc), \
MR_COMMON(vnt, vnc), 0)
#define MR_DEF_LLNVI(e, ln, port, num, path) \
MR_DEF_LLNVI_GEN(e, ln, port, MR_FALSE, path, NULL)
#define MR_DEF_LLNVIT(e, ln, port, num, path) \
MR_DEF_LLNVI_GEN(e, ln, port, MR_TRUE, path, NULL)
#define MR_DEF_LLNVI_U(e, ln, port, num, path) \
MR_DEF_LLNVI_GEN(e, ln, port, MR_FALSE, num, path, \
&MR_USER_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)))
#define MR_DEF_LLNVIT_U(e, ln, port, num, path) \
MR_DEF_LLNVI_GEN(e, ln, port, MR_TRUE, num, path, \
&MR_USER_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)))
/*-------------------------------------------------------------------------*/
#define MR_DECL_LL(e, ln) \
MR_declare_label(MR_label_name(MR_add_prefix(e), ln)); \
static const MR_LabelLayout \
MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)); \
#define MR_DECL_LLNVI(e, ln) \
MR_declare_label(MR_label_name(MR_add_prefix(e), ln)); \
static const MR_LabelLayoutNoVarInfo \
MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)); \
#define MR_DECL_LL1(e, ln1) \
MR_DECL_LL(e, ln1)
#define MR_DECL_LL2(e, ln1, ln2) \
MR_DECL_LL(e, ln1) \
MR_DECL_LL(e, ln2)
#define MR_DECL_LL3(e, ln1, ln2, ln3) \
MR_DECL_LL(e, ln1) \
MR_DECL_LL(e, ln2) \
MR_DECL_LL(e, ln3)
#define MR_DECL_LL4(e, ln1, ln2, ln3, ln4) \
MR_DECL_LL(e, ln1) \
MR_DECL_LL(e, ln2) \
MR_DECL_LL(e, ln3) \
MR_DECL_LL(e, ln4)
#define MR_DECL_LL5(e, ln1, ln2, ln3, ln4, ln5) \
MR_DECL_LL(e, ln1) \
MR_DECL_LL(e, ln2) \
MR_DECL_LL(e, ln3) \
MR_DECL_LL(e, ln4) \
MR_DECL_LL(e, ln5)
#define MR_DECL_LL6(e, ln1, ln2, ln3, ln4, ln5, ln6) \
MR_DECL_LL(e, ln1) \
MR_DECL_LL(e, ln2) \
MR_DECL_LL(e, ln3) \
MR_DECL_LL(e, ln4) \
MR_DECL_LL(e, ln5) \
MR_DECL_LL(e, ln6)
#define MR_DECL_LL7(e, ln1, ln2, ln3, ln4, ln5, ln6, ln7) \
MR_DECL_LL(e, ln1) \
MR_DECL_LL(e, ln2) \
MR_DECL_LL(e, ln3) \
MR_DECL_LL(e, ln4) \
MR_DECL_LL(e, ln5) \
MR_DECL_LL(e, ln6) \
MR_DECL_LL(e, ln7)
#define MR_DECL_LL8(e, ln1, ln2, ln3, ln4, ln5, ln6, ln7, ln8) \
MR_DECL_LL(e, ln1) \
MR_DECL_LL(e, ln2) \
MR_DECL_LL(e, ln3) \
MR_DECL_LL(e, ln4) \
MR_DECL_LL(e, ln5) \
MR_DECL_LL(e, ln6) \
MR_DECL_LL(e, ln7) \
MR_DECL_LL(e, ln8)
#define MR_DECL_LL9(e, ln1, ln2, ln3, ln4, ln5, ln6, ln7, ln8, ln9) \
MR_DECL_LL(e, ln1) \
MR_DECL_LL(e, ln2) \
MR_DECL_LL(e, ln3) \
MR_DECL_LL(e, ln4) \
MR_DECL_LL(e, ln5) \
MR_DECL_LL(e, ln6) \
MR_DECL_LL(e, ln7) \
MR_DECL_LL(e, ln8) \
MR_DECL_LL(e, ln9)
#define MR_DECL_LL10(e, ln1, ln2, ln3, ln4, ln5, ln6, ln7, ln8, ln9, ln10) \
MR_DECL_LL(e, ln1) \
MR_DECL_LL(e, ln2) \
MR_DECL_LL(e, ln3) \
MR_DECL_LL(e, ln4) \
MR_DECL_LL(e, ln5) \
MR_DECL_LL(e, ln6) \
MR_DECL_LL(e, ln7) \
MR_DECL_LL(e, ln8) \
MR_DECL_LL(e, ln9) \
MR_DECL_LL(e, ln10)
/*-------------------------------------------------------------------------*/
/*
** These macros are used as shorthands in generated C source files
** for some fields of MR_LabelLayouts.
**
** We need to cast the addresses of proc layout structures because there
** are several kinds of proc layouts, of different (though compatible) types.
*/
#define MR_LL(e, port, num, path) \
MR_PROC_LAYOUT(MR_add_prefix(e)), \
MR_PASTE2(MR_PORT_, port), \
MR_NOT_HIDDEN, (num), (path), NULL
#define MR_LL_H(e, port, num, path) \
MR_PROC_LAYOUT(MR_add_prefix(e)), \
MR_PASTE2(MR_PORT_, port), \
MR_HIDDEN, (num), (path), NULL
#define MR_LL_U(e, port, num, path, ue) \
MR_PROC_LAYOUT(MR_add_prefix(e)), \
MR_PASTE2(MR_PORT_, port), \
MR_NOT_HIDDEN, (num), (path), (ue)
#define MR_LL_H_U(e, port, num, path, ue) \
MR_PROC_LAYOUT(MR_add_prefix(e)), \
MR_PASTE2(MR_PORT_, port), \
MR_HIDDEN, (num), (path), (ue)
#if 0
/* these are new but already obsolete */
#define MR_LLV(lt, vn, tp) \
(const void *) (lt), \
(const MR_uint_least16_t *) (vn), \
(const MR_TypeParamLocns *) (tp)
#define MR_LLV_CC(ltt, ltc, vnt, vnc, tp) \
(const void *) MR_COMMON(ltt, ltc), \
(const MR_uint_least16_t *) MR_COMMON(vnt, vnc), \
(const MR_TypeParamLocns *) (tp)
#define MR_LLV_CCC(ltt, ltc, vnt, vnc, tpt, tpc) \
(const void *) MR_COMMON(ltt, ltc), \
(const MR_uint_least16_t *) MR_COMMON(vnt, vnc), \
(const MR_TypeParamLocns *) MR_COMMON(tpt, tpc)
#define MR_LLV_CC0(ltt, ltc, vnt, vnc) \
(const void *) MR_COMMON(ltt, ltc), \
(const MR_uint_least16_t *) MR_COMMON(vnt, vnc), \
(const MR_TypeParamLocns *) 0
#endif
#define MR_LLVS(m, p, h, s) \
&MR_pseudo_type_infos(m)[p], \
&MR_hlds_var_nums(m)[h], \
&MR_short_locns(m)[s]
#define MR_LLVL(m, p, h, s, l) \
&MR_pseudo_type_infos(m)[p], \
&MR_hlds_var_nums(m)[h], \
&MR_short_locns(m)[s], \
&MR_long_locns(m)[l]
#define MR_LLVS0(m, p, h, s) \
0, \
MR_LLVS(m, p, h, s)
#define MR_LLVL0(m, p, h, s, l) \
0, \
MR_LLVL(m, p, h, s, l)
#define MR_LLVSC(m, tpt, tpc, p, h, s) \
(const MR_TypeParamLocns *) MR_COMMON(tpt, tpc), \
MR_LLVS(m, p, h, s)
#define MR_LLVLC(m, tpt, tpc, p, h, s, l) \
(const MR_TypeParamLocns *) MR_COMMON(tpt, tpc), \
MR_LLVL(m, p, h, s, l)
#define MR_cast_to_pti1(r1) \
(MR_PseudoTypeInfo) (r1),
#define MR_cast_to_pti2(r1, r2) \
(MR_PseudoTypeInfo) (r1), \
(MR_PseudoTypeInfo) (r2),
#define MR_cast_to_pti3(r1, r2, r3) \
(MR_PseudoTypeInfo) (r1), \
(MR_PseudoTypeInfo) (r2), \
(MR_PseudoTypeInfo) (r3)
#define MR_cast_to_pti4(r1, r2, r3, r4) \
(MR_PseudoTypeInfo) (r1), \
(MR_PseudoTypeInfo) (r2), \
(MR_PseudoTypeInfo) (r3), \
(MR_PseudoTypeInfo) (r4),
#define MR_cast_to_pti5(r1, r2, r3, r4, r5) \
(MR_PseudoTypeInfo) (r1), \
(MR_PseudoTypeInfo) (r2), \
(MR_PseudoTypeInfo) (r3), \
(MR_PseudoTypeInfo) (r4), \
(MR_PseudoTypeInfo) (r5),
#define MR_cast_to_pti6(r1, r2, r3, r4, r5, r6) \
(MR_PseudoTypeInfo) (r1), \
(MR_PseudoTypeInfo) (r2), \
(MR_PseudoTypeInfo) (r3), \
(MR_PseudoTypeInfo) (r4), \
(MR_PseudoTypeInfo) (r5), \
(MR_PseudoTypeInfo) (r6),
#define MR_cast_to_pti7(r1, r2, r3, r4, r5, r6, r7) \
(MR_PseudoTypeInfo) (r1), \
(MR_PseudoTypeInfo) (r2), \
(MR_PseudoTypeInfo) (r3), \
(MR_PseudoTypeInfo) (r4), \
(MR_PseudoTypeInfo) (r5), \
(MR_PseudoTypeInfo) (r6), \
(MR_PseudoTypeInfo) (r7),
#define MR_cast_to_pti8(r1, r2, r3, r4, r5, r6, r7, r8) \
(MR_PseudoTypeInfo) (r1), \
(MR_PseudoTypeInfo) (r2), \
(MR_PseudoTypeInfo) (r3), \
(MR_PseudoTypeInfo) (r4), \
(MR_PseudoTypeInfo) (r5), \
(MR_PseudoTypeInfo) (r6), \
(MR_PseudoTypeInfo) (r7), \
(MR_PseudoTypeInfo) (r8),
#define MR_cast_to_pti9(r1, r2, r3, r4, r5, r6, r7, r8, r9) \
(MR_PseudoTypeInfo) (r1), \
(MR_PseudoTypeInfo) (r2), \
(MR_PseudoTypeInfo) (r3), \
(MR_PseudoTypeInfo) (r4), \
(MR_PseudoTypeInfo) (r5), \
(MR_PseudoTypeInfo) (r6), \
(MR_PseudoTypeInfo) (r7), \
(MR_PseudoTypeInfo) (r8), \
(MR_PseudoTypeInfo) (r9),
#define MR_cast_to_pti10(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10) \
(MR_PseudoTypeInfo) (r1), \
(MR_PseudoTypeInfo) (r2), \
(MR_PseudoTypeInfo) (r3), \
(MR_PseudoTypeInfo) (r4), \
(MR_PseudoTypeInfo) (r5), \
(MR_PseudoTypeInfo) (r6), \
(MR_PseudoTypeInfo) (r7), \
(MR_PseudoTypeInfo) (r8), \
(MR_PseudoTypeInfo) (r9), \
(MR_PseudoTypeInfo) (r10),
/*-------------------------------------------------------------------------*/
/*
** Definitions for MR_ProcLayout.
*/
/*
** The MR_TableIoDecl structure.
**
** To enable declarative debugging of I/O actions, the compiler generates one
** of these structures for each I/O primitive. The compiler transforms the
** bodies of those primitives to create a block of memory and fill it in with
** (1) a pointer to the primitive's MR_TableIoDecl structure and (2) the
** values of the primitive's arguments (both input and output, but excluding
** the I/O states). The array of pseudo-typeinfos pointed to by the ptis field
** gives the types of these arguments, while the filtered_arity field gives
** the number of saved arguments, which will be all the arguments except the
** I/O states. The number in this field is the size of the ptis array, and
** the size of the block exclusive of the pointer. The proc field allows us
** to identify the primitive procedure. This is all the information we need
** to describe the I/O action to the user.
*/
typedef struct MR_TableIoDecl_Struct {
const MR_ProcLayout *MR_table_io_decl_proc;
MR_Integer MR_table_io_decl_filtered_arity;
const MR_PseudoTypeInfo *MR_table_io_decl_ptis;
const MR_TypeParamLocns *MR_table_io_decl_type_params;
} MR_TableIoDecl;
/*
** MR_TableInfo: compiler generated information describing the tabling
** data structures used by a procedure.
**
** For I/O tabled procedures, the information is in the io_decl field.
** For other kinds of tabled procedures, it is in the gen field.
** The init field is used for initialization only.
**
** The MR_table_proc field is not const because the structure it points to
** has fields containing statistics, which are updated at runtime.
*/
typedef union {
const void *MR_table_init;
const MR_TableIoDecl *MR_table_io_decl;
const MR_Table_Gen *MR_table_gen;
MR_ProcTableInfo *MR_table_proc;
} MR_TableInfo;
/*
** The MR_StackTraversal structure contains the following fields:
**
** The code_addr field points to the start of the procedure's code.
** This allows the profiler to figure out which procedure a sampled program
** counter belongs to, and allows the debugger to implement retry.
**
** The succip_locn field encodes the location of the saved succip if it is
** saved in a general purpose stack slot. If the succip is saved in a special
** purpose stack slot (as it is for model_non procedures) or if the procedure
** never saves the succip (as in leaf procedures), this field will contain -1.
**
** The stack_slots field gives the number of general purpose stack slots
** in the procedure.
**
** The detism field encodes the determinism of the procedure.
*/
typedef struct MR_StackTraversal_Struct {
MR_Code *MR_trav_code_addr;
MR_LongLval MR_trav_succip_locn;
MR_int_least16_t MR_trav_stack_slots;
MR_Determinism MR_trav_detism;
} MR_StackTraversal;
#define MR_PROC_LAYOUT_IS_UCI(entry) \
MR_PROC_ID_IS_UCI(entry->MR_sle_proc_id)
/*
** The MR_ExecTrace structure contains the following fields.
**
** The call_label field points to the label layout structure for the label
** associated with the call event at the entry to the procedure. The purpose
** of this field is to allow the debugger to find out which variables
** are where on entry, so it can reexecute the procedure if asked to do so
** and if the values of the required variables are still available.
**
** The labels field contains a pointer to an array of pointers to label layout
** structures; the size of the array is given by the num_labels field. The
** initial part of the array will contain a pointer to the label layout
** structure of every interface event in the procedure; the later parts will
** contain a pointer to the label layout structure of every internal event.
** There is no ordering on the events beyond interface first, internal second.
**
** The used_var_names field points to an array that contains offsets
** into the string table, with the offset at index i-1 giving the name of
** variable i (since variable numbers start at one). If a variable has no name
** or cannot be referred to from an event, the offset will be zero, at which
** offset the string table will contain an empty string.
**
** The max_named_var_num field gives the number of elements in the
** used_var_names table, which is also the number of the highest numbered
** named variable. Note that unnamed variables may have numbers higher than
** this.
**
** The max_r_num field tells the debugger which Mercury abstract machine
** registers need saving in MR_trace: besides the special registers, it is
** the general-purpose registers rN for values of N up to and including the
** value of this field. Note that this field contains an upper bound; in
** general, there will be calls to MR_trace at which the number of the highest
** numbered general purpose (i.e. rN) registers is less than this. However,
** storing the upper bound gets us almost all the benefit (of not saving and
** restoring all the thousand rN registers) for a small fraction of the static
** space cost of storing the actual number in label layout structures.
**
** If the procedure is compiled with deep tracing, the maybe_from_full field
** will contain a negative number. If it is compiled with shallow tracing,
** it will contain the number of the stack slot that holds the flag that says
** whether this incarnation of the procedure was called from deeply traced code
** or not. (The determinism of the procedure decides whether the stack slot
** refers to a stackvar or a framevar.)
**
** If tabling of I/O actions is enabled, the maybe_io_seq field will contain
** the number of the stack slot that holds the value the I/O action counter
** had on entry to this procedure. Even procedures that do not have I/O state
** arguments will have such a slot, since they or their descendants may call
** unsafe_perform_io.
**
** If trailing is not enabled, the maybe_trail field will contain a negative
** number. If it is enabled, it will contain number of the first of two stack
** slots used for checkpointing the state of the trail on entry to the
** procedure. The first contains the trail pointer, the second the ticket.
**
** If the procedure lives on the nondet stack, or if it cannot create any
** temporary nondet stack frames, the maybe_maxfr field will contain a negative
** number. If it lives on the det stack, and can create temporary nondet stack
** frames, it will contain the number number of the stack slot that contains the
** value of maxfr on entry, for use in executing the retry debugger command
** from the middle of the procedure.
**
** The eval_method field contains a representation of the evaluation method
** used by the procedure. The retry command needs this information if it is
** to reset the call tables of the procedure invocations being retried.
**
** We cannot put enums into structures as bit fields. To avoid wasting space,
** we put MR_EvalMethodInts into structures instead of MR_EvalMethods
** themselves.
**
** If the procedure is compiled with some form of tabling, the maybe_call_table
** field contains the number of the stack slot through which we can reach the
** call table entry for this call. In forms of tabling which associate a C
** structure (MR_Subgoal, MR_MemoNonRecord) with a call table entry, the slot
** will point to that structure; in other forms of tabling, it will point
** to the call's MR_TableNode.
**
** The flags field encodes boolean properties of the procedure. For now,
** the only property is whether the procedure has a pair of I/O state
** arguments.
**
** If the procedure lives on the nondet stack, or if it cannot create any
** temporary nondet stack frames, the maybe_maxfr field will contain a negative
** number. If it lives on the det stack, and can create temporary nondet stack
** frames, it will contain the number of the stack slot that contains the
** value of maxfr on entry, for use in executing the retry debugger command
** from the middle of the procedure.
*/
#define MR_EVAL_METHOD_MEMO_STRICT MR_EVAL_METHOD_MEMO
#define MR_EVAL_METHOD_MEMO_FAST_LOOSE MR_EVAL_METHOD_MEMO
#define MR_EVAL_METHOD_MEMO_SPECIFIED MR_EVAL_METHOD_MEMO
typedef enum {
MR_EVAL_METHOD_NORMAL,
MR_EVAL_METHOD_LOOP_CHECK,
MR_EVAL_METHOD_MEMO,
MR_EVAL_METHOD_MINIMAL_STACK_COPY,
MR_EVAL_METHOD_MINIMAL_OWN_STACKS_CONSUMER,
MR_EVAL_METHOD_MINIMAL_OWN_STACKS_GENERATOR,
MR_EVAL_METHOD_TABLE_IO,
MR_EVAL_METHOD_TABLE_IO_DECL,
MR_EVAL_METHOD_TABLE_IO_UNITIZE,
MR_EVAL_METHOD_TABLE_IO_UNITIZE_DECL
} MR_EvalMethod;
typedef MR_int_least8_t MR_EvalMethodInt;
typedef enum {
MR_DEFINE_MERCURY_ENUM_CONST(MR_TRACE_LEVEL_NONE),
MR_DEFINE_MERCURY_ENUM_CONST(MR_TRACE_LEVEL_BASIC),
MR_DEFINE_MERCURY_ENUM_CONST(MR_TRACE_LEVEL_BASIC_USER),
MR_DEFINE_MERCURY_ENUM_CONST(MR_TRACE_LEVEL_SHALLOW),
MR_DEFINE_MERCURY_ENUM_CONST(MR_TRACE_LEVEL_DEEP),
MR_DEFINE_MERCURY_ENUM_CONST(MR_TRACE_LEVEL_DECL_REP)
} MR_TraceLevel;
typedef MR_int_least8_t MR_TraceLevelInt;
typedef struct MR_ExecTrace_Struct {
const MR_LabelLayout *MR_exec_call_label;
const MR_ModuleLayout *MR_exec_module_layout;
const MR_LabelLayout **MR_exec_labels;
MR_uint_least32_t MR_exec_num_labels;
MR_TableInfo MR_exec_table_info;
const MR_uint_least16_t *MR_exec_head_var_nums;
const MR_uint_least32_t *MR_exec_used_var_names;
MR_uint_least16_t MR_exec_num_head_vars;
MR_uint_least16_t MR_exec_max_named_var_num;
MR_uint_least16_t MR_exec_max_r_num;
MR_int_least8_t MR_exec_maybe_from_full;
MR_int_least8_t MR_exec_maybe_io_seq;
MR_int_least8_t MR_exec_maybe_trail;
MR_int_least8_t MR_exec_maybe_maxfr;
MR_EvalMethodInt MR_exec_eval_method_CAST_ME;
MR_int_least8_t MR_exec_maybe_call_table;
MR_TraceLevelInt MR_exec_trace_level_CAST_ME;
MR_uint_least8_t MR_exec_flags;
MR_int_least8_t MR_exec_maybe_tail_rec;
} MR_ExecTrace;
#define MR_compute_max_mr_num(max_mr_num, layout) \
do { \
int max_r_num; \
\
max_r_num = (layout)->MR_sll_entry->MR_sle_max_r_num + \
MR_NUM_SPECIAL_REG; \
max_mr_num = MR_max(max_r_num, MR_FIRST_UNREAL_R_SLOT); \
} while (0)
#define MR_PROC_LAYOUT_FLAG_HAS_IO_STATE_PAIR 0x1
#define MR_trace_find_reused_frames(proc_layout, sp, reused_frames) \
do { \
const MR_ExecTrace *exec_trace; \
int tailrec_slot; \
\
exec_trace = proc_layout->MR_sle_exec_trace; \
if (exec_trace == NULL) { \
(reused_frames) = 0; \
} else { \
tailrec_slot = proc_layout->MR_sle_maybe_tailrec; \
if (tailrec_slot <= 0) { \
(reused_frames) = 0; \
} else { \
if (MR_DETISM_DET_STACK(proc_layout->MR_sle_detism)) { \
(reused_frames) = MR_based_stackvar((sp), tailrec_slot);\
} else { \
MR_fatal_error("tailrec reuses nondet stack frames"); \
} \
} \
} \
} while (0)
/*
** Proc layout structures contain one, two or three substructures.
**
** - The first substructure is the MR_StackTraversal structure, which contains
** information that enables the stack to be traversed, e.g. for accurate gc.
** It is always present if proc layouts are present at all.
**
** - The second group is the MR_ProcId union, which identifies the
** procedure in terms that are meaningful to both humans and machines.
** It will be generated only if the module is compiled with stack tracing,
** execution tracing or profiling. The MR_ProcId union has two alternatives,
** one for user-defined procedures and one for procedures of the compiler
** generated Unify, Index and Compare predicates.
**
** - The third group is everything else. Currently, this consists of
** information that is of interest to the debugger, to the deep profiler,
** or both.
**
** The information that is of interest to the debugger only is stored in
** the MR_ExecTrace structure, which will be generated only if the module
** is compiled with execution tracing. The information that is of interest to
** the deep profiler is stored in the MR_ProcStatic structure, which will be
** generated only if the module is compiled in a deep profiling grade. The
** other fields in the group are of interest to both the debugger and the
** deep profiler, and will be generated if either execution tracing or deep
** profiling is enabled.
**
** If the body_bytes field is NULL, it means that no representation of the
** procedure body is available. If non-NULL, it contains a pointer to an
** array of bytecodes that represents the body of the procedure. The
** bytecode array should be interpreted by the read_proc_rep predicate in
** mdbcomp/program_representation.m (it starts with an encoded form of the
** array's length). Its contents are generated by compiler/prog_rep.m.
**
** The module_common_layout field points to the part of the module layout
** structure of the module containing the procedure that is common to the
** debugger and the deep profiler. Amongst other things, it gives access to
** the string table that the body_bytes fields refers to.
**
** The runtime system considers all proc layout structures to be of type
** MR_ProcLayout, but must use the macros defined below to check for the
** existence of each substructure before accessing the fields of that
** substructure. The macros are MR_PROC_LAYOUT_HAS_PROC_ID to check for the
** MR_ProcId substructure, MR_PROC_LAYOUT_HAS_EXEC_TRACE to check for the
** MR_ExecTrace substructure, and MR_PROC_LAYOUT_HAS_PROC_STATIC to check for
** the MR_ProcStatic substructure.
**
** The reason why some substructures may be missing is to save space.
** If the options with which a module is compiled do not require execution
** tracing, then the MR_ExecTrace substructure will not present, and if the
** options do not require procedure identification, then the MR_ProcId
** substructure will not be present either. The body_bytes and module_layout
** fields cannot be non-NULL unless at least one of exec trace and proc static
** substructures is present, but they are otherwise independent of those
** substructures.
**
** The compiler itself generates proc layout structures using the following
** three types.
**
** - When generating only stack traversal information, the compiler will
** generate proc layout structures of type MR_ProcLayout_Traversal.
**
** - When generating stack traversal and procedure id information, plus
** possibly others, the compiler will generate proc layout structures of
** types MR_ProcLayoutUser and MR_ProcLayoutUCI.
*/
struct MR_ProcLayout_Struct {
MR_StackTraversal MR_sle_traversal;
MR_ProcId MR_sle_proc_id;
MR_STATIC_CODE_CONST MR_ExecTrace *MR_sle_exec_trace;
MR_ProcStatic *MR_sle_proc_static;
const MR_uint_least8_t *MR_sle_body_bytes;
const MR_ModuleCommonLayout *MR_sle_module_common_layout;
};
typedef struct MR_ProcLayoutUser_Struct {
MR_StackTraversal MR_user_traversal;
MR_UserProcId MR_user_id;
MR_STATIC_CODE_CONST MR_ExecTrace *MR_sle_exec_trace;
MR_ProcStatic *MR_sle_proc_static;
const MR_uint_least8_t *MR_sle_body_bytes;
const MR_ModuleCommonLayout *MR_sle_module_common_layout;
} MR_ProcLayoutUser;
typedef struct MR_ProcLayoutUCI_Struct {
MR_StackTraversal MR_uci_traversal;
MR_UCIProcId MR_uci_id;
MR_STATIC_CODE_CONST MR_ExecTrace *MR_sle_exec_trace;
MR_ProcStatic *MR_sle_proc_static;
const MR_uint_least8_t *MR_sle_body_bytes;
const MR_ModuleCommonLayout *MR_sle_module_common_layout;
} MR_ProcLayoutUCI;
typedef struct MR_ProcLayout_Traversal_Struct {
MR_StackTraversal MR_trav_traversal;
MR_Word MR_trav_no_proc_id; /* will be -1 */
} MR_ProcLayout_Traversal;
#define MR_PROC_LAYOUT_HAS_PROC_ID(entry) \
(MR_PROC_ID_EXISTS(entry->MR_sle_proc_id))
#define MR_PROC_LAYOUT_HAS_EXEC_TRACE(entry) \
(MR_PROC_LAYOUT_HAS_PROC_ID(entry) && \
entry->MR_sle_exec_trace != NULL)
#define MR_PROC_LAYOUT_HAS_PROC_STATIC(entry) \
(MR_PROC_LAYOUT_HAS_PROC_ID(entry) && \
entry->MR_sle_proc_static != NULL)
#define MR_PROC_LAYOUT_HAS_THIRD_GROUP(entry) \
(MR_PROC_LAYOUT_HAS_PROC_ID(entry) && \
( entry->MR_sle_exec_trace != NULL \
|| entry->MR_sle_proc_static != NULL))
#define MR_sle_code_addr MR_sle_traversal.MR_trav_code_addr
#define MR_sle_succip_locn MR_sle_traversal.MR_trav_succip_locn
#define MR_sle_stack_slots MR_sle_traversal.MR_trav_stack_slots
#define MR_sle_detism MR_sle_traversal.MR_trav_detism
#define MR_sle_user MR_sle_proc_id.MR_proc_user
#define MR_sle_uci MR_sle_proc_id.MR_proc_uci
#define MR_sle_call_label MR_sle_exec_trace->MR_exec_call_label
#define MR_sle_module_layout MR_sle_exec_trace->MR_exec_module_layout
#define MR_sle_labels MR_sle_exec_trace->MR_exec_labels
#define MR_sle_num_labels MR_sle_exec_trace->MR_exec_num_labels
#define MR_sle_tabling_pointer MR_sle_exec_trace->MR_exec_tabling_pointer
#define MR_sle_table_info MR_sle_exec_trace->MR_exec_table_info
#define MR_sle_head_var_nums MR_sle_exec_trace->MR_exec_head_var_nums
#define MR_sle_num_head_vars MR_sle_exec_trace->MR_exec_num_head_vars
#define MR_sle_used_var_names MR_sle_exec_trace->MR_exec_used_var_names
#define MR_sle_max_named_var_num MR_sle_exec_trace->MR_exec_max_named_var_num
#define MR_sle_max_r_num MR_sle_exec_trace->MR_exec_max_r_num
#define MR_sle_maybe_from_full MR_sle_exec_trace->MR_exec_maybe_from_full
#define MR_sle_maybe_io_seq MR_sle_exec_trace->MR_exec_maybe_io_seq
#define MR_sle_maybe_trail MR_sle_exec_trace->MR_exec_maybe_trail
#define MR_sle_maybe_maxfr MR_sle_exec_trace->MR_exec_maybe_maxfr
#define MR_sle_maybe_call_table MR_sle_exec_trace->MR_exec_maybe_call_table
#define MR_sle_maybe_decl_debug MR_sle_exec_trace->MR_exec_maybe_decl_debug
#define MR_sle_maybe_tailrec MR_sle_exec_trace->MR_exec_maybe_tail_rec
#define MR_sle_eval_method(proc_layout_ptr) \
((MR_EvalMethod) (proc_layout_ptr)-> \
MR_sle_exec_trace->MR_exec_eval_method_CAST_ME)
#define MR_sle_trace_level(proc_layout_ptr) \
((MR_TraceLevel) (proc_layout_ptr)-> \
MR_sle_exec_trace->MR_exec_trace_level_CAST_ME)
#define MR_proc_has_io_state_pair(proc_layout_ptr) \
((proc_layout_ptr)->MR_sle_exec_trace->MR_exec_flags \
& MR_PROC_LAYOUT_FLAG_HAS_IO_STATE_PAIR)
/* Adjust the arity of functions for printing. */
#define MR_sle_user_adjusted_arity(entry) \
((entry)->MR_sle_user.MR_user_arity - \
(((entry)->MR_sle_user.MR_user_pred_or_func == MR_FUNCTION) ? 1 : 0))
/*
** Return the name (if any) of the variable with the given HLDS variable number
** in the procedure indicated by the first argument.
*/
extern MR_ConstString MR_hlds_var_name(const MR_ProcLayout *entry,
int hlds_var_num);
/*
** Given a string, see whether its end consists a sequence of digits.
** If yes, return the offset of the first digit in this sequence relative
** to the start of the string. Otherwise, return a negative number.
*/
extern int MR_find_start_of_num_suffix(const char *str);
/*
** Define a layout structure for a procedure, containing information
** for stack traversal and procedure identification.
**
** The slot count and the succip location parameters do not have to be
** supplied for procedures that live on the nondet stack, since for such
** procedures the size of the frame can be deduced from the prevfr field
** and the location of the succip is fixed.
**
** An unknown slot count should be signalled by MR_PROC_NO_SLOT_COUNT.
** An unknown succip location should be signalled by MR_LONG_LVAL_TYPE_UNKNOWN.
**
** For the procedure identification, we always use the same module name
** for the defining and declaring modules, since procedures whose code
** is hand-written as C modules cannot be inlined in other Mercury modules.
**
** Due to the possibility that code addresses are not static, any use of
** the MR_MAKE_PROC_ID_PROC_LAYOUT macro has to be accompanied by a call to the
** MR_INIT_PROC_LAYOUT_ADDR macro in the initialization code of the C module
** that defines the entry. (The cast in the body of MR_INIT_PROC_LAYOUT_ADDR
** is needed because compiler-generated layout structures may use any of the
** variant types listed above.)
*/
#define MR_PROC_NO_SLOT_COUNT -1
#ifdef MR_STATIC_CODE_ADDRESSES
#define MR_MAKE_PROC_LAYOUT_ADDR(entry) MR_ENTRY(entry)
#define MR_INIT_PROC_LAYOUT_ADDR(entry) do { } while (0)
#else
#define MR_MAKE_PROC_LAYOUT_ADDR(entry) ((MR_Code *) NULL)
#define MR_INIT_PROC_LAYOUT_ADDR(entry) \
do { \
((MR_ProcLayout *) & \
MR_PASTE2(mercury_data__proc_layout__, entry)) \
->MR_sle_code_addr = MR_ENTRY(entry); \
} while (0)
#endif
#define MR_MAKE_USER_PROC_STATIC_PROC_LAYOUT(sc, detism, slots, succip_locn, \
pf, module, name, arity, mode, proc_static) \
MR_declare_entry(MR_proc_entry_user_name(module, name, \
arity, mode)); \
sc const MR_ProcLayoutUser \
MR_proc_layout_user_name(module, name, arity, mode) = { \
{ \
MR_MAKE_PROC_LAYOUT_ADDR( \
MR_proc_entry_user_name(module, name, \
arity, mode)), \
succip_locn, \
slots, \
detism \
}, \
{ \
pf, \
MR_STRINGIFY(module), \
MR_STRINGIFY(module), \
MR_STRINGIFY(name), \
arity, \
mode \
}, \
NULL, \
(MR_ProcStatic *) proc_static \
}
#define MR_MAKE_UCI_PROC_STATIC_PROC_LAYOUT(sc, detism, slots, succip_locn, \
module, name, type, arity, mode, proc_static) \
MR_declare_entry(MR_proc_entry_uci_name(module, name, \
type, arity, mode)); \
sc const MR_ProcLayoutUCI \
MR_proc_layout_uci_name(module, name, type, arity, mode) = { \
{ \
MR_MAKE_PROC_LAYOUT_ADDR( \
MR_proc_entry_uci_name(module, name, \
type, arity, mode)), \
succip_locn, \
slots, \
detism \
}, \
{ \
MR_STRINGIFY(type), \
MR_STRINGIFY(module), \
MR_STRINGIFY(module), \
MR_STRINGIFY(name), \
arity, \
mode \
}, \
NULL, \
(MR_ProcStatic *) proc_static \
}
#define MR_NO_EXTERN_DECL
#define MR_STATIC_USER_PROC_STATIC_PROC_LAYOUT(detism, slots, succip_locn, \
pf, module, name, arity, mode) \
MR_MAKE_USER_PROC_STATIC_PROC_LAYOUT(static, detism, slots, \
succip_locn, pf, module, name, arity, mode, \
&MR_proc_static_user_name(module, name, arity, mode))
#define MR_EXTERN_USER_PROC_STATIC_PROC_LAYOUT(detism, slots, succip_locn, \
pf, module, name, arity, mode) \
MR_MAKE_USER_PROC_STATIC_PROC_LAYOUT(MR_NO_EXTERN_DECL, detism, slots, \
succip_locn, pf, module, name, arity, mode, \
&MR_proc_static_user_name(module, name, arity, mode))
#define MR_STATIC_UCI_PROC_STATIC_PROC_LAYOUT(detism, slots, succip_locn, \
module, name, type, arity, mode) \
MR_MAKE_UCI_PROC_STATIC_PROC_LAYOUT(static, detism, slots, \
succip_locn, module, name, type, arity, mode, \
&MR_proc_static_uci_name(module, name, type, arity, mode))
#define MR_EXTERN_UCI_PROC_STATIC_PROC_LAYOUT(detism, slots, succip_locn, \
module, name, type, arity, mode) \
MR_MAKE_UCI_PROC_STATIC_PROC_LAYOUT(MR_NO_EXTERN_DECL, detism, slots, \
succip_locn, module, name, type, arity, mode, \
&MR_proc_static_uci_name(module, name, type, arity, mode))
#define MR_STATIC_USER_PROC_ID_PROC_LAYOUT(detism, slots, succip_locn, \
pf, module, name, arity, mode) \
MR_MAKE_USER_PROC_STATIC_PROC_LAYOUT(static, detism, slots, \
succip_locn, pf, module, name, arity, mode, NULL)
#define MR_EXTERN_USER_PROC_ID_PROC_LAYOUT(detism, slots, succip_locn, \
pf, module, name, arity, mode) \
MR_MAKE_USER_PROC_STATIC_PROC_LAYOUT(MR_NO_EXTERN_DECL, detism, slots, \
succip_locn, pf, module, name, arity, mode, NULL)
#define MR_DECLARE_UCI_PROC_STATIC_LAYOUTS(mod, n, a) \
const MR_ProcLayoutUCI \
MR_proc_layout_uci_name(mod, __Unify__, n, a, 0); \
const MR_ProcLayoutUCI \
MR_proc_layout_uci_name(mod, __Compare__, n, a, 0); \
const MR_ProcLayoutUCI \
MR_proc_layout_uci_name(mod, __CompareRep__, n, a, 0);
/*
** In procedures compiled with execution tracing, three items are stored
** in stack slots with fixed numbers. They are:
**
** the event number of the last event before the call event,
** the call number, and
** the call depth.
**
** Note that the first slot does not store the number of the call event
** itself, but rather the number of the call event minus one. The reason
** for this is that (a) incrementing the number stored in this slot would
** increase executable size, and (b) if the procedure is shallow traced,
** MR_trace may not be called for the call event, so we cannot shift the
** burden of initializing fields to the MR_trace of the call event either.
**
** The following macros will access the fixed slots. They can be used whenever
** MR_PROC_LAYOUT_HAS_EXEC_TRACE(entry) is true; which set you should use
** depends on the determinism of the procedure.
**
** These macros have to be kept in sync with compiler/trace.m.
*/
#define MR_event_num_framevar(base_curfr) MR_based_framevar(base_curfr, 1)
#define MR_call_num_framevar(base_curfr) MR_based_framevar(base_curfr, 2)
#define MR_call_depth_framevar(base_curfr) MR_based_framevar(base_curfr, 3)
#define MR_event_num_stackvar(base_sp) MR_based_stackvar(base_sp, 1)
#define MR_call_num_stackvar(base_sp) MR_based_stackvar(base_sp, 2)
#define MR_call_depth_stackvar(base_sp) MR_based_stackvar(base_sp, 3)
/*
** In model_non procedures compiled with --trace-redo, one or two other items
** are stored in fixed stack slots. These are
**
** the address of the layout structure for the redo event
** the saved copy of the from-full flag (only if trace level is shallow)
**
** The following macros will access these slots. They should be used only from
** within the code that calls MR_trace for the REDO event.
**
** This macros have to be kept in sync with compiler/trace.m.
*/
#define MR_redo_layout_framevar(base_curfr) MR_based_framevar(base_curfr, 4)
#define MR_redo_fromfull_framevar(base_curfr) MR_based_framevar(base_curfr, 5)
/*-------------------------------------------------------------------------*/
/*
** Definitions for MR_ModuleLayout.
**
** The layout structure for a module contains the following fields.
**
** The MR_ml_name field contains the name of the module.
**
** The MR_ml_string_table field contains the module's string table, which
** contains strings referred to by other layout structures in the module
** (initially only the tables containing variables names, referred to from
** label layout structures). The MR_ml_string_table_size field gives the size
** of the table in bytes.
**
** The MR_ml_procs field points to an array containing pointers to the proc
** layout structures of all the procedures in the module; the MR_ml_proc_count
** field gives the number of entries in the array.
**
** The MR_ml_module_file_layout field points to an array of N file layout
** pointers if the module has labels corresponding to contexts that refer
** to the names of N files. For each file, the table gives its name, the
** number of labels in that file in this module, and for each such label,
** it gives its line number and a pointer to its label layout struct.
** The corresponding elements of the label_lineno and label_layout arrays
** refer to the same label. (The reason why they are not stored together
** is space efficiency; adding a 16 bit field to a label layout structure would
** require padding.) The labels are sorted on line number.
**
** The MR_ml_trace_level field gives the trace level that the module was
** compiled with. If the MR_TraceLevel enum is modified, then the
** corresponding function in compiler/trace_params.m must also be updated.
**
** The MR_ml_suppressed_events events field encodes the set of event types
** (ports) that were suppressed when generating code for this module. The bit
** given by the expression (1 << MR_PORT_<PORTTYPE>) will be set in this
** integer iff trace port MR_PORT_<PORTTYPE> is suppressed.
**
** The MR_ml_label_exec_count field points to an array of integers, with each
** integer holding the number of times execution has reached a given label.
** Each label's layout structure records the index of that label in this array.
** The most direct way to go the other way, to find out which label owns a
** particular slot in this array, is to search the label arrays in the file
** layout structures, and test their MR_sll_label_num_in_module fields.
** (If we needed faster access, we could add another array with elements
** corresponding to MR_ml_label_exec_count's pointing to the labels' layout
** structures.)
**
** The MR_ml_num_label_exec_counts field contains the number of elements
** in the MR_ml_label_exec_count array.
*/
typedef struct MR_ModuleFileLayout_Struct {
MR_ConstString MR_mfl_filename;
MR_Integer MR_mfl_label_count;
/* the following fields point to arrays of size MR_mfl_label_count */
const MR_int_least16_t *MR_mfl_label_lineno;
const MR_LabelLayout **MR_mfl_label_layout;
} MR_ModuleFileLayout;
/*
** The version of the data structures in this file -- useful for bootstrapping.
** If you write runtime code that checks this version number and can at least
** handle the previous version of the data structure, it makes it easier to
** bootstrap changes to these data structures.
**
** This number should be kept in sync with layout_version_number in
** compiler/layout_out.m.
*/
#define MR_LAYOUT_VERSION MR_LAYOUT_VERSION__COMMON
#define MR_LAYOUT_VERSION__USER_DEFINED 1
#define MR_LAYOUT_VERSION__EVENTSETNAME 2
#define MR_LAYOUT_VERSION__SYNTH_ATTR 3
#define MR_LAYOUT_VERSION__COMMON 4
struct MR_ModuleCommonLayout_Struct {
MR_uint_least8_t MR_mlc_version_number;
MR_ConstString MR_mlc_name;
MR_Integer MR_mlc_string_table_size;
const char *MR_mlc_string_table;
};
struct MR_ModuleLayout_Struct {
const MR_ModuleCommonLayout *MR_ml_common;
MR_Integer MR_ml_proc_count;
const MR_ProcLayout **MR_ml_procs;
MR_Integer MR_ml_filename_count;
const MR_ModuleFileLayout **MR_ml_module_file_layout;
MR_TraceLevel MR_ml_trace_level;
MR_int_least32_t MR_ml_suppressed_events;
MR_int_least32_t MR_ml_num_label_exec_counts;
MR_Unsigned *MR_ml_label_exec_count;
const char *MR_ml_user_event_set_name;
const char *MR_ml_user_event_set_desc;
MR_int_least16_t MR_ml_user_event_max_num_attr;
MR_int_least16_t MR_ml_num_user_event_specs;
MR_UserEventSpec *MR_ml_user_event_specs;
};
#define MR_ml_version_number MR_ml_common->MR_mlc_version_number
#define MR_ml_name MR_ml_common->MR_mlc_name
#define MR_ml_string_table_size MR_ml_common->MR_mlc_string_table_size
#define MR_ml_string_table MR_ml_common->MR_mlc_string_table
/*-------------------------------------------------------------------------*/
/*
** Definitions for MR_ClosureId.
**
** Each closure contains an MR_ClosureId structure. The proc_id field
** identifies the procedure called by the closure. The other fields identify
** the context where the closure was created.
**
** The compiler generates closure id structures as either MR_UserClosureId
** or MR_UCIClosureId structures in order to avoid initializing the
** MR_ProcId union through an inappropriate member.
*/
struct MR_ClosureId_Struct {
MR_ProcId MR_closure_proc_id;
MR_ConstString MR_closure_module_name;
MR_ConstString MR_closure_file_name;
MR_Integer MR_closure_line_number;
MR_ConstString MR_closure_goal_path;
};
struct MR_UserClosureId_Struct {
MR_UserProcId MR_user_closure_proc_id;
MR_ConstString MR_user_closure_module_name;
MR_ConstString MR_user_closure_file_name;
MR_Integer MR_user_closure_line_number;
MR_ConstString MR_user_closure_goal_path;
};
struct MR_UCIClosureId_Struct {
MR_UCIProcId MR_uci_closure_proc_id;
MR_ConstString MR_uci_closure_module_name;
MR_ConstString MR_uci_closure_file_name;
MR_Integer MR_uci_closure_line_number;
MR_ConstString MR_uci_closure_goal_path;
};
#endif /* not MERCURY_STACK_LAYOUT_H */