[m-rev.] for review: a step towards Mercury-level RTTI for Java and IL

Peter Ross pro at missioncriticalit.com
Fri Jun 28 01:23:13 AEST 2002


On Thu, May 16, 2002 at 02:20:47AM +1000, Zoltan Somogyi wrote:
> 
> For review by Fergus and/or Pete.
> 
> Zoltan.
> 
> Another step towards RTTI in Mercury.
> 
> This step redefines the representation of type_ctor_infos inside the
> compiler to be identical to the representation we will need for
> efficient interpretation of RTTI data structures in Mercury, following
> on from an earlier step which did the same for (pseudo)typeinfos.
> 
> Instead of the type_ctor_info being broken down into its components in
> type_ctor_info.m, the breakdown process is now performed in rtti_out.m
> (for the LLDS backend) and rtti_to_mlds.m (for the MLDS backend).
> Eventually, the IL and Java backends will stop using rtti_to_mlds.m
> for this purpose, and will instead write out the type_ctor_data
> structures as static data to be interpreted directly.
> 

> Index: compiler/rtti.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/rtti.m,v
> retrieving revision 1.18
> diff -u -b -r1.18 rtti.m
> --- compiler/rtti.m	12 Apr 2002 01:24:13 -0000	1.18
> +++ compiler/rtti.m	13 May 2002 10:00:31 -0000
> +
> +	% A type_ctor_details structure contains all the information that the
> +	% runtime system needs to know about the data representation scheme
> +	% used by a type constructor.
> +	%
> +	% The alternatives that correspond to discriminated union types have
> +	% four kinds of information.
> +	%
> +	% First, an indication of whether the type has user-defined equality or
> +	% not.
> +	%
> +	% Second, a list of descriptors containing all the function symbols
> +	% defined by the type, in declaration order.
> +	%
> +	% Third, a table that allows the runtime system to map a value in
> +	% memory to a printable representation (i.e. to implement the
> +	% deconstruct operation).
> +	%
> +	% Fourth, a table that allows the runtime system to map a printable
> +	% representation to a value in memory (i.e. to implement the
> +	% construct operation).
> +	%
> +	% For types in which some function symbols are represented by reserved
> +	% addresses, the third component is in two parts: a list of function
> +	% symbols so represented, and a table indexed by the primary tag for
> +	% all the other function symbols. The runtime system must check every
> +	% element on the list before looking at the primary tag.
> +	%
> +	% For notag types, the single functor descriptor fills the roles of
> +	% the second, third and fourth components.
> +
> +:- type type_ctor_details
> +	--->	enum(
> +			enum_axioms		:: equality_axioms,
> +			enum_functors		:: list(enum_functor),
> +			enum_value_table	:: map(int, enum_functor),
> +			enum_name_table		:: map(string, enum_functor)
> +		)
> +	;	du(
> +			du_axioms		:: equality_axioms,
> +			du_functors		:: list(du_functor),
> +			du_value_table		:: ptag_map,
> +			du_name_table		:: map(string, map(int,
> +							du_functor))
> +		)
> +	;	reserved(
> +			res_axioms		:: equality_axioms,
> +			res_functors		:: list(maybe_reserved_functor),
> +			res_value_table_res	:: list(reserved_functor),
> +			res_value_table_du	:: ptag_map,
> +			res_name_table		:: map(string, map(int,
> +							maybe_reserved_functor))
> +		)
> +	;	notag(
> +			notag_axioms		:: equality_axioms,
> +			notag_functor		:: notag_functor
> +		)

A short description of these four alternatives added above would be useful.

> +	;	eqv(
> +			eqv_type		:: rtti_maybe_pseudo_type_info
> +		)
> +	;	builtin(
> +			builtin_ctor		:: builtin_ctor
> +		)
> +	;	impl_artifact(
> +			impl_ctor		:: impl_ctor
> +		)
> +	;	foreign.

> +
> +	% Descriptor for a functor in reserved address type.
> +	%
> +	% This type mostly corresponds to the C union
> +	% MR_MaybeResAddrFunctorDesc.

Why only mostly corresponds to MR_MaybeResAddrFunctorDesc?  A
description of why would be useful.
> +
> +	% Describes the types of the existentially types arguments of a
> +	% discriminated union functor.
> +	%
> +	% This type corresponds to the C type MR_DuExistInfo.

s/existentially types/existentially typed/

> @@ -163,278 +285,85 @@
> +	% These tables let the runtime system interpret values in memory
> +	% of general discriminated union types.
> +	%
> +	% The runtime system should first use the primary tag to index into
> +	% the type's ptag_map. It can then find the location (if any) of the
> +	% secondary tag, and use the secondary tag (or zero if there isn't one)
> +	% to index into the stag_map to find the functor descriptor.
> +	%
> +	% The type sectag_table corresponds to the C type MR_DuPtagLayout.
> +	% The two maps are implemented in C as simple arrays.
>  
> +:- type ptag_map	== map(int, sectag_table).	% key is primary tag
> +:- type stag_map	== map(int, du_functor).	% key is secondary tag
>  
> +:- type	sectag_table
> +	--->	sectag_table(
> +			sectag_locn		:: sectag_locn,
> +			sectag_num_sharers	:: int,
> +			sectag_map		:: stag_map
> +		).
>  
> +	% Describes the location of the secondary tag for a given primary tag
> +	% value in a given type.
> +:- type sectag_locn
> +	--->	sectag_none
> +	;	sectag_local
> +	;	sectag_remote.
>  
> +	% Describes the location of the secondary tag and its value for a
> +	% given functor in a given type.
> +:- type sectag_and_locn
> +	--->	sectag_none
> +	;	sectag_local(int)
> +	;	sectag_remote(int).
>  
> +	% Information about an argument of a functor in a discriminated union
> +	% type.
> +:- type du_arg_info
> +	--->	du_arg_info(
> +			du_arg_name	:: maybe(string),
> +			du_arg_type	:: rtti_maybe_pseudo_type_info_or_self
>  		).
>  
> +	% An rtti_maybe_pseudo_type_info identifies the type of a function
> +	% symbol's argument. If the type of the argument is the same as the
> +	% type of the whole term, it should be bound to self. Otherwise, if
> +	% the argument's type is ground, it should be bound to plain; if it
> +	% is non-ground, it should be bound to pseudo.
> +:- type rtti_maybe_pseudo_type_info_or_self
> +	--->	pseudo(rtti_pseudo_type_info)
> +	;	plain(rtti_type_info)
> +	;	self.
> +
> +	% The list of type constructors for types that are built into the
> +	% Mercury language. The compiler never creates type_ctor_datas for
> +	% these, but RTTI predicates implemented in Mercury will need to
> +	% know about them.
> +:- type builtin_ctor
> +	--->	int
> +	;	float
> +	;	char
> +	;	string
> +	;	univ
> +	;	void
> +	;	c_pointer.	% maybe more to come later
> +
> +	% The list of type constructors that are used behind the scenes by
> +	% the Mercury implementation. The compiler never creates
> +	% type_ctor_datas for these, but RTTI predicates implemented
> +	% in Mercury will need to know about them.
> +:- type impl_ctor
> +	--->	sp
> +	;	hp
> +	;	maxfr
> +	;	curfr.		% maybe more to come later
> +
> +%-----------------------------------------------------------------------------%
> +%
> +% The data structures representing type class dictionaries.
>  
>  	% A base_typeclass_info holds information about a typeclass instance.
>  	% See notes/type_class_transformation.html for details.
> @@ -521,6 +432,88 @@
>  			is_special_pred_instance	::	bool
>  		).
>  
> +%-----------------------------------------------------------------------------%
> +%
> +% The data structures representing the XXX
> +

Looks like you are missing something here.

> +	% 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
> +	--->	type_ctor_info(
> +			type_ctor_data
> +		)
> +	;	type_info(
> +			rtti_type_info
> +		)
> +	;	pseudo_type_info(
> +			rtti_pseudo_type_info
> +		)
> +	;	base_typeclass_info(
> +			module_name,	% module containing instance decl.
> +			class_id,	% specifies class name & class arity
> +			string,		% encodes the names and arities of the
> +					% types in the instance declaration
> +
> +			base_typeclass_info
> +		).
> +
> Index: compiler/rtti_out.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/rtti_out.m,v
> retrieving revision 1.29
> diff -u -b -r1.29 rtti_out.m
> --- compiler/rtti_out.m	24 Apr 2002 07:37:32 -0000	1.29
> +++ compiler/rtti_out.m	15 May 2002 09:11:21 -0000
> @@ -271,421 +556,255 @@
>  
> +:- pred output_du_arg_types(rtti_type_ctor::in, int::in,
> +	list(rtti_maybe_pseudo_type_info_or_self)::in,
>  	decl_set::in, decl_set::out, io__state::di, io__state::uo) is det.
>  
> +output_du_arg_types(RttiTypeCtor, Ordinal, ArgTypes, DeclSet0, DeclSet) -->
> +	list__foldl2(output_maybe_pseudo_type_info_or_self_defn, ArgTypes,
>  		DeclSet0, DeclSet1),
> +	{ ArgTypeDatas = list__map(maybe_pseudo_type_info_or_self_to_rtti_data,
> +		ArgTypes) },
> +	output_rtti_datas_decls(ArgTypeDatas, "", "", 0, _,
>  		DeclSet1, DeclSet2),
> +	output_generic_rtti_data_defn_start(RttiTypeCtor, field_types(Ordinal),
> +		DeclSet2, DeclSet),
> +	io__write_string(" = {\n"),
> +	{ ArgRttiDatas = list__map(maybe_pseudo_type_info_or_self_to_rtti_data,
> +		ArgTypes) },
>  	output_cast_addr_of_rtti_datas("(MR_PseudoTypeInfo) ", ArgRttiDatas),
> +	io__write_string("};\n").
> +
Could this list be empty?  If so you need to put a dummy entry in here.

> +:- pred output_du_arg_names(rtti_type_ctor::in, int::in,
> +	list(maybe(string))::in, decl_set::in, decl_set::out,
> +	io__state::di, io__state::uo) is det.
> +
> +output_du_arg_names(RttiTypeCtor, Ordinal, MaybeNames, DeclSet0, DeclSet) -->
> +	output_generic_rtti_data_defn_start(RttiTypeCtor, field_names(Ordinal),
> +		DeclSet0, DeclSet),
> +	io__write_string(" = {\n"),
> +	output_maybe_quoted_strings(MaybeNames),
> +	io__write_string("};\n").
> +
Again what if there is are no names?

Maybe it would be a good idea for each place where we output an array to check
that the array isn't empty.  Maybe some sort of utility predicate, which takes
as an argument the dummy value to put output.

> Index: compiler/rtti_to_mlds.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/rtti_to_mlds.m,v
> retrieving revision 1.31
> diff -u -b -r1.31 rtti_to_mlds.m
> --- compiler/rtti_to_mlds.m	24 Apr 2002 07:37:33 -0000	1.31
> +++ compiler/rtti_to_mlds.m	15 May 2002 09:16:54 -0000
> @@ -689,22 +1109,25 @@
>  % the type names mentioned here should be defined in runtime/mercury.h
>  % (or in some header file that is included by that one)
>  
> +% XXX factor out code common with rtti_name_c_type in rtti_out.m
> +% XXX check res_addr entries

Have you checked this?

>  mlds_rtti_type_name(exist_locns(_)) =		"DuExistLocn".
>  mlds_rtti_type_name(exist_info(_)) =		"DuExistInfo".
>  mlds_rtti_type_name(field_names(_)) =		"ConstString".
>  mlds_rtti_type_name(field_types(_)) =		"PseudoTypeInfo".
> -mlds_rtti_type_name(reserved_addrs) =		"ReservedAddrs".
> -mlds_rtti_type_name(reserved_addr_functors) =	"ReservedAddrFunctors".
> +mlds_rtti_type_name(res_addrs) =		"ReservedAddrs".
> +mlds_rtti_type_name(res_addr_functors) =	"ReservedAddrFunctors".
>  mlds_rtti_type_name(enum_functor_desc(_)) =	"EnumFunctorDesc".
>  mlds_rtti_type_name(notag_functor_desc) =	"NotagFunctorDesc".
>  mlds_rtti_type_name(du_functor_desc(_)) =	"DuFunctorDesc".
> -mlds_rtti_type_name(reserved_addr_functor_desc(_)) = "ReservedAddrFunctorDesc".
> +mlds_rtti_type_name(res_functor_desc(_)) =	"ReservedAddrFunctorDesc".
>  mlds_rtti_type_name(enum_name_ordered_table) =	"EnumFunctorDescPtr".
>  mlds_rtti_type_name(enum_value_ordered_table) =	"EnumFunctorDescPtr".
>  mlds_rtti_type_name(du_name_ordered_table) =	"DuFunctorDescPtr".
>  mlds_rtti_type_name(du_stag_ordered_table(_)) =	"DuFunctorDescPtr".
>  mlds_rtti_type_name(du_ptag_ordered_table) =	"DuPtagLayout".
> -mlds_rtti_type_name(reserved_addr_table) =	"ReservedAddrTypeDesc".
> +mlds_rtti_type_name(res_value_ordered_table) =	"ReservedAddrTypeDesc".
> +mlds_rtti_type_name(res_name_ordered_table) =	"ReservedAddrTypeDesc".
>  mlds_rtti_type_name(type_ctor_info) =		"TypeCtorInfo_Struct".
>  mlds_rtti_type_name(base_typeclass_info(_, _, _)) = "BaseTypeclassInfo".
>  mlds_rtti_type_name(type_info(TypeInfo)) =
> Index: compiler/type_ctor_info.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/type_ctor_info.m,v
> retrieving revision 1.27
> diff -u -b -r1.27 type_ctor_info.m
> --- compiler/type_ctor_info.m	13 May 2002 09:44:20 -0000	1.27
> +++ compiler/type_ctor_info.m	15 May 2002 15:35:54 -0000
> @@ -44,6 +44,9 @@
>  :- pred type_ctor_info__generate_rtti(module_info::in, list(rtti_data)::out)
>  	is det.
>  
> +:- func compute_contains_var_bit_vector(
> +	list(rtti_maybe_pseudo_type_info_or_self)) = int.
> +

A comment explaining what this function does would be useful.  From my
reading of the name, I would assume it returns a bool.

>  :- implementation.
>  
>  :- import_module backend_libs__rtti, backend_libs__pseudo_type_info.
> @@ -163,126 +178,47 @@
>  	(
>  		TypeBody = abstract_type,
> -		TypeCtorRep = unknown,
> -		NumFunctors = -1,
> -		FunctorsInfo = no_functors,
> -		LayoutInfo = no_layout,
> -		TypeTables = [],
> -		NumPtags = -1
> +		error("type_ctor_info__gen_type_ctor_data: abstract_type")
>  	;
>  			% We treat foreign_types as equivalent to the
>  			% type builtin__c_pointer.

This comment needs to be removed.

>  		TypeBody = foreign_type(_, _),
> -		Ctxt = term__context("builtin.m", 1),
> -		Type = functor(term__atom(":"), [
> -				functor(term__atom("builtin"), [], Ctxt),
> -				functor(term__atom("c_pointer"), [], Ctxt)],
> -				Ctxt),
> -		gen_layout_info_eqv_type(Type, TypeArity,
> -				TypeCtorRep, NumFunctors, FunctorsInfo,
> -				LayoutInfo, NumPtags, TypeTables)
> +		Details = foreign
>  	;

> @@ -652,178 +487,96 @@
>  % groups the rttis into groups depending on their primary tags; this is
>  % how the type layout structure is constructed.
>  
> +:- type maybe_reserved_rep
> +	--->	reserved_rep(
> +			reserved_address
> +		)
> +	;	du_rep(
> +			du_rep
>  		).
>  
> +:- pred type_ctor_info__make_maybe_res_functors(list(constructor)::in,
> +	int::in, cons_tag_values::in, int::in, module_info::in,
> +	list(maybe_reserved_functor)::out) is det.
> +
> +type_ctor_info__make_maybe_res_functors([], _, _, _, _, []).
> +type_ctor_info__make_maybe_res_functors([Functor | Functors], NextOrdinal,
> +		ConsTagMap, TypeArity, ModuleInfo,
> +		[MaybeResFunctor | MaybeResFunctors]) :-
> +	Functor = ctor(ExistTvars, Constraints, SymName, ConstructorArgs),
> +	list__length(ConstructorArgs, Arity),
>  	unqualify_name(SymName, FunctorName),
> +	make_cons_id_from_qualified_sym_name(SymName, ConstructorArgs, ConsId),
>  	map__lookup(ConsTagMap, ConsId, ConsTag),
> +	type_ctor_info__process_cons_tag(ConsTag, ConsRep),
> +	list__map(type_ctor_info__generate_du_arg_info(TypeArity, ExistTvars),
> +		ConstructorArgs, ArgInfos),
>  	( ExistTvars = [] ->
> +		MaybeExistInfo = no
>  	;
>  		module_info_classes(ModuleInfo, ClassTable),
> +		type_ctor_info__generate_exist_into(ExistTvars,
> +			Constraints, ClassTable, ExistInfo),
>  		MaybeExistInfo = yes(ExistInfo)
>  	),
> +	(	
> +		ConsRep = du_rep(DuRep),
> +		DuFunctor = du_functor(FunctorName, Arity, NextOrdinal,
> +			DuRep, ArgInfos, MaybeExistInfo),
> +		MaybeResFunctor = du_func(DuFunctor)
> +	;
> +		ConsRep = reserved_rep(ResRep),
> +		require(unify(Arity, 0),
> +			"type_ctor_info__make_maybe_res_functors: bad arity"),
> +		require(unify(ArgInfos, []),
> +			"type_ctor_info__make_maybe_res_functors: bad arsg"),

s/arsg/args/

> +		require(unify(MaybeExistInfo, no),
> +			"type_ctor_info__make_maybe_res_functors: bad exist"),
> +		ResFunctor = reserved_functor(FunctorName, NextOrdinal,
> +			ResRep),
> +		MaybeResFunctor = res_func(ResFunctor)
> +	),
> +	type_ctor_info__make_maybe_res_functors(Functors, NextOrdinal + 1,
> +		ConsTagMap, TypeArity, ModuleInfo, MaybeResFunctors).
>  
> -:- pred type_ctor_info__process_cons_tag(cons_tag::in, rtti_name::in,
> -		cons_representation::out, tag_map::in, tag_map::out) is det.
> +:- pred type_ctor_info__process_cons_tag(cons_tag::in, maybe_reserved_rep::out)
> +	is det.
>  

> Index: library/map.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/library/map.m,v
> retrieving revision 1.80
> diff -u -b -r1.80 map.m
> --- library/map.m	24 May 2001 02:32:28 -0000	1.80
> +++ library/map.m	11 May 2002 10:34:17 -0000
> @@ -37,6 +37,8 @@
>  :- func map__init = map(K, V).
>  :- mode map__init = uo is det.
>  
> +:- func map__init_singleton(K, V) = map(K, V).
> +
>  	% Check whether a map is empty.
>  :- pred map__is_empty(map(_,_)).
>  :- mode map__is_empty(in) is semidet.
> @@ -786,6 +788,9 @@
>  
>  map__init = M :-
>  	map__init(M).
> +
> +map__init_singleton(K, V) =
> +	map__det_insert(map__init, K, V).
>  
>  map__search(M, K) = V :-
>  	map__search(M, K, V).

This change is not mentioned in the log message.  The added predicate
should also be documented in the NEWS file.

--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list