Files
mercury/compiler/ml_util.m
Zoltan Somogyi 941be20e27 Type_desc__get_functor looks up the types of the arguments of a function
Estimated hours taken: 16
Branches: main

Type_desc__get_functor looks up the types of the arguments of a function
symbol. This predicate used to abort when an argument has an existential
type. This diff makes type_desc__get_functor work even in that case.
However, since in such cases the type of an argument is not a ground type,
this diff has to add the concept of a pseudo_type_desc, a descriptor for
a not necessarily ground type. Pseudo_type_descs are implemented as
MR_PseudoTypeInfos.

runtime/mercury_type_info.[ch]:
	Add new macros to operate on pseudo_type_infos. Most have a structure
	modelled on corresponding macros operating on type_infos.

	Provide versions of MR_get_arg_type_info, MR_compare_type_info,
	MR_unify_type_info, MR_collapse_equivalences,
	MR_type_params_vector_to_list, MR_create_type_info and
	MR_create_type_info_maybe_existq that work on pseudo_type_infos,
	not type_infos.

	Change MR_pseudo_type_info_vector_to_type_info_list, which implements
	the core of get_functor, to return pseudo_type_infos instead of
	type_infos, and rename it to reflect this fact.

	Change to four-space indentation to reduce the number of lines
	that have to be wrapped.

runtime/mercury_make_type_info_body.h:
	Generalize the code for creating type_infos to also be handle
	pseudo_type_infos.

	Change to four-space indentation to reduce the number of lines
	that have to be wrapped.

runtime/mercury_type_desc.[ch]:
	Provide versions of MR_make_type_ctor_desc and MR_type_ctor_and_args
	that work on pseudo_type_infos, not type_infos.

	Change to four-space indentation to reduce the number of lines
	that have to be wrapped.

runtime/mercury_builtin_types.[ch]:
runtime/mercury_builtin_types_proc_layouts.h:
runtime/mercury_hlc_types.h:
runtime/mercury_unify_compare_body.h:
	Add the C types, global variables and functions necessary for the
	new builtin Mercury type pseudo_type_desc. This type must be builtin,
	because its structure (MR_PseudoTypeInfo) is defined in C, and as such
	cannot be unified, compared, deconstructed etc without hand-written
	C code.

runtime/mercury_deep_copy.c:
runtime/mercury_deep_copy_body.h:
	Handle the copying of pseudo_type_infos/pseudo_type_descs. This code
	is almost the same as the code to copy type_infos, but must of course
	handle type variables, and the arguments are themselves copied as
	pseudo_type_infos, not type_infos.

runtime/mercury_types.h:
	Since deep copy needs to create pseudo_type_infos, provide a version
	of the MR_PseudoTypeInfo type without const.

runtime/mercury_construct.c:
runtime/mercury_deconstruct.c:
	Handle pseudo_type_descs just as we handle type_descs: neither can be
	constructed, nor do they have function symbols with named arguments.

runtime/mercury_ml_expand_body.c:
	Provide code to deconstruct pseudo_type_descs. This code is almost
	the same as the code to deconstruct type_descs, but must of course
	handle type variables, and the arguments are themselves
	pseudo_type_descs, not type_descs.

runtime/mercury_tabling.c:
	Catch attempts to table pseudo_type_infos.

runtime/mercury_tags.h:
	Add macros for constructing lists of
	pseudo_type_infos/pseudo_type_descs.

runtime/mercury_wrapper.[ch]:
	Define global variables holding the addresses of the typeinfos for
	describing pseudo_type_descs and lists of pseudo_type_descs.

runtime/mercury_init.c:
	Add the extern declarations required by new code in mkinit.c.

util/mkinit.c:
	Make the addresses of the typeinfos for describing pseudo_type_descs
	and lists of pseudo_type_descs, defined in the library, known to the
	runtime.

library/type_desc.m:
	Add a new builtin type, pseudo_type_desc, for describing possibly
	nonground types.

	Add utility predicates for operating on pseudo_type_descs.

library/private_builtin.m:
	Handle the new builtin type.

	Add builtin typeinfos for describing pseudo_type_descs and lists of
	pseudo_type_descs, since some functions in the runtime need them
	for memory profiling.

library/rtti_implementation.m:
	Handle the new builtin type, mostly by ignoring it, since the backends
	that use this module do not have any notion of pseudo_type_infos.

	Bring the module up to date with our formatting guidelines.

library/construct.m:
	Make get_functor return a list of pseudo_type_descs instead of
	type_descs.

	Change the name of the version of get_functor that returns argument
	names, to distinguish it from the base version by more than just the
	arity.

	Make the order of predicates more logical.

library/std_util.m:
	Change the name of the version of get_functor that returns argument
	names, to distinguish it from the base version by more than just the
	arity.

	However, this name change is effectively the only change: both
	get_functor and get_functor_with_names still return lists of
	type_descs. This means that they will throw exceptions in the presence
	of existential types, but code using them need no algorithmic changes.

library/term.m:
library/term_to_xml.m:
	Add module qualifiers as necessary; no algorithmic changes.

library/list.m:
	Add two general-purpose predicates, all_true and all_false,
	for use in the other library modules.

compiler/ml_util.m:
compiler/mlds_to_gcc.m:
compiler/rtti.m:
compiler/type_ctor_info.m:
	Make sure we handle the new builtin type as a builtin type, and not
	try to have the compiler create a type_ctor_info for it.

deep_profiler/canonical.m:
	Delete the local definition of all_true.

tests/hard_coded/construct_test.{m,exp}:
	Update this test case to test the ability to retrieve the names of the
	fields of function symbols with existential types.

	Add module qualifications as necessary.

tests/hard_coded/construct_test_exist.{m,exp}:
	Add a tougher test case to print the types of the arguments of
	function symbols with existential types.

tests/hard_coded/Mmakefile:
	Add the new test case, and sort the names of the tests.
2004-12-14 01:07:32 +00:00

640 lines
21 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 1999-2004 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
% File: ml_util.m
% Main author: fjh, trd
% This module contains utility predicates for manipulating the MLDS.
%-----------------------------------------------------------------------------%
:- module ml_backend__ml_util.
:- interface.
:- import_module libs__globals. % for foreign_language
:- import_module ml_backend__mlds.
:- import_module parse_tree__prog_data.
:- import_module list, std_util.
%-----------------------------------------------------------------------------%
% succeeds iff the definitions contain the entry point to
% the a main predicate.
%
:- pred defns_contain_main(mlds__defns::in) is semidet.
%-----------------------------------------------------------------------------%
% return `true' if the statement is a tail call which
% can be optimized into a jump back to the start of the
% function
:- pred can_optimize_tailcall(mlds__qualified_entity_name::in, mlds__stmt::in)
is semidet.
%-----------------------------------------------------------------------------%
%
% routines that deal with statements
%
% nondeterministically generates sub-statements from statements.
:- pred statements_contains_statement(mlds__statements::in,
mlds__statement::out) is nondet.
:- pred statement_contains_statement(mlds__statement::in, mlds__statement::out)
is multi.
:- pred stmt_contains_statement(mlds__stmt::in, mlds__statement::out)
is nondet.
% succeeds iff this statement contains a reference to the
% specified variable
:- pred statement_contains_var(mlds__statement::in, mlds__data::in) is semidet.
:- pred has_foreign_languages(mlds__statement::in, list(foreign_language)::out)
is det.
%-----------------------------------------------------------------------------%
%
% routines that deal with definitions
%
% defn_contains_foreign_code(NativeTargetLang, Defn):
% Succeeds iff this definition contains outline_foreign_proc
% statements, or inline_target_code statements in a target
% language other than the specified native target language.
% XXX perhaps we should eliminate the need to check for
% inline_target_code, because it shouldn't be generated
% with target language different to the native target
% language in the long run.
:- pred defn_contains_foreign_code(target_lang::in, mlds__defn::in) is semidet.
% defn_contains_foreign_code(ForeignLang, Defn):
% Succeeds iff this definition contains outline_foreign_proc
% statements for the given foreign language.
:- pred defn_contains_outline_foreign_proc(foreign_language::in,
mlds__defn::in) is semidet.
% Succeeds iff this definition is a type definition.
:- pred defn_is_type(mlds__defn::in) is semidet.
% Succeeds iff this definition is a function definition.
:- pred defn_is_function(mlds__defn::in) is semidet.
% Succeeds iff this definition is a data definition which
% defines a type_ctor_info constant.
:- pred defn_is_type_ctor_info(mlds__defn::in) is semidet.
% Succeeds iff this definition is a data definition which
% defines a variable whose type is mlds__commit_type.
:- pred defn_is_commit_type_var(mlds__defn::in) is semidet.
% Succeeds iff this definition has `public' in the access
% field in its decl_flags.
:- pred defn_is_public(mlds__defn::in) is semidet.
% Succeeds iff these definitions contains a reference to
% the specified variable.
:- pred defns_contains_var(mlds__defns::in, mlds__data::in) is semidet.
% Succeeds iff this definition contains a reference to
% the specified variable.
:- pred defn_contains_var(mlds__defn::in, mlds__data::in) is semidet.
%-----------------------------------------------------------------------------%
%
% routines that deal with lvals/rvals
%
%
% initializer_contains_var:
% rvals_contains_var:
% maybe_rval_contains_var:
% rval_contains_var:
% lvals_contains_var:
% lval_contains_var:
% Succeeds iff the specified construct contains a reference to
% the specified variable.
%
:- pred initializer_contains_var(mlds__initializer::in, mlds__data::in)
is semidet.
:- pred rvals_contains_var(list(mlds__rval)::in, mlds__data::in) is semidet.
:- pred maybe_rval_contains_var(maybe(mlds__rval)::in, mlds__data::in)
is semidet.
:- pred rval_contains_var(mlds__rval::in, mlds__data::in) is semidet.
:- pred lvals_contains_var(list(mlds__lval)::in, mlds__data::in) is semidet.
:- pred lval_contains_var(mlds__lval::in, mlds__data::in) is semidet.
%-----------------------------------------------------------------------------%
% Does the type require the lowlevel representation on the indicated
% backend?
:- pred type_needs_lowlevel_rep(compilation_target::in,
prog_data__type::in) is semidet.
:- pred type_ctor_needs_lowlevel_rep(compilation_target::in,
type_ctor::in) is semidet.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module backend_libs__rtti.
:- import_module check_hlds__type_util.
:- import_module parse_tree__prog_io.
:- import_module parse_tree__prog_util.
:- import_module bool, list, std_util.
%-----------------------------------------------------------------------------%
defns_contain_main(Defns) :-
list__member(Defn, Defns),
Defn = mlds__defn(Name, _, _, _),
Name = function(FuncName, _, _, _),
FuncName = pred(predicate, _, "main", 2, _, _).
can_optimize_tailcall(Name, Call) :-
Call = call(_Signature, FuncRval, MaybeObject, _CallArgs,
_Results, CallKind),
%
% check if this call can be optimized as a tail call
%
( CallKind = tail_call ; CallKind = no_return_call ),
%
% check if the callee adddress is the same as
% the caller
%
FuncRval = const(code_addr_const(CodeAddr)),
(
CodeAddr = proc(QualifiedProcLabel, _Sig),
MaybeSeqNum = no
;
CodeAddr = internal(QualifiedProcLabel, SeqNum, _Sig),
MaybeSeqNum = yes(SeqNum)
),
QualifiedProcLabel = qual(ModuleName, module_qual, PredLabel - ProcId),
% check that the module name matches
Name = qual(ModuleName, module_qual, FuncName),
% check that the PredLabel, ProcId, and MaybeSeqNum match
FuncName = function(PredLabel, ProcId, MaybeSeqNum, _),
%
% In C++, `this' is a constant, so our usual technique
% of assigning the arguments won't work if it is a
% member function. Thus we don't do this optimization
% if we're optimizing a member function call
%
MaybeObject = no.
%-----------------------------------------------------------------------------%
%
% routines that deal with statements
%
% statement_contains_statement:
% statements_contains_statement:
% maybe_statement_contains_statement:
% nondeterministically generates sub-statements from statements.
statements_contains_statement(Statements, SubStatement) :-
list__member(Statement, Statements),
statement_contains_statement(Statement, SubStatement).
:- pred maybe_statement_contains_statement(maybe(mlds__statement)::in,
mlds__statement::out) is nondet.
maybe_statement_contains_statement(no, _Statement) :- fail.
maybe_statement_contains_statement(yes(Statement), SubStatement) :-
statement_contains_statement(Statement, SubStatement).
statement_contains_statement(Statement, Statement).
statement_contains_statement(Statement, SubStatement) :-
Statement = mlds__statement(Stmt, _Context),
stmt_contains_statement(Stmt, SubStatement).
stmt_contains_statement(Stmt, SubStatement) :-
(
Stmt = block(_Defns, Statements),
statements_contains_statement(Statements, SubStatement)
;
Stmt = while(_Rval, Statement, _Once),
statement_contains_statement(Statement, SubStatement)
;
Stmt = if_then_else(_Cond, Then, MaybeElse),
( statement_contains_statement(Then, SubStatement)
; maybe_statement_contains_statement(MaybeElse, SubStatement)
)
;
Stmt = switch(_Type, _Val, _Range, Cases, Default),
( cases_contains_statement(Cases, SubStatement)
; default_contains_statement(Default, SubStatement)
)
;
Stmt = label(_Label),
fail
;
Stmt = goto(_),
fail
;
Stmt = computed_goto(_Rval, _Labels),
fail
;
Stmt = call(_Sig, _Func, _Obj, _Args, _RetLvals, _TailCall),
fail
;
Stmt = return(_Rvals),
fail
;
Stmt = do_commit(_Ref),
fail
;
Stmt = try_commit(_Ref, Statement, Handler),
( statement_contains_statement(Statement, SubStatement)
; statement_contains_statement(Handler, SubStatement)
)
;
Stmt = atomic(_AtomicStmt),
fail
).
:- pred cases_contains_statement(list(mlds__switch_case)::in,
mlds__statement::out) is nondet.
cases_contains_statement(Cases, SubStatement) :-
list__member(Case, Cases),
Case = _MatchCond - Statement,
statement_contains_statement(Statement, SubStatement).
:- pred default_contains_statement(mlds__switch_default::in,
mlds__statement::out) is nondet.
default_contains_statement(default_do_nothing, _) :- fail.
default_contains_statement(default_is_unreachable, _) :- fail.
default_contains_statement(default_case(Statement), SubStatement) :-
statement_contains_statement(Statement, SubStatement).
% statements_contains_var:
% maybe_statement_contains_var:
% statement_contains_var:
% trail_op_contains_var:
% atomic_stmt_contains_var:
% Succeeds iff the specified construct contains a reference to
% the specified variable.
:- pred statements_contains_var(mlds__statements::in, mlds__data::in)
is semidet.
statements_contains_var(Statements, Name) :-
list__member(Statement, Statements),
statement_contains_var(Statement, Name).
:- pred maybe_statement_contains_var(maybe(mlds__statement)::in,
mlds__data::in) is semidet.
% maybe_statement_contains_var(no, _) :- fail.
maybe_statement_contains_var(yes(Statement), Name) :-
statement_contains_var(Statement, Name).
statement_contains_var(Statement, Name) :-
Statement = mlds__statement(Stmt, _Context),
stmt_contains_var(Stmt, Name).
:- pred stmt_contains_var(mlds__stmt::in, mlds__data::in) is semidet.
stmt_contains_var(Stmt, Name) :-
(
Stmt = block(Defns, Statements),
( defns_contains_var(Defns, Name)
; statements_contains_var(Statements, Name)
)
;
Stmt = while(Rval, Statement, _Once),
( rval_contains_var(Rval, Name)
; statement_contains_var(Statement, Name)
)
;
Stmt = if_then_else(Cond, Then, MaybeElse),
( rval_contains_var(Cond, Name)
; statement_contains_var(Then, Name)
; maybe_statement_contains_var(MaybeElse, Name)
)
;
Stmt = switch(_Type, Val, _Range, Cases, Default),
( rval_contains_var(Val, Name)
; cases_contains_var(Cases, Name)
; default_contains_var(Default, Name)
)
;
Stmt = label(_Label),
fail
;
Stmt = goto(_),
fail
;
Stmt = computed_goto(Rval, _Labels),
rval_contains_var(Rval, Name)
;
Stmt = call(_Sig, Func, Obj, Args, RetLvals, _TailCall),
( rval_contains_var(Func, Name)
; maybe_rval_contains_var(Obj, Name)
; rvals_contains_var(Args, Name)
; lvals_contains_var(RetLvals, Name)
)
;
Stmt = return(Rvals),
rvals_contains_var(Rvals, Name)
;
Stmt = do_commit(Ref),
rval_contains_var(Ref, Name)
;
Stmt = try_commit(Ref, Statement, Handler),
( lval_contains_var(Ref, Name)
; statement_contains_var(Statement, Name)
; statement_contains_var(Handler, Name)
)
;
Stmt = atomic(AtomicStmt),
atomic_stmt_contains_var(AtomicStmt, Name)
).
:- pred cases_contains_var(list(mlds__switch_case)::in, mlds__data::in)
is semidet.
cases_contains_var(Cases, Name) :-
list__member(Case, Cases),
Case = _MatchConds - Statement,
statement_contains_var(Statement, Name).
:- pred default_contains_var(mlds__switch_default::in, mlds__data::in)
is semidet.
% default_contains_var(default_do_nothing, _) :- fail.
% default_contains_var(default_is_unreachable, _) :- fail.
default_contains_var(default_case(Statement), Name) :-
statement_contains_var(Statement, Name).
:- pred atomic_stmt_contains_var(mlds__atomic_statement::in, mlds__data::in)
is semidet.
% atomic_stmt_contains_var(comment(_), _Name) :- fail.
atomic_stmt_contains_var(assign(Lval, Rval), Name) :-
( lval_contains_var(Lval, Name)
; rval_contains_var(Rval, Name)
).
atomic_stmt_contains_var(new_object(Target, _MaybeTag, _HasSecTag, _Type,
_MaybeSize, _MaybeCtorName, Args, _ArgTypes), Name) :-
( lval_contains_var(Target, Name)
; rvals_contains_var(Args, Name)
).
% atomic_stmt_contains_var(gc_check, _) :- fail.
atomic_stmt_contains_var(mark_hp(Lval), Name) :-
lval_contains_var(Lval, Name).
atomic_stmt_contains_var(restore_hp(Rval), Name) :-
rval_contains_var(Rval, Name).
atomic_stmt_contains_var(trail_op(TrailOp), Name) :-
trail_op_contains_var(TrailOp, Name).
atomic_stmt_contains_var(inline_target_code(_Lang, Components), Name) :-
list__member(Component, Components),
target_code_component_contains_var(Component, Name).
:- pred trail_op_contains_var(trail_op::in, mlds__data::in) is semidet.
trail_op_contains_var(store_ticket(Lval), Name) :-
lval_contains_var(Lval, Name).
trail_op_contains_var(reset_ticket(Rval, _Reason), Name) :-
rval_contains_var(Rval, Name).
% trail_op_contains_var(discard_ticket, _Name) :- fail.
% trail_op_contains_var(prune_ticket, _Name) :- fail.
trail_op_contains_var(mark_ticket_stack(Lval), Name) :-
lval_contains_var(Lval, Name).
trail_op_contains_var(prune_tickets_to(Rval), Name) :-
rval_contains_var(Rval, Name).
:- pred target_code_component_contains_var(target_code_component::in,
mlds__data::in) is semidet.
%target_code_component_contains_var(raw_target_code(_Code), _Name) :-
% fail.
%target_code_component_contains_var(user_target_code(_Code, _Context), _Name) :-
% fail.
target_code_component_contains_var(target_code_input(Rval), Name) :-
rval_contains_var(Rval, Name).
target_code_component_contains_var(target_code_output(Lval), Name) :-
lval_contains_var(Lval, Name).
target_code_component_contains_var(name(EntityName), DataName) :-
EntityName = qual(ModuleName, QualKind, data(UnqualDataName)),
DataName = qual(ModuleName, QualKind, UnqualDataName),
% this is a place where we can succeed
true.
has_foreign_languages(Statement, Langs) :-
GetTargetCode = (pred(Lang::out) is nondet :-
statement_contains_statement(Statement, SubStatement),
SubStatement = statement(atomic(
outline_foreign_proc(Lang, _, _, _)), _)
),
solutions(GetTargetCode, Langs).
%-----------------------------------------------------------------------------%
%
% routines that deal with definitions
%
defn_contains_foreign_code(NativeTargetLang, Defn) :-
Defn = mlds__defn(_Name, _Context, _Flags, Body),
Body = function(_, _, defined_here(FunctionBody), _),
statement_contains_statement(FunctionBody, Statement),
Statement = mlds__statement(Stmt, _),
(
Stmt = atomic(inline_target_code(TargetLang, _)),
TargetLang \= NativeTargetLang
;
Stmt = atomic(outline_foreign_proc(_, _, _, _))
).
defn_contains_outline_foreign_proc(ForeignLang, Defn) :-
Defn = mlds__defn(_Name, _Context, _Flags, Body),
Body = function(_, _, defined_here(FunctionBody), _),
statement_contains_statement(FunctionBody, Statement),
Statement = mlds__statement(Stmt, _),
Stmt = atomic(outline_foreign_proc(ForeignLang, _, _, _)).
defn_is_type(Defn) :-
Defn = mlds__defn(Name, _Context, _Flags, _Body),
Name = type(_, _).
defn_is_function(Defn) :-
Defn = mlds__defn(Name, _Context, _Flags, _Body),
Name = function(_, _, _, _).
defn_is_type_ctor_info(Defn) :-
Defn = mlds__defn(_Name, _Context, _Flags, Body),
Body = mlds__data(Type, _, _),
Type = mlds__rtti_type(item_type(RttiId)),
RttiId = ctor_rtti_id(_, RttiName),
RttiName = type_ctor_info.
defn_is_commit_type_var(Defn) :-
Defn = mlds__defn(_Name, _Context, _Flags, Body),
Body = mlds__data(Type, _, _),
Type = mlds__commit_type.
defn_is_public(Defn) :-
Defn = mlds__defn(_Name, _Context, Flags, _Body),
access(Flags) = public.
% defns_contains_var:
% defn_contains_var:
% defn_body_contains_var:
% function_body_contains_var:
% Succeeds iff the specified construct contains a reference to
% the specified variable.
%
defns_contains_var(Defns, Name) :-
list__member(Defn, Defns),
defn_contains_var(Defn, Name).
defn_contains_var(mlds__defn(_Name, _Context, _Flags, DefnBody), Name) :-
defn_body_contains_var(DefnBody, Name).
:- pred defn_body_contains_var(mlds__entity_defn::in, mlds__data::in)
is semidet.
% XXX Should we include variables in the GC_TraceCode field here?
defn_body_contains_var(mlds__data(_Type, Initializer, _GC_TraceCode), Name) :-
initializer_contains_var(Initializer, Name).
defn_body_contains_var(mlds__function(_PredProcId, _Params, FunctionBody,
_Attrs), Name) :-
function_body_contains_var(FunctionBody, Name).
defn_body_contains_var(mlds__class(ClassDefn), Name) :-
ClassDefn = mlds__class_defn(_Kind, _Imports, _Inherits, _Implements,
CtorDefns, FieldDefns),
( defns_contains_var(FieldDefns, Name)
; defns_contains_var(CtorDefns, Name)
).
:- pred function_body_contains_var(function_body::in, mlds__data::in)
is semidet.
% function_body_contains_var(external, _) :- fail.
function_body_contains_var(defined_here(Statement), Name) :-
statement_contains_var(Statement, Name).
%-----------------------------------------------------------------------------%
%
% routines that deal with lvals/rvals
%
%
% initializer_contains_var:
% rvals_contains_var:
% maybe_rval_contains_var:
% rval_contains_var:
% lvals_contains_var:
% lval_contains_var:
% Succeeds iff the specified construct contains a reference to
% the specified variable.
%
% initializer_contains_var(no_initializer, _) :- fail.
initializer_contains_var(init_obj(Rval), Name) :-
rval_contains_var(Rval, Name).
initializer_contains_var(init_struct(_Type, Inits), Name) :-
list__member(Init, Inits),
initializer_contains_var(Init, Name).
initializer_contains_var(init_array(Inits), Name) :-
list__member(Init, Inits),
initializer_contains_var(Init, Name).
rvals_contains_var(Rvals, Name) :-
list__member(Rval, Rvals),
rval_contains_var(Rval, Name).
% maybe_rval_contains_var(no, _Name) :- fail.
maybe_rval_contains_var(yes(Rval), Name) :-
rval_contains_var(Rval, Name).
rval_contains_var(lval(Lval), Name) :-
lval_contains_var(Lval, Name).
rval_contains_var(mkword(_Tag, Rval), Name) :-
rval_contains_var(Rval, Name).
rval_contains_var(const(Const), QualDataName) :-
Const = data_addr_const(DataAddr),
DataAddr = data_addr(ModuleName, DataName),
QualDataName = qual(ModuleName, _QualKind, DataName),
% this is a place where we can succeed
true.
rval_contains_var(unop(_Op, Rval), Name) :-
rval_contains_var(Rval, Name).
rval_contains_var(binop(_Op, X, Y), Name) :-
( rval_contains_var(X, Name)
; rval_contains_var(Y, Name)
).
rval_contains_var(mem_addr(Lval), Name) :-
lval_contains_var(Lval, Name).
lvals_contains_var(Lvals, Name) :-
list__member(Lval, Lvals),
lval_contains_var(Lval, Name).
lval_contains_var(field(_MaybeTag, Rval, _FieldId, _, _), Name) :-
rval_contains_var(Rval, Name).
lval_contains_var(mem_ref(Rval, _Type), Name) :-
rval_contains_var(Rval, Name).
lval_contains_var(var(qual(ModuleName, QualKind, Name), _Type),
qual(ModuleName, QualKind, var(Name))) :-
% this is another place where we can succeed
true.
%-----------------------------------------------------------------------------%
type_needs_lowlevel_rep(Target, Type) :-
type_to_ctor_and_args(Type, TypeCtor, _Args),
type_ctor_needs_lowlevel_rep(Target, TypeCtor).
% XXX Do we need to do the same for the Java back-end?
type_ctor_needs_lowlevel_rep(il, TypeName - _Arity) :-
mercury_public_builtin_module(Builtin),
mercury_private_builtin_module(PrivateBuiltin),
RttiImplementation = unqualified("rtti_implementation"),
StdUtil = unqualified("std_util"),
TypeDesc = unqualified("type_desc"),
( TypeName = qualified(PrivateBuiltin, "base_typeclass_info")
; TypeName = qualified(PrivateBuiltin, "type_ctor_info")
; TypeName = qualified(PrivateBuiltin, "typeclass_info")
; TypeName = qualified(PrivateBuiltin, "type_info")
% Use lowlevel types for all types in rtti_implementation
% as this allows as to add new types needed to manipulate
% the RTTI type safely easily.
; TypeName = qualified(RttiImplementation, _)
; TypeName = qualified(TypeDesc, "type_desc")
; TypeName = qualified(TypeDesc, "pseudo_type_desc")
; TypeName = qualified(TypeDesc, "type_ctor_desc")
% Types which don't have a Mercury representation.
; TypeName = qualified(PrivateBuiltin, "ref")
; TypeName = qualified(PrivateBuiltin, "heap_pointer")
; TypeName = qualified(Builtin, "c_pointer")
% XXX These types are referenced in IL and C# code,
% so it is easier to just keep their low level representation
% for the moment.
; TypeName = qualified(Builtin, "comparison_result")
; TypeName = qualified(StdUtil, "univ")
; TypeName = qualified(StdUtil, "mutvar")
).
%-----------------------------------------------------------------------------%