Files
mercury/compiler/code_info.m
Andrew Bromage fda56846cb With any luck, this should be the call_graph branch successfully
merged.  Do not use --constraint-propagation, because it doesn't
schedule conjunctions properly yet.
1995-07-04 03:15:30 +00:00

1720 lines
58 KiB
Mathematica

%---------------------------------------------------------------------------%
% Copyright (C) 1995 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: code_info.m
%
% main author: conway.
%
% This file defines the code_info type and various operations on it.
%
% The code_info structure is a 'state' used by the code generator.
%
% The following assumptions are made about the state of the high-level
% data structure:
% o Variables can be stored in any number of distinct places.
% o Registers may contain a value corresponding to more than
% one variable.
% o Procedures are in superhomogeneous form. This means that
% construction unifications and builtins are not nested.
% o Evaluation of arguments in construction and deconstruction
% unifications is lazy. This means that arguments in a
% `don't care' mode are ignored, and that assignments
% are cached.
%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- module code_info.
:- interface.
:- import_module hlds, llds.
:- import_module code_util, tree, set, std_util, globals, unify_proc.
:- type code_info.
% Create a new code_info structure.
:- pred code_info__init(varset, liveness_info, call_info, bool, globals,
pred_id, proc_id, proc_info, code_model, instmap,
follow_vars, module_info, shape_table, code_info).
:- mode code_info__init(in, in, in, in, in, in, in, in, in, in, in, in, in, out)
is det.
% Generate the next local label in sequence.
% Bool option is if the label can be accessed externally.
:- pred code_info__get_next_label(label, bool, code_info, code_info).
:- mode code_info__get_next_label(out, in, in, out) is det.
% Generate the next local label number in sequence.
:- pred code_info__get_next_label_number(int, code_info, code_info).
:- mode code_info__get_next_label_number(out, in, out) is det.
% Create a code address for which holds the address
% of the specified predicate.
:- pred code_info__make_entry_label(module_info, pred_id, proc_id, code_addr,
code_info, code_info).
:- mode code_info__make_entry_label(in, in, in, out, in, out) is det.
% Get the variables for the current procedure.
:- pred code_info__get_varset(varset, code_info, code_info).
:- mode code_info__get_varset(out, in, out) is det.
% Set the variables for the current procedure.
:- pred code_info__set_varset(varset, code_info, code_info).
:- mode code_info__set_varset(in, in, out) is det.
% Get the hlds mapping from variables to
% stack slots
:- pred code_info__get_call_info(call_info, code_info, code_info).
:- mode code_info__get_call_info(out, in, out) is det.
% Set the hlds mapping from variables to
% stack slots
:- pred code_info__set_call_info(call_info, code_info, code_info).
:- mode code_info__set_call_info(in, in, out) is det.
:- pred code_info__get_pred_id(pred_id, code_info, code_info).
:- mode code_info__get_pred_id(out, in, out) is det.
:- pred code_info__set_pred_id(pred_id, code_info, code_info).
:- mode code_info__set_pred_id(in, in, out) is det.
:- pred code_info__get_proc_id(proc_id, code_info, code_info).
:- mode code_info__get_proc_id(out, in, out) is det.
:- pred code_info__set_proc_id(proc_id, code_info, code_info).
:- mode code_info__set_proc_id(in, in, out) is det.
:- pred code_info__cache_expression(var, rval, code_info, code_info).
:- mode code_info__cache_expression(in, in, in, out) is det.
% Generate code to either setup the input arguments for a call
% (i.e. in the caller), or to setup the output arguments in the
% predicate epilog (i.e. in the callee).
:- type call_direction ---> caller ; callee.
:- pred code_info__setup_call(assoc_list(var, arg_info),
call_direction, code_tree, code_info, code_info).
:- mode code_info__setup_call(in, in, out, in, out) is det.
:- pred code_info__save_variable_on_stack(var, code_tree,
code_info, code_info).
:- mode code_info__save_variable_on_stack(in, out, in, out) is det.
% Succeed if the given variable is live at the
% end of this goal.
:- pred code_info__variable_is_live(var, code_info, code_info).
:- mode code_info__variable_is_live(in, in, out) is semidet.
% Get the call argument info for a given mode
% of a given predicate
:- pred code_info__get_pred_proc_arginfo(pred_id, proc_id, list(arg_info),
code_info, code_info).
:- mode code_info__get_pred_proc_arginfo(in, in, out, in, out) is det.
% Get the call argument information for the
% current procedure
:- pred code_info__get_arginfo(list(arg_info), code_info, code_info).
:- mode code_info__get_arginfo(out, in, out) is det.
:- pred code_info__get_headvars(list(var), code_info, code_info).
:- mode code_info__get_headvars(out, in, out) is det.
:- pred code_info__cons_id_to_tag(var, cons_id, cons_tag,
code_info, code_info).
:- mode code_info__cons_id_to_tag(in, in, out, in, out) is det.
:- pred code_info__get_total_stackslot_count(int, code_info, code_info).
:- mode code_info__get_total_stackslot_count(out, in, out) is det.
:- pred code_info__clear_all_registers(code_info, code_info).
:- mode code_info__clear_all_registers(in, out) is det.
:- pred code_info__get_live_variables(list(var), code_info, code_info).
:- mode code_info__get_live_variables(out, in, out) is det.
:- pred code_info__generate_forced_saves(code_tree, code_info, code_info).
:- mode code_info__generate_forced_saves(out, in, out) is det.
:- pred code_info__grab_code_info(code_info, code_info, code_info).
:- mode code_info__grab_code_info(out, in, out) is det.
:- pred code_info__slap_code_info(code_info, code_info, code_info).
:- mode code_info__slap_code_info(in, in, out) is det.
:- pred code_info__get_proc_info(proc_info, code_info, code_info).
:- mode code_info__get_proc_info(out, in, out) is det.
:- pred code_info__get_succip_used(bool, code_info, code_info).
:- mode code_info__get_succip_used(out, 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.
:- pred code_info__remake_with_store_map(code_info, code_info).
:- mode code_info__remake_with_store_map(in, out) is det.
:- pred code_info__remake_with_call_info(code_info, code_info).
:- mode code_info__remake_with_call_info(in, out) is det.
:- pred code_info__update_liveness_info(delta_liveness, code_info, code_info).
:- mode code_info__update_liveness_info(in, in, out) is det.
:- pred code_info__update_deadness_info(delta_liveness, code_info, code_info).
:- mode code_info__update_deadness_info(in, in, out) is det.
:- pred code_info__set_var_location(var, lval, code_info, code_info).
:- mode code_info__set_var_location(in, in, in, out) is det.
:- pred code_info__produce_variable(var, code_tree, rval, code_info, code_info).
:- mode code_info__produce_variable(in, out, out, in, out) is det.
:- pred code_info__place_var(var, lval, code_tree, code_info, code_info).
:- mode code_info__place_var(in, in, out, in, out) is det.
:- pred code_info__make_vars_dead(set(var), code_info, code_info).
:- mode code_info__make_vars_dead(in, in, out) is det.
:- pred code_info__make_vars_live(set(var), code_info, code_info).
:- mode code_info__make_vars_live(in, in, out) is det.
:- pred code_info__get_liveness_info(liveness_info, code_info, code_info).
:- mode code_info__get_liveness_info(out, in, out) is det.
:- pred code_info__set_liveness_info(liveness_info, code_info, code_info).
:- mode code_info__set_liveness_info(in, in, out) is det.
:- pred code_info__acquire_reg(reg, code_info, code_info).
:- mode code_info__acquire_reg(out, in, out) is det.
:- pred code_info__release_reg(reg, code_info, code_info).
:- mode code_info__release_reg(in, in, out) is det.
:- pred code_info__get_module_info(module_info, code_info, code_info).
:- mode code_info__get_module_info(out, in, out) is det.
:- pred code_info__get_shapes(shape_table, code_info, code_info).
:- mode code_info__get_shapes(out, in, out) is det.
:- pred code_info__set_shapes(shape_table, code_info, code_info).
:- mode code_info__set_shapes(in, in, out) is det.
:- type failure_cont
---> known(label) % on failure we jump to `Label'
; do_fail % on failure we do a `fail()'
; unknown. % on failure we do a `redo()'
% push a new failure continuation onto the stack
:- pred code_info__push_failure_cont(failure_cont, code_info, code_info).
:- mode code_info__push_failure_cont(in, in, out) is det.
% pop the failure continuation stack
:- pred code_info__pop_failure_cont(code_info, code_info).
:- mode code_info__pop_failure_cont(in, out) is det.
% lookup the value on the top of the failure continuation stack
:- pred code_info__failure_cont(failure_cont, code_info, code_info).
:- mode code_info__failure_cont(out, in, out) is det.
:- pred code_info__failure_cont_address(failure_cont, code_addr).
:- mode code_info__failure_cont_address(in, out) is det.
% generate some code to restore the current redoip, by looking
% at the top of the failure continuation stack.
:- pred code_info__restore_failure_cont(code_tree, code_info, code_info).
:- mode code_info__restore_failure_cont(out, in, out) is det.
:- pred code_info__stack_variable(int, lval, code_info, code_info).
:- mode code_info__stack_variable(in, out, in, out) is det.
:- pred code_info__generate_nondet_saves(code_tree, code_info, code_info).
:- mode code_info__generate_nondet_saves(out, in, out) is det.
:- pred code_info__generate_failure(code_tree, code_info, code_info).
:- mode code_info__generate_failure(out, in, out) is det.
:- pred code_info__generate_test_and_fail(rval, code_tree,
code_info, code_info).
:- mode code_info__generate_test_and_fail(in, out, in, out) is det.
:- pred code_info__generate_pre_commit(code_tree, label, code_info, code_info).
:- mode code_info__generate_pre_commit(out, out, in, out) is det.
:- pred code_info__generate_commit(label, code_tree, code_info, code_info).
:- mode code_info__generate_commit(in, out, in, out) is det.
:- pred code_info__save_hp(code_tree, code_info, code_info).
:- mode code_info__save_hp(out, in, out) is det.
:- pred code_info__restore_hp(code_tree, code_info, code_info).
:- mode code_info__restore_hp(out, in, out) is det.
:- pred code_info__save_redoip(code_tree, code_info, code_info).
:- mode code_info__save_redoip(out, in, out) is det.
:- pred code_info__restore_redoip(code_tree, code_info, code_info).
:- mode code_info__restore_redoip(out, in, out) is det.
:- pred code_info__get_old_hp(code_tree, code_info, code_info).
:- mode code_info__get_old_hp(out, in, out) is det.
:- pred code_info__pop_stack(code_tree, code_info, code_info).
:- mode code_info__pop_stack(out, in, out) is det.
:- pred code_info__maybe_save_hp(bool, code_tree, code_info, code_info).
:- mode code_info__maybe_save_hp(in, out, in, out) is det.
:- pred code_info__maybe_restore_hp(bool, code_tree, code_info, code_info).
:- mode code_info__maybe_restore_hp(in, out, in, out) is det.
:- pred code_info__maybe_get_old_hp(bool, code_tree, code_info, code_info).
:- mode code_info__maybe_get_old_hp(in, out, in, out) is det.
:- pred code_info__maybe_pop_stack(bool, code_tree, code_info, code_info).
:- mode code_info__maybe_pop_stack(in, out, in, out) is det.
:- pred code_info__get_globals(globals, code_info, code_info).
:- mode code_info__get_globals(out, in, out) is det.
:- pred code_info__set_globals(globals, code_info, code_info).
:- mode code_info__set_globals(in, in, out) is det.
:- pred code_info__push_store_map(map(var, lval), code_info, code_info).
:- mode code_info__push_store_map(in, in, out) is det.
:- pred code_info__pop_store_map(code_info, code_info).
:- mode code_info__pop_store_map(in, out) is det.
:- pred code_info__current_store_map(map(var, lval), code_info, code_info).
:- mode code_info__current_store_map(out, in, out) is det.
:- pred code_info__variable_type(var, type, code_info, code_info).
:- mode code_info__variable_type(in, out, in, out) is det.
:- pred code_info__get_requests(unify_requests, code_info, code_info).
:- mode code_info__get_requests(out, in, out) is det.
:- pred code_info__generate_stack_livevals(set(var), set(lval),
code_info, code_info).
:- mode code_info__generate_stack_livevals(in, out, in, out) is det.
:- pred code_info__generate_stack_livelvals(set(var), list(liveinfo),
code_info, code_info).
:- mode code_info__generate_stack_livelvals(in, out, in, out) is det.
:- pred code_info__variable_to_string(var, string, code_info, code_info).
:- mode code_info__variable_to_string(in, out, in, out) is det.
:- pred code_info__apply_instmap_delta(instmap_delta, code_info, code_info).
:- mode code_info__apply_instmap_delta(in, in, out) is det.
:- pred code_info__get_instmap(instmap, code_info, code_info).
:- mode code_info__get_instmap(out, in, out) is det.
:- pred code_info__set_instmap(instmap, code_info, code_info).
:- mode code_info__set_instmap(in, in, out) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module string, require, char, list, map, bimap, tree, int.
:- import_module code_exprn, set, varset, term, stack, prog_io.
:- import_module type_util, mode_util, options, shapes.
:- pred code_info__get_label_count(int, code_info, code_info).
:- mode code_info__get_label_count(out, in, out) is det.
:- pred code_info__set_label_count(int, code_info, code_info).
:- mode code_info__set_label_count(in, in, out) is det.
:- type junk ---> junk.
:- type code_info --->
code_info(
int, % The number of stack slots allocated.
% for storing variables.
% (Some extra stack slots are used
% for saving and restoring registers.)
int, % Counter for the local labels used
% by this procedure.
varset, % The variables in this procedure.
call_info, % The storage allocations for the
% live variables at the end of the
% current switch.
pred_id, % The label of the current predicate.
proc_id, % The label of the current procedure.
junk, % JUNK
% what is stored in each register.
exprn_info, % A map storing the information about
% the status of each variable.
proc_info, % The proc_info for the this procedure.
bool, % do we need to store succip?
fall_through, % The failure continuation stack
module_info, % The module_info structure - you just
% never know when you might need it.
% It should be read-only.
liveness_info, % Variables that are live
% after this goal
stack(map(var, lval)),
% Store Map - where to put things
code_model, % The model of the current procedure
instmap, % insts of variables
pair(int), % The current and maximum (respectively)
% number of extra temporary stackslots
% that have been pushed during the
% procedure
globals, % code generation options
stack(pair(lval)),% the locations in use on the stack
shape_table, % Table of shapes.
junk,
junk
).
:- type fall_through == stack(failure_cont).
%---------------------------------------------------------------------------%
code_info__init(Varset, Liveness, CallInfo, SaveSuccip, Globals,
PredId, ProcId, ProcInfo, CodeModel, Requests,
_FollowVars, ModuleInfo, Shapes, C) :-
proc_info_headvars(ProcInfo, HeadVars),
proc_info_arg_info(ProcInfo, ArgInfos),
assoc_list__from_corresponding_lists(HeadVars, ArgInfos, Args),
code_info__build_input_arg_list(Args, ArgList),
globals__get_options(Globals, Options),
code_exprn__init_state(ArgList, Varset, Options, ExprnInfo),
stack__init(Continue),
stack__init(StoreMapStack0),
stack__init(PushedVals0),
map__init(StoreMap),
stack__push(StoreMapStack0, StoreMap, StoreMapStack),
code_info__max_slot(CallInfo, SlotCount0),
(
CodeModel = model_non
->
SlotCount is SlotCount0 + 1
;
SlotCount = SlotCount0
),
C = code_info(
SlotCount,
0,
Varset,
CallInfo,
PredId,
ProcId,
junk,
ExprnInfo,
ProcInfo,
SaveSuccip,
Continue,
ModuleInfo,
Liveness,
StoreMapStack,
CodeModel,
Requests,
0 - 0,
Globals,
PushedVals0,
Shapes,
junk,
junk
).
:- pred code_info__build_input_arg_list(assoc_list(var, arg_info),
assoc_list(var, lval)).
:- mode code_info__build_input_arg_list(in, out) is det.
code_info__build_input_arg_list([], []).
code_info__build_input_arg_list([V - Arg|Rest0], VarArgs) :-
Arg = arg_info(Loc, Mode),
(
Mode = top_in
->
code_util__arg_loc_to_register(Loc, Reg),
VarArgs = [V - reg(Reg)|VarArgs0]
;
VarArgs = VarArgs0
),
code_info__build_input_arg_list(Rest0, VarArgs0).
%---------------------------------------------------------------------------%
:- pred code_info__max_slot(call_info, int).
:- mode code_info__max_slot(in, out) is det.
code_info__max_slot(CallInfo, SlotCount) :-
map__values(CallInfo, CallList),
code_info__max_slot_2(CallList, 0, SlotCount).
:- pred code_info__max_slot_2(list(lval), int, int).
:- mode code_info__max_slot_2(in, in, out) is det.
code_info__max_slot_2([], Max, Max).
code_info__max_slot_2([L|Ls], Max0, Max) :-
(
L = stackvar(N)
->
int__max(N, Max0, Max1)
;
L = framevar(N)
->
int__max(N, Max0, Max1)
;
Max1 = Max0
),
code_info__max_slot_2(Ls, Max1, Max).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
code_info__get_next_label(Label, Cont0) -->
code_info__get_pred_id(PredId),
code_info__get_proc_id(ProcId),
code_info__get_next_label_number(N),
code_info__get_module_info(ModuleInfo),
{ module_info_pred_info(ModuleInfo, PredId, PredInfo) },
(
{ Cont0 = yes }
->
(
{ pred_info_is_exported(PredInfo) }
->
{ Cont = exported }
;
{ Cont = local }
)
;
{ Cont = no }
),
{ code_util__make_local_label(ModuleInfo, PredId, ProcId, N, Cont,
Label)
}.
code_info__get_next_label_number(N) -->
code_info__get_label_count(N0),
{ N is N0 + 1 },
code_info__set_label_count(N).
%---------------------------------------------------------------------------%
code_info__make_entry_label(ModuleInfo, PredId, ProcId, PredAddress) -->
code_info__get_globals(Globals),
code_info__get_pred_id(CurPredId),
code_info__get_proc_id(CurProcId),
{
globals__lookup_int_option(Globals, procs_per_c_function, ProcsPerFunc),
module_info_preds(ModuleInfo, Preds),
map__lookup(Preds, PredId, PredInfo),
(
( pred_info_is_imported(PredInfo)
; ProcsPerFunc \= 0,
\+ (PredId = CurPredId, ProcId = CurProcId)
)
->
code_util__make_proc_label(ModuleInfo,
PredId, ProcId, ProcLabel),
PredAddress = imported(ProcLabel)
;
code_util__make_local_entry_label(ModuleInfo,
PredId, ProcId, Label),
PredAddress = label(Label)
)
}.
%---------------------------------------------------------------------------%
% XXX We could use the sanity checking mechanism...
code_info__clear_all_registers -->
code_info__get_exprn_info(Exprn0),
{ code_exprn__clobber_regs([], Exprn0, Exprn) },
code_info__set_exprn_info(Exprn).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- pred code_info__get_variable_slot(var, lval, code_info, code_info).
:- mode code_info__get_variable_slot(in, out, in, out) is det.
code_info__get_variable_slot(Var, Slot) -->
code_info__get_call_info(CallInfo),
{ map__lookup(CallInfo, Var, Slot) }.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
% 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.
:- code_info__cons_id_to_tag(_, X, _, _, _) when X. % NU-Prolog indexing.
code_info__cons_id_to_tag(_Var, int_const(X), int_constant(X)) --> [].
code_info__cons_id_to_tag(_Var, float_const(X), float_constant(X)) --> [].
code_info__cons_id_to_tag(_Var, string_const(X), string_constant(X)) --> [].
code_info__cons_id_to_tag(_Var, address_const(P,M), address_constant(P,M))
--> [].
code_info__cons_id_to_tag(_Var, pred_const(P,M), pred_closure_tag(P,M)) --> [].
code_info__cons_id_to_tag(Var, cons(Name, Arity), Tag) -->
%
% Lookup the type of the variable
%
code_info__variable_type(Var, Type),
(
% handle the `character' type specially
{ Type = term__functor(term__atom("character"), [], _) },
{ string__char_to_string(Char, Name) }
->
{ char_to_int(Char, CharCode) },
{ Tag = int_constant(CharCode) }
;
% handle higher-order pred types specially
{ Type = term__functor(term__atom("pred"), PredArgTypes, _) }
->
{ list__length(PredArgTypes, PredArity) },
code_info__get_module_info(ModuleInfo),
{ module_info_get_predicate_table(ModuleInfo, PredicateTable) },
{ TotalArity is Arity + PredArity },
{
predicate_table_search_name_arity(PredicateTable,
Name, TotalArity, PredIds)
->
(
PredIds = [PredId]
->
predicate_table_get_preds(PredicateTable, Preds),
map__lookup(Preds, PredId, PredInfo),
pred_info_procedures(PredInfo, Procs),
map__keys(Procs, ProcIds),
(
ProcIds = [ProcId]
->
Tag = pred_closure_tag(PredId, ProcId)
;
error("sorry, not implemented: taking address of predicate with multiple modes")
)
;
% cons_id ought to include the module prefix, so
% that we could use predicate_table__search_m_n_a to
% prevent this from happening
string__append("code_info__cons_id_to_tag: ambiguous pred ", Name, Msg),
error(Msg)
)
;
% the type-checker should ensure that this never happens
error("code_info__cons_id_to_tag: invalid pred")
}
;
% Use the type to determine the type_id
{ type_to_type_id(Type, TypeId0, _) ->
TypeId = TypeId0
;
% the type-checker should ensure that this never happens
error("code_info__cons_id_to_tag: invalid type")
},
% Given the type_id, lookup up the constructor tag
% table for that type
code_info__get_module_info(ModuleInfo),
{ module_info_types(ModuleInfo, TypeTable) },
{ map__lookup(TypeTable, TypeId, TypeDefn) },
{
TypeDefn = hlds__type_defn(_, _,
du_type(_, ConsTable0, _), _, _)
->
ConsTable = ConsTable0
;
% this should never happen
error(
"code_info__cons_id_to_tag: type is not d.u. type?"
)
},
% Finally look up the cons_id in the table
{ map__lookup(ConsTable, cons(Name, Arity), Tag) }
).
%---------------------------------------------------------------------------%
code_info__get_live_variables(VarList) -->
code_info__get_liveness_info(Vars),
{ set__to_sorted_list(Vars, VarList) }.
%---------------------------------------------------------------------------%
code_info__variable_is_live(Var) -->
code_info__get_liveness_info(Liveness),
{ set__member(Var, Liveness) }.
%---------------------------------------------------------------------------%
code_info__get_pred_proc_arginfo(PredId, ProcId, ArgInfo) -->
code_info__get_module_info(ModuleInfo),
{ module_info_preds(ModuleInfo, Preds) },
{ map__lookup(Preds, PredId, PredInfo) },
{ pred_info_procedures(PredInfo, Procs) },
{ map__lookup(Procs, ProcId, ProcInfo) },
{ proc_info_arg_info(ProcInfo, ArgInfo) }.
%---------------------------------------------------------------------------%
code_info__set_var_location(Var, Lval) -->
code_info__get_exprn_info(Exprn0),
{ code_exprn__set_var_location(Var, Lval, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn).
%---------------------------------------------------------------------------%
code_info__produce_variable(Var, Code, Rval) -->
code_info__get_exprn_info(Exprn0),
{ code_exprn__produce_var(Var, Rval, Code, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn).
%---------------------------------------------------------------------------%
code_info__place_var(Var, Lval, Code) -->
code_info__get_exprn_info(Exprn0),
{ code_exprn__place_var(Var, Lval, Code, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn).
%---------------------------------------------------------------------------%
code_info__acquire_reg(Reg) -->
code_info__get_exprn_info(Exprn0),
{ code_exprn__acquire_reg(Reg, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn).
%---------------------------------------------------------------------------%
code_info__release_reg(Reg) -->
code_info__get_exprn_info(Exprn0),
{ code_exprn__release_reg(Reg, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn).
%---------------------------------------------------------------------------%
code_info__cache_expression(Var, Rval) -->
code_info__get_exprn_info(Exprn0),
{ code_exprn__cache_exprn(Var, Rval, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn).
%---------------------------------------------------------------------------%
code_info__setup_call([], _Direction, empty) --> [].
code_info__setup_call([V - arg_info(Loc,Mode)|Rest], Direction, Code) -->
(
{
Mode = top_in,
Direction = caller
;
Mode = top_out,
Direction = callee
}
->
{ code_util__arg_loc_to_register(Loc, Reg) },
code_info__get_exprn_info(Exprn0),
{ code_exprn__place_var(V, reg(Reg), Code0, Exprn0, Exprn1) },
% We need to test that either the variable
% is live OR it occurs in the remaining arguments
% because of a bug in polymorphism.m which
% causes some compiler generated code to violate
% superhomogeneous form
(
code_info__variable_is_live(V)
->
{ IsLive = yes }
;
{ IsLive = no }
),
{
list__member(Vtmp - _, Rest),
V = Vtmp
->
Occurs = yes
;
Occurs = no
},
(
% We can't simply use a disj here
% because of bugs in modes/det_analysis
{ bool__or(Occurs, IsLive, yes) }
->
{ code_exprn__lock_reg(Reg, Exprn1, Exprn2) },
code_info__set_exprn_info(Exprn2),
code_info__setup_call(Rest, Direction, Code1),
code_info__get_exprn_info(Exprn3),
{ code_exprn__unlock_reg(Reg, Exprn3, Exprn) },
code_info__set_exprn_info(Exprn),
{ Code = tree(Code0, Code1) }
;
{ code_exprn__lock_reg(Reg, Exprn1, Exprn2) },
{ code_exprn__var_becomes_dead(V, Exprn2, Exprn3) },
code_info__set_exprn_info(Exprn3),
code_info__setup_call(Rest, Direction, Code1),
code_info__get_exprn_info(Exprn4),
{ code_exprn__unlock_reg(Reg, Exprn4, Exprn) },
code_info__set_exprn_info(Exprn),
{ Code = tree(Code0, Code1) }
)
;
code_info__setup_call(Rest, Direction, Code)
).
%---------------------------------------------------------------------------%
code_info__save_variable_on_stack(Var, Code) -->
code_info__get_variable_slot(Var, Slot),
code_info__get_exprn_info(Exprn0),
{ code_exprn__place_var(Var, Slot, Code, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn).
%---------------------------------------------------------------------------%
code_info__get_arginfo(ArgInfo) -->
code_info__get_pred_id(PredId),
code_info__get_proc_id(ProcId),
code_info__get_pred_proc_arginfo(PredId, ProcId, ArgInfo).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
code_info__generate_forced_saves(Code) -->
code_info__current_store_map(StoreMap),
code_info__get_call_info(CallInfo),
code_info__get_live_variables(Vars),
code_info__generate_forced_saves_2(Vars, StoreMap, CallInfo, Code).
:- pred code_info__generate_forced_saves_2(list(var), map(var, lval),
map(var, lval), code_tree, code_info, code_info).
:- mode code_info__generate_forced_saves_2(in, in, in, out, in, out) is det.
code_info__generate_forced_saves_2([], _Store, _Call, empty) --> [].
code_info__generate_forced_saves_2([V|Vs], Store, Call, Code) -->
(
{ map__search(Store, V, Lval) }
->
code_info__get_exprn_info(Exprn0),
{ code_exprn__place_var(V, Lval, Code0, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn)
;
{ map__search(Call, V, Lval) }
->
code_info__get_exprn_info(Exprn0),
{ code_exprn__place_var(V, Lval, Code0, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn)
;
{ error("code_info__generate_forced_saves: variable not found") }
),
code_info__generate_forced_saves_2(Vs, Store, Call, Code1),
{ Code = tree(Code0, Code1) }.
%---------------------------------------------------------------------------%
code_info__generate_nondet_saves(Code) -->
code_info__get_call_info(CallInfo),
{ map__to_assoc_list(CallInfo, CallList) },
code_info__generate_nondet_saves_2(CallList, Code).
:- pred code_info__generate_nondet_saves_2(assoc_list(var, lval), code_tree,
code_info, code_info).
:- mode code_info__generate_nondet_saves_2(in, out, in, out) is det.
code_info__generate_nondet_saves_2([], empty) --> [].
code_info__generate_nondet_saves_2([Var - StackThing|VarSlots], Code) -->
(
code_info__variable_is_live(Var)
->
code_info__get_exprn_info(Exprn0),
{ code_exprn__place_var(Var, StackThing, Code0,
Exprn0, Exprn) },
code_info__set_exprn_info(Exprn)
;
{ Code0 = empty }
),
{ Code = tree(Code0, Code1) },
code_info__generate_nondet_saves_2(VarSlots, Code1).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
code_info__get_headvars(HeadVars) -->
code_info__get_module_info(ModuleInfo),
code_info__get_pred_id(PredId),
code_info__get_proc_id(ProcId),
{ module_info_preds(ModuleInfo, Preds) },
{ map__lookup(Preds, PredId, PredInfo) },
{ pred_info_procedures(PredInfo, Procs) },
{ map__lookup(Procs, ProcId, ProcInfo) },
{ proc_info_headvars(ProcInfo, HeadVars) }.
%---------------------------------------------------------------------------%
% code_info__remake_with_store_map rebuilds the register info and
% variable info data structures. It operates under the assumption
% that if a variable is live, it is stored somewhere. What is more,
% it assumes that if a variable is live, then there is a copy of it
% stored on the stack in the location given by the store map. This
% means that it only makes sense to call this predicate in situations
% such as the start of disjuncts where it only makes sense to have
% variables on the stack. (Note that disj_gen contains a piece of
% magic to use the register versions of variables if possible in the
% first disjunct).
code_info__remake_with_store_map -->
code_info__get_varset(Varset),
code_info__get_live_variables(VarList),
{ set__list_to_set(VarList, Vars) },
code_info__get_call_info(CallInfo),
code_info__current_store_map(StoreMap),
{ map__overlay(CallInfo, StoreMap, LvalMap0) },
{ map__select(LvalMap0, Vars, LvalMap) },
{ map__to_assoc_list(LvalMap, VarLvals) },
code_info__get_globals(Globals),
{ globals__get_options(Globals, Options) },
{ code_exprn__init_state(VarLvals, Varset, Options, Exprn) },
code_info__set_exprn_info(Exprn).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
% code_info__remake_with_call_info rebuilds the register info and the
% variable info structures. It operates under the assumption that if
% a variable is live, then it should be located in the storage indicated
% by the call info information. This is for use at the end of the branches
% in branched structures, where we need to ensure that variables are
% stored in consistient places.
code_info__remake_with_call_info -->
code_info__get_varset(Varset),
code_info__get_live_variables(VarList),
{ set__list_to_set(VarList, Vars) },
code_info__get_call_info(CallInfo),
{ map__select(CallInfo, Vars, LvalMap) },
{ map__to_assoc_list(LvalMap, VarLvals) },
code_info__get_globals(Globals),
{ globals__get_options(Globals, Options) },
{ code_exprn__init_state(VarLvals, Varset, Options, Exprn) },
code_info__set_exprn_info(Exprn).
%---------------------------------------------------------------------------%
code_info__update_liveness_info(Births - _Deaths) -->
code_info__get_liveness_info(Liveness0),
{ set__union(Liveness0, Births, Liveness) },
code_info__set_liveness_info(Liveness).
code_info__update_deadness_info(_Births - Deaths) -->
code_info__get_liveness_info(Liveness0),
{ set__difference(Liveness0, Deaths, Liveness) },
code_info__set_liveness_info(Liveness).
%---------------------------------------------------------------------------%
code_info__make_vars_dead(Vars) -->
{ set__to_sorted_list(Vars, VarList) },
code_info__make_vars_dead_2(VarList).
:- pred code_info__make_vars_dead_2(list(var), code_info, code_info).
:- mode code_info__make_vars_dead_2(in, in, out) is det.
code_info__make_vars_dead_2([]) --> [].
code_info__make_vars_dead_2([V|Vs]) -->
code_info__get_exprn_info(Exprn0),
{ code_exprn__var_becomes_dead(V, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn),
code_info__make_vars_dead_2(Vs).
%---------------------------------------------------------------------------%
code_info__make_vars_live(Vars) -->
{ set__to_sorted_list(Vars, VarList) },
code_info__make_vars_live_2(VarList).
:- pred code_info__make_vars_live_2(list(var), code_info, code_info).
:- mode code_info__make_vars_live_2(in, in, out) is det.
code_info__make_vars_live_2([]) --> [].
code_info__make_vars_live_2([V|Vs]) -->
(
code_info__current_store_map(Store),
{ map__search(Store, V, Lval0) }
->
{ Lval = Lval0 }
;
code_info__get_call_info(Call),
{ map__search(Call, V, Lval0) }
->
{ Lval = Lval0 }
;
{ error("I don't know where to put this variable") }
),
code_info__get_exprn_info(Exprn0),
{ code_exprn__maybe_set_var_location(V, Lval, Exprn0, Exprn) },
code_info__set_exprn_info(Exprn),
code_info__make_vars_live_2(Vs).
%---------------------------------------------------------------------------%
code_info__maybe_save_hp(Maybe, Code) -->
( { Maybe = yes } ->
code_info__save_hp(Code)
;
{ Code = empty }
).
code_info__maybe_restore_hp(Maybe, Code) -->
( { Maybe = yes } ->
code_info__restore_hp(Code)
;
{ Code = empty }
).
code_info__maybe_get_old_hp(Maybe, Code) -->
( { Maybe = yes } ->
code_info__get_old_hp(Code)
;
{ Code = empty }
).
code_info__maybe_pop_stack(Maybe, Code) -->
( { Maybe = yes } ->
code_info__pop_stack(Code)
;
{ Code = empty }
).
%---------------------------------------------------------------------------%
code_info__save_hp(Code) -->
code_info__push_temp(hp, HpSlot),
{ Code = node([ mark_hp(HpSlot) - "Save heap pointer" ]) }.
code_info__restore_hp(Code) -->
code_info__pop_temp(Lval),
{ Code = node([ restore_hp(lval(Lval)) - "Restore heap pointer" ]) }.
code_info__get_old_hp(Code) -->
code_info__get_stack_top(Lval),
{ Code = node([ restore_hp(lval(Lval)) - "Reset heap pointer" ]) }.
code_info__save_redoip(Code) -->
code_info__push_temp(redoip(lval(maxfr)), RedoIpSlot),
{ Code = node([ assign(RedoIpSlot, lval(redoip(lval(maxfr))))
- "Save the redoip" ]) }.
code_info__restore_redoip(Code) -->
code_info__pop_temp(Lval),
{ Code = node([ assign(redoip(lval(maxfr)), lval(Lval))
- "Restore the redoip" ]) }.
%---------------------------------------------------------------------------%
code_info__stack_variable(Num, Lval) -->
code_info__get_proc_model(CodeModel),
(
{ CodeModel = model_non }
->
{ Num1 is Num - 1 }, % framevars start at zero
{ Lval = framevar(Num1) }
;
{ Lval = stackvar(Num) } % stackvars start at one
).
%---------------------------------------------------------------------------%
% The det stack frame is organized as follows.
%
% ... unused ...
% sp ---> <first unused slot>
% <space for local var 1>
% ... local vars ...
% <space for local var n>
% <space for temporary reg save 1>
% ... temporary reg saves ...
% <space for temporary reg save n>
% <space for succip>
%
% The stack pointer points to the first free location at the
% top of the stack.
%
% `code_info__num_stackslots' counts the number of slots reserved
% for saving local variables.
%
% `code_info__max_push_count' counts the number of slots reserved
% for saving and restoring registers (hp, redoip, etc.)
%
% `code_info__succip_used' determines whether we need a slot to
% hold the succip.
%
% The variable part of the nondet stack is organized in the same way
% as the det stack (but the nondet stack also contains several other
% fixed fields.)
%---------------------------------------------------------------------------%
% Returns the total stackslot count, but not including space for
% succip.
code_info__get_total_stackslot_count(NumSlots) -->
code_info__get_stackslot_count(SlotsForVars),
code_info__get_max_push_count(SlotsForTemps),
{ NumSlots is SlotsForVars + SlotsForTemps }.
%---------------------------------------------------------------------------%
% `push_temp' doesn't actually increment the stack pointer, it just
% increments the push count. The space will be allocated in the
% procedure prologue.
:- pred code_info__push_temp(lval, lval, code_info, code_info).
:- mode code_info__push_temp(in, out, in, out) is det.
code_info__push_temp(Item, StackVar) -->
code_info__get_push_count(Count0),
{ Count is Count0 + 1 },
code_info__set_push_count(Count),
code_info__get_stackslot_count(NumSlots),
{ Slot is Count + NumSlots },
code_info__stack_variable(Slot, StackVar),
code_info__get_pushed_values(VStack0),
{ stack__push(VStack0, StackVar - Item, VStack) },
code_info__set_pushed_values(VStack).
%---------------------------------------------------------------------------%
% `pop_stack' and `pop_temp' don't actually decrement the stack
% pointer, they just decrement the push count. The space will
% be deallocated in the procedure epilogue.
code_info__pop_stack(empty) -->
code_info__get_push_count(Count0),
{ Count is Count0 - 1 },
code_info__set_push_count(Count),
code_info__get_pushed_values(VStack0),
{ stack__pop_det(VStack0, _, VStack) },
code_info__set_pushed_values(VStack).
:- pred code_info__pop_temp(lval, code_info, code_info).
:- mode code_info__pop_temp(out, in, out) is det.
code_info__pop_temp(StackVar) -->
code_info__get_push_count(Count0),
{ Count is Count0 - 1 },
code_info__set_push_count(Count),
code_info__get_pushed_values(VStack0),
{ stack__pop_det(VStack0, _, VStack) },
code_info__set_pushed_values(VStack),
code_info__get_stackslot_count(NumSlots),
{ Slot is Count0 + NumSlots },
code_info__stack_variable(Slot, StackVar).
:- pred code_info__get_stack_top(lval, code_info, code_info).
:- mode code_info__get_stack_top(out, in, out) is det.
code_info__get_stack_top(StackVar) -->
code_info__get_push_count(Count),
code_info__get_stackslot_count(NumSlots),
{ Slot is Count + NumSlots },
code_info__stack_variable(Slot, StackVar).
%---------------------------------------------------------------------------%
code_info__generate_failure(Code) -->
code_info__failure_cont(Cont),
{ code_info__failure_cont_address(Cont, FailureAddress) },
{ Code = node([ goto(FailureAddress, FailureAddress) - "Fail" ]) }.
code_info__generate_test_and_fail(Rval, Code) -->
code_info__failure_cont(Cont),
{ code_info__failure_cont_address(Cont, FailureAddress) },
{ code_util__neg_rval(Rval, NegRval) },
{ Code = node([ if_val(NegRval, FailureAddress) -
"Test for failure" ]) }.
code_info__failure_cont_address(known(Label), label(Label)).
code_info__failure_cont_address(do_fail, do_fail).
code_info__failure_cont_address(unknown, do_redo).
%---------------------------------------------------------------------------%
% `pre_commit' and `commit' should be generated as a pair
% surrounding a non-det goal.
% If the goal succeeds, the `commit' will cut any choice points
% generated in the goal.
code_info__generate_pre_commit(PreCommit, FailLabel) -->
code_info__get_globals(Globals),
{ globals__get_gc_method(Globals, GC_Method) },
( { GC_Method = accurate } ->
% the pushes and pops on the det stack below will cause
% problems for accurate garbage collection.
{ error("code_info__generate_pre_commit: gc=accurate not supported") }
;
[]
),
code_info__get_proc_model(CodeModel),
( { CodeModel = model_non } ->
{ PushCode = node([incr_sp(3) -
"push space for curfr, maxfr, and redoip"]) },
{ CurfrSlot = stackvar(1) },
{ MaxfrSlot = stackvar(2) },
{ RedoipSlot = stackvar(3) }
;
{ PushCode = empty },
code_info__push_temp(curfr, CurfrSlot),
code_info__push_temp(maxfr, MaxfrSlot),
code_info__push_temp(redoip(lval(maxfr)), RedoipSlot)
),
{ SaveCode = node([
assign(CurfrSlot, lval(curfr)) -
"Save current nondet frame pointer",
assign(MaxfrSlot, lval(maxfr)) -
"Save top of nondet stack",
assign(RedoipSlot, lval(redoip(lval(maxfr)))) -
"Save the top redoip"
]) },
code_info__get_next_label(FailLabel, yes),
code_info__push_failure_cont(known(FailLabel)),
{ SetRedoip = node([
assign(redoip(lval(maxfr)),
const(address_const(label(FailLabel)))) -
"Hijack the failure continuation"
]) },
{ PreCommit = tree(tree(PushCode, SaveCode), SetRedoip) }.
code_info__generate_commit(FailLabel, Commit) -->
code_info__get_next_label(SuccLabel, yes),
{ GotoSuccLabel = node([
goto(label(SuccLabel), label(SuccLabel)) -
"Jump to success continuation",
label(FailLabel) - "Failure continuation"
]) },
{ SuccLabelCode = node([
label(SuccLabel) - "Success continuation"
]) },
code_info__pop_failure_cont,
code_info__get_proc_model(CodeModel),
( { CodeModel = model_non } ->
{ PopCode = node([decr_sp(3) - "pop redoip & curfr"]) },
{ RedoipSlot = stackvar(3) },
{ MaxfrSlot = stackvar(2) },
{ CurfrSlot = stackvar(1) }
;
{ PopCode = empty },
code_info__pop_temp(RedoipSlot),
code_info__pop_temp(MaxfrSlot),
code_info__pop_temp(CurfrSlot)
),
{ RestoreMaxfr = node([
assign(maxfr, lval(MaxfrSlot)) -
"Prune away unwanted choice-points"
]) },
{ RestoreRedoip = node([
assign(redoip(lval(maxfr)), lval(RedoipSlot)) -
"Restore the top redoip"
]) },
{ RestoreCurfr = node([
assign(curfr, lval(CurfrSlot)) -
"Prune nondet frame pointer"
]) },
code_info__generate_failure(Fail),
{ SuccessCode = tree(RestoreMaxfr, tree(RestoreRedoip, RestoreCurfr)) },
{ FailCode = tree(RestoreRedoip, tree(RestoreCurfr, Fail)) },
{ Commit = tree(tree(SuccessCode, GotoSuccLabel),
tree(FailCode, SuccLabelCode)) }.
%---------------------------------------------------------------------------%
code_info__push_failure_cont(Cont) -->
code_info__get_fall_through(Fall0),
{ stack__push(Fall0, Cont, Fall) },
code_info__set_fall_through(Fall).
code_info__pop_failure_cont -->
(
code_info__get_fall_through(Fall0),
{ stack__pop(Fall0, _, Fall) },
code_info__set_fall_through(Fall)
->
[]
;
{ error("code_info__pop_failure_cont: empty stack") }
).
code_info__failure_cont(Cont) -->
code_info__get_fall_through(Fall),
(
{ stack__top(Fall, Cont0) }
->
{ Cont = Cont0 }
;
{ error("code_info__failure_cont: no failure continuation") }
).
code_info__restore_failure_cont(ContCode) -->
code_info__failure_cont(FailCont),
( { FailCont = known(ContLab) } ->
{ Label = label(ContLab) }
; { FailCont = do_fail } ->
{ Label = do_fail }
;
{ error("cannot restore unknown failure continuation") }
),
{ ContCode = node([
modframe(Label) - "Restore failure continuation"
]) }.
%---------------------------------------------------------------------------%
code_info__push_store_map(Map) -->
code_info__get_store_map(Maps0),
{ stack__push(Maps0, Map, Maps) },
code_info__set_store_map(Maps).
code_info__pop_store_map -->
code_info__get_store_map(Maps0),
{ stack__pop_det(Maps0, _, Maps) },
code_info__set_store_map(Maps).
code_info__current_store_map(Map) -->
code_info__get_store_map(Maps0),
(
{ stack__top(Maps0, Map0) }
->
{ Map = Map0 }
;
{ error("No store map on stack") }
).
%---------------------------------------------------------------------------%
code_info__generate_stack_livevals(Args, LiveVals) -->
code_info__get_live_variables(LiveVars),
{ set__list_to_set(LiveVars, Vars0) },
{ set__difference(Vars0, Args, Vars) },
{ set__to_sorted_list(Vars, VarList) },
{ set__init(LiveVals0) },
code_info__generate_stack_livevals_2(VarList, LiveVals0, LiveVals1),
code_info__get_pushed_values(Pushed),
{ code_info__generate_stack_livevals_3(Pushed, LiveVals1, LiveVals) }.
:- pred code_info__generate_stack_livevals_2(list(var), set(lval), set(lval),
code_info, code_info).
:- mode code_info__generate_stack_livevals_2(in, in, out, in, out) is det.
code_info__generate_stack_livevals_2([], Vals, Vals) --> [].
code_info__generate_stack_livevals_2([V|Vs], Vals0, Vals) -->
code_info__get_variable_slot(V, Slot),
{ set__insert(Vals0, Slot, Vals1) },
code_info__generate_stack_livevals_2(Vs, Vals1, Vals).
:- pred code_info__generate_stack_livevals_3(stack(pair(lval)),
set(lval), set(lval)).
:- mode code_info__generate_stack_livevals_3(in, in, out) is det.
code_info__generate_stack_livevals_3(Stack0, Vals0, Vals) :-
(
stack__pop(Stack0, Top - _, Stack1)
->
set__insert(Vals0, Top, Vals1),
code_info__generate_stack_livevals_3(Stack1, Vals1, Vals)
;
Vals = Vals0
).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
code_info__get_requests(Requests) -->
code_info__get_module_info(ModuleInfo),
{ module_info_get_unify_requests(ModuleInfo, Requests) }.
%---------------------------------------------------------------------------%
code_info__apply_instmap_delta(Delta) -->
code_info__get_instmap(InstMap0),
{ apply_instmap_delta(InstMap0, Delta, InstMap) },
code_info__set_instmap(InstMap).
%---------------------------------------------------------------------------%
code_info__generate_stack_livelvals(Args, LiveVals) -->
code_info__get_live_variables(LiveVars),
{ set__list_to_set(LiveVars, Vars0) },
{ set__difference(Vars0, Args, Vars) },
{ set__to_sorted_list(Vars, VarList) },
{ set__init(LiveVals0) },
code_info__generate_stack_livelvals_2(VarList, LiveVals0, LiveVals1),
{ set__to_sorted_list(LiveVals1, LiveVals2) },
code_info__livevals_to_livelvals(LiveVals2, LiveVals3),
code_info__get_pushed_values(Pushed),
{ code_info__generate_stack_livelvals_3(Pushed, LiveVals3, LiveVals) }.
:- pred code_info__generate_stack_livelvals_2(list(var),
set(pair(lval, var)),
set(pair(lval, var)),
code_info, code_info).
:- mode code_info__generate_stack_livelvals_2(in, in, out, in, out) is det.
code_info__generate_stack_livelvals_2([], Vals, Vals) --> [].
code_info__generate_stack_livelvals_2([V|Vs], Vals0, Vals) -->
code_info__get_variable_slot(V, Slot),
{ set__insert(Vals0, Slot - V, Vals1) },
code_info__generate_stack_livelvals_2(Vs, Vals1, Vals).
:- pred code_info__generate_stack_livelvals_3(stack(pair(lval)),
list(liveinfo), list(liveinfo)).
:- mode code_info__generate_stack_livelvals_3(in, in, out) is det.
code_info__generate_stack_livelvals_3(Stack0, LiveInfo0, LiveInfo) :-
(
stack__pop(Stack0, Top - StoredLval , Stack1)
->
code_info__get_shape_num(StoredLval, S_Num),
LiveInfo = [live_lvalue(Top, S_Num) | Lives],
code_info__generate_stack_livelvals_3(Stack1, LiveInfo0, Lives)
;
LiveInfo = LiveInfo0
).
:- pred code_info__get_shape_num(lval, int).
:- mode code_info__get_shape_num(in, out) is det.
code_info__get_shape_num(succip, -1).
code_info__get_shape_num(hp, -2).
code_info__get_shape_num(maxfr, -3).
code_info__get_shape_num(curfr, -7). % XXX magic numbers! is this one right?
code_info__get_shape_num(succfr(_), -7). % XXX magic numbers! is this one right?
code_info__get_shape_num(prevfr(_), -7). % XXX magic numbers! is this one right?
code_info__get_shape_num(redoip(_), -4). % And this one?
code_info__get_shape_num(sp, -5).
code_info__get_shape_num(lvar(_), -6).
code_info__get_shape_num(field(_, _, _), -6).
code_info__get_shape_num(temp(_), -6).
code_info__get_shape_num(reg(_), -6).
code_info__get_shape_num(stackvar(_), -6).
code_info__get_shape_num(framevar(_), -6).
:- pred code_info__livevals_to_livelvals(list(pair(lval, var)), list(liveinfo),
code_info, code_info).
:- mode code_info__livevals_to_livelvals(in, out, in, out) is det.
code_info__livevals_to_livelvals([], [], C, C).
code_info__livevals_to_livelvals([L - V|Ls], [live_lvalue(L, S_Num )|Lives]) -->
code_info__get_module_info(Module),
code_info__get_shapes(S_Tab0),
{ module_info_types(Module, Type_Table) } ,
code_info__variable_type(V, Type),
{ shapes__request_shape_number(Type - ground, Type_Table,
S_Tab0, S_Tab1, S_Num) } ,
code_info__set_shapes(S_Tab1),
code_info__livevals_to_livelvals(Ls, Lives).
%---------------------------------------------------------------------------%
code_info__variable_type(Var, Type) -->
code_info__get_proc_info(ProcInfo),
{ proc_info_vartypes(ProcInfo, VarTypes) },
{ map__lookup(VarTypes, Var, Type) }.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- pred code_info__get_stackslot_count(int, code_info, code_info).
:- mode code_info__get_stackslot_count(out, in, out) is det.
% :- pred code_info__get_registers(register_info, code_info, code_info).
% :- mode code_info__get_registers(out, in, out) is det.
%
% :- pred code_info__set_registers(register_info, code_info, code_info).
% :- mode code_info__set_registers(in, in, out) is det.
:- pred code_info__get_exprn_info(exprn_info, code_info, code_info).
:- mode code_info__get_exprn_info(out, in, out) is det.
:- pred code_info__set_exprn_info(exprn_info, code_info, code_info).
:- mode code_info__set_exprn_info(in, in, out) is det.
% Get the fall though point for failure
:- pred code_info__get_fall_through(fall_through, code_info, code_info).
:- mode code_info__get_fall_through(out, in, out) is det.
% Set the fall though point for failure
:- pred code_info__set_fall_through(fall_through, code_info, code_info).
:- mode code_info__set_fall_through(in, in, out) is det.
:- pred code_info__get_proc_model(code_model, code_info, code_info).
:- mode code_info__get_proc_model(out, in, out) is det.
:- pred code_info__get_push_count(int, code_info, code_info).
:- mode code_info__get_push_count(out, in, out) is det.
:- pred code_info__set_push_count(int, code_info, code_info).
:- mode code_info__set_push_count(in, in, out) is det.
:- pred code_info__get_max_push_count(int, code_info, code_info).
:- mode code_info__get_max_push_count(out, in, out) is det.
:- pred code_info__set_max_push_count(int, code_info, code_info).
:- mode code_info__set_max_push_count(in, in, out) is det.
:- pred code_info__get_store_map(stack(map(var, lval)), code_info, code_info).
:- mode code_info__get_store_map(out, in, out) is det.
:- pred code_info__set_store_map(stack(map(var, lval)), code_info, code_info).
:- mode code_info__set_store_map(in, in, out) is det.
:- pred code_info__get_pushed_values(stack(pair(lval)), code_info, code_info).
:- mode code_info__get_pushed_values(out, in, out) is det.
:- pred code_info__set_pushed_values(stack(pair(lval)), code_info, code_info).
:- mode code_info__set_pushed_values(in, in, out) is det.
code_info__get_stackslot_count(A, CI, CI) :-
CI = code_info(A, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _).
% code_info__set_stackslot_count(A, CI0, CI) :-
% CI0 = code_info(_, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
% T, U, V),
% CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
% T, U, V).
code_info__get_label_count(B, CI, CI) :-
CI = code_info(_, B, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _).
code_info__set_label_count(B, CI0, CI) :-
CI0 = code_info(A, _, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_varset(C, CI, CI) :-
CI = code_info(_, _, C, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _).
code_info__set_varset(C, CI0, CI) :-
CI0 = code_info(A, B, _, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_call_info(D, CI, CI) :-
CI = code_info(_, _, _, D, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _).
code_info__set_call_info(D, CI0, CI) :-
CI0 = code_info(A, B, C, _, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_pred_id(E, CI, CI) :-
CI = code_info(_, _, _, _, E, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _).
code_info__set_pred_id(E, CI0, CI) :-
CI0 = code_info(A, B, C, D, _, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_proc_id(F, CI, CI) :-
CI = code_info(_, _, _, _, _, F, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _).
code_info__set_proc_id(F, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, _, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
% code_info__get_registers(G, CI, CI) :-
% CI = code_info(_, _, _, _, _, _, G, _, _, _, _, _, _, _, _, _, _, _, _,
% _, _, _).
% code_info__set_registers(G, CI0, CI) :-
% CI0 = code_info(A, B, C, D, E, F, _, H, I, J, K, L, M, N, O, P, Q, R, S,
% T, U, V),
% CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
% T, U, V).
code_info__get_exprn_info(H, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, H, _, _, _, _, _, _, _, _, _, _, _,
_, _, _).
code_info__set_exprn_info(H, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, _, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_proc_info(I, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, I, _, _, _, _, _, _, _, _, _, _,
_, _, _).
code_info__get_succip_used(J, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, J, _, _, _, _, _, _, _, _, _,
_, _, _).
code_info__set_succip_used(J, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, H, I, _, K, L, M, N, O, P, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_fall_through(K, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, K, _, _, _, _, _, _, _, _,
_, _, _).
code_info__set_fall_through(K, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, H, I, J, _, L, M, N, O, P, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_module_info(L, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, _, L, _, _, _, _, _, _, _,
_, _, _).
% It is a bad idea to allow the code generator to module_info
% in arbitrary ways.
% code_info__set_module_info(L, CI0, CI) :-
% CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, _, M, N, O, P, Q, R, S, T, U, V),
% CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V).
code_info__get_liveness_info(M, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, M, _, _, _, _, _, _,
_, _, _).
code_info__set_liveness_info(M, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, _, N, O, P, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_store_map(N, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, N, _, _, _, _, _,
_, _, _).
code_info__set_store_map(N, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, _, O, P, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_proc_model(O, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, O, _, _, _, _,
_, _, _).
code_info__get_instmap(P, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, P, _, _, _,
_, _, _).
code_info__set_instmap(P, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, _, Q, R, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_push_count(Q, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
Q - _, _, _, _, _, _).
code_info__get_max_push_count(QMax, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_ - QMax, _, _, _, _, _).
code_info__set_push_count(Q, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
_ - QMax0, R, S, T, U, V),
int__max(QMax0, Q, QMax),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
Q - QMax, R, S, T, U, V).
code_info__set_max_push_count(QMax, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
Q - _, R, S, T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
Q - QMax, R, S, T, U, V).
code_info__get_globals(R, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, R, _,
_, _, _).
code_info__set_globals(R, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, _, S,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_pushed_values(S, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, S,
_, _, _).
code_info__set_pushed_values(S, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, _,
T, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
code_info__get_shapes(T, CI, CI) :-
CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
T, _, _).
code_info__set_shapes(T, CI0, CI) :-
CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
_, U, V),
CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
T, U, V).
%---------------------------------------------------------------------------%
code_info__grab_code_info(C, C, C).
code_info__slap_code_info(C0, C1, C) :-
code_info__get_label_count(L, C1, _),
code_info__set_label_count(L, C0, C2),
code_info__get_succip_used(S, C1, _),
code_info__set_succip_used(S, C2, C3),
code_info__get_store_map(F, C1, _),
code_info__set_store_map(F, C3, C4),
code_info__get_fall_through(J, C1, _),
code_info__set_fall_through(J, C4, C5),
code_info__get_max_push_count(PC, C1, _),
code_info__set_max_push_count(PC, C5, C).
%---------------------------------------------------------------------------%
:- pred code_info__make_assignment_comment(var, lval, string,
code_info, code_info).
:- mode code_info__make_assignment_comment(in, in, out, in, out) is det.
code_info__make_assignment_comment(Var, _Lval, Comment) -->
code_info__variable_to_string(Var, Name),
{ string__append("Assigning from ", Name, Comment) }.
code_info__variable_to_string(Var, VarName) -->
code_info__get_varset(Varset),
(
{ varset__lookup_name(Varset, Var, Name) }
->
{ VarName = Name }
;
{ term__var_to_int(Var, Int) },
{ string__int_to_string(Int, IntString) },
{ string__append("variable number ", IntString, VarName) }
).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%