mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-18 23:35:25 +00:00
Fix a long-known undocumented bug in which preds for which
code_gen.{nl,pp}:
Fix a long-known undocumented bug in which preds for which
the main conj has inst 'unreachable' aborted.
Before generating a negated goal, save live variables onto
the stack so we can find them again later.
ite_gen.nl:
Before generating the condition of an if-then-else, save the
live variables onto the stack so that we can find them in the
else clause.
live_vars.nl:
Add interference for the cases where live vars are saved before
negations and ite conditions.
This commit is contained in:
@@ -528,11 +528,18 @@ code_gen__generate_det_prolog(EntryCode, SUsed) -->
|
||||
:- mode code_gen__generate_det_epilog(out, in, out) is det.
|
||||
|
||||
code_gen__generate_det_epilog(ExitCode) -->
|
||||
code_info__get_instmap(Instmap),
|
||||
code_info__get_arginfo(ArgModes),
|
||||
code_info__get_headvars(HeadVars),
|
||||
{ assoc_list__from_corresponding_lists(HeadVars, ArgModes, Args)},
|
||||
(
|
||||
{ Instmap = unreachable }
|
||||
->
|
||||
{ CodeA = empty }
|
||||
;
|
||||
code_info__setup_call(Args, HeadVars, callee, CodeA)
|
||||
),
|
||||
code_info__get_succip_used(Used),
|
||||
{ assoc_list__from_corresponding_lists(HeadVars, ArgModes, Args) },
|
||||
code_info__setup_call(Args, HeadVars, callee, CodeA),
|
||||
code_info__get_total_stackslot_count(NS0),
|
||||
(
|
||||
{ Used = yes }
|
||||
@@ -620,11 +627,18 @@ code_gen__generate_semi_prolog(EntryCode, SUsed) -->
|
||||
:- mode code_gen__generate_semi_epilog(out, in, out) is det.
|
||||
|
||||
code_gen__generate_semi_epilog(Instr) -->
|
||||
code_info__get_instmap(Instmap),
|
||||
code_info__get_arginfo(ArgModes),
|
||||
code_info__get_headvars(HeadVars),
|
||||
{assoc_list__from_corresponding_lists(HeadVars,ArgModes,Args) },
|
||||
(
|
||||
{ Instmap = unreachable }
|
||||
->
|
||||
{ CodeA = empty }
|
||||
;
|
||||
code_info__setup_call(Args, HeadVars, callee, CodeA)
|
||||
),
|
||||
code_info__get_succip_used(Used),
|
||||
{ assoc_list__from_corresponding_lists(HeadVars, ArgModes, Args) },
|
||||
code_info__setup_call(Args, HeadVars, callee, CodeA),
|
||||
code_info__get_total_stackslot_count(NS0),
|
||||
code_info__failure_cont(FailCont),
|
||||
{ code_gen__output_args(Args, LiveArgs0) },
|
||||
@@ -731,10 +745,17 @@ code_gen__generate_non_prolog(EntryCode, no) -->
|
||||
:- mode code_gen__generate_non_epilog(out, in, out) is det.
|
||||
|
||||
code_gen__generate_non_epilog(Instr) -->
|
||||
code_info__get_instmap(Instmap),
|
||||
code_info__get_arginfo(ArgModes),
|
||||
code_info__get_headvars(HeadVars),
|
||||
{ assoc_list__from_corresponding_lists(HeadVars, ArgModes, Args) },
|
||||
code_info__setup_call(Args, HeadVars, callee, CodeA),
|
||||
{assoc_list__from_corresponding_lists(HeadVars,ArgModes,Args) },
|
||||
(
|
||||
{ Instmap = unreachable }
|
||||
->
|
||||
{ CodeA = empty }
|
||||
;
|
||||
code_info__setup_call(Args, HeadVars, callee, CodeA)
|
||||
),
|
||||
{ code_gen__output_args(Args, LiveArgs) },
|
||||
{ LiveValCode = node([
|
||||
livevals(LiveArgs) - ""
|
||||
@@ -918,17 +939,19 @@ code_gen__generate_negation(Goal, Code) -->
|
||||
code_info__get_next_label(SuccLab),
|
||||
code_info__push_failure_cont(known(SuccLab)),
|
||||
code_info__maybe_save_hp(Reclaim, SaveHeapCode),
|
||||
code_info__generate_nondet_saves(SaveCode),
|
||||
% The contained goal cannot be nondet, because if it's
|
||||
% mode-correct, it won't have any output vars, and so
|
||||
% it will be semi-det.
|
||||
code_gen__generate_semi_goal(Goal, GoalCode),
|
||||
code_info__remake_with_call_info,
|
||||
code_info__maybe_restore_hp(Reclaim, RestoreHeapCode),
|
||||
code_info__pop_failure_cont,
|
||||
code_info__generate_failure(FailCode),
|
||||
{ SuccessCode = node([
|
||||
label(SuccLab) - "negated goal failed, so proceed"
|
||||
]) },
|
||||
{ Code = tree(tree(SaveHeapCode, GoalCode),
|
||||
{ Code = tree(tree(tree(SaveHeapCode, SaveCode), GoalCode),
|
||||
tree(FailCode, tree(SuccessCode, RestoreHeapCode))) }.
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
@@ -41,17 +41,19 @@ ite_gen__generate_det_ite(CondGoal, ThenGoal, ElseGoal, Instr) -->
|
||||
code_info__maybe_save_hp(ReclaimHeap, HPSaveCode),
|
||||
code_info__get_next_label(ElseLab),
|
||||
code_info__push_failure_cont(known(ElseLab)),
|
||||
code_info__generate_nondet_saves(SaveCode),
|
||||
% Grab the instmap
|
||||
code_info__get_instmap(InstMap),
|
||||
% generate the semi-deterministic test goal
|
||||
code_info__get_instmap(InstMap),
|
||||
code_info__grab_code_info(CodeInfo),
|
||||
code_gen__generate_semi_goal(CondGoal, TestCode),
|
||||
code_info__pop_failure_cont,
|
||||
code_info__grab_code_info(CodeInfo),
|
||||
code_info__maybe_pop_stack(ReclaimHeap, HPPopCode),
|
||||
code_gen__generate_forced_det_goal(ThenGoal, ThenGoalCode),
|
||||
% generate code that executes the then condition
|
||||
% and branches to the end of the if-then-else
|
||||
code_info__slap_code_info(CodeInfo),
|
||||
code_info__remake_with_call_info,
|
||||
% restore the instmap
|
||||
code_info__set_instmap(InstMap),
|
||||
code_info__maybe_restore_hp(ReclaimHeap, HPRestoreCode),
|
||||
@@ -74,7 +76,7 @@ ite_gen__generate_det_ite(CondGoal, ThenGoal, ElseGoal, Instr) -->
|
||||
) },
|
||||
% generate the then condition
|
||||
{ Instr = tree(
|
||||
tree(HPSaveCode, TestCode),
|
||||
tree(tree(HPSaveCode, SaveCode), TestCode),
|
||||
tree(ThenCode, ElseCode)
|
||||
) },
|
||||
code_info__remake_with_store_map.
|
||||
@@ -95,18 +97,23 @@ ite_gen__generate_semidet_ite(CondGoal, ThenGoal, ElseGoal, Instr) -->
|
||||
code_info__maybe_save_hp(ReclaimHeap, HPSaveCode),
|
||||
code_info__get_next_label(ElseLab),
|
||||
code_info__push_failure_cont(known(ElseLab)),
|
||||
code_info__generate_nondet_saves(SaveCode),
|
||||
% generate the semi-deterministic test goal
|
||||
code_gen__generate_semi_goal(CondGoal, CondCode),
|
||||
code_info__pop_failure_cont,
|
||||
code_info__get_instmap(InstMap),
|
||||
code_info__grab_code_info(CodeInfo),
|
||||
code_info__maybe_pop_stack(ReclaimHeap, HPPopCode),
|
||||
code_gen__generate_forced_semi_goal(ThenGoal, ThenGoalCode),
|
||||
code_info__slap_code_info(CodeInfo),
|
||||
code_info__remake_with_call_info,
|
||||
% restore the instmap
|
||||
code_info__set_instmap(InstMap),
|
||||
code_info__maybe_restore_hp(ReclaimHeap, HPRestoreCode),
|
||||
code_gen__generate_forced_semi_goal(ElseGoal, ElseGoalCode),
|
||||
code_info__get_next_label(EndLab),
|
||||
{ TestCode = tree(
|
||||
HPSaveCode,
|
||||
tree(HPSaveCode, SaveCode),
|
||||
CondCode
|
||||
) },
|
||||
{ ThenCode = tree(
|
||||
@@ -147,6 +154,7 @@ ite_gen__generate_nondet_ite(CondGoal, ThenGoal, ElseGoal, Instr) -->
|
||||
code_info__maybe_save_hp(ReclaimHeap, HPSaveCode),
|
||||
code_info__get_next_label(ElseLab),
|
||||
code_info__push_failure_cont(known(ElseLab)),
|
||||
code_info__generate_nondet_saves(SaveCode),
|
||||
{ CondGoal = _ - GoalInfo },
|
||||
{ goal_info_determinism(GoalInfo, CondDeterminism) },
|
||||
{ CondDeterminism = nondeterministic ->
|
||||
@@ -164,16 +172,20 @@ ite_gen__generate_nondet_ite(CondGoal, ThenGoal, ElseGoal, Instr) -->
|
||||
;
|
||||
{ RestoreRedoipCode = empty }
|
||||
),
|
||||
code_info__get_instmap(InstMap),
|
||||
code_info__grab_code_info(CodeInfo),
|
||||
code_info__maybe_pop_stack(ReclaimHeap, HPPopCode),
|
||||
code_gen__generate_forced_non_goal(ThenGoal, ThenGoalCode),
|
||||
code_info__slap_code_info(CodeInfo),
|
||||
code_info__remake_with_call_info,
|
||||
% restore the instmap
|
||||
code_info__set_instmap(InstMap),
|
||||
code_info__maybe_restore_hp(ReclaimHeap, HPRestoreCode),
|
||||
code_gen__generate_forced_non_goal(ElseGoal, ElseGoalCode),
|
||||
code_info__get_next_label(EndLab),
|
||||
{ TestCode = tree(
|
||||
tree(
|
||||
HPSaveCode,
|
||||
tree(HPSaveCode, SaveCode),
|
||||
ModRedoipCode
|
||||
),
|
||||
CondCode
|
||||
|
||||
@@ -167,7 +167,8 @@ detect_live_vars_in_goal_2(switch(_Var, _Det, Cases0), ExtraLives0, Liveness0,
|
||||
detect_live_vars_in_goal_2(if_then_else(_Vars, Cond0, Then0, Else0),
|
||||
ExtraLives0, Liveness0, LiveSets0, Category,
|
||||
ModuleInfo, ExtraLives, Liveness, LiveSets) :-
|
||||
detect_live_vars_in_goal(Cond0, ExtraLives0, Liveness0, LiveSets0,
|
||||
set__insert(LiveSets0, Liveness0, LiveSets0A),
|
||||
detect_live_vars_in_goal(Cond0, ExtraLives0, Liveness0, LiveSets0A,
|
||||
Category,ModuleInfo, ExtraLives1, Liveness1, LiveSets1),
|
||||
detect_live_vars_in_goal(Then0, ExtraLives1, Liveness1, LiveSets1,
|
||||
Category,ModuleInfo,ExtraLives2, _Liveness2, LiveSets2),
|
||||
@@ -176,7 +177,8 @@ detect_live_vars_in_goal_2(if_then_else(_Vars, Cond0, Then0, Else0),
|
||||
|
||||
detect_live_vars_in_goal_2(not(Goal0), ExtraLives0, Liveness0, LiveSets0,
|
||||
Category, ModuleInfo, ExtraLives, Liveness, LiveSets) :-
|
||||
detect_live_vars_in_goal(Goal0, ExtraLives0, Liveness0, LiveSets0,
|
||||
set__insert(LiveSets0, Liveness0, LiveSets1),
|
||||
detect_live_vars_in_goal(Goal0, ExtraLives0, Liveness0, LiveSets1,
|
||||
Category, ModuleInfo, ExtraLives, Liveness, LiveSets).
|
||||
|
||||
detect_live_vars_in_goal_2(some(_Vs, Goal0), ExtraLives0, Liveness0, LiveSets0,
|
||||
|
||||
Reference in New Issue
Block a user