for review: new method of handling failures, part 4b of 6
Zoltan Somogyi
zs at cs.mu.OZ.AU
Thu Jul 2 16:32:13 AEST 1998
%---------------------------------------------------------------------------%
-code_info__failure_is_direct_branch(CodeAddr) -->
- code_info__top_failure_cont(FailureCont),
- { FailureCont = failure_cont(ContInfo, FailureMap) },
- { code_info__fail_cont_is_known(ContInfo) },
- code_info__pick_matching_resume_addr(FailureMap, CodeAddr).
-
code_info__generate_failure(Code) -->
- code_info__top_failure_cont(FailureCont),
- { FailureCont = failure_cont(ContInfo, FailureMap) },
+ code_info__get_fail_info(FailInfo),
+ { FailInfo = fail_info(ResumePoints, ResumeKnown, _) },
(
- { code_info__fail_cont_is_known(ContInfo) }
- ->
+ { ResumeKnown = resume_point_known },
+ { stack__top_det(ResumePoints, TopResumePoint) },
(
- code_info__pick_matching_resume_addr(FailureMap,
+ code_info__pick_matching_resume_addr(TopResumePoint,
FailureAddress0)
->
{ FailureAddress = FailureAddress0 },
{ PlaceCode = empty }
;
- { code_info__pick_first_resume_point(FailureMap,
+ { code_info__pick_first_resume_point(TopResumePoint,
Map, FailureAddress) },
{ map__to_assoc_list(Map, AssocList) },
- code_info__grab_code_info(CodeInfo),
+ code_info__remember_position(CurPos),
code_info__place_vars(AssocList, PlaceCode),
- code_info__slap_code_info(CodeInfo)
+ code_info__reset_to_position(CurPos)
),
{ BranchCode = node([goto(FailureAddress) - "fail"]) },
{ Code = tree(PlaceCode, BranchCode) }
;
+ { ResumeKnown = resume_point_unknown },
{ Code = node([goto(do_redo) - "fail"]) }
).
code_info__fail_if_rval_is_false(Rval0, Code) -->
- code_info__top_failure_cont(FailureCont),
- { FailureCont = failure_cont(ContInfo, FailureMap) },
+ code_info__get_fail_info(FailInfo),
+ { FailInfo = fail_info(ResumePoints, ResumeKnown, _) },
(
- { code_info__fail_cont_is_known(ContInfo) }
- ->
+ { ResumeKnown = resume_point_known },
+ { stack__top_det(ResumePoints, TopResumePoint) },
(
- code_info__pick_matching_resume_addr(FailureMap,
+ code_info__pick_matching_resume_addr(TopResumePoint,
FailureAddress0)
->
% We branch away if the test *fails*
@@ -1689,19 +1494,19 @@
"Test for failure"
]) }
;
- { code_info__pick_first_resume_point(FailureMap,
+ { code_info__pick_first_resume_point(TopResumePoint,
Map, FailureAddress) },
{ map__to_assoc_list(Map, AssocList) },
code_info__get_next_label(SuccessLabel),
- code_info__grab_code_info(CodeInfo),
+ code_info__remember_position(CurPos),
code_info__place_vars(AssocList, PlaceCode),
- code_info__slap_code_info(CodeInfo),
+ code_info__reset_to_position(CurPos),
{ SuccessAddress = label(SuccessLabel) },
% We branch away if the test *fails*,
- % therefore we branch around the code
- % that moves variables to their failure
- % locations and branches away
- % if the test succeeds
+ % therefore if the test succeeds, we branch
+ % around the code that moves variables to
+ % their failure locations and branches away
+ % to the failure continuation
{ TestCode = node([
if_val(Rval0, SuccessAddress) -
"Test for failure"
@@ -1715,213 +1520,600 @@
{ Code = tree(TestCode, tree(PlaceCode, TailCode)) }
)
;
- { FailureAddress = do_redo },
- % We branch away if the test *fails*
- { code_util__neg_rval(Rval0, Rval) },
- { Code = node([
- if_val(Rval, FailureAddress) -
- "Test for failure"
- ]) }
+ { ResumeKnown = resume_point_unknown },
+ % We branch away if the test *fails*
+ { code_util__neg_rval(Rval0, Rval) },
+ { Code = node([
+ if_val(Rval, do_redo) -
+ "Test for failure"
+ ]) }
+ ).
+
+%---------------------------------------------------------------------------%
+
+code_info__failure_is_direct_branch(CodeAddr) -->
+ code_info__get_fail_info(FailInfo),
+ { FailInfo = fail_info(ResumePoints, resume_point_known, _) },
+ { stack__top(ResumePoints, TopResumePoint) },
+ code_info__pick_matching_resume_addr(TopResumePoint, CodeAddr).
+
+code_info__may_use_nondet_tailcall(MayTailCall) -->
+ code_info__get_fail_info(FailInfo),
+ { FailInfo = fail_info(ResumePoints, ResumeKnown, _) },
+ (
+ { ResumeKnown = resume_point_known },
+ { stack__top_det(ResumePoints, TopResumePoint) },
+ { TopResumePoint = stack_only(_, do_fail) }
+ ->
+ { MayTailCall = yes }
+ ;
+ { MayTailCall = no }
+ ).
+
+%---------------------------------------------------------------------------%
+
+ % See whether the current locations of variables match the locations
+ % associated with any of the options in the given failure map.
+ % If yes, return the code_addr of that option.
+
+:- pred code_info__pick_matching_resume_addr(resume_point_info::in,
+ code_addr::out, code_info::in, code_info::out) is semidet.
+
+code_info__pick_matching_resume_addr(ResumeMaps, Addr) -->
+ code_info__variable_locations(Locations),
+ {
+ ResumeMaps = orig_only(Map1, Addr1),
+ ( code_info__match_resume_loc(Map1, Locations) ->
+ Addr = Addr1
+ ;
+ fail
+ )
+ ;
+ ResumeMaps = stack_only(Map1, Addr1),
+ ( code_info__match_resume_loc(Map1, Locations) ->
+ Addr = Addr1
+ ;
+ fail
+ )
+ ;
+ ResumeMaps = orig_and_stack(Map1, Addr1, Map2, Addr2),
+ ( code_info__match_resume_loc(Map1, Locations) ->
+ Addr = Addr1
+ ; code_info__match_resume_loc(Map2, Locations) ->
+ Addr = Addr2
+ ;
+ fail
+ )
+ ;
+ ResumeMaps = stack_and_orig(Map1, Addr1, Map2, Addr2),
+ ( code_info__match_resume_loc(Map1, Locations) ->
+ Addr = Addr1
+ ; code_info__match_resume_loc(Map2, Locations) ->
+ Addr = Addr2
+ ;
+ fail
+ )
+ }.
+
+:- pred code_info__match_resume_loc(resume_map::in, resume_map::in) is semidet.
+
+code_info__match_resume_loc(Map, Locations0) :-
+ map__keys(Map, KeyList),
+ set__list_to_set(KeyList, Keys),
+ map__select(Locations0, Keys, Locations),
+ map__to_assoc_list(Locations, List),
+ \+ (
+ list__member(Thingy, List),
+ \+ (
+ Thingy = Var - Actual,
+ map__search(Map, Var, Rvals),
+ set__subset(Rvals, Actual)
+ )
+ ).
+
+:- pred code_info__pick_first_resume_point(resume_point_info::in,
+ resume_map::out, code_addr::out) is det.
+
+code_info__pick_first_resume_point(orig_only(Map, Addr), Map, Addr).
+code_info__pick_first_resume_point(stack_only(Map, Addr), Map, Addr).
+code_info__pick_first_resume_point(orig_and_stack(Map, Addr, _, _), Map, Addr).
+code_info__pick_first_resume_point(stack_and_orig(Map, Addr, _, _), Map, Addr).
+
+:- pred code_info__pick_stack_resume_point(resume_point_info::in,
+ resume_map::out, code_addr::out) is det.
+
+code_info__pick_stack_resume_point(ResumePoint, Map, Addr) :-
+ ( code_info__maybe_pick_stack_resume_point(ResumePoint, Map1, Addr1) ->
+ Map = Map1,
+ Addr = Addr1
+ ;
+ error("no stack resume point")
+ ).
+
+:- pred code_info__maybe_pick_stack_resume_point(resume_point_info::in,
+ resume_map::out, code_addr::out) is semidet.
+
+code_info__maybe_pick_stack_resume_point(stack_only(Map, Addr), Map, Addr).
+code_info__maybe_pick_stack_resume_point(orig_and_stack(_, _, Map, Addr),
+ Map, Addr).
+code_info__maybe_pick_stack_resume_point(stack_and_orig(Map, Addr, _, _),
+ Map, Addr).
+
+%---------------------------------------------------------------------------%
+
+code_info__produce_vars(Vars, Map, Code) -->
+ { set__to_sorted_list(Vars, VarList) },
+ code_info__produce_vars_2(VarList, Map, Code).
+
+:- pred code_info__produce_vars_2(list(var)::in,
+ map(var, set(rval))::out,
+ code_tree::out, code_info::in, code_info::out) is det.
+
+code_info__produce_vars_2([], Map, empty) -->
+ { map__init(Map) }.
+code_info__produce_vars_2([V | Vs], Map, Code) -->
+ code_info__produce_vars_2(Vs, Map0, Code0),
+ code_info__produce_variable_in_reg_or_stack(V, Code1, Rval),
+ { set__singleton_set(Rvals, Rval) },
+ { map__set(Map0, V, Rvals, Map) },
+ { Code = tree(Code0, Code1) }.
+
+code_info__flush_resume_vars_to_stack(Code) -->
+ code_info__get_fail_info(FailInfo),
+ { FailInfo = fail_info(ResumePointStack, _, _) },
+ { stack__top_det(ResumePointStack, ResumePoint) },
+ { code_info__pick_stack_resume_point(ResumePoint, StackMap, _) },
+ { map__to_assoc_list(StackMap, StackLocs) },
+ code_info__place_vars(StackLocs, Code).
+
+%---------------------------------------------------------------------------%
+
+:- pred code_info__init_fail_info(code_model::in, maybe(set(var))::in,
+ resume_point_info::out, code_info::in, code_info::out) is det.
+
+code_info__init_fail_info(CodeModel, MaybeFailVars, ResumePoint) -->
+ (
+ { CodeModel = model_det },
+ code_info__get_next_label(ResumeLabel),
+ { ResumeAddress = label(ResumeLabel) },
+ { ResumeKnown = resume_point_unknown },
+ { CurfrMaxfr = may_be_different }
+ ;
+ { CodeModel = model_semi },
+ % The resume point for this label
+ % will be part of the procedure epilog.
+ code_info__get_next_label(ResumeLabel),
+ { ResumeAddress = label(ResumeLabel) },
+ { ResumeKnown = resume_point_known },
+ { CurfrMaxfr = may_be_different }
+ ;
+ { CodeModel = model_non },
+ ( { MaybeFailVars = yes(_) } ->
+ code_info__get_next_label(ResumeLabel),
+ { ResumeAddress = label(ResumeLabel) }
+ ;
+ { ResumeAddress = do_fail }
+ ),
+ { ResumeKnown = resume_point_known },
+ { CurfrMaxfr = must_be_equal }
+ ),
+ ( { MaybeFailVars = yes(FailVars) } ->
+ code_info__get_stack_slots(StackSlots),
+ { map__select(StackSlots, FailVars, StackMap0) },
+ { map__to_assoc_list(StackMap0, StackList0) },
+ { code_info__make_singleton_sets(StackList0, StackList) },
+ { map__from_assoc_list(StackList, StackMap) }
+ ;
+ { map__init(StackMap) }
+ ),
+ { ResumePoint = stack_only(StackMap, ResumeAddress) },
+ { stack__init(ResumeStack0) },
+ { stack__push(ResumeStack0, ResumePoint, ResumeStack) },
+ { FailInfo = fail_info(ResumeStack, ResumeKnown, CurfrMaxfr) },
+ code_info__set_fail_info(FailInfo).
+
+%---------------------------------------------------------------------------%
+
+code_info__make_resume_point(ResumeVars, ResumeLocs, FullMap, ResumePoint) -->
+ code_info__get_stack_slots(StackSlots),
+ { map__select(FullMap, ResumeVars, OrigMap) },
+ (
+ { ResumeLocs = orig_only },
+ code_info__get_next_label(OrigLabel),
+ { OrigAddr = label(OrigLabel) },
+ { ResumePoint = orig_only(OrigMap, OrigAddr) }
+ ;
+ { ResumeLocs = stack_only },
+ { map__select(StackSlots, ResumeVars, StackMap0) },
+ { map__to_assoc_list(StackMap0, StackList0) },
+ { code_info__make_singleton_sets(StackList0, StackList) },
+ { map__from_assoc_list(StackList, StackMap) },
+ code_info__get_next_label(StackLabel),
+ { StackAddr = label(StackLabel) },
+ { ResumePoint = stack_only(StackMap, StackAddr) }
+ ;
+ { ResumeLocs = orig_and_stack },
+ { map__select(StackSlots, ResumeVars, StackMap0) },
+ { map__to_assoc_list(StackMap0, StackList0) },
+ { code_info__make_singleton_sets(StackList0, StackList) },
+ { map__from_assoc_list(StackList, StackMap) },
+ code_info__get_next_label(OrigLabel),
+ { OrigAddr = label(OrigLabel) },
+ code_info__get_next_label(StackLabel),
+ { StackAddr = label(StackLabel) },
+ { ResumePoint = orig_and_stack(OrigMap, OrigAddr,
+ StackMap, StackAddr) }
+ ;
+ { ResumeLocs = stack_and_orig },
+ { map__select(StackSlots, ResumeVars, StackMap0) },
+ { map__to_assoc_list(StackMap0, StackList0) },
+ { code_info__make_singleton_sets(StackList0, StackList) },
+ { map__from_assoc_list(StackList, StackMap) },
+ code_info__get_next_label(StackLabel),
+ { StackAddr = label(StackLabel) },
+ code_info__get_next_label(OrigLabel),
+ { OrigAddr = label(OrigLabel) },
+ { ResumePoint = stack_and_orig(StackMap, StackAddr,
+ OrigMap, OrigAddr) }
+ ).
+
+:- pred code_info__make_singleton_sets(assoc_list(var, lval)::in,
+ assoc_list(var, set(rval))::out) is det.
+
+code_info__make_singleton_sets([], []).
+code_info__make_singleton_sets([V - L | Rest0], [V - Rs | Rest]) :-
+ set__singleton_set(Rs, lval(L)),
+ code_info__make_singleton_sets(Rest0, Rest).
+
+%---------------------------------------------------------------------------%
+
+ % The code we generate for a resumption point looks like this:
+ %
+ % label(StackLabel)
+ % <assume variables are where StackMap says they are>
+ % <copy variables to their locations according to OrigMap>
+ % label(OrigLabel)
+ % <assume variables are where OrigMap says they are>
+ %
+ % Failures at different points may cause control to arrive at
+ % the resumption point via either label, which is why the last
+ % line is necessary.
+ %
+ % The idea is that failures from other procedures will go to
+ % StackLabel, and that failures from this procedure while
+ % everything is in its original place will go to OrigLabel.
+ % Failures from this procedure where not everything is in its
+ % original place can go to either, after moving the resume variables
+ % to the places where the label expects them.
+ %
+ % The above layout (stack, then orig) is the most common. However,
+ % liveness.m may decide that one or other of the two labels will
+ % never be referred to (e.g. because there are no calls inside
+ % the range of effect of the resumption point or because a call
+ % follows immediately after the establishment of the resumption
+ % point), or that it would be more efficient to put the two labels
+ % in the other order (e.g. because the code after the resumption point
+ % needs most of the variables in their stack slots).
+
+code_info__generate_resume_point(ResumePoint, Code) -->
+ (
+ { ResumePoint = orig_only(Map1, Addr1) },
+ { extract_label_from_code_addr(Addr1, Label1) },
+ { Code = node([
+ label(Label1) -
+ "orig only failure continuation"
+ ]) },
+ code_info__set_var_locations(Map1)
+ ;
+ { ResumePoint = stack_only(Map1, Addr1) },
+ { extract_label_from_code_addr(Addr1, Label1) },
+ { Code = node([
+ label(Label1) -
+ "stack only failure continuation"
+ ]) },
+ code_info__set_var_locations(Map1)
+ ;
+ { ResumePoint = stack_and_orig(Map1, Addr1, Map2, Addr2) },
+ { extract_label_from_code_addr(Addr1, Label1) },
+ { extract_label_from_code_addr(Addr2, Label2) },
+ { Label1Code = node([
+ label(Label1) -
+ "stack failure continuation before orig"
+ ]) },
+ code_info__set_var_locations(Map1),
+ { map__to_assoc_list(Map2, AssocList2) },
+ code_info__place_resume_vars(AssocList2, PlaceCode),
+ { Label2Code = node([
+ label(Label2) -
+ "orig failure continuation after stack"
+ ]) },
+ code_info__set_var_locations(Map2),
+ { Code = tree(Label1Code, tree(PlaceCode, Label2Code)) }
+ ;
+ { ResumePoint = orig_and_stack(Map1, Addr1, Map2, Addr2) },
+ { extract_label_from_code_addr(Addr1, Label1) },
+ { extract_label_from_code_addr(Addr2, Label2) },
+ { Label1Code = node([
+ label(Label1) -
+ "orig failure continuation before stack"
+ ]) },
+ code_info__set_var_locations(Map1),
+ { map__to_assoc_list(Map2, AssocList2) },
+ code_info__place_resume_vars(AssocList2, PlaceCode),
+ { Label2Code = node([
+ label(Label2) -
+ "stack failure continuation after orig"
+ ]) },
+ code_info__set_var_locations(Map2),
+ { Code = tree(Label1Code, tree(PlaceCode, Label2Code)) }
+ ).
+
+:- pred extract_label_from_code_addr(code_addr::in, label::out) is det.
+
+extract_label_from_code_addr(CodeAddr, Label) :-
+ ( CodeAddr = label(Label0) ->
+ Label = Label0
+ ;
+ error("code_info__generate_resume_setup: non-label!")
).
-%---------------------------------------------------------------------------%
+:- pred code_info__place_resume_vars(assoc_list(var, set(rval))::in,
+ code_tree::out, code_info::in, code_info::out) is det.
- % See whether the current locations of variables match the locations
- % associated with any of the options in the given failure map.
- % If yes, return the code_addr of that option.
+code_info__place_resume_vars([], empty) --> [].
+code_info__place_resume_vars([Var - TargetSet | Rest], Code) -->
+ { set__to_sorted_list(TargetSet, Targets) },
+ code_info__place_resume_var(Var, Targets, FirstCode),
+ { Code = tree(FirstCode, RestCode) },
+ code_info__place_resume_vars(Rest, RestCode).
-:- pred code_info__pick_matching_resume_addr(resume_maps, code_addr,
- code_info, code_info).
-:- mode code_info__pick_matching_resume_addr(in, out, in, out) is semidet.
+:- pred code_info__place_resume_var(var::in, list(rval)::in, code_tree::out,
+ code_info::in, code_info::out) is det.
-code_info__pick_matching_resume_addr(ResumeMaps, Addr) -->
- code_info__variable_locations(Locations),
- {
- ResumeMaps = orig_only(Map1, Addr1),
- ( code_info__match_resume_loc(Map1, Locations) ->
- Addr = Addr1
- ;
- fail
- )
- ;
- ResumeMaps = stack_only(Map1, Addr1),
- ( code_info__match_resume_loc(Map1, Locations) ->
- Addr = Addr1
- ;
- fail
- )
- ;
- ResumeMaps = orig_and_stack(Map1, Addr1, Map2, Addr2),
- ( code_info__match_resume_loc(Map1, Locations) ->
- Addr = Addr1
- ; code_info__match_resume_loc(Map2, Locations) ->
- Addr = Addr2
- ;
- fail
- )
+code_info__place_resume_var(_Var, [], empty) --> [].
+code_info__place_resume_var(Var, [Target | Targets], Code) -->
+ ( { Target = lval(TargetLval) } ->
+ code_info__place_var(Var, TargetLval, FirstCode)
;
- ResumeMaps = stack_and_orig(Map1, Addr1, Map2, Addr2),
- ( code_info__match_resume_loc(Map1, Locations) ->
- Addr = Addr1
- ; code_info__match_resume_loc(Map2, Locations) ->
- Addr = Addr2
- ;
- fail
- )
- }.
+ { error("code_info__place_resume_var: not lval") }
+ ),
+ { Code = tree(FirstCode, RestCode) },
+ code_info__place_resume_var(Var, Targets, RestCode).
-:- pred code_info__match_resume_loc(resume_map, resume_map).
-:- mode code_info__match_resume_loc(in, in) is semidet.
+ % Reset the code generator's database of what is where.
+ % Remember that the variables in the map are available in their
+ % associated rvals; forget about all other variables.
-code_info__match_resume_loc(Map, Locations0) :-
- map__keys(Map, KeyList),
- set__list_to_set(KeyList, Keys),
- map__select(Locations0, Keys, Locations),
- map__to_assoc_list(Locations, List),
- \+ (
- list__member(Thingy, List),
- \+ (
- Thingy = Var - Actual,
- map__search(Map, Var, Rvals),
- set__subset(Rvals, Actual)
- )
- ).
+:- pred code_info__set_var_locations(resume_map::in,
+ code_info::in, code_info::out) is det.
- % Find the first label that will be generated for the
- % given failure continuation based on the scheme used by
- % code_info__generate_failure_cont.
+code_info__set_var_locations(Map) -->
+ { map__to_assoc_list(Map, List0) },
+ { code_info__flatten_varlval_list(List0, List) },
+ code_info__get_exprn_info(Exprn0),
+ { code_exprn__reinit_state(List, Exprn0, Exprn) },
+ code_info__set_exprn_info(Exprn).
-:- pred code_info__find_first_resume_label(failure_cont, code_addr).
-:- mode code_info__find_first_resume_label(in, out) is det.
+:- pred code_info__flatten_varlval_list(assoc_list(var, set(rval))::in,
+ assoc_list(var, rval)::out) is det.
-code_info__find_first_resume_label(FailureCont, Address) :-
- FailureCont = failure_cont(ContInfo, FailMap),
- (
- ContInfo = nondet(_, MaybeRedoLabel),
- MaybeRedoLabel = yes(RedoLabel)
- ->
- Address = label(RedoLabel)
- ;
- code_info__pick_first_resume_point(FailMap, _, Address)
- ).
+code_info__flatten_varlval_list([], []).
+code_info__flatten_varlval_list([V - Rvals | Rest0], All) :-
+ code_info__flatten_varlval_list(Rest0, Rest),
+ set__to_sorted_list(Rvals, RvalList),
+ code_info__flatten_varlval_list_2(RvalList, V, Rest1),
+ list__append(Rest1, Rest, All).
-:- pred code_info__pick_first_resume_point(resume_maps, resume_map, code_addr).
-:- mode code_info__pick_first_resume_point(in, out, out) is det.
+:- pred code_info__flatten_varlval_list_2(list(rval)::in, var::in,
+ assoc_list(var, rval)::out) is det.
-code_info__pick_first_resume_point(orig_only(Map, Addr), Map, Addr).
-code_info__pick_first_resume_point(stack_only(Map, Addr), Map, Addr).
-code_info__pick_first_resume_point(orig_and_stack(Map, Addr, _, _), Map, Addr).
-code_info__pick_first_resume_point(stack_and_orig(Map, Addr, _, _), Map, Addr).
+code_info__flatten_varlval_list_2([], _V, []).
+code_info__flatten_varlval_list_2([R | Rs], V, [V - R | Rest]) :-
+ code_info__flatten_varlval_list_2(Rs, V, Rest).
-:- pred code_info__pick_last_resume_point(resume_maps, resume_map, code_addr).
-:- mode code_info__pick_last_resume_point(in, out, out) is det.
+code_info__resume_point_vars(ResumePoint, Vars) :-
+ code_info__pick_first_resume_point(ResumePoint, ResumeMap, _),
+ map__keys(ResumeMap, Vars).
-code_info__pick_last_resume_point(orig_only(Map, Addr), Map, Addr).
-code_info__pick_last_resume_point(stack_only(Map, Addr), Map, Addr).
-code_info__pick_last_resume_point(orig_and_stack( _, _, Map, Addr), Map, Addr).
-code_info__pick_last_resume_point(stack_and_orig( _, _, Map, Addr), Map, Addr).
-
-:- pred code_info__pick_stack_resume_point(resume_maps, resume_map, code_addr).
-:- mode code_info__pick_stack_resume_point(in, out, out) is det.
-
-code_info__pick_stack_resume_point(orig_only(_, _), _, _) :-
- error("no stack resume point").
-code_info__pick_stack_resume_point(stack_only(Map, Addr), Map, Addr).
-code_info__pick_stack_resume_point(orig_and_stack(_, _, Map, Addr), Map, Addr).
-code_info__pick_stack_resume_point(stack_and_orig(Map, Addr, _, _), Map, Addr).
+code_info__resume_point_stack_addr(ResumePoint, StackAddr) :-
+ code_info__pick_stack_resume_point(ResumePoint, _, StackAddr).
%---------------------------------------------------------------------------%
-code_info__unset_failure_cont(Code) -->
- code_info__flush_resume_vars_to_stack(Code),
- code_info__top_failure_cont(FailureCont0),
- { FailureCont0 = failure_cont(ContInfo0, FailureMap) },
- code_info__pop_failure_cont,
- {
- ContInfo0 = semidet,
- error("unset of semidet failure cont")
- ;
- ContInfo0 = nondet(_, MaybeRedoLabel),
- ContInfo = nondet(unknown, MaybeRedoLabel)
- },
- { FailureCont = failure_cont(ContInfo, FailureMap) },
- code_info__push_failure_cont(FailureCont).
+:- type det_commit_info
+ ---> det_commit_info(
+ maybe(lval), % location of saved maxfr
+ maybe(pair(lval)) % location of saved ticket
+ % counter and trail pointer
+ ).
-code_info__flush_resume_vars_to_stack(Code) -->
- code_info__top_failure_cont(FailureCont0),
- { FailureCont0 = failure_cont(_, FailureMap) },
- { code_info__pick_stack_resume_point(FailureMap, StackMap, _) },
- { map__to_assoc_list(StackMap, StackLocs) },
- code_info__place_resume_vars(StackLocs, Code).
+code_info__generate_det_pre_commit(DetCommitInfo, Code) -->
+ code_info__get_fail_info(FailInfo0),
+ { FailInfo0 = fail_info(_, _, CurfrMaxfr) },
+ (
+ { CurfrMaxfr = may_be_different },
+ code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
+ { SaveMaxfrCode = node([
+ assign(MaxfrSlot, lval(maxfr))
+ - "save the value of maxfr"
+ ]) },
+ { MaybeMaxfrSlot = yes(MaxfrSlot) }
+ ;
+ { CurfrMaxfr = must_be_equal },
+ { SaveMaxfrCode = empty },
+ { MaybeMaxfrSlot = no }
+ ),
+ code_info__maybe_save_trail_info(MaybeTrailSlots, SaveTrailCode),
+ { DetCommitInfo = det_commit_info(MaybeMaxfrSlot, MaybeTrailSlots) },
+ { Code = tree(SaveMaxfrCode, SaveTrailCode) }.
-code_info__may_use_nondet_tailcall(MayTailCall) -->
- code_info__top_failure_cont(FailureCont),
- { FailureCont = failure_cont(ContInfo, FailureMap) },
+code_info__generate_det_commit(DetCommitInfo, Code) -->
+ { DetCommitInfo = det_commit_info(MaybeMaxfrSlot, MaybeTrailSlots) },
(
- { code_info__fail_cont_is_known(ContInfo) },
- { FailureMap = stack_only(_, do_fail) }
- ->
- { MayTailCall = yes }
+ { MaybeMaxfrSlot = yes(MaxfrSlot) },
+ { RestoreMaxfrCode = node([
+ assign(maxfr, lval(MaxfrSlot))
+ - "restore the value of maxfr - perform commit"
+ ]) },
+ code_info__release_temp_slot(MaxfrSlot)
;
- { MayTailCall = no }
- ).
+ { MaybeMaxfrSlot = no },
+ { RestoreMaxfrCode = node([
+ assign(maxfr, lval(curfr))
+ - "restore the value of maxfr - perform commit"
+ ]) }
+ ),
+ code_info__maybe_restore_trail_info(MaybeTrailSlots,
+ CommitTrailCode, _),
+ { Code = tree(RestoreMaxfrCode, CommitTrailCode) }.
%---------------------------------------------------------------------------%
-code_info__do_soft_cut(TheFrame, Code, ContCode) -->
- code_info__top_failure_cont(FailureCont),
- { FailureCont = failure_cont(ContInfo, _) },
+:- type semi_commit_info
+ ---> semi_commit_info(
+ fail_info, % fail_info on entry
+ resume_point_info,
+ commit_hijack_info,
+ maybe(pair(lval)) % location of saved ticket
+ % counter and trail pointer
+ ).
+
+:- type commit_hijack_info
+ ---> commit_quarter_hijack
+ ; commit_half_hijack(
+ lval % the stack slot in which we saved
+ % the value of the hijacked redoip
+ )
+ ; commit_full_hijack(
+ lval, % the stack slot in which we saved
+ % the value of the hijacked redoip
+ lval, % the stack slot in which we saved
+ % the value of the hijacked redofr
+ lval % the stack slot in which we saved
+ % the value of maxfr
+ ).
+
+code_info__generate_semi_pre_commit(SemiCommitInfo, Code) -->
+ code_info__get_fail_info(FailInfo0),
+ { FailInfo0 = fail_info(ResumePoints0, ResumeKnown, CurfrMaxfr) },
+ { stack__top_det(ResumePoints0, TopResumePoint) },
+ code_info__clone_resume_point(TopResumePoint, NewResumePoint),
+ { stack__push(ResumePoints0, NewResumePoint, ResumePoints) },
+ { FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr) },
+ code_info__set_fail_info(FailInfo),
+
+ { code_info__pick_stack_resume_point(NewResumePoint, _, StackLabel) },
+ { StackLabelConst = const(code_addr_const(StackLabel)) },
(
- { code_info__fail_cont_is_known(ContInfo) }
- ->
- { code_info__find_first_resume_label(FailureCont, Address) }
+ { CurfrMaxfr = may_be_different },
+ code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
+ RedoipSlot),
+ code_info__acquire_temp_slot(lval(redofr(lval(maxfr))),
+ RedofrSlot),
+ code_info__acquire_temp_slot(lval(maxfr),
+ MaxfrSlot),
+ { HijackInfo = commit_full_hijack(RedoipSlot, RedofrSlot,
+ MaxfrSlot) },
+ { HijackCode = node([
+ assign(RedoipSlot, lval(redoip(lval(maxfr))))
+ - "prepare for full commit hijack",
+ assign(RedofrSlot, lval(redofr(lval(maxfr))))
+ - "prepare for full commit hijack",
+ assign(MaxfrSlot, lval(maxfr))
+ - "prepare for full commit hijack",
+ assign(redofr(lval(maxfr)), lval(curfr))
+ - "hijack the redofr slot",
+ assign(redoip(lval(maxfr)), StackLabelConst)
+ - "hijack the redoip slot"
+ ]) }
;
- % If the newly uncovered cont is unknown then
- % we must have created a new frame before the
- % condition which we no longer need, so we
- % set its redoip to do_fail.
- { Address = do_fail }
+ { CurfrMaxfr = must_be_equal },
+ (
+ { ResumeKnown = resume_point_unknown },
+ code_info__acquire_temp_slot(lval(redoip(lval(curfr))),
+ RedoipSlot),
+ { HijackInfo = commit_half_hijack(RedoipSlot) },
+ { HijackCode = node([
+ assign(RedoipSlot, lval(redoip(lval(curfr))))
+ - "prepare for half commit hijack",
+ assign(redoip(lval(curfr)), StackLabelConst)
+ - "hijack the redofr slot"
+ ]) }
+ ;
+ { ResumeKnown = resume_point_known },
+ { HijackInfo = commit_quarter_hijack },
+ { HijackCode = node([
+ assign(redoip(lval(curfr)), StackLabelConst)
+ - "hijack the redofr slot"
+ ]) }
+ )
),
- code_info__get_globals(Globals),
- { globals__lookup_bool_option(Globals, use_trail, UseTrail) },
- ( { UseTrail = yes } ->
- code_info__get_next_label(ContLabel),
- { ContAddress = label(ContLabel) },
- { ContCode = node([
- label(ContLabel) - "soft cut failure cont entry point",
- discard_ticket - "pop ticket stack",
- goto(Address) - "branch to prev failure continuation"
+ code_info__maybe_save_trail_info(MaybeTrailSlots, SaveTrailCode),
+ { SemiCommitInfo = semi_commit_info(FailInfo0, NewResumePoint,
+ HijackInfo, MaybeTrailSlots) },
+ { Code = tree(HijackCode, SaveTrailCode) }.
+
+code_info__generate_semi_commit(SemiCommitInfo, Code) -->
+ { SemiCommitInfo = semi_commit_info(FailInfo, ResumePoint,
+ HijackInfo, MaybeTrailSlots) },
+
+ code_info__set_fail_info(FailInfo),
+ (
+ { HijackInfo = commit_full_hijack(RedoipSlot, RedofrSlot,
+ MaxfrSlot) },
+ { SuccessUndoCode = node([
+ assign(maxfr, lval(MaxfrSlot))
+ - "restore maxfr for full commit hijack",
+ assign(redoip(lval(maxfr)), lval(RedoipSlot))
+ - "restore redoip for full commit hijack",
+ assign(redofr(lval(maxfr)), lval(RedofrSlot))
+ - "restore redofr for full commit hijack"
+ ]) },
+ { FailureUndoCode = node([
+ assign(redoip(lval(maxfr)), lval(RedoipSlot))
+ - "restore redoip for full commit hijack",
+ assign(redofr(lval(maxfr)), lval(RedofrSlot))
+ - "restore redofr for full commit hijack"
+ ]) }
+ ;
+ { HijackInfo = commit_half_hijack(RedoipSlot) },
+ { SuccessUndoCode = node([
+ assign(maxfr, lval(curfr))
+ - "restore maxfr for half commit hijack",
+ assign(redoip(lval(maxfr)), lval(RedoipSlot))
+ - "restore redoip for half commit hijack"
+ ]) },
+ { FailureUndoCode = node([
+ assign(redoip(lval(maxfr)), lval(RedoipSlot))
+ - "restore redoip for half commit hijack"
]) }
;
- { ContAddress = Address },
- { ContCode = empty }
+ { HijackInfo = commit_quarter_hijack },
+ { FailInfo = fail_info(ResumePoints, _, _) },
+ { stack__top_det(ResumePoints, TopResumePoint) },
+ { code_info__pick_stack_resume_point(TopResumePoint,
+ _, StackLabel) },
+ { StackLabelConst = const(code_addr_const(StackLabel)) },
+ { SuccessUndoCode = node([
+ assign(maxfr, lval(curfr))
+ - "restore maxfr for quarter commit hijack",
+ assign(redoip(lval(maxfr)), StackLabelConst)
+ - "restore redoip for quarter commit hijack"
+ ]) },
+ { FailureUndoCode = node([
+ assign(redoip(lval(maxfr)), StackLabelConst)
+ - "restore redoip for quarter commit hijack"
+ ]) }
),
- { Code = node([
- assign(redoip(lval(TheFrame)),
- const(code_addr_const(ContAddress)))
- - "prune away the `else' case of the if-then-else"
- ]) }.
-%---------------------------------------------------------------------------%
+ code_info__remember_position(AfterCommit),
+ code_info__generate_resume_point(ResumePoint, ResumePointCode),
+ code_info__generate_failure(FailCode),
+ code_info__reset_to_position(AfterCommit),
-code_info__generate_semi_pre_commit(RedoLabel, Slots, PreCommit) -->
- code_info__generate_pre_commit_saves(Slots, SaveCode),
- code_info__get_next_label(ResumeLabel),
- code_info__top_failure_cont(FailureCont0),
- { FailureCont0 = failure_cont(_, FailureMap0) },
- { code_info__pick_stack_resume_point(FailureMap0, StackMap, _) },
- { FailureCont = failure_cont(nondet(known, no),
- stack_only(StackMap, label(ResumeLabel))) },
- code_info__push_failure_cont(FailureCont),
- code_info__get_next_label(RedoLabel),
- { HijackCode = node([
- assign(redoip(lval(maxfr)),
- const(code_addr_const(label(RedoLabel)))) -
- "Hijack the failure cont"
- ]) },
- { PreCommit = tree(SaveCode, HijackCode) }.
+ code_info__maybe_restore_trail_info(MaybeTrailSlots,
+ CommitTrailCode, RestoreTrailCode),
-code_info__generate_semi_commit(RedoLabel, Slots, Commit) -->
code_info__get_next_label(SuccLabel),
{ GotoSuccLabel = node([
goto(label(SuccLabel)) - "Jump to success continuation"
@@ -1929,240 +2121,104 @@
{ SuccLabelCode = node([
label(SuccLabel) - "Success continuation"
]) },
- { RedoLabelCode = node([
- label(RedoLabel) - "Failure (redo) continuation"
- ]) },
-
- code_info__grab_code_info(CodeInfo0),
- code_info__top_failure_cont(FailureCont),
- { FailureCont = failure_cont(_, FailureMaps) },
- code_info__generate_resume_setup(FailureMaps, FailureContCode),
- code_info__pop_failure_cont,
- code_info__generate_failure(Fail),
- code_info__slap_code_info(CodeInfo0),
- code_info__pop_failure_cont,
-
- code_info__undo_pre_commit_saves(Slots, RestoreMaxfr, RestoreRedoip,
- RestoreCurfr, SuccPopCode, FailPopCode),
-
{ SuccessCode =
- tree(RestoreMaxfr,
- tree(RestoreRedoip,
- tree(RestoreCurfr,
- SuccPopCode)))
+ tree(SuccessUndoCode,
+ CommitTrailCode)
},
- { FailCode =
- tree(RedoLabelCode,
- tree(RestoreCurfr,
- tree(FailureContCode,
- tree(RestoreRedoip,
- tree(FailPopCode,
- Fail)))))
+ { FailureCode =
+ tree(ResumePointCode,
+ tree(FailureUndoCode,
+ tree(RestoreTrailCode,
+ FailCode)))
},
- { Commit =
+ { Code =
tree(SuccessCode,
tree(GotoSuccLabel,
- tree(FailCode,
+ tree(FailureCode,
SuccLabelCode)))
}.
%---------------------------------------------------------------------------%
-code_info__generate_det_pre_commit(Slots, PreCommit) -->
- code_info__generate_pre_commit_saves(Slots, PreCommit),
- % Since the code we are cutting is model_non, it will call
- % unset_failure_cont. If the current top entry on the failure stack
- % at the time is semidet, this would cause unset_failure_cont to abort.
- % We therefore push a dummy nondet failure continuation onto the
- % failure stack. Since the code we are cutting across is multi,
- % the failure continuation will never actually be used.
- code_info__top_failure_cont(FailureCont0),
- { FailureCont0 = failure_cont(_, FailureMap) },
- { code_info__pick_stack_resume_point(FailureMap, StackMap, _) },
- { FailureCont = failure_cont(nondet(known, no),
- stack_only(StackMap, do_fail)) },
- code_info__push_failure_cont(FailureCont).
-
-code_info__generate_det_commit(Slots, Commit) -->
- % Remove the dummy failure continuation pushed by det_pre_commit.
- code_info__pop_failure_cont,
- code_info__undo_pre_commit_saves(Slots, RestoreMaxfr, RestoreRedoip,
- RestoreCurfr, SuccPopCode, _FailPopCode),
- { Commit = tree(RestoreMaxfr,
- tree(RestoreRedoip,
- tree(RestoreCurfr,
- SuccPopCode)))
- }.
-
-%---------------------------------------------------------------------------%
-
-:- pred code_info__generate_pre_commit_saves(commit_slots, code_tree,
- code_info, code_info).
-:- mode code_info__generate_pre_commit_saves(out, out, in, out) is det.
+:- pred code_info__maybe_save_trail_info(maybe(pair(lval))::out,
+ code_tree::out, code_info::in, code_info::out) is det.
-code_info__generate_pre_commit_saves(Slots, Code) -->
+code_info__maybe_save_trail_info(MaybeTrailSlots, SaveTrailCode) -->
code_info__get_globals(Globals),
{ globals__lookup_bool_option(Globals, use_trail, UseTrail) },
( { UseTrail = yes } ->
- { NumSlots = 5 },
- { SaveMessage =
- "push space for curfr, maxfr, redoip, ticket_counter and trail_ptr" }
+ code_info__acquire_temp_slot(ticket_counter, CounterSlot),
+ code_info__acquire_temp_slot(ticket, TrailPtrSlot),
+ { MaybeTrailSlots = yes(CounterSlot - TrailPtrSlot) },
+ { SaveTrailCode = node([
+ mark_ticket_stack(CounterSlot)
+ - "save the ticket counter",
+ store_ticket(TrailPtrSlot)
+ - "save the trail pointer"
+ ]) }
;
- { NumSlots = 3 },
- { SaveMessage = "push space for curfr, maxfr, and redoip" }
- ),
- code_info__get_proc_model(CodeModel),
- ( { CodeModel = model_non } ->
- % the pushes and pops on the det stack below will cause
- % problems for accurate garbage collection. Hence we
- % make sure the commit vals are made live, so gc
- % can figure out what is going on later.
- code_info__get_module_info(ModuleInfo),
- code_info__get_pred_id(PredId),
- { predicate_module(ModuleInfo, PredId, ModuleName) },
- { predicate_name(ModuleInfo, PredId, PredName) },
- { prog_out__sym_name_to_string(ModuleName, ModuleNameString) },
- { string__append_list(["commit in ",
- ModuleNameString, ":", PredName], Message) },
- { PushCode = node([
- incr_sp(NumSlots, Message) - SaveMessage
+ { MaybeTrailSlots = no },
+ { SaveTrailCode = empty }
+ ).
+
+:- pred code_info__maybe_restore_trail_info(maybe(pair(lval))::in,
+ code_tree::out, code_tree::out, code_info::in, code_info::out) is det.
+
+code_info__maybe_restore_trail_info(MaybeTrailSlots,
+ CommitCode, RestoreCode) -->
+ (
+ { MaybeTrailSlots = no },
+ { CommitCode = empty },
+ { RestoreCode = empty }
+ ;
+ { MaybeTrailSlots = yes(CounterSlot - TrailPtrSlot) },
+ { CommitTrailCode = node([
+ reset_ticket(lval(TrailPtrSlot), commit)
+ - "discard trail entries and restore trail ptr"
]) },
- { CurfrSlot = stackvar(1) },
- { MaxfrSlot = stackvar(2) },
- { RedoipSlot = stackvar(3) },
- ( { UseTrail = yes } ->
- { TicketCounterSlot = stackvar(4) },
- { TrailPtrSlot = stackvar(5) },
- { MaybeTrailSlots = yes(TicketCounterSlot -
- TrailPtrSlot) }
- ;
- { MaybeTrailSlots = no }
- ),
- { Slots = commit_slots(CurfrSlot, MaxfrSlot, RedoipSlot,
- MaybeTrailSlots) },
- code_info__add_commit_triple
- ;
- { PushCode = empty },
- code_info__acquire_temp_slot(lval(curfr), CurfrSlot),
- code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
- code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
- RedoipSlot),
- ( { UseTrail = yes } ->
- code_info__acquire_temp_slot(ticket_counter,
- TicketCounterSlot),
- code_info__acquire_temp_slot(ticket, TrailPtrSlot),
- { MaybeTrailSlots = yes(TicketCounterSlot -
- TrailPtrSlot) }
- ;
- { MaybeTrailSlots = no }
- ),
- { Slots = commit_slots(CurfrSlot, MaxfrSlot, RedoipSlot,
- MaybeTrailSlots) }
- ),
- { SaveCode = node([
- assign(CurfrSlot, lval(curfr)) -
- "Save current nondet frame pointer",
- assign(MaxfrSlot, lval(maxfr)) -
- "Save top of nondet stack",
- assign(RedoipSlot, lval(redoip(lval(maxfr)))) -
- "Save the top redoip"
- ]) },
- { MaybeTrailSlots = yes(TheTicketCounterSlot - TheTrailPtrSlot) ->
- MaybeSaveTrailCode = node([
- mark_ticket_stack(TheTicketCounterSlot) -
- "Save the ticket counter",
- store_ticket(TheTrailPtrSlot) -
- "Save the trail pointer"
- ])
- ;
- MaybeSaveTrailCode = empty
- },
- { Code = tree(PushCode, tree(SaveCode, MaybeSaveTrailCode)) }.
+ { RestoreTrailCode = node([
+ reset_ticket(lval(TrailPtrSlot), undo)
+ - "apply trail entries and restore trail ptr"
+ ]) },
+ { RestoreCounterCode = node([
+ discard_tickets_to(lval(CounterSlot))
+ - "restore the ticket counter"
+ ]) },
+ code_info__release_temp_slot(CounterSlot),
+ code_info__release_temp_slot(TrailPtrSlot),
+ { CommitCode = tree(CommitTrailCode, RestoreCounterCode) },
+ { RestoreCode = tree(RestoreTrailCode, RestoreCounterCode) }
+ ).
-:- pred code_info__undo_pre_commit_saves(commit_slots, code_tree, code_tree,
- code_tree, code_tree, code_tree, code_info, code_info).
-:- mode code_info__undo_pre_commit_saves(in, out, out, out, out, out, in, out)
- is det.
+%---------------------------------------------------------------------------%
-code_info__undo_pre_commit_saves(Slots, RestoreMaxfr, RestoreRedoip,
- RestoreCurfr, SuccPopCode, FailPopCode) -->
- { Slots = commit_slots(CurfrSlot, MaxfrSlot, RedoipSlot,
- MaybeTrailSlots) },
- { RestoreMaxfr = node([
- assign(maxfr, lval(MaxfrSlot)) -
- "Prune away unwanted choice-points"
- ]) },
- { RestoreRedoip = node([
- assign(redoip(lval(maxfr)), lval(RedoipSlot)) -
- "Restore the top redoip"
- ]) },
- { RestoreCurfr = node([
- assign(curfr, lval(CurfrSlot)) -
- "Restore nondet frame pointer"
- ]) },
- code_info__get_proc_model(CodeModel),
- ( { CodeModel = model_non } ->
- code_info__rem_commit_triple,
- ( { MaybeTrailSlots = yes(TicketCounterSlot - TrailPtrSlot) } ->
- { CommitTrail = node([
- reset_ticket(lval(TrailPtrSlot), commit) -
- "discard trail entries and restore trail ptr"
- ]) },
- { RestoreTrail = node([
- reset_ticket(lval(TrailPtrSlot), undo) -
- "apply trail entries and restore trail ptr"
- ]) },
- { RestoreTicketCounter = node([
- discard_tickets_to(lval(TicketCounterSlot)) -
- "restore the ticket counter"
- ]) },
- { NumSlots = 5 },
- { PopMessage =
- "pop curfr, maxfr, redoip, ticket_counter and trail_ptr" }
- ;
- { CommitTrail = empty },
- { RestoreTrail = empty },
- { RestoreTicketCounter = empty },
- { NumSlots = 3 },
- { PopMessage = "pop curfr, maxfr, and redoip" }
- ),
- { MainPopCode = node([
- decr_sp(NumSlots) - PopMessage
- ]) }
+:- pred code_info__clone_resume_point(resume_point_info::in,
+ resume_point_info::out, code_info::in, code_info::out) is det.
+
+code_info__clone_resume_point(ResumePoint0, ResumePoint) -->
+ (
+ { ResumePoint0 = orig_only(_, _) },
+ { error("cloning orig_only resume point") }
;
- code_info__release_temp_slot(CurfrSlot),
- code_info__release_temp_slot(MaxfrSlot),
- code_info__release_temp_slot(RedoipSlot),
- ( { MaybeTrailSlots = yes(TicketCounterSlot - TrailPtrSlot) } ->
- { CommitTrail = node([
- reset_ticket(lval(TrailPtrSlot), commit) -
- "discard trail entries and restore trail ptr"
- ]) },
- { RestoreTrail = node([
- reset_ticket(lval(TrailPtrSlot), undo) -
- "apply trail entries and restore trail ptr"
- ]) },
- { RestoreTicketCounter = node([
- discard_tickets_to(lval(TicketCounterSlot)) -
- "restore the ticket counter"
- ]) },
- code_info__release_temp_slot(TicketCounterSlot),
- code_info__release_temp_slot(TrailPtrSlot)
- ;
- { CommitTrail = empty },
- { RestoreTrail = empty },
- { RestoreTicketCounter = empty }
- ),
- { MainPopCode = empty }
- ),
- { SuccPopCode =
- tree(CommitTrail,
- tree(RestoreTicketCounter,
- MainPopCode)) },
- { FailPopCode =
- tree(RestoreTrail,
- tree(RestoreTicketCounter,
- MainPopCode)) }.
+ { ResumePoint0 = stack_only(Map1, _) },
+ code_info__get_next_label(Label1),
+ { Addr1 = label(Label1) },
+ { ResumePoint = stack_only(Map1, Addr1) }
+ ;
+ { ResumePoint0 = stack_and_orig(Map1, _, Map2, _) },
+ code_info__get_next_label(Label1),
+ { Addr1 = label(Label1) },
+ code_info__get_next_label(Label2),
+ { Addr2 = label(Label2) },
+ { ResumePoint = stack_and_orig(Map1, Addr1, Map2, Addr2) }
+ ;
+ { ResumePoint0 = orig_and_stack(Map1, _, Map2, _) },
+ code_info__get_next_label(Label2),
+ { Addr2 = label(Label2) },
+ code_info__get_next_label(Label1),
+ { Addr1 = label(Label1) },
+ { ResumePoint = stack_and_orig(Map2, Addr2, Map1, Addr1) }
+ ).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
@@ -2330,7 +2386,7 @@
% Used for cases where the temp slot might still be needed again
% on backtracking and thus can't be reused in the code that follows.
:- pred code_info__reset_and_pop_ticket(lval, reset_trail_reason,
- code_tree, code_info, code_info).
+ code_tree, code_info, code_info).
:- mode code_info__reset_and_pop_ticket(in, in, out, in, out) is det.
:- pred code_info__discard_ticket(lval, code_tree, code_info, code_info).
@@ -2350,8 +2406,7 @@
:- pred code_info__maybe_reset_and_pop_ticket(maybe(lval),
reset_trail_reason, code_tree, code_info, code_info).
-:- mode code_info__maybe_reset_and_pop_ticket(in, in, out, in, out)
- is det.
+:- mode code_info__maybe_reset_and_pop_ticket(in, in, out, in, out) is det.
:- pred code_info__maybe_discard_ticket(maybe(lval), code_tree,
code_info, code_info).
@@ -2456,11 +2511,9 @@
{ Code = empty }
).
-code_info__maybe_reset_and_pop_ticket(MaybeTicketSlot, Reason, Code)
- -->
+code_info__maybe_reset_and_pop_ticket(MaybeTicketSlot, Reason, Code) -->
( { MaybeTicketSlot = yes(TicketSlot) } ->
- code_info__reset_and_pop_ticket(TicketSlot, Reason,
- Code)
+ code_info__reset_and_pop_ticket(TicketSlot, Reason, Code)
;
{ Code = empty }
).
@@ -2530,20 +2583,6 @@
:- pred code_info__clear_r1(code_tree, code_info, code_info).
:- mode code_info__clear_r1(out, in, out) is det.
-:- pred code_info__generate_branch_end(code_model, store_map, code_tree,
- code_info, code_info).
-:- mode code_info__generate_branch_end(in, in, out, in, out) is det.
-
- % code_info__remake_with_store_map throws away the exprn_info data
- % structure, forgetting the current locations of all variables,
- % and rebuilds it from scratch based on the given store map.
- % The new exprn_info will know about only the variables present
- % in the store map, and will believe they are where the store map
- % says they are.
-
-:- pred code_info__remake_with_store_map(store_map, code_info, code_info).
-:- mode code_info__remake_with_store_map(in, in, out) is det.
-
:- type call_direction ---> caller ; callee.
% Generate code to either setup the input arguments for a call
@@ -2681,34 +2720,6 @@
%---------------------------------------------------------------------------%
-code_info__generate_branch_end(CodeModel, StoreMap, Code) -->
- code_info__get_exprn_info(Exprn0),
- { map__to_assoc_list(StoreMap, VarLocs) },
- { code_exprn__place_vars(VarLocs, PlaceCode, Exprn0, Exprn) },
- code_info__set_exprn_info(Exprn),
- ( { CodeModel = model_non } ->
- code_info__unset_failure_cont(FlushCode),
- { Code = tree(PlaceCode, FlushCode) }
- ;
- { Code = PlaceCode }
- ).
-
-code_info__remake_with_store_map(StoreMap) -->
- { map__to_assoc_list(StoreMap, VarLvals) },
- { code_info__fixup_lvallist(VarLvals, VarRvals) },
- code_info__get_exprn_info(Exprn0),
- { code_exprn__reinit_state(VarRvals, Exprn0, Exprn) },
- code_info__set_exprn_info(Exprn).
-
-:- pred code_info__fixup_lvallist(assoc_list(var, lval), assoc_list(var, rval)).
-:- mode code_info__fixup_lvallist(in, out) is det.
-
-code_info__fixup_lvallist([], []).
-code_info__fixup_lvallist([V - L | Ls], [V - lval(L) | Rs]) :-
- code_info__fixup_lvallist(Ls, Rs).
-
-%---------------------------------------------------------------------------%
-
code_info__setup_call([], _Direction, empty) --> [].
code_info__setup_call([V - arg_info(Loc, Mode) | Rest], Direction, Code) -->
(
@@ -2804,7 +2815,7 @@
code_info, code_info).
:- mode code_info__generate_stack_livevals(in, out, in, out) is det.
-:- pred code_info__generate_stack_livelvals(set(var), instmap,
+:- pred code_info__generate_stack_livelvals(set(var), instmap,
list(liveinfo), code_info, code_info).
:- mode code_info__generate_stack_livelvals(in, in, out, in, out) is det.
@@ -2821,9 +2832,7 @@
code_info__generate_var_livevals(VarList, LiveVals0, LiveVals1),
code_info__get_temps_in_use(TempsSet),
{ map__to_assoc_list(TempsSet, Temps) },
- { code_info__generate_temp_livevals(Temps, LiveVals1, LiveVals2) },
- code_info__get_commit_triple_count(Triples),
- { code_info__generate_commit_livevals(Triples, LiveVals2, LiveVals) }.
+ { code_info__generate_temp_livevals(Temps, LiveVals1, LiveVals) }.
:- pred code_info__generate_var_livevals(list(var), set(lval), set(lval),
code_info, code_info).
@@ -2844,26 +2853,6 @@
set__insert(Vals0, Slot, Vals1),
code_info__generate_temp_livevals(Slots, Vals1, Vals).
-:- pred code_info__generate_commit_livevals(int, set(lval), set(lval)).
-:- mode code_info__generate_commit_livevals(in, in, out) is det.
-
-code_info__generate_commit_livevals(Triples0, Vals0, Vals) :-
- ( Triples0 = 0 ->
- Vals = Vals0
- ;
- CurfrSlot is (Triples0 - 1) * 3 + 1,
- MaxfrSlot is (Triples0 - 1) * 3 + 2,
- RedoipSlot is (Triples0 - 1) * 3 + 3,
- CurfrVar = stackvar(CurfrSlot),
- MaxfrVar = stackvar(MaxfrSlot),
- RedoipVar = stackvar(RedoipSlot),
- set__insert(Vals0, CurfrVar, Vals1),
- set__insert(Vals1, MaxfrVar, Vals2),
- set__insert(Vals2, RedoipVar, Vals3),
- Triples1 is Triples0 - 1,
- code_info__generate_commit_livevals(Triples1, Vals3, Vals)
- ).
-
%---------------------------------------------------------------------------%
code_info__generate_stack_livelvals(Args, AfterCallInstMap, LiveVals) -->
@@ -2890,9 +2879,7 @@
AfterCallInstMap, LiveVals3),
code_info__get_temps_in_use(TempsSet),
{ map__to_assoc_list(TempsSet, Temps) },
- { code_info__generate_temp_livelvals(Temps, LiveVals3, LiveVals4) },
- code_info__get_commit_triple_count(Triples),
- { code_info__generate_commit_livelvals(Triples, LiveVals4, LiveVals) }.
+ { code_info__generate_temp_livelvals(Temps, LiveVals3, LiveVals) }.
:- pred code_info__generate_var_livelvals(list(var),
set(pair(lval, var)), set(pair(lval, var)), code_info, code_info).
@@ -2914,35 +2901,6 @@
code_info__get_live_value_type(StoredLval, LiveValueType),
code_info__generate_temp_livelvals(Slots, LiveInfo0, LiveInfo1).
-:- pred code_info__generate_commit_livelvals(int,
- list(liveinfo), list(liveinfo)).
-:- mode code_info__generate_commit_livelvals(in, in, out) is det.
-
-code_info__generate_commit_livelvals(Triples0, LiveInfo0, LiveInfo) :-
- ( Triples0 = 0 ->
- LiveInfo = LiveInfo0
- ;
- Triples1 is Triples0 - 1,
- code_info__generate_commit_livelvals(Triples1,
- LiveInfo0, LiveInfo1),
- CurfrSlot is (Triples0 - 1) * 3 + 1,
- MaxfrSlot is (Triples0 - 1) * 3 + 2,
- RedoipSlot is (Triples0 - 1) * 3 + 3,
- CurfrVar = stackvar(CurfrSlot),
- MaxfrVar = stackvar(MaxfrSlot),
- RedoipVar = stackvar(RedoipSlot),
- code_info__get_live_value_type(lval(curfr), CurfrValueType),
- code_info__get_live_value_type(lval(maxfr), MaxfrValueType),
- code_info__get_live_value_type(lval(redoip(lval(maxfr))),
- RedoipValueType),
- LiveInfo2 = [live_lvalue(CurfrVar, CurfrValueType, "", []) |
- LiveInfo1],
- LiveInfo3 = [live_lvalue(MaxfrVar, MaxfrValueType, "", []) |
- LiveInfo2],
- LiveInfo = [live_lvalue(RedoipVar, RedoipValueType, "", []) |
- LiveInfo3]
- ).
-
:- pred code_info__livevals_to_livelvals(assoc_list(lval, var), bool,
instmap, list(liveinfo), code_info, code_info).
:- mode code_info__livevals_to_livelvals(in, in, in, out, in, out) is det.
@@ -2977,6 +2935,7 @@
code_info__get_live_value_type(lval(curfr), curfr).
code_info__get_live_value_type(lval(succfr(_)), unwanted).
code_info__get_live_value_type(lval(prevfr(_)), unwanted).
+code_info__get_live_value_type(lval(redofr(_)), unwanted).
code_info__get_live_value_type(lval(redoip(_)), unwanted).
code_info__get_live_value_type(lval(succip(_)), unwanted).
code_info__get_live_value_type(lval(sp), unwanted).
More information about the developers
mailing list