Files
mercury/compiler/ml_util.m
Julien Fischer 00d8243570 General improvements and bug fixes to the MLDS backend, most
Estimated hours taken: 20

General improvements and bug fixes to the MLDS backend, most
of which were prompted by working on the Java backend.

The definition of mlds__lval now includes type information for
variables.  This is necessary because if enumerations are treated
as objects (as in the Java backend) rather than integers we need to know
when to create new objects.  At the level this occurs there was
previously no way to distinguish between an integer that is an integer,
and one that represents an enumeration.

Added the access specifier `local' to the declaration flags.  This fixes
a bug in which the local variables of a function were being declared
`private'.

Redefined ctor_name so that they are fully qualified.  This was necessary
because the Java backend represents discriminated unions as nested
classes and we need to be able to determine the fully qualified name of
the constructor in order to call it, do casts, etc.

Added `mlds__unknown_type' to `mlds__type'.  This is due to the change
in the definition of mlds_lval above.  In ml_code_util.m, env_ptr's are
created as dangling references.  The new definition of mlds__lval expects
there to be a type as well, but at this point it hasn't been
generated (and won't be until the ml_elim_nested pass).  Rather than just
guess the type we should declare the type to be unknown and print out an
error message if an unknown type makes it through to one of the backends.

Fixed a bug in the `--det-copy-out' option.

Shifted code for detecting entry point to main/2 from mercury_compile.m
to ml_util.m

compiler/mercury_compile.m:
compiler/ml_util.m:
	Shifted code for detecting entry point to main/2 from mercury_compile.m
	to ml_util.m
compiler/mlds.m:
	Added `local' as an access specifier.
	Extended definition of mlds__lval to include type information
	for variables.
	Added `mlds__unknown_type' to the mlds types so that when
	the compiler generates variables without yet knowing their
	type we can mark them as this, rather than hoping that the
	correct types eventually get added.
	Redefined ctor_name so that it is fully qualified.
	Made changes to comments to reflect above changes.

compiler/ml_code_gen.m:
	Mark the generated functions as `one_copy' rather than `per_instance',
	so that they get generated as static methods for the Java back-end.
	Fixed a bug with the --det-copy-out option.

compiler/ml_code_util.m:
	Fixed a bug that was causing the wrong declaration flags to be
	set for fields in du constructors.
	Changed the name of the predicate `ml_qualify_var' to
	`ml_gen_var_lval'.

compiler/ml_type_gen.m:
	Mark the generated types as `one_copy' rather than `per_instance',
	so that they get generated as static nested classes for the Java
	back-end.
	Changed comments to reflect that classes and enumeration constants
	should be static.
	Export functions that generate declaration flags because they
	are used in other modules as well.
	Added a new predicate `ml_gen_mlds_field_decl' that correctly
	generates fields of classes in discriminated unions.

compiler/ml_unify_gen.m:
	Changed the code that generates ctor_id's so that it generates
	the new sort.

compiler/ml_call_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_string_switch.m:
compiler/ml_tailcall.m:
compiler/mlds_to_il.m:
compiler/mlds_to_c.m:
compiler/mlds_to_gcc.m:
compiler/mlds_to_ilasm.m:
compiler/rtti_to_mlds.m:
	Fixed things so that they conform to the changes above.
2001-02-20 07:52:19 +00:00

348 lines
11 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 1999-2001 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_util.
:- interface.
:- import_module mlds.
:- import_module list, std_util.
%-----------------------------------------------------------------------------%
% succeeds iff the definitions contain the entry point to
% the a main predicate.
%
:- pred defns_contain_main(mlds__defns).
:- mode defns_contain_main(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, mlds__stmt).
:- mode can_optimize_tailcall(in, in) is semidet.
%-----------------------------------------------------------------------------%
%
% routines that deal with statements
%
% nondeterministically generates sub-statements from statements.
:- pred statements_contains_statement(mlds__statements, mlds__statement).
:- mode statements_contains_statement(in, out) is nondet.
:- pred statement_contains_statement(mlds__statement, mlds__statement).
:- mode statement_contains_statement(in, out) is multi.
:- pred stmt_contains_statement(mlds__stmt, mlds__statement).
:- mode stmt_contains_statement(in, out) is nondet.
%-----------------------------------------------------------------------------%
%
% routines that deal with definitions
%
% defn_contains_foreign_code(NativeTargetLang, Defn):
% Succeeds iff this definition contains target_code
% statements in a target language other than the
% specified native target language.
:- pred defn_contains_foreign_code(target_lang, mlds__defn).
:- mode defn_contains_foreign_code(in, in) is semidet.
% Succeeds iff this definition is a type definition.
:- pred defn_is_type(mlds__defn).
:- mode defn_is_type(in) is semidet.
% Succeeds iff this definition is a function definition.
:- pred defn_is_function(mlds__defn).
:- mode defn_is_function(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).
:- mode defn_is_type_ctor_info(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).
:- mode defn_is_commit_type_var(in) is semidet.
% Succeeds iff this definition has `public' in the access
% field in its decl_flags.
:- pred defn_is_public(mlds__defn).
:- mode defn_is_public(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, mlds__var).
:- mode initializer_contains_var(in, in) is semidet.
:- pred rvals_contains_var(list(mlds__rval), mlds__var).
:- mode rvals_contains_var(in, in) is semidet.
:- pred maybe_rval_contains_var(maybe(mlds__rval), mlds__var).
:- mode maybe_rval_contains_var(in, in) is semidet.
:- pred rval_contains_var(mlds__rval, mlds__var).
:- mode rval_contains_var(in, in) is semidet.
:- pred lvals_contains_var(list(mlds__lval), mlds__var).
:- mode lvals_contains_var(in, in) is semidet.
:- pred lval_contains_var(mlds__lval, mlds__var).
:- mode lval_contains_var(in, in) is semidet.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module rtti.
:- import_module bool, list, std_util, prog_data.
%-----------------------------------------------------------------------------%
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, IsTailCall),
%
% check if this call can be optimized as a tail call
%
IsTailCall = tail_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, PredLabel - ProcId),
% check that the module name matches
Name = qual(ModuleName, 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
%
statements_contains_statement(Statements, SubStatement) :-
list__member(Statement, Statements),
statement_contains_statement(Statement, SubStatement).
:- pred maybe_statement_contains_statement(maybe(mlds__statement),
mlds__statement).
:- mode maybe_statement_contains_statement(in, 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), mlds__statement).
:- mode cases_contains_statement(in, 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, mlds__statement).
:- mode default_contains_statement(in, 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).
%-----------------------------------------------------------------------------%
%
% routines that deal with definitions
%
defn_contains_foreign_code(NativeTargetLang, Defn) :-
Defn = mlds__defn(_Name, _Context, _Flags, Body),
Body = function(_, _, yes(FunctionBody)),
statement_contains_statement(FunctionBody, Statement),
Statement = mlds__statement(Stmt, _),
Stmt = atomic(target_code(TargetLang, _)),
TargetLang \= NativeTargetLang.
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(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) \= private.
%-----------------------------------------------------------------------------%
%
% 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(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), _Name) :- fail.
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(Name, _Type), Name). /* this is where we can succeed! */
%-----------------------------------------------------------------------------%