Files
mercury/mdbcomp/program_representation.m
2025-01-24 13:38:10 +11:00

2160 lines
79 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2001-2012 The University of Melbourne.
% Copyright (C) 2014-2019, 2021-2023, 2025 The Mercury team.
% This file is distributed under the terms specified in COPYING.LIB.
%---------------------------------------------------------------------------%
%
% File: program_representation.m
% Authors: zs, dougl
%
% This module defines the representation of procedure bodies used by the
% declarative debugger and the deep profiler.
%
% One of the things we want the declarative debugger to be able to do
% is to let the user specify which part of which output argument of an
% incorrect or inadmissible atom is suspicious, and then find out where
% that particular subterm came from, i.e. where it was bound. Doing this
% requires knowing what the bodies of that procedure and its descendants are.
%
% If the Mercury compiler is invoked with the right options, it will include
% in each procedure layout a pointer to a simplified representation of the goal
% that is the body of the corresponding procedure. We use a simplified
% representation partly because we want to insulate the code using procedure
% representations from irrelevant changes in HLDS types, and partly because
% we want to minimize the space taken in up in executables by these
% representations.
%
% The current representation is intended to contain all the information
% we are pretty sure can be usefully exploited by the declarative debugger
% and/or the deep profiler.
%---------------------------------------------------------------------------%
:- module mdbcomp.program_representation.
:- interface.
:- import_module mdbcomp.goal_path.
:- import_module mdbcomp.prim_data.
:- import_module mdbcomp.rtti_access.
:- import_module mdbcomp.sym_name.
:- import_module bool.
:- import_module io.
:- import_module list.
:- import_module map.
:- import_module maybe.
:- import_module type_desc.
:- import_module unit.
%---------------------------------------------------------------------------%
%
% The representation of programs, as recorded by the compiler for use
% by tools such as the declarative debugger and the deep profiler.
%
:- type prog_rep(GoalAnnotation)
---> prog_rep(
module_map(GoalAnnotation)
).
:- type prog_rep == prog_rep(unit).
% A map of module names to module representations.
%
:- type module_map(GoalAnnotation) ==
map(string, module_rep(GoalAnnotation)).
:- type module_map == module_map(unit).
:- type module_rep(GoalAnnotation)
---> module_rep(
mr_name :: string, % The module name.
mr_string_table :: string_table,
mr_oisu_types :: list(oisu_type_procs),
mr_type_rep_table :: map(int, type_rep),
mr_procs :: proc_map(GoalAnnotation)
).
:- type module_rep == module_rep(unit).
:- type oisu_type_procs
---> oisu_type_procs(
otp_type_ctor :: string, % name of type_ctor; arity 0
otp_creators :: list(string_proc_label),
otp_mutators :: list(string_proc_label),
otp_destructors :: list(string_proc_label)
).
:- type type_rep
---> defined_type_rep(sym_name, list(type_rep))
; builtin_type_rep(builtin_type_rep)
; tuple_type_rep(list(type_rep))
; higher_order_type_rep(list(type_rep), maybe(type_rep))
; type_var_rep(int).
:- type encoded_type_table == map(int, type_rep).
:- type builtin_type_rep
---> builtin_type_int_rep
; builtin_type_uint_rep
; builtin_type_int8_rep
; builtin_type_uint8_rep
; builtin_type_int16_rep
; builtin_type_uint16_rep
; builtin_type_int32_rep
; builtin_type_uint32_rep
; builtin_type_int64_rep
; builtin_type_uint64_rep
; builtin_type_float_rep
; builtin_type_string_rep
; builtin_type_char_rep.
% A map of proc names to proc_reps.
%
:- type proc_map(GoalAnnotation) ==
map(string_proc_label, proc_rep(GoalAnnotation)).
:- type proc_map == proc_map(unit).
:- type proc_rep(GoalAnnotation)
---> proc_rep(
pr_id :: string_proc_label,
pr_defn :: proc_defn_rep(GoalAnnotation)
).
:- type proc_rep == proc_rep(unit).
% A string_proc_label is a data structure that uniquely identifies a
% procedure. It is a version of the proc_label type from prim_data.m
% that can be used outside the compiler, e.g. in RTTI data structures
% and in data files generated by deep profiling.
%
% When procedures are imported from one module to another, for example for
% inter-module optimisations, the def_module field may be different to the
% decl_module field. If this is the case, then the procedure has been
% imported into the def_module from the decl_module. This is also true
% for the type_module and def_module fields in the str_special_proc_label
% constructor.
%
:- type string_proc_label
---> str_ordinary_proc_label(
s_ord_pred_or_func :: pred_or_func,
s_ord_decl_module :: string,
s_ord_def_module :: string,
s_ord_name :: string,
s_ord_arity :: int,
s_ord_mode :: int
)
; str_special_proc_label(
s_spec_type_name :: string,
s_spec_type_module :: string,
s_spec_def_module :: string,
s_spec_pred_name :: string,
s_spec_arity :: int,
s_spec_mode :: int
).
:- type proclabel_kind_token
---> proclabel_user_predicate
; proclabel_user_function
; proclabel_special.
:- pred is_proclabel_kind(int::in, proclabel_kind_token::out) is semidet.
% A representation of the procedure definitions (clause heads and bodies)
% that we execute. These are generated by the compiler, which stores them
% in the form of a bytecode representation in a field of the proc_layout
% structures in the executable.
%
% Each element of this structure will correspond one-to-one
% to an element of the original HLDS at the code generation stage.
:- type proc_defn_rep(GoalAnnotation)
---> proc_defn_rep(
% The head variables, in order, including the ones introduced
% by the compiler.
pdr_head_vars :: list(head_var_rep),
% The procedure body.
pdr_goal :: goal_rep(GoalAnnotation),
% The variable name table.
pdr_var_name_table :: var_name_table,
% The variable type table, if present.
pdr_var_type_table :: maybe(var_type_table),
% The determinism of the procedure. Note that this may be
% looser than the determinism of the procedure's body goal.
pdr_detism :: detism_rep
).
:- type proc_defn_rep == proc_defn_rep(unit).
:- type goal_rep(GoalAnnotation)
---> goal_rep(
% The expression this goal represents.
goal_expr_rep :: goal_expr_rep(GoalAnnotation),
% The determinism of this goal.
goal_detism_rep :: detism_rep,
% This slot may be used to annotate the goal with some extra
% information. The deep profiling tools make use of this
% to associate coverage profiling data with goals.
goal_annotation :: GoalAnnotation
).
:- type goal_rep == goal_rep(unit).
:- type goal_expr_rep(GoalAnnotation)
---> conj_rep(
% The conjuncts in the original order.
list(goal_rep(GoalAnnotation))
)
; disj_rep(
% The disjuncts in the original order.
list(goal_rep(GoalAnnotation))
)
; switch_rep(
% The variable being switched on.
var_rep,
% Completeness of the switch.
switch_can_fail_rep,
% The switch arms in the original order.
list(case_rep(GoalAnnotation))
)
; ite_rep(
% The condition, the then branch and the else branch.
goal_rep(GoalAnnotation),
goal_rep(GoalAnnotation),
goal_rep(GoalAnnotation)
)
; negation_rep(
% The negated goal.
goal_rep(GoalAnnotation)
)
; scope_rep(
% The quantified goal.
goal_rep(GoalAnnotation),
maybe_cut
)
; atomic_goal_rep(
string, % Filename of context.
int, % Line number of context.
list(var_rep), % The sorted list of the variables
% bound by the atomic goal.
atomic_goal_rep
).
:- type case_rep(GoalAnnotation)
---> case_rep(
% The name and arity of the first function symbol for which
% this switch arm is applicable.
cr_main_cons_id :: cons_id_arity_rep,
% The names and arities of any other function symbols for
% this switch arm.
cr_other_cons_ids :: list(cons_id_arity_rep),
% The code of the switch arm.
cr_case_goal :: goal_rep(GoalAnnotation)
).
:- type case_rep == case_rep(unit).
:- type switch_can_fail_rep
---> switch_can_fail_rep
; switch_can_not_fail_rep.
:- type atomic_goal_rep
---> unify_construct_rep(
var_rep,
cons_id_rep,
list(var_rep)
)
; unify_deconstruct_rep(
var_rep,
cons_id_rep,
list(var_rep)
)
; partial_deconstruct_rep(
% A partial deconstruction of the form
% X = f(Y_1, Y_2, ..., Y_n)
% where X is more instantiated after the unification
% than before.
var_rep, % X
cons_id_rep, % f
list(maybe(var_rep))
% The list of Y_i's. Y_i's which are input
% are wrapped in `yes', while the other
% Y_i positions are `no'.
)
; partial_construct_rep(
% A partial construction of the form
% X = f(Y_1, Y_2, ..., Y_n)
% where X is free before the unification and bound,
% but not ground, after the unification.
var_rep, % X
cons_id_rep, % f
list(maybe(var_rep))
% The list of Y_i's. Y_i's which are input
% are wrapped in `yes', while the other
% Y_i positions are `no'.
)
; unify_assign_rep(
var_rep, % target
var_rep % source
)
; cast_rep(
var_rep, % target
var_rep % source
)
; unify_simple_test_rep(
var_rep,
var_rep
)
; pragma_foreign_code_rep(
list(var_rep) % arguments
)
; higher_order_call_rep(
var_rep, % the closure to call
list(var_rep) % the call's plain arguments
)
; method_call_rep(
var_rep, % typeclass info var
int, % method number
list(var_rep) % the call's plain arguments
)
; plain_call_rep(
string, % name of called pred's module
string, % name of the called pred
list(var_rep) % the call's arguments
)
; builtin_call_rep(
% This represents inline builtins only.
string, % name of called pred's module
string, % name of the called pred
list(var_rep) % the call's arguments
)
; event_call_rep(
string, % name of the event
list(var_rep) % the call's arguments
).
:- type var_rep == int.
:- type head_var_rep
---> head_var_rep(
head_var_var :: var_rep,
head_var_mode :: var_mode_rep
).
:- type var_mode_rep
---> var_mode_rep(
vm_initial_inst :: inst_rep,
vm_final_inst :: inst_rep
).
:- type inst_rep
---> ir_free_rep
; ir_ground_rep
; ir_other_rep.
% Instantiation states that are not understood by the bytecode
% representation are stored as ir_other_rep.
:- type cons_id_arity_rep
---> cons_id_arity_rep(
cons_id_rep,
int
).
:- type cons_id_rep == string.
:- type detism_rep
---> det_rep
; semidet_rep
; nondet_rep
; multidet_rep
; cc_nondet_rep
; cc_multidet_rep
; erroneous_rep
; failure_rep.
:- type solution_count_rep
---> at_most_zero_rep
; at_most_one_rep % Including committed choice.
; at_most_many_rep.
:- type can_fail_rep
---> can_fail_rep
; cannot_fail_rep.
:- type committed_choice
---> committed_choice
; not_committed_choice.
%---------------------------------------------------------------------------%
%
% Operations on determinisms.
%
:- func detism_get_solutions(detism_rep) = solution_count_rep.
:- func detism_get_can_fail(detism_rep) = can_fail_rep.
:- pred detism_components(detism_rep, solution_count_rep, can_fail_rep).
:- mode detism_components(in, out, out) is det.
:- mode detism_components(out, in, in) is multi.
:- pred detism_committed_choice(detism_rep, committed_choice).
:- mode detism_committed_choice(in, out) is det.
:- mode detism_committed_choice(out, in) is multi.
%---------------------------------------------------------------------------%
%
% Operations on variable name tables.
%
% A table of var_rep to string mappings.
%
% This table may not contain all the variables in the procedure. Variables
% created by the compiler are not included. The table may be empty if it is
% not required, such as when used with the declarative debugger.
%
:- type var_name_table.
% Retrieve the name for this variable if it is known, otherwise fail.
%
:- pred search_var_name(var_name_table::in, var_rep::in, string::out)
is semidet.
% Retrieve the name for this variable if it is known, otherwise,
% return `no'.
%
:- pred maybe_search_var_name(var_name_table::in, var_rep::in,
maybe(string)::out) is det.
% Lookup the name of a variable within the variable table. If the variable
% is unknown a distinct name is automatically generated.
%
:- pred lookup_var_name(var_name_table::in, var_rep::in, string::out) is det.
% A table mapping var_reps to representations of the variables' types.
% It is intended to be used by a program analysis for order-independent
% state update in the auto-parallelisation feedback tool.
%
% This table should exist in any procedure that is named in a oisu pragma.
% In other procedures, it may or may not be there (currently, it isn't).
%
:- type var_type_table == map(var_rep, type_rep).
%---------------------------------------------------------------------------%
%
% Operations on goals.
%
% If the given atomic goal behaves like a call in the sense that it
% generates events as ordinary calls do, then return the list of variables
% that are passed as arguments.
%
:- func atomic_goal_generates_event_like_call(atomic_goal_rep) =
maybe(list(var_rep)).
% call_does_not_generate_events(ModuleName, PredName, Arity):
%
% Succeed iff a call to the named predicate will not generate events
% in a debugging grade.
%
:- pred call_does_not_generate_events(string::in, string::in, int::in)
is semidet.
% If the given goal generates internal events directly, then return yes;
% otherwise, return no.
%
:- func goal_generates_internal_event(goal_rep(unit)) = bool.
% The atomic goal's module, name and arity.
%
:- type atomic_goal_id
---> atomic_goal_id(string, string, int).
% Can we find out the atomic goal's name, module and arity from
% its atomic_goal_rep? If so, return them; otherwise, return no.
%
:- func atomic_goal_identifiable(atomic_goal_rep) = maybe(atomic_goal_id).
:- func head_var_to_var(head_var_rep) = var_rep.
% Extract the goal from a case, this is implemented here so it can be used
% as a higher order value.
%
:- pred case_get_goal(case_rep(T)::in, goal_rep(T)::out) is det.
% Transform the annotations on a goal representation. This may change
% not only the values of the annotations, but also their type.
%
:- pred transform_goal_rep(pred(T, U)::in(pred(in, out) is det),
goal_rep(T)::in, goal_rep(U)::out) is det.
%---------------------------------------------------------------------------%
% Describe a call site.
%
:- type call_site
---> call_site(
caller :: string_proc_label,
slot :: int,
call_type_and_callee :: call_type_and_callee
).
% The type and callee of call. The callee is known only for plain calls.
%
:- type call_type_and_callee
---> callback_call
; higher_order_call
; method_call
; plain_call(string_proc_label)
; special_call.
% User-visible head variables are represented by a number from 1..N,
% where N is the user-visible arity.
%
% Both user-visible and compiler-generated head variables can be
% referred to via their position in the full list of head variables;
% the first head variable is at position 1.
:- type arg_pos
---> user_head_var(int)
% Nth in the list of arguments after filtering out
% non-user-visible vars.
; any_head_var(int)
% Nth in the list of all arguments.
; any_head_var_from_back(int).
% (M-N+1)th argument in the list of all arguments, where N is
% the value of the int in the constructor and M is the total number
% of arguments.
% A particular subterm within a term is represented by a term_path.
% This is the list of argument positions that need to be followed
% in order to travel from the root to the subterm. This list is in
% top-down order (i.e. the argument number in the top function symbol
% is first).
:- type term_path == list(int).
%---------------------------------------------------------------------------%
% Returns type_of(_ : proc_defn_rep), for use in C code.
%
:- func proc_defn_rep_type = type_desc.
% Returns type_of(_ : goal_rep), for use in C code.
%
:- func goal_rep_type = type_desc.
%---------------------------------------------------------------------------%
%
% Conversions between the internal form of program representations
% and their form as stored in bytecode.
%
% Construct a representation of the interface determinism of a
% procedure. The code we have chosen is not sequential; instead
% it encodes the various properties of each determinism.
% This must match the encoding of MR_Determinism in
% mercury_stack_layout.h.
%
% The 8 bit is set iff the context is first_solution.
% The 4 bit is set iff the min number of solutions is more than zero.
% The 2 bit is set iff the max number of solutions is more than zero.
% The 1 bit is set iff the max number of solutions is more than one.
%
:- func detism_rep(detism_rep) = int.
:- pred determinism_representation(detism_rep, int).
:- mode determinism_representation(in, out) is det.
:- mode determinism_representation(out, in) is semidet.
:- pred inst_representation(inst_rep, int).
:- mode inst_representation(in, out) is det.
:- mode inst_representation(out, in) is semidet.
:- type bytecode_goal_type
---> goal_conj
; goal_disj
; goal_switch
; goal_ite
; goal_neg
; goal_scope
; goal_construct
; goal_deconstruct
; goal_partial_construct
; goal_partial_deconstruct
; goal_assign
; goal_cast
; goal_simple_test
; goal_foreign
; goal_ho_call
; goal_method_call
; goal_plain_call
; goal_builtin_call
; goal_event_call.
:- func goal_type_to_byte(bytecode_goal_type) = int.
:- pred byte_to_goal_type(int::in, bytecode_goal_type::out) is semidet.
% We represent a variable number as
% - one byte if all variable numbers fit into one byte,
% - two bytes if all variable numbers fit into two bytes, but
% some do not fit into one byte, and
% - four bytes if some variable numbers do not fit into two bytes.
% This assumes that all variable numbers fit into four bytes.
%
:- type var_num_rep
---> var_num_1_byte
; var_num_2_bytes
; var_num_4_bytes.
% 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 maybe_include_var_name_table
---> do_not_include_var_name_table
; include_var_name_table.
% Describe whether references to the types of variables should be included
% in the variable table. The types themselves are in a separate table next
% to the module's string table.
%
:- type maybe_include_var_types
---> do_not_include_var_types
; include_var_types.
% This predicate is here only for reading Deep.procrep files in an
% old format, for backwards compatibility.
%
:- pred var_num_rep_byte(var_num_rep, int).
:- mode var_num_rep_byte(in, out) is det.
:- mode var_num_rep_byte(out, in) is semidet.
% This predicate is the replacement for var_num_rep_byte.
%
:- pred var_flag_byte(var_num_rep,
maybe_include_var_name_table, maybe_include_var_types, int).
:- mode var_flag_byte(in, in, in, out) is det.
:- mode var_flag_byte(out, out, out, in) is semidet.
% Represent whether a scope goal cuts away solutions or not.
%
:- pred cut_byte(maybe_cut, int).
:- mode cut_byte(in, out) is det.
:- mode cut_byte(out, in) is semidet.
:- pred can_fail_byte(switch_can_fail_rep, int).
:- mode can_fail_byte(in, out) is det.
:- mode can_fail_byte(out, in) is semidet.
%---------------------------------------------------------------------------%
% read_prog_rep_file(FileName, Result, !IO)
%
:- pred read_prog_rep_file(string::in, io.res(prog_rep)::out, io::di, io::uo)
is det.
:- pred trace_read_proc_defn_rep(bytecode_bytes::in, label_layout::in,
proc_defn_rep::out) is semidet.
%---------------------------------------------------------------------------%
% Some predicates that operate on polymorphic values do not need
% the type_infos describing the types bound to the variables.
% It is of course faster not to pass type_infos to such predicates
% (especially since we may also be able to avoid constructing those
% type_infos), and it can also be easier for a compiler module
% (e.g. common.m, size_prof.m) that generates calls to such predicates
% not to have to create those type_infos.
%
% All the predicates for whose names no_type_info_builtin succeeds
% are defined by compiler implementors. They are all predicates
% implemented by foreign language code in the standard library.
% For some, but not all, the compiler generates code inline.
%
% If you are adding a predicate to no_type_info_builtin, remember that
% this will only affect code built by a compiler linked with the new
% mdbcomp library. For example, if you add a predicate P to
% no_type_info_builtin, the compiler building the stage 1 library
% won't yet know about P. The stage 1 compiler _will_ know about P,
% so stage 2 is when P will be compiled differently.
%
% XXX ARITY The last argument should be pred_form_arity.
%
:- pred no_type_info_builtin(module_name::in, string::in, int::in) is semidet.
%---------------------------------------------------------------------------%
:- type coverage_point_info
---> coverage_point_info(
% Identifies the goal that this coverage point is near.
% If cp_type is cp_type_branch_arm, the coverage point is
% immediately before this goal, otherwise it is immediately
% after.
reverse_goal_path,
% The type of this coverage point.
cp_type
).
% This enumeration specifies the type of coverage point. A branch arm
% is an arm of an if-then-else, switch or disj goal. The coverage_after
% type is used to measure the coverage after the goal its coverage point
% refers to.
:- type cp_type
---> cp_type_coverage_after
; cp_type_branch_arm.
% Gives the value in C for this coverage point type.
%
:- pred coverage_point_type_c_value(cp_type::in, string::out) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module mdbcomp.builtin_modules.
:- import_module int.
:- import_module require.
:- import_module string.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
detism_get_solutions(Detism) = Solutions :-
detism_components(Detism, Solutions, _).
detism_get_can_fail(Detism) = CanFail :-
detism_components(Detism, _, CanFail).
detism_components(det_rep, at_most_one_rep, cannot_fail_rep).
detism_components(semidet_rep, at_most_one_rep, can_fail_rep).
detism_components(multidet_rep, at_most_many_rep, cannot_fail_rep).
detism_components(nondet_rep, at_most_many_rep, can_fail_rep).
detism_components(cc_multidet_rep, at_most_one_rep, cannot_fail_rep).
detism_components(cc_nondet_rep, at_most_one_rep, can_fail_rep).
detism_components(erroneous_rep, at_most_zero_rep, cannot_fail_rep).
detism_components(failure_rep, at_most_zero_rep, can_fail_rep).
detism_committed_choice(det_rep, not_committed_choice).
detism_committed_choice(semidet_rep, not_committed_choice).
detism_committed_choice(multidet_rep, not_committed_choice).
detism_committed_choice(nondet_rep, not_committed_choice).
detism_committed_choice(cc_multidet_rep, committed_choice).
detism_committed_choice(cc_nondet_rep, committed_choice).
detism_committed_choice(erroneous_rep, not_committed_choice).
detism_committed_choice(failure_rep, not_committed_choice).
%---------------------------------------------------------------------------%
:- type var_name_table == map(var_rep, string).
search_var_name(VarNameTable, VarRep, String) :-
map.search(VarNameTable, VarRep, String).
maybe_search_var_name(VarNameTable, VarRep, MaybeString) :-
( if search_var_name(VarNameTable, VarRep, String) then
MaybeString = yes(String)
else
MaybeString = no
).
lookup_var_name(VarNameTable, VarRep, String) :-
( if search_var_name(VarNameTable, VarRep, StringPrime) then
String = StringPrime
else
% Generate an automatic name for the variable.
String = string.format("V_%d", [i(VarRep)])
).
%---------------------------------------------------------------------------%
atomic_goal_generates_event_like_call(GoalRep) = Generates :-
(
( GoalRep = unify_construct_rep(_, _, _)
; GoalRep = unify_deconstruct_rep(_, _, _)
; GoalRep = partial_construct_rep(_, _, _)
; GoalRep = partial_deconstruct_rep(_, _, _)
; GoalRep = unify_assign_rep(_, _)
; GoalRep = unify_simple_test_rep(_, _)
; GoalRep = cast_rep(_, _)
; GoalRep = pragma_foreign_code_rep(_)
; GoalRep = builtin_call_rep(_, _, _)
; GoalRep = event_call_rep(_, _)
),
Generates = no
;
( GoalRep = higher_order_call_rep(_, Args)
; GoalRep = method_call_rep(_, _, Args)
),
Generates = yes(Args)
;
GoalRep = plain_call_rep(ModuleName, PredName, Args),
NumArgs = list.length(Args),
( if call_does_not_generate_events(ModuleName, PredName, NumArgs) then
Generates = no
else
Generates = yes(Args)
)
).
call_does_not_generate_events(ModuleName, PredName, Arity) :-
(
SymModuleName = string_to_sym_name(ModuleName),
non_traced_mercury_builtin_module(SymModuleName)
;
% The debugger cannot handle calls to polymorphic builtins that
% do not take a type_info argument, so such calls are not traced.
SymModuleName = string_to_sym_name(ModuleName),
no_type_info_builtin(SymModuleName, PredName, Arity)
;
pred_is_external(ModuleName, PredName, Arity)
;
% Events from compiler generated predicates are not included in the
% annotated trace at the moment.
( PredName = "__Unify__"
; PredName = "__Index__"
; PredName = "__Compare__"
)
).
goal_generates_internal_event(goal_rep(GoalExpr, _, _)) = InternalEvent :-
require_complete_switch [GoalExpr]
(
( GoalExpr = conj_rep(_)
; GoalExpr = scope_rep(_, _)
; GoalExpr = atomic_goal_rep(_, _, _, _)
% Atomic goals may generate interface events,
% but not internal events.
),
InternalEvent = no
;
( GoalExpr = disj_rep(_)
; GoalExpr = switch_rep(_, _, _)
; GoalExpr = ite_rep(_, _, _)
; GoalExpr = negation_rep(_)
),
InternalEvent = yes
).
atomic_goal_identifiable(AtomicGoalExpr) = Identifieable :-
(
( AtomicGoalExpr = unify_construct_rep(_, _, _)
; AtomicGoalExpr = unify_deconstruct_rep(_, _, _)
; AtomicGoalExpr = partial_construct_rep(_, _, _)
; AtomicGoalExpr = partial_deconstruct_rep(_, _, _)
; AtomicGoalExpr = unify_assign_rep(_, _)
; AtomicGoalExpr = unify_simple_test_rep(_, _)
; AtomicGoalExpr = cast_rep(_, _)
; AtomicGoalExpr = pragma_foreign_code_rep(_)
; AtomicGoalExpr = higher_order_call_rep(_, _)
; AtomicGoalExpr = method_call_rep(_, _, _)
; AtomicGoalExpr = event_call_rep(_, _)
),
Identifieable = no
;
AtomicGoalExpr = builtin_call_rep(Module, Name, Args),
Identifieable = yes(atomic_goal_id(Module, Name, length(Args)))
;
AtomicGoalExpr = plain_call_rep(Module, Name, Args),
Identifieable = yes(atomic_goal_id(Module, Name, length(Args)))
).
head_var_to_var(head_var_rep(Var, _)) = Var.
case_get_goal(case_rep(_, _, Goal), Goal).
%---------------------------------------------------------------------------%
transform_goal_rep(Pred, Goal0, Goal) :-
Goal0 = goal_rep(Expr0, Detism, AnnotationT),
transform_goal_expr(Pred, Expr0, Expr),
Pred(AnnotationT, AnnotationU),
Goal = goal_rep(Expr, Detism, AnnotationU).
:- pred transform_goal_expr(pred(T, U)::in(pred(in, out) is det),
goal_expr_rep(T)::in, goal_expr_rep(U)::out) is det.
transform_goal_expr(Pred, Expr0, Expr) :-
(
Expr0 = conj_rep(Conjs0),
list.map(transform_goal_rep(Pred), Conjs0, Conjs),
Expr = conj_rep(Conjs)
;
Expr0 = disj_rep(Disjs0),
list.map(transform_goal_rep(Pred), Disjs0, Disjs),
Expr = disj_rep(Disjs)
;
Expr0 = switch_rep(Var, CanFail, Cases0),
map(transform_switch_case(Pred), Cases0, Cases),
Expr = switch_rep(Var, CanFail, Cases)
;
Expr0 = ite_rep(Cond0, Then0, Else0),
transform_goal_rep(Pred, Cond0, Cond),
transform_goal_rep(Pred, Then0, Then),
transform_goal_rep(Pred, Else0, Else),
Expr = ite_rep(Cond, Then, Else)
;
Expr0 = negation_rep(NegGoal0),
transform_goal_rep(Pred, NegGoal0, NegGoal),
Expr = negation_rep(NegGoal)
;
Expr0 = scope_rep(SubGoal0, MaybeCut),
transform_goal_rep(Pred, SubGoal0, SubGoal),
Expr = scope_rep(SubGoal, MaybeCut)
;
Expr0 = atomic_goal_rep(Filename, Lineno, BoundVars, AtomicGoal),
Expr = atomic_goal_rep(Filename, Lineno, BoundVars, AtomicGoal)
).
:- pred transform_switch_case(pred(T, U)::in(pred(in, out) is det),
case_rep(T)::in, case_rep(U)::out) is det.
transform_switch_case(Pred, Case0, Case) :-
Case0 = case_rep(MainConsId, OtherConsIds, Goal0),
transform_goal_rep(Pred, Goal0, Goal),
Case = case_rep(MainConsId, OtherConsIds, Goal).
%---------------------------------------------------------------------------%
:- pragma foreign_export("C", proc_defn_rep_type = out,
"ML_proc_defn_rep_type").
proc_defn_rep_type = type_of(_ : proc_defn_rep).
:- pragma foreign_export("C", goal_rep_type = out,
"ML_goal_rep_type").
goal_rep_type = type_of(_ : goal_rep).
%---------------------------------------------------------------------------%
detism_rep(Detism) = Rep :-
determinism_representation(Detism, Rep).
% This encoding must match the encoding of MR_Determinism in
% runtime/mercury_stack_layout.h. The rationale for this encoding
% is documented there.
determinism_representation(det_rep, 6).
determinism_representation(semidet_rep, 2).
determinism_representation(nondet_rep, 3).
determinism_representation(multidet_rep, 7).
determinism_representation(erroneous_rep, 4).
determinism_representation(failure_rep, 0).
determinism_representation(cc_nondet_rep, 10).
determinism_representation(cc_multidet_rep, 14).
inst_representation(ir_free_rep, 0).
inst_representation(ir_ground_rep, 1).
inst_representation(ir_other_rep, 2).
goal_type_to_byte(Type) = TypeInt :-
goal_type_byte(TypeInt, Type).
byte_to_goal_type(TypeInt, Type) :-
goal_type_byte(TypeInt, Type).
:- pred goal_type_byte(int, bytecode_goal_type).
:- mode goal_type_byte(in, out) is semidet.
:- mode goal_type_byte(out, in) is det.
goal_type_byte(1, goal_conj).
goal_type_byte(2, goal_disj).
goal_type_byte(3, goal_switch).
goal_type_byte(4, goal_ite).
goal_type_byte(5, goal_neg).
goal_type_byte(6, goal_scope).
goal_type_byte(7, goal_construct).
goal_type_byte(8, goal_deconstruct).
goal_type_byte(9, goal_partial_construct).
goal_type_byte(10, goal_partial_deconstruct).
goal_type_byte(11, goal_assign).
goal_type_byte(12, goal_cast).
goal_type_byte(13, goal_simple_test).
goal_type_byte(14, goal_foreign).
goal_type_byte(15, goal_ho_call).
goal_type_byte(16, goal_method_call).
goal_type_byte(17, goal_plain_call).
goal_type_byte(18, goal_builtin_call).
goal_type_byte(19, goal_event_call).
%---------------------------------------------------------------------------%
var_num_rep_byte(var_num_1_byte, 0).
var_num_rep_byte(var_num_2_bytes, 1).
var_num_rep_byte(var_num_4_bytes, 2).
var_flag_byte(var_num_1_byte,
do_not_include_var_name_table, do_not_include_var_types, 0).
var_flag_byte(var_num_1_byte,
do_not_include_var_name_table, include_var_types, 1).
var_flag_byte(var_num_1_byte,
include_var_name_table, do_not_include_var_types, 2).
var_flag_byte(var_num_1_byte,
include_var_name_table, include_var_types, 3).
var_flag_byte(var_num_2_bytes,
do_not_include_var_name_table, do_not_include_var_types, 4).
var_flag_byte(var_num_2_bytes,
do_not_include_var_name_table, include_var_types, 5).
var_flag_byte(var_num_2_bytes,
include_var_name_table, do_not_include_var_types, 6).
var_flag_byte(var_num_2_bytes,
include_var_name_table, include_var_types, 7).
var_flag_byte(var_num_4_bytes,
do_not_include_var_name_table, do_not_include_var_types, 8).
var_flag_byte(var_num_4_bytes,
do_not_include_var_name_table, include_var_types, 9).
var_flag_byte(var_num_4_bytes,
include_var_name_table, do_not_include_var_types, 10).
var_flag_byte(var_num_4_bytes,
include_var_name_table, include_var_types, 11).
cut_byte(scope_is_no_cut, 0).
cut_byte(scope_is_cut, 1).
can_fail_byte(switch_can_fail_rep, 0).
can_fail_byte(switch_can_not_fail_rep, 1).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
%
% The top level of the code that reads the representation of a whole program
% from a file.
%
read_prog_rep_file(FileName, Result, !IO) :-
read_file_as_bytecode(FileName, ReadResult, !IO),
(
ReadResult = error(Error),
Result = error(Error)
;
ReadResult = ok(ByteCode),
( if
some [!Pos] (
!:Pos = 0,
read_line(ByteCode, Line, !Pos),
( if Line = old_procrep_id_string then
ExpectNewFormat = no
else if Line = new_procrep_id_string then
ExpectNewFormat = yes
else
fail
),
read_module_reps(ExpectNewFormat, ByteCode,
map.init, ModuleReps, !Pos),
ByteCode = bytecode(_, Size),
!.Pos = Size
)
then
Result = ok(prog_rep(ModuleReps))
else
Msg = FileName ++ ": is not a valid program representation file",
Result = error(io.make_io_error(Msg))
)
).
% Return the string written out by MR_write_out_procrep_id_string.
%
:- func old_procrep_id_string = string.
:- func new_procrep_id_string = string.
old_procrep_id_string = "Mercury deep profiler procrep version 5\n".
new_procrep_id_string = "Mercury deep profiler procrep version 6\n".
:- pred read_file_as_bytecode(string::in, io.res(bytecode)::out,
io::di, io::uo) is det.
read_file_as_bytecode(FileName, Result, !IO) :-
read_file_as_bytecode_2(FileName, ByteCode, Size, Error, !IO),
( if Size < 0 then
io.make_io_error_from_system_error(Error,
"opening " ++ FileName ++ ": ", IOError, !IO),
Result = error(IOError)
else
Result = ok(bytecode(ByteCode, Size))
).
:- pragma foreign_decl("C", "
#ifdef MR_HAVE_SYS_STAT_H
#include <sys/stat.h>
#include <fcntl.h>
#endif
").
:- pred read_file_as_bytecode_2(string::in, bytecode_bytes::out, int::out,
io.system_error::out, io::di, io::uo) is det.
:- pragma foreign_proc("C",
read_file_as_bytecode_2(FileName::in, Bytes::out, Size::out, Error::out,
_IO0::di, _IO::uo),
[will_not_call_mercury, thread_safe, promise_pure],
"
#if defined(MR_HAVE_SYS_STAT_H) && \
defined(MR_HAVE_STAT) && \
defined(MR_HAVE_OPEN)
struct stat statbuf;
if (stat(FileName, &statbuf) != 0) {
Bytes = NULL;
Size = -1;
Error = errno;
} else {
int fd;
char *buf;
Size = statbuf.st_size;
MR_allocate_aligned_string_msg(buf, Size, MR_ALLOC_ID);
fd = open(FileName, O_RDONLY, 0);
if (fd < 0) {
Bytes = NULL;
Size = -1;
Error = errno;
} else {
if (read(fd, buf, Size) != Size) {
Bytes = NULL;
Size = -1;
Error = errno;
} else {
if (close(fd) != 0) {
Bytes = NULL;
Size = -1;
Error = errno;
} else {
Bytes = (MR_uint_least8_t *) buf;
Error = 0;
}
}
}
}
#else
MR_fatal_error(""read_file_as_bytecode: not supported on this platform"");
#endif
").
%---------------------------------------------------------------------------%
%
% The top level of the code that reads the representation of a procedure
% from that procedure's proc layout structure.
%
:- pragma foreign_export("C", trace_read_proc_defn_rep(in, in, out),
"MR_MDBCOMP_trace_read_proc_defn_rep").
trace_read_proc_defn_rep(Bytes, LabelLayout, ProcDefnRep) :-
ProcLayout = containing_proc_layout(LabelLayout),
( if containing_module_layout(ProcLayout, ModuleLayout) then
StringTable = module_string_table(ModuleLayout)
else
unexpected($pred, "no module layout")
),
some [!Pos] (
!:Pos = 0,
% The size of the bytecode is not recorded anywhere in the proc layout
% except at the start of the bytecode itself.
DummyByteCode = bytecode(Bytes, 4),
read_int32(DummyByteCode, Size, !Pos),
ByteCode = bytecode(Bytes, Size),
read_string_via_offset(ByteCode, StringTable, FileName, !Pos),
Info = read_proc_rep_info(FileName),
% The declarative debugger does not need variable type representations
% from the bytecode. It has access to actual type_infos in label
% layouts.
ExpectNewFormat = yes,
read_var_table(ExpectNewFormat, ByteCode, StringTable,
map.init, VarNumRep, VarNameTable, _MaybeVarTypeTable, !Pos),
read_head_vars(VarNumRep, ByteCode, HeadVars, !Pos),
read_goal(VarNumRep, ByteCode, StringTable, Info, Goal, !Pos),
read_determinism(ByteCode, Detism, !Pos),
ProcDefnRep = proc_defn_rep(HeadVars, Goal, VarNameTable, no, Detism),
expect(unify(!.Pos, Size), $pred, "limit mismatch")
).
%---------------------------------------------------------------------------%
%
% Operations that parse the (remaining part of) the bytecode string
% as various components of a program representation.
%
:- pred read_module_reps(bool::in, bytecode::in,
module_map(unit)::in, module_map(unit)::out,
int::in, int::out) is semidet.
read_module_reps(ExpectNewFormat, ByteCode, !ModuleReps, !Pos) :-
read_byte(ByteCode, MoreByte, !Pos),
is_more_modules(MoreByte, MoreModules),
(
MoreModules = no_more_modules
;
MoreModules = next_module,
read_module_rep(ExpectNewFormat, ByteCode, ModuleRep, !Pos),
map.det_insert(ModuleRep ^ mr_name, ModuleRep, !ModuleReps),
disable_warning [suspicious_recursion] (
read_module_reps(ExpectNewFormat, ByteCode, !ModuleReps, !Pos)
)
).
:- pred read_module_rep(bool::in, bytecode::in, module_rep(unit)::out,
int::in, int::out) is semidet.
read_module_rep(ExpectNewFormat, ByteCode, ModuleRep, !Pos) :-
read_len_string(ByteCode, ModuleName, !Pos),
trace [io(!IO), compiletime(flag("debug_oisu_bytecode"))] (
io.output_stream(OutputStream, !IO),
io.format(OutputStream, "module rep for %s\n", [s(ModuleName)], !IO)
),
read_string_table(ByteCode, StringTable, !Pos),
(
ExpectNewFormat = no,
OISUTypes = [],
map.init(TypeTable)
;
ExpectNewFormat = yes,
read_num(ByteCode, NumOISUTypes, !Pos),
( if NumOISUTypes > 0 then
OISUStartPos = !.Pos,
read_int32(ByteCode, OISUSize, !Pos),
trace [io(!IO), compiletime(flag("debug_oisu_bytecode"))] (
io.output_stream(OutputStream, !IO),
io.format(OutputStream, "OISU num types %d\n",
[i(NumOISUTypes)], !IO),
io.format(OutputStream, "OISU bytecode size %d\n",
[i(OISUSize)], !IO)
),
read_n_items(read_oisu_type_procs(ByteCode), NumOISUTypes,
OISUTypes, !Pos),
expect(unify(!.Pos, OISUStartPos + OISUSize), $pred,
"oisu limit mismatch")
else
OISUTypes = []
),
read_num(ByteCode, NumTableTypes, !Pos),
( if NumTableTypes > 0 then
TypeStartPos = !.Pos,
read_int32(ByteCode, TypeSize, !Pos),
trace [io(!IO), compiletime(flag("debug_oisu_bytecode"))] (
io.output_stream(OutputStream, !IO),
io.format(OutputStream, "num types %d\n",
[i(NumOISUTypes)], !IO),
io.format(OutputStream, "type bytecode size %d\n",
[i(TypeSize)], !IO)
),
read_n_encoded_types(ByteCode, StringTable, 0, NumTableTypes,
map.init, TypeTable, !Pos),
expect(unify(!.Pos, TypeStartPos + TypeSize), $pred,
"type limit mismatch")
else
map.init(TypeTable)
)
),
read_proc_reps(ExpectNewFormat, ByteCode, StringTable, TypeTable,
map.init, ProcReps, !Pos),
ModuleRep = module_rep(ModuleName, StringTable, OISUTypes, TypeTable,
ProcReps).
%---------------------%
:- pred read_oisu_type_procs(bytecode::in, oisu_type_procs::out,
int::in, int::out) is semidet.
read_oisu_type_procs(ByteCode, OISUTypeProcs, !Pos) :-
read_len_string(ByteCode, TypeCtorName, !Pos),
read_num(ByteCode, NumCreators, !Pos),
read_n_items(read_string_proc_label(ByteCode), NumCreators,
CreatorProcLabels, !Pos),
read_num(ByteCode, NumMutators, !Pos),
read_n_items(read_string_proc_label(ByteCode), NumMutators,
MutatorProcLabels, !Pos),
read_num(ByteCode, NumDestructors, !Pos),
read_n_items(read_string_proc_label(ByteCode), NumDestructors,
DestructorProcLabels, !Pos),
OISUTypeProcs = oisu_type_procs(TypeCtorName,
CreatorProcLabels, MutatorProcLabels, DestructorProcLabels).
%---------------------%
:- pred read_n_encoded_types(bytecode::in, string_table::in, int::in, int::in,
encoded_type_table::in, encoded_type_table::out,
int::in, int::out) is semidet.
read_n_encoded_types(ByteCode, StringTable, CurTypeNum, NumTableTypes,
!TypeTable, !Pos) :-
( if CurTypeNum < NumTableTypes then
read_encoded_type(ByteCode, StringTable, !.TypeTable, TypeRep, !Pos),
map.det_insert(CurTypeNum, TypeRep, !TypeTable),
read_n_encoded_types(ByteCode, StringTable,
CurTypeNum + 1, NumTableTypes, !TypeTable, !Pos)
else
true
).
:- pred read_encoded_type(bytecode::in, string_table::in,
encoded_type_table::in, type_rep::out, int::in, int::out) is semidet.
read_encoded_type(ByteCode, StringTable, TypeTable, TypeRep, !Pos) :-
% The encoding read here is created by add_type_to_table in compiler/
% prog_rep_table.m. The code here and there must be kept in sync.
read_byte(ByteCode, Selector, !Pos),
(
Selector = 0,
read_string_via_offset(ByteCode, StringTable, TypeCtorStr, !Pos),
TypeCtorSymName = string_to_sym_name(TypeCtorStr),
TypeRep = defined_type_rep(TypeCtorSymName, [])
;
Selector = 1,
read_string_via_offset(ByteCode, StringTable, TypeCtorStr, !Pos),
TypeCtorSymName = string_to_sym_name(TypeCtorStr),
read_num(ByteCode, TypeNumArg1, !Pos),
map.lookup(TypeTable, TypeNumArg1, TypeRepArg1),
TypeRep = defined_type_rep(TypeCtorSymName, [TypeRepArg1])
;
Selector = 2,
read_string_via_offset(ByteCode, StringTable, TypeCtorStr, !Pos),
TypeCtorSymName = string_to_sym_name(TypeCtorStr),
read_num(ByteCode, TypeNumArg1, !Pos),
read_num(ByteCode, TypeNumArg2, !Pos),
map.lookup(TypeTable, TypeNumArg1, TypeRepArg1),
map.lookup(TypeTable, TypeNumArg2, TypeRepArg2),
TypeRep = defined_type_rep(TypeCtorSymName, [TypeRepArg1, TypeRepArg2])
;
Selector = 3,
read_string_via_offset(ByteCode, StringTable, TypeCtorStr, !Pos),
TypeCtorSymName = string_to_sym_name(TypeCtorStr),
read_num(ByteCode, TypeNumArg1, !Pos),
read_num(ByteCode, TypeNumArg2, !Pos),
read_num(ByteCode, TypeNumArg3, !Pos),
map.lookup(TypeTable, TypeNumArg1, TypeRepArg1),
map.lookup(TypeTable, TypeNumArg2, TypeRepArg2),
map.lookup(TypeTable, TypeNumArg3, TypeRepArg3),
TypeRep = defined_type_rep(TypeCtorSymName,
[TypeRepArg1, TypeRepArg2, TypeRepArg3])
;
Selector = 4,
read_string_via_offset(ByteCode, StringTable, TypeCtorStr, !Pos),
TypeCtorSymName = string_to_sym_name(TypeCtorStr),
read_num(ByteCode, NumArgs, !Pos),
read_n_items(read_num(ByteCode), NumArgs, TypeNumArgs, !Pos),
list.map(map.lookup(TypeTable), TypeNumArgs, TypeRepArgs),
TypeRep = defined_type_rep(TypeCtorSymName, TypeRepArgs)
;
Selector = 5,
TypeRep = builtin_type_rep(builtin_type_int_rep)
;
Selector = 6,
TypeRep = builtin_type_rep(builtin_type_uint_rep)
;
Selector = 7,
TypeRep = builtin_type_rep(builtin_type_float_rep)
;
Selector = 8,
TypeRep = builtin_type_rep(builtin_type_string_rep)
;
Selector = 9,
TypeRep = builtin_type_rep(builtin_type_char_rep)
;
Selector = 10,
read_num(ByteCode, NumArgs, !Pos),
read_n_items(read_num(ByteCode), NumArgs, TypeNumArgs, !Pos),
list.map(map.lookup(TypeTable), TypeNumArgs, TypeRepArgs),
TypeRep = tuple_type_rep(TypeRepArgs)
;
Selector = 11,
read_num(ByteCode, NumArgs, !Pos),
read_n_items(read_num(ByteCode), NumArgs, TypeNumArgs, !Pos),
list.map(map.lookup(TypeTable), TypeNumArgs, TypeRepArgs),
TypeRep = higher_order_type_rep(TypeRepArgs, no)
;
Selector = 12,
read_num(ByteCode, NumArgs, !Pos),
read_n_items(read_num(ByteCode), NumArgs, TypeNumArgs, !Pos),
list.map(map.lookup(TypeTable), TypeNumArgs, TypeRepArgs),
read_num(ByteCode, TypeNumReturn, !Pos),
map.lookup(TypeTable, TypeNumReturn, TypeRepReturn),
TypeRep = higher_order_type_rep(TypeRepArgs, yes(TypeRepReturn))
;
Selector = 13,
read_num(ByteCode, VarNum, !Pos),
TypeRep = type_var_rep(VarNum)
;
% XXX in order to avoid bumping the deep profiler binary compatibility
% version number when the fixed size integers were added, the newly
% added types were assigned unused Selector values. The next time the
% format of the program representation file is changed for some
% unavoidable reason this should be tidied up.
Selector = 14,
TypeRep = builtin_type_rep(builtin_type_int8_rep)
;
Selector = 15,
TypeRep = builtin_type_rep(builtin_type_uint8_rep)
;
Selector = 16,
TypeRep = builtin_type_rep(builtin_type_int16_rep)
;
Selector = 17,
TypeRep = builtin_type_rep(builtin_type_uint16_rep)
;
Selector = 18,
TypeRep = builtin_type_rep(builtin_type_int32_rep)
;
Selector = 19,
TypeRep = builtin_type_rep(builtin_type_uint32_rep)
;
Selector = 20,
TypeRep = builtin_type_rep(builtin_type_int64_rep)
;
Selector = 21,
TypeRep = builtin_type_rep(builtin_type_uint64_rep)
).
%---------------------%
:- pred read_proc_reps(bool::in, bytecode::in, string_table::in,
encoded_type_table::in, proc_map(unit)::in, proc_map(unit)::out,
int::in, int::out) is semidet.
read_proc_reps(ExpectNewFormat, ByteCode, StringTable, TypeTable, !ProcReps,
!Pos) :-
read_byte(ByteCode, MoreByte, !Pos),
is_more_procs(MoreByte, MoreProcs),
(
MoreProcs = no_more_procs
;
MoreProcs = next_proc,
read_proc_rep(ExpectNewFormat, ByteCode, StringTable, TypeTable,
ProcRep, !Pos),
map.det_insert(ProcRep ^ pr_id, ProcRep, !ProcReps),
disable_warning [suspicious_recursion] (
read_proc_reps(ExpectNewFormat, ByteCode, StringTable, TypeTable,
!ProcReps, !Pos)
)
).
:- pred read_proc_rep(bool::in, bytecode::in, string_table::in,
encoded_type_table::in, proc_rep(unit)::out, int::in, int::out) is semidet.
read_proc_rep(ExpectNewFormat, ByteCode, StringTable, TypeTable, ProcRep,
!Pos) :-
read_string_proc_label(ByteCode, ProcLabel, !Pos),
StartPos = !.Pos,
read_int32(ByteCode, Size, !Pos),
read_string_via_offset(ByteCode, StringTable, FileName, !Pos),
Info = read_proc_rep_info(FileName),
read_var_table(ExpectNewFormat, ByteCode, StringTable, TypeTable,
VarNumRep, VarNameTable, MaybeVarTypeTable, !Pos),
read_head_vars(VarNumRep, ByteCode, HeadVars, !Pos),
read_goal(VarNumRep, ByteCode, StringTable, Info, Goal, !Pos),
read_determinism(ByteCode, Detism, !Pos),
ProcDefnRep = proc_defn_rep(HeadVars, Goal, VarNameTable,
MaybeVarTypeTable, Detism),
expect(unify(!.Pos, StartPos + Size), $pred, "limit mismatch"),
ProcRep = proc_rep(ProcLabel, ProcDefnRep).
:- pred read_string_proc_label(bytecode::in, string_proc_label::out,
int::in, int::out) is semidet.
read_string_proc_label(ByteCode, ProcLabel, !Pos) :-
read_byte(ByteCode, Byte, !Pos),
is_proclabel_kind(Byte, ProcLabelKind),
(
ProcLabelKind = proclabel_special,
read_len_string(ByteCode, TypeName, !Pos),
read_len_string(ByteCode, TypeModule, !Pos),
read_len_string(ByteCode, DefModule, !Pos),
read_len_string(ByteCode, PredName, !Pos),
read_num(ByteCode, Arity, !Pos),
read_num(ByteCode, ModeNum, !Pos),
ProcLabel = str_special_proc_label(TypeName, TypeModule, DefModule,
PredName, Arity, ModeNum)
;
(
ProcLabelKind = proclabel_user_predicate,
PredOrFunc = pf_predicate
;
ProcLabelKind = proclabel_user_function,
PredOrFunc = pf_function
),
read_len_string(ByteCode, DeclModule, !Pos),
read_len_string(ByteCode, DefModule, !Pos),
read_len_string(ByteCode, PredName, !Pos),
read_num(ByteCode, Arity, !Pos),
read_num(ByteCode, ModeNum, !Pos),
ProcLabel = str_ordinary_proc_label(PredOrFunc, DeclModule, DefModule,
PredName, Arity, ModeNum)
).
%---------------------%
% Read the var table from the bytecode. The var table contains the names
% of all the variables used in the procedure representation, and may
% (or may not) also contain their types.
%
:- pred read_var_table(bool::in, bytecode::in, string_table::in,
encoded_type_table::in, var_num_rep::out, var_name_table::out,
maybe(var_type_table)::out, int::in, int::out) is semidet.
read_var_table(ExpectNewFormat, ByteCode, StringTable, TypeTable, VarNumRep,
VarNameTable, MaybeVarTypeTable, !Pos) :-
(
ExpectNewFormat = no,
read_var_num_rep(ByteCode, VarNumRep, !Pos),
read_int32(ByteCode, NumVarsInTable, !Pos),
read_var_name_table_entries(NumVarsInTable, VarNumRep, ByteCode,
StringTable, map.init, VarNameTable, !Pos),
MaybeVarTypeTable = no
;
ExpectNewFormat = yes,
read_var_flag(ByteCode, VarNumRep, IncludeVarNameTable,
IncludeVarTypes, !Pos),
(
IncludeVarNameTable = do_not_include_var_name_table,
expect(unify(IncludeVarTypes, do_not_include_var_types),
$pred, "var types but not names"),
map.init(VarNameTable),
MaybeVarTypeTable = no
;
IncludeVarNameTable = include_var_name_table,
(
IncludeVarTypes = do_not_include_var_types,
read_num(ByteCode, NumVarsInTable, !Pos),
read_var_name_table_entries(NumVarsInTable, VarNumRep,
ByteCode, StringTable, map.init, VarNameTable, !Pos),
MaybeVarTypeTable = no
;
IncludeVarTypes = include_var_types,
read_num(ByteCode, NumVarsInTable, !Pos),
read_var_name_type_table_entries(NumVarsInTable, VarNumRep,
ByteCode, StringTable, TypeTable, map.init, VarNameTable,
map.init, VarTypeTable, !Pos),
MaybeVarTypeTable = yes(VarTypeTable)
)
)
).
% Read entries from the variable name table until there are no more
% entries left to read.
%
:- pred read_var_name_table_entries(var_rep::in, var_num_rep::in,
bytecode::in, string_table::in, var_name_table::in, var_name_table::out,
int::in, int::out) is semidet.
read_var_name_table_entries(NumVarsLeftInTable, VarNumRep,
ByteCode, StringTable, !VarNameTable, !Pos) :-
( if NumVarsLeftInTable > 0 then
read_var(VarNumRep, ByteCode, VarRep, !Pos),
read_string_via_offset(ByteCode, StringTable, VarName, !Pos),
map.det_insert(VarRep, VarName, !VarNameTable),
read_var_name_table_entries(NumVarsLeftInTable - 1, VarNumRep,
ByteCode, StringTable, !VarNameTable, !Pos)
else
% No more variables to read.
true
).
% Read entries from the variable name and type table until
% there are no more entries left to read.
%
:- pred read_var_name_type_table_entries(var_rep::in, var_num_rep::in,
bytecode::in, string_table::in, encoded_type_table::in,
var_name_table::in, var_name_table::out,
var_type_table::in, var_type_table::out, int::in, int::out) is semidet.
read_var_name_type_table_entries(NumVarsLeftInTable, VarNumRep,
ByteCode, StringTable, TypeTable, !VarNameTable, !VarTypeTable, !Pos) :-
( if NumVarsLeftInTable > 0 then
read_var(VarNumRep, ByteCode, VarRep, !Pos),
read_string_via_offset(ByteCode, StringTable, VarName, !Pos),
map.det_insert(VarRep, VarName, !VarNameTable),
read_num(ByteCode, TypeNum, !Pos),
map.lookup(TypeTable, TypeNum, TypeRep),
map.det_insert(VarRep, TypeRep, !VarTypeTable),
read_var_name_type_table_entries(NumVarsLeftInTable - 1, VarNumRep,
ByteCode, StringTable, TypeTable, !VarNameTable, !VarTypeTable,
!Pos)
else
% No more variables to read.
true
).
%---------------------%
:- type read_proc_rep_info
---> read_proc_rep_info(
rpri_filename :: string
).
:- pred read_goal(var_num_rep::in, bytecode::in, string_table::in,
read_proc_rep_info::in, goal_rep::out, int::in, int::out) is semidet.
read_goal(VarNumRep, ByteCode, StringTable, Info, Goal, !Pos) :-
read_byte(ByteCode, GoalTypeByte, !Pos),
( if byte_to_goal_type(GoalTypeByte, GoalType) then
(
GoalType = goal_conj,
read_goals(VarNumRep, ByteCode, StringTable, Info, Goals, !Pos),
GoalExpr = conj_rep(Goals)
;
GoalType = goal_disj,
read_goals(VarNumRep, ByteCode, StringTable, Info, Goals, !Pos),
GoalExpr = disj_rep(Goals)
;
GoalType = goal_neg,
disable_warning [suspicious_recursion] (
read_goal(VarNumRep, ByteCode, StringTable, Info, SubGoal,
!Pos)
),
GoalExpr = negation_rep(SubGoal)
;
GoalType = goal_ite,
disable_warning [suspicious_recursion] (
read_goal(VarNumRep, ByteCode, StringTable, Info, Cond, !Pos),
read_goal(VarNumRep, ByteCode, StringTable, Info, Then, !Pos),
read_goal(VarNumRep, ByteCode, StringTable, Info, Else, !Pos)
),
GoalExpr = ite_rep(Cond, Then, Else)
;
GoalType = goal_switch,
read_switch_can_fail(ByteCode, CanFail, !Pos),
read_var(VarNumRep, ByteCode, Var, !Pos),
read_cases(VarNumRep, ByteCode, StringTable, Info, Cases, !Pos),
GoalExpr = switch_rep(Var, CanFail, Cases)
;
GoalType = goal_assign,
read_var(VarNumRep, ByteCode, Target, !Pos),
read_var(VarNumRep, ByteCode, Source, !Pos),
AtomicGoal = unify_assign_rep(Target, Source),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_construct,
read_var(VarNumRep, ByteCode, Var, !Pos),
read_cons_id(ByteCode, StringTable, ConsId, !Pos),
read_vars(VarNumRep, ByteCode, ArgVars, !Pos),
AtomicGoal = unify_construct_rep(Var, ConsId, ArgVars),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_deconstruct,
read_var(VarNumRep, ByteCode, Var, !Pos),
read_cons_id(ByteCode, StringTable, ConsId, !Pos),
read_vars(VarNumRep, ByteCode, ArgVars, !Pos),
AtomicGoal = unify_deconstruct_rep(Var, ConsId, ArgVars),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_partial_construct,
read_var(VarNumRep, ByteCode, Var, !Pos),
read_cons_id(ByteCode, StringTable, ConsId, !Pos),
read_maybe_vars(VarNumRep, ByteCode, MaybeVars, !Pos),
AtomicGoal = partial_construct_rep(Var, ConsId, MaybeVars),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_partial_deconstruct,
read_var(VarNumRep, ByteCode, Var, !Pos),
read_cons_id(ByteCode, StringTable, ConsId, !Pos),
read_maybe_vars(VarNumRep, ByteCode, MaybeVars, !Pos),
AtomicGoal = partial_deconstruct_rep(Var, ConsId, MaybeVars),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_simple_test,
read_var(VarNumRep, ByteCode, Var1, !Pos),
read_var(VarNumRep, ByteCode, Var2, !Pos),
AtomicGoal = unify_simple_test_rep(Var1, Var2),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_scope,
read_byte(ByteCode, MaybeCutByte, !Pos),
( if cut_byte(MaybeCutPrime, MaybeCutByte) then
MaybeCut = MaybeCutPrime
else
unexpected($pred, "bad maybe_cut")
),
disable_warning [suspicious_recursion] (
read_goal(VarNumRep, ByteCode, StringTable, Info, SubGoal,
!Pos)
),
GoalExpr = scope_rep(SubGoal, MaybeCut)
;
GoalType = goal_ho_call,
read_var(VarNumRep, ByteCode, Var, !Pos),
read_vars(VarNumRep, ByteCode, Args, !Pos),
AtomicGoal = higher_order_call_rep(Var, Args),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_method_call,
read_var(VarNumRep, ByteCode, Var, !Pos),
read_method_num(ByteCode, MethodNum, !Pos),
read_vars(VarNumRep, ByteCode, Args, !Pos),
AtomicGoal = method_call_rep(Var, MethodNum, Args),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_cast,
read_var(VarNumRep, ByteCode, OutputVar, !Pos),
read_var(VarNumRep, ByteCode, InputVar, !Pos),
AtomicGoal = cast_rep(OutputVar, InputVar),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_plain_call,
read_string_via_offset(ByteCode, StringTable, ModuleName, !Pos),
read_string_via_offset(ByteCode, StringTable, PredName, !Pos),
read_vars(VarNumRep, ByteCode, Args, !Pos),
AtomicGoal = plain_call_rep(ModuleName, PredName, Args),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_builtin_call,
read_string_via_offset(ByteCode, StringTable, ModuleName, !Pos),
read_string_via_offset(ByteCode, StringTable, PredName, !Pos),
read_vars(VarNumRep, ByteCode, Args, !Pos),
AtomicGoal = builtin_call_rep(ModuleName, PredName, Args),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_event_call,
read_string_via_offset(ByteCode, StringTable, EventName, !Pos),
read_vars(VarNumRep, ByteCode, Args, !Pos),
AtomicGoal = event_call_rep(EventName, Args),
read_atomic_info(VarNumRep, ByteCode, StringTable,
Info, AtomicGoal, GoalExpr, !Pos)
;
GoalType = goal_foreign,
read_vars(VarNumRep, ByteCode, Args, !Pos),
AtomicGoal = pragma_foreign_code_rep(Args),
read_atomic_info(VarNumRep, ByteCode, StringTable, Info,
AtomicGoal, GoalExpr, !Pos)
),
read_determinism(ByteCode, Detism, !Pos),
Goal = goal_rep(GoalExpr, Detism, unit)
else
unexpected($pred, "invalid goal type")
).
:- pred read_atomic_info(var_num_rep::in, bytecode::in, string_table::in,
read_proc_rep_info::in, atomic_goal_rep::in, goal_expr_rep(unit)::out,
int::in, int::out) is semidet.
read_atomic_info(VarNumRep, ByteCode, StringTable, Info, AtomicGoal, GoalExpr,
!Pos) :-
read_string_via_offset(ByteCode, StringTable, FileName0, !Pos),
( if FileName0 = "" then
FileName = Info ^ rpri_filename
else
FileName = FileName0
),
read_lineno(ByteCode, LineNo, !Pos),
read_vars(VarNumRep, ByteCode, BoundVars, !Pos),
GoalExpr = atomic_goal_rep(FileName, LineNo, BoundVars, AtomicGoal).
:- pred read_goals(var_num_rep::in, bytecode::in, string_table::in,
read_proc_rep_info::in, list(goal_rep)::out, int::in, int::out) is semidet.
read_goals(VarNumRep, ByteCode, StringTable, Info, Goals, !Pos) :-
read_length(ByteCode, Len, !Pos),
read_n_items(read_goal(VarNumRep, ByteCode, StringTable, Info), Len, Goals,
!Pos).
:- pred read_cases(var_num_rep::in, bytecode::in, string_table::in,
read_proc_rep_info::in, list(case_rep(unit))::out, int::in, int::out)
is semidet.
read_cases(VarNumRep, ByteCode, StringTable, Info, Cases, !Pos) :-
read_length(ByteCode, Len, !Pos),
read_n_items(read_case(VarNumRep, ByteCode, StringTable, Info), Len, Cases,
!Pos).
:- pred read_case(var_num_rep::in, bytecode::in, string_table::in,
read_proc_rep_info::in, case_rep(unit)::out,
int::in, int::out) is semidet.
read_case(VarNumRep, ByteCode, StringTable, Info, Case, !Pos) :-
read_cons_id_arity(ByteCode, StringTable, MainConsId, !Pos),
read_length(ByteCode, NumOtherConsIds, !Pos),
read_n_items(read_cons_id_arity(ByteCode, StringTable), NumOtherConsIds,
OtherConsIds, !Pos),
read_goal(VarNumRep, ByteCode, StringTable, Info, Goal, !Pos),
Case = case_rep(MainConsId, OtherConsIds, Goal).
:- pred read_cons_id_arity(bytecode::in, string_table::in,
cons_id_arity_rep::out, int::in, int::out) is semidet.
read_cons_id_arity(ByteCode, StringTable, ConsId, !Pos) :-
read_cons_id(ByteCode, StringTable, ConsIdFunctor, !Pos),
read_short(ByteCode, ConsIdArity, !Pos),
ConsId = cons_id_arity_rep(ConsIdFunctor, ConsIdArity).
:- pred read_vars(var_num_rep::in, bytecode::in, list(var_rep)::out,
int::in, int::out) is semidet.
read_vars(VarNumRep, ByteCode, Vars, !Pos) :-
read_length(ByteCode, Len, !Pos),
read_n_items(read_var(VarNumRep, ByteCode), Len, Vars, !Pos).
:- pred read_var(var_num_rep::in, bytecode::in, var_rep::out,
int::in, int::out) is semidet.
read_var(VarNumRep, ByteCode, Var, !Pos) :-
(
VarNumRep = var_num_1_byte,
read_byte(ByteCode, Var, !Pos)
;
VarNumRep = var_num_2_bytes,
read_short(ByteCode, Var, !Pos)
;
VarNumRep = var_num_4_bytes,
read_int32(ByteCode, Var, !Pos)
).
:- pred read_maybe_vars(var_num_rep::in, bytecode::in,
list(maybe(var_rep))::out, int::in, int::out) is semidet.
read_maybe_vars(VarNumRep, ByteCode, MaybeVars, !Pos) :-
read_length(ByteCode, Len, !Pos),
read_n_items(read_maybe_var(VarNumRep, ByteCode), Len, MaybeVars, !Pos).
:- pred read_maybe_var(var_num_rep::in, bytecode::in,
maybe(var_rep)::out, int::in, int::out) is semidet.
read_maybe_var(VarNumRep, ByteCode, MaybeVar, !Pos) :-
read_byte(ByteCode, YesOrNo, !Pos),
( if YesOrNo = 1 then
read_var(VarNumRep, ByteCode, Var, !Pos),
MaybeVar = yes(Var)
else if YesOrNo = 0 then
MaybeVar = no
else
unexpected($pred, "invalid yes or no flag")
).
:- pred read_head_vars(var_num_rep::in, bytecode::in,
list(head_var_rep)::out, int::in, int::out) is semidet.
read_head_vars(VarNumRep, ByteCode, HeadVars, !Pos) :-
read_length(ByteCode, Len, !Pos),
read_n_items(read_head_var(VarNumRep, ByteCode), Len, HeadVars, !Pos).
:- pred read_head_var(var_num_rep::in, bytecode::in, head_var_rep::out,
int::in, int::out) is semidet.
read_head_var(VarNumRep, ByteCode, HeadVar, !Pos) :-
read_var(VarNumRep, ByteCode, Var, !Pos),
read_inst(ByteCode, InitialInst, !Pos),
read_inst(ByteCode, FinalInst, !Pos),
HeadVar = head_var_rep(Var, var_mode_rep(InitialInst, FinalInst)).
:- pred read_inst(bytecode::in, inst_rep::out, int::in, int::out) is semidet.
read_inst(ByteCode, Inst, !Pos) :-
read_byte(ByteCode, Byte, !Pos),
inst_representation(Inst, Byte).
:- pred read_length(bytecode::in, var_rep::out, int::in, int::out) is semidet.
read_length(ByteCode, Len, !Pos) :-
read_int32(ByteCode, Len, !Pos).
:- pred read_lineno(bytecode::in, int::out, int::in, int::out) is semidet.
read_lineno(ByteCode, LineNo, !Pos) :-
read_int32(ByteCode, LineNo, !Pos).
:- pred read_method_num(bytecode::in, int::out, int::in, int::out) is semidet.
read_method_num(ByteCode, MethodNum, !Pos) :-
read_short(ByteCode, MethodNum, !Pos).
:- pred read_cons_id(bytecode::in, string_table::in, cons_id_rep::out,
int::in, int::out) is semidet.
read_cons_id(ByteCode, StringTable, ConsId, !Pos) :-
read_string_via_offset(ByteCode, StringTable, ConsId, !Pos).
:- pred read_var_num_rep(bytecode::in, var_num_rep::out, int::in, int::out)
is semidet.
read_var_num_rep(ByteCode, VarNumRep, !Pos) :-
read_byte(ByteCode, Byte, !Pos),
( if var_num_rep_byte(VarNumRepPrime, Byte) then
VarNumRep = VarNumRepPrime
else
unexpected($pred, "unknown var_num_rep")
).
:- pred read_var_flag(bytecode::in, var_num_rep::out,
maybe_include_var_name_table::out, maybe_include_var_types::out,
int::in, int::out) is semidet.
read_var_flag(ByteCode, VarNumRep, IncludeVarNameTable, IncludeVarTypes,
!Pos) :-
read_byte(ByteCode, Byte, !Pos),
( if
var_flag_byte(VarNumRepPrime,
IncludeVarNameTablePrime, IncludeVarTypesPrime, Byte)
then
VarNumRep = VarNumRepPrime,
IncludeVarNameTable = IncludeVarNameTablePrime,
IncludeVarTypes = IncludeVarTypesPrime
else
unexpected($pred, "unknown var_flag_byte")
).
:- pred read_determinism(bytecode::in, detism_rep::out, int::in, int::out)
is semidet.
read_determinism(ByteCode, Detism, !Pos) :-
read_byte(ByteCode, DetismByte, !Pos),
( if determinism_representation(DetismPrime, DetismByte) then
Detism = DetismPrime
else
unexpected($pred, "bad detism")
).
:- pred read_switch_can_fail(bytecode::in, switch_can_fail_rep::out,
int::in, int::out) is semidet.
read_switch_can_fail(Bytecode, CanFail, !Pos) :-
read_byte(Bytecode, CanFailByte, !Pos),
( if
(
CanFailByte = 0,
CanFailPrime = switch_can_fail_rep
;
CanFailByte = 1,
CanFailPrime = switch_can_not_fail_rep
)
then
CanFail = CanFailPrime
else
unexpected($pred, "bad switch_can_fail")
).
%---------------------------------------------------------------------------%
:- type more_modules
---> no_more_modules
; next_module.
:- pragma foreign_enum("C", more_modules/0, [
no_more_modules - "MR_no_more_modules",
next_module - "MR_next_module"
]).
:- pred is_more_modules(int::in, more_modules::out) is semidet.
:- pragma foreign_proc("C",
is_more_modules(Int::in, MoreModules::out),
[promise_pure, will_not_call_mercury, thread_safe],
"
MoreModules = (MR_MoreModules) Int;
switch (MoreModules) {
case MR_no_more_modules:
case MR_next_module:
SUCCESS_INDICATOR = MR_TRUE;
break;
default:
SUCCESS_INDICATOR = MR_FALSE;
break;
}
").
:- type more_procs
---> no_more_procs
; next_proc.
:- pragma foreign_enum("C", more_procs/0, [
no_more_procs - "MR_no_more_procs",
next_proc - "MR_next_proc"
]).
:- pred is_more_procs(int::in, more_procs::out) is semidet.
:- pragma foreign_proc("C",
is_more_procs(Int::in, MoreProcs::out),
[promise_pure, will_not_call_mercury, thread_safe],
"
MoreProcs = (MR_MoreProcs) Int;
switch (MoreProcs) {
case MR_no_more_procs:
case MR_next_proc:
SUCCESS_INDICATOR = MR_TRUE;
break;
default:
SUCCESS_INDICATOR = MR_FALSE;
break;
}
").
:- pragma foreign_enum("C", proclabel_kind_token/0, [
proclabel_user_predicate - "MR_proclabel_user_predicate",
proclabel_user_function - "MR_proclabel_user_function",
proclabel_special - "MR_proclabel_special"
]).
:- pragma foreign_proc("C",
is_proclabel_kind(Int::in, ProcLabelKind::out),
[promise_pure, will_not_call_mercury, thread_safe],
"
ProcLabelKind = (MR_ProcLabelToken) Int;
switch (ProcLabelKind) {
case MR_proclabel_user_predicate:
case MR_proclabel_user_function:
case MR_proclabel_special:
SUCCESS_INDICATOR = MR_TRUE;
break;
default:
SUCCESS_INDICATOR = MR_FALSE;
break;
}
").
%---------------------------------------------------------------------------%
% An abstraction to read the given number of items using the higher order
% predicate.
%
:- pred read_n_items(pred(T, int, int), int, list(T), int, int).
:- mode read_n_items(in(pred(out, in, out) is det), in, out, in, out) is det.
:- mode read_n_items(in(pred(out, in, out) is semidet), in, out, in, out)
is semidet.
read_n_items(Read, N, Items, !Pos) :-
( if N > 0 then
Read(Item, !Pos),
read_n_items(Read, N - 1, TailItems, !Pos),
Items = [ Item | TailItems ]
else
Items = []
).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
no_type_info_builtin(ModuleName, PredName, Arity) :-
% NOTE Any predicates listed here should also be handled by
% process_no_type_info_builtin in compiler/term_constr_initial.m.
(
PredName = "unsafe_promise_unique", Arity = 2,
ModuleName = mercury_public_builtin_module
;
( PredName = "builtin_compound_eq", Arity = 2
; PredName = "builtin_compound_lt", Arity = 2
; PredName = "compare_local_int16_bitfields", Arity = 4
; PredName = "compare_local_int32_bitfields", Arity = 4
; PredName = "compare_local_int8_bitfields", Arity = 4
; PredName = "compare_local_uint_bitfields", Arity = 5
; PredName = "compare_local_uint_words", Arity = 3
; PredName = "compare_remote_int16_bitfields", Arity = 6
; PredName = "compare_remote_int32_bitfields", Arity = 6
; PredName = "compare_remote_int8_bitfields", Arity = 6
; PredName = "compare_remote_uint_bitfields", Arity = 7
; PredName = "compare_remote_uint_words", Arity = 5
; PredName = "instance_constraint_from_typeclass_info", Arity = 3
; PredName = "partial_inst_copy", Arity = 2
; PredName = "store_at_ref_impure", Arity = 2
; PredName = "superclass_from_typeclass_info", Arity = 3
; PredName = "type_info_from_typeclass_info", Arity = 3
; PredName = "unconstrained_type_info_from_typeclass_info", Arity = 3
; PredName = "unify_remote_arg_words", Arity = 4
; PredName = "unsafe_type_cast", Arity = 2
),
ModuleName = mercury_private_builtin_module
;
( PredName = "table_lookup_insert_enum", Arity = 4
; PredName = "table_lookup_insert_typeclassinfo", Arity = 3
; PredName = "table_lookup_insert_typeinfo", Arity = 3
; PredName = "table_restore_any_answer", Arity = 3
),
ModuleName = mercury_table_builtin_module
;
PredName = "increment_size", Arity = 2,
ModuleName = mercury_term_size_prof_builtin_module
;
( PredName = "get_future", Arity = 2
; PredName = "new_future", Arity = 2
; PredName = "signal_future", Arity = 2
; PredName = "wait_future", Arity = 2
),
ModuleName = mercury_par_builtin_module
;
( PredName = "result_call_4", Arity = 4
; PredName = "result_call_5", Arity = 5
; PredName = "result_call_6", Arity = 6
; PredName = "result_call_7", Arity = 7
; PredName = "result_call_8", Arity = 8
; PredName = "result_call_9", Arity = 9
; PredName = "semidet_call_3", Arity = 3
; PredName = "semidet_call_4", Arity = 4
; PredName = "semidet_call_5", Arity = 5
; PredName = "semidet_call_6", Arity = 6
; PredName = "semidet_call_7", Arity = 7
; PredName = "semidet_call_8", Arity = 8
),
ModuleName = mercury_rtti_implementation_builtin_module
).
% True iff the given predicate has a `:- pragma external_pred' declaration.
% Note that the arity includes the hidden type info arguments for
% polymorphic predicates.
%
:- pred pred_is_external(string::in, string::in, int::in) is semidet.
pred_is_external("exception", "builtin_catch", 4).
pred_is_external("exception", "builtin_throw", 1).
pred_is_external("builtin", "unify", 3).
pred_is_external("builtin", "compare", 4).
pred_is_external("builtin", "compare_representation", 4).
pred_is_external("backjump", "builtin_choice_id", 1).
pred_is_external("backjump", "builtin_backjump", 1).
pred_is_external("par_builtin", "lc_finish", 1).
pred_is_external("par_builtin", "lc_wait_free_slot", 2).
%---------------------------------------------------------------------------%
%
% Please keep runtime/mercury_deep_profiling.h updated when modifying this
% section.
%
:- pragma foreign_enum("C", cp_type/0,
[
cp_type_coverage_after - "MR_cp_type_coverage_after",
cp_type_branch_arm - "MR_cp_type_branch_arm"
]).
coverage_point_type_c_value(cp_type_coverage_after,
"MR_cp_type_coverage_after").
coverage_point_type_c_value(cp_type_branch_arm,
"MR_cp_type_branch_arm").
%---------------------------------------------------------------------------%
:- end_module mdbcomp.program_representation.
%---------------------------------------------------------------------------%