Files
mercury/compiler/code_util.m
Fergus Henderson d6ca6e3797 Ensure that Makefile.mercury can be used as a generic
*Makefile*:
	Ensure that Makefile.mercury can be used as a generic
	Makefile for Mercury programs.  It now gets included by the
	Makefiles in the tests/ directory.
	(It's highly likely that these changes have broken something.)

code_util.nl, peephole.nl, code_info.nl:
	Move peephole__neg_rval to code_util.nl, so that it can
	also be used by code_info.nl.  Improve it a bit.

disj_gen.nl:
	Minor stylistic changes.

peephole.nl:
	Use bintree_set(label) rather than map(label, bool).

ite_gen.nl:
	Implement non-deterministic if-then-elses.

mercury_compile.nl:
	Change the action in the automatically generated .dep makefile
	to use `$(MNL)' rather than `$(NC)' to link the `.no' files
	together.

mode_util.nl, mode_info.nl:
	Fix some (recently detected) determinism errors.

options.nl:
	Rearrange the options into a vaguely meaninful order and
	add a couple of comments.
1994-08-30 21:07:52 +00:00

190 lines
6.7 KiB
Mathematica

%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- module code_util.
:- interface.
:- import_module hlds, llds.
:- pred code_util__make_entry_label(module_info, pred_id, proc_id, code_addr).
:- mode code_util__make_entry_label(in, in, in, out) is det.
:- pred code_util__make_local_entry_label(module_info, pred_id, proc_id, label).
:- mode code_util__make_local_entry_label(in, in, in, out) is det.
:- pred code_util__make_nonlocal_entry_label(module_info,
pred_id, proc_id, code_addr).
:- mode code_util__make_nonlocal_entry_label(in, in, in, out) is det.
:- pred code_util__make_local_label(module_info, pred_id, proc_id, int, label).
:- mode code_util__make_local_label(in, in, in, in, out) is det.
:- pred code_util__uni_mode_to_unilabel(uni_mode, unilabel).
:- mode code_util__uni_mode_to_unilabel(in, out) is det.
:- pred code_util__arg_loc_to_register(arg_loc, reg).
:- mode code_util__arg_loc_to_register(in, out) is det.
% Determine whether a goal might allocate some heap space,
% i.e. whether it contains any construction unifications
% or predicate calls.
:- pred code_util__goal_may_allocate_heap(hlds__goal).
:- mode code_util__goal_may_allocate_heap(in) is semidet.
:- pred code_util__goal_list_may_allocate_heap(list(hlds__goal)).
:- mode code_util__goal_list_may_allocate_heap(in) is semidet.
% Negate a condition.
% This is used mostly just to make the generated code more readable.
:- pred code_util__neg_rval(rval, rval).
:- mode code_util__neg_rval(in, out) is det.
:- pred atom_to_operator(string, operator).
:- mode atom_to_operator(in, out) is semidet.
:- mode atom_to_operator(out, in) is semidet.
%---------------------------------------------------------------------------%
:- implementation.
:- import_module list, hlds, map, std_util.
%---------------------------------------------------------------------------%
code_util__make_local_entry_label(ModuleInfo, PredId, ProcId, Label) :-
predicate_module(ModuleInfo, PredId, ModuleName),
predicate_name(ModuleInfo, PredId, PredName),
predicate_arity(ModuleInfo, PredId, Arity),
Label = entrylabel(ModuleName, PredName, Arity, ProcId).
code_util__make_nonlocal_entry_label(ModuleInfo, PredId, ProcId, Label) :-
predicate_module(ModuleInfo, PredId, ModuleName),
predicate_name(ModuleInfo, PredId, PredName),
predicate_arity(ModuleInfo, PredId, Arity),
Label = nonlocal(ModuleName, PredName, Arity, ProcId).
code_util__make_local_label(ModuleInfo, PredId, ProcId, LabelNum, Label) :-
predicate_module(ModuleInfo, PredId, ModuleName),
predicate_name(ModuleInfo, PredId, PredName),
predicate_arity(ModuleInfo, PredId, Arity),
Label = label(ModuleName, PredName, Arity, ProcId, LabelNum).
code_util__make_entry_label(ModuleInfo, PredId, ProcId, PredAddress) :-
module_info_preds(ModuleInfo, Preds),
map__lookup(Preds, PredId, PredInfo),
(
pred_info_is_imported(PredInfo)
->
code_util__make_nonlocal_entry_label(ModuleInfo,
PredId, ProcId, PredAddress)
;
code_util__make_local_entry_label(ModuleInfo,
PredId, ProcId, Label),
PredAddress = local(Label)
).
%-----------------------------------------------------------------------------%
code_util__uni_mode_to_unilabel(_UniMode,
unilabel("xxx","outofline","unification")).
%-----------------------------------------------------------------------------%
code_util__arg_loc_to_register(ArgLoc, r(ArgLoc)).
%-----------------------------------------------------------------------------%
atom_to_operator("builtin_plus", (+)).
atom_to_operator("builtin_minus", (-)).
atom_to_operator("builtin_times", (*)).
atom_to_operator("builtin_div", (/)).
atom_to_operator("builtin_mod", (mod)).
atom_to_operator(">", (>)).
atom_to_operator("<", (<)).
atom_to_operator(">=", (>=)).
atom_to_operator("=<", (<=)).
%-----------------------------------------------------------------------------%
% This code may _look_ nondeterministic, but it's really semidet,
% and Mercury is smart enough to know this.
code_util__goal_may_allocate_heap(Goal - _GoalInfo) :-
code_util__goal_may_allocate_heap_2(Goal).
:- pred code_util__goal_may_allocate_heap_2(hlds__goal_expr).
:- mode code_util__goal_may_allocate_heap_2(in) is semidet.
code_util__goal_may_allocate_heap_2(call(_, _, _, not_builtin, _, _)).
code_util__goal_may_allocate_heap_2(unify(_, _, _, construct(_,_,Args,_), _)) :-
Args = [_|_].
code_util__goal_may_allocate_heap_2(some(_Vars, Goal)) :-
code_util__goal_may_allocate_heap(Goal).
code_util__goal_may_allocate_heap_2(not(_Vars, Goal)) :-
code_util__goal_may_allocate_heap(Goal).
code_util__goal_may_allocate_heap_2(conj(Goals)) :-
code_util__goal_list_may_allocate_heap(Goals).
code_util__goal_may_allocate_heap_2(disj(Goals)) :-
code_util__goal_list_may_allocate_heap(Goals).
code_util__goal_may_allocate_heap_2(switch(_Var, _Det, Cases)) :-
code_util__cases_may_allocate_heap(Cases).
code_util__goal_may_allocate_heap_2(if_then_else(_Vars, A, B, C)) :-
(
code_util__goal_may_allocate_heap(A)
;
code_util__goal_may_allocate_heap(B)
;
code_util__goal_may_allocate_heap(C)
).
:- pred code_util__cases_may_allocate_heap(list(case)).
:- mode code_util__cases_may_allocate_heap(in) is semidet.
code_util__cases_may_allocate_heap([case(_, Goal) | _]) :-
code_util__goal_may_allocate_heap(Goal).
code_util__cases_may_allocate_heap([_ | Cases]) :-
code_util__cases_may_allocate_heap(Cases).
code_util__goal_list_may_allocate_heap([Goal | _]) :-
code_util__goal_may_allocate_heap(Goal).
code_util__goal_list_may_allocate_heap([_ | Goals]) :-
code_util__goal_list_may_allocate_heap(Goals).
%-----------------------------------------------------------------------------%
% Negate a condition.
% This is used mostly just to make the generated code more readable.
code_util__neg_rval(Rval, NegRval) :-
( code_util__neg_rval_2(Rval, NegRval0) ->
NegRval = NegRval0
;
NegRval = not(Rval)
).
:- pred code_util__neg_rval_2(rval, rval).
:- mode code_util__neg_rval_2(in, out) is semidet.
code_util__neg_rval_2(not(Rval), Rval).
code_util__neg_rval_2(binop(Op, X, Y), binop(NegOp, X, Y)) :-
code_util__neg_op(Op, NegOp).
code_util__neg_rval_2(false, true).
code_util__neg_rval_2(true, false).
:- pred code_util__neg_op(operator, operator).
:- mode code_util__neg_op(in, out) is semidet.
code_util__neg_op(eq, ne).
code_util__neg_op(ne, eq).
code_util__neg_op(<, >=).
code_util__neg_op(<=, >).
code_util__neg_op(>, <=).
code_util__neg_op(>=, <).
%-----------------------------------------------------------------------------%