mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 09:23:44 +00:00
449 lines
18 KiB
Mathematica
449 lines
18 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2001-2009, 2011 The University of Melbourne.
|
|
% Copyright (C) 2014-2015, 2019, 2022 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: layout.m.
|
|
% Author: zs.
|
|
%
|
|
% Definitions of Mercury types for representing layout structures within
|
|
% the compiler. Layout structures 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, the deep profiler and (eventually) the accurate garbage
|
|
% collector.
|
|
%
|
|
% When output by layout_out.m, values of most these types will correspond
|
|
% to the C types defined in runtime/mercury_stack_layout.h or
|
|
% runtime/mercury_deep_profiling.h; the documentation of those types
|
|
% can be found there. The names of the C types are listed next to the
|
|
% function symbol whose arguments represent their contents.
|
|
%
|
|
% The code to generate values of these types is in stack_layout.m and
|
|
% deep_profiling.m.
|
|
%
|
|
% This module should be, but as yet isn't, independent of whether we are
|
|
% compiling to LLDS or MLDS.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module ll_backend.layout.
|
|
:- interface.
|
|
|
|
:- import_module hlds.
|
|
:- import_module hlds.hlds_rtti.
|
|
:- import_module hlds.pred_name.
|
|
:- import_module libs.
|
|
:- import_module libs.trace_params.
|
|
:- import_module ll_backend.llds.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_data_event.
|
|
:- import_module parse_tree.prog_data_pragma.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module bool.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module maybe.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Closure layouts.
|
|
%
|
|
|
|
:- type closure_proc_id_data
|
|
---> closure_proc_id_data(
|
|
% defines MR_ClosureId
|
|
caller_proc_label :: proc_label,
|
|
caller_closure_seq_no :: int,
|
|
closure_proc_label :: proc_label,
|
|
closure_module_name :: module_name,
|
|
closure_file_name :: string,
|
|
closure_line_number :: int,
|
|
closure_origin :: pred_origin,
|
|
closure_goal_path :: string
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Proc layouts and their components.
|
|
%
|
|
|
|
:- type user_event_data
|
|
---> user_event_data(
|
|
user_event_number :: int,
|
|
user_event_locns :: rval,
|
|
user_event_var_nums :: layout_slot_name
|
|
).
|
|
|
|
:- type basic_label_layout
|
|
---> basic_label_layout(
|
|
proc_label :: proc_label,
|
|
label_num :: int,
|
|
proc_layout_name :: layout_name,
|
|
maybe_port :: maybe(trace_port),
|
|
maybe_is_hidden :: maybe(bool),
|
|
label_num_in_module :: int,
|
|
maybe_goal_path :: maybe(int), % offset
|
|
maybe_user_info :: maybe(layout_slot_name)
|
|
).
|
|
|
|
:- type label_short_var_info
|
|
---> label_short_var_info(
|
|
% part of MR_LabelLayout
|
|
lsvi_encoded_var_count :: int, % encodes #Long=0 and #Short
|
|
lsvi_type_params :: rval,
|
|
lsvi_ptis :: int, % -1 if none, otherwise slot#
|
|
lsvi_hlds_var_nums :: int, % -1 if none, otherwise slot#
|
|
lsvi_short_locns :: int % -1 if none, otherwise slot#
|
|
).
|
|
|
|
:- type label_long_var_info
|
|
---> label_long_var_info(
|
|
% part of MR_LabelLayout
|
|
llvi_encoded_var_count :: int, % encodes #Long>0 and #Short
|
|
llvi_type_params :: rval,
|
|
llvi_ptis :: int, % -1 if none, otherwise slot#
|
|
llvi_hlds_var_nums :: int, % -1 if none, otherwise slot#
|
|
llvi_short_locns :: int, % -1 if none, otherwise slot#
|
|
llvi_long_locns :: int % -1 if none, otherwise slot#
|
|
).
|
|
|
|
:- type label_layout_no_vars
|
|
---> label_layout_no_vars(
|
|
% defines MR_LabelLayoutNoVarInfo
|
|
basic_label_layout
|
|
).
|
|
|
|
:- type label_layout_short_vars
|
|
---> label_layout_short_vars(
|
|
% defines MR_LabelLayout
|
|
basic_label_layout,
|
|
label_short_var_info
|
|
).
|
|
|
|
:- type label_layout_long_vars
|
|
---> label_layout_long_vars(
|
|
% defines MR_LabelLayout
|
|
basic_label_layout,
|
|
label_long_var_info
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Proc layouts and their components.
|
|
%
|
|
|
|
:- type proc_layout_stack_traversal
|
|
---> proc_layout_stack_traversal(
|
|
% defines MR_StackTraversal
|
|
% The proc entry label will be `no' if we don't have
|
|
% static code addresses.
|
|
plst_entry_label :: maybe(label),
|
|
|
|
plst_succip_slot :: maybe(int),
|
|
plst_stack_slot_count :: int,
|
|
plst_detism :: determinism
|
|
).
|
|
|
|
% The deep_slot_info gives the stack slot numbers that hold
|
|
% the values returned by the call port code, which are needed to let
|
|
% exception.throw perform the work we need to do at the excp port.
|
|
% The old_outermost slot is needed only with the save/restore approach;
|
|
% the old_outermost field contain -1 otherwise. All fields will contain
|
|
% -1 if the variables are never saved on the stack because the
|
|
% predicate makes no calls (in which case it cannot throw exceptions,
|
|
% because to do that it would need to call exception.throw, directly or
|
|
% indirectly.)
|
|
:- type deep_excp_slots
|
|
---> deep_excp_slots(
|
|
top_csd :: int,
|
|
middle_csd :: int,
|
|
old_outermost :: int
|
|
).
|
|
|
|
:- type proc_layout_proc_static
|
|
---> proc_layout_proc_static(
|
|
plps_file_name :: string,
|
|
plps_line_number :: int,
|
|
plps_is_in_interface :: bool,
|
|
plps_excp_slots :: deep_excp_slots,
|
|
plps_call_site_statics :: maybe({int, int}),
|
|
plps_coverage_points :: maybe({int, int})
|
|
).
|
|
|
|
:- type table_io_args_data
|
|
---> table_io_args_data(
|
|
% The number of head variables that are stored in the answer
|
|
% block. Besides the values of the output arguments,
|
|
% which are needed to make the I/O action idempotent,
|
|
% it also includes the values of the input arguments.
|
|
% Some of these, the type_infos, mdb needs in order to
|
|
% convert the type-specific representations of the outputs
|
|
% to a term that the debugger's user can print or browse.
|
|
% The other inputs are needed to allow the debugger's user
|
|
% to judge whether the output are correct or not.
|
|
tia_answerblock_arity :: int,
|
|
|
|
% This rval stores a vector of answerblock_arity pseudo-
|
|
% typeinfos, one for each headvar stored in the answer block.
|
|
tia_ptis :: rval,
|
|
|
|
% This rval represents a vector mapping each type variable
|
|
% that occurs in the above pseudo-typeinfos to the location
|
|
% of the type_info that is currently bound to that type
|
|
% variable.
|
|
tia_type_params :: rval
|
|
).
|
|
|
|
:- type table_io_entry_data
|
|
---> table_io_entry_data(
|
|
% defines MR_TableIoEntry
|
|
tie_proc_ptr :: layout_name,
|
|
tie_maybe_args :: maybe(table_io_args_data)
|
|
).
|
|
|
|
:- type data_or_slot_id
|
|
---> data_or_slot_is_data(data_id)
|
|
; data_or_slot_is_slot(layout_slot_name).
|
|
|
|
:- type proc_layout_exec_trace
|
|
---> proc_layout_exec_trace(
|
|
% defines MR_ExecTrace
|
|
plet_maybe_call_label_slot :: maybe(layout_slot_name),
|
|
|
|
% The label layouts of the events in the predicate.
|
|
plet_proc_event_layouts :: layout_slot_name,
|
|
plet_num_proc_event_layouts :: int,
|
|
|
|
plet_maybe_table_info :: maybe(data_or_slot_id),
|
|
|
|
% The variable numbers of the head variables, including the
|
|
% ones added by the compiler, in order. The length of the list
|
|
% must be the same as the procedure's arity. The maybe will be
|
|
% `no' if the procedure has no head variables.
|
|
plet_head_var_nums :: maybe(layout_slot_name),
|
|
plet_num_head_var_nums :: int,
|
|
|
|
% Each variable name is an offset into the module's
|
|
% string table. The maybe will be `no' if the procedure
|
|
% has no variables.
|
|
plet_var_names :: maybe(layout_slot_name),
|
|
|
|
plet_max_var_num :: int,
|
|
plet_max_reg_r_num :: int,
|
|
plet_max_reg_f_num :: int,
|
|
plet_maybe_from_full_slot :: maybe(int),
|
|
plet_maybe_io_seq_slot :: maybe(int),
|
|
plet_maybe_trail_slot :: maybe(int),
|
|
plet_maybe_maxfr_slot :: maybe(int),
|
|
plet_eval_method :: eval_method,
|
|
plet_maybe_call_table_slot :: maybe(int),
|
|
plet_maybe_tail_rec_slot :: maybe(int),
|
|
plet_eff_trace_level :: eff_trace_level,
|
|
plet_exec_trace_flags :: int
|
|
).
|
|
|
|
:- type maybe_proc_id_and_more
|
|
---> no_proc_id_and_more
|
|
; proc_id_and_more(
|
|
maybe_proc_static :: maybe(layout_slot_name),
|
|
maybe_exec_trace :: maybe(layout_slot_name),
|
|
|
|
% The procedure body represented as a list of bytecodes.
|
|
proc_body_bytes :: maybe(layout_slot_name),
|
|
|
|
% The name of the module_layout structure.
|
|
proc_module_layout :: layout_name
|
|
).
|
|
|
|
:- type proc_layout_data
|
|
---> proc_layout_data(
|
|
% defines MR_ProcLayout
|
|
proc_layout_label :: rtti_proc_label,
|
|
proc_layout_trav :: proc_layout_stack_traversal,
|
|
proc_layout_more :: maybe_proc_id_and_more
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Module layouts and their components.
|
|
%
|
|
|
|
% This type is for strings which may contain embedded null characters.
|
|
% When a string_with_0s is written, a null character will be written
|
|
% in between each string in the list.
|
|
%
|
|
:- type string_with_0s
|
|
---> string_with_0s(list(string)).
|
|
|
|
:- type event_set_layout_data
|
|
---> event_set_layout_data(
|
|
event_set_data,
|
|
|
|
% Maps each event number to an rval that gives the vector
|
|
% of typeinfos for the arguments of that event.
|
|
map(int, rval)
|
|
).
|
|
|
|
:- type file_layout_data
|
|
---> file_layout_data(
|
|
file_name :: string,
|
|
line_no_label_list :: assoc_list(int, layout_slot_name)
|
|
).
|
|
|
|
:- type module_layout_data
|
|
---> module_layout_data(
|
|
% The part of MR_ModuleLayout that is needed for both
|
|
% deep profiling and debugging.
|
|
mld_module_name :: module_name,
|
|
mld_string_table_size :: int,
|
|
mld_string_table :: string_with_0s,
|
|
|
|
% The parts that are specific to deep profiling and to
|
|
% debugging.
|
|
mld_maybe_deep_prof :: maybe(module_layout_deep_prof),
|
|
mld_maybe_debug :: maybe(module_layout_debug)
|
|
).
|
|
|
|
:- type module_layout_deep_prof
|
|
---> module_layout_deep_prof(
|
|
% Defines part of MR_ModuleLayout.
|
|
mldp_num_oisu_types :: int,
|
|
mldp_oisu_bytes :: list(int),
|
|
mldp_num_table_types :: int,
|
|
mldp_type_table_bytes :: list(int)
|
|
).
|
|
|
|
:- type module_layout_debug
|
|
---> module_layout_debug(
|
|
% Defines part of MR_ModuleLayout.
|
|
mld_proc_layout_names :: list(layout_name),
|
|
mld_file_layouts :: list(file_layout_data),
|
|
mld_trace_level :: trace_level,
|
|
mld_suppressed_events :: int,
|
|
mld_num_label_exec_count :: int,
|
|
mld_maybe_event_specs :: maybe(event_set_layout_data)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Allocation site information.
|
|
%
|
|
|
|
:- type alloc_site_info
|
|
---> alloc_site_info(
|
|
% define MR_AllocSiteInfo
|
|
as_proc_label :: proc_label,
|
|
as_context :: prog_context,
|
|
as_type :: string,
|
|
as_size :: int
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Global variables that hold arrays of layout structures.
|
|
%
|
|
|
|
:- type label_vars
|
|
---> label_has_no_var_info
|
|
; label_has_short_var_info
|
|
; label_has_long_var_info.
|
|
|
|
:- type layout_slot_name
|
|
---> layout_slot(layout_array_name, int).
|
|
|
|
:- type layout_array_name
|
|
---> pseudo_type_info_array
|
|
; hlds_var_nums_array
|
|
; short_locns_array
|
|
; long_locns_array
|
|
; user_event_layout_array
|
|
; user_event_var_nums_array
|
|
; label_layout_array(label_vars)
|
|
|
|
; proc_static_call_sites_array
|
|
; proc_static_cp_static_array
|
|
; proc_static_cp_dynamic_array
|
|
; proc_static_array
|
|
; proc_head_var_nums_array
|
|
% A vector of variable numbers, containing the numbers of the
|
|
% procedure's head variables, including the ones generated by
|
|
% the compiler.
|
|
; proc_var_names_array
|
|
% A vector of variable names (represented as offsets into
|
|
% the string table) for a procedure layout structure.
|
|
; proc_body_bytecodes_array
|
|
; proc_table_io_entry_array
|
|
; proc_event_layouts_array
|
|
; proc_exec_trace_array
|
|
; threadscope_string_table_array
|
|
; alloc_site_array.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Global variables that hold individual layout structures.
|
|
%
|
|
|
|
:- type proc_layout_kind
|
|
---> proc_layout_traversal
|
|
; proc_layout_proc_id(proc_layout_user_or_uci).
|
|
|
|
:- type proc_layout_user_or_uci
|
|
---> user
|
|
; uci.
|
|
|
|
% Each layout_name identifies a global variable holding one layout
|
|
% structure. We prefer to put layout structures into arrays, because
|
|
% one array holding all N layout structures of a given kind require
|
|
% less space in the symbol table and relocation information sections
|
|
% of object files than N separate global variables, and the reduction
|
|
% in the number of symbols should also improve link times. In some arrays,
|
|
% it is also possible to use an element or sequence of elements two or more
|
|
% times, giving an element of compression.
|
|
%
|
|
% The layout structures we still put into global variables individually are
|
|
%
|
|
% - procedure layouts, which have to have a name derivable from the name of
|
|
% the procedure they represent, since in deep profiling grades call site
|
|
% static structures contain pointers to the proc layout structures of the
|
|
% callee procedures;
|
|
% - layouts for closures, which are relatively few in number,
|
|
% so arrays would do little good; and
|
|
% - module layouts and their components, of which each module will have
|
|
% just one, so arrays would do absolutely *no* good.
|
|
%
|
|
:- type layout_name
|
|
---> proc_layout(rtti_proc_label, proc_layout_kind)
|
|
; closure_proc_id(proc_label, int, proc_label)
|
|
; file_layout(module_name, int)
|
|
; file_layout_line_number_vector(module_name, int)
|
|
; file_layout_label_layout_vector(module_name, int)
|
|
; module_layout_string_table(module_name)
|
|
; module_layout_file_vector(module_name)
|
|
; module_layout_proc_vector(module_name)
|
|
; module_layout_label_exec_count(module_name, int)
|
|
; module_layout_event_set_desc(module_name)
|
|
; module_layout_event_arg_names(module_name, int)
|
|
; module_layout_event_synth_attrs(module_name, int)
|
|
; module_layout_event_synth_attr_args(module_name, int, int)
|
|
; module_layout_event_synth_attr_order(module_name, int, int)
|
|
; module_layout_event_synth_order(module_name, int)
|
|
; module_layout_event_specs(module_name)
|
|
; module_layout_oisu_bytes(module_name)
|
|
; module_layout_type_table_bytes(module_name)
|
|
; module_layout(module_name).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module ll_backend.layout.
|
|
%-----------------------------------------------------------------------------%
|