mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 01:13:30 +00:00
compiler/inst_lookup.m:
compiler/inst_mode_type_prop.m:
compiler/inst_test.m:
compiler/inst_util.m:
compiler/mode_util.m:
compiler/type_util.m:
Move these modules from the check_hlds package to the hlds package.
The reason is that all the content of five of these modules, and
most of the content of one module (inst_util.m) is not used
exclusively during semantic checking passes. (A later diff
should deal with the exception.) Some are used by the pass that
builds the initial HLDS, and all are used by middle-end and backend
passes. The move therefore reduces the number of inappropriate imports
of the check_hlds package.
compiler/check_hlds.m:
compiler/hlds.m:
Effect the transfer.
compiler/*.m:
Conform to the changes above.
1053 lines
42 KiB
Mathematica
1053 lines
42 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2000-2012 The University of Melbourne.
|
|
% Copyright (C) 2015-2019, 2021-2025 The Mercury team.
|
|
% 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.
|
|
%
|
|
% debugger and the deep profiler. Since this representation is to be included
|
|
% in debuggable and deep-profilable executables, it should be as compact
|
|
% as possible, and therefore contains only the information required by
|
|
% its two clients. The structure of this representation is defined
|
|
% by mdbcomp/program_representation.m.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module ll_backend.prog_rep.
|
|
:- interface.
|
|
|
|
:- import_module hlds.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.instmap.
|
|
:- import_module ll_backend.prog_rep_tables.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.program_representation.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.var_table.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module cord.
|
|
:- 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)).
|
|
|
|
% Encode the information in a module's oisu pragmas into bytecode,
|
|
% for use by the automatic parallelization feedback tool.
|
|
%
|
|
:- pred encode_oisu_type_procs(module_info::in,
|
|
assoc_list(type_ctor, oisu_preds)::in, int::out, cord(int)::out) is det.
|
|
|
|
% Create the bytecodes for the given procedure.
|
|
%
|
|
:- pred represent_proc_as_bytecodes(list(prog_var)::in, hlds_goal::in,
|
|
instmap::in, var_table::in, var_num_map::in, module_info::in,
|
|
maybe_include_var_name_table::in, maybe_include_var_types::in,
|
|
determinism::in, string_table_info::in, string_table_info::out,
|
|
type_table_info::in, type_table_info::out, list(int)::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- type prog_rep_info
|
|
---> prog_rep_info(
|
|
pri_module_info :: module_info,
|
|
pri_filename :: string,
|
|
pri_var_table :: var_table,
|
|
pri_var_num_map :: var_num_map,
|
|
pri_var_num_rep :: var_num_rep,
|
|
pri_flatten_par_conjs :: flatten_par_conjs
|
|
).
|
|
|
|
:- type flatten_par_conjs
|
|
---> flatten_par_conjs
|
|
; expect_no_par_conjs.
|
|
|
|
:- pred goal_to_goal_rep(prog_rep_info::in, instmap::in, hlds_goal::in,
|
|
goal_rep::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.
|
|
:- import_module backend_libs.proc_label.
|
|
:- import_module check_hlds.
|
|
:- import_module check_hlds.mode_test.
|
|
:- import_module hlds.code_model.
|
|
:- import_module hlds.goal_transform.
|
|
:- import_module hlds.hlds_class.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module hlds.inst_test.
|
|
:- import_module hlds.pred_name.
|
|
:- import_module mdbcomp.goal_path.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module mdbcomp.rtti_access.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.parse_tree_out_cons_id.
|
|
:- import_module parse_tree.prog_util.
|
|
:- import_module parse_tree.set_of_var.
|
|
|
|
:- import_module int.
|
|
:- import_module maybe.
|
|
:- import_module require.
|
|
:- import_module std_util.
|
|
:- import_module string.
|
|
:- import_module term_context.
|
|
:- import_module unit.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
encode_oisu_type_procs(_ModuleInfo, [], 0, cord.init).
|
|
encode_oisu_type_procs(ModuleInfo, [Pair | Pairs], NumOISUTypes, Bytes) :-
|
|
encode_oisu_type_procs(ModuleInfo, Pairs, TailNumOISUTypes, TailBytes),
|
|
module_info_get_name(ModuleInfo, ModuleName),
|
|
Pair = TypeCtor - Preds,
|
|
TypeCtor = type_ctor(TypeCtorSymName, _TypeCtorArity),
|
|
(
|
|
TypeCtorSymName = qualified(TypeCtorModuleName, TypeCtorName)
|
|
;
|
|
TypeCtorSymName = unqualified(_),
|
|
unexpected($pred, "unqualified type_ctor name")
|
|
),
|
|
( if TypeCtorModuleName = ModuleName then
|
|
encode_len_string(TypeCtorName, TypeCtorNameBytes),
|
|
Preds = oisu_preds(CreatorPreds, MutatorPreds, DestructorPreds),
|
|
|
|
list.length(CreatorPreds, NumCreatorPreds),
|
|
list.length(MutatorPreds, NumMutatorPreds),
|
|
list.length(DestructorPreds, NumDestructorPreds),
|
|
encode_num_det(NumCreatorPreds, NumCreatorPredsBytes),
|
|
encode_num_det(NumMutatorPreds, NumMutatorPredsBytes),
|
|
encode_num_det(NumDestructorPreds, NumDestructorPredsBytes),
|
|
list.map(encode_oisu_proc(ModuleInfo), CreatorPreds,
|
|
CreatorPredBytes),
|
|
list.map(encode_oisu_proc(ModuleInfo), MutatorPreds,
|
|
MutatorPredBytes),
|
|
list.map(encode_oisu_proc(ModuleInfo), DestructorPreds,
|
|
DestructorPredBytes),
|
|
|
|
HeadBytes = cord.from_list(TypeCtorNameBytes)
|
|
++ cord.from_list(NumCreatorPredsBytes)
|
|
++ cord.cord_list_to_cord(CreatorPredBytes)
|
|
++ cord.from_list(NumMutatorPredsBytes)
|
|
++ cord.cord_list_to_cord(MutatorPredBytes)
|
|
++ cord.from_list(NumDestructorPredsBytes)
|
|
++ cord.cord_list_to_cord(DestructorPredBytes),
|
|
|
|
NumOISUTypes = 1 + TailNumOISUTypes,
|
|
Bytes = HeadBytes ++ TailBytes
|
|
else
|
|
NumOISUTypes = TailNumOISUTypes,
|
|
Bytes = TailBytes
|
|
).
|
|
|
|
:- pred encode_oisu_proc(module_info::in, pred_id::in, cord(int)::out) is det.
|
|
|
|
encode_oisu_proc(ModuleInfo, PredId, BytesCord) :-
|
|
module_info_pred_info(ModuleInfo, PredId, PredInfo),
|
|
pred_info_get_proc_table(PredInfo, ProcTable),
|
|
map.to_assoc_list(ProcTable, Procs),
|
|
( if Procs = [ProcId - _ProcInfo] then
|
|
ProcLabel = make_proc_label(ModuleInfo, PredId, ProcId),
|
|
encode_string_proc_label(ProcLabel, BytesCord)
|
|
else
|
|
unexpected($pred, "OISU pred should have exactly one proc")
|
|
).
|
|
|
|
:- pred encode_string_proc_label(proc_label::in, cord(int)::out) is det.
|
|
|
|
encode_string_proc_label(ProcLabel, BytesCord) :-
|
|
(
|
|
ProcLabel = ordinary_proc_label(DefModuleName, PredOrFunc,
|
|
DeclModuleName, PredName, Arity, ModeNum),
|
|
(
|
|
PredOrFunc = pf_predicate,
|
|
KindByte = string_proclabel_kind_user_predicate
|
|
;
|
|
PredOrFunc = pf_function,
|
|
KindByte = string_proclabel_kind_user_function
|
|
),
|
|
encode_len_string(sym_name_to_string(DeclModuleName),
|
|
DeclModuleNameBytes),
|
|
encode_len_string(sym_name_to_string(DefModuleName),
|
|
DefModuleNameBytes),
|
|
encode_len_string(PredName, PredNameBytes),
|
|
encode_num_det(Arity, ArityBytes),
|
|
encode_num_det(ModeNum, ModeNumBytes),
|
|
BytesCord = cord.from_list([KindByte | DeclModuleNameBytes])
|
|
++ cord.from_list(DefModuleNameBytes)
|
|
++ cord.from_list(PredNameBytes)
|
|
++ cord.from_list(ArityBytes)
|
|
++ cord.from_list(ModeNumBytes)
|
|
;
|
|
ProcLabel = special_proc_label(DefModuleName, SpecialPredId,
|
|
TypeModuleName, TypeName, TypeArity, ModeNum),
|
|
TypeCtor = type_ctor(qualified(TypeModuleName, TypeName), TypeArity),
|
|
% XXX The long names generated by uci_pred_name, including the __s,
|
|
% are wasted here. All we should need is a single byte, which is
|
|
% one of 'u', 'c' or 'i', or an equivalent enum.
|
|
PredName = uci_pred_name(SpecialPredId, TypeCtor),
|
|
|
|
KindByte = string_proclabel_kind_special,
|
|
encode_len_string(TypeName, TypeNameBytes),
|
|
encode_len_string(sym_name_to_string(TypeModuleName),
|
|
TypeModuleNameBytes),
|
|
encode_len_string(sym_name_to_string(DefModuleName),
|
|
DefModuleNameBytes),
|
|
encode_len_string(PredName, PredNameBytes),
|
|
encode_num_det(TypeArity, TypeArityBytes),
|
|
encode_num_det(ModeNum, ModeNumBytes),
|
|
BytesCord = cord.from_list([KindByte | TypeNameBytes])
|
|
++ cord.from_list(TypeModuleNameBytes)
|
|
++ cord.from_list(DefModuleNameBytes)
|
|
++ cord.from_list(PredNameBytes)
|
|
++ cord.from_list(TypeArityBytes)
|
|
++ cord.from_list(ModeNumBytes)
|
|
).
|
|
|
|
% The definitions of these functions should be kept in sync with
|
|
% the definition of the MR_ProcLabelToken type in mercury_deep_profiling.h.
|
|
%
|
|
:- func string_proclabel_kind_user_predicate = int.
|
|
:- func string_proclabel_kind_user_function = int.
|
|
:- func string_proclabel_kind_special = int.
|
|
|
|
string_proclabel_kind_user_predicate = 0.
|
|
string_proclabel_kind_user_function = 1.
|
|
string_proclabel_kind_special = 2.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
represent_proc_as_bytecodes(HeadVars, Goal, InstMap0, VarTable, VarNumMap,
|
|
ModuleInfo, IncludeVarNameTable, IncludeVarTypes, ProcDetism,
|
|
!StringTable, !TypeTable, ProcRepBytes) :-
|
|
Goal = hlds_goal(_, GoalInfo),
|
|
Context = goal_info_get_context(GoalInfo),
|
|
FileName = term_context.context_file(Context),
|
|
represent_var_table_as_bytecode(IncludeVarNameTable, IncludeVarTypes,
|
|
VarTable, VarNumMap, VarNumRep, VarNameTableBytes,
|
|
!StringTable, !TypeTable),
|
|
Info = prog_rep_info(ModuleInfo, FileName, VarTable, VarNumMap, VarNumRep,
|
|
expect_no_par_conjs),
|
|
InstmapDelta = goal_info_get_instmap_delta(GoalInfo),
|
|
|
|
encode_string_as_table_offset(FileName, FileNameBytes, !StringTable),
|
|
goal_to_byte_list(Goal, InstMap0, Info, GoalBytes, !StringTable),
|
|
DetismByte = represent_determinism(ProcDetism),
|
|
ProcRepBytes0 = FileNameBytes ++ VarNameTableBytes ++
|
|
encode_head_vars_func(Info, InstMap0, InstmapDelta, HeadVars) ++
|
|
GoalBytes ++ [DetismByte],
|
|
encode_int32_det(list.length(ProcRepBytes0) + 4, LimitBytes),
|
|
ProcRepBytes = LimitBytes ++ ProcRepBytes0.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Create bytecodes for the variable name table.
|
|
%
|
|
% If a variable name table is not requested, an empty table is created.
|
|
% The variable name table also includes information about the
|
|
% representation of variable numbers within the bytecode.
|
|
%
|
|
% The representation of variables and the variable name table
|
|
% restricts the number of possible variables in a procedure to 2^31.
|
|
%
|
|
:- pred represent_var_table_as_bytecode(maybe_include_var_name_table::in,
|
|
maybe_include_var_types::in, var_table::in,
|
|
var_num_map::in, var_num_rep::out, list(int)::out,
|
|
string_table_info::in, string_table_info::out,
|
|
type_table_info::in, type_table_info::out) is det.
|
|
|
|
represent_var_table_as_bytecode(IncludeVarNameTable, IncludeVarTypes,
|
|
VarTable, VarNumMap, VarNumRep, Bytes, !StringTable, !TypeTable) :-
|
|
map.foldl(max_var_num, VarNumMap, 0) = MaxVarNum,
|
|
( if MaxVarNum =< 127 then
|
|
VarNumRep = var_num_1_byte
|
|
else if MaxVarNum =< 32767 then
|
|
VarNumRep = var_num_2_bytes
|
|
else
|
|
VarNumRep = var_num_4_bytes
|
|
),
|
|
var_flag_byte(VarNumRep, IncludeVarNameTable, IncludeVarTypes, FlagByte),
|
|
(
|
|
IncludeVarNameTable = include_var_name_table,
|
|
(
|
|
IncludeVarTypes = do_not_include_var_types,
|
|
% It is more efficient to make the switch over the representation
|
|
% size just once here, than to make it when representing each
|
|
% variable.
|
|
(
|
|
VarNumRep = var_num_1_byte,
|
|
map.foldl3(encode_var_name_table_entry_1_byte, VarNumMap,
|
|
0, NumVars, [], VarNameTableEntriesBytes, !StringTable)
|
|
;
|
|
VarNumRep = var_num_2_bytes,
|
|
map.foldl3(encode_var_name_table_entry_2_byte, VarNumMap,
|
|
0, NumVars, [], VarNameTableEntriesBytes, !StringTable)
|
|
;
|
|
VarNumRep = var_num_4_bytes,
|
|
map.foldl3(encode_var_name_table_entry_4_byte, VarNumMap,
|
|
0, NumVars, [], VarNameTableEntriesBytes, !StringTable)
|
|
)
|
|
;
|
|
IncludeVarTypes = include_var_types,
|
|
map.foldl4(encode_var_name_type_table_entry(VarNumRep, VarTable),
|
|
VarNumMap, 0, NumVars,
|
|
[], VarNameTableEntriesBytes, !StringTable, !TypeTable)
|
|
),
|
|
encode_num_det(NumVars, NumVarsBytes),
|
|
Bytes = [FlagByte] ++ NumVarsBytes ++ VarNameTableEntriesBytes
|
|
;
|
|
IncludeVarNameTable = do_not_include_var_name_table,
|
|
expect(unify(IncludeVarTypes, do_not_include_var_types), $pred,
|
|
"IncludeVarTypes but not IncludeVarNameTable"),
|
|
Bytes = [FlagByte]
|
|
).
|
|
|
|
:- func max_var_num(prog_var, pair(int, string), int) = int.
|
|
|
|
max_var_num(_, VarNum1 - _, VarNum2) = Max :-
|
|
Max = max(VarNum1, VarNum2).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% To avoid repeated tests of the size of variable representations, we have
|
|
% a specialized version for each different variable number encoding size.
|
|
%
|
|
% Some variables that the compiler creates are named automatically,
|
|
% these and unnamed variables should not be included in the variable
|
|
% name table.
|
|
%
|
|
|
|
:- pred encode_var_name_table_entry_1_byte(prog_var::in, pair(int, string)::in,
|
|
int::in, int::out, list(int)::in, list(int)::out,
|
|
string_table_info::in, string_table_info::out) is det.
|
|
|
|
encode_var_name_table_entry_1_byte(_ProgVar, VarNum - VarName,
|
|
!NumVars, !VarNameTableBytes, !StringTable) :-
|
|
( if is_compiler_introduced_varname(VarName) then
|
|
true
|
|
else
|
|
!:NumVars = !.NumVars + 1,
|
|
VarBytes = [VarNum],
|
|
encode_string_as_table_offset(VarName, VarNameBytes, !StringTable),
|
|
!:VarNameTableBytes = VarBytes ++ VarNameBytes ++ !.VarNameTableBytes
|
|
).
|
|
|
|
:- pred encode_var_name_table_entry_2_byte(prog_var::in, pair(int, string)::in,
|
|
int::in, int::out, list(int)::in, list(int)::out,
|
|
string_table_info::in, string_table_info::out) is det.
|
|
|
|
encode_var_name_table_entry_2_byte(_ProgVar, VarNum - VarName,
|
|
!NumVars, !VarNameTableBytes, !StringTable) :-
|
|
( if is_compiler_introduced_varname(VarName) then
|
|
true
|
|
else
|
|
!:NumVars = !.NumVars + 1,
|
|
encode_short_det(VarNum, VarBytes),
|
|
encode_string_as_table_offset(VarName, VarNameBytes, !StringTable),
|
|
!:VarNameTableBytes = VarBytes ++ VarNameBytes ++ !.VarNameTableBytes
|
|
).
|
|
|
|
:- pred encode_var_name_table_entry_4_byte(prog_var::in, pair(int, string)::in,
|
|
int::in, int::out, list(int)::in, list(int)::out,
|
|
string_table_info::in, string_table_info::out) is det.
|
|
|
|
encode_var_name_table_entry_4_byte(_ProgVar, VarNum - VarName,
|
|
!NumVars, !VarNameTableBytes, !StringTable) :-
|
|
( if is_compiler_introduced_varname(VarName) then
|
|
true
|
|
else
|
|
!:NumVars = !.NumVars + 1,
|
|
encode_int32_det(VarNum, VarBytes),
|
|
encode_string_as_table_offset(VarName, VarNameBytes, !StringTable),
|
|
!:VarNameTableBytes = VarBytes ++ VarNameBytes ++ !.VarNameTableBytes
|
|
).
|
|
|
|
:- pred encode_var_name_type_table_entry(var_num_rep::in, var_table::in,
|
|
prog_var::in, pair(int, string)::in, int::in, int::out,
|
|
list(int)::in, list(int)::out,
|
|
string_table_info::in, string_table_info::out,
|
|
type_table_info::in, type_table_info::out) is det.
|
|
|
|
encode_var_name_type_table_entry(VarNumRep, VarTable, Var, VarNum - VarName,
|
|
!NumVars, !VarNameTableBytes, !StringTable, !TypeTable) :-
|
|
!:NumVars = !.NumVars + 1,
|
|
lookup_var_type(VarTable, Var, Type),
|
|
(
|
|
VarNumRep = var_num_1_byte,
|
|
VarBytes = [VarNum]
|
|
;
|
|
VarNumRep = var_num_2_bytes,
|
|
encode_short_det(VarNum, VarBytes)
|
|
;
|
|
VarNumRep = var_num_4_bytes,
|
|
encode_int32_det(VarNum, VarBytes)
|
|
),
|
|
encode_string_as_table_offset(VarName, VarNameBytes, !StringTable),
|
|
encode_type_as_table_ref(Type, TypeBytes, !StringTable, !TypeTable),
|
|
!:VarNameTableBytes = VarBytes ++ VarNameBytes ++ TypeBytes
|
|
++ !.VarNameTableBytes.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred is_compiler_introduced_varname(string::in) is semidet.
|
|
|
|
is_compiler_introduced_varname(VarName) :-
|
|
(
|
|
( VarName = ""
|
|
; VarName = "ProcStaticLayout"
|
|
; VarName = "TopCSD"
|
|
; VarName = "MiddleCSD"
|
|
; VarName = "ActivationPtr"
|
|
; VarName = "SiteNum"
|
|
; VarName = "MethodNum"
|
|
)
|
|
;
|
|
some [Prefix] (
|
|
( 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_info::in, string_table_info::out) is det.
|
|
|
|
goal_to_byte_list(Goal, InstMap0, Info, Bytes, !StringTable) :-
|
|
goal_to_goal_rep(Info, InstMap0, Goal, GoalRep),
|
|
encode_goal_rep(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, Goals0),
|
|
FlattenParConjs = Info ^ pri_flatten_par_conjs,
|
|
(
|
|
FlattenParConjs = flatten_par_conjs,
|
|
% Flatten all conjunction types, the current conjunction may be a
|
|
% plain conjunction with par conjunctions in it, or vice-versa.
|
|
flatten_conj(Goals0, Goals)
|
|
;
|
|
FlattenParConjs = expect_no_par_conjs,
|
|
Goals = Goals0,
|
|
expect(unify(ConjType, plain_conj), $pred,
|
|
"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),
|
|
apply_instmap_delta(InstmapDelta, Instmap0, 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),
|
|
( if InnerDetism = OuterDetism then
|
|
MaybeCut = scope_is_no_cut
|
|
else
|
|
MaybeCut = scope_is_cut
|
|
),
|
|
GoalExprRep = scope_rep(SubGoalRep, MaybeCut)
|
|
;
|
|
( GoalExpr = unify(_, _, _, _, _)
|
|
; GoalExpr = generic_call(_, _, _, _, _)
|
|
; GoalExpr = plain_call(_, _, _, _, _, _)
|
|
; GoalExpr = call_foreign_proc(_, _, _, _, _, _, _)
|
|
),
|
|
goal_info_to_atomic_goal_rep_fields(GoalInfo, Instmap0, Info,
|
|
FileName, LineNo, BoundVars),
|
|
BoundVarsRep = map(var_to_var_rep(Info), BoundVars),
|
|
(
|
|
GoalExpr = unify(_, _, _, Unification, _),
|
|
(
|
|
Unification = assign(Target, Source),
|
|
AtomicGoalRep = unify_assign_rep(
|
|
var_to_var_rep(Info, Target),
|
|
var_to_var_rep(Info, Source))
|
|
;
|
|
(
|
|
Unification = construct(Var, ConsId, ArgVars, ArgModes,
|
|
_, _, _)
|
|
;
|
|
Unification = deconstruct(Var, ConsId, ArgVars, ArgModes,
|
|
_, _)
|
|
),
|
|
VarRep = var_to_var_rep(Info, Var),
|
|
ConsIdRep = cons_id_rep(ConsId),
|
|
ArgVarsRep = list.map(var_to_var_rep(Info), ArgVars),
|
|
filter_input_args(Info, ArgModes, ArgVars, MaybeArgVars),
|
|
MaybeArgVarsRep = list.map(map_maybe(var_to_var_rep(Info)),
|
|
MaybeArgVars),
|
|
(
|
|
Unification = construct(_, _, _, _, _, _, _),
|
|
( if lhs_finals_are_ground(Info, ArgVars, ArgModes) then
|
|
AtomicGoalRep = unify_construct_rep(VarRep, ConsIdRep,
|
|
ArgVarsRep)
|
|
else
|
|
AtomicGoalRep = partial_construct_rep(VarRep,
|
|
ConsIdRep, MaybeArgVarsRep)
|
|
)
|
|
;
|
|
Unification = deconstruct(_, _, _, _, _, _),
|
|
( if list.member(Var, BoundVars) then
|
|
AtomicGoalRep = partial_deconstruct_rep(VarRep,
|
|
ConsIdRep, MaybeArgVarsRep)
|
|
else
|
|
AtomicGoalRep = unify_deconstruct_rep(VarRep,
|
|
ConsIdRep, ArgVarsRep)
|
|
)
|
|
)
|
|
;
|
|
Unification = simple_test(Var1, Var2),
|
|
AtomicGoalRep = unify_simple_test_rep(
|
|
var_to_var_rep(Info, Var1),
|
|
var_to_var_rep(Info, Var2))
|
|
;
|
|
Unification = complicated_unify(_, _, _),
|
|
unexpected($pred, "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, method_proc_num(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(_),
|
|
( if ArgsRep = [InputArgRep, OutputArgRep] then
|
|
AtomicGoalRep = cast_rep(OutputArgRep, InputArgRep)
|
|
else
|
|
unexpected($pred, "cast/coerce 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)
|
|
)
|
|
;
|
|
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)
|
|
),
|
|
GoalExprRep = atomic_goal_rep(FileName, LineNo, BoundVarsRep,
|
|
AtomicGoalRep)
|
|
;
|
|
GoalExpr = shorthand(_),
|
|
% These should have been expanded out by now.
|
|
unexpected($pred, "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 ^ hg_info,
|
|
InstmapDelta = goal_info_get_instmap_delta(GoalInfo),
|
|
apply_instmap_delta(InstmapDelta, Instmap0, 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 encode_goal_rep(prog_rep_info::in, goal_rep::in, list(int)::out,
|
|
string_table_info::in, string_table_info::out) is det.
|
|
|
|
encode_goal_rep(Info, goal_rep(GoalExpr, Detism, _), Bytes, !StringTable) :-
|
|
(
|
|
GoalExpr = conj_rep(GoalReps),
|
|
map_foldl(encode_goal_rep(Info), GoalReps, ConjBytesList,
|
|
!StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_conj)] ++
|
|
encode_length_func(GoalReps) ++ condense(ConjBytesList)
|
|
;
|
|
GoalExpr = disj_rep(GoalReps),
|
|
map_foldl(encode_goal_rep(Info), GoalReps, DisjBytesList,
|
|
!StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_disj)] ++
|
|
encode_length_func(GoalReps) ++ condense(DisjBytesList)
|
|
;
|
|
GoalExpr = negation_rep(SubGoal),
|
|
encode_goal_rep(Info, SubGoal, SubGoalBytes, !StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_neg)] ++ SubGoalBytes
|
|
;
|
|
GoalExpr = ite_rep(Cond, Then, Else),
|
|
encode_goal_rep(Info, Cond, CondBytes, !StringTable),
|
|
encode_goal_rep(Info, Then, ThenBytes, !StringTable),
|
|
encode_goal_rep(Info, Else, ElseBytes, !StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_ite)] ++
|
|
CondBytes ++ ThenBytes ++ ElseBytes
|
|
;
|
|
GoalExpr = atomic_goal_rep(FileName, Line, BoundVars, AtomicGoalRep),
|
|
encode_string_as_table_offset(FileName, FileNameBytes, !StringTable),
|
|
AtomicBytes = FileNameBytes ++ encode_lineno_func(Line) ++
|
|
encode_var_reps_func(Info, BoundVars),
|
|
(
|
|
AtomicGoalRep = unify_assign_rep(Target, Source),
|
|
ExprBytes = [goal_type_to_byte(goal_assign)] ++
|
|
encode_var_rep_func(Info, Target) ++
|
|
encode_var_rep_func(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 = encode_var_reps_func(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 = encode_maybe_var_reps_func(Info, MaybeArgs)
|
|
),
|
|
encode_string_as_table_offset(ConsId, ConsIdBytes, !StringTable),
|
|
VarBytes = encode_var_rep_func(Info, Var),
|
|
ExprBytes = [AtomicTypeByte] ++ VarBytes ++ ConsIdBytes ++
|
|
ArgsBytes ++ AtomicBytes
|
|
;
|
|
AtomicGoalRep = unify_simple_test_rep(Var1, Var2),
|
|
ExprBytes = [goal_type_to_byte(goal_simple_test)] ++
|
|
encode_var_rep_func(Info, Var1) ++
|
|
encode_var_rep_func(Info, Var2) ++
|
|
AtomicBytes
|
|
;
|
|
AtomicGoalRep = higher_order_call_rep(PredVar, Args),
|
|
ExprBytes = [goal_type_to_byte(goal_ho_call)] ++
|
|
encode_var_rep_func(Info, PredVar) ++
|
|
encode_var_reps_func(Info, Args) ++
|
|
AtomicBytes
|
|
;
|
|
AtomicGoalRep = method_call_rep(Var, MethodNum, Args),
|
|
ExprBytes = [goal_type_to_byte(goal_method_call)] ++
|
|
encode_var_rep_func(Info, Var) ++
|
|
encode_method_num_func(MethodNum) ++
|
|
encode_var_reps_func(Info, Args) ++
|
|
AtomicBytes
|
|
;
|
|
AtomicGoalRep = event_call_rep(EventName, Args),
|
|
encode_string_as_table_offset(EventName, EventNameBytes,
|
|
!StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_event_call)] ++
|
|
EventNameBytes ++
|
|
encode_var_reps_func(Info, Args) ++
|
|
AtomicBytes
|
|
;
|
|
AtomicGoalRep = cast_rep(Target, Source),
|
|
ExprBytes = [goal_type_to_byte(goal_cast)] ++
|
|
encode_var_rep_func(Info, Target) ++
|
|
encode_var_rep_func(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
|
|
),
|
|
encode_string_as_table_offset(ModuleName, ModuleNameBytes,
|
|
!StringTable),
|
|
encode_string_as_table_offset(PredName, PredNameBytes,
|
|
!StringTable),
|
|
ExprBytes = [goal_type_to_byte(CallType)] ++
|
|
ModuleNameBytes ++
|
|
PredNameBytes ++
|
|
encode_var_reps_func(Info, Args) ++
|
|
AtomicBytes
|
|
;
|
|
AtomicGoalRep = pragma_foreign_code_rep(Args),
|
|
ExprBytes = [goal_type_to_byte(goal_foreign)] ++
|
|
encode_var_reps_func(Info, Args) ++ AtomicBytes
|
|
)
|
|
;
|
|
GoalExpr = switch_rep(SwitchVar, CanFail, Cases),
|
|
list.map_foldl(encode_case_rep(Info), Cases, CasesBytesList,
|
|
!StringTable),
|
|
can_fail_byte(CanFail, CanFailByte),
|
|
ExprBytes = [goal_type_to_byte(goal_switch)] ++
|
|
[CanFailByte] ++
|
|
encode_var_rep_func(Info, SwitchVar) ++
|
|
encode_length_func(Cases) ++ list.condense(CasesBytesList)
|
|
;
|
|
GoalExpr = scope_rep(SubGoal, MaybeCut),
|
|
cut_byte(MaybeCut, MaybeCutByte),
|
|
encode_goal_rep(Info, SubGoal, SubGoalBytes, !StringTable),
|
|
ExprBytes = [goal_type_to_byte(goal_scope)] ++ [MaybeCutByte] ++
|
|
SubGoalBytes
|
|
),
|
|
determinism_representation(Detism, DetismByte),
|
|
Bytes = ExprBytes ++ [DetismByte].
|
|
|
|
:- pred encode_case_rep(prog_rep_info::in, case_rep::in, list(int)::out,
|
|
string_table_info::in, string_table_info::out) is det.
|
|
|
|
encode_case_rep(Info, Case, Bytes, !StringTable) :-
|
|
Case = case_rep(MainConsId, OtherConsIds, Goal),
|
|
encode_goal_rep(Info, Goal, GoalBytes, !StringTable),
|
|
encode_cons_id_and_arity_rep(MainConsId, MainConsIdBytes, !StringTable),
|
|
map_foldl(encode_cons_id_and_arity_rep,
|
|
OtherConsIds, OtherConsIdsByteLists, !StringTable),
|
|
Bytes = MainConsIdBytes ++ encode_length_func(OtherConsIds) ++
|
|
list.condense(OtherConsIdsByteLists) ++ GoalBytes.
|
|
|
|
:- pred lhs_finals_are_ground(prog_rep_info::in,
|
|
list(prog_var)::in, list(unify_mode)::in) is semidet.
|
|
|
|
lhs_finals_are_ground(_, [], []).
|
|
lhs_finals_are_ground(_, [], [_ | _]) :-
|
|
unexpected($pred, "list length mismatch").
|
|
lhs_finals_are_ground(_, [_ | _], []) :-
|
|
unexpected($pred, "list length mismatch").
|
|
lhs_finals_are_ground(Info, [Var | Vars], [UnifyMode | UnifyModes]) :-
|
|
VarTable = Info ^ pri_var_table,
|
|
lookup_var_type(VarTable, Var, Type),
|
|
UnifyMode = unify_modes_li_lf_ri_rf(_, LHSFinalInst, _, _),
|
|
ModuleInfo = Info ^ pri_module_info,
|
|
inst_is_ground(ModuleInfo, Type, LHSFinalInst),
|
|
lhs_finals_are_ground(Info, Vars, UnifyModes).
|
|
|
|
:- pred rhs_is_input(prog_rep_info::in, unify_mode::in) is semidet.
|
|
|
|
rhs_is_input(Info, UnifyMode) :-
|
|
UnifyMode = unify_modes_li_lf_ri_rf(_, _, RHSInitInst, _),
|
|
init_inst_is_input(Info ^ pri_module_info, RHSInitInst).
|
|
|
|
:- pred filter_input_args(prog_rep_info::in, list(unify_mode)::in,
|
|
list(prog_var)::in, list(maybe(prog_var))::out) is det.
|
|
|
|
filter_input_args(_, [], [], []).
|
|
filter_input_args(_, [], [_ | _], _) :-
|
|
unexpected($pred, "mismatched lists").
|
|
filter_input_args(_, [_ | _], [], _) :-
|
|
unexpected($pred, "mismatched lists").
|
|
filter_input_args(Info, [Mode | Modes], [Var | Vars],
|
|
[MaybeVar | MaybeVars]) :-
|
|
( if rhs_is_input(Info, Mode) then
|
|
MaybeVar = yes(Var)
|
|
else
|
|
MaybeVar = no
|
|
),
|
|
filter_input_args(Info, Modes, Vars, MaybeVars).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- 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),
|
|
FileName0 = term_context.context_file(Context),
|
|
( if FileName0 = Info ^ pri_filename then
|
|
FileName = ""
|
|
else
|
|
FileName = FileName0
|
|
),
|
|
LineNo = term_context.context_line(Context),
|
|
InstmapDelta = goal_info_get_instmap_delta(GoalInfo),
|
|
instmap_delta_changed_vars(InstmapDelta, ChangedVarsSet),
|
|
set_of_var.to_sorted_list(ChangedVarsSet, ChangedVars),
|
|
ModuleInfo = Info ^ pri_module_info,
|
|
VarTable = Info ^ pri_var_table,
|
|
list.negated_filter(
|
|
var_is_ground_in_instmap(ModuleInfo, VarTable, Instmap0),
|
|
ChangedVars, BoundVars).
|
|
|
|
:- pred encode_cons_id_and_arity_rep(cons_id_arity_rep::in, list(int)::out,
|
|
string_table_info::in, string_table_info::out) is det.
|
|
|
|
encode_cons_id_and_arity_rep(ConsIdArity, ConsIdBytes, !StringTable) :-
|
|
ConsIdArity = cons_id_arity_rep(ConsId, Arity),
|
|
encode_string_as_table_offset(ConsId, FunctorBytes, !StringTable),
|
|
encode_short_det(Arity, ArityBytes),
|
|
ConsIdBytes = FunctorBytes ++ ArityBytes.
|
|
|
|
:- func cons_id_rep(cons_id) = string.
|
|
|
|
cons_id_rep(du_data_ctor(du_ctor(SymName, _, _))) =
|
|
prog_rep.sym_base_name_to_string(SymName).
|
|
cons_id_rep(tuple_cons(_)) = "{}".
|
|
cons_id_rep(some_int_const(IntConst)) = Str :-
|
|
int_const_to_string_and_suffix(IntConst, Str, _Suffix).
|
|
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(IDCKind)) =
|
|
impl_defined_const_kind_to_str(IDCKind).
|
|
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(type_info_const(_)) = "$type_info_const".
|
|
cons_id_rep(typeclass_info_const(_)) = "$typeclass_info_const".
|
|
cons_id_rep(ground_term_const(_, _)) = "$ground_term_const".
|
|
cons_id_rep(tabling_info_const(_)) = "$tabling_info_const".
|
|
cons_id_rep(table_io_entry_desc(_)) = "$table_io_entry_desc".
|
|
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 encode_string_as_table_offset(string::in, list(int)::out,
|
|
string_table_info::in, string_table_info::out) is det.
|
|
|
|
encode_string_as_table_offset(String, Bytes, !StringTable) :-
|
|
lookup_string_in_table(String, Index, !StringTable),
|
|
encode_int32_det(Index, Bytes).
|
|
|
|
:- pred encode_type_as_table_ref(mer_type::in, list(int)::out,
|
|
string_table_info::in, string_table_info::out,
|
|
type_table_info::in, type_table_info::out) is det.
|
|
|
|
encode_type_as_table_ref(Type, Bytes, !StringTable, !TypeTable) :-
|
|
lookup_type_in_table(Type, Index, !StringTable, !TypeTable),
|
|
encode_num_det(Index, Bytes).
|
|
|
|
:- func encode_var_reps_func(prog_rep_info, list(var_rep)) = list(int).
|
|
|
|
encode_var_reps_func(Info, Vars) =
|
|
encode_length_func(Vars) ++
|
|
list.condense(list.map(encode_var_rep_func(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 encode_var_rep_func(prog_rep_info, var_rep) = list(int).
|
|
|
|
encode_var_rep_func(Info, Var) = Bytes :-
|
|
VarNumRep = Info ^ pri_var_num_rep,
|
|
(
|
|
VarNumRep = var_num_1_byte,
|
|
Bytes = [Var]
|
|
;
|
|
VarNumRep = var_num_2_bytes,
|
|
encode_short_det(Var, Bytes)
|
|
;
|
|
VarNumRep = var_num_4_bytes,
|
|
encode_int32_det(Var, Bytes)
|
|
).
|
|
|
|
:- func encode_maybe_var_reps_func(prog_rep_info, list(maybe(var_rep))) =
|
|
list(int).
|
|
|
|
encode_maybe_var_reps_func(Info, Vars) =
|
|
encode_length_func(Vars) ++
|
|
list.condense(list.map(encode_maybe_var_rep_func(Info), Vars)).
|
|
|
|
:- func encode_maybe_var_rep_func(prog_rep_info, maybe(var_rep)) = list(int).
|
|
|
|
encode_maybe_var_rep_func(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 | encode_var_rep_func(Info, Var)]
|
|
;
|
|
MaybeVar = no,
|
|
Bytes = [0]
|
|
).
|
|
|
|
:- func encode_head_vars_func(prog_rep_info, instmap, instmap_delta,
|
|
list(prog_var)) = list(int).
|
|
|
|
encode_head_vars_func(Info, InitialInstmap, InstmapDelta, Vars) =
|
|
encode_length_func(Vars) ++
|
|
list.condense(list.map(
|
|
encode_head_var_func(Info, InitialInstmap, InstmapDelta), Vars)).
|
|
|
|
:- func encode_head_var_func(prog_rep_info, instmap, instmap_delta,
|
|
prog_var) = list(int).
|
|
|
|
encode_head_var_func(Info, InitialInstmap, InstmapDelta, Var) = Bytes :-
|
|
encode_var_rep_func(Info, var_to_var_rep(Info, Var)) = VarBytes,
|
|
ModuleInfo = Info ^ pri_module_info,
|
|
instmap_lookup_var(InitialInstmap, Var, InitialInst),
|
|
( if instmap_delta_search_var(InstmapDelta, Var, FinalInstPrime) then
|
|
FinalInst = FinalInstPrime
|
|
else
|
|
% If the variable is not in the instmap delta, then its instantiation
|
|
% cannot possibly change.
|
|
FinalInst = InitialInst
|
|
),
|
|
VarTable = Info ^ pri_var_table,
|
|
lookup_var_type(VarTable, Var, Type),
|
|
Bytes = VarBytes ++
|
|
[inst_to_byte(ModuleInfo, Type, InitialInst),
|
|
inst_to_byte(ModuleInfo, Type, FinalInst)].
|
|
|
|
:- func inst_to_byte(module_info, mer_type, mer_inst) = int.
|
|
|
|
inst_to_byte(ModuleInfo, Type, MerInst) = Byte :-
|
|
( if MerInst = free then
|
|
InstRep = ir_free_rep
|
|
else if inst_is_ground(ModuleInfo, Type, MerInst) then
|
|
InstRep = ir_ground_rep
|
|
else
|
|
InstRep = ir_other_rep
|
|
),
|
|
inst_representation(InstRep, Byte).
|
|
|
|
:- func encode_length_func(list(T)) = list(int).
|
|
|
|
encode_length_func(List) = Bytes :-
|
|
encode_int32_det(list.length(List), Bytes).
|
|
|
|
:- func encode_lineno_func(int) = list(int).
|
|
|
|
encode_lineno_func(VarNum) = Bytes :-
|
|
encode_int32_det(VarNum, Bytes).
|
|
|
|
:- func encode_method_num_func(int) = list(int).
|
|
|
|
encode_method_num_func(VarNum) = Bytes :-
|
|
encode_short_det(VarNum, Bytes).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module ll_backend.prog_rep.
|
|
%-----------------------------------------------------------------------------%
|