Files
mercury/compiler/ml_global_data.m
2026-01-15 05:52:08 +11:00

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.
%---------------------------------------------------------------------------%