mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-19 07:45:09 +00:00
Estimated hours taken: 40 Branches: main Move all the frequently occurring layout structures and components of layout structures into arrays where possible. By replacing N global variables holding individual layout structures or layout structure components with one global variable holding an array of them, we reduce the sizes of the symbol tables stored in object files, which should speed up both the C compiler and the linker. Measured on the modules of the library, mdbcomp and compiler directories compiled in grade asm_fast.gc.debug, this diff reduces the size of the generated C source files by 7.8%, the size of the generated object files by 10.4%, and the number of symbols in the symbol tables of those object files by a whopping 42.8%. (These improvements include, and are not on top of, the improvements in my previous similar diff.) runtime/mercury_stack_layout.h: Each label layout structure has information about the type and location of every variable that is live at that label. We store this information in three arrays: an array of pseudo-typeinfos giving the types of all these variables, and two arrays MR_ShortLvals and MR_LongLvals respectively giving their locations. (Most of the time, the location's encoded form fits into one byte (the MR_ShortLval) but sometimes it needs more bits (this is when we use MR_LongLval)). We used to store these three arrays, whose elements are different types, in a single occurrence-specific common structure, one after the other, with a cumbersome mechanism being required to access them. We now store them as segments of three separate arrays, of pseudo-typeinfos, MR_ShortLvals and MR_LongLvals respectively. This makes access simpler and faster (which will matter more to any accurate garbage collector than it does to the debugger). It also allows more scope for compression, since reusing an existing segment of one of the three arrays is easier than reusing an entire common structure, which would require the equivalent of exact matches on all three arrays. Since most label layout structures that have information about variables can encode the variables' locations using only MR_ShortLvals, create a version of the label layout structure type that omits the field used to record the whereabouts of the long location descriptors. Add macros now generated by the compiler to initialize layout structures. Simplify a one-field struct. runtime/mercury_grade.h: Increment the binary compatibility version number for debuggable executables, since .c and .o files from before and after the change to label layout structures are NOT compatible. runtime/mercury_type_info.h: Fix some binary-compatibility-related bit rot. runtime/mercury_misc.h: Move here the existing macros used by the compiler when generating references to layout arrays, and add new ones. runtime/mercury_goto.h: Delete the macros moved to mercury_misc.h. Conform to the changes in mercury_stack_layout.h. runtime/Mmakefile: Prevent the unnecessary rebuilding of mercury_conf.h. runtime/mercury_accurate_gc.c: runtime/mercury_agc_debug.c: runtime/mercury_layout_util.c: runtime/mercury_stack_trace.c: runtime/mercury_types.h: trace/mercury_trace.c: trace/mercury_trace_vars.c: Conform to the changes in mercury_stack_layout.h. runtime/mercury_wrapper.c: Improve the debug support a bit. runtime/mercury_engine.h: Fix style. compiler/layout.m: Make the change described at the top. Almost all layout structures are now in arrays. The only exceptions are those that occur rarely, and proc layouts, whose names need to be derivable from the name of the procedure itself. Instead of having a single type "layout_data" that can represent different kinds of single global variables (not array slots), have different kinds for different purposes. This makes the code clearer and allows traversals that do not have to skip over inapplicable kinds of layout structures. compiler/layout_out.m: Output the new arrays. compiler/stack_layout.m: Generate the new arrays. Previously, an individual term generated by stack_layout.m could represent several components of a layout structure, with the components separated by layout_out.m. We now do the separation in stack_layout.m itself, adding each component to the array to which it belongs. Instead of passing around a single stack_layout_info structure, pass around several smaller one. This is preferable, since I found out the hard way that including everything in one structure would give the structure 51 fields. Most parts of the module work with only one or two of these structures, which makes their role clearer. Cluster related predicates together. compiler/options.m: doc/user_guide.texi: Add an option that control whether stack_layout.m will attempt to compress the layout arrays that can meaningfully be comressed. compiler/llds.m: Remove the old distinction between a data_addr and a data_name, replacing both types with a single new one: data_id. Since different kinds of data_names were treated differently in many places, the distinction in types (which was intended to allow us to process data_addrs that wrapped data_names differently from other kinds of data_addrs) wasn't buying us anything anymore. The new data_id type allows for the possibility that the code generator wants to generate a reference to an address it does not know yet, because it is a slot in a layout array, and the slot has not been allocated yet. Add the information from which the new layout array structures will be generated to the LLDS. compiler/llds_out.m: Call layout_out.m to output the new layout arrays. Adapt the decl_id type to the replacement of data_addrs by data_ids. Don't both keeping track of the have-vs-have-not-declared status of structures that are always declared at the start. When writing out a data_addr, for some kinds of data_addr, llds_out.m would write out the name of the relevant variable, while for some other kinds, it would write out its address. This diff separates out those those things into separate predicates, each of which behaves consistently. compiler/mercury_compile_llds_back_end.m: Convey the intended contents of the new layout arrays from stack_layout.m to llds_out.m. compiler/continuation_info.m: Add a type required by the way we now generate proc_static structures for deep profiling. compiler/hlds_rtti.m: Add distinguishing prefixes to the field names of the rtti_proc_label type. compiler/code_info.m: compiler/code_util.m: compiler/erl_rtti.m: compiler/exprn_aux.m: compiler/global_data.m: compiler/ll_pseudo_type_info.m: compiler/ml_code_util.m: compiler/opt_debug.m: compiler/proc_gen.m: compiler/prog_rep.m: compiler/rtti_out.m: compiler/unify_gen.m: Conform to the changes above. tests/debugger/declarative/track_through_catch.exp: Expect procedures to be listed in the proper order. tests/EXPECT_FAIL_TESTS.asm_fast.gc.debug: tests/EXPECT_FAIL_TESTS.asm_fast.gc.profdeep: Add these files to ignore expected failues in these grades.
1217 lines
47 KiB
Mathematica
1217 lines
47 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2003-2009 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: global_data.m.
|
|
% Author: zs.
|
|
%
|
|
% This module manages global data structures for the LLDS backend.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module ll_backend.global_data.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module ll_backend.continuation_info.
|
|
:- import_module ll_backend.layout.
|
|
:- import_module ll_backend.llds.
|
|
:- import_module mdbcomp.prim_data. % for module_name
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module bool.
|
|
:- import_module list.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- type global_data.
|
|
|
|
:- pred global_data_init(static_cell_info::in, global_data::out) is det.
|
|
|
|
:- pred global_data_add_new_proc_var(pred_proc_id::in, tabling_info_struct::in,
|
|
global_data::in, global_data::out) is det.
|
|
|
|
:- pred global_data_add_new_proc_layout(pred_proc_id::in, proc_layout_info::in,
|
|
global_data::in, global_data::out) is det.
|
|
|
|
:- pred global_data_update_proc_layout(pred_proc_id::in, proc_layout_info::in,
|
|
global_data::in, global_data::out) is det.
|
|
|
|
:- pred global_data_add_new_closure_layouts(list(closure_proc_id_data)::in,
|
|
global_data::in, global_data::out) is det.
|
|
|
|
:- pred global_data_maybe_get_proc_layout(global_data::in, pred_proc_id::in,
|
|
proc_layout_info::out) is semidet.
|
|
|
|
:- pred global_data_get_proc_layout(global_data::in, pred_proc_id::in,
|
|
proc_layout_info::out) is det.
|
|
|
|
:- pred global_data_get_all_proc_vars(global_data::in,
|
|
list(tabling_info_struct)::out) is det.
|
|
|
|
:- pred global_data_get_all_proc_layouts(global_data::in,
|
|
list(proc_layout_info)::out) is det.
|
|
|
|
:- pred global_data_get_all_closure_layouts(global_data::in,
|
|
list(closure_proc_id_data)::out) is det.
|
|
|
|
:- pred global_data_get_static_cell_info(global_data::in,
|
|
static_cell_info::out) is det.
|
|
|
|
:- pred global_data_set_static_cell_info(static_cell_info::in,
|
|
global_data::in, global_data::out) is det.
|
|
|
|
:- type static_cell_info.
|
|
|
|
:- func init_static_cell_info(module_name, have_unboxed_floats, bool)
|
|
= static_cell_info.
|
|
|
|
:- pred add_scalar_static_cell(assoc_list(rval, llds_type)::in, data_id::out,
|
|
static_cell_info::in, static_cell_info::out) is det.
|
|
|
|
:- pred add_scalar_static_cell_natural_types(list(rval)::in, data_id::out,
|
|
static_cell_info::in, static_cell_info::out) is det.
|
|
|
|
:- pred find_general_llds_types(have_unboxed_floats::in, list(mer_type)::in,
|
|
list(list(rval))::in, list(llds_type)::out) is semidet.
|
|
|
|
:- pred add_vector_static_cell(list(llds_type)::in,
|
|
list(list(rval))::in, data_id::out,
|
|
static_cell_info::in, static_cell_info::out) is det.
|
|
|
|
:- pred search_scalar_static_cell_offset(static_cell_info::in, data_id::in,
|
|
int::in, rval::out) is semidet.
|
|
|
|
:- pred get_static_cells(static_cell_info::in,
|
|
list(scalar_common_data_array)::out, list(vector_common_data_array)::out)
|
|
is det.
|
|
|
|
% Given an rval, and the value of the --unboxed_float option, figure out
|
|
% the type the rval would have as an argument. Normally that's the same
|
|
% as its usual type; the exception is that for boxed floats, the type
|
|
% is data_ptr (i.e. the type of the boxed value) rather than float
|
|
% (the type of the unboxed value).
|
|
%
|
|
:- func rval_type_as_arg(have_unboxed_floats, rval) = llds_type.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- type static_cell_remap_info.
|
|
|
|
% bump_type_num_counter(Increment, !GlobalData)
|
|
%
|
|
% Increment the type counter in GlobalData by Increment.
|
|
%
|
|
:- pred bump_type_num_counter(int::in, global_data::in, global_data::out)
|
|
is det.
|
|
|
|
% merge_global_datas(GlobalDataA, GlobalDataB, GlobalData, Remap)
|
|
%
|
|
% Merge two global data structures, where static cell information from
|
|
% GlobalDataA takes precedence over GlobalDataB. The type numbers of the
|
|
% two global_data structures must be distinct. Remap contains the
|
|
% information necessary for remap_static_cell_references/3.
|
|
%
|
|
:- pred merge_global_datas(global_data::in, global_data::in, global_data::out,
|
|
static_cell_remap_info::out) is det.
|
|
|
|
% Update instructions in a C procedure that reference the static cells
|
|
% from the GlobalDataB that was passed to merge_global_datas/4, to
|
|
% reference the static cells of the merged global_data structure.
|
|
%
|
|
:- pred remap_static_cell_references(static_cell_remap_info::in,
|
|
c_procedure::in, c_procedure::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module libs.compiler_util.
|
|
:- import_module ll_backend.layout.
|
|
|
|
:- import_module bimap.
|
|
:- import_module counter.
|
|
:- import_module int.
|
|
:- import_module map.
|
|
:- import_module maybe.
|
|
:- import_module pair.
|
|
:- import_module require.
|
|
:- import_module svbimap.
|
|
:- import_module svmap.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- type proc_var_map == map(pred_proc_id, tabling_info_struct).
|
|
:- type proc_layout_map == map(pred_proc_id, proc_layout_info).
|
|
|
|
:- type global_data
|
|
---> global_data(
|
|
% Information about the global variables defined by
|
|
% each procedure.
|
|
gd_proc_var_map :: proc_var_map,
|
|
|
|
% Information about the layout structures defined by
|
|
% each procedure.
|
|
gd_proc_layout_map :: proc_layout_map,
|
|
|
|
% The list of all closure layouts generated in this module.
|
|
% While all closure layouts are different from all other
|
|
% layout_data, it is possible, although unlikely, for
|
|
% two closures to have the same layout.
|
|
gd_closure_layouts :: list(closure_proc_id_data),
|
|
|
|
% Information about all the statically allocated cells
|
|
% created so far.
|
|
gd_static_cell_info :: static_cell_info
|
|
).
|
|
|
|
global_data_init(StaticCellInfo, GlobalData) :-
|
|
map.init(EmptyDataMap),
|
|
map.init(EmptyLayoutMap),
|
|
GlobalData = global_data(EmptyDataMap, EmptyLayoutMap, [], StaticCellInfo).
|
|
|
|
global_data_add_new_proc_var(PredProcId, ProcVar, !GlobalData) :-
|
|
ProcVarMap0 = !.GlobalData ^ gd_proc_var_map,
|
|
map.det_insert(ProcVarMap0, PredProcId, ProcVar, ProcVarMap),
|
|
!GlobalData ^ gd_proc_var_map := ProcVarMap.
|
|
|
|
global_data_add_new_proc_layout(PredProcId, ProcLayout, !GlobalData) :-
|
|
ProcLayoutMap0 = !.GlobalData ^ gd_proc_layout_map,
|
|
map.det_insert(ProcLayoutMap0, PredProcId, ProcLayout, ProcLayoutMap),
|
|
!GlobalData ^ gd_proc_layout_map := ProcLayoutMap.
|
|
|
|
global_data_update_proc_layout(PredProcId, ProcLayout, !GlobalData) :-
|
|
ProcLayoutMap0 = !.GlobalData ^ gd_proc_layout_map,
|
|
map.det_update(ProcLayoutMap0, PredProcId, ProcLayout, ProcLayoutMap),
|
|
!GlobalData ^ gd_proc_layout_map := ProcLayoutMap.
|
|
|
|
global_data_add_new_closure_layouts(NewClosureLayouts, !GlobalData) :-
|
|
ClosureLayouts0 = !.GlobalData ^ gd_closure_layouts,
|
|
list.append(NewClosureLayouts, ClosureLayouts0, ClosureLayouts),
|
|
!GlobalData ^ gd_closure_layouts := ClosureLayouts.
|
|
|
|
global_data_maybe_get_proc_layout(GlobalData, PredProcId, ProcLayout) :-
|
|
ProcLayoutMap = GlobalData ^ gd_proc_layout_map,
|
|
map.search(ProcLayoutMap, PredProcId, ProcLayout).
|
|
|
|
global_data_get_proc_layout(GlobalData, PredProcId, ProcLayout) :-
|
|
ProcLayoutMap = GlobalData ^ gd_proc_layout_map,
|
|
map.lookup(ProcLayoutMap, PredProcId, ProcLayout).
|
|
|
|
global_data_get_all_proc_vars(GlobalData, ProcVars) :-
|
|
ProcVarMap = GlobalData ^ gd_proc_var_map,
|
|
map.values(ProcVarMap, ProcVars).
|
|
|
|
global_data_get_all_proc_layouts(GlobalData, ProcLayouts) :-
|
|
ProcLayoutMap = GlobalData ^ gd_proc_layout_map,
|
|
map.values(ProcLayoutMap, ProcLayouts).
|
|
|
|
global_data_get_all_closure_layouts(GlobalData, ClosureLayouts) :-
|
|
ClosureLayouts = GlobalData ^ gd_closure_layouts.
|
|
|
|
global_data_get_static_cell_info(GlobalData, StaticCellInfo) :-
|
|
StaticCellInfo = GlobalData ^ gd_static_cell_info.
|
|
|
|
global_data_set_static_cell_info(StaticCellInfo, !GlobalData) :-
|
|
!GlobalData ^ gd_static_cell_info := StaticCellInfo.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% There is one scalar_cell_group for every group of scalar cells that
|
|
% share the same sequence of argument types. We don't actually need the
|
|
% cell type here, since we can't get to a scalar_cell_group from
|
|
% the scalar_cell_group_map field of the static_cell_sub_info
|
|
% without knowing it.
|
|
%
|
|
:- type scalar_cell_group
|
|
---> scalar_cell_group(
|
|
scalar_cell_counter :: counter, % next cell number
|
|
scalar_cell_group_members :: bimap(list(rval), data_id),
|
|
scalar_cell_rev_array :: list(common_cell_value)
|
|
).
|
|
|
|
% There is one vector_cell_group for every group of vector cells that
|
|
% share the same sequence of argument types. We don't actually need the
|
|
% cell type here, since we can't get to a vector_cell_group from
|
|
% the vector_cell_group_map field of the static_cell_sub_info
|
|
% without knowing it.
|
|
%
|
|
% Whereas in a scalar_cell_group, we try to find cells with the same
|
|
% content and represent them just once, we do not do so for vectors,
|
|
% because (a) the required lookup would be expensive due to the huge keys
|
|
% required, and (b) the probability of finding two vectors with identical
|
|
% contents is about zero.
|
|
%
|
|
% The vector_cell_map field maps the cell num of a vector cell to its
|
|
% contents, the contents being a sequence of cells.
|
|
%
|
|
:- type vector_cell_group
|
|
---> vector_cell_group(
|
|
vector_cell_counter :: counter, % next cell number
|
|
vector_cell_map :: map(int, vector_contents)
|
|
).
|
|
|
|
:- type vector_contents
|
|
---> vector_contents(list(common_cell_value)).
|
|
|
|
:- type static_cell_sub_info
|
|
---> static_cell_sub_info(
|
|
scsi_module_name :: module_name, % base file name
|
|
scsi_unbox_float :: have_unboxed_floats,
|
|
scsi_common_data :: bool
|
|
).
|
|
|
|
:- type cell_type_bimap == bimap(common_cell_type, type_num).
|
|
:- type scalar_type_cell_map == map(type_num, scalar_cell_group).
|
|
:- type vector_type_cell_map == map(type_num, vector_cell_group).
|
|
|
|
:- type static_cell_info
|
|
---> static_cell_info(
|
|
sci_sub_info :: static_cell_sub_info,
|
|
sci_type_counter :: counter, % next type number
|
|
|
|
% Maps types to type numbers and vice versa.
|
|
sci_cell_type_num_map :: cell_type_bimap,
|
|
|
|
% Maps the cell type number to the information we have
|
|
% for all scalar cells of that type.
|
|
sci_scalar_cell_group_map :: scalar_type_cell_map,
|
|
|
|
% Maps the cell type number to the information we have
|
|
% for all vector cells of that type.
|
|
sci_vector_cell_group_map :: vector_type_cell_map
|
|
).
|
|
|
|
init_static_cell_info(BaseName, UnboxFloat, CommonData) = Info0 :-
|
|
SubInfo0 = static_cell_sub_info(BaseName, UnboxFloat, CommonData),
|
|
Info0 = static_cell_info(SubInfo0, counter.init(0), bimap.init,
|
|
map.init, map.init).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
add_scalar_static_cell_natural_types(Args, DataId, !Info) :-
|
|
list.map(associate_natural_type(!.Info ^ sci_sub_info ^ scsi_unbox_float),
|
|
Args, ArgsTypes),
|
|
add_scalar_static_cell(ArgsTypes, DataId, !Info).
|
|
|
|
add_scalar_static_cell(ArgsTypes0, DataId, !Info) :-
|
|
% If we have an empty cell, place a dummy field in it,
|
|
% so that the generated C structure isn't empty.
|
|
(
|
|
ArgsTypes0 = [],
|
|
ArgsTypes = [const(llconst_int(-1)) - lt_integer]
|
|
;
|
|
ArgsTypes0 = [_ | _],
|
|
ArgsTypes = ArgsTypes0
|
|
),
|
|
compute_cell_type(ArgsTypes, CellType, CellTypeAndValue),
|
|
do_add_scalar_static_cell(ArgsTypes, CellType, CellTypeAndValue, DataId,
|
|
!Info).
|
|
|
|
:- pred do_add_scalar_static_cell(assoc_list(rval, llds_type)::in,
|
|
common_cell_type::in, common_cell_value::in, data_id::out,
|
|
static_cell_info::in, static_cell_info::out) is det.
|
|
|
|
do_add_scalar_static_cell(ArgsTypes, CellType, CellValue, DataId, !Info) :-
|
|
assoc_list.keys(ArgsTypes, Args),
|
|
some [!CellGroup] (
|
|
TypeNumMap0 = !.Info ^ sci_cell_type_num_map,
|
|
CellGroupMap0 = !.Info ^ sci_scalar_cell_group_map,
|
|
( bimap.search(TypeNumMap0, CellType, OldTypeNum) ->
|
|
TypeNum = OldTypeNum,
|
|
( map.search(CellGroupMap0, TypeNum, !:CellGroup) ->
|
|
true
|
|
;
|
|
!:CellGroup = init_scalar_cell_group
|
|
)
|
|
;
|
|
TypeNumCounter0 = !.Info ^ sci_type_counter,
|
|
counter.allocate(TypeRawNum, TypeNumCounter0, TypeNumCounter),
|
|
TypeNum = type_num(TypeRawNum),
|
|
!Info ^ sci_type_counter := TypeNumCounter,
|
|
|
|
bimap.det_insert(TypeNumMap0, CellType, TypeNum, TypeNumMap),
|
|
!Info ^ sci_cell_type_num_map := TypeNumMap,
|
|
|
|
!:CellGroup = init_scalar_cell_group
|
|
),
|
|
MembersMap0 = !.CellGroup ^ scalar_cell_group_members,
|
|
( bimap.search(MembersMap0, Args, DataIdPrime) ->
|
|
DataId = DataIdPrime
|
|
;
|
|
CellNumCounter0 = !.CellGroup ^ scalar_cell_counter,
|
|
counter.allocate(CellNum, CellNumCounter0, CellNumCounter),
|
|
!CellGroup ^ scalar_cell_counter := CellNumCounter,
|
|
DataId = scalar_common_data_id(TypeNum, CellNum),
|
|
RevArray0 = !.CellGroup ^ scalar_cell_rev_array,
|
|
RevArray = [CellValue | RevArray0],
|
|
!CellGroup ^ scalar_cell_rev_array := RevArray,
|
|
InsertCommonData = !.Info ^ sci_sub_info ^ scsi_common_data,
|
|
(
|
|
InsertCommonData = yes,
|
|
bimap.det_insert(MembersMap0, Args, DataId, MembersMap),
|
|
!CellGroup ^ scalar_cell_group_members := MembersMap
|
|
;
|
|
InsertCommonData = no
|
|
% With --no-common-data, we never insert any cell into
|
|
% CellGroupMap, ensuring that it stays empty. This can
|
|
% be useful when comparing the LLDS and MLDS backends.
|
|
),
|
|
map.set(CellGroupMap0, TypeNum, !.CellGroup, CellGroupMap),
|
|
!Info ^ sci_scalar_cell_group_map := CellGroupMap
|
|
)
|
|
).
|
|
|
|
:- func init_scalar_cell_group = scalar_cell_group.
|
|
|
|
init_scalar_cell_group = scalar_cell_group(counter.init(0), bimap.init, []).
|
|
|
|
search_scalar_static_cell_offset(Info, DataId, Offset, Rval) :-
|
|
DataId = scalar_common_data_id(TypeNum, _CellNum),
|
|
CellGroupMap = Info ^ sci_scalar_cell_group_map,
|
|
map.lookup(CellGroupMap, TypeNum, CellGroup),
|
|
CellGroupMembers = CellGroup ^ scalar_cell_group_members,
|
|
bimap.reverse_lookup(CellGroupMembers, Rvals, DataId),
|
|
list.index0_det(Rvals, Offset, Rval).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
find_general_llds_types(UnboxFloat, Types, [Vector | Vectors], LLDSTypes) :-
|
|
list.map(natural_type(UnboxFloat), Vector, LLDSTypes0),
|
|
find_general_llds_types_2(UnboxFloat, Types, Vectors,
|
|
LLDSTypes0, LLDSTypes).
|
|
|
|
:- pred find_general_llds_types_2(have_unboxed_floats::in, list(mer_type)::in,
|
|
list(list(rval))::in, list(llds_type)::in, list(llds_type)::out)
|
|
is semidet.
|
|
|
|
find_general_llds_types_2(_UnboxFloat, _Types, [], !LLDSTypes).
|
|
find_general_llds_types_2(UnboxFloat, Types, [Vector | Vectors], !LLDSTypes) :-
|
|
find_general_llds_types_in_cell(UnboxFloat, Types, Vector, !LLDSTypes),
|
|
find_general_llds_types_2(UnboxFloat, Types, Vectors, !LLDSTypes).
|
|
|
|
:- pred find_general_llds_types_in_cell(have_unboxed_floats::in,
|
|
list(mer_type)::in, list(rval)::in, list(llds_type)::in,
|
|
list(llds_type)::out) is semidet.
|
|
|
|
find_general_llds_types_in_cell(_UnboxFloat, [], [], [], []).
|
|
find_general_llds_types_in_cell(UnboxFloat, [_Type | Types], [Rval | Rvals],
|
|
[LLDSType0 | LLDSTypes0], [LLDSType | LLDSTypes]) :-
|
|
natural_type(UnboxFloat, Rval, NaturalType),
|
|
% For user-defined types, some function symbols may be constants
|
|
% (whose representations yield integer rvals) while others may be
|
|
% non-constants (whose representations yield data_ptr rvals).
|
|
% We need to be able to handle switches in which a variable of such a type
|
|
% has a value of one kind in one switch arm and a value of the other kind
|
|
% in another switch arm. We can mix the two because it is OK to initialize
|
|
% a field declared to be a data_ptr with an integer rval.
|
|
%
|
|
% If there are any other similar cases, they should be added here.
|
|
% The value of Type may be useful in such code.
|
|
(
|
|
NaturalType = LLDSType0
|
|
->
|
|
LLDSType = LLDSType0
|
|
;
|
|
NaturalType = lt_integer,
|
|
LLDSType0 = lt_data_ptr
|
|
->
|
|
LLDSType = lt_data_ptr
|
|
;
|
|
NaturalType = lt_data_ptr,
|
|
LLDSType0 = lt_integer
|
|
->
|
|
LLDSType = lt_data_ptr
|
|
;
|
|
fail
|
|
),
|
|
find_general_llds_types_in_cell(UnboxFloat, Types, Rvals,
|
|
LLDSTypes0, LLDSTypes).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
add_vector_static_cell(LLDSTypes, VectorData, DataId, !Info) :-
|
|
require(list.is_not_empty(LLDSTypes), "add_vector_static_cell: no types"),
|
|
require(list.is_not_empty(VectorData), "add_vector_static_cell: no data"),
|
|
|
|
% We don't to use grouped_args_type, since that would (a) make the code
|
|
% below significantly more complex, and (b) the type declaration can be
|
|
% expected to be only a small fraction of the size of the variable
|
|
% definition, so the saving in C code size wouldn't be significant.
|
|
|
|
CellType = plain_type(LLDSTypes),
|
|
VectorCells = list.map(pair_vector_element(LLDSTypes), VectorData),
|
|
some [!CellGroup] (
|
|
TypeNumMap0 = !.Info ^ sci_cell_type_num_map,
|
|
CellGroupMap0 = !.Info ^ sci_vector_cell_group_map,
|
|
( bimap.search(TypeNumMap0, CellType, TypeNumPrime) ->
|
|
TypeNum = TypeNumPrime,
|
|
( map.search(CellGroupMap0, TypeNum, !:CellGroup) ->
|
|
true
|
|
;
|
|
!:CellGroup = init_vector_cell_group
|
|
)
|
|
;
|
|
TypeNumCounter0 = !.Info ^ sci_type_counter,
|
|
counter.allocate(TypeNum0, TypeNumCounter0, TypeNumCounter),
|
|
TypeNum = type_num(TypeNum0),
|
|
!Info ^ sci_type_counter := TypeNumCounter,
|
|
|
|
bimap.det_insert(TypeNumMap0, CellType, TypeNum, TypeNumMap),
|
|
!Info ^ sci_cell_type_num_map := TypeNumMap,
|
|
|
|
!:CellGroup = init_vector_cell_group
|
|
),
|
|
CellNumCounter0 = !.CellGroup ^ vector_cell_counter,
|
|
counter.allocate(CellNum, CellNumCounter0, CellNumCounter),
|
|
!CellGroup ^ vector_cell_counter := CellNumCounter,
|
|
DataId = vector_common_data_id(TypeNum, CellNum),
|
|
CellMap0 = !.CellGroup ^ vector_cell_map,
|
|
VectorContents = vector_contents(VectorCells),
|
|
map.det_insert(CellMap0, CellNum, VectorContents, CellMap),
|
|
!CellGroup ^ vector_cell_map := CellMap,
|
|
map.set(CellGroupMap0, TypeNum, !.CellGroup, CellGroupMap),
|
|
!Info ^ sci_vector_cell_group_map := CellGroupMap
|
|
).
|
|
|
|
:- func init_vector_cell_group = vector_cell_group.
|
|
|
|
init_vector_cell_group = vector_cell_group(counter.init(0), map.init).
|
|
|
|
:- func pair_vector_element(list(llds_type), list(rval)) = common_cell_value.
|
|
|
|
pair_vector_element(Types, Args) = plain_value(ArgsTypes) :-
|
|
assoc_list.from_corresponding_lists(Args, Types, ArgsTypes).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
get_static_cells(Info, ScalarDatas, VectorDatas) :-
|
|
TypeNumMap = Info ^ sci_cell_type_num_map,
|
|
map.foldl(add_scalar_static_cell_for_type(TypeNumMap),
|
|
Info ^ sci_scalar_cell_group_map, [], RevScalarDatas),
|
|
list.reverse(RevScalarDatas, ScalarDatas),
|
|
map.foldl(add_all_vector_static_cells_for_type(TypeNumMap),
|
|
Info ^ sci_vector_cell_group_map, [], RevVectorDatas),
|
|
list.reverse(RevVectorDatas, VectorDatas).
|
|
|
|
:- pred add_scalar_static_cell_for_type(cell_type_bimap::in,
|
|
type_num::in, scalar_cell_group::in,
|
|
list(scalar_common_data_array)::in, list(scalar_common_data_array)::out)
|
|
is det.
|
|
|
|
add_scalar_static_cell_for_type(TypeNumMap, TypeNum, CellGroup,
|
|
!Arrays) :-
|
|
bimap.reverse_lookup(TypeNumMap, CellType, TypeNum),
|
|
list.reverse(CellGroup ^ scalar_cell_rev_array, ArrayContents),
|
|
Array = scalar_common_data_array(CellType, TypeNum, ArrayContents),
|
|
!:Arrays = [Array | !.Arrays].
|
|
|
|
:- pred add_all_vector_static_cells_for_type(cell_type_bimap::in,
|
|
type_num::in, vector_cell_group::in,
|
|
list(vector_common_data_array)::in, list(vector_common_data_array)::out)
|
|
is det.
|
|
|
|
add_all_vector_static_cells_for_type(TypeNumMap, TypeNum, CellGroup,
|
|
!Arrays) :-
|
|
bimap.reverse_lookup(TypeNumMap, CellType, TypeNum),
|
|
map.foldl(add_one_vector_static_cell(TypeNum, CellType),
|
|
CellGroup ^ vector_cell_map, !Arrays).
|
|
|
|
:- pred add_one_vector_static_cell(type_num::in, common_cell_type::in,
|
|
int::in, vector_contents::in,
|
|
list(vector_common_data_array)::in, list(vector_common_data_array)::out)
|
|
is det.
|
|
|
|
add_one_vector_static_cell(TypeNum, CellType, CellNum,
|
|
vector_contents(VectorContents), !Arrays) :-
|
|
Array = vector_common_data_array(CellType, TypeNum, CellNum,
|
|
VectorContents),
|
|
!:Arrays = [Array | !.Arrays].
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred compute_cell_type(assoc_list(rval, llds_type)::in,
|
|
common_cell_type::out, common_cell_value::out) is det.
|
|
|
|
compute_cell_type(ArgsTypes, CellType, CellValue) :-
|
|
(
|
|
ArgsTypes = [FirstArg - FirstArgType | LaterArgsTypes],
|
|
threshold_group_types(FirstArgType, [FirstArg], LaterArgsTypes,
|
|
TypeGroups, TypeAndArgGroups),
|
|
OldLength = list.length(ArgsTypes),
|
|
NewLength = list.length(TypeAndArgGroups),
|
|
OldLength >= NewLength * 2
|
|
->
|
|
CellType = grouped_args_type(TypeGroups),
|
|
CellValue = grouped_args_value(TypeAndArgGroups)
|
|
;
|
|
CellType = plain_type(assoc_list.values(ArgsTypes)),
|
|
CellValue = plain_value(ArgsTypes)
|
|
).
|
|
|
|
:- pred threshold_group_types(llds_type::in, list(rval)::in,
|
|
assoc_list(rval, llds_type)::in, assoc_list(llds_type, int)::out,
|
|
list(common_cell_arg_group)::out) is semidet.
|
|
|
|
threshold_group_types(CurType, RevArgsSoFar, LaterArgsTypes, TypeGroups,
|
|
TypeAndArgGroups) :-
|
|
(
|
|
LaterArgsTypes = [],
|
|
make_arg_groups(CurType, RevArgsSoFar, TypeGroup, TypeAndArgGroup),
|
|
TypeGroups = [TypeGroup],
|
|
TypeAndArgGroups = [TypeAndArgGroup]
|
|
;
|
|
LaterArgsTypes = [NextArg - NextType | MoreArgsTypes],
|
|
( CurType = NextType ->
|
|
threshold_group_types(CurType, [NextArg | RevArgsSoFar],
|
|
MoreArgsTypes, TypeGroups, TypeAndArgGroups)
|
|
;
|
|
threshold_group_types(NextType, [NextArg], MoreArgsTypes,
|
|
TypeGroupsTail, TypeAndArgGroupsTail),
|
|
make_arg_groups(CurType, RevArgsSoFar, TypeGroup, TypeAndArgGroup),
|
|
TypeGroups = [TypeGroup | TypeGroupsTail],
|
|
TypeAndArgGroups = [TypeAndArgGroup | TypeAndArgGroupsTail]
|
|
)
|
|
).
|
|
|
|
:- pred make_arg_groups(llds_type::in, list(rval)::in,
|
|
pair(llds_type, int)::out, common_cell_arg_group::out) is det.
|
|
|
|
make_arg_groups(Type, RevArgs, TypeGroup, TypeAndArgGroup) :-
|
|
( RevArgs = [Arg] ->
|
|
TypeGroup = Type - 1,
|
|
TypeAndArgGroup = common_cell_ungrouped_arg(Type, Arg)
|
|
;
|
|
list.length(RevArgs, NumArgs),
|
|
list.reverse(RevArgs, Args),
|
|
TypeGroup = Type - NumArgs,
|
|
TypeAndArgGroup = common_cell_grouped_args(Type, NumArgs, Args)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
rval_type_as_arg(UnboxedFloat, Rval) = Type :-
|
|
natural_type(UnboxedFloat, Rval, Type).
|
|
|
|
:- pred natural_type(have_unboxed_floats::in, rval::in, llds_type::out) is det.
|
|
|
|
natural_type(UnboxFloat, Rval, Type) :-
|
|
llds.rval_type(Rval, Type0),
|
|
(
|
|
Type0 = lt_float,
|
|
UnboxFloat = do_not_have_unboxed_floats
|
|
->
|
|
Type = lt_data_ptr
|
|
;
|
|
Type = Type0
|
|
).
|
|
|
|
:- pred associate_natural_type(have_unboxed_floats::in, rval::in,
|
|
pair(rval, llds_type)::out) is det.
|
|
|
|
associate_natural_type(UnboxFloat, Rval, Rval - Type) :-
|
|
natural_type(UnboxFloat, Rval, Type).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- type static_cell_remap_info
|
|
---> static_cell_remap_info(
|
|
cell_type_num_remap,
|
|
map(type_num, scalar_cell_group_remap)
|
|
% A map from the _old_ type number, to the mapping of old
|
|
% data_names to new_data names.
|
|
).
|
|
|
|
:- type cell_type_num_remap == map(type_num, type_num).
|
|
% Mapping of old to new type numbers.
|
|
|
|
:- type scalar_cell_group_remap == map(data_id, data_id).
|
|
% Mapping of old to new data_names.
|
|
|
|
bump_type_num_counter(Increment, !GlobalData) :-
|
|
Counter0 = !.GlobalData ^ gd_static_cell_info ^ sci_type_counter,
|
|
counter.allocate(N, Counter0, _),
|
|
Counter = counter.init(N + Increment),
|
|
!GlobalData ^ gd_static_cell_info ^ sci_type_counter := Counter.
|
|
|
|
merge_global_datas(GlobalDataA, GlobalDataB, GlobalData, Remap) :-
|
|
GlobalDataA = global_data(ProcVarMapA, ProcLayoutMapA, ClosureLayoutsA,
|
|
StaticCellInfoA),
|
|
GlobalDataB = global_data(ProcVarMapB, ProcLayoutMapB, ClosureLayoutsB,
|
|
StaticCellInfoB),
|
|
GlobalData = global_data(ProcVarMap, ProcLayoutMap, ClosureLayouts,
|
|
StaticCellInfo),
|
|
ProcVarMap = map.old_merge(ProcVarMapA, ProcVarMapB),
|
|
ProcLayoutMap = map.old_merge(ProcLayoutMapA, ProcLayoutMapB),
|
|
ClosureLayouts = ClosureLayoutsA ++ ClosureLayoutsB,
|
|
merge_static_cell_infos(StaticCellInfoA, StaticCellInfoB, StaticCellInfo,
|
|
Remap).
|
|
|
|
:- pred merge_static_cell_infos(static_cell_info::in, static_cell_info::in,
|
|
static_cell_info::out, static_cell_remap_info::out) is det.
|
|
|
|
merge_static_cell_infos(SCIa, SCIb, SCI, Remap) :-
|
|
SCIa = static_cell_info(SubInfoA, TypeCounterA,
|
|
CellTypeNumMapA, ScalarCellGroupMapA, VectorCellGroupMapA),
|
|
SCIb = static_cell_info(SubInfoB, _TypeCounterB,
|
|
CellTypeNumMapB, ScalarCellGroupMapB, VectorCellGroupMapB),
|
|
expect(unify(SubInfoA, SubInfoB), this_file, "merge_static_cell_info"),
|
|
|
|
% Merge cell type number maps.
|
|
bimap.foldl3(merge_cell_type_num_maps, CellTypeNumMapB,
|
|
TypeCounterA, TypeCounter, CellTypeNumMapA, CellTypeNumMap,
|
|
map.init, CellTypeNumMapRemap),
|
|
|
|
% Merge the scalar and vector cell group maps.
|
|
merge_scalar_cell_group_maps(CellTypeNumMapRemap,
|
|
ScalarCellGroupMapA, ScalarCellGroupMapB,
|
|
ScalarCellGroupMap, ScalarCellGroupRemap),
|
|
merge_vector_cell_group_maps(CellTypeNumMapRemap,
|
|
VectorCellGroupMapA, VectorCellGroupMapB,
|
|
VectorCellGroupMap),
|
|
|
|
Remap = static_cell_remap_info(CellTypeNumMapRemap, ScalarCellGroupRemap),
|
|
|
|
% Remap the information in the static_cell_info info itself.
|
|
SCI0 = static_cell_info(SubInfoA, TypeCounter,
|
|
CellTypeNumMap, ScalarCellGroupMap, VectorCellGroupMap),
|
|
remap_static_cell_info(Remap, SCI0, SCI).
|
|
|
|
:- pred merge_cell_type_num_maps(common_cell_type::in, type_num::in,
|
|
counter::in, counter::out, cell_type_bimap::in, cell_type_bimap::out,
|
|
cell_type_num_remap::in, cell_type_num_remap::out) is det.
|
|
|
|
merge_cell_type_num_maps(CellType, BTypeNum,
|
|
!TypeCounter, !CellTypeNumMap, !TypeNumRemap) :-
|
|
( bimap.search(!.CellTypeNumMap, CellType, ATypeNum) ->
|
|
% A type also in GlobalDataA.
|
|
svmap.det_insert(BTypeNum, ATypeNum, !TypeNumRemap)
|
|
;
|
|
% A type not in GlobalDataA.
|
|
counter.allocate(N, !TypeCounter),
|
|
NewTypeNum = type_num(N),
|
|
svmap.det_insert(BTypeNum, NewTypeNum, !TypeNumRemap),
|
|
svbimap.det_insert(CellType, NewTypeNum, !CellTypeNumMap)
|
|
).
|
|
|
|
:- pred merge_scalar_cell_group_maps(cell_type_num_remap::in,
|
|
scalar_type_cell_map::in, scalar_type_cell_map::in,
|
|
scalar_type_cell_map::out,
|
|
map(type_num, scalar_cell_group_remap)::out) is det.
|
|
|
|
merge_scalar_cell_group_maps(TypeNumRemap,
|
|
ScalarCellGroupMapA, ScalarCellGroupMapB,
|
|
ScalarCellGroupMap, ScalarCellGroupRemap) :-
|
|
map.foldl2(merge_scalar_cell_group_maps_2(TypeNumRemap),
|
|
ScalarCellGroupMapB,
|
|
ScalarCellGroupMapA, ScalarCellGroupMap,
|
|
map.init, ScalarCellGroupRemap).
|
|
|
|
:- pred merge_scalar_cell_group_maps_2(cell_type_num_remap::in,
|
|
type_num::in, scalar_cell_group::in,
|
|
scalar_type_cell_map::in,
|
|
scalar_type_cell_map::out,
|
|
map(type_num, scalar_cell_group_remap)::in,
|
|
map(type_num, scalar_cell_group_remap)::out) is det.
|
|
|
|
merge_scalar_cell_group_maps_2(TypeNumRemap, BTypeNum, BScalarCellGroup,
|
|
!ScalarCellGroupMap, !Remap) :-
|
|
map.lookup(TypeNumRemap, BTypeNum, TypeNum),
|
|
( map.search(!.ScalarCellGroupMap, TypeNum, ScalarCellGroupPrime) ->
|
|
ScalarCellGroup0 = ScalarCellGroupPrime
|
|
;
|
|
% Could do this more efficiently.
|
|
ScalarCellGroup0 = scalar_cell_group(counter.init(0), bimap.init, [])
|
|
),
|
|
merge_scalar_cell_groups(TypeNum, ScalarCellGroup0, BScalarCellGroup,
|
|
ScalarCellGroup, ScalarCellGroupRemap),
|
|
svmap.set(TypeNum, ScalarCellGroup, !ScalarCellGroupMap),
|
|
svmap.det_insert(BTypeNum, ScalarCellGroupRemap, !Remap).
|
|
|
|
:- pred merge_scalar_cell_groups(type_num::in,
|
|
scalar_cell_group::in, scalar_cell_group::in, scalar_cell_group::out,
|
|
scalar_cell_group_remap::out) is det.
|
|
|
|
merge_scalar_cell_groups(TypeNum, GroupA, GroupB, GroupAB, GroupRemap) :-
|
|
GroupA = scalar_cell_group(_CounterA, GroupMembersA, RevArrayA),
|
|
GroupB = scalar_cell_group(_CounterB, GroupMembersB, RevArrayB),
|
|
GroupAB = scalar_cell_group(CounterAB, GroupMembersAB, RevArrayAB),
|
|
|
|
CounterAB = counter.init(length(RevArrayAB)),
|
|
|
|
ArrayA = reverse(RevArrayA),
|
|
ArrayB = reverse(RevArrayB),
|
|
ArrayAB = ArrayA ++ delete_elems(ArrayB, ArrayA),
|
|
RevArrayAB = reverse(ArrayAB),
|
|
|
|
bimap.foldl2(merge_scalar_cell_groups_2(TypeNum, ArrayB, ArrayAB),
|
|
GroupMembersB,
|
|
GroupMembersA, GroupMembersAB, map.init, GroupRemap).
|
|
|
|
:- pred merge_scalar_cell_groups_2(type_num::in,
|
|
list(common_cell_value)::in, list(common_cell_value)::in,
|
|
list(rval)::in, data_id::in,
|
|
bimap(list(rval), data_id)::in, bimap(list(rval), data_id)::out,
|
|
scalar_cell_group_remap::in, scalar_cell_group_remap::out) is det.
|
|
|
|
merge_scalar_cell_groups_2(TypeNum, ArrayB, ArrayAB,
|
|
Rvals, BDataId, !GroupMembers, !GroupRemap) :-
|
|
( bimap.search(!.GroupMembers, Rvals, DataId) ->
|
|
% Seen this list of rvals before in the group.
|
|
svmap.det_insert(BDataId, DataId, !GroupRemap)
|
|
;
|
|
% Not seen this list of rvals before in the group.
|
|
(
|
|
BDataId = scalar_common_data_id(_, BCellNum),
|
|
% Look up what value this cell number referred to in the B array.
|
|
% Find the cell number of the same value in the combined A+B array.
|
|
CommonCellValue = list.det_index0(ArrayB, BCellNum),
|
|
CellNum = nth_member_lookup0(ArrayAB, CommonCellValue),
|
|
% Add the new data name.
|
|
DataId = scalar_common_data_id(TypeNum, CellNum),
|
|
svbimap.det_insert(Rvals, DataId, !GroupMembers),
|
|
svmap.det_insert(BDataId, DataId, !GroupRemap)
|
|
;
|
|
( BDataId = rtti_data_id(_)
|
|
; BDataId = proc_tabling_data_id(_, _)
|
|
; BDataId = vector_common_data_id(_, _)
|
|
; BDataId = layout_id(_)
|
|
; BDataId = layout_slot_id(_, _)
|
|
),
|
|
unexpected(this_file, "merge_scalar_cell_groups_2")
|
|
)
|
|
).
|
|
|
|
:- pred merge_vector_cell_group_maps(cell_type_num_remap::in,
|
|
vector_type_cell_map::in, vector_type_cell_map::in,
|
|
vector_type_cell_map::out) is det.
|
|
|
|
merge_vector_cell_group_maps(TypeNumRemap, VectorCellGroupMapA,
|
|
VectorCellGroupMapB, VectorCellGroupMap) :-
|
|
map.foldl(merge_vector_cell_group_maps_2(TypeNumRemap),
|
|
VectorCellGroupMapB,
|
|
VectorCellGroupMapA, VectorCellGroupMap).
|
|
|
|
:- pred merge_vector_cell_group_maps_2(cell_type_num_remap::in,
|
|
type_num::in, vector_cell_group::in,
|
|
vector_type_cell_map::in, vector_type_cell_map::out) is det.
|
|
|
|
merge_vector_cell_group_maps_2(TypeNumRemap, OldTypeNum, VectorCellGroup,
|
|
!VectorCellGroupMap) :-
|
|
map.lookup(TypeNumRemap, OldTypeNum, NewTypeNum),
|
|
svmap.det_insert(NewTypeNum, VectorCellGroup, !VectorCellGroupMap).
|
|
|
|
:- func nth_member_lookup0(list(T), T) = int.
|
|
|
|
nth_member_lookup0(List, Elem) = Pos-1 :-
|
|
list.nth_member_lookup(List, Elem, Pos).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% The scalar cell group and vector cell group contents themselves
|
|
% need to be updated to use the merged cell information.
|
|
%
|
|
:- pred remap_static_cell_info(static_cell_remap_info::in,
|
|
static_cell_info::in, static_cell_info::out) is det.
|
|
|
|
remap_static_cell_info(Remap, !SCI) :-
|
|
ScalarMap0 = !.SCI ^ sci_scalar_cell_group_map,
|
|
VectorMap0 = !.SCI ^ sci_vector_cell_group_map,
|
|
map.map_values_only(remap_scalar_cell_group(Remap), ScalarMap0, ScalarMap),
|
|
map.map_values_only(remap_vector_cell_group(Remap), VectorMap0, VectorMap),
|
|
!SCI ^ sci_scalar_cell_group_map := ScalarMap,
|
|
!SCI ^ sci_vector_cell_group_map := VectorMap.
|
|
|
|
:- pred remap_scalar_cell_group(static_cell_remap_info::in,
|
|
scalar_cell_group::in, scalar_cell_group::out) is det.
|
|
|
|
remap_scalar_cell_group(Remap, !ScalarCellGroup) :-
|
|
Array0 = !.ScalarCellGroup ^ scalar_cell_rev_array,
|
|
list.map(remap_common_cell_value(Remap), Array0, Array),
|
|
!ScalarCellGroup ^ scalar_cell_rev_array := Array.
|
|
|
|
:- pred remap_vector_cell_group(static_cell_remap_info::in,
|
|
vector_cell_group::in, vector_cell_group::out) is det.
|
|
|
|
remap_vector_cell_group(Remap, !VectorCellGroup) :-
|
|
!.VectorCellGroup = vector_cell_group(Counter, Map0),
|
|
map.map_values_only(remap_vector_contents(Remap), Map0, Map),
|
|
!:VectorCellGroup = vector_cell_group(Counter, Map).
|
|
|
|
:- pred remap_vector_contents(static_cell_remap_info::in,
|
|
vector_contents::in, vector_contents::out) is det.
|
|
|
|
remap_vector_contents(Remap, !Contents) :-
|
|
!.Contents = vector_contents(Values0),
|
|
list.map(remap_common_cell_value(Remap), Values0, Values),
|
|
!:Contents = vector_contents(Values).
|
|
|
|
:- pred remap_common_cell_value(static_cell_remap_info::in,
|
|
common_cell_value::in, common_cell_value::out) is det.
|
|
|
|
remap_common_cell_value(Remap, !CommonCellValue) :-
|
|
(
|
|
!.CommonCellValue = plain_value(RvalsTypes0),
|
|
list.map(remap_plain_value(Remap), RvalsTypes0, RvalsTypes),
|
|
!:CommonCellValue = plain_value(RvalsTypes)
|
|
;
|
|
!.CommonCellValue = grouped_args_value(ArgGroup0),
|
|
list.map(remap_arg_group_value(Remap), ArgGroup0, ArgGroup),
|
|
!:CommonCellValue = grouped_args_value(ArgGroup)
|
|
).
|
|
|
|
:- pred remap_plain_value(static_cell_remap_info::in,
|
|
pair(rval, llds_type)::in, pair(rval, llds_type)::out) is det.
|
|
|
|
remap_plain_value(Remap, Rval0 - Type, Rval - Type) :-
|
|
remap_rval(Remap, Rval0, Rval).
|
|
|
|
:- pred remap_arg_group_value(static_cell_remap_info::in,
|
|
common_cell_arg_group::in, common_cell_arg_group::out) is det.
|
|
|
|
remap_arg_group_value(Remap, !GroupedArgs) :-
|
|
(
|
|
!.GroupedArgs = common_cell_grouped_args(Type, Fields, Rvals0),
|
|
list.map(remap_rval(Remap), Rvals0, Rvals),
|
|
!:GroupedArgs = common_cell_grouped_args(Type, Fields, Rvals)
|
|
;
|
|
!.GroupedArgs = common_cell_ungrouped_arg(Type, Rvals0),
|
|
remap_rval(Remap, Rvals0, Rvals),
|
|
!:GroupedArgs = common_cell_ungrouped_arg(Type, Rvals)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
remap_static_cell_references(Remap, !Procedure) :-
|
|
Code0 = !.Procedure ^ cproc_code,
|
|
list.map(remap_instruction(Remap), Code0, Code),
|
|
!Procedure ^ cproc_code := Code.
|
|
|
|
:- pred remap_instruction(static_cell_remap_info::in,
|
|
instruction::in, instruction::out) is det.
|
|
|
|
remap_instruction(Remap, !Instr) :-
|
|
!.Instr = llds_instr(Uinstr0, Comment),
|
|
remap_instr(Remap, Uinstr0, Uinstr),
|
|
!:Instr = llds_instr(Uinstr, Comment).
|
|
|
|
:- pred remap_instr(static_cell_remap_info::in, instr::in, instr::out) is det.
|
|
|
|
remap_instr(Remap, Instr0, Instr) :-
|
|
(
|
|
Instr0 = block(NumIntTemps, NumFloatTemps, Block0),
|
|
list.map(remap_instruction(Remap), Block0, Block),
|
|
Instr = block(NumIntTemps, NumFloatTemps, Block)
|
|
;
|
|
Instr0 = assign(Lval, Rval0),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Instr = assign(Lval, Rval)
|
|
;
|
|
Instr0 = keep_assign(Lval, Rval0),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Instr = keep_assign(Lval, Rval)
|
|
;
|
|
Instr0 = if_val(Rval0, CodeAddr),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Instr = if_val(Rval, CodeAddr)
|
|
;
|
|
Instr0 = foreign_proc_code(A, Comps0, B, C, D, E, F, G, H, I),
|
|
list.map(remap_foreign_proc_component(Remap), Comps0, Comps),
|
|
Instr = foreign_proc_code(A, Comps, B, C, D, E, F, G, H, I)
|
|
;
|
|
Instr0 = computed_goto(Rval0, MaybeLabels),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Instr = computed_goto(Rval, MaybeLabels)
|
|
;
|
|
Instr0 = save_maxfr(Lval0),
|
|
remap_lval(Remap, Lval0, Lval),
|
|
Instr = save_maxfr(Lval)
|
|
;
|
|
Instr0 = restore_maxfr(Lval0),
|
|
remap_lval(Remap, Lval0, Lval),
|
|
Instr = restore_maxfr(Lval)
|
|
;
|
|
Instr0 = incr_hp(Lval0, MaybeTag, MaybeOffset, SizeRval0, Prof,
|
|
Atomic, MaybeRegion0, MaybeReuse0),
|
|
remap_lval(Remap, Lval0, Lval),
|
|
remap_rval(Remap, SizeRval0, SizeRval),
|
|
(
|
|
MaybeRegion0 = yes(Region0),
|
|
remap_rval(Remap, Region0, Region),
|
|
MaybeRegion = yes(Region)
|
|
;
|
|
MaybeRegion0 = no,
|
|
MaybeRegion = no
|
|
),
|
|
(
|
|
MaybeReuse0 = llds_reuse(Reuse0, MaybeFlag0),
|
|
remap_rval(Remap, Reuse0, Reuse),
|
|
(
|
|
MaybeFlag0 = yes(Flag0),
|
|
remap_lval(Remap, Flag0, Flag),
|
|
MaybeFlag = yes(Flag)
|
|
;
|
|
MaybeFlag0 = no,
|
|
MaybeFlag = no
|
|
),
|
|
MaybeReuse = llds_reuse(Reuse, MaybeFlag)
|
|
;
|
|
MaybeReuse0 = no_llds_reuse,
|
|
MaybeReuse = no_llds_reuse
|
|
),
|
|
Instr = incr_hp(Lval, MaybeTag, MaybeOffset, SizeRval, Prof,
|
|
Atomic, MaybeRegion, MaybeReuse)
|
|
;
|
|
Instr0 = mark_hp(Lval0),
|
|
remap_lval(Remap, Lval0, Lval),
|
|
Instr = mark_hp(Lval)
|
|
;
|
|
Instr0 = restore_hp(Rval0),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Instr = restore_hp(Rval)
|
|
;
|
|
Instr0 = free_heap(Rval0),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Instr = free_heap(Rval)
|
|
;
|
|
Instr0 = push_region_frame(StackId, EmbeddedStackFrame),
|
|
Instr = push_region_frame(StackId, EmbeddedStackFrame)
|
|
;
|
|
Instr0 = region_fill_frame(FillOp, EmbeddedStackFrame, IdRval0,
|
|
NumLval0, AddrLval0),
|
|
remap_rval(Remap, IdRval0, IdRval),
|
|
remap_lval(Remap, NumLval0, NumLval),
|
|
remap_lval(Remap, AddrLval0, AddrLval),
|
|
Instr = region_fill_frame(FillOp, EmbeddedStackFrame, IdRval,
|
|
NumLval, AddrLval)
|
|
;
|
|
Instr0 = region_set_fixed_slot(SetOp, EmbeddedStackFrame, ValueRval0),
|
|
remap_rval(Remap, ValueRval0, ValueRval),
|
|
Instr = region_set_fixed_slot(SetOp, EmbeddedStackFrame, ValueRval)
|
|
;
|
|
Instr0 = use_and_maybe_pop_region_frame(UseOp, EmbeddedStackFrame),
|
|
Instr = use_and_maybe_pop_region_frame(UseOp, EmbeddedStackFrame)
|
|
;
|
|
Instr0 = store_ticket(Lval0),
|
|
remap_lval(Remap, Lval0, Lval),
|
|
Instr = store_ticket(Lval)
|
|
;
|
|
Instr0 = reset_ticket(Rval0, Reason),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Instr = reset_ticket(Rval, Reason)
|
|
;
|
|
Instr0 = mark_ticket_stack(Lval0),
|
|
remap_lval(Remap, Lval0, Lval),
|
|
Instr = mark_ticket_stack(Lval)
|
|
;
|
|
Instr0 = prune_tickets_to(Rval0),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Instr = prune_tickets_to(Rval)
|
|
;
|
|
Instr0 = init_sync_term(Lval0, NumJoins),
|
|
remap_lval(Remap, Lval0, Lval),
|
|
Instr = init_sync_term(Lval, NumJoins)
|
|
;
|
|
Instr0 = join_and_continue(Lval0, Label),
|
|
remap_lval(Remap, Lval0, Lval),
|
|
Instr = join_and_continue(Lval, Label)
|
|
;
|
|
( Instr0 = comment(_)
|
|
; Instr0 = livevals(_)
|
|
; Instr0 = llcall(_, _, _, _, _, _)
|
|
; Instr0 = mkframe(_, _)
|
|
; Instr0 = label(_)
|
|
; Instr0 = goto(_)
|
|
; Instr0 = arbitrary_c_code(_, _, _)
|
|
; Instr0 = prune_ticket
|
|
; Instr0 = discard_ticket
|
|
; Instr0 = incr_sp(_, _, _)
|
|
; Instr0 = decr_sp(_)
|
|
; Instr0 = decr_sp_and_return(_)
|
|
; Instr0 = fork_new_child(_, _)
|
|
),
|
|
Instr = Instr0
|
|
).
|
|
|
|
:- pred remap_foreign_proc_component(static_cell_remap_info::in,
|
|
foreign_proc_component::in, foreign_proc_component::out) is det.
|
|
|
|
remap_foreign_proc_component(Remap, Comp0, Comp) :-
|
|
(
|
|
Comp0 = foreign_proc_inputs(Inputs0),
|
|
list.map(remap_foreign_proc_input(Remap), Inputs0, Inputs),
|
|
Comp = foreign_proc_inputs(Inputs)
|
|
;
|
|
Comp0 = foreign_proc_outputs(Outputs0),
|
|
list.map(remap_foreign_proc_output(Remap), Outputs0, Outputs),
|
|
Comp = foreign_proc_outputs(Outputs)
|
|
;
|
|
( Comp0 = foreign_proc_raw_code(_, _, _, _)
|
|
; Comp0 = foreign_proc_user_code(_, _, _)
|
|
; Comp0 = foreign_proc_fail_to(_)
|
|
; Comp0 = foreign_proc_noop
|
|
),
|
|
Comp = Comp0
|
|
).
|
|
|
|
:- pred remap_foreign_proc_input(static_cell_remap_info::in,
|
|
foreign_proc_input::in, foreign_proc_input::out) is det.
|
|
|
|
remap_foreign_proc_input(Remap, Input0, Input) :-
|
|
Input0 = foreign_proc_input(A, B, C, D, Rval0, E, F),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Input = foreign_proc_input(A, B, C, D, Rval, E, F).
|
|
|
|
:- pred remap_foreign_proc_output(static_cell_remap_info::in,
|
|
foreign_proc_output::in, foreign_proc_output::out) is det.
|
|
|
|
remap_foreign_proc_output(Remap, Output0, Output) :-
|
|
Output0 = foreign_proc_output(Lval0, A, B, C, D, E, F),
|
|
remap_lval(Remap, Lval0, Lval),
|
|
Output = foreign_proc_output(Lval, A, B, C, D, E, F).
|
|
|
|
:- pred remap_lval(static_cell_remap_info::in, lval::in, lval::out) is det.
|
|
|
|
remap_lval(Remap, Lval0, Lval) :-
|
|
(
|
|
Lval0 = field(MaybeTag, Rval0, FieldNum),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Lval = field(MaybeTag, Rval, FieldNum)
|
|
;
|
|
Lval0 = mem_ref(Rval0),
|
|
remap_rval(Remap, Rval0, Rval),
|
|
Lval = mem_ref(Rval)
|
|
;
|
|
( Lval0 = reg(_, _)
|
|
; Lval0 = succip
|
|
; Lval0 = maxfr
|
|
; Lval0 = curfr
|
|
; Lval0 = hp
|
|
; Lval0 = sp
|
|
; Lval0 = parent_sp
|
|
; Lval0 = temp(_, _)
|
|
; Lval0 = stackvar(_)
|
|
; Lval0 = parent_stackvar(_)
|
|
; Lval0 = framevar(_)
|
|
; Lval0 = succip_slot(_)
|
|
; Lval0 = redoip_slot(_)
|
|
; Lval0 = redofr_slot(_)
|
|
; Lval0 = succfr_slot(_)
|
|
; Lval0 = prevfr_slot(_)
|
|
; Lval0 = global_var_ref(_)
|
|
; Lval0 = lvar(_)
|
|
),
|
|
Lval = Lval0
|
|
).
|
|
|
|
:- pred remap_rval(static_cell_remap_info::in, rval::in, rval::out) is det.
|
|
|
|
remap_rval(Remap, Rval0, Rval) :-
|
|
(
|
|
Rval0 = lval(Lval0),
|
|
remap_lval(Remap, Lval0, Lval),
|
|
Rval = lval(Lval)
|
|
;
|
|
Rval0 = var(_),
|
|
Rval = Rval0
|
|
;
|
|
Rval0 = mkword(Tag, Ptr0),
|
|
remap_rval(Remap, Ptr0, Ptr),
|
|
Rval = mkword(Tag, Ptr)
|
|
;
|
|
Rval0 = const(Const0),
|
|
remap_rval_const(Remap, Const0, Const),
|
|
Rval = const(Const)
|
|
;
|
|
Rval0 = unop(Unop, A0),
|
|
remap_rval(Remap, A0, A),
|
|
Rval = unop(Unop, A)
|
|
;
|
|
Rval0 = binop(Binop, A0, B0),
|
|
remap_rval(Remap, A0, A),
|
|
remap_rval(Remap, B0, B),
|
|
Rval = binop(Binop, A, B)
|
|
;
|
|
Rval0 = mem_addr(MemRef0),
|
|
remap_mem_ref(Remap, MemRef0, MemRef),
|
|
Rval = mem_addr(MemRef)
|
|
).
|
|
|
|
:- pred remap_rval_const(static_cell_remap_info::in,
|
|
rval_const::in, rval_const::out) is det.
|
|
|
|
remap_rval_const(Remap, Const0, Const) :-
|
|
(
|
|
Const0 = llconst_data_addr(DataId0, MaybeOffset),
|
|
(
|
|
DataId0 = scalar_common_data_id(TypeNum0, _CellNum),
|
|
Remap = static_cell_remap_info(TypeNumRemap, ScalarCellGroupRemap),
|
|
( map.contains(TypeNumRemap, TypeNum0) ->
|
|
map.lookup(ScalarCellGroupRemap, TypeNum0, ScalarCellGroup),
|
|
map.lookup(ScalarCellGroup, DataId0, DataId)
|
|
;
|
|
DataId = DataId0
|
|
)
|
|
;
|
|
DataId0 = vector_common_data_id(TypeNum0, CellNum),
|
|
Remap = static_cell_remap_info(TypeNumRemap, _),
|
|
( map.search(TypeNumRemap, TypeNum0, TypeNum) ->
|
|
DataId = vector_common_data_id(TypeNum, CellNum)
|
|
;
|
|
DataId = DataId0
|
|
)
|
|
;
|
|
( DataId0 = rtti_data_id(_)
|
|
; DataId0 = proc_tabling_data_id(_, _)
|
|
; DataId0 = layout_id(_)
|
|
; DataId0 = layout_slot_id(_, _)
|
|
),
|
|
DataId = DataId0
|
|
),
|
|
Const = llconst_data_addr(DataId, MaybeOffset)
|
|
;
|
|
( Const0 = llconst_true
|
|
; Const0 = llconst_false
|
|
; Const0 = llconst_int(_)
|
|
; Const0 = llconst_foreign(_, _)
|
|
; Const0 = llconst_float(_)
|
|
; Const0 = llconst_string(_)
|
|
; Const0 = llconst_multi_string(_)
|
|
; Const0 = llconst_code_addr(_)
|
|
),
|
|
Const = Const0
|
|
).
|
|
|
|
:- pred remap_mem_ref(static_cell_remap_info::in, mem_ref::in, mem_ref::out)
|
|
is det.
|
|
|
|
remap_mem_ref(Remap, MemRef0, MemRef) :-
|
|
(
|
|
( MemRef0 = stackvar_ref(_)
|
|
; MemRef0 = framevar_ref(_)
|
|
),
|
|
MemRef = MemRef0
|
|
;
|
|
MemRef0 = heap_ref(Ptr0, Tag, FieldNum),
|
|
remap_rval(Remap, Ptr0, Ptr),
|
|
MemRef = heap_ref(Ptr, Tag, FieldNum)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- func this_file = string.
|
|
|
|
this_file = "global_data.m".
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module global_data.
|
|
%-----------------------------------------------------------------------------%
|