[m-dev.] for review: update alias branch [2]
Simon Taylor
stayl at cs.mu.OZ.AU
Tue May 4 15:55:47 AEST 1999
-----------------------------------------------------------------------------
The diffs for the following modules are relative to the alias branch:
-----------------------------------------------------------------------------
Index: code_info.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/code_info.m,v
retrieving revision 1.211.2.20
diff -u -u -r1.211.2.20 code_info.m
--- code_info.m 1998/11/24 06:27:21 1.211.2.20
+++ code_info.m 1999/05/03 06:32:25
@@ -1,5 +1,5 @@
%---------------------------------------------------------------------------%
-% Copyright (C) 1994-1998 The University of Melbourne.
+% Copyright (C) 1994-1999 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.
%---------------------------------------------------------------------------%
@@ -36,10 +36,10 @@
:- implementation.
-:- import_module code_util, code_exprn, prog_out, inst_match.
+:- import_module code_util, code_exprn, llds_out, prog_out, inst_match.
:- import_module arg_info, type_util, mode_util, options.
-:- import_module term, varset.
+:- import_module term, varset.
:- import_module set, stack.
:- import_module string, require, char, bimap, tree, int.
@@ -65,11 +65,10 @@
% Create a new code_info structure. Also return the
% outermost resumption point, and info about the non-fixed
% stack slots used for tracing purposes.
-:- pred code_info__init(prog_varset, set(prog_var), stack_slots, bool, globals,
- pred_id, proc_id, proc_info, instmap, follow_vars, module_info,
- int, resume_point_info, trace_slot_info, code_info).
-:- mode code_info__init(in, in, in, in, in, in, in, in, in, in, in, in,
- out, out, out) is det.
+:- pred code_info__init(bool, globals, pred_id, proc_id, proc_info,
+ follow_vars, module_info, int, resume_point_info,
+ trace_slot_info, code_info).
+:- mode code_info__init(in, in, in, in, in, in, in, in, out, out, out) is det.
% Get the globals table.
:- pred code_info__get_globals(globals, code_info, code_info).
@@ -123,14 +122,27 @@
:- pred code_info__get_cell_count(int, code_info, code_info).
:- mode code_info__get_cell_count(out, in, out) is det.
+:- pred code_info__set_cell_count(int, code_info, code_info).
+:- mode code_info__set_cell_count(in, in, out) is det.
+
% Get the flag that indicates whether succip is used or not.
:- pred code_info__get_succip_used(bool, code_info, code_info).
:- mode code_info__get_succip_used(out, in, out) is det.
+ % Get the label layout information created by tracing
+ % during code generation.
:- pred code_info__get_layout_info(map(label, internal_layout_info),
code_info, code_info).
:- mode code_info__get_layout_info(out, in, out) is det.
+ % Get the global static data structures that have
+ % been created during code generation and which do
+ % not have to be scanned by llds_common, since they
+ % have no common parts by construction.
+:- pred code_info__get_non_common_static_data(list(comp_gen_c_data),
+ code_info, code_info).
+:- mode code_info__get_non_common_static_data(out, in, out) is det.
+
%---------------------------------------------------------------------------%
:- implementation.
@@ -172,9 +184,6 @@
:- pred code_info__set_label_count(int, code_info, code_info).
:- mode code_info__set_label_count(in, in, out) is det.
-:- pred code_info__set_cell_count(int, code_info, code_info).
-:- mode code_info__set_cell_count(in, in, out) is det.
-
:- pred code_info__set_succip_used(bool, code_info, code_info).
:- mode code_info__set_succip_used(in, in, out) is det.
@@ -196,6 +205,10 @@
code_info, code_info).
:- mode code_info__set_temp_content_map(in, in, out) is det.
+:- pred code_info__set_non_common_static_data(list(comp_gen_c_data),
+ code_info, code_info).
+:- mode code_info__set_non_common_static_data(in, in, out) is det.
+
%---------------------------------------------------------------------------%
% The code_info structure has three groups of fields.
@@ -263,7 +276,7 @@
int, % The maximum number of extra
% temporary stackslots that have been
% used during the procedure.
- map(lval, slot_contents)
+ map(lval, slot_contents),
% The temporary locations that have ever been
% used on the stack, and what they contain.
% Once we have used a stack slot to store
@@ -274,20 +287,27 @@
% which would make it impossible to describe
% to gc what the slot contains after the end
% of the branched control structure.
+ list(comp_gen_c_data)
+ % Static data structures created for this
+ % procedure which do not need to be scanned
+ % by llds_common.
).
%---------------------------------------------------------------------------%
-code_info__init(Varset, Liveness, StackSlots, SaveSuccip, Globals,
- PredId, ProcId, ProcInfo, Instmap, FollowVars, ModuleInfo,
- CellCount, ResumePoint, TraceSlotInfo, CodeInfo) :-
+code_info__init(SaveSuccip, Globals, PredId, ProcId, ProcInfo, FollowVars,
+ ModuleInfo, CellCount, ResumePoint, TraceSlotInfo, CodeInfo) :-
+ proc_info_get_initial_instmap(ProcInfo, ModuleInfo, InstMap),
+ proc_info_liveness_info(ProcInfo, Liveness),
proc_info_headvars(ProcInfo, HeadVars),
proc_info_arg_info(ProcInfo, ArgInfos),
proc_info_interface_code_model(ProcInfo, CodeModel),
assoc_list__from_corresponding_lists(HeadVars, ArgInfos, Args),
arg_info__build_input_arg_list(Args, ArgList),
globals__get_options(Globals, Options),
- code_exprn__init_state(ArgList, Varset, StackSlots, FollowVars,
+ proc_info_varset(ProcInfo, VarSet),
+ proc_info_stack_slots(ProcInfo, StackSlots),
+ code_exprn__init_state(ArgList, VarSet, StackSlots, FollowVars,
Options, ExprnInfo),
stack__init(ResumePoints),
globals__lookup_bool_option(Globals, allow_hijacks, AllowHijack),
@@ -313,12 +333,12 @@
PredId,
ProcId,
ProcInfo,
- Varset,
+ VarSet,
SlotMax,
no,
Liveness,
- Instmap,
+ InstMap,
Zombies,
ExprnInfo,
TempsInUse,
@@ -329,7 +349,8 @@
SaveSuccip,
LayoutMap,
0,
- TempContentMap
+ TempContentMap,
+ []
),
code_info__init_maybe_trace_info(Globals, ModuleInfo, ProcInfo,
MaybeFailVars, TraceSlotInfo, CodeInfo0, CodeInfo1),
@@ -357,163 +378,173 @@
code_info__get_globals(SA, CI, CI) :-
CI = code_info(SA, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _).
+ _, _, _, _, _, _, _, _, _, _, _, _, _).
code_info__get_module_info(SB, CI, CI) :-
CI = code_info(_, SB, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _).
+ _, _, _, _, _, _, _, _, _, _, _, _, _).
code_info__get_pred_id(SC, CI, CI) :-
CI = code_info(_, _, SC, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _).
+ _, _, _, _, _, _, _, _, _, _, _, _, _).
code_info__get_proc_id(SD, CI, CI) :-
CI = code_info(_, _, _, SD, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _).
+ _, _, _, _, _, _, _, _, _, _, _, _, _).
code_info__get_proc_info(SE, CI, CI) :-
CI = code_info(_, _, _, _, SE, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _).
+ _, _, _, _, _, _, _, _, _, _, _, _, _).
code_info__get_varset(SF, CI, CI) :-
CI = code_info(_, _, _, _, _, SF, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _).
+ _, _, _, _, _, _, _, _, _, _, _, _, _).
code_info__get_var_slot_count(SG, CI, CI) :-
CI = code_info(_, _, _, _, _, _, SG, _,
- _, _, _, _, _, _, _, _, _, _, _, _).
+ _, _, _, _, _, _, _, _, _, _, _, _, _).
code_info__get_maybe_trace_info(SH, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, SH,
- _, _, _, _, _, _, _, _, _, _, _, _).
+ _, _, _, _, _, _, _, _, _, _, _, _, _).
code_info__get_forward_live_vars(LA, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- LA, _, _, _, _, _, _, _, _, _, _, _).
+ LA, _, _, _, _, _, _, _, _, _, _, _, _).
code_info__get_instmap(LB, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, LB, _, _, _, _, _, _, _, _, _, _).
+ _, LB, _, _, _, _, _, _, _, _, _, _, _).
code_info__get_zombies(LC, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, _, LC, _, _, _, _, _, _, _, _, _).
+ _, _, LC, _, _, _, _, _, _, _, _, _, _).
code_info__get_exprn_info(LD, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, _, _, LD, _, _, _, _, _, _, _, _).
+ _, _, _, LD, _, _, _, _, _, _, _, _, _).
code_info__get_temps_in_use(LE, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, _, _, _, LE, _, _, _, _, _, _, _).
+ _, _, _, _, LE, _, _, _, _, _, _, _, _).
code_info__get_fail_info(LF, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, _, _, _, _, LF, _, _, _, _, _, _).
+ _, _, _, _, _, LF, _, _, _, _, _, _, _).
code_info__get_label_count(PA, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, _, _, _, _, _, PA, _, _, _, _, _).
+ _, _, _, _, _, _, PA, _, _, _, _, _, _).
code_info__get_cell_count(PB, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, PB, _, _, _, _).
+ _, _, _, _, _, _, _, PB, _, _, _, _, _).
code_info__get_succip_used(PC, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, PC, _, _, _).
+ _, _, _, _, _, _, _, _, PC, _, _, _, _).
code_info__get_layout_info(PD, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, PD, _, _).
+ _, _, _, _, _, _, _, _, _, PD, _, _, _).
code_info__get_max_temp_slot_count(PE, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, PE, _).
+ _, _, _, _, _, _, _, _, _, _, PE, _, _).
code_info__get_temp_content_map(PF, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, PF).
+ _, _, _, _, _, _, _, _, _, _, _, PF, _).
+
+code_info__get_non_common_static_data(PG, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, PG).
%---------------------------------------------------------------------------%
code_info__set_maybe_trace_info(SH, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, _,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF),
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_forward_live_vars(LA, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- _, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF),
+ _, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_instmap(LB, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, _, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF),
+ LA, _, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_zombies(LC, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, _, LD, LE, LF, PA, PB, PC, PD, PE, PF),
+ LA, LB, _, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_exprn_info(LD, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, _, LE, LF, PA, PB, PC, PD, PE, PF),
+ LA, LB, LC, _, LE, LF, PA, PB, PC, PD, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_temps_in_use(LE, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, _, LF, PA, PB, PC, PD, PE, PF),
+ LA, LB, LC, LD, _, LF, PA, PB, PC, PD, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_fail_info(LF, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, _, PA, PB, PC, PD, PE, PF),
+ LA, LB, LC, LD, LE, _, PA, PB, PC, PD, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_label_count(PA, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, _, PB, PC, PD, PE, PF),
+ LA, LB, LC, LD, LE, LF, _, PB, PC, PD, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_cell_count(PB, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, _, PC, PD, PE, PF),
+ LA, LB, LC, LD, LE, LF, PA, _, PC, PD, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_succip_used(PC, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, _, PD, PE, PF),
+ LA, LB, LC, LD, LE, LF, PA, PB, _, PD, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_layout_info(PD, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, _, PE, PF),
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, _, PE, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_max_temp_slot_count(PE, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, _, PF),
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, _, PF, PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__set_temp_content_map(PF, CI0, CI) :-
CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, _ ),
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, _ , PG),
CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
+
+code_info__set_non_common_static_data(PG, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, _ ),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
@@ -560,12 +591,6 @@
code_info, code_info).
:- mode code_info__lookup_type_defn(in, out, in, out) is det.
- % For each type variable in the given list, find out where the
- % typeinfo var for that type variable is.
-:- pred code_info__find_typeinfos_for_tvars(list(tvar),
- map(tvar, set(layout_locn)), code_info, code_info).
-:- mode code_info__find_typeinfos_for_tvars(in, out, in, out) is det.
-
% Given a constructor id, and a variable (so that we can work out the
% type of the constructor), determine correct tag (representation)
% of that constructor.
@@ -638,6 +663,14 @@
code_info, code_info).
:- mode code_info__add_trace_layout_for_label(in, in, in, out) is det.
+:- pred code_info__add_gc_layout_for_label(label, layout_label_info,
+ code_info, code_info).
+:- mode code_info__add_gc_layout_for_label(in, in, in, out) is det.
+
+:- pred code_info__add_non_common_static_data(comp_gen_c_data,
+ code_info, code_info).
+:- mode code_info__add_non_common_static_data(in, in, out) is det.
+
%---------------------------------------------------------------------------%
:- implementation.
@@ -664,10 +697,6 @@
code_exprn__set_follow_vars(FollowVars, ExprnInfo0, ExprnInfo),
code_info__set_exprn_info(ExprnInfo, CI0, CI).
-:- pred code_info__get_active_temps_data(assoc_list(lval, slot_contents),
- code_info, code_info).
-:- mode code_info__get_active_temps_data(out, in, out) is det.
-
%-----------------------------------------------------------------------------%
% Update the code info structure to be consistent
@@ -723,9 +752,15 @@
%---------------------------------------------------------------------------%
-code_info__variable_type(Var, Type) -->
+:- pred code_info__get_var_types(map(prog_var, type), code_info, code_info).
+:- mode code_info__get_var_types(out, in, out) is det.
+
+code_info__get_var_types(VarTypes) -->
code_info__get_proc_info(ProcInfo),
- { proc_info_vartypes(ProcInfo, VarTypes) },
+ { proc_info_vartypes(ProcInfo, VarTypes) }.
+
+code_info__variable_type(Var, Type) -->
+ code_info__get_var_types(VarTypes),
{ map__lookup(VarTypes, Var, Type) }.
code_info__lookup_type_defn(Type, TypeDefn) -->
@@ -738,44 +773,6 @@
{ module_info_types(ModuleInfo, TypeTable) },
{ map__lookup(TypeTable, TypeId, TypeDefn) }.
-code_info__find_typeinfos_for_tvars(TypeVars, TypeInfoDataMap) -->
- code_info__variable_locations(VarLocs),
- code_info__get_varset(VarSet),
- code_info__get_proc_info(ProcInfo),
- { proc_info_typeinfo_varmap(ProcInfo, TypeInfoMap) },
- { map__apply_to_list(TypeVars, TypeInfoMap, TypeInfoLocns) },
- { FindLocn = lambda([TypeInfoLocn::in, Locns::out] is det, (
- type_info_locn_var(TypeInfoLocn, TypeInfoVar),
- (
- map__search(VarLocs, TypeInfoVar, TypeInfoRvalSet)
- ->
- ConvertRval = lambda([Locn::out] is nondet, (
- set__member(Rval, TypeInfoRvalSet),
- Rval = lval(Lval),
- (
- TypeInfoLocn = typeclass_info(_,
- FieldNum),
- Locn = indirect(Lval, FieldNum)
- ;
- TypeInfoLocn = type_info(_),
- Locn = direct(Lval)
- )
- )),
- solutions_set(ConvertRval, Locns)
- ;
- varset__lookup_name(VarSet, TypeInfoVar,
- VarString),
- string__format("%s: %s %s",
- [s("code_info__find_typeinfos_for_tvars"),
- s("can't find lval for type_info var"),
- s(VarString)], ErrStr),
- error(ErrStr)
- )
- )) },
- { list__map(FindLocn, TypeInfoLocns, TypeInfoVarLocns) },
- { map__from_corresponding_lists(TypeVars, TypeInfoVarLocns,
- TypeInfoDataMap) }.
-
code_info__cons_id_to_tag(Var, ConsId, ConsTag) -->
code_info__variable_type(Var, Type),
code_info__get_module_info(ModuleInfo),
@@ -869,12 +866,38 @@
},
code_info__set_layout_info(Internals).
+code_info__add_gc_layout_for_label(Label, LayoutInfo) -->
+ code_info__get_layout_info(Internals0),
+ { map__search(Internals0, Label, Internal0) ->
+ Internal0 = internal_layout_info(Exec, Agc0),
+ ( Agc0 = no ->
+ true
+ ;
+ error("adding gc layout for already known label")
+ ),
+ Internal = internal_layout_info(Exec, yes(LayoutInfo)),
+ map__set(Internals0, Label, Internal, Internals)
+ ;
+ Internal = internal_layout_info(no, yes(LayoutInfo)),
+ map__det_insert(Internals0, Label, Internal, Internals)
+ },
+ code_info__set_layout_info(Internals).
+
+:- pred code_info__get_active_temps_data(assoc_list(lval, slot_contents),
+ code_info, code_info).
+:- mode code_info__get_active_temps_data(out, in, out) is det.
+
code_info__get_active_temps_data(Temps) -->
code_info__get_temps_in_use(TempsInUse),
code_info__get_temp_content_map(TempContentMap),
{ map__select(TempContentMap, TempsInUse, TempsInUseContentMap) },
{ map__to_assoc_list(TempsInUseContentMap, Temps) }.
+code_info__add_non_common_static_data(NonCommonData) -->
+ code_info__get_non_common_static_data(NonCommonDatas0),
+ code_info__set_non_common_static_data(
+ [NonCommonData | NonCommonDatas0]).
+
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
@@ -901,6 +924,10 @@
code_info, code_info).
:- mode code_info__after_all_branches(in, in, in, out) is det.
+:- pred code_info__save_hp_in_branch(code_tree, lval, position_info,
+ position_info).
+:- mode code_info__save_hp_in_branch(out, out, in, out) is det.
+
:- implementation.
:- type position_info
@@ -919,11 +946,11 @@
code_info__reset_to_position(position_info(PosCI), CurCI, NextCI) :-
% The static fields in PosCI and CurCI should be identical.
PosCI = code_info(_, _, _, _, _, _, _, _,
- LA, LB, LC, LD, LE, LF, _, _, _, _, _, _ ),
+ LA, LB, LC, LD, LE, LF, _, _, _, _, _, _, _ ),
CurCI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- _, _, _, _, _, _, PA, PB, PC, PD, PE, PF),
+ _, _, _, _, _, _, PA, PB, PC, PD, PE, PF, PG),
NextCI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
- LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG).
code_info__generate_branch_end(StoreMap, MaybeEnd0, MaybeEnd, Code) -->
code_info__get_exprn_info(Exprn0),
@@ -1022,6 +1049,11 @@
code_info__fixup_lval(V - store_info(val, L), V - value(lval(L))).
code_info__fixup_lval(V - store_info(ref, L), V - reference(L)).
+code_info__save_hp_in_branch(Code, Slot, Pos0, Pos) :-
+ Pos0 = position_info(CodeInfo0),
+ code_info__save_hp(Code, Slot, CodeInfo0, CodeInfo),
+ Pos = position_info(CodeInfo).
+
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
@@ -1213,6 +1245,12 @@
:- pred code_info__resume_point_stack_addr(resume_point_info::in,
code_addr::out) is det.
+ % Convert resume_map to map(var, set(rval)),
+ % removing all reference()'s.
+:- pred code_info__resume_map_to_variable_locations(
+ map(prog_var, set(val_or_ref))::in,
+ map(prog_var, set(rval))::out) is det.
+
%---------------------------------------------------------------------------%
:- implementation.
@@ -1671,8 +1709,10 @@
:- type commit_hijack_info
---> commit_temp_frame(
- lval % The stack slot in which we saved
+ lval, % The stack slot in which we saved
% the old value of maxfr.
+ bool % Do we bracket the goal with
+ % MR_commit_mark and MR_commit_cut?
)
; commit_quarter_hijack
; commit_half_hijack(
@@ -1705,14 +1745,45 @@
{ Allow = not_allowed ; CondEnv = inside_non_condition }
->
code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
- { HijackInfo = commit_temp_frame(MaxfrSlot) },
{ MaxfrCode = node([
assign(MaxfrSlot, lval(maxfr))
- "prepare for temp frame commit"
]) },
code_info__create_temp_frame(StackLabel,
"prepare for temp frame commit", TempFrameCode),
- { HijackCode = tree(MaxfrCode, TempFrameCode) }
+ code_info__get_globals(Globals),
+ { globals__lookup_bool_option(Globals, use_minimal_model,
+ UseMinimalModel) },
+ { HijackInfo = commit_temp_frame(MaxfrSlot, UseMinimalModel) },
+ {
+ UseMinimalModel = yes,
+ % If the code we are committing across starts but
+ % does not complete the evaluation of a tabled subgoal,
+ % the cut will remove the generator's choice point,
+ % so that the evaluation of the subgoal will never
+ % be completed. We handle such "dangling" generators
+ % by removing them from the subgoal trie of the
+ % tabled procedure. This requires knowing what
+ % tabled subgoals are started inside commits,
+ % which is why we wrap the goal being committed across
+ % inside MR_commit_{mark,cut}.
+ Components = [
+ pragma_c_raw_code(
+ "\tsave_transient_registers();\n"),
+ pragma_c_raw_code(
+ "\tMR_commit_mark();\n"),
+ pragma_c_raw_code(
+ "\trestore_transient_registers();\n")
+ ],
+ MarkCode = node([
+ pragma_c([], Components, will_not_call_mercury,
+ no, no) - ""
+ ])
+ ;
+ UseMinimalModel = no,
+ MarkCode = empty
+ },
+ { HijackCode = tree(MaxfrCode, tree(TempFrameCode, MarkCode)) }
;
{ ResumeKnown = resume_point_known },
{ CurfrMaxfr = must_be_equal }
@@ -1726,6 +1797,7 @@
{ CurfrMaxfr = must_be_equal }
->
% Here ResumeKnown must be resume_point_unknown.
+
code_info__acquire_temp_slot(lval(redoip(lval(curfr))),
RedoipSlot),
{ HijackInfo = commit_half_hijack(RedoipSlot) },
@@ -1767,13 +1839,30 @@
HijackInfo, MaybeTrailSlots) },
code_info__set_fail_info(FailInfo),
+ % XXX should release the temp slots in each arm of the switch
(
- { HijackInfo = commit_temp_frame(MaxfrSlot) },
- { SuccessUndoCode = node([
+ { HijackInfo = commit_temp_frame(MaxfrSlot, UseMinimalModel) },
+ { MaxfrCode = node([
assign(maxfr, lval(MaxfrSlot))
- - "restore maxfr for full commit hijack"
+ - "restore maxfr for temp frame hijack"
]) },
- { FailureUndoCode = SuccessUndoCode }
+ {
+ UseMinimalModel = yes,
+ % See the comment in prepare_for_semi_commit above.
+ Components = [
+ pragma_c_raw_code("\tMR_commit_cut();\n")
+ ],
+ CutCode = node([
+ pragma_c([], Components,
+ will_not_call_mercury, no, no)
+ - "commit for temp frame hijack"
+ ])
+ ;
+ UseMinimalModel = no,
+ CutCode = empty
+ },
+ { SuccessUndoCode = tree(MaxfrCode, CutCode) },
+ { FailureUndoCode = tree(MaxfrCode, CutCode) }
;
{ HijackInfo = commit_quarter_hijack },
{ FailInfo = fail_info(ResumePoints, _, _, _, _) },
@@ -2094,19 +2183,7 @@
map(prog_var, set(rval))::in) is semidet.
code_info__match_resume_loc(Map0, Locations0) :-
- % Convert resume_map to map(var, set(rval)), removing all reference()'s.
- map__to_assoc_list(Map0, AL0),
- Filter = lambda([V::in, R::out] is semidet, (
- V = Variable - VVals,
- set__to_sorted_list(VVals, Vs),
- list__filter_map(code_exprn__value_to_rval, Vs, Rs),
- Rs \= [],
- set__sorted_list_to_set(Rs, RvalsSet),
- R = Variable - RvalsSet
- )),
- list__filter_map(Filter, AL0, AL),
- map__from_assoc_list(AL, Map),
-
+ code_info__resume_map_to_variable_locations(Map0, Map),
map__keys(Map, KeyList),
set__list_to_set(KeyList, Keys),
map__select(Locations0, Keys, Locations),
@@ -2332,7 +2409,8 @@
label(Label1) -
"stack only failure continuation"
]) },
- code_info__set_var_locations(Map1)
+ code_info__set_var_locations(Map1),
+ code_info__generate_resume_layout(Label1, Map1)
;
{ ResumePoint = stack_and_orig(Map1, Addr1, Map2, Addr2) },
{ extract_label_from_code_addr(Addr1, Label1) },
@@ -2342,6 +2420,7 @@
"stack failure continuation before orig"
]) },
code_info__set_var_locations(Map1),
+ code_info__generate_resume_layout(Label1, Map1),
{ map__to_assoc_list(Map2, AssocList2) },
code_info__place_resume_vars(AssocList2, PlaceCode),
{ Label2Code = node([
@@ -2366,6 +2445,7 @@
"stack failure continuation after orig"
]) },
code_info__set_var_locations(Map2),
+ code_info__generate_resume_layout(Label2, Map2),
{ Code = tree(Label1Code, tree(PlaceCode, Label2Code)) }
).
@@ -2442,7 +2522,7 @@
code_info__resume_point_stack_addr(ResumePoint, StackAddr) :-
code_info__pick_stack_resume_point(ResumePoint, _, StackAddr).
-%---------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
:- pred code_info__maybe_save_trail_info(maybe(pair(lval))::out,
code_tree::out, code_info::in, code_info::out) is det.
@@ -2525,6 +2605,21 @@
).
%---------------------------------------------------------------------------%
+
+code_info__resume_map_to_variable_locations(Map0, Map) :-
+ map__to_assoc_list(Map0, AL0),
+ Filter = lambda([V::in, R::out] is semidet, (
+ V = Variable - VVals,
+ set__to_sorted_list(VVals, Vs),
+ list__filter_map(code_exprn__value_to_rval, Vs, Rs),
+ Rs \= [],
+ set__sorted_list_to_set(Rs, RvalsSet),
+ R = Variable - RvalsSet
+ )),
+ list__filter_map(Filter, AL0, AL),
+ map__from_assoc_list(AL, Map).
+
+%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
% Submodule to deal with liveness issues.
@@ -3270,98 +3365,34 @@
code_info__generate_return_live_lvalues(OutputArgLocs, ReturnInstMap,
LiveLvalues) -->
+ code_info__variable_locations(VarLocs),
code_info__get_known_variables(Vars),
- code_info__get_globals(Globals),
- { globals__want_return_var_layouts(Globals, WantReturnVarLayout) },
- code_info__get_inst_table(InstTable),
- code_info__find_return_var_lvals(Vars, OutputArgLocs, VarLvals),
- code_info__generate_var_live_lvalues(VarLvals, InstTable,
- ReturnInstMap, WantReturnVarLayout, VarLiveLvalues),
-
code_info__get_active_temps_data(Temps),
- { code_info__generate_temp_live_lvalues(Temps, TempLiveLvalues) },
-
- { list__append(VarLiveLvalues, TempLiveLvalues, LiveLvalues) }.
-
-:- pred code_info__find_return_var_lvals(list(prog_var)::in,
- assoc_list(prog_var, arg_loc)::in, assoc_list(prog_var, lval)::out,
- code_info::in, code_info::out) is det.
-
-code_info__find_return_var_lvals([], _, []) --> [].
-code_info__find_return_var_lvals([Var | Vars], OutputArgLocs,
- [Var - Lval | VarLvals]) -->
- ( { assoc_list__search(OutputArgLocs, Var, ArgLoc) } ->
- % On return, output arguments are in their registers.
- { code_util__arg_loc_to_register(ArgLoc, Lval) }
- ;
- % On return, other live variables are in their stack slots.
- code_info__get_variable_slot(Var, Lval)
- ),
- code_info__find_return_var_lvals(Vars, OutputArgLocs, VarLvals).
-
-:- pred code_info__generate_temp_live_lvalues(
- assoc_list(lval, slot_contents)::in, list(liveinfo)::out) is det.
-
-code_info__generate_temp_live_lvalues([], []).
-code_info__generate_temp_live_lvalues([Temp | Temps], [Live | Lives]) :-
- Temp = Slot - Contents,
- code_info__get_live_value_type(Contents, LiveLvalueType),
- map__init(Empty),
- Live = live_lvalue(direct(Slot), LiveLvalueType, Empty),
- code_info__generate_temp_live_lvalues(Temps, Lives).
+ code_info__get_proc_info(ProcInfo),
+ code_info__get_globals(Globals),
+ { proc_info_inst_table(ProcInfo, InstTable) },
+ { continuation_info__generate_return_live_lvalues(OutputArgLocs,
+ ReturnInstMap, InstTable, Vars, VarLocs,
+ Temps, ProcInfo, Globals, LiveLvalues) }.
-:- pred code_info__generate_var_live_lvalues(assoc_list(prog_var, lval)::in,
- inst_table::in, instmap::in, bool::in, list(liveinfo)::out,
+:- pred code_info__generate_resume_layout(label::in, resume_map::in,
code_info::in, code_info::out) is det.
-code_info__generate_var_live_lvalues([], _, _, _, []) --> [].
-code_info__generate_var_live_lvalues([Var - Lval | VarLvals], InstTable,
- InstMap, WantReturnVarLayout, [Live | Lives]) -->
- (
- { WantReturnVarLayout = yes }
- ->
- code_info__get_varset(VarSet),
- { varset__lookup_name(VarSet, Var, Name) },
- code_info__variable_type(Var, Type),
- { instmap__lookup_var(InstMap, Var, Inst) },
- { type_util__vars(Type, TypeVars) },
- code_info__find_typeinfos_for_tvars(TypeVars, TypeParams),
- { QualInst = qualified_inst(InstTable, Inst) },
- { VarInfo = var(Var, Name, Type, QualInst) },
- { Live = live_lvalue(direct(Lval), VarInfo, TypeParams) }
+code_info__generate_resume_layout(Label, ResumeMap) -->
+ code_info__get_globals(Globals),
+ { globals__lookup_bool_option(Globals, agc_stack_layout,
+ AgcStackLayout) },
+ ( { AgcStackLayout = yes } ->
+ code_info__get_active_temps_data(Temps),
+ code_info__get_instmap(InstMap),
+ code_info__get_inst_table(InstTable),
+ code_info__get_proc_info(ProcInfo),
+ { continuation_info__generate_resume_layout(ResumeMap,
+ Temps, InstMap, InstTable, ProcInfo, Layout) },
+ code_info__add_gc_layout_for_label(Label, Layout)
;
- { map__init(Empty) },
- { Live = live_lvalue(direct(Lval), unwanted, Empty) }
- ),
- code_info__generate_var_live_lvalues(VarLvals, InstTable, InstMap,
- WantReturnVarLayout, Lives).
-
-:- pred code_info__get_live_value_type(slot_contents::in, live_value_type::out)
- is det.
-
-code_info__get_live_value_type(lval(succip), succip).
-code_info__get_live_value_type(lval(hp), hp).
-code_info__get_live_value_type(lval(maxfr), maxfr).
-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).
-code_info__get_live_value_type(lval(lvar(_)), unwanted).
-code_info__get_live_value_type(lval(field(_, _, _)), unwanted).
-code_info__get_live_value_type(lval(temp(_, _)), unwanted).
-code_info__get_live_value_type(lval(reg(_, _)), unwanted).
-code_info__get_live_value_type(lval(stackvar(_)), unwanted).
-code_info__get_live_value_type(lval(framevar(_)), unwanted).
-code_info__get_live_value_type(lval(mem_ref(_)), unwanted). % XXX
-code_info__get_live_value_type(ticket, unwanted). % XXX we may need to
- % modify this, if the GC is going
- % to garbage-collect the trail.
-code_info__get_live_value_type(ticket_counter, unwanted).
-code_info__get_live_value_type(sync_term, unwanted).
-code_info__get_live_value_type(trace_data, unwanted).
+ []
+ ).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
@@ -3396,15 +3427,6 @@
% during code generation.
:- interface.
-
-:- type slot_contents
- ---> ticket % a ticket (trail pointer)
- ; ticket_counter % a copy of the ticket counter
- ; trace_data
- ; sync_term % a syncronization term used
- % at the end of par_conjs.
- % see par_conj_gen.m for details.
- ; lval(lval).
% Returns the total stackslot count, but not including space for
% succip. This total can change in the future if this call is
Index: continuation_info.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/continuation_info.m,v
retrieving revision 1.3.4.10
diff -u -u -r1.3.4.10 continuation_info.m
--- continuation_info.m 1998/11/24 06:27:33 1.3.4.10
+++ continuation_info.m 1999/04/29 02:45:08
@@ -1,5 +1,5 @@
%-----------------------------------------------------------------------------%
-% Copyright (C) 1997-1998 The University of Melbourne.
+% Copyright (C) 1997-1999 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.
%-----------------------------------------------------------------------------%
@@ -8,10 +8,10 @@
% Main author: trd.
% Extensive modifications by zs.
%
-% This file defines the continuation_info data structure, which the code
-% generator uses to collect information that will later be converted into
-% stack_layout tables for accurate garbage collection, for stack tracing,
-% execution tracing and perhaps other purposes.
+% This file defines the data structures the code generator uses to collect
+% information that will later be converted into layout tables for accurate
+% garbage collection, for stack tracing, execution tracing and perhaps
+% other purposes.
%
% Information is collected in several passes.
%
@@ -22,21 +22,27 @@
%
% 2 During code generation for the procedure, provided the option
% trace_stack_layouts is set, we add layout information for labels
-% that represent trace ports to the code generator state.
+% that represent trace ports to the code generator state. If
+% agc_stack_layouts is set, we add layout information for the stack
+% label in each resumption point. And regardless of option settings,
+% we also generate layouts to be attached to any closures we create.
%
% 3 After we finish generating code for a procedure, we record
% all the static information about the procedure (some of which
% is available only after code generation), together with the
% info about internal labels accumulated in the code generator state,
-% in the continuation_info structure (which is part of HLDS).
+% in the global_data structure (which is part of HLDS).
%
% 4 If agc_stack_layouts is set, we make a pass over the
% optimized code recorded in the final LLDS instructions.
% In this pass, we collect information from call instructions
% about the internal labels to which calls can return.
-% This info will also go straight into the continuation_info
+% This info will also go straight into the global_data
% in the HLDS.
%
+% This module defines the data structures used by all passes. It also
+% implements the whole of pass 4, and various fractions of the other passes.
+%
% stack_layout.m converts the information collected in this module into
% stack_layout tables.
@@ -47,16 +53,8 @@
:- interface.
:- import_module llds, hlds_module, hlds_pred, hlds_data, prog_data.
-:- import_module trace, globals.
-:- import_module set, map, list, std_util, bool.
-
- %
- % Information used by the continuation_info module.
- % This is an abstract data type - when processing is finished
- % use continuation_info__get_all_entries to retrieve the
- % completed proc_layout_infos.
- %
-:- type continuation_info.
+:- import_module (inst), instmap, trace, globals.
+:- import_module std_util, bool, list, assoc_list, set, map.
%
% Information for any procedure, includes information about the
@@ -169,103 +167,98 @@
live_value_type % info about the variable
).
- % Return an initialized continuation info structure.
+:- type closure_layout_info
+ ---> closure_layout_info(
+ list(closure_arg_info),
+ % there is one closure_arg_info for each
+ % argument of the called procedure,
+ % even the args which are not in the closure
+ map(tvar, set(layout_locn))
+ % locations of polymorphic type vars,
+ % encoded so that rN refers to argument N
+ ).
-:- pred continuation_info__init(continuation_info::out) is det.
+:- type closure_arg_info
+ ---> closure_arg_info(
+ type, % The type of the argument.
+ (inst) % The initial inst of the argument.
+
+ % It may be useful in the future to include
+ % info about the final insts and about
+ % the determinism. This would allow us
+ % to implement checked dynamic inst casts,
+ % which may be helpful for dynamic loading.
+ % It may also be useful for printing
+ % closures and for providing user-level
+ % RTTI access.
+ ).
- %
- % Add all the information accumulated by the first three passes
- % above for a single procedure.
- %
- % Takes the pred_proc_id, entry label, the number of stack slots,
- % the determinism of the proc, the stack slot of the succip
- % in this proc (if there is one), the label of the call event
- % (if there is such an event), info about the tracing slots of this
- % proc, a flag saying whether we definitely need a procedure id
- % section in the procedure layout, as well as the layouts at all
- % the trace event labels.
- %
-:- pred continuation_info__add_proc_info(pred_proc_id::in, label::in,
- int::in, determinism::in, maybe(int)::in, maybe(label)::in,
- trace_slot_info::in, bool::in, proc_label_layout_info::in,
- continuation_info::in, continuation_info::out) is det.
+:- type slot_contents
+ ---> ticket % a ticket (trail pointer)
+ ; ticket_counter % a copy of the ticket counter
+ ; trace_data
+ ; sync_term % a syncronization term used
+ % at the end of par_conjs.
+ % see par_conj_gen.m for details.
+ ; lval(lval).
- %
% Call continuation_info__maybe_process_proc_llds on the code
% of every procedure in the list.
- %
:- pred continuation_info__maybe_process_llds(list(c_procedure)::in,
- module_info::in, continuation_info::in, continuation_info::out) is det.
+ module_info::in, global_data::in, global_data::out) is det.
- %
% Check whether this procedure ought to have any layout structures
- % generated for it. If yes, then update the continuation_info to
+ % generated for it. If yes, then update the global_data to
% include all the continuation labels within a proc. Whether or not
% the information about a continuation label includes the variables
% live at that label depends on the values of options.
- %
:- pred continuation_info__maybe_process_proc_llds(list(instruction)::in,
pred_proc_id::in, module_info::in,
- continuation_info::in, continuation_info::out) is det.
-
- %
- % Get the finished list of proc_layout_infos.
- %
-:- pred continuation_info__get_all_proc_layouts(continuation_info::in,
- list(proc_layout_info)::out) is det.
+ global_data::in, global_data::out) is det.
- %
% Check whether the given procedure should have at least (a) a basic
% stack layout, and (b) a procedure id layout generated for it.
% The two bools returned answer these two questions respectively.
- %
:- pred continuation_info__basic_stack_layout_for_proc(pred_info::in,
globals::in, bool::out, bool::out) is det.
+ % Generate the layout information we need for the return point
+ % of a call.
+:- pred continuation_info__generate_return_live_lvalues(
+ assoc_list(prog_var, arg_loc)::in, instmap::in, inst_table::in,
+ list(prog_var)::in, map(prog_var, set(rval))::in,
+ assoc_list(lval, slot_contents)::in, proc_info::in,
+ globals::in, list(liveinfo)::out) is det.
+
+ % Generate the layout information we need for a resumption point,
+ % a label where forward execution can restart after backtracking.
+:- pred continuation_info__generate_resume_layout(
+ map(prog_var, set(val_or_ref))::in,
+ assoc_list(lval, slot_contents)::in, instmap::in, inst_table::in,
+ proc_info::in, layout_label_info::out) is det.
+
+ % Generate the layout information we need to include in a closure.
+:- pred continuation_info__generate_closure_layout(module_info::in,
+ pred_id::in, proc_id::in, closure_layout_info::out) is det.
+
+ % For each type variable in the given list, find out where the
+ % typeinfo var for that type variable is.
+:- pred continuation_info__find_typeinfos_for_tvars(list(tvar)::in,
+ map(prog_var, set(rval))::in, proc_info::in,
+ map(tvar, set(layout_locn))::out) is det.
+
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
-:- import_module options, type_util.
-:- import_module require.
-
- % The continuation_info data structure
-:- type continuation_info == map(pred_proc_id, proc_layout_info).
+:- import_module hlds_goal, code_info, code_util, type_util, options.
+:- import_module string, require, varset, term.
%-----------------------------------------------------------------------------%
% Exported predicates.
- %
- % Initialize the continuation_info
- %
-
-continuation_info__init(ContInfo) :-
- map__init(ContInfo).
-
- %
- % Add the info for this proc (a proc_layout_info) to the
- % continuation_info.
- %
-continuation_info__add_proc_info(PredProcId, EntryLabel, StackSize,
- Detism, SuccipLocation, MaybeTraceCallLabel, TraceSlotInfo,
- ForceProcId, InternalMap, ContInfo0, ContInfo) :-
- ( map__contains(ContInfo0, PredProcId) ->
- error("duplicate continuation_info for proc.")
- ;
- LayoutInfo = proc_layout_info(EntryLabel, Detism, StackSize,
- SuccipLocation, MaybeTraceCallLabel,
- TraceSlotInfo, ForceProcId, InternalMap),
- map__det_insert(ContInfo0, PredProcId, LayoutInfo, ContInfo)
- ).
-
- %
- % Get all the proc_layout_infos.
- %
-continuation_info__get_all_proc_layouts(ContInfo, Entries) :-
- map__values(ContInfo, Entries).
-
continuation_info__maybe_process_llds([], _) --> [].
continuation_info__maybe_process_llds([Proc | Procs], ModuleInfo) -->
{ Proc = c_procedure(_, _, PredProcId, Instrs) },
@@ -290,17 +283,17 @@
%
% Process the list of instructions for this proc, adding
- % all internal label information to the continuation_info.
+ % all internal label information to global_data.
%
:- pred continuation_info__process_proc_llds(pred_proc_id::in,
list(instruction)::in, bool::in,
- continuation_info::in, continuation_info::out) is det.
+ global_data::in, global_data::out) is det.
continuation_info__process_proc_llds(PredProcId, Instructions,
- WantReturnInfo, ContInfo0, ContInfo) :-
+ WantReturnInfo, GlobalData0, GlobalData) :-
% Get all the continuation info from the call instructions.
- map__lookup(ContInfo0, PredProcId, ProcLayoutInfo0),
+ global_data_get_proc_layout(GlobalData0, PredProcId, ProcLayoutInfo0),
ProcLayoutInfo0 = proc_layout_info(A, B, C, D, E, F, G, Internals0),
GetCallLivevals = lambda([Instr::in, Pair::out] is semidet, (
Instr = call(_, label(Label), LiveInfo, _) - _Comment,
@@ -313,7 +306,8 @@
Calls, Internals0, Internals),
ProcLayoutInfo = proc_layout_info(A, B, C, D, E, F, G, Internals),
- map__det_update(ContInfo0, PredProcId, ProcLayoutInfo, ContInfo).
+ global_data_update_proc_layout(GlobalData0, PredProcId, ProcLayoutInfo,
+ GlobalData).
%-----------------------------------------------------------------------------%
@@ -421,5 +415,270 @@
list__member(Type, ArgTypes),
type_is_higher_order(Type, _, _)
)).
+
+%-----------------------------------------------------------------------------%
+
+continuation_info__generate_return_live_lvalues(OutputArgLocs, InstTable,
+ ReturnInstMap, Vars, VarLocs, Temps, ProcInfo,
+ Globals, LiveLvalues) :-
+ globals__want_return_var_layouts(Globals, WantReturnVarLayout),
+ proc_info_stack_slots(ProcInfo, StackSlots),
+ continuation_info__find_return_var_lvals(Vars, StackSlots,
+ OutputArgLocs, VarLvals),
+ continuation_info__generate_var_live_lvalues(VarLvals, InstTable,
+ ReturnInstMap, VarLocs, ProcInfo,
+ WantReturnVarLayout, VarLiveLvalues),
+ continuation_info__generate_temp_live_lvalues(Temps, TempLiveLvalues),
+ list__append(VarLiveLvalues, TempLiveLvalues, LiveLvalues).
+
+:- pred continuation_info__find_return_var_lvals(list(prog_var)::in,
+ stack_slots::in, assoc_list(prog_var, arg_loc)::in,
+ assoc_list(prog_var, lval)::out) is det.
+
+continuation_info__find_return_var_lvals([], _, _, []).
+continuation_info__find_return_var_lvals([Var | Vars], StackSlots,
+ OutputArgLocs, [Var - Lval | VarLvals]) :-
+ ( assoc_list__search(OutputArgLocs, Var, ArgLoc) ->
+ % On return, output arguments are in their registers.
+ code_util__arg_loc_to_register(ArgLoc, Lval)
+ ;
+ % On return, other live variables are in their stack slots.
+ map__lookup(StackSlots, Var, Lval)
+ ),
+ continuation_info__find_return_var_lvals(Vars, StackSlots,
+ OutputArgLocs, VarLvals).
+
+:- pred continuation_info__generate_temp_live_lvalues(
+ assoc_list(lval, slot_contents)::in, list(liveinfo)::out) is det.
+
+continuation_info__generate_temp_live_lvalues([], []).
+continuation_info__generate_temp_live_lvalues([Temp | Temps], [Live | Lives]) :-
+ Temp = Slot - Contents,
+ continuation_info__live_value_type(Contents, LiveLvalueType),
+ map__init(Empty),
+ Live = live_lvalue(direct(Slot), LiveLvalueType, Empty),
+ continuation_info__generate_temp_live_lvalues(Temps, Lives).
+
+:- pred continuation_info__generate_var_live_lvalues(
+ assoc_list(prog_var, lval)::in, instmap::in, inst_table::in,
+ map(prog_var, set(rval))::in, proc_info::in,
+ bool::in, list(liveinfo)::out) is det.
+
+continuation_info__generate_var_live_lvalues([], _, _, _, _, _, []).
+continuation_info__generate_var_live_lvalues([Var - Lval | VarLvals],
+ InstMap, InstTable, VarLocs, ProcInfo,
+ WantReturnVarLayout, [Live | Lives]) :-
+ ( WantReturnVarLayout = yes ->
+ continuation_info__generate_layout_for_var(Var, InstMap,
+ InstTable, ProcInfo, LiveValueType, TypeVars),
+ continuation_info__find_typeinfos_for_tvars(TypeVars,
+ VarLocs, ProcInfo, TypeParams),
+ Live = live_lvalue(direct(Lval), LiveValueType, TypeParams)
+ ;
+ map__init(Empty),
+ Live = live_lvalue(direct(Lval), unwanted, Empty)
+ ),
+ continuation_info__generate_var_live_lvalues(VarLvals, InstMap,
+ InstTable, VarLocs, ProcInfo, WantReturnVarLayout, Lives).
+
+%---------------------------------------------------------------------------%
+
+continuation_info__generate_resume_layout(ResumeMap, Temps,
+ InstMap, InstTable, ProcInfo, Layout) :-
+ map__to_assoc_list(ResumeMap, ResumeList),
+ set__init(TVars0),
+ continuation_info__generate_resume_layout_for_vars(ResumeList,
+ InstMap, InstTable, ProcInfo, VarInfos, TVars0, TVars),
+ set__list_to_set(VarInfos, VarInfoSet),
+ set__to_sorted_list(TVars, TVarList),
+
+ % Typeinfos should never be passed by reference.
+ code_info__resume_map_to_variable_locations(ResumeMap, ResumeVarLocs),
+ continuation_info__find_typeinfos_for_tvars(TVarList, ResumeVarLocs,
+ ProcInfo, TVarInfoMap),
+ continuation_info__generate_temp_var_infos(Temps, TempInfos),
+ set__list_to_set(TempInfos, TempInfoSet),
+ set__union(VarInfoSet, TempInfoSet, AllInfoSet),
+ Layout = layout_label_info(AllInfoSet, TVarInfoMap).
+
+:- pred continuation_info__generate_resume_layout_for_vars(
+ assoc_list(prog_var, set(val_or_ref))::in, instmap::in, inst_table::in,
+ proc_info::in, list(var_info)::out,
+ set(tvar)::in, set(tvar)::out) is det.
+
+continuation_info__generate_resume_layout_for_vars([], _, _, _,
+ [], TVars, TVars).
+continuation_info__generate_resume_layout_for_vars([Var - RvalSet | VarRvals],
+ InstMap, InstTable, ProcInfo, [VarInfo | VarInfos],
+ TVars0, TVars) :-
+ continuation_info__generate_resume_layout_for_var(Var, RvalSet,
+ InstMap, InstTable, ProcInfo, VarInfo, TypeVars),
+ set__insert_list(TVars0, TypeVars, TVars1),
+ continuation_info__generate_resume_layout_for_vars(VarRvals,
+ InstMap, InstTable, ProcInfo, VarInfos, TVars1, TVars).
+
+:- pred continuation_info__generate_resume_layout_for_var(prog_var::in,
+ set(val_or_ref)::in, instmap::in, inst_table::in, proc_info::in,
+ var_info::out, list(tvar)::out) is det.
+
+continuation_info__generate_resume_layout_for_var(Var, ValOrRefSet, InstMap,
+ InstTable, ProcInfo, VarInfo, TypeVars) :-
+ set__to_sorted_list(ValOrRefSet, VarOrRefList),
+ ( VarOrRefList = [ValOrRefPrime] ->
+ ValOrRef = ValOrRefPrime
+ ;
+ error("var has more than one rval in stack resume map")
+ ),
+ (
+ ValOrRef = value(Rval),
+ ( Rval = lval(LvalPrime) ->
+ Lval = LvalPrime
+ ;
+ error("var rval is not lval in stack resume map")
+ )
+ ;
+ ValOrRef = reference(Lval)
+ ),
+ continuation_info__generate_layout_for_var(Var, InstMap, InstTable,
+ ProcInfo, LiveValueType, TypeVars),
+ VarInfo = var_info(direct(Lval), LiveValueType).
+
+:- pred continuation_info__generate_temp_var_infos(
+ assoc_list(lval, slot_contents)::in, list(var_info)::out) is det.
+
+continuation_info__generate_temp_var_infos([], []).
+continuation_info__generate_temp_var_infos([Temp | Temps], [Live | Lives]) :-
+ Temp = Slot - Contents,
+ continuation_info__live_value_type(Contents, LiveLvalueType),
+ Live = var_info(direct(Slot), LiveLvalueType),
+ continuation_info__generate_temp_var_infos(Temps, Lives).
+
+%---------------------------------------------------------------------------%
+
+:- pred continuation_info__generate_layout_for_var(prog_var::in,
+ instmap::in, inst_table::in, proc_info::in,
+ live_value_type::out, list(tvar)::out) is det.
+
+continuation_info__generate_layout_for_var(Var, InstMap, InstTable, ProcInfo,
+ LiveValueType, TypeVars) :-
+ proc_info_varset(ProcInfo, VarSet),
+ proc_info_vartypes(ProcInfo, VarTypes),
+ varset__lookup_name(VarSet, Var, "V_", Name),
+ instmap__lookup_var(InstMap, Var, Inst),
+ map__lookup(VarTypes, Var, Type),
+ LiveValueType = var(Var, Name, Type, qualified_inst(InstTable, Inst)),
+ type_util__vars(Type, TypeVars).
+
+%---------------------------------------------------------------------------%
+
+continuation_info__generate_closure_layout(ModuleInfo, PredId, ProcId,
+ ClosureLayout) :-
+ module_info_pred_proc_info(ModuleInfo, PredId, ProcId, _, ProcInfo),
+ proc_info_headvars(ProcInfo, HeadVars),
+ proc_info_arg_info(ProcInfo, ArgInfos),
+ proc_info_vartypes(ProcInfo, VarTypes),
+ proc_info_get_initial_instmap(ProcInfo, ModuleInfo, InstMap),
+ proc_info_inst_table(ProcInfo, InstTable),
+ map__init(VarLocs0),
+ set__init(TypeVars0),
+ assoc_list__from_corresponding_lists(HeadVars, ArgInfos, VarArgInfos),
+ continuation_info__build_closure_info(VarArgInfos, ArgLayouts,
+ VarTypes, InstMap, InstTable, VarLocs0, VarLocs,
+ TypeVars0, TypeVars),
+ set__to_sorted_list(TypeVars, TypeVarsList),
+ continuation_info__find_typeinfos_for_tvars(TypeVarsList, VarLocs,
+ ProcInfo, TypeInfoDataMap),
+ ClosureLayout = closure_layout_info(ArgLayouts, TypeInfoDataMap).
+
+:- pred continuation_info__build_closure_info(
+ assoc_list(prog_var, arg_info)::in, list(closure_arg_info)::out,
+ map(prog_var, type)::in, instmap::in, inst_table::in,
+ map(prog_var, set(rval))::in, map(prog_var, set(rval))::out,
+ set(tvar)::in, set(tvar)::out) is det.
+
+continuation_info__build_closure_info([], [], _, _, _, VarLocs, VarLocs,
+ TypeVars, TypeVars).
+continuation_info__build_closure_info([Var - ArgInfo | VarArgInfos],
+ [Layout | Layouts], VarTypes, InstMap, InstTable,
+ VarLocs0, VarLocs, TypeVars0, TypeVars) :-
+ ArgInfo = arg_info(ArgLoc, _ArgMode),
+ map__lookup(VarTypes, Var, Type),
+ instmap__lookup_var(InstMap, Var, Inst),
+ Layout = closure_arg_info(Type, Inst),
+ set__singleton_set(Locations, lval(reg(r, ArgLoc))),
+ map__det_insert(VarLocs0, Var, Locations, VarLocs1),
+ type_util__vars(Type, VarTypeVars),
+ set__insert_list(TypeVars0, VarTypeVars, TypeVars1),
+ continuation_info__build_closure_info(VarArgInfos, Layouts,
+ VarTypes, InstMap, InstTable, VarLocs1, VarLocs,
+ TypeVars1, TypeVars).
+
+%---------------------------------------------------------------------------%
+
+continuation_info__find_typeinfos_for_tvars(TypeVars, VarLocs, ProcInfo,
+ TypeInfoDataMap) :-
+ proc_info_varset(ProcInfo, VarSet),
+ proc_info_typeinfo_varmap(ProcInfo, TypeInfoMap),
+ map__apply_to_list(TypeVars, TypeInfoMap, TypeInfoLocns),
+ FindLocn = lambda([TypeInfoLocn::in, Locns::out] is det, (
+ type_info_locn_var(TypeInfoLocn, TypeInfoVar),
+ (
+ map__search(VarLocs, TypeInfoVar, TypeInfoRvalSet)
+ ->
+ ConvertRval = lambda([Locn::out] is nondet, (
+ set__member(Rval, TypeInfoRvalSet),
+ Rval = lval(Lval),
+ (
+ TypeInfoLocn = typeclass_info(_,
+ FieldNum),
+ Locn = indirect(Lval, FieldNum)
+ ;
+ TypeInfoLocn = type_info(_),
+ Locn = direct(Lval)
+ )
+ )),
+ solutions_set(ConvertRval, Locns)
+ ;
+ varset__lookup_name(VarSet, TypeInfoVar,
+ VarString),
+ string__format("%s: %s %s",
+ [s("code_info__find_typeinfos_for_tvars"),
+ s("can't find lval for type_info var"),
+ s(VarString)], ErrStr),
+ error(ErrStr)
+ )
+ )),
+ list__map(FindLocn, TypeInfoLocns, TypeInfoVarLocns),
+ map__from_corresponding_lists(TypeVars, TypeInfoVarLocns,
+ TypeInfoDataMap).
+
+%-----------------------------------------------------------------------------%
+
+:- pred continuation_info__live_value_type(slot_contents::in,
+ live_value_type::out) is det.
+
+continuation_info__live_value_type(lval(succip), succip).
+continuation_info__live_value_type(lval(hp), hp).
+continuation_info__live_value_type(lval(maxfr), maxfr).
+continuation_info__live_value_type(lval(curfr), curfr).
+continuation_info__live_value_type(lval(succfr(_)), unwanted).
+continuation_info__live_value_type(lval(prevfr(_)), unwanted).
+continuation_info__live_value_type(lval(redofr(_)), unwanted).
+continuation_info__live_value_type(lval(redoip(_)), unwanted).
+continuation_info__live_value_type(lval(succip(_)), unwanted).
+continuation_info__live_value_type(lval(sp), unwanted).
+continuation_info__live_value_type(lval(lvar(_)), unwanted).
+continuation_info__live_value_type(lval(field(_, _, _)), unwanted).
+continuation_info__live_value_type(lval(temp(_, _)), unwanted).
+continuation_info__live_value_type(lval(reg(_, _)), unwanted).
+continuation_info__live_value_type(lval(stackvar(_)), unwanted).
+continuation_info__live_value_type(lval(framevar(_)), unwanted).
+continuation_info__live_value_type(lval(mem_ref(_)), unwanted). % XXX
+continuation_info__live_value_type(ticket, unwanted). % XXX we may need to
+ % modify this, if the GC is going
+ % to garbage-collect the trail.
+continuation_info__live_value_type(ticket_counter, unwanted).
+continuation_info__live_value_type(sync_term, unwanted).
+continuation_info__live_value_type(trace_data, unwanted).
%-----------------------------------------------------------------------------%
Index: hlds_pred.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_pred.m,v
retrieving revision 1.35.4.19
diff -u -u -r1.35.4.19 hlds_pred.m
--- hlds_pred.m 1998/11/24 06:28:44 1.35.4.19
+++ hlds_pred.m 1998/12/15 01:44:31
<< snip >>
@@ -319,7 +365,8 @@
% hlds_pred__define_new_pred(Goal, CallGoal, Args, ExtraArgs, InstMap,
% PredName, TVarSet, VarTypes, ClassContext, TVarMap, TCVarMap,
- % VarSet, Markers, InstTable, ModuleInfo0, ModuleInfo, PredProcId)
+ % VarSet, Markers, Owner, InstTable, ModuleInfo0, ModuleInfo,
+ % PredProcId)
%
% Create a new predicate for the given goal, returning a goal to
% call the created predicate. ExtraArgs is the list of extra
@@ -330,8 +377,22 @@
list(prog_var), instmap, string, tvarset, map(prog_var, type),
class_constraints, map(tvar, type_info_locn),
map(class_constraint, prog_var), prog_varset, pred_markers,
- inst_table, module_info, module_info, pred_proc_id).
-:- mode hlds_pred__define_new_pred(in, out, in, out, in, in, in, in,
+ aditi_owner, inst_table, module_info, module_info,
+ pred_proc_id).
+:- mode hlds_pred__define_new_pred(in, out, in, out, in, in, in, in, in, in,
+ in, in, in, in, in, in, out, out) is det.
+
+ % Same as above, except that the argument modes are given explicitly
+ % rather than computed from the goal's instmap_delta. This is useful
+ % when the instmap_delta for the procedure is out of date and
+ % needs to be recomputed.
+:- pred hlds_pred__define_new_pred(hlds_goal, hlds_goal, list(prog_var),
+ list(prog_var), instmap, list(mode), string, tvarset,
+ map(prog_var, type), class_constraints,
+ map(tvar, type_info_locn), map(class_constraint, prog_var),
+ prog_varset, pred_markers, aditi_owner, inst_table,
+ module_info, module_info, pred_proc_id).
+:- mode hlds_pred__define_new_pred(in, out, in, out, in, in, in, in, in, in,
in, in, in, in, in, in, in, out, out) is det.
% Various predicates for accessing the information stored in the
<< snip >>
@@ -973,22 +1089,39 @@
add_marker(Markers, Marker, [Marker | Markers]).
+remove_marker(Markers0, Marker, Markers) :-
+ list__delete_all(Markers0, Marker, Markers).
+
markers_to_marker_list(Markers, Markers).
+marker_list_to_markers(Markers, Markers).
+
%-----------------------------------------------------------------------------%
hlds_pred__define_new_pred(Goal0, Goal, ArgVars0, ExtraTypeInfos, InstMap0,
PredName, TVarSet, VarTypes0, ClassContext, TVarMap, TCVarMap,
- VarSet0, Markers, InstTable, ModuleInfo0, ModuleInfo,
+ VarSet0, Markers, Owner, InstTable, ModuleInfo0, ModuleInfo,
PredProcId) :-
Goal0 = _GoalExpr - GoalInfo,
goal_info_get_instmap_delta(GoalInfo, InstMapDelta),
instmap__apply_instmap_delta(InstMap0, InstMapDelta, InstMap),
-
+
+ compute_arg_modes(ArgVars0, InstMap0, InstMap, ArgModes),
+ hlds_pred__define_new_pred(Goal0, Goal, ArgVars0, ExtraTypeInfos,
+ InstMap0, ArgModes, PredName, TVarSet, VarTypes0,
+ ClassContext, TVarMap, TCVarMap, VarSet0, Markers,
+ Owner, InstTable, ModuleInfo0, ModuleInfo, PredProcId).
+
+hlds_pred__define_new_pred(Goal0, Goal, ArgVars0, ExtraTypeInfos, _InstMap0,
+ ArgModes, PredName, TVarSet, VarTypes0, ClassContext, TVarMap,
+ TCVarMap, VarSet0, Markers, Owner, InstTable,
+ ModuleInfo0, ModuleInfo, PredProcId) :-
% XXX The set of existentially quantified type variables
% here might not be correct.
ExistQVars = [],
+ Goal0 = _ - GoalInfo,
+
% If typeinfo_liveness is set, all type_infos for the argument
% variables need to be passed in, not just the ones that are used.
module_info_globals(ModuleInfo0, Globals),
@@ -1008,12 +1141,15 @@
goal_info_get_context(GoalInfo, Context),
goal_info_get_determinism(GoalInfo, Detism),
- compute_arg_types_modes(ArgVars, VarTypes0, InstMap0, InstMap,
- ArgTypes, ArgModes),
+
+ list__length(ExtraTypeInfos, NumExtraTypeInfos),
+ in_mode(InMode),
+ list__duplicate(NumExtraTypeInfos, InMode, InModes),
+ list__append(InModes, ArgModes, AllArgModes),
module_info_name(ModuleInfo0, ModuleName),
SymName = qualified(ModuleName, PredName),
- Modes = argument_modes(InstTable, ArgModes), % YYY
+ Modes = argument_modes(InstTable, AllArgModes), % YYY
% Remove unneeded variables from the vartypes and varset.
goal_util__goal_vars(Goal0, GoalVars0),
@@ -1036,9 +1172,10 @@
ProcInfo0),
proc_info_set_maybe_termination_info(ProcInfo0, TermInfo, ProcInfo),
+ map__apply_to_list(ArgVars, VarTypes, ArgTypes),
pred_info_create(ModuleName, SymName, TVarSet, ExistQVars, ArgTypes,
true, Context, local, Markers, predicate, ClassContext,
- ProcInfo, ProcId, PredInfo),
+ Owner, ProcInfo, ProcId, PredInfo),
module_info_get_predicate_table(ModuleInfo0, PredTable0),
predicate_table_insert(PredTable0, PredInfo, PredId,
@@ -1050,18 +1187,15 @@
Goal = GoalExpr - GoalInfo,
PredProcId = proc(PredId, ProcId).
-:- pred compute_arg_types_modes(list(prog_var)::in, map(prog_var, type)::in,
- instmap::in, instmap::in, list(type)::out, list(mode)::out) is det.
+:- pred compute_arg_modes(list(prog_var)::in, instmap::in, instmap::in,
+ list(mode)::out) is det.
-compute_arg_types_modes([], _, _, _, [], []).
-compute_arg_types_modes([Var | Vars], VarTypes, InstMap0, InstMap,
- [Type | Types], [Mode | Modes]) :-
- map__lookup(VarTypes, Var, Type),
+compute_arg_modes([], _, _, []).
+compute_arg_modes([Var | Vars], InstMap0, InstMap, [Mode | Modes]) :-
instmap__lookup_var(InstMap0, Var, Inst0),
instmap__lookup_var(InstMap, Var, Inst),
Mode = (Inst0 -> Inst),
- compute_arg_types_modes(Vars, VarTypes, InstMap0, InstMap,
- Types, Modes).
+ compute_arg_modes(Vars, InstMap0, InstMap, Modes).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
<< snip >>
Index: unify_gen.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/unify_gen.m,v
retrieving revision 1.83.2.11
diff -u -u -r1.83.2.11 unify_gen.m
--- unify_gen.m 1998/11/24 06:32:38 1.83.2.11
+++ unify_gen.m 1999/05/03 06:36:04
@@ -1,5 +1,5 @@
%---------------------------------------------------------------------------%
-% Copyright (C) 1994-1998 The University of Melbourne.
+% Copyright (C) 1994-1999 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.
%---------------------------------------------------------------------------%
@@ -39,8 +39,8 @@
:- import_module hlds_module, hlds_pred, prog_data, prog_out, code_util.
:- import_module mode_util, type_util, code_aux, hlds_out, tree, arg_info.
-:- import_module inst_match.
-:- import_module term, bool, string, list, int, map, require, std_util.
+:- import_module globals, options, continuation_info, stack_layout, inst_match.
+:- import_module term, bool, string, int, list, map, require, std_util.
:- type uni_val ---> ref(prog_var)
; lval(lval).
@@ -231,25 +231,28 @@
unify_gen__generate_tag_rval_2(code_addr_constant(_, _), _Rval, _TestRval) :-
% This should never happen
error("Attempted code_addr unification").
-unify_gen__generate_tag_rval_2(base_type_info_constant(_, _, _), _, _) :-
+unify_gen__generate_tag_rval_2(type_ctor_info_constant(_, _, _), _, _) :-
% This should never happen
- error("Attempted base_type_info unification").
+ error("Attempted type_ctor_info unification").
unify_gen__generate_tag_rval_2(base_typeclass_info_constant(_, _, _), _, _) :-
% This should never happen
error("Attempted base_typeclass_info unification").
+unify_gen__generate_tag_rval_2(tabling_pointer_constant(_, _), _, _) :-
+ % This should never happen
+ error("Attempted tabling_pointer unification").
unify_gen__generate_tag_rval_2(no_tag, _Rval, TestRval) :-
TestRval = const(true).
-unify_gen__generate_tag_rval_2(simple_tag(SimpleTag), Rval, TestRval) :-
+unify_gen__generate_tag_rval_2(unshared_tag(UnsharedTag), Rval, TestRval) :-
TestRval = binop(eq, unop(tag, Rval),
- unop(mktag, const(int_const(SimpleTag)))).
-unify_gen__generate_tag_rval_2(complicated_tag(Bits, Num), Rval, TestRval) :-
+ unop(mktag, const(int_const(UnsharedTag)))).
+unify_gen__generate_tag_rval_2(shared_remote_tag(Bits, Num), Rval, TestRval) :-
TestRval = binop(and,
binop(eq, unop(tag, Rval),
unop(mktag, const(int_const(Bits)))),
binop(eq, lval(field(yes(Bits), Rval,
const(int_const(0)))),
const(int_const(Num)))).
-unify_gen__generate_tag_rval_2(complicated_constant_tag(Bits, Num), Rval,
+unify_gen__generate_tag_rval_2(shared_local_tag(Bits, Num), Rval,
TestRval) :-
TestRval = binop(eq, Rval,
mkword(Bits, unop(mkbody, const(int_const(Num))))).
@@ -295,7 +298,7 @@
{ error(
"unify_gen__generate_construction_2: no_tag: arity != 1") }
).
-unify_gen__generate_construction_2(simple_tag(SimpleTag),
+unify_gen__generate_construction_2(unshared_tag(UnsharedTag),
Var, Args, Modes, IMDelta, Code) -->
code_info__get_module_info(ModuleInfo),
code_info__get_inst_table(InstTable),
@@ -309,14 +312,15 @@
{ unify_gen__var_type_msg(VarType, VarTypeMsg) },
% XXX Later we will need to worry about
% whether the cell must be unique or not.
- { Expr = create(SimpleTag, RVals, no, CellNo, VarTypeMsg) },
+ { Expr = create(UnsharedTag, RVals, uniform(no), can_be_either,
+ CellNo, VarTypeMsg) },
code_info__cache_expression(Var, Expr),
unify_gen__aliased_vars_set_location(Args, ArgTypes, Modes,
- InstMap0, InstMap, InstTable, ModuleInfo, Var, SimpleTag,
+ InstMap0, InstMap, InstTable, ModuleInfo, Var, UnsharedTag,
0, Code0),
unify_gen__maybe_place_refs(Var, Code1),
{ Code = tree(Code0, Code1) }.
-unify_gen__generate_construction_2(complicated_tag(Bits0, Num0),
+unify_gen__generate_construction_2(shared_remote_tag(Bits0, Num0),
Var, Args, Modes, IMDelta, Code) -->
code_info__get_module_info(ModuleInfo),
code_info__get_inst_table(InstTable),
@@ -332,17 +336,19 @@
{ unify_gen__var_type_msg(VarType, VarTypeMsg) },
% XXX Later we will need to worry about
% whether the cell must be unique or not.
- { Expr = create(Bits0, RVals, no, CellNo, VarTypeMsg) },
+ { Expr = create(Bits0, RVals, uniform(no), can_be_either,
+ CellNo, VarTypeMsg) },
code_info__cache_expression(Var, Expr),
unify_gen__aliased_vars_set_location(Args, ArgTypes, Modes, InstMap0,
InstMap, InstTable, ModuleInfo, Var, Bits0, 1, Code0),
unify_gen__maybe_place_refs(Var, Code1),
{ Code = tree(Code0, Code1) }.
-unify_gen__generate_construction_2(complicated_constant_tag(Bits1, Num1),
+unify_gen__generate_construction_2(shared_local_tag(Bits1, Num1),
Var, _Args, _Modes, _IMDelta, Code) -->
- unify_gen__cache_unification(Var,
- mkword(Bits1, unop(mkbody, const(int_const(Num1)))), Code).
-unify_gen__generate_construction_2(base_type_info_constant(ModuleName,
+ { Code = empty },
+ code_info__cache_expression(Var,
+ mkword(Bits1, unop(mkbody, const(int_const(Num1))))).
+unify_gen__generate_construction_2(type_ctor_info_constant(ModuleName,
TypeName, TypeArity), Var, Args, _Modes, _IMDelta, Code) -->
( { Args = [] } ->
[]
@@ -350,7 +356,7 @@
{ error("unify_gen: type-info constant has args") }
),
unify_gen__cache_unification(Var, const(data_addr_const(data_addr(
- ModuleName, base_type(info, TypeName, TypeArity)))), Code).
+ ModuleName, type_ctor(info, TypeName, TypeArity)))), Code).
unify_gen__generate_construction_2(base_typeclass_info_constant(ModuleName,
ClassId, Instance), Var, Args, _Modes, _IMDelta, Code) -->
( { Args = [] } ->
@@ -358,8 +364,22 @@
;
{ error("unify_gen: typeclass-info constant has args") }
),
- unify_gen__cache_unification(Var, const(data_addr_const(data_addr(
- ModuleName, base_typeclass_info(ClassId, Instance)))), Code).
+ { Code = empty },
+ code_info__cache_expression(Var, const(data_addr_const(data_addr(
+ ModuleName, base_typeclass_info(ClassId, Instance))))).
+unify_gen__generate_construction_2(tabling_pointer_constant(PredId, ProcId),
+ Var, Args, _Modes, _IMDelta, Code) -->
+ ( { Args = [] } ->
+ []
+ ;
+ { error("unify_gen: tabling pointer constant has args") }
+ ),
+ { Code = empty },
+ code_info__get_module_info(ModuleInfo),
+ { code_util__make_proc_label(ModuleInfo, PredId, ProcId, ProcLabel) },
+ { module_info_name(ModuleInfo, ModuleName) },
+ { DataAddr = data_addr(ModuleName, tabling_pointer(ProcLabel)) },
+ code_info__cache_expression(Var, const(data_addr_const(DataAddr))).
unify_gen__generate_construction_2(code_addr_constant(PredId, ProcId),
Var, Args, _Modes, _IMDelta, Code) -->
( { Args = [] } ->
@@ -373,6 +393,9 @@
Code).
unify_gen__generate_construction_2(pred_closure_tag(PredId, ProcId),
Var, Args, Modes, IMDelta, Code) -->
+ % This code constructs or extends a closure.
+ % The structure of closures is defined in runtime/mercury_ho_call.h.
+
code_info__get_module_info(ModuleInfo),
{ module_info_preds(ModuleInfo, Preds) },
{ map__lookup(Preds, PredId, PredInfo) },
@@ -402,8 +425,16 @@
% new closure P from the old closure P0 by appending the args X, Y, Z.
% The advantage of this optimization is that when P is called, we
% will only need to do one indirect call rather than two.
-% (Hmm... is this optimization really worth it? It probably
-% doesn't happen very often, and it's not guaranteed to be a win.)
+% Its disadvantage is that the cost of creating the closure P is greater.
+% Whether this is a net win depend on the number of times P is called.
+%
+% The pattern that this optimization looks for happens rarely at the moment.
+% The reason is that although we allow the creation of closures with a simple
+% syntax (e.g. P0 = append4([1])), we don't allow their extension with a
+% similarly simple syntax (e.g. P = call(P0, [2])). In fact, typecheck.m
+% contains code to detect such constructs, because it does not have code
+% to typecheck them (you get a message about call/2 should be used as a goal,
+% not an expression).
%
{ proc_info_goal(ProcInfo, ProcInfoGoal) },
{ proc_info_interface_code_model(ProcInfo, CodeModel) },
@@ -428,46 +459,63 @@
% closure
code_info__produce_variable(CallPred, Code98, Value)
;
- code_info__get_next_label(LoopEnd),
code_info__get_next_label(LoopStart),
+ code_info__get_next_label(LoopTest),
code_info__acquire_reg(r, LoopCounter),
code_info__acquire_reg(r, NumOldArgs),
code_info__acquire_reg(r, NewClosure),
{ Zero = const(int_const(0)) },
{ One = const(int_const(1)) },
+ { Two = const(int_const(2)) },
+ { Three = const(int_const(3)) },
{ list__length(CallArgs, NumNewArgs) },
{ NumNewArgs_Rval = const(int_const(NumNewArgs)) },
- { NumNewArgsPlusTwo is NumNewArgs + 2 },
- { NumNewArgsPlusTwo_Rval =
- const(int_const(NumNewArgsPlusTwo)) },
+ { NumNewArgsPlusThree is NumNewArgs + 3 },
+ { NumNewArgsPlusThree_Rval =
+ const(int_const(NumNewArgsPlusThree)) },
code_info__produce_variable(CallPred, Code1, OldClosure),
{ Code2 = node([
comment("build new closure from old closure") - "",
assign(NumOldArgs,
- lval(field(yes(0), OldClosure, Zero)))
+ lval(field(yes(0), OldClosure, Two)))
- "get number of arguments",
incr_hp(NewClosure, no,
binop(+, lval(NumOldArgs),
- NumNewArgsPlusTwo_Rval), "closure")
+ NumNewArgsPlusThree_Rval), "closure")
- "allocate new closure",
assign(field(yes(0), lval(NewClosure), Zero),
+ lval(field(yes(0), OldClosure, Zero)))
+ - "set closure layout structure",
+ assign(field(yes(0), lval(NewClosure), One),
+ lval(field(yes(0), OldClosure, One)))
+ - "set closure code pointer",
+ assign(field(yes(0), lval(NewClosure), Two),
binop(+, lval(NumOldArgs), NumNewArgs_Rval))
- "set new number of arguments",
- assign(LoopCounter, Zero)
+ assign(NumOldArgs, binop(+, lval(NumOldArgs), Three))
+ - "set up loop limit",
+ assign(LoopCounter, Three)
- "initialize loop counter",
+ % It is possible for the number of hidden arguments
+ % to be zero, in which case the body of this loop
+ % should not be executed at all. This is why we
+ % jump to the loop condition test.
+ goto(label(LoopTest))
+ - "enter the copy loop at the conceptual top",
label(LoopStart) - "start of loop",
- assign(LoopCounter,
- binop(+, lval(LoopCounter), One))
- - "increment loop counter",
assign(field(yes(0), lval(NewClosure),
lval(LoopCounter)),
lval(field(yes(0), OldClosure,
lval(LoopCounter))))
- - "copy old field",
- if_val(binop(<=, lval(LoopCounter),
- lval(NumOldArgs)), label(LoopStart))
- - "repeat the loop?",
- label(LoopEnd) - "end of loop"
+ - "copy old hidden argument",
+ assign(LoopCounter,
+ binop(+, lval(LoopCounter), One))
+ - "increment loop counter",
+ label(LoopTest)
+ - "do we have more old arguments to copy?",
+ if_val(binop(<, lval(LoopCounter), lval(NumOldArgs)),
+ label(LoopStart))
+ - "repeat the loop?"
]) },
unify_gen__generate_extra_closure_args(CallArgs,
LoopCounter, NewClosure, Code3),
@@ -481,15 +529,50 @@
{ SkipFirstArg = yes }
;
{ Code98 = empty },
- { proc_info_arg_info(ProcInfo, ArgInfo) },
code_info__make_entry_label(ModuleInfo, PredId, ProcId, no,
- CodeAddress),
- code_info__get_next_cell_number(CellNo),
+ CodeAddr),
+ { code_util__extract_proc_label_from_code_addr(CodeAddr,
+ ProcLabel) },
+ { globals__lookup_bool_option(Globals, typeinfo_liveness,
+ TypeInfoLiveness) },
+ {
+ TypeInfoLiveness = yes,
+ continuation_info__generate_closure_layout(
+ ModuleInfo, PredId, ProcId, ClosureInfo),
+ MaybeClosureInfo = yes(ClosureInfo)
+ ;
+ TypeInfoLiveness = no,
+ % In the absence of typeinfo liveness, procedures
+ % are not guaranteed to have typeinfos for all the
+ % type variables in their signatures. Such a missing
+ % typeinfo would cause a compile-time abort in
+ % continuation_info__generate_closure_layout,
+ % and even if that predicate was modified,
+ % we still couldn't generate a usable layout
+ % structure.
+ MaybeClosureInfo = no
+ },
+ code_info__get_cell_count(CNum0),
+ { stack_layout__construct_closure_layout(ProcLabel,
+ MaybeClosureInfo, ClosureLayoutMaybeRvals,
+ ClosureLayoutArgTypes, CNum0, CNum) },
+ code_info__set_cell_count(CNum),
+ code_info__get_next_cell_number(ClosureLayoutCellNo),
+ { ClosureLayout = create(0, ClosureLayoutMaybeRvals,
+ ClosureLayoutArgTypes, must_be_static,
+ ClosureLayoutCellNo, "closure_layout") },
{ list__length(Args, NumArgs) },
+ { proc_info_arg_info(ProcInfo, ArgInfo) },
{ unify_gen__generate_pred_args(Args, ArgInfo, PredArgs) },
- { Vector = [yes(const(int_const(NumArgs))),
- yes(const(code_addr_const(CodeAddress))) | PredArgs] },
- { Value = create(0, Vector, no, CellNo, "closure") },
+ { Vector = [
+ yes(ClosureLayout),
+ yes(const(code_addr_const(CodeAddr))),
+ yes(const(int_const(NumArgs)))
+ | PredArgs
+ ] },
+ code_info__get_next_cell_number(ClosureCellNo),
+ { Value = create(0, Vector, uniform(no), can_be_either,
+ ClosureCellNo, "closure") },
{ NumExtraProcArgs = 0 },
{ SkipFirstArg = no }
),
@@ -552,25 +635,26 @@
code_info__produce_variable(Var, Code0, Value),
{ One = const(int_const(1)) },
{ Code1 = node([
- assign(LoopCounter,
- binop(+, lval(LoopCounter), One))
- - "increment argument counter",
assign(field(yes(0), lval(NewClosure), lval(LoopCounter)),
Value)
- - "set new argument field"
+ - "set new argument field",
+ assign(LoopCounter,
+ binop(+, lval(LoopCounter), One))
+ - "increment argument counter"
]) },
{ Code = tree(tree(Code0, Code1), Code2) },
unify_gen__generate_extra_closure_args(Vars, LoopCounter,
NewClosure, Code2).
:- pred unify_gen__generate_pred_args(list(prog_var), list(arg_info),
- list(maybe(rval))).
+ list(maybe(rval))).
:- mode unify_gen__generate_pred_args(in, in, out) is det.
unify_gen__generate_pred_args([], _, []).
unify_gen__generate_pred_args([_|_], [], _) :-
error("unify_gen__generate_pred_args: insufficient args").
-unify_gen__generate_pred_args([Var|Vars], [ArgInfo|ArgInfos], [Rval|Rvals]) :-
+unify_gen__generate_pred_args([Var | Vars], [ArgInfo | ArgInfos],
+ [Rval | Rvals]) :-
ArgInfo = arg_info(_, ArgMode),
( ArgMode = top_in ->
Rval = yes(var(Var))
@@ -738,12 +822,15 @@
{ Tag = code_addr_constant(_, _) },
{ Code = empty }
;
- { Tag = base_type_info_constant(_, _, _) },
+ { Tag = type_ctor_info_constant(_, _, _) },
{ Code = empty }
;
{ Tag = base_typeclass_info_constant(_, _, _) },
{ Code = empty }
;
+ { Tag = tabling_pointer_constant(_, _) },
+ { Code = empty }
+ ;
{ Tag = no_tag },
( { Args = [Arg], Modes = [Mode] } ->
code_info__variable_type(Arg, Type),
@@ -753,15 +840,15 @@
{ error("unify_gen__generate_det_deconstruction: no_tag: arity != 1") }
)
;
- { Tag = simple_tag(SimpleTag) },
+ { Tag = unshared_tag(UnsharedTag) },
{ Rval = var(Var) },
{ unify_gen__make_fields_and_argvars(Args, Rval, 0,
- SimpleTag, Fields, ArgVars) },
+ UnsharedTag, Fields, ArgVars) },
unify_gen__var_types(Args, ArgTypes),
unify_gen__generate_unify_args(Fields, ArgVars,
Modes, ArgTypes, IMDelta, Code)
;
- { Tag = complicated_tag(Bits0, _Num0) },
+ { Tag = shared_remote_tag(Bits0, _Num0) },
{ Rval = var(Var) },
{ unify_gen__make_fields_and_argvars(Args, Rval, 1,
Bits0, Fields, ArgVars) },
@@ -769,7 +856,7 @@
unify_gen__generate_unify_args(Fields, ArgVars,
Modes, ArgTypes, IMDelta, Code)
;
- { Tag = complicated_constant_tag(_Bits1, _Num1) },
+ { Tag = shared_local_tag(_Bits1, _Num1) },
{ Code = empty } % if this is det, then nothing happens
).
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list