Files
mercury/compiler/rtti.m
Zoltan Somogyi 4ccc3b32ac Cleanup of the type_ctor_infos and their components, to achieve two goals.
Estimated hours taken: 65

Cleanup of the type_ctor_infos and their components, to achieve two goals.
First, the new data structure is defined in strongly typed C, with only
two unions, whereas the old data structure was defined by a bunch of macros
that used casts all over the place. The new design should therefore make it
significantly easier to debug code that uses RTTI, and to get it right in
the first place. Second, the new data structures are logically organized,
whereas the old ones had several bad features (such as fixed fields coming
after variable-length arrays in "structures") required by backward
compatibility.

For the time being, the runtime system will be able to handle type_ctor_infos
using both the old and the new data structures, which are distinguished by
the type_ctor_info's version number.

To minimize the disruption caused by such bootstrapping, this change also
incorporates an improvement in the RTTI: for most pseudo_type_infos included
in the RTTI, it records information that allows the runtime system to tell
whether the pseudo_type_info is ground or not; if it is, then the runtime
need not scan the pseudo_type_info looking for type parameters to expand.
Based on statistics I have gathered, this will eliminate between half and two
thirds of all such scans when we do unification and comparison by RTTI.

This change does not impact the structures of typeinfos, base_typeclass_infos
or typeclass_infos.

runtime/mercury_type_info.h:
	Define the C types for the new type_ctor_info components.

	Update the C type for type_ctor_infos themselves, and the macros
	that act on it.

	Centralize the list of files that depend on type info representation
	here.

	Make the names of the two macros that give the number of (all kinds of)
	type info vars and the number of existential type info vars consistent.

runtime/mercury_std.h:
	Change a comment to refer to one of these renamed macros by its new
	name.

compiler/rtti.m:
compiler/rtti_out.m:
	New files: rtti.m defines new types that allow us to construct
	Mercury representations of the C structures we want to emit,
	and rtti_out.m converts those representations to C definitions.
	These files are intended to be independent of whether the backend
	is LLDS or MLDS. At the moment, there are several vestiges that
	tie them to LLDS, mostly due to (a) the lack of a shared common
	infrastructure between llds_out.m and mlds_to_c.m, and (b)
	the continued use of the old representation of (pseudo-) typeinfos
	as rvals. These concerns will be addressed in a future change.

compiler/llds.m:
	Update the definition of the comp_gen_c_data and data_addr types
	to account for the new RTTI structures.

compiler/llds_out.m:
	Update the code to output comp_gen_c_data and data_addr values
	to account for the new RTTI structures.

	Make some parts of the code more modular, so that rtti_out.m
	can use what used to be selected parts of predicates.

	Export several predicates for use by rtti_out.m. Some of these
	should later be moved to a file for infrastructure shared by
	llds_out.m and mlds_to_*.m. Others should be made internal again
	when the representation of typeinfos is made independent of the LLDS.

	Rename some predicates to better reflect their purpose.

compiler/base_type_layout.m:
compiler/base_type_info.m:
	These files are obsoleted by this change. They remain in CVS, but
	are no longer used. All of base_type_info.m has been moved into
	type_ctor_info.m, and so have the parts of base_type_layout.m
	that create the functors and layout structures inside type_ctor_infos;
	the remaining part of base_type_layout.m is now in pseudo_type_info.m.

compiler/pseudo_type_info.m:
	New file containing the code to create pseudo_type_infos from
	base_type_layout.m, slightly updated for the new compiler structure.

compiler/type_ctor_info.m:
        New module: almost total rewrite of the base_type_info.m and the
	relevant part of base_type_layout.m for the new data structure.

	Do not invoke base_typeclass_info.m, since the structures it creates
	are not parts of the type_ctor_infos.

compiler/ml_base_type_info.m:
	Comment out obsolete unfinished code. It should be replaced by
	calls to type_ctor_info, once type_ctor_info's dependence on LLDS
	has been eliminated.

compiler/hlds_module.m:
	Rename the data structure from which type_ctor_infos are generated.
	Delete the data structure from which type_ctor_layouts were generated,
	since it is redundant.

	Switch to using field names.

compiler/make_tags.m:
compiler/hlds_data.m:
	make_tags.m had code that duplicated much of the the functionality
	of an existing predicate in hlds_data.m. This change moves that
	predicate to hlds_data where it belongs, and gives it an appropriate
	name.

compiler/mercury_compile.m:
	Do not invoke the predicates that used to be in base_type_layouts
	directly; let type_ctor_info do it for the types for which it is
	appropriate.

	Do invoke base_typeclass_info directly.

compiler/dead_proc_elim.m:
compiler/llds_common.m:
compiler/opt_debug.m:
compiler/stack_layout.m:
compiler/unify_gen.m:
	Trivial changes to conform to the changes in the representation of
	compiler-generated C data.

compiler/notes/compiler_design.html:
	Updates to reflect the new files.

runtime/mercury_deep_copy_body.h:
runtime/mercury_tabling.c:
runtime/mercury_type_info.c:
	Provide alternate implementations of functionality that used the
	old functors and layout structures, to use the new ones instead
	if the relevant type_ctor_info's version number calls for it.
	In many cases, doing this cleanly required reducing the scopes of
	variables.

runtime/mercury_tabling.[ch]:
	Note where additional work on tabling of typeclass infos is needed,
	but do not do the work yet, since it would conflict with DJ's coming
	change.

library/std_util.m:
	Provide alternate implementations of functionality that used the
	old functors and layout structures, to use the new ones instead
	if the relevant type_ctor_info's version number calls for it.
	In many cases, doing this cleanly required reducing the scopes of
	variables.

	The predicates get_functor and construct take an integer argument
	that identifies a functor of a du type. The integer used to be
	the functor's ordinal number in the type definition, but this
	was not documented. It is now the functor's position in the list
	of the type's functors sorted first on name and then on arity.
	This functionality is potentially more useful, since io__read
	could do binary instead of linear search when looking for a given
	functor. This is an incompatibility, but a very minor one.

	Add a new predicate, get_functor_ordinal, to provide a way
	to convert lexicographic position into ordinal position.
	This is not used yet.

	Rename the two different kinds of variables named "info" so that
	one can tell them apart.

tests/hard_coded/construct.exp:
	Update the expected output of this test based on the new definition
	of the meaning of functor numbers in the get_functor and construct
	predicates in std_util.

tests/hard_coded/deep_copy.{m,exp}:
	Add some code to test the "type contains var" bit vector in du
	functor descriptions.

tests/hard_coded/existential_rtti.{m,exp}:
	Make the test case print out results as it goes along, to make it
	easier which subtask a core dump is coming from. Update the expected
	output accordingly.
2000-03-10 13:38:21 +00:00

427 lines
13 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 2000 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.
%-----------------------------------------------------------------------------%
%
% Definitions of data structures for representing run-time type information
% within the compiler. When output by rtti_out.m, values of most these types
% will correspond to the types defined in runtime/mercury_type_info.h;
% the documentation of those types can be found there.
%
% Eventually, this module will be independent of whether we are compiling
% to LLDS or MLDS. For the time being, it depends on LLDS.
%
% Author: zs.
%-----------------------------------------------------------------------------%
:- module rtti.
:- interface.
:- import_module llds, prog_data.
:- import_module bool, list, std_util.
% For a given du type and a primary tag value, this says where,
% if anywhere, the secondary tag is.
:- type sectag_locn
---> sectag_none
; sectag_local
; sectag_remote.
% For a given du family type, this says whether the user has defined
% their own unification predicate.
:- type equality_axioms
---> standard
; user_defined.
% For a notag or equiv type, this says whether the target type
% contains variables or not.
:- type equiv_type_inst
---> equiv_type_is_ground
; equiv_type_is_not_ground.
% The compiler is concerned with the type constructor representations
% of only the types it generates RTTI information for; it need not and
% does not know about the type_ctor_reps of types which have
% hand-defined RTTI.
:- type type_ctor_rep
---> enum(equality_axioms)
; du(equality_axioms)
; notag(equality_axioms, equiv_type_inst)
; equiv(equiv_type_inst)
; unknown.
% Different kinds of types have different type_layout information
% generated for them, and some have no type_layout info at all.
% This type represents values that will be put into the type_layout
% field of a MR_TypeCtorInfo.
:- type type_ctor_layout_info
---> enum_layout(
rtti_name
)
; notag_layout(
rtti_name
)
; du_layout(
rtti_name
)
; equiv_layout(
rval
)
; no_layout.
% Different kinds of types have different type_functors information
% generated for them, and some have no type_functors info at all.
% This type represents values that will be put into the type_functors
% field of a MR_TypeCtorInfo.
:- type type_ctor_functors_info
---> enum_functors(
rtti_name
)
; notag_functors(
rtti_name
)
; du_functors(
rtti_name
)
; no_functors.
% This type corresponds to the C type MR_DuExistLocn.
:- type exist_typeinfo_locn
---> plain_typeinfo(
int % The typeinfo is stored
% directly in the cell, at this
% offset.
)
; typeinfo_in_tci(
int, % The typeinfo is stored
% indirectly in the typeclass
% info stored at this offset
% in the cell.
int % To find the typeinfo inside
% the typeclass info structure,
% give this integer to the
% MR_typeclass_info_type_info
% macro.
).
% This type corresponds to the MR_DuPtagTypeLayout C type.
:- type du_ptag_layout
---> du_ptag_layout(
int, % number of function symbols
% sharing this primary tag
sectag_locn,
rtti_name % a vector of size num_sharers;
% element N points to the
% functor descriptor for the
% functor with secondary tag S;
% if sectag_locn is none, S=0
).
% Values of this type uniquely identify a type in the program.
:- type rtti_type_id
---> rtti_type_id(
module_name, % module name
string, % type ctor's name
arity % type ctor's arity
).
% Global data generated by the compiler. Usually readonly,
% with one exception: data containing code addresses must
% be initialized at runtime in grades that don't support static
% code initializers.
:- type rtti_data
---> exist_locns(
rtti_type_id, % identifies the type
int, % identifies functor in type
% The remaining argument of this function symbol
% corresponds to an array of MR_ExistTypeInfoLocns.
list(exist_typeinfo_locn)
)
; exist_info(
rtti_type_id, % identifies the type
int, % identifies functor in type
% The remaining arguments of this function symbol
% correspond to the MR_DuExistInfo C type.
int, % number of plain typeinfos
int, % number of typeinfos in tcis
int, % number of tcis
rtti_name % table of typeinfo locations
)
; field_names(
rtti_type_id, % identifies the type
int, % identifies functor in type
list(maybe(string)) % gives the field names
)
; enum_functor_desc(
rtti_type_id, % identifies the type
% The remaining arguments of this function symbol
% correspond one-to-one to the fields of
% MR_EnumFunctorDesc.
string, % functor name
int % ordinal number of functor
% (also its value)
)
; notag_functor_desc(
rtti_type_id, % identifies the type
% The remaining arguments of this function symbol
% correspond one-to-one to the fields of
% the MR_NotagFunctorDesc C type.
string, % functor name
rval % pseudo typeinfo of argument
)
; du_functor_desc(
rtti_type_id, % identifies the type
% The remaining arguments of this function symbol
% correspond one-to-one to the fields of
% the MR_DuFunctorDesc C type.
string, % functor name
int, % functor primary tag
int, % functor secondary tag
sectag_locn,
int, % ordinal number of functor
% in type definition
arity, % the functor's visible arity
int, % a bit vector of size at most
% contains_var_bit_vector_size
% which contains a 1 bit in the
% position given by 1 << N if
% the type of argument N
% contains variables (assuming
% that arguments are numbered
% from zero)
rval, % a vector of length arity
% containing the pseudo
% typeinfos of the arguments
maybe(rtti_name), % possibly a vector of length
% arity containing the names
% of the arguments, if any
maybe(rtti_name) % information about the
% existentially quantified
% type variables, if any
)
; enum_name_ordered_table(
rtti_type_id, % identifies the type
% The remaining argument of this function symbol
% corresponds to the functors_enum alternative of
% the MR_TypeFunctors C type.
list(rtti_name)
)
; enum_value_ordered_table(
rtti_type_id, % identifies the type
% The remaining argument of this function symbol
% corresponds to the MR_EnumTypeLayout C type.
list(rtti_name)
)
; du_name_ordered_table(
rtti_type_id, % identifies the type
% The remaining argument of this function symbol
% corresponds to the functors_du alternative of
% the MR_TypeFunctors C type.
list(rtti_name)
)
; du_stag_ordered_table(
rtti_type_id, % identifies the type
int, % primary tag value
% The remaining argument of this function symbol
% corresponds to the MR_sectag_alternatives field
% of the MR_DuPtagTypeLayout C type.
list(rtti_name)
)
; du_ptag_ordered_table(
rtti_type_id, % identifies the type
% The remaining argument of this function symbol
% corresponds to the elements of the MR_DuTypeLayout
% C type.
list(du_ptag_layout)
)
; type_ctor_info(
% The arguments of this function symbol correspond
% one-to-one to the fields of the MR_TypeCtorInfo
% C type.
rtti_type_id, % identifies the type
maybe(code_addr), % unify
maybe(code_addr), % index
maybe(code_addr), % compare
type_ctor_rep,
maybe(code_addr), % solver
maybe(code_addr), % init
int, % RTTI version number
int, % num of ptags used if ctor_rep
% is DU or DUUSEREQ
int, % number of functors in type
type_ctor_functors_info,% the functor layout
type_ctor_layout_info, % the layout table
maybe(rtti_name), % the type's hash cons table
maybe(code_addr) % prettyprinter
).
:- type rtti_name
---> exist_locns(int) % functor ordinal
; exist_info(int) % functor ordinal
; field_names(int) % functor ordinal
; enum_functor_desc(int) % functor ordinal
; notag_functor_desc
; du_functor_desc(int) % functor ordinal
; enum_name_ordered_table
; enum_value_ordered_table
; du_name_ordered_table
; du_stag_ordered_table(int) % primary tag
; du_ptag_ordered_table
; type_ctor_info
; type_hashcons_pointer.
% Return the C variable name of the RTTI data structure identified
% by the input arguments.
:- pred rtti__addr_to_string(rtti_type_id::in, rtti_name::in, string::out)
is det.
% Return the C representation of a secondary tag location.
:- pred rtti__sectag_locn_to_string(sectag_locn::in, string::out) is det.
% Return the C representation of a type_ctor_rep value.
:- pred rtti__type_ctor_rep_to_string(type_ctor_rep::in, string::out) is det.
% Return true iff the given type of RTTI data structure includes
% code addresses.
:- pred rtti__name_would_include_code_address(rtti_name::in, bool::out) is det.
:- implementation.
:- import_module llds_out.
:- import_module string.
rtti__addr_to_string(RttiTypeId, RttiName, Str) :-
RttiTypeId = rtti_type_id(ModuleName0, TypeName0, TypeArity),
llds_out__sym_name_mangle(ModuleName0, ModuleName),
llds_out__name_mangle(TypeName0, TypeName),
string__int_to_string(TypeArity, A_str),
(
RttiName = exist_locns(Ordinal),
string__int_to_string(Ordinal, O_str),
string__append_list([ModuleName, "__exist_locns_",
TypeName, "_", A_str, "_", O_str], Str)
;
RttiName = exist_info(Ordinal),
string__int_to_string(Ordinal, O_str),
string__append_list([ModuleName, "__exist_info_",
TypeName, "_", A_str, "_", O_str], Str)
;
RttiName = field_names(Ordinal),
string__int_to_string(Ordinal, O_str),
string__append_list([ModuleName, "__field_names_",
TypeName, "_", A_str, "_", O_str], Str)
;
RttiName = enum_functor_desc(Ordinal),
string__int_to_string(Ordinal, O_str),
string__append_list([ModuleName, "__enum_functor_desc_",
TypeName, "_", A_str, "_", O_str], Str)
;
RttiName = notag_functor_desc,
string__append_list([ModuleName, "__notag_functor_desc_",
TypeName, "_", A_str], Str)
;
RttiName = du_functor_desc(Ordinal),
string__int_to_string(Ordinal, O_str),
string__append_list([ModuleName, "__du_functor_desc_",
TypeName, "_", A_str, "_", O_str], Str)
;
RttiName = enum_name_ordered_table,
string__append_list([ModuleName, "__enum_name_ordered_",
TypeName, "_", A_str], Str)
;
RttiName = enum_value_ordered_table,
string__append_list([ModuleName, "__enum_value_ordered_",
TypeName, "_", A_str], Str)
;
RttiName = du_name_ordered_table,
string__append_list([ModuleName, "__du_name_ordered_",
TypeName, "_", A_str], Str)
;
RttiName = du_stag_ordered_table(Ptag),
string__int_to_string(Ptag, P_str),
string__append_list([ModuleName, "__du_stag_ordered_",
TypeName, "_", A_str, "_", P_str], Str)
;
RttiName = du_ptag_ordered_table,
string__append_list([ModuleName, "__du_ptag_ordered_",
TypeName, "_", A_str], Str)
;
RttiName = type_ctor_info,
string__append_list([ModuleName, "__type_ctor_info_",
TypeName, "_", A_str], Str)
;
RttiName = type_hashcons_pointer,
string__append_list([ModuleName, "__hashcons_ptr_",
TypeName, "_", A_str], Str)
).
rtti__sectag_locn_to_string(sectag_none, "MR_SECTAG_NONE").
rtti__sectag_locn_to_string(sectag_local, "MR_SECTAG_LOCAL").
rtti__sectag_locn_to_string(sectag_remote, "MR_SECTAG_REMOTE").
rtti__type_ctor_rep_to_string(du(standard),
"MR_TYPECTOR_REP_DU").
rtti__type_ctor_rep_to_string(du(user_defined),
"MR_TYPECTOR_REP_DU_USEREQ").
rtti__type_ctor_rep_to_string(enum(standard),
"MR_TYPECTOR_REP_ENUM").
rtti__type_ctor_rep_to_string(enum(user_defined),
"MR_TYPECTOR_REP_ENUM_USEREQ").
rtti__type_ctor_rep_to_string(notag(standard, equiv_type_is_not_ground),
"MR_TYPECTOR_REP_NOTAG").
rtti__type_ctor_rep_to_string(notag(user_defined, equiv_type_is_not_ground),
"MR_TYPECTOR_REP_NOTAG_USEREQ").
rtti__type_ctor_rep_to_string(notag(standard, equiv_type_is_ground),
"MR_TYPECTOR_REP_NOTAG_GROUND").
rtti__type_ctor_rep_to_string(notag(user_defined, equiv_type_is_ground),
"MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ").
rtti__type_ctor_rep_to_string(equiv(equiv_type_is_not_ground),
"MR_TYPECTOR_REP_EQUIV").
rtti__type_ctor_rep_to_string(equiv(equiv_type_is_ground),
"MR_TYPECTOR_REP_EQUIV_GROUND").
rtti__type_ctor_rep_to_string(unknown,
"MR_TYPECTOR_REP_UNKNOWN").
rtti__name_would_include_code_address(exist_locns(_), no).
rtti__name_would_include_code_address(exist_info(_), no).
rtti__name_would_include_code_address(field_names(_), no).
rtti__name_would_include_code_address(enum_functor_desc(_), no).
rtti__name_would_include_code_address(notag_functor_desc, no).
rtti__name_would_include_code_address(du_functor_desc(_), no).
rtti__name_would_include_code_address(enum_name_ordered_table, no).
rtti__name_would_include_code_address(enum_value_ordered_table, no).
rtti__name_would_include_code_address(du_name_ordered_table, no).
rtti__name_would_include_code_address(du_stag_ordered_table(_), no).
rtti__name_would_include_code_address(du_ptag_ordered_table, no).
rtti__name_would_include_code_address(type_ctor_info, yes).
rtti__name_would_include_code_address(type_hashcons_pointer, no).