Skip to content

Commit

Permalink
Fix Mantis bug #354.
Browse files Browse the repository at this point in the history
I/O tabling has two main purposes. The first and more important is to allow the
debugger to replay parts of the program execution for the programmer, which
requires making I/O operations idempotent (so that we get the same results on
the second, third etc "execution" as on the first). The second purpose is to
let the person using the debugger actually see a list of the I/O actions, and
their results.

The root of the problem here is that the compiler can do the second part
only if it has access to the type_infos describing the types of the arguments
of the I/O action. With the current infrastructure for representing typeclass
information, this is not always possible in the presence of typeclass
constraints on I/O action predicates. The reason is that polymorphism.m can
put the typeinfo for a type variable that is subject to a typeclass constraint
arbitrarily deep inside the typeclass_info for that constraint, but the RTTI
can encode such locations only up to a fixed depth (currently only the
shallowest embedded is encodable).

Before this fix, the test case for this bug got a compiler abort when the
I/O tabling transformation tried to figure out how to table the typeclass
info representing the typeclass constraint on a I/O action predicate.

We still cannot table typeclass infos. We could store them (I/O tabling
does not require anything more complicated), but the problem of deeply buried
typeinfos inside them would still remain. So this fix consists of two parts:

- for typeclass constrained I/O primitives, recording only enough information
  to allow them to replayed (the first purpose above), and not to print them
  out (the second purpose), and
- getting the runtime system to understand this, and not crash with a core dump
  in the absence of the information required for the second purpose.

This second part requires changes to the RTTI used by I/O tabling. These
changes BREAK BINARY COMPATIBILITY in debug grades.

runtime/mercury_stack_layout.h:
    Rename the MR_TableIoDecl structure as the MR_TableIoEntry structure,
    since the I/O table entries that it describes are used not just for
    declarative debugging, but also for printing out I/O actions.

    Add a field to it that specifies whether the fields describing
    the types of the I/O action's arguments are meaningful.

runtime/mercury_grade.h:
    Bump the debug-only binary compatibility version number, since
    the change to mercury_stack_layout.h requires it.

runtime/mercury_trace_base.[ch]:
    When returning information about a tabled I/O action, return a boolean
    that says whether the information abouts its arguments is actually
    present or not. Do not return information about the arguments if
    we cannot convert them into univs due to missing type information.

browser/io_action.m:
    Pay attention to the new info returned by MR_trace_get_action,
    and avoid a potential core dump by generating a description of the
    requested I/O action only if the argument type information needed
    to generate that description is actually available.

trace/mercury_trace_vars.c:
    Pay attention to the new info returned by MR_trace_get_action.
    When the argument type information needed to generate an accurate
    description of the I/O action is not available, generate a
    "description" that mentions this fact.

trace/mercury_trace_cmd_browsing.c:
    Make the fix to mercury_trace_vars.c easier to test by adding a mechanism
    to print out all existing I/O actions, as long as there aren't too many
    of them.

compiler/hlds_pred.m:
compiler/layout.m:
compiler/prog_data.m:
    Prepare for the possibility that we have cannot record the information
    needed to reconstruct the runtime types of the arguments of a I/O tabled
    predicate.

compiler/table_gen.m:
    If an I/O tabled predicate has one or more typeclass constraints,
    do not attempt to record the RTTI needed to reconstruct the types
    of its arguments at runtime.

compiler/continuation_info.m:
compiler/hlds_data.m:
    Rename some data structures that referred to the old MR_TableIoDecl
    structure to refer to its replacement, the MR_TableIoEntry structure.

compiler/bytecode_gen.m:
compiler/ctgc.selector.m:
compiler/dead_proc_elim.m:
compiler/dependency_graph.m:
compiler/erl_unify_gen.m:
compiler/export.m:
compiler/higher_order.m:
compiler/hlds_code_util.m:
compiler/hlds_out_mode.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
compiler/hlds_pred.m:
compiler/implementation_defined_literals.m:
compiler/inst_check.m:
compiler/layout.m:
compiler/layout_out.m:
compiler/llds.m:
compiler/llds_out_data.m:
compiler/llds_out_file.m:
compiler/llds_out_util.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_to_mercury.m:
compiler/ml_global_data.m:
compiler/ml_switch_gen.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/mode_util.m:
compiler/module_qual.m:
compiler/opt_debug.m:
compiler/proc_gen.m:
compiler/prog_data.m:
compiler/prog_out.m:
compiler/prog_rep.m:
compiler/prog_type.m:
compiler/prog_util.m:
compiler/rbmm.execution_path.m:
compiler/stack_layout.m:
compiler/structure_reuse.direct.choose_reuse.m:
compiler/switch_gen.m:
compiler/switch_util.m:
compiler/type_ctor_info.m:
compiler/unify_gen.m:
compiler/unused_imports.m:
compiler/xml_documentation.m:
runtime/mercury_misc.h:
runtime/mercury_tabling.h:
    Conform to the above changes.

tests/debugger/tabled_typeclass.{m,inp,exp,exp2}:
    New test case to test that I/O actions that have typeclass constraints
    on them can be printed in mdb.

tests/debugger/Mmakefile:
tests/debugger/Mercury.options:
    Enable the new case.
  • Loading branch information
zsomogyi committed Aug 29, 2014
1 parent fc867fe commit 8a6ffaa
Show file tree
Hide file tree
Showing 62 changed files with 713 additions and 330 deletions.
9 changes: 5 additions & 4 deletions browser/io_action.m
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,20 @@
"{
const char *problem;
const char *proc_name;
MR_Bool is_func;
MR_Word args;
MR_bool io_action_tabled;
MR_Word is_func;
MR_bool have_arg_infos;
MR_Word args;
MR_String ProcName;
MR_save_transient_hp();
io_action_tabled = MR_trace_get_action(SeqNum, &proc_name, &is_func,
&args);
&have_arg_infos, &args);
MR_restore_transient_hp();
/* cast away const */
ProcName = (MR_String) (MR_Integer) proc_name;
if (io_action_tabled) {
if (io_action_tabled && have_arg_infos) {
MaybeIOAction = MR_IO_ACTION_make_yes_io_action(ProcName, is_func,
args);
} else {
Expand Down
10 changes: 5 additions & 5 deletions compiler/bytecode_gen.m
Original file line number Diff line number Diff line change
Expand Up @@ -789,8 +789,8 @@
ConsId = tabling_info_const(_),
sorry($module, $pred, "bytecode cannot implement tabling")
;
ConsId = table_io_decl(_),
sorry($module, $pred, "bytecode cannot implement table io decl")
ConsId = table_io_entry_desc(_),
sorry($module, $pred, "bytecode cannot implement table io entry desc")
;
ConsId = deep_profiling_proc_layout(_),
sorry($module, $pred, "bytecode cannot implement deep profiling")
Expand Down Expand Up @@ -842,9 +842,9 @@
map_cons_tag(deep_profiling_proc_layout_tag(_, _), _) :-
unexpected($module, $pred, "deep_profiling_proc_layout_tag cons tag " ++
"for non-deep_profiling_proc_static cons id").
map_cons_tag(table_io_decl_tag(_, _), _) :-
unexpected($module, $pred, "table_io_decl_tag cons tag " ++
"for non-table_io_decl cons id").
map_cons_tag(table_io_entry_tag(_, _), _) :-
unexpected($module, $pred, "table_io_entry_tag cons tag " ++
"for non-table_io_entry_desc cons id").
map_cons_tag(reserved_address_tag(_), _) :-
% These should only be generated if the --num-reserved-addresses
% or --num-reserved-objects options are used.
Expand Down
2 changes: 1 addition & 1 deletion compiler/continuation_info.m
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@
).

:- type proc_layout_table_info
---> proc_table_io_decl(
---> proc_table_io_entry(
proc_table_io_info
)
; proc_table_struct(
Expand Down
2 changes: 1 addition & 1 deletion compiler/ctgc.selector.m
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
; ConsId = typeclass_info_const(_)
; ConsId = ground_term_const(_, _)
; ConsId = tabling_info_const(_)
; ConsId = table_io_decl(_)
; ConsId = table_io_entry_desc(_)
; ConsId = deep_profiling_proc_layout(_)
),
unexpected($module, $pred, "cannot handle cons_id")
Expand Down
2 changes: 1 addition & 1 deletion compiler/dead_proc_elim.m
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@
; ConsId = type_info_cell_constructor(_)
; ConsId = typeclass_info_cell_constructor
; ConsId = deep_profiling_proc_layout(_)
; ConsId = table_io_decl(_)
; ConsId = table_io_entry_desc(_)
)
% Do nothing.
)
Expand Down
2 changes: 1 addition & 1 deletion compiler/dependency_graph.m
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ func dependency_node(pred_proc_id) = T
; ConsId = typeclass_info_const(_)
; ConsId = ground_term_const(_, _)
; ConsId = tabling_info_const(_)
; ConsId = table_io_decl(_)
; ConsId = table_io_entry_desc(_)
; ConsId = deep_profiling_proc_layout(_)
)
).
Expand Down
2 changes: 1 addition & 1 deletion compiler/erl_unify_gen.m
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@
;
( ConsId = tabling_info_const(_)
; ConsId = deep_profiling_proc_layout(_)
; ConsId = table_io_decl(_)
; ConsId = table_io_entry_desc(_)
),
sorry($module, $pred,
"tabling and deep profiling not supported on Erlang backend")
Expand Down
2 changes: 1 addition & 1 deletion compiler/export.m
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,7 @@
; TagVal = ground_term_const_tag(_, _)
; TagVal = tabling_info_tag(_, _)
; TagVal = deep_profiling_proc_layout_tag(_, _)
; TagVal = table_io_decl_tag(_, _)
; TagVal = table_io_entry_tag(_, _)
; TagVal = single_functor_tag
; TagVal = unshared_tag(_)
; TagVal = direct_arg_tag(_)
Expand Down
2 changes: 1 addition & 1 deletion compiler/higher_order.m
Original file line number Diff line number Diff line change
Expand Up @@ -918,7 +918,7 @@
; ConsId = ground_term_const(_, _)
; ConsId = tabling_info_const(_)
; ConsId = deep_profiling_proc_layout(_)
; ConsId = table_io_decl(_)
; ConsId = table_io_entry_desc(_)
),
IsInteresting = no
;
Expand Down
4 changes: 2 additions & 2 deletions compiler/hlds_code_util.m
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@
proc(PredId, ProcId) = unshroud_pred_proc_id(ShroudedPredProcId),
Tag = deep_profiling_proc_layout_tag(PredId, ProcId)
;
ConsId = table_io_decl(ShroudedPredProcId),
ConsId = table_io_entry_desc(ShroudedPredProcId),
proc(PredId, ProcId) = unshroud_pred_proc_id(ShroudedPredProcId),
Tag = table_io_decl_tag(PredId, ProcId)
Tag = table_io_entry_tag(PredId, ProcId)
;
ConsId = tuple_cons(Arity),
% Tuples do not need a tag. Note that unary tuples are not treated
Expand Down
8 changes: 4 additions & 4 deletions compiler/hlds_data.m
Original file line number Diff line number Diff line change
Expand Up @@ -630,9 +630,9 @@
% This is for constants representing procedure descriptions for
% deep profiling.

; table_io_decl_tag(pred_id, proc_id)
; table_io_entry_tag(pred_id, proc_id)
% This is for constants representing the structure that allows us
% to decode the contents of the memory block containing the
% to decode the contents of the answer block containing the
% headvars of I/O primitives.

; single_functor_tag
Expand Down Expand Up @@ -769,7 +769,7 @@
; Tag = type_info_const_tag(_)
; Tag = typeclass_info_const_tag(_)
; Tag = tabling_info_tag(_, _)
; Tag = table_io_decl_tag(_, _)
; Tag = table_io_entry_tag(_, _)
; Tag = deep_profiling_proc_layout_tag(_, _)
),
MaybePrimaryTag = no
Expand Down Expand Up @@ -804,7 +804,7 @@
; Tag = typeclass_info_const_tag(_)
; Tag = tabling_info_tag(_, _)
; Tag = deep_profiling_proc_layout_tag(_, _)
; Tag = table_io_decl_tag(_, _)
; Tag = table_io_entry_tag(_, _)
; Tag = no_tag
; Tag = reserved_address_tag(_)
; Tag = unshared_tag(_PrimaryTag)
Expand Down
4 changes: 2 additions & 2 deletions compiler/hlds_out_mode.m
Original file line number Diff line number Diff line change
Expand Up @@ -607,9 +607,9 @@
FunctorName = "tabling_info_const",
Term = term.functor(term.string(FunctorName), [], Context)
;
ConsId = table_io_decl(_),
ConsId = table_io_entry_desc(_),
term.context_init(Context),
FunctorName = "table_io_decl",
FunctorName = "table_io_entry_desc",
Term = term.functor(term.string(FunctorName), [], Context)
;
ConsId = deep_profiling_proc_layout(_),
Expand Down
12 changes: 9 additions & 3 deletions compiler/hlds_out_pred.m
Original file line number Diff line number Diff line change
Expand Up @@ -1088,9 +1088,15 @@
io::di, io::uo) is det.

write_proc_table_io_info(TVarSet, ProcTableIOInfo, !IO) :-
ProcTableIOInfo = proc_table_io_info(ArgInfos),
io.write_string("% proc table io info: io tabled\n", !IO),
write_table_arg_infos(TVarSet, ArgInfos, !IO).
ProcTableIOInfo = proc_table_io_info(MaybeArgInfos),
(
MaybeArgInfos = no,
io.write_string("% proc table io info: io tabled, no arg_infos\n", !IO)
;
MaybeArgInfos = yes(ArgInfos),
io.write_string("% proc table io info: io tabled, arg_infos:\n", !IO),
write_table_arg_infos(TVarSet, ArgInfos, !IO)
).

write_table_arg_infos(TVarSet, TableArgInfos, !IO) :-
TableArgInfos = table_arg_infos(ArgInfos, TVarMap),
Expand Down
12 changes: 6 additions & 6 deletions compiler/hlds_out_util.m
Original file line number Diff line number Diff line change
Expand Up @@ -720,10 +720,10 @@
++ pred_id_to_string(ModuleInfo, PredId)
++ ", " ++ int_to_string(ProcIdInt) ++ ")"
;
ConsId = table_io_decl(ShroudedPredProcId),
ConsId = table_io_entry_desc(ShroudedPredProcId),
proc(PredId, ProcId) = unshroud_pred_proc_id(ShroudedPredProcId),
proc_id_to_int(ProcId, ProcIdInt),
Str = "table_io_decl("
Str = "table_io_entry_desc("
++ pred_id_to_string(ModuleInfo, PredId)
++ " (mode " ++ int_to_string(ProcIdInt) ++ "))"
;
Expand Down Expand Up @@ -813,10 +813,10 @@
"<tabling_info " ++ int_to_string(PredId) ++
", " ++ int_to_string(ProcId) ++ ">"
;
ConsId = table_io_decl(PredProcId),
ConsId = table_io_entry_desc(PredProcId),
PredProcId = shrouded_pred_proc_id(PredId, ProcId),
String =
"<table_io_decl " ++ int_to_string(PredId) ++ ", " ++
"<table_io_entry_desc " ++ int_to_string(PredId) ++ ", " ++
int_to_string(ProcId) ++ ">"
;
ConsId = deep_profiling_proc_layout(PredProcId),
Expand Down Expand Up @@ -940,10 +940,10 @@
"<tabling_info " ++ int_to_string(PredId) ++
", " ++ int_to_string(ProcId) ++ ">"
;
ConsId = table_io_decl(PredProcId),
ConsId = table_io_entry_desc(PredProcId),
PredProcId = shrouded_pred_proc_id(PredId, ProcId),
String =
"<table_io_decl " ++ int_to_string(PredId) ++ ", " ++
"<table_io_entry_desc " ++ int_to_string(PredId) ++ ", " ++
int_to_string(ProcId) ++ ">"
;
ConsId = deep_profiling_proc_layout(PredProcId),
Expand Down
2 changes: 1 addition & 1 deletion compiler/hlds_pred.m
Original file line number Diff line number Diff line change
Expand Up @@ -1895,7 +1895,7 @@
% table_arg_infos is the one in the proc_info in which
% the proc_table_io_info is stored.

table_arg_infos
maybe(table_arg_infos)
).

:- type table_step_desc
Expand Down
2 changes: 1 addition & 1 deletion compiler/implementation_defined_literals.m
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
; ConsId = ground_term_const(_, _)
; ConsId = tabling_info_const(_)
; ConsId = deep_profiling_proc_layout(_)
; ConsId = table_io_decl(_)
; ConsId = table_io_entry_desc(_)
),
Goal = Goal0
)
Expand Down
2 changes: 1 addition & 1 deletion compiler/inst_check.m
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@
; ConsId = ground_term_const(_, _)
; ConsId = tabling_info_const(_)
; ConsId = deep_profiling_proc_layout(_)
; ConsId = table_io_decl(_)
; ConsId = table_io_entry_desc(_)
),
MaybeFunctor = no
).
Expand Down
39 changes: 29 additions & 10 deletions compiler/layout.m
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +173,35 @@
plps_coverage_points :: maybe({int, int})
).

:- type table_io_decl_data
---> table_io_decl_data(
% defines MR_TableIoDecl
tid_proc_ptr :: layout_name,
tid_num_ptis :: int,

% pseudo-typeinfos for headvars
tid_ptis :: rval,
:- type table_io_args_data
---> table_io_args_data(
% The number of head variables that are stored in the answer
% block. Besides the values of the output arguments,
% which are needed to make the I/O action idempotent,
% it also includes the values of the input arguments.
% Some of these, the type_infos, mdb needs in order to
% convert the type-specific representations of the outputs
% to a term that the debugger's user can print or browse.
% The other inputs are needed to allow the debugger's user
% to judge whether the output are correct or not.
tia_answerblock_arity :: int,

% This rval stores a vector of answerblock_arity pseudo-
% typeinfos, one for each headvar stored in the answer block.
tia_ptis :: rval,

% This rval represents a vector mapping each type variable
% that occurs in the above pseudo-typeinfos to the location
% of the type_info that is currently bound to that type
% variable.
tia_type_params :: rval
).

tid_type_params :: rval
:- type table_io_entry_data
---> table_io_entry_data(
% defines MR_TableIoEntry
tie_proc_ptr :: layout_name,
tie_maybe_args :: maybe(table_io_args_data)
).

:- type data_or_slot_id
Expand Down Expand Up @@ -356,7 +375,7 @@
% A vector of variable names (represented as offsets into
% the string table) for a procedure layout structure.
; proc_body_bytecodes_array
; proc_table_io_decl_array
; proc_table_io_entry_array
; proc_event_layouts_array
; proc_exec_trace_array
; threadscope_string_table_array
Expand Down
Loading

0 comments on commit 8a6ffaa

Please sign in to comment.