mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
768 lines
31 KiB
Mathematica
768 lines
31 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2009-2012 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: ml_global_data.m.
|
|
% Main author: zs.
|
|
%
|
|
% This module is part of the MLDS code generator. It handles the generation
|
|
% of data structures that are "born global", i.e. they belong to the generated
|
|
% module as a whole, not to any particular function in it.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module ml_backend.ml_global_data.
|
|
:- interface.
|
|
|
|
:- import_module backend_libs.
|
|
:- import_module backend_libs.rtti.
|
|
:- import_module ml_backend.mlds.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module bimap.
|
|
:- import_module cord.
|
|
:- import_module counter.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module maybe.
|
|
|
|
% This abstract type represents the MLDS code generator's repository of
|
|
% data structures that are "born global", i.e. the ones for which we
|
|
% known from the start that they will be defined at file scope.
|
|
%
|
|
:- type ml_global_data.
|
|
|
|
:- type use_common_cells
|
|
---> do_not_use_common_cells
|
|
; use_common_cells.
|
|
|
|
:- type have_unboxed_floats
|
|
---> have_unboxed_floats
|
|
; do_not_have_unboxed_floats.
|
|
|
|
:- type have_unboxed_int64s
|
|
---> have_unboxed_int64s
|
|
; do_not_have_unboxed_int64s.
|
|
|
|
:- type ml_scalar_cell_map ==
|
|
map(ml_scalar_common_type_num, ml_scalar_cell_group).
|
|
|
|
:- type ml_scalar_cell_group
|
|
---> ml_scalar_cell_group(
|
|
mscg_type :: mlds_type,
|
|
mscg_array_size :: initializer_array_size,
|
|
|
|
mscg_counter :: counter, % next cell number
|
|
mscg_members :: bimap(mlds_initializer,
|
|
mlds_scalar_common),
|
|
mscg_rows :: cord(mlds_initializer)
|
|
).
|
|
|
|
:- type ml_vector_cell_map ==
|
|
map(ml_vector_common_type_num, ml_vector_cell_group).
|
|
|
|
:- type ml_vector_cell_group
|
|
---> ml_vector_cell_group(
|
|
mvcg_type :: mlds_type,
|
|
mvcg_type_defn :: mlds_struct_defn,
|
|
mvcg_field_ids :: list(mlds_field_id),
|
|
|
|
mvcg_next_row :: int,
|
|
mvcg_rows :: cord(mlds_initializer)
|
|
).
|
|
|
|
:- type ml_alloc_site_data
|
|
---> ml_alloc_site_data(
|
|
masd_proc_label :: mlds_function_name,
|
|
masd_context :: prog_context,
|
|
masd_type :: string,
|
|
masd_size :: int
|
|
).
|
|
|
|
% Initialize the ml_global_data structure to a value that represents
|
|
% no global data structures known yet.
|
|
%
|
|
:- func ml_global_data_init(mlds_target_lang, use_common_cells,
|
|
have_unboxed_floats, have_unboxed_int64s) = ml_global_data.
|
|
|
|
% ml_global_data_get_all_global_defns(GlobalData,
|
|
% ScalarCellGroupMap, VectorCellGroupMap, AllocIds,
|
|
% RttiDefns, CellDefns, ClosureWrapperFuncDefns):
|
|
%
|
|
% Get all the global definitions implicit in the argument.
|
|
%
|
|
:- pred ml_global_data_get_all_global_defns(ml_global_data::in,
|
|
ml_scalar_cell_map::out, ml_vector_cell_map::out,
|
|
assoc_list(mlds_alloc_id, ml_alloc_site_data)::out,
|
|
list(mlds_global_var_defn)::out, list(mlds_global_var_defn)::out,
|
|
list(mlds_function_defn)::out) is det.
|
|
|
|
:- pred ml_global_data_get_target(ml_global_data::in,
|
|
mlds_target_lang::out) is det.
|
|
:- pred ml_global_data_have_unboxed_floats(ml_global_data::in,
|
|
have_unboxed_floats::out) is det.
|
|
:- pred ml_global_data_have_unboxed_int64s(ml_global_data::in,
|
|
have_unboxed_int64s::out) is det.
|
|
|
|
% This type maps the names of rtti data structures that have already been
|
|
% generated to the rval that refers to that data structure, and its type.
|
|
%
|
|
% The code generator looks up this map whenever it is needs a reference to
|
|
% an RTTI data structure that may or may not have been generated before.
|
|
% If it finds the id of that data structure in this map, it uses the
|
|
% corresponding value *without* generating the duplicate definition.
|
|
% Of course, this requires the code generator to add the original
|
|
% definition of the data structure to the ml_globals_data whenever it adds
|
|
% new entries to this map.
|
|
%
|
|
% At the moment, the only data structures that are potentially duplicated
|
|
% are the representations of type_infos and pseudo_type_infos, so only
|
|
% these rtti_ids will be in this map.
|
|
%
|
|
:- type ml_rtti_rval_type_map == map(rtti_id, ml_rval_and_type).
|
|
:- type ml_rval_and_type
|
|
---> ml_rval_and_type(
|
|
mlds_rval,
|
|
mlds_type
|
|
).
|
|
|
|
% Return the component of the given ml_global_data that contains
|
|
% information about potentially duplicated RTTI global definitions.
|
|
%
|
|
:- pred ml_global_data_get_pdup_rval_type_map(ml_global_data::in,
|
|
ml_rtti_rval_type_map::out) is det.
|
|
|
|
% ml_global_data_get_closure_wrapper_func_defns(GlobalData,
|
|
% ClosureWrapperFuncDefns):
|
|
% ml_global_data_set_closure_wrapper_func_defns(ClosureWrapperFuncDefns,
|
|
% !GlobalData):
|
|
%
|
|
% Get and set the cord of closure wrapper function definitions.
|
|
% Like other function definitions, these may need flattening
|
|
% by ml_elim_nested.m.
|
|
%
|
|
:- pred ml_global_data_get_closure_wrapper_func_defns(ml_global_data::in,
|
|
cord(mlds_function_defn)::out) is det.
|
|
:- pred ml_global_data_set_closure_wrapper_func_defns(
|
|
cord(mlds_function_defn)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
% Map the given rtti_id to the given ml_rval_and_type, and record the
|
|
% generation of the given global data definitions.
|
|
%
|
|
:- pred ml_global_data_add_pdup_rtti_id(rtti_id::in, ml_rval_and_type::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
% Add to the global data structure one or more definitions that are
|
|
% "unique by construction". Some of these are guaranteed to be flat
|
|
% definitions (definitions for which ml_elim_nested is an identity
|
|
% operation), while some have no such guarantee.
|
|
%
|
|
:- pred ml_global_data_add_rtti_defn(mlds_global_var_defn::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
:- pred ml_global_data_add_closure_wrapper_func_defns(
|
|
list(mlds_function_defn)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
% Generate a definition for a static scalar constant, given the constant's
|
|
% name prefix, type, and initializer (access is always acc_private),
|
|
% and return a reference to the constant itself (not its address).
|
|
%
|
|
:- pred ml_gen_static_scalar_const_value(mlds_module_name::in,
|
|
mlds_global_const_var::in, mlds_type::in, mlds_initializer::in,
|
|
prog_context::in, mlds_rval::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
% Generate a definition for a static scalar constant, given the constant's
|
|
% name prefix, type, and initializer (access is always acc_private),
|
|
% and return a reference to the constant's address.
|
|
%
|
|
:- pred ml_gen_static_scalar_const_addr(mlds_module_name::in,
|
|
mlds_global_const_var::in, mlds_type::in, mlds_initializer::in,
|
|
prog_context::in, mlds_rval::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
% Look up (and if necessary, create) the type of the structure needed
|
|
% to hold a vector of values of the given types. Return the number of the
|
|
% type, so that it can be given to ml_gen_static_vector_defn later,
|
|
% and both the type itself and the names of its fields, so that they
|
|
% can be used in code that builds and/or uses the vector.
|
|
%
|
|
:- pred ml_gen_static_vector_type(mlds_module_name::in, prog_context::in,
|
|
mlds_target_lang::in, list(mlds_type)::in,
|
|
ml_vector_common_type_num::out, mlds_type::out, list(mlds_field_id)::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
% Generate a definition for a static vector constant, given the constant's
|
|
% type and an initializer for each row.
|
|
%
|
|
:- pred ml_gen_static_vector_defn(mlds_module_name::in,
|
|
ml_vector_common_type_num::in, list(mlds_initializer)::in,
|
|
mlds_vector_common::out, ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
% Generate or look up an allocation site.
|
|
%
|
|
:- pred ml_gen_alloc_site(mlds_function_name::in, maybe(cons_id)::in, int::in,
|
|
prog_context::in, mlds_alloc_id::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.builtin_ops.
|
|
:- import_module ml_backend.ml_type_gen.
|
|
:- import_module parse_tree.parse_tree_out_sym_name.
|
|
:- import_module parse_tree.prog_type.
|
|
|
|
:- import_module bool.
|
|
:- import_module int.
|
|
:- import_module require.
|
|
:- import_module string.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type ml_scalar_cell_type
|
|
---> ml_scalar_cell_type(mlds_type, initializer_array_size).
|
|
:- type ml_scalar_cell_type_map
|
|
== map(ml_scalar_cell_type, ml_scalar_common_type_num).
|
|
|
|
:- type ml_vector_cell_type_map
|
|
== map(list(mlds_type), ml_vector_common_type_num).
|
|
|
|
:- type ml_alloc_id_map
|
|
== bimap(mlds_alloc_id, ml_alloc_site_data).
|
|
|
|
:- type ml_global_data
|
|
---> ml_global_data(
|
|
mgd_pdup_rval_type_map :: ml_rtti_rval_type_map,
|
|
mgd_target :: mlds_target_lang,
|
|
mgd_use_common_cells :: use_common_cells,
|
|
mgd_have_unboxed_floats :: have_unboxed_floats,
|
|
mgd_have_unboxed_int64s :: have_unboxed_int64s,
|
|
mgd_const_counter :: counter,
|
|
|
|
mgd_cell_defns :: cord(mlds_global_var_defn),
|
|
mgd_rtti_defns :: cord(mlds_global_var_defn),
|
|
mgd_closure_wrapper_funcs :: cord(mlds_function_defn),
|
|
|
|
mgd_cell_type_counter :: counter,
|
|
|
|
mgd_scalar_type_num_map :: ml_scalar_cell_type_map,
|
|
mgd_scalar_cell_group_map :: ml_scalar_cell_map,
|
|
|
|
mgd_vector_type_num_map :: ml_vector_cell_type_map,
|
|
mgd_vector_cell_group_map :: ml_vector_cell_map,
|
|
|
|
mgd_alloc_id_counter :: counter,
|
|
mgd_alloc_id_map :: ml_alloc_id_map
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
ml_global_data_init(Target, UseCommonCells,
|
|
HaveUnboxedFloats, HaveUnboxedInt64s) = GlobalData :-
|
|
GlobalData = ml_global_data(map.init, Target, UseCommonCells,
|
|
HaveUnboxedFloats, HaveUnboxedInt64s, counter.init(1),
|
|
cord.init, cord.init, cord.init,
|
|
counter.init(1), map.init, map.init, map.init, map.init,
|
|
counter.init(0), bimap.init).
|
|
|
|
ml_global_data_get_all_global_defns(GlobalData,
|
|
ScalarCellGroupMap, VectorCellGroupMap, AllocIds,
|
|
RttiDefns, CellDefns, ClosureWrapperFuncDefns) :-
|
|
GlobalData = ml_global_data(_PDupRvalTypeMap, _Target, _UseCommonCells,
|
|
_HaveUnboxedFloats, _HaveUnboxedInt64s, _ConstCounter,
|
|
CellDefnsCord, RttiDefnsCord, ClosureWrapperFuncDefnsCord,
|
|
_TypeNumCounter,
|
|
_ScalarTypeNumMap, ScalarCellGroupMap,
|
|
_VectorTypeNumMap, VectorCellGroupMap,
|
|
_AllocIdNumCounter, AllocIdMap),
|
|
bimap.to_assoc_list(AllocIdMap, AllocIds),
|
|
RttiDefns = cord.to_list(RttiDefnsCord),
|
|
CellDefns = cord.to_list(CellDefnsCord),
|
|
ClosureWrapperFuncDefns = cord.to_list(ClosureWrapperFuncDefnsCord).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Access predicates for the ml_global_data type.
|
|
%
|
|
|
|
:- pred ml_global_data_get_const_counter(ml_global_data::in,
|
|
counter::out) is det.
|
|
:- pred ml_global_data_get_cell_defns(ml_global_data::in,
|
|
cord(mlds_global_var_defn)::out) is det.
|
|
:- pred ml_global_data_get_rtti_defns(ml_global_data::in,
|
|
cord(mlds_global_var_defn)::out) is det.
|
|
|
|
ml_global_data_get_target(GlobalData, X) :-
|
|
X = GlobalData ^ mgd_target.
|
|
ml_global_data_have_unboxed_floats(GlobalData, X) :-
|
|
X = GlobalData ^ mgd_have_unboxed_floats.
|
|
ml_global_data_have_unboxed_int64s(GlobalData, X) :-
|
|
X = GlobalData ^ mgd_have_unboxed_int64s.
|
|
ml_global_data_get_pdup_rval_type_map(GlobalData, X) :-
|
|
X = GlobalData ^ mgd_pdup_rval_type_map.
|
|
ml_global_data_get_const_counter(GlobalData, X) :-
|
|
X = GlobalData ^ mgd_const_counter.
|
|
ml_global_data_get_cell_defns(GlobalData, X) :-
|
|
X = GlobalData ^ mgd_cell_defns.
|
|
ml_global_data_get_rtti_defns(GlobalData, X) :-
|
|
X = GlobalData ^ mgd_rtti_defns.
|
|
ml_global_data_get_closure_wrapper_func_defns(GlobalData, X) :-
|
|
X = GlobalData ^ mgd_closure_wrapper_funcs.
|
|
|
|
:- pred ml_global_data_set_pdup_rval_type_map(ml_rtti_rval_type_map::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
:- pred ml_global_data_set_const_counter(counter::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
:- pred ml_global_data_set_cell_defns(cord(mlds_global_var_defn)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
:- pred ml_global_data_set_rtti_defns(cord(mlds_global_var_defn)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
ml_global_data_set_pdup_rval_type_map(X, !GlobalData) :-
|
|
!GlobalData ^ mgd_pdup_rval_type_map := X.
|
|
ml_global_data_set_const_counter(X, !GlobalData) :-
|
|
!GlobalData ^ mgd_const_counter := X.
|
|
ml_global_data_set_cell_defns(X, !GlobalData) :-
|
|
!GlobalData ^ mgd_cell_defns := X.
|
|
ml_global_data_set_rtti_defns(X, !GlobalData) :-
|
|
!GlobalData ^ mgd_rtti_defns := X.
|
|
ml_global_data_set_closure_wrapper_func_defns(X, !GlobalData) :-
|
|
!GlobalData ^ mgd_closure_wrapper_funcs := X.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
ml_global_data_add_pdup_rtti_id(RttiId, RvalType, !GlobalData) :-
|
|
ml_global_data_get_pdup_rval_type_map(!.GlobalData, PDupRvalTypeMap0),
|
|
map.det_insert(RttiId, RvalType, PDupRvalTypeMap0, PDupRvalTypeMap),
|
|
ml_global_data_set_pdup_rval_type_map(PDupRvalTypeMap, !GlobalData).
|
|
|
|
ml_global_data_add_rtti_defn(Defn, !GlobalData) :-
|
|
ml_global_data_get_rtti_defns(!.GlobalData, RttiDefns0),
|
|
cord.snoc(Defn, RttiDefns0, RttiDefns),
|
|
ml_global_data_set_rtti_defns(RttiDefns, !GlobalData).
|
|
|
|
ml_global_data_add_closure_wrapper_func_defns(FuncDefns, !GlobalData) :-
|
|
ml_global_data_get_closure_wrapper_func_defns(!.GlobalData,
|
|
ClosureWrapperDefns0),
|
|
cord.snoc_list(FuncDefns, ClosureWrapperDefns0, ClosureWrapperDefns),
|
|
ml_global_data_set_closure_wrapper_func_defns(ClosureWrapperDefns,
|
|
!GlobalData).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
ml_gen_static_scalar_const_value(MLDS_ModuleName, ConstVarKind, ConstType0,
|
|
Initializer0, Context, DataRval, !GlobalData) :-
|
|
ml_maybe_specialize_generic_array_type(ConstType0, ConstType,
|
|
Initializer0, Initializer),
|
|
UseCommonCells = !.GlobalData ^ mgd_use_common_cells,
|
|
(
|
|
UseCommonCells = use_common_cells,
|
|
ml_gen_scalar_static_defn(MLDS_ModuleName, ConstType, Initializer,
|
|
Common, !GlobalData),
|
|
DataRval = ml_scalar_common(Common)
|
|
;
|
|
UseCommonCells = do_not_use_common_cells,
|
|
ml_gen_plain_static_defn(ConstVarKind, ConstType, Initializer,
|
|
Context, VarName, !GlobalData),
|
|
QualVarName = qual_global_var_name(MLDS_ModuleName, VarName),
|
|
DataVar = ml_global_var(QualVarName, ConstType),
|
|
DataRval = ml_lval(DataVar)
|
|
).
|
|
|
|
ml_gen_static_scalar_const_addr(MLDS_ModuleName, ConstVarKind, ConstType0,
|
|
Initializer0, Context, DataAddrRval, !GlobalData) :-
|
|
ml_maybe_specialize_generic_array_type(ConstType0, ConstType,
|
|
Initializer0, Initializer),
|
|
UseCommonCells = !.GlobalData ^ mgd_use_common_cells,
|
|
(
|
|
UseCommonCells = use_common_cells,
|
|
ml_gen_scalar_static_defn(MLDS_ModuleName, ConstType, Initializer,
|
|
Common, !GlobalData),
|
|
DataAddrRval = ml_scalar_common_addr(Common)
|
|
;
|
|
UseCommonCells = do_not_use_common_cells,
|
|
ml_gen_plain_static_defn(ConstVarKind, ConstType, Initializer,
|
|
Context, VarName, !GlobalData),
|
|
DataAddrRval =
|
|
ml_const(mlconst_data_addr_global_var(MLDS_ModuleName, VarName))
|
|
).
|
|
|
|
:- pred ml_gen_scalar_static_defn(mlds_module_name::in, mlds_type::in,
|
|
mlds_initializer::in, mlds_scalar_common::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
ml_gen_scalar_static_defn(MLDS_ModuleName, ConstType, Initializer0, Common,
|
|
!GlobalData) :-
|
|
Initializer = Initializer0,
|
|
% We could set Initializer using the following code instead, but
|
|
% while it does sometimes discover that two initializers that differ
|
|
% in their MLDS forms would nevertheless generate the same C code,
|
|
% it does so very rarely. (For example, at one time this code
|
|
% reduced the total size of the .rodata sections of the .o files
|
|
% in the compiler directory from 160,636 bytes to 160,540 bytes.)
|
|
% The small improvement in memory efficiency does not justify
|
|
% the execution time cost of the code needed to get it.
|
|
% ml_global_data_get_target(!.GlobalData, Target),
|
|
% (
|
|
% Target = ml_target_c,
|
|
% % Attempt to eliminate differences between MLDS initializers
|
|
% % that will not affect the C code we generate.
|
|
% Initializer = semicanonicalize_types_in_initializer_for_c(Initializer0)
|
|
% ;
|
|
% ( Target = ml_target_csharp
|
|
% ; Target = ml_target_java
|
|
% ),
|
|
% Initializer = Initializer0
|
|
% ),
|
|
InitArraySize = get_initializer_array_size(Initializer),
|
|
CellType = ml_scalar_cell_type(ConstType, InitArraySize),
|
|
some [!CellGroup] (
|
|
TypeNumMap0 = !.GlobalData ^ mgd_scalar_type_num_map,
|
|
CellGroupMap0 = !.GlobalData ^ mgd_scalar_cell_group_map,
|
|
( if map.search(TypeNumMap0, CellType, OldTypeNum) then
|
|
TypeNum = OldTypeNum,
|
|
( if map.search(CellGroupMap0, TypeNum, !:CellGroup) then
|
|
true
|
|
else
|
|
!:CellGroup = ml_scalar_cell_group(ConstType,
|
|
InitArraySize, counter.init(0), bimap.init, cord.empty)
|
|
)
|
|
else
|
|
TypeNumCounter0 = !.GlobalData ^ mgd_cell_type_counter,
|
|
counter.allocate(TypeRawNum, TypeNumCounter0, TypeNumCounter),
|
|
TypeNum = ml_scalar_common_type_num(TypeRawNum),
|
|
!GlobalData ^ mgd_cell_type_counter := TypeNumCounter,
|
|
|
|
map.det_insert(CellType, TypeNum, TypeNumMap0, TypeNumMap),
|
|
!GlobalData ^ mgd_scalar_type_num_map := TypeNumMap,
|
|
|
|
!:CellGroup = ml_scalar_cell_group(ConstType,
|
|
InitArraySize, counter.init(0), bimap.init, cord.empty)
|
|
),
|
|
|
|
RowCounter0 = !.CellGroup ^ mscg_counter,
|
|
counter.allocate(RowNum, RowCounter0, RowCounter),
|
|
MembersMap0 = !.CellGroup ^ mscg_members,
|
|
NewCommon =
|
|
mlds_scalar_common(MLDS_ModuleName, ConstType, TypeNum, RowNum),
|
|
bimap.search_insert(Initializer, NewCommon, MaybeOldCommon,
|
|
MembersMap0, MembersMap),
|
|
(
|
|
MaybeOldCommon = yes(OldCommon),
|
|
% We cannot get here if !.CellGroup wasn't found in CellGroupMap0.
|
|
Common = OldCommon
|
|
;
|
|
MaybeOldCommon = no,
|
|
Common = NewCommon,
|
|
!CellGroup ^ mscg_counter := RowCounter,
|
|
!CellGroup ^ mscg_members := MembersMap,
|
|
|
|
Rows0 = !.CellGroup ^ mscg_rows,
|
|
cord.snoc(Initializer, Rows0, Rows),
|
|
!CellGroup ^ mscg_rows := Rows,
|
|
|
|
map.set(TypeNum, !.CellGroup, CellGroupMap0, CellGroupMap),
|
|
!GlobalData ^ mgd_scalar_cell_group_map := CellGroupMap
|
|
)
|
|
).
|
|
|
|
:- pred ml_gen_plain_static_defn(mlds_global_const_var::in, mlds_type::in,
|
|
mlds_initializer::in, prog_context::in, mlds_global_var_name::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
ml_gen_plain_static_defn(ConstVarKind, ConstType,
|
|
Initializer, Context, VarName, !GlobalData) :-
|
|
ml_global_data_get_const_counter(!.GlobalData, ConstCounter0),
|
|
counter.allocate(ConstNum, ConstCounter0, ConstCounter),
|
|
ml_global_data_set_const_counter(ConstCounter, !GlobalData),
|
|
|
|
VarName = gvn_const_var(ConstVarKind, ConstNum),
|
|
% The GC never needs to trace static constants, because they can never
|
|
% point into the heap; they can point only to other static constants.
|
|
GCStatement = gc_no_stmt,
|
|
DeclFlags = mlds_global_var_decl_flags(gvar_acc_module_only, const),
|
|
DataDefn = mlds_global_var_defn(VarName, Context, DeclFlags, ConstType,
|
|
Initializer, GCStatement),
|
|
|
|
ml_global_data_get_cell_defns(!.GlobalData, CellDefns0),
|
|
cord.snoc(DataDefn, CellDefns0, CellDefns),
|
|
ml_global_data_set_cell_defns(CellDefns, !GlobalData).
|
|
|
|
:- pred ml_maybe_specialize_generic_array_type(mlds_type::in, mlds_type::out,
|
|
mlds_initializer::in, mlds_initializer::out) is det.
|
|
|
|
ml_maybe_specialize_generic_array_type(ConstType0, ConstType,
|
|
Initializer0, Initializer) :-
|
|
( if
|
|
ConstType0 = mlds_array_type(mlds_generic_type),
|
|
Initializer0 = init_array(Inits0),
|
|
list.map2(ml_specialize_generic_array_init, Inits0, Inits, Types),
|
|
% XXX ARG_PACK Specialize int64 and uint64 elements as well.
|
|
list.member(mlds_builtin_type_float, Types)
|
|
then
|
|
ConstType = mlds_mostly_generic_array_type(Types),
|
|
Initializer = init_array(Inits)
|
|
else
|
|
ConstType = ConstType0,
|
|
Initializer = Initializer0
|
|
).
|
|
|
|
:- pred ml_specialize_generic_array_init(mlds_initializer::in,
|
|
mlds_initializer::out, mlds_type::out) is det.
|
|
|
|
ml_specialize_generic_array_init(Init0, Init, Type) :-
|
|
( if
|
|
Init0 = init_obj(Rval0),
|
|
% XXX ARG_PACK Specialize int64 and uint64 elements as well.
|
|
ml_specialize_generic_array_rval(Rval0, Rval)
|
|
then
|
|
Init = init_obj(Rval),
|
|
Type = mlds_builtin_type_float
|
|
else
|
|
Init = Init0,
|
|
Type = mlds_generic_type
|
|
).
|
|
|
|
:- pred ml_specialize_generic_array_rval(mlds_rval::in, mlds_rval::out)
|
|
is semidet.
|
|
|
|
ml_specialize_generic_array_rval(!Rval) :-
|
|
(
|
|
!.Rval = ml_const(mlconst_float(_))
|
|
;
|
|
( !.Rval = ml_box(Type, SubRval)
|
|
; !.Rval = ml_unbox(Type, SubRval)
|
|
; !.Rval = ml_cast(Type, SubRval)
|
|
),
|
|
% XXX ARG_PACK Specialize for int64s and uint64s as well.
|
|
(
|
|
Type = mlds_builtin_type_float,
|
|
!:Rval = SubRval
|
|
;
|
|
Type = mercury_nb_type(_, CtorCat),
|
|
CtorCat = ctor_cat_user(cat_user_notag),
|
|
ml_specialize_generic_array_rval(SubRval, !:Rval)
|
|
)
|
|
;
|
|
!.Rval = ml_binop(Op, _, _),
|
|
ml_specialize_generic_array_binop(Op, yes)
|
|
).
|
|
|
|
:- pred ml_specialize_generic_array_binop(binary_op::in, bool::out) is det.
|
|
|
|
ml_specialize_generic_array_binop(Op, IsFloat) :-
|
|
(
|
|
( Op = int_arith(_, _)
|
|
; Op = unchecked_left_shift(_, _)
|
|
; Op = unchecked_right_shift(_, _)
|
|
; Op = bitwise_and(_)
|
|
; Op = bitwise_or(_)
|
|
; Op = bitwise_xor(_)
|
|
; Op = logical_and
|
|
; Op = logical_or
|
|
; Op = int_cmp(_, _)
|
|
; Op = int_as_uint_cmp(_)
|
|
; Op = in_range
|
|
; Op = float_cmp(_)
|
|
; Op = str_cmp(_)
|
|
; Op = offset_str_eq(_, _)
|
|
; Op = str_nzp
|
|
; Op = body
|
|
; Op = array_index(_) % should not be an initializer anyway
|
|
; Op = string_unsafe_index_code_unit
|
|
; Op = pointer_equal_conservative
|
|
; Op = int64_from_dword
|
|
; Op = uint64_from_dword
|
|
),
|
|
IsFloat = no
|
|
;
|
|
( Op = float_arith(_)
|
|
; Op = float_from_dword
|
|
),
|
|
IsFloat = yes
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
ml_gen_static_vector_type(MLDS_ModuleName, Context, Target, ArgTypes,
|
|
TypeNum, StructType, FieldIds, !GlobalData) :-
|
|
TypeNumMap0 = !.GlobalData ^ mgd_vector_type_num_map,
|
|
( if map.search(TypeNumMap0, ArgTypes, OldTypeNum) then
|
|
TypeNum = OldTypeNum,
|
|
CellGroupMap = !.GlobalData ^ mgd_vector_cell_group_map,
|
|
map.lookup(CellGroupMap, TypeNum, CellGroup),
|
|
CellGroup = ml_vector_cell_group(StructType, _TypeDefn, FieldIds, _, _)
|
|
else
|
|
TypeNumCounter0 = !.GlobalData ^ mgd_cell_type_counter,
|
|
counter.allocate(TypeRawNum, TypeNumCounter0, TypeNumCounter),
|
|
TypeRawNumStr = string.int_to_string(TypeRawNum),
|
|
TypeNum = ml_vector_common_type_num(TypeRawNum),
|
|
!GlobalData ^ mgd_cell_type_counter := TypeNumCounter,
|
|
|
|
map.det_insert(ArgTypes, TypeNum, TypeNumMap0, TypeNumMap),
|
|
!GlobalData ^ mgd_vector_type_num_map := TypeNumMap,
|
|
|
|
FieldFlags = mlds_field_var_decl_flags(per_instance, const),
|
|
ml_gen_vector_cell_field_types(Context, FieldFlags,
|
|
TypeRawNum, 0, ArgTypes, FieldNames, FieldDefns, FieldInfos),
|
|
|
|
StructName = "vector_common_type_" ++ TypeRawNumStr,
|
|
StructId = mlds_struct_id(MLDS_ModuleName, StructName),
|
|
(
|
|
Target = ml_target_c,
|
|
MaybeCtorDefn = maybe.no
|
|
;
|
|
( Target = ml_target_java
|
|
; Target = ml_target_csharp
|
|
),
|
|
CtorDefn = ml_gen_struct_constructor_function(StructId,
|
|
MLDS_ModuleName, FieldInfos, Context),
|
|
MaybeCtorDefn = maybe.yes(CtorDefn)
|
|
),
|
|
StructDefn = mlds_struct_defn(StructName, Context,
|
|
FieldDefns, MaybeCtorDefn),
|
|
|
|
MLDS_ClassModuleName = mlds_append_class_qualifier_module_qual(
|
|
MLDS_ModuleName, StructName, 0),
|
|
StructType = mlds_struct_type(StructId),
|
|
make_named_fields(MLDS_ClassModuleName, StructType, FieldNames,
|
|
FieldIds),
|
|
|
|
CellGroup = ml_vector_cell_group(StructType, StructDefn,
|
|
FieldIds, 0, cord.empty),
|
|
|
|
CellGroupMap0 = !.GlobalData ^ mgd_vector_cell_group_map,
|
|
map.det_insert(TypeNum, CellGroup, CellGroupMap0, CellGroupMap),
|
|
!GlobalData ^ mgd_vector_cell_group_map := CellGroupMap
|
|
).
|
|
|
|
:- pred ml_gen_vector_cell_field_types(prog_context::in,
|
|
mlds_field_var_decl_flags::in, int::in, int::in, list(mlds_type)::in,
|
|
list(mlds_field_var_name)::out, list(mlds_field_var_defn)::out,
|
|
list(mlds_field_info)::out) is det.
|
|
|
|
ml_gen_vector_cell_field_types(_, _, _, _, [], [], [], []).
|
|
ml_gen_vector_cell_field_types(Context, Flags, TypeRawNum, FieldNum,
|
|
[Type | Types], [FieldVarName | FieldVarNames],
|
|
[FieldDataDefn | FieldDataDefns], [FieldInfo | FieldInfos]) :-
|
|
FieldVarName = fvn_global_data_field(TypeRawNum, FieldNum),
|
|
FieldDataDefn = mlds_field_var_defn(FieldVarName, Context, Flags,
|
|
Type, no_initializer, gc_no_stmt),
|
|
FieldInfo = mlds_field_info(FieldVarName, Type, gc_no_stmt, Context),
|
|
ml_gen_vector_cell_field_types(Context, Flags, TypeRawNum,
|
|
FieldNum + 1, Types, FieldVarNames, FieldDataDefns, FieldInfos).
|
|
|
|
:- pred make_named_fields(mlds_module_name::in, mlds_type::in,
|
|
list(mlds_field_var_name)::in, list(mlds_field_id)::out) is det.
|
|
|
|
make_named_fields(_, _, [], []).
|
|
make_named_fields(MLDS_ModuleName, StructType, [FieldName | FieldNames],
|
|
[FieldId | FieldIds]) :-
|
|
QualName = qual_field_var_name(MLDS_ModuleName, module_qual, FieldName),
|
|
FieldId = ml_field_named(QualName, StructType),
|
|
make_named_fields(MLDS_ModuleName, StructType, FieldNames, FieldIds).
|
|
|
|
ml_gen_static_vector_defn(MLDS_ModuleName, TypeNum, RowInitializers, Common,
|
|
!GlobalData) :-
|
|
some [!CellGroup] (
|
|
list.length(RowInitializers, NumRows),
|
|
CellGroupMap0 = !.GlobalData ^ mgd_vector_cell_group_map,
|
|
map.lookup(CellGroupMap0, TypeNum, !:CellGroup),
|
|
|
|
NextRow0 = !.CellGroup ^ mvcg_next_row,
|
|
StartRowNum = NextRow0,
|
|
NextRow = NextRow0 + NumRows,
|
|
!CellGroup ^ mvcg_next_row := NextRow,
|
|
|
|
StructType = !.CellGroup ^ mvcg_type,
|
|
Common = mlds_vector_common(MLDS_ModuleName, StructType, TypeNum,
|
|
StartRowNum, NumRows),
|
|
|
|
Rows0 = !.CellGroup ^ mvcg_rows,
|
|
cord.snoc_list(RowInitializers, Rows0, Rows),
|
|
!CellGroup ^ mvcg_rows := Rows,
|
|
|
|
map.det_update(TypeNum, !.CellGroup, CellGroupMap0, CellGroupMap),
|
|
!GlobalData ^ mgd_vector_cell_group_map := CellGroupMap
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
ml_gen_alloc_site(ProcLabel, MaybeConsId, Size, Context, AllocId,
|
|
!GlobalData) :-
|
|
(
|
|
MaybeConsId = yes(ConsId),
|
|
TypeStr = cons_id_to_alloc_site_string(ConsId)
|
|
;
|
|
MaybeConsId = no,
|
|
TypeStr = "unknown"
|
|
),
|
|
AllocData = ml_alloc_site_data(ProcLabel, Context, TypeStr, Size),
|
|
Map0 = !.GlobalData ^ mgd_alloc_id_map,
|
|
( if bimap.search(Map0, AllocId0, AllocData) then
|
|
AllocId = AllocId0
|
|
else
|
|
Counter0 = !.GlobalData ^ mgd_alloc_id_counter,
|
|
counter.allocate(AllocIdNum, Counter0, Counter),
|
|
AllocId = mlds_alloc_id(AllocIdNum),
|
|
bimap.det_insert(AllocId, AllocData, Map0, Map),
|
|
!GlobalData ^ mgd_alloc_id_counter := Counter,
|
|
!GlobalData ^ mgd_alloc_id_map := Map
|
|
).
|
|
|
|
:- func cons_id_to_alloc_site_string(cons_id) = string.
|
|
|
|
cons_id_to_alloc_site_string(ConsId) = TypeStr :-
|
|
(
|
|
ConsId = du_data_ctor(du_ctor(_, _, TypeCtor)),
|
|
TypeStr = type_ctor_to_string(TypeCtor)
|
|
;
|
|
ConsId = tuple_cons(Arity),
|
|
TypeStr = "{}/" ++ string.from_int(Arity)
|
|
;
|
|
ConsId = closure_cons(_),
|
|
TypeStr = "closure"
|
|
;
|
|
ConsId = type_info_cell_constructor(_),
|
|
TypeStr = "private_builtin.type_info/0"
|
|
;
|
|
ConsId = typeclass_info_cell_constructor,
|
|
TypeStr = "typeclass_info"
|
|
;
|
|
ConsId = type_info_const(_),
|
|
TypeStr = "type_info_const"
|
|
;
|
|
ConsId = typeclass_info_const(_),
|
|
TypeStr = "typeclass_info_const"
|
|
;
|
|
ConsId = ground_term_const(_, _),
|
|
TypeStr = "ground_term_const"
|
|
;
|
|
( ConsId = some_int_const(_)
|
|
; ConsId = float_const(_)
|
|
; ConsId = char_const(_)
|
|
; ConsId = string_const(_)
|
|
; ConsId = impl_defined_const(_)
|
|
; ConsId = type_ctor_info_const(_, _, _)
|
|
; ConsId = base_typeclass_info_const(_, _, _, _)
|
|
; ConsId = tabling_info_const(_)
|
|
; ConsId = table_io_entry_desc(_)
|
|
; ConsId = deep_profiling_proc_layout(_)
|
|
),
|
|
unexpected($pred, "unexpected cons_id")
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module ml_backend.ml_global_data.
|
|
%---------------------------------------------------------------------------%
|