Files
mercury/compiler/prog_rep.m
Zoltan Somogyi 2d0bfc0674 The algorithm that decides whether the order independent state update
Estimated hours taken: 120
Branches: main

The algorithm that decides whether the order independent state update
transformation is applicable in a given module needs access to the list
of oisu pragmas in that module, and to information about the types
of variables in the procedures named in those pragmas. This diff
puts this information in Deep.procrep files, to make them available
to the autoparallelization feedback program, to which that algorithm
will later be added.

Compilers that have this diff will generate Deep.procrep files in a new,
slightly different format, but the deep profiler will be able to read
Deep.procrep files not just in the new format, but in the old format as well.

runtime/mercury_stack_layout.h:
	Add to module layout structures the fields holding the new information
	we want to put into Deep.procrep files. This means three things:

	- a bytecode array in module layout structures encoding the list
	  of oisu pragmas in the module;
	- additions to the bytecode arrays in procedure layout structures
	  mapping the procedure's variables to their types; and
	- a bytecode array containing the encoded versions of those types
	  themselves in the module layout structure. This allows us to
	  represent each type used in the module just once.

	Since there is now information in module layout structures that
	is needed only for deep profiling, as well as information that is
	needed only for debugging, the old arrangement that split a module's
	information between two structures, MR_ModuleLayout (debug specific
	info) and MR_ModuleCommonLayout (info used by both debugging and
	profiling), is no longer approriate. We could add a third structure
	containing profiling-specific info, but it is simpler to move
	all the info into just one structure, some of whose fields
	may not be used. This wastes only a few words of memory per module,
	but allows the runtime system to avoid unnecessary indirections.

runtime/mercury_types.h:
	Remove the type synonym for the deleted type.

runtime/mercury_grade.h:
	The change in mercury_stack_layout.h destroys binary compatibility
	with previous versions of Mercury for debug and deep profiling grades,
	so bump their grade-component-specific version numbers.

runtime/mercury_deep_profiling.c:
	Write out the information in the new fields in module layout
	structures, if they are filled in.

	Since this changes the format of the Deep.procrep file, bump
	its version number.

runtime/mercury_deep_profiling.h:
runtime/mercury_stack_layout.c:
	Conform to the change to mercury_stack_layout.h.

mdbcomp/program_representation.m:
	Add to module representations information about the oisu pragmas
	defined in that module, and the type table of the module.
	Optionally add to procedure representations a map mapping
	the variables of the procedure to their types.

	Rename the old var_table type to be the var_name_table type,
	since it contains just names. Make the var to type map separate,
	since it will be there only for selected procedures.

	Modify the predicates reading in module and procedure representations
	to allow them to read in the new representation, while still accepting
	the old one. Use the version number in the Deep.procrep file to decide
	which format to expect.

mdbcomp/rtti_access.m:
	Add functions to encode the data representations that this module
	also decodes.

	Conform to the changes above.

mdbcomp/feedback.automatic_parallelism.m:
	Conform the changes above.

mdbcomp/prim_data.m:
	Fix layout.

compiler/layout.m:
	Update the compiler's representation of layout structures
	to conform to the change to runtime/mercury_stack_layout.h.

compiler/layout_out.m:
	Output the new parts of module layout structures.

compiler/opt_debug.m:
	Allow the debugging of code referring to the new parts of
	module layout structures.

compiler/llds_out_file.m:
	Conform to the move to a single module layout structure.

compiler/prog_rep_tables.m:
	This new module provided mechanisms for building the string table
	and the type table components of module layouts. The string table
	part is old (it is moved here from stack_layout.m); the type table
	part is new.

	Putting this code in a module of its own allows us to remove
	a circular dependency between prog_rep.m and stack_layout.m;
	instead, both now just depend on prog_rep_tables.m.

compiler/ll_backend.m:
	Add the new module.

compiler/notes/compiler_design.html:
	Describe the new module.

compiler/prog_rep.m:
	When generating the representation of a module for deep profiling,
	include the information needed by the order independent state update
	analysis: the list of oisu pragmas in the module, if any, and
	information about the types of variables in selected procedures.

	To avoid having these additions increasing the size of the bytecode
	representation too much, convert some fixed 32 bit numbers in the
	bytecode to use variable sized numbers, which will usually be 8 or 16
	bits.

	Do not use predicates from bytecode_gen.m to encode numbers,
	since there is nothing keeping these in sync with the code that
	reads them in mdbcomp/program_representation.m. Instead, use
	new predicates in program_representation.m itself.

compiler/stack_layout.m:
	Generate the new parts of module layouts.

	Remove the code moved to prog_rep_tables.m.

compiler/continuation_info.m:
compiler/proc_gen.m:
	Make some more information available to stack_layout.m.

compiler/prog_data.m:
	Fix some formatting.

compiler/introduce_parallelism.m:
	Conform to the renaming of the var_table type.

compiler/follow_code.m:
	Fix the bug that used to cause the failure of the
	hard_coded/mode_check_clauses test case in deep profiling grades.

deep_profiler/program_representation_utils.m:
	Output the new parts of module and procedure representations,
	to allow the correctness of this change to be tested.

deep_profiler/mdprof_create_feedback.m:
	If we cannot read the Deep.procrep file, print a single error message
	and exit, instead of continuing with an analysis that will generate
	a whole bunch of error messages, one for each attempt to access
	a procedure's representation.

deep_profiler/mdprof_procrep.m:
	Give this program an option that specifies what file it is to
	look at; do not hardwire in "Deep.procrep" in the current directory.

deep_profiler/report.m:
	Add a report type that just prints the representation of a module.
	It returns the same information as mdprof_procrep, but from within
	the deep profiler, which can be more convenient.

deep_profiler/create_report.m:
deep_profiler/display_report.m:
	Respectively create and display the new report type.

deep_profiler/query.m:
	Recognize a query asking for the new report type.

deep_profiler/autopar_calc_overlap.m:
deep_profiler/autopar_find_best_par.m:
deep_profiler/autopar_reports.m:
deep_profiler/autopar_search_callgraph.m:
deep_profiler/autopar_search_goals.m:
deep_profiler/autopar_types.m:
deep_profiler/branch_and_bound.m:
deep_profiler/coverage.m:
deep_profiler/display.m:
deep_profiler/html_format.m:
deep_profiler/mdprof_test.m:
deep_profiler/measurements.m:
deep_profiler/query.m:
deep_profiler/read_profile.m:
deep_profiler/recursion_patterns.m:
deep_profiler/top_procs.m:
deep_profiler/top_procs.m:
	Conform to the changes above.

	Fix layout.

tests/debugger/declarative/dependency.exp2:
	Add this file as a possible expected output. It contains the new
	field added to module representations.
2012-10-24 04:59:55 +00:00

1026 lines
41 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2000-2012 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.prog_rep_tables.
:- import_module mdbcomp.program_representation.
:- import_module parse_tree.prog_data.
:- 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, vartypes::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_filename :: string,
pri_vartypes :: vartypes,
pri_var_num_map :: var_num_map,
pri_var_num_rep :: var_num_rep,
pri_module_info :: module_info,
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.proc_label.
:- import_module check_hlds.inst_match.
:- import_module check_hlds.mode_util.
:- import_module hlds.code_model.
:- import_module hlds.goal_util.
:- import_module hlds.hlds_pred.
:- import_module hlds.special_pred.
:- import_module mdbcomp.
:- import_module mdbcomp.goal_path.
:- import_module mdbcomp.prim_data.
:- import_module mdbcomp.rtti_access.
:- import_module parse_tree.prog_util.
:- import_module parse_tree.set_of_var.
:- 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.
%-----------------------------------------------------------------------------%
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($module, $pred, "unqualified type_ctor name")
),
( TypeCtorModuleName = ModuleName ->
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
;
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_procedures(PredInfo, ProcTable),
map.to_assoc_list(ProcTable, Procs),
( Procs = [ProcId - _ProcInfo] ->
ProcLabel = make_proc_label(ModuleInfo, PredId, ProcId),
encode_string_proc_label(ProcLabel, BytesCord)
;
unexpected($module, $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),
PredName = special_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, VarTypes, VarNumMap,
ModuleInfo, IncludeVarNameTable, IncludeVarTypes, ProcDetism,
!StringTable, !TypeTable, ProcRepBytes) :-
Goal = hlds_goal(_, GoalInfo),
Context = goal_info_get_context(GoalInfo),
term.context_file(Context, FileName),
represent_var_table_as_bytecode(IncludeVarNameTable, IncludeVarTypes,
VarTypes, VarNumMap, VarNumRep, VarNameTableBytes,
!StringTable, !TypeTable),
Info = prog_rep_info(FileName, VarTypes, VarNumMap, VarNumRep, ModuleInfo,
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, vartypes::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,
VarTypes, VarNumMap, VarNumRep, Bytes, !StringTable, !TypeTable) :-
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_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, VarTypes),
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),
$module, $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) :-
( compiler_introduced_varname(VarName) ->
true
;
!: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) :-
( compiler_introduced_varname(VarName) ->
true
;
!: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) :-
( compiler_introduced_varname(VarName) ->
true
;
!: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, vartypes::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, VarTypes, Var, VarNum - VarName,
!NumVars, !VarNameTableBytes, !StringTable, !TypeTable) :-
!:NumVars = !.NumVars + 1,
lookup_var_type(VarTypes, 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 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_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), $module, $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),
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($module, $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, 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($module, $pred, "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($module, $pred, "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($module, $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 ^ 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 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_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($module, $pred, "mismatched lists").
filter_input_args(_, [_ | _], [], _) :-
unexpected($module, $pred, "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_of_var.to_sorted_list(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.
:- pred encode_cons_id(cons_id::in, list(int)::out,
string_table_info::in, string_table_info::out) is det.
encode_cons_id(SymName, Bytes, !StringTable) :-
encode_string_as_table_offset(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(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_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 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),
( instmap_delta_search_var(InstmapDelta, Var, FinalInstPrime) ->
FinalInst = FinalInstPrime
;
% If the variable is not in the instmap delta, then its instantiation
% cannot possibly change.
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 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.
%-----------------------------------------------------------------------------%