mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-18 02:43:40 +00:00
trace/mercury_trace_cmd_developer.c:
trace/mercury_trace_tables.[ch]:
Add two options to the mdb command "ambiguity".
Print ambiguities between function and predicate forms of the same
operation, such as list.length, only if the new option -b, or
--both-pred-and-func, is given.
Print ambiguities involving procedures that were created by type
specialization only if the new option -s, or --typespec is given.
(The -t option name was already taken.)
These changes remove from the ambiguity command's output
(some of) the parts that are not useful when one wants to eliminate
ambiguities by renaming.
Clarify a heading.
doc/user_guide.texi:
Document the above changes.
runtime/mercury_proc_id.h:
Fix a field name that has become misleading.
MR_UserProcId_Structs have a field named MR_user_arity.
In this name, the "MR_user_" part is a prefix shared by the other
fields in that structure, to indicate that they are part of the id
of a user-defined procedure, as opposed to a compiler-created
unify, compare or index procedure. However, the arity it contains
is what the compiler now calls a pred_form_arity: it does not count
type_info and typeclass_info arguments added by polymorphism, but
it *does* count function return values for functions. This is now
misleading, because in the compiler, a user_arity does *not* count
function return values for functions.
Replace this field name with MR_user_pred_form_arity, which tells
readers that this arity is a pred_form_arity. The presence of the
"user" part of the name may still cause some confusion, but at least
that confusion should motivate readers to look up the field name,
whose comment should clarify things.
mdbcomp/rtti_access.m:
runtime/mercury_debug.c:
runtime/mercury_deep_profiling.c:
runtime/mercury_ho_call.c:
runtime/mercury_layout_util.c:
runtime/mercury_ml_expand_body.h:
runtime/mercury_stack_layout.h:
runtime/mercury_trace_base.c:
trace/mercury_trace.c:
trace/mercury_trace_external.c:
trace/mercury_trace_util.c:
Conform to the change in mercury_proc_id.h.
tests/debugger/ambiguity.{m,inp,exp}:
tests/debugger/ambiguity_helper.m:
Expand this test case to test the new functionality.
The type specialized predicates are in a new helper module,
because this is the simplest way to avoid dead procedure elimination
deleting any of the predicates whose names we want to test for ambiguities.
890 lines
29 KiB
Mathematica
890 lines
29 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2005-2007, 2009-2011 The University of Melbourne.
|
|
% Copyright (C) 2014-2015, 2017-2018 The Mercury team.
|
|
% This file is distributed under the terms specified in COPYING.LIB.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: rtti_access.m.
|
|
% Main authors: zs, maclarty
|
|
%
|
|
% This module contains an interface to the label_layout and proc_layout
|
|
% types which are used in the C backend of the debugger.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module mdbcomp.rtti_access.
|
|
:- interface.
|
|
|
|
:- import_module mdbcomp.goal_path.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module mdbcomp.trace_counts.
|
|
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
|
|
:- type label_layout.
|
|
|
|
:- func get_proc_layout_from_label_layout(label_layout) = proc_layout.
|
|
|
|
:- func get_goal_path_from_label_layout(label_layout) = goal_path_string.
|
|
|
|
:- func get_goal_path_from_maybe_label(maybe(label_layout)) = goal_path_string.
|
|
|
|
:- func get_port_from_label_layout(label_layout) = trace_port.
|
|
|
|
:- func get_path_port_from_label_layout(label_layout) = path_port.
|
|
|
|
:- pred get_context_from_label_layout(label_layout::in, string::out, int::out)
|
|
is semidet.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type proc_layout.
|
|
|
|
:- func get_proc_label_from_layout(proc_layout) = proc_label.
|
|
|
|
:- func get_proc_name(proc_label) = string.
|
|
|
|
% find_initial_version_arg_num(Proc, OutputArgNum, InputArgNum):
|
|
%
|
|
% Given a procedure and an output argument number of that procedure,
|
|
% find an input argument which has the same name as the output argument,
|
|
% expect for a numerical suffix and possibly an underscore. The output
|
|
% argument name needn't have a numerical suffix, but if it does, then the
|
|
% input argument's numerical suffix should be less that the numerical
|
|
% suffix of the output argument. This procedure is used as a heuristic to
|
|
% determine when it is worth checking if a subterm appearing in the output
|
|
% argument also appears in the same position in the input argument.
|
|
% The heuristic is used by the subterm dependency tracking algorithm
|
|
% to help speed up the search.
|
|
% Argument numbers start at one.
|
|
% This procedure is implemented in C to avoid having to allocate memory
|
|
% to import non-word-aligned strings into Mercury code.
|
|
%
|
|
:- pred find_initial_version_arg_num(proc_layout::in, int::in, int::out)
|
|
is semidet.
|
|
|
|
:- func get_all_modes_for_layout(proc_layout) = list(proc_layout).
|
|
|
|
:- func containing_proc_layout(label_layout) = proc_layout.
|
|
|
|
:- func proc_bytecode_bytes(proc_layout) = bytecode_bytes.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type string_table
|
|
---> string_table(
|
|
string_table_chars,
|
|
% The characters of the string table, which may include
|
|
% null characters.
|
|
|
|
int
|
|
% The number of characters in the string table.
|
|
).
|
|
|
|
:- type module_layout.
|
|
:- type string_table_chars.
|
|
|
|
:- pred containing_module_layout(proc_layout::in, module_layout::out)
|
|
is semidet.
|
|
|
|
:- func module_string_table(module_layout) = string_table.
|
|
|
|
:- func lookup_string_table(string_table, int) = string.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type bytecode
|
|
---> bytecode(
|
|
bytecode_bytes, % The bytes of the bytecode.
|
|
int % The number of bytes in the bytecode.
|
|
).
|
|
|
|
:- type bytecode_bytes
|
|
---> dummy_bytecode_bytes.
|
|
|
|
:- pragma foreign_type("C", bytecode_bytes, "const MR_uint_least8_t *",
|
|
[can_pass_as_mercury_type, stable]).
|
|
% The following definitions are only stubs.
|
|
:- pragma foreign_type("C#", bytecode_bytes, "object", []).
|
|
:- pragma foreign_type("Java", bytecode_bytes, "java.lang.Object", []).
|
|
|
|
% read_byte(ByteCode, Byte, !Pos):
|
|
%
|
|
% Read a single byte.
|
|
%
|
|
:- pred read_byte(bytecode::in, int::out, int::in, int::out) is semidet.
|
|
|
|
% read_short(ByteCode, Short, !Pos):
|
|
%
|
|
% Read a short that is represented by two bytes.
|
|
%
|
|
:- pred read_short(bytecode::in, int::out, int::in, int::out) is semidet.
|
|
|
|
% read_int32(ByteCode, Int, !Pos):
|
|
%
|
|
% Read four byte integer.
|
|
%
|
|
:- pred read_int32(bytecode::in, int::out, int::in, int::out) is semidet.
|
|
|
|
% read_num(ByteCode, Num, !Pos):
|
|
%
|
|
% Read an integer encoded using the deep profiler's variable length
|
|
% encoding scheme.
|
|
%
|
|
:- pred read_num(bytecode::in, int::out, int::in, int::out) is semidet.
|
|
|
|
% read_string_via_offset(ByteCode, StringTable, String, !Pos):
|
|
%
|
|
% Read a string represented as a four-byte integer giving an offset
|
|
% in the string table.
|
|
%
|
|
:- pred read_string_via_offset(bytecode::in, string_table::in, string::out,
|
|
int::in, int::out) is semidet.
|
|
|
|
% read_line(ByteCode, Line, !Pos):
|
|
%
|
|
% Read a sequence of characters ending in a newline.
|
|
%
|
|
:- pred read_line(bytecode::in, string::out, int::in, int::out) is semidet.
|
|
|
|
% read_len_string(ByteCode, String, !Pos):
|
|
%
|
|
% Read a string represented as a <length, characters> sequence, in which
|
|
% the length is encoded using the deep profiler's variable length
|
|
% encoding scheme.
|
|
%
|
|
:- pred read_len_string(bytecode::in, string::out, int::in, int::out)
|
|
is semidet.
|
|
|
|
% read_string_table(ByteCode, StringTable, !Pos):
|
|
%
|
|
% Given that ByteCode contains a string table starting at the position
|
|
% given by !.Pos, return that string table and set !:Pos to point to
|
|
% the first byte after it.
|
|
%
|
|
:- pred read_string_table(bytecode::in, string_table::out,
|
|
int::in, int::out) is semidet.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred encode_byte(int::in, list(int)::out) is semidet.
|
|
:- pred encode_byte_det(int::in, list(int)::out) is det.
|
|
:- func encode_byte_func(int) = list(int).
|
|
|
|
:- pred encode_short(int::in, list(int)::out) is semidet.
|
|
:- pred encode_short_det(int::in, list(int)::out) is det.
|
|
:- func encode_short_func(int) = list(int).
|
|
|
|
:- pred encode_int32(int::in, list(int)::out) is semidet.
|
|
:- pred encode_int32_det(int::in, list(int)::out) is det.
|
|
:- func encode_int32_func(int) = list(int).
|
|
|
|
:- pred encode_num(int::in, list(int)::out) is semidet.
|
|
:- pred encode_num_det(int::in, list(int)::out) is det.
|
|
:- func encode_num_func(int) = list(int).
|
|
|
|
:- pred encode_len_string(string::in, list(int)::out) is det.
|
|
:- func encode_len_string_func(string) = list(int).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module mdbcomp.sym_name.
|
|
|
|
:- import_module char.
|
|
:- import_module int.
|
|
:- import_module require.
|
|
:- import_module string.
|
|
|
|
:- pragma foreign_type("C", label_layout, "const MR_LabelLayout *",
|
|
[can_pass_as_mercury_type, stable]).
|
|
% The following definitions are only stubs.
|
|
:- pragma foreign_type("C#", label_layout, "object", []).
|
|
:- pragma foreign_type("Java", label_layout, "java.lang.Object", []).
|
|
|
|
:- pragma foreign_proc("C",
|
|
get_proc_layout_from_label_layout(Label::in) = (ProcLayout::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
ProcLayout = Label->MR_sll_entry;
|
|
").
|
|
|
|
:- pragma foreign_proc("C",
|
|
get_goal_path_from_label_layout(Label::in) = (GoalPath::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
GoalPath = (MR_String) MR_label_goal_path(Label);
|
|
").
|
|
|
|
get_goal_path_from_maybe_label(yes(Label))
|
|
= get_goal_path_from_label_layout(Label).
|
|
get_goal_path_from_maybe_label(no) = "".
|
|
|
|
:- pragma foreign_proc("C",
|
|
get_context_from_label_layout(Label::in, FileName::out, LineNo::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
const char *filename;
|
|
int line_no;
|
|
|
|
SUCCESS_INDICATOR = MR_find_context(Label, &filename, &line_no);
|
|
LineNo = (MR_Integer) line_no;
|
|
MR_TRACE_USE_HP(
|
|
MR_make_aligned_string(FileName, (MR_String) filename);
|
|
);
|
|
").
|
|
|
|
:- pragma foreign_proc("C",
|
|
get_port_from_label_layout(Label::in) = (Port::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
Port = Label->MR_sll_port;
|
|
").
|
|
|
|
get_path_port_from_label_layout(Label) = PathPort :-
|
|
Port = get_port_from_label_layout(Label),
|
|
GoalPathStr = get_goal_path_from_label_layout(Label),
|
|
rev_goal_path_from_string_det(GoalPathStr, GoalPath),
|
|
PathPort = make_path_port(GoalPath, Port).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pragma foreign_type("C", proc_layout, "const MR_ProcLayout *",
|
|
[can_pass_as_mercury_type, stable]).
|
|
% The following definitions are only stubs.
|
|
:- pragma foreign_type("C#", proc_layout, "object", []).
|
|
:- pragma foreign_type("Java", proc_layout, "java.lang.Object", []).
|
|
|
|
get_proc_label_from_layout(Layout) = ProcLabel :-
|
|
( if proc_layout_is_uci(Layout) then
|
|
proc_layout_get_uci_fields(Layout, TypeName, TypeModule,
|
|
DefModule, PredName, TypeArity, ModeNum),
|
|
( special_pred_name_arity(SpecialIdPrime, _, PredName, _) ->
|
|
SpecialId = SpecialIdPrime
|
|
;
|
|
unexpected($pred, "bad special_pred_id")
|
|
),
|
|
SymDefModule = string_to_sym_name(DefModule),
|
|
SymTypeModule = string_to_sym_name(TypeModule),
|
|
ProcLabel = special_proc_label(SymDefModule, SpecialId,
|
|
SymTypeModule, TypeName, TypeArity, ModeNum)
|
|
else
|
|
proc_layout_get_non_uci_fields(Layout, PredOrFunc,
|
|
DeclModule, DefModule, PredName, Arity, ModeNum),
|
|
SymDefModule = string_to_sym_name(DefModule),
|
|
SymDeclModule = string_to_sym_name(DeclModule),
|
|
ProcLabel = ordinary_proc_label(SymDefModule, PredOrFunc,
|
|
SymDeclModule, PredName, Arity, ModeNum)
|
|
).
|
|
|
|
get_proc_name(ordinary_proc_label(_, _, _, ProcName, _, _)) = ProcName.
|
|
get_proc_name(special_proc_label(_, _, _, ProcName , _, _)) = ProcName.
|
|
|
|
:- pred proc_layout_is_uci(proc_layout::in) is semidet.
|
|
|
|
:- pragma foreign_proc("C",
|
|
proc_layout_is_uci(Layout::in),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
if (MR_PROC_ID_IS_UCI(Layout->MR_sle_proc_id)) {
|
|
SUCCESS_INDICATOR = MR_TRUE;
|
|
} else {
|
|
SUCCESS_INDICATOR = MR_FALSE;
|
|
}
|
|
").
|
|
|
|
:- pred proc_layout_get_uci_fields(proc_layout::in, string::out,
|
|
string::out, string::out, string::out, int::out, int::out) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
proc_layout_get_uci_fields(Layout::in, TypeName::out, TypeModule::out,
|
|
DefModule::out, PredName::out, TypeArity::out, ModeNum::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
const MR_UCIProcId *proc_id;
|
|
|
|
proc_id = &Layout->MR_sle_uci;
|
|
|
|
/* The casts are there to cast away const without warnings */
|
|
TypeName = (MR_String) (MR_Integer) proc_id->MR_uci_type_name;
|
|
TypeModule = (MR_String) (MR_Integer) proc_id->MR_uci_type_module;
|
|
DefModule = (MR_String) (MR_Integer) proc_id->MR_uci_def_module;
|
|
PredName = (MR_String) (MR_Integer) proc_id->MR_uci_pred_name;
|
|
TypeArity = proc_id->MR_uci_type_arity;
|
|
ModeNum = proc_id->MR_uci_mode;
|
|
").
|
|
|
|
:- pred proc_layout_get_non_uci_fields(proc_layout::in, pred_or_func::out,
|
|
string::out, string::out, string::out, int::out, int::out) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
proc_layout_get_non_uci_fields(Layout::in, PredOrFunc::out,
|
|
DeclModule::out, DefModule::out, PredName::out,
|
|
Arity::out, ModeNum::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
const MR_UserProcId *proc_id;
|
|
|
|
proc_id = &Layout->MR_sle_user;
|
|
|
|
/* The casts are there to cast away const without warnings */
|
|
PredOrFunc = proc_id->MR_user_pred_or_func;
|
|
DeclModule = (MR_String) (MR_Integer) proc_id->MR_user_decl_module;
|
|
DefModule = (MR_String) (MR_Integer) proc_id->MR_user_def_module;
|
|
PredName = (MR_String) (MR_Integer) proc_id->MR_user_name;
|
|
Arity = proc_id->MR_user_pred_form_arity;
|
|
ModeNum = proc_id->MR_user_mode;
|
|
").
|
|
|
|
:- pragma foreign_proc("C",
|
|
find_initial_version_arg_num(Layout::in, OutArgNum::in, InArgNum::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
const MR_ProcLayout *proc;
|
|
int out_hlds_num;
|
|
const char *out_name;
|
|
int should_copy_out;
|
|
|
|
proc = Layout;
|
|
|
|
if (! MR_PROC_LAYOUT_HAS_EXEC_TRACE(proc)) {
|
|
MR_fatal_error(""find_initial_version_arg_num: proc"");
|
|
}
|
|
|
|
out_hlds_num = proc->MR_sle_head_var_nums[OutArgNum - 1];
|
|
out_name = MR_hlds_var_name(proc, out_hlds_num, &should_copy_out);
|
|
if (out_name == NULL || MR_streq(out_name, """")) {
|
|
/* out_hlds_num was not named by the user */
|
|
SUCCESS_INDICATOR = MR_FALSE;
|
|
} else {
|
|
char out_name_buf[MR_MAX_VARNAME_SIZE];
|
|
int out_base_name_len;
|
|
int out_numerical_suffix;
|
|
int num_matches;
|
|
int in_hlds_num;
|
|
int in_arg_num;
|
|
const char *in_name;
|
|
int start_of_num;
|
|
int in_numerical_suffix;
|
|
int head_var_num;
|
|
int call_var_num;
|
|
int call_num_vars;
|
|
const MR_LabelLayout *call_label;
|
|
MR_bool found;
|
|
|
|
if (should_copy_out) {
|
|
strncpy(out_name_buf, out_name, sizeof(out_name_buf) - 1);
|
|
out_name_buf[sizeof(out_name_buf) - 1] = '\\0';
|
|
out_name = (const char *) out_name_buf;
|
|
}
|
|
|
|
start_of_num = MR_find_start_of_num_suffix(out_name);
|
|
if (start_of_num < 0) {
|
|
out_base_name_len = strlen(out_name);
|
|
out_numerical_suffix = -1;
|
|
} else {
|
|
out_base_name_len = start_of_num;
|
|
out_numerical_suffix = atoi(out_name + start_of_num);
|
|
}
|
|
|
|
num_matches = 0;
|
|
in_arg_num = -1;
|
|
|
|
for (head_var_num = 0; head_var_num < proc->MR_sle_num_head_vars;
|
|
head_var_num++)
|
|
{
|
|
in_hlds_num = proc->MR_sle_head_var_nums[head_var_num];
|
|
in_name = MR_hlds_var_name(proc, in_hlds_num, NULL);
|
|
if (in_name == NULL || MR_streq(in_name, """")) {
|
|
continue;
|
|
}
|
|
|
|
start_of_num = MR_find_start_of_num_suffix(in_name);
|
|
if (start_of_num < 0) {
|
|
continue;
|
|
}
|
|
|
|
if (! (
|
|
(
|
|
/*
|
|
** The names are exactly the same except
|
|
** for the numerical suffix.
|
|
*/
|
|
start_of_num == out_base_name_len &&
|
|
MR_strneq(out_name, in_name, start_of_num)
|
|
)
|
|
||
|
|
(
|
|
/*
|
|
** The names are exactly the same except
|
|
** for an underscore and the numerical suffix
|
|
** (as is the case with state variable notation).
|
|
*/
|
|
start_of_num == out_base_name_len + 1 &&
|
|
start_of_num > 0 &&
|
|
in_name[start_of_num - 1] == '_' &&
|
|
MR_strneq(out_name, in_name, start_of_num - 1)
|
|
)
|
|
))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
in_numerical_suffix = atoi(in_name + start_of_num);
|
|
if (! ((in_numerical_suffix >= out_numerical_suffix)
|
|
|| (out_numerical_suffix < 0)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
call_label = proc->MR_sle_call_label;
|
|
if (! MR_has_valid_var_count(call_label)) {
|
|
continue;
|
|
}
|
|
|
|
if (! MR_has_valid_var_info(call_label)) {
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
** The in_hlds_num has the same prefix as the output variable.
|
|
** Check if in_hlds_num is an input argument.
|
|
*/
|
|
call_num_vars = MR_all_desc_var_count(call_label);
|
|
found = MR_FALSE;
|
|
for (call_var_num = 0 ; call_var_num < call_num_vars;
|
|
call_var_num++)
|
|
{
|
|
if (call_label->MR_sll_var_nums[call_var_num] == in_hlds_num) {
|
|
found = MR_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (! found) {
|
|
continue;
|
|
}
|
|
|
|
num_matches++;
|
|
in_arg_num = head_var_num;
|
|
}
|
|
|
|
if (num_matches == 1) {
|
|
InArgNum = in_arg_num + 1;
|
|
SUCCESS_INDICATOR = MR_TRUE;
|
|
} else {
|
|
SUCCESS_INDICATOR = MR_FALSE;
|
|
}
|
|
}
|
|
").
|
|
|
|
:- pragma foreign_proc("C",
|
|
get_all_modes_for_layout(Layout::in) = (Layouts::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
const MR_ModuleLayout *module;
|
|
const MR_ProcLayout *proc;
|
|
int i;
|
|
MR_Word list;
|
|
MR_bool match;
|
|
const MR_ProcLayout *selected_proc;
|
|
|
|
selected_proc = Layout;
|
|
|
|
if (! MR_PROC_LAYOUT_HAS_EXEC_TRACE(selected_proc)) {
|
|
MR_fatal_error(""get_all_modes_for_layout: selected_proc"");
|
|
}
|
|
|
|
module = selected_proc->MR_sle_module_layout;
|
|
list = MR_list_empty();
|
|
for (i = 0; i < module->MR_ml_proc_count; i++) {
|
|
proc = module->MR_ml_procs[i];
|
|
if (! MR_PROC_LAYOUT_HAS_EXEC_TRACE(selected_proc)) {
|
|
MR_fatal_error(""get_all_modes_for_layout: proc"");
|
|
}
|
|
|
|
if (MR_PROC_LAYOUT_IS_UCI(selected_proc)
|
|
&& MR_PROC_LAYOUT_IS_UCI(proc))
|
|
{
|
|
const MR_UCIProcId *proc_id;
|
|
const MR_UCIProcId *selected_proc_id;
|
|
|
|
proc_id = &proc->MR_sle_uci;
|
|
selected_proc_id = &selected_proc->MR_sle_uci;
|
|
|
|
if (MR_streq(proc_id->MR_uci_type_name,
|
|
selected_proc_id->MR_uci_type_name)
|
|
&& MR_streq(proc_id->MR_uci_type_module,
|
|
selected_proc_id->MR_uci_type_module)
|
|
&& MR_streq(proc_id->MR_uci_pred_name,
|
|
selected_proc_id->MR_uci_pred_name)
|
|
&& (proc_id->MR_uci_type_arity ==
|
|
selected_proc_id->MR_uci_type_arity))
|
|
{
|
|
match = MR_TRUE;
|
|
} else {
|
|
match = MR_FALSE;
|
|
}
|
|
} else if (!MR_PROC_LAYOUT_IS_UCI(selected_proc)
|
|
&& !MR_PROC_LAYOUT_IS_UCI(proc))
|
|
{
|
|
const MR_UserProcId *proc_id;
|
|
const MR_UserProcId *selected_proc_id;
|
|
|
|
proc_id = &proc->MR_sle_user;
|
|
selected_proc_id = &selected_proc->MR_sle_user;
|
|
|
|
if ((proc_id->MR_user_pred_or_func ==
|
|
selected_proc_id->MR_user_pred_or_func)
|
|
&& MR_streq(proc_id->MR_user_decl_module,
|
|
selected_proc_id->MR_user_decl_module)
|
|
&& MR_streq(proc_id->MR_user_name,
|
|
selected_proc_id->MR_user_name)
|
|
&& (proc_id->MR_user_pred_form_arity ==
|
|
selected_proc_id->MR_user_pred_form_arity))
|
|
{
|
|
match = MR_TRUE;
|
|
} else {
|
|
match = MR_FALSE;
|
|
}
|
|
} else {
|
|
match = MR_FALSE;
|
|
}
|
|
|
|
if (match) {
|
|
list = MR_int_list_cons((MR_Integer) proc, list);
|
|
}
|
|
}
|
|
|
|
Layouts = list;
|
|
").
|
|
|
|
:- pragma foreign_proc("C",
|
|
containing_proc_layout(LabelLayout::in) = (ProcLayout::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
ProcLayout = LabelLayout->MR_sll_entry;
|
|
").
|
|
|
|
:- pragma foreign_proc("C",
|
|
proc_bytecode_bytes(ProcLayout::in) = (ByteCodeBytes::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
ByteCodeBytes = ProcLayout->MR_sle_body_bytes;
|
|
#ifdef MR_DEBUG_PROC_REP
|
|
printf(""lookup_proc_bytecode: %p %p\\n"", ProcLayout, ByteCodeBytes);
|
|
#endif
|
|
").
|
|
|
|
:- pragma foreign_proc("C#",
|
|
proc_bytecode_bytes(_ProcLayout::in) = (_ByteCodeBytes::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
throw new System.Exception(\"not supported in C# grade\");
|
|
").
|
|
|
|
:- pragma foreign_proc("Java",
|
|
proc_bytecode_bytes(_ProcLayout::in) = (_ByteCodeBytes::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
if (1 == 1) throw new Error(\"not supported in java grade\");
|
|
").
|
|
|
|
% Default version for non-C backends.
|
|
proc_bytecode_bytes(_) = dummy_bytecode_bytes.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pragma foreign_type("C", module_layout, "const MR_ModuleLayout *",
|
|
[can_pass_as_mercury_type, stable]).
|
|
% The following definitions are only stubs.
|
|
:- pragma foreign_type("C#", module_layout, "object", []).
|
|
:- pragma foreign_type("Java", module_layout, "java.lang.Object", []).
|
|
|
|
:- pragma foreign_type("C", string_table_chars, "MR_ConstString",
|
|
[can_pass_as_mercury_type, stable]).
|
|
% The following definitions are only stubs.
|
|
:- pragma foreign_type("C#", string_table_chars, "object", []).
|
|
:- pragma foreign_type("Java", string_table_chars, "java.lang.Object", []).
|
|
|
|
:- pragma foreign_proc("C",
|
|
containing_module_layout(ProcLayout::in, ModuleLayout::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
if (MR_PROC_LAYOUT_HAS_THIRD_GROUP(ProcLayout)) {
|
|
ModuleLayout = ProcLayout->MR_sle_module_layout;
|
|
SUCCESS_INDICATOR = MR_TRUE;
|
|
} else {
|
|
SUCCESS_INDICATOR = MR_FALSE;
|
|
}
|
|
").
|
|
|
|
module_string_table(ModuleLayout) = StringTable :-
|
|
module_string_table_components(ModuleLayout, StringTableChars, Size),
|
|
StringTable = string_table(StringTableChars, Size).
|
|
|
|
:- pred module_string_table_components(module_layout::in,
|
|
string_table_chars::out, int::out) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
module_string_table_components(ModuleLayout::in,
|
|
StringTableChars::out, Size::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
StringTableChars = ModuleLayout->MR_ml_string_table;
|
|
Size = ModuleLayout->MR_ml_string_table_size;
|
|
").
|
|
|
|
lookup_string_table(StringTable, NameCode) = Str :-
|
|
StringTable = string_table(StringTableChars, Size),
|
|
Str = lookup_string_table_2(StringTableChars, Size, NameCode).
|
|
|
|
:- func lookup_string_table_2(string_table_chars, int, int) = string.
|
|
|
|
:- pragma foreign_proc("C",
|
|
lookup_string_table_2(StringTableChars::in, StringTableSize::in,
|
|
NameCode::in) = (Str::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
MR_ConstString str0;
|
|
int should_copy;
|
|
|
|
str0 = MR_name_in_string_table(StringTableChars, StringTableSize,
|
|
(MR_uint_least32_t)NameCode, &should_copy);
|
|
if (should_copy) {
|
|
MR_make_aligned_string(Str, str0);
|
|
} else {
|
|
MR_make_aligned_string_copy(Str, str0);
|
|
}
|
|
").
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
read_byte(ByteCode, Value, !Pos) :-
|
|
ByteCode = bytecode(Bytes, Size),
|
|
!.Pos + 1 =< Size,
|
|
read_byte_2(Bytes, Value, !Pos).
|
|
|
|
:- pred read_byte_2(bytecode_bytes::in, int::out, int::in, int::out) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
read_byte_2(ByteCode::in, Value::out, Pos0::in, Pos::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
Value = ByteCode[Pos0];
|
|
Pos = Pos0 + 1;
|
|
").
|
|
|
|
read_short(ByteCode, Value, !Pos) :-
|
|
ByteCode = bytecode(Bytes, Size),
|
|
!.Pos + 2 =< Size,
|
|
read_short_2(Bytes, Value, !Pos).
|
|
|
|
:- pred read_short_2(bytecode_bytes::in, int::out, int::in, int::out) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
read_short_2(ByteCode::in, Value::out, Pos0::in, Pos::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
Value = (ByteCode[Pos0] << 8) + ByteCode[Pos0+1];
|
|
Pos = Pos0 + 2;
|
|
").
|
|
|
|
read_int32(ByteCode, Value, !Pos) :-
|
|
ByteCode = bytecode(Bytes, Size),
|
|
!.Pos + 4 =< Size,
|
|
read_int32_2(Bytes, Value, !Pos).
|
|
|
|
:- pred read_int32_2(bytecode_bytes::in, int::out, int::in, int::out) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
read_int32_2(ByteCode::in, Value::out, Pos0::in, Pos::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
Value = (ByteCode[Pos0] << 24) + (ByteCode[Pos0+1] << 16) +
|
|
(ByteCode[Pos0+2] << 8) + ByteCode[Pos0+3];
|
|
Pos = Pos0 + 4;
|
|
").
|
|
|
|
read_num(ByteCode, Num, !Pos) :-
|
|
read_num_2(ByteCode, 0, Num, !Pos).
|
|
|
|
:- pred read_num_2(bytecode::in, int::in, int::out, int::in, int::out)
|
|
is semidet.
|
|
|
|
read_num_2(ByteCode, Num0, Num, !Pos) :-
|
|
read_byte(ByteCode, Byte, !Pos),
|
|
Num1 = (Num0 << 7) \/ (Byte /\ 0x7F),
|
|
( if Byte /\ 0x80 = 0 then
|
|
Num = Num1
|
|
else
|
|
read_num_2(ByteCode, Num1, Num, !Pos)
|
|
).
|
|
|
|
read_string_via_offset(ByteCode, StringTable, String, !Pos) :-
|
|
read_int32(ByteCode, Offset, !Pos),
|
|
String = lookup_string_table(StringTable, Offset).
|
|
|
|
read_line(ByteCode, Line, !Pos) :-
|
|
read_line_2(ByteCode, [], RevChars, !Pos),
|
|
string.from_rev_char_list(RevChars, Line).
|
|
|
|
:- pred read_line_2(bytecode::in, list(char)::in, list(char)::out,
|
|
int::in, int::out) is semidet.
|
|
|
|
read_line_2(ByteCode, !RevChars, !Pos) :-
|
|
read_byte(ByteCode, Byte, !Pos),
|
|
char.from_int(Byte, Char),
|
|
( if Char = '\n' then
|
|
!:RevChars = [Char | !.RevChars]
|
|
else
|
|
!:RevChars = [Char | !.RevChars],
|
|
disable_warning [suspicious_recursion] (
|
|
read_line_2(ByteCode, !RevChars, !Pos)
|
|
)
|
|
).
|
|
|
|
read_len_string(ByteCode, String, !Pos) :-
|
|
read_num(ByteCode, Length, !Pos),
|
|
read_len_string_2(ByteCode, Length, [], RevChars, !Pos),
|
|
string.from_rev_char_list(RevChars, String).
|
|
|
|
:- pred read_len_string_2(bytecode::in, int::in,
|
|
list(char)::in, list(char)::out, int::in, int::out) is semidet.
|
|
|
|
read_len_string_2(ByteCode, N, !RevChars, !Pos) :-
|
|
( if N =< 0 then
|
|
true
|
|
else
|
|
read_byte(ByteCode, Byte, !Pos),
|
|
char.from_int(Byte, Char),
|
|
!:RevChars = [Char | !.RevChars],
|
|
read_len_string_2(ByteCode, N - 1, !RevChars, !Pos)
|
|
).
|
|
|
|
read_string_table(ByteCode, StringTable, !Pos) :-
|
|
read_num(ByteCode, Size, !Pos),
|
|
ByteCode = bytecode(Bytes, NumBytes),
|
|
!.Pos + Size =< NumBytes,
|
|
bytecode_string_table_2(Bytes, !.Pos, Size, StringTableChars),
|
|
!:Pos = !.Pos + Size,
|
|
StringTable = string_table(StringTableChars, Size).
|
|
|
|
:- pred bytecode_string_table_2(bytecode_bytes::in, Offset::in, Size::in,
|
|
string_table_chars::out) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
bytecode_string_table_2(Bytes::in, Offset::in, Size::in,
|
|
StringTableChars::out),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
char *buf;
|
|
char *table;
|
|
MR_Unsigned i;
|
|
|
|
MR_allocate_aligned_string_msg(buf, Size, MR_ALLOC_ID);
|
|
table = ((char *) Bytes) + Offset;
|
|
for (i = 0; i < Size; i++) {
|
|
buf[i] = table[i];
|
|
}
|
|
|
|
StringTableChars = (MR_ConstString) buf;
|
|
").
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
encode_byte(Byte, [Byte]) :-
|
|
Byte >= 0,
|
|
Byte < 128.
|
|
|
|
encode_byte_det(Byte, Bytes) :-
|
|
( if encode_byte(Byte, BytesPrime) then
|
|
Bytes = BytesPrime
|
|
else
|
|
unexpected($pred, "encode_byte failed")
|
|
).
|
|
|
|
encode_byte_func(Byte) = Bytes :-
|
|
encode_byte_det(Byte, Bytes).
|
|
|
|
encode_short(Short, [Byte1, Byte2]) :-
|
|
Short >= 0,
|
|
Byte2 = Short /\ 255,
|
|
Byte1 = Short / 256,
|
|
Byte1 < 128.
|
|
|
|
encode_short_det(Short, Bytes) :-
|
|
( if encode_short(Short, BytesPrime) then
|
|
Bytes = BytesPrime
|
|
else
|
|
unexpected($pred, "encode_short failed")
|
|
).
|
|
|
|
encode_short_func(Short) = Bytes :-
|
|
encode_short_det(Short, Bytes).
|
|
|
|
encode_int32(Int32, [Byte1, Byte2, Byte3, Byte4]) :-
|
|
Int32 >= 0,
|
|
Byte4 = Int32 /\ 255,
|
|
Bytes123 = Int32 / 256,
|
|
Byte3 = Bytes123 /\ 255,
|
|
Bytes12 = Bytes123 / 256,
|
|
Byte2 = Bytes12 /\ 255,
|
|
Byte1 = Bytes12 / 256,
|
|
Byte1 < 128.
|
|
|
|
encode_int32_det(Int32, Bytes) :-
|
|
( if encode_int32(Int32, BytesPrime) then
|
|
Bytes = BytesPrime
|
|
else
|
|
unexpected($pred, "encode_int32 failed")
|
|
).
|
|
|
|
encode_int32_func(Int32) = Bytes :-
|
|
encode_int32_det(Int32, Bytes).
|
|
|
|
encode_num(Num, Bytes) :-
|
|
Num >= 0,
|
|
LastByte = Num /\ 127,
|
|
NextNum = Num / 128,
|
|
encode_num_2(NextNum, [LastByte], Bytes).
|
|
|
|
:- pred encode_num_2(int::in, list(int)::in, list(int)::out) is det.
|
|
|
|
encode_num_2(Num, RestBytes, Bytes) :-
|
|
( if Num = 0 then
|
|
Bytes = RestBytes
|
|
else
|
|
CurByte = (Num /\ 127) \/ 128,
|
|
NextNum = Num / 128,
|
|
encode_num_2(NextNum, [CurByte | RestBytes], Bytes)
|
|
).
|
|
|
|
encode_num_det(Num, Bytes) :-
|
|
( if encode_num(Num, BytesPrime) then
|
|
Bytes = BytesPrime
|
|
else
|
|
unexpected($pred, "encode_num failed")
|
|
).
|
|
|
|
encode_num_func(Num) = Bytes :-
|
|
encode_num_det(Num, Bytes).
|
|
|
|
encode_len_string(String, Bytes) :-
|
|
string.length(String, Length),
|
|
encode_num_det(Length, LengthBytes),
|
|
string.to_char_list(String, Chars),
|
|
CharBytes = list.map(char.to_int, Chars),
|
|
Bytes = LengthBytes ++ CharBytes.
|
|
|
|
encode_len_string_func(String) = Bytes :-
|
|
encode_len_string(String, Bytes).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module mdbcomp.rtti_access.
|
|
%---------------------------------------------------------------------------%
|