mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-20 16:31:04 +00:00
Makefile.common: Add a pair of rules for builing the library dependencies. *_gen.nl code_info.nl: Fix spelling error. code_gen.nl toplevel.nl: Pass io__state into the top of the code generator to print status messages. liveness.nl: More fixes. Needs change to goal_info structure. Will happen soon.
137 lines
4.4 KiB
Mathematica
137 lines
4.4 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module switch_gen.
|
|
|
|
:- interface.
|
|
|
|
:- import_module hlds, llds, code_gen, code_info, code_util.
|
|
|
|
:- pred switch_gen__generate_det_switch(var, list(case),
|
|
code_tree, code_info, code_info).
|
|
:- mode switch_gen__generate_det_switch(in, in, out, in, out) is det.
|
|
|
|
:- pred switch_gen__generate_semi_switch(var, list(case),
|
|
code_tree, code_info, code_info).
|
|
:- mode switch_gen__generate_semi_switch(in, in, out, in, out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- implementation.
|
|
|
|
:- import_module tree, list, map, std_util, require.
|
|
|
|
switch_gen__generate_det_switch(CaseVar, Cases, Instr) -->
|
|
code_info__flush_variable(CaseVar, Code0),
|
|
code_info__get_variable_register(CaseVar, Lval),
|
|
{ VarCode = node(Code0) },
|
|
code_info__get_next_label(EndLabel),
|
|
switch_gen__generate_det_cases(Cases, CaseVar,
|
|
Lval, EndLabel, CasesCode),
|
|
{ Instr = tree(VarCode, CasesCode) },
|
|
code_info__remake_code_info.
|
|
|
|
:- pred switch_gen__generate_det_cases(list(case), var, lval, label,
|
|
code_tree, code_info, code_info).
|
|
:- mode switch_gen__generate_det_cases(in, in, in, in, out, in, out) is det.
|
|
|
|
switch_gen__generate_det_cases([], _Var, _Lval, EndLabel, Code) -->
|
|
{ Code = node([label(EndLabel) - " End of switch"]) }.
|
|
switch_gen__generate_det_cases([case(Cons, Goal)|Cases], Var, Lval, EndLabel,
|
|
CasesCode) -->
|
|
code_info__get_next_label(ElseLab),
|
|
code_info__grab_code_info(CodeInfo),
|
|
code_info__cons_id_to_abstag(Var, Cons, Tag),
|
|
(
|
|
{ Tag = simple(TagNum0) }
|
|
->
|
|
{ TagNum = TagNum0 }
|
|
;
|
|
{ Tag = unsimple(TagNum1) }
|
|
->
|
|
{ TagNum = TagNum1 }
|
|
;
|
|
{ error("This can never happen") }
|
|
),
|
|
{ TestCode = node([
|
|
if_tag(Lval, TagNum, ElseLab) - "Test the tag"
|
|
]) },
|
|
% generate the case as a semi-deterministc goal
|
|
code_gen__generate_forced_det_goal(Goal, ThisCode),
|
|
{ ElseLabel = node([
|
|
goto(EndLabel) - "skip to the end of the switch",
|
|
label(ElseLab) - "next case"
|
|
]) },
|
|
% generate the rest of the cases.
|
|
code_info__slap_code_info(CodeInfo),
|
|
switch_gen__generate_det_cases(Cases, Var, Lval, EndLabel, CasesCode0),
|
|
{ CasesCode = tree(tree(TestCode, ThisCode),
|
|
tree(ElseLabel, CasesCode0)) }.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
switch_gen__generate_semi_switch(CaseVar, Cases, Instr) -->
|
|
code_info__flush_variable(CaseVar, Code0),
|
|
code_info__get_variable_register(CaseVar, Lval),
|
|
{ VarCode = node(Code0) },
|
|
code_info__get_next_label(EndLabel),
|
|
switch_gen__generate_semi_cases(Cases, CaseVar, Lval,
|
|
EndLabel, CasesCode),
|
|
{ Instr = tree(VarCode, CasesCode) },
|
|
code_info__remake_code_info.
|
|
|
|
:- pred switch_gen__generate_semi_cases(list(case), var, lval, label,
|
|
code_tree, code_info, code_info).
|
|
:- mode switch_gen__generate_semi_cases(in, in, in, in, out, in, out) is det.
|
|
|
|
switch_gen__generate_semi_cases([], _Var, _Lval, EndLabel, Code) -->
|
|
code_info__get_fall_through(FallThrough),
|
|
{ Code = node([
|
|
goto(FallThrough) - "fail",
|
|
label(EndLabel) - "End of switch"
|
|
]) }.
|
|
switch_gen__generate_semi_cases([case(Cons, Goal)|Cases], Var, Lval, EndLabel,
|
|
CasesCode) -->
|
|
code_info__grab_code_info(CodeInfo),
|
|
code_info__get_next_label(ElseLab),
|
|
code_info__cons_id_to_abstag(Var, Cons, Tag),
|
|
(
|
|
{ Tag = simple(TagNum0) }
|
|
->
|
|
{ TagNum = TagNum0 }
|
|
;
|
|
{ Tag = unsimple(TagNum1) }
|
|
->
|
|
{ TagNum = TagNum1 }
|
|
;
|
|
{ error("This can never happen") }
|
|
),
|
|
{ TestCode = node([
|
|
if_tag(Lval, TagNum, ElseLab) - "Test the tag"
|
|
]) },
|
|
% generate the case as a semi-deterministc goal
|
|
code_gen__generate_forced_semi_goal(Goal, ThisCode),
|
|
{ ElseLabel = node([
|
|
goto(EndLabel) - "skip to the end of the switch",
|
|
label(ElseLab) - "next case"
|
|
]) },
|
|
% If there are more cases, the we need to restore
|
|
% the expression cache, etc.
|
|
(
|
|
{ Cases = [_|_] }
|
|
->
|
|
code_info__slap_code_info(CodeInfo)
|
|
;
|
|
{ true }
|
|
),
|
|
% generate the rest of the cases.
|
|
switch_gen__generate_semi_cases(Cases, Var, Lval, EndLabel, CasesCode0),
|
|
{ CasesCode = tree(tree(TestCode, ThisCode),
|
|
tree(ElseLabel, CasesCode0)) }.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|