mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 23:05:21 +00:00
Estimated hours taken: 6 Branches: main Delete the old tree.m module (which did a small subset of what cords now do), and switch to using cords instead. This is more standard, as well as very slightly more efficient, because with cords, e.g. concatenating ten code fragments of which eight are empty doesn't allocate ten cons cells. My measurements show a 0.1% reduction in executable size and a 0.3% reduction in compilation time. Both of those are in the noise; the main reason for the change is more convenient coding. compiler/tree.m: Remove this module. compiler/libs.m: Remove the inclusion of tree.m. compiler/notes/compiler_design.html: Remove the description of tree.m. compiler/bytecode.m: Switch to using cords to represent code in the bytecode backend. compiler/llds.m: Switch to using cords to represent code in the LLDS backend. compiler/mlds_to_il.m: Switch to using cords to represent IL code being built. compiler/bytecode_gen.m: compiler/call_gen.m: compiler/code_gen.m: compiler/code_info.m: compiler/commit_gen.m: compiler/dense_switch.m: compiler/disj_gen.m: compiler/ite_gen.m: compiler/lookup_switch.m: compiler/lookup_util.m: compiler/middle_rec.m: compiler/par_conj_gen.m: compiler/pragma_c_gen.m: compiler/proc_gen.m: compiler/string_switch.m: compiler/switch_case.m: compiler/switch_gen.m: compiler/tag_switch.m: compiler/trace_gen.m: compiler/unify_gen.m: compiler/var_locn.m: Conform to the changes above. library/cord.m: Add a predicate form of map.
144 lines
5.4 KiB
Mathematica
144 lines
5.4 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2007, 2009 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: switch_case.m.
|
|
% Author: zs.
|
|
%
|
|
% Utility predicates for handling switch cases, especially those representing
|
|
% more than one cons_id, for the LLDS backend.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module ll_backend.switch_case.
|
|
|
|
:- interface.
|
|
|
|
:- import_module hlds.code_model.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module ll_backend.code_info.
|
|
:- import_module ll_backend.llds.
|
|
|
|
:- import_module map.
|
|
|
|
:- type represent_params
|
|
---> represent_params(
|
|
switch_var_name :: string,
|
|
switch_goal_info :: hlds_goal_info,
|
|
switch_code_model :: code_model,
|
|
starting_position :: position_info,
|
|
switch_end_label :: label
|
|
).
|
|
|
|
:- type case_code_included
|
|
---> case_code_not_yet_included
|
|
; case_code_already_included.
|
|
|
|
:- type case_label_info
|
|
---> case_label_info(
|
|
case_description :: string,
|
|
case_code :: llds_code,
|
|
case_code_included :: case_code_included
|
|
).
|
|
|
|
:- type case_label_map == map(label, case_label_info).
|
|
|
|
% represent_tagged_case_for_llds(Params, TaggedCase, Label,
|
|
% !CaseLabelMap, !MaybeEnd, !CI):
|
|
%
|
|
% Given TaggedCase, generate code for it (using the information in Params,
|
|
% and updating MaybeEnd and CI). The code will start with the newly
|
|
% allocated label Label. This label will represent the case in
|
|
% CaseLabelMap. The corresponding case_label_info will contain a comment
|
|
% describing the case in terms of the cons_ids it handles, the generated
|
|
% code (starting with the label instruction for Label and ending with
|
|
% the jump to the end label of the switch), and an indication that this
|
|
% code has not yet been included anywhere.
|
|
%
|
|
:- pred represent_tagged_case_for_llds(represent_params::in,
|
|
tagged_case::in, label::out, case_label_map::in, case_label_map::out,
|
|
branch_end::in, branch_end::out, code_info::in, code_info::out) is det.
|
|
|
|
% generate_case_code_or_jump(CaseLabel, Code, !CaseLabelMap):
|
|
%
|
|
:- pred generate_case_code_or_jump(label::in, llds_code::out,
|
|
case_label_map::in, case_label_map::out) is det.
|
|
|
|
:- pred add_remaining_case(label::in, case_label_info::in,
|
|
llds_code::in, llds_code::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.switch_util.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module hlds.hlds_llds.
|
|
:- import_module hlds.hlds_out.
|
|
:- import_module ll_backend.code_gen.
|
|
:- import_module ll_backend.trace_gen.
|
|
|
|
:- import_module cord.
|
|
:- import_module list.
|
|
:- import_module string.
|
|
:- import_module svmap.
|
|
|
|
represent_tagged_case_for_llds(Params, TaggedCase, Label, !CaseLabelMap,
|
|
!MaybeEnd, !CI) :-
|
|
Params = represent_params(SwitchVarName, SwitchGoalInfo, CodeModel,
|
|
BranchStart, EndLabel),
|
|
TaggedCase = tagged_case(MainTaggedConsId, OtherTaggedConsIds, Goal),
|
|
project_cons_name_and_tag(MainTaggedConsId, MainConsName, _),
|
|
list.map2(project_cons_name_and_tag, OtherTaggedConsIds,
|
|
OtherConsNames, _),
|
|
Comment = case_comment(SwitchVarName, MainConsName, OtherConsNames),
|
|
reset_to_position(BranchStart, !CI),
|
|
get_next_label(Label, !CI),
|
|
LabelCode = singleton(
|
|
llds_instr(label(Label), Comment)
|
|
),
|
|
maybe_generate_internal_event_code(Goal, SwitchGoalInfo, TraceCode, !CI),
|
|
generate_goal(CodeModel, Goal, GoalCode, !CI),
|
|
goal_info_get_store_map(SwitchGoalInfo, StoreMap),
|
|
generate_branch_end(StoreMap, !MaybeEnd, SaveCode, !CI),
|
|
GotoEndCode = singleton(
|
|
llds_instr(goto(code_label(EndLabel)),
|
|
"goto end of switch on " ++ SwitchVarName)
|
|
),
|
|
Code = LabelCode ++ TraceCode ++ GoalCode ++ SaveCode ++ GotoEndCode,
|
|
CaseInfo = case_label_info(Comment, Code, case_code_not_yet_included),
|
|
svmap.det_insert(Label, CaseInfo, !CaseLabelMap).
|
|
|
|
generate_case_code_or_jump(CaseLabel, Code, !CaseLabelMap) :-
|
|
map.lookup(!.CaseLabelMap, CaseLabel, CaseInfo0),
|
|
CaseInfo0 = case_label_info(Comment, CaseCode, CaseIncluded),
|
|
(
|
|
CaseIncluded = case_code_not_yet_included,
|
|
Code = CaseCode,
|
|
CaseInfo = CaseInfo0 ^ case_code_included
|
|
:= case_code_already_included,
|
|
svmap.det_update(CaseLabel, CaseInfo, !CaseLabelMap)
|
|
;
|
|
CaseIncluded = case_code_already_included,
|
|
% We cannot include the case's code, since it has already been included
|
|
% somewhere else.
|
|
Code = singleton(
|
|
llds_instr(goto(code_label(CaseLabel)), "goto " ++ Comment)
|
|
)
|
|
).
|
|
|
|
add_remaining_case(_Label, CaseInfo, !Code) :-
|
|
CaseInfo = case_label_info(_Comment, CaseCode, CaseIncluded),
|
|
(
|
|
CaseIncluded = case_code_not_yet_included,
|
|
!:Code = !.Code ++ CaseCode
|
|
;
|
|
CaseIncluded = case_code_already_included
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|