mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-21 04:13:46 +00:00
143 lines
4.5 KiB
Mathematica
143 lines
4.5 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ts=4 sw=4 et ft=mercury
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module actual_expected.
|
|
:- interface.
|
|
|
|
:- import_module io.
|
|
|
|
:- pred main(io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module bool.
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module maybe.
|
|
:- import_module require.
|
|
:- import_module set.
|
|
:- import_module string.
|
|
|
|
main(!IO) :-
|
|
find_compulsory_lvals([], no, no, no, MaybeCompulsoryLvals),
|
|
io.write(MaybeCompulsoryLvals, !IO).
|
|
|
|
:- type instruction
|
|
---> llcall(int, int)
|
|
; goto(code_addr)
|
|
; livevals(set(lval)).
|
|
|
|
:- type lval
|
|
---> reg(int).
|
|
|
|
:- type rval
|
|
---> rvalconst(int).
|
|
|
|
:- type code_addr
|
|
---> code_addr_label(label)
|
|
; code_addr_do_fail.
|
|
|
|
:- type label
|
|
---> label(string).
|
|
|
|
:- type maybe_compulsory_lvals
|
|
---> known(set(lval))
|
|
; unknown_must_assume_all.
|
|
|
|
:- type livemap == map(label, set(lval)).
|
|
|
|
:- pred find_compulsory_lvals(list(instruction)::in, maybe(livemap)::in,
|
|
maybe(label)::in, bool::in, maybe_compulsory_lvals::out) is det.
|
|
|
|
find_compulsory_lvals([], MaybeLiveMap, MaybeFallThrough,
|
|
_PrevLivevals, MaybeCompulsoryLvals) :-
|
|
(
|
|
MaybeFallThrough = yes(FallThrough),
|
|
(
|
|
MaybeLiveMap = yes(LiveMap),
|
|
map.lookup(LiveMap, FallThrough, CompulsoryLvals),
|
|
MaybeCompulsoryLvals = known(CompulsoryLvals)
|
|
;
|
|
MaybeLiveMap = no,
|
|
MaybeCompulsoryLvals = unknown_must_assume_all
|
|
)
|
|
;
|
|
MaybeFallThrough = no,
|
|
MaybeCompulsoryLvals = unknown_must_assume_all
|
|
).
|
|
find_compulsory_lvals([Instr | Instrs], MaybeLiveMap, MaybeFallThrough,
|
|
PrevLivevals, !:MaybeCompulsoryLvals) :-
|
|
( if
|
|
Instr = livevals(LiveLvals)
|
|
then
|
|
find_compulsory_lvals(Instrs, MaybeLiveMap, MaybeFallThrough,
|
|
yes, !:MaybeCompulsoryLvals),
|
|
union_maybe_compulsory_lvals(LiveLvals, !MaybeCompulsoryLvals)
|
|
else if
|
|
Instr = llcall(_, _)
|
|
then
|
|
require(unify(PrevLivevals, yes),
|
|
"find_compulsory_lvals: call without livevals"),
|
|
% The livevals instruction will include all the live lvals
|
|
% in MaybeCompulsoryLvals after we return.
|
|
!:MaybeCompulsoryLvals = known(set.init)
|
|
else if
|
|
Instr = goto(_Target)
|
|
then
|
|
% The livevals instruction will include all the live lvals
|
|
% in MaybeCompulsoryLvals after we return.
|
|
!:MaybeCompulsoryLvals = known(set.init)
|
|
else
|
|
possible_targets(Instr, Labels, NonLabelCodeAddrs),
|
|
(
|
|
NonLabelCodeAddrs = [],
|
|
(
|
|
Labels = [],
|
|
% Optimize the common case
|
|
find_compulsory_lvals(Instrs, MaybeLiveMap, MaybeFallThrough,
|
|
no, !:MaybeCompulsoryLvals)
|
|
;
|
|
Labels = [_ | _],
|
|
(
|
|
MaybeLiveMap = yes(LiveMap),
|
|
list.map(map.lookup(LiveMap), Labels, LabelsLiveLvals),
|
|
AllLabelsLiveLvals = set.union_list(LabelsLiveLvals),
|
|
find_compulsory_lvals(Instrs, LiveMap,
|
|
MaybeFallThrough, no, !:MaybeCompulsoryLvals),
|
|
union_maybe_compulsory_lvals(AllLabelsLiveLvals,
|
|
!MaybeCompulsoryLvals)
|
|
;
|
|
MaybeLiveMap = no,
|
|
!:MaybeCompulsoryLvals = unknown_must_assume_all
|
|
)
|
|
)
|
|
;
|
|
NonLabelCodeAddrs = [_ | _],
|
|
!:MaybeCompulsoryLvals = unknown_must_assume_all
|
|
)
|
|
).
|
|
|
|
:- pred union_maybe_compulsory_lvals(set(lval)::in,
|
|
maybe_compulsory_lvals::in, maybe_compulsory_lvals::out) is det.
|
|
|
|
union_maybe_compulsory_lvals(New, !MaybeCompulsoryLvals) :-
|
|
(
|
|
!.MaybeCompulsoryLvals = known(OldCompulsoryLvals),
|
|
set.union(New, OldCompulsoryLvals, AllCompulsoryLvals),
|
|
!:MaybeCompulsoryLvals = known(AllCompulsoryLvals)
|
|
;
|
|
!.MaybeCompulsoryLvals = unknown_must_assume_all
|
|
).
|
|
|
|
:- pred possible_targets(instruction::in, list(label)::out,
|
|
list(code_addr)::out) is det.
|
|
|
|
possible_targets(llcall(_, _), [], []).
|
|
possible_targets(goto(code_addr_label(Label)), [Label], []).
|
|
possible_targets(goto(code_addr_do_fail), [], [code_addr_do_fail]).
|