mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 21:35:49 +00:00
Estimated hours taken: 2 Branches: main, release Make the system compiler with --warn-unused-imports. browser/*.m: library/*.m: compiler/*.m: Remove unnecesary imports as flagged by --warn-unused-imports. In some files, do some minor cleanup along the way.
802 lines
32 KiB
Mathematica
802 lines
32 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2000-2010 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: prog_rep.m.
|
|
% Authors: zs, maclarty.
|
|
%
|
|
% This module generates a representation of HLDS goals for the declarative
|
|
% debugger. Since this representation is to be included in debuggable
|
|
% executables, it should be as compact as possible, and therefore contains
|
|
% only the information required by the declarative debugger. The structure
|
|
% of this representation is defined by mdbcomp/program_representation.m.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module ll_backend.prog_rep.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.instmap.
|
|
:- import_module ll_backend.stack_layout.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module mdbcomp.program_representation.
|
|
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module pair.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% A var_num_map maps each variable that occurs in any of a procedure's
|
|
% layout structures to a number that uniquely identifies that variable,
|
|
% and to its name.
|
|
%
|
|
% The integer returned by term.var_to_int are a dense set when we consider
|
|
% all the original variables of a procedure. However, it can become less
|
|
% dense when an optimization removes all references to a variable, and
|
|
% becomes less dense still when we consider only variables that occur
|
|
% in a layout structure. This is why we allocate our own id numbers.
|
|
%
|
|
:- type var_num_map == map(prog_var, pair(int, string)).
|
|
|
|
% Describe whether a variable name table should be included in the
|
|
% bytecode. The variable name table actually adds the strings into the
|
|
% module's string table.
|
|
%
|
|
:- type include_variable_table
|
|
---> include_variable_table
|
|
; do_not_include_variable_table.
|
|
|
|
% Create the bytecodes for the given procedure.
|
|
%
|
|
:- pred represent_proc_as_bytecodes(list(prog_var)::in, hlds_goal::in,
|
|
instmap::in, vartypes::in, var_num_map::in, module_info::in,
|
|
include_variable_table::in, determinism::in,
|
|
string_table::in, string_table::out, list(int)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type prog_rep_info
|
|
---> prog_rep_info(
|
|
pri_filename :: string,
|
|
pri_vartypes :: vartypes,
|
|
pri_var_num_map :: var_num_map,
|
|
pri_var_num_rep :: var_num_rep,
|
|
pri_module_info :: module_info
|
|
).
|
|
|
|
:- pred goal_to_goal_rep(prog_rep_info::in, instmap::in, hlds_goal::in,
|
|
goal_rep::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.bytecode_data.
|
|
:- import_module check_hlds.inst_match.
|
|
:- import_module check_hlds.mode_util.
|
|
:- import_module hlds.code_model.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module parse_tree.prog_util.
|
|
|
|
:- import_module int.
|
|
:- import_module maybe.
|
|
:- import_module require.
|
|
:- import_module set.
|
|
:- import_module std_util.
|
|
:- import_module string.
|
|
:- import_module term.
|
|
:- import_module unit.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
represent_proc_as_bytecodes(HeadVars, Goal, InstMap0, VarTypes, VarNumMap,
|
|
ModuleInfo, IncludeVarTable, ProcDetism, !StringTable, ProcRepBytes) :-
|
|
Goal = hlds_goal(_, GoalInfo),
|
|
Context = goal_info_get_context(GoalInfo),
|
|
term.context_file(Context, FileName),
|
|
represent_var_table_as_bytecode(IncludeVarTable, VarNumMap, VarNumRep,
|
|
VarTableBytes, !StringTable),
|
|
Info = prog_rep_info(FileName, VarTypes, VarNumMap, VarNumRep, ModuleInfo),
|
|
InstmapDelta = goal_info_get_instmap_delta(GoalInfo),
|
|
|
|
string_to_byte_list(FileName, FileNameBytes, !StringTable),
|
|
goal_to_byte_list(Goal, InstMap0, Info, GoalBytes, !StringTable),
|
|
DetismByte = represent_determinism(ProcDetism),
|
|
ProcRepBytes0 = FileNameBytes ++ VarTableBytes ++
|
|
head_vars_to_byte_list(Info, InstMap0, InstmapDelta, HeadVars) ++
|
|
GoalBytes ++ [DetismByte],
|
|
int32_to_byte_list(list.length(ProcRepBytes0) + 4, LimitBytes),
|
|
ProcRepBytes = LimitBytes ++ ProcRepBytes0.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Create bytecodes for the variable table.
|
|
%
|
|
% If a variable table is not requested, an empty table is created.
|
|
% The variable table also includes information about the representation
|
|
% of variable numbers within the bytecode.
|
|
%
|
|
% The representation of variables and the variable table restricts the
|
|
% number of possible variables in a procedure to 2^31.
|
|
%
|
|
:- pred represent_var_table_as_bytecode(include_variable_table::in,
|
|
var_num_map::in, var_num_rep::out, list(int)::out,
|
|
string_table::in, string_table::out) is det.
|
|
|
|
represent_var_table_as_bytecode(IncludeVarTable, VarNumMap, VarNumRep,
|
|
ByteList, !StringTable) :-
|
|
map.foldl(max_var_num, VarNumMap, 0) = MaxVarNum,
|
|
( MaxVarNum =< 127 ->
|
|
VarNumRep = var_num_1_byte
|
|
; MaxVarNum =< 32767 ->
|
|
VarNumRep = var_num_2_bytes
|
|
;
|
|
VarNumRep = var_num_4_bytes
|
|
),
|
|
var_num_rep_byte(VarNumRep, VarNumRepByte),
|
|
(
|
|
IncludeVarTable = include_variable_table,
|
|
map.foldl3(var_table_entry_bytelist(VarNumRep), VarNumMap, 0, NumVars,
|
|
[], VarTableEntriesBytes, !StringTable)
|
|
;
|
|
IncludeVarTable = do_not_include_variable_table,
|
|
NumVars = 0,
|
|
VarTableEntriesBytes = []
|
|
),
|
|
int32_to_byte_list(NumVars, NumVarsBytes),
|
|
ByteList = [VarNumRepByte] ++ NumVarsBytes ++ VarTableEntriesBytes.
|
|
|
|
:- func max_var_num(prog_var, pair(int, string), int) = int.
|
|
|
|
max_var_num(_, VarNum1 - _, VarNum2) = Max :-
|
|
Max = max(VarNum1, VarNum2).
|
|
|
|
:- pred var_table_entry_bytelist(var_num_rep::in,
|
|
prog_var::in, pair(int, string)::in, int::in, int::out,
|
|
list(int)::in, list(int)::out,
|
|
string_table::in, string_table::out) is det.
|
|
|
|
var_table_entry_bytelist(VarNumRep, _ProgVar, VarNum - VarName,
|
|
!NumVars, !VarTableBytes, !StringTable) :-
|
|
(
|
|
% Some variables that the compiler creates are named automatically,
|
|
% these and unnamed variables should not be included in the variable
|
|
% table.
|
|
compiler_introduced_varname(VarName)
|
|
->
|
|
true
|
|
;
|
|
!:NumVars = !.NumVars + 1,
|
|
(
|
|
VarNumRep = var_num_1_byte,
|
|
VarBytes = [VarNum]
|
|
;
|
|
VarNumRep = var_num_2_bytes,
|
|
short_to_byte_list(VarNum, VarBytes)
|
|
;
|
|
VarNumRep = var_num_4_bytes,
|
|
int32_to_byte_list(VarNum, VarBytes)
|
|
),
|
|
string_to_byte_list(VarName, VarNameBytes, !StringTable),
|
|
!:VarTableBytes = VarBytes ++ VarNameBytes ++ !.VarTableBytes
|
|
).
|
|
|
|
:- pred compiler_introduced_varname(string::in) is semidet.
|
|
|
|
compiler_introduced_varname("").
|
|
compiler_introduced_varname("ProcStaticLayout").
|
|
compiler_introduced_varname("TopCSD").
|
|
compiler_introduced_varname("MiddleCSD").
|
|
compiler_introduced_varname("ActivationPtr").
|
|
compiler_introduced_varname("SiteNum").
|
|
compiler_introduced_varname("MethodNum").
|
|
compiler_introduced_varname(VarName) :-
|
|
( Prefix = "V_"
|
|
; Prefix = "HeadVar__"
|
|
; Prefix = "TypeClassInfo_for_"
|
|
; Prefix = "TypeInfo_"
|
|
; Prefix = "TypeCtorInfo_"
|
|
; Prefix = "STATE_VARIABLE_"
|
|
; Prefix = "DCG_"
|
|
),
|
|
prefix(VarName, Prefix).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred goal_to_byte_list(hlds_goal::in, instmap::in, prog_rep_info::in,
|
|
list(int)::out, string_table::in, string_table::out) is det.
|
|
|
|
goal_to_byte_list(Goal, InstMap0, Info, Bytes, !StringTable) :-
|
|
goal_to_goal_rep(Info, InstMap0, Goal, GoalRep),
|
|
goal_rep_to_byte_list(Info, GoalRep, Bytes, !StringTable).
|
|
|
|
goal_to_goal_rep(Info, Instmap0, hlds_goal(GoalExpr, GoalInfo), GoalRep) :-
|
|
Detism = goal_info_get_determinism(GoalInfo),
|
|
detism_to_detism_rep(Detism, DetismRep),
|
|
GoalRep = goal_rep(GoalExprRep, DetismRep, unit),
|
|
(
|
|
GoalExpr = conj(ConjType, Goals),
|
|
expect(unify(ConjType, plain_conj), this_file,
|
|
"non-plain conjunction and declarative debugging"),
|
|
conj_to_conj_rep(Info, Instmap0, Goals, GoalReps),
|
|
GoalExprRep = conj_rep(GoalReps)
|
|
;
|
|
GoalExpr = disj(Goals),
|
|
% Since eash disjunct begins with the same instmap we can use map
|
|
map(goal_to_goal_rep(Info, Instmap0), Goals, GoalReps),
|
|
GoalExprRep = disj_rep(GoalReps)
|
|
;
|
|
GoalExpr = negation(SubGoal),
|
|
goal_to_goal_rep(Info, Instmap0, SubGoal, SubGoalRep),
|
|
GoalExprRep = negation_rep(SubGoalRep)
|
|
;
|
|
GoalExpr = if_then_else(_, Cond, Then, Else),
|
|
Cond = hlds_goal(_, CondGoalInfo),
|
|
InstmapDelta = goal_info_get_instmap_delta(CondGoalInfo),
|
|
instmap.apply_instmap_delta(Instmap0, InstmapDelta, InstmapAfterCond),
|
|
goal_to_goal_rep(Info, Instmap0, Cond, CondRep),
|
|
goal_to_goal_rep(Info, InstmapAfterCond, Then, ThenRep),
|
|
goal_to_goal_rep(Info, Instmap0, Else, ElseRep),
|
|
GoalExprRep = ite_rep(CondRep, ThenRep, ElseRep)
|
|
;
|
|
GoalExpr = switch(Var, CanFail, Cases),
|
|
map(case_to_case_rep(Info, Instmap0), Cases, CasesRep),
|
|
(
|
|
CanFail = can_fail,
|
|
CanFailRep = switch_can_fail_rep
|
|
;
|
|
CanFail = cannot_fail,
|
|
CanFailRep = switch_can_not_fail_rep
|
|
),
|
|
VarRep = var_to_var_rep(Info, Var),
|
|
GoalExprRep = switch_rep(VarRep, CanFailRep, CasesRep)
|
|
;
|
|
GoalExpr = scope(_, SubGoal),
|
|
SubGoal = hlds_goal(_, SubGoalInfo),
|
|
goal_to_goal_rep(Info, Instmap0, SubGoal, SubGoalRep),
|
|
OuterDetism = goal_info_get_determinism(GoalInfo),
|
|
InnerDetism = goal_info_get_determinism(SubGoalInfo),
|
|
( InnerDetism = OuterDetism ->
|
|
MaybeCut = scope_is_no_cut
|
|
;
|
|
MaybeCut = scope_is_cut
|
|
),
|
|
GoalExprRep = scope_rep(SubGoalRep, MaybeCut)
|
|
;
|
|
( GoalExpr = unify(_, _, _, _, _)
|
|
; GoalExpr = generic_call(_, _, _, _)
|
|
; GoalExpr = plain_call(_, _, _, _, _, _)
|
|
; GoalExpr = call_foreign_proc(_, _, _, _, _, _, _)
|
|
),
|
|
(
|
|
GoalExpr = unify(_, _, _, Uni, _),
|
|
(
|
|
Uni = assign(Target, Source),
|
|
AtomicGoalRep = unify_assign_rep(
|
|
var_to_var_rep(Info, Target),
|
|
var_to_var_rep(Info, Source))
|
|
;
|
|
( Uni = construct(Var, ConsId, Args, ArgModes, _, _, _)
|
|
; Uni = deconstruct(Var, ConsId, Args, ArgModes, _, _)
|
|
),
|
|
VarRep = var_to_var_rep(Info, Var),
|
|
ConsIdRep = cons_id_rep(ConsId),
|
|
ArgsRep = map(var_to_var_rep(Info), Args),
|
|
filter_input_args(Info, ArgModes, Args, MaybeArgs),
|
|
MaybeArgsRep = map(map_maybe(var_to_var_rep(Info)), MaybeArgs),
|
|
(
|
|
Uni = construct(_, _, _, _, _, _, _),
|
|
( list.all_true(lhs_final_is_ground(Info), ArgModes) ->
|
|
AtomicGoalRep = unify_construct_rep(VarRep, ConsIdRep,
|
|
ArgsRep)
|
|
;
|
|
AtomicGoalRep = partial_construct_rep(VarRep, ConsIdRep,
|
|
MaybeArgsRep)
|
|
)
|
|
;
|
|
Uni = deconstruct(_, _, _, _, _, _),
|
|
( list.member(Var, BoundVars) ->
|
|
AtomicGoalRep = partial_deconstruct_rep(VarRep,
|
|
ConsIdRep, MaybeArgsRep)
|
|
;
|
|
AtomicGoalRep = unify_deconstruct_rep(VarRep, ConsIdRep,
|
|
ArgsRep)
|
|
)
|
|
)
|
|
;
|
|
Uni = simple_test(Var1, Var2),
|
|
AtomicGoalRep = unify_simple_test_rep(
|
|
var_to_var_rep(Info, Var1),
|
|
var_to_var_rep(Info, Var2))
|
|
;
|
|
Uni = complicated_unify(_, _, _),
|
|
unexpected(this_file, "goal_expr_to_byte_list: complicated_unify")
|
|
)
|
|
;
|
|
GoalExpr = generic_call(GenericCall, Args, _, _),
|
|
ArgsRep = map(var_to_var_rep(Info), Args),
|
|
(
|
|
GenericCall = higher_order(PredVar, _, _, _),
|
|
PredVarRep = var_to_var_rep(Info, PredVar),
|
|
AtomicGoalRep = higher_order_call_rep(PredVarRep, ArgsRep)
|
|
;
|
|
GenericCall = class_method(Var, Num, _, _),
|
|
VarRep = var_to_var_rep(Info, Var),
|
|
AtomicGoalRep = method_call_rep(VarRep, Num, ArgsRep)
|
|
;
|
|
GenericCall = event_call(EventName),
|
|
AtomicGoalRep = event_call_rep(EventName, ArgsRep)
|
|
;
|
|
GenericCall = cast(_),
|
|
( ArgsRep = [InputArgRep, OutputArgRep] ->
|
|
AtomicGoalRep = cast_rep(OutputArgRep, InputArgRep)
|
|
;
|
|
unexpected(this_file,
|
|
"goal_expr_goal_expr_rep: cast arity != 2")
|
|
)
|
|
)
|
|
;
|
|
GoalExpr = plain_call(PredId, _, Args, Builtin, _, _),
|
|
module_info_pred_info(Info ^ pri_module_info, PredId, PredInfo),
|
|
ModuleSymName = pred_info_module(PredInfo),
|
|
ModuleName = sym_name_to_string(ModuleSymName),
|
|
PredName = pred_info_name(PredInfo),
|
|
ArgsRep = map(var_to_var_rep(Info), Args),
|
|
(
|
|
Builtin = not_builtin,
|
|
AtomicGoalRep = plain_call_rep(ModuleName, PredName, ArgsRep)
|
|
;
|
|
Builtin = inline_builtin,
|
|
AtomicGoalRep = builtin_call_rep(ModuleName, PredName, ArgsRep)
|
|
;
|
|
Builtin = out_of_line_builtin,
|
|
unexpected(this_file,
|
|
"goal_expr_to_byte_list: out_of_line_builtin")
|
|
)
|
|
;
|
|
GoalExpr = call_foreign_proc(_, _PredId, _, Args, _, _, _),
|
|
ArgVarsRep = list.map(
|
|
compose(var_to_var_rep(Info), foreign_arg_var), Args),
|
|
AtomicGoalRep = pragma_foreign_code_rep(ArgVarsRep)
|
|
),
|
|
goal_info_to_atomic_goal_rep_fields(GoalInfo, Instmap0, Info,
|
|
FileName, LineNo, BoundVars),
|
|
BoundVarsRep = map(var_to_var_rep(Info), BoundVars),
|
|
GoalExprRep = atomic_goal_rep(FileName, LineNo, BoundVarsRep,
|
|
AtomicGoalRep)
|
|
;
|
|
GoalExpr = shorthand(_),
|
|
% These should have been expanded out by now.
|
|
unexpected(this_file, "goal_expr_to_byte_list: unexpected shorthand")
|
|
).
|
|
|
|
:- pred conj_to_conj_rep(prog_rep_info::in, instmap::in, list(hlds_goal)::in,
|
|
list(goal_rep)::out) is det.
|
|
|
|
conj_to_conj_rep(_, _, [], []).
|
|
conj_to_conj_rep(Info, Instmap0, [Conj | Conjs], [ConjRep | ConjReps]) :-
|
|
goal_to_goal_rep(Info, Instmap0, Conj, ConjRep),
|
|
GoalInfo = Conj ^ hlds_goal_info,
|
|
InstmapDelta = goal_info_get_instmap_delta(GoalInfo),
|
|
instmap.apply_instmap_delta(Instmap0, InstmapDelta, Instmap1),
|
|
conj_to_conj_rep(Info, Instmap1, Conjs, ConjReps).
|
|
|
|
:- pred case_to_case_rep(prog_rep_info::in, instmap::in,
|
|
case::in, case_rep::out) is det.
|
|
|
|
case_to_case_rep(Info, Instmap, case(FirstConsId, OtherConsIds, Goal),
|
|
case_rep(FirstConsIdRep, OtherConsIdsRep, GoalRep)) :-
|
|
goal_to_goal_rep(Info, Instmap, Goal, GoalRep),
|
|
cons_id_to_cons_id_rep(FirstConsId, FirstConsIdRep),
|
|
map(cons_id_to_cons_id_rep, OtherConsIds, OtherConsIdsRep).
|
|
|
|
:- pred cons_id_to_cons_id_rep(cons_id::in, cons_id_arity_rep::out) is det.
|
|
|
|
cons_id_to_cons_id_rep(ConsId, cons_id_arity_rep(ConsIdName, Arity)) :-
|
|
ConsIdName = cons_id_rep(ConsId),
|
|
MaybeArity = cons_id_maybe_arity(ConsId),
|
|
(
|
|
MaybeArity = yes(Arity)
|
|
;
|
|
MaybeArity = no,
|
|
Arity = 0
|
|
).
|
|
|
|
:- pred detism_to_detism_rep(determinism::in, detism_rep::out) is det.
|
|
|
|
detism_to_detism_rep(detism_det, det_rep).
|
|
detism_to_detism_rep(detism_semi, semidet_rep).
|
|
detism_to_detism_rep(detism_multi, multidet_rep).
|
|
detism_to_detism_rep(detism_non, nondet_rep).
|
|
detism_to_detism_rep(detism_cc_multi, cc_multidet_rep).
|
|
detism_to_detism_rep(detism_cc_non, cc_nondet_rep).
|
|
detism_to_detism_rep(detism_erroneous, erroneous_rep).
|
|
detism_to_detism_rep(detism_failure, failure_rep).
|
|
|
|
:- pred goal_rep_to_byte_list(prog_rep_info::in, goal_rep::in,
|
|
list(int)::out, string_table::in, string_table::out) is det.
|
|
|
|
goal_rep_to_byte_list(Info, goal_rep(GoalExpr, Detism, _), Bytes, !StringTable) :-
|
|
(
|
|
GoalExpr = conj_rep(GoalReps),
|
|
map_foldl(goal_rep_to_byte_list(Info), GoalReps, ConjBytesList,
|
|
!StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_conj)] ++
|
|
length_to_byte_list(GoalReps) ++ condense(ConjBytesList)
|
|
;
|
|
GoalExpr = disj_rep(GoalReps),
|
|
map_foldl(goal_rep_to_byte_list(Info), GoalReps, DisjBytesList,
|
|
!StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_disj)] ++
|
|
length_to_byte_list(GoalReps) ++ condense(DisjBytesList)
|
|
;
|
|
GoalExpr = negation_rep(SubGoal),
|
|
goal_rep_to_byte_list(Info, SubGoal, SubGoalBytes, !StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_neg)] ++ SubGoalBytes
|
|
;
|
|
GoalExpr = ite_rep(Cond, Then, Else),
|
|
goal_rep_to_byte_list(Info, Cond, CondBytes, !StringTable),
|
|
goal_rep_to_byte_list(Info, Then, ThenBytes, !StringTable),
|
|
goal_rep_to_byte_list(Info, Else, ElseBytes, !StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_ite)] ++
|
|
CondBytes ++ ThenBytes ++ ElseBytes
|
|
;
|
|
GoalExpr = atomic_goal_rep(FileName, Line, BoundVars, AtomicGoalRep),
|
|
string_to_byte_list(FileName, FileNameBytes, !StringTable),
|
|
AtomicBytes = FileNameBytes ++ lineno_to_byte_list(Line) ++
|
|
var_reps_to_byte_list(Info, BoundVars),
|
|
(
|
|
AtomicGoalRep = unify_assign_rep(Target, Source),
|
|
ExprBytes = [goal_type_to_byte(goal_assign)] ++
|
|
var_rep_to_byte_list(Info, Target) ++
|
|
var_rep_to_byte_list(Info, Source) ++
|
|
AtomicBytes
|
|
;
|
|
( AtomicGoalRep = unify_construct_rep(_, _, _)
|
|
; AtomicGoalRep = unify_deconstruct_rep(_, _, _)
|
|
; AtomicGoalRep = partial_construct_rep(_, _, _)
|
|
; AtomicGoalRep = partial_deconstruct_rep(_, _, _)
|
|
),
|
|
(
|
|
(
|
|
AtomicGoalRep = unify_construct_rep(Var, ConsId, Args),
|
|
AtomicTypeByte = goal_type_to_byte(goal_construct)
|
|
;
|
|
AtomicGoalRep = unify_deconstruct_rep(Var, ConsId, Args),
|
|
AtomicTypeByte = goal_type_to_byte(goal_deconstruct)
|
|
),
|
|
ArgsBytes = var_reps_to_byte_list(Info, Args)
|
|
;
|
|
(
|
|
AtomicGoalRep = partial_deconstruct_rep(Var, ConsId,
|
|
MaybeArgs),
|
|
AtomicTypeByte =
|
|
goal_type_to_byte(goal_partial_deconstruct)
|
|
;
|
|
AtomicGoalRep = partial_construct_rep(Var, ConsId,
|
|
MaybeArgs),
|
|
AtomicTypeByte = goal_type_to_byte(goal_partial_construct)
|
|
),
|
|
ArgsBytes = maybe_var_reps_to_byte_list(Info, MaybeArgs)
|
|
),
|
|
string_to_byte_list(ConsId, ConsIdBytes, !StringTable),
|
|
VarBytes = var_rep_to_byte_list(Info, Var),
|
|
ExprBytes = [AtomicTypeByte] ++ VarBytes ++ ConsIdBytes ++
|
|
ArgsBytes ++ AtomicBytes
|
|
;
|
|
AtomicGoalRep = unify_simple_test_rep(Var1, Var2),
|
|
ExprBytes = [goal_type_to_byte(goal_simple_test)] ++
|
|
var_rep_to_byte_list(Info, Var1) ++
|
|
var_rep_to_byte_list(Info, Var2) ++
|
|
AtomicBytes
|
|
;
|
|
AtomicGoalRep = higher_order_call_rep(PredVar, Args),
|
|
ExprBytes = [goal_type_to_byte(goal_ho_call)] ++
|
|
var_rep_to_byte_list(Info, PredVar) ++
|
|
var_reps_to_byte_list(Info, Args) ++
|
|
AtomicBytes
|
|
;
|
|
AtomicGoalRep = method_call_rep(Var, MethodNum, Args),
|
|
ExprBytes = [goal_type_to_byte(goal_method_call)] ++
|
|
var_rep_to_byte_list(Info, Var) ++
|
|
method_num_to_byte_list(MethodNum) ++
|
|
var_reps_to_byte_list(Info, Args) ++
|
|
AtomicBytes
|
|
;
|
|
AtomicGoalRep = event_call_rep(EventName, Args),
|
|
string_to_byte_list(EventName, EventNameBytes, !StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_event_call)] ++
|
|
EventNameBytes ++
|
|
var_reps_to_byte_list(Info, Args) ++
|
|
AtomicBytes
|
|
;
|
|
AtomicGoalRep = cast_rep(Target, Source),
|
|
ExprBytes = [goal_type_to_byte(goal_cast)] ++
|
|
var_rep_to_byte_list(Info, Target) ++
|
|
var_rep_to_byte_list(Info, Source) ++
|
|
AtomicBytes
|
|
;
|
|
(
|
|
AtomicGoalRep = plain_call_rep(ModuleName, PredName, Args),
|
|
CallType = goal_plain_call
|
|
;
|
|
AtomicGoalRep = builtin_call_rep(ModuleName, PredName, Args),
|
|
CallType = goal_builtin_call
|
|
),
|
|
string_to_byte_list(ModuleName, ModuleNameBytes, !StringTable),
|
|
string_to_byte_list(PredName, PredNameBytes, !StringTable),
|
|
ExprBytes = [goal_type_to_byte(CallType)] ++
|
|
ModuleNameBytes ++
|
|
PredNameBytes ++
|
|
var_reps_to_byte_list(Info, Args) ++
|
|
AtomicBytes
|
|
;
|
|
AtomicGoalRep = pragma_foreign_code_rep(Args),
|
|
ExprBytes = [goal_type_to_byte(goal_foreign)] ++
|
|
var_reps_to_byte_list(Info, Args) ++ AtomicBytes
|
|
)
|
|
;
|
|
GoalExpr = switch_rep(SwitchVar, CanFail, Cases),
|
|
map_foldl(case_rep_to_byte_list(Info), Cases, CasesBytesList,
|
|
!StringTable),
|
|
can_fail_byte(CanFail, CanFailByte),
|
|
ExprBytes = [goal_type_to_byte(goal_switch)] ++
|
|
[CanFailByte] ++
|
|
var_rep_to_byte_list(Info, SwitchVar) ++
|
|
length_to_byte_list(Cases) ++ condense(CasesBytesList)
|
|
;
|
|
GoalExpr = scope_rep(SubGoal, MaybeCut),
|
|
cut_byte(MaybeCut, MaybeCutByte),
|
|
goal_rep_to_byte_list(Info, SubGoal, SubGoalBytes, !StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_scope)] ++ [MaybeCutByte] ++
|
|
SubGoalBytes
|
|
),
|
|
determinism_representation(Detism, DetismByte),
|
|
Bytes = ExprBytes ++ [DetismByte].
|
|
|
|
:- pred case_rep_to_byte_list(prog_rep_info::in, case_rep::in, list(int)::out,
|
|
string_table::in, string_table::out) is det.
|
|
|
|
case_rep_to_byte_list(Info, Case, Bytes, !StringTable) :-
|
|
Case = case_rep(MainConsId, OtherConsIds, Goal),
|
|
goal_rep_to_byte_list(Info, Goal, GoalBytes, !StringTable),
|
|
cons_id_and_arity_rep_to_byte_list(MainConsId, MainConsIdBytes,
|
|
!StringTable),
|
|
map_foldl(cons_id_and_arity_rep_to_byte_list,
|
|
OtherConsIds, OtherConsIdsByteLists, !StringTable),
|
|
Bytes = MainConsIdBytes ++ length_to_byte_list(OtherConsIds) ++
|
|
condense(OtherConsIdsByteLists) ++ GoalBytes.
|
|
|
|
:- pred lhs_final_is_ground(prog_rep_info::in, uni_mode::in) is semidet.
|
|
|
|
lhs_final_is_ground(Info, (_ - _) -> (LHSFinalInst - _)) :-
|
|
inst_is_ground(Info ^ pri_module_info, LHSFinalInst).
|
|
|
|
:- pred rhs_is_input(prog_rep_info::in, uni_mode::in) is semidet.
|
|
|
|
rhs_is_input(Info, (_ - RHSInitialInst) -> (_ - RHSFinalInst)) :-
|
|
mode_is_input(Info ^ pri_module_info, RHSInitialInst -> RHSFinalInst).
|
|
|
|
:- pred filter_input_args(prog_rep_info::in, list(uni_mode)::in,
|
|
list(prog_var)::in, list(maybe(prog_var))::out) is det.
|
|
|
|
filter_input_args(_, [], [], []).
|
|
filter_input_args(Info, [Mode | Modes], [Var | Vars],
|
|
[MaybeVar | MaybeVars]) :-
|
|
( rhs_is_input(Info, Mode) ->
|
|
MaybeVar = yes(Var)
|
|
;
|
|
MaybeVar = no
|
|
),
|
|
filter_input_args(Info, Modes, Vars, MaybeVars).
|
|
filter_input_args(_, [], [_ | _], _) :-
|
|
unexpected(this_file, "filter_input_args: mismatched lists").
|
|
filter_input_args(_, [_ | _], [], _) :-
|
|
unexpected(this_file, "filter_input_args: mismatched lists").
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred goal_info_to_atomic_goal_rep_fields(hlds_goal_info::in, instmap::in,
|
|
prog_rep_info::in, string::out, int::out, list(prog_var)::out) is det.
|
|
|
|
goal_info_to_atomic_goal_rep_fields(GoalInfo, Instmap0, Info, FileName, LineNo,
|
|
BoundVars) :-
|
|
Context = goal_info_get_context(GoalInfo),
|
|
term.context_file(Context, FileName0),
|
|
( FileName0 = Info ^ pri_filename ->
|
|
FileName = ""
|
|
;
|
|
FileName = FileName0
|
|
),
|
|
term.context_line(Context, LineNo),
|
|
InstmapDelta = goal_info_get_instmap_delta(GoalInfo),
|
|
instmap.apply_instmap_delta(Instmap0, InstmapDelta, Instmap),
|
|
instmap_changed_vars(Instmap0, Instmap, Info ^ pri_vartypes,
|
|
Info ^ pri_module_info, ChangedVars),
|
|
set.to_sorted_list(ChangedVars, BoundVars).
|
|
|
|
:- pred cons_id_and_arity_rep_to_byte_list(cons_id_arity_rep::in,
|
|
list(int)::out, string_table::in, string_table::out) is det.
|
|
|
|
cons_id_and_arity_rep_to_byte_list(ConsIdArity, ConsIdBytes, !StringTable) :-
|
|
ConsIdArity = cons_id_arity_rep(ConsId, Arity),
|
|
string_to_byte_list(ConsId, FunctorBytes, !StringTable),
|
|
short_to_byte_list(Arity, ArityBytes),
|
|
ConsIdBytes = FunctorBytes ++ ArityBytes.
|
|
|
|
:- pred cons_id_to_byte_list(cons_id::in, list(int)::out,
|
|
string_table::in, string_table::out) is det.
|
|
|
|
cons_id_to_byte_list(SymName, Bytes, !StringTable) :-
|
|
string_to_byte_list(cons_id_rep(SymName), Bytes, !StringTable).
|
|
|
|
:- func cons_id_rep(cons_id) = string.
|
|
|
|
cons_id_rep(cons(SymName, _, _)) =
|
|
prog_rep.sym_base_name_to_string(SymName).
|
|
cons_id_rep(tuple_cons(_)) = "{}".
|
|
cons_id_rep(int_const(Int)) = string.int_to_string(Int).
|
|
cons_id_rep(float_const(Float)) = string.float_to_string(Float).
|
|
cons_id_rep(char_const(Char)) = string.char_to_string(Char).
|
|
cons_id_rep(string_const(String)) = """" ++ String ++ """".
|
|
cons_id_rep(impl_defined_const(Name)) = "$" ++ Name.
|
|
cons_id_rep(closure_cons(_, _)) = "$closure_cons".
|
|
cons_id_rep(type_ctor_info_const(_, _, _)) = "$type_ctor_info_const".
|
|
cons_id_rep(base_typeclass_info_const(_, _, _, _)) =
|
|
"$base_typeclass_info_const".
|
|
cons_id_rep(type_info_cell_constructor(_)) = "$type_info_cell_constructor".
|
|
cons_id_rep(typeclass_info_cell_constructor) =
|
|
"$typeclass_info_cell_constructor".
|
|
cons_id_rep(tabling_info_const(_)) = "$tabling_info_const".
|
|
cons_id_rep(table_io_decl(_)) = "$table_io_decl".
|
|
cons_id_rep(deep_profiling_proc_layout(_)) = "$deep_profiling_proc_layout".
|
|
|
|
:- func sym_base_name_to_string(sym_name) = string.
|
|
|
|
sym_base_name_to_string(unqualified(String)) = String.
|
|
sym_base_name_to_string(qualified(_, String)) = String.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% The operations to convert primitive constructs to bytecode.
|
|
%
|
|
% We use the operations defined in bytecode_data. Each of the functions below
|
|
% stands for a given primitive construct. If we need to expand the number of
|
|
% bytes we use to represent one of these, it should be sufficient to change
|
|
% the number of bits here and in mdbcomp/program_representation.m.
|
|
%
|
|
% Warning: the predicates we use from bytecode_data deal with signed integers,
|
|
% but we here use them to represent unsigned quantities. This effectively
|
|
% halves their range.
|
|
|
|
:- pred string_to_byte_list(string::in, list(int)::out,
|
|
string_table::in, string_table::out) is det.
|
|
|
|
string_to_byte_list(String, Bytes, !StringTable) :-
|
|
stack_layout.lookup_string_in_table(String, Index, !StringTable),
|
|
int32_to_byte_list(Index, Bytes).
|
|
|
|
:- func var_reps_to_byte_list(prog_rep_info, list(var_rep)) = list(int).
|
|
|
|
var_reps_to_byte_list(Info, Vars) =
|
|
length_to_byte_list(Vars) ++
|
|
list.condense(list.map(var_rep_to_byte_list(Info), Vars)).
|
|
|
|
:- func var_to_var_rep(prog_rep_info, prog_var) = int.
|
|
|
|
var_to_var_rep(Info, Var) = Num :-
|
|
map.lookup(Info ^ pri_var_num_map, Var, Num - _).
|
|
|
|
:- func var_rep_to_byte_list(prog_rep_info, var_rep) = list(int).
|
|
|
|
var_rep_to_byte_list(Info, Var) = Bytes :-
|
|
(
|
|
Info ^ pri_var_num_rep = var_num_1_byte,
|
|
Bytes = [Var]
|
|
;
|
|
Info ^ pri_var_num_rep = var_num_2_bytes,
|
|
short_to_byte_list(Var, Bytes)
|
|
;
|
|
Info ^ pri_var_num_rep = var_num_4_bytes,
|
|
int32_to_byte_list(Var, Bytes)
|
|
).
|
|
|
|
:- func maybe_var_reps_to_byte_list(prog_rep_info, list(maybe(var_rep))) =
|
|
list(int).
|
|
|
|
maybe_var_reps_to_byte_list(Info, Vars) =
|
|
length_to_byte_list(Vars) ++
|
|
list.condense(list.map(maybe_var_rep_to_byte_list(Info), Vars)).
|
|
|
|
:- func maybe_var_rep_to_byte_list(prog_rep_info, maybe(var_rep)) = list(int).
|
|
|
|
maybe_var_rep_to_byte_list(Info, MaybeVar) = Bytes :-
|
|
% This is not the most efficient representation, however maybe(var_rep)s
|
|
% are only used for partial unifications which are rare.
|
|
(
|
|
MaybeVar = yes(Var),
|
|
Bytes = [1 | var_rep_to_byte_list(Info, Var)]
|
|
;
|
|
MaybeVar = no,
|
|
Bytes = [0]
|
|
).
|
|
|
|
:- func head_vars_to_byte_list(prog_rep_info, instmap, instmap_delta,
|
|
list(prog_var)) = list(int).
|
|
|
|
head_vars_to_byte_list(Info, InitialInstmap, InstmapDelta, Vars) =
|
|
length_to_byte_list(Vars) ++
|
|
list.condense(list.map(
|
|
head_var_to_byte_list(Info, InitialInstmap, InstmapDelta), Vars)).
|
|
|
|
:- func head_var_to_byte_list(prog_rep_info, instmap, instmap_delta,
|
|
prog_var) = list(int).
|
|
|
|
head_var_to_byte_list(Info, InitialInstmap, InstmapDelta, Var) = Bytes :-
|
|
var_rep_to_byte_list(Info, var_to_var_rep(Info, Var)) = VarBytes,
|
|
ModuleInfo = Info ^ pri_module_info,
|
|
instmap_lookup_var(InitialInstmap, Var, InitialInst),
|
|
( instmap_delta_search_var(InstmapDelta, Var, FinalInstPrime) ->
|
|
FinalInst = FinalInstPrime
|
|
;
|
|
% if the variable is not in the instmap delta, then its instantiation
|
|
% cannot possibly change. It has the same instantiation that it begun
|
|
% with.
|
|
FinalInst = InitialInst
|
|
),
|
|
Bytes = VarBytes ++ [inst_to_byte(ModuleInfo, InitialInst),
|
|
inst_to_byte(ModuleInfo, FinalInst)].
|
|
|
|
:- func inst_to_byte(module_info, mer_inst) = int.
|
|
|
|
inst_to_byte(ModuleInfo, MerInst) = Byte :-
|
|
(
|
|
( MerInst = free
|
|
; MerInst = free(_)
|
|
)
|
|
->
|
|
InstRep = ir_free_rep
|
|
;
|
|
inst_is_ground(ModuleInfo, MerInst)
|
|
->
|
|
InstRep = ir_ground_rep
|
|
;
|
|
InstRep = ir_other_rep
|
|
),
|
|
inst_representation(InstRep, Byte).
|
|
|
|
:- func length_to_byte_list(list(T)) = list(int).
|
|
|
|
length_to_byte_list(List) = Bytes :-
|
|
int32_to_byte_list(list.length(List), Bytes).
|
|
|
|
:- func lineno_to_byte_list(int) = list(int).
|
|
|
|
lineno_to_byte_list(VarNum) = Bytes :-
|
|
int32_to_byte_list(VarNum, Bytes).
|
|
|
|
:- func method_num_to_byte_list(int) = list(int).
|
|
|
|
method_num_to_byte_list(VarNum) = Bytes :-
|
|
short_to_byte_list(VarNum, Bytes).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- func this_file = string.
|
|
|
|
this_file = "prog_rep.m".
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module prog_rep.
|
|
%---------------------------------------------------------------------------%
|