mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 01:13:30 +00:00
1918 lines
79 KiB
Mathematica
1918 lines
79 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2001-2012 The University of Melbourne.
|
|
% Copyright (C) 2014-2024 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: rtti_to_mlds.m.
|
|
% Authors: fjh, zs.
|
|
%
|
|
% This module defines routines to convert from the back-end-independent
|
|
% RTTI data structures into MLDS definitions.
|
|
% The RTTI data structures are used for static data that is used
|
|
% for handling RTTI, polymorphism, and typeclasses.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module ml_backend.rtti_to_mlds.
|
|
:- interface.
|
|
|
|
:- import_module backend_libs.
|
|
:- import_module backend_libs.rtti.
|
|
:- import_module hlds.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module ml_backend.ml_global_data.
|
|
:- import_module ml_backend.mlds.
|
|
|
|
:- import_module list.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Add the MLDS definitions for the given rtti_data(s) to the
|
|
% ml_global_data structure.
|
|
%
|
|
:- pred add_rtti_datas_to_mlds(module_info::in, mlds_target_lang::in,
|
|
list(rtti_data)::in, ml_global_data::in, ml_global_data::out) is det.
|
|
:- pred add_rtti_data_to_mlds(module_info::in, mlds_target_lang::in,
|
|
rtti_data::in, ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
% Given a list of MLDS RTTI data definitions, return the definitions
|
|
% as a list of SCCs, such that if X appears in the initialiser for Y,
|
|
% but not vice versa, then X appears in an earlier SCC in the list
|
|
% than the SCC containing Y. If X appears in the initialiser for Y
|
|
% *and* vice versa, then X and Y will be in the same SCC, and their
|
|
% relative order is not guaranteed. This may, or may not, be a problem,
|
|
% but at least the existence of a non-singleton SCC points out
|
|
% the possible issue.
|
|
%
|
|
:- func order_mlds_rtti_defns_into_sccs(list(mlds_global_var_defn)) =
|
|
list(list(mlds_global_var_defn)).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.type_ctor_info.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module hlds.hlds_rtti.
|
|
:- import_module libs.
|
|
:- import_module libs.globals.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.builtin_modules.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module ml_backend.ml_args_util.
|
|
:- import_module ml_backend.ml_closure_gen.
|
|
:- import_module ml_backend.ml_code_util.
|
|
:- import_module ml_backend.ml_gen_info.
|
|
:- import_module ml_backend.ml_util.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module bool.
|
|
:- import_module counter.
|
|
:- import_module digraph.
|
|
:- import_module int16.
|
|
:- import_module int32.
|
|
:- import_module int8.
|
|
:- import_module map.
|
|
:- import_module maybe.
|
|
:- import_module pair.
|
|
:- import_module require.
|
|
:- import_module set.
|
|
:- import_module term_context.
|
|
:- import_module uint.
|
|
:- import_module uint16.
|
|
:- import_module uint32.
|
|
:- import_module uint8.
|
|
:- import_module univ.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
add_rtti_datas_to_mlds(ModuleInfo, Target, RttiDatas, !GlobalData) :-
|
|
list.foldl(add_rtti_data_to_mlds(ModuleInfo, Target),
|
|
RttiDatas, !GlobalData).
|
|
|
|
add_rtti_data_to_mlds(ModuleInfo, Target, RttiData, !GlobalData) :-
|
|
( if RttiData = rtti_data_pseudo_type_info(type_var(_)) then
|
|
% These just get represented as integers, so we don't need to define
|
|
% a structure for them; which is why rtti_data_to_id/3 does not
|
|
% handle this case.
|
|
true
|
|
else
|
|
gen_init_rtti_data_defn(ModuleInfo, Target, RttiData, !GlobalData)
|
|
).
|
|
|
|
:- pred rtti_name_and_init_to_defn(rtti_type_ctor::in, ctor_rtti_name::in,
|
|
mlds_initializer::in, ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer, !GlobalData) :-
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName),
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData).
|
|
|
|
:- pred rtti_id_and_init_to_defn(rtti_id::in, mlds_initializer::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData) :-
|
|
Name = gvn_rtti_var(RttiId),
|
|
rtti_entity_name_and_init_to_defn(Name, RttiId, Initializer, !GlobalData).
|
|
|
|
:- pred rtti_entity_name_and_init_to_defn(mlds_global_var_name::in,
|
|
rtti_id::in, mlds_initializer::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
rtti_entity_name_and_init_to_defn(Name, RttiId, Initializer, !GlobalData) :-
|
|
% Generate the context.
|
|
%
|
|
% XXX The rtti_data ought to include a prog_context (the context of the
|
|
% corresponding type or instance definition).
|
|
Context = dummy_context,
|
|
|
|
% Generate the declaration flags.
|
|
Exported = rtti_id_is_exported(RttiId),
|
|
(
|
|
Exported = no,
|
|
Access = gvar_acc_module_only
|
|
;
|
|
Exported = yes,
|
|
Access = gvar_acc_whole_program
|
|
),
|
|
Flags = rtti_data_decl_flags(Access),
|
|
|
|
% The GC never needs to trace these definitions, because they are static
|
|
% constants, and can point only to other static constants, not to the heap.
|
|
GCStatement = gc_no_stmt,
|
|
|
|
% Generate the declaration body, i.e. the type and the initializer.
|
|
MLDS_Type = mlds_rtti_type(item_type(RttiId)),
|
|
DataDefn = mlds_global_var_defn(Name, Context, Flags, MLDS_Type,
|
|
Initializer, GCStatement),
|
|
|
|
ml_global_data_add_rtti_defn(DataDefn, !GlobalData).
|
|
|
|
% Return the declaration flags appropriate for an rtti_data.
|
|
%
|
|
:- func rtti_data_decl_flags(global_var_access) = mlds_global_var_decl_flags.
|
|
|
|
rtti_data_decl_flags(Access) = mlds_global_var_decl_flags(Access, const).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Return an MLDS initializer for the given RTTI definition
|
|
% occurring in the given module.
|
|
%
|
|
:- pred gen_init_rtti_data_defn(module_info::in, mlds_target_lang::in,
|
|
rtti_data::in, ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_init_rtti_data_defn(ModuleInfo, Target, RttiData, !GlobalData) :-
|
|
rtti_data_to_id(RttiData, RttiId),
|
|
Name = gvn_rtti_var(RttiId),
|
|
(
|
|
RttiData = rtti_data_base_typeclass_info(_InstanceModule, _ClassId,
|
|
_InstanceStr, BaseTypeClassInfo),
|
|
BaseTypeClassInfo = base_typeclass_info(N1, N2, N3, N4, N5, Methods),
|
|
NumExtra = BaseTypeClassInfo ^ num_extra,
|
|
list.map_foldl(gen_init_method(ModuleInfo, Target, NumExtra),
|
|
Methods, MethodInitializers, !GlobalData),
|
|
Initializer = init_array([
|
|
gen_init_boxed_int(N1),
|
|
gen_init_boxed_int(N2),
|
|
gen_init_boxed_int(N3),
|
|
gen_init_boxed_int(N4),
|
|
gen_init_boxed_int(N5)
|
|
| MethodInitializers
|
|
]),
|
|
rtti_entity_name_and_init_to_defn(Name, RttiId, Initializer,
|
|
!GlobalData)
|
|
;
|
|
RttiData = rtti_data_type_info(TypeInfo),
|
|
gen_type_info_defn(ModuleInfo, Target, TypeInfo, Name,
|
|
RttiId, !GlobalData)
|
|
;
|
|
RttiData = rtti_data_pseudo_type_info(PseudoTypeInfo),
|
|
gen_pseudo_type_info_defn(ModuleInfo, Target, PseudoTypeInfo, Name,
|
|
RttiId, !GlobalData)
|
|
;
|
|
RttiData = rtti_data_type_class_decl(TCDecl),
|
|
gen_type_class_decl_defn(ModuleInfo, Target, TCDecl, Name,
|
|
RttiId, !GlobalData)
|
|
;
|
|
RttiData = rtti_data_type_class_instance(Instance),
|
|
gen_type_class_instance_defn(ModuleInfo, Target, Instance, Name,
|
|
RttiId, !GlobalData)
|
|
;
|
|
RttiData = rtti_data_type_ctor_info(TypeCtorData),
|
|
TypeCtorData = type_ctor_data(Version, TypeModule, TypeName,
|
|
TypeArity, UnifyUniv, CompareUniv, Flags, TypeCtorDetails),
|
|
RttiTypeCtor = rtti_type_ctor(TypeModule, TypeName, TypeArity),
|
|
TypeModuleName = sym_name_to_string(TypeModule),
|
|
MaybeNumPtags = type_ctor_details_num_ptags(TypeCtorDetails),
|
|
(
|
|
MaybeNumPtags = yes(NumPtags),
|
|
NumPtagsEncoding = int8.det_from_int(NumPtags)
|
|
;
|
|
MaybeNumPtags = no,
|
|
NumPtagsEncoding = -1i8
|
|
),
|
|
MaybeNumFunctors = type_ctor_details_num_functors(TypeCtorDetails),
|
|
(
|
|
MaybeNumFunctors = yes(NumFunctors),
|
|
NumFunctorsEncoding = NumFunctors
|
|
;
|
|
MaybeNumFunctors = no,
|
|
NumFunctorsEncoding = -1
|
|
),
|
|
FunctorsRttiId = ctor_rtti_id(RttiTypeCtor, type_ctor_type_functors),
|
|
LayoutRttiId = ctor_rtti_id(RttiTypeCtor, type_ctor_type_layout),
|
|
|
|
gen_functors_layout_info(ModuleInfo, Target, RttiTypeCtor,
|
|
TypeCtorDetails, FunctorsInfo, LayoutInfo, NumberMapInfo,
|
|
BaseTypeCtorInitializer, !GlobalData),
|
|
|
|
% Note that gen_init_special_pred will by necessity add an extra
|
|
% level of indirection to calling the special preds. However, the
|
|
% backend compiler should be smart enough to ensure that this is
|
|
% inlined away.
|
|
gen_init_special_pred(ModuleInfo, Target,
|
|
UnifyUniv, UnifyInitializer, !GlobalData),
|
|
gen_init_special_pred(ModuleInfo, Target,
|
|
CompareUniv, CompareInitializer, !GlobalData),
|
|
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
% MR_type_ctor_arity -- XXX MAKE_FIELD_UNSIGNED
|
|
gen_init_int(uint16.to_int(TypeArity)),
|
|
% MR_type_ctor_version
|
|
gen_init_uint8(Version),
|
|
% MR_type_ctor_num_ptags
|
|
gen_init_int8(NumPtagsEncoding),
|
|
% MR_type_ctor_rep_CAST_ME
|
|
gen_init_type_ctor_rep(TypeCtorData),
|
|
% MR_type_ctor_unify_pred
|
|
UnifyInitializer,
|
|
% MR_type_ctor_compare_pred
|
|
CompareInitializer,
|
|
% MR_type_ctor_module_name
|
|
gen_init_string(TypeModuleName),
|
|
% MR_type_ctor_name
|
|
gen_init_string(TypeName),
|
|
% In the C back-end, these two "structs" are actually unions.
|
|
% We need to use `init_struct' here so that the initializers
|
|
% get enclosed in curly braces.
|
|
% MR_type_ctor_functors
|
|
init_struct(mlds_rtti_type(item_type(FunctorsRttiId)), [
|
|
FunctorsInfo
|
|
]),
|
|
% MR_type_ctor_layout
|
|
init_struct(mlds_rtti_type(item_type(LayoutRttiId)), [
|
|
LayoutInfo
|
|
]),
|
|
% MR_type_ctor_num_functors
|
|
gen_init_int(NumFunctorsEncoding),
|
|
% MR_type_ctor_flags
|
|
gen_init_uint16(encode_type_ctor_flags(Flags)),
|
|
% MR_type_ctor_functor_number_map
|
|
NumberMapInfo,
|
|
% MR_type_ctor_base
|
|
BaseTypeCtorInitializer
|
|
|
|
% These two are commented out while the corresponding fields of the
|
|
% MR_TypeCtorInfo_Struct type are commented out.
|
|
% gen_init_maybe(gen_init_rtti_name(RttiTypeCtor), MaybeHashCons),
|
|
% XXX this may need to change to call
|
|
% gen_init_special_pred, if this is re-enabled.
|
|
% gen_init_proc_id_from_univ(ModuleInfo, PrettyprinterProc)
|
|
]),
|
|
rtti_entity_name_and_init_to_defn(Name, RttiId, Initializer,
|
|
!GlobalData)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred gen_type_class_decl_defn(module_info::in, mlds_target_lang::in,
|
|
tc_decl::in, mlds_global_var_name::in, rtti_id::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_type_class_decl_defn(ModuleInfo, Target, TCDecl, Name, RttiId,
|
|
!GlobalData) :-
|
|
TCDecl = tc_decl(TCId, Version, Supers),
|
|
TCId = tc_id(TCName, TVarNames, MethodIds),
|
|
TCName = tc_name(ModuleSymName, ClassName, Arity),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
TVarNamesRttiId = tc_rtti_id(TCName, type_class_id_var_names),
|
|
(
|
|
TVarNames = [],
|
|
TVarNamesInitType = mlds_rtti_type(item_type(TVarNamesRttiId)),
|
|
TVarNamesInitializer = gen_init_null_pointer(TVarNamesInitType)
|
|
;
|
|
TVarNames = [_ | _],
|
|
gen_tc_id_var_names(TVarNamesRttiId, TVarNames, !GlobalData),
|
|
TVarNamesInitializer = gen_init_rtti_id(ModuleName, TVarNamesRttiId)
|
|
),
|
|
MethodIdsRttiId = tc_rtti_id(TCName, type_class_id_method_ids),
|
|
(
|
|
MethodIds = [],
|
|
MethodIdsInitType = mlds_rtti_type(item_type(MethodIdsRttiId)),
|
|
MethodIdsInitializer = gen_init_null_pointer(MethodIdsInitType)
|
|
;
|
|
MethodIds = [_ | _],
|
|
gen_tc_id_method_ids(MethodIdsRttiId, TCName, MethodIds, !GlobalData),
|
|
MethodIdsInitializer = gen_init_rtti_id(ModuleName, MethodIdsRttiId)
|
|
),
|
|
TCIdRttiId = tc_rtti_id(TCName, type_class_id),
|
|
ModuleSymNameStr = sym_name_to_string(ModuleSymName),
|
|
list.length(TVarNames, NumTVars),
|
|
list.length(MethodIds, NumMethods),
|
|
TCIdInitializer = init_struct(mlds_rtti_type(item_type(TCIdRttiId)), [
|
|
gen_init_string(ModuleSymNameStr),
|
|
gen_init_string(ClassName),
|
|
gen_init_int(Arity),
|
|
gen_init_int(NumTVars),
|
|
gen_init_int(NumMethods),
|
|
TVarNamesInitializer,
|
|
MethodIdsInitializer
|
|
]),
|
|
rtti_id_and_init_to_defn(TCIdRttiId, TCIdInitializer, !GlobalData),
|
|
(
|
|
Supers = []
|
|
;
|
|
Supers = [_ | _],
|
|
list.map_foldl2(
|
|
gen_tc_constraint(ModuleInfo, Target, make_decl_super_id(TCName)),
|
|
Supers, SuperRttiIds, counter.init(1), _, !GlobalData),
|
|
SuperArrayRttiName = type_class_decl_supers,
|
|
SuperArrayRttiId = tc_rtti_id(TCName, SuperArrayRttiName),
|
|
ElementType = mlds_rtti_type(element_type(SuperArrayRttiId)),
|
|
SuperArrayInitializer = gen_init_array(
|
|
gen_init_cast_rtti_id(ElementType, ModuleName), SuperRttiIds),
|
|
rtti_id_and_init_to_defn(SuperArrayRttiId, SuperArrayInitializer,
|
|
!GlobalData)
|
|
),
|
|
% XXX Is MethodIdsRttiId the right thing to take the type from?
|
|
SupersInitType = mlds_rtti_type(item_type(MethodIdsRttiId)),
|
|
SupersInitializer = gen_init_null_pointer(SupersInitType),
|
|
list.length(Supers, NumSupers),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
gen_init_rtti_id(ModuleName, TCIdRttiId),
|
|
gen_init_int(Version),
|
|
gen_init_int(NumSupers),
|
|
SupersInitializer
|
|
]),
|
|
rtti_entity_name_and_init_to_defn(Name, RttiId, Initializer, !GlobalData).
|
|
|
|
:- pred make_decl_super_id(tc_name::in, int::in, int::in, rtti_id::out) is det.
|
|
|
|
make_decl_super_id(TCName, TCNum, Arity, RttiId) :-
|
|
TCRttiName = type_class_decl_super(TCNum, Arity),
|
|
RttiId = tc_rtti_id(TCName, TCRttiName).
|
|
|
|
:- pred gen_tc_id_var_names(rtti_id::in, list(string)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_tc_id_var_names(RttiId, Names, !GlobalData) :-
|
|
Initializer = gen_init_array(gen_init_string, Names),
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData).
|
|
|
|
:- pred gen_tc_id_method_ids(rtti_id::in, tc_name::in, list(tc_method_id)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_tc_id_method_ids(RttiId, TCName, MethodIds, !GlobalData) :-
|
|
Initializer = gen_init_array(gen_tc_id_method_id(TCName), MethodIds),
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData).
|
|
|
|
:- func gen_tc_id_method_id(tc_name, tc_method_id) = mlds_initializer.
|
|
|
|
gen_tc_id_method_id(TCName, MethodId) = Initializer :-
|
|
MethodId =
|
|
tc_method_id(MethodName, pred_form_arity(MethodArity), PredOrFunc),
|
|
RttiId = tc_rtti_id(TCName, type_class_id_method_ids),
|
|
Initializer = init_struct(mlds_rtti_type(element_type(RttiId)), [
|
|
gen_init_string(MethodName),
|
|
gen_init_int(MethodArity),
|
|
gen_init_pred_or_func(PredOrFunc)
|
|
]).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred gen_type_class_instance_defn(module_info::in, mlds_target_lang::in,
|
|
tc_instance::in, mlds_global_var_name::in, rtti_id::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_type_class_instance_defn(ModuleInfo, Target, Instance, Name, RttiId,
|
|
!GlobalData) :-
|
|
Instance = tc_instance(TCName, Types, NumTypeVars,
|
|
InstanceConstraints, _Methods),
|
|
TCDeclRttiId = tc_rtti_id(TCName, type_class_decl),
|
|
list.length(InstanceConstraints, NumInstanceConstraints),
|
|
InstanceTypesTCRttiName = type_class_instance_tc_type_vector(Types),
|
|
InstanceTypesRttiId = tc_rtti_id(TCName, InstanceTypesTCRttiName),
|
|
InstanceConstrsTCRttiName = type_class_instance_constraints(Types),
|
|
InstanceConstrsRttiId = tc_rtti_id(TCName, InstanceConstrsTCRttiName),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
|
|
TypeRttiDatas = list.map(maybe_pseudo_type_info_to_rtti_data, Types),
|
|
gen_pseudo_type_info_array(ModuleInfo, Target, TypeRttiDatas,
|
|
TypesInitializer, !GlobalData),
|
|
rtti_id_and_init_to_defn(InstanceTypesRttiId, TypesInitializer,
|
|
!GlobalData),
|
|
|
|
list.map_foldl2(
|
|
gen_tc_constraint(ModuleInfo, Target,
|
|
make_instance_constr_id(TCName, Types)),
|
|
InstanceConstraints, TCConstrIds, counter.init(1), _, !GlobalData),
|
|
ElementType = mlds_rtti_type(element_type(InstanceConstrsRttiId)),
|
|
InstanceConstrsInitializer = gen_init_array(
|
|
gen_init_cast_rtti_id(ElementType, ModuleName), TCConstrIds),
|
|
rtti_id_and_init_to_defn(InstanceConstrsRttiId, InstanceConstrsInitializer,
|
|
!GlobalData),
|
|
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
gen_init_rtti_id(ModuleName, TCDeclRttiId),
|
|
gen_init_int(NumTypeVars),
|
|
gen_init_int(NumInstanceConstraints),
|
|
gen_init_rtti_id(ModuleName, InstanceTypesRttiId),
|
|
gen_init_rtti_id(ModuleName, InstanceConstrsRttiId)
|
|
]),
|
|
rtti_entity_name_and_init_to_defn(Name, RttiId, Initializer, !GlobalData).
|
|
|
|
:- pred make_instance_constr_id(tc_name::in, list(tc_type)::in,
|
|
int::in, int::in, rtti_id::out) is det.
|
|
|
|
make_instance_constr_id(TCName, Types, TCNum, Arity, RttiId) :-
|
|
RttiName = type_class_instance_constraint(Types, TCNum, Arity),
|
|
RttiId = tc_rtti_id(TCName, RttiName).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred gen_type_info_defn(module_info::in, mlds_target_lang::in,
|
|
rtti_type_info::in, mlds_global_var_name::in, rtti_id::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_type_info_defn(ModuleInfo, Target, RttiTypeInfo, Name, RttiId,
|
|
!GlobalData) :-
|
|
(
|
|
RttiTypeInfo = plain_arity_zero_type_info(_),
|
|
unexpected($pred, "plain_arity_zero_type_info")
|
|
;
|
|
RttiTypeInfo = plain_type_info(RttiTypeCtor, ArgTypes),
|
|
ml_global_data_get_pdup_rval_type_map(!.GlobalData, PDupRvalTypeMap),
|
|
( if map.search(PDupRvalTypeMap, RttiId, _) then
|
|
% We have already generated the required global data structures.
|
|
true
|
|
else
|
|
ArgRttiDatas = list.map(type_info_to_rtti_data, ArgTypes),
|
|
RealRttiDatas = list.filter(real_rtti_data, ArgRttiDatas),
|
|
list.foldl(add_rtti_data_to_mlds(ModuleInfo, Target),
|
|
RealRttiDatas, !GlobalData),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_type_ctor_info),
|
|
gen_init_cast_rtti_datas_array(mlds_type_info_type,
|
|
ModuleName, ArgRttiDatas)
|
|
]),
|
|
rtti_entity_name_and_init_to_defn(Name, RttiId, Initializer,
|
|
!GlobalData),
|
|
|
|
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
|
|
Rval = ml_const(mlconst_data_addr_rtti(MLDS_ModuleName, RttiId)),
|
|
Type = mlds_rtti_type(item_type(RttiId)),
|
|
RvalType = ml_rval_and_type(Rval, Type),
|
|
|
|
ml_global_data_add_pdup_rtti_id(RttiId, RvalType, !GlobalData)
|
|
)
|
|
;
|
|
RttiTypeInfo = var_arity_type_info(VarArityId, ArgTypes),
|
|
ml_global_data_get_pdup_rval_type_map(!.GlobalData, PDupRvalTypeMap),
|
|
( if map.search(PDupRvalTypeMap, RttiId, _) then
|
|
% We have already generated the required global data structures.
|
|
true
|
|
else
|
|
ArgRttiDatas = list.map(type_info_to_rtti_data, ArgTypes),
|
|
RealRttiDatas = list.filter(real_rtti_data, ArgRttiDatas),
|
|
list.foldl(add_rtti_data_to_mlds(ModuleInfo, Target),
|
|
RealRttiDatas, !GlobalData),
|
|
RttiTypeCtor = var_arity_id_to_rtti_type_ctor(VarArityId),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
|
|
InitRttiName = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_type_ctor_info),
|
|
InitCastRttiDatasArray = gen_init_cast_rtti_datas_array(
|
|
mlds_type_info_type, ModuleName, ArgRttiDatas),
|
|
(
|
|
Target = ml_target_java,
|
|
% For Java we need to omit the arity argument as the
|
|
% TypeInfo_Struct class doesn't have a constructor that
|
|
% supports it -- see java/runtime/TypeInfo_Struct.java for
|
|
% details.
|
|
%
|
|
% NOTE: this needs to be kept consistent with
|
|
%
|
|
% polymorphism.polymorphism_construct_type_info/10
|
|
% java/runtime/TypeInfo_Struct.java
|
|
%
|
|
% as well as the code for handling pseudo type-infos below.
|
|
%
|
|
InitializerArgs = [InitRttiName, InitCastRttiDatasArray]
|
|
;
|
|
( Target = ml_target_c
|
|
; Target = ml_target_csharp
|
|
),
|
|
InitializerArgs = [
|
|
InitRttiName,
|
|
gen_init_int(list.length(ArgTypes)),
|
|
InitCastRttiDatasArray]
|
|
),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)),
|
|
InitializerArgs),
|
|
rtti_entity_name_and_init_to_defn(Name, RttiId, Initializer,
|
|
!GlobalData),
|
|
|
|
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
|
|
Rval = ml_const(mlconst_data_addr_rtti(MLDS_ModuleName, RttiId)),
|
|
Type = mlds_rtti_type(item_type(RttiId)),
|
|
RvalType = ml_rval_and_type(Rval, Type),
|
|
|
|
ml_global_data_add_pdup_rtti_id(RttiId, RvalType, !GlobalData)
|
|
)
|
|
).
|
|
|
|
:- pred gen_pseudo_type_info_defn(module_info::in, mlds_target_lang::in,
|
|
rtti_pseudo_type_info::in, mlds_global_var_name::in, rtti_id::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_pseudo_type_info_defn(ModuleInfo, Target, RttiPseudoTypeInfo, Name, RttiId,
|
|
!GlobalData) :-
|
|
(
|
|
RttiPseudoTypeInfo = plain_arity_zero_pseudo_type_info(_),
|
|
unexpected($pred, "plain_arity_zero_pseudo_type_info")
|
|
;
|
|
RttiPseudoTypeInfo = plain_pseudo_type_info(RttiTypeCtor, ArgTypes),
|
|
ml_global_data_get_pdup_rval_type_map(!.GlobalData, PDupRvalTypeMap),
|
|
( if map.search(PDupRvalTypeMap, RttiId, _) then
|
|
% We have already generated the required global data structures.
|
|
true
|
|
else
|
|
ArgRttiDatas = list.map(maybe_pseudo_type_info_to_rtti_data,
|
|
ArgTypes),
|
|
RealRttiDatas = list.filter(real_rtti_data, ArgRttiDatas),
|
|
list.foldl(add_rtti_data_to_mlds(ModuleInfo, Target),
|
|
RealRttiDatas, !GlobalData),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_type_ctor_info),
|
|
gen_init_cast_rtti_datas_array(mlds_pseudo_type_info_type,
|
|
ModuleName, ArgRttiDatas)
|
|
]),
|
|
rtti_entity_name_and_init_to_defn(Name, RttiId, Initializer,
|
|
!GlobalData),
|
|
|
|
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
|
|
Rval = ml_const(mlconst_data_addr_rtti(MLDS_ModuleName, RttiId)),
|
|
Type = mlds_rtti_type(item_type(RttiId)),
|
|
RvalType = ml_rval_and_type(Rval, Type),
|
|
|
|
ml_global_data_add_pdup_rtti_id(RttiId, RvalType, !GlobalData)
|
|
)
|
|
;
|
|
RttiPseudoTypeInfo = var_arity_pseudo_type_info(VarArityId, ArgTypes),
|
|
ml_global_data_get_pdup_rval_type_map(!.GlobalData, PDupRvalTypeMap),
|
|
( if map.search(PDupRvalTypeMap, RttiId, _) then
|
|
% We have already generated the required global data structures.
|
|
true
|
|
else
|
|
ArgRttiDatas = list.map(maybe_pseudo_type_info_to_rtti_data,
|
|
ArgTypes),
|
|
RealRttiDatas = list.filter(real_rtti_data, ArgRttiDatas),
|
|
list.foldl(add_rtti_data_to_mlds(ModuleInfo, Target),
|
|
RealRttiDatas, !GlobalData),
|
|
RttiTypeCtor = var_arity_id_to_rtti_type_ctor(VarArityId),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
module_info_get_globals(ModuleInfo, Globals),
|
|
globals.get_target(Globals, TargetLang),
|
|
|
|
InitRttiName = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_type_ctor_info),
|
|
InitCastRttiDatasArray = gen_init_cast_rtti_datas_array(
|
|
mlds_pseudo_type_info_type, ModuleName, ArgRttiDatas),
|
|
( if TargetLang = target_java then
|
|
% For Java we need to omit the arity argument as the
|
|
% TypeInfo_Struct class doesn't have a constructor that
|
|
% supports it. The TypeInfo_Struct class is used to represent
|
|
% pseudo type-infos with the Java backend.
|
|
% (See java/runtime/PseudoTypeInfo.java for details.)
|
|
InitializerArgs = [InitRttiName, InitCastRttiDatasArray]
|
|
else
|
|
InitializerArgs = [
|
|
InitRttiName,
|
|
gen_init_int(list.length(ArgTypes)),
|
|
InitCastRttiDatasArray
|
|
]
|
|
),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)),
|
|
InitializerArgs),
|
|
rtti_entity_name_and_init_to_defn(Name, RttiId, Initializer,
|
|
!GlobalData),
|
|
|
|
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
|
|
Rval = ml_const(mlconst_data_addr_rtti(MLDS_ModuleName, RttiId)),
|
|
Type = mlds_rtti_type(item_type(RttiId)),
|
|
RvalType = ml_rval_and_type(Rval, Type),
|
|
|
|
ml_global_data_add_pdup_rtti_id(RttiId, RvalType, !GlobalData)
|
|
)
|
|
;
|
|
RttiPseudoTypeInfo = type_var(_),
|
|
unexpected($pred, "type_var")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred gen_functors_layout_info(module_info::in, mlds_target_lang::in,
|
|
rtti_type_ctor::in, type_ctor_details::in,
|
|
mlds_initializer::out, mlds_initializer::out, mlds_initializer::out,
|
|
mlds_initializer::out, ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_functors_layout_info(ModuleInfo, Target, RttiTypeCtor, TypeCtorDetails,
|
|
FunctorInitializer, LayoutInitializer, NumberMapInitializer,
|
|
BaseTypeCtorInitializer, !GlobalData) :-
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
(
|
|
TypeCtorDetails = tcd_enum(_, _IsDummy, EnumFunctors,
|
|
EnumByOrd, EnumByName, FunctorNumberMap, MaybeBaseTypeCtor),
|
|
list.foldl(gen_enum_functor_desc(ModuleInfo, RttiTypeCtor),
|
|
EnumFunctors, !GlobalData),
|
|
gen_enum_ordinal_ordered_table(ModuleInfo, RttiTypeCtor,
|
|
EnumByOrd, !GlobalData),
|
|
gen_enum_name_ordered_table(ModuleInfo, RttiTypeCtor,
|
|
EnumByName, !GlobalData),
|
|
gen_functor_number_map(RttiTypeCtor, FunctorNumberMap, !GlobalData),
|
|
LayoutInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_enum_ordinal_ordered_table),
|
|
FunctorInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_enum_name_ordered_table),
|
|
NumberMapInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_functor_number_map),
|
|
BaseTypeCtorInitializer = gen_init_base_type_ctor(ModuleName, Target,
|
|
MaybeBaseTypeCtor)
|
|
;
|
|
TypeCtorDetails = tcd_foreign_enum(ForeignEnumLang, _,
|
|
ForeignEnumFunctors, ForeignEnumByOrdinal, ForeignEnumByName,
|
|
FunctorNumberMap),
|
|
list.foldl(
|
|
gen_foreign_enum_functor_desc(ModuleInfo, ForeignEnumLang,
|
|
RttiTypeCtor),
|
|
ForeignEnumFunctors, !GlobalData),
|
|
gen_foreign_enum_ordinal_ordered_table(ModuleInfo, RttiTypeCtor,
|
|
ForeignEnumByOrdinal, !GlobalData),
|
|
gen_foreign_enum_name_ordered_table(ModuleInfo, RttiTypeCtor,
|
|
ForeignEnumByName, !GlobalData),
|
|
gen_functor_number_map(RttiTypeCtor, FunctorNumberMap, !GlobalData),
|
|
LayoutInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_foreign_enum_ordinal_ordered_table),
|
|
FunctorInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_foreign_enum_name_ordered_table),
|
|
NumberMapInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_functor_number_map),
|
|
BaseTypeCtorInitializer = gen_init_base_type_ctor(ModuleName, Target,
|
|
no)
|
|
;
|
|
TypeCtorDetails = tcd_du(_, DuFunctors, DuByPtag, DuByName,
|
|
FunctorNumberMap, MaybeBaseTypeCtor),
|
|
list.foldl(gen_du_functor_desc(ModuleInfo, Target, RttiTypeCtor),
|
|
DuFunctors, !GlobalData),
|
|
gen_du_ptag_ordered_table(ModuleInfo, RttiTypeCtor,
|
|
DuByPtag, !GlobalData),
|
|
gen_du_name_ordered_table(ModuleInfo, RttiTypeCtor,
|
|
DuByName, !GlobalData),
|
|
gen_functor_number_map(RttiTypeCtor, FunctorNumberMap, !GlobalData),
|
|
LayoutInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_du_ptag_ordered_table),
|
|
FunctorInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_du_name_ordered_table),
|
|
NumberMapInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_functor_number_map),
|
|
BaseTypeCtorInitializer = gen_init_base_type_ctor(ModuleName, Target,
|
|
MaybeBaseTypeCtor)
|
|
;
|
|
TypeCtorDetails = tcd_notag(_, NotagFunctor, MaybeBaseTypeCtor),
|
|
gen_functor_number_map(RttiTypeCtor, [0u32], !GlobalData),
|
|
LayoutInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_notag_functor_desc),
|
|
FunctorInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_notag_functor_desc),
|
|
NumberMapInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_functor_number_map),
|
|
gen_notag_functor_desc(ModuleInfo, Target, RttiTypeCtor, NotagFunctor,
|
|
!GlobalData),
|
|
BaseTypeCtorInitializer = gen_init_base_type_ctor(ModuleName, Target,
|
|
MaybeBaseTypeCtor)
|
|
;
|
|
TypeCtorDetails = tcd_eqv(EqvType),
|
|
TypeRttiData = maybe_pseudo_type_info_to_rtti_data(EqvType),
|
|
gen_pseudo_type_info(ModuleInfo, Target, TypeRttiData,
|
|
LayoutInitializer, !GlobalData),
|
|
% The type is a lie, but a safe one.
|
|
FunctorInitializer = gen_init_null_pointer(mlds_generic_type),
|
|
NumberMapInitializer = gen_init_null_pointer(mlds_generic_type),
|
|
BaseTypeCtorInitializer = gen_init_base_type_ctor(ModuleName, Target,
|
|
no)
|
|
;
|
|
( TypeCtorDetails = tcd_builtin(_)
|
|
; TypeCtorDetails = tcd_impl_artifact(_)
|
|
; TypeCtorDetails = tcd_foreign(_)
|
|
),
|
|
LayoutInitializer = gen_init_null_pointer(mlds_generic_type),
|
|
FunctorInitializer = gen_init_null_pointer(mlds_generic_type),
|
|
NumberMapInitializer = gen_init_null_pointer(mlds_generic_type),
|
|
BaseTypeCtorInitializer = gen_init_base_type_ctor(ModuleName, Target,
|
|
no)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred gen_enum_functor_desc(module_info::in, rtti_type_ctor::in,
|
|
enum_functor::in, ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_enum_functor_desc(_ModuleInfo, RttiTypeCtor, EnumFunctor, !GlobalData) :-
|
|
EnumFunctor = enum_functor(FunctorName, Ordinal, enum_value(Value)),
|
|
RttiName = type_ctor_enum_functor_desc(Ordinal),
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
% MR_enum_functor_name
|
|
gen_init_string(FunctorName),
|
|
% MR_enum_functor_value -- XXX MAKE_FIELD_UNSIGNED
|
|
gen_init_int32(int32.cast_from_uint32(Value))
|
|
]),
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData).
|
|
|
|
:- pred gen_foreign_enum_functor_desc(module_info::in, foreign_language::in,
|
|
rtti_type_ctor::in, foreign_enum_functor::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_foreign_enum_functor_desc(_ModuleInfo, Lang, RttiTypeCtor,
|
|
ForeignEnumFunctor, !GlobalData) :-
|
|
ForeignEnumFunctor = foreign_enum_functor(FunctorName, Ordinal, Value),
|
|
RttiName = type_ctor_foreign_enum_functor_desc(Ordinal),
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
% MR_foreign_enum_functor_name
|
|
gen_init_string(FunctorName),
|
|
% MR_foreign_enum_functor_ordinal -- XXX MAKE_FIELD_UNSIGNED
|
|
gen_init_int32(int32.cast_from_uint32(Ordinal)),
|
|
% MR_foreign_enum_functor_value
|
|
gen_init_foreign(Lang, Value)
|
|
]),
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData).
|
|
|
|
:- pred gen_notag_functor_desc(module_info::in, mlds_target_lang::in,
|
|
rtti_type_ctor::in, notag_functor::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_notag_functor_desc(ModuleInfo, Target, RttiTypeCtor, NotagFunctorDesc,
|
|
!GlobalData) :-
|
|
NotagFunctorDesc = notag_functor(FunctorName, ArgType, MaybeArgName,
|
|
FunctorSubtypeInfo),
|
|
ArgTypeRttiData = maybe_pseudo_type_info_to_rtti_data(ArgType),
|
|
gen_pseudo_type_info(ModuleInfo, Target, ArgTypeRttiData, PTIInitializer,
|
|
!GlobalData),
|
|
RttiName = type_ctor_notag_functor_desc,
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
% MR_notag_functor_name
|
|
gen_init_string(FunctorName),
|
|
% MR_notag_functor_arg_type
|
|
PTIInitializer,
|
|
% MR_notag_functor_arg_name
|
|
gen_init_maybe(mlds_builtin_type_string, gen_init_string,
|
|
MaybeArgName),
|
|
% MR_notag_functor_subtype
|
|
gen_init_functor_subtype_info(FunctorSubtypeInfo)
|
|
]),
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData).
|
|
|
|
:- pred gen_du_functor_desc(module_info::in, mlds_target_lang::in,
|
|
rtti_type_ctor::in, du_functor::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_du_functor_desc(ModuleInfo, Target, RttiTypeCtor, DuFunctor,
|
|
!GlobalData) :-
|
|
DuFunctor = du_functor(FunctorName, Arity, Ordinal, Rep, ArgInfos,
|
|
MaybeExistInfo, FunctorSubtypeInfo),
|
|
ArgTypes = list.map(du_arg_info_type, ArgInfos),
|
|
MaybeArgNames = list.map(du_arg_info_name, ArgInfos),
|
|
HaveArgNames = (if list.member(yes(_), MaybeArgNames) then yes else no),
|
|
ContainsVarBitVector = compute_contains_var_bit_vector(ArgTypes),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
(
|
|
ArgInfos = [_ | _],
|
|
gen_field_types(ModuleInfo, Target, RttiTypeCtor, Ordinal, ArgTypes,
|
|
!GlobalData),
|
|
ArgTypeInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_field_types(Ordinal))
|
|
;
|
|
ArgInfos = [],
|
|
ArgTypeInitializer = gen_init_null_pointer(
|
|
mlds_rtti_type(item_type(
|
|
ctor_rtti_id(RttiTypeCtor, type_ctor_field_types(0u32)))))
|
|
),
|
|
(
|
|
HaveArgNames = yes,
|
|
gen_field_names(ModuleInfo, RttiTypeCtor, Ordinal,
|
|
MaybeArgNames, !GlobalData),
|
|
ArgNameInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_field_names(Ordinal))
|
|
;
|
|
HaveArgNames = no,
|
|
ArgNameInitializer = gen_init_null_pointer(
|
|
mlds_rtti_type(item_type(
|
|
ctor_rtti_id(RttiTypeCtor, type_ctor_field_names(0u32)))))
|
|
),
|
|
gen_field_locns(ModuleInfo, RttiTypeCtor, Ordinal, ArgInfos, HaveArgLocns,
|
|
!GlobalData),
|
|
(
|
|
HaveArgLocns = yes,
|
|
ArgLocnsInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_field_locns(Ordinal))
|
|
;
|
|
HaveArgLocns = no,
|
|
ArgLocnsInitializer = gen_init_null_pointer(
|
|
mlds_rtti_type(item_type(
|
|
ctor_rtti_id(RttiTypeCtor, type_ctor_field_locns(0u32)))))
|
|
),
|
|
(
|
|
MaybeExistInfo = yes(ExistInfo),
|
|
gen_exist_info(ModuleInfo, Target, RttiTypeCtor, Ordinal, ExistInfo,
|
|
!GlobalData),
|
|
ExistInfoInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_exist_info(Ordinal))
|
|
;
|
|
MaybeExistInfo = no,
|
|
ExistInfoInitializer = gen_init_null_pointer(
|
|
mlds_rtti_type(item_type(
|
|
ctor_rtti_id(RttiTypeCtor, type_ctor_exist_info(0u32)))))
|
|
),
|
|
(
|
|
Rep = du_ll_rep(Ptag, SectagAndLocn),
|
|
Ptag = ptag(PtagUint8)
|
|
;
|
|
Rep = du_hl_rep(Data),
|
|
PtagUint8 = 0u8,
|
|
SectagAndLocn = sectag_locn_remote_word(Data)
|
|
),
|
|
(
|
|
SectagAndLocn = sectag_locn_none,
|
|
Locn = sectag_none,
|
|
Stag = -1,
|
|
NumSectagBits = 0u8
|
|
;
|
|
SectagAndLocn = sectag_locn_none_direct_arg,
|
|
Locn = sectag_none_direct_arg,
|
|
Stag = -1,
|
|
NumSectagBits = 0u8
|
|
;
|
|
SectagAndLocn = sectag_locn_local_rest_of_word(StagUint),
|
|
Locn = sectag_local_rest_of_word,
|
|
Stag = uint.cast_to_int(StagUint),
|
|
NumSectagBits = 0u8
|
|
;
|
|
SectagAndLocn = sectag_locn_local_bits(StagUint, NumSectagBits, Mask),
|
|
Locn = sectag_local_bits(NumSectagBits, Mask),
|
|
Stag = uint.cast_to_int(StagUint)
|
|
;
|
|
SectagAndLocn = sectag_locn_remote_word(StagUint),
|
|
Locn = sectag_remote_word,
|
|
Stag = uint.cast_to_int(StagUint),
|
|
NumSectagBits = 0u8
|
|
;
|
|
SectagAndLocn = sectag_locn_remote_bits(StagUint, NumSectagBits, Mask),
|
|
Locn = sectag_remote_bits(NumSectagBits, Mask),
|
|
Stag = uint.cast_to_int(StagUint)
|
|
),
|
|
RttiName = type_ctor_du_functor_desc(Ordinal),
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName),
|
|
ArityInt16 = int16.cast_from_uint16(Arity), % XXX MAKE_FIELD_UNSIGNED
|
|
OrdinalInt32 = int32.cast_from_uint32(Ordinal), % XXX MAKE_FIELD_UNSIGNED
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
gen_init_string(FunctorName), % MR_du_functor_name
|
|
gen_init_int16(ArityInt16), % MR_du_functor_orig_arity
|
|
gen_init_uint16(ContainsVarBitVector),
|
|
% MR_du_functor_arg_type_contains_var
|
|
gen_init_sectag_locn(Locn), % MR_du_functor_sectag_locn
|
|
gen_init_uint8(PtagUint8), % MR_du_functor_primary
|
|
gen_init_int(Stag), % MR_du_functor_secondary
|
|
gen_init_int32(OrdinalInt32), % MR_du_functor_ordinal
|
|
ArgTypeInitializer, % MR_du_functor_arg_types
|
|
ArgNameInitializer, % MR_du_functor_arg_names
|
|
ArgLocnsInitializer, % MR_du_functor_arg_locns
|
|
ExistInfoInitializer, % MR_du_functor_exist_info
|
|
gen_init_functor_subtype_info(FunctorSubtypeInfo),
|
|
% MR_du_functor_subtype_constraints
|
|
gen_init_uint8(NumSectagBits) % MR_du_functor_num_sectag_bits
|
|
]),
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- func gen_init_exist_locn(rtti_type_ctor, exist_typeinfo_locn) =
|
|
mlds_initializer.
|
|
|
|
gen_init_exist_locn(RttiTypeCtor, ExistTypeInfoLocn) = Initializer :-
|
|
(
|
|
ExistTypeInfoLocn = typeinfo_in_tci(SlotInCell, SlotInTci),
|
|
SlotInTciEncoding = int16.cast_from_uint16(SlotInTci)
|
|
;
|
|
ExistTypeInfoLocn = plain_typeinfo(SlotInCell),
|
|
SlotInTciEncoding = -1i16
|
|
),
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, type_ctor_exist_locn),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
% MR_exist_arg_num -- XXX MAKE_FIELD_UNSIGNED
|
|
gen_init_int16(int16.cast_from_uint16(SlotInCell)),
|
|
% MR_exist_offset_in_tci
|
|
gen_init_int16(SlotInTciEncoding)
|
|
]).
|
|
|
|
:- pred gen_exist_locns_array(module_info::in, rtti_type_ctor::in, uint32::in,
|
|
list(exist_typeinfo_locn)::in, ml_global_data::in, ml_global_data::out)
|
|
is det.
|
|
|
|
gen_exist_locns_array(_ModuleInfo, RttiTypeCtor, Ordinal, Locns,
|
|
!GlobalData) :-
|
|
Initializer = gen_init_array(gen_init_exist_locn(RttiTypeCtor), Locns),
|
|
RttiName = type_ctor_exist_locns(Ordinal),
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- pred gen_tc_constraint(module_info::in, mlds_target_lang::in,
|
|
pred(int, int, rtti_id)::in(pred(in, in, out) is det),
|
|
tc_constraint::in, rtti_id::out, counter::in, counter::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_tc_constraint(ModuleInfo, Target, MakeRttiId, Constraint, RttiId,
|
|
!Counter, !GlobalData) :-
|
|
Constraint = tc_constraint(TCName, Types),
|
|
list.length(Types, Arity),
|
|
counter.allocate(TCNum, !Counter),
|
|
MakeRttiId(TCNum, Arity, RttiId),
|
|
TCDeclRttiName = type_class_decl,
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
TypeRttiDatas = list.map(maybe_pseudo_type_info_to_rtti_data, Types),
|
|
gen_pseudo_type_info_array(ModuleInfo, Target, TypeRttiDatas,
|
|
PTIInitializers, !GlobalData),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
gen_init_tc_rtti_name(ModuleName, TCName, TCDeclRttiName),
|
|
PTIInitializers
|
|
]),
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData).
|
|
|
|
:- pred make_exist_tc_constr_id(rtti_type_ctor::in, uint32::in, int::in,
|
|
int::in, rtti_id::out) is det.
|
|
|
|
make_exist_tc_constr_id(RttiTypeCtor, Ordinal, TCNum, Arity, RttiId) :-
|
|
RttiName = type_ctor_exist_tc_constr(Ordinal, TCNum, Arity),
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName).
|
|
|
|
:- pred gen_exist_info(module_info::in, mlds_target_lang::in,
|
|
rtti_type_ctor::in, uint32::in, exist_info::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_exist_info(ModuleInfo, Target, RttiTypeCtor, Ordinal, ExistInfo,
|
|
!GlobalData) :-
|
|
ExistInfo = exist_info(Plain, InTci, Constraints, Locns),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
RttiName = type_ctor_exist_info(Ordinal),
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName),
|
|
list.length(Constraints, Tci),
|
|
(
|
|
Constraints = [],
|
|
ConstrInitializer = gen_init_null_pointer(
|
|
mlds_rtti_type(item_type(ctor_rtti_id(RttiTypeCtor,
|
|
type_ctor_exist_tc_constrs(Ordinal)))))
|
|
;
|
|
Constraints = [_ | _],
|
|
ConstrInitializer = gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_exist_tc_constrs(Ordinal)),
|
|
list.map_foldl2(
|
|
gen_tc_constraint(ModuleInfo, Target,
|
|
make_exist_tc_constr_id(RttiTypeCtor, Ordinal)),
|
|
Constraints, TCConstrIds, counter.init(1), _, !GlobalData),
|
|
TCConstrArrayRttiName = type_ctor_exist_tc_constrs(Ordinal),
|
|
TCConstrArrayRttiId = ctor_rtti_id(RttiTypeCtor,
|
|
TCConstrArrayRttiName),
|
|
ElementType = mlds_rtti_type(element_type(TCConstrArrayRttiId)),
|
|
TCConstrArrayInitializer = gen_init_array(
|
|
gen_init_cast_rtti_id(ElementType, ModuleName), TCConstrIds),
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, TCConstrArrayRttiName,
|
|
TCConstrArrayInitializer, !GlobalData)
|
|
),
|
|
gen_exist_locns_array(ModuleInfo, RttiTypeCtor, Ordinal, Locns,
|
|
!GlobalData),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
% MR_exist_typeinfos_plain -- XXX MAKE_FIELD_UNSIGNED
|
|
gen_init_int16(int16.cast_from_uint16(Plain)),
|
|
% MR_exist_typeinfos_in_tci -- XXX MAKE_FIELD_UNSIGNED
|
|
gen_init_int16(int16.cast_from_uint16(InTci)),
|
|
% MR_exist_tcis -- XXX MAKE_FIELD_UNSIGNED
|
|
gen_init_int16(int16.det_from_int(Tci)),
|
|
% MR_exist_typeinfo_locns
|
|
gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_exist_locns(Ordinal)),
|
|
% MR_exist_constraints
|
|
ConstrInitializer
|
|
]),
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData).
|
|
|
|
:- pred gen_field_types(module_info::in, mlds_target_lang::in,
|
|
rtti_type_ctor::in, uint32::in,
|
|
list(rtti_maybe_pseudo_type_info_or_self)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_field_types(ModuleInfo, Target, RttiTypeCtor, Ordinal, Types,
|
|
!GlobalData) :-
|
|
TypeRttiDatas = list.map(maybe_pseudo_type_info_or_self_to_rtti_data,
|
|
Types),
|
|
gen_pseudo_type_info_array(ModuleInfo, Target, TypeRttiDatas, Initializer,
|
|
!GlobalData),
|
|
RttiName = type_ctor_field_types(Ordinal),
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- pred gen_field_names(module_info::in, rtti_type_ctor::in, uint32::in,
|
|
list(maybe(string))::in, ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_field_names(_ModuleInfo, RttiTypeCtor, Ordinal, MaybeNames, !GlobalData) :-
|
|
Initializer = gen_init_array(
|
|
gen_init_maybe(mlds_builtin_type_string, gen_init_string),
|
|
MaybeNames),
|
|
RttiName = type_ctor_field_names(Ordinal),
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- pred gen_field_locns(module_info::in, rtti_type_ctor::in, uint32::in,
|
|
list(du_arg_info)::in, bool::out, ml_global_data::in, ml_global_data::out)
|
|
is det.
|
|
|
|
gen_field_locns(_ModuleInfo, RttiTypeCtor, Ordinal, ArgInfos, HaveArgLocns,
|
|
!GlobalData) :-
|
|
( if
|
|
some [ArgInfo] (
|
|
list.member(ArgInfo, ArgInfos),
|
|
ArgInfo ^ du_arg_pos_width \= apw_full(_, _)
|
|
)
|
|
then
|
|
HaveArgLocns = yes,
|
|
RttiName = type_ctor_field_locns(Ordinal),
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName),
|
|
list.map(gen_field_locn(RttiId), ArgInfos, ArgLocnInitializers),
|
|
Initializer = init_array(ArgLocnInitializers),
|
|
rtti_id_and_init_to_defn(RttiId, Initializer, !GlobalData)
|
|
else
|
|
HaveArgLocns = no
|
|
).
|
|
|
|
:- pred gen_field_locn(rtti_id::in, du_arg_info::in, mlds_initializer::out)
|
|
is det.
|
|
|
|
gen_field_locn(RttiId, ArgInfo, ArgLocnInitializer) :-
|
|
ArgPosWidth = ArgInfo ^ du_arg_pos_width,
|
|
% The meanings of the various special values of MR_arg_bits
|
|
% are documented next to the definition of the MR_DuArgLocn type
|
|
% in mercury_type_info.h.
|
|
(
|
|
ArgPosWidth = apw_full(arg_only_offset(ArgOnlyOffset), _),
|
|
Shift = 0,
|
|
% NumBits = 0 means the argument takes a full word.
|
|
NumBits = 0
|
|
;
|
|
ArgPosWidth = apw_double(arg_only_offset(ArgOnlyOffset), _,
|
|
DoubleWordKind),
|
|
Shift = 0,
|
|
% NumBits = -1, -2 and -3 mean the argument takes two words,
|
|
% containing a float, int64 and uint64 respectively.
|
|
(
|
|
DoubleWordKind = dw_float,
|
|
NumBits = -1
|
|
;
|
|
DoubleWordKind = dw_int64,
|
|
NumBits = -2
|
|
;
|
|
DoubleWordKind = dw_uint64,
|
|
NumBits = -3
|
|
)
|
|
;
|
|
(
|
|
ArgPosWidth = apw_partial_first(arg_only_offset(ArgOnlyOffset),
|
|
_, arg_shift(Shift), arg_num_bits(NumBits0), _, Fill)
|
|
;
|
|
ArgPosWidth = apw_partial_shifted(arg_only_offset(ArgOnlyOffset),
|
|
_, arg_shift(Shift), arg_num_bits(NumBits0), _, Fill)
|
|
),
|
|
% NumBits = -4 to -9 mean the argument takes part a word
|
|
% and contains an 8, 16 or 32 bit sized int or uint.
|
|
(
|
|
( Fill = fill_enum
|
|
; Fill = fill_char21
|
|
),
|
|
NumBits = NumBits0
|
|
;
|
|
Fill = fill_int8,
|
|
NumBits = -4
|
|
;
|
|
Fill = fill_uint8,
|
|
NumBits = -5
|
|
;
|
|
Fill = fill_int16,
|
|
NumBits = -6
|
|
;
|
|
Fill = fill_uint16,
|
|
NumBits = -7
|
|
;
|
|
Fill = fill_int32,
|
|
NumBits = -8
|
|
;
|
|
Fill = fill_uint32,
|
|
NumBits = -9
|
|
)
|
|
;
|
|
(
|
|
ArgPosWidth = apw_none_shifted(arg_only_offset(ArgOnlyOffset), _)
|
|
;
|
|
ArgPosWidth = apw_none_nowhere,
|
|
ArgOnlyOffset = -1
|
|
),
|
|
% NumBits = -10 means the argument is of a dummy type,
|
|
% and takes no space at all.
|
|
Shift = 0,
|
|
NumBits = -10
|
|
),
|
|
ArgLocnInitializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
gen_init_int(ArgOnlyOffset), % MR_arg_offset
|
|
gen_init_int(Shift), % MR_arg_shift
|
|
gen_init_int(NumBits) % MR_arg_bits
|
|
]).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred gen_enum_ordinal_ordered_table(module_info::in, rtti_type_ctor::in,
|
|
map(uint32, enum_functor)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_enum_ordinal_ordered_table(ModuleInfo, RttiTypeCtor, EnumByOrd,
|
|
!GlobalData) :-
|
|
map.values(EnumByOrd, Functors),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
FunctorRttiNames = list.map(enum_functor_rtti_name, Functors),
|
|
Initializer = gen_init_rtti_names_array(ModuleName, RttiTypeCtor,
|
|
FunctorRttiNames),
|
|
RttiName = type_ctor_enum_ordinal_ordered_table,
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- pred gen_enum_name_ordered_table(module_info::in, rtti_type_ctor::in,
|
|
map(string, enum_functor)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_enum_name_ordered_table(ModuleInfo, RttiTypeCtor, EnumByName,
|
|
!GlobalData) :-
|
|
map.values(EnumByName, Functors),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
FunctorRttiNames = list.map(enum_functor_rtti_name, Functors),
|
|
Initializer = gen_init_rtti_names_array(ModuleName, RttiTypeCtor,
|
|
FunctorRttiNames),
|
|
RttiName = type_ctor_enum_name_ordered_table,
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- pred gen_foreign_enum_ordinal_ordered_table(module_info::in,
|
|
rtti_type_ctor::in, map(uint32, foreign_enum_functor)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_foreign_enum_ordinal_ordered_table(ModuleInfo, RttiTypeCtor,
|
|
ForeignEnumByOrdinal, !GlobalData) :-
|
|
map.values(ForeignEnumByOrdinal, Functors),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
FunctorRttiNames = list.map(foreign_enum_functor_rtti_name, Functors),
|
|
Initializer = gen_init_rtti_names_array(ModuleName, RttiTypeCtor,
|
|
FunctorRttiNames),
|
|
RttiName = type_ctor_foreign_enum_ordinal_ordered_table,
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- pred gen_foreign_enum_name_ordered_table(module_info::in,
|
|
rtti_type_ctor::in, map(string, foreign_enum_functor)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_foreign_enum_name_ordered_table(ModuleInfo, RttiTypeCtor,
|
|
ForeignEnumByName, !GlobalData) :-
|
|
map.values(ForeignEnumByName, Functors),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
FunctorRttiNames = list.map(foreign_enum_functor_rtti_name, Functors),
|
|
Initializer = gen_init_rtti_names_array(ModuleName, RttiTypeCtor,
|
|
FunctorRttiNames),
|
|
RttiName = type_ctor_foreign_enum_name_ordered_table,
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- pred gen_du_ptag_ordered_table(module_info::in, rtti_type_ctor::in,
|
|
map(ptag, sectag_table)::in, ml_global_data::in, ml_global_data::out)
|
|
is det.
|
|
|
|
gen_du_ptag_ordered_table(ModuleInfo, RttiTypeCtor, PtagMap, !GlobalData) :-
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
map.to_assoc_list(PtagMap, PtagList),
|
|
list.foldl(gen_du_stag_ordered_table(ModuleName, RttiTypeCtor), PtagList,
|
|
!GlobalData),
|
|
(
|
|
PtagList = [FirstPtag - _ | _],
|
|
FirstPtag = ptag(LeastPtag)
|
|
;
|
|
PtagList = [],
|
|
unexpected($pred, "bad ptag list")
|
|
),
|
|
gen_du_ptag_ordered_table_body(ModuleName, RttiTypeCtor, LeastPtag,
|
|
PtagList, PtagInitializers),
|
|
RttiName = type_ctor_du_ptag_ordered_table,
|
|
Initializer = init_array(PtagInitializers),
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- pred gen_du_ptag_ordered_table_body(module_name::in, rtti_type_ctor::in,
|
|
uint8::in, assoc_list(ptag, sectag_table)::in, list(mlds_initializer)::out)
|
|
is det.
|
|
|
|
gen_du_ptag_ordered_table_body(_, _, _, [], []).
|
|
gen_du_ptag_ordered_table_body(ModuleName, RttiTypeCtor, LeastPtag,
|
|
[Ptag - SectagTable | PtagTail], [Initializer | Initializers]) :-
|
|
Ptag = ptag(PtagUint8),
|
|
% ptags for a subtype may start higher than zero, and may skip values.
|
|
expect(LeastPtag =< PtagUint8, $pred, "ptag mismatch"),
|
|
SectagTable = sectag_table(SectagLocn, NumSectagBits, NumSharers,
|
|
_SectagMap),
|
|
RttiName = type_ctor_du_ptag_layout(Ptag),
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName),
|
|
compute_du_ptag_layout_flags(SectagTable, Flags),
|
|
Initializer = init_struct(mlds_rtti_type(item_type(RttiId)), [
|
|
% MR_sectag_sharers
|
|
gen_init_uint32(NumSharers),
|
|
% MR_sectag_locn
|
|
gen_init_sectag_locn(SectagLocn),
|
|
% MR_sectag_alternatives
|
|
gen_init_rtti_name(ModuleName, RttiTypeCtor,
|
|
type_ctor_du_stag_ordered_table(Ptag)),
|
|
% MR_sectag_numbits
|
|
gen_init_int8(NumSectagBits),
|
|
% MR_du_ptag,
|
|
gen_init_uint8(PtagUint8),
|
|
% MR_du_ptag_flags
|
|
gen_init_uint8(encode_du_ptag_layout_flags(Flags))
|
|
]),
|
|
NextLeastPtag = PtagUint8 + 1u8,
|
|
gen_du_ptag_ordered_table_body(ModuleName, RttiTypeCtor, NextLeastPtag,
|
|
PtagTail, Initializers).
|
|
|
|
:- pred gen_du_stag_ordered_table(module_name::in, rtti_type_ctor::in,
|
|
pair(ptag, sectag_table)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_du_stag_ordered_table(ModuleName, RttiTypeCtor, Ptag - SectagTable,
|
|
!GlobalData) :-
|
|
SectagTable = sectag_table(_SectagLocn, _NumSectagBits, _NumSharers,
|
|
SectagMap),
|
|
map.values(SectagMap, SectagFunctors),
|
|
FunctorRttiNames = list.map(du_functor_rtti_name, SectagFunctors),
|
|
Initializer = gen_init_rtti_names_array(ModuleName, RttiTypeCtor,
|
|
FunctorRttiNames),
|
|
RttiName = type_ctor_du_stag_ordered_table(Ptag),
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- pred gen_du_name_ordered_table(module_info::in, rtti_type_ctor::in,
|
|
map(string, map(uint16, du_functor))::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_du_name_ordered_table(ModuleInfo, RttiTypeCtor, NameArityMap,
|
|
!GlobalData) :-
|
|
map.values(NameArityMap, ArityMaps),
|
|
list.map(map.values, ArityMaps, FunctorLists),
|
|
list.condense(FunctorLists, Functors),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
FunctorRttiNames = list.map(du_functor_rtti_name, Functors),
|
|
Initializer = gen_init_rtti_names_array(ModuleName, RttiTypeCtor,
|
|
FunctorRttiNames),
|
|
RttiName = type_ctor_du_name_ordered_table,
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- pred gen_functor_number_map(rtti_type_ctor::in, list(uint32)::in,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_functor_number_map(RttiTypeCtor, FunctorNumberMap, !GlobalData) :-
|
|
Initializer = gen_init_array(gen_init_functor_number, FunctorNumberMap),
|
|
RttiName = type_ctor_functor_number_map,
|
|
rtti_name_and_init_to_defn(RttiTypeCtor, RttiName, Initializer,
|
|
!GlobalData).
|
|
|
|
:- func gen_init_functor_number(uint32) = mlds_initializer.
|
|
|
|
gen_init_functor_number(NumUint32) = Init :-
|
|
% XXX MAKE_FIELD_UNSIGNED
|
|
Num = uint32.cast_to_int(NumUint32),
|
|
Init = gen_init_int(Num).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- func gen_init_base_type_ctor(module_name, mlds_target_lang,
|
|
maybe(type_ctor)) = mlds_initializer.
|
|
|
|
gen_init_base_type_ctor(ModuleName, Target, MaybeBaseTypeCtor) = Initializer :-
|
|
% The MR_type_ctor_base field is only required in high-level data grades.
|
|
( if mlds_target_high_level_data(Target) = yes then
|
|
(
|
|
MaybeBaseTypeCtor = yes(BaseTypeCtor),
|
|
BaseTypeCtor = type_ctor(SymName, Arity),
|
|
(
|
|
SymName = qualified(TypeModule, TypeName)
|
|
;
|
|
SymName = unqualified(_),
|
|
unexpected($pred, "base type ctor is not module qualified")
|
|
),
|
|
RttiTypeCtor = rtti_type_ctor(TypeModule, TypeName,
|
|
uint16.det_from_int(Arity)),
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, type_ctor_type_ctor_info),
|
|
Initializer = gen_init_rtti_id(ModuleName, RttiId)
|
|
;
|
|
MaybeBaseTypeCtor = no,
|
|
% The type is a lie, but a safe one.
|
|
Initializer = gen_init_null_pointer(mlds_generic_type)
|
|
)
|
|
else
|
|
Initializer = no_initializer
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- func gen_init_rtti_names_array(module_name, rtti_type_ctor,
|
|
list(ctor_rtti_name)) = mlds_initializer.
|
|
|
|
gen_init_rtti_names_array(ModuleName, RttiTypeCtor, RttiNames) =
|
|
gen_init_array(gen_init_rtti_name(ModuleName, RttiTypeCtor), RttiNames).
|
|
|
|
:- func gen_init_cast_rtti_datas_array(mlds_type, module_name,
|
|
list(rtti_data)) = mlds_initializer.
|
|
|
|
gen_init_cast_rtti_datas_array(Type, ModuleName, RttiDatas) =
|
|
gen_init_array(gen_init_cast_rtti_data(Type, ModuleName), RttiDatas).
|
|
|
|
% Generate the MLDS initializer comprising the rtti_name
|
|
% for a given rtti_data, converted to mlds_generic_type.
|
|
%
|
|
:- func gen_init_cast_rtti_data(mlds_type, module_name, rtti_data) =
|
|
mlds_initializer.
|
|
|
|
gen_init_cast_rtti_data(DestType, ModuleName, RttiData) = Initializer :-
|
|
( if
|
|
RttiData = rtti_data_pseudo_type_info(type_var(VarNum))
|
|
then
|
|
% rtti_data_to_id/3 does not handle this case
|
|
SrcType = mlds_builtin_type_int(int_type_int),
|
|
Initializer = init_obj(gen_cast(SrcType, DestType,
|
|
ml_const(mlconst_int(VarNum))))
|
|
else if
|
|
RttiData = rtti_data_base_typeclass_info(TCName, InstanceModuleName,
|
|
InstanceString, _)
|
|
then
|
|
SrcType = mlds_rtti_type(item_type(tc_rtti_id(TCName,
|
|
type_class_base_typeclass_info(InstanceModuleName,
|
|
InstanceString)))),
|
|
MLDS_ModuleName = mercury_module_name_to_mlds(InstanceModuleName),
|
|
RttiId = tc_rtti_id(TCName, type_class_base_typeclass_info(
|
|
InstanceModuleName, InstanceString)),
|
|
Rval = ml_const(mlconst_data_addr_rtti(MLDS_ModuleName, RttiId)),
|
|
Initializer = init_obj(gen_cast(SrcType, DestType, Rval))
|
|
else
|
|
rtti_data_to_id(RttiData, RttiId),
|
|
Initializer = gen_init_cast_rtti_id(DestType, ModuleName, RttiId)
|
|
).
|
|
|
|
% Currently casts only store the destination type.
|
|
%
|
|
:- func gen_cast(mlds_type, mlds_type, mlds_rval) = mlds_rval.
|
|
|
|
gen_cast(_SrcType, DestType, SubRval) = ml_cast(DestType, SubRval).
|
|
|
|
% Generate an MLDS initializer comprising just the rval
|
|
% for a given rtti_id.
|
|
%
|
|
:- func gen_init_rtti_id(module_name, rtti_id) = mlds_initializer.
|
|
|
|
gen_init_rtti_id(ModuleName, ctor_rtti_id(RttiTypeCtor, RttiName)) =
|
|
gen_init_rtti_name(ModuleName, RttiTypeCtor, RttiName).
|
|
gen_init_rtti_id(ModuleName, tc_rtti_id(TCName, TCRttiName)) =
|
|
gen_init_tc_rtti_name(ModuleName, TCName, TCRttiName).
|
|
|
|
% Generate an MLDS initializer comprising just the rval
|
|
% for a given rtti_name.
|
|
%
|
|
:- func gen_init_rtti_name(module_name, rtti_type_ctor, ctor_rtti_name) =
|
|
mlds_initializer.
|
|
|
|
gen_init_rtti_name(ModuleName, RttiTypeCtor, RttiName) =
|
|
init_obj(gen_rtti_name(ModuleName, RttiTypeCtor, RttiName)).
|
|
|
|
% Generate an MLDS initializer comprising just the rval
|
|
% for a given tc_rtti_name.
|
|
%
|
|
:- func gen_init_tc_rtti_name(module_name, tc_name, tc_rtti_name) =
|
|
mlds_initializer.
|
|
|
|
gen_init_tc_rtti_name(ModuleName, TCName, TCRttiName) =
|
|
init_obj(gen_tc_rtti_name(ModuleName, TCName, TCRttiName)).
|
|
|
|
% Generate the MLDS initializer comprising the rtti_name
|
|
% for a given rtti_name, converted to the given type.
|
|
%
|
|
:- func gen_init_cast_rtti_id(mlds_type, module_name, rtti_id)
|
|
= mlds_initializer.
|
|
|
|
gen_init_cast_rtti_id(DestType, ModuleName, RttiId) = Initializer :-
|
|
SrcType = mlds_rtti_type(item_type(RttiId)),
|
|
Initializer = init_obj(gen_cast(SrcType, DestType,
|
|
gen_rtti_id(ModuleName, RttiId))).
|
|
|
|
% Generate the MLDS rval for an rtti_id.
|
|
%
|
|
:- func gen_rtti_id(module_name, rtti_id) = mlds_rval.
|
|
|
|
gen_rtti_id(ThisModuleName, ctor_rtti_id(RttiTypeCtor, RttiName)) =
|
|
gen_rtti_name(ThisModuleName, RttiTypeCtor, RttiName).
|
|
gen_rtti_id(ThisModuleName, tc_rtti_id(TCName, TCRttiName)) =
|
|
gen_tc_rtti_name(ThisModuleName, TCName, TCRttiName).
|
|
|
|
:- func gen_rtti_name(module_name, rtti_type_ctor, ctor_rtti_name)
|
|
= mlds_rval.
|
|
|
|
gen_rtti_name(ThisModuleName, RttiTypeCtor0, RttiName) = Rval :-
|
|
% Typeinfos and pseudo typeinfos are defined locally to each module.
|
|
% Other kinds of RTTI data are defined in the module that defines
|
|
% the type which they are for.
|
|
( if
|
|
(
|
|
RttiName = type_ctor_type_info(TypeInfo),
|
|
( TypeInfo = plain_type_info(_, _)
|
|
; TypeInfo = var_arity_type_info(_, _)
|
|
)
|
|
;
|
|
RttiName = type_ctor_pseudo_type_info(PseudoTypeInfo),
|
|
( PseudoTypeInfo = plain_pseudo_type_info(_, _)
|
|
; PseudoTypeInfo = var_arity_pseudo_type_info(_, _)
|
|
)
|
|
)
|
|
then
|
|
ModuleName = ThisModuleName,
|
|
RttiTypeCtor = RttiTypeCtor0
|
|
else
|
|
RttiTypeCtor0 = rtti_type_ctor(RttiModuleName,
|
|
RttiTypeName, RttiTypeArity),
|
|
|
|
% Although the builtin types `int', `float', etc. are treated
|
|
% as part of the `builtin' module, for historical reasons they
|
|
% don't have any qualifiers at this point, so we need to add
|
|
% the `builtin' qualifier now.
|
|
( if RttiModuleName = unqualified("") then
|
|
ModuleName = mercury_public_builtin_module,
|
|
RttiTypeCtor = rtti_type_ctor(RttiModuleName,
|
|
RttiTypeName, RttiTypeArity)
|
|
else
|
|
ModuleName = RttiModuleName,
|
|
RttiTypeCtor = RttiTypeCtor0
|
|
)
|
|
),
|
|
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
|
|
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName),
|
|
Rval = ml_const(mlconst_data_addr_rtti(MLDS_ModuleName, RttiId)).
|
|
|
|
:- func gen_tc_rtti_name(module_name, tc_name, tc_rtti_name) = mlds_rval.
|
|
|
|
gen_tc_rtti_name(_ThisModuleName, TCName, TCRttiName) = Rval :-
|
|
(
|
|
TCRttiName = type_class_base_typeclass_info(InstanceModuleName, _),
|
|
MLDS_ModuleName = mercury_module_name_to_mlds(InstanceModuleName)
|
|
;
|
|
TCRttiName = type_class_id,
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
;
|
|
TCRttiName = type_class_decl,
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
;
|
|
TCRttiName = type_class_decl_super(_, _),
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
;
|
|
TCRttiName = type_class_decl_supers,
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
;
|
|
TCRttiName = type_class_id_var_names,
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
;
|
|
TCRttiName = type_class_id_method_ids,
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
;
|
|
TCRttiName = type_class_instance(_Types),
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
;
|
|
TCRttiName = type_class_instance_tc_type_vector(_Types),
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
;
|
|
TCRttiName = type_class_instance_constraint(_Types, _, _),
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
;
|
|
TCRttiName = type_class_instance_constraints(_Types),
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
;
|
|
TCRttiName = type_class_instance_methods(_Types),
|
|
MLDS_ModuleName = mlds_module_name_from_tc_name(TCName)
|
|
),
|
|
RttiId = tc_rtti_id(TCName, TCRttiName),
|
|
Rval = ml_const(mlconst_data_addr_rtti(MLDS_ModuleName, RttiId)).
|
|
|
|
:- func mlds_module_name_from_tc_name(tc_name) = mlds_module_name.
|
|
|
|
mlds_module_name_from_tc_name(TCName) = MLDS_ModuleName :-
|
|
TCName = tc_name(ModuleName, _ClassName, _Arity),
|
|
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred gen_pseudo_type_info(module_info::in, mlds_target_lang::in,
|
|
rtti_data::in, mlds_initializer::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_pseudo_type_info(ModuleInfo, Target, PTIRttiData, Initializer,
|
|
!GlobalData) :-
|
|
( if real_rtti_data(PTIRttiData) then
|
|
add_rtti_data_to_mlds(ModuleInfo, Target, PTIRttiData, !GlobalData)
|
|
else
|
|
% Since PTIRttiData does not correspond to a global data definition,
|
|
% we have nothing to do.
|
|
true
|
|
),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
Initializer = gen_init_cast_rtti_data(mlds_pseudo_type_info_type,
|
|
ModuleName, PTIRttiData).
|
|
|
|
:- pred gen_pseudo_type_info_array(module_info::in, mlds_target_lang::in,
|
|
list(rtti_data)::in, mlds_initializer::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_pseudo_type_info_array(ModuleInfo, Target, PTIRttiDatas, Initializer,
|
|
!GlobalData) :-
|
|
RealRttiDatas = list.filter(real_rtti_data, PTIRttiDatas),
|
|
list.foldl(add_rtti_data_to_mlds(ModuleInfo, Target),
|
|
RealRttiDatas, !GlobalData),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
Initializer = gen_init_cast_rtti_datas_array(mlds_pseudo_type_info_type,
|
|
ModuleName, PTIRttiDatas).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred gen_init_method(module_info::in, mlds_target_lang::in,
|
|
int::in, rtti_proc_label::in, mlds_initializer::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_init_method(ModuleInfo, Target, NumExtra, RttiProcLabel, Initializer,
|
|
!GlobalData) :-
|
|
% We can't store the address of the typeclass method directly in the
|
|
% base_typeclass_info; instead, we need to generate a wrapper function
|
|
% that extracts the NumExtra parameters it needs from the typeclass_info,
|
|
% and store the address of that wrapper function in the
|
|
% base_typeclass_info.
|
|
%
|
|
% Note that this means there are two levels of wrappers: the wrapper that
|
|
% we generate here calls the procedure introduced by check_typeclass.m,
|
|
% and that in turn calls the user's procedure. Hopefully the Mercury
|
|
% HLDS->HLDS inlining and/or the target code compiler will be able
|
|
% to optimize this...
|
|
%
|
|
gen_wrapper_func_and_initializer(ModuleInfo, Target, NumExtra,
|
|
RttiProcLabel, typeclass_info_closure, Initializer, !GlobalData).
|
|
|
|
:- pred gen_init_special_pred(module_info::in, mlds_target_lang::in,
|
|
univ::in, mlds_initializer::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_init_special_pred(ModuleInfo, Target, RttiProcIdUniv, Initializer,
|
|
!GlobalData) :-
|
|
% We can't store the address of the special pred procedure directly in the
|
|
% type_ctor_info because when the special pred is called by looking up
|
|
% its address in the type_ctor_info it is always called with its arguments
|
|
% boxed, but the generated special pred may operate on unboxed values,
|
|
% hence we need to generate a wrapper function which unboxes the arguments
|
|
% if necessary.
|
|
det_univ_to_type(RttiProcIdUniv, RttiProcId),
|
|
( if RttiProcId ^ rpl_proc_arity = pred_form_arity(0) then
|
|
% If there are no arguments, then there is no unboxing to do,
|
|
% so we don't need a wrapper. (This case can occur with
|
|
% --no-special-preds, where the procedure will be
|
|
% private_builtin.unused/0.)
|
|
% XXX --no-special-preds does not exist anymore.
|
|
Initializer = gen_init_proc_id(ModuleInfo, RttiProcId)
|
|
else
|
|
NumExtra = 0,
|
|
gen_wrapper_func_and_initializer(ModuleInfo, Target,
|
|
NumExtra, RttiProcId, special_pred_closure, Initializer,
|
|
!GlobalData)
|
|
).
|
|
|
|
:- pred gen_wrapper_func_and_initializer(module_info::in, mlds_target_lang::in,
|
|
int::in, rtti_proc_label::in, closure_kind::in, mlds_initializer::out,
|
|
ml_global_data::in, ml_global_data::out) is det.
|
|
|
|
gen_wrapper_func_and_initializer(ModuleInfo, Target, NumExtra, RttiProcId,
|
|
ClosureKind, Initializer, !GlobalData) :-
|
|
some [!Info] (
|
|
% We start off by creating a fresh MLGenInfo here, using the pred_id
|
|
% and proc_id of the wrapped procedure. This requires considerable
|
|
% care. We need to call ml_gen_info_bump_counters to ensure that
|
|
% the function label allocated for the wrapper func does not overlap
|
|
% with any function labels used when generating code for the wrapped
|
|
% procedure.
|
|
%
|
|
% The empty const struct map is a lie, but a white lie; the RTTI
|
|
% data cannot contain any type_info_const or typeclass_info_const
|
|
% cons_ids.
|
|
|
|
PredId = RttiProcId ^ rpl_pred_id,
|
|
ProcId = RttiProcId ^ rpl_proc_id,
|
|
PredProcId = proc(PredId, ProcId),
|
|
InSccInfo = in_scc_info(not_in_tscc,
|
|
is_not_target_of_self_trcall, is_not_target_of_mutual_trcall, []),
|
|
InSccMap = map.singleton(PredProcId, InSccInfo),
|
|
init_ml_gen_tscc_info(ModuleInfo, InSccMap, tscc_self_rec_only,
|
|
TsccInfo),
|
|
module_info_proc_info(ModuleInfo, PredId, ProcId, ProcInfo),
|
|
!:Info = ml_gen_info_init(ModuleInfo, Target, map.init, PredProcId,
|
|
ProcInfo, !.GlobalData, TsccInfo),
|
|
ml_gen_info_bump_counters(!Info),
|
|
|
|
% Now we can safely go ahead and generate the wrapper function.
|
|
Context = dummy_context,
|
|
ml_gen_closure_wrapper(PredId, ProcId, ClosureKind, NumExtra, Context,
|
|
WrapperFuncRval, WrapperFuncType, !Info),
|
|
ml_gen_info_get_closure_wrapper_defns(!.Info, ClosureWrapperDefns),
|
|
ml_gen_info_get_global_data(!.Info, !:GlobalData),
|
|
ml_global_data_add_closure_wrapper_func_defns(ClosureWrapperDefns,
|
|
!GlobalData),
|
|
|
|
% The initializer for the wrapper is just the wrapper function's
|
|
% address, converted to mlds_generic_type (by boxing).
|
|
Initializer = init_obj(ml_box(WrapperFuncType, WrapperFuncRval))
|
|
).
|
|
|
|
:- func gen_init_proc_id(module_info, rtti_proc_label) = mlds_initializer.
|
|
|
|
gen_init_proc_id(ModuleInfo, RttiProcId) = Initializer :-
|
|
% Construct an rval for the address of this procedure
|
|
% (this is similar to ml_gen_proc_addr_rval).
|
|
ml_gen_pred_label_from_rtti(ModuleInfo, RttiProcId, PredLabel, PredModule),
|
|
ProcId = RttiProcId ^ rpl_proc_id,
|
|
ProcLabel = mlds_proc_label(PredLabel, ProcId),
|
|
FuncLabel = mlds_func_label(ProcLabel, proc_func),
|
|
QualFuncLabel = qual_func_label(PredModule, FuncLabel),
|
|
Params = ml_gen_proc_params_from_rtti_no_gc_stmts(ModuleInfo, RttiProcId),
|
|
Signature = mlds_get_func_signature(Params),
|
|
CodeAddr = mlds_code_addr(QualFuncLabel, Signature),
|
|
ProcAddrRval = ml_const(mlconst_code_addr(CodeAddr)),
|
|
|
|
% Convert the procedure address to a generic type. We need to use a
|
|
% generic type because since the actual type for the procedure will
|
|
% depend on how many type_info parameters it takes, which will depend
|
|
% on the type's arity.
|
|
ProcAddrArg = ml_box(mlds_func_type(Params), ProcAddrRval),
|
|
Initializer = init_obj(ProcAddrArg).
|
|
|
|
:- func gen_init_proc_id_from_univ(module_info, univ) =
|
|
mlds_initializer.
|
|
:- pragma consider_used(func(gen_init_proc_id_from_univ/2)).
|
|
|
|
gen_init_proc_id_from_univ(ModuleInfo, ProcLabelUniv) = Initializer :-
|
|
det_univ_to_type(ProcLabelUniv, ProcLabel),
|
|
Initializer = gen_init_proc_id(ModuleInfo, ProcLabel).
|
|
|
|
% Succeed iff the specified rtti_data is one that requires an
|
|
% explicit mlds_defn to define it.
|
|
%
|
|
:- pred real_rtti_data(rtti_data::in) is semidet.
|
|
|
|
real_rtti_data(RttiData) :-
|
|
not (
|
|
(
|
|
RttiData = rtti_data_type_info(TypeInfo),
|
|
TypeInfo = plain_arity_zero_type_info(_)
|
|
;
|
|
RttiData = rtti_data_pseudo_type_info(PseudoTypeInfo),
|
|
( PseudoTypeInfo = plain_arity_zero_pseudo_type_info(_)
|
|
; PseudoTypeInfo = type_var(_)
|
|
)
|
|
)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Conversion functions for builtin enumeration types.
|
|
%
|
|
% This handles sectag_locn, functor_subtype_info and type_ctor_rep. The rvals
|
|
% generated are just named constants in the private_builtin module, which the
|
|
% Mercury runtime is expected to define.
|
|
%
|
|
|
|
:- func gen_init_pred_or_func(pred_or_func) = mlds_initializer.
|
|
|
|
gen_init_pred_or_func(PredOrFunc) = Initializer :-
|
|
rtti.pred_or_func_to_target_string(PredOrFunc, TargetPrefixes, Name),
|
|
Initializer = gen_init_builtin_const(TargetPrefixes, Name).
|
|
|
|
:- func gen_init_sectag_locn(sectag_locn) = mlds_initializer.
|
|
|
|
gen_init_sectag_locn(Locn) = Initializer :-
|
|
rtti.sectag_locn_to_string(Locn, TargetPrefixes, Name),
|
|
Initializer = gen_init_builtin_const(TargetPrefixes, Name).
|
|
|
|
:- func gen_init_functor_subtype_info(functor_subtype_info) = mlds_initializer.
|
|
|
|
gen_init_functor_subtype_info(Info) = Initializer :-
|
|
rtti.functor_subtype_info_to_string(Info, TargetPrefixes,
|
|
Name),
|
|
Initializer = gen_init_builtin_const(TargetPrefixes, Name).
|
|
|
|
:- func gen_init_type_ctor_rep(type_ctor_data) = mlds_initializer.
|
|
|
|
gen_init_type_ctor_rep(TypeCtorData) = Initializer :-
|
|
rtti.type_ctor_rep_to_string(TypeCtorData, TargetPrefixes, Name),
|
|
Initializer = gen_init_builtin_const(TargetPrefixes, Name).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Ordering RTTI definitions.
|
|
%
|
|
|
|
order_mlds_rtti_defns_into_sccs(Defns) = OrdSccDefns :-
|
|
some [!Graph] (
|
|
digraph.init(!:Graph),
|
|
list.foldl2(add_rtti_defn_nodes, Defns, !Graph, map.init, NameMap),
|
|
list.foldl(add_rtti_defn_arcs, Defns, !Graph),
|
|
OrdSccSets = digraph.return_sccs_in_to_from_order(!.Graph)
|
|
),
|
|
list.map(set.to_sorted_list, OrdSccSets, OrdSccLists),
|
|
list.filter_map(keep_only_defns_in_name_map(NameMap),
|
|
OrdSccLists, OrdSccDefns).
|
|
|
|
:- pred add_rtti_defn_nodes(mlds_global_var_defn::in,
|
|
digraph(mlds_global_var_name)::in, digraph(mlds_global_var_name)::out,
|
|
map(mlds_global_var_name, mlds_global_var_defn)::in,
|
|
map(mlds_global_var_name, mlds_global_var_defn)::out) is det.
|
|
|
|
add_rtti_defn_nodes(GlobalVarDefn, !Graph, !NameMap) :-
|
|
GlobalVarName = GlobalVarDefn ^ mgvd_name,
|
|
digraph.add_vertex(GlobalVarName, _, !Graph),
|
|
map.det_insert(GlobalVarName, GlobalVarDefn, !NameMap).
|
|
|
|
:- pred add_rtti_defn_arcs(mlds_global_var_defn::in,
|
|
digraph(mlds_global_var_name)::in, digraph(mlds_global_var_name)::out)
|
|
is det.
|
|
|
|
add_rtti_defn_arcs(GlobalVarDefn, !Graph) :-
|
|
GlobalVarDefn =
|
|
mlds_global_var_defn(GlobalVarName, _, _, Type, Initializer, _GCStmt),
|
|
( if Type = mlds_rtti_type(_) then
|
|
add_rtti_defn_arcs_initializer(GlobalVarName, Initializer, !Graph)
|
|
else
|
|
unexpected($pred, "expected rtti entity_data")
|
|
).
|
|
|
|
:- pred add_rtti_defn_arcs_initializer(mlds_global_var_name::in,
|
|
mlds_initializer::in,
|
|
digraph(mlds_global_var_name)::in, digraph(mlds_global_var_name)::out)
|
|
is det.
|
|
|
|
add_rtti_defn_arcs_initializer(DefnGlobalVarName, Initializer, !Graph) :-
|
|
(
|
|
Initializer = init_obj(Rval),
|
|
add_rtti_defn_arcs_rval(DefnGlobalVarName, Rval, !Graph)
|
|
;
|
|
( Initializer = init_struct(_, Initializers)
|
|
; Initializer = init_array(Initializers)
|
|
),
|
|
list.foldl(add_rtti_defn_arcs_initializer(DefnGlobalVarName),
|
|
Initializers, !Graph)
|
|
;
|
|
Initializer = no_initializer
|
|
).
|
|
|
|
:- pred add_rtti_defn_arcs_rval(mlds_global_var_name::in, mlds_rval::in,
|
|
digraph(mlds_global_var_name)::in, digraph(mlds_global_var_name)::out)
|
|
is det.
|
|
|
|
add_rtti_defn_arcs_rval(DefnGlobalVarName, Rval, !Graph) :-
|
|
(
|
|
Rval = ml_lval(Lval),
|
|
add_rtti_defn_arcs_lval(DefnGlobalVarName, Lval, !Graph)
|
|
;
|
|
Rval = ml_const(Const),
|
|
add_rtti_defn_arcs_const(DefnGlobalVarName, Const, !Graph)
|
|
;
|
|
( Rval = ml_mkword(_Tag, SubRvalA)
|
|
; Rval = ml_box(_, SubRvalA)
|
|
; Rval = ml_unbox(_, SubRvalA)
|
|
; Rval = ml_cast(_, SubRvalA)
|
|
; Rval = ml_unop(_, SubRvalA)
|
|
; Rval = ml_vector_common_row_addr(_, SubRvalA)
|
|
),
|
|
add_rtti_defn_arcs_rval(DefnGlobalVarName, SubRvalA, !Graph)
|
|
;
|
|
Rval = ml_binop(_, SubRvalA, SubRvalB),
|
|
add_rtti_defn_arcs_rval(DefnGlobalVarName, SubRvalA, !Graph),
|
|
add_rtti_defn_arcs_rval(DefnGlobalVarName, SubRvalB, !Graph)
|
|
;
|
|
Rval = ml_mem_addr(SubLval),
|
|
add_rtti_defn_arcs_lval(DefnGlobalVarName, SubLval, !Graph)
|
|
;
|
|
( Rval = ml_scalar_common(_)
|
|
; Rval = ml_scalar_common_addr(_)
|
|
; Rval = ml_self(_)
|
|
)
|
|
).
|
|
|
|
:- pred add_rtti_defn_arcs_lval(mlds_global_var_name::in, mlds_lval::in,
|
|
digraph(mlds_global_var_name)::in, digraph(mlds_global_var_name)::out)
|
|
is det.
|
|
|
|
add_rtti_defn_arcs_lval(DefnGlobalVarName, Lval, !Graph) :-
|
|
(
|
|
( Lval = ml_field(_, SubRval, _, _, _)
|
|
; Lval = ml_mem_ref(SubRval, _)
|
|
),
|
|
add_rtti_defn_arcs_rval(DefnGlobalVarName, SubRval, !Graph)
|
|
;
|
|
( Lval = ml_target_global_var_ref(env_var_ref(_))
|
|
; Lval = ml_local_var(_, _)
|
|
; Lval = ml_global_var(_, _)
|
|
)
|
|
).
|
|
|
|
:- pred add_rtti_defn_arcs_const(mlds_global_var_name::in,
|
|
mlds_rval_const::in,
|
|
digraph(mlds_global_var_name)::in, digraph(mlds_global_var_name)::out)
|
|
is det.
|
|
|
|
add_rtti_defn_arcs_const(DefnGlobalVarName, Const, !Graph) :-
|
|
(
|
|
Const = mlconst_data_addr_rtti(_, RttiId),
|
|
GlobalVarName = gvn_rtti_var(RttiId),
|
|
digraph.add_vertices_and_edge(DefnGlobalVarName, GlobalVarName, !Graph)
|
|
;
|
|
( Const = mlconst_true
|
|
; Const = mlconst_false
|
|
; Const = mlconst_int(_)
|
|
; Const = mlconst_uint(_)
|
|
; Const = mlconst_int8(_)
|
|
; Const = mlconst_uint8(_)
|
|
; Const = mlconst_int16(_)
|
|
; Const = mlconst_uint16(_)
|
|
; Const = mlconst_int32(_)
|
|
; Const = mlconst_uint32(_)
|
|
; Const = mlconst_int64(_)
|
|
; Const = mlconst_uint64(_)
|
|
; Const = mlconst_enum(_, _)
|
|
; Const = mlconst_char(_)
|
|
; Const = mlconst_foreign(_, _, _)
|
|
; Const = mlconst_float(_)
|
|
; Const = mlconst_string(_)
|
|
; Const = mlconst_multi_string(_)
|
|
; Const = mlconst_named_const(_, _)
|
|
; Const = mlconst_code_addr(_)
|
|
; Const = mlconst_data_addr_local_var(_)
|
|
; Const = mlconst_data_addr_global_var(_, _)
|
|
; Const = mlconst_data_addr_tabling(_, _)
|
|
; Const = mlconst_null(_)
|
|
)
|
|
).
|
|
|
|
:- pred keep_only_defns_in_name_map(
|
|
map(mlds_global_var_name, mlds_global_var_defn)::in,
|
|
list(mlds_global_var_name)::in, list(mlds_global_var_defn)::out)
|
|
is semidet.
|
|
|
|
keep_only_defns_in_name_map(NameMap, SccDefns0, SccDefns) :-
|
|
list.filter_map(map.search(NameMap), SccDefns0, SccDefns),
|
|
% DO not return SCCs that contain zero definitions.
|
|
SccDefns = [_ | _].
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module ml_backend.rtti_to_mlds.
|
|
%-----------------------------------------------------------------------------%
|